<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[41328] trunk/src: Plupload:</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta" style="font-size: 105%">
<dt style="float: left; width: 6em; font-weight: bold">Revision</dt> <dd><a style="font-weight: bold" href="https://core.trac.wordpress.org/changeset/41328">41328</a><script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","description":"Review this Commit","action":{"@type":"ViewAction","url":"https://core.trac.wordpress.org/changeset/41328","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>azaozz</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2017-09-01 12:27:49 +0000 (Fri, 01 Sep 2017)</dd>
</dl>

<pre style='padding-left: 1em; margin: 2em 0; border-left: 2px solid #ccc; line-height: 1.25; font-size: 105%; font-family: sans-serif'>Plupload:
- Update to 2.1.9.
- Include the non-minified plupload.js and moxie.js.
- Remove support for Flash and Silverlight, the available runtime options are `html5` and `html4`.
- Delete plupload.flash.swf and plupload.silverlight.xap.

Fixes <a href="https://core.trac.wordpress.org/ticket/41755">#41755</a>.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunksrcwpadminincludesmediaphp">trunk/src/wp-admin/includes/media.php</a></li>
<li><a href="#trunksrcwpadminincludesupdatecorephp">trunk/src/wp-admin/includes/update-core.php</a></li>
<li><a href="#trunksrcwpincludesjspluploadpluploadfullminjs">trunk/src/wp-includes/js/plupload/plupload.full.min.js</a></li>
<li><a href="#trunksrcwpincludesmediaphp">trunk/src/wp-includes/media.php</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunksrcwpincludesjspluploadmoxiejs">trunk/src/wp-includes/js/plupload/moxie.js</a></li>
<li><a href="#trunksrcwpincludesjspluploadpluploadjs">trunk/src/wp-includes/js/plupload/plupload.js</a></li>
</ul>

<h3>Removed Paths</h3>
<ul>
<li><a href="#trunksrcwpincludesjspluploadpluploadflashswf">trunk/src/wp-includes/js/plupload/plupload.flash.swf</a></li>
<li><a href="#trunksrcwpincludesjspluploadpluploadsilverlightxap">trunk/src/wp-includes/js/plupload/plupload.silverlight.xap</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunksrcwpadminincludesmediaphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-admin/includes/media.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-admin/includes/media.php     2017-09-01 08:49:50 UTC (rev 41327)
+++ trunk/src/wp-admin/includes/media.php       2017-09-01 12:27:49 UTC (rev 41328)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1868,15 +1868,16 @@
</span><span class="cx" style="display: block; padding: 0 10px">  */
</span><span class="cx" style="display: block; padding: 0 10px"> $post_params = apply_filters( 'upload_post_params', $post_params );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/*
+ * Since 4.9 the `runtimes` setting is hardcoded in our version of Plupload to `html5,html4`,
+ * and the `flash_swf_url` and `silverlight_xap_url` are not used.
+ */
</ins><span class="cx" style="display: block; padding: 0 10px"> $plupload_init = array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        'runtimes'            => 'html5,flash,silverlight,html4',
</del><span class="cx" style="display: block; padding: 0 10px">         'browse_button'       => 'plupload-browse-button',
</span><span class="cx" style="display: block; padding: 0 10px">        'container'           => 'plupload-upload-ui',
</span><span class="cx" style="display: block; padding: 0 10px">        'drop_element'        => 'drag-drop-area',
</span><span class="cx" style="display: block; padding: 0 10px">        'file_data_name'      => 'async-upload',
</span><span class="cx" style="display: block; padding: 0 10px">        'url'                 => $upload_action_url,
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        'flash_swf_url'       => includes_url( 'js/plupload/plupload.flash.swf' ),
-       'silverlight_xap_url' => includes_url( 'js/plupload/plupload.silverlight.xap' ),
</del><span class="cx" style="display: block; padding: 0 10px">         'filters' => array(
</span><span class="cx" style="display: block; padding: 0 10px">                'max_file_size'   => $max_upload_size . 'b',
</span><span class="cx" style="display: block; padding: 0 10px">        ),
</span></span></pre></div>
<a id="trunksrcwpadminincludesupdatecorephp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-admin/includes/update-core.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-admin/includes/update-core.php       2017-09-01 08:49:50 UTC (rev 41327)
+++ trunk/src/wp-admin/includes/update-core.php 2017-09-01 12:27:49 UTC (rev 41328)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -712,6 +712,9 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 'wp-includes/js/tinymce/skins/lightgray/fonts/tinymce-small.json',
</span><span class="cx" style="display: block; padding: 0 10px"> 'wp-includes/js/tinymce/skins/lightgray/fonts/tinymce.json',
</span><span class="cx" style="display: block; padding: 0 10px"> 'wp-includes/js/tinymce/skins/lightgray/skin.ie7.min.css',
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+// 4.9
+'wp-includes/js/plupload/plupload.flash.swf',
+'wp-includes/js/plupload/plupload.silverlight.xap',
</ins><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span></span></pre></div>
<a id="trunksrcwpincludesjspluploadmoxiejs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/src/wp-includes/js/plupload/moxie.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/js/plupload/moxie.js                                (rev 0)
+++ trunk/src/wp-includes/js/plupload/moxie.js  2017-09-01 12:27:49 UTC (rev 41328)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,9901 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+;var MXI_DEBUG = true;
+/**
+ * mOxie - multi-runtime File API & XMLHttpRequest L2 Polyfill
+ * v1.3.5
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ *
+ * Date: 2016-05-15
+ */
+/**
+ * Compiled inline version. (Library mode)
+ */
+
+/**
+ * Modified for WordPress, Silverlight and Flash runtimes support was removed.
+ * See https://core.trac.wordpress.org/ticket/41755.
+ */
+
+/*jshint smarttabs:true, undef:true, latedef:true, curly:true, bitwise:true, camelcase:true */
+/*globals $code */
+
+(function(exports, undefined) {
+       "use strict";
+
+       var modules = {};
+
+       function require(ids, callback) {
+               var module, defs = [];
+
+               for (var i = 0; i < ids.length; ++i) {
+                       module = modules[ids[i]] || resolve(ids[i]);
+                       if (!module) {
+                               throw 'module definition dependecy not found: ' + ids[i];
+                       }
+
+                       defs.push(module);
+               }
+
+               callback.apply(null, defs);
+       }
+
+       function define(id, dependencies, definition) {
+               if (typeof id !== 'string') {
+                       throw 'invalid module definition, module id must be defined and be a string';
+               }
+
+               if (dependencies === undefined) {
+                       throw 'invalid module definition, dependencies must be specified';
+               }
+
+               if (definition === undefined) {
+                       throw 'invalid module definition, definition function must be specified';
+               }
+
+               require(dependencies, function() {
+                       modules[id] = definition.apply(null, arguments);
+               });
+       }
+
+       function defined(id) {
+               return !!modules[id];
+       }
+
+       function resolve(id) {
+               var target = exports;
+               var fragments = id.split(/[.\/]/);
+
+               for (var fi = 0; fi < fragments.length; ++fi) {
+                       if (!target[fragments[fi]]) {
+                               return;
+                       }
+
+                       target = target[fragments[fi]];
+               }
+
+               return target;
+       }
+
+       function expose(ids) {
+               for (var i = 0; i < ids.length; i++) {
+                       var target = exports;
+                       var id = ids[i];
+                       var fragments = id.split(/[.\/]/);
+
+                       for (var fi = 0; fi < fragments.length - 1; ++fi) {
+                               if (target[fragments[fi]] === undefined) {
+                                       target[fragments[fi]] = {};
+                               }
+
+                               target = target[fragments[fi]];
+                       }
+
+                       target[fragments[fragments.length - 1]] = modules[id];
+               }
+       }
+
+// Included from: src/javascript/core/utils/Basic.js
+
+/**
+ * Basic.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+define('moxie/core/utils/Basic', [], function() {
+       /**
+       Gets the true type of the built-in object (better version of typeof).
+       @author Angus Croll (http://javascriptweblog.wordpress.com/)
+
+       @method typeOf
+       @for Utils
+       @static
+       @param {Object} o Object to check.
+       @return {String} Object [[Class]]
+       */
+       var typeOf = function(o) {
+               var undef;
+
+               if (o === undef) {
+                       return 'undefined';
+               } else if (o === null) {
+                       return 'null';
+               } else if (o.nodeType) {
+                       return 'node';
+               }
+
+               // the snippet below is awesome, however it fails to detect null, undefined and arguments types in IE lte 8
+               return ({}).toString.call(o).match(/\s([a-z|A-Z]+)/)[1].toLowerCase();
+       };
+               
+       /**
+       Extends the specified object with another object.
+
+       @method extend
+       @static
+       @param {Object} target Object to extend.
+       @param {Object} [obj]* Multiple objects to extend with.
+       @return {Object} Same as target, the extended object.
+       */
+       var extend = function(target) {
+               var undef;
+
+               each(arguments, function(arg, i) {
+                       if (i > 0) {
+                               each(arg, function(value, key) {
+                                       if (value !== undef) {
+                                               if (typeOf(target[key]) === typeOf(value) && !!~inArray(typeOf(value), ['array', 'object'])) {
+                                                       extend(target[key], value);
+                                               } else {
+                                                       target[key] = value;
+                                               }
+                                       }
+                               });
+                       }
+               });
+               return target;
+       };
+               
+       /**
+       Executes the callback function for each item in array/object. If you return false in the
+       callback it will break the loop.
+
+       @method each
+       @static
+       @param {Object} obj Object to iterate.
+       @param {function} callback Callback function to execute for each item.
+       */
+       var each = function(obj, callback) {
+               var length, key, i, undef;
+
+               if (obj) {
+                       if (typeOf(obj.length) === 'number') { // it might be Array, FileList or even arguments object
+                               // Loop array items
+                               for (i = 0, length = obj.length; i < length; i++) {
+                                       if (callback(obj[i], i) === false) {
+                                               return;
+                                       }
+                               }
+                       } else if (typeOf(obj) === 'object') {
+                               // Loop object items
+                               for (key in obj) {
+                                       if (obj.hasOwnProperty(key)) {
+                                               if (callback(obj[key], key) === false) {
+                                                       return;
+                                               }
+                                       }
+                               }
+                       }
+               }
+       };
+
+       /**
+       Checks if object is empty.
+       
+       @method isEmptyObj
+       @static
+       @param {Object} o Object to check.
+       @return {Boolean}
+       */
+       var isEmptyObj = function(obj) {
+               var prop;
+
+               if (!obj || typeOf(obj) !== 'object') {
+                       return true;
+               }
+
+               for (prop in obj) {
+                       return false;
+               }
+
+               return true;
+       };
+
+       /**
+       Recieve an array of functions (usually async) to call in sequence, each  function
+       receives a callback as first argument that it should call, when it completes. Finally,
+       after everything is complete, main callback is called. Passing truthy value to the
+       callback as a first argument will interrupt the sequence and invoke main callback
+       immediately.
+
+       @method inSeries
+       @static
+       @param {Array} queue Array of functions to call in sequence
+       @param {Function} cb Main callback that is called in the end, or in case of error
+       */
+       var inSeries = function(queue, cb) {
+               var i = 0, length = queue.length;
+
+               if (typeOf(cb) !== 'function') {
+                       cb = function() {};
+               }
+
+               if (!queue || !queue.length) {
+                       cb();
+               }
+
+               function callNext(i) {
+                       if (typeOf(queue[i]) === 'function') {
+                               queue[i](function(error) {
+                                       /*jshint expr:true */
+                                       ++i < length && !error ? callNext(i) : cb(error);
+                               });
+                       }
+               }
+               callNext(i);
+       };
+
+
+       /**
+       Recieve an array of functions (usually async) to call in parallel, each  function
+       receives a callback as first argument that it should call, when it completes. After 
+       everything is complete, main callback is called. Passing truthy value to the
+       callback as a first argument will interrupt the process and invoke main callback
+       immediately.
+
+       @method inParallel
+       @static
+       @param {Array} queue Array of functions to call in sequence
+       @param {Function} cb Main callback that is called in the end, or in case of error
+       */
+       var inParallel = function(queue, cb) {
+               var count = 0, num = queue.length, cbArgs = new Array(num);
+
+               each(queue, function(fn, i) {
+                       fn(function(error) {
+                               if (error) {
+                                       return cb(error);
+                               }
+                               
+                               var args = [].slice.call(arguments);
+                               args.shift(); // strip error - undefined or not
+
+                               cbArgs[i] = args;
+                               count++;
+
+                               if (count === num) {
+                                       cbArgs.unshift(null);
+                                       cb.apply(this, cbArgs);
+                               } 
+                       });
+               });
+       };
+       
+       
+       /**
+       Find an element in array and return it's index if present, otherwise return -1.
+       
+       @method inArray
+       @static
+       @param {Mixed} needle Element to find
+       @param {Array} array
+       @return {Int} Index of the element, or -1 if not found
+       */
+       var inArray = function(needle, array) {
+               if (array) {
+                       if (Array.prototype.indexOf) {
+                               return Array.prototype.indexOf.call(array, needle);
+                       }
+               
+                       for (var i = 0, length = array.length; i < length; i++) {
+                               if (array[i] === needle) {
+                                       return i;
+                               }
+                       }
+               }
+               return -1;
+       };
+
+
+       /**
+       Returns elements of first array if they are not present in second. And false - otherwise.
+
+       @private
+       @method arrayDiff
+       @param {Array} needles
+       @param {Array} array
+       @return {Array|Boolean}
+       */
+       var arrayDiff = function(needles, array) {
+               var diff = [];
+
+               if (typeOf(needles) !== 'array') {
+                       needles = [needles];
+               }
+
+               if (typeOf(array) !== 'array') {
+                       array = [array];
+               }
+
+               for (var i in needles) {
+                       if (inArray(needles[i], array) === -1) {
+                               diff.push(needles[i]);
+                       }       
+               }
+               return diff.length ? diff : false;
+       };
+
+
+       /**
+       Find intersection of two arrays.
+
+       @private
+       @method arrayIntersect
+       @param {Array} array1
+       @param {Array} array2
+       @return {Array} Intersection of two arrays or null if there is none
+       */
+       var arrayIntersect = function(array1, array2) {
+               var result = [];
+               each(array1, function(item) {
+                       if (inArray(item, array2) !== -1) {
+                               result.push(item);
+                       }
+               });
+               return result.length ? result : null;
+       };
+       
+       
+       /**
+       Forces anything into an array.
+       
+       @method toArray
+       @static
+       @param {Object} obj Object with length field.
+       @return {Array} Array object containing all items.
+       */
+       var toArray = function(obj) {
+               var i, arr = [];
+
+               for (i = 0; i < obj.length; i++) {
+                       arr[i] = obj[i];
+               }
+
+               return arr;
+       };
+       
+                       
+       /**
+       Generates an unique ID. The only way a user would be able to get the same ID is if the two persons
+       at the same exact millisecond manage to get the same 5 random numbers between 0-65535; it also uses 
+       a counter so each ID is guaranteed to be unique for the given page. It is more probable for the earth 
+       to be hit with an asteroid.
+       
+       @method guid
+       @static
+       @param {String} prefix to prepend (by default 'o' will be prepended).
+       @method guid
+       @return {String} Virtually unique id.
+       */
+       var guid = (function() {
+               var counter = 0;
+               
+               return function(prefix) {
+                       var guid = new Date().getTime().toString(32), i;
+
+                       for (i = 0; i < 5; i++) {
+                               guid += Math.floor(Math.random() * 65535).toString(32);
+                       }
+                       
+                       return (prefix || 'o_') + guid + (counter++).toString(32);
+               };
+       }());
+       
+
+       /**
+       Trims white spaces around the string
+       
+       @method trim
+       @static
+       @param {String} str
+       @return {String}
+       */
+       var trim = function(str) {
+               if (!str) {
+                       return str;
+               }
+               return String.prototype.trim ? String.prototype.trim.call(str) : str.toString().replace(/^\s*/, '').replace(/\s*$/, '');
+       };
+
+
+       /**
+       Parses the specified size string into a byte value. For example 10kb becomes 10240.
+       
+       @method parseSizeStr
+       @static
+       @param {String/Number} size String to parse or number to just pass through.
+       @return {Number} Size in bytes.
+       */
+       var parseSizeStr = function(size) {
+               if (typeof(size) !== 'string') {
+                       return size;
+               }
+               
+               var muls = {
+                               t: 1099511627776,
+                               g: 1073741824,
+                               m: 1048576,
+                               k: 1024
+                       },
+                       mul;
+
+
+               size = /^([0-9\.]+)([tmgk]?)$/.exec(size.toLowerCase().replace(/[^0-9\.tmkg]/g, ''));
+               mul = size[2];
+               size = +size[1];
+               
+               if (muls.hasOwnProperty(mul)) {
+                       size *= muls[mul];
+               }
+               return Math.floor(size);
+       };
+
+
+       /**
+        * Pseudo sprintf implementation - simple way to replace tokens with specified values.
+        *
+        * @param {String} str String with tokens
+        * @return {String} String with replaced tokens
+        */
+       var sprintf = function(str) {
+               var args = [].slice.call(arguments, 1);
+
+               return str.replace(/%[a-z]/g, function() {
+                       var value = args.shift();
+                       return typeOf(value) !== 'undefined' ? value : '';
+               });
+       };
+       
+
+       return {
+               guid: guid,
+               typeOf: typeOf,
+               extend: extend,
+               each: each,
+               isEmptyObj: isEmptyObj,
+               inSeries: inSeries,
+               inParallel: inParallel,
+               inArray: inArray,
+               arrayDiff: arrayDiff,
+               arrayIntersect: arrayIntersect,
+               toArray: toArray,
+               trim: trim,
+               sprintf: sprintf,
+               parseSizeStr: parseSizeStr
+       };
+});
+
+// Included from: src/javascript/core/utils/Env.js
+
+/**
+ * Env.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+define("moxie/core/utils/Env", [
+       "moxie/core/utils/Basic"
+], function(Basic) {
+       
+       /**
+        * UAParser.js v0.7.7
+        * Lightweight JavaScript-based User-Agent string parser
+        * https://github.com/faisalman/ua-parser-js
+        *
+        * Copyright Â© 2012-2015 Faisal Salman <fyzlman@gmail.com>
+        * Dual licensed under GPLv2 & MIT
+        */
+       var UAParser = (function (undefined) {
+
+           //////////////
+           // Constants
+           /////////////
+
+
+           var EMPTY       = '',
+               UNKNOWN     = '?',
+               FUNC_TYPE   = 'function',
+               UNDEF_TYPE  = 'undefined',
+               OBJ_TYPE    = 'object',
+               MAJOR       = 'major',
+               MODEL       = 'model',
+               NAME        = 'name',
+               TYPE        = 'type',
+               VENDOR      = 'vendor',
+               VERSION     = 'version',
+               ARCHITECTURE= 'architecture',
+               CONSOLE     = 'console',
+               MOBILE      = 'mobile',
+               TABLET      = 'tablet';
+
+
+           ///////////
+           // Helper
+           //////////
+
+
+           var util = {
+               has : function (str1, str2) {
+                   return str2.toLowerCase().indexOf(str1.toLowerCase()) !== -1;
+               },
+               lowerize : function (str) {
+                   return str.toLowerCase();
+               }
+           };
+
+
+           ///////////////
+           // Map helper
+           //////////////
+
+
+           var mapper = {
+
+               rgx : function () {
+
+                   // loop through all regexes maps
+                   for (var result, i = 0, j, k, p, q, matches, match, args = arguments; i < args.length; i += 2) {
+
+                       var regex = args[i],       // even sequence (0,2,4,..)
+                           props = args[i + 1];   // odd sequence (1,3,5,..)
+
+                       // construct object barebones
+                       if (typeof(result) === UNDEF_TYPE) {
+                           result = {};
+                           for (p in props) {
+                               q = props[p];
+                               if (typeof(q) === OBJ_TYPE) {
+                                   result[q[0]] = undefined;
+                               } else {
+                                   result[q] = undefined;
+                               }
+                           }
+                       }
+
+                       // try matching uastring with regexes
+                       for (j = k = 0; j < regex.length; j++) {
+                           matches = regex[j].exec(this.getUA());
+                           if (!!matches) {
+                               for (p = 0; p < props.length; p++) {
+                                   match = matches[++k];
+                                   q = props[p];
+                                   // check if given property is actually array
+                                   if (typeof(q) === OBJ_TYPE && q.length > 0) {
+                                       if (q.length == 2) {
+                                           if (typeof(q[1]) == FUNC_TYPE) {
+                                               // assign modified match
+                                               result[q[0]] = q[1].call(this, match);
+                                           } else {
+                                               // assign given value, ignore regex match
+                                               result[q[0]] = q[1];
+                                           }
+                                       } else if (q.length == 3) {
+                                           // check whether function or regex
+                                           if (typeof(q[1]) === FUNC_TYPE && !(q[1].exec && q[1].test)) {
+                                               // call function (usually string mapper)
+                                               result[q[0]] = match ? q[1].call(this, match, q[2]) : undefined;
+                                           } else {
+                                               // sanitize match using given regex
+                                               result[q[0]] = match ? match.replace(q[1], q[2]) : undefined;
+                                           }
+                                       } else if (q.length == 4) {
+                                               result[q[0]] = match ? q[3].call(this, match.replace(q[1], q[2])) : undefined;
+                                       }
+                                   } else {
+                                       result[q] = match ? match : undefined;
+                                   }
+                               }
+                               break;
+                           }
+                       }
+
+                       if(!!matches) break; // break the loop immediately if match found
+                   }
+                   return result;
+               },
+
+               str : function (str, map) {
+
+                   for (var i in map) {
+                       // check if array
+                       if (typeof(map[i]) === OBJ_TYPE && map[i].length > 0) {
+                           for (var j = 0; j < map[i].length; j++) {
+                               if (util.has(map[i][j], str)) {
+                                   return (i === UNKNOWN) ? undefined : i;
+                               }
+                           }
+                       } else if (util.has(map[i], str)) {
+                           return (i === UNKNOWN) ? undefined : i;
+                       }
+                   }
+                   return str;
+               }
+           };
+
+
+           ///////////////
+           // String map
+           //////////////
+
+
+           var maps = {
+
+               browser : {
+                   oldsafari : {
+                       major : {
+                           '1' : ['/8', '/1', '/3'],
+                           '2' : '/4',
+                           '?' : '/'
+                       },
+                       version : {
+                           '1.0'   : '/8',
+                           '1.2'   : '/1',
+                           '1.3'   : '/3',
+                           '2.0'   : '/412',
+                           '2.0.2' : '/416',
+                           '2.0.3' : '/417',
+                           '2.0.4' : '/419',
+                           '?'     : '/'
+                       }
+                   }
+               },
+
+               device : {
+                   sprint : {
+                       model : {
+                           'Evo Shift 4G' : '7373KT'
+                       },
+                       vendor : {
+                           'HTC'       : 'APA',
+                           'Sprint'    : 'Sprint'
+                       }
+                   }
+               },
+
+               os : {
+                   windows : {
+                       version : {
+                           'ME'        : '4.90',
+                           'NT 3.11'   : 'NT3.51',
+                           'NT 4.0'    : 'NT4.0',
+                           '2000'      : 'NT 5.0',
+                           'XP'        : ['NT 5.1', 'NT 5.2'],
+                           'Vista'     : 'NT 6.0',
+                           '7'         : 'NT 6.1',
+                           '8'         : 'NT 6.2',
+                           '8.1'       : 'NT 6.3',
+                           'RT'        : 'ARM'
+                       }
+                   }
+               }
+           };
+
+
+           //////////////
+           // Regex map
+           /////////////
+
+
+           var regexes = {
+
+               browser : [[
+               
+                   // Presto based
+                   /(opera\smini)\/([\w\.-]+)/i,                                       // Opera Mini
+                   /(opera\s[mobiletab]+).+version\/([\w\.-]+)/i,                      // Opera Mobi/Tablet
+                   /(opera).+version\/([\w\.]+)/i,                                     // Opera > 9.80
+                   /(opera)[\/\s]+([\w\.]+)/i                                          // Opera < 9.80
+
+                   ], [NAME, VERSION], [
+
+                   /\s(opr)\/([\w\.]+)/i                                               // Opera Webkit
+                   ], [[NAME, 'Opera'], VERSION], [
+
+                   // Mixed
+                   /(kindle)\/([\w\.]+)/i,                                             // Kindle
+                   /(lunascape|maxthon|netfront|jasmine|blazer)[\/\s]?([\w\.]+)*/i,
+                                                                                       // Lunascape/Maxthon/Netfront/Jasmine/Blazer
+
+                   // Trident based
+                   /(avant\s|iemobile|slim|baidu)(?:browser)?[\/\s]?([\w\.]*)/i,
+                                                                                       // Avant/IEMobile/SlimBrowser/Baidu
+                   /(?:ms|\()(ie)\s([\w\.]+)/i,                                        // Internet Explorer
+
+                   // Webkit/KHTML based
+                   /(rekonq)\/([\w\.]+)*/i,                                            // Rekonq
+                   /(chromium|flock|rockmelt|midori|epiphany|silk|skyfire|ovibrowser|bolt|iron|vivaldi)\/([\w\.-]+)/i
+                                                                                       // Chromium/Flock/RockMelt/Midori/Epiphany/Silk/Skyfire/Bolt/Iron
+                   ], [NAME, VERSION], [
+
+                   /(trident).+rv[:\s]([\w\.]+).+like\sgecko/i                         // IE11
+                   ], [[NAME, 'IE'], VERSION], [
+
+                   /(edge)\/((\d+)?[\w\.]+)/i                                          // Microsoft Edge
+                   ], [NAME, VERSION], [
+
+                   /(yabrowser)\/([\w\.]+)/i                                           // Yandex
+                   ], [[NAME, 'Yandex'], VERSION], [
+
+                   /(comodo_dragon)\/([\w\.]+)/i                                       // Comodo Dragon
+                   ], [[NAME, /_/g, ' '], VERSION], [
+
+                   /(chrome|omniweb|arora|[tizenoka]{5}\s?browser)\/v?([\w\.]+)/i,
+                                                                                       // Chrome/OmniWeb/Arora/Tizen/Nokia
+                   /(uc\s?browser|qqbrowser)[\/\s]?([\w\.]+)/i
+                                                                                       // UCBrowser/QQBrowser
+                   ], [NAME, VERSION], [
+
+                   /(dolfin)\/([\w\.]+)/i                                              // Dolphin
+                   ], [[NAME, 'Dolphin'], VERSION], [
+
+                   /((?:android.+)crmo|crios)\/([\w\.]+)/i                             // Chrome for Android/iOS
+                   ], [[NAME, 'Chrome'], VERSION], [
+
+                   /XiaoMi\/MiuiBrowser\/([\w\.]+)/i                                   // MIUI Browser
+                   ], [VERSION, [NAME, 'MIUI Browser']], [
+
+                   /android.+version\/([\w\.]+)\s+(?:mobile\s?safari|safari)/i         // Android Browser
+                   ], [VERSION, [NAME, 'Android Browser']], [
+
+                   /FBAV\/([\w\.]+);/i                                                 // Facebook App for iOS
+                   ], [VERSION, [NAME, 'Facebook']], [
+
+                   /version\/([\w\.]+).+?mobile\/\w+\s(safari)/i                       // Mobile Safari
+                   ], [VERSION, [NAME, 'Mobile Safari']], [
+
+                   /version\/([\w\.]+).+?(mobile\s?safari|safari)/i                    // Safari & Safari Mobile
+                   ], [VERSION, NAME], [
+
+                   /webkit.+?(mobile\s?safari|safari)(\/[\w\.]+)/i                     // Safari < 3.0
+                   ], [NAME, [VERSION, mapper.str, maps.browser.oldsafari.version]], [
+
+                   /(konqueror)\/([\w\.]+)/i,                                          // Konqueror
+                   /(webkit|khtml)\/([\w\.]+)/i
+                   ], [NAME, VERSION], [
+
+                   // Gecko based
+                   /(navigator|netscape)\/([\w\.-]+)/i                                 // Netscape
+                   ], [[NAME, 'Netscape'], VERSION], [
+                   /(swiftfox)/i,                                                      // Swiftfox
+                   /(icedragon|iceweasel|camino|chimera|fennec|maemo\sbrowser|minimo|conkeror)[\/\s]?([\w\.\+]+)/i,
+                                                                                       // IceDragon/Iceweasel/Camino/Chimera/Fennec/Maemo/Minimo/Conkeror
+                   /(firefox|seamonkey|k-meleon|icecat|iceape|firebird|phoenix)\/([\w\.-]+)/i,
+                                                                                       // Firefox/SeaMonkey/K-Meleon/IceCat/IceApe/Firebird/Phoenix
+                   /(mozilla)\/([\w\.]+).+rv\:.+gecko\/\d+/i,                          // Mozilla
+
+                   // Other
+                   /(polaris|lynx|dillo|icab|doris|amaya|w3m|netsurf)[\/\s]?([\w\.]+)/i,
+                                                                                       // Polaris/Lynx/Dillo/iCab/Doris/Amaya/w3m/NetSurf
+                   /(links)\s\(([\w\.]+)/i,                                            // Links
+                   /(gobrowser)\/?([\w\.]+)*/i,                                        // GoBrowser
+                   /(ice\s?browser)\/v?([\w\._]+)/i,                                   // ICE Browser
+                   /(mosaic)[\/\s]([\w\.]+)/i                                          // Mosaic
+                   ], [NAME, VERSION]
+               ],
+
+               engine : [[
+
+                   /windows.+\sedge\/([\w\.]+)/i                                       // EdgeHTML
+                   ], [VERSION, [NAME, 'EdgeHTML']], [
+
+                   /(presto)\/([\w\.]+)/i,                                             // Presto
+                   /(webkit|trident|netfront|netsurf|amaya|lynx|w3m)\/([\w\.]+)/i,     // WebKit/Trident/NetFront/NetSurf/Amaya/Lynx/w3m
+                   /(khtml|tasman|links)[\/\s]\(?([\w\.]+)/i,                          // KHTML/Tasman/Links
+                   /(icab)[\/\s]([23]\.[\d\.]+)/i                                      // iCab
+                   ], [NAME, VERSION], [
+
+                   /rv\:([\w\.]+).*(gecko)/i                                           // Gecko
+                   ], [VERSION, NAME]
+               ],
+
+               os : [[
+
+                   // Windows based
+                   /microsoft\s(windows)\s(vista|xp)/i                                 // Windows (iTunes)
+                   ], [NAME, VERSION], [
+                   /(windows)\snt\s6\.2;\s(arm)/i,                                     // Windows RT
+                   /(windows\sphone(?:\sos)*|windows\smobile|windows)[\s\/]?([ntce\d\.\s]+\w)/i
+                   ], [NAME, [VERSION, mapper.str, maps.os.windows.version]], [
+                   /(win(?=3|9|n)|win\s9x\s)([nt\d\.]+)/i
+                   ], [[NAME, 'Windows'], [VERSION, mapper.str, maps.os.windows.version]], [
+
+                   // Mobile/Embedded OS
+                   /\((bb)(10);/i                                                      // BlackBerry 10
+                   ], [[NAME, 'BlackBerry'], VERSION], [
+                   /(blackberry)\w*\/?([\w\.]+)*/i,                                    // Blackberry
+                   /(tizen)[\/\s]([\w\.]+)/i,                                          // Tizen
+                   /(android|webos|palm\os|qnx|bada|rim\stablet\sos|meego|contiki)[\/\s-]?([\w\.]+)*/i,
+                                                                                       // Android/WebOS/Palm/QNX/Bada/RIM/MeeGo/Contiki
+                   /linux;.+(sailfish);/i                                              // Sailfish OS
+                   ], [NAME, VERSION], [
+                   /(symbian\s?os|symbos|s60(?=;))[\/\s-]?([\w\.]+)*/i                 // Symbian
+                   ], [[NAME, 'Symbian'], VERSION], [
+                   /\((series40);/i                                                    // Series 40
+                   ], [NAME], [
+                   /mozilla.+\(mobile;.+gecko.+firefox/i                               // Firefox OS
+                   ], [[NAME, 'Firefox OS'], VERSION], [
+
+                   // Console
+                   /(nintendo|playstation)\s([wids3portablevu]+)/i,                    // Nintendo/Playstation
+
+                   // GNU/Linux based
+                   /(mint)[\/\s\(]?(\w+)*/i,                                           // Mint
+                   /(mageia|vectorlinux)[;\s]/i,                                       // Mageia/VectorLinux
+                   /(joli|[kxln]?ubuntu|debian|[open]*suse|gentoo|arch|slackware|fedora|mandriva|centos|pclinuxos|redhat|zenwalk|linpus)[\/\s-]?([\w\.-]+)*/i,
+                                                                                       // Joli/Ubuntu/Debian/SUSE/Gentoo/Arch/Slackware
+                                                                                       // Fedora/Mandriva/CentOS/PCLinuxOS/RedHat/Zenwalk/Linpus
+                   /(hurd|linux)\s?([\w\.]+)*/i,                                       // Hurd/Linux
+                   /(gnu)\s?([\w\.]+)*/i                                               // GNU
+                   ], [NAME, VERSION], [
+
+                   /(cros)\s[\w]+\s([\w\.]+\w)/i                                       // Chromium OS
+                   ], [[NAME, 'Chromium OS'], VERSION],[
+
+                   // Solaris
+                   /(sunos)\s?([\w\.]+\d)*/i                                           // Solaris
+                   ], [[NAME, 'Solaris'], VERSION], [
+
+                   // BSD based
+                   /\s([frentopc-]{0,4}bsd|dragonfly)\s?([\w\.]+)*/i                   // FreeBSD/NetBSD/OpenBSD/PC-BSD/DragonFly
+                   ], [NAME, VERSION],[
+
+                   /(ip[honead]+)(?:.*os\s*([\w]+)*\slike\smac|;\sopera)/i             // iOS
+                   ], [[NAME, 'iOS'], [VERSION, /_/g, '.']], [
+
+                   /(mac\sos\sx)\s?([\w\s\.]+\w)*/i,
+                   /(macintosh|mac(?=_powerpc)\s)/i                                    // Mac OS
+                   ], [[NAME, 'Mac OS'], [VERSION, /_/g, '.']], [
+
+                   // Other
+                   /((?:open)?solaris)[\/\s-]?([\w\.]+)*/i,                            // Solaris
+                   /(haiku)\s(\w+)/i,                                                  // Haiku
+                   /(aix)\s((\d)(?=\.|\)|\s)[\w\.]*)*/i,                               // AIX
+                   /(plan\s9|minix|beos|os\/2|amigaos|morphos|risc\sos|openvms)/i,
+                                                                                       // Plan9/Minix/BeOS/OS2/AmigaOS/MorphOS/RISCOS/OpenVMS
+                   /(unix)\s?([\w\.]+)*/i                                              // UNIX
+                   ], [NAME, VERSION]
+               ]
+           };
+
+
+           /////////////////
+           // Constructor
+           ////////////////
+
+
+           var UAParser = function (uastring) {
+
+               var ua = uastring || ((window && window.navigator && window.navigator.userAgent) ? window.navigator.userAgent : EMPTY);
+
+               this.getBrowser = function () {
+                   return mapper.rgx.apply(this, regexes.browser);
+               };
+               this.getEngine = function () {
+                   return mapper.rgx.apply(this, regexes.engine);
+               };
+               this.getOS = function () {
+                   return mapper.rgx.apply(this, regexes.os);
+               };
+               this.getResult = function() {
+                   return {
+                       ua      : this.getUA(),
+                       browser : this.getBrowser(),
+                       engine  : this.getEngine(),
+                       os      : this.getOS()
+                   };
+               };
+               this.getUA = function () {
+                   return ua;
+               };
+               this.setUA = function (uastring) {
+                   ua = uastring;
+                   return this;
+               };
+               this.setUA(ua);
+           };
+
+           return UAParser;
+       })();
+
+
+       function version_compare(v1, v2, operator) {
+         // From: http://phpjs.org/functions
+         // +      original by: Philippe Jausions (http://pear.php.net/user/jausions)
+         // +      original by: Aidan Lister (http://aidanlister.com/)
+         // + reimplemented by: Kankrelune (http://www.webfaktory.info/)
+         // +      improved by: Brett Zamir (http://brett-zamir.me)
+         // +      improved by: Scott Baker
+         // +      improved by: Theriault
+         // *        example 1: version_compare('8.2.5rc', '8.2.5a');
+         // *        returns 1: 1
+         // *        example 2: version_compare('8.2.50', '8.2.52', '<');
+         // *        returns 2: true
+         // *        example 3: version_compare('5.3.0-dev', '5.3.0');
+         // *        returns 3: -1
+         // *        example 4: version_compare('4.1.0.52','4.01.0.51');
+         // *        returns 4: 1
+
+         // Important: compare must be initialized at 0.
+         var i = 0,
+           x = 0,
+           compare = 0,
+           // vm maps textual PHP versions to negatives so they're less than 0.
+           // PHP currently defines these as CASE-SENSITIVE. It is important to
+           // leave these as negatives so that they can come before numerical versions
+           // and as if no letters were there to begin with.
+           // (1alpha is < 1 and < 1.1 but > 1dev1)
+           // If a non-numerical value can't be mapped to this table, it receives
+           // -7 as its value.
+           vm = {
+             'dev': -6,
+             'alpha': -5,
+             'a': -5,
+             'beta': -4,
+             'b': -4,
+             'RC': -3,
+             'rc': -3,
+             '#': -2,
+             'p': 1,
+             'pl': 1
+           },
+           // This function will be called to prepare each version argument.
+           // It replaces every _, -, and + with a dot.
+           // It surrounds any nonsequence of numbers/dots with dots.
+           // It replaces sequences of dots with a single dot.
+           //    version_compare('4..0', '4.0') == 0
+           // Important: A string of 0 length needs to be converted into a value
+           // even less than an unexisting value in vm (-7), hence [-8].
+           // It's also important to not strip spaces because of this.
+           //   version_compare('', ' ') == 1
+           prepVersion = function (v) {
+             v = ('' + v).replace(/[_\-+]/g, '.');
+             v = v.replace(/([^.\d]+)/g, '.$1.').replace(/\.{2,}/g, '.');
+             return (!v.length ? [-8] : v.split('.'));
+           },
+           // This converts a version component to a number.
+           // Empty component becomes 0.
+           // Non-numerical component becomes a negative number.
+           // Numerical component becomes itself as an integer.
+           numVersion = function (v) {
+             return !v ? 0 : (isNaN(v) ? vm[v] || -7 : parseInt(v, 10));
+           };
+
+         v1 = prepVersion(v1);
+         v2 = prepVersion(v2);
+         x = Math.max(v1.length, v2.length);
+         for (i = 0; i < x; i++) {
+           if (v1[i] == v2[i]) {
+             continue;
+           }
+           v1[i] = numVersion(v1[i]);
+           v2[i] = numVersion(v2[i]);
+           if (v1[i] < v2[i]) {
+             compare = -1;
+             break;
+           } else if (v1[i] > v2[i]) {
+             compare = 1;
+             break;
+           }
+         }
+         if (!operator) {
+           return compare;
+         }
+
+         // Important: operator is CASE-SENSITIVE.
+         // "No operator" seems to be treated as "<."
+         // Any other values seem to make the function return null.
+         switch (operator) {
+         case '>':
+         case 'gt':
+           return (compare > 0);
+         case '>=':
+         case 'ge':
+           return (compare >= 0);
+         case '<=':
+         case 'le':
+           return (compare <= 0);
+         case '==':
+         case '=':
+         case 'eq':
+           return (compare === 0);
+         case '<>':
+         case '!=':
+         case 'ne':
+           return (compare !== 0);
+         case '':
+         case '<':
+         case 'lt':
+           return (compare < 0);
+         default:
+           return null;
+         }
+       }
+
+
+       var can = (function() {
+               var caps = {
+                               define_property: (function() {
+                                       /* // currently too much extra code required, not exactly worth it
+                                       try { // as of IE8, getters/setters are supported only on DOM elements
+                                               var obj = {};
+                                               if (Object.defineProperty) {
+                                                       Object.defineProperty(obj, 'prop', {
+                                                               enumerable: true,
+                                                               configurable: true
+                                                       });
+                                                       return true;
+                                               }
+                                       } catch(ex) {}
+
+                                       if (Object.prototype.__defineGetter__ && Object.prototype.__defineSetter__) {
+                                               return true;
+                                       }*/
+                                       return false;
+                               }()),
+
+                               create_canvas: (function() {
+                                       // On the S60 and BB Storm, getContext exists, but always returns undefined
+                                       // so we actually have to call getContext() to verify
+                                       // github.com/Modernizr/Modernizr/issues/issue/97/
+                                       var el = document.createElement('canvas');
+                                       return !!(el.getContext && el.getContext('2d'));
+                               }()),
+
+                               return_response_type: function(responseType) {
+                                       try {
+                                               if (Basic.inArray(responseType, ['', 'text', 'document']) !== -1) {
+                                                       return true;
+                                               } else if (window.XMLHttpRequest) {
+                                                       var xhr = new XMLHttpRequest();
+                                                       xhr.open('get', '/'); // otherwise Gecko throws an exception
+                                                       if ('responseType' in xhr) {
+                                                               xhr.responseType = responseType;
+                                                               // as of 23.0.1271.64, Chrome switched from throwing exception to merely logging it to the console (why? o why?)
+                                                               if (xhr.responseType !== responseType) {
+                                                                       return false;
+                                                               }
+                                                               return true;
+                                                       }
+                                               }
+                                       } catch (ex) {}
+                                       return false;
+                               },
+
+                               // ideas for this heavily come from Modernizr (http://modernizr.com/)
+                               use_data_uri: (function() {
+                                       var du = new Image();
+
+                                       du.onload = function() {
+                                               caps.use_data_uri = (du.width === 1 && du.height === 1);
+                                       };
+                                       
+                                       setTimeout(function() {
+                                               du.src = "data:image/gif;base64,R0lGODlhAQABAIAAAP8AAAAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==";
+                                       }, 1);
+                                       return false;
+                               }()),
+
+                               use_data_uri_over32kb: function() { // IE8
+                                       return caps.use_data_uri && (Env.browser !== 'IE' || Env.version >= 9);
+                               },
+
+                               use_data_uri_of: function(bytes) {
+                                       return (caps.use_data_uri && bytes < 33000 || caps.use_data_uri_over32kb());
+                               },
+
+                               use_fileinput: function() {
+                                       if (navigator.userAgent.match(/(Android (1.0|1.1|1.5|1.6|2.0|2.1))|(Windows Phone (OS 7|8.0))|(XBLWP)|(ZuneWP)|(w(eb)?OSBrowser)|(webOS)|(Kindle\/(1.0|2.0|2.5|3.0))/)) {
+                                               return false;
+                                       }
+
+                                       var el = document.createElement('input');
+                                       el.setAttribute('type', 'file');
+                                       return !el.disabled;
+                               }
+                       };
+
+               return function(cap) {
+                       var args = [].slice.call(arguments);
+                       args.shift(); // shift of cap
+                       return Basic.typeOf(caps[cap]) === 'function' ? caps[cap].apply(this, args) : !!caps[cap];
+               };
+       }());
+
+
+       var uaResult = new UAParser().getResult();
+
+
+       var Env = {
+               can: can,
+
+               uaParser: UAParser,
+               
+               browser: uaResult.browser.name,
+               version: uaResult.browser.version,
+               os: uaResult.os.name, // everybody intuitively types it in a lowercase for some reason
+               osVersion: uaResult.os.version,
+
+               verComp: version_compare,
+
+               global_event_dispatcher: "moxie.core.EventTarget.instance.dispatchEvent"
+       };
+
+       // for backward compatibility
+       // @deprecated Use `Env.os` instead
+       Env.OS = Env.os;
+
+       if (MXI_DEBUG) {
+               Env.debug = {
+                       runtime: true,
+                       events: false
+               };
+
+               Env.log = function() {
+                       
+                       function logObj(data) {
+                               // TODO: this should recursively print out the object in a pretty way
+                               console.appendChild(document.createTextNode(data + "\n"));
+                       }
+
+                       var data = arguments[0];
+
+                       if (Basic.typeOf(data) === 'string') {
+                               data = Basic.sprintf.apply(this, arguments);
+                       }
+
+                       if (window && window.console && window.console.log) {
+                               window.console.log(data);
+                       } else if (document) {
+                               var console = document.getElementById('moxie-console');
+                               if (!console) {
+                                       console = document.createElement('pre');
+                                       console.id = 'moxie-console';
+                                       //console.style.display = 'none';
+                                       document.body.appendChild(console);
+                               }
+
+                               if (Basic.inArray(Basic.typeOf(data), ['object', 'array']) !== -1) {
+                                       logObj(data);
+                               } else {
+                                       console.appendChild(document.createTextNode(data + "\n"));
+                               }
+                       }
+               };
+       }
+
+       return Env;
+});
+
+// Included from: src/javascript/core/I18n.js
+
+/**
+ * I18n.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+define("moxie/core/I18n", [
+       "moxie/core/utils/Basic"
+], function(Basic) {
+       var i18n = {};
+
+       return {
+               /**
+                * Extends the language pack object with new items.
+                *
+                * @param {Object} pack Language pack items to add.
+                * @return {Object} Extended language pack object.
+                */
+               addI18n: function(pack) {
+                       return Basic.extend(i18n, pack);
+               },
+
+               /**
+                * Translates the specified string by checking for the english string in the language pack lookup.
+                *
+                * @param {String} str String to look for.
+                * @return {String} Translated string or the input string if it wasn't found.
+                */
+               translate: function(str) {
+                       return i18n[str] || str;
+               },
+
+               /**
+                * Shortcut for translate function
+                *
+                * @param {String} str String to look for.
+                * @return {String} Translated string or the input string if it wasn't found.
+                */
+               _: function(str) {
+                       return this.translate(str);
+               },
+
+               /**
+                * Pseudo sprintf implementation - simple way to replace tokens with specified values.
+                *
+                * @param {String} str String with tokens
+                * @return {String} String with replaced tokens
+                */
+               sprintf: function(str) {
+                       var args = [].slice.call(arguments, 1);
+
+                       return str.replace(/%[a-z]/g, function() {
+                               var value = args.shift();
+                               return Basic.typeOf(value) !== 'undefined' ? value : '';
+                       });
+               }
+       };
+});
+
+// Included from: src/javascript/core/utils/Mime.js
+
+/**
+ * Mime.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+define("moxie/core/utils/Mime", [
+       "moxie/core/utils/Basic",
+       "moxie/core/I18n"
+], function(Basic, I18n) {
+       
+       var mimeData = "" +
+               "application/msword,doc dot," +
+               "application/pdf,pdf," +
+               "application/pgp-signature,pgp," +
+               "application/postscript,ps ai eps," +
+               "application/rtf,rtf," +
+               "application/vnd.ms-excel,xls xlb," +
+               "application/vnd.ms-powerpoint,ppt pps pot," +
+               "application/zip,zip," +
+               "application/x-shockwave-flash,swf swfl," +
+               "application/vnd.openxmlformats-officedocument.wordprocessingml.document,docx," +
+               "application/vnd.openxmlformats-officedocument.wordprocessingml.template,dotx," +
+               "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,xlsx," +
+               "application/vnd.openxmlformats-officedocument.presentationml.presentation,pptx," +
+               "application/vnd.openxmlformats-officedocument.presentationml.template,potx," +
+               "application/vnd.openxmlformats-officedocument.presentationml.slideshow,ppsx," +
+               "application/x-javascript,js," +
+               "application/json,json," +
+               "audio/mpeg,mp3 mpga mpega mp2," +
+               "audio/x-wav,wav," +
+               "audio/x-m4a,m4a," +
+               "audio/ogg,oga ogg," +
+               "audio/aiff,aiff aif," +
+               "audio/flac,flac," +
+               "audio/aac,aac," +
+               "audio/ac3,ac3," +
+               "audio/x-ms-wma,wma," +
+               "image/bmp,bmp," +
+               "image/gif,gif," +
+               "image/jpeg,jpg jpeg jpe," +
+               "image/photoshop,psd," +
+               "image/png,png," +
+               "image/svg+xml,svg svgz," +
+               "image/tiff,tiff tif," +
+               "text/plain,asc txt text diff log," +
+               "text/html,htm html xhtml," +
+               "text/css,css," +
+               "text/csv,csv," +
+               "text/rtf,rtf," +
+               "video/mpeg,mpeg mpg mpe m2v," +
+               "video/quicktime,qt mov," +
+               "video/mp4,mp4," +
+               "video/x-m4v,m4v," +
+               "video/x-flv,flv," +
+               "video/x-ms-wmv,wmv," +
+               "video/avi,avi," +
+               "video/webm,webm," +
+               "video/3gpp,3gpp 3gp," +
+               "video/3gpp2,3g2," +
+               "video/vnd.rn-realvideo,rv," +
+               "video/ogg,ogv," + 
+               "video/x-matroska,mkv," +
+               "application/vnd.oasis.opendocument.formula-template,otf," +
+               "application/octet-stream,exe";
+       
+       
+       var Mime = {
+
+               mimes: {},
+
+               extensions: {},
+
+               // Parses the default mime types string into a mimes and extensions lookup maps
+               addMimeType: function (mimeData) {
+                       var items = mimeData.split(/,/), i, ii, ext;
+                       
+                       for (i = 0; i < items.length; i += 2) {
+                               ext = items[i + 1].split(/ /);
+
+                               // extension to mime lookup
+                               for (ii = 0; ii < ext.length; ii++) {
+                                       this.mimes[ext[ii]] = items[i];
+                               }
+                               // mime to extension lookup
+                               this.extensions[items[i]] = ext;
+                       }
+               },
+
+
+               extList2mimes: function (filters, addMissingExtensions) {
+                       var self = this, ext, i, ii, type, mimes = [];
+                       
+                       // convert extensions to mime types list
+                       for (i = 0; i < filters.length; i++) {
+                               ext = filters[i].extensions.split(/\s*,\s*/);
+
+                               for (ii = 0; ii < ext.length; ii++) {
+                                       
+                                       // if there's an asterisk in the list, then accept attribute is not required
+                                       if (ext[ii] === '*') {
+                                               return [];
+                                       }
+
+                                       type = self.mimes[ext[ii]];
+                                       if (type && Basic.inArray(type, mimes) === -1) {
+                                               mimes.push(type);
+                                       }
+
+                                       // future browsers should filter by extension, finally
+                                       if (addMissingExtensions && /^\w+$/.test(ext[ii])) {
+                                               mimes.push('.' + ext[ii]);
+                                       } else if (!type) {
+                                               // if we have no type in our map, then accept all
+                                               return [];
+                                       }
+                               }
+                       }
+                       return mimes;
+               },
+
+
+               mimes2exts: function(mimes) {
+                       var self = this, exts = [];
+                       
+                       Basic.each(mimes, function(mime) {
+                               if (mime === '*') {
+                                       exts = [];
+                                       return false;
+                               }
+
+                               // check if this thing looks like mime type
+                               var m = mime.match(/^(\w+)\/(\*|\w+)$/);
+                               if (m) {
+                                       if (m[2] === '*') { 
+                                               // wildcard mime type detected
+                                               Basic.each(self.extensions, function(arr, mime) {
+                                                       if ((new RegExp('^' + m[1] + '/')).test(mime)) {
+                                                               [].push.apply(exts, self.extensions[mime]);
+                                                       }
+                                               });
+                                       } else if (self.extensions[mime]) {
+                                               [].push.apply(exts, self.extensions[mime]);
+                                       }
+                               }
+                       });
+                       return exts;
+               },
+
+
+               mimes2extList: function(mimes) {
+                       var accept = [], exts = [];
+
+                       if (Basic.typeOf(mimes) === 'string') {
+                               mimes = Basic.trim(mimes).split(/\s*,\s*/);
+                       }
+
+                       exts = this.mimes2exts(mimes);
+                       
+                       accept.push({
+                               title: I18n.translate('Files'),
+                               extensions: exts.length ? exts.join(',') : '*'
+                       });
+                       
+                       // save original mimes string
+                       accept.mimes = mimes;
+
+                       return accept;
+               },
+
+
+               getFileExtension: function(fileName) {
+                       var matches = fileName && fileName.match(/\.([^.]+)$/);
+                       if (matches) {
+                               return matches[1].toLowerCase();
+                       }
+                       return '';
+               },
+
+               getFileMime: function(fileName) {
+                       return this.mimes[this.getFileExtension(fileName)] || '';
+               }
+       };
+
+       Mime.addMimeType(mimeData);
+
+       return Mime;
+});
+
+// Included from: src/javascript/core/utils/Dom.js
+
+/**
+ * Dom.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+define('moxie/core/utils/Dom', ['moxie/core/utils/Env'], function(Env) {
+
+       /**
+       Get DOM Element by it's id.
+
+       @method get
+       @for Utils
+       @param {String} id Identifier of the DOM Element
+       @return {DOMElement}
+       */
+       var get = function(id) {
+               if (typeof id !== 'string') {
+                       return id;
+               }
+               return document.getElementById(id);
+       };
+
+       /**
+       Checks if specified DOM element has specified class.
+
+       @method hasClass
+       @static
+       @param {Object} obj DOM element like object to add handler to.
+       @param {String} name Class name
+       */
+       var hasClass = function(obj, name) {
+               if (!obj.className) {
+                       return false;
+               }
+
+               var regExp = new RegExp("(^|\\s+)"+name+"(\\s+|$)");
+               return regExp.test(obj.className);
+       };
+
+       /**
+       Adds specified className to specified DOM element.
+
+       @method addClass
+       @static
+       @param {Object} obj DOM element like object to add handler to.
+       @param {String} name Class name
+       */
+       var addClass = function(obj, name) {
+               if (!hasClass(obj, name)) {
+                       obj.className = !obj.className ? name : obj.className.replace(/\s+$/, '') + ' ' + name;
+               }
+       };
+
+       /**
+       Removes specified className from specified DOM element.
+
+       @method removeClass
+       @static
+       @param {Object} obj DOM element like object to add handler to.
+       @param {String} name Class name
+       */
+       var removeClass = function(obj, name) {
+               if (obj.className) {
+                       var regExp = new RegExp("(^|\\s+)"+name+"(\\s+|$)");
+                       obj.className = obj.className.replace(regExp, function($0, $1, $2) {
+                               return $1 === ' ' && $2 === ' ' ? ' ' : '';
+                       });
+               }
+       };
+
+       /**
+       Returns a given computed style of a DOM element.
+
+       @method getStyle
+       @static
+       @param {Object} obj DOM element like object.
+       @param {String} name Style you want to get from the DOM element
+       */
+       var getStyle = function(obj, name) {
+               if (obj.currentStyle) {
+                       return obj.currentStyle[name];
+               } else if (window.getComputedStyle) {
+                       return window.getComputedStyle(obj, null)[name];
+               }
+       };
+
+
+       /**
+       Returns the absolute x, y position of an Element. The position will be returned in a object with x, y fields.
+
+       @method getPos
+       @static
+       @param {Element} node HTML element or element id to get x, y position from.
+       @param {Element} root Optional root element to stop calculations at.
+       @return {object} Absolute position of the specified element object with x, y fields.
+       */
+       var getPos = function(node, root) {
+               var x = 0, y = 0, parent, doc = document, nodeRect, rootRect;
+
+               node = node;
+               root = root || doc.body;
+
+               // Returns the x, y cordinate for an element on IE 6 and IE 7
+               function getIEPos(node) {
+                       var bodyElm, rect, x = 0, y = 0;
+
+                       if (node) {
+                               rect = node.getBoundingClientRect();
+                               bodyElm = doc.compatMode === "CSS1Compat" ? doc.documentElement : doc.body;
+                               x = rect.left + bodyElm.scrollLeft;
+                               y = rect.top + bodyElm.scrollTop;
+                       }
+
+                       return {
+                               x : x,
+                               y : y
+                       };
+               }
+
+               // Use getBoundingClientRect on IE 6 and IE 7 but not on IE 8 in standards mode
+               if (node && node.getBoundingClientRect && Env.browser === 'IE' && (!doc.documentMode || doc.documentMode < 8)) {
+                       nodeRect = getIEPos(node);
+                       rootRect = getIEPos(root);
+
+                       return {
+                               x : nodeRect.x - rootRect.x,
+                               y : nodeRect.y - rootRect.y
+                       };
+               }
+
+               parent = node;
+               while (parent && parent != root && parent.nodeType) {
+                       x += parent.offsetLeft || 0;
+                       y += parent.offsetTop || 0;
+                       parent = parent.offsetParent;
+               }
+
+               parent = node.parentNode;
+               while (parent && parent != root && parent.nodeType) {
+                       x -= parent.scrollLeft || 0;
+                       y -= parent.scrollTop || 0;
+                       parent = parent.parentNode;
+               }
+
+               return {
+                       x : x,
+                       y : y
+               };
+       };
+
+       /**
+       Returns the size of the specified node in pixels.
+
+       @method getSize
+       @static
+       @param {Node} node Node to get the size of.
+       @return {Object} Object with a w and h property.
+       */
+       var getSize = function(node) {
+               return {
+                       w : node.offsetWidth || node.clientWidth,
+                       h : node.offsetHeight || node.clientHeight
+               };
+       };
+
+       return {
+               get: get,
+               hasClass: hasClass,
+               addClass: addClass,
+               removeClass: removeClass,
+               getStyle: getStyle,
+               getPos: getPos,
+               getSize: getSize
+       };
+});
+
+// Included from: src/javascript/core/Exceptions.js
+
+/**
+ * Exceptions.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+define('moxie/core/Exceptions', [
+       'moxie/core/utils/Basic'
+], function(Basic) {
+       function _findKey(obj, value) {
+               var key;
+               for (key in obj) {
+                       if (obj[key] === value) {
+                               return key;
+                       }
+               }
+               return null;
+       }
+
+       return {
+               RuntimeError: (function() {
+                       var namecodes = {
+                               NOT_INIT_ERR: 1,
+                               NOT_SUPPORTED_ERR: 9,
+                               JS_ERR: 4
+                       };
+
+                       function RuntimeError(code) {
+                               this.code = code;
+                               this.name = _findKey(namecodes, code);
+                               this.message = this.name + ": RuntimeError " + this.code;
+                       }
+                       
+                       Basic.extend(RuntimeError, namecodes);
+                       RuntimeError.prototype = Error.prototype;
+                       return RuntimeError;
+               }()),
+               
+               OperationNotAllowedException: (function() {
+                       
+                       function OperationNotAllowedException(code) {
+                               this.code = code;
+                               this.name = 'OperationNotAllowedException';
+                       }
+                       
+                       Basic.extend(OperationNotAllowedException, {
+                               NOT_ALLOWED_ERR: 1
+                       });
+                       
+                       OperationNotAllowedException.prototype = Error.prototype;
+                       
+                       return OperationNotAllowedException;
+               }()),
+
+               ImageError: (function() {
+                       var namecodes = {
+                               WRONG_FORMAT: 1,
+                               MAX_RESOLUTION_ERR: 2,
+                               INVALID_META_ERR: 3
+                       };
+
+                       function ImageError(code) {
+                               this.code = code;
+                               this.name = _findKey(namecodes, code);
+                               this.message = this.name + ": ImageError " + this.code;
+                       }
+                       
+                       Basic.extend(ImageError, namecodes);
+                       ImageError.prototype = Error.prototype;
+
+                       return ImageError;
+               }()),
+
+               FileException: (function() {
+                       var namecodes = {
+                               NOT_FOUND_ERR: 1,
+                               SECURITY_ERR: 2,
+                               ABORT_ERR: 3,
+                               NOT_READABLE_ERR: 4,
+                               ENCODING_ERR: 5,
+                               NO_MODIFICATION_ALLOWED_ERR: 6,
+                               INVALID_STATE_ERR: 7,
+                               SYNTAX_ERR: 8
+                       };
+
+                       function FileException(code) {
+                               this.code = code;
+                               this.name = _findKey(namecodes, code);
+                               this.message = this.name + ": FileException " + this.code;
+                       }
+                       
+                       Basic.extend(FileException, namecodes);
+                       FileException.prototype = Error.prototype;
+                       return FileException;
+               }()),
+               
+               DOMException: (function() {
+                       var namecodes = {
+                               INDEX_SIZE_ERR: 1,
+                               DOMSTRING_SIZE_ERR: 2,
+                               HIERARCHY_REQUEST_ERR: 3,
+                               WRONG_DOCUMENT_ERR: 4,
+                               INVALID_CHARACTER_ERR: 5,
+                               NO_DATA_ALLOWED_ERR: 6,
+                               NO_MODIFICATION_ALLOWED_ERR: 7,
+                               NOT_FOUND_ERR: 8,
+                               NOT_SUPPORTED_ERR: 9,
+                               INUSE_ATTRIBUTE_ERR: 10,
+                               INVALID_STATE_ERR: 11,
+                               SYNTAX_ERR: 12,
+                               INVALID_MODIFICATION_ERR: 13,
+                               NAMESPACE_ERR: 14,
+                               INVALID_ACCESS_ERR: 15,
+                               VALIDATION_ERR: 16,
+                               TYPE_MISMATCH_ERR: 17,
+                               SECURITY_ERR: 18,
+                               NETWORK_ERR: 19,
+                               ABORT_ERR: 20,
+                               URL_MISMATCH_ERR: 21,
+                               QUOTA_EXCEEDED_ERR: 22,
+                               TIMEOUT_ERR: 23,
+                               INVALID_NODE_TYPE_ERR: 24,
+                               DATA_CLONE_ERR: 25
+                       };
+
+                       function DOMException(code) {
+                               this.code = code;
+                               this.name = _findKey(namecodes, code);
+                               this.message = this.name + ": DOMException " + this.code;
+                       }
+                       
+                       Basic.extend(DOMException, namecodes);
+                       DOMException.prototype = Error.prototype;
+                       return DOMException;
+               }()),
+               
+               EventException: (function() {
+                       function EventException(code) {
+                               this.code = code;
+                               this.name = 'EventException';
+                       }
+                       
+                       Basic.extend(EventException, {
+                               UNSPECIFIED_EVENT_TYPE_ERR: 0
+                       });
+                       
+                       EventException.prototype = Error.prototype;
+                       
+                       return EventException;
+               }())
+       };
+});
+
+// Included from: src/javascript/core/EventTarget.js
+
+/**
+ * EventTarget.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+define('moxie/core/EventTarget', [
+       'moxie/core/utils/Env',
+       'moxie/core/Exceptions',
+       'moxie/core/utils/Basic'
+], function(Env, x, Basic) {
+       /**
+       Parent object for all event dispatching components and objects
+
+       @class EventTarget
+       @constructor EventTarget
+       */
+       function EventTarget() {
+               // hash of event listeners by object uid
+               var eventpool = {};
+                               
+               Basic.extend(this, {
+                       
+                       /**
+                       Unique id of the event dispatcher, usually overriden by children
+
+                       @property uid
+                       @type String
+                       */
+                       uid: null,
+                       
+                       /**
+                       Can be called from within a child  in order to acquire uniqie id in automated manner
+
+                       @method init
+                       */
+                       init: function() {
+                               if (!this.uid) {
+                                       this.uid = Basic.guid('uid_');
+                               }
+                       },
+
+                       /**
+                       Register a handler to a specific event dispatched by the object
+
+                       @method addEventListener
+                       @param {String} type Type or basically a name of the event to subscribe to
+                       @param {Function} fn Callback function that will be called when event happens
+                       @param {Number} [priority=0] Priority of the event handler - handlers with higher priorities will be called first
+                       @param {Object} [scope=this] A scope to invoke event handler in
+                       */
+                       addEventListener: function(type, fn, priority, scope) {
+                               var self = this, list;
+
+                               // without uid no event handlers can be added, so make sure we got one
+                               if (!this.hasOwnProperty('uid')) {
+                                       this.uid = Basic.guid('uid_');
+                               }
+                               
+                               type = Basic.trim(type);
+                               
+                               if (/\s/.test(type)) {
+                                       // multiple event types were passed for one handler
+                                       Basic.each(type.split(/\s+/), function(type) {
+                                               self.addEventListener(type, fn, priority, scope);
+                                       });
+                                       return;
+                               }
+                               
+                               type = type.toLowerCase();
+                               priority = parseInt(priority, 10) || 0;
+                               
+                               list = eventpool[this.uid] && eventpool[this.uid][type] || [];
+                               list.push({fn : fn, priority : priority, scope : scope || this});
+                               
+                               if (!eventpool[this.uid]) {
+                                       eventpool[this.uid] = {};
+                               }
+                               eventpool[this.uid][type] = list;
+                       },
+                       
+                       /**
+                       Check if any handlers were registered to the specified event
+
+                       @method hasEventListener
+                       @param {String} type Type or basically a name of the event to check
+                       @return {Mixed} Returns a handler if it was found and false, if - not
+                       */
+                       hasEventListener: function(type) {
+                               var list = type ? eventpool[this.uid] && eventpool[this.uid][type] : eventpool[this.uid];
+                               return list ? list : false;
+                       },
+                       
+                       /**
+                       Unregister the handler from the event, or if former was not specified - unregister all handlers
+
+                       @method removeEventListener
+                       @param {String} type Type or basically a name of the event
+                       @param {Function} [fn] Handler to unregister
+                       */
+                       removeEventListener: function(type, fn) {
+                               type = type.toLowerCase();
+       
+                               var list = eventpool[this.uid] && eventpool[this.uid][type], i;
+       
+                               if (list) {
+                                       if (fn) {
+                                               for (i = list.length - 1; i >= 0; i--) {
+                                                       if (list[i].fn === fn) {
+                                                               list.splice(i, 1);
+                                                               break;
+                                                       }
+                                               }
+                                       } else {
+                                               list = [];
+                                       }
+       
+                                       // delete event list if it has become empty
+                                       if (!list.length) {
+                                               delete eventpool[this.uid][type];
+                                               
+                                               // and object specific entry in a hash if it has no more listeners attached
+                                               if (Basic.isEmptyObj(eventpool[this.uid])) {
+                                                       delete eventpool[this.uid];
+                                               }
+                                       }
+                               }
+                       },
+                       
+                       /**
+                       Remove all event handlers from the object
+
+                       @method removeAllEventListeners
+                       */
+                       removeAllEventListeners: function() {
+                               if (eventpool[this.uid]) {
+                                       delete eventpool[this.uid];
+                               }
+                       },
+                       
+                       /**
+                       Dispatch the event
+
+                       @method dispatchEvent
+                       @param {String/Object} Type of event or event object to dispatch
+                       @param {Mixed} [...] Variable number of arguments to be passed to a handlers
+                       @return {Boolean} true by default and false if any handler returned false
+                       */
+                       dispatchEvent: function(type) {
+                               var uid, list, args, tmpEvt, evt = {}, result = true, undef;
+                               
+                               if (Basic.typeOf(type) !== 'string') {
+                                       // we can't use original object directly (because of Silverlight)
+                                       tmpEvt = type;
+
+                                       if (Basic.typeOf(tmpEvt.type) === 'string') {
+                                               type = tmpEvt.type;
+
+                                               if (tmpEvt.total !== undef && tmpEvt.loaded !== undef) { // progress event
+                                                       evt.total = tmpEvt.total;
+                                                       evt.loaded = tmpEvt.loaded;
+                                               }
+                                               evt.async = tmpEvt.async || false;
+                                       } else {
+                                               throw new x.EventException(x.EventException.UNSPECIFIED_EVENT_TYPE_ERR);
+                                       }
+                               }
+                               
+                               // check if event is meant to be dispatched on an object having specific uid
+                               if (type.indexOf('::') !== -1) {
+                                       (function(arr) {
+                                               uid = arr[0];
+                                               type = arr[1];
+                                       }(type.split('::')));
+                               } else {
+                                       uid = this.uid;
+                               }
+                               
+                               type = type.toLowerCase();
+                                                               
+                               list = eventpool[uid] && eventpool[uid][type];
+
+                               if (list) {
+                                       // sort event list by prority
+                                       list.sort(function(a, b) { return b.priority - a.priority; });
+                                       
+                                       args = [].slice.call(arguments);
+                                       
+                                       // first argument will be pseudo-event object
+                                       args.shift();
+                                       evt.type = type;
+                                       args.unshift(evt);
+
+                                       if (MXI_DEBUG && Env.debug.events) {
+                                               Env.log("Event '%s' fired on %u", evt.type, uid);     
+                                       }
+
+                                       // Dispatch event to all listeners
+                                       var queue = [];
+                                       Basic.each(list, function(handler) {
+                                               // explicitly set the target, otherwise events fired from shims do not get it
+                                               args[0].target = handler.scope;
+                                               // if event is marked as async, detach the handler
+                                               if (evt.async) {
+                                                       queue.push(function(cb) {
+                                                               setTimeout(function() {
+                                                                       cb(handler.fn.apply(handler.scope, args) === false);
+                                                               }, 1);
+                                                       });
+                                               } else {
+                                                       queue.push(function(cb) {
+                                                               cb(handler.fn.apply(handler.scope, args) === false); // if handler returns false stop propagation
+                                                       });
+                                               }
+                                       });
+                                       if (queue.length) {
+                                               Basic.inSeries(queue, function(err) {
+                                                       result = !err;
+                                               });
+                                       }
+                               }
+                               return result;
+                       },
+                       
+                       /**
+                       Alias for addEventListener
+
+                       @method bind
+                       @protected
+                       */
+                       bind: function() {
+                               this.addEventListener.apply(this, arguments);
+                       },
+                       
+                       /**
+                       Alias for removeEventListener
+
+                       @method unbind
+                       @protected
+                       */
+                       unbind: function() {
+                               this.removeEventListener.apply(this, arguments);
+                       },
+                       
+                       /**
+                       Alias for removeAllEventListeners
+
+                       @method unbindAll
+                       @protected
+                       */
+                       unbindAll: function() {
+                               this.removeAllEventListeners.apply(this, arguments);
+                       },
+                       
+                       /**
+                       Alias for dispatchEvent
+
+                       @method trigger
+                       @protected
+                       */
+                       trigger: function() {
+                               return this.dispatchEvent.apply(this, arguments);
+                       },
+                       
+
+                       /**
+                       Handle properties of on[event] type.
+
+                       @method handleEventProps
+                       @private
+                       */
+                       handleEventProps: function(dispatches) {
+                               var self = this;
+
+                               this.bind(dispatches.join(' '), function(e) {
+                                       var prop = 'on' + e.type.toLowerCase();
+                                       if (Basic.typeOf(this[prop]) === 'function') {
+                                               this[prop].apply(this, arguments);
+                                       }
+                               });
+
+                               // object must have defined event properties, even if it doesn't make use of them
+                               Basic.each(dispatches, function(prop) {
+                                       prop = 'on' + prop.toLowerCase(prop);
+                                       if (Basic.typeOf(self[prop]) === 'undefined') {
+                                               self[prop] = null; 
+                                       }
+                               });
+                       }
+                       
+               });
+       }
+
+       EventTarget.instance = new EventTarget(); 
+
+       return EventTarget;
+});
+
+// Included from: src/javascript/runtime/Runtime.js
+
+/**
+ * Runtime.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+define('moxie/runtime/Runtime', [
+       "moxie/core/utils/Env",
+       "moxie/core/utils/Basic",
+       "moxie/core/utils/Dom",
+       "moxie/core/EventTarget"
+], function(Env, Basic, Dom, EventTarget) {
+       var runtimeConstructors = {}, runtimes = {};
+
+       /**
+       Common set of methods and properties for every runtime instance
+
+       @class Runtime
+
+       @param {Object} options
+       @param {String} type Sanitized name of the runtime
+       @param {Object} [caps] Set of capabilities that differentiate specified runtime
+       @param {Object} [modeCaps] Set of capabilities that do require specific operational mode
+       @param {String} [preferredMode='browser'] Preferred operational mode to choose if no required capabilities were requested
+       */
+       function Runtime(options, type, caps, modeCaps, preferredMode) {
+               /**
+               Dispatched when runtime is initialized and ready.
+               Results in RuntimeInit on a connected component.
+
+               @event Init
+               */
+
+               /**
+               Dispatched when runtime fails to initialize.
+               Results in RuntimeError on a connected component.
+
+               @event Error
+               */
+
+               var self = this
+               , _shim
+               , _uid = Basic.guid(type + '_')
+               , defaultMode = preferredMode || 'browser'
+               ;
+
+               options = options || {};
+
+               // register runtime in private hash
+               runtimes[_uid] = this;
+
+               /**
+               Default set of capabilities, which can be redifined later by specific runtime
+
+               @private
+               @property caps
+               @type Object
+               */
+               caps = Basic.extend({
+                       // Runtime can: 
+                       // provide access to raw binary data of the file
+                       access_binary: false,
+                       // provide access to raw binary data of the image (image extension is optional) 
+                       access_image_binary: false,
+                       // display binary data as thumbs for example
+                       display_media: false,
+                       // make cross-domain requests
+                       do_cors: false,
+                       // accept files dragged and dropped from the desktop
+                       drag_and_drop: false,
+                       // filter files in selection dialog by their extensions
+                       filter_by_extension: true,
+                       // resize image (and manipulate it raw data of any file in general)
+                       resize_image: false,
+                       // periodically report how many bytes of total in the file were uploaded (loaded)
+                       report_upload_progress: false,
+                       // provide access to the headers of http response 
+                       return_response_headers: false,
+                       // support response of specific type, which should be passed as an argument
+                       // e.g. runtime.can('return_response_type', 'blob')
+                       return_response_type: false,
+                       // return http status code of the response
+                       return_status_code: true,
+                       // send custom http header with the request
+                       send_custom_headers: false,
+                       // pick up the files from a dialog
+                       select_file: false,
+                       // select whole folder in file browse dialog
+                       select_folder: false,
+                       // select multiple files at once in file browse dialog
+                       select_multiple: true,
+                       // send raw binary data, that is generated after image resizing or manipulation of other kind
+                       send_binary_string: false,
+                       // send cookies with http request and therefore retain session
+                       send_browser_cookies: true,
+                       // send data formatted as multipart/form-data
+                       send_multipart: true,
+                       // slice the file or blob to smaller parts
+                       slice_blob: false,
+                       // upload file without preloading it to memory, stream it out directly from disk
+                       stream_upload: false,
+                       // programmatically trigger file browse dialog
+                       summon_file_dialog: false,
+                       // upload file of specific size, size should be passed as argument
+                       // e.g. runtime.can('upload_filesize', '500mb')
+                       upload_filesize: true,
+                       // initiate http request with specific http method, method should be passed as argument
+                       // e.g. runtime.can('use_http_method', 'put')
+                       use_http_method: true
+               }, caps);
+                       
+       
+               // default to the mode that is compatible with preferred caps
+               if (options.preferred_caps) {
+                       defaultMode = Runtime.getMode(modeCaps, options.preferred_caps, defaultMode);
+               }
+
+               if (MXI_DEBUG && Env.debug.runtime) {
+                       Env.log("\tdefault mode: %s", defaultMode);   
+               }
+               
+               // small extension factory here (is meant to be extended with actual extensions constructors)
+               _shim = (function() {
+                       var objpool = {};
+                       return {
+                               exec: function(uid, comp, fn, args) {
+                                       if (_shim[comp]) {
+                                               if (!objpool[uid]) {
+                                                       objpool[uid] = {
+                                                               context: this,
+                                                               instance: new _shim[comp]()
+                                                       };
+                                               }
+                                               if (objpool[uid].instance[fn]) {
+                                                       return objpool[uid].instance[fn].apply(this, args);
+                                               }
+                                       }
+                               },
+
+                               removeInstance: function(uid) {
+                                       delete objpool[uid];
+                               },
+
+                               removeAllInstances: function() {
+                                       var self = this;
+                                       Basic.each(objpool, function(obj, uid) {
+                                               if (Basic.typeOf(obj.instance.destroy) === 'function') {
+                                                       obj.instance.destroy.call(obj.context);
+                                               }
+                                               self.removeInstance(uid);
+                                       });
+                               }
+                       };
+               }());
+
+
+               // public methods
+               Basic.extend(this, {
+                       /**
+                       Specifies whether runtime instance was initialized or not
+
+                       @property initialized
+                       @type {Boolean}
+                       @default false
+                       */
+                       initialized: false, // shims require this flag to stop initialization retries
+
+                       /**
+                       Unique ID of the runtime
+
+                       @property uid
+                       @type {String}
+                       */
+                       uid: _uid,
+
+                       /**
+                       Runtime type (e.g. flash, html5, etc)
+
+                       @property type
+                       @type {String}
+                       */
+                       type: type,
+
+                       /**
+                       Runtime (not native one) may operate in browser or client mode.
+
+                       @property mode
+                       @private
+                       @type {String|Boolean} current mode or false, if none possible
+                       */
+                       mode: Runtime.getMode(modeCaps, (options.required_caps), defaultMode),
+
+                       /**
+                       id of the DOM container for the runtime (if available)
+
+                       @property shimid
+                       @type {String}
+                       */
+                       shimid: _uid + '_container',
+
+                       /**
+                       Number of connected clients. If equal to zero, runtime can be destroyed
+
+                       @property clients
+                       @type {Number}
+                       */
+                       clients: 0,
+
+                       /**
+                       Runtime initialization options
+
+                       @property options
+                       @type {Object}
+                       */
+                       options: options,
+
+                       /**
+                       Checks if the runtime has specific capability
+
+                       @method can
+                       @param {String} cap Name of capability to check
+                       @param {Mixed} [value] If passed, capability should somehow correlate to the value
+                       @param {Object} [refCaps] Set of capabilities to check the specified cap against (defaults to internal set)
+                       @return {Boolean} true if runtime has such capability and false, if - not
+                       */
+                       can: function(cap, value) {
+                               var refCaps = arguments[2] || caps;
+
+                               // if cap var is a comma-separated list of caps, convert it to object (key/value)
+                               if (Basic.typeOf(cap) === 'string' && Basic.typeOf(value) === 'undefined') {
+                                       cap = Runtime.parseCaps(cap);
+                               }
+
+                               if (Basic.typeOf(cap) === 'object') {
+                                       for (var key in cap) {
+                                               if (!this.can(key, cap[key], refCaps)) {
+                                                       return false;
+                                               }
+                                       }
+                                       return true;
+                               }
+
+                               // check the individual cap
+                               if (Basic.typeOf(refCaps[cap]) === 'function') {
+                                       return refCaps[cap].call(this, value);
+                               } else {
+                                       return (value === refCaps[cap]);
+                               }
+                       },
+
+                       /**
+                       Returns container for the runtime as DOM element
+
+                       @method getShimContainer
+                       @return {DOMElement}
+                       */
+                       getShimContainer: function() {
+                               var container, shimContainer = Dom.get(this.shimid);
+
+                               // if no container for shim, create one
+                               if (!shimContainer) {
+                                       container = this.options.container ? Dom.get(this.options.container) : document.body;
+
+                                       // create shim container and insert it at an absolute position into the outer container
+                                       shimContainer = document.createElement('div');
+                                       shimContainer.id = this.shimid;
+                                       shimContainer.className = 'moxie-shim moxie-shim-' + this.type;
+
+                                       Basic.extend(shimContainer.style, {
+                                               position: 'absolute',
+                                               top: '0px',
+                                               left: '0px',
+                                               width: '1px',
+                                               height: '1px',
+                                               overflow: 'hidden'
+                                       });
+
+                                       container.appendChild(shimContainer);
+                                       container = null;
+                               }
+
+                               return shimContainer;
+                       },
+
+                       /**
+                       Returns runtime as DOM element (if appropriate)
+
+                       @method getShim
+                       @return {DOMElement}
+                       */
+                       getShim: function() {
+                               return _shim;
+                       },
+
+                       /**
+                       Invokes a method within the runtime itself (might differ across the runtimes)
+
+                       @method shimExec
+                       @param {Mixed} []
+                       @protected
+                       @return {Mixed} Depends on the action and component
+                       */
+                       shimExec: function(component, action) {
+                               var args = [].slice.call(arguments, 2);
+                               return self.getShim().exec.call(this, this.uid, component, action, args);
+                       },
+
+                       /**
+                       Operaional interface that is used by components to invoke specific actions on the runtime
+                       (is invoked in the scope of component)
+
+                       @method exec
+                       @param {Mixed} []*
+                       @protected
+                       @return {Mixed} Depends on the action and component
+                       */
+                       exec: function(component, action) { // this is called in the context of component, not runtime
+                               var args = [].slice.call(arguments, 2);
+
+                               if (self[component] && self[component][action]) {
+                                       return self[component][action].apply(this, args);
+                               }
+                               return self.shimExec.apply(this, arguments);
+                       },
+
+                       /**
+                       Destroys the runtime (removes all events and deletes DOM structures)
+
+                       @method destroy
+                       */
+                       destroy: function() {
+                               if (!self) {
+                                       return; // obviously already destroyed
+                               }
+
+                               var shimContainer = Dom.get(this.shimid);
+                               if (shimContainer) {
+                                       shimContainer.parentNode.removeChild(shimContainer);
+                               }
+
+                               if (_shim) {
+                                       _shim.removeAllInstances();
+                               }
+
+                               this.unbindAll();
+                               delete runtimes[this.uid];
+                               this.uid = null; // mark this runtime as destroyed
+                               _uid = self = _shim = shimContainer = null;
+                       }
+               });
+
+               // once we got the mode, test against all caps
+               if (this.mode && options.required_caps && !this.can(options.required_caps)) {
+                       this.mode = false;
+               }       
+       }
+
+
+       /**
+       Default order to try different runtime types
+
+       @property order
+       @type String
+       @static
+       */
+       Runtime.order = 'html5,html4';
+
+
+       /**
+       Retrieves runtime from private hash by it's uid
+
+       @method getRuntime
+       @private
+       @static
+       @param {String} uid Unique identifier of the runtime
+       @return {Runtime|Boolean} Returns runtime, if it exists and false, if - not
+       */
+       Runtime.getRuntime = function(uid) {
+               return runtimes[uid] ? runtimes[uid] : false;
+       };
+
+
+       /**
+       Register constructor for the Runtime of new (or perhaps modified) type
+
+       @method addConstructor
+       @static
+       @param {String} type Runtime type (e.g. flash, html5, etc)
+       @param {Function} construct Constructor for the Runtime type
+       */
+       Runtime.addConstructor = function(type, constructor) {
+               constructor.prototype = EventTarget.instance;
+               runtimeConstructors[type] = constructor;
+       };
+
+
+       /**
+       Get the constructor for the specified type.
+
+       method getConstructor
+       @static
+       @param {String} type Runtime type (e.g. flash, html5, etc)
+       @return {Function} Constructor for the Runtime type
+       */
+       Runtime.getConstructor = function(type) {
+               return runtimeConstructors[type] || null;
+       };
+
+
+       /**
+       Get info about the runtime (uid, type, capabilities)
+
+       @method getInfo
+       @static
+       @param {String} uid Unique identifier of the runtime
+       @return {Mixed} Info object or null if runtime doesn't exist
+       */
+       Runtime.getInfo = function(uid) {
+               var runtime = Runtime.getRuntime(uid);
+
+               if (runtime) {
+                       return {
+                               uid: runtime.uid,
+                               type: runtime.type,
+                               mode: runtime.mode,
+                               can: function() {
+                                       return runtime.can.apply(runtime, arguments);
+                               }
+                       };
+               }
+               return null;
+       };
+
+
+       /**
+       Convert caps represented by a comma-separated string to the object representation.
+
+       @method parseCaps
+       @static
+       @param {String} capStr Comma-separated list of capabilities
+       @return {Object}
+       */
+       Runtime.parseCaps = function(capStr) {
+               var capObj = {};
+
+               if (Basic.typeOf(capStr) !== 'string') {
+                       return capStr || {};
+               }
+
+               Basic.each(capStr.split(','), function(key) {
+                       capObj[key] = true; // we assume it to be - true
+               });
+
+               return capObj;
+       };
+
+       /**
+       Test the specified runtime for specific capabilities.
+
+       @method can
+       @static
+       @param {String} type Runtime type (e.g. flash, html5, etc)
+       @param {String|Object} caps Set of capabilities to check
+       @return {Boolean} Result of the test
+       */
+       Runtime.can = function(type, caps) {
+               var runtime
+               , constructor = Runtime.getConstructor(type)
+               , mode
+               ;
+               if (constructor) {
+                       runtime = new constructor({
+                               required_caps: caps
+                       });
+                       mode = runtime.mode;
+                       runtime.destroy();
+                       return !!mode;
+               }
+               return false;
+       };
+
+
+       /**
+       Figure out a runtime that supports specified capabilities.
+
+       @method thatCan
+       @static
+       @param {String|Object} caps Set of capabilities to check
+       @param {String} [runtimeOrder] Comma-separated list of runtimes to check against
+       @return {String} Usable runtime identifier or null
+       */
+       Runtime.thatCan = function(caps, runtimeOrder) {
+               var types = (runtimeOrder || Runtime.order).split(/\s*,\s*/);
+               for (var i in types) {
+                       if (Runtime.can(types[i], caps)) {
+                               return types[i];
+                       }
+               }
+               return null;
+       };
+
+
+       /**
+       Figure out an operational mode for the specified set of capabilities.
+
+       @method getMode
+       @static
+       @param {Object} modeCaps Set of capabilities that depend on particular runtime mode
+       @param {Object} [requiredCaps] Supplied set of capabilities to find operational mode for
+       @param {String|Boolean} [defaultMode='browser'] Default mode to use 
+       @return {String|Boolean} Compatible operational mode
+       */
+       Runtime.getMode = function(modeCaps, requiredCaps, defaultMode) {
+               var mode = null;
+
+               if (Basic.typeOf(defaultMode) === 'undefined') { // only if not specified
+                       defaultMode = 'browser';
+               }
+
+               if (requiredCaps && !Basic.isEmptyObj(modeCaps)) {
+                       // loop over required caps and check if they do require the same mode
+                       Basic.each(requiredCaps, function(value, cap) {
+                               if (modeCaps.hasOwnProperty(cap)) {
+                                       var capMode = modeCaps[cap](value);
+
+                                       // make sure we always have an array
+                                       if (typeof(capMode) === 'string') {
+                                               capMode = [capMode];
+                                       }
+                                       
+                                       if (!mode) {
+                                               mode = capMode;                                         
+                                       } else if (!(mode = Basic.arrayIntersect(mode, capMode))) {
+                                               // if cap requires conflicting mode - runtime cannot fulfill required caps
+
+                                               if (MXI_DEBUG && Env.debug.runtime) {
+                                                       Env.log("\t\t%c: %v (conflicting mode requested: %s)", cap, value, capMode);  
+                                               }
+
+                                               return (mode = false);
+                                       }                                       
+                               }
+
+                               if (MXI_DEBUG && Env.debug.runtime) {
+                                       Env.log("\t\t%c: %v (compatible modes: %s)", cap, value, mode);       
+                               }
+                       });
+
+                       if (mode) {
+                               return Basic.inArray(defaultMode, mode) !== -1 ? defaultMode : mode[0];
+                       } else if (mode === false) {
+                               return false;
+                       }
+               }
+               return defaultMode; 
+       };
+
+
+       /**
+       Capability check that always returns true
+
+       @private
+       @static
+       @return {True}
+       */
+       Runtime.capTrue = function() {
+               return true;
+       };
+
+       /**
+       Capability check that always returns false
+
+       @private
+       @static
+       @return {False}
+       */
+       Runtime.capFalse = function() {
+               return false;
+       };
+
+       /**
+       Evaluate the expression to boolean value and create a function that always returns it.
+
+       @private
+       @static
+       @param {Mixed} expr Expression to evaluate
+       @return {Function} Function returning the result of evaluation
+       */
+       Runtime.capTest = function(expr) {
+               return function() {
+                       return !!expr;
+               };
+       };
+
+       return Runtime;
+});
+
+// Included from: src/javascript/runtime/RuntimeClient.js
+
+/**
+ * RuntimeClient.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+define('moxie/runtime/RuntimeClient', [
+       'moxie/core/utils/Env',
+       'moxie/core/Exceptions',
+       'moxie/core/utils/Basic',
+       'moxie/runtime/Runtime'
+], function(Env, x, Basic, Runtime) {
+       /**
+       Set of methods and properties, required by a component to acquire ability to connect to a runtime
+
+       @class RuntimeClient
+       */
+       return function RuntimeClient() {
+               var runtime;
+
+               Basic.extend(this, {
+                       /**
+                       Connects to the runtime specified by the options. Will either connect to existing runtime or create a new one.
+                       Increments number of clients connected to the specified runtime.
+
+                       @private
+                       @method connectRuntime
+                       @param {Mixed} options Can be a runtme uid or a set of key-value pairs defining requirements and pre-requisites
+                       */
+                       connectRuntime: function(options) {
+                               var comp = this, ruid;
+
+                               function initialize(items) {
+                                       var type, constructor;
+
+                                       // if we ran out of runtimes
+                                       if (!items.length) {
+                                               comp.trigger('RuntimeError', new x.RuntimeError(x.RuntimeError.NOT_INIT_ERR));
+                                               runtime = null;
+                                               return;
+                                       }
+
+                                       type = items.shift().toLowerCase();
+                                       constructor = Runtime.getConstructor(type);
+                                       if (!constructor) {
+                                               initialize(items);
+                                               return;
+                                       }
+
+                                       if (MXI_DEBUG && Env.debug.runtime) {
+                                               Env.log("Trying runtime: %s", type);
+                                               Env.log(options);
+                                       }
+
+                                       // try initializing the runtime
+                                       runtime = new constructor(options);
+
+                                       runtime.bind('Init', function() {
+                                               // mark runtime as initialized
+                                               runtime.initialized = true;
+
+                                               if (MXI_DEBUG && Env.debug.runtime) {
+                                                       Env.log("Runtime '%s' initialized", runtime.type);
+                                               }
+
+                                               // jailbreak ...
+                                               setTimeout(function() {
+                                                       runtime.clients++;
+                                                       // this will be triggered on component
+                                                       comp.trigger('RuntimeInit', runtime);
+                                               }, 1);
+                                       });
+
+                                       runtime.bind('Error', function() {
+                                               if (MXI_DEBUG && Env.debug.runtime) {
+                                                       Env.log("Runtime '%s' failed to initialize", runtime.type);
+                                               }
+
+                                               runtime.destroy(); // runtime cannot destroy itself from inside at a right moment, thus we do it here
+                                               initialize(items);
+                                       });
+
+                                       /*runtime.bind('Exception', function() { });*/
+
+                                       if (MXI_DEBUG && Env.debug.runtime) {
+                                               Env.log("\tselected mode: %s", runtime.mode); 
+                                       }
+
+                                       // check if runtime managed to pick-up operational mode
+                                       if (!runtime.mode) {
+                                               runtime.trigger('Error');
+                                               return;
+                                       }
+
+                                       runtime.init();
+                               }
+
+                               // check if a particular runtime was requested
+                               if (Basic.typeOf(options) === 'string') {
+                                       ruid = options;
+                               } else if (Basic.typeOf(options.ruid) === 'string') {
+                                       ruid = options.ruid;
+                               }
+
+                               if (ruid) {
+                                       runtime = Runtime.getRuntime(ruid);
+                                       if (runtime) {
+                                               runtime.clients++;
+                                               return runtime;
+                                       } else {
+                                               // there should be a runtime and there's none - weird case
+                                               throw new x.RuntimeError(x.RuntimeError.NOT_INIT_ERR);
+                                       }
+                               }
+
+                               // initialize a fresh one, that fits runtime list and required features best
+                               initialize((options.runtime_order || Runtime.order).split(/\s*,\s*/));
+                       },
+
+
+                       /**
+                       Disconnects from the runtime. Decrements number of clients connected to the specified runtime.
+
+                       @private
+                       @method disconnectRuntime
+                       */
+                       disconnectRuntime: function() {
+                               if (runtime && --runtime.clients <= 0) {
+                                       runtime.destroy();
+                               }
+
+                               // once the component is disconnected, it shouldn't have access to the runtime
+                               runtime = null;
+                       },
+
+
+                       /**
+                       Returns the runtime to which the client is currently connected.
+
+                       @method getRuntime
+                       @return {Runtime} Runtime or null if client is not connected
+                       */
+                       getRuntime: function() {
+                               if (runtime && runtime.uid) {
+                                       return runtime;
+                               }
+                               return runtime = null; // make sure we do not leave zombies rambling around
+                       },
+
+
+                       /**
+                       Handy shortcut to safely invoke runtime extension methods.
+                       
+                       @private
+                       @method exec
+                       @return {Mixed} Whatever runtime extension method returns
+                       */
+                       exec: function() {
+                               if (runtime) {
+                                       return runtime.exec.apply(this, arguments);
+                               }
+                               return null;
+                       }
+
+               });
+       };
+
+
+});
+
+// Included from: src/javascript/file/FileInput.js
+
+/**
+ * FileInput.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+define('moxie/file/FileInput', [
+       'moxie/core/utils/Basic',
+       'moxie/core/utils/Env',
+       'moxie/core/utils/Mime',
+       'moxie/core/utils/Dom',
+       'moxie/core/Exceptions',
+       'moxie/core/EventTarget',
+       'moxie/core/I18n',
+       'moxie/runtime/Runtime',
+       'moxie/runtime/RuntimeClient'
+], function(Basic, Env, Mime, Dom, x, EventTarget, I18n, Runtime, RuntimeClient) {
+       /**
+       Provides a convenient way to create cross-browser file-picker. Generates file selection dialog on click,
+       converts selected files to _File_ objects, to be used in conjunction with _Image_, preloaded in memory
+       with _FileReader_ or uploaded to a server through _XMLHttpRequest_.
+
+       @class FileInput
+       @constructor
+       @extends EventTarget
+       @uses RuntimeClient
+       @param {Object|String|DOMElement} options If options is string or node, argument is considered as _browse\_button_.
+               @param {String|DOMElement} options.browse_button DOM Element to turn into file picker.
+               @param {Array} [options.accept] Array of mime types to accept. By default accepts all.
+               @param {String} [options.file='file'] Name of the file field (not the filename).
+               @param {Boolean} [options.multiple=false] Enable selection of multiple files.
+               @param {Boolean} [options.directory=false] Turn file input into the folder input (cannot be both at the same time).
+               @param {String|DOMElement} [options.container] DOM Element to use as a container for file-picker. Defaults to parentNode 
+               for _browse\_button_.
+               @param {Object|String} [options.required_caps] Set of required capabilities, that chosen runtime must support.
+
+       @example
+               <div id="container">
+                       <a id="file-picker" href="javascript:;">Browse...</a>
+               </div>
+
+               <script>
+                       var fileInput = new mOxie.FileInput({
+                               browse_button: 'file-picker', // or document.getElementById('file-picker')
+                               container: 'container',
+                               accept: [
+                                       {title: "Image files", extensions: "jpg,gif,png"} // accept only images
+                               ],
+                               multiple: true // allow multiple file selection
+                       });
+
+                       fileInput.onchange = function(e) {
+                               // do something to files array
+                               console.info(e.target.files); // or this.files or fileInput.files
+                       };
+
+                       fileInput.init(); // initialize
+               </script>
+       */
+       var dispatches = [
+               /**
+               Dispatched when runtime is connected and file-picker is ready to be used.
+
+               @event ready
+               @param {Object} event
+               */
+               'ready',
+
+               /**
+               Dispatched right after [ready](#event_ready) event, and whenever [refresh()](#method_refresh) is invoked. 
+               Check [corresponding documentation entry](#method_refresh) for more info.
+
+               @event refresh
+               @param {Object} event
+               */
+
+               /**
+               Dispatched when selection of files in the dialog is complete.
+
+               @event change
+               @param {Object} event
+               */
+               'change',
+
+               'cancel', // TODO: might be useful
+
+               /**
+               Dispatched when mouse cursor enters file-picker area. Can be used to style element
+               accordingly.
+
+               @event mouseenter
+               @param {Object} event
+               */
+               'mouseenter',
+
+               /**
+               Dispatched when mouse cursor leaves file-picker area. Can be used to style element
+               accordingly.
+
+               @event mouseleave
+               @param {Object} event
+               */
+               'mouseleave',
+
+               /**
+               Dispatched when functional mouse button is pressed on top of file-picker area.
+
+               @event mousedown
+               @param {Object} event
+               */
+               'mousedown',
+
+               /**
+               Dispatched when functional mouse button is released on top of file-picker area.
+
+               @event mouseup
+               @param {Object} event
+               */
+               'mouseup'
+       ];
+
+       function FileInput(options) {
+               if (MXI_DEBUG) {
+                       Env.log("Instantiating FileInput...");        
+               }
+
+               var self = this,
+                       container, browseButton, defaults;
+
+               // if flat argument passed it should be browse_button id
+               if (Basic.inArray(Basic.typeOf(options), ['string', 'node']) !== -1) {
+                       options = { browse_button : options };
+               }
+
+               // this will help us to find proper default container
+               browseButton = Dom.get(options.browse_button);
+               if (!browseButton) {
+                       // browse button is required
+                       throw new x.DOMException(x.DOMException.NOT_FOUND_ERR);
+               }
+
+               // figure out the options
+               defaults = {
+                       accept: [{
+                               title: I18n.translate('All Files'),
+                               extensions: '*'
+                       }],
+                       name: 'file',
+                       multiple: false,
+                       required_caps: false,
+                       container: browseButton.parentNode || document.body
+               };
+               
+               options = Basic.extend({}, defaults, options);
+
+               // convert to object representation
+               if (typeof(options.required_caps) === 'string') {
+                       options.required_caps = Runtime.parseCaps(options.required_caps);
+               }
+                                       
+               // normalize accept option (could be list of mime types or array of title/extensions pairs)
+               if (typeof(options.accept) === 'string') {
+                       options.accept = Mime.mimes2extList(options.accept);
+               }
+
+               container = Dom.get(options.container);
+               // make sure we have container
+               if (!container) {
+                       container = document.body;
+               }
+
+               // make container relative, if it's not
+               if (Dom.getStyle(container, 'position') === 'static') {
+                       container.style.position = 'relative';
+               }
+
+               container = browseButton = null; // IE
+                                               
+               RuntimeClient.call(self);
+               
+               Basic.extend(self, {
+                       /**
+                       Unique id of the component
+
+                       @property uid
+                       @protected
+                       @readOnly
+                       @type {String}
+                       @default UID
+                       */
+                       uid: Basic.guid('uid_'),
+                       
+                       /**
+                       Unique id of the connected runtime, if any.
+
+                       @property ruid
+                       @protected
+                       @type {String}
+                       */
+                       ruid: null,
+
+                       /**
+                       Unique id of the runtime container. Useful to get hold of it for various manipulations.
+
+                       @property shimid
+                       @protected
+                       @type {String}
+                       */
+                       shimid: null,
+                       
+                       /**
+                       Array of selected mOxie.File objects
+
+                       @property files
+                       @type {Array}
+                       @default null
+                       */
+                       files: null,
+
+                       /**
+                       Initializes the file-picker, connects it to runtime and dispatches event ready when done.
+
+                       @method init
+                       */
+                       init: function() {
+                               self.bind('RuntimeInit', function(e, runtime) {
+                                       self.ruid = runtime.uid;
+                                       self.shimid = runtime.shimid;
+
+                                       self.bind("Ready", function() {
+                                               self.trigger("Refresh");
+                                       }, 999);
+
+                                       // re-position and resize shim container
+                                       self.bind('Refresh', function() {
+                                               var pos, size, browseButton, shimContainer;
+                                               
+                                               browseButton = Dom.get(options.browse_button);
+                                               shimContainer = Dom.get(runtime.shimid); // do not use runtime.getShimContainer(), since it will create container if it doesn't exist
+
+                                               if (browseButton) {
+                                                       pos = Dom.getPos(browseButton, Dom.get(options.container));
+                                                       size = Dom.getSize(browseButton);
+
+                                                       if (shimContainer) {
+                                                               Basic.extend(shimContainer.style, {
+                                                                       top     : pos.y + 'px',
+                                                                       left    : pos.x + 'px',
+                                                                       width   : size.w + 'px',
+                                                                       height  : size.h + 'px'
+                                                               });
+                                                       }
+                                               }
+                                               shimContainer = browseButton = null;
+                                       });
+                                       
+                                       runtime.exec.call(self, 'FileInput', 'init', options);
+                               });
+
+                               // runtime needs: options.required_features, options.runtime_order and options.container
+                               self.connectRuntime(Basic.extend({}, options, {
+                                       required_caps: {
+                                               select_file: true
+                                       }
+                               }));
+                       },
+
+                       /**
+                       Disables file-picker element, so that it doesn't react to mouse clicks.
+
+                       @method disable
+                       @param {Boolean} [state=true] Disable component if - true, enable if - false
+                       */
+                       disable: function(state) {
+                               var runtime = this.getRuntime();
+                               if (runtime) {
+                                       runtime.exec.call(this, 'FileInput', 'disable', Basic.typeOf(state) === 'undefined' ? true : state);
+                               }
+                       },
+
+
+                       /**
+                       Reposition and resize dialog trigger to match the position and size of browse_button element.
+
+                       @method refresh
+                       */
+                       refresh: function() {
+                               self.trigger("Refresh");
+                       },
+
+
+                       /**
+                       Destroy component.
+
+                       @method destroy
+                       */
+                       destroy: function() {
+                               var runtime = this.getRuntime();
+                               if (runtime) {
+                                       runtime.exec.call(this, 'FileInput', 'destroy');
+                                       this.disconnectRuntime();
+                               }
+
+                               if (Basic.typeOf(this.files) === 'array') {
+                                       // no sense in leaving associated files behind
+                                       Basic.each(this.files, function(file) {
+                                               file.destroy();
+                                       });
+                               } 
+                               this.files = null;
+
+                               this.unbindAll();
+                       }
+               });
+
+               this.handleEventProps(dispatches);
+       }
+
+       FileInput.prototype = EventTarget.instance;
+
+       return FileInput;
+});
+
+// Included from: src/javascript/core/utils/Encode.js
+
+/**
+ * Encode.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+define('moxie/core/utils/Encode', [], function() {
+
+       /**
+       Encode string with UTF-8
+
+       @method utf8_encode
+       @for Utils
+       @static
+       @param {String} str String to encode
+       @return {String} UTF-8 encoded string
+       */
+       var utf8_encode = function(str) {
+               return unescape(encodeURIComponent(str));
+       };
+       
+       /**
+       Decode UTF-8 encoded string
+
+       @method utf8_decode
+       @static
+       @param {String} str String to decode
+       @return {String} Decoded string
+       */
+       var utf8_decode = function(str_data) {
+               return decodeURIComponent(escape(str_data));
+       };
+       
+       /**
+       Decode Base64 encoded string (uses browser's default method if available),
+       from: https://raw.github.com/kvz/phpjs/master/functions/url/base64_decode.js
+
+       @method atob
+       @static
+       @param {String} data String to decode
+       @return {String} Decoded string
+       */
+       var atob = function(data, utf8) {
+               if (typeof(window.atob) === 'function') {
+                       return utf8 ? utf8_decode(window.atob(data)) : window.atob(data);
+               }
+
+               // http://kevin.vanzonneveld.net
+               // +   original by: Tyler Akins (http://rumkin.com)
+               // +   improved by: Thunder.m
+               // +      input by: Aman Gupta
+               // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
+               // +   bugfixed by: Onno Marsman
+               // +   bugfixed by: Pellentesque Malesuada
+               // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
+               // +      input by: Brett Zamir (http://brett-zamir.me)
+               // +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
+               // *     example 1: base64_decode('S2V2aW4gdmFuIFpvbm5ldmVsZA==');
+               // *     returns 1: 'Kevin van Zonneveld'
+               // mozilla has this native
+               // - but breaks in 2.0.0.12!
+               //if (typeof this.window.atob == 'function') {
+               //    return atob(data);
+               //}
+               var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
+               var o1, o2, o3, h1, h2, h3, h4, bits, i = 0,
+                       ac = 0,
+                       dec = "",
+                       tmp_arr = [];
+
+               if (!data) {
+                       return data;
+               }
+
+               data += '';
+
+               do { // unpack four hexets into three octets using index points in b64
+                       h1 = b64.indexOf(data.charAt(i++));
+                       h2 = b64.indexOf(data.charAt(i++));
+                       h3 = b64.indexOf(data.charAt(i++));
+                       h4 = b64.indexOf(data.charAt(i++));
+
+                       bits = h1 << 18 | h2 << 12 | h3 << 6 | h4;
+
+                       o1 = bits >> 16 & 0xff;
+                       o2 = bits >> 8 & 0xff;
+                       o3 = bits & 0xff;
+
+                       if (h3 == 64) {
+                               tmp_arr[ac++] = String.fromCharCode(o1);
+                       } else if (h4 == 64) {
+                               tmp_arr[ac++] = String.fromCharCode(o1, o2);
+                       } else {
+                               tmp_arr[ac++] = String.fromCharCode(o1, o2, o3);
+                       }
+               } while (i < data.length);
+
+               dec = tmp_arr.join('');
+
+               return utf8 ? utf8_decode(dec) : dec;
+       };
+       
+       /**
+       Base64 encode string (uses browser's default method if available),
+       from: https://raw.github.com/kvz/phpjs/master/functions/url/base64_encode.js
+
+       @method btoa
+       @static
+       @param {String} data String to encode
+       @return {String} Base64 encoded string
+       */
+       var btoa = function(data, utf8) {
+               if (utf8) {
+                       data = utf8_encode(data);
+               }
+
+               if (typeof(window.btoa) === 'function') {
+                       return window.btoa(data);
+               }
+
+               // http://kevin.vanzonneveld.net
+               // +   original by: Tyler Akins (http://rumkin.com)
+               // +   improved by: Bayron Guevara
+               // +   improved by: Thunder.m
+               // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
+               // +   bugfixed by: Pellentesque Malesuada
+               // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
+               // +   improved by: RafaÅ‚ Kukawski (http://kukawski.pl)
+               // *     example 1: base64_encode('Kevin van Zonneveld');
+               // *     returns 1: 'S2V2aW4gdmFuIFpvbm5ldmVsZA=='
+               // mozilla has this native
+               // - but breaks in 2.0.0.12!
+               var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
+               var o1, o2, o3, h1, h2, h3, h4, bits, i = 0,
+                       ac = 0,
+                       enc = "",
+                       tmp_arr = [];
+
+               if (!data) {
+                       return data;
+               }
+
+               do { // pack three octets into four hexets
+                       o1 = data.charCodeAt(i++);
+                       o2 = data.charCodeAt(i++);
+                       o3 = data.charCodeAt(i++);
+
+                       bits = o1 << 16 | o2 << 8 | o3;
+
+                       h1 = bits >> 18 & 0x3f;
+                       h2 = bits >> 12 & 0x3f;
+                       h3 = bits >> 6 & 0x3f;
+                       h4 = bits & 0x3f;
+
+                       // use hexets to index into b64, and append result to encoded string
+                       tmp_arr[ac++] = b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4);
+               } while (i < data.length);
+
+               enc = tmp_arr.join('');
+
+               var r = data.length % 3;
+
+               return (r ? enc.slice(0, r - 3) : enc) + '==='.slice(r || 3);
+       };
+
+
+       return {
+               utf8_encode: utf8_encode,
+               utf8_decode: utf8_decode,
+               atob: atob,
+               btoa: btoa
+       };
+});
+
+// Included from: src/javascript/file/Blob.js
+
+/**
+ * Blob.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+define('moxie/file/Blob', [
+       'moxie/core/utils/Basic',
+       'moxie/core/utils/Encode',
+       'moxie/runtime/RuntimeClient'
+], function(Basic, Encode, RuntimeClient) {
+       
+       var blobpool = {};
+
+       /**
+       @class Blob
+       @constructor
+       @param {String} ruid Unique id of the runtime, to which this blob belongs to
+       @param {Object} blob Object "Native" blob object, as it is represented in the runtime
+       */
+       function Blob(ruid, blob) {
+
+               function _sliceDetached(start, end, type) {
+                       var blob, data = blobpool[this.uid];
+
+                       if (Basic.typeOf(data) !== 'string' || !data.length) {
+                               return null; // or throw exception
+                       }
+
+                       blob = new Blob(null, {
+                               type: type,
+                               size: end - start
+                       });
+                       blob.detach(data.substr(start, blob.size));
+
+                       return blob;
+               }
+
+               RuntimeClient.call(this);
+
+               if (ruid) {     
+                       this.connectRuntime(ruid);
+               }
+
+               if (!blob) {
+                       blob = {};
+               } else if (Basic.typeOf(blob) === 'string') { // dataUrl or binary string
+                       blob = { data: blob };
+               }
+
+               Basic.extend(this, {
+                       
+                       /**
+                       Unique id of the component
+
+                       @property uid
+                       @type {String}
+                       */
+                       uid: blob.uid || Basic.guid('uid_'),
+                       
+                       /**
+                       Unique id of the connected runtime, if falsy, then runtime will have to be initialized 
+                       before this Blob can be used, modified or sent
+
+                       @property ruid
+                       @type {String}
+                       */
+                       ruid: ruid,
+       
+                       /**
+                       Size of blob
+
+                       @property size
+                       @type {Number}
+                       @default 0
+                       */
+                       size: blob.size || 0,
+                       
+                       /**
+                       Mime type of blob
+
+                       @property type
+                       @type {String}
+                       @default ''
+                       */
+                       type: blob.type || '',
+                       
+                       /**
+                       @method slice
+                       @param {Number} [start=0]
+                       */
+                       slice: function(start, end, type) {             
+                               if (this.isDetached()) {
+                                       return _sliceDetached.apply(this, arguments);
+                               }
+                               return this.getRuntime().exec.call(this, 'Blob', 'slice', this.getSource(), start, end, type);
+                       },
+
+                       /**
+                       Returns "native" blob object (as it is represented in connected runtime) or null if not found
+
+                       @method getSource
+                       @return {Blob} Returns "native" blob object or null if not found
+                       */
+                       getSource: function() {
+                               if (!blobpool[this.uid]) {
+                                       return null;    
+                               }
+                               return blobpool[this.uid];
+                       },
+
+                       /** 
+                       Detaches blob from any runtime that it depends on and initialize with standalone value
+
+                       @method detach
+                       @protected
+                       @param {DOMString} [data=''] Standalone value
+                       */
+                       detach: function(data) {
+                               if (this.ruid) {
+                                       this.getRuntime().exec.call(this, 'Blob', 'destroy');
+                                       this.disconnectRuntime();
+                                       this.ruid = null;
+                               }
+
+                               data = data || '';
+
+                               // if dataUrl, convert to binary string
+                               if (data.substr(0, 5) == 'data:') {
+                                       var base64Offset = data.indexOf(';base64,');
+                                       this.type = data.substring(5, base64Offset);
+                                       data = Encode.atob(data.substring(base64Offset + 8));
+                               }
+
+                               this.size = data.length;
+
+                               blobpool[this.uid] = data;
+                       },
+
+                       /**
+                       Checks if blob is standalone (detached of any runtime)
+                       
+                       @method isDetached
+                       @protected
+                       @return {Boolean}
+                       */
+                       isDetached: function() {
+                               return !this.ruid && Basic.typeOf(blobpool[this.uid]) === 'string';
+                       },
+                       
+                       /** 
+                       Destroy Blob and free any resources it was using
+
+                       @method destroy
+                       */
+                       destroy: function() {
+                               this.detach();
+                               delete blobpool[this.uid];
+                       }
+               });
+
+               
+               if (blob.data) {
+                       this.detach(blob.data); // auto-detach if payload has been passed
+               } else {
+                       blobpool[this.uid] = blob;      
+               }
+       }
+       
+       return Blob;
+});
+
+// Included from: src/javascript/file/File.js
+
+/**
+ * File.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+define('moxie/file/File', [
+       'moxie/core/utils/Basic',
+       'moxie/core/utils/Mime',
+       'moxie/file/Blob'
+], function(Basic, Mime, Blob) {
+       /**
+       @class File
+       @extends Blob
+       @constructor
+       @param {String} ruid Unique id of the runtime, to which this blob belongs to
+       @param {Object} file Object "Native" file object, as it is represented in the runtime
+       */
+       function File(ruid, file) {
+               if (!file) { // avoid extra errors in case we overlooked something
+                       file = {};
+               }
+
+               Blob.apply(this, arguments);
+
+               if (!this.type) {
+                       this.type = Mime.getFileMime(file.name);
+               }
+
+               // sanitize file name or generate new one
+               var name;
+               if (file.name) {
+                       name = file.name.replace(/\\/g, '/');
+                       name = name.substr(name.lastIndexOf('/') + 1);
+               } else if (this.type) {
+                       var prefix = this.type.split('/')[0];
+                       name = Basic.guid((prefix !== '' ? prefix : 'file') + '_');
+                       
+                       if (Mime.extensions[this.type]) {
+                               name += '.' + Mime.extensions[this.type][0]; // append proper extension if possible
+                       }
+               }
+               
+               
+               Basic.extend(this, {
+                       /**
+                       File name
+
+                       @property name
+                       @type {String}
+                       @default UID
+                       */
+                       name: name || Basic.guid('file_'),
+
+                       /**
+                       Relative path to the file inside a directory
+
+                       @property relativePath
+                       @type {String}
+                       @default ''
+                       */
+                       relativePath: '',
+                       
+                       /**
+                       Date of last modification
+
+                       @property lastModifiedDate
+                       @type {String}
+                       @default now
+                       */
+                       lastModifiedDate: file.lastModifiedDate || (new Date()).toLocaleString() // Thu Aug 23 2012 19:40:00 GMT+0400 (GET)
+               });
+       }
+
+       File.prototype = Blob.prototype;
+
+       return File;
+});
+
+// Included from: src/javascript/file/FileDrop.js
+
+/**
+ * FileDrop.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+define('moxie/file/FileDrop', [
+       'moxie/core/I18n',
+       'moxie/core/utils/Dom',
+       'moxie/core/Exceptions',
+       'moxie/core/utils/Basic',
+       'moxie/core/utils/Env',
+       'moxie/file/File',
+       'moxie/runtime/RuntimeClient',
+       'moxie/core/EventTarget',
+       'moxie/core/utils/Mime'
+], function(I18n, Dom, x, Basic, Env, File, RuntimeClient, EventTarget, Mime) {
+       /**
+       Turn arbitrary DOM element to a drop zone accepting files. Converts selected files to _File_ objects, to be used 
+       in conjunction with _Image_, preloaded in memory with _FileReader_ or uploaded to a server through 
+       _XMLHttpRequest_.
+
+       @example
+               <div id="drop_zone">
+                       Drop files here
+               </div>
+               <br />
+               <div id="filelist"></div>
+
+               <script type="text/javascript">
+                       var fileDrop = new mOxie.FileDrop('drop_zone'), fileList = mOxie.get('filelist');
+
+                       fileDrop.ondrop = function() {
+                               mOxie.each(this.files, function(file) {
+                                       fileList.innerHTML += '<div>' + file.name + '</div>';
+                               });
+                       };
+
+                       fileDrop.init();
+               </script>
+
+       @class FileDrop
+       @constructor
+       @extends EventTarget
+       @uses RuntimeClient
+       @param {Object|String} options If options has typeof string, argument is considered as options.drop_zone
+               @param {String|DOMElement} options.drop_zone DOM Element to turn into a drop zone
+               @param {Array} [options.accept] Array of mime types to accept. By default accepts all
+               @param {Object|String} [options.required_caps] Set of required capabilities, that chosen runtime must support
+       */
+       var dispatches = [
+               /**
+               Dispatched when runtime is connected and drop zone is ready to accept files.
+
+               @event ready
+               @param {Object} event
+               */
+               'ready', 
+
+               /**
+               Dispatched when dragging cursor enters the drop zone.
+
+               @event dragenter
+               @param {Object} event
+               */
+               'dragenter',
+
+               /**
+               Dispatched when dragging cursor leaves the drop zone.
+
+               @event dragleave
+               @param {Object} event
+               */
+               'dragleave', 
+
+               /**
+               Dispatched when file is dropped onto the drop zone.
+
+               @event drop
+               @param {Object} event
+               */
+               'drop', 
+
+               /**
+               Dispatched if error occurs.
+
+               @event error
+               @param {Object} event
+               */
+               'error'
+       ];
+
+       function FileDrop(options) {
+               if (MXI_DEBUG) {
+                       Env.log("Instantiating FileDrop..."); 
+               }
+
+               var self = this, defaults;
+
+               // if flat argument passed it should be drop_zone id
+               if (typeof(options) === 'string') {
+                       options = { drop_zone : options };
+               }
+
+               // figure out the options
+               defaults = {
+                       accept: [{
+                               title: I18n.translate('All Files'),
+                               extensions: '*'
+                       }],
+                       required_caps: {
+                               drag_and_drop: true
+                       }
+               };
+               
+               options = typeof(options) === 'object' ? Basic.extend({}, defaults, options) : defaults;
+
+               // this will help us to find proper default container
+               options.container = Dom.get(options.drop_zone) || document.body;
+
+               // make container relative, if it is not
+               if (Dom.getStyle(options.container, 'position') === 'static') {
+                       options.container.style.position = 'relative';
+               }
+                                       
+               // normalize accept option (could be list of mime types or array of title/extensions pairs)
+               if (typeof(options.accept) === 'string') {
+                       options.accept = Mime.mimes2extList(options.accept);
+               }
+
+               RuntimeClient.call(self);
+
+               Basic.extend(self, {
+                       uid: Basic.guid('uid_'),
+
+                       ruid: null,
+
+                       files: null,
+
+                       init: function() {              
+                               self.bind('RuntimeInit', function(e, runtime) {
+                                       self.ruid = runtime.uid;
+                                       runtime.exec.call(self, 'FileDrop', 'init', options);
+                                       self.dispatchEvent('ready');
+                               });
+                                                       
+                               // runtime needs: options.required_features, options.runtime_order and options.container
+                               self.connectRuntime(options); // throws RuntimeError
+                       },
+
+                       destroy: function() {
+                               var runtime = this.getRuntime();
+                               if (runtime) {
+                                       runtime.exec.call(this, 'FileDrop', 'destroy');
+                                       this.disconnectRuntime();
+                               }
+                               this.files = null;
+                               
+                               this.unbindAll();
+                       }
+               });
+
+               this.handleEventProps(dispatches);
+       }
+
+       FileDrop.prototype = EventTarget.instance;
+
+       return FileDrop;
+});
+
+// Included from: src/javascript/file/FileReader.js
+
+/**
+ * FileReader.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+define('moxie/file/FileReader', [
+       'moxie/core/utils/Basic',
+       'moxie/core/utils/Encode',
+       'moxie/core/Exceptions',
+       'moxie/core/EventTarget',
+       'moxie/file/Blob',
+       'moxie/runtime/RuntimeClient'
+], function(Basic, Encode, x, EventTarget, Blob, RuntimeClient) {
+       /**
+       Utility for preloading o.Blob/o.File objects in memory. By design closely follows [W3C FileReader](http://www.w3.org/TR/FileAPI/#dfn-filereader)
+       interface. Where possible uses native FileReader, where - not falls back to shims.
+
+       @class FileReader
+       @constructor FileReader
+       @extends EventTarget
+       @uses RuntimeClient
+       */
+       var dispatches = [
+
+               /** 
+               Dispatched when the read starts.
+
+               @event loadstart
+               @param {Object} event
+               */
+               'loadstart', 
+
+               /** 
+               Dispatched while reading (and decoding) blob, and reporting partial Blob data (progess.loaded/progress.total).
+
+               @event progress
+               @param {Object} event
+               */
+               'progress', 
+
+               /** 
+               Dispatched when the read has successfully completed.
+
+               @event load
+               @param {Object} event
+               */
+               'load', 
+
+               /** 
+               Dispatched when the read has been aborted. For instance, by invoking the abort() method.
+
+               @event abort
+               @param {Object} event
+               */
+               'abort', 
+
+               /** 
+               Dispatched when the read has failed.
+
+               @event error
+               @param {Object} event
+               */
+               'error', 
+
+               /** 
+               Dispatched when the request has completed (either in success or failure).
+
+               @event loadend
+               @param {Object} event
+               */
+               'loadend'
+       ];
+       
+       function FileReader() {
+
+               RuntimeClient.call(this);
+
+               Basic.extend(this, {
+                       /**
+                       UID of the component instance.
+
+                       @property uid
+                       @type {String}
+                       */
+                       uid: Basic.guid('uid_'),
+
+                       /**
+                       Contains current state of FileReader object. Can take values of FileReader.EMPTY, FileReader.LOADING
+                       and FileReader.DONE.
+
+                       @property readyState
+                       @type {Number}
+                       @default FileReader.EMPTY
+                       */
+                       readyState: FileReader.EMPTY,
+                       
+                       /**
+                       Result of the successful read operation.
+
+                       @property result
+                       @type {String}
+                       */
+                       result: null,
+                       
+                       /**
+                       Stores the error of failed asynchronous read operation.
+
+                       @property error
+                       @type {DOMError}
+                       */
+                       error: null,
+                       
+                       /**
+                       Initiates reading of File/Blob object contents to binary string.
+
+                       @method readAsBinaryString
+                       @param {Blob|File} blob Object to preload
+                       */
+                       readAsBinaryString: function(blob) {
+                               _read.call(this, 'readAsBinaryString', blob);
+                       },
+                       
+                       /**
+                       Initiates reading of File/Blob object contents to dataURL string.
+
+                       @method readAsDataURL
+                       @param {Blob|File} blob Object to preload
+                       */
+                       readAsDataURL: function(blob) {
+                               _read.call(this, 'readAsDataURL', blob);
+                       },
+                       
+                       /**
+                       Initiates reading of File/Blob object contents to string.
+
+                       @method readAsText
+                       @param {Blob|File} blob Object to preload
+                       */
+                       readAsText: function(blob) {
+                               _read.call(this, 'readAsText', blob);
+                       },
+                       
+                       /**
+                       Aborts preloading process.
+
+                       @method abort
+                       */
+                       abort: function() {
+                               this.result = null;
+                               
+                               if (Basic.inArray(this.readyState, [FileReader.EMPTY, FileReader.DONE]) !== -1) {
+                                       return;
+                               } else if (this.readyState === FileReader.LOADING) {
+                                       this.readyState = FileReader.DONE;
+                               }
+
+                               this.exec('FileReader', 'abort');
+                               
+                               this.trigger('abort');
+                               this.trigger('loadend');
+                       },
+
+                       /**
+                       Destroy component and release resources.
+
+                       @method destroy
+                       */
+                       destroy: function() {
+                               this.abort();
+                               this.exec('FileReader', 'destroy');
+                               this.disconnectRuntime();
+                               this.unbindAll();
+                       }
+               });
+
+               // uid must already be assigned
+               this.handleEventProps(dispatches);
+
+               this.bind('Error', function(e, err) {
+                       this.readyState = FileReader.DONE;
+                       this.error = err;
+               }, 999);
+               
+               this.bind('Load', function(e) {
+                       this.readyState = FileReader.DONE;
+               }, 999);
+
+               
+               function _read(op, blob) {
+                       var self = this;                        
+
+                       this.trigger('loadstart');
+
+                       if (this.readyState === FileReader.LOADING) {
+                               this.trigger('error', new x.DOMException(x.DOMException.INVALID_STATE_ERR));
+                               this.trigger('loadend');
+                               return;
+                       }
+
+                       // if source is not o.Blob/o.File
+                       if (!(blob instanceof Blob)) {
+                               this.trigger('error', new x.DOMException(x.DOMException.NOT_FOUND_ERR));
+                               this.trigger('loadend');
+                               return;
+                       }
+
+                       this.result = null;
+                       this.readyState = FileReader.LOADING;
+                       
+                       if (blob.isDetached()) {
+                               var src = blob.getSource();
+                               switch (op) {
+                                       case 'readAsText':
+                                       case 'readAsBinaryString':
+                                               this.result = src;
+                                               break;
+                                       case 'readAsDataURL':
+                                               this.result = 'data:' + blob.type + ';base64,' + Encode.btoa(src);
+                                               break;
+                               }
+                               this.readyState = FileReader.DONE;
+                               this.trigger('load');
+                               this.trigger('loadend');
+                       } else {
+                               this.connectRuntime(blob.ruid);
+                               this.exec('FileReader', 'read', op, blob);
+                       }
+               }
+       }
+       
+       /**
+       Initial FileReader state
+
+       @property EMPTY
+       @type {Number}
+       @final
+       @static
+       @default 0
+       */
+       FileReader.EMPTY = 0;
+
+       /**
+       FileReader switches to this state when it is preloading the source
+
+       @property LOADING
+       @type {Number}
+       @final
+       @static
+       @default 1
+       */
+       FileReader.LOADING = 1;
+
+       /**
+       Preloading is complete, this is a final state
+
+       @property DONE
+       @type {Number}
+       @final
+       @static
+       @default 2
+       */
+       FileReader.DONE = 2;
+
+       FileReader.prototype = EventTarget.instance;
+
+       return FileReader;
+});
+
+// Included from: src/javascript/core/utils/Url.js
+
+/**
+ * Url.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+define('moxie/core/utils/Url', [], function() {
+       /**
+       Parse url into separate components and fill in absent parts with parts from current url,
+       based on https://raw.github.com/kvz/phpjs/master/functions/url/parse_url.js
+
+       @method parseUrl
+       @for Utils
+       @static
+       @param {String} url Url to parse (defaults to empty string if undefined)
+       @return {Object} Hash containing extracted uri components
+       */
+       var parseUrl = function(url, currentUrl) {
+               var key = ['source', 'scheme', 'authority', 'userInfo', 'user', 'pass', 'host', 'port', 'relative', 'path', 'directory', 'file', 'query', 'fragment']
+               , i = key.length
+               , ports = {
+                       http: 80,
+                       https: 443
+               }
+               , uri = {}
+               , regex = /^(?:([^:\/?#]+):)?(?:\/\/()(?:(?:()(?:([^:@\/]*):?([^:@\/]*))?@)?([^:\/?#]*)(?::(\d*))?))?()(?:(()(?:(?:[^?#\/]*\/)*)()(?:[^?#]*))(?:\\?([^#]*))?(?:#(.*))?)/
+               , m = regex.exec(url || '')
+               ;
+                                       
+               while (i--) {
+                       if (m[i]) {
+                               uri[key[i]] = m[i];
+                       }
+               }
+
+               // when url is relative, we set the origin and the path ourselves
+               if (!uri.scheme) {
+                       // come up with defaults
+                       if (!currentUrl || typeof(currentUrl) === 'string') {
+                               currentUrl = parseUrl(currentUrl || document.location.href);
+                       }
+
+                       uri.scheme = currentUrl.scheme;
+                       uri.host = currentUrl.host;
+                       uri.port = currentUrl.port;
+
+                       var path = '';
+                       // for urls without trailing slash we need to figure out the path
+                       if (/^[^\/]/.test(uri.path)) {
+                               path = currentUrl.path;
+                               // if path ends with a filename, strip it
+                               if (/\/[^\/]*\.[^\/]*$/.test(path)) {
+                                       path = path.replace(/\/[^\/]+$/, '/');
+                               } else {
+                                       // avoid double slash at the end (see #127)
+                                       path = path.replace(/\/?$/, '/');
+                               }
+                       }
+                       uri.path = path + (uri.path || ''); // site may reside at domain.com or domain.com/subdir
+               }
+
+               if (!uri.port) {
+                       uri.port = ports[uri.scheme] || 80;
+               } 
+               
+               uri.port = parseInt(uri.port, 10);
+
+               if (!uri.path) {
+                       uri.path = "/";
+               }
+
+               delete uri.source;
+
+               return uri;
+       };
+
+       /**
+       Resolve url - among other things will turn relative url to absolute
+
+       @method resolveUrl
+       @static
+       @param {String|Object} url Either absolute or relative, or a result of parseUrl call
+       @return {String} Resolved, absolute url
+       */
+       var resolveUrl = function(url) {
+               var ports = { // we ignore default ports
+                       http: 80,
+                       https: 443
+               }
+               , urlp = typeof(url) === 'object' ? url : parseUrl(url);
+               ;
+
+               return urlp.scheme + '://' + urlp.host + (urlp.port !== ports[urlp.scheme] ? ':' + urlp.port : '') + urlp.path + (urlp.query ? urlp.query : '');
+       };
+
+       /**
+       Check if specified url has the same origin as the current document
+
+       @method hasSameOrigin
+       @param {String|Object} url
+       @return {Boolean}
+       */
+       var hasSameOrigin = function(url) {
+               function origin(url) {
+                       return [url.scheme, url.host, url.port].join('/');
+               }
+                       
+               if (typeof url === 'string') {
+                       url = parseUrl(url);
+               }       
+               
+               return origin(parseUrl()) === origin(url);
+       };
+
+       return {
+               parseUrl: parseUrl,
+               resolveUrl: resolveUrl,
+               hasSameOrigin: hasSameOrigin
+       };
+});
+
+// Included from: src/javascript/runtime/RuntimeTarget.js
+
+/**
+ * RuntimeTarget.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+define('moxie/runtime/RuntimeTarget', [
+       'moxie/core/utils/Basic',
+       'moxie/runtime/RuntimeClient',
+       "moxie/core/EventTarget"
+], function(Basic, RuntimeClient, EventTarget) {
+       /**
+       Instance of this class can be used as a target for the events dispatched by shims,
+       when allowing them onto components is for either reason inappropriate
+
+       @class RuntimeTarget
+       @constructor
+       @protected
+       @extends EventTarget
+       */
+       function RuntimeTarget() {
+               this.uid = Basic.guid('uid_');
+               
+               RuntimeClient.call(this);
+
+               this.destroy = function() {
+                       this.disconnectRuntime();
+                       this.unbindAll();
+               };
+       }
+
+       RuntimeTarget.prototype = EventTarget.instance;
+
+       return RuntimeTarget;
+});
+
+// Included from: src/javascript/file/FileReaderSync.js
+
+/**
+ * FileReaderSync.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+define('moxie/file/FileReaderSync', [
+       'moxie/core/utils/Basic',
+       'moxie/runtime/RuntimeClient',
+       'moxie/core/utils/Encode'
+], function(Basic, RuntimeClient, Encode) {
+       /**
+       Synchronous FileReader implementation. Something like this is available in WebWorkers environment, here
+       it can be used to read only preloaded blobs/files and only below certain size (not yet sure what that'd be,
+       but probably < 1mb). Not meant to be used directly by user.
+
+       @class FileReaderSync
+       @private
+       @constructor
+       */
+       return function() {
+               RuntimeClient.call(this);
+
+               Basic.extend(this, {
+                       uid: Basic.guid('uid_'),
+
+                       readAsBinaryString: function(blob) {
+                               return _read.call(this, 'readAsBinaryString', blob);
+                       },
+                       
+                       readAsDataURL: function(blob) {
+                               return _read.call(this, 'readAsDataURL', blob);
+                       },
+                       
+                       /*readAsArrayBuffer: function(blob) {
+                               return _read.call(this, 'readAsArrayBuffer', blob);
+                       },*/
+                       
+                       readAsText: function(blob) {
+                               return _read.call(this, 'readAsText', blob);
+                       }
+               });
+
+               function _read(op, blob) {
+                       if (blob.isDetached()) {
+                               var src = blob.getSource();
+                               switch (op) {
+                                       case 'readAsBinaryString':
+                                               return src;
+                                       case 'readAsDataURL':
+                                               return 'data:' + blob.type + ';base64,' + Encode.btoa(src);
+                                       case 'readAsText':
+                                               var txt = '';
+                                               for (var i = 0, length = src.length; i < length; i++) {
+                                                       txt += String.fromCharCode(src[i]);
+                                               }
+                                               return txt;
+                               }
+                       } else {
+                               var result = this.connectRuntime(blob.ruid).exec.call(this, 'FileReaderSync', 'read', op, blob);
+                               this.disconnectRuntime();
+                               return result;
+                       }
+               }
+       };
+});
+
+// Included from: src/javascript/xhr/FormData.js
+
+/**
+ * FormData.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+define("moxie/xhr/FormData", [
+       "moxie/core/Exceptions",
+       "moxie/core/utils/Basic",
+       "moxie/file/Blob"
+], function(x, Basic, Blob) {
+       /**
+       FormData
+
+       @class FormData
+       @constructor
+       */
+       function FormData() {
+               var _blob, _fields = [];
+
+               Basic.extend(this, {
+                       /**
+                       Append another key-value pair to the FormData object
+
+                       @method append
+                       @param {String} name Name for the new field
+                       @param {String|Blob|Array|Object} value Value for the field
+                       */
+                       append: function(name, value) {
+                               var self = this, valueType = Basic.typeOf(value);
+
+                               // according to specs value might be either Blob or String
+                               if (value instanceof Blob) {
+                                       _blob = {
+                                               name: name,
+                                               value: value // unfortunately we can only send single Blob in one FormData
+                                       };
+                               } else if ('array' === valueType) {
+                                       name += '[]';
+
+                                       Basic.each(value, function(value) {
+                                               self.append(name, value);
+                                       });
+                               } else if ('object' === valueType) {
+                                       Basic.each(value, function(value, key) {
+                                               self.append(name + '[' + key + ']', value);
+                                       });
+                               } else if ('null' === valueType || 'undefined' === valueType || 'number' === valueType && isNaN(value)) {
+                                       self.append(name, "false");
+                               } else {
+                                       _fields.push({
+                                               name: name,
+                                               value: value.toString()
+                                       });
+                               }
+                       },
+
+                       /**
+                       Checks if FormData contains Blob.
+
+                       @method hasBlob
+                       @return {Boolean}
+                       */
+                       hasBlob: function() {
+                               return !!this.getBlob();
+                       },
+
+                       /**
+                       Retrieves blob.
+
+                       @method getBlob
+                       @return {Object} Either Blob if found or null
+                       */
+                       getBlob: function() {
+                               return _blob && _blob.value || null;
+                       },
+
+                       /**
+                       Retrieves blob field name.
+
+                       @method getBlobName
+                       @return {String} Either Blob field name or null
+                       */
+                       getBlobName: function() {
+                               return _blob && _blob.name || null;
+                       },
+
+                       /**
+                       Loop over the fields in FormData and invoke the callback for each of them.
+
+                       @method each
+                       @param {Function} cb Callback to call for each field
+                       */
+                       each: function(cb) {
+                               Basic.each(_fields, function(field) {
+                                       cb(field.value, field.name);
+                               });
+
+                               if (_blob) {
+                                       cb(_blob.value, _blob.name);
+                               }
+                       },
+
+                       destroy: function() {
+                               _blob = null;
+                               _fields = [];
+                       }
+               });
+       }
+
+       return FormData;
+});
+
+// Included from: src/javascript/xhr/XMLHttpRequest.js
+
+/**
+ * XMLHttpRequest.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+define("moxie/xhr/XMLHttpRequest", [
+       "moxie/core/utils/Basic",
+       "moxie/core/Exceptions",
+       "moxie/core/EventTarget",
+       "moxie/core/utils/Encode",
+       "moxie/core/utils/Url",
+       "moxie/runtime/Runtime",
+       "moxie/runtime/RuntimeTarget",
+       "moxie/file/Blob",
+       "moxie/file/FileReaderSync",
+       "moxie/xhr/FormData",
+       "moxie/core/utils/Env",
+       "moxie/core/utils/Mime"
+], function(Basic, x, EventTarget, Encode, Url, Runtime, RuntimeTarget, Blob, FileReaderSync, FormData, Env, Mime) {
+
+       var httpCode = {
+               100: 'Continue',
+               101: 'Switching Protocols',
+               102: 'Processing',
+
+               200: 'OK',
+               201: 'Created',
+               202: 'Accepted',
+               203: 'Non-Authoritative Information',
+               204: 'No Content',
+               205: 'Reset Content',
+               206: 'Partial Content',
+               207: 'Multi-Status',
+               226: 'IM Used',
+
+               300: 'Multiple Choices',
+               301: 'Moved Permanently',
+               302: 'Found',
+               303: 'See Other',
+               304: 'Not Modified',
+               305: 'Use Proxy',
+               306: 'Reserved',
+               307: 'Temporary Redirect',
+
+               400: 'Bad Request',
+               401: 'Unauthorized',
+               402: 'Payment Required',
+               403: 'Forbidden',
+               404: 'Not Found',
+               405: 'Method Not Allowed',
+               406: 'Not Acceptable',
+               407: 'Proxy Authentication Required',
+               408: 'Request Timeout',
+               409: 'Conflict',
+               410: 'Gone',
+               411: 'Length Required',
+               412: 'Precondition Failed',
+               413: 'Request Entity Too Large',
+               414: 'Request-URI Too Long',
+               415: 'Unsupported Media Type',
+               416: 'Requested Range Not Satisfiable',
+               417: 'Expectation Failed',
+               422: 'Unprocessable Entity',
+               423: 'Locked',
+               424: 'Failed Dependency',
+               426: 'Upgrade Required',
+
+               500: 'Internal Server Error',
+               501: 'Not Implemented',
+               502: 'Bad Gateway',
+               503: 'Service Unavailable',
+               504: 'Gateway Timeout',
+               505: 'HTTP Version Not Supported',
+               506: 'Variant Also Negotiates',
+               507: 'Insufficient Storage',
+               510: 'Not Extended'
+       };
+
+       function XMLHttpRequestUpload() {
+               this.uid = Basic.guid('uid_');
+       }
+       
+       XMLHttpRequestUpload.prototype = EventTarget.instance;
+
+       /**
+       Implementation of XMLHttpRequest
+
+       @class XMLHttpRequest
+       @constructor
+       @uses RuntimeClient
+       @extends EventTarget
+       */
+       var dispatches = [
+               'loadstart',
+
+               'progress',
+
+               'abort',
+
+               'error',
+
+               'load',
+
+               'timeout',
+
+               'loadend'
+
+               // readystatechange (for historical reasons)
+       ]; 
+       
+       var NATIVE = 1, RUNTIME = 2;
+                                       
+       function XMLHttpRequest() {
+               var self = this,
+                       // this (together with _p() @see below) is here to gracefully upgrade to setter/getter syntax where possible
+                       props = {
+                               /**
+                               The amount of milliseconds a request can take before being terminated. Initially zero. Zero means there is no timeout.
+
+                               @property timeout
+                               @type Number
+                               @default 0
+                               */
+                               timeout: 0,
+
+                               /**
+                               Current state, can take following values:
+                               UNSENT (numeric value 0)
+                               The object has been constructed.
+
+                               OPENED (numeric value 1)
+                               The open() method has been successfully invoked. During this state request headers can be set using setRequestHeader() and the request can be made using the send() method.
+
+                               HEADERS_RECEIVED (numeric value 2)
+                               All redirects (if any) have been followed and all HTTP headers of the final response have been received. Several response members of the object are now available.
+
+                               LOADING (numeric value 3)
+                               The response entity body is being received.
+
+                               DONE (numeric value 4)
+
+                               @property readyState
+                               @type Number
+                               @default 0 (UNSENT)
+                               */
+                               readyState: XMLHttpRequest.UNSENT,
+
+                               /**
+                               True when user credentials are to be included in a cross-origin request. False when they are to be excluded
+                               in a cross-origin request and when cookies are to be ignored in its response. Initially false.
+
+                               @property withCredentials
+                               @type Boolean
+                               @default false
+                               */
+                               withCredentials: false,
+
+                               /**
+                               Returns the HTTP status code.
+
+                               @property status
+                               @type Number
+                               @default 0
+                               */
+                               status: 0,
+
+                               /**
+                               Returns the HTTP status text.
+
+                               @property statusText
+                               @type String
+                               */
+                               statusText: "",
+
+                               /**
+                               Returns the response type. Can be set to change the response type. Values are:
+                               the empty string (default), "arraybuffer", "blob", "document", "json", and "text".
+                               
+                               @property responseType
+                               @type String
+                               */
+                               responseType: "",
+
+                               /**
+                               Returns the document response entity body.
+                               
+                               Throws an "InvalidStateError" exception if responseType is not the empty string or "document".
+
+                               @property responseXML
+                               @type Document
+                               */
+                               responseXML: null,
+
+                               /**
+                               Returns the text response entity body.
+                               
+                               Throws an "InvalidStateError" exception if responseType is not the empty string or "text".
+
+                               @property responseText
+                               @type String
+                               */
+                               responseText: null,
+
+                               /**
+                               Returns the response entity body (http://www.w3.org/TR/XMLHttpRequest/#response-entity-body).
+                               Can become: ArrayBuffer, Blob, Document, JSON, Text
+                               
+                               @property response
+                               @type Mixed
+                               */
+                               response: null
+                       },
+
+                       _async = true,
+                       _url,
+                       _method,
+                       _headers = {},
+                       _user,
+                       _password,
+                       _encoding = null,
+                       _mimeType = null,
+
+                       // flags
+                       _sync_flag = false,
+                       _send_flag = false,
+                       _upload_events_flag = false,
+                       _upload_complete_flag = false,
+                       _error_flag = false,
+                       _same_origin_flag = false,
+
+                       // times
+                       _start_time,
+                       _timeoutset_time,
+
+                       _finalMime = null,
+                       _finalCharset = null,
+
+                       _options = {},
+                       _xhr,
+                       _responseHeaders = '',
+                       _responseHeadersBag
+                       ;
+
+               
+               Basic.extend(this, props, {
+                       /**
+                       Unique id of the component
+
+                       @property uid
+                       @type String
+                       */
+                       uid: Basic.guid('uid_'),
+                       
+                       /**
+                       Target for Upload events
+
+                       @property upload
+                       @type XMLHttpRequestUpload
+                       */
+                       upload: new XMLHttpRequestUpload(),
+                       
+
+                       /**
+                       Sets the request method, request URL, synchronous flag, request username, and request password.
+
+                       Throws a "SyntaxError" exception if one of the following is true:
+
+                       method is not a valid HTTP method.
+                       url cannot be resolved.
+                       url contains the "user:password" format in the userinfo production.
+                       Throws a "SecurityError" exception if method is a case-insensitive match for CONNECT, TRACE or TRACK.
+
+                       Throws an "InvalidAccessError" exception if one of the following is true:
+
+                       Either user or password is passed as argument and the origin of url does not match the XMLHttpRequest origin.
+                       There is an associated XMLHttpRequest document and either the timeout attribute is not zero,
+                       the withCredentials attribute is true, or the responseType attribute is not the empty string.
+
+
+                       @method open
+                       @param {String} method HTTP method to use on request
+                       @param {String} url URL to request
+                       @param {Boolean} [async=true] If false request will be done in synchronous manner. Asynchronous by default.
+                       @param {String} [user] Username to use in HTTP authentication process on server-side
+                       @param {String} [password] Password to use in HTTP authentication process on server-side
+                       */
+                       open: function(method, url, async, user, password) {
+                               var urlp;
+                               
+                               // first two arguments are required
+                               if (!method || !url) {
+                                       throw new x.DOMException(x.DOMException.SYNTAX_ERR);
+                               }
+                               
+                               // 2 - check if any code point in method is higher than U+00FF or after deflating method it does not match the method
+                               if (/[\u0100-\uffff]/.test(method) || Encode.utf8_encode(method) !== method) {
+                                       throw new x.DOMException(x.DOMException.SYNTAX_ERR);
+                               }
+
+                               // 3
+                               if (!!~Basic.inArray(method.toUpperCase(), ['CONNECT', 'DELETE', 'GET', 'HEAD', 'OPTIONS', 'POST', 'PUT', 'TRACE', 'TRACK'])) {
+                                       _method = method.toUpperCase();
+                               }
+                               
+                               
+                               // 4 - allowing these methods poses a security risk
+                               if (!!~Basic.inArray(_method, ['CONNECT', 'TRACE', 'TRACK'])) {
+                                       throw new x.DOMException(x.DOMException.SECURITY_ERR);
+                               }
+
+                               // 5
+                               url = Encode.utf8_encode(url);
+                               
+                               // 6 - Resolve url relative to the XMLHttpRequest base URL. If the algorithm returns an error, throw a "SyntaxError".
+                               urlp = Url.parseUrl(url);
+
+                               _same_origin_flag = Url.hasSameOrigin(urlp);
+                                                                                                                               
+                               // 7 - manually build up absolute url
+                               _url = Url.resolveUrl(url);
+               
+                               // 9-10, 12-13
+                               if ((user || password) && !_same_origin_flag) {
+                                       throw new x.DOMException(x.DOMException.INVALID_ACCESS_ERR);
+                               }
+
+                               _user = user || urlp.user;
+                               _password = password || urlp.pass;
+                               
+                               // 11
+                               _async = async || true;
+                               
+                               if (_async === false && (_p('timeout') || _p('withCredentials') || _p('responseType') !== "")) {
+                                       throw new x.DOMException(x.DOMException.INVALID_ACCESS_ERR);
+                               }
+                               
+                               // 14 - terminate abort()
+                               
+                               // 15 - terminate send()
+
+                               // 18
+                               _sync_flag = !_async;
+                               _send_flag = false;
+                               _headers = {};
+                               _reset.call(this);
+
+                               // 19
+                               _p('readyState', XMLHttpRequest.OPENED);
+                               
+                               // 20
+                               this.dispatchEvent('readystatechange');
+                       },
+                       
+                       /**
+                       Appends an header to the list of author request headers, or if header is already
+                       in the list of author request headers, combines its value with value.
+
+                       Throws an "InvalidStateError" exception if the state is not OPENED or if the send() flag is set.
+                       Throws a "SyntaxError" exception if header is not a valid HTTP header field name or if value
+                       is not a valid HTTP header field value.
+                       
+                       @method setRequestHeader
+                       @param {String} header
+                       @param {String|Number} value
+                       */
+                       setRequestHeader: function(header, value) {
+                               var uaHeaders = [ // these headers are controlled by the user agent
+                                               "accept-charset",
+                                               "accept-encoding",
+                                               "access-control-request-headers",
+                                               "access-control-request-method",
+                                               "connection",
+                                               "content-length",
+                                               "cookie",
+                                               "cookie2",
+                                               "content-transfer-encoding",
+                                               "date",
+                                               "expect",
+                                               "host",
+                                               "keep-alive",
+                                               "origin",
+                                               "referer",
+                                               "te",
+                                               "trailer",
+                                               "transfer-encoding",
+                                               "upgrade",
+                                               "user-agent",
+                                               "via"
+                                       ];
+                               
+                               // 1-2
+                               if (_p('readyState') !== XMLHttpRequest.OPENED || _send_flag) {
+                                       throw new x.DOMException(x.DOMException.INVALID_STATE_ERR);
+                               }
+
+                               // 3
+                               if (/[\u0100-\uffff]/.test(header) || Encode.utf8_encode(header) !== header) {
+                                       throw new x.DOMException(x.DOMException.SYNTAX_ERR);
+                               }
+
+                               // 4
+                               /* this step is seemingly bypassed in browsers, probably to allow various unicode characters in header values
+                               if (/[\u0100-\uffff]/.test(value) || Encode.utf8_encode(value) !== value) {
+                                       throw new x.DOMException(x.DOMException.SYNTAX_ERR);
+                               }*/
+
+                               header = Basic.trim(header).toLowerCase();
+                               
+                               // setting of proxy-* and sec-* headers is prohibited by spec
+                               if (!!~Basic.inArray(header, uaHeaders) || /^(proxy\-|sec\-)/.test(header)) {
+                                       return false;
+                               }
+
+                               // camelize
+                               // browsers lowercase header names (at least for custom ones)
+                               // header = header.replace(/\b\w/g, function($1) { return $1.toUpperCase(); });
+                               
+                               if (!_headers[header]) {
+                                       _headers[header] = value;
+                               } else {
+                                       // http://tools.ietf.org/html/rfc2616#section-4.2 (last paragraph)
+                                       _headers[header] += ', ' + value;
+                               }
+                               return true;
+                       },
+
+                       /**
+                       Returns all headers from the response, with the exception of those whose field name is Set-Cookie or Set-Cookie2.
+
+                       @method getAllResponseHeaders
+                       @return {String} reponse headers or empty string
+                       */
+                       getAllResponseHeaders: function() {
+                               return _responseHeaders || '';
+                       },
+
+                       /**
+                       Returns the header field value from the response of which the field name matches header, 
+                       unless the field name is Set-Cookie or Set-Cookie2.
+
+                       @method getResponseHeader
+                       @param {String} header
+                       @return {String} value(s) for the specified header or null
+                       */
+                       getResponseHeader: function(header) {
+                               header = header.toLowerCase();
+
+                               if (_error_flag || !!~Basic.inArray(header, ['set-cookie', 'set-cookie2'])) {
+                                       return null;
+                               }
+
+                               if (_responseHeaders && _responseHeaders !== '') {
+                                       // if we didn't parse response headers until now, do it and keep for later
+                                       if (!_responseHeadersBag) {
+                                               _responseHeadersBag = {};
+                                               Basic.each(_responseHeaders.split(/\r\n/), function(line) {
+                                                       var pair = line.split(/:\s+/);
+                                                       if (pair.length === 2) { // last line might be empty, omit
+                                                               pair[0] = Basic.trim(pair[0]); // just in case
+                                                               _responseHeadersBag[pair[0].toLowerCase()] = { // simply to retain header name in original form
+                                                                       header: pair[0],
+                                                                       value: Basic.trim(pair[1])
+                                                               };
+                                                       }
+                                               });
+                                       }
+                                       if (_responseHeadersBag.hasOwnProperty(header)) {
+                                               return _responseHeadersBag[header].header + ': ' + _responseHeadersBag[header].value;
+                                       }
+                               }
+                               return null;
+                       },
+                       
+                       /**
+                       Sets the Content-Type header for the response to mime.
+                       Throws an "InvalidStateError" exception if the state is LOADING or DONE.
+                       Throws a "SyntaxError" exception if mime is not a valid media type.
+
+                       @method overrideMimeType
+                       @param String mime Mime type to set
+                       */
+                       overrideMimeType: function(mime) {
+                               var matches, charset;
+                       
+                               // 1
+                               if (!!~Basic.inArray(_p('readyState'), [XMLHttpRequest.LOADING, XMLHttpRequest.DONE])) {
+                                       throw new x.DOMException(x.DOMException.INVALID_STATE_ERR);
+                               }
+
+                               // 2
+                               mime = Basic.trim(mime.toLowerCase());
+
+                               if (/;/.test(mime) && (matches = mime.match(/^([^;]+)(?:;\scharset\=)?(.*)$/))) {
+                                       mime = matches[1];
+                                       if (matches[2]) {
+                                               charset = matches[2];
+                                       }
+                               }
+
+                               if (!Mime.mimes[mime]) {
+                                       throw new x.DOMException(x.DOMException.SYNTAX_ERR);
+                               }
+
+                               // 3-4
+                               _finalMime = mime;
+                               _finalCharset = charset;
+                       },
+                       
+                       /**
+                       Initiates the request. The optional argument provides the request entity body.
+                       The argument is ignored if request method is GET or HEAD.
+
+                       Throws an "InvalidStateError" exception if the state is not OPENED or if the send() flag is set.
+
+                       @method send
+                       @param {Blob|Document|String|FormData} [data] Request entity body
+                       @param {Object} [options] Set of requirements and pre-requisities for runtime initialization
+                       */
+                       send: function(data, options) {                                 
+                               if (Basic.typeOf(options) === 'string') {
+                                       _options = { ruid: options };
+                               } else if (!options) {
+                                       _options = {};
+                               } else {
+                                       _options = options;
+                               }
+                                                                                                                       
+                               // 1-2
+                               if (this.readyState !== XMLHttpRequest.OPENED || _send_flag) {
+                                       throw new x.DOMException(x.DOMException.INVALID_STATE_ERR);
+                               }
+                               
+                               // 3                                    
+                               // sending Blob
+                               if (data instanceof Blob) {
+                                       _options.ruid = data.ruid;
+                                       _mimeType = data.type || 'application/octet-stream';
+                               }
+                               
+                               // FormData
+                               else if (data instanceof FormData) {
+                                       if (data.hasBlob()) {
+                                               var blob = data.getBlob();
+                                               _options.ruid = blob.ruid;
+                                               _mimeType = blob.type || 'application/octet-stream';
+                                       }
+                               }
+                               
+                               // DOMString
+                               else if (typeof data === 'string') {
+                                       _encoding = 'UTF-8';
+                                       _mimeType = 'text/plain;charset=UTF-8';
+                                       
+                                       // data should be converted to Unicode and encoded as UTF-8
+                                       data = Encode.utf8_encode(data);
+                               }
+
+                               // if withCredentials not set, but requested, set it automatically
+                               if (!this.withCredentials) {
+                                       this.withCredentials = (_options.required_caps && _options.required_caps.send_browser_cookies) && !_same_origin_flag;
+                               }
+
+                               // 4 - storage mutex
+                               // 5
+                               _upload_events_flag = (!_sync_flag && this.upload.hasEventListener()); // DSAP
+                               // 6
+                               _error_flag = false;
+                               // 7
+                               _upload_complete_flag = !data;
+                               // 8 - Asynchronous steps
+                               if (!_sync_flag) {
+                                       // 8.1
+                                       _send_flag = true;
+                                       // 8.2
+                                       // this.dispatchEvent('loadstart'); // will be dispatched either by native or runtime xhr
+                                       // 8.3
+                                       //if (!_upload_complete_flag) {
+                                               // this.upload.dispatchEvent('loadstart');      // will be dispatched either by native or runtime xhr
+                                       //}
+                               }
+                               // 8.5 - Return the send() method call, but continue running the steps in this algorithm.
+                               _doXHR.call(this, data);
+                       },
+                       
+                       /**
+                       Cancels any network activity.
+                       
+                       @method abort
+                       */
+                       abort: function() {
+                               _error_flag = true;
+                               _sync_flag = false;
+
+                               if (!~Basic.inArray(_p('readyState'), [XMLHttpRequest.UNSENT, XMLHttpRequest.OPENED, XMLHttpRequest.DONE])) {
+                                       _p('readyState', XMLHttpRequest.DONE);
+                                       _send_flag = false;
+
+                                       if (_xhr) {
+                                               _xhr.getRuntime().exec.call(_xhr, 'XMLHttpRequest', 'abort', _upload_complete_flag);
+                                       } else {
+                                               throw new x.DOMException(x.DOMException.INVALID_STATE_ERR);
+                                       }
+
+                                       _upload_complete_flag = true;
+                               } else {
+                                       _p('readyState', XMLHttpRequest.UNSENT);
+                               }
+                       },
+
+                       destroy: function() {
+                               if (_xhr) {
+                                       if (Basic.typeOf(_xhr.destroy) === 'function') {
+                                               _xhr.destroy();
+                                       }
+                                       _xhr = null;
+                               }
+
+                               this.unbindAll();
+
+                               if (this.upload) {
+                                       this.upload.unbindAll();
+                                       this.upload = null;
+                               }
+                       }
+               });
+
+               this.handleEventProps(dispatches.concat(['readystatechange'])); // for historical reasons
+               this.upload.handleEventProps(dispatches);
+
+               /* this is nice, but maybe too lengthy
+
+               // if supported by JS version, set getters/setters for specific properties
+               o.defineProperty(this, 'readyState', {
+                       configurable: false,
+
+                       get: function() {
+                               return _p('readyState');
+                       }
+               });
+
+               o.defineProperty(this, 'timeout', {
+                       configurable: false,
+
+                       get: function() {
+                               return _p('timeout');
+                       },
+
+                       set: function(value) {
+
+                               if (_sync_flag) {
+                                       throw new x.DOMException(x.DOMException.INVALID_ACCESS_ERR);
+                               }
+
+                               // timeout still should be measured relative to the start time of request
+                               _timeoutset_time = (new Date).getTime();
+
+                               _p('timeout', value);
+                       }
+               });
+
+               // the withCredentials attribute has no effect when fetching same-origin resources
+               o.defineProperty(this, 'withCredentials', {
+                       configurable: false,
+
+                       get: function() {
+                               return _p('withCredentials');
+                       },
+
+                       set: function(value) {
+                               // 1-2
+                               if (!~o.inArray(_p('readyState'), [XMLHttpRequest.UNSENT, XMLHttpRequest.OPENED]) || _send_flag) {
+                                       throw new x.DOMException(x.DOMException.INVALID_STATE_ERR);
+                               }
+
+                               // 3-4
+                               if (_anonymous_flag || _sync_flag) {
+                                       throw new x.DOMException(x.DOMException.INVALID_ACCESS_ERR);
+                               }
+
+                               // 5
+                               _p('withCredentials', value);
+                       }
+               });
+
+               o.defineProperty(this, 'status', {
+                       configurable: false,
+
+                       get: function() {
+                               return _p('status');
+                       }
+               });
+
+               o.defineProperty(this, 'statusText', {
+                       configurable: false,
+
+                       get: function() {
+                               return _p('statusText');
+                       }
+               });
+
+               o.defineProperty(this, 'responseType', {
+                       configurable: false,
+
+                       get: function() {
+                               return _p('responseType');
+                       },
+
+                       set: function(value) {
+                               // 1
+                               if (!!~o.inArray(_p('readyState'), [XMLHttpRequest.LOADING, XMLHttpRequest.DONE])) {
+                                       throw new x.DOMException(x.DOMException.INVALID_STATE_ERR);
+                               }
+
+                               // 2
+                               if (_sync_flag) {
+                                       throw new x.DOMException(x.DOMException.INVALID_ACCESS_ERR);
+                               }
+
+                               // 3
+                               _p('responseType', value.toLowerCase());
+                       }
+               });
+
+               o.defineProperty(this, 'responseText', {
+                       configurable: false,
+
+                       get: function() {
+                               // 1
+                               if (!~o.inArray(_p('responseType'), ['', 'text'])) {
+                                       throw new x.DOMException(x.DOMException.INVALID_STATE_ERR);
+                               }
+
+                               // 2-3
+                               if (_p('readyState') !== XMLHttpRequest.DONE && _p('readyState') !== XMLHttpRequest.LOADING || _error_flag) {
+                                       throw new x.DOMException(x.DOMException.INVALID_STATE_ERR);
+                               }
+
+                               return _p('responseText');
+                       }
+               });
+
+               o.defineProperty(this, 'responseXML', {
+                       configurable: false,
+
+                       get: function() {
+                               // 1
+                               if (!~o.inArray(_p('responseType'), ['', 'document'])) {
+                                       throw new x.DOMException(x.DOMException.INVALID_STATE_ERR);
+                               }
+
+                               // 2-3
+                               if (_p('readyState') !== XMLHttpRequest.DONE || _error_flag) {
+                                       throw new x.DOMException(x.DOMException.INVALID_STATE_ERR);
+                               }
+
+                               return _p('responseXML');
+                       }
+               });
+
+               o.defineProperty(this, 'response', {
+                       configurable: false,
+
+                       get: function() {
+                               if (!!~o.inArray(_p('responseType'), ['', 'text'])) {
+                                       if (_p('readyState') !== XMLHttpRequest.DONE && _p('readyState') !== XMLHttpRequest.LOADING || _error_flag) {
+                                               return '';
+                                       }
+                               }
+
+                               if (_p('readyState') !== XMLHttpRequest.DONE || _error_flag) {
+                                       return null;
+                               }
+
+                               return _p('response');
+                       }
+               });
+
+               */
+
+               function _p(prop, value) {
+                       if (!props.hasOwnProperty(prop)) {
+                               return;
+                       }
+                       if (arguments.length === 1) { // get
+                               return Env.can('define_property') ? props[prop] : self[prop];
+                       } else { // set
+                               if (Env.can('define_property')) {
+                                       props[prop] = value;
+                               } else {
+                                       self[prop] = value;
+                               }
+                       }
+               }
+               
+               /*
+               function _toASCII(str, AllowUnassigned, UseSTD3ASCIIRules) {
+                       // TODO: http://tools.ietf.org/html/rfc3490#section-4.1
+                       return str.toLowerCase();
+               }
+               */
+               
+               
+               function _doXHR(data) {
+                       var self = this;
+                       
+                       _start_time = new Date().getTime();
+
+                       _xhr = new RuntimeTarget();
+
+                       function loadEnd() {
+                               if (_xhr) { // it could have been destroyed by now
+                                       _xhr.destroy();
+                                       _xhr = null;
+                               }
+                               self.dispatchEvent('loadend');
+                               self = null;
+                       }
+
+                       function exec(runtime) {
+                               _xhr.bind('LoadStart', function(e) {
+                                       _p('readyState', XMLHttpRequest.LOADING);
+                                       self.dispatchEvent('readystatechange');
+
+                                       self.dispatchEvent(e);
+                                       
+                                       if (_upload_events_flag) {
+                                               self.upload.dispatchEvent(e);
+                                       }
+                               });
+                               
+                               _xhr.bind('Progress', function(e) {
+                                       if (_p('readyState') !== XMLHttpRequest.LOADING) {
+                                               _p('readyState', XMLHttpRequest.LOADING); // LoadStart unreliable (in Flash for example)
+                                               self.dispatchEvent('readystatechange');
+                                       }
+                                       self.dispatchEvent(e);
+                               });
+                               
+                               _xhr.bind('UploadProgress', function(e) {
+                                       if (_upload_events_flag) {
+                                               self.upload.dispatchEvent({
+                                                       type: 'progress',
+                                                       lengthComputable: false,
+                                                       total: e.total,
+                                                       loaded: e.loaded
+                                               });
+                                       }
+                               });
+                               
+                               _xhr.bind('Load', function(e) {
+                                       _p('readyState', XMLHttpRequest.DONE);
+                                       _p('status', Number(runtime.exec.call(_xhr, 'XMLHttpRequest', 'getStatus') || 0));
+                                       _p('statusText', httpCode[_p('status')] || "");
+                                       
+                                       _p('response', runtime.exec.call(_xhr, 'XMLHttpRequest', 'getResponse', _p('responseType')));
+
+                                       if (!!~Basic.inArray(_p('responseType'), ['text', ''])) {
+                                               _p('responseText', _p('response'));
+                                       } else if (_p('responseType') === 'document') {
+                                               _p('responseXML', _p('response'));
+                                       }
+
+                                       _responseHeaders = runtime.exec.call(_xhr, 'XMLHttpRequest', 'getAllResponseHeaders');
+
+                                       self.dispatchEvent('readystatechange');
+                                       
+                                       if (_p('status') > 0) { // status 0 usually means that server is unreachable
+                                               if (_upload_events_flag) {
+                                                       self.upload.dispatchEvent(e);
+                                               }
+                                               self.dispatchEvent(e);
+                                       } else {
+                                               _error_flag = true;
+                                               self.dispatchEvent('error');
+                                       }
+                                       loadEnd();
+                               });
+
+                               _xhr.bind('Abort', function(e) {
+                                       self.dispatchEvent(e);
+                                       loadEnd();
+                               });
+                               
+                               _xhr.bind('Error', function(e) {
+                                       _error_flag = true;
+                                       _p('readyState', XMLHttpRequest.DONE);
+                                       self.dispatchEvent('readystatechange');
+                                       _upload_complete_flag = true;
+                                       self.dispatchEvent(e);
+                                       loadEnd();
+                               });
+
+                               runtime.exec.call(_xhr, 'XMLHttpRequest', 'send', {
+                                       url: _url,
+                                       method: _method,
+                                       async: _async,
+                                       user: _user,
+                                       password: _password,
+                                       headers: _headers,
+                                       mimeType: _mimeType,
+                                       encoding: _encoding,
+                                       responseType: self.responseType,
+                                       withCredentials: self.withCredentials,
+                                       options: _options
+                               }, data);
+                       }
+
+                       // clarify our requirements
+                       if (typeof(_options.required_caps) === 'string') {
+                               _options.required_caps = Runtime.parseCaps(_options.required_caps);
+                       }
+
+                       _options.required_caps = Basic.extend({}, _options.required_caps, {
+                               return_response_type: self.responseType
+                       });
+
+                       if (data instanceof FormData) {
+                               _options.required_caps.send_multipart = true;
+                       }
+
+                       if (!Basic.isEmptyObj(_headers)) {
+                               _options.required_caps.send_custom_headers = true;
+                       }
+
+                       if (!_same_origin_flag) {
+                               _options.required_caps.do_cors = true;
+                       }
+                       
+
+                       if (_options.ruid) { // we do not need to wait if we can connect directly
+                               exec(_xhr.connectRuntime(_options));
+                       } else {
+                               _xhr.bind('RuntimeInit', function(e, runtime) {
+                                       exec(runtime);
+                               });
+                               _xhr.bind('RuntimeError', function(e, err) {
+                                       self.dispatchEvent('RuntimeError', err);
+                               });
+                               _xhr.connectRuntime(_options);
+                       }
+               }
+       
+               
+               function _reset() {
+                       _p('responseText', "");
+                       _p('responseXML', null);
+                       _p('response', null);
+                       _p('status', 0);
+                       _p('statusText', "");
+                       _start_time = _timeoutset_time = null;
+               }
+       }
+
+       XMLHttpRequest.UNSENT = 0;
+       XMLHttpRequest.OPENED = 1;
+       XMLHttpRequest.HEADERS_RECEIVED = 2;
+       XMLHttpRequest.LOADING = 3;
+       XMLHttpRequest.DONE = 4;
+       
+       XMLHttpRequest.prototype = EventTarget.instance;
+
+       return XMLHttpRequest;
+});
+
+// Included from: src/javascript/runtime/Transporter.js
+
+/**
+ * Transporter.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+define("moxie/runtime/Transporter", [
+       "moxie/core/utils/Basic",
+       "moxie/core/utils/Encode",
+       "moxie/runtime/RuntimeClient",
+       "moxie/core/EventTarget"
+], function(Basic, Encode, RuntimeClient, EventTarget) {
+       function Transporter() {
+               var mod, _runtime, _data, _size, _pos, _chunk_size;
+
+               RuntimeClient.call(this);
+
+               Basic.extend(this, {
+                       uid: Basic.guid('uid_'),
+
+                       state: Transporter.IDLE,
+
+                       result: null,
+
+                       transport: function(data, type, options) {
+                               var self = this;
+
+                               options = Basic.extend({
+                                       chunk_size: 204798
+                               }, options);
+
+                               // should divide by three, base64 requires this
+                               if ((mod = options.chunk_size % 3)) {
+                                       options.chunk_size += 3 - mod;
+                               }
+
+                               _chunk_size = options.chunk_size;
+
+                               _reset.call(this);
+                               _data = data;
+                               _size = data.length;
+
+                               if (Basic.typeOf(options) === 'string' || options.ruid) {
+                                       _run.call(self, type, this.connectRuntime(options));
+                               } else {
+                                       // we require this to run only once
+                                       var cb = function(e, runtime) {
+                                               self.unbind("RuntimeInit", cb);
+                                               _run.call(self, type, runtime);
+                                       };
+                                       this.bind("RuntimeInit", cb);
+                                       this.connectRuntime(options);
+                               }
+                       },
+
+                       abort: function() {
+                               var self = this;
+
+                               self.state = Transporter.IDLE;
+                               if (_runtime) {
+                                       _runtime.exec.call(self, 'Transporter', 'clear');
+                                       self.trigger("TransportingAborted");
+                               }
+
+                               _reset.call(self);
+                       },
+
+
+                       destroy: function() {
+                               this.unbindAll();
+                               _runtime = null;
+                               this.disconnectRuntime();
+                               _reset.call(this);
+                       }
+               });
+
+               function _reset() {
+                       _size = _pos = 0;
+                       _data = this.result = null;
+               }
+
+               function _run(type, runtime) {
+                       var self = this;
+
+                       _runtime = runtime;
+
+                       //self.unbind("RuntimeInit");
+
+                       self.bind("TransportingProgress", function(e) {
+                               _pos = e.loaded;
+
+                               if (_pos < _size && Basic.inArray(self.state, [Transporter.IDLE, Transporter.DONE]) === -1) {
+                                       _transport.call(self);
+                               }
+                       }, 999);
+
+                       self.bind("TransportingComplete", function() {
+                               _pos = _size;
+                               self.state = Transporter.DONE;
+                               _data = null; // clean a bit
+                               self.result = _runtime.exec.call(self, 'Transporter', 'getAsBlob', type || '');
+                       }, 999);
+
+                       self.state = Transporter.BUSY;
+                       self.trigger("TransportingStarted");
+                       _transport.call(self);
+               }
+
+               function _transport() {
+                       var self = this,
+                               chunk,
+                               bytesLeft = _size - _pos;
+
+                       if (_chunk_size > bytesLeft) {
+                               _chunk_size = bytesLeft;
+                       }
+
+                       chunk = Encode.btoa(_data.substr(_pos, _chunk_size));
+                       _runtime.exec.call(self, 'Transporter', 'receive', chunk, _size);
+               }
+       }
+
+       Transporter.IDLE = 0;
+       Transporter.BUSY = 1;
+       Transporter.DONE = 2;
+
+       Transporter.prototype = EventTarget.instance;
+
+       return Transporter;
+});
+
+// Included from: src/javascript/image/Image.js
+
+/**
+ * Image.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+define("moxie/image/Image", [
+       "moxie/core/utils/Basic",
+       "moxie/core/utils/Dom",
+       "moxie/core/Exceptions",
+       "moxie/file/FileReaderSync",
+       "moxie/xhr/XMLHttpRequest",
+       "moxie/runtime/Runtime",
+       "moxie/runtime/RuntimeClient",
+       "moxie/runtime/Transporter",
+       "moxie/core/utils/Env",
+       "moxie/core/EventTarget",
+       "moxie/file/Blob",
+       "moxie/file/File",
+       "moxie/core/utils/Encode"
+], function(Basic, Dom, x, FileReaderSync, XMLHttpRequest, Runtime, RuntimeClient, Transporter, Env, EventTarget, Blob, File, Encode) {
+       /**
+       Image preloading and manipulation utility. Additionally it provides access to image meta info (Exif, GPS) and raw binary data.
+
+       @class Image
+       @constructor
+       @extends EventTarget
+       */
+       var dispatches = [
+               'progress',
+
+               /**
+               Dispatched when loading is complete.
+
+               @event load
+               @param {Object} event
+               */
+               'load',
+
+               'error',
+
+               /**
+               Dispatched when resize operation is complete.
+               
+               @event resize
+               @param {Object} event
+               */
+               'resize',
+
+               /**
+               Dispatched when visual representation of the image is successfully embedded
+               into the corresponsing container.
+
+               @event embedded
+               @param {Object} event
+               */
+               'embedded'
+       ];
+
+       function Image() {
+
+               RuntimeClient.call(this);
+
+               Basic.extend(this, {
+                       /**
+                       Unique id of the component
+
+                       @property uid
+                       @type {String}
+                       */
+                       uid: Basic.guid('uid_'),
+
+                       /**
+                       Unique id of the connected runtime, if any.
+
+                       @property ruid
+                       @type {String}
+                       */
+                       ruid: null,
+
+                       /**
+                       Name of the file, that was used to create an image, if available. If not equals to empty string.
+
+                       @property name
+                       @type {String}
+                       @default ""
+                       */
+                       name: "",
+
+                       /**
+                       Size of the image in bytes. Actual value is set only after image is preloaded.
+
+                       @property size
+                       @type {Number}
+                       @default 0
+                       */
+                       size: 0,
+
+                       /**
+                       Width of the image. Actual value is set only after image is preloaded.
+
+                       @property width
+                       @type {Number}
+                       @default 0
+                       */
+                       width: 0,
+
+                       /**
+                       Height of the image. Actual value is set only after image is preloaded.
+
+                       @property height
+                       @type {Number}
+                       @default 0
+                       */
+                       height: 0,
+
+                       /**
+                       Mime type of the image. Currently only image/jpeg and image/png are supported. Actual value is set only after image is preloaded.
+
+                       @property type
+                       @type {String}
+                       @default ""
+                       */
+                       type: "",
+
+                       /**
+                       Holds meta info (Exif, GPS). Is populated only for image/jpeg. Actual value is set only after image is preloaded.
+
+                       @property meta
+                       @type {Object}
+                       @default {}
+                       */
+                       meta: {},
+
+                       /**
+                       Alias for load method, that takes another mOxie.Image object as a source (see load).
+
+                       @method clone
+                       @param {Image} src Source for the image
+                       @param {Boolean} [exact=false] Whether to activate in-depth clone mode
+                       */
+                       clone: function() {
+                               this.load.apply(this, arguments);
+                       },
+
+                       /**
+                       Loads image from various sources. Currently the source for new image can be: mOxie.Image, mOxie.Blob/mOxie.File, 
+                       native Blob/File, dataUrl or URL. Depending on the type of the source, arguments - differ. When source is URL, 
+                       Image will be downloaded from remote destination and loaded in memory.
+
+                       @example
+                               var img = new mOxie.Image();
+                               img.onload = function() {
+                                       var blob = img.getAsBlob();
+                                       
+                                       var formData = new mOxie.FormData();
+                                       formData.append('file', blob);
+
+                                       var xhr = new mOxie.XMLHttpRequest();
+                                       xhr.onload = function() {
+                                               // upload complete
+                                       };
+                                       xhr.open('post', 'upload.php');
+                                       xhr.send(formData);
+                               };
+                               img.load("http://www.moxiecode.com/images/mox-logo.jpg"); // notice file extension (.jpg)
+                       
+
+                       @method load
+                       @param {Image|Blob|File|String} src Source for the image
+                       @param {Boolean|Object} [mixed]
+                       */
+                       load: function() {
+                               _load.apply(this, arguments);
+                       },
+
+                       /**
+                       Downsizes the image to fit the specified width/height. If crop is supplied, image will be cropped to exact dimensions.
+
+                       @method downsize
+                       @param {Object} opts
+                               @param {Number} opts.width Resulting width
+                               @param {Number} [opts.height=width] Resulting height (optional, if not supplied will default to width)
+                               @param {Boolean} [opts.crop=false] Whether to crop the image to exact dimensions
+                               @param {Boolean} [opts.preserveHeaders=true] Whether to preserve meta headers (on JPEGs after resize)
+                               @param {String} [opts.resample=false] Resampling algorithm to use for resizing
+                       */
+                       downsize: function(opts) {
+                               var defaults = {
+                                       width: this.width,
+                                       height: this.height,
+                                       type: this.type || 'image/jpeg',
+                                       quality: 90,
+                                       crop: false,
+                                       preserveHeaders: true,
+                                       resample: false
+                               };
+
+                               if (typeof(opts) === 'object') {
+                                       opts = Basic.extend(defaults, opts);
+                               } else {
+                                       // for backward compatibility
+                                       opts = Basic.extend(defaults, {
+                                               width: arguments[0],
+                                               height: arguments[1],
+                                               crop: arguments[2],
+                                               preserveHeaders: arguments[3]
+                                       });
+                               }
+
+                               try {
+                                       if (!this.size) { // only preloaded image objects can be used as source
+                                               throw new x.DOMException(x.DOMException.INVALID_STATE_ERR);
+                                       }
+
+                                       // no way to reliably intercept the crash due to high resolution, so we simply avoid it
+                                       if (this.width > Image.MAX_RESIZE_WIDTH || this.height > Image.MAX_RESIZE_HEIGHT) {
+                                               throw new x.ImageError(x.ImageError.MAX_RESOLUTION_ERR);
+                                       }
+
+                                       this.exec('Image', 'downsize', opts.width, opts.height, opts.crop, opts.preserveHeaders);
+                               } catch(ex) {
+                                       // for now simply trigger error event
+                                       this.trigger('error', ex.code);
+                               }
+                       },
+
+                       /**
+                       Alias for downsize(width, height, true). (see downsize)
+                       
+                       @method crop
+                       @param {Number} width Resulting width
+                       @param {Number} [height=width] Resulting height (optional, if not supplied will default to width)
+                       @param {Boolean} [preserveHeaders=true] Whether to preserve meta headers (on JPEGs after resize)
+                       */
+                       crop: function(width, height, preserveHeaders) {
+                               this.downsize(width, height, true, preserveHeaders);
+                       },
+
+                       getAsCanvas: function() {
+                               if (!Env.can('create_canvas')) {
+                                       throw new x.RuntimeError(x.RuntimeError.NOT_SUPPORTED_ERR);
+                               }
+
+                               var runtime = this.connectRuntime(this.ruid);
+                               return runtime.exec.call(this, 'Image', 'getAsCanvas');
+                       },
+
+                       /**
+                       Retrieves image in it's current state as mOxie.Blob object. Cannot be run on empty or image in progress (throws
+                       DOMException.INVALID_STATE_ERR).
+
+                       @method getAsBlob
+                       @param {String} [type="image/jpeg"] Mime type of resulting blob. Can either be image/jpeg or image/png
+                       @param {Number} [quality=90] Applicable only together with mime type image/jpeg
+                       @return {Blob} Image as Blob
+                       */
+                       getAsBlob: function(type, quality) {
+                               if (!this.size) {
+                                       throw new x.DOMException(x.DOMException.INVALID_STATE_ERR);
+                               }
+                               return this.exec('Image', 'getAsBlob', type || 'image/jpeg', quality || 90);
+                       },
+
+                       /**
+                       Retrieves image in it's current state as dataURL string. Cannot be run on empty or image in progress (throws
+                       DOMException.INVALID_STATE_ERR).
+
+                       @method getAsDataURL
+                       @param {String} [type="image/jpeg"] Mime type of resulting blob. Can either be image/jpeg or image/png
+                       @param {Number} [quality=90] Applicable only together with mime type image/jpeg
+                       @return {String} Image as dataURL string
+                       */
+                       getAsDataURL: function(type, quality) {
+                               if (!this.size) {
+                                       throw new x.DOMException(x.DOMException.INVALID_STATE_ERR);
+                               }
+                               return this.exec('Image', 'getAsDataURL', type || 'image/jpeg', quality || 90);
+                       },
+
+                       /**
+                       Retrieves image in it's current state as binary string. Cannot be run on empty or image in progress (throws
+                       DOMException.INVALID_STATE_ERR).
+
+                       @method getAsBinaryString
+                       @param {String} [type="image/jpeg"] Mime type of resulting blob. Can either be image/jpeg or image/png
+                       @param {Number} [quality=90] Applicable only together with mime type image/jpeg
+                       @return {String} Image as binary string
+                       */
+                       getAsBinaryString: function(type, quality) {
+                               var dataUrl = this.getAsDataURL(type, quality);
+                               return Encode.atob(dataUrl.substring(dataUrl.indexOf('base64,') + 7));
+                       },
+
+                       /**
+                       Embeds a visual representation of the image into the specified node. Depending on the runtime, 
+                       it might be a canvas, an img node or a thrid party shim object (Flash or SilverLight - very rare, 
+                       can be used in legacy browsers that do not have canvas or proper dataURI support).
+
+                       @method embed
+                       @param {DOMElement} el DOM element to insert the image object into
+                       @param {Object} [opts]
+                               @param {Number} [opts.width] The width of an embed (defaults to the image width)
+                               @param {Number} [opts.height] The height of an embed (defaults to the image height)
+                               @param {String} [type="image/jpeg"] Mime type
+                               @param {Number} [quality=90] Quality of an embed, if mime type is image/jpeg
+                               @param {Boolean} [crop=false] Whether to crop an embed to the specified dimensions
+                       */
+                       embed: function(el, opts) {
+                               var self = this
+                               , runtime // this has to be outside of all the closures to contain proper runtime
+                               ;
+
+                               opts = Basic.extend({
+                                       width: this.width,
+                                       height: this.height,
+                                       type: this.type || 'image/jpeg',
+                                       quality: 90
+                               }, opts || {});
+                               
+
+                               function render(type, quality) {
+                                       var img = this;
+
+                                       // if possible, embed a canvas element directly
+                                       if (Env.can('create_canvas')) {
+                                               var canvas = img.getAsCanvas();
+                                               if (canvas) {
+                                                       el.appendChild(canvas);
+                                                       canvas = null;
+                                                       img.destroy();
+                                                       self.trigger('embedded');
+                                                       return;
+                                               }
+                                       }
+
+                                       var dataUrl = img.getAsDataURL(type, quality);
+                                       if (!dataUrl) {
+                                               throw new x.ImageError(x.ImageError.WRONG_FORMAT);
+                                       }
+
+                                       if (Env.can('use_data_uri_of', dataUrl.length)) {
+                                               el.innerHTML = '<img src="' + dataUrl + '" width="' + img.width + '" height="' + img.height + '" />';
+                                               img.destroy();
+                                               self.trigger('embedded');
+                                       } else {
+                                               var tr = new Transporter();
+
+                                               tr.bind("TransportingComplete", function() {
+                                                       runtime = self.connectRuntime(this.result.ruid);
+
+                                                       self.bind("Embedded", function() {
+                                                               // position and size properly
+                                                               Basic.extend(runtime.getShimContainer().style, {
+                                                                       //position: 'relative',
+                                                                       top: '0px',
+                                                                       left: '0px',
+                                                                       width: img.width + 'px',
+                                                                       height: img.height + 'px'
+                                                               });
+
+                                                               // some shims (Flash/SilverLight) reinitialize, if parent element is hidden, reordered or it's
+                                                               // position type changes (in Gecko), but since we basically need this only in IEs 6/7 and
+                                                               // sometimes 8 and they do not have this problem, we can comment this for now
+                                                               /*tr.bind("RuntimeInit", function(e, runtime) {
+                                                                       tr.destroy();
+                                                                       runtime.destroy();
+                                                                       onResize.call(self); // re-feed our image data
+                                                               });*/
+
+                                                               runtime = null; // release
+                                                       }, 999);
+
+                                                       runtime.exec.call(self, "ImageView", "display", this.result.uid, width, height);
+                                                       img.destroy();
+                                               });
+
+                                               tr.transport(Encode.atob(dataUrl.substring(dataUrl.indexOf('base64,') + 7)), type, {
+                                                       required_caps: {
+                                                               display_media: true
+                                                       },
+                                                       runtime_order: 'flash,silverlight',
+                                                       container: el
+                                               });
+                                       }
+                               }
+
+                               try {
+                                       if (!(el = Dom.get(el))) {
+                                               throw new x.DOMException(x.DOMException.INVALID_NODE_TYPE_ERR);
+                                       }
+
+                                       if (!this.size) { // only preloaded image objects can be used as source
+                                               throw new x.DOMException(x.DOMException.INVALID_STATE_ERR);
+                                       }
+                                       
+                                       // high-resolution images cannot be consistently handled across the runtimes
+                                       if (this.width > Image.MAX_RESIZE_WIDTH || this.height > Image.MAX_RESIZE_HEIGHT) {
+                                               //throw new x.ImageError(x.ImageError.MAX_RESOLUTION_ERR);
+                                       }
+
+                                       var imgCopy = new Image();
+
+                                       imgCopy.bind("Resize", function() {
+                                               render.call(this, opts.type, opts.quality);
+                                       });
+
+                                       imgCopy.bind("Load", function() {
+                                               imgCopy.downsize(opts);
+                                       });
+
+                                       // if embedded thumb data is available and dimensions are big enough, use it
+                                       if (this.meta.thumb && this.meta.thumb.width >= opts.width && this.meta.thumb.height >= opts.height) {
+                                               imgCopy.load(this.meta.thumb.data);
+                                       } else {
+                                               imgCopy.clone(this, false);
+                                       }
+
+                                       return imgCopy;
+                               } catch(ex) {
+                                       // for now simply trigger error event
+                                       this.trigger('error', ex.code);
+                               }
+                       },
+
+                       /**
+                       Properly destroys the image and frees resources in use. If any. Recommended way to dispose mOxie.Image object.
+
+                       @method destroy
+                       */
+                       destroy: function() {
+                               if (this.ruid) {
+                                       this.getRuntime().exec.call(this, 'Image', 'destroy');
+                                       this.disconnectRuntime();
+                               }
+                               this.unbindAll();
+                       }
+               });
+
+
+               // this is here, because in order to bind properly, we need uid, which is created above
+               this.handleEventProps(dispatches);
+
+               this.bind('Load Resize', function() {
+                       _updateInfo.call(this);
+               }, 999);
+
+
+               function _updateInfo(info) {
+                       if (!info) {
+                               info = this.exec('Image', 'getInfo');
+                       }
+
+                       this.size = info.size;
+                       this.width = info.width;
+                       this.height = info.height;
+                       this.type = info.type;
+                       this.meta = info.meta;
+
+                       // update file name, only if empty
+                       if (this.name === '') {
+                               this.name = info.name;
+                       }
+               }
+               
+
+               function _load(src) {
+                       var srcType = Basic.typeOf(src);
+
+                       try {
+                               // if source is Image
+                               if (src instanceof Image) {
+                                       if (!src.size) { // only preloaded image objects can be used as source
+                                               throw new x.DOMException(x.DOMException.INVALID_STATE_ERR);
+                                       }
+                                       _loadFromImage.apply(this, arguments);
+                               }
+                               // if source is o.Blob/o.File
+                               else if (src instanceof Blob) {
+                                       if (!~Basic.inArray(src.type, ['image/jpeg', 'image/png'])) {
+                                               throw new x.ImageError(x.ImageError.WRONG_FORMAT);
+                                       }
+                                       _loadFromBlob.apply(this, arguments);
+                               }
+                               // if native blob/file
+                               else if (Basic.inArray(srcType, ['blob', 'file']) !== -1) {
+                                       _load.call(this, new File(null, src), arguments[1]);
+                               }
+                               // if String
+                               else if (srcType === 'string') {
+                                       // if dataUrl String
+                                       if (src.substr(0, 5) === 'data:') {
+                                               _load.call(this, new Blob(null, { data: src }), arguments[1]);
+                                       }
+                                       // else assume Url, either relative or absolute
+                                       else {
+                                               _loadFromUrl.apply(this, arguments);
+                                       }
+                               }
+                               // if source seems to be an img node
+                               else if (srcType === 'node' && src.nodeName.toLowerCase() === 'img') {
+                                       _load.call(this, src.src, arguments[1]);
+                               }
+                               else {
+                                       throw new x.DOMException(x.DOMException.TYPE_MISMATCH_ERR);
+                               }
+                       } catch(ex) {
+                               // for now simply trigger error event
+                               this.trigger('error', ex.code);
+                       }
+               }
+
+
+               function _loadFromImage(img, exact) {
+                       var runtime = this.connectRuntime(img.ruid);
+                       this.ruid = runtime.uid;
+                       runtime.exec.call(this, 'Image', 'loadFromImage', img, (Basic.typeOf(exact) === 'undefined' ? true : exact));
+               }
+
+
+               function _loadFromBlob(blob, options) {
+                       var self = this;
+
+                       self.name = blob.name || '';
+
+                       function exec(runtime) {
+                               self.ruid = runtime.uid;
+                               runtime.exec.call(self, 'Image', 'loadFromBlob', blob);
+                       }
+
+                       if (blob.isDetached()) {
+                               this.bind('RuntimeInit', function(e, runtime) {
+                                       exec(runtime);
+                               });
+
+                               // convert to object representation
+                               if (options && typeof(options.required_caps) === 'string') {
+                                       options.required_caps = Runtime.parseCaps(options.required_caps);
+                               }
+
+                               this.connectRuntime(Basic.extend({
+                                       required_caps: {
+                                               access_image_binary: true,
+                                               resize_image: true
+                                       }
+                               }, options));
+                       } else {
+                               exec(this.connectRuntime(blob.ruid));
+                       }
+               }
+
+
+               function _loadFromUrl(url, options) {
+                       var self = this, xhr;
+
+                       xhr = new XMLHttpRequest();
+
+                       xhr.open('get', url);
+                       xhr.responseType = 'blob';
+
+                       xhr.onprogress = function(e) {
+                               self.trigger(e);
+                       };
+
+                       xhr.onload = function() {
+                               _loadFromBlob.call(self, xhr.response, true);
+                       };
+
+                       xhr.onerror = function(e) {
+                               self.trigger(e);
+                       };
+
+                       xhr.onloadend = function() {
+                               xhr.destroy();
+                       };
+
+                       xhr.bind('RuntimeError', function(e, err) {
+                               self.trigger('RuntimeError', err);
+                       });
+
+                       xhr.send(null, options);
+               }
+       }
+
+       // virtual world will crash on you if image has a resolution higher than this:
+       Image.MAX_RESIZE_WIDTH = 8192;
+       Image.MAX_RESIZE_HEIGHT = 8192; 
+
+       Image.prototype = EventTarget.instance;
+
+       return Image;
+});
+
+// Included from: src/javascript/runtime/html5/Runtime.js
+
+/**
+ * Runtime.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+/*global File:true */
+
+/**
+Defines constructor for HTML5 runtime.
+
+@class moxie/runtime/html5/Runtime
+@private
+*/
+define("moxie/runtime/html5/Runtime", [
+       "moxie/core/utils/Basic",
+       "moxie/core/Exceptions",
+       "moxie/runtime/Runtime",
+       "moxie/core/utils/Env"
+], function(Basic, x, Runtime, Env) {
+       
+       var type = "html5", extensions = {};
+       
+       function Html5Runtime(options) {
+               var I = this
+               , Test = Runtime.capTest
+               , True = Runtime.capTrue
+               ;
+
+               var caps = Basic.extend({
+                               access_binary: Test(window.FileReader || window.File && window.File.getAsDataURL),
+                               access_image_binary: function() {
+                                       return I.can('access_binary') && !!extensions.Image;
+                               },
+                               display_media: Test(Env.can('create_canvas') || Env.can('use_data_uri_over32kb')),
+                               do_cors: Test(window.XMLHttpRequest && 'withCredentials' in new XMLHttpRequest()),
+                               drag_and_drop: Test(function() {
+                                       // this comes directly from Modernizr: http://www.modernizr.com/
+                                       var div = document.createElement('div');
+                                       // IE has support for drag and drop since version 5, but doesn't support dropping files from desktop
+                                       return (('draggable' in div) || ('ondragstart' in div && 'ondrop' in div)) && 
+                                               (Env.browser !== 'IE' || Env.verComp(Env.version, 9, '>'));
+                               }()),
+                               filter_by_extension: Test(function() { // if you know how to feature-detect this, please suggest
+                                       return (Env.browser === 'Chrome' && Env.verComp(Env.version, 28, '>=')) || 
+                                               (Env.browser === 'IE' && Env.verComp(Env.version, 10, '>=')) || 
+                                               (Env.browser === 'Safari' && Env.verComp(Env.version, 7, '>='));
+                               }()),
+                               return_response_headers: True,
+                               return_response_type: function(responseType) {
+                                       if (responseType === 'json' && !!window.JSON) { // we can fake this one even if it's not supported
+                                               return true;
+                                       } 
+                                       return Env.can('return_response_type', responseType);
+                               },
+                               return_status_code: True,
+                               report_upload_progress: Test(window.XMLHttpRequest && new XMLHttpRequest().upload),
+                               resize_image: function() {
+                                       return I.can('access_binary') && Env.can('create_canvas');
+                               },
+                               select_file: function() {
+                                       return Env.can('use_fileinput') && window.File;
+                               },
+                               select_folder: function() {
+                                       return I.can('select_file') && Env.browser === 'Chrome' && Env.verComp(Env.version, 21, '>=');
+                               },
+                               select_multiple: function() {
+                                       // it is buggy on Safari Windows and iOS
+                                       return I.can('select_file') &&
+                                               !(Env.browser === 'Safari' && Env.os === 'Windows') &&
+                                               !(Env.os === 'iOS' && Env.verComp(Env.osVersion, "7.0.0", '>') && Env.verComp(Env.osVersion, "8.0.0", '<'));
+                               },
+                               send_binary_string: Test(window.XMLHttpRequest && (new XMLHttpRequest().sendAsBinary || (window.Uint8Array && window.ArrayBuffer))),
+                               send_custom_headers: Test(window.XMLHttpRequest),
+                               send_multipart: function() {
+                                       return !!(window.XMLHttpRequest && new XMLHttpRequest().upload && window.FormData) || I.can('send_binary_string');
+                               },
+                               slice_blob: Test(window.File && (File.prototype.mozSlice || File.prototype.webkitSlice || File.prototype.slice)),
+                               stream_upload: function(){
+                                       return I.can('slice_blob') && I.can('send_multipart');
+                               },
+                               summon_file_dialog: function() { // yeah... some dirty sniffing here...
+                                       return I.can('select_file') && (
+                                               (Env.browser === 'Firefox' && Env.verComp(Env.version, 4, '>=')) ||
+                                               (Env.browser === 'Opera' && Env.verComp(Env.version, 12, '>=')) ||
+                                               (Env.browser === 'IE' && Env.verComp(Env.version, 10, '>=')) ||
+                                               !!~Basic.inArray(Env.browser, ['Chrome', 'Safari'])
+                                       );
+                               },
+                               upload_filesize: True
+                       }, 
+                       arguments[2]
+               );
+
+               Runtime.call(this, options, (arguments[1] || type), caps);
+
+
+               Basic.extend(this, {
+
+                       init : function() {
+                               this.trigger("Init");
+                       },
+
+                       destroy: (function(destroy) { // extend default destroy method
+                               return function() {
+                                       destroy.call(I);
+                                       destroy = I = null;
+                               };
+                       }(this.destroy))
+               });
+
+               Basic.extend(this.getShim(), extensions);
+       }
+
+       Runtime.addConstructor(type, Html5Runtime);
+
+       return extensions;
+});
+
+// Included from: src/javascript/core/utils/Events.js
+
+/**
+ * Events.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+define('moxie/core/utils/Events', [
+       'moxie/core/utils/Basic'
+], function(Basic) {
+       var eventhash = {}, uid = 'moxie_' + Basic.guid();
+       
+       // IE W3C like event funcs
+       function preventDefault() {
+               this.returnValue = false;
+       }
+
+       function stopPropagation() {
+               this.cancelBubble = true;
+       }
+
+       /**
+       Adds an event handler to the specified object and store reference to the handler
+       in objects internal Plupload registry (@see removeEvent).
+       
+       @method addEvent
+       @for Utils
+       @static
+       @param {Object} obj DOM element like object to add handler to.
+       @param {String} name Name to add event listener to.
+       @param {Function} callback Function to call when event occurs.
+       @param {String} [key] that might be used to add specifity to the event record.
+       */
+       var addEvent = function(obj, name, callback, key) {
+               var func, events;
+                                       
+               name = name.toLowerCase();
+
+               // Add event listener
+               if (obj.addEventListener) {
+                       func = callback;
+                       
+                       obj.addEventListener(name, func, false);
+               } else if (obj.attachEvent) {
+                       func = function() {
+                               var evt = window.event;
+
+                               if (!evt.target) {
+                                       evt.target = evt.srcElement;
+                               }
+
+                               evt.preventDefault = preventDefault;
+                               evt.stopPropagation = stopPropagation;
+
+                               callback(evt);
+                       };
+
+                       obj.attachEvent('on' + name, func);
+               }
+               
+               // Log event handler to objects internal mOxie registry
+               if (!obj[uid]) {
+                       obj[uid] = Basic.guid();
+               }
+               
+               if (!eventhash.hasOwnProperty(obj[uid])) {
+                       eventhash[obj[uid]] = {};
+               }
+               
+               events = eventhash[obj[uid]];
+               
+               if (!events.hasOwnProperty(name)) {
+                       events[name] = [];
+               }
+                               
+               events[name].push({
+                       func: func,
+                       orig: callback, // store original callback for IE
+                       key: key
+               });
+       };
+       
+       
+       /**
+       Remove event handler from the specified object. If third argument (callback)
+       is not specified remove all events with the specified name.
+       
+       @method removeEvent
+       @static
+       @param {Object} obj DOM element to remove event listener(s) from.
+       @param {String} name Name of event listener to remove.
+       @param {Function|String} [callback] might be a callback or unique key to match.
+       */
+       var removeEvent = function(obj, name, callback) {
+               var type, undef;
+               
+               name = name.toLowerCase();
+               
+               if (obj[uid] && eventhash[obj[uid]] && eventhash[obj[uid]][name]) {
+                       type = eventhash[obj[uid]][name];
+               } else {
+                       return;
+               }
+                       
+               for (var i = type.length - 1; i >= 0; i--) {
+                       // undefined or not, key should match
+                       if (type[i].orig === callback || type[i].key === callback) {
+                               if (obj.removeEventListener) {
+                                       obj.removeEventListener(name, type[i].func, false);
+                               } else if (obj.detachEvent) {
+                                       obj.detachEvent('on'+name, type[i].func);
+                               }
+                               
+                               type[i].orig = null;
+                               type[i].func = null;
+                               type.splice(i, 1);
+                               
+                               // If callback was passed we are done here, otherwise proceed
+                               if (callback !== undef) {
+                                       break;
+                               }
+                       }
+               }
+               
+               // If event array got empty, remove it
+               if (!type.length) {
+                       delete eventhash[obj[uid]][name];
+               }
+               
+               // If mOxie registry has become empty, remove it
+               if (Basic.isEmptyObj(eventhash[obj[uid]])) {
+                       delete eventhash[obj[uid]];
+                       
+                       // IE doesn't let you remove DOM object property with - delete
+                       try {
+                               delete obj[uid];
+                       } catch(e) {
+                               obj[uid] = undef;
+                       }
+               }
+       };
+       
+       
+       /**
+       Remove all kind of events from the specified object
+       
+       @method removeAllEvents
+       @static
+       @param {Object} obj DOM element to remove event listeners from.
+       @param {String} [key] unique key to match, when removing events.
+       */
+       var removeAllEvents = function(obj, key) {              
+               if (!obj || !obj[uid]) {
+                       return;
+               }
+               
+               Basic.each(eventhash[obj[uid]], function(events, name) {
+                       removeEvent(obj, name, key);
+               });
+       };
+
+       return {
+               addEvent: addEvent,
+               removeEvent: removeEvent,
+               removeAllEvents: removeAllEvents
+       };
+});
+
+// Included from: src/javascript/runtime/html5/file/FileInput.js
+
+/**
+ * FileInput.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+/**
+@class moxie/runtime/html5/file/FileInput
+@private
+*/
+define("moxie/runtime/html5/file/FileInput", [
+       "moxie/runtime/html5/Runtime",
+       "moxie/file/File",
+       "moxie/core/utils/Basic",
+       "moxie/core/utils/Dom",
+       "moxie/core/utils/Events",
+       "moxie/core/utils/Mime",
+       "moxie/core/utils/Env"
+], function(extensions, File, Basic, Dom, Events, Mime, Env) {
+       
+       function FileInput() {
+               var _options;
+
+               Basic.extend(this, {
+                       init: function(options) {
+                               var comp = this, I = comp.getRuntime(), input, shimContainer, mimes, browseButton, zIndex, top;
+
+                               _options = options;
+
+                               // figure out accept string
+                               mimes = _options.accept.mimes || Mime.extList2mimes(_options.accept, I.can('filter_by_extension'));
+
+                               shimContainer = I.getShimContainer();
+
+                               shimContainer.innerHTML = '<input id="' + I.uid +'" type="file" style="font-size:999px;opacity:0;"' +
+                                       (_options.multiple && I.can('select_multiple') ? 'multiple' : '') + 
+                                       (_options.directory && I.can('select_folder') ? 'webkitdirectory directory' : '') + // Chrome 11+
+                                       (mimes ? ' accept="' + mimes.join(',') + '"' : '') + ' />';
+
+                               input = Dom.get(I.uid);
+
+                               // prepare file input to be placed underneath the browse_button element
+                               Basic.extend(input.style, {
+                                       position: 'absolute',
+                                       top: 0,
+                                       left: 0,
+                                       width: '100%',
+                                       height: '100%'
+                               });
+
+
+                               browseButton = Dom.get(_options.browse_button);
+
+                               // Route click event to the input[type=file] element for browsers that support such behavior
+                               if (I.can('summon_file_dialog')) {
+                                       if (Dom.getStyle(browseButton, 'position') === 'static') {
+                                               browseButton.style.position = 'relative';
+                                       }
+
+                                       zIndex = parseInt(Dom.getStyle(browseButton, 'z-index'), 10) || 1;
+
+                                       browseButton.style.zIndex = zIndex;
+                                       shimContainer.style.zIndex = zIndex - 1;
+
+                                       Events.addEvent(browseButton, 'click', function(e) {
+                                               var input = Dom.get(I.uid);
+                                               if (input && !input.disabled) { // for some reason FF (up to 8.0.1 so far) lets to click disabled input[type=file]
+                                                       input.click();
+                                               }
+                                               e.preventDefault();
+                                       }, comp.uid);
+                               }
+
+                               /* Since we have to place input[type=file] on top of the browse_button for some browsers,
+                               browse_button loses interactivity, so we restore it here */
+                               top = I.can('summon_file_dialog') ? browseButton : shimContainer;
+
+                               Events.addEvent(top, 'mouseover', function() {
+                                       comp.trigger('mouseenter');
+                               }, comp.uid);
+
+                               Events.addEvent(top, 'mouseout', function() {
+                                       comp.trigger('mouseleave');
+                               }, comp.uid);
+
+                               Events.addEvent(top, 'mousedown', function() {
+                                       comp.trigger('mousedown');
+                               }, comp.uid);
+
+                               Events.addEvent(Dom.get(_options.container), 'mouseup', function() {
+                                       comp.trigger('mouseup');
+                               }, comp.uid);
+
+
+                               input.onchange = function onChange(e) { // there should be only one handler for this
+                                       comp.files = [];
+
+                                       Basic.each(this.files, function(file) {
+                                               var relativePath = '';
+
+                                               if (_options.directory) {
+                                                       // folders are represented by dots, filter them out (Chrome 11+)
+                                                       if (file.name == ".") {
+                                                               // if it looks like a folder...
+                                                               return true;
+                                                       }
+                                               }
+
+                                               if (file.webkitRelativePath) {
+                                                       relativePath = '/' + file.webkitRelativePath.replace(/^\//, '');
+                                               }
+                                               
+                                               file = new File(I.uid, file);
+                                               file.relativePath = relativePath;
+
+                                               comp.files.push(file);
+                                       });
+
+                                       // clearing the value enables the user to select the same file again if they want to
+                                       if (Env.browser !== 'IE' && Env.browser !== 'IEMobile') {
+                                               this.value = '';
+                                       } else {
+                                               // in IE input[type="file"] is read-only so the only way to reset it is to re-insert it
+                                               var clone = this.cloneNode(true);
+                                               this.parentNode.replaceChild(clone, this);
+                                               clone.onchange = onChange;
+                                       }
+
+                                       if (comp.files.length) {
+                                               comp.trigger('change');
+                                       }
+                               };
+
+                               // ready event is perfectly asynchronous
+                               comp.trigger({
+                                       type: 'ready',
+                                       async: true
+                               });
+
+                               shimContainer = null;
+                       },
+
+
+                       disable: function(state) {
+                               var I = this.getRuntime(), input;
+
+                               if ((input = Dom.get(I.uid))) {
+                                       input.disabled = !!state;
+                               }
+                       },
+
+                       destroy: function() {
+                               var I = this.getRuntime()
+                               , shim = I.getShim()
+                               , shimContainer = I.getShimContainer()
+                               ;
+                               
+                               Events.removeAllEvents(shimContainer, this.uid);
+                               Events.removeAllEvents(_options && Dom.get(_options.container), this.uid);
+                               Events.removeAllEvents(_options && Dom.get(_options.browse_button), this.uid);
+                               
+                               if (shimContainer) {
+                                       shimContainer.innerHTML = '';
+                               }
+
+                               shim.removeInstance(this.uid);
+
+                               _options = shimContainer = shim = null;
+                       }
+               });
+       }
+
+       return (extensions.FileInput = FileInput);
+});
+
+// Included from: src/javascript/runtime/html5/file/Blob.js
+
+/**
+ * Blob.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+/**
+@class moxie/runtime/html5/file/Blob
+@private
+*/
+define("moxie/runtime/html5/file/Blob", [
+       "moxie/runtime/html5/Runtime",
+       "moxie/file/Blob"
+], function(extensions, Blob) {
+
+       function HTML5Blob() {
+               function w3cBlobSlice(blob, start, end) {
+                       var blobSlice;
+
+                       if (window.File.prototype.slice) {
+                               try {
+                                       blob.slice();   // depricated version will throw WRONG_ARGUMENTS_ERR exception
+                                       return blob.slice(start, end);
+                               } catch (e) {
+                                       // depricated slice method
+                                       return blob.slice(start, end - start);
+                               }
+                       // slice method got prefixed: https://bugzilla.mozilla.org/show_bug.cgi?id=649672
+                       } else if ((blobSlice = window.File.prototype.webkitSlice || window.File.prototype.mozSlice)) {
+                               return blobSlice.call(blob, start, end);
+                       } else {
+                               return null; // or throw some exception
+                       }
+               }
+
+               this.slice = function() {
+                       return new Blob(this.getRuntime().uid, w3cBlobSlice.apply(this, arguments));
+               };
+       }
+
+       return (extensions.Blob = HTML5Blob);
+});
+
+// Included from: src/javascript/runtime/html5/file/FileDrop.js
+
+/**
+ * FileDrop.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+/**
+@class moxie/runtime/html5/file/FileDrop
+@private
+*/
+define("moxie/runtime/html5/file/FileDrop", [
+       "moxie/runtime/html5/Runtime",
+       'moxie/file/File',
+       "moxie/core/utils/Basic",
+       "moxie/core/utils/Dom",
+       "moxie/core/utils/Events",
+       "moxie/core/utils/Mime"
+], function(extensions, File, Basic, Dom, Events, Mime) {
+       
+       function FileDrop() {
+               var _files = [], _allowedExts = [], _options, _ruid;
+
+               Basic.extend(this, {
+                       init: function(options) {
+                               var comp = this, dropZone;
+
+                               _options = options;
+                               _ruid = comp.ruid; // every dropped-in file should have a reference to the runtime
+                               _allowedExts = _extractExts(_options.accept);
+                               dropZone = _options.container;
+
+                               Events.addEvent(dropZone, 'dragover', function(e) {
+                                       if (!_hasFiles(e)) {
+                                               return;
+                                       }
+                                       e.preventDefault();
+                                       e.dataTransfer.dropEffect = 'copy';
+                               }, comp.uid);
+
+                               Events.addEvent(dropZone, 'drop', function(e) {
+                                       if (!_hasFiles(e)) {
+                                               return;
+                                       }
+                                       e.preventDefault();
+
+                                       _files = [];
+
+                                       // Chrome 21+ accepts folders via Drag'n'Drop
+                                       if (e.dataTransfer.items && e.dataTransfer.items[0].webkitGetAsEntry) {
+                                               _readItems(e.dataTransfer.items, function() {
+                                                       comp.files = _files;
+                                                       comp.trigger("drop");
+                                               });
+                                       } else {
+                                               Basic.each(e.dataTransfer.files, function(file) {
+                                                       _addFile(file);
+                                               });
+                                               comp.files = _files;
+                                               comp.trigger("drop");
+                                       }
+                               }, comp.uid);
+
+                               Events.addEvent(dropZone, 'dragenter', function(e) {
+                                       comp.trigger("dragenter");
+                               }, comp.uid);
+
+                               Events.addEvent(dropZone, 'dragleave', function(e) {
+                                       comp.trigger("dragleave");
+                               }, comp.uid);
+                       },
+
+                       destroy: function() {
+                               Events.removeAllEvents(_options && Dom.get(_options.container), this.uid);
+                               _ruid = _files = _allowedExts = _options = null;
+                       }
+               });
+
+
+               function _hasFiles(e) {
+                       if (!e.dataTransfer || !e.dataTransfer.types) { // e.dataTransfer.files is not available in Gecko during dragover
+                               return false;
+                       }
+
+                       var types = Basic.toArray(e.dataTransfer.types || []);
+
+                       return Basic.inArray("Files", types) !== -1 ||
+                               Basic.inArray("public.file-url", types) !== -1 || // Safari < 5
+                               Basic.inArray("application/x-moz-file", types) !== -1 // Gecko < 1.9.2 (< Firefox 3.6)
+                               ;
+               }
+
+
+               function _addFile(file, relativePath) {
+                       if (_isAcceptable(file)) {
+                               var fileObj = new File(_ruid, file);
+                               fileObj.relativePath = relativePath || '';
+                               _files.push(fileObj);
+                       }
+               }
+
+               
+               function _extractExts(accept) {
+                       var exts = [];
+                       for (var i = 0; i < accept.length; i++) {
+                               [].push.apply(exts, accept[i].extensions.split(/\s*,\s*/));
+                       }
+                       return Basic.inArray('*', exts) === -1 ? exts : [];
+               }
+
+
+               function _isAcceptable(file) {
+                       if (!_allowedExts.length) {
+                               return true;
+                       }
+                       var ext = Mime.getFileExtension(file.name);
+                       return !ext || Basic.inArray(ext, _allowedExts) !== -1;
+               }
+
+
+               function _readItems(items, cb) {
+                       var entries = [];
+                       Basic.each(items, function(item) {
+                               var entry = item.webkitGetAsEntry();
+                               // Address #998 (https://code.google.com/p/chromium/issues/detail?id=332579)
+                               if (entry) {
+                                       // file() fails on OSX when the filename contains a special character (e.g. umlaut): see #61
+                                       if (entry.isFile) {
+                                               _addFile(item.getAsFile(), entry.fullPath);
+                                       } else {
+                                               entries.push(entry);
+                                       }
+                               }
+                       });
+
+                       if (entries.length) {
+                               _readEntries(entries, cb);
+                       } else {
+                               cb();
+                       }
+               }
+
+
+               function _readEntries(entries, cb) {
+                       var queue = [];
+                       Basic.each(entries, function(entry) {
+                               queue.push(function(cbcb) {
+                                       _readEntry(entry, cbcb);
+                               });
+                       });
+                       Basic.inSeries(queue, function() {
+                               cb();
+                       });
+               }
+
+
+               function _readEntry(entry, cb) {
+                       if (entry.isFile) {
+                               entry.file(function(file) {
+                                       _addFile(file, entry.fullPath);
+                                       cb();
+                               }, function() {
+                                       // fire an error event maybe
+                                       cb();
+                               });
+                       } else if (entry.isDirectory) {
+                               _readDirEntry(entry, cb);
+                       } else {
+                               cb(); // not file, not directory? what then?..
+                       }
+               }
+
+
+               function _readDirEntry(dirEntry, cb) {
+                       var entries = [], dirReader = dirEntry.createReader();
+
+                       // keep quering recursively till no more entries
+                       function getEntries(cbcb) {
+                               dirReader.readEntries(function(moreEntries) {
+                                       if (moreEntries.length) {
+                                               [].push.apply(entries, moreEntries);
+                                               getEntries(cbcb);
+                                       } else {
+                                               cbcb();
+                                       }
+                               }, cbcb);
+                       }
+
+                       // ...and you thought FileReader was crazy...
+                       getEntries(function() {
+                               _readEntries(entries, cb);
+                       }); 
+               }
+       }
+
+       return (extensions.FileDrop = FileDrop);
+});
+
+// Included from: src/javascript/runtime/html5/file/FileReader.js
+
+/**
+ * FileReader.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+/**
+@class moxie/runtime/html5/file/FileReader
+@private
+*/
+define("moxie/runtime/html5/file/FileReader", [
+       "moxie/runtime/html5/Runtime",
+       "moxie/core/utils/Encode",
+       "moxie/core/utils/Basic"
+], function(extensions, Encode, Basic) {
+       
+       function FileReader() {
+               var _fr, _convertToBinary = false;
+
+               Basic.extend(this, {
+
+                       read: function(op, blob) {
+                               var comp = this;
+
+                               comp.result = '';
+
+                               _fr = new window.FileReader();
+
+                               _fr.addEventListener('progress', function(e) {
+                                       comp.trigger(e);
+                               });
+
+                               _fr.addEventListener('load', function(e) {
+                                       comp.result = _convertToBinary ? _toBinary(_fr.result) : _fr.result;
+                                       comp.trigger(e);
+                               });
+
+                               _fr.addEventListener('error', function(e) {
+                                       comp.trigger(e, _fr.error);
+                               });
+
+                               _fr.addEventListener('loadend', function(e) {
+                                       _fr = null;
+                                       comp.trigger(e);
+                               });
+
+                               if (Basic.typeOf(_fr[op]) === 'function') {
+                                       _convertToBinary = false;
+                                       _fr[op](blob.getSource());
+                               } else if (op === 'readAsBinaryString') { // readAsBinaryString is depricated in general and never existed in IE10+
+                                       _convertToBinary = true;
+                                       _fr.readAsDataURL(blob.getSource());
+                               }
+                       },
+
+                       abort: function() {
+                               if (_fr) {
+                                       _fr.abort();
+                               }
+                       },
+
+                       destroy: function() {
+                               _fr = null;
+                       }
+               });
+
+               function _toBinary(str) {
+                       return Encode.atob(str.substring(str.indexOf('base64,') + 7));
+               }
+       }
+
+       return (extensions.FileReader = FileReader);
+});
+
+// Included from: src/javascript/runtime/html5/xhr/XMLHttpRequest.js
+
+/**
+ * XMLHttpRequest.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+/*global ActiveXObject:true */
+
+/**
+@class moxie/runtime/html5/xhr/XMLHttpRequest
+@private
+*/
+define("moxie/runtime/html5/xhr/XMLHttpRequest", [
+       "moxie/runtime/html5/Runtime",
+       "moxie/core/utils/Basic",
+       "moxie/core/utils/Mime",
+       "moxie/core/utils/Url",
+       "moxie/file/File",
+       "moxie/file/Blob",
+       "moxie/xhr/FormData",
+       "moxie/core/Exceptions",
+       "moxie/core/utils/Env"
+], function(extensions, Basic, Mime, Url, File, Blob, FormData, x, Env) {
+       
+       function XMLHttpRequest() {
+               var self = this
+               , _xhr
+               , _filename
+               ;
+
+               Basic.extend(this, {
+                       send: function(meta, data) {
+                               var target = this
+                               , isGecko2_5_6 = (Env.browser === 'Mozilla' && Env.verComp(Env.version, 4, '>=') && Env.verComp(Env.version, 7, '<'))
+                               , isAndroidBrowser = Env.browser === 'Android Browser'
+                               , mustSendAsBinary = false
+                               ;
+
+                               // extract file name
+                               _filename = meta.url.replace(/^.+?\/([\w\-\.]+)$/, '$1').toLowerCase();
+
+                               _xhr = _getNativeXHR();
+                               _xhr.open(meta.method, meta.url, meta.async, meta.user, meta.password);
+
+
+                               // prepare data to be sent
+                               if (data instanceof Blob) {
+                                       if (data.isDetached()) {
+                                               mustSendAsBinary = true;
+                                       }
+                                       data = data.getSource();
+                               } else if (data instanceof FormData) {
+
+                                       if (data.hasBlob()) {
+                                               if (data.getBlob().isDetached()) {
+                                                       data = _prepareMultipart.call(target, data); // _xhr must be instantiated and be in OPENED state
+                                                       mustSendAsBinary = true;
+                                               } else if ((isGecko2_5_6 || isAndroidBrowser) && Basic.typeOf(data.getBlob().getSource()) === 'blob' && window.FileReader) {
+                                                       // Gecko 2/5/6 can't send blob in FormData: https://bugzilla.mozilla.org/show_bug.cgi?id=649150
+                                                       // Android browsers (default one and Dolphin) seem to have the same issue, see: #613
+                                                       _preloadAndSend.call(target, meta, data);
+                                                       return; // _preloadAndSend will reinvoke send() with transmutated FormData =%D
+                                               }       
+                                       }
+
+                                       // transfer fields to real FormData
+                                       if (data instanceof FormData) { // if still a FormData, e.g. not mangled by _prepareMultipart()
+                                               var fd = new window.FormData();
+                                               data.each(function(value, name) {
+                                                       if (value instanceof Blob) {
+                                                               fd.append(name, value.getSource());
+                                                       } else {
+                                                               fd.append(name, value);
+                                                       }
+                                               });
+                                               data = fd;
+                                       }
+                               }
+
+
+                               // if XHR L2
+                               if (_xhr.upload) {
+                                       if (meta.withCredentials) {
+                                               _xhr.withCredentials = true;
+                                       }
+
+                                       _xhr.addEventListener('load', function(e) {
+                                               target.trigger(e);
+                                       });
+
+                                       _xhr.addEventListener('error', function(e) {
+                                               target.trigger(e);
+                                       });
+
+                                       // additionally listen to progress events
+                                       _xhr.addEventListener('progress', function(e) {
+                                               target.trigger(e);
+                                       });
+
+                                       _xhr.upload.addEventListener('progress', function(e) {
+                                               target.trigger({
+                                                       type: 'UploadProgress',
+                                                       loaded: e.loaded,
+                                                       total: e.total
+                                               });
+                                       });
+                               // ... otherwise simulate XHR L2
+                               } else {
+                                       _xhr.onreadystatechange = function onReadyStateChange() {
+                                               
+                                               // fake Level 2 events
+                                               switch (_xhr.readyState) {
+                                                       
+                                                       case 1: // XMLHttpRequest.OPENED
+                                                               // readystatechanged is fired twice for OPENED state (in IE and Mozilla) - neu
+                                                               break;
+                                                       
+                                                       // looks like HEADERS_RECEIVED (state 2) is not reported in Opera (or it's old versions) - neu
+                                                       case 2: // XMLHttpRequest.HEADERS_RECEIVED
+                                                               break;
+                                                               
+                                                       case 3: // XMLHttpRequest.LOADING 
+                                                               // try to fire progress event for not XHR L2
+                                                               var total, loaded;
+                                                               
+                                                               try {
+                                                                       if (Url.hasSameOrigin(meta.url)) { // Content-Length not accessible for cross-domain on some browsers
+                                                                               total = _xhr.getResponseHeader('Content-Length') || 0; // old Safari throws an exception here
+                                                                       }
+
+                                                                       if (_xhr.responseText) { // responseText was introduced in IE7
+                                                                               loaded = _xhr.responseText.length;
+                                                                       }
+                                                               } catch(ex) {
+                                                                       total = loaded = 0;
+                                                               }
+
+                                                               target.trigger({
+                                                                       type: 'progress',
+                                                                       lengthComputable: !!total,
+                                                                       total: parseInt(total, 10),
+                                                                       loaded: loaded
+                                                               });
+                                                               break;
+                                                               
+                                                       case 4: // XMLHttpRequest.DONE
+                                                               // release readystatechange handler (mostly for IE)
+                                                               _xhr.onreadystatechange = function() {};
+
+                                                               // usually status 0 is returned when server is unreachable, but FF also fails to status 0 for 408 timeout
+                                                               if (_xhr.status === 0) {
+                                                                       target.trigger('error');
+                                                               } else {
+                                                                       target.trigger('load');
+                                                               }                                                       
+                                                               break;
+                                               }
+                                       };
+                               }
+                               
+
+                               // set request headers
+                               if (!Basic.isEmptyObj(meta.headers)) {
+                                       Basic.each(meta.headers, function(value, header) {
+                                               _xhr.setRequestHeader(header, value);
+                                       });
+                               }
+
+                               // request response type
+                               if ("" !== meta.responseType && 'responseType' in _xhr) {
+                                       if ('json' === meta.responseType && !Env.can('return_response_type', 'json')) { // we can fake this one
+                                               _xhr.responseType = 'text';
+                                       } else {
+                                               _xhr.responseType = meta.responseType;
+                                       }
+                               }
+
+                               // send ...
+                               if (!mustSendAsBinary) {
+                                       _xhr.send(data);
+                               } else {
+                                       if (_xhr.sendAsBinary) { // Gecko
+                                               _xhr.sendAsBinary(data);
+                                       } else { // other browsers having support for typed arrays
+                                               (function() {
+                                                       // mimic Gecko's sendAsBinary
+                                                       var ui8a = new Uint8Array(data.length);
+                                                       for (var i = 0; i < data.length; i++) {
+                                                               ui8a[i] = (data.charCodeAt(i) & 0xff);
+                                                       }
+                                                       _xhr.send(ui8a.buffer);
+                                               }());
+                                       }
+                               }
+
+                               target.trigger('loadstart');
+                       },
+
+                       getStatus: function() {
+                               // according to W3C spec it should return 0 for readyState < 3, but instead it throws an exception
+                               try {
+                                       if (_xhr) {
+                                               return _xhr.status;
+                                       }
+                               } catch(ex) {}
+                               return 0;
+                       },
+
+                       getResponse: function(responseType) {
+                               var I = this.getRuntime();
+
+                               try {
+                                       switch (responseType) {
+                                               case 'blob':
+                                                       var file = new File(I.uid, _xhr.response);
+                                                       
+                                                       // try to extract file name from content-disposition if possible (might be - not, if CORS for example)  
+                                                       var disposition = _xhr.getResponseHeader('Content-Disposition');
+                                                       if (disposition) {
+                                                               // extract filename from response header if available
+                                                               var match = disposition.match(/filename=([\'\"'])([^\1]+)\1/);
+                                                               if (match) {
+                                                                       _filename = match[2];
+                                                               }
+                                                       }
+                                                       file.name = _filename;
+
+                                                       // pre-webkit Opera doesn't set type property on the blob response
+                                                       if (!file.type) {
+                                                               file.type = Mime.getFileMime(_filename);
+                                                       }
+                                                       return file;
+
+                                               case 'json':
+                                                       if (!Env.can('return_response_type', 'json')) {
+                                                               return _xhr.status === 200 && !!window.JSON ? JSON.parse(_xhr.responseText) : null;
+                                                       }
+                                                       return _xhr.response;
+
+                                               case 'document':
+                                                       return _getDocument(_xhr);
+
+                                               default:
+                                                       return _xhr.responseText !== '' ? _xhr.responseText : null; // against the specs, but for consistency across the runtimes
+                                       }
+                               } catch(ex) {
+                                       return null;
+                               }                               
+                       },
+
+                       getAllResponseHeaders: function() {
+                               try {
+                                       return _xhr.getAllResponseHeaders();
+                               } catch(ex) {}
+                               return '';
+                       },
+
+                       abort: function() {
+                               if (_xhr) {
+                                       _xhr.abort();
+                               }
+                       },
+
+                       destroy: function() {
+                               self = _filename = null;
+                       }
+               });
+
+
+               // here we go... ugly fix for ugly bug
+               function _preloadAndSend(meta, data) {
+                       var target = this, blob, fr;
+                               
+                       // get original blob
+                       blob = data.getBlob().getSource();
+                       
+                       // preload blob in memory to be sent as binary string
+                       fr = new window.FileReader();
+                       fr.onload = function() {
+                               // overwrite original blob
+                               data.append(data.getBlobName(), new Blob(null, {
+                                       type: blob.type,
+                                       data: fr.result
+                               }));
+                               // invoke send operation again
+                               self.send.call(target, meta, data);
+                       };
+                       fr.readAsBinaryString(blob);
+               }
+
+               
+               function _getNativeXHR() {
+                       if (window.XMLHttpRequest && !(Env.browser === 'IE' && Env.verComp(Env.version, 8, '<'))) { // IE7 has native XHR but it's buggy
+                               return new window.XMLHttpRequest();
+                       } else {
+                               return (function() {
+                                       var progIDs = ['Msxml2.XMLHTTP.6.0', 'Microsoft.XMLHTTP']; // if 6.0 available, use it, otherwise failback to default 3.0
+                                       for (var i = 0; i < progIDs.length; i++) {
+                                               try {
+                                                       return new ActiveXObject(progIDs[i]);
+                                               } catch (ex) {}
+                                       }
+                               })();
+                       }
+               }
+               
+               // @credits Sergey Ilinsky      (http://www.ilinsky.com/)
+               function _getDocument(xhr) {
+                       var rXML = xhr.responseXML;
+                       var rText = xhr.responseText;
+                       
+                       // Try parsing responseText (@see: http://www.ilinsky.com/articles/XMLHttpRequest/#bugs-ie-responseXML-content-type)
+                       if (Env.browser === 'IE' && rText && rXML && !rXML.documentElement && /[^\/]+\/[^\+]+\+xml/.test(xhr.getResponseHeader("Content-Type"))) {
+                               rXML = new window.ActiveXObject("Microsoft.XMLDOM");
+                               rXML.async = false;
+                               rXML.validateOnParse = false;
+                               rXML.loadXML(rText);
+                       }
+       
+                       // Check if there is no error in document
+                       if (rXML) {
+                               if ((Env.browser === 'IE' && rXML.parseError !== 0) || !rXML.documentElement || rXML.documentElement.tagName === "parsererror") {
+                                       return null;
+                               }
+                       }
+                       return rXML;
+               }
+
+
+               function _prepareMultipart(fd) {
+                       var boundary = '----moxieboundary' + new Date().getTime()
+                       , dashdash = '--'
+                       , crlf = '\r\n'
+                       , multipart = ''
+                       , I = this.getRuntime()
+                       ;
+
+                       if (!I.can('send_binary_string')) {
+                               throw new x.RuntimeError(x.RuntimeError.NOT_SUPPORTED_ERR);
+                       }
+
+                       _xhr.setRequestHeader('Content-Type', 'multipart/form-data; boundary=' + boundary);
+
+                       // append multipart parameters
+                       fd.each(function(value, name) {
+                               // Firefox 3.6 failed to convert multibyte characters to UTF-8 in sendAsBinary(), 
+                               // so we try it here ourselves with: unescape(encodeURIComponent(value))
+                               if (value instanceof Blob) {
+                                       // Build RFC2388 blob
+                                       multipart += dashdash + boundary + crlf +
+                                               'Content-Disposition: form-data; name="' + name + '"; filename="' + unescape(encodeURIComponent(value.name || 'blob')) + '"' + crlf +
+                                               'Content-Type: ' + (value.type || 'application/octet-stream') + crlf + crlf +
+                                               value.getSource() + crlf;
+                               } else {
+                                       multipart += dashdash + boundary + crlf +
+                                               'Content-Disposition: form-data; name="' + name + '"' + crlf + crlf +
+                                               unescape(encodeURIComponent(value)) + crlf;
+                               }
+                       });
+
+                       multipart += dashdash + boundary + dashdash + crlf;
+
+                       return multipart;
+               }
+       }
+
+       return (extensions.XMLHttpRequest = XMLHttpRequest);
+});
+
+// Included from: src/javascript/runtime/html5/utils/BinaryReader.js
+
+/**
+ * BinaryReader.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+/**
+@class moxie/runtime/html5/utils/BinaryReader
+@private
+*/
+define("moxie/runtime/html5/utils/BinaryReader", [
+       "moxie/core/utils/Basic"
+], function(Basic) {
+
+       
+       function BinaryReader(data) {
+               if (data instanceof ArrayBuffer) {
+                       ArrayBufferReader.apply(this, arguments);
+               } else {
+                       UTF16StringReader.apply(this, arguments);
+               }
+       }
+       Â 
+
+       Basic.extend(BinaryReader.prototype, {
+               
+               littleEndian: false,
+
+
+               read: function(idx, size) {
+                       var sum, mv, i;
+
+                       if (idx + size > this.length()) {
+                               throw new Error("You are trying to read outside the source boundaries.");
+                       }
+                       
+                       mv = this.littleEndian 
+                               ? 0 
+                               : -8 * (size - 1)
+                       ;
+
+                       for (i = 0, sum = 0; i < size; i++) {
+                               sum |= (this.readByteAt(idx + i) << Math.abs(mv + i*8));
+                       }
+                       return sum;
+               },
+
+
+               write: function(idx, num, size) {
+                       var mv, i, str = '';
+
+                       if (idx > this.length()) {
+                               throw new Error("You are trying to write outside the source boundaries.");
+                       }
+
+                       mv = this.littleEndian 
+                               ? 0 
+                               : -8 * (size - 1)
+                       ;
+
+                       for (i = 0; i < size; i++) {
+                               this.writeByteAt(idx + i, (num >> Math.abs(mv + i*8)) & 255);
+                       }
+               },
+
+
+               BYTE: function(idx) {
+                       return this.read(idx, 1);
+               },
+
+
+               SHORT: function(idx) {
+                       return this.read(idx, 2);
+               },
+
+
+               LONG: function(idx) {
+                       return this.read(idx, 4);
+               },
+
+
+               SLONG: function(idx) { // 2's complement notation
+                       var num = this.read(idx, 4);
+                       return (num > 2147483647 ? num - 4294967296 : num);
+               },
+
+
+               CHAR: function(idx) {
+                       return String.fromCharCode(this.read(idx, 1));
+               },
+
+
+               STRING: function(idx, count) {
+                       return this.asArray('CHAR', idx, count).join('');
+               },
+
+
+               asArray: function(type, idx, count) {
+                       var values = [];
+
+                       for (var i = 0; i < count; i++) {
+                               values[i] = this[type](idx + i);
+                       }
+                       return values;
+               }
+       });
+
+
+       function ArrayBufferReader(data) {
+               var _dv = new DataView(data);
+
+               Basic.extend(this, {
+                       
+                       readByteAt: function(idx) {
+                               return _dv.getUint8(idx);
+                       },
+
+
+                       writeByteAt: function(idx, value) {
+                               _dv.setUint8(idx, value);
+                       },
+                       
+
+                       SEGMENT: function(idx, size, value) {
+                               switch (arguments.length) {
+                                       case 2:
+                                               return data.slice(idx, idx + size);
+
+                                       case 1:
+                                               return data.slice(idx);
+
+                                       case 3:
+                                               if (value === null) {
+                                                       value = new ArrayBuffer();
+                                               }
+
+                                               if (value instanceof ArrayBuffer) {                                     
+                                                       var arr = new Uint8Array(this.length() - size + value.byteLength);
+                                                       if (idx > 0) {
+                                                               arr.set(new Uint8Array(data.slice(0, idx)), 0);
+                                                       }
+                                                       arr.set(new Uint8Array(value), idx);
+                                                       arr.set(new Uint8Array(data.slice(idx + size)), idx + value.byteLength);
+
+                                                       this.clear();
+                                                       data = arr.buffer;
+                                                       _dv = new DataView(data);
+                                                       break;
+                                               }
+
+                                       default: return data;
+                               }
+                       },
+
+
+                       length: function() {
+                               return data ? data.byteLength : 0;
+                       },
+
+
+                       clear: function() {
+                               _dv = data = null;
+                       }
+               });
+       }
+
+
+       function UTF16StringReader(data) {
+               Basic.extend(this, {
+                       
+                       readByteAt: function(idx) {
+                               return data.charCodeAt(idx);
+                       },
+
+
+                       writeByteAt: function(idx, value) {
+                               putstr(String.fromCharCode(value), idx, 1);
+                       },
+
+
+                       SEGMENT: function(idx, length, segment) {
+                               switch (arguments.length) {
+                                       case 1:
+                                               return data.substr(idx);
+                                       case 2:
+                                               return data.substr(idx, length);
+                                       case 3:
+                                               putstr(segment !== null ? segment : '', idx, length);
+                                               break;
+                                       default: return data;
+                               }
+                       },
+
+
+                       length: function() {
+                               return data ? data.length : 0;
+                       }, 
+
+                       clear: function() {
+                               data = null;
+                       }
+               });
+
+
+               function putstr(segment, idx, length) {
+                       length = arguments.length === 3 ? length : data.length - idx - 1;
+                       data = data.substr(0, idx) + segment + data.substr(length + idx);
+               }
+       }
+
+
+       return BinaryReader;
+});
+
+// Included from: src/javascript/runtime/html5/image/JPEGHeaders.js
+
+/**
+ * JPEGHeaders.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */

+/**
+@class moxie/runtime/html5/image/JPEGHeaders
+@private
+*/
+define("moxie/runtime/html5/image/JPEGHeaders", [
+       "moxie/runtime/html5/utils/BinaryReader",
+       "moxie/core/Exceptions"
+], function(BinaryReader, x) {
+       
+       return function JPEGHeaders(data) {
+               var headers = [], _br, idx, marker, length = 0;
+
+               _br = new BinaryReader(data);
+
+               // Check if data is jpeg
+               if (_br.SHORT(0) !== 0xFFD8) {
+                       _br.clear();
+                       throw new x.ImageError(x.ImageError.WRONG_FORMAT);
+               }
+
+               idx = 2;
+
+               while (idx <= _br.length()) {
+                       marker = _br.SHORT(idx);
+
+                       // omit RST (restart) markers
+                       if (marker >= 0xFFD0 && marker <= 0xFFD7) {
+                               idx += 2;
+                               continue;
+                       }
+
+                       // no headers allowed after SOS marker
+                       if (marker === 0xFFDA || marker === 0xFFD9) {
+                               break;
+                       }
+
+                       length = _br.SHORT(idx + 2) + 2;
+
+                       // APPn marker detected
+                       if (marker >= 0xFFE1 && marker <= 0xFFEF) {
+                               headers.push({
+                                       hex: marker,
+                                       name: 'APP' + (marker & 0x000F),
+                                       start: idx,
+                                       length: length,
+                                       segment: _br.SEGMENT(idx, length)
+                               });
+                       }
+
+                       idx += length;
+               }
+
+               _br.clear();
+
+               return {
+                       headers: headers,
+
+                       restore: function(data) {
+                               var max, i, br;
+
+                               br = new BinaryReader(data);
+
+                               idx = br.SHORT(2) == 0xFFE0 ? 4 + br.SHORT(4) : 2;
+
+                               for (i = 0, max = headers.length; i < max; i++) {
+                                       br.SEGMENT(idx, 0, headers[i].segment);
+                                       idx += headers[i].length;
+                               }
+
+                               data = br.SEGMENT();
+                               br.clear();
+                               return data;
+                       },
+
+                       strip: function(data) {
+                               var br, headers, jpegHeaders, i;
+
+                               jpegHeaders = new JPEGHeaders(data);
+                               headers = jpegHeaders.headers;
+                               jpegHeaders.purge();
+
+                               br = new BinaryReader(data);
+
+                               i = headers.length;
+                               while (i--) {
+                                       br.SEGMENT(headers[i].start, headers[i].length, '');
+                               }
+                               
+                               data = br.SEGMENT();
+                               br.clear();
+                               return data;
+                       },
+
+                       get: function(name) {
+                               var array = [];
+
+                               for (var i = 0, max = headers.length; i < max; i++) {
+                                       if (headers[i].name === name.toUpperCase()) {
+                                               array.push(headers[i].segment);
+                                       }
+                               }
+                               return array;
+                       },
+
+                       set: function(name, segment) {
+                               var array = [], i, ii, max;
+
+                               if (typeof(segment) === 'string') {
+                                       array.push(segment);
+                               } else {
+                                       array = segment;
+                               }
+
+                               for (i = ii = 0, max = headers.length; i < max; i++) {
+                                       if (headers[i].name === name.toUpperCase()) {
+                                               headers[i].segment = array[ii];
+                                               headers[i].length = array[ii].length;
+                                               ii++;
+                                       }
+                                       if (ii >= array.length) {
+                                               break;
+                                       }
+                               }
+                       },
+
+                       purge: function() {
+                               this.headers = headers = [];
+                       }
+               };
+       };
+});
+
+// Included from: src/javascript/runtime/html5/image/ExifParser.js
+
+/**
+ * ExifParser.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+/**
+@class moxie/runtime/html5/image/ExifParser
+@private
+*/
+define("moxie/runtime/html5/image/ExifParser", [
+       "moxie/core/utils/Basic",
+       "moxie/runtime/html5/utils/BinaryReader",
+       "moxie/core/Exceptions"
+], function(Basic, BinaryReader, x) {
+       
+       function ExifParser(data) {
+               var __super__, tags, tagDescs, offsets, idx, Tiff;
+               
+               BinaryReader.call(this, data);
+
+               tags = {
+                       tiff: {
+                               /*
+                               The image orientation viewed in terms of rows and columns.
+
+                               1 = The 0th row is at the visual top of the image, and the 0th column is the visual left-hand side.
+                               2 = The 0th row is at the visual top of the image, and the 0th column is the visual right-hand side.
+                               3 = The 0th row is at the visual bottom of the image, and the 0th column is the visual right-hand side.
+                               4 = The 0th row is at the visual bottom of the image, and the 0th column is the visual left-hand side.
+                               5 = The 0th row is the visual left-hand side of the image, and the 0th column is the visual top.
+                               6 = The 0th row is the visual right-hand side of the image, and the 0th column is the visual top.
+                               7 = The 0th row is the visual right-hand side of the image, and the 0th column is the visual bottom.
+                               8 = The 0th row is the visual left-hand side of the image, and the 0th column is the visual bottom.
+                               */
+                               0x0112: 'Orientation',
+                               0x010E: 'ImageDescription',
+                               0x010F: 'Make',
+                               0x0110: 'Model',
+                               0x0131: 'Software',
+                               0x8769: 'ExifIFDPointer',
+                               0x8825: 'GPSInfoIFDPointer'
+                       },
+                       exif: {
+                               0x9000: 'ExifVersion',
+                               0xA001: 'ColorSpace',
+                               0xA002: 'PixelXDimension',
+                               0xA003: 'PixelYDimension',
+                               0x9003: 'DateTimeOriginal',
+                               0x829A: 'ExposureTime',
+                               0x829D: 'FNumber',
+                               0x8827: 'ISOSpeedRatings',
+                               0x9201: 'ShutterSpeedValue',
+                               0x9202: 'ApertureValue' ,
+                               0x9207: 'MeteringMode',
+                               0x9208: 'LightSource',
+                               0x9209: 'Flash',
+                               0x920A: 'FocalLength',
+                               0xA402: 'ExposureMode',
+                               0xA403: 'WhiteBalance',
+                               0xA406: 'SceneCaptureType',
+                               0xA404: 'DigitalZoomRatio',
+                               0xA408: 'Contrast',
+                               0xA409: 'Saturation',
+                               0xA40A: 'Sharpness'
+                       },
+                       gps: {
+                               0x0000: 'GPSVersionID',
+                               0x0001: 'GPSLatitudeRef',
+                               0x0002: 'GPSLatitude',
+                               0x0003: 'GPSLongitudeRef',
+                               0x0004: 'GPSLongitude'
+                       },
+
+                       thumb: {
+                               0x0201: 'JPEGInterchangeFormat',
+                               0x0202: 'JPEGInterchangeFormatLength'
+                       }
+               };
+
+               tagDescs = {
+                       'ColorSpace': {
+                               1: 'sRGB',
+                               0: 'Uncalibrated'
+                       },
+
+                       'MeteringMode': {
+                               0: 'Unknown',
+                               1: 'Average',
+                               2: 'CenterWeightedAverage',
+                               3: 'Spot',
+                               4: 'MultiSpot',
+                               5: 'Pattern',
+                               6: 'Partial',
+                               255: 'Other'
+                       },
+
+                       'LightSource': {
+                               1: 'Daylight',
+                               2: 'Fliorescent',
+                               3: 'Tungsten',
+                               4: 'Flash',
+                               9: 'Fine weather',
+                               10: 'Cloudy weather',
+                               11: 'Shade',
+                               12: 'Daylight fluorescent (D 5700 - 7100K)',
+                               13: 'Day white fluorescent (N 4600 -5400K)',
+                               14: 'Cool white fluorescent (W 3900 - 4500K)',
+                               15: 'White fluorescent (WW 3200 - 3700K)',
+                               17: 'Standard light A',
+                               18: 'Standard light B',
+                               19: 'Standard light C',
+                               20: 'D55',
+                               21: 'D65',
+                               22: 'D75',
+                               23: 'D50',
+                               24: 'ISO studio tungsten',
+                               255: 'Other'
+                       },
+
+                       'Flash': {
+                               0x0000: 'Flash did not fire',
+                               0x0001: 'Flash fired',
+                               0x0005: 'Strobe return light not detected',
+                               0x0007: 'Strobe return light detected',
+                               0x0009: 'Flash fired, compulsory flash mode',
+                               0x000D: 'Flash fired, compulsory flash mode, return light not detected',
+                               0x000F: 'Flash fired, compulsory flash mode, return light detected',
+                               0x0010: 'Flash did not fire, compulsory flash mode',
+                               0x0018: 'Flash did not fire, auto mode',
+                               0x0019: 'Flash fired, auto mode',
+                               0x001D: 'Flash fired, auto mode, return light not detected',
+                               0x001F: 'Flash fired, auto mode, return light detected',
+                               0x0020: 'No flash function',
+                               0x0041: 'Flash fired, red-eye reduction mode',
+                               0x0045: 'Flash fired, red-eye reduction mode, return light not detected',
+                               0x0047: 'Flash fired, red-eye reduction mode, return light detected',
+                               0x0049: 'Flash fired, compulsory flash mode, red-eye reduction mode',
+                               0x004D: 'Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected',
+                               0x004F: 'Flash fired, compulsory flash mode, red-eye reduction mode, return light detected',
+                               0x0059: 'Flash fired, auto mode, red-eye reduction mode',
+                               0x005D: 'Flash fired, auto mode, return light not detected, red-eye reduction mode',
+                               0x005F: 'Flash fired, auto mode, return light detected, red-eye reduction mode'
+                       },
+
+                       'ExposureMode': {
+                               0: 'Auto exposure',
+                               1: 'Manual exposure',
+                               2: 'Auto bracket'
+                       },
+
+                       'WhiteBalance': {
+                               0: 'Auto white balance',
+                               1: 'Manual white balance'
+                       },
+
+                       'SceneCaptureType': {
+                               0: 'Standard',
+                               1: 'Landscape',
+                               2: 'Portrait',
+                               3: 'Night scene'
+                       },
+
+                       'Contrast': {
+                               0: 'Normal',
+                               1: 'Soft',
+                               2: 'Hard'
+                       },
+
+                       'Saturation': {
+                               0: 'Normal',
+                               1: 'Low saturation',
+                               2: 'High saturation'
+                       },
+
+                       'Sharpness': {
+                               0: 'Normal',
+                               1: 'Soft',
+                               2: 'Hard'
+                       },
+
+                       // GPS related
+                       'GPSLatitudeRef': {
+                               N: 'North latitude',
+                               S: 'South latitude'
+                       },
+
+                       'GPSLongitudeRef': {
+                               E: 'East longitude',
+                               W: 'West longitude'
+                       }
+               };
+
+               offsets = {
+                       tiffHeader: 10
+               };
+               
+               idx = offsets.tiffHeader;
+
+               __super__ = {
+                       clear: this.clear
+               };
+
+               // Public functions
+               Basic.extend(this, {
+                       
+                       read: function() {
+                               try {
+                                       return ExifParser.prototype.read.apply(this, arguments);
+                               } catch (ex) {
+                                       throw new x.ImageError(x.ImageError.INVALID_META_ERR);
+                               }
+                       },
+
+
+                       write: function() {
+                               try {
+                                       return ExifParser.prototype.write.apply(this, arguments);
+                               } catch (ex) {
+                                       throw new x.ImageError(x.ImageError.INVALID_META_ERR);
+                               }
+                       },
+
+
+                       UNDEFINED: function() {
+                               return this.BYTE.apply(this, arguments);
+                       },
+
+
+                       RATIONAL: function(idx) {
+                               return this.LONG(idx) / this.LONG(idx + 4)
+                       },
+
+
+                       SRATIONAL: function(idx) {
+                               return this.SLONG(idx) / this.SLONG(idx + 4)
+                       },
+
+                       ASCII: function(idx) {
+                               return this.CHAR(idx);
+                       },
+
+                       TIFF: function() {
+                               return Tiff || null;
+                       },
+
+
+                       EXIF: function() {
+                               var Exif = null;
+
+                               if (offsets.exifIFD) {
+                                       try {
+                                               Exif = extractTags.call(this, offsets.exifIFD, tags.exif);
+                                       } catch(ex) {
+                                               return null;
+                                       }
+
+                                       // Fix formatting of some tags
+                                       if (Exif.ExifVersion && Basic.typeOf(Exif.ExifVersion) === 'array') {
+                                               for (var i = 0, exifVersion = ''; i < Exif.ExifVersion.length; i++) {
+                                                       exifVersion += String.fromCharCode(Exif.ExifVersion[i]);
+                                               }
+                                               Exif.ExifVersion = exifVersion;
+                                       }
+                               }
+
+                               return Exif;
+                       },
+
+
+                       GPS: function() {
+                               var GPS = null;
+
+                               if (offsets.gpsIFD) {
+                                       try {
+                                               GPS = extractTags.call(this, offsets.gpsIFD, tags.gps);
+                                       } catch (ex) {
+                                               return null;
+                                       }
+
+                                       // iOS devices (and probably some others) do not put in GPSVersionID tag (why?..)
+                                       if (GPS.GPSVersionID && Basic.typeOf(GPS.GPSVersionID) === 'array') {
+                                               GPS.GPSVersionID = GPS.GPSVersionID.join('.');
+                                       }
+                               }
+
+                               return GPS;
+                       },
+
+
+                       thumb: function() {
+                               if (offsets.IFD1) {
+                                       try {
+                                               var IFD1Tags = extractTags.call(this, offsets.IFD1, tags.thumb);
+                                               
+                                               if ('JPEGInterchangeFormat' in IFD1Tags) {
+                                                       return this.SEGMENT(offsets.tiffHeader + IFD1Tags.JPEGInterchangeFormat, IFD1Tags.JPEGInterchangeFormatLength);
+                                               }
+                                       } catch (ex) {}
+                               }
+                               return null;
+                       },
+
+
+                       setExif: function(tag, value) {
+                               // Right now only setting of width/height is possible
+                               if (tag !== 'PixelXDimension' && tag !== 'PixelYDimension') { return false; }
+
+                               return setTag.call(this, 'exif', tag, value);
+                       },
+
+
+                       clear: function() {
+                               __super__.clear();
+                               data = tags = tagDescs = Tiff = offsets = __super__ = null;
+                       }
+               });
+
+
+               // Check if that's APP1 and that it has EXIF
+               if (this.SHORT(0) !== 0xFFE1 || this.STRING(4, 5).toUpperCase() !== "EXIF\0") {
+                       throw new x.ImageError(x.ImageError.INVALID_META_ERR);
+               }
+
+               // Set read order of multi-byte data
+               this.littleEndian = (this.SHORT(idx) == 0x4949);
+
+               // Check if always present bytes are indeed present
+               if (this.SHORT(idx+=2) !== 0x002A) {
+                       throw new x.ImageError(x.ImageError.INVALID_META_ERR);
+               }
+
+               offsets.IFD0 = offsets.tiffHeader + this.LONG(idx += 2);
+               Tiff = extractTags.call(this, offsets.IFD0, tags.tiff);
+
+               if ('ExifIFDPointer' in Tiff) {
+                       offsets.exifIFD = offsets.tiffHeader + Tiff.ExifIFDPointer;
+                       delete Tiff.ExifIFDPointer;
+               }
+
+               if ('GPSInfoIFDPointer' in Tiff) {
+                       offsets.gpsIFD = offsets.tiffHeader + Tiff.GPSInfoIFDPointer;
+                       delete Tiff.GPSInfoIFDPointer;
+               }
+
+               if (Basic.isEmptyObj(Tiff)) {
+                       Tiff = null;
+               }
+
+               // check if we have a thumb as well
+               var IFD1Offset = this.LONG(offsets.IFD0 + this.SHORT(offsets.IFD0) * 12 + 2);
+               if (IFD1Offset) {
+                       offsets.IFD1 = offsets.tiffHeader + IFD1Offset;
+               }
+
+
+               function extractTags(IFD_offset, tags2extract) {
+                       var data = this;
+                       var length, i, tag, type, count, size, offset, value, values = [], hash = {};
+                       
+                       var types = {
+                               1 : 'BYTE',
+                               7 : 'UNDEFINED',
+                               2 : 'ASCII',
+                               3 : 'SHORT',
+                               4 : 'LONG',
+                               5 : 'RATIONAL',
+                               9 : 'SLONG',
+                               10: 'SRATIONAL'
+                       };
+
+                       var sizes = {
+                               'BYTE'          : 1,
+                               'UNDEFINED'     : 1,
+                               'ASCII'         : 1,
+                               'SHORT'         : 2,
+                               'LONG'          : 4,
+                               'RATIONAL'      : 8,
+                               'SLONG'         : 4,
+                               'SRATIONAL'     : 8
+                       };
+
+                       length = data.SHORT(IFD_offset);
+
+                       // The size of APP1 including all these elements shall not exceed the 64 Kbytes specified in the JPEG standard.
+
+                       for (i = 0; i < length; i++) {
+                               values = [];
+
+                               // Set binary reader pointer to beginning of the next tag
+                               offset = IFD_offset + 2 + i*12;
+
+                               tag = tags2extract[data.SHORT(offset)];
+
+                               if (tag === undefined) {
+                                       continue; // Not the tag we requested
+                               }
+
+                               type = types[data.SHORT(offset+=2)];
+                               count = data.LONG(offset+=2);
+                               size = sizes[type];
+
+                               if (!size) {
+                                       throw new x.ImageError(x.ImageError.INVALID_META_ERR);
+                               }
+
+                               offset += 4;
+
+                               // tag can only fit 4 bytes of data, if data is larger we should look outside
+                               if (size * count > 4) {
+                                       // instead of data tag contains an offset of the data
+                                       offset = data.LONG(offset) + offsets.tiffHeader;
+                               }
+
+                               // in case we left the boundaries of data throw an early exception
+                               if (offset + size * count >= this.length()) {
+                                       throw new x.ImageError(x.ImageError.INVALID_META_ERR);
+                               } 
+
+                               // special care for the string
+                               if (type === 'ASCII') {
+                                       hash[tag] = Basic.trim(data.STRING(offset, count).replace(/\0$/, '')); // strip trailing NULL
+                                       continue;
+                               } else {
+                                       values = data.asArray(type, offset, count);
+                                       value = (count == 1 ? values[0] : values);
+
+                                       if (tagDescs.hasOwnProperty(tag) && typeof value != 'object') {
+                                               hash[tag] = tagDescs[tag][value];
+                                       } else {
+                                               hash[tag] = value;
+                                       }
+                               }
+                       }
+
+                       return hash;
+               }
+
+               // At the moment only setting of simple (LONG) values, that do not require offset recalculation, is supported
+               function setTag(ifd, tag, value) {
+                       var offset, length, tagOffset, valueOffset = 0;
+
+                       // If tag name passed translate into hex key
+                       if (typeof(tag) === 'string') {
+                               var tmpTags = tags[ifd.toLowerCase()];
+                               for (var hex in tmpTags) {
+                                       if (tmpTags[hex] === tag) {
+                                               tag = hex;
+                                               break;
+                                       }
+                               }
+                       }
+                       offset = offsets[ifd.toLowerCase() + 'IFD'];
+                       length = this.SHORT(offset);
+
+                       for (var i = 0; i < length; i++) {
+                               tagOffset = offset + 12 * i + 2;
+
+                               if (this.SHORT(tagOffset) == tag) {
+                                       valueOffset = tagOffset + 8;
+                                       break;
+                               }
+                       }
+
+                       if (!valueOffset) {
+                               return false;
+                       }
+
+                       try {
+                               this.write(valueOffset, value, 4);
+                       } catch(ex) {
+                               return false;
+                       }
+
+                       return true;
+               }
+       }
+
+       ExifParser.prototype = BinaryReader.prototype;
+
+       return ExifParser;
+});
+
+// Included from: src/javascript/runtime/html5/image/JPEG.js
+
+/**
+ * JPEG.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+/**
+@class moxie/runtime/html5/image/JPEG
+@private
+*/
+define("moxie/runtime/html5/image/JPEG", [
+       "moxie/core/utils/Basic",
+       "moxie/core/Exceptions",
+       "moxie/runtime/html5/image/JPEGHeaders",
+       "moxie/runtime/html5/utils/BinaryReader",
+       "moxie/runtime/html5/image/ExifParser"
+], function(Basic, x, JPEGHeaders, BinaryReader, ExifParser) {
+       
+       function JPEG(data) {
+               var _br, _hm, _ep, _info;
+
+               _br = new BinaryReader(data);
+
+               // check if it is jpeg
+               if (_br.SHORT(0) !== 0xFFD8) {
+                       throw new x.ImageError(x.ImageError.WRONG_FORMAT);
+               }
+
+               // backup headers
+               _hm = new JPEGHeaders(data);
+
+               // extract exif info
+               try {
+                       _ep = new ExifParser(_hm.get('app1')[0]);
+               } catch(ex) {}
+
+               // get dimensions
+               _info = _getDimensions.call(this);
+
+               Basic.extend(this, {
+                       type: 'image/jpeg',
+
+                       size: _br.length(),
+
+                       width: _info && _info.width || 0,
+
+                       height: _info && _info.height || 0,
+
+                       setExif: function(tag, value) {
+                               if (!_ep) {
+                                       return false; // or throw an exception
+                               }
+
+                               if (Basic.typeOf(tag) === 'object') {
+                                       Basic.each(tag, function(value, tag) {
+                                               _ep.setExif(tag, value);
+                                       });
+                               } else {
+                                       _ep.setExif(tag, value);
+                               }
+
+                               // update internal headers
+                               _hm.set('app1', _ep.SEGMENT());
+                       },
+
+                       writeHeaders: function() {
+                               if (!arguments.length) {
+                                       // if no arguments passed, update headers internally
+                                       return _hm.restore(data);
+                               }
+                               return _hm.restore(arguments[0]);
+                       },
+
+                       stripHeaders: function(data) {
+                               return _hm.strip(data);
+                       },
+
+                       purge: function() {
+                               _purge.call(this);
+                       }
+               });
+
+               if (_ep) {
+                       this.meta = {
+                               tiff: _ep.TIFF(),
+                               exif: _ep.EXIF(),
+                               gps: _ep.GPS(),
+                               thumb: _getThumb()
+                       };
+               }
+
+
+               function _getDimensions(br) {
+                       var idx = 0
+                       , marker
+                       , length
+                       ;
+
+                       if (!br) {
+                               br = _br;
+                       }
+
+                       // examine all through the end, since some images might have very large APP segments
+                       while (idx <= br.length()) {
+                               marker = br.SHORT(idx += 2);
+
+                               if (marker >= 0xFFC0 && marker <= 0xFFC3) { // SOFn
+                                       idx += 5; // marker (2 bytes) + length (2 bytes) + Sample precision (1 byte)
+                                       return {
+                                               height: br.SHORT(idx),
+                                               width: br.SHORT(idx += 2)
+                                       };
+                               }
+                               length = br.SHORT(idx += 2);
+                               idx += length - 2;
+                       }
+                       return null;
+               }
+
+
+               function _getThumb() {
+                       var data =  _ep.thumb()
+                       , br
+                       , info
+                       ;
+
+                       if (data) {
+                               br = new BinaryReader(data);
+                               info = _getDimensions(br);
+                               br.clear();
+
+                               if (info) {
+                                       info.data = data;
+                                       return info;
+                               }
+                       }
+                       return null;
+               }
+
+
+               function _purge() {
+                       if (!_ep || !_hm || !_br) { 
+                               return; // ignore any repeating purge requests
+                       }
+                       _ep.clear();
+                       _hm.purge();
+                       _br.clear();
+                       _info = _hm = _ep = _br = null;
+               }
+       }
+
+       return JPEG;
+});
+
+// Included from: src/javascript/runtime/html5/image/PNG.js
+
+/**
+ * PNG.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+/**
+@class moxie/runtime/html5/image/PNG
+@private
+*/
+define("moxie/runtime/html5/image/PNG", [
+       "moxie/core/Exceptions",
+       "moxie/core/utils/Basic",
+       "moxie/runtime/html5/utils/BinaryReader"
+], function(x, Basic, BinaryReader) {
+       
+       function PNG(data) {
+               var _br, _hm, _ep, _info;
+
+               _br = new BinaryReader(data);
+
+               // check if it's png
+               (function() {
+                       var idx = 0, i = 0
+                       , signature = [0x8950, 0x4E47, 0x0D0A, 0x1A0A]
+                       ;
+
+                       for (i = 0; i < signature.length; i++, idx += 2) {
+                               if (signature[i] != _br.SHORT(idx)) {
+                                       throw new x.ImageError(x.ImageError.WRONG_FORMAT);
+                               }
+                       }
+               }());
+
+               function _getDimensions() {
+                       var chunk, idx;
+
+                       chunk = _getChunkAt.call(this, 8);
+
+                       if (chunk.type == 'IHDR') {
+                               idx = chunk.start;
+                               return {
+                                       width: _br.LONG(idx),
+                                       height: _br.LONG(idx += 4)
+                               };
+                       }
+                       return null;
+               }
+
+               function _purge() {
+                       if (!_br) {
+                               return; // ignore any repeating purge requests
+                       }
+                       _br.clear();
+                       data = _info = _hm = _ep = _br = null;
+               }
+
+               _info = _getDimensions.call(this);
+
+               Basic.extend(this, {
+                       type: 'image/png',
+
+                       size: _br.length(),
+
+                       width: _info.width,
+
+                       height: _info.height,
+
+                       purge: function() {
+                               _purge.call(this);
+                       }
+               });
+
+               // for PNG we can safely trigger purge automatically, as we do not keep any data for later
+               _purge.call(this);
+
+               function _getChunkAt(idx) {
+                       var length, type, start, CRC;
+
+                       length = _br.LONG(idx);
+                       type = _br.STRING(idx += 4, 4);
+                       start = idx += 4;
+                       CRC = _br.LONG(idx + length);
+
+                       return {
+                               length: length,
+                               type: type,
+                               start: start,
+                               CRC: CRC
+                       };
+               }
+       }
+
+       return PNG;
+});
+
+// Included from: src/javascript/runtime/html5/image/ImageInfo.js
+
+/**
+ * ImageInfo.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+/**
+@class moxie/runtime/html5/image/ImageInfo
+@private
+*/
+define("moxie/runtime/html5/image/ImageInfo", [
+       "moxie/core/utils/Basic",
+       "moxie/core/Exceptions",
+       "moxie/runtime/html5/image/JPEG",
+       "moxie/runtime/html5/image/PNG"
+], function(Basic, x, JPEG, PNG) {
+       /**
+       Optional image investigation tool for HTML5 runtime. Provides the following features:
+       - ability to distinguish image type (JPEG or PNG) by signature
+       - ability to extract image width/height directly from it's internals, without preloading in memory (fast)
+       - ability to extract APP headers from JPEGs (Exif, GPS, etc)
+       - ability to replace width/height tags in extracted JPEG headers
+       - ability to restore APP headers, that were for example stripped during image manipulation
+
+       @class ImageInfo
+       @constructor
+       @param {String} data Image source as binary string
+       */
+       return function(data) {
+               var _cs = [JPEG, PNG], _img;
+
+               // figure out the format, throw: ImageError.WRONG_FORMAT if not supported
+               _img = (function() {
+                       for (var i = 0; i < _cs.length; i++) {
+                               try {
+                                       return new _cs[i](data);
+                               } catch (ex) {
+                                       // console.info(ex);
+                               }
+                       }
+                       throw new x.ImageError(x.ImageError.WRONG_FORMAT);
+               }());
+
+               Basic.extend(this, {
+                       /**
+                       Image Mime Type extracted from it's depths
+
+                       @property type
+                       @type {String}
+                       @default ''
+                       */
+                       type: '',
+
+                       /**
+                       Image size in bytes
+
+                       @property size
+                       @type {Number}
+                       @default 0
+                       */
+                       size: 0,
+
+                       /**
+                       Image width extracted from image source
+
+                       @property width
+                       @type {Number}
+                       @default 0
+                       */
+                       width: 0,
+
+                       /**
+                       Image height extracted from image source
+
+                       @property height
+                       @type {Number}
+                       @default 0
+                       */
+                       height: 0,
+
+                       /**
+                       Sets Exif tag. Currently applicable only for width and height tags. Obviously works only with JPEGs.
+
+                       @method setExif
+                       @param {String} tag Tag to set
+                       @param {Mixed} value Value to assign to the tag
+                       */
+                       setExif: function() {},
+
+                       /**
+                       Restores headers to the source.
+
+                       @method writeHeaders
+                       @param {String} data Image source as binary string
+                       @return {String} Updated binary string
+                       */
+                       writeHeaders: function(data) {
+                               return data;
+                       },
+
+                       /**
+                       Strip all headers from the source.
+
+                       @method stripHeaders
+                       @param {String} data Image source as binary string
+                       @return {String} Updated binary string
+                       */
+                       stripHeaders: function(data) {
+                               return data;
+                       },
+
+                       /**
+                       Dispose resources.
+
+                       @method purge
+                       */
+                       purge: function() {
+                               data = null;
+                       }
+               });
+
+               Basic.extend(this, _img);
+
+               this.purge = function() {
+                       _img.purge();
+                       _img = null;
+               };
+       };
+});
+
+// Included from: src/javascript/runtime/html5/image/MegaPixel.js
+
+/**
+(The MIT License)
+
+Copyright (c) 2012 Shinichi Tomita <shinichi.tomita@gmail.com>;
+
+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.
+*/
+
+/**
+ * Mega pixel image rendering library for iOS6 Safari
+ *
+ * Fixes iOS6 Safari's image file rendering issue for large size image (over mega-pixel),
+ * which causes unexpected subsampling when drawing it in canvas.
+ * By using this library, you can safely render the image with proper stretching.
+ *
+ * Copyright (c) 2012 Shinichi Tomita <shinichi.tomita@gmail.com>
+ * Released under the MIT license
+ */
+
+/**
+@class moxie/runtime/html5/image/MegaPixel
+@private
+*/
+define("moxie/runtime/html5/image/MegaPixel", [], function() {
+
+       /**
+        * Rendering image element (with resizing) into the canvas element
+        */
+       function renderImageToCanvas(img, canvas, options) {
+               var iw = img.naturalWidth, ih = img.naturalHeight;
+               var width = options.width, height = options.height;
+               var x = options.x || 0, y = options.y || 0;
+               var ctx = canvas.getContext('2d');
+               if (detectSubsampling(img)) {
+                       iw /= 2;
+                       ih /= 2;
+               }
+               var d = 1024; // size of tiling canvas
+               var tmpCanvas = document.createElement('canvas');
+               tmpCanvas.width = tmpCanvas.height = d;
+               var tmpCtx = tmpCanvas.getContext('2d');
+               var vertSquashRatio = detectVerticalSquash(img, iw, ih);
+               var sy = 0;
+               while (sy < ih) {
+                       var sh = sy + d > ih ? ih - sy : d;
+                       var sx = 0;
+                       while (sx < iw) {
+                               var sw = sx + d > iw ? iw - sx : d;
+                               tmpCtx.clearRect(0, 0, d, d);
+                               tmpCtx.drawImage(img, -sx, -sy);
+                               var dx = (sx * width / iw + x) << 0;
+                               var dw = Math.ceil(sw * width / iw);
+                               var dy = (sy * height / ih / vertSquashRatio + y) << 0;
+                               var dh = Math.ceil(sh * height / ih / vertSquashRatio);
+                               ctx.drawImage(tmpCanvas, 0, 0, sw, sh, dx, dy, dw, dh);
+                               sx += d;
+                       }
+                       sy += d;
+               }
+               tmpCanvas = tmpCtx = null;
+       }
+
+       /**
+        * Detect subsampling in loaded image.
+        * In iOS, larger images than 2M pixels may be subsampled in rendering.
+        */
+       function detectSubsampling(img) {
+               var iw = img.naturalWidth, ih = img.naturalHeight;
+               if (iw * ih > 1024 * 1024) { // subsampling may happen over megapixel image
+                       var canvas = document.createElement('canvas');
+                       canvas.width = canvas.height = 1;
+                       var ctx = canvas.getContext('2d');
+                       ctx.drawImage(img, -iw + 1, 0);
+                       // subsampled image becomes half smaller in rendering size.
+                       // check alpha channel value to confirm image is covering edge pixel or not.
+                       // if alpha value is 0 image is not covering, hence subsampled.
+                       return ctx.getImageData(0, 0, 1, 1).data[3] === 0;
+               } else {
+                       return false;
+               }
+       }
+
+
+       /**
+        * Detecting vertical squash in loaded image.
+        * Fixes a bug which squash image vertically while drawing into canvas for some images.
+        */
+       function detectVerticalSquash(img, iw, ih) {
+               var canvas = document.createElement('canvas');
+               canvas.width = 1;
+               canvas.height = ih;
+               var ctx = canvas.getContext('2d');
+               ctx.drawImage(img, 0, 0);
+               var data = ctx.getImageData(0, 0, 1, ih).data;
+               // search image edge pixel position in case it is squashed vertically.
+               var sy = 0;
+               var ey = ih;
+               var py = ih;
+               while (py > sy) {
+                       var alpha = data[(py - 1) * 4 + 3];
+                       if (alpha === 0) {
+                               ey = py;
+                       } else {
+                       sy = py;
+                       }
+                       py = (ey + sy) >> 1;
+               }
+               canvas = null;
+               var ratio = (py / ih);
+               return (ratio === 0) ? 1 : ratio;
+       }
+
+       return {
+               isSubsampled: detectSubsampling,
+               renderTo: renderImageToCanvas
+       };
+});
+
+// Included from: src/javascript/runtime/html5/image/Image.js
+
+/**
+ * Image.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+/**
+@class moxie/runtime/html5/image/Image
+@private
+*/
+define("moxie/runtime/html5/image/Image", [
+       "moxie/runtime/html5/Runtime",
+       "moxie/core/utils/Basic",
+       "moxie/core/Exceptions",
+       "moxie/core/utils/Encode",
+       "moxie/file/Blob",
+       "moxie/file/File",
+       "moxie/runtime/html5/image/ImageInfo",
+       "moxie/runtime/html5/image/MegaPixel",
+       "moxie/core/utils/Mime",
+       "moxie/core/utils/Env"
+], function(extensions, Basic, x, Encode, Blob, File, ImageInfo, MegaPixel, Mime, Env) {
+       
+       function HTML5Image() {
+               var me = this
+               , _img, _imgInfo, _canvas, _binStr, _blob
+               , _modified = false // is set true whenever image is modified
+               , _preserveHeaders = true
+               ;
+
+               Basic.extend(this, {
+                       loadFromBlob: function(blob) {
+                               var comp = this, I = comp.getRuntime()
+                               , asBinary = arguments.length > 1 ? arguments[1] : true
+                               ;
+
+                               if (!I.can('access_binary')) {
+                                       throw new x.RuntimeError(x.RuntimeError.NOT_SUPPORTED_ERR);
+                               }
+
+                               _blob = blob;
+
+                               if (blob.isDetached()) {
+                                       _binStr = blob.getSource();
+                                       _preload.call(this, _binStr);
+                                       return;
+                               } else {
+                                       _readAsDataUrl.call(this, blob.getSource(), function(dataUrl) {
+                                               if (asBinary) {
+                                                       _binStr = _toBinary(dataUrl);
+                                               }
+                                               _preload.call(comp, dataUrl);
+                                       });
+                               }
+                       },
+
+                       loadFromImage: function(img, exact) {
+                               this.meta = img.meta;
+
+                               _blob = new File(null, {
+                                       name: img.name,
+                                       size: img.size,
+                                       type: img.type
+                               });
+
+                               _preload.call(this, exact ? (_binStr = img.getAsBinaryString()) : img.getAsDataURL());
+                       },
+
+                       getInfo: function() {
+                               var I = this.getRuntime(), info;
+
+                               if (!_imgInfo && _binStr && I.can('access_image_binary')) {
+                                       _imgInfo = new ImageInfo(_binStr);
+                               }
+
+                               info = {
+                                       width: _getImg().width || 0,
+                                       height: _getImg().height || 0,
+                                       type: _blob.type || Mime.getFileMime(_blob.name),
+                                       size: _binStr && _binStr.length || _blob.size || 0,
+                                       name: _blob.name || '',
+                                       meta: _imgInfo && _imgInfo.meta || this.meta || {}
+                               };
+
+                               // store thumbnail data as blob
+                               if (info.meta && info.meta.thumb && !(info.meta.thumb.data instanceof Blob)) {
+                                       info.meta.thumb.data = new Blob(null, {
+                                               type: 'image/jpeg',
+                                               data: info.meta.thumb.data
+                                       });
+                               }
+
+                               return info;
+                       },
+
+                       downsize: function() {
+                               _downsize.apply(this, arguments);
+                       },
+
+                       getAsCanvas: function() {
+                               if (_canvas) {
+                                       _canvas.id = this.uid + '_canvas';
+                               }
+                               return _canvas;
+                       },
+
+                       getAsBlob: function(type, quality) {
+                               if (type !== this.type) {
+                                       // if different mime type requested prepare image for conversion
+                                       _downsize.call(this, this.width, this.height, false);
+                               }
+                               return new File(null, {
+                                       name: _blob.name || '',
+                                       type: type,
+                                       data: me.getAsBinaryString.call(this, type, quality)
+                               });
+                       },
+
+                       getAsDataURL: function(type) {
+                               var quality = arguments[1] || 90;
+
+                               // if image has not been modified, return the source right away
+                               if (!_modified) {
+                                       return _img.src;
+                               }
+
+                               if ('image/jpeg' !== type) {
+                                       return _canvas.toDataURL('image/png');
+                               } else {
+                                       try {
+                                               // older Geckos used to result in an exception on quality argument
+                                               return _canvas.toDataURL('image/jpeg', quality/100);
+                                       } catch (ex) {
+                                               return _canvas.toDataURL('image/jpeg');
+                                       }
+                               }
+                       },
+
+                       getAsBinaryString: function(type, quality) {
+                               // if image has not been modified, return the source right away
+                               if (!_modified) {
+                                       // if image was not loaded from binary string
+                                       if (!_binStr) {
+                                               _binStr = _toBinary(me.getAsDataURL(type, quality));
+                                       }
+                                       return _binStr;
+                               }
+
+                               if ('image/jpeg' !== type) {
+                                       _binStr = _toBinary(me.getAsDataURL(type, quality));
+                               } else {
+                                       var dataUrl;
+
+                                       // if jpeg
+                                       if (!quality) {
+                                               quality = 90;
+                                       }
+
+                                       try {
+                                               // older Geckos used to result in an exception on quality argument
+                                               dataUrl = _canvas.toDataURL('image/jpeg', quality/100);
+                                       } catch (ex) {
+                                               dataUrl = _canvas.toDataURL('image/jpeg');
+                                       }
+
+                                       _binStr = _toBinary(dataUrl);
+
+                                       if (_imgInfo) {
+                                               _binStr = _imgInfo.stripHeaders(_binStr);
+
+                                               if (_preserveHeaders) {
+                                                       // update dimensions info in exif
+                                                       if (_imgInfo.meta && _imgInfo.meta.exif) {
+                                                               _imgInfo.setExif({
+                                                                       PixelXDimension: this.width,
+                                                                       PixelYDimension: this.height
+                                                               });
+                                                       }
+
+                                                       // re-inject the headers
+                                                       _binStr = _imgInfo.writeHeaders(_binStr);
+                                               }
+
+                                               // will be re-created from fresh on next getInfo call
+                                               _imgInfo.purge();
+                                               _imgInfo = null;
+                                       }
+                               }
+
+                               _modified = false;
+
+                               return _binStr;
+                       },
+
+                       destroy: function() {
+                               me = null;
+                               _purge.call(this);
+                               this.getRuntime().getShim().removeInstance(this.uid);
+                       }
+               });
+
+
+               function _getImg() {
+                       if (!_canvas && !_img) {
+                               throw new x.ImageError(x.DOMException.INVALID_STATE_ERR);
+                       }
+                       return _canvas || _img;
+               }
+
+
+               function _toBinary(str) {
+                       return Encode.atob(str.substring(str.indexOf('base64,') + 7));
+               }
+
+
+               function _toDataUrl(str, type) {
+                       return 'data:' + (type || '') + ';base64,' + Encode.btoa(str);
+               }
+
+
+               function _preload(str) {
+                       var comp = this;
+
+                       _img = new Image();
+                       _img.onerror = function() {
+                               _purge.call(this);
+                               comp.trigger('error', x.ImageError.WRONG_FORMAT);
+                       };
+                       _img.onload = function() {
+                               comp.trigger('load');
+                       };
+
+                       _img.src = str.substr(0, 5) == 'data:' ? str : _toDataUrl(str, _blob.type);
+               }
+
+
+               function _readAsDataUrl(file, callback) {
+                       var comp = this, fr;
+
+                       // use FileReader if it's available
+                       if (window.FileReader) {
+                               fr = new FileReader();
+                               fr.onload = function() {
+                                       callback(this.result);
+                               };
+                               fr.onerror = function() {
+                                       comp.trigger('error', x.ImageError.WRONG_FORMAT);
+                               };
+                               fr.readAsDataURL(file);
+                       } else {
+                               return callback(file.getAsDataURL());
+                       }
+               }
+
+               function _downsize(width, height, crop, preserveHeaders) {
+                       var self = this
+                       , scale
+                       , mathFn
+                       , x = 0
+                       , y = 0
+                       , img
+                       , destWidth
+                       , destHeight
+                       , orientation
+                       ;
+
+                       _preserveHeaders = preserveHeaders; // we will need to check this on export (see getAsBinaryString())
+
+                       // take into account orientation tag
+                       orientation = (this.meta && this.meta.tiff && this.meta.tiff.Orientation) || 1;
+
+                       if (Basic.inArray(orientation, [5,6,7,8]) !== -1) { // values that require 90 degree rotation
+                               // swap dimensions
+                               var tmp = width;
+                               width = height;
+                               height = tmp;
+                       }
+
+                       img = _getImg();
+
+                       // unify dimensions
+                       if (!crop) {
+                               scale = Math.min(width/img.width, height/img.height);
+                       } else {
+                               // one of the dimensions may exceed the actual image dimensions - we need to take the smallest value
+                               width = Math.min(width, img.width);
+                               height = Math.min(height, img.height);
+
+                               scale = Math.max(width/img.width, height/img.height);
+                       }
+               
+                       // we only downsize here
+                       if (scale > 1 && !crop && preserveHeaders) {
+                               this.trigger('Resize');
+                               return;
+                       }
+
+                       // prepare canvas if necessary
+                       if (!_canvas) {
+                               _canvas = document.createElement("canvas");
+                       }
+
+                       // calculate dimensions of proportionally resized image
+                       destWidth = Math.round(img.width * scale);      
+                       destHeight = Math.round(img.height * scale);
+
+                       // scale image and canvas
+                       if (crop) {
+                               _canvas.width = width;
+                               _canvas.height = height;
+
+                               // if dimensions of the resulting image still larger than canvas, center it
+                               if (destWidth > width) {
+                                       x = Math.round((destWidth - width) / 2);
+                               }
+
+                               if (destHeight > height) {
+                                       y = Math.round((destHeight - height) / 2);
+                               }
+                       } else {
+                               _canvas.width = destWidth;
+                               _canvas.height = destHeight;
+                       }
+
+                       // rotate if required, according to orientation tag
+                       if (!_preserveHeaders) {
+                               _rotateToOrientaion(_canvas.width, _canvas.height, orientation);
+                       }
+
+                       _drawToCanvas.call(this, img, _canvas, -x, -y, destWidth, destHeight);
+
+                       this.width = _canvas.width;
+                       this.height = _canvas.height;
+
+                       _modified = true;
+                       self.trigger('Resize');
+               }
+
+
+               function _drawToCanvas(img, canvas, x, y, w, h) {
+                       if (Env.OS === 'iOS') { 
+                               // avoid squish bug in iOS6
+                               MegaPixel.renderTo(img, canvas, { width: w, height: h, x: x, y: y });
+                       } else {
+                               var ctx = canvas.getContext('2d');
+                               ctx.drawImage(img, x, y, w, h);
+                       }
+               }
+
+
+               /**
+               * Transform canvas coordination according to specified frame size and orientation
+               * Orientation value is from EXIF tag
+               * @author Shinichi Tomita <shinichi.tomita@gmail.com>
+               */
+               function _rotateToOrientaion(width, height, orientation) {
+                       switch (orientation) {
+                               case 5:
+                               case 6:
+                               case 7:
+                               case 8:
+                                       _canvas.width = height;
+                                       _canvas.height = width;
+                                       break;
+                               default:
+                                       _canvas.width = width;
+                                       _canvas.height = height;
+                       }
+
+                       /**
+                       1 = The 0th row is at the visual top of the image, and the 0th column is the visual left-hand side.
+                       2 = The 0th row is at the visual top of the image, and the 0th column is the visual right-hand side.
+                       3 = The 0th row is at the visual bottom of the image, and the 0th column is the visual right-hand side.
+                       4 = The 0th row is at the visual bottom of the image, and the 0th column is the visual left-hand side.
+                       5 = The 0th row is the visual left-hand side of the image, and the 0th column is the visual top.
+                       6 = The 0th row is the visual right-hand side of the image, and the 0th column is the visual top.
+                       7 = The 0th row is the visual right-hand side of the image, and the 0th column is the visual bottom.
+                       8 = The 0th row is the visual left-hand side of the image, and the 0th column is the visual bottom.
+                       */
+
+                       var ctx = _canvas.getContext('2d');
+                       switch (orientation) {
+                               case 2:
+                                       // horizontal flip
+                                       ctx.translate(width, 0);
+                                       ctx.scale(-1, 1);
+                                       break;
+                               case 3:
+                                       // 180 rotate left
+                                       ctx.translate(width, height);
+                                       ctx.rotate(Math.PI);
+                                       break;
+                               case 4:
+                                       // vertical flip
+                                       ctx.translate(0, height);
+                                       ctx.scale(1, -1);
+                                       break;
+                               case 5:
+                                       // vertical flip + 90 rotate right
+                                       ctx.rotate(0.5 * Math.PI);
+                                       ctx.scale(1, -1);
+                                       break;
+                               case 6:
+                                       // 90 rotate right
+                                       ctx.rotate(0.5 * Math.PI);
+                                       ctx.translate(0, -height);
+                                       break;
+                               case 7:
+                                       // horizontal flip + 90 rotate right
+                                       ctx.rotate(0.5 * Math.PI);
+                                       ctx.translate(width, -height);
+                                       ctx.scale(-1, 1);
+                                       break;
+                               case 8:
+                                       // 90 rotate left
+                                       ctx.rotate(-0.5 * Math.PI);
+                                       ctx.translate(-width, 0);
+                                       break;
+                       }
+               }
+
+
+               function _purge() {
+                       if (_imgInfo) {
+                               _imgInfo.purge();
+                               _imgInfo = null;
+                       }
+                       _binStr = _img = _canvas = _blob = null;
+                       _modified = false;
+               }
+       }
+
+       return (extensions.Image = HTML5Image);
+});
+
+/**
+ * Stub for moxie/runtime/flash/Runtime
+ * @private
+ */
+define("moxie/runtime/flash/Runtime", [
+], function() {
+       return {};
+});
+
+/**
+ * Stub for moxie/runtime/silverlight/Runtime
+ * @private
+ */
+define("moxie/runtime/silverlight/Runtime", [
+], function() {
+       return {};
+});
+
+// Included from: src/javascript/runtime/html4/Runtime.js
+
+/**
+ * Runtime.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+/*global File:true */
+
+/**
+Defines constructor for HTML4 runtime.
+
+@class moxie/runtime/html4/Runtime
+@private
+*/
+define("moxie/runtime/html4/Runtime", [
+       "moxie/core/utils/Basic",
+       "moxie/core/Exceptions",
+       "moxie/runtime/Runtime",
+       "moxie/core/utils/Env"
+], function(Basic, x, Runtime, Env) {
+       
+       var type = 'html4', extensions = {};
+
+       function Html4Runtime(options) {
+               var I = this
+               , Test = Runtime.capTest
+               , True = Runtime.capTrue
+               ;
+
+               Runtime.call(this, options, type, {
+                       access_binary: Test(window.FileReader || window.File && File.getAsDataURL),
+                       access_image_binary: false,
+                       display_media: Test(extensions.Image && (Env.can('create_canvas') || Env.can('use_data_uri_over32kb'))),
+                       do_cors: false,
+                       drag_and_drop: false,
+                       filter_by_extension: Test(function() { // if you know how to feature-detect this, please suggest
+                               return (Env.browser === 'Chrome' && Env.verComp(Env.version, 28, '>=')) || 
+                                       (Env.browser === 'IE' && Env.verComp(Env.version, 10, '>=')) || 
+                                       (Env.browser === 'Safari' && Env.verComp(Env.version, 7, '>='));
+                       }()),
+                       resize_image: function() {
+                               return extensions.Image && I.can('access_binary') && Env.can('create_canvas');
+                       },
+                       report_upload_progress: false,
+                       return_response_headers: false,
+                       return_response_type: function(responseType) {
+                               if (responseType === 'json' && !!window.JSON) {
+                                       return true;
+                               } 
+                               return !!~Basic.inArray(responseType, ['text', 'document', '']);
+                       },
+                       return_status_code: function(code) {
+                               return !Basic.arrayDiff(code, [200, 404]);
+                       },
+                       select_file: function() {
+                               return Env.can('use_fileinput');
+                       },
+                       select_multiple: false,
+                       send_binary_string: false,
+                       send_custom_headers: false,
+                       send_multipart: true,
+                       slice_blob: false,
+                       stream_upload: function() {
+                               return I.can('select_file');
+                       },
+                       summon_file_dialog: function() { // yeah... some dirty sniffing here...
+                               return I.can('select_file') && (
+                                       (Env.browser === 'Firefox' && Env.verComp(Env.version, 4, '>=')) ||
+                                       (Env.browser === 'Opera' && Env.verComp(Env.version, 12, '>=')) ||
+                                       (Env.browser === 'IE' && Env.verComp(Env.version, 10, '>=')) ||
+                                       !!~Basic.inArray(Env.browser, ['Chrome', 'Safari'])
+                               );
+                       },
+                       upload_filesize: True,
+                       use_http_method: function(methods) {
+                               return !Basic.arrayDiff(methods, ['GET', 'POST']);
+                       }
+               });
+
+
+               Basic.extend(this, {
+                       init : function() {
+                               this.trigger("Init");
+                       },
+
+                       destroy: (function(destroy) { // extend default destroy method
+                               return function() {
+                                       destroy.call(I);
+                                       destroy = I = null;
+                               };
+                       }(this.destroy))
+               });
+
+               Basic.extend(this.getShim(), extensions);
+       }
+
+       Runtime.addConstructor(type, Html4Runtime);
+
+       return extensions;
+});
+
+// Included from: src/javascript/runtime/html4/file/FileInput.js
+
+/**
+ * FileInput.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+/**
+@class moxie/runtime/html4/file/FileInput
+@private
+*/
+define("moxie/runtime/html4/file/FileInput", [
+       "moxie/runtime/html4/Runtime",
+       "moxie/file/File",
+       "moxie/core/utils/Basic",
+       "moxie/core/utils/Dom",
+       "moxie/core/utils/Events",
+       "moxie/core/utils/Mime",
+       "moxie/core/utils/Env"
+], function(extensions, File, Basic, Dom, Events, Mime, Env) {
+       
+       function FileInput() {
+               var _uid, _mimes = [], _options;
+
+               function addInput() {
+                       var comp = this, I = comp.getRuntime(), shimContainer, browseButton, currForm, form, input, uid;
+
+                       uid = Basic.guid('uid_');
+
+                       shimContainer = I.getShimContainer(); // we get new ref everytime to avoid memory leaks in IE
+
+                       if (_uid) { // move previous form out of the view
+                               currForm = Dom.get(_uid + '_form');
+                               if (currForm) {
+                                       Basic.extend(currForm.style, { top: '100%' });
+                               }
+                       }
+
+                       // build form in DOM, since innerHTML version not able to submit file for some reason
+                       form = document.createElement('form');
+                       form.setAttribute('id', uid + '_form');
+                       form.setAttribute('method', 'post');
+                       form.setAttribute('enctype', 'multipart/form-data');
+                       form.setAttribute('encoding', 'multipart/form-data');
+
+                       Basic.extend(form.style, {
+                               overflow: 'hidden',
+                               position: 'absolute',
+                               top: 0,
+                               left: 0,
+                               width: '100%',
+                               height: '100%'
+                       });
+
+                       input = document.createElement('input');
+                       input.setAttribute('id', uid);
+                       input.setAttribute('type', 'file');
+                       input.setAttribute('name', _options.name || 'Filedata');
+                       input.setAttribute('accept', _mimes.join(','));
+
+                       Basic.extend(input.style, {
+                               fontSize: '999px',
+                               opacity: 0
+                       });
+
+                       form.appendChild(input);
+                       shimContainer.appendChild(form);
+
+                       // prepare file input to be placed underneath the browse_button element
+                       Basic.extend(input.style, {
+                               position: 'absolute',
+                               top: 0,
+                               left: 0,
+                               width: '100%',
+                               height: '100%'
+                       });
+
+                       if (Env.browser === 'IE' && Env.verComp(Env.version, 10, '<')) {
+                               Basic.extend(input.style, {
+                                       filter : "progid:DXImageTransform.Microsoft.Alpha(opacity=0)"
+                               });
+                       }
+
+                       input.onchange = function() { // there should be only one handler for this
+                               var file;
+
+                               if (!this.value) {
+                                       return;
+                               }
+
+                               if (this.files) { // check if browser is fresh enough
+                                       file = this.files[0];
+
+                                       // ignore empty files (IE10 for example hangs if you try to send them via XHR)
+                                       if (file.size === 0) {
+                                               form.parentNode.removeChild(form);
+                                               return;
+                                       }
+                               } else {
+                                       file = {
+                                               name: this.value
+                                       };
+                               }
+
+                               file = new File(I.uid, file);
+
+                               // clear event handler
+                               this.onchange = function() {}; 
+                               addInput.call(comp); 
+
+                               comp.files = [file];
+
+                               // substitute all ids with file uids (consider file.uid read-only - we cannot do it the other way around)
+                               input.setAttribute('id', file.uid);
+                               form.setAttribute('id', file.uid + '_form');
+                               
+                               comp.trigger('change');
+
+                               input = form = null;
+                       };
+
+
+                       // route click event to the input
+                       if (I.can('summon_file_dialog')) {
+                               browseButton = Dom.get(_options.browse_button);
+                               Events.removeEvent(browseButton, 'click', comp.uid);
+                               Events.addEvent(browseButton, 'click', function(e) {
+                                       if (input && !input.disabled) { // for some reason FF (up to 8.0.1 so far) lets to click disabled input[type=file]
+                                               input.click();
+                                       }
+                                       e.preventDefault();
+                               }, comp.uid);
+                       }
+
+                       _uid = uid;
+
+                       shimContainer = currForm = browseButton = null;
+               }
+
+               Basic.extend(this, {
+                       init: function(options) {
+                               var comp = this, I = comp.getRuntime(), shimContainer;
+
+                               // figure out accept string
+                               _options = options;
+                               _mimes = options.accept.mimes || Mime.extList2mimes(options.accept, I.can('filter_by_extension'));
+
+                               shimContainer = I.getShimContainer();
+
+                               (function() {
+                                       var browseButton, zIndex, top;
+
+                                       browseButton = Dom.get(options.browse_button);
+
+                                       // Route click event to the input[type=file] element for browsers that support such behavior
+                                       if (I.can('summon_file_dialog')) {
+                                               if (Dom.getStyle(browseButton, 'position') === 'static') {
+                                                       browseButton.style.position = 'relative';
+                                               }
+
+                                               zIndex = parseInt(Dom.getStyle(browseButton, 'z-index'), 10) || 1;
+
+                                               browseButton.style.zIndex = zIndex;
+                                               shimContainer.style.zIndex = zIndex - 1;
+                                       }
+
+                                       /* Since we have to place input[type=file] on top of the browse_button for some browsers,
+                                       browse_button loses interactivity, so we restore it here */
+                                       top = I.can('summon_file_dialog') ? browseButton : shimContainer;
+
+                                       Events.addEvent(top, 'mouseover', function() {
+                                               comp.trigger('mouseenter');
+                                       }, comp.uid);
+
+                                       Events.addEvent(top, 'mouseout', function() {
+                                               comp.trigger('mouseleave');
+                                       }, comp.uid);
+
+                                       Events.addEvent(top, 'mousedown', function() {
+                                               comp.trigger('mousedown');
+                                       }, comp.uid);
+
+                                       Events.addEvent(Dom.get(options.container), 'mouseup', function() {
+                                               comp.trigger('mouseup');
+                                       }, comp.uid);
+
+                                       browseButton = null;
+                               }());
+
+                               addInput.call(this);
+
+                               shimContainer = null;
+
+                               // trigger ready event asynchronously
+                               comp.trigger({
+                                       type: 'ready',
+                                       async: true
+                               });
+                       },
+
+
+                       disable: function(state) {
+                               var input;
+
+                               if ((input = Dom.get(_uid))) {
+                                       input.disabled = !!state;
+                               }
+                       },
+
+                       destroy: function() {
+                               var I = this.getRuntime()
+                               , shim = I.getShim()
+                               , shimContainer = I.getShimContainer()
+                               ;
+                               
+                               Events.removeAllEvents(shimContainer, this.uid);
+                               Events.removeAllEvents(_options && Dom.get(_options.container), this.uid);
+                               Events.removeAllEvents(_options && Dom.get(_options.browse_button), this.uid);
+                               
+                               if (shimContainer) {
+                                       shimContainer.innerHTML = '';
+                               }
+
+                               shim.removeInstance(this.uid);
+
+                               _uid = _mimes = _options = shimContainer = shim = null;
+                       }
+               });
+       }
+
+       return (extensions.FileInput = FileInput);
+});
+
+// Included from: src/javascript/runtime/html4/file/FileReader.js
+
+/**
+ * FileReader.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+/**
+@class moxie/runtime/html4/file/FileReader
+@private
+*/
+define("moxie/runtime/html4/file/FileReader", [
+       "moxie/runtime/html4/Runtime",
+       "moxie/runtime/html5/file/FileReader"
+], function(extensions, FileReader) {
+       return (extensions.FileReader = FileReader);
+});
+
+// Included from: src/javascript/runtime/html4/xhr/XMLHttpRequest.js
+
+/**
+ * XMLHttpRequest.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+/**
+@class moxie/runtime/html4/xhr/XMLHttpRequest
+@private
+*/
+define("moxie/runtime/html4/xhr/XMLHttpRequest", [
+       "moxie/runtime/html4/Runtime",
+       "moxie/core/utils/Basic",
+       "moxie/core/utils/Dom",
+       "moxie/core/utils/Url",
+       "moxie/core/Exceptions",
+       "moxie/core/utils/Events",
+       "moxie/file/Blob",
+       "moxie/xhr/FormData"
+], function(extensions, Basic, Dom, Url, x, Events, Blob, FormData) {
+       
+       function XMLHttpRequest() {
+               var _status, _response, _iframe;
+
+               function cleanup(cb) {
+                       var target = this, uid, form, inputs, i, hasFile = false;
+
+                       if (!_iframe) {
+                               return;
+                       }
+
+                       uid = _iframe.id.replace(/_iframe$/, '');
+
+                       form = Dom.get(uid + '_form');
+                       if (form) {
+                               inputs = form.getElementsByTagName('input');
+                               i = inputs.length;
+
+                               while (i--) {
+                                       switch (inputs[i].getAttribute('type')) {
+                                               case 'hidden':
+                                                       inputs[i].parentNode.removeChild(inputs[i]);
+                                                       break;
+                                               case 'file':
+                                                       hasFile = true; // flag the case for later
+                                                       break;
+                                       }
+                               }
+                               inputs = [];
+
+                               if (!hasFile) { // we need to keep the form for sake of possible retries
+                                       form.parentNode.removeChild(form);
+                               }
+                               form = null;
+                       }
+
+                       // without timeout, request is marked as canceled (in console)
+                       setTimeout(function() {
+                               Events.removeEvent(_iframe, 'load', target.uid);
+                               if (_iframe.parentNode) { // #382
+                                       _iframe.parentNode.removeChild(_iframe);
+                               }
+
+                               // check if shim container has any other children, if - not, remove it as well
+                               var shimContainer = target.getRuntime().getShimContainer();
+                               if (!shimContainer.children.length) {
+                                       shimContainer.parentNode.removeChild(shimContainer);
+                               }
+
+                               shimContainer = _iframe = null;
+                               cb();
+                       }, 1);
+               }
+
+               Basic.extend(this, {
+                       send: function(meta, data) {
+                               var target = this, I = target.getRuntime(), uid, form, input, blob;
+
+                               _status = _response = null;
+
+                               function createIframe() {
+                                       var container = I.getShimContainer() || document.body
+                                       , temp = document.createElement('div')
+                                       ;
+
+                                       // IE 6 won't be able to set the name using setAttribute or iframe.name
+                                       temp.innerHTML = '<iframe id="' + uid + '_iframe" name="' + uid + '_iframe" src="javascript:&quot;&quot;" style="display:none"></iframe>';
+                                       _iframe = temp.firstChild;
+                                       container.appendChild(_iframe);
+
+                                       /* _iframe.onreadystatechange = function() {
+                                               console.info(_iframe.readyState);
+                                       };*/
+
+                                       Events.addEvent(_iframe, 'load', function() { // _iframe.onload doesn't work in IE lte 8
+                                               var el;
+
+                                               try {
+                                                       el = _iframe.contentWindow.document || _iframe.contentDocument || window.frames[_iframe.id].document;
+
+                                                       // try to detect some standard error pages
+                                                       if (/^4(0[0-9]|1[0-7]|2[2346])\s/.test(el.title)) { // test if title starts with 4xx HTTP error
+                                                               _status = el.title.replace(/^(\d+).*$/, '$1');
+                                                       } else {
+                                                               _status = 200;
+                                                               // get result
+                                                               _response = Basic.trim(el.body.innerHTML);
+
+                                                               // we need to fire these at least once
+                                                               target.trigger({
+                                                                       type: 'progress',
+                                                                       loaded: _response.length,
+                                                                       total: _response.length
+                                                               });
+
+                                                               if (blob) { // if we were uploading a file
+                                                                       target.trigger({
+                                                                               type: 'uploadprogress',
+                                                                               loaded: blob.size || 1025,
+                                                                               total: blob.size || 1025
+                                                                       });
+                                                               }
+                                                       }
+                                               } catch (ex) {
+                                                       if (Url.hasSameOrigin(meta.url)) {
+                                                               // if response is sent with error code, iframe in IE gets redirected to res://ieframe.dll/http_x.htm
+                                                               // which obviously results to cross domain error (wtf?)
+                                                               _status = 404;
+                                                       } else {
+                                                               cleanup.call(target, function() {
+                                                                       target.trigger('error');
+                                                               });
+                                                               return;
+                                                       }
+                                               }       
+                                       
+                                               cleanup.call(target, function() {
+                                                       target.trigger('load');
+                                               });
+                                       }, target.uid);
+                               } // end createIframe
+
+                               // prepare data to be sent and convert if required
+                               if (data instanceof FormData && data.hasBlob()) {
+                                       blob = data.getBlob();
+                                       uid = blob.uid;
+                                       input = Dom.get(uid);
+                                       form = Dom.get(uid + '_form');
+                                       if (!form) {
+                                               throw new x.DOMException(x.DOMException.NOT_FOUND_ERR);
+                                       }
+                               } else {
+                                       uid = Basic.guid('uid_');
+
+                                       form = document.createElement('form');
+                                       form.setAttribute('id', uid + '_form');
+                                       form.setAttribute('method', meta.method);
+                                       form.setAttribute('enctype', 'multipart/form-data');
+                                       form.setAttribute('encoding', 'multipart/form-data');
+
+                                       I.getShimContainer().appendChild(form);
+                               }
+
+                               // set upload target
+                               form.setAttribute('target', uid + '_iframe');
+
+                               if (data instanceof FormData) {
+                                       data.each(function(value, name) {
+                                               if (value instanceof Blob) {
+                                                       if (input) {
+                                                               input.setAttribute('name', name);
+                                                       }
+                                               } else {
+                                                       var hidden = document.createElement('input');
+
+                                                       Basic.extend(hidden, {
+                                                               type : 'hidden',
+                                                               name : name,
+                                                               value : value
+                                                       });
+
+                                                       // make sure that input[type="file"], if it's there, comes last
+                                                       if (input) {
+                                                               form.insertBefore(hidden, input);
+                                                       } else {
+                                                               form.appendChild(hidden);
+                                                       }
+                                               }
+                                       });
+                               }
+
+                               // set destination url
+                               form.setAttribute("action", meta.url);
+
+                               createIframe();
+                               form.submit();
+                               target.trigger('loadstart');
+                       },
+
+                       getStatus: function() {
+                               return _status;
+                       },
+
+                       getResponse: function(responseType) {
+                               if ('json' === responseType) {
+                                       // strip off <pre>..</pre> tags that might be enclosing the response
+                                       if (Basic.typeOf(_response) === 'string' && !!window.JSON) {
+                                               try {
+                                                       return JSON.parse(_response.replace(/^\s*<pre[^>]*>/, '').replace(/<\/pre>\s*$/, ''));
+                                               } catch (ex) {
+                                                       return null;
+                                               }
+                                       } 
+                               } else if ('document' === responseType) {
+
+                               }
+                               return _response;
+                       },
+
+                       abort: function() {
+                               var target = this;
+
+                               if (_iframe && _iframe.contentWindow) {
+                                       if (_iframe.contentWindow.stop) { // FireFox/Safari/Chrome
+                                               _iframe.contentWindow.stop();
+                                       } else if (_iframe.contentWindow.document.execCommand) { // IE
+                                               _iframe.contentWindow.document.execCommand('Stop');
+                                       } else {
+                                               _iframe.src = "about:blank";
+                                       }
+                               }
+
+                               cleanup.call(this, function() {
+                                       // target.dispatchEvent('readystatechange');
+                                       target.dispatchEvent('abort');
+                               });
+                       }
+               });
+       }
+
+       return (extensions.XMLHttpRequest = XMLHttpRequest);
+});
+
+// Included from: src/javascript/runtime/html4/image/Image.js
+
+/**
+ * Image.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+/**
+@class moxie/runtime/html4/image/Image
+@private
+*/
+define("moxie/runtime/html4/image/Image", [
+       "moxie/runtime/html4/Runtime",
+       "moxie/runtime/html5/image/Image"
+], function(extensions, Image) {
+       return (extensions.Image = Image);
+});
+
+expose(["moxie/core/utils/Basic","moxie/core/utils/Env","moxie/core/I18n","moxie/core/utils/Mime","moxie/core/utils/Dom","moxie/core/Exceptions","moxie/core/EventTarget","moxie/runtime/Runtime","moxie/runtime/RuntimeClient","moxie/file/FileInput","moxie/core/utils/Encode","moxie/file/Blob","moxie/file/File","moxie/file/FileDrop","moxie/file/FileReader","moxie/core/utils/Url","moxie/runtime/RuntimeTarget","moxie/file/FileReaderSync","moxie/xhr/FormData","moxie/xhr/XMLHttpRequest","moxie/runtime/Transporter","moxie/image/Image","moxie/core/utils/Events"]);
+})(this);
+/**
+ * o.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+/*global moxie:true */
+
+/**
+Globally exposed namespace with the most frequently used public classes and handy methods.
+
+@class o
+@static
+@private
+*/
+(function(exports) {
+       "use strict";
+
+       var o = {}, inArray = exports.moxie.core.utils.Basic.inArray;
+
+       // directly add some public classes
+       // (we do it dynamically here, since for custom builds we cannot know beforehand what modules were included)
+       (function addAlias(ns) {
+               var name, itemType;
+               for (name in ns) {
+                       itemType = typeof(ns[name]);
+                       if (itemType === 'object' && !~inArray(name, ['Exceptions', 'Env', 'Mime'])) {
+                               addAlias(ns[name]);
+                       } else if (itemType === 'function') {
+                               o[name] = ns[name];
+                       }
+               }
+       })(exports.moxie);
+
+       // add some manually
+       o.Env = exports.moxie.core.utils.Env;
+       o.Mime = exports.moxie.core.utils.Mime;
+       o.Exceptions = exports.moxie.core.Exceptions;
+
+       // expose globally
+       exports.mOxie = o;
+       if (!exports.o) {
+               exports.o = o;
+       }
+       return o;
+})(this);
</ins></span></pre></div>
<a id="trunksrcwpincludesjspluploadpluploadflashswf"></a>
<div class="binary"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Deleted: trunk/src/wp-includes/js/plupload/plupload.flash.swf</h4>
<pre class="diff"><span>
<span class="cx">(Binary files differ)
</span></span></pre></div>
<a id="trunksrcwpincludesjspluploadpluploadfullminjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/js/plupload/plupload.full.min.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/js/plupload/plupload.full.min.js    2017-09-01 08:49:50 UTC (rev 41327)
+++ trunk/src/wp-includes/js/plupload/plupload.full.min.js      2017-09-01 12:27:49 UTC (rev 41328)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,6 +1,7 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+var MXI_DEBUG=0;
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px">  * mOxie - multi-runtime File API & XMLHttpRequest L2 Polyfill
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * v1.3.4
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * v1.3.5
</ins><span class="cx" style="display: block; padding: 0 10px">  *
</span><span class="cx" style="display: block; padding: 0 10px">  * Copyright 2013, Moxiecode Systems AB
</span><span class="cx" style="display: block; padding: 0 10px">  * Released under GPL License.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -8,15 +9,20 @@
</span><span class="cx" style="display: block; padding: 0 10px">  * License: http://www.plupload.com/license
</span><span class="cx" style="display: block; padding: 0 10px">  * Contributing: http://www.plupload.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px">  *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Date: 2015-07-18
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Date: 2016-05-15
</ins><span class="cx" style="display: block; padding: 0 10px">  */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-!function(e,t){"use strict";function n(e,t){for(var n,i=[],r=0;r<e.length;++r){if(n=s[e[r]]||o(e[r]),!n)throw"module definition dependecy not found: "+e[r];i.push(n)}t.apply(null,i)}function i(e,i,r){if("string"!=typeof e)throw"invalid module definition, module id must be defined and be a string";if(i===t)throw"invalid module definition, dependencies must be specified";if(r===t)throw"invalid module definition, definition function must be specified";n(i,function(){s[e]=r.apply(null,arguments)})}function r(e){return!!s[e]}function o(t){for(var n=e,i=t.split(/[.\/]/),r=0;r<i.length;++r){if(!n[i[r]])return;n=n[i[r]]}return n}function a(n){for(var i=0;i<n.length;i++){for(var r=e,o=n[i],a=o.split(/[.\/]/),u=0;u<a.length-1;++u)r[a[u]]===t&&(r[a[u]]={}),r=r[a[u]];r[a[a.length-1]]=s[o]}}var s={},u="moxie/core/uti
 ls/Basic",c="moxie/core/utils/Env",l="moxie/core/I18n",d="moxie/core/utils/Mime",h="moxie/core/utils/Dom",f="moxie/core/Exceptions",p="moxie/core/EventTarget",m="moxie/runtime/Runtime",g="moxie/runtime/RuntimeClient",v="moxie/file/FileInput",w="moxie/core/utils/Encode",y="moxie/file/Blob",E="moxie/file/File",_="moxie/file/FileDrop",b="moxie/file/FileReader",x="moxie/core/utils/Url",R="moxie/runtime/RuntimeTarget",A="moxie/file/FileReaderSync",I="moxie/xhr/FormData",T="moxie/xhr/XMLHttpRequest",S="moxie/runtime/Transporter",O="moxie/image/Image",D="moxie/runtime/html5/Runtime",N="moxie/core/utils/Events",L="moxie/runtime/html5/file/FileInput",C="moxie/runtime/html5/file/Blob",M="moxie/runtime/html5/file/FileDrop",F="mo
 xie/runtime/html5/file/FileReader",P="moxie/runtime/html5/xhr/XMLHttpRequest",H="moxie/runtime/html5/utils/BinaryReader",B="moxie/runtime/html5/image/JPEGHeaders",k="moxie/runtime/html5/image/ExifParser",U="moxie/runtime/html5/image/JPEG",G="moxie/runtime/html5/image/PNG",z="moxie/runtime/html5/image/ImageInfo",q="moxie/runtime/html5/image/MegaPixel",j="moxie/runtime/html5/image/Image",X="moxie/runtime/flash/Runtime",V="moxie/runtime/flash/file/FileInput",W="moxie/runtime/flash/file/Blob",Y="moxie/runtime/flash/file/FileReader",$="moxie/runtime/flash/file/FileReaderSync",J="moxie/runtime/flash/xhr/XMLHttpRequest",Z="moxie/runtime/flash/runtime/Transporter",K="moxie/runtime/flash/image/Image",Q="moxie/runtime/silverlight/Runtime",ee="moxie/runtime/silverlight/file/FileInput",te="moxie/ru
 ntime/silverlight/file/Blob",ne="moxie/runtime/silverlight/file/FileDrop",ie="moxie/runtime/silverlight/file/FileReader",re="moxie/runtime/silverlight/file/FileReaderSync",oe="moxie/runtime/silverlight/xhr/XMLHttpRequest",ae="moxie/runtime/silverlight/runtime/Transporter",se="moxie/runtime/silverlight/image/Image",ue="moxie/runtime/html4/Runtime",ce="moxie/runtime/html4/file/FileInput",le="moxie/runtime/html4/file/FileReader",de="moxie/runtime/html4/xhr/XMLHttpRequest",he="moxie/runtime/html4/image/Image";i(u,[],function(){var e=function(e){var t;return e===t?"undefined":null===e?"null":e.nodeType?"node":{}.toString.call(e).match(/\s([a-z|A-Z]+)/)[1].toLowerCase()},t=function(i){var r;return n(arguments,function(o,s){s>0&&n(o,function(n,o){n!==r&&(e(i[o])===e(n)&&~a(e(n),["array","object"])?t(i
 [o],n):i[o]=n)})}),i},n=function(t,n){var i,r,o,a;if(t)if("number"===e(t.length)){for(o=0,i=t.length;i>o;o++)if(n(t[o],o)===!1)return}else if("object"===e(t))for(r in t)if(t.hasOwnProperty(r)&&n(t[r],r)===!1)return},i=function(t){var n;if(!t||"object"!==e(t))return!0;for(n in t)return!1;return!0},r=function(t,n){function i(r){"function"===e(t[r])&&t[r](function(e){++r<o&&!e?i(r):n(e)})}var r=0,o=t.length;"function"!==e(n)&&(n=function(){}),t&&t.length||n(),i(r)},o=function(e,t){var i=0,r=e.length,o=new Array(r);n(e,function(e,n){e(function(e){if(e)return t(e);var a=[].slice.call(arguments);a.shift(),o[n]=a,i++,i===r&&(o.unshift(null),t.apply(this,o))})})},a=function(e,t){if(t){if(Array.prototype.indexOf)return Array.prototype.indexOf.call(t,e);for(var n=0,i=t.length;i>n;n++)if(t[n]===e)return n}return-1},s=function(t,n){var i=[];"array"!==e(t)&&(t=[t]),"a
 rray"!==e(n)&&(n=[n]);for(var r in t)-1===a(t[r],n)&&i.push(t[r]);return i.length?i:!1},u=function(e,t){var i=[];return n(e,function(e){-1!==a(e,t)&&i.push(e)}),i.length?i:null},c=function(e){var t,n=[];for(t=0;t<e.length;t++)n[t]=e[t];return n},l=function(){var e=0;return function(t){var n=(new Date).getTime().toString(32),i;for(i=0;5>i;i++)n+=Math.floor(65535*Math.random()).toString(32);return(t||"o_")+n+(e++).toString(32)}}(),d=function(e){return e?String.prototype.trim?String.prototype.trim.call(e):e.toString().replace(/^\s*/,"").replace(/\s*$/,""):e},h=function(e){if("string"!=typeof e)return e;var t={t:1099511627776,g:1073741824,m:1048576,k:1024},n;return e=/^([0-9\.]+)([tmgk]?)$/.exec(e.toLowerCase().replace(/[^0-9\.tmkg]/g,"")),n=e[2],e=+e[1],t.hasOwnProperty(n)&&(e*=t[n]),Math.floor(e)},f=function(t){var n=[].slice.call(arguments,1);return t.replace(/%[a-z]/g,function(){var t=n.shif
 t();return"undefined"!==e(t)?t:""})};return{guid:l,typeOf:e,extend:t,each:n,isEmptyObj:i,inSeries:r,inParallel:o,inArray:a,arrayDiff:s,arrayIntersect:u,toArray:c,trim:d,sprintf:f,parseSizeStr:h}}),i(c,[u],function(e){function t(e,t,n){var i=0,r=0,o=0,a={dev:-6,alpha:-5,a:-5,beta:-4,b:-4,RC:-3,rc:-3,"#":-2,p:1,pl:1},s=function(e){return e=(""+e).replace(/[_\-+]/g,"."),e=e.replace(/([^.\d]+)/g,".$1.").replace(/\.{2,}/g,"."),e.length?e.split("."):[-8]},u=function(e){return e?isNaN(e)?a[e]||-7:parseInt(e,10):0};for(e=s(e),t=s(t),r=Math.max(e.length,t.length),i=0;r>i;i++)if(e[i]!=t[i]){if(e[i]=u(e[i]),t[i]=u(t[i]),e[i]<t[i]){o=-1;break}if(e[i]>t[i]){o=1;break}}if(!n)return o;switch(n){case">":case"gt":return o>0;case">=":case"ge":return o>=0;case"<=":case"le":return 0>=o;case"==":case"=":case"eq&quo
 t;:return 0===o;case"<>":case"!=":case"ne":return 0!==o;case"":case"<":case"lt":return 0>o;default:return null}}var n=function(e){var t="",n="?",i="function",r="undefined",o="object",a="major",s="model",u="name",c="type",l="vendor",d="version",h="architecture",f="console",p="mobile",m="tablet",g={has:function(e,t){return-1!==t.toLowerCase().indexOf(e.toLowerCase())},lowerize:function(e){return e.toLowerCase()}},v={rgx:function(){for(var t,n=0,a,s,u,c,l,d,h=arguments;n<h.length;n+=2){var f=h[n],p=h[n+1];if(typeof t===r){t={};for(u in p)c=p[u],typeof c===o?t[c[0]]=e:t[c]=e}for(a=s=0;a<f.length;a++)if(l=f[a].exec(this.getUA())){for(u=0;u<p.length;u++)d=l[++s],c=p[u],typeof c===o&&c.length>0?2==c.length?typeof c[1]==i?t[c[0]]=c[1].call(this,d):t[c[0
 ]]=c[1]:3==c.length?typeof c[1]!==i||c[1].exec&&c[1].test?t[c[0]]=d?d.replace(c[1],c[2]):e:t[c[0]]=d?c[1].call(this,d,c[2]):e:4==c.length&&(t[c[0]]=d?c[3].call(this,d.replace(c[1],c[2])):e):t[c]=d?d:e;break}if(l)break}return t},str:function(t,i){for(var r in i)if(typeof i[r]===o&&i[r].length>0){for(var a=0;a<i[r].length;a++)if(g.has(i[r][a],t))return r===n?e:r}else if(g.has(i[r],t))return r===n?e:r;return t}},w={browser:{oldsafari:{major:{1:["/8","/1","/3"],2:"/4","?":"/"},version:{"1.0":"/8",1.2:"/1",1.3:"/3","2.0":"/412","2.0.2":"/416","2.0.3":"/417","2.0.4":"/419","?":"/"}}},device:{sprint:{model:{"Evo Shift 4G":"7373KT"},vendor:{HTC:"APA",Sprint:"Sprint"}}},os:{windows:{version:{ME:"4.90","NT 3.11&q
 uot;:"NT3.51","NT 4.0":"NT4.0",2000:"NT 5.0",XP:["NT 5.1","NT 5.2"],Vista:"NT 6.0",7:"NT 6.1",8:"NT 6.2",8.1:"NT 6.3",RT:"ARM"}}}},y={browser:[[/(opera\smini)\/([\w\.-]+)/i,/(opera\s[mobiletab]+).+version\/([\w\.-]+)/i,/(opera).+version\/([\w\.]+)/i,/(opera)[\/\s]+([\w\.]+)/i],[u,d],[/\s(opr)\/([\w\.]+)/i],[[u,"Opera"],d],[/(kindle)\/([\w\.]+)/i,/(lunascape|maxthon|netfront|jasmine|blazer)[\/\s]?([\w\.]+)*/i,/(avant\s|iemobile|slim|baidu)(?:browser)?[\/\s]?([\w\.]*)/i,/(?:ms|\()(ie)\s([\w\.]+)/i,/(rekonq)\/([\w\.]+)*/i,/(chromium|flock|rockmelt|midori|epiphany|silk|skyfire|ovibrowser|bolt|iron|vivaldi)\/([\w\.-]+)/i],[u,d],[/(trident).+rv[:\s]([\w\.]+).+like\sgecko/i],[[u,"IE"],d],[/(edge)\/((\d+)?[\w\.]+)/i],[u,d],[/(yabrowser)\/([\w\.]+)/i],[[u,"Yandex"],d],[/(comodo_dragon)\/([\w\.]+)/i],[[u,/_/g," "],d],[/(chrome|omniweb|arora|[tiz
 enoka]{5}\s?browser)\/v?([\w\.]+)/i,/(uc\s?browser|qqbrowser)[\/\s]?([\w\.]+)/i],[u,d],[/(dolfin)\/([\w\.]+)/i],[[u,"Dolphin"],d],[/((?:android.+)crmo|crios)\/([\w\.]+)/i],[[u,"Chrome"],d],[/XiaoMi\/MiuiBrowser\/([\w\.]+)/i],[d,[u,"MIUI Browser"]],[/android.+version\/([\w\.]+)\s+(?:mobile\s?safari|safari)/i],[d,[u,"Android Browser"]],[/FBAV\/([\w\.]+);/i],[d,[u,"Facebook"]],[/version\/([\w\.]+).+?mobile\/\w+\s(safari)/i],[d,[u,"Mobile Safari"]],[/version\/([\w\.]+).+?(mobile\s?safari|safari)/i],[d,u],[/webkit.+?(mobile\s?safari|safari)(\/[\w\.]+)/i],[u,[d,v.str,w.browser.oldsafari.version]],[/(konqueror)\/([\w\.]+)/i,/(webkit|khtml)\/([\w\.]+)/i],[u,d],[/(navigator|netscape)\/([\w\.-]+)/i],[[u,"Netscape"],d],[/(swiftfox)/i,/(icedragon|iceweasel|camino|chimera|fennec|maemo\sbrowser|minimo|conkeror)[\/\s]?([\w\.\+]+)/i,/(firefox|seamonkey|k-meleon|icecat|iceape|firebird|phoenix)\/([\w\.-]+)/i,/(mozilla)\/([\w\.]+).+
 rv\:.+gecko\/\d+/i,/(polaris|lynx|dillo|icab|doris|amaya|w3m|netsurf)[\/\s]?([\w\.]+)/i,/(links)\s\(([\w\.]+)/i,/(gobrowser)\/?([\w\.]+)*/i,/(ice\s?browser)\/v?([\w\._]+)/i,/(mosaic)[\/\s]([\w\.]+)/i],[u,d]],engine:[[/windows.+\sedge\/([\w\.]+)/i],[d,[u,"EdgeHTML"]],[/(presto)\/([\w\.]+)/i,/(webkit|trident|netfront|netsurf|amaya|lynx|w3m)\/([\w\.]+)/i,/(khtml|tasman|links)[\/\s]\(?([\w\.]+)/i,/(icab)[\/\s]([23]\.[\d\.]+)/i],[u,d],[/rv\:([\w\.]+).*(gecko)/i],[d,u]],os:[[/microsoft\s(windows)\s(vista|xp)/i],[u,d],[/(windows)\snt\s6\.2;\s(arm)/i,/(windows\sphone(?:\sos)*|windows\smobile|windows)[\s\/]?([ntce\d\.\s]+\w)/i],[u,[d,v.str,w.os.windows.version]],[/(win(?=3|9|n)|win\s9x\s)([nt\d\.]+)/i],[[u,"Windows"],[d,v.str,w.os.windows.version]],[/\((bb)(10);/i],[[u,"BlackBerry"],d],[/(blackberry)\w*\/?([\w\.]+)*/i,/(tizen)[\/\s]([\w\.]+)/i,/(android|webos|palm\os|qnx|bada|rim\stablet\sos|meego|contiki)[\/\s-]?([\w\.]+)*/i,/linux;.+(sailfish);/i],[u,d],[/(sym
 bian\s?os|symbos|s60(?=;))[\/\s-]?([\w\.]+)*/i],[[u,"Symbian"],d],[/\((series40);/i],[u],[/mozilla.+\(mobile;.+gecko.+firefox/i],[[u,"Firefox OS"],d],[/(nintendo|playstation)\s([wids3portablevu]+)/i,/(mint)[\/\s\(]?(\w+)*/i,/(mageia|vectorlinux)[;\s]/i,/(joli|[kxln]?ubuntu|debian|[open]*suse|gentoo|arch|slackware|fedora|mandriva|centos|pclinuxos|redhat|zenwalk|linpus)[\/\s-]?([\w\.-]+)*/i,/(hurd|linux)\s?([\w\.]+)*/i,/(gnu)\s?([\w\.]+)*/i],[u,d],[/(cros)\s[\w]+\s([\w\.]+\w)/i],[[u,"Chromium OS"],d],[/(sunos)\s?([\w\.]+\d)*/i],[[u,"Solaris"],d],[/\s([frentopc-]{0,4}bsd|dragonfly)\s?([\w\.]+)*/i],[u,d],[/(ip[honead]+)(?:.*os\s*([\w]+)*\slike\smac|;\sopera)/i],[[u,"iOS"],[d,/_/g,"."]],[/(mac\sos\sx)\s?([\w\s\.]+\w)*/i,/(macintosh|mac(?=_powerpc)\s)/i],[[u,"Mac OS"],[d,/_/g,"."]],[/((?:open)?solaris)[\/\s-]?([\w\.]+)*/i,/(haiku)\s(\w+)/i,/(aix)\s((\d)(?=\.|\)|\s)[\w\.]*)*/i,/(plan\s9|minix|beos|os\/2|amigaos
 |morphos|risc\sos|openvms)/i,/(unix)\s?([\w\.]+)*/i],[u,d]]},E=function(e){var n=e||(window&&window.navigator&&window.navigator.userAgent?window.navigator.userAgent:t);this.getBrowser=function(){return v.rgx.apply(this,y.browser)},this.getEngine=function(){return v.rgx.apply(this,y.engine)},this.getOS=function(){return v.rgx.apply(this,y.os)},this.getResult=function(){return{ua:this.getUA(),browser:this.getBrowser(),engine:this.getEngine(),os:this.getOS()}},this.getUA=function(){return n},this.setUA=function(e){return n=e,this},this.setUA(n)};return E}(),i=function(){var t={define_property:function(){return!1}(),create_canvas:function(){var e=document.createElement("canvas");return!(!e.getContext||!e.getContext("2d"))}(),return_response_type:function(t){try{if(-1!==e.inArray(t,["","text","document"]))return!0;if(window.XMLHttpRequest){var n=new XMLHttpRequest;if(n.open("get","/"),"responseType
 "in n)return n.responseType=t,n.responseType!==t?!1:!0}}catch(i){}return!1},use_data_uri:function(){var e=new Image;return e.onload=function(){t.use_data_uri=1===e.width&&1===e.height},setTimeout(function(){e.src="data:image/gif;base64,R0lGODlhAQABAIAAAP8AAAAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw=="},1),!1}(),use_data_uri_over32kb:function(){return t.use_data_uri&&("IE"!==o.browser||o.version>=9)},use_data_uri_of:function(e){return t.use_data_uri&&33e3>e||t.use_data_uri_over32kb()},use_fileinput:function(){if(navigator.userAgent.match(/(Android (1.0|1.1|1.5|1.6|2.0|2.1))|(Windows Phone (OS 7|8.0))|(XBLWP)|(ZuneWP)|(w(eb)?OSBrowser)|(webOS)|(Kindle\/(1.0|2.0|2.5|3.0))/))return!1;var e=document.createElement("input");return e.setAttribute("type","file"),!e.disabled}};return function(n){var i=[].slice.call(arguments);return i.shift(),"function"===e.typeOf(t[n])?t[n].apply(this,i):!!t[n]}}(),r=(n
 ew n).getResult(),o={can:i,uaParser:n,browser:r.browser.name,version:r.browser.version,os:r.os.name,osVersion:r.os.version,verComp:t,swf_url:"../flash/Moxie.swf",xap_url:"../silverlight/Moxie.xap",global_event_dispatcher:"moxie.core.EventTarget.instance.dispatchEvent"};return o.OS=o.os,o}),i(l,[u],function(e){var t={};return{addI18n:function(n){return e.extend(t,n)},translate:function(e){return t[e]||e},_:function(e){return this.translate(e)},sprintf:function(t){var n=[].slice.call(arguments,1);return t.replace(/%[a-z]/g,function(){var t=n.shift();return"undefined"!==e.typeOf(t)?t:""})}}}),i(d,[u,l],function(e,t){var n="application/msword,doc dot,application/pdf,pdf,application/pgp-signature,pgp,application/postscript,ps ai eps,application/rtf,rtf,application/vnd.ms-excel,xls xlb,application/vnd.ms-powerpoint,ppt pps pot,application/zip,zip,application/x-shockwave-flash,swf swfl,application/vnd.openxmlformats-officedocument.word
 processingml.document,docx,application/vnd.openxmlformats-officedocument.wordprocessingml.template,dotx,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,xlsx,application/vnd.openxmlformats-officedocument.presentationml.presentation,pptx,application/vnd.openxmlformats-officedocument.presentationml.template,potx,application/vnd.openxmlformats-officedocument.presentationml.slideshow,ppsx,application/x-javascript,js,application/json,json,audio/mpeg,mp3 mpga mpega mp2,audio/x-wav,wav,audio/x-m4a,m4a,audio/ogg,oga ogg,audio/aiff,aiff aif,audio/flac,flac,audio/aac,aac,audio/ac3,ac3,audio/x-ms-wma,wma,image/bmp,bmp,image/gif,gif,image/jpeg,jpg jpeg jpe,image/photoshop,psd,image/png,png,image/svg+xml,svg svgz,image/tiff,tiff tif,text/plain,asc txt text diff log,text/html,htm html xhtml,text/css,css,text/csv,csv,text/rtf,rtf,video/mpeg,mpeg mpg mpe m2v,video/quicktime,qt mov,video/mp4,mp4,video/x-m4v,m4v,video/x-flv,flv,video/x-ms-wmv,wmv,video/avi,avi,video/webm,webm,video/3
 gpp,3gpp 3gp,video/3gpp2,3g2,video/vnd.rn-realvideo,rv,video/ogg,ogv,video/x-matroska,mkv,application/vnd.oasis.opendocument.formula-template,otf,application/octet-stream,exe",i={mimes:{},extensions:{},addMimeType:function(e){var t=e.split(/,/),n,i,r;for(n=0;n<t.length;n+=2){for(r=t[n+1].split(/ /),i=0;i<r.length;i++)this.mimes[r[i]]=t[n];this.extensions[t[n]]=r}},extList2mimes:function(t,n){var i=this,r,o,a,s,u=[];for(o=0;o<t.length;o++)for(r=t[o].extensions.split(/\s*,\s*/),a=0;a<r.length;a++){if("*"===r[a])return[];if(s=i.mimes[r[a]],s&&-1===e.inArray(s,u)&&u.push(s),n&&/^\w+$/.test(r[a]))u.push("."+r[a]);else if(!s)return[]}return u},mimes2exts:function(t){var n=this,i=[];return e.each(t,function(t){if("*"===t)return i=[],!1;var r=t.match(/^(\w+)\/(\*|\w+)$/);r&&("*"===r[2]?e.each(n.extensions,function(e,t){new RegExp("^"+r[1]+"/").test(t)&&[].push.apply(i,n.exten
 sions[t])}):n.extensions[t]&&[].push.apply(i,n.extensions[t]))}),i},mimes2extList:function(n){var i=[],r=[];return"string"===e.typeOf(n)&&(n=e.trim(n).split(/\s*,\s*/)),r=this.mimes2exts(n),i.push({title:t.translate("Files"),extensions:r.length?r.join(","):"*"}),i.mimes=n,i},getFileExtension:function(e){var t=e&&e.match(/\.([^.]+)$/);return t?t[1].toLowerCase():""},getFileMime:function(e){return this.mimes[this.getFileExtension(e)]||""}};return i.addMimeType(n),i}),i(h,[c],function(e){var t=function(e){return"string"!=typeof e?e:document.getElementById(e)},n=function(e,t){if(!e.className)return!1;var n=new RegExp("(^|\\s+)"+t+"(\\s+|$)");return n.test(e.className)},i=function(e,t){n(e,t)||(e.className=e.className?e.className.replace(/\s+$/,"")+" "+t:t)},r=function(e,t){if(e.className){var n=new RegExp("(^|\\s+)"+t+"(\\s+|$)");e.cla
 ssName=e.className.replace(n,function(e,t,n){return" "===t&&" "===n?" ":""})}},o=function(e,t){return e.currentStyle?e.currentStyle[t]:window.getComputedStyle?window.getComputedStyle(e,null)[t]:void 0},a=function(t,n){function i(e){var t,n,i=0,r=0;return e&&(n=e.getBoundingClientRect(),t="CSS1Compat"===s.compatMode?s.documentElement:s.body,i=n.left+t.scrollLeft,r=n.top+t.scrollTop),{x:i,y:r}}var r=0,o=0,a,s=document,u,c;if(t=t,n=n||s.body,t&&t.getBoundingClientRect&&"IE"===e.browser&&(!s.documentMode||s.documentMode<8))return u=i(t),c=i(n),{x:u.x-c.x,y:u.y-c.y};for(a=t;a&&a!=n&&a.nodeType;)r+=a.offsetLeft||0,o+=a.offsetTop||0,a=a.offsetParent;for(a=t.parentNode;a&&a!=n&&a.nodeType;)r-=a.scrollLeft||0,o-=a.scrollTop||0,a=a.parentNode;return{x:r,y:o}},s=function(e){return{w:e.offsetWidth||e.clientWidth,h:e.offsetHeight||e.clientHeight}};return{get:t,ha
 sClass:n,addClass:i,removeClass:r,getStyle:o,getPos:a,getSize:s}}),i(f,[u],function(e){function t(e,t){var n;for(n in e)if(e[n]===t)return n;return null}return{RuntimeError:function(){function n(e){this.code=e,this.name=t(i,e),this.message=this.name+": RuntimeError "+this.code}var i={NOT_INIT_ERR:1,NOT_SUPPORTED_ERR:9,JS_ERR:4};return e.extend(n,i),n.prototype=Error.prototype,n}(),OperationNotAllowedException:function(){function t(e){this.code=e,this.name="OperationNotAllowedException"}return e.extend(t,{NOT_ALLOWED_ERR:1}),t.prototype=Error.prototype,t}(),ImageError:function(){function n(e){this.code=e,this.name=t(i,e),this.message=this.name+": ImageError "+this.code}var i={WRONG_FORMAT:1,MAX_RESOLUTION_ERR:2,INVALID_META_ERR:3};return e.extend(n,i),n.prototype=Error.prototype,n}(),FileException:function(){function n(e){this.code=e,this.name=t(i,e),this.message=this.name+": FileException "+this.code}var i={NOT_FOUND_ERR:1,SECURITY_ERR:2,ABORT
 _ERR:3,NOT_READABLE_ERR:4,ENCODING_ERR:5,NO_MODIFICATION_ALLOWED_ERR:6,INVALID_STATE_ERR:7,SYNTAX_ERR:8};return e.extend(n,i),n.prototype=Error.prototype,n}(),DOMException:function(){function n(e){this.code=e,this.name=t(i,e),this.message=this.name+": DOMException "+this.code}var i={INDEX_SIZE_ERR:1,DOMSTRING_SIZE_ERR:2,HIERARCHY_REQUEST_ERR:3,WRONG_DOCUMENT_ERR:4,INVALID_CHARACTER_ERR:5,NO_DATA_ALLOWED_ERR:6,NO_MODIFICATION_ALLOWED_ERR:7,NOT_FOUND_ERR:8,NOT_SUPPORTED_ERR:9,INUSE_ATTRIBUTE_ERR:10,INVALID_STATE_ERR:11,SYNTAX_ERR:12,INVALID_MODIFICATION_ERR:13,NAMESPACE_ERR:14,INVALID_ACCESS_ERR:15,VALIDATION_ERR:16,TYPE_MISMATCH_ERR:17,SECURITY_ERR:18,NETWORK_ERR:19,ABORT_ERR:20,URL_MISMATCH_ERR:21,QUOTA_EXCEEDED_ERR:22,TIMEOUT_ERR:23,INVALID_NODE_TYPE_ERR:24,DATA_CLONE_ERR:25};return e.extend(n,i),n.prototype=Error.prototype,n}(),EventException:function(){function t(e){this.code=e,this.name="EventException"}return e.extend(t,{UNSPECIFIED_EVENT_TYPE_ERR:0}),t.prot
 otype=Error.prototype,t}()}}),i(p,[c,f,u],function(e,t,n){function i(){var e={};n.extend(this,{uid:null,init:function(){this.uid||(this.uid=n.guid("uid_"))},addEventListener:function(t,i,r,o){var a=this,s;return this.hasOwnProperty("uid")||(this.uid=n.guid("uid_")),t=n.trim(t),/\s/.test(t)?void n.each(t.split(/\s+/),function(e){a.addEventListener(e,i,r,o)}):(t=t.toLowerCase(),r=parseInt(r,10)||0,s=e[this.uid]&&e[this.uid][t]||[],s.push({fn:i,priority:r,scope:o||this}),e[this.uid]||(e[this.uid]={}),void(e[this.uid][t]=s))},hasEventListener:function(t){var n=t?e[this.uid]&&e[this.uid][t]:e[this.uid];return n?n:!1},removeEventListener:function(t,i){t=t.toLowerCase();var r=e[this.uid]&&e[this.uid][t],o;if(r){if(i){for(o=r.length-1;o>=0;o--)if(r[o].fn===i){r.splice(o,1);break}}else r=[];r.length||(delete e[this.uid][t],n.isEmptyObj(e[this.uid])&&delete e[this.uid])}},removeAllEventListeners:function(){e[this.uid]&&d
 elete e[this.uid]},dispatchEvent:function(i){var r,o,a,s,u={},c=!0,l;if("string"!==n.typeOf(i)){if(s=i,"string"!==n.typeOf(s.type))throw new t.EventException(t.EventException.UNSPECIFIED_EVENT_TYPE_ERR);i=s.type,s.total!==l&&s.loaded!==l&&(u.total=s.total,u.loaded=s.loaded),u.async=s.async||!1}if(-1!==i.indexOf("::")?!function(e){r=e[0],i=e[1]}(i.split("::")):r=this.uid,i=i.toLowerCase(),o=e[r]&&e[r][i]){o.sort(function(e,t){return t.priority-e.priority}),a=[].slice.call(arguments),a.shift(),u.type=i,a.unshift(u);var d=[];n.each(o,function(e){a[0].target=e.scope,d.push(u.async?function(t){setTimeout(function(){t(e.fn.apply(e.scope,a)===!1)},1)}:function(t){t(e.fn.apply(e.scope,a)===!1)})}),d.length&&n.inSeries(d,function(e){c=!e})}return c},bind:function(){this.addEventListener.apply(this,arguments)},unbind:function(){this.removeEventListener.apply(this,arguments)},unbindAll:function(){this.removeAllEventListene
 rs.apply(this,arguments)},trigger:function(){return this.dispatchEvent.apply(this,arguments)},handleEventProps:function(e){var t=this;this.bind(e.join(" "),function(e){var t="on"+e.type.toLowerCase();"function"===n.typeOf(this[t])&&this[t].apply(this,arguments)}),n.each(e,function(e){e="on"+e.toLowerCase(e),"undefined"===n.typeOf(t[e])&&(t[e]=null)})}})}return i.instance=new i,i}),i(m,[c,u,h,p],function(e,t,n,i){function r(e,i,o,s,u){var c=this,l,d=t.guid(i+"_"),h=u||"browser";e=e||{},a[d]=this,o=t.extend({access_binary:!1,access_image_binary:!1,display_media:!1,do_cors:!1,drag_and_drop:!1,filter_by_extension:!0,resize_image:!1,report_upload_progress:!1,return_response_headers:!1,return_response_type:!1,return_status_code:!0,send_custom_headers:!1,select_file:!1,select_folder:!1,select_multiple:!0,send_binary_string:!1,send_browser_cookies:!0,send_multipart:!0,slice_blob:!1,stream_upload:!1,summon_
 file_dialog:!1,upload_filesize:!0,use_http_method:!0},o),e.preferred_caps&&(h=r.getMode(s,e.preferred_caps,h)),l=function(){var e={};return{exec:function(t,n,i,r){return l[n]&&(e[t]||(e[t]={context:this,instance:new l[n]}),e[t].instance[i])?e[t].instance[i].apply(this,r):void 0},removeInstance:function(t){delete e[t]},removeAllInstances:function(){var n=this;t.each(e,function(e,i){"function"===t.typeOf(e.instance.destroy)&&e.instance.destroy.call(e.context),n.removeInstance(i)})}}}(),t.extend(this,{initialized:!1,uid:d,type:i,mode:r.getMode(s,e.required_caps,h),shimid:d+"_container",clients:0,options:e,can:function(e,n){var i=arguments[2]||o;if("string"===t.typeOf(e)&&"undefined"===t.typeOf(n)&&(e=r.parseCaps(e)),"object"===t.typeOf(e)){for(var a in e)if(!this.can(a,e[a],i))return!1;return!0}return"function"===t.typeOf(i[e])?i[e].call(this,n):n===i[e]},getShimContainer:function(){var 
 e,i=n.get(this.shimid);return i||(e=this.options.container?n.get(this.options.container):document.body,i=document.createElement("div"),i.id=this.shimid,i.className="moxie-shim moxie-shim-"+this.type,t.extend(i.style,{position:"absolute",top:"0px",left:"0px",width:"1px",height:"1px",overflow:"hidden"}),e.appendChild(i),e=null),i},getShim:function(){return l},shimExec:function(e,t){var n=[].slice.call(arguments,2);return c.getShim().exec.call(this,this.uid,e,t,n)},exec:function(e,t){var n=[].slice.call(arguments,2);return c[e]&&c[e][t]?c[e][t].apply(this,n):c.shimExec.apply(this,arguments)},destroy:function(){if(c){var e=n.get(this.shimid);e&&e.parentNode.removeChild(e),l&&l.removeAllInstances(),this.unbindAll(),delete a[this.uid],this.uid=null,d=c=l=e=null}}}),this.mode&&e.required_caps&&!this.can(e.required_caps)&&(this.mode=!1)}var o={},a={};return r.order
 ="html5,flash,silverlight,html4",r.getRuntime=function(e){return a[e]?a[e]:!1},r.addConstructor=function(e,t){t.prototype=i.instance,o[e]=t},r.getConstructor=function(e){return o[e]||null},r.getInfo=function(e){var t=r.getRuntime(e);return t?{uid:t.uid,type:t.type,mode:t.mode,can:function(){return t.can.apply(t,arguments)}}:null},r.parseCaps=function(e){var n={};return"string"!==t.typeOf(e)?e||{}:(t.each(e.split(","),function(e){n[e]=!0}),n)},r.can=function(e,t){var n,i=r.getConstructor(e),o;return i?(n=new i({required_caps:t}),o=n.mode,n.destroy(),!!o):!1},r.thatCan=function(e,t){var n=(t||r.order).split(/\s*,\s*/);for(var i in n)if(r.can(n[i],e))return n[i];return null},r.getMode=function(e,n,i){var r=null;if("undefined"===t.typeOf(i)&&(i="browser"),n&&!t.isEmptyObj(e)){if(t.each(n,function(n,i){if(e.hasOwnProperty(i)){var o=e[i](n);if("string"==typeof o&&(o=[o]),r){if(!(r=t.arrayIntersect(r,o)))re
 turn r=!1}else r=o}}),r)return-1!==t.inArray(i,r)?i:r[0];if(r===!1)return!1}return i},r.capTrue=function(){return!0},r.capFalse=function(){return!1},r.capTest=function(e){return function(){return!!e}},r}),i(g,[c,f,u,m],function(e,t,n,i){return function r(){var e;n.extend(this,{connectRuntime:function(r){function o(n){var s,u;return n.length?(s=n.shift().toLowerCase(),(u=i.getConstructor(s))?(e=new u(r),e.bind("Init",function(){e.initialized=!0,setTimeout(function(){e.clients++,a.trigger("RuntimeInit",e)},1)}),e.bind("Error",function(){e.destroy(),o(n)}),e.mode?void e.init():void e.trigger("Error")):void o(n)):(a.trigger("RuntimeError",new t.RuntimeError(t.RuntimeError.NOT_INIT_ERR)),void(e=null))}var a=this,s;if("string"===n.typeOf(r)?s=r:"string"===n.typeOf(r.ruid)&&(s=r.ruid),s){if(e=i.getRuntime(s))return e.clients++,e;throw new t.RuntimeError(t.RuntimeError.NOT_INIT_ERR)}o((r.runtime_order||i.order).sp
 lit(/\s*,\s*/))},disconnectRuntime:function(){e&&--e.clients<=0&&e.destroy(),e=null},getRuntime:function(){return e&&e.uid?e:e=null},exec:function(){return e?e.exec.apply(this,arguments):null}})}}),i(v,[u,c,d,h,f,p,l,m,g],function(e,t,n,i,r,o,a,s,u){function c(t){var o=this,c,d,h;if(-1!==e.inArray(e.typeOf(t),["string","node"])&&(t={browse_button:t}),d=i.get(t.browse_button),!d)throw new r.DOMException(r.DOMException.NOT_FOUND_ERR);h={accept:[{title:a.translate("All Files"),extensions:"*"}],name:"file",multiple:!1,required_caps:!1,container:d.parentNode||document.body},t=e.extend({},h,t),"string"==typeof t.required_caps&&(t.required_caps=s.parseCaps(t.required_caps)),"string"==typeof t.accept&&(t.accept=n.mimes2extList(t.accept)),c=i.get(t.container),c||(c=document.body),"static"===i.getStyle(c,"position")&&(c.style.position="relat
 ive"),c=d=null,u.call(o),e.extend(o,{uid:e.guid("uid_"),ruid:null,shimid:null,files:null,init:function(){o.bind("RuntimeInit",function(n,r){o.ruid=r.uid,o.shimid=r.shimid,o.bind("Ready",function(){o.trigger("Refresh")},999),o.bind("Refresh",function(){var n,o,a,s;a=i.get(t.browse_button),s=i.get(r.shimid),a&&(n=i.getPos(a,i.get(t.container)),o=i.getSize(a),s&&e.extend(s.style,{top:n.y+"px",left:n.x+"px",width:o.w+"px",height:o.h+"px"})),s=a=null}),r.exec.call(o,"FileInput","init",t)}),o.connectRuntime(e.extend({},t,{required_caps:{select_file:!0}}))},disable:function(t){var n=this.getRuntime();n&&n.exec.call(this,"FileInput","disable","undefined"===e.typeOf(t)?!0:t)},refresh:function(){o.trigger("Refresh")},destroy:function(){var t=this.getRuntime();t&&(t.exec.call(this,"FileInput","d
 estroy"),this.disconnectRuntime()),"array"===e.typeOf(this.files)&&e.each(this.files,function(e){e.destroy()}),this.files=null,this.unbindAll()}}),this.handleEventProps(l)}var l=["ready","change","cancel","mouseenter","mouseleave","mousedown","mouseup"];return c.prototype=o.instance,c}),i(w,[],function(){var e=function(e){return unescape(encodeURIComponent(e))},t=function(e){return decodeURIComponent(escape(e))},n=function(e,n){if("function"==typeof window.atob)return n?t(window.atob(e)):window.atob(e);var i="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",r,o,a,s,u,c,l,d,h=0,f=0,p="",m=[];if(!e)return e;e+="";do s=i.indexOf(e.charAt(h++)),u=i.indexOf(e.charAt(h++)),c=i.indexOf(e.charAt(h++)),l=i.indexOf(e.charAt(h++)),d=s<<18|u<<12|c<<6|l,r=d>>16&255,o=d>>8&255,a=255&d,64==c?m[f++]=String.fr
 omCharCode(r):64==l?m[f++]=String.fromCharCode(r,o):m[f++]=String.fromCharCode(r,o,a);while(h<e.length);return p=m.join(""),n?t(p):p},i=function(t,n){if(n&&(t=e(t)),"function"==typeof window.btoa)return window.btoa(t);var i="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",r,o,a,s,u,c,l,d,h=0,f=0,p="",m=[];if(!t)return t;do r=t.charCodeAt(h++),o=t.charCodeAt(h++),a=t.charCodeAt(h++),d=r<<16|o<<8|a,s=d>>18&63,u=d>>12&63,c=d>>6&63,l=63&d,m[f++]=i.charAt(s)+i.charAt(u)+i.charAt(c)+i.charAt(l);while(h<t.length);p=m.join("");var g=t.length%3;return(g?p.slice(0,g-3):p)+"===".slice(g||3)};return{utf8_encode:e,utf8_decode:t,atob:n,btoa:i}}),i(y,[u,w,g],function(e,t,n){function i(o,a){function s(t,n,o){var a,s=r[this.uid];return"string"===e.typeOf(s)&&s.length?(a=new i(null,{type:o,size:n-t}),a.detach(s.substr(t,a.size)),a):null}n.call(th
 is),o&&this.connectRuntime(o),a?"string"===e.typeOf(a)&&(a={data:a}):a={},e.extend(this,{uid:a.uid||e.guid("uid_"),ruid:o,size:a.size||0,type:a.type||"",slice:function(e,t,n){return this.isDetached()?s.apply(this,arguments):this.getRuntime().exec.call(this,"Blob","slice",this.getSource(),e,t,n)},getSource:function(){return r[this.uid]?r[this.uid]:null},detach:function(e){if(this.ruid&&(this.getRuntime().exec.call(this,"Blob","destroy"),this.disconnectRuntime(),this.ruid=null),e=e||"","data:"==e.substr(0,5)){var n=e.indexOf(";base64,");this.type=e.substring(5,n),e=t.atob(e.substring(n+8))}this.size=e.length,r[this.uid]=e},isDetached:function(){return!this.ruid&&"string"===e.typeOf(r[this.uid])},destroy:function(){this.detach(),delete r[this.uid]}}),a.data?this.detach(a.data):r[this.uid]=a}var r={};return i}),i(E,[u,d,y],function(e,t,n){function
  i(i,r){r||(r={}),n.apply(this,arguments),this.type||(this.type=t.getFileMime(r.name));var o;if(r.name)o=r.name.replace(/\\/g,"/"),o=o.substr(o.lastIndexOf("/")+1);else if(this.type){var a=this.type.split("/")[0];o=e.guid((""!==a?a:"file")+"_"),t.extensions[this.type]&&(o+="."+t.extensions[this.type][0])}e.extend(this,{name:o||e.guid("file_"),relativePath:"",lastModifiedDate:r.lastModifiedDate||(new Date).toLocaleString()})}return i.prototype=n.prototype,i}),i(_,[l,h,f,u,c,E,g,p,d],function(e,t,n,i,r,o,a,s,u){function c(n){var r=this,o;"string"==typeof n&&(n={drop_zone:n}),o={accept:[{title:e.translate("All Files"),extensions:"*"}],required_caps:{drag_and_drop:!0}},n="object"==typeof n?i.extend({},o,n):o,n.container=t.get(n.drop_zone)||document.body,"static"===t.getStyle(n.container,"position")&&(n.container.sty
 le.position="relative"),"string"==typeof n.accept&&(n.accept=u.mimes2extList(n.accept)),a.call(r),i.extend(r,{uid:i.guid("uid_"),ruid:null,files:null,init:function(){r.bind("RuntimeInit",function(e,t){r.ruid=t.uid,t.exec.call(r,"FileDrop","init",n),r.dispatchEvent("ready")}),r.connectRuntime(n)},destroy:function(){var e=this.getRuntime();e&&(e.exec.call(this,"FileDrop","destroy"),this.disconnectRuntime()),this.files=null,this.unbindAll()}}),this.handleEventProps(l)}var l=["ready","dragenter","dragleave","drop","error"];return c.prototype=s.instance,c}),i(b,[u,w,f,p,y,g],function(e,t,n,i,r,o){function a(){function i(e,i){var o=this;if(this.trigger("loadstart"),this.readyState===a.LOADING)return this.trigger("error",new n.DOMException(n.DOMException.INVALID_STATE_ERR)),void this.trigger("loadend");if(!
 (i instanceof r))return this.trigger("error",new n.DOMException(n.DOMException.NOT_FOUND_ERR)),void this.trigger("loadend");if(this.result=null,this.readyState=a.LOADING,i.isDetached()){var s=i.getSource();switch(e){case"readAsText":case"readAsBinaryString":this.result=s;break;case"readAsDataURL":this.result="data:"+i.type+";base64,"+t.btoa(s)}this.readyState=a.DONE,this.trigger("load"),this.trigger("loadend")}else this.connectRuntime(i.ruid),this.exec("FileReader","read",e,i)}o.call(this),e.extend(this,{uid:e.guid("uid_"),readyState:a.EMPTY,result:null,error:null,readAsBinaryString:function(e){i.call(this,"readAsBinaryString",e)},readAsDataURL:function(e){i.call(this,"readAsDataURL",e)},readAsText:function(e){i.call(this,"readAsText",e);
-},abort:function(){this.result=null,-1===e.inArray(this.readyState,[a.EMPTY,a.DONE])&&(this.readyState===a.LOADING&&(this.readyState=a.DONE),this.exec("FileReader","abort"),this.trigger("abort"),this.trigger("loadend"))},destroy:function(){this.abort(),this.exec("FileReader","destroy"),this.disconnectRuntime(),this.unbindAll()}}),this.handleEventProps(s),this.bind("Error",function(e,t){this.readyState=a.DONE,this.error=t},999),this.bind("Load",function(e){this.readyState=a.DONE},999)}var s=["loadstart","progress","load","abort","error","loadend"];return a.EMPTY=0,a.LOADING=1,a.DONE=2,a.prototype=i.instance,a}),i(x,[],function(){var e=function(t,n){for(var i=["source","scheme","authority","userInfo","user","pass","host","port","relative",&quo
 t;path","directory","file","query","fragment"],r=i.length,o={http:80,https:443},a={},s=/^(?:([^:\/?#]+):)?(?:\/\/()(?:(?:()(?:([^:@\/]*):?([^:@\/]*))?@)?([^:\/?#]*)(?::(\d*))?))?()(?:(()(?:(?:[^?#\/]*\/)*)()(?:[^?#]*))(?:\\?([^#]*))?(?:#(.*))?)/,u=s.exec(t||"");r--;)u[r]&&(a[i[r]]=u[r]);if(!a.scheme){n&&"string"!=typeof n||(n=e(n||document.location.href)),a.scheme=n.scheme,a.host=n.host,a.port=n.port;var c="";/^[^\/]/.test(a.path)&&(c=n.path,c=/\/[^\/]*\.[^\/]*$/.test(c)?c.replace(/\/[^\/]+$/,"/"):c.replace(/\/?$/,"/")),a.path=c+(a.path||"")}return a.port||(a.port=o[a.scheme]||80),a.port=parseInt(a.port,10),a.path||(a.path="/"),delete a.source,a},t=function(t){var n={http:80,https:443},i="object"==typeof t?t:e(t);return i.scheme+"://"+i.host+(i.port!==n[i.scheme]?":"+i.port:"")+i.path+(i.query?i.query:&quot
 ;")},n=function(t){function n(e){return[e.scheme,e.host,e.port].join("/")}return"string"==typeof t&&(t=e(t)),n(e())===n(t)};return{parseUrl:e,resolveUrl:t,hasSameOrigin:n}}),i(R,[u,g,p],function(e,t,n){function i(){this.uid=e.guid("uid_"),t.call(this),this.destroy=function(){this.disconnectRuntime(),this.unbindAll()}}return i.prototype=n.instance,i}),i(A,[u,g,w],function(e,t,n){return function(){function i(e,t){if(!t.isDetached()){var i=this.connectRuntime(t.ruid).exec.call(this,"FileReaderSync","read",e,t);return this.disconnectRuntime(),i}var r=t.getSource();switch(e){case"readAsBinaryString":return r;case"readAsDataURL":return"data:"+t.type+";base64,"+n.btoa(r);case"readAsText":for(var o="",a=0,s=r.length;s>a;a++)o+=String.fromCharCode(r[a]);return o}}t.call(this),e.extend(this,{uid:e.guid("uid_"),readAsBinaryString:function(e){return i.call(this
 ,"readAsBinaryString",e)},readAsDataURL:function(e){return i.call(this,"readAsDataURL",e)},readAsText:function(e){return i.call(this,"readAsText",e)}})}}),i(I,[f,u,y],function(e,t,n){function i(){var e,i=[];t.extend(this,{append:function(r,o){var a=this,s=t.typeOf(o);o instanceof n?e={name:r,value:o}:"array"===s?(r+="[]",t.each(o,function(e){a.append(r,e)})):"object"===s?t.each(o,function(e,t){a.append(r+"["+t+"]",e)}):"null"===s||"undefined"===s||"number"===s&&isNaN(o)?a.append(r,"false"):i.push({name:r,value:o.toString()})},hasBlob:function(){return!!this.getBlob()},getBlob:function(){return e&&e.value||null},getBlobName:function(){return e&&e.name||null},each:function(n){t.each(i,function(e){n(e.value,e.name)}),e&&n(e.value,e.name)},destroy:function(){e=null,i=[]}})}return i}),i(T,[u,f,p,w,x,m,R,y,A,I,c,d],function(e,t,n,i,r,o,a,s
 ,u,c,l,d){function h(){this.uid=e.guid("uid_")}function f(){function n(e,t){return w.hasOwnProperty(e)?1===arguments.length?l.can("define_property")?w[e]:v[e]:void(l.can("define_property")?w[e]=t:v[e]=t):void 0}function u(t){function i(){B&&(B.destroy(),B=null),s.dispatchEvent("loadend"),s=null}function r(r){B.bind("LoadStart",function(e){n("readyState",f.LOADING),s.dispatchEvent("readystatechange"),s.dispatchEvent(e),O&&s.upload.dispatchEvent(e)}),B.bind("Progress",function(e){n("readyState")!==f.LOADING&&(n("readyState",f.LOADING),s.dispatchEvent("readystatechange")),s.dispatchEvent(e)}),B.bind("UploadProgress",function(e){O&&s.upload.dispatchEvent({type:"progress",lengthComputable:!1,total:e.total,loaded:e.loaded})}),B.bind("Load",function(t){n("readyState",f.DONE),n("status",Number(r.exec.c
 all(B,"XMLHttpRequest","getStatus")||0)),n("statusText",p[n("status")]||""),n("response",r.exec.call(B,"XMLHttpRequest","getResponse",n("responseType"))),~e.inArray(n("responseType"),["text",""])?n("responseText",n("response")):"document"===n("responseType")&&n("responseXML",n("response")),k=r.exec.call(B,"XMLHttpRequest","getAllResponseHeaders"),s.dispatchEvent("readystatechange"),n("status")>0?(O&&s.upload.dispatchEvent(t),s.dispatchEvent(t)):(N=!0,s.dispatchEvent("error")),i()}),B.bind("Abort",function(e){s.dispatchEvent(e),i()}),B.bind("Error",function(e){N=!0,n("readyState",f.DONE),s.dispatchEvent("readystatechange"),D=!0,s.dispatchEvent(e),i()}),r.exec.call(B,"XMLHttpRequest","s
 end",{url:E,method:_,async:y,user:x,password:R,headers:b,mimeType:I,encoding:A,responseType:s.responseType,withCredentials:s.withCredentials,options:H},t)}var s=this;C=(new Date).getTime(),B=new a,"string"==typeof H.required_caps&&(H.required_caps=o.parseCaps(H.required_caps)),H.required_caps=e.extend({},H.required_caps,{return_response_type:s.responseType}),t instanceof c&&(H.required_caps.send_multipart=!0),e.isEmptyObj(b)||(H.required_caps.send_custom_headers=!0),L||(H.required_caps.do_cors=!0),H.ruid?r(B.connectRuntime(H)):(B.bind("RuntimeInit",function(e,t){r(t)}),B.bind("RuntimeError",function(e,t){s.dispatchEvent("RuntimeError",t)}),B.connectRuntime(H))}function g(){n("responseText",""),n("responseXML",null),n("response",null),n("status",0),n("statusText",""),C=M=null}var v=this,w={timeout:0,readyState:f.UNSENT,withCredentials:!1,status:0,statusTe
 xt:"",responseType:"",responseXML:null,responseText:null,response:null},y=!0,E,_,b={},x,R,A=null,I=null,T=!1,S=!1,O=!1,D=!1,N=!1,L=!1,C,M,F=null,P=null,H={},B,k="",U;e.extend(this,w,{uid:e.guid("uid_"),upload:new h,open:function(o,a,s,u,c){var l;if(!o||!a)throw new t.DOMException(t.DOMException.SYNTAX_ERR);if(/[\u0100-\uffff]/.test(o)||i.utf8_encode(o)!==o)throw new t.DOMException(t.DOMException.SYNTAX_ERR);if(~e.inArray(o.toUpperCase(),["CONNECT","DELETE","GET","HEAD","OPTIONS","POST","PUT","TRACE","TRACK"])&&(_=o.toUpperCase()),~e.inArray(_,["CONNECT","TRACE","TRACK"]))throw new t.DOMException(t.DOMException.SECURITY_ERR);if(a=i.utf8_encode(a),l=r.parseUrl(a),L=r.hasSameOrigin(l),E=r.resolveUrl(a),(u||c)&&!L)throw new t.DOMException(t.DOMException.INVALID_ACCESS_ERR);if(x=u||l.user,R=c||l.pass,y=s||!0,y===!1
 &&(n("timeout")||n("withCredentials")||""!==n("responseType")))throw new t.DOMException(t.DOMException.INVALID_ACCESS_ERR);T=!y,S=!1,b={},g.call(this),n("readyState",f.OPENED),this.dispatchEvent("readystatechange")},setRequestHeader:function(r,o){var a=["accept-charset","accept-encoding","access-control-request-headers","access-control-request-method","connection","content-length","cookie","cookie2","content-transfer-encoding","date","expect","host","keep-alive","origin","referer","te","trailer","transfer-encoding","upgrade","user-agent","via"];if(n("readyState")!==f.OPENED||S)throw new t.DOMException(t.DOMException.INVALID_STATE_ERR);if(/[\u0100-\uffff]/.test(r)||i.utf8_encode(r)!==r)throw new t.DOM
 Exception(t.DOMException.SYNTAX_ERR);return r=e.trim(r).toLowerCase(),~e.inArray(r,a)||/^(proxy\-|sec\-)/.test(r)?!1:(b[r]?b[r]+=", "+o:b[r]=o,!0)},getAllResponseHeaders:function(){return k||""},getResponseHeader:function(t){return t=t.toLowerCase(),N||~e.inArray(t,["set-cookie","set-cookie2"])?null:k&&""!==k&&(U||(U={},e.each(k.split(/\r\n/),function(t){var n=t.split(/:\s+/);2===n.length&&(n[0]=e.trim(n[0]),U[n[0].toLowerCase()]={header:n[0],value:e.trim(n[1])})})),U.hasOwnProperty(t))?U[t].header+": "+U[t].value:null},overrideMimeType:function(i){var r,o;if(~e.inArray(n("readyState"),[f.LOADING,f.DONE]))throw new t.DOMException(t.DOMException.INVALID_STATE_ERR);if(i=e.trim(i.toLowerCase()),/;/.test(i)&&(r=i.match(/^([^;]+)(?:;\scharset\=)?(.*)$/))&&(i=r[1],r[2]&&(o=r[2])),!d.mimes[i])throw new t.DOMException(t.DOMException.SYNTAX_ERR);F=i,P=o},send:function(n,r){if
 (H="string"===e.typeOf(r)?{ruid:r}:r?r:{},this.readyState!==f.OPENED||S)throw new t.DOMException(t.DOMException.INVALID_STATE_ERR);if(n instanceof s)H.ruid=n.ruid,I=n.type||"application/octet-stream";else if(n instanceof c){if(n.hasBlob()){var o=n.getBlob();H.ruid=o.ruid,I=o.type||"application/octet-stream"}}else"string"==typeof n&&(A="UTF-8",I="text/plain;charset=UTF-8",n=i.utf8_encode(n));this.withCredentials||(this.withCredentials=H.required_caps&&H.required_caps.send_browser_cookies&&!L),O=!T&&this.upload.hasEventListener(),N=!1,D=!n,T||(S=!0),u.call(this,n)},abort:function(){if(N=!0,T=!1,~e.inArray(n("readyState"),[f.UNSENT,f.OPENED,f.DONE]))n("readyState",f.UNSENT);else{if(n("readyState",f.DONE),S=!1,!B)throw new t.DOMException(t.DOMException.INVALID_STATE_ERR);B.getRuntime().exec.call(B,"XMLHttpRequest","abort",D),D=!0}},destroy:functio
 n(){B&&("function"===e.typeOf(B.destroy)&&B.destroy(),B=null),this.unbindAll(),this.upload&&(this.upload.unbindAll(),this.upload=null)}}),this.handleEventProps(m.concat(["readystatechange"])),this.upload.handleEventProps(m)}var p={100:"Continue",101:"Switching Protocols",102:"Processing",200:"OK",201:"Created",202:"Accepted",203:"Non-Authoritative Information",204:"No Content",205:"Reset Content",206:"Partial Content",207:"Multi-Status",226:"IM Used",300:"Multiple Choices",301:"Moved Permanently",302:"Found",303:"See Other",304:"Not Modified",305:"Use Proxy",306:"Reserved",307:"Temporary Redirect",400:"Bad Request",401:"Unauthorized",402:"Payment Required",403:"Forbidden",404:"Not Found",405:&q
 uot;Method Not Allowed",406:"Not Acceptable",407:"Proxy Authentication Required",408:"Request Timeout",409:"Conflict",410:"Gone",411:"Length Required",412:"Precondition Failed",413:"Request Entity Too Large",414:"Request-URI Too Long",415:"Unsupported Media Type",416:"Requested Range Not Satisfiable",417:"Expectation Failed",422:"Unprocessable Entity",423:"Locked",424:"Failed Dependency",426:"Upgrade Required",500:"Internal Server Error",501:"Not Implemented",502:"Bad Gateway",503:"Service Unavailable",504:"Gateway Timeout",505:"HTTP Version Not Supported",506:"Variant Also Negotiates",507:"Insufficient Storage",510:"Not Extended"};h.prototype=n.instance;var m=["loadstart","progress","abort","error
 ","load","timeout","loadend"],g=1,v=2;return f.UNSENT=0,f.OPENED=1,f.HEADERS_RECEIVED=2,f.LOADING=3,f.DONE=4,f.prototype=n.instance,f}),i(S,[u,w,g,p],function(e,t,n,i){function r(){function i(){l=d=0,c=this.result=null}function o(t,n){var i=this;u=n,i.bind("TransportingProgress",function(t){d=t.loaded,l>d&&-1===e.inArray(i.state,[r.IDLE,r.DONE])&&a.call(i)},999),i.bind("TransportingComplete",function(){d=l,i.state=r.DONE,c=null,i.result=u.exec.call(i,"Transporter","getAsBlob",t||"")},999),i.state=r.BUSY,i.trigger("TransportingStarted"),a.call(i)}function a(){var e=this,n,i=l-d;h>i&&(h=i),n=t.btoa(c.substr(d,h)),u.exec.call(e,"Transporter","receive",n,l)}var s,u,c,l,d,h;n.call(this),e.extend(this,{uid:e.guid("uid_"),state:r.IDLE,result:null,transport:function(t,n,r){var a=this;if(r=e.extend({chunk_size:204798},r),(s=r.chunk_size%3)
 &&(r.chunk_size+=3-s),h=r.chunk_size,i.call(this),c=t,l=t.length,"string"===e.typeOf(r)||r.ruid)o.call(a,n,this.connectRuntime(r));else{var u=function(e,t){a.unbind("RuntimeInit",u),o.call(a,n,t)};this.bind("RuntimeInit",u),this.connectRuntime(r)}},abort:function(){var e=this;e.state=r.IDLE,u&&(u.exec.call(e,"Transporter","clear"),e.trigger("TransportingAborted")),i.call(e)},destroy:function(){this.unbindAll(),u=null,this.disconnectRuntime(),i.call(this)}})}return r.IDLE=0,r.BUSY=1,r.DONE=2,r.prototype=i.instance,r}),i(O,[u,h,f,A,T,m,g,S,c,p,y,E,w],function(e,t,n,i,r,o,a,s,u,c,l,d,h){function f(){function i(e){e||(e=this.exec("Image","getInfo")),this.size=e.size,this.width=e.width,this.height=e.height,this.type=e.type,this.meta=e.meta,""===this.name&&(this.name=e.name)}function c(t){var i=e.typeOf(t);try{if(t instanceof f){if(!t.size)throw new n.DOMException(n.DOMExcepti
 on.INVALID_STATE_ERR);m.apply(this,arguments)}else if(t instanceof l){if(!~e.inArray(t.type,["image/jpeg","image/png"]))throw new n.ImageError(n.ImageError.WRONG_FORMAT);g.apply(this,arguments)}else if(-1!==e.inArray(i,["blob","file"]))c.call(this,new d(null,t),arguments[1]);else if("string"===i)"data:"===t.substr(0,5)?c.call(this,new l(null,{data:t}),arguments[1]):v.apply(this,arguments);else{if("node"!==i||"img"!==t.nodeName.toLowerCase())throw new n.DOMException(n.DOMException.TYPE_MISMATCH_ERR);c.call(this,t.src,arguments[1])}}catch(r){this.trigger("error",r.code)}}function m(t,n){var i=this.connectRuntime(t.ruid);this.ruid=i.uid,i.exec.call(this,"Image","loadFromImage",t,"undefined"===e.typeOf(n)?!0:n)}function g(t,n){function i(e){r.ruid=e.uid,e.exec.call(r,"Image","loadFromBlob",t)}var r=this;r.name=t.name||"",t.isDetached()?(th
 is.bind("RuntimeInit",function(e,t){i(t)}),n&&"string"==typeof n.required_caps&&(n.required_caps=o.parseCaps(n.required_caps)),this.connectRuntime(e.extend({required_caps:{access_image_binary:!0,resize_image:!0}},n))):i(this.connectRuntime(t.ruid))}function v(e,t){var n=this,i;i=new r,i.open("get",e),i.responseType="blob",i.onprogress=function(e){n.trigger(e)},i.onload=function(){g.call(n,i.response,!0)},i.onerror=function(e){n.trigger(e)},i.onloadend=function(){i.destroy()},i.bind("RuntimeError",function(e,t){n.trigger("RuntimeError",t)}),i.send(null,t)}a.call(this),e.extend(this,{uid:e.guid("uid_"),ruid:null,name:"",size:0,width:0,height:0,type:"",meta:{},clone:function(){this.load.apply(this,arguments)},load:function(){c.apply(this,arguments)},downsize:function(t){var i={width:this.width,height:this.height,type:this.type||"image/jpeg",quality:90,crop:!1,preserveHead
 ers:!0,resample:!1};t="object"==typeof t?e.extend(i,t):e.extend(i,{width:arguments[0],height:arguments[1],crop:arguments[2],preserveHeaders:arguments[3]});try{if(!this.size)throw new n.DOMException(n.DOMException.INVALID_STATE_ERR);if(this.width>f.MAX_RESIZE_WIDTH||this.height>f.MAX_RESIZE_HEIGHT)throw new n.ImageError(n.ImageError.MAX_RESOLUTION_ERR);this.exec("Image","downsize",t.width,t.height,t.crop,t.preserveHeaders)}catch(r){this.trigger("error",r.code)}},crop:function(e,t,n){this.downsize(e,t,!0,n)},getAsCanvas:function(){if(!u.can("create_canvas"))throw new n.RuntimeError(n.RuntimeError.NOT_SUPPORTED_ERR);var e=this.connectRuntime(this.ruid);return e.exec.call(this,"Image","getAsCanvas")},getAsBlob:function(e,t){if(!this.size)throw new n.DOMException(n.DOMException.INVALID_STATE_ERR);return this.exec("Image","getAsBlob",e||"image/jpeg",t||90)},getAsDataURL:function(e,t){
 if(!this.size)throw new n.DOMException(n.DOMException.INVALID_STATE_ERR);return this.exec("Image","getAsDataURL",e||"image/jpeg",t||90)},getAsBinaryString:function(e,t){var n=this.getAsDataURL(e,t);return h.atob(n.substring(n.indexOf("base64,")+7))},embed:function(i,r){function o(t,r){var o=this;if(u.can("create_canvas")){var l=o.getAsCanvas();if(l)return i.appendChild(l),l=null,o.destroy(),void a.trigger("embedded")}var d=o.getAsDataURL(t,r);if(!d)throw new n.ImageError(n.ImageError.WRONG_FORMAT);if(u.can("use_data_uri_of",d.length))i.innerHTML='<img src="'+d+'" width="'+o.width+'" height="'+o.height+'" />',o.destroy(),a.trigger("embedded");else{var f=new s;f.bind("TransportingComplete",function(){c=a.connectRuntime(this.result.ruid),a.bind("Embedded",function(){e.extend(c.getShimContainer().style,{top:"0px",left:"0px",width:o.w
 idth+"px",height:o.height+"px"}),c=null},999),c.exec.call(a,"ImageView","display",this.result.uid,width,height),o.destroy()}),f.transport(h.atob(d.substring(d.indexOf("base64,")+7)),t,{required_caps:{display_media:!0},runtime_order:"flash,silverlight",container:i})}}var a=this,c;r=e.extend({width:this.width,height:this.height,type:this.type||"image/jpeg",quality:90},r||{});try{if(!(i=t.get(i)))throw new n.DOMException(n.DOMException.INVALID_NODE_TYPE_ERR);if(!this.size)throw new n.DOMException(n.DOMException.INVALID_STATE_ERR);this.width>f.MAX_RESIZE_WIDTH||this.height>f.MAX_RESIZE_HEIGHT;var l=new f;return l.bind("Resize",function(){o.call(this,r.type,r.quality)}),l.bind("Load",function(){l.downsize(r)}),this.meta.thumb&&this.meta.thumb.width>=r.width&&this.meta.thumb.height>=r.height?l.load(this.meta.thumb.data):l.clone(this,!1),l}catch(d){this.trigger("error&
 quot;,d.code)}},destroy:function(){this.ruid&&(this.getRuntime().exec.call(this,"Image","destroy"),this.disconnectRuntime()),this.unbindAll()}}),this.handleEventProps(p),this.bind("Load Resize",function(){i.call(this)},999)}var p=["progress","load","error","resize","embedded"];return f.MAX_RESIZE_WIDTH=8192,f.MAX_RESIZE_HEIGHT=8192,f.prototype=c.instance,f}),i(D,[u,f,m,c],function(e,t,n,i){function r(t){var r=this,s=n.capTest,u=n.capTrue,c=e.extend({access_binary:s(window.FileReader||window.File&&window.File.getAsDataURL),access_image_binary:function(){return r.can("access_binary")&&!!a.Image},display_media:s(i.can("create_canvas")||i.can("use_data_uri_over32kb")),do_cors:s(window.XMLHttpRequest&&"withCredentials"in new XMLHttpRequest),drag_and_drop:s(function(){var e=document.createElement("div");return("draggable&quo
 t;in e||"ondragstart"in e&&"ondrop"in e)&&("IE"!==i.browser||i.verComp(i.version,9,">"))}()),filter_by_extension:s(function(){return"Chrome"===i.browser&&i.verComp(i.version,28,">=")||"IE"===i.browser&&i.verComp(i.version,10,">=")||"Safari"===i.browser&&i.verComp(i.version,7,">=")}()),return_response_headers:u,return_response_type:function(e){return"json"===e&&window.JSON?!0:i.can("return_response_type",e)},return_status_code:u,report_upload_progress:s(window.XMLHttpRequest&&(new XMLHttpRequest).upload),resize_image:function(){return r.can("access_binary")&&i.can("create_canvas")},select_file:function(){return i.can("use_fileinput")&&window.File},select_folder:function(){return r.can("select_file")&&"Chrome"===i.browser&&
 amp;i.verComp(i.version,21,">=")},select_multiple:function(){return!(!r.can("select_file")||"Safari"===i.browser&&"Windows"===i.os||"iOS"===i.os&&i.verComp(i.osVersion,"7.0.0",">")&&i.verComp(i.osVersion,"8.0.0","<"))},send_binary_string:s(window.XMLHttpRequest&&((new XMLHttpRequest).sendAsBinary||window.Uint8Array&&window.ArrayBuffer)),send_custom_headers:s(window.XMLHttpRequest),send_multipart:function(){return!!(window.XMLHttpRequest&&(new XMLHttpRequest).upload&&window.FormData)||r.can("send_binary_string")},slice_blob:s(window.File&&(File.prototype.mozSlice||File.prototype.webkitSlice||File.prototype.slice)),stream_upload:function(){return r.can("slice_blob")&&r.can("send_multipart")},summon_file_dialog:function(){return r.can("select_file")&&("Firefox"
 ===i.browser&&i.verComp(i.version,4,">=")||"Opera"===i.browser&&i.verComp(i.version,12,">=")||"IE"===i.browser&&i.verComp(i.version,10,">=")||!!~e.inArray(i.browser,["Chrome","Safari"]))},upload_filesize:u},arguments[2]);n.call(this,t,arguments[1]||o,c),e.extend(this,{init:function(){this.trigger("Init")},destroy:function(e){return function(){e.call(r),e=r=null}}(this.destroy)}),e.extend(this.getShim(),a)}var o="html5",a={};return n.addConstructor(o,r),a}),i(N,[u],function(e){function t(){this.returnValue=!1}function n(){this.cancelBubble=!0}var i={},r="moxie_"+e.guid(),o=function(o,a,s,u){var c,l;a=a.toLowerCase(),o.addEventListener?(c=s,o.addEventListener(a,c,!1)):o.attachEvent&&(c=function(){var e=window.event;e.target||(e.target=e.srcElement),e.preventDefault=t,e.stopPropagation=n,s(e)},o.attachEvent("on"+a,c)),o[r]||(o[r]=e.guid(
 )),i.hasOwnProperty(o[r])||(i[o[r]]={}),l=i[o[r]],l.hasOwnProperty(a)||(l[a]=[]),l[a].push({func:c,orig:s,key:u})},a=function(t,n,o){var a,s;if(n=n.toLowerCase(),t[r]&&i[t[r]]&&i[t[r]][n]){a=i[t[r]][n];for(var u=a.length-1;u>=0&&(a[u].orig!==o&&a[u].key!==o||(t.removeEventListener?t.removeEventListener(n,a[u].func,!1):t.detachEvent&&t.detachEvent("on"+n,a[u].func),a[u].orig=null,a[u].func=null,a.splice(u,1),o===s));u--);if(a.length||delete i[t[r]][n],e.isEmptyObj(i[t[r]])){delete i[t[r]];try{delete t[r]}catch(c){t[r]=s}}}},s=function(t,n){t&&t[r]&&e.each(i[t[r]],function(e,i){a(t,i,n)})};return{addEvent:o,removeEvent:a,removeAllEvents:s}}),i(L,[D,E,u,h,N,d,c],function(e,t,n,i,r,o,a){function s(){var e;n.extend(this,{init:function(s){var u=this,c=u.getRuntime(),l,d,h,f,p,m;e=s,h=e.accept.mimes||o.extList2mimes(e.accept,c.can("filter_by_extension")),d=c.getShimContainer(),d.innerHTML='<input id="'+c
 .uid+'" type="file" style="font-size:999px;opacity:0;"'+(e.multiple&&c.can("select_multiple")?"multiple":"")+(e.directory&&c.can("select_folder")?"webkitdirectory directory":"")+(h?' accept="'+h.join(",")+'"':"")+" />",l=i.get(c.uid),n.extend(l.style,{position:"absolute",top:0,left:0,width:"100%",height:"100%"}),f=i.get(e.browse_button),c.can("summon_file_dialog")&&("static"===i.getStyle(f,"position")&&(f.style.position="relative"),p=parseInt(i.getStyle(f,"z-index"),10)||1,f.style.zIndex=p,d.style.zIndex=p-1,r.addEvent(f,"click",function(e){var t=i.get(c.uid);t&&!t.disabled&&t.click(),e.preventDefault()},u.uid)),m=c.can("summon_file_dialog")?f:d,r.addEvent(m,"mouseover",function(){u.trigger("mouse
 enter")},u.uid),r.addEvent(m,"mouseout",function(){u.trigger("mouseleave")},u.uid),r.addEvent(m,"mousedown",function(){u.trigger("mousedown")},u.uid),r.addEvent(i.get(e.container),"mouseup",function(){u.trigger("mouseup")},u.uid),l.onchange=function g(i){if(u.files=[],n.each(this.files,function(n){var i="";return e.directory&&"."==n.name?!0:(n.webkitRelativePath&&(i="/"+n.webkitRelativePath.replace(/^\//,"")),n=new t(c.uid,n),n.relativePath=i,void u.files.push(n))}),"IE"!==a.browser&&"IEMobile"!==a.browser)this.value="";else{var r=this.cloneNode(!0);this.parentNode.replaceChild(r,this),r.onchange=g}u.files.length&&u.trigger("change")},u.trigger({type:"ready",async:!0}),d=null},disable:function(e){var t=this.getRuntime(),n;(n=i.get(t.uid))&&(n.disabled=!!e)},destroy:function(){var t=this.getR
 untime(),n=t.getShim(),o=t.getShimContainer();r.removeAllEvents(o,this.uid),r.removeAllEvents(e&&i.get(e.container),this.uid),r.removeAllEvents(e&&i.get(e.browse_button),this.uid),o&&(o.innerHTML=""),n.removeInstance(this.uid),e=o=n=null}})}return e.FileInput=s}),i(C,[D,y],function(e,t){function n(){function e(e,t,n){var i;if(!window.File.prototype.slice)return(i=window.File.prototype.webkitSlice||window.File.prototype.mozSlice)?i.call(e,t,n):null;try{return e.slice(),e.slice(t,n)}catch(r){return e.slice(t,n-t)}}this.slice=function(){return new t(this.getRuntime().uid,e.apply(this,arguments))}}return e.Blob=n}),i(M,[D,E,u,h,N,d],function(e,t,n,i,r,o){function a(){function e(e){if(!e.dataTransfer||!e.dataTransfer.types)return!1;var t=n.toArray(e.dataTransfer.types||[]);return-1!==n.inArray("Files",t)||-1!==n.inArray("public.file-url",t)||-1!==n.inArray("application/x-moz-file",t)}function a(e,n){if(u(e)){var i=new t(g,e)
 ;i.relativePath=n||"",f.push(i)}}function s(e){for(var t=[],i=0;i<e.length;i++)[].push.apply(t,e[i].extensions.split(/\s*,\s*/));return-1===n.inArray("*",t)?t:[]}function u(e){if(!p.length)return!0;var t=o.getFileExtension(e.name);return!t||-1!==n.inArray(t,p)}function c(e,t){var i=[];n.each(e,function(e){var t=e.webkitGetAsEntry();t&&(t.isFile?a(e.getAsFile(),t.fullPath):i.push(t))}),i.length?l(i,t):t()}function l(e,t){var i=[];n.each(e,function(e){i.push(function(t){d(e,t)})}),n.inSeries(i,function(){t()})}function d(e,t){e.isFile?e.file(function(n){a(n,e.fullPath),t()},function(){t()}):e.isDirectory?h(e,t):t()}function h(e,t){function n(e){r.readEntries(function(t){t.length?([].push.apply(i,t),n(e)):e()},e)}var i=[],r=e.createReader();n(function(){l(i,t)})}var f=[],p=[],m,g;n.extend(this,{init:function(t){var i=this,o;m=t,g=i.ruid,p=s(m.accept),o=m.container,r.addEvent(o,"dragover",function(t){e(t)&&(t.preventDefault(),t.dataTransf
 er.dropEffect="copy")},i.uid),r.addEvent(o,"drop",function(t){e(t)&&(t.preventDefault(),f=[],t.dataTransfer.items&&t.dataTransfer.items[0].webkitGetAsEntry?c(t.dataTransfer.items,function(){i.files=f,i.trigger("drop")}):(n.each(t.dataTransfer.files,function(e){a(e)}),i.files=f,i.trigger("drop")))},i.uid),r.addEvent(o,"dragenter",function(e){i.trigger("dragenter")},i.uid),r.addEvent(o,"dragleave",function(e){i.trigger("dragleave")},i.uid)},destroy:function(){r.removeAllEvents(m&&i.get(m.container),this.uid),g=f=p=m=null}})}return e.FileDrop=a}),i(F,[D,w,u],function(e,t,n){function i(){function e(e){return t.atob(e.substring(e.indexOf("base64,")+7))}var i,r=!1;n.extend(this,{read:function(t,o){var a=this;a.result="",i=new window.FileReader,i.addEventListener("progress",function(e){a.trigger(e)}),i.addEventListener("load",function(t){a.result=r
 ?e(i.result):i.result,a.trigger(t)}),i.addEventListener("error",function(e){a.trigger(e,i.error)}),i.addEventListener("loadend",function(e){i=null,a.trigger(e)}),"function"===n.typeOf(i[t])?(r=!1,i[t](o.getSource())):"readAsBinaryString"===t&&(r=!0,i.readAsDataURL(o.getSource()))},abort:function(){i&&i.abort()},destroy:function(){i=null}})}return e.FileReader=i}),i(P,[D,u,d,x,E,y,I,f,c],function(e,t,n,i,r,o,a,s,u){function c(){function e(e,t){var n=this,i,r;i=t.getBlob().getSource(),r=new window.FileReader,r.onload=function(){t.append(t.getBlobName(),new o(null,{type:i.type,data:r.result})),h.send.call(n,e,t)},r.readAsBinaryString(i)}function c(){return!window.XMLHttpRequest||"IE"===u.browser&&u.verComp(u.version,8,"<")?function(){for(var e=["Msxml2.XMLHTTP.6.0","Microsoft.XMLHTTP"],t=0;t<e.length;t++)try{return new ActiveXObject(e[t])}catch(n){}}():new window.XMLHttpRequest
 }function l(e){var t=e.responseXML,n=e.responseText;return"IE"===u.browser&&n&&t&&!t.documentElement&&/[^\/]+\/[^\+]+\+xml/.test(e.getResponseHeader("Content-Type"))&&(t=new window.ActiveXObject("Microsoft.XMLDOM"),t.async=!1,t.validateOnParse=!1,t.loadXML(n)),t&&("IE"===u.browser&&0!==t.parseError||!t.documentElement||"parsererror"===t.documentElement.tagName)?null:t}function d(e){var t="----moxieboundary"+(new Date).getTime(),n="--",i="\r\n",r="",a=this.getRuntime();if(!a.can("send_binary_string"))throw new s.RuntimeError(s.RuntimeError.NOT_SUPPORTED_ERR);return f.setRequestHeader("Content-Type","multipart/form-data; boundary="+t),e.each(function(e,a){r+=e instanceof o?n+t+i+'Content-Disposition: form-data; name="'+a+'"; filename="'+unescape(encodeURIComponent(e.name||"blob"))+'&quot
 ;'+i+"Content-Type: "+(e.type||"application/octet-stream")+i+i+e.getSource()+i:n+t+i+'Content-Disposition: form-data; name="'+a+'"'+i+i+unescape(encodeURIComponent(e))+i}),r+=n+t+n+i}var h=this,f,p;t.extend(this,{send:function(n,r){var s=this,l="Mozilla"===u.browser&&u.verComp(u.version,4,">=")&&u.verComp(u.version,7,"<"),h="Android Browser"===u.browser,m=!1;if(p=n.url.replace(/^.+?\/([\w\-\.]+)$/,"$1").toLowerCase(),f=c(),f.open(n.method,n.url,n.async,n.user,n.password),r instanceof o)r.isDetached()&&(m=!0),r=r.getSource();else if(r instanceof a){if(r.hasBlob())if(r.getBlob().isDetached())r=d.call(s,r),m=!0;else if((l||h)&&"blob"===t.typeOf(r.getBlob().getSource())&&window.FileReader)return void e.call(s,n,r);if(r instanceof a){var g=new window.FormData;r.each(function(e,t){e instanceof o?g.append(t,e.getSource()):g.append(t,e)}),r=g}}f.upload?(n.w
 ithCredentials&&(f.withCredentials=!0),f.addEventListener("load",function(e){s.trigger(e)}),f.addEventListener("error",function(e){s.trigger(e)}),f.addEventListener("progress",function(e){s.trigger(e)}),f.upload.addEventListener("progress",function(e){s.trigger({type:"UploadProgress",loaded:e.loaded,total:e.total})})):f.onreadystatechange=function v(){switch(f.readyState){case 1:break;case 2:break;case 3:var e,t;try{i.hasSameOrigin(n.url)&&(e=f.getResponseHeader("Content-Length")||0),f.responseText&&(t=f.responseText.length)}catch(r){e=t=0}s.trigger({type:"progress",lengthComputable:!!e,total:parseInt(e,10),loaded:t});break;case 4:f.onreadystatechange=function(){},s.trigger(0===f.status?"error":"load")}},t.isEmptyObj(n.headers)||t.each(n.headers,function(e,t){f.setRequestHeader(t,e)}),""!==n.responseType&&"responseType"in f&&("jso
 n"!==n.responseType||u.can("return_response_type","json")?f.responseType=n.responseType:f.responseType="text"),m?f.sendAsBinary?f.sendAsBinary(r):!function(){for(var e=new Uint8Array(r.length),t=0;t<r.length;t++)e[t]=255&r.charCodeAt(t);f.send(e.buffer)}():f.send(r),s.trigger("loadstart")},getStatus:function(){try{if(f)return f.status}catch(e){}return 0},getResponse:function(e){var t=this.getRuntime();try{switch(e){case"blob":var i=new r(t.uid,f.response),o=f.getResponseHeader("Content-Disposition");if(o){var a=o.match(/filename=([\'\"'])([^\1]+)\1/);a&&(p=a[2])}return i.name=p,i.type||(i.type=n.getFileMime(p)),i;case"json":return u.can("return_response_type","json")?f.response:200===f.status&&window.JSON?JSON.parse(f.responseText):null;case"document":return l(f);default:return""!==f.responseText?f.responseText:null}}catch(s){return null}},ge
 tAllResponseHeaders:function(){try{return f.getAllResponseHeaders()}catch(e){}return""},abort:function(){f&&f.abort()},destroy:function(){h=p=null}})}return e.XMLHttpRequest=c}),i(H,[u],function(e){function t(e){e instanceof ArrayBuffer?n.apply(this,arguments):i.apply(this,arguments)}function n(t){var n=new DataView(t);e.extend(this,{readByteAt:function(e){return n.getUint8(e)},writeByteAt:function(e,t){n.setUint8(e,t)},SEGMENT:function(e,i,r){switch(arguments.length){case 2:return t.slice(e,e+i);case 1:return t.slice(e);case 3:if(null===r&&(r=new ArrayBuffer),r instanceof ArrayBuffer){var o=new Uint8Array(this.length()-i+r.byteLength);e>0&&o.set(new Uint8Array(t.slice(0,e)),0),o.set(new Uint8Array(r),e),o.set(new Uint8Array(t.slice(e+i)),e+r.byteLength),this.clear(),t=o.buffer,n=new DataView(t);break}default:return t}},length:function(){return t?t.byteLength:0},clear:function(){n=t=null}})}function i(t){function n(e,n,i){i=3===arguments.length?i
 :t.length-n-1,t=t.substr(0,n)+e+t.substr(i+n)}e.extend(this,{readByteAt:function(e){return t.charCodeAt(e)},writeByteAt:function(e,t){n(String.fromCharCode(t),e,1)},SEGMENT:function(e,i,r){switch(arguments.length){case 1:return t.substr(e);case 2:return t.substr(e,i);case 3:n(null!==r?r:"",e,i);break;default:return t}},length:function(){return t?t.length:0},clear:function(){t=null}})}return e.extend(t.prototype,{littleEndian:!1,read:function(e,t){var n,i,r;if(e+t>this.length())throw new Error("You are trying to read outside the source boundaries.");for(i=this.littleEndian?0:-8*(t-1),r=0,n=0;t>r;r++)n|=this.readByteAt(e+r)<<Math.abs(i+8*r);return n},write:function(e,t,n){var i,r,o="";if(e>this.length())throw new Error("You are trying to write outside the source boundaries.");for(i=this.littleEndian?0:-8*(n-1),r=0;n>r;r++)this.writeByteAt(e+r,t>>Math.abs(i+8*r)&255)},BYTE:function(e){return this.read(e,1)},SHORT:funct
 ion(e){return this.read(e,2)},LONG:function(e){return this.read(e,4)},SLONG:function(e){var t=this.read(e,4);return t>2147483647?t-4294967296:t},CHAR:function(e){return String.fromCharCode(this.read(e,1))},STRING:function(e,t){return this.asArray("CHAR",e,t).join("")},asArray:function(e,t,n){for(var i=[],r=0;n>r;r++)i[r]=this[e](t+r);return i}}),t}),i(B,[H,f],function(e,t){return function n(i){var r=[],o,a,s,u=0;if(o=new e(i),65496!==o.SHORT(0))throw o.clear(),new t.ImageError(t.ImageError.WRONG_FORMAT);for(a=2;a<=o.length();)if(s=o.SHORT(a),s>=65488&&65495>=s)a+=2;else{if(65498===s||65497===s)break;u=o.SHORT(a+2)+2,s>=65505&&65519>=s&&r.push({hex:s,name:"APP"+(15&s),start:a,length:u,segment:o.SEGMENT(a,u)}),a+=u}return o.clear(),{headers:r,restore:function(t){var n,i,o;for(o=new e(t),a=65504==o.SHORT(2)?4+o.SHORT(4):2,i=0,n=r.length;n>i;i++)o.SEGMENT(a,0,r[i].segment),a+=r[i].length;return t=o.SEGMENT
 (),o.clear(),t},strip:function(t){var i,r,o,a;for(o=new n(t),r=o.headers,o.purge(),i=new e(t),a=r.length;a--;)i.SEGMENT(r[a].start,r[a].length,"");return t=i.SEGMENT(),i.clear(),t},get:function(e){for(var t=[],n=0,i=r.length;i>n;n++)r[n].name===e.toUpperCase()&&t.push(r[n].segment);return t},
-set:function(e,t){var n=[],i,o,a;for("string"==typeof t?n.push(t):n=t,i=o=0,a=r.length;a>i&&(r[i].name===e.toUpperCase()&&(r[i].segment=n[o],r[i].length=n[o].length,o++),!(o>=n.length));i++);},purge:function(){this.headers=r=[]}}}}),i(k,[u,H,f],function(e,n,i){function r(o){function a(n,r){var o=this,a,s,u,c,h,f,p,m,g=[],v={},w={1:"BYTE",7:"UNDEFINED",2:"ASCII",3:"SHORT",4:"LONG",5:"RATIONAL",9:"SLONG",10:"SRATIONAL"},y={BYTE:1,UNDEFINED:1,ASCII:1,SHORT:2,LONG:4,RATIONAL:8,SLONG:4,SRATIONAL:8};for(a=o.SHORT(n),s=0;a>s;s++)if(g=[],p=n+2+12*s,u=r[o.SHORT(p)],u!==t){if(c=w[o.SHORT(p+=2)],h=o.LONG(p+=2),f=y[c],!f)throw new i.ImageError(i.ImageError.INVALID_META_ERR);if(p+=4,f*h>4&&(p=o.LONG(p)+d.tiffHeader),p+f*h>=this.length())throw new i.ImageError(i.ImageError.INVALID_META_ERR);"ASCII"!==c?(g=o.asArray(c,p,h),m=1==h?g[0]:g,l.hasOwnProperty(u)&
 &"object"!=typeof m?v[u]=l[u][m]:v[u]=m):v[u]=e.trim(o.STRING(p,h).replace(/\0$/,""))}return v}function s(e,t,n){var i,r,o,a=0;if("string"==typeof t){var s=c[e.toLowerCase()];for(var u in s)if(s[u]===t){t=u;break}}i=d[e.toLowerCase()+"IFD"],r=this.SHORT(i);for(var l=0;r>l;l++)if(o=i+12*l+2,this.SHORT(o)==t){a=o+8;break}if(!a)return!1;try{this.write(a,n,4)}catch(h){return!1}return!0}var u,c,l,d,h,f;if(n.call(this,o),c={tiff:{274:"Orientation",270:"ImageDescription",271:"Make",272:"Model",305:"Software",34665:"ExifIFDPointer",34853:"GPSInfoIFDPointer"},exif:{36864:"ExifVersion",40961:"ColorSpace",40962:"PixelXDimension",40963:"PixelYDimension",36867:"DateTimeOriginal",33434:"ExposureTime",33437:"FNumber",34855:"ISOSpeedRatings",37377:"ShutterSpeedValue",37378:"ApertureValue&qu
 ot;,37383:"MeteringMode",37384:"LightSource",37385:"Flash",37386:"FocalLength",41986:"ExposureMode",41987:"WhiteBalance",41990:"SceneCaptureType",41988:"DigitalZoomRatio",41992:"Contrast",41993:"Saturation",41994:"Sharpness"},gps:{0:"GPSVersionID",1:"GPSLatitudeRef",2:"GPSLatitude",3:"GPSLongitudeRef",4:"GPSLongitude"},thumb:{513:"JPEGInterchangeFormat",514:"JPEGInterchangeFormatLength"}},l={ColorSpace:{1:"sRGB",0:"Uncalibrated"},MeteringMode:{0:"Unknown",1:"Average",2:"CenterWeightedAverage",3:"Spot",4:"MultiSpot",5:"Pattern",6:"Partial",255:"Other"},LightSource:{1:"Daylight",2:"Fliorescent",3:"Tungsten",4:"Flash",9:"Fine weather",10:"Cloudy weather&quo
 t;,11:"Shade",12:"Daylight fluorescent (D 5700 - 7100K)",13:"Day white fluorescent (N 4600 -5400K)",14:"Cool white fluorescent (W 3900 - 4500K)",15:"White fluorescent (WW 3200 - 3700K)",17:"Standard light A",18:"Standard light B",19:"Standard light C",20:"D55",21:"D65",22:"D75",23:"D50",24:"ISO studio tungsten",255:"Other"},Flash:{0:"Flash did not fire",1:"Flash fired",5:"Strobe return light not detected",7:"Strobe return light detected",9:"Flash fired, compulsory flash mode",13:"Flash fired, compulsory flash mode, return light not detected",15:"Flash fired, compulsory flash mode, return light detected",16:"Flash did not fire, compulsory flash mode",24:"Flash did not fire, auto mode",25:"Flash fired, auto mode",29:"Flash fired, auto mode, ret
 urn light not detected",31:"Flash fired, auto mode, return light detected",32:"No flash function",65:"Flash fired, red-eye reduction mode",69:"Flash fired, red-eye reduction mode, return light not detected",71:"Flash fired, red-eye reduction mode, return light detected",73:"Flash fired, compulsory flash mode, red-eye reduction mode",77:"Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected",79:"Flash fired, compulsory flash mode, red-eye reduction mode, return light detected",89:"Flash fired, auto mode, red-eye reduction mode",93:"Flash fired, auto mode, return light not detected, red-eye reduction mode",95:"Flash fired, auto mode, return light detected, red-eye reduction mode"},ExposureMode:{0:"Auto exposure",1:"Manual exposure",2:"Auto bracket"},WhiteBalance:{0:"Auto white balance",1:"Manual 
 white balance"},SceneCaptureType:{0:"Standard",1:"Landscape",2:"Portrait",3:"Night scene"},Contrast:{0:"Normal",1:"Soft",2:"Hard"},Saturation:{0:"Normal",1:"Low saturation",2:"High saturation"},Sharpness:{0:"Normal",1:"Soft",2:"Hard"},GPSLatitudeRef:{N:"North latitude",S:"South latitude"},GPSLongitudeRef:{E:"East longitude",W:"West longitude"}},d={tiffHeader:10},h=d.tiffHeader,u={clear:this.clear},e.extend(this,{read:function(){try{return r.prototype.read.apply(this,arguments)}catch(e){throw new i.ImageError(i.ImageError.INVALID_META_ERR)}},write:function(){try{return r.prototype.write.apply(this,arguments)}catch(e){throw new i.ImageError(i.ImageError.INVALID_META_ERR)}},UNDEFINED:function(){return this.BYTE.apply(this,arguments)},RATIONAL:function(e){return this.LONG(e)/this.LONG(e+4)},SRATIONAL:function(e){re
 turn this.SLONG(e)/this.SLONG(e+4)},ASCII:function(e){return this.CHAR(e)},TIFF:function(){return f||null},EXIF:function(){var t=null;if(d.exifIFD){try{t=a.call(this,d.exifIFD,c.exif)}catch(n){return null}if(t.ExifVersion&&"array"===e.typeOf(t.ExifVersion)){for(var i=0,r="";i<t.ExifVersion.length;i++)r+=String.fromCharCode(t.ExifVersion[i]);t.ExifVersion=r}}return t},GPS:function(){var t=null;if(d.gpsIFD){try{t=a.call(this,d.gpsIFD,c.gps)}catch(n){return null}t.GPSVersionID&&"array"===e.typeOf(t.GPSVersionID)&&(t.GPSVersionID=t.GPSVersionID.join("."))}return t},thumb:function(){if(d.IFD1)try{var e=a.call(this,d.IFD1,c.thumb);if("JPEGInterchangeFormat"in e)return this.SEGMENT(d.tiffHeader+e.JPEGInterchangeFormat,e.JPEGInterchangeFormatLength)}catch(t){}return null},setExif:function(e,t){return"PixelXDimension"!==e&&"PixelYDimension"!==e?!1:s.call(this,"exif",e,t)},clear:
 function(){u.clear(),o=c=l=f=d=u=null}}),65505!==this.SHORT(0)||"EXIF\x00"!==this.STRING(4,5).toUpperCase())throw new i.ImageError(i.ImageError.INVALID_META_ERR);if(this.littleEndian=18761==this.SHORT(h),42!==this.SHORT(h+=2))throw new i.ImageError(i.ImageError.INVALID_META_ERR);d.IFD0=d.tiffHeader+this.LONG(h+=2),f=a.call(this,d.IFD0,c.tiff),"ExifIFDPointer"in f&&(d.exifIFD=d.tiffHeader+f.ExifIFDPointer,delete f.ExifIFDPointer),"GPSInfoIFDPointer"in f&&(d.gpsIFD=d.tiffHeader+f.GPSInfoIFDPointer,delete f.GPSInfoIFDPointer),e.isEmptyObj(f)&&(f=null);var p=this.LONG(d.IFD0+12*this.SHORT(d.IFD0)+2);p&&(d.IFD1=d.tiffHeader+p)}return r.prototype=n.prototype,r}),i(U,[u,f,B,H,k],function(e,t,n,i,r){function o(o){function a(e){var t=0,n,i;for(e||(e=c);t<=e.length();){if(n=e.SHORT(t+=2),n>=65472&&65475>=n)return t+=5,{height:e.SHORT(t),width:e.SHORT(t+=2)};i=e.SHORT(t+=2),t+=i-2}return null}function s(){var e=d.th
 umb(),t,n;return e&&(t=new i(e),n=a(t),t.clear(),n)?(n.data=e,n):null}function u(){d&&l&&c&&(d.clear(),l.purge(),c.clear(),h=l=d=c=null)}var c,l,d,h;if(c=new i(o),65496!==c.SHORT(0))throw new t.ImageError(t.ImageError.WRONG_FORMAT);l=new n(o);try{d=new r(l.get("app1")[0])}catch(f){}h=a.call(this),e.extend(this,{type:"image/jpeg",size:c.length(),width:h&&h.width||0,height:h&&h.height||0,setExif:function(t,n){return d?("object"===e.typeOf(t)?e.each(t,function(e,t){d.setExif(t,e)}):d.setExif(t,n),void l.set("app1",d.SEGMENT())):!1},writeHeaders:function(){return l.restore(arguments.length?arguments[0]:o)},stripHeaders:function(e){return l.strip(e)},purge:function(){u.call(this)}}),d&&(this.meta={tiff:d.TIFF(),exif:d.EXIF(),gps:d.GPS(),thumb:s()})}return o}),i(G,[f,u,H],function(e,t,n){function i(i){function r(){var e,t;return e=a.call(this,8),"IHDR"==e.type?(t=e.start,{width:s.LONG
 (t),height:s.LONG(t+=4)}):null}function o(){s&&(s.clear(),i=l=u=c=s=null)}function a(e){var t,n,i,r;return t=s.LONG(e),n=s.STRING(e+=4,4),i=e+=4,r=s.LONG(e+t),{length:t,type:n,start:i,CRC:r}}var s,u,c,l;s=new n(i),function(){var t=0,n=0,i=[35152,20039,3338,6666];for(n=0;n<i.length;n++,t+=2)if(i[n]!=s.SHORT(t))throw new e.ImageError(e.ImageError.WRONG_FORMAT)}(),l=r.call(this),t.extend(this,{type:"image/png",size:s.length(),width:l.width,height:l.height,purge:function(){o.call(this)}}),o.call(this)}return i}),i(z,[u,f,U,G],function(e,t,n,i){return function(r){var o=[n,i],a;a=function(){for(var e=0;e<o.length;e++)try{return new o[e](r)}catch(n){}throw new t.ImageError(t.ImageError.WRONG_FORMAT)}(),e.extend(this,{type:"",size:0,width:0,height:0,setExif:function(){},writeHeaders:function(e){return e},stripHeaders:function(e){return e},purge:function(){r=null}}),e.extend(this,a),this.purge=function(){a.purge(),a=null}}}),i(q,[],function(){function e(e,i,
 r){var o=e.naturalWidth,a=e.naturalHeight,s=r.width,u=r.height,c=r.x||0,l=r.y||0,d=i.getContext("2d");t(e)&&(o/=2,a/=2);var h=1024,f=document.createElement("canvas");f.width=f.height=h;for(var p=f.getContext("2d"),m=n(e,o,a),g=0;a>g;){for(var v=g+h>a?a-g:h,w=0;o>w;){var y=w+h>o?o-w:h;p.clearRect(0,0,h,h),p.drawImage(e,-w,-g);var E=w*s/o+c<<0,_=Math.ceil(y*s/o),b=g*u/a/m+l<<0,x=Math.ceil(v*u/a/m);d.drawImage(f,0,0,y,v,E,b,_,x),w+=h}g+=h}f=p=null}function t(e){var t=e.naturalWidth,n=e.naturalHeight;if(t*n>1048576){var i=document.createElement("canvas");i.width=i.height=1;var r=i.getContext("2d");return r.drawImage(e,-t+1,0),0===r.getImageData(0,0,1,1).data[3]}return!1}function n(e,t,n){var i=document.createElement("canvas");i.width=1,i.height=n;var r=i.getContext("2d");r.drawImage(e,0,0);for(var o=r.getImageData(0,0,1,n).data,a=0,s=n,u=n;u>a;){var c=o[4*(u-1)+3];0===c?s=u:a=u,u=
 s+a>>1}i=null;var l=u/n;return 0===l?1:l}return{isSubsampled:t,renderTo:e}}),i(j,[D,u,f,w,y,E,z,q,d,c],function(e,t,n,i,r,o,a,s,u,c){function l(){function e(){if(!_&&!y)throw new n.ImageError(n.DOMException.INVALID_STATE_ERR);return _||y}function l(e){return i.atob(e.substring(e.indexOf("base64,")+7))}function d(e,t){return"data:"+(t||"")+";base64,"+i.btoa(e)}function h(e){var t=this;y=new Image,y.onerror=function(){v.call(this),t.trigger("error",n.ImageError.WRONG_FORMAT)},y.onload=function(){t.trigger("load")},y.src="data:"==e.substr(0,5)?e:d(e,x.type)}function f(e,t){var i=this,r;return window.FileReader?(r=new FileReader,r.onload=function(){t(this.result)},r.onerror=function(){i.trigger("error",n.ImageError.WRONG_FORMAT)},r.readAsDataURL(e),void 0):t(e.getAsDataURL())}function p(n,i,r,o){var a=this,s,u,c=0,l=0,d,h,f,p;if(A=o,p=this.meta&&this.meta.tiff&&this.meta.tiff.Or
 ientation||1,-1!==t.inArray(p,[5,6,7,8])){var v=n;n=i,i=v}return d=e(),r?(n=Math.min(n,d.width),i=Math.min(i,d.height),s=Math.max(n/d.width,i/d.height)):s=Math.min(n/d.width,i/d.height),s>1&&!r&&o?void this.trigger("Resize"):(_||(_=document.createElement("canvas")),h=Math.round(d.width*s),f=Math.round(d.height*s),r?(_.width=n,_.height=i,h>n&&(c=Math.round((h-n)/2)),f>i&&(l=Math.round((f-i)/2))):(_.width=h,_.height=f),A||g(_.width,_.height,p),m.call(this,d,_,-c,-l,h,f),this.width=_.width,this.height=_.height,R=!0,void a.trigger("Resize"))}function m(e,t,n,i,r,o){if("iOS"===c.OS)s.renderTo(e,t,{width:r,height:o,x:n,y:i});else{var a=t.getContext("2d");a.drawImage(e,n,i,r,o)}}function g(e,t,n){switch(n){case 5:case 6:case 7:case 8:_.width=t,_.height=e;break;default:_.width=e,_.height=t}var i=_.getContext("2d");switch(n){case 2:i.translate(e,0),i.scale(-1,1);break;case 3:i.translate(e,t),
 i.rotate(Math.PI);break;case 4:i.translate(0,t),i.scale(1,-1);break;case 5:i.rotate(.5*Math.PI),i.scale(1,-1);break;case 6:i.rotate(.5*Math.PI),i.translate(0,-t);break;case 7:i.rotate(.5*Math.PI),i.translate(e,-t),i.scale(-1,1);break;case 8:i.rotate(-.5*Math.PI),i.translate(-e,0)}}function v(){E&&(E.purge(),E=null),b=y=_=x=null,R=!1}var w=this,y,E,_,b,x,R=!1,A=!0;t.extend(this,{loadFromBlob:function(e){var t=this,i=t.getRuntime(),r=arguments.length>1?arguments[1]:!0;if(!i.can("access_binary"))throw new n.RuntimeError(n.RuntimeError.NOT_SUPPORTED_ERR);return x=e,e.isDetached()?(b=e.getSource(),void h.call(this,b)):void f.call(this,e.getSource(),function(e){r&&(b=l(e)),h.call(t,e)})},loadFromImage:function(e,t){this.meta=e.meta,x=new o(null,{name:e.name,size:e.size,type:e.type}),h.call(this,t?b=e.getAsBinaryString():e.getAsDataURL())},getInfo:function(){var t=this.getRuntime(),n;return!E&&b&&t.can("access_image_binary")&&(
 E=new a(b)),n={width:e().width||0,height:e().height||0,type:x.type||u.getFileMime(x.name),size:b&&b.length||x.size||0,name:x.name||"",meta:E&&E.meta||this.meta||{}},!n.meta||!n.meta.thumb||n.meta.thumb.data instanceof r||(n.meta.thumb.data=new r(null,{type:"image/jpeg",data:n.meta.thumb.data})),n},downsize:function(){p.apply(this,arguments)},getAsCanvas:function(){return _&&(_.id=this.uid+"_canvas"),_},getAsBlob:function(e,t){return e!==this.type&&p.call(this,this.width,this.height,!1),new o(null,{name:x.name||"",type:e,data:w.getAsBinaryString.call(this,e,t)})},getAsDataURL:function(e){var t=arguments[1]||90;if(!R)return y.src;if("image/jpeg"!==e)return _.toDataURL("image/png");try{return _.toDataURL("image/jpeg",t/100)}catch(n){return _.toDataURL("image/jpeg")}},getAsBinaryString:function(e,t){if(!R)return b||(b=l(w.getAsDataURL(e,t))),b;if("image/jpeg"!==e)b=l
 (w.getAsDataURL(e,t));else{var n;t||(t=90);try{n=_.toDataURL("image/jpeg",t/100)}catch(i){n=_.toDataURL("image/jpeg")}b=l(n),E&&(b=E.stripHeaders(b),A&&(E.meta&&E.meta.exif&&E.setExif({PixelXDimension:this.width,PixelYDimension:this.height}),b=E.writeHeaders(b)),E.purge(),E=null)}return R=!1,b},destroy:function(){w=null,v.call(this),this.getRuntime().getShim().removeInstance(this.uid)}})}return e.Image=l}),i(X,[u,c,h,f,m],function(e,t,n,i,r){function o(){var e;try{e=navigator.plugins["Shockwave Flash"],e=e.description}catch(t){try{e=new ActiveXObject("ShockwaveFlash.ShockwaveFlash").GetVariable("$version")}catch(n){e="0.0"}}return e=e.match(/\d+/g),parseFloat(e[0]+"."+e[1])}function a(e){var i=n.get(e);i&&"OBJECT"==i.nodeName&&("IE"===t.browser?(i.style.display="none",function r(){4==i.readyState?s(e):setTimeout(r,10)}()):i.parentNode.re
 moveChild(i))}function s(e){var t=n.get(e);if(t){for(var i in t)"function"==typeof t[i]&&(t[i]=null);t.parentNode.removeChild(t)}}function u(s){var u=this,d;s=e.extend({swf_url:t.swf_url},s),r.call(this,s,c,{access_binary:function(e){return e&&"browser"===u.mode},access_image_binary:function(e){return e&&"browser"===u.mode},display_media:r.capTrue,do_cors:r.capTrue,drag_and_drop:!1,report_upload_progress:function(){return"client"===u.mode},resize_image:r.capTrue,return_response_headers:!1,return_response_type:function(t){return"json"===t&&window.JSON?!0:!e.arrayDiff(t,["","text","document"])||"browser"===u.mode},return_status_code:function(t){return"browser"===u.mode||!e.arrayDiff(t,[200,404])},select_file:r.capTrue,select_multiple:r.capTrue,send_binary_string:function(e){return e&&"browser"===u.mode},send_browser_cookies:function(e){r
 eturn e&&"browser"===u.mode},send_custom_headers:function(e){return e&&"browser"===u.mode},send_multipart:r.capTrue,slice_blob:function(e){return e&&"browser"===u.mode},stream_upload:function(e){return e&&"browser"===u.mode},summon_file_dialog:!1,upload_filesize:function(t){return e.parseSizeStr(t)<=2097152||"client"===u.mode},use_http_method:function(t){return!e.arrayDiff(t,["GET","POST"])}},{access_binary:function(e){return e?"browser":"client"},access_image_binary:function(e){return e?"browser":"client"},report_upload_progress:function(e){return e?"browser":"client"},return_response_type:function(t){return e.arrayDiff(t,["","text","json","document"])?"browser":["client","browser"]},return_status_code:function(t){return e.arrayDiff(t,[200,404])?&quot
 ;browser":["client","browser"]},send_binary_string:function(e){return e?"browser":"client"},send_browser_cookies:function(e){return e?"browser":"client"},send_custom_headers:function(e){return e?"browser":"client"},stream_upload:function(e){return e?"client":"browser"},upload_filesize:function(t){return e.parseSizeStr(t)>=2097152?"client":"browser"}},"client"),o()<10&&(this.mode=!1),e.extend(this,{getShim:function(){return n.get(this.uid)},shimExec:function(e,t){var n=[].slice.call(arguments,2);return u.getShim().exec(this.uid,e,t,n)},init:function(){var n,r,o;o=this.getShimContainer(),e.extend(o.style,{position:"absolute",top:"-8px",left:"-8px",width:"9px",height:"9px",overflow:"hidden"}),n='<object id="'+this.uid+'" type="application/x-shockwave-flash" 
 data="'+s.swf_url+'" ',"IE"===t.browser&&(n+='classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" '),n+='width="100%" height="100%" style="outline:0"><param name="movie" value="'+s.swf_url+'" /><param name="flashvars" value="uid='+escape(this.uid)+"&target="+t.global_event_dispatcher+'" /><param name="wmode" value="transparent" /><param name="allowscriptaccess" value="always" /></object>',"IE"===t.browser?(r=document.createElement("div"),o.appendChild(r),r.outerHTML=n,r=o=null):o.innerHTML=n,d=setTimeout(function(){u&&!u.initialized&&u.trigger("Error",new i.RuntimeError(i.RuntimeError.NOT_INIT_ERR))},5e3)},destroy:function(e){return function(){a(u.uid),e.call(u),clearTimeout(d),s=d=e=u=null}}(this.destroy)},l)}var c="flash",l={};return
  r.addConstructor(c,u),l}),i(V,[X,E,u],function(e,t,n){var i={init:function(e){var i=this,r=this.getRuntime();this.bind("Change",function(){var e=r.shimExec.call(i,"FileInput","getFiles");i.files=[],n.each(e,function(e){i.files.push(new t(r.uid,e))})},999),this.getRuntime().shimExec.call(this,"FileInput","init",{name:e.name,accept:e.accept,multiple:e.multiple}),this.trigger("ready")}};return e.FileInput=i}),i(W,[X,y],function(e,t){var n={slice:function(e,n,i,r){var o=this.getRuntime();return 0>n?n=Math.max(e.size+n,0):n>0&&(n=Math.min(n,e.size)),0>i?i=Math.max(e.size+i,0):i>0&&(i=Math.min(i,e.size)),e=o.shimExec.call(this,"Blob","slice",n,i,r||""),e&&(e=new t(o.uid,e)),e}};return e.Blob=n}),i(Y,[X,w],function(e,t){function n(e,n){switch(n){case"readAsText":return t.atob(e,"utf8");case"readAsBinaryString":return t.atob(e);case&quo
 t;readAsDataURL":return e}return null}var i={read:function(e,t){var i=this;return i.result="","readAsDataURL"===e&&(i.result="data:"+(t.type||"")+";base64,"),i.bind("Progress",function(t,r){r&&(i.result+=n(r,e))},999),i.getRuntime().shimExec.call(this,"FileReader","readAsBase64",t.uid)}};return e.FileReader=i}),i($,[X,w],function(e,t){function n(e,n){switch(n){case"readAsText":return t.atob(e,"utf8");case"readAsBinaryString":return t.atob(e);case"readAsDataURL":return e}return null}var i={read:function(e,t){var i,r=this.getRuntime();return(i=r.shimExec.call(this,"FileReaderSync","readAsBase64",t.uid))?("readAsDataURL"===e&&(i="data:"+(t.type||"")+";base64,"+i),n(i,e,t.type)):null}};return e.FileReaderSync=i}),i(J,[X,u,y,E,A,I,S],function(e,t,n,i,r,o,a){var s={send:function(e,i)
 {function r(){e.transport=l.mode,l.shimExec.call(c,"XMLHttpRequest","send",e,i)}function s(e,t){l.shimExec.call(c,"XMLHttpRequest","appendBlob",e,t.uid),i=null,r()}function u(e,t){var n=new a;n.bind("TransportingComplete",function(){t(this.result)}),n.transport(e.getSource(),e.type,{ruid:l.uid})}var c=this,l=c.getRuntime();if(t.isEmptyObj(e.headers)||t.each(e.headers,function(e,t){l.shimExec.call(c,"XMLHttpRequest","setRequestHeader",t,e.toString())}),i instanceof o){var d;if(i.each(function(e,t){e instanceof n?d=t:l.shimExec.call(c,"XMLHttpRequest","append",t,e)}),i.hasBlob()){var h=i.getBlob();h.isDetached()?u(h,function(e){h.destroy(),s(d,e)}):s(d,h)}else i=null,r()}else i instanceof n?i.isDetached()?u(i,function(e){i.destroy(),i=e.uid,r()}):(i=i.uid,r()):r()},getResponse:function(e){var n,o,a=this.getRuntime();if(o=a.shimExec.call(this,"XMLHttpRequest","getResponseAsBlob&quot
 ;)){if(o=new i(a.uid,o),"blob"===e)return o;try{if(n=new r,~t.inArray(e,["","text"]))return n.readAsText(o);if("json"===e&&window.JSON)return JSON.parse(n.readAsText(o))}finally{o.destroy()}}return null},abort:function(e){var t=this.getRuntime();t.shimExec.call(this,"XMLHttpRequest","abort"),this.dispatchEvent("readystatechange"),this.dispatchEvent("abort")}};return e.XMLHttpRequest=s}),i(Z,[X,y],function(e,t){var n={getAsBlob:function(e){var n=this.getRuntime(),i=n.shimExec.call(this,"Transporter","getAsBlob",e);return i?new t(n.uid,i):null}};return e.Transporter=n}),i(K,[X,u,S,y,A],function(e,t,n,i,r){var o={loadFromBlob:function(e){function t(e){r.shimExec.call(i,"Image","loadFromBlob",e.uid),i=r=null}var i=this,r=i.getRuntime();if(e.isDetached()){var o=new n;o.bind("TransportingComplete",function(){t(o.result.getSource())}),o.transport(e.getSo
 urce(),e.type,{ruid:r.uid})}else t(e.getSource())},loadFromImage:function(e){var t=this.getRuntime();return t.shimExec.call(this,"Image","loadFromImage",e.uid)},getInfo:function(){var e=this.getRuntime(),t=e.shimExec.call(this,"Image","getInfo");return!t.meta||!t.meta.thumb||t.meta.thumb.data instanceof i||(t.meta.thumb.data=new i(e.uid,t.meta.thumb.data)),t},getAsBlob:function(e,t){var n=this.getRuntime(),r=n.shimExec.call(this,"Image","getAsBlob",e,t);return r?new i(n.uid,r):null},getAsDataURL:function(){var e=this.getRuntime(),t=e.Image.getAsBlob.apply(this,arguments),n;return t?(n=new r,n.readAsDataURL(t)):null}};return e.Image=o}),i(Q,[u,c,h,f,m],function(e,t,n,i,r){function o(e){var t=!1,n=null,i,r,o,a,s,u=0;try{try{n=new ActiveXObject("AgControl.AgControl"),n.IsVersionSupported(e)&&(t=!0),n=null}catch(c){var l=navigator.plugins["Silverlight Plug-In"];if(l){for(i=l.description,"1.0.302
 26.2"===i&&(i="2.0.30226.2"),r=i.split(".");r.length>3;)r.pop();for(;r.length<4;)r.push(0);for(o=e.split(".");o.length>4;)o.pop();do a=parseInt(o[u],10),s=parseInt(r[u],10),u++;while(u<o.length&&a===s);s>=a&&!isNaN(a)&&(t=!0)}}}catch(d){t=!1}return t}function a(a){var c=this,l;a=e.extend({xap_url:t.xap_url},a),r.call(this,a,s,{access_binary:r.capTrue,access_image_binary:r.capTrue,display_media:r.capTrue,do_cors:r.capTrue,drag_and_drop:!1,report_upload_progress:r.capTrue,resize_image:r.capTrue,return_response_headers:function(e){return e&&"client"===c.mode},return_response_type:function(e){return"json"!==e?!0:!!window.JSON},return_status_code:function(t){return"client"===c.mode||!e.arrayDiff(t,[200,404])},select_file:r.capTrue,select_multiple:r.capTrue,send_binary_string:r.capTrue,send_browser_cookies:function(e){return e&&"browser"===c.mode},send_
 custom_headers:function(e){return e&&"client"===c.mode},send_multipart:r.capTrue,slice_blob:r.capTrue,stream_upload:!0,summon_file_dialog:!1,upload_filesize:r.capTrue,use_http_method:function(t){return"client"===c.mode||!e.arrayDiff(t,["GET","POST"])}},{return_response_headers:function(e){return e?"client":"browser"},return_status_code:function(t){return e.arrayDiff(t,[200,404])?"client":["client","browser"]},send_browser_cookies:function(e){return e?"browser":"client"},send_custom_headers:function(e){return e?"client":"browser"},use_http_method:function(t){return e.arrayDiff(t,["GET","POST"])?"client":["client","browser"]}}),o("2.0.31005.0")&&"Opera"!==t.browser||(this.mode=!1),e.extend(this,{getShim:function(){return n.get(this.uid).content.Moxie},shimExec:function(e,t
 ){var n=[].slice.call(arguments,2);return c.getShim().exec(this.uid,e,t,n)},init:function(){var e;e=this.getShimContainer(),e.innerHTML='<object id="'+this.uid+'" data="data:application/x-silverlight," type="application/x-silverlight-2" width="100%" height="100%" style="outline:none;"><param name="source" value="'+a.xap_url+'"/><param name="background" value="Transparent"/><param name="windowless" value="true"/><param name="enablehtmlaccess" value="true"/><param name="initParams" value="uid='+this.uid+",target="+t.global_event_dispatcher+'"/></object>',l=setTimeout(function(){c&&!c.initialized&&c.trigger("Error",new i.RuntimeError(i.RuntimeError.NOT_INIT_ERR))},"Windows"!==t.OS?1e4:5e3)},destroy:function(e){return function(){e.call(c),clea
 rTimeout(l),a=l=e=c=null}}(this.destroy)},u)}var s="silverlight",u={};return r.addConstructor(s,a),u}),i(ee,[Q,E,u],function(e,t,n){var i={init:function(e){function i(e){for(var t="",n=0;n<e.length;n++)t+=(""!==t?"|":"")+e[n].title+" | *."+e[n].extensions.replace(/,/g,";*.");return t}var r=this,o=this.getRuntime();this.bind("Change",function(){var e=o.shimExec.call(r,"FileInput","getFiles");r.files=[],n.each(e,function(e){r.files.push(new t(o.uid,e))})},999),this.getRuntime().shimExec.call(this,"FileInput","init",i(e.accept),e.name,e.multiple),this.trigger("ready")}};return e.FileInput=i}),i(te,[Q,u,W],function(e,t,n){return e.Blob=t.extend({},n)}),i(ne,[Q,h,N],function(e,t,n){var i={init:function(){var e=this,i=e.getRuntime(),r;return r=i.getShimContainer(),n.addEvent(r,"dragover",function(e){e.preventDefault(),e.stopPropagation(),e.dataTran
 sfer.dropEffect="copy"},e.uid),n.addEvent(r,"dragenter",function(e){e.preventDefault();var n=t.get(i.uid).dragEnter(e);n&&e.stopPropagation()},e.uid),n.addEvent(r,"drop",function(e){e.preventDefault();var n=t.get(i.uid).dragDrop(e);n&&e.stopPropagation()},e.uid),i.shimExec.call(this,"FileDrop","init")}};return e.FileDrop=i}),i(ie,[Q,u,Y],function(e,t,n){return e.FileReader=t.extend({},n)}),i(re,[Q,u,$],function(e,t,n){return e.FileReaderSync=t.extend({},n)}),i(oe,[Q,u,J],function(e,t,n){return e.XMLHttpRequest=t.extend({},n)}),i(ae,[Q,u,Z],function(e,t,n){return e.Transporter=t.extend({},n)}),i(se,[Q,u,y,K],function(e,t,n,i){return e.Image=t.extend({},i,{getInfo:function(){var e=this.getRuntime(),i=["tiff","exif","gps","thumb"],r={meta:{}},o=e.shimExec.call(this,"Image","getInfo");return o.meta&&(t.each(i,function(e){var t=o.meta[e],n,i,a,s;if(t&&
 amp;t.keys)for(r.meta[e]={},i=0,a=t.keys.length;a>i;i++)n=t.keys[i],s=t[n],s&&(/^(\d|[1-9]\d+)$/.test(s)?s=parseInt(s,10):/^\d*\.\d+$/.test(s)&&(s=parseFloat(s)),r.meta[e][n]=s)}),!r.meta||!r.meta.thumb||r.meta.thumb.data instanceof n||(r.meta.thumb.data=new n(e.uid,r.meta.thumb.data))),r.width=parseInt(o.width,10),r.height=parseInt(o.height,10),r.size=parseInt(o.size,10),r.type=o.type,r.name=o.name,r}})}),i(ue,[u,f,m,c],function(e,t,n,i){function r(t){var r=this,s=n.capTest,u=n.capTrue;n.call(this,t,o,{access_binary:s(window.FileReader||window.File&&File.getAsDataURL),access_image_binary:!1,display_media:s(a.Image&&(i.can("create_canvas")||i.can("use_data_uri_over32kb"))),do_cors:!1,drag_and_drop:!1,filter_by_extension:s(function(){return"Chrome"===i.browser&&i.verComp(i.version,28,">=")||"IE"===i.browser&&i.verComp(i.version,10,">=")||"Safari"===i.browser&
 amp;&i.verComp(i.version,7,">=")}()),resize_image:function(){return a.Image&&r.can("access_binary")&&i.can("create_canvas")},report_upload_progress:!1,return_response_headers:!1,return_response_type:function(t){return"json"===t&&window.JSON?!0:!!~e.inArray(t,["text","document",""])},return_status_code:function(t){return!e.arrayDiff(t,[200,404])},select_file:function(){return i.can("use_fileinput")},select_multiple:!1,send_binary_string:!1,send_custom_headers:!1,send_multipart:!0,slice_blob:!1,stream_upload:function(){return r.can("select_file")},summon_file_dialog:function(){return r.can("select_file")&&("Firefox"===i.browser&&i.verComp(i.version,4,">=")||"Opera"===i.browser&&i.verComp(i.version,12,">=")||"IE"===i.browser&&i.verComp(i.version,10,">=")||!!
 ~e.inArray(i.browser,["Chrome","Safari"]))},upload_filesize:u,use_http_method:function(t){return!e.arrayDiff(t,["GET","POST"])}}),e.extend(this,{init:function(){this.trigger("Init")},destroy:function(e){return function(){e.call(r),e=r=null}}(this.destroy)}),e.extend(this.getShim(),a)}var o="html4",a={};return n.addConstructor(o,r),a}),i(ce,[ue,E,u,h,N,d,c],function(e,t,n,i,r,o,a){function s(){function e(){var o=this,l=o.getRuntime(),d,h,f,p,m,g;g=n.guid("uid_"),d=l.getShimContainer(),s&&(f=i.get(s+"_form"),f&&n.extend(f.style,{top:"100%"})),p=document.createElement("form"),p.setAttribute("id",g+"_form"),p.setAttribute("method","post"),p.setAttribute("enctype","multipart/form-data"),p.setAttribute("encoding","multipart/form-data"),n.extend(p.style,{overflow:"hidden",position:"
 absolute",top:0,left:0,width:"100%",height:"100%"}),m=document.createElement("input"),m.setAttribute("id",g),m.setAttribute("type","file"),m.setAttribute("name",c.name||"Filedata"),m.setAttribute("accept",u.join(",")),n.extend(m.style,{fontSize:"999px",opacity:0}),p.appendChild(m),d.appendChild(p),n.extend(m.style,{position:"absolute",top:0,left:0,width:"100%",height:"100%"}),"IE"===a.browser&&a.verComp(a.version,10,"<")&&n.extend(m.style,{filter:"progid:DXImageTransform.Microsoft.Alpha(opacity=0)"}),m.onchange=function(){var n;if(this.value){if(this.files){if(n=this.files[0],0===n.size)return void p.parentNode.removeChild(p)}else n={name:this.value};n=new t(l.uid,n),this.onchange=function(){},e.call(o),o.files=[n],m.setAttribute("id",n.uid),p.setAttribute("id",n.uid+&quot
 ;_form"),o.trigger("change"),m=p=null}},l.can("summon_file_dialog")&&(h=i.get(c.browse_button),r.removeEvent(h,"click",o.uid),r.addEvent(h,"click",function(e){m&&!m.disabled&&m.click(),e.preventDefault()},o.uid)),s=g,d=f=h=null}var s,u=[],c;n.extend(this,{init:function(t){var n=this,a=n.getRuntime(),s;c=t,u=t.accept.mimes||o.extList2mimes(t.accept,a.can("filter_by_extension")),s=a.getShimContainer(),function(){var e,o,u;e=i.get(t.browse_button),a.can("summon_file_dialog")&&("static"===i.getStyle(e,"position")&&(e.style.position="relative"),o=parseInt(i.getStyle(e,"z-index"),10)||1,e.style.zIndex=o,s.style.zIndex=o-1),u=a.can("summon_file_dialog")?e:s,r.addEvent(u,"mouseover",function(){n.trigger("mouseenter")},n.uid),r.addEvent(u,"mouseout",function(){n.trigger("mouseleave")},n.uid),r.addEve
 nt(u,"mousedown",function(){n.trigger("mousedown")},n.uid),r.addEvent(i.get(t.container),"mouseup",function(){n.trigger("mouseup")},n.uid),e=null}(),e.call(this),s=null,n.trigger({type:"ready",async:!0})},disable:function(e){var t;(t=i.get(s))&&(t.disabled=!!e)},destroy:function(){var e=this.getRuntime(),t=e.getShim(),n=e.getShimContainer();r.removeAllEvents(n,this.uid),r.removeAllEvents(c&&i.get(c.container),this.uid),r.removeAllEvents(c&&i.get(c.browse_button),this.uid),n&&(n.innerHTML=""),t.removeInstance(this.uid),s=u=c=n=t=null}})}return e.FileInput=s}),i(le,[ue,F],function(e,t){return e.FileReader=t}),i(de,[ue,u,h,x,f,N,y,I],function(e,t,n,i,r,o,a,s){function u(){function e(e){var t=this,i,r,a,s,u=!1;if(l){if(i=l.id.replace(/_iframe$/,""),r=n.get(i+"_form")){for(a=r.getElementsByTagName("input"),s=a.length;s--;)switch(a[s].getAttribute("type")){ca
 se"hidden":a[s].parentNode.removeChild(a[s]);break;case"file":u=!0}a=[],u||r.parentNode.removeChild(r),r=null}setTimeout(function(){o.removeEvent(l,"load",t.uid),l.parentNode&&l.parentNode.removeChild(l);var n=t.getRuntime().getShimContainer();n.children.length||n.parentNode.removeChild(n),n=l=null,e()},1)}}var u,c,l;t.extend(this,{send:function(d,h){function f(){var n=m.getShimContainer()||document.body,r=document.createElement("div");r.innerHTML='<iframe id="'+g+'_iframe" name="'+g+'_iframe" src="javascript:&quot;&quot;" style="display:none"></iframe>',l=r.firstChild,n.appendChild(l),o.addEvent(l,"load",function(){var n;try{n=l.contentWindow.document||l.contentDocument||window.frames[l.id].document,/^4(0[0-9]|1[0-7]|2[2346])\s/.test(n.title)?u=n.title.replace(/^(\d+).*$/,"$1"):(u=200,c=t.trim(n.body.innerHTML),p.trigger({type:"progress",loaded:c
 .length,total:c.length}),y&&p.trigger({type:"uploadprogress",loaded:y.size||1025,total:y.size||1025}))}catch(r){if(!i.hasSameOrigin(d.url))return void e.call(p,function(){p.trigger("error")});u=404}e.call(p,function(){p.trigger("load")})},p.uid)}var p=this,m=p.getRuntime(),g,v,w,y;if(u=c=null,h instanceof s&&h.hasBlob()){if(y=h.getBlob(),g=y.uid,w=n.get(g),v=n.get(g+"_form"),!v)throw new r.DOMException(r.DOMException.NOT_FOUND_ERR)}else g=t.guid("uid_"),v=document.createElement("form"),v.setAttribute("id",g+"_form"),v.setAttribute("method",d.method),v.setAttribute("enctype","multipart/form-data"),v.setAttribute("encoding","multipart/form-data"),m.getShimContainer().appendChild(v);v.setAttribute("target",g+"_iframe"),h instanceof s&&h.each(function(e,n){if(e instanceof a)w&&w.setAttribute("name"
 ,n);else{var i=document.createElement("input");t.extend(i,{type:"hidden",name:n,value:e}),w?v.insertBefore(i,w):v.appendChild(i)}}),v.setAttribute("action",d.url),f(),v.submit(),p.trigger("loadstart")},getStatus:function(){return u},getResponse:function(e){if("json"===e&&"string"===t.typeOf(c)&&window.JSON)try{
-return JSON.parse(c.replace(/^\s*<pre[^>]*>/,"").replace(/<\/pre>\s*$/,""))}catch(n){return null}return c},abort:function(){var t=this;l&&l.contentWindow&&(l.contentWindow.stop?l.contentWindow.stop():l.contentWindow.document.execCommand?l.contentWindow.document.execCommand("Stop"):l.src="about:blank"),e.call(this,function(){t.dispatchEvent("abort")})}})}return e.XMLHttpRequest=u}),i(he,[ue,j],function(e,t){return e.Image=t}),a([u,c,l,d,h,f,p,m,g,v,w,y,E,_,b,x,R,A,I,T,S,O,N])}(this);;(function(e){"use strict";var t={},n=e.moxie.core.utils.Basic.inArray;return function r(e){var i,s;for(i in e)s=typeof e[i],s==="object"&&!~n(i,["Exceptions","Env","Mime"])?r(e[i]):s==="function"&&(t[i]=e[i])}(e.moxie),t.Env=e.moxie.core.utils.Env,t.Mime=e.moxie.core.utils.Mime,t.Exceptions=e.moxie.core.Exceptions,e.mOxie=t,e.o||(e.o=t),t})(this);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Modified for WordPress, Silverlight and Flash runtimes support was removed.
+ * See https://core.trac.wordpress.org/ticket/41755.
+ */
+!function(a,b){"use strict";function c(a,b){for(var c,d=[],f=0;f<a.length;++f){if(c=g[a[f]]||e(a[f]),!c)throw"module definition dependecy not found: "+a[f];d.push(c)}b.apply(null,d)}function d(a,d,e){if("string"!=typeof a)throw"invalid module definition, module id must be defined and be a string";if(d===b)throw"invalid module definition, dependencies must be specified";if(e===b)throw"invalid module definition, definition function must be specified";c(d,function(){g[a]=e.apply(null,arguments)})}function e(b){for(var c=a,d=b.split(/[.\/]/),e=0;e<d.length;++e){if(!c[d[e]])return;c=c[d[e]]}return c}function f(c){for(var d=0;d<c.length;d++){for(var e=a,f=c[d],h=f.split(/[.\/]/),i=0;i<h.length-1;++i)e[h[i]]===b&&(e[h[i]]={}),e=e[h[i]];e[h[h.length-1]]=g[f]}}var g={};d("moxie/core/utils/Basic",[],function(){var a=function(a){var b;return a===b?"undefined":null===a?"null":a.nodeType
 ?"node":{}.toString.call(a).match(/\s([a-z|A-Z]+)/)[1].toLowerCase()},b=function(d){var e;return c(arguments,function(f,h){h>0&&c(f,function(c,f){c!==e&&(a(d[f])===a(c)&&~g(a(c),["array","object"])?b(d[f],c):d[f]=c)})}),d},c=function(b,c){var d,e,f;if(b)if("number"===a(b.length)){for(f=0,d=b.length;f<d;f++)if(c(b[f],f)===!1)return}else if("object"===a(b))for(e in b)if(b.hasOwnProperty(e)&&c(b[e],e)===!1)return},d=function(b){var c;if(!b||"object"!==a(b))return!0;for(c in b)return!1;return!0},e=function(b,c){function d(e){"function"===a(b[e])&&b[e](function(a){++e<f&&!a?d(e):c(a)})}var e=0,f=b.length;"function"!==a(c)&&(c=function(){}),b&&b.length||c(),d(e)},f=function(a,b){var d=0,e=a.length,f=new Array(e);c(a,function(a,c){a(function(a){if(a)return b(a);var g=[].slice.call(arguments);g.shift(),f[c]=g,d++,d===e&&(f.unshift(n
 ull),b.apply(this,f))})})},g=function(a,b){if(b){if(Array.prototype.indexOf)return Array.prototype.indexOf.call(b,a);for(var c=0,d=b.length;c<d;c++)if(b[c]===a)return c}return-1},h=function(b,c){var d=[];"array"!==a(b)&&(b=[b]),"array"!==a(c)&&(c=[c]);for(var e in b)g(b[e],c)===-1&&d.push(b[e]);return!!d.length&&d},i=function(a,b){var d=[];return c(a,function(a){g(a,b)!==-1&&d.push(a)}),d.length?d:null},j=function(a){var b,c=[];for(b=0;b<a.length;b++)c[b]=a[b];return c},k=function(){var a=0;return function(b){var c,d=(new Date).getTime().toString(32);for(c=0;c<5;c++)d+=Math.floor(65535*Math.random()).toString(32);return(b||"o_")+d+(a++).toString(32)}}(),l=function(a){return a?String.prototype.trim?String.prototype.trim.call(a):a.toString().replace(/^\s*/,"").replace(/\s*$/,""):a},m=function(a){if("string"!=typeof a)return a;var b,c={t:1099511627776,g:1073741824,m:1048576,k:10
 24};return a=/^([0-9\.]+)([tmgk]?)$/.exec(a.toLowerCase().replace(/[^0-9\.tmkg]/g,"")),b=a[2],a=+a[1],c.hasOwnProperty(b)&&(a*=c[b]),Math.floor(a)},n=function(b){var c=[].slice.call(arguments,1);return b.replace(/%[a-z]/g,function(){var b=c.shift();return"undefined"!==a(b)?b:""})};return{guid:k,typeOf:a,extend:b,each:c,isEmptyObj:d,inSeries:e,inParallel:f,inArray:g,arrayDiff:h,arrayIntersect:i,toArray:j,trim:l,sprintf:n,parseSizeStr:m}}),d("moxie/core/utils/Env",["moxie/core/utils/Basic"],function(a){function b(a,b,c){var d=0,e=0,f=0,g={dev:-6,alpha:-5,a:-5,beta:-4,b:-4,RC:-3,rc:-3,"#":-2,p:1,pl:1},h=function(a){return a=(""+a).replace(/[_\-+]/g,"."),a=a.replace(/([^.\d]+)/g,".$1.").replace(/\.{2,}/g,"."),a.length?a.split("."):[-8]},i=function(a){return a?isNaN(a)?g[a]||-7:parseInt(a,10):0};for(a=h(a),b=h(b),e=Math.max(a.length,b.length),d=0;d<e;d++)if(a[d]!=b[d])
 {if(a[d]=i(a[d]),b[d]=i(b[d]),a[d]<b[d]){f=-1;break}if(a[d]>b[d]){f=1;break}}if(!c)return f;switch(c){case">":case"gt":return f>0;case">=":case"ge":return f>=0;case"<=":case"le":return f<=0;case"==":case"=":case"eq":return 0===f;case"<>":case"!=":case"ne":return 0!==f;case"":case"<":case"lt":return f<0;default:return null}}var c=function(a){var b="",c="?",d="function",e="undefined",f="object",g="name",h="version",i={has:function(a,b){return b.toLowerCase().indexOf(a.toLowerCase())!==-1},lowerize:function(a){return a.toLowerCase()}},j={rgx:function(){for(var b,c,g,h,i,j,k,l=0,m=arguments;l<m.length;l+=2){var n=m[l],o=m[l+1];if(typeof b===e){b={};for(h in o)i=o[h],typeof i===f?b[i[0]]=a:b[i]=a}for(c=g=0;c<n.length;c++)if(j=n[c]
 .exec(this.getUA())){for(h=0;h<o.length;h++)k=j[++g],i=o[h],typeof i===f&&i.length>0?2==i.length?typeof i[1]==d?b[i[0]]=i[1].call(this,k):b[i[0]]=i[1]:3==i.length?typeof i[1]!==d||i[1].exec&&i[1].test?b[i[0]]=k?k.replace(i[1],i[2]):a:b[i[0]]=k?i[1].call(this,k,i[2]):a:4==i.length&&(b[i[0]]=k?i[3].call(this,k.replace(i[1],i[2])):a):b[i]=k?k:a;break}if(j)break}return b},str:function(b,d){for(var e in d)if(typeof d[e]===f&&d[e].length>0){for(var g=0;g<d[e].length;g++)if(i.has(d[e][g],b))return e===c?a:e}else if(i.has(d[e],b))return e===c?a:e;return b}},k={browser:{oldsafari:{major:{1:["/8","/1","/3"],2:"/4","?":"/"},version:{"1.0":"/8",1.2:"/1",1.3:"/3","2.0":"/412","2.0.2":"/416","2.0.3":"/417","2.0.4":"/419","?":"/"}}},device:{sprint:{model:{&q
 uot;Evo Shift 4G":"7373KT"},vendor:{HTC:"APA",Sprint:"Sprint"}}},os:{windows:{version:{ME:"4.90","NT 3.11":"NT3.51","NT 4.0":"NT4.0",2000:"NT 5.0",XP:["NT 5.1","NT 5.2"],Vista:"NT 6.0",7:"NT 6.1",8:"NT 6.2",8.1:"NT 6.3",RT:"ARM"}}}},l={browser:[[/(opera\smini)\/([\w\.-]+)/i,/(opera\s[mobiletab]+).+version\/([\w\.-]+)/i,/(opera).+version\/([\w\.]+)/i,/(opera)[\/\s]+([\w\.]+)/i],[g,h],[/\s(opr)\/([\w\.]+)/i],[[g,"Opera"],h],[/(kindle)\/([\w\.]+)/i,/(lunascape|maxthon|netfront|jasmine|blazer)[\/\s]?([\w\.]+)*/i,/(avant\s|iemobile|slim|baidu)(?:browser)?[\/\s]?([\w\.]*)/i,/(?:ms|\()(ie)\s([\w\.]+)/i,/(rekonq)\/([\w\.]+)*/i,/(chromium|flock|rockmelt|midori|epiphany|silk|skyfire|ovibrowser|bolt|iron|vivaldi)\/([\w\.-]+)/i],[g,h],[/(trident).+rv[:\s]([\w\.]+).+like\sgecko/i],[[g,"IE"],h],[/(edge)\/((\d+)?[\w
 \.]+)/i],[g,h],[/(yabrowser)\/([\w\.]+)/i],[[g,"Yandex"],h],[/(comodo_dragon)\/([\w\.]+)/i],[[g,/_/g," "],h],[/(chrome|omniweb|arora|[tizenoka]{5}\s?browser)\/v?([\w\.]+)/i,/(uc\s?browser|qqbrowser)[\/\s]?([\w\.]+)/i],[g,h],[/(dolfin)\/([\w\.]+)/i],[[g,"Dolphin"],h],[/((?:android.+)crmo|crios)\/([\w\.]+)/i],[[g,"Chrome"],h],[/XiaoMi\/MiuiBrowser\/([\w\.]+)/i],[h,[g,"MIUI Browser"]],[/android.+version\/([\w\.]+)\s+(?:mobile\s?safari|safari)/i],[h,[g,"Android Browser"]],[/FBAV\/([\w\.]+);/i],[h,[g,"Facebook"]],[/version\/([\w\.]+).+?mobile\/\w+\s(safari)/i],[h,[g,"Mobile Safari"]],[/version\/([\w\.]+).+?(mobile\s?safari|safari)/i],[h,g],[/webkit.+?(mobile\s?safari|safari)(\/[\w\.]+)/i],[g,[h,j.str,k.browser.oldsafari.version]],[/(konqueror)\/([\w\.]+)/i,/(webkit|khtml)\/([\w\.]+)/i],[g,h],[/(navigator|netscape)\/([\w\.-]+)/i],[[g,"Netscape"],h],[/(swiftfox)/i,/(icedragon|iceweasel|camino|chimera|
 fennec|maemo\sbrowser|minimo|conkeror)[\/\s]?([\w\.\+]+)/i,/(firefox|seamonkey|k-meleon|icecat|iceape|firebird|phoenix)\/([\w\.-]+)/i,/(mozilla)\/([\w\.]+).+rv\:.+gecko\/\d+/i,/(polaris|lynx|dillo|icab|doris|amaya|w3m|netsurf)[\/\s]?([\w\.]+)/i,/(links)\s\(([\w\.]+)/i,/(gobrowser)\/?([\w\.]+)*/i,/(ice\s?browser)\/v?([\w\._]+)/i,/(mosaic)[\/\s]([\w\.]+)/i],[g,h]],engine:[[/windows.+\sedge\/([\w\.]+)/i],[h,[g,"EdgeHTML"]],[/(presto)\/([\w\.]+)/i,/(webkit|trident|netfront|netsurf|amaya|lynx|w3m)\/([\w\.]+)/i,/(khtml|tasman|links)[\/\s]\(?([\w\.]+)/i,/(icab)[\/\s]([23]\.[\d\.]+)/i],[g,h],[/rv\:([\w\.]+).*(gecko)/i],[h,g]],os:[[/microsoft\s(windows)\s(vista|xp)/i],[g,h],[/(windows)\snt\s6\.2;\s(arm)/i,/(windows\sphone(?:\sos)*|windows\smobile|windows)[\s\/]?([ntce\d\.\s]+\w)/i],[g,[h,j.str,k.os.windows.version]],[/(win(?=3|9|n)|win\s9x\s)([nt\d\.]+)/i],[[g,"Windows"],[h,j.str,k.os.windows.version]],[/\((bb)(10);/i],[[g,"BlackBerry"],h],[/(blackberry)\w*\/?([
 \w\.]+)*/i,/(tizen)[\/\s]([\w\.]+)/i,/(android|webos|palm\os|qnx|bada|rim\stablet\sos|meego|contiki)[\/\s-]?([\w\.]+)*/i,/linux;.+(sailfish);/i],[g,h],[/(symbian\s?os|symbos|s60(?=;))[\/\s-]?([\w\.]+)*/i],[[g,"Symbian"],h],[/\((series40);/i],[g],[/mozilla.+\(mobile;.+gecko.+firefox/i],[[g,"Firefox OS"],h],[/(nintendo|playstation)\s([wids3portablevu]+)/i,/(mint)[\/\s\(]?(\w+)*/i,/(mageia|vectorlinux)[;\s]/i,/(joli|[kxln]?ubuntu|debian|[open]*suse|gentoo|arch|slackware|fedora|mandriva|centos|pclinuxos|redhat|zenwalk|linpus)[\/\s-]?([\w\.-]+)*/i,/(hurd|linux)\s?([\w\.]+)*/i,/(gnu)\s?([\w\.]+)*/i],[g,h],[/(cros)\s[\w]+\s([\w\.]+\w)/i],[[g,"Chromium OS"],h],[/(sunos)\s?([\w\.]+\d)*/i],[[g,"Solaris"],h],[/\s([frentopc-]{0,4}bsd|dragonfly)\s?([\w\.]+)*/i],[g,h],[/(ip[honead]+)(?:.*os\s*([\w]+)*\slike\smac|;\sopera)/i],[[g,"iOS"],[h,/_/g,"."]],[/(mac\sos\sx)\s?([\w\s\.]+\w)*/i,/(macintosh|mac(?=_powerpc)\s)/i],[[g,"Mac OS&quot
 ;],[h,/_/g,"."]],[/((?:open)?solaris)[\/\s-]?([\w\.]+)*/i,/(haiku)\s(\w+)/i,/(aix)\s((\d)(?=\.|\)|\s)[\w\.]*)*/i,/(plan\s9|minix|beos|os\/2|amigaos|morphos|risc\sos|openvms)/i,/(unix)\s?([\w\.]+)*/i],[g,h]]},m=function(a){var c=a||(window&&window.navigator&&window.navigator.userAgent?window.navigator.userAgent:b);this.getBrowser=function(){return j.rgx.apply(this,l.browser)},this.getEngine=function(){return j.rgx.apply(this,l.engine)},this.getOS=function(){return j.rgx.apply(this,l.os)},this.getResult=function(){return{ua:this.getUA(),browser:this.getBrowser(),engine:this.getEngine(),os:this.getOS()}},this.getUA=function(){return c},this.setUA=function(a){return c=a,this},this.setUA(c)};return m}(),d=function(){var b={define_property:function(){return!1}(),create_canvas:function(){var a=document.createElement("canvas");return!(!a.getContext||!a.getContext("2d"))}(),return_response_type:function(b){try{if(a.inArray(b,["","t
 ext","document"])!==-1)return!0;if(window.XMLHttpRequest){var c=new XMLHttpRequest;if(c.open("get","/"),"responseType"in c)return c.responseType=b,c.responseType===b}}catch(d){}return!1},use_data_uri:function(){var a=new Image;return a.onload=function(){b.use_data_uri=1===a.width&&1===a.height},setTimeout(function(){a.src="data:image/gif;base64,R0lGODlhAQABAIAAAP8AAAAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw=="},1),!1}(),use_data_uri_over32kb:function(){return b.use_data_uri&&("IE"!==f.browser||f.version>=9)},use_data_uri_of:function(a){return b.use_data_uri&&a<33e3||b.use_data_uri_over32kb()},use_fileinput:function(){if(navigator.userAgent.match(/(Android (1.0|1.1|1.5|1.6|2.0|2.1))|(Windows Phone (OS 7|8.0))|(XBLWP)|(ZuneWP)|(w(eb)?OSBrowser)|(webOS)|(Kindle\/(1.0|2.0|2.5|3.0))/))return!1;var a=document.createElement("input");return a.setAttribute("type","file"),!a
 .disabled}};return function(c){var d=[].slice.call(arguments);return d.shift(),"function"===a.typeOf(b[c])?b[c].apply(this,d):!!b[c]}}(),e=(new c).getResult(),f={can:d,uaParser:c,browser:e.browser.name,version:e.browser.version,os:e.os.name,osVersion:e.os.version,verComp:b,global_event_dispatcher:"moxie.core.EventTarget.instance.dispatchEvent"};return f.OS=f.os,MXI_DEBUG&&(f.debug={runtime:!0,events:!1},f.log=function(){function b(a){d.appendChild(document.createTextNode(a+"\n"))}var c=arguments[0];if("string"===a.typeOf(c)&&(c=a.sprintf.apply(this,arguments)),window&&window.console&&window.console.log)window.console.log(c);else if(document){var d=document.getElementById("moxie-console");d||(d=document.createElement("pre"),d.id="moxie-console",document.body.appendChild(d)),a.inArray(a.typeOf(c),["object","array"])!==-1?b(c):d.appendChild(document.createTextNode(c
 +"\n"))}}),f}),d("moxie/core/I18n",["moxie/core/utils/Basic"],function(a){var b={};return{addI18n:function(c){return a.extend(b,c)},translate:function(a){return b[a]||a},_:function(a){return this.translate(a)},sprintf:function(b){var c=[].slice.call(arguments,1);return b.replace(/%[a-z]/g,function(){var b=c.shift();return"undefined"!==a.typeOf(b)?b:""})}}}),d("moxie/core/utils/Mime",["moxie/core/utils/Basic","moxie/core/I18n"],function(a,b){var c="application/msword,doc dot,application/pdf,pdf,application/pgp-signature,pgp,application/postscript,ps ai eps,application/rtf,rtf,application/vnd.ms-excel,xls xlb,application/vnd.ms-powerpoint,ppt pps pot,application/zip,zip,application/x-shockwave-flash,swf swfl,application/vnd.openxmlformats-officedocument.wordprocessingml.document,docx,application/vnd.openxmlformats-officedocument.wordprocessingml.template,dotx,application/vnd.openxmlformats-officedocum
 ent.spreadsheetml.sheet,xlsx,application/vnd.openxmlformats-officedocument.presentationml.presentation,pptx,application/vnd.openxmlformats-officedocument.presentationml.template,potx,application/vnd.openxmlformats-officedocument.presentationml.slideshow,ppsx,application/x-javascript,js,application/json,json,audio/mpeg,mp3 mpga mpega mp2,audio/x-wav,wav,audio/x-m4a,m4a,audio/ogg,oga ogg,audio/aiff,aiff aif,audio/flac,flac,audio/aac,aac,audio/ac3,ac3,audio/x-ms-wma,wma,image/bmp,bmp,image/gif,gif,image/jpeg,jpg jpeg jpe,image/photoshop,psd,image/png,png,image/svg+xml,svg svgz,image/tiff,tiff tif,text/plain,asc txt text diff log,text/html,htm html xhtml,text/css,css,text/csv,csv,text/rtf,rtf,video/mpeg,mpeg mpg mpe m2v,video/quicktime,qt mov,video/mp4,mp4,video/x-m4v,m4v,video/x-flv,flv,video/x-ms-wmv,wmv,video/avi,avi,video/webm,webm,video/3gpp,3gpp 3gp,video/3gpp2,3g2,video/vnd.rn-realvideo,rv,video/ogg,ogv,video/x-matroska,mkv,application/vnd.oasis.opendocument.formula-template,otf,
 application/octet-stream,exe",d={mimes:{},extensions:{},addMimeType:function(a){var b,c,d,e=a.split(/,/);for(b=0;b<e.length;b+=2){for(d=e[b+1].split(/ /),c=0;c<d.length;c++)this.mimes[d[c]]=e[b];this.extensions[e[b]]=d}},extList2mimes:function(b,c){var d,e,f,g,h=this,i=[];for(e=0;e<b.length;e++)for(d=b[e].extensions.split(/\s*,\s*/),f=0;f<d.length;f++){if("*"===d[f])return[];if(g=h.mimes[d[f]],g&&a.inArray(g,i)===-1&&i.push(g),c&&/^\w+$/.test(d[f]))i.push("."+d[f]);else if(!g)return[]}return i},mimes2exts:function(b){var c=this,d=[];return a.each(b,function(b){if("*"===b)return d=[],!1;var e=b.match(/^(\w+)\/(\*|\w+)$/);e&&("*"===e[2]?a.each(c.extensions,function(a,b){new RegExp("^"+e[1]+"/").test(b)&&[].push.apply(d,c.extensions[b])}):c.extensions[b]&&[].push.apply(d,c.extensions[b]))}),d},mimes2extList:function(c){var d=[],e=[];return"string"===a.t
 ypeOf(c)&&(c=a.trim(c).split(/\s*,\s*/)),e=this.mimes2exts(c),d.push({title:b.translate("Files"),extensions:e.length?e.join(","):"*"}),d.mimes=c,d},getFileExtension:function(a){var b=a&&a.match(/\.([^.]+)$/);return b?b[1].toLowerCase():""},getFileMime:function(a){return this.mimes[this.getFileExtension(a)]||""}};return d.addMimeType(c),d}),d("moxie/core/utils/Dom",["moxie/core/utils/Env"],function(a){var b=function(a){return"string"!=typeof a?a:document.getElementById(a)},c=function(a,b){if(!a.className)return!1;var c=new RegExp("(^|\\s+)"+b+"(\\s+|$)");return c.test(a.className)},d=function(a,b){c(a,b)||(a.className=a.className?a.className.replace(/\s+$/,"")+" "+b:b)},e=function(a,b){if(a.className){var c=new RegExp("(^|\\s+)"+b+"(\\s+|$)");a.className=a.className.replace(c,function(a,b,c){return" "===b&&"
  "===c?" ":""})}},f=function(a,b){return a.currentStyle?a.currentStyle[b]:window.getComputedStyle?window.getComputedStyle(a,null)[b]:void 0},g=function(b,c){function d(a){var b,c,d=0,e=0;return a&&(c=a.getBoundingClientRect(),b="CSS1Compat"===j.compatMode?j.documentElement:j.body,d=c.left+b.scrollLeft,e=c.top+b.scrollTop),{x:d,y:e}}var e,f,g,h=0,i=0,j=document;if(b=b,c=c||j.body,b&&b.getBoundingClientRect&&"IE"===a.browser&&(!j.documentMode||j.documentMode<8))return f=d(b),g=d(c),{x:f.x-g.x,y:f.y-g.y};for(e=b;e&&e!=c&&e.nodeType;)h+=e.offsetLeft||0,i+=e.offsetTop||0,e=e.offsetParent;for(e=b.parentNode;e&&e!=c&&e.nodeType;)h-=e.scrollLeft||0,i-=e.scrollTop||0,e=e.parentNode;return{x:h,y:i}},h=function(a){return{w:a.offsetWidth||a.clientWidth,h:a.offsetHeight||a.clientHeight}};return{get:b,hasClass:c,addClass:d,removeClass:e,getStyle:f,getPos:g,getSize:h}}),d("moxie/cor
 e/Exceptions",["moxie/core/utils/Basic"],function(a){function b(a,b){var c;for(c in a)if(a[c]===b)return c;return null}return{RuntimeError:function(){function c(a){this.code=a,this.name=b(d,a),this.message=this.name+": RuntimeError "+this.code}var d={NOT_INIT_ERR:1,NOT_SUPPORTED_ERR:9,JS_ERR:4};return a.extend(c,d),c.prototype=Error.prototype,c}(),OperationNotAllowedException:function(){function b(a){this.code=a,this.name="OperationNotAllowedException"}return a.extend(b,{NOT_ALLOWED_ERR:1}),b.prototype=Error.prototype,b}(),ImageError:function(){function c(a){this.code=a,this.name=b(d,a),this.message=this.name+": ImageError "+this.code}var d={WRONG_FORMAT:1,MAX_RESOLUTION_ERR:2,INVALID_META_ERR:3};return a.extend(c,d),c.prototype=Error.prototype,c}(),FileException:function(){function c(a){this.code=a,this.name=b(d,a),this.message=this.name+": FileException "+this.code}var d={NOT_FOUND_ERR:1,SECURITY_ERR:2,ABORT_ERR:3,NOT_READABLE
 _ERR:4,ENCODING_ERR:5,NO_MODIFICATION_ALLOWED_ERR:6,INVALID_STATE_ERR:7,SYNTAX_ERR:8};return a.extend(c,d),c.prototype=Error.prototype,c}(),DOMException:function(){function c(a){this.code=a,this.name=b(d,a),this.message=this.name+": DOMException "+this.code}var d={INDEX_SIZE_ERR:1,DOMSTRING_SIZE_ERR:2,HIERARCHY_REQUEST_ERR:3,WRONG_DOCUMENT_ERR:4,INVALID_CHARACTER_ERR:5,NO_DATA_ALLOWED_ERR:6,NO_MODIFICATION_ALLOWED_ERR:7,NOT_FOUND_ERR:8,NOT_SUPPORTED_ERR:9,INUSE_ATTRIBUTE_ERR:10,INVALID_STATE_ERR:11,SYNTAX_ERR:12,INVALID_MODIFICATION_ERR:13,NAMESPACE_ERR:14,INVALID_ACCESS_ERR:15,VALIDATION_ERR:16,TYPE_MISMATCH_ERR:17,SECURITY_ERR:18,NETWORK_ERR:19,ABORT_ERR:20,URL_MISMATCH_ERR:21,QUOTA_EXCEEDED_ERR:22,TIMEOUT_ERR:23,INVALID_NODE_TYPE_ERR:24,DATA_CLONE_ERR:25};return a.extend(c,d),c.prototype=Error.prototype,c}(),EventException:function(){function b(a){this.code=a,this.name="EventException"}return a.extend(b,{UNSPECIFIED_EVENT_TYPE_ERR:0}),b.prototype=Error.prototy
 pe,b}()}}),d("moxie/core/EventTarget",["moxie/core/utils/Env","moxie/core/Exceptions","moxie/core/utils/Basic"],function(a,b,c){function d(){var d={};c.extend(this,{uid:null,init:function(){this.uid||(this.uid=c.guid("uid_"))},addEventListener:function(a,b,e,f){var g,h=this;return this.hasOwnProperty("uid")||(this.uid=c.guid("uid_")),a=c.trim(a),/\s/.test(a)?void c.each(a.split(/\s+/),function(a){h.addEventListener(a,b,e,f)}):(a=a.toLowerCase(),e=parseInt(e,10)||0,g=d[this.uid]&&d[this.uid][a]||[],g.push({fn:b,priority:e,scope:f||this}),d[this.uid]||(d[this.uid]={}),void(d[this.uid][a]=g))},hasEventListener:function(a){var b=a?d[this.uid]&&d[this.uid][a]:d[this.uid];return!!b&&b},removeEventListener:function(a,b){a=a.toLowerCase();var e,f=d[this.uid]&&d[this.uid][a];if(f){if(b){for(e=f.length-1;e>=0;e--)if(f[e].fn===b){f.splice(e,1);break}}else f=[];f.length||(delete d[this.uid][
 a],c.isEmptyObj(d[this.uid])&&delete d[this.uid])}},removeAllEventListeners:function(){d[this.uid]&&delete d[this.uid]},dispatchEvent:function(e){var f,g,h,i,j,k={},l=!0;if("string"!==c.typeOf(e)){if(i=e,"string"!==c.typeOf(i.type))throw new b.EventException(b.EventException.UNSPECIFIED_EVENT_TYPE_ERR);e=i.type,i.total!==j&&i.loaded!==j&&(k.total=i.total,k.loaded=i.loaded),k.async=i.async||!1}if(e.indexOf("::")!==-1?!function(a){f=a[0],e=a[1]}(e.split("::")):f=this.uid,e=e.toLowerCase(),g=d[f]&&d[f][e]){g.sort(function(a,b){return b.priority-a.priority}),h=[].slice.call(arguments),h.shift(),k.type=e,h.unshift(k),MXI_DEBUG&&a.debug.events&&a.log("Event '%s' fired on %u",k.type,f);var m=[];c.each(g,function(a){h[0].target=a.scope,k.async?m.push(function(b){setTimeout(function(){b(a.fn.apply(a.scope,h)===!1)},1)}):m.push(function(b){b(a.fn.apply(a.scope,h)===!1)})}),m.length&&a
 mp;c.inSeries(m,function(a){l=!a})}return l},bind:function(){this.addEventListener.apply(this,arguments)},unbind:function(){this.removeEventListener.apply(this,arguments)},unbindAll:function(){this.removeAllEventListeners.apply(this,arguments)},trigger:function(){return this.dispatchEvent.apply(this,arguments)},handleEventProps:function(a){var b=this;this.bind(a.join(" "),function(a){var b="on"+a.type.toLowerCase();"function"===c.typeOf(this[b])&&this[b].apply(this,arguments)}),c.each(a,function(a){a="on"+a.toLowerCase(a),"undefined"===c.typeOf(b[a])&&(b[a]=null)})}})}return d.instance=new d,d}),d("moxie/runtime/Runtime",["moxie/core/utils/Env","moxie/core/utils/Basic","moxie/core/utils/Dom","moxie/core/EventTarget"],function(a,b,c,d){function e(d,f,h,i,j){var k,l=this,m=b.guid(f+"_"),n=j||"browser";d=d||{},g[m]=this,h=b.extend({access_binary:!1,acc
 ess_image_binary:!1,display_media:!1,do_cors:!1,drag_and_drop:!1,filter_by_extension:!0,resize_image:!1,report_upload_progress:!1,return_response_headers:!1,return_response_type:!1,return_status_code:!0,send_custom_headers:!1,select_file:!1,select_folder:!1,select_multiple:!0,send_binary_string:!1,send_browser_cookies:!0,send_multipart:!0,slice_blob:!1,stream_upload:!1,summon_file_dialog:!1,upload_filesize:!0,use_http_method:!0},h),d.preferred_caps&&(n=e.getMode(i,d.preferred_caps,n)),MXI_DEBUG&&a.debug.runtime&&a.log("\tdefault mode: %s",n),k=function(){var a={};return{exec:function(b,c,d,e){if(k[c]&&(a[b]||(a[b]={context:this,instance:new k[c]}),a[b].instance[d]))return a[b].instance[d].apply(this,e)},removeInstance:function(b){delete a[b]},removeAllInstances:function(){var c=this;b.each(a,function(a,d){"function"===b.typeOf(a.instance.destroy)&&a.instance.destroy.call(a.context),c.removeInstance(d)})}}}(),b.extend(this,{
 initialized:!1,uid:m,type:f,mode:e.getMode(i,d.required_caps,n),shimid:m+"_container",clients:0,options:d,can:function(a,c){var d=arguments[2]||h;if("string"===b.typeOf(a)&&"undefined"===b.typeOf(c)&&(a=e.parseCaps(a)),"object"===b.typeOf(a)){for(var f in a)if(!this.can(f,a[f],d))return!1;return!0}return"function"===b.typeOf(d[a])?d[a].call(this,c):c===d[a]},getShimContainer:function(){var a,d=c.get(this.shimid);return d||(a=this.options.container?c.get(this.options.container):document.body,d=document.createElement("div"),d.id=this.shimid,d.className="moxie-shim moxie-shim-"+this.type,b.extend(d.style,{position:"absolute",top:"0px",left:"0px",width:"1px",height:"1px",overflow:"hidden"}),a.appendChild(d),a=null),d},getShim:function(){return k},shimExec:function(a,b){var c=[].slice.call(arguments,2);return l.getShim().exec.call(this,this.uid
 ,a,b,c)},exec:function(a,b){var c=[].slice.call(arguments,2);return l[a]&&l[a][b]?l[a][b].apply(this,c):l.shimExec.apply(this,arguments)},destroy:function(){if(l){var a=c.get(this.shimid);a&&a.parentNode.removeChild(a),k&&k.removeAllInstances(),this.unbindAll(),delete g[this.uid],this.uid=null,m=l=k=a=null}}}),this.mode&&d.required_caps&&!this.can(d.required_caps)&&(this.mode=!1)}var f={},g={};return e.order="html5,html4",e.getRuntime=function(a){return!!g[a]&&g[a]},e.addConstructor=function(a,b){b.prototype=d.instance,f[a]=b},e.getConstructor=function(a){return f[a]||null},e.getInfo=function(a){var b=e.getRuntime(a);return b?{uid:b.uid,type:b.type,mode:b.mode,can:function(){return b.can.apply(b,arguments)}}:null},e.parseCaps=function(a){var c={};return"string"!==b.typeOf(a)?a||{}:(b.each(a.split(","),function(a){c[a]=!0}),c)},e.can=function(a,b){var c,d,f=e.getConstructor(a);return!!f&&(c=
 new f({required_caps:b}),d=c.mode,c.destroy(),!!d)},e.thatCan=function(a,b){var c=(b||e.order).split(/\s*,\s*/);for(var d in c)if(e.can(c[d],a))return c[d];return null},e.getMode=function(c,d,e){var f=null;if("undefined"===b.typeOf(e)&&(e="browser"),d&&!b.isEmptyObj(c)){if(b.each(d,function(d,e){if(c.hasOwnProperty(e)){var g=c[e](d);if("string"==typeof g&&(g=[g]),f){if(!(f=b.arrayIntersect(f,g)))return MXI_DEBUG&&a.debug.runtime&&a.log("\t\t%c: %v (conflicting mode requested: %s)",e,d,g),f=!1}else f=g}MXI_DEBUG&&a.debug.runtime&&a.log("\t\t%c: %v (compatible modes: %s)",e,d,f)}),f)return b.inArray(e,f)!==-1?e:f[0];if(f===!1)return!1}return e},e.capTrue=function(){return!0},e.capFalse=function(){return!1},e.capTest=function(a){return function(){return!!a}},e}),d("moxie/runtime/RuntimeClient",["moxie/core/utils/Env","moxie/core/Exceptions","moxie
 /core/utils/Basic","moxie/runtime/Runtime"],function(a,b,c,d){return function(){var e;c.extend(this,{connectRuntime:function(f){function g(c){var h,j;return c.length?(h=c.shift().toLowerCase(),(j=d.getConstructor(h))?(MXI_DEBUG&&a.debug.runtime&&(a.log("Trying runtime: %s",h),a.log(f)),e=new j(f),e.bind("Init",function(){e.initialized=!0,MXI_DEBUG&&a.debug.runtime&&a.log("Runtime '%s' initialized",e.type),setTimeout(function(){e.clients++,i.trigger("RuntimeInit",e)},1)}),e.bind("Error",function(){MXI_DEBUG&&a.debug.runtime&&a.log("Runtime '%s' failed to initialize",e.type),e.destroy(),g(c)}),MXI_DEBUG&&a.debug.runtime&&a.log("\tselected mode: %s",e.mode),e.mode?void e.init():void e.trigger("Error")):void g(c)):(i.trigger("RuntimeError",new b.RuntimeError(b.RuntimeError.NOT_INIT_ERR)),void(e=null))}var h,i=this;if(&qu
 ot;string"===c.typeOf(f)?h=f:"string"===c.typeOf(f.ruid)&&(h=f.ruid),h){if(e=d.getRuntime(h))return e.clients++,e;throw new b.RuntimeError(b.RuntimeError.NOT_INIT_ERR)}g((f.runtime_order||d.order).split(/\s*,\s*/))},disconnectRuntime:function(){e&&--e.clients<=0&&e.destroy(),e=null},getRuntime:function(){return e&&e.uid?e:e=null},exec:function(){return e?e.exec.apply(this,arguments):null}})}}),d("moxie/file/FileInput",["moxie/core/utils/Basic","moxie/core/utils/Env","moxie/core/utils/Mime","moxie/core/utils/Dom","moxie/core/Exceptions","moxie/core/EventTarget","moxie/core/I18n","moxie/runtime/Runtime","moxie/runtime/RuntimeClient"],function(a,b,c,d,e,f,g,h,i){function j(f){MXI_DEBUG&&b.log("Instantiating FileInput...");var j,l,m,n=this;if(a.inArray(a.typeOf(f),["string","node"])!==-1&&(f={b
 rowse_button:f}),l=d.get(f.browse_button),!l)throw new e.DOMException(e.DOMException.NOT_FOUND_ERR);m={accept:[{title:g.translate("All Files"),extensions:"*"}],name:"file",multiple:!1,required_caps:!1,container:l.parentNode||document.body},f=a.extend({},m,f),"string"==typeof f.required_caps&&(f.required_caps=h.parseCaps(f.required_caps)),"string"==typeof f.accept&&(f.accept=c.mimes2extList(f.accept)),j=d.get(f.container),j||(j=document.body),"static"===d.getStyle(j,"position")&&(j.style.position="relative"),j=l=null,i.call(n),a.extend(n,{uid:a.guid("uid_"),ruid:null,shimid:null,files:null,init:function(){n.bind("RuntimeInit",function(b,c){n.ruid=c.uid,n.shimid=c.shimid,n.bind("Ready",function(){n.trigger("Refresh")},999),n.bind("Refresh",function(){var b,e,g,h;g=d.get(f.browse_button),h=d.get(c.shimid),g&&(b=d.getPos(g,d.ge
 t(f.container)),e=d.getSize(g),h&&a.extend(h.style,{top:b.y+"px",left:b.x+"px",width:e.w+"px",height:e.h+"px"})),h=g=null}),c.exec.call(n,"FileInput","init",f)}),n.connectRuntime(a.extend({},f,{required_caps:{select_file:!0}}))},disable:function(b){var c=this.getRuntime();c&&c.exec.call(this,"FileInput","disable","undefined"===a.typeOf(b)||b)},refresh:function(){n.trigger("Refresh")},destroy:function(){var b=this.getRuntime();b&&(b.exec.call(this,"FileInput","destroy"),this.disconnectRuntime()),"array"===a.typeOf(this.files)&&a.each(this.files,function(a){a.destroy()}),this.files=null,this.unbindAll()}}),this.handleEventProps(k)}var k=["ready","change","cancel","mouseenter","mouseleave","mousedown","mouseup"];return j.prototype=f.instance,j}),d("moxi
 e/core/utils/Encode",[],function(){var a=function(a){return unescape(encodeURIComponent(a))},b=function(a){return decodeURIComponent(escape(a))},c=function(a,c){if("function"==typeof window.atob)return c?b(window.atob(a)):window.atob(a);var d,e,f,g,h,i,j,k,l="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",m=0,n=0,o="",p=[];if(!a)return a;a+="";do g=l.indexOf(a.charAt(m++)),h=l.indexOf(a.charAt(m++)),i=l.indexOf(a.charAt(m++)),j=l.indexOf(a.charAt(m++)),k=g<<18|h<<12|i<<6|j,d=k>>16&255,e=k>>8&255,f=255&k,64==i?p[n++]=String.fromCharCode(d):64==j?p[n++]=String.fromCharCode(d,e):p[n++]=String.fromCharCode(d,e,f);while(m<a.length);return o=p.join(""),c?b(o):o},d=function(b,c){if(c&&(b=a(b)),"function"==typeof window.btoa)return window.btoa(b);var d,e,f,g,h,i,j,k,l="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",m=0,n=0,o=
 "",p=[];if(!b)return b;do d=b.charCodeAt(m++),e=b.charCodeAt(m++),f=b.charCodeAt(m++),k=d<<16|e<<8|f,g=k>>18&63,h=k>>12&63,i=k>>6&63,j=63&k,p[n++]=l.charAt(g)+l.charAt(h)+l.charAt(i)+l.charAt(j);while(m<b.length);o=p.join("");var q=b.length%3;return(q?o.slice(0,q-3):o)+"===".slice(q||3)};return{utf8_encode:a,utf8_decode:b,atob:c,btoa:d}}),d("moxie/file/Blob",["moxie/core/utils/Basic","moxie/core/utils/Encode","moxie/runtime/RuntimeClient"],function(a,b,c){function d(f,g){function h(b,c,f){var g,h=e[this.uid];return"string"===a.typeOf(h)&&h.length?(g=new d(null,{type:f,size:c-b}),g.detach(h.substr(b,g.size)),g):null}c.call(this),f&&this.connectRuntime(f),g?"string"===a.typeOf(g)&&(g={data:g}):g={},a.extend(this,{uid:g.uid||a.guid("uid_"),ruid:f,size:g.size||0,type:g.type||"",slice:function(a,b,c){return 
 this.isDetached()?h.apply(this,arguments):this.getRuntime().exec.call(this,"Blob","slice",this.getSource(),a,b,c)},getSource:function(){return e[this.uid]?e[this.uid]:null},detach:function(a){if(this.ruid&&(this.getRuntime().exec.call(this,"Blob","destroy"),this.disconnectRuntime(),this.ruid=null),a=a||"","data:"==a.substr(0,5)){var c=a.indexOf(";base64,");this.type=a.substring(5,c),a=b.atob(a.substring(c+8))}this.size=a.length,e[this.uid]=a},isDetached:function(){return!this.ruid&&"string"===a.typeOf(e[this.uid])},destroy:function(){this.detach(),delete e[this.uid]}}),g.data?this.detach(g.data):e[this.uid]=g}var e={};return d}),d("moxie/file/File",["moxie/core/utils/Basic","moxie/core/utils/Mime","moxie/file/Blob"],function(a,b,c){function d(d,e){e||(e={}),c.apply(this,arguments),this.type||(this.type=b.getFileMime(e.name));var f;if(e.name)f=e.name
 .replace(/\\/g,"/"),f=f.substr(f.lastIndexOf("/")+1);else if(this.type){var g=this.type.split("/")[0];f=a.guid((""!==g?g:"file")+"_"),b.extensions[this.type]&&(f+="."+b.extensions[this.type][0])}a.extend(this,{name:f||a.guid("file_"),relativePath:"",lastModifiedDate:e.lastModifiedDate||(new Date).toLocaleString()})}return d.prototype=c.prototype,d}),d("moxie/file/FileDrop",["moxie/core/I18n","moxie/core/utils/Dom","moxie/core/Exceptions","moxie/core/utils/Basic","moxie/core/utils/Env","moxie/file/File","moxie/runtime/RuntimeClient","moxie/core/EventTarget","moxie/core/utils/Mime"],function(a,b,c,d,e,f,g,h,i){function j(c){MXI_DEBUG&&e.log("Instantiating FileDrop...");var f,h=this;"string"==typeof c&&(c={drop_zone:c}),f={accept:[{title:a.translate("
 All Files"),extensions:"*"}],required_caps:{drag_and_drop:!0}},c="object"==typeof c?d.extend({},f,c):f,c.container=b.get(c.drop_zone)||document.body,"static"===b.getStyle(c.container,"position")&&(c.container.style.position="relative"),"string"==typeof c.accept&&(c.accept=i.mimes2extList(c.accept)),g.call(h),d.extend(h,{uid:d.guid("uid_"),ruid:null,files:null,init:function(){h.bind("RuntimeInit",function(a,b){h.ruid=b.uid,b.exec.call(h,"FileDrop","init",c),h.dispatchEvent("ready")}),h.connectRuntime(c)},destroy:function(){var a=this.getRuntime();a&&(a.exec.call(this,"FileDrop","destroy"),this.disconnectRuntime()),this.files=null,this.unbindAll()}}),this.handleEventProps(k)}var k=["ready","dragenter","dragleave","drop","error"];return j.prototype=h.instance,j}),d("moxie/fil
 e/FileReader",["moxie/core/utils/Basic","moxie/core/utils/Encode","moxie/core/Exceptions","moxie/core/EventTarget","moxie/file/Blob","moxie/runtime/RuntimeClient"],function(a,b,c,d,e,f){function g(){function d(a,d){if(this.trigger("loadstart"),this.readyState===g.LOADING)return this.trigger("error",new c.DOMException(c.DOMException.INVALID_STATE_ERR)),void this.trigger("loadend");if(!(d instanceof e))return this.trigger("error",new c.DOMException(c.DOMException.NOT_FOUND_ERR)),void this.trigger("loadend");if(this.result=null,this.readyState=g.LOADING,d.isDetached()){var f=d.getSource();switch(a){case"readAsText":case"readAsBinaryString":this.result=f;break;case"readAsDataURL":this.result="data:"+d.type+";base64,"+b.btoa(f)}this.readyState=g.DONE,this.trigger("load"),this.trigger("loadend")}else this.c
 onnectRuntime(d.ruid),this.exec("FileReader","read",a,d);
+}f.call(this),a.extend(this,{uid:a.guid("uid_"),readyState:g.EMPTY,result:null,error:null,readAsBinaryString:function(a){d.call(this,"readAsBinaryString",a)},readAsDataURL:function(a){d.call(this,"readAsDataURL",a)},readAsText:function(a){d.call(this,"readAsText",a)},abort:function(){this.result=null,a.inArray(this.readyState,[g.EMPTY,g.DONE])===-1&&(this.readyState===g.LOADING&&(this.readyState=g.DONE),this.exec("FileReader","abort"),this.trigger("abort"),this.trigger("loadend"))},destroy:function(){this.abort(),this.exec("FileReader","destroy"),this.disconnectRuntime(),this.unbindAll()}}),this.handleEventProps(h),this.bind("Error",function(a,b){this.readyState=g.DONE,this.error=b},999),this.bind("Load",function(a){this.readyState=g.DONE},999)}var h=["loadstart","progress","load","abort","error",&qu
 ot;loadend"];return g.EMPTY=0,g.LOADING=1,g.DONE=2,g.prototype=d.instance,g}),d("moxie/core/utils/Url",[],function(){var a=function(b,c){for(var d=["source","scheme","authority","userInfo","user","pass","host","port","relative","path","directory","file","query","fragment"],e=d.length,f={http:80,https:443},g={},h=/^(?:([^:\/?#]+):)?(?:\/\/()(?:(?:()(?:([^:@\/]*):?([^:@\/]*))?@)?([^:\/?#]*)(?::(\d*))?))?()(?:(()(?:(?:[^?#\/]*\/)*)()(?:[^?#]*))(?:\\?([^#]*))?(?:#(.*))?)/,i=h.exec(b||"");e--;)i[e]&&(g[d[e]]=i[e]);if(!g.scheme){c&&"string"!=typeof c||(c=a(c||document.location.href)),g.scheme=c.scheme,g.host=c.host,g.port=c.port;var j="";/^[^\/]/.test(g.path)&&(j=c.path,j=/\/[^\/]*\.[^\/]*$/.test(j)?j.replace(/\/[^\/]+$/,"/"):j.replace(/\/?$/,"/")),g.path=j+(g.pat
 h||"")}return g.port||(g.port=f[g.scheme]||80),g.port=parseInt(g.port,10),g.path||(g.path="/"),delete g.source,g},b=function(b){var c={http:80,https:443},d="object"==typeof b?b:a(b);return d.scheme+"://"+d.host+(d.port!==c[d.scheme]?":"+d.port:"")+d.path+(d.query?d.query:"")},c=function(b){function c(a){return[a.scheme,a.host,a.port].join("/")}return"string"==typeof b&&(b=a(b)),c(a())===c(b)};return{parseUrl:a,resolveUrl:b,hasSameOrigin:c}}),d("moxie/runtime/RuntimeTarget",["moxie/core/utils/Basic","moxie/runtime/RuntimeClient","moxie/core/EventTarget"],function(a,b,c){function d(){this.uid=a.guid("uid_"),b.call(this),this.destroy=function(){this.disconnectRuntime(),this.unbindAll()}}return d.prototype=c.instance,d}),d("moxie/file/FileReaderSync",["moxie/core/utils/Basic","moxie/runtime/RuntimeClient","
 moxie/core/utils/Encode"],function(a,b,c){return function(){function d(a,b){if(!b.isDetached()){var d=this.connectRuntime(b.ruid).exec.call(this,"FileReaderSync","read",a,b);return this.disconnectRuntime(),d}var e=b.getSource();switch(a){case"readAsBinaryString":return e;case"readAsDataURL":return"data:"+b.type+";base64,"+c.btoa(e);case"readAsText":for(var f="",g=0,h=e.length;g<h;g++)f+=String.fromCharCode(e[g]);return f}}b.call(this),a.extend(this,{uid:a.guid("uid_"),readAsBinaryString:function(a){return d.call(this,"readAsBinaryString",a)},readAsDataURL:function(a){return d.call(this,"readAsDataURL",a)},readAsText:function(a){return d.call(this,"readAsText",a)}})}}),d("moxie/xhr/FormData",["moxie/core/Exceptions","moxie/core/utils/Basic","moxie/file/Blob"],function(a,b,c){function d(){var a,d=[];b.extend(this,{appen
 d:function(e,f){var g=this,h=b.typeOf(f);f instanceof c?a={name:e,value:f}:"array"===h?(e+="[]",b.each(f,function(a){g.append(e,a)})):"object"===h?b.each(f,function(a,b){g.append(e+"["+b+"]",a)}):"null"===h||"undefined"===h||"number"===h&&isNaN(f)?g.append(e,"false"):d.push({name:e,value:f.toString()})},hasBlob:function(){return!!this.getBlob()},getBlob:function(){return a&&a.value||null},getBlobName:function(){return a&&a.name||null},each:function(c){b.each(d,function(a){c(a.value,a.name)}),a&&c(a.value,a.name)},destroy:function(){a=null,d=[]}})}return d}),d("moxie/xhr/XMLHttpRequest",["moxie/core/utils/Basic","moxie/core/Exceptions","moxie/core/EventTarget","moxie/core/utils/Encode","moxie/core/utils/Url","moxie/runtime/Runtime","moxie/runtime/RuntimeTarget","moxie/file/Blob&qu
 ot;,"moxie/file/FileReaderSync","moxie/xhr/FormData","moxie/core/utils/Env","moxie/core/utils/Mime"],function(a,b,c,d,e,f,g,h,i,j,k,l){function m(){this.uid=a.guid("uid_")}function n(){function c(a,b){if(A.hasOwnProperty(a))return 1===arguments.length?k.can("define_property")?A[a]:z[a]:void(k.can("define_property")?A[a]=b:z[a]=b)}function i(b){function d(){x&&(x.destroy(),x=null),h.dispatchEvent("loadend"),h=null}function e(e){x.bind("LoadStart",function(a){c("readyState",n.LOADING),h.dispatchEvent("readystatechange"),h.dispatchEvent(a),H&&h.upload.dispatchEvent(a)}),x.bind("Progress",function(a){c("readyState")!==n.LOADING&&(c("readyState",n.LOADING),h.dispatchEvent("readystatechange")),h.dispatchEvent(a)}),x.bind("UploadProgress",function(a){H&&h.upload.dispatchEvent({type:"progress&quot
 ;,lengthComputable:!1,total:a.total,loaded:a.loaded})}),x.bind("Load",function(b){c("readyState",n.DONE),c("status",Number(e.exec.call(x,"XMLHttpRequest","getStatus")||0)),c("statusText",o[c("status")]||""),c("response",e.exec.call(x,"XMLHttpRequest","getResponse",c("responseType"))),~a.inArray(c("responseType"),["text",""])?c("responseText",c("response")):"document"===c("responseType")&&c("responseXML",c("response")),O=e.exec.call(x,"XMLHttpRequest","getAllResponseHeaders"),h.dispatchEvent("readystatechange"),c("status")>0?(H&&h.upload.dispatchEvent(b),h.dispatchEvent(b)):(J=!0,h.dispatchEvent("error")),d()}),x.bind("Abort",function(a){h.dispatchEvent(a),d()}),x.bind("Error",function(a){J
 =!0,c("readyState",n.DONE),h.dispatchEvent("readystatechange"),I=!0,h.dispatchEvent(a),d()}),e.exec.call(x,"XMLHttpRequest","send",{url:r,method:s,async:B,user:t,password:u,headers:C,mimeType:E,encoding:D,responseType:h.responseType,withCredentials:h.withCredentials,options:N},b)}var h=this;v=(new Date).getTime(),x=new g,"string"==typeof N.required_caps&&(N.required_caps=f.parseCaps(N.required_caps)),N.required_caps=a.extend({},N.required_caps,{return_response_type:h.responseType}),b instanceof j&&(N.required_caps.send_multipart=!0),a.isEmptyObj(C)||(N.required_caps.send_custom_headers=!0),K||(N.required_caps.do_cors=!0),N.ruid?e(x.connectRuntime(N)):(x.bind("RuntimeInit",function(a,b){e(b)}),x.bind("RuntimeError",function(a,b){h.dispatchEvent("RuntimeError",b)}),x.connectRuntime(N))}function q(){c("responseText",""),c("responseXML",null),c("response&quo
 t;,null),c("status",0),c("statusText",""),v=w=null}var r,s,t,u,v,w,x,y,z=this,A={timeout:0,readyState:n.UNSENT,withCredentials:!1,status:0,statusText:"",responseType:"",responseXML:null,responseText:null,response:null},B=!0,C={},D=null,E=null,F=!1,G=!1,H=!1,I=!1,J=!1,K=!1,L=null,M=null,N={},O="";a.extend(this,A,{uid:a.guid("uid_"),upload:new m,open:function(f,g,h,i,j){var k;if(!f||!g)throw new b.DOMException(b.DOMException.SYNTAX_ERR);if(/[\u0100-\uffff]/.test(f)||d.utf8_encode(f)!==f)throw new b.DOMException(b.DOMException.SYNTAX_ERR);if(~a.inArray(f.toUpperCase(),["CONNECT","DELETE","GET","HEAD","OPTIONS","POST","PUT","TRACE","TRACK"])&&(s=f.toUpperCase()),~a.inArray(s,["CONNECT","TRACE","TRACK"]))throw new b.DOMException(b.DOMException.SECURITY_ERR);if(g=d.utf8_encode(g),k=e.parseUrl(g
 ),K=e.hasSameOrigin(k),r=e.resolveUrl(g),(i||j)&&!K)throw new b.DOMException(b.DOMException.INVALID_ACCESS_ERR);if(t=i||k.user,u=j||k.pass,B=h||!0,B===!1&&(c("timeout")||c("withCredentials")||""!==c("responseType")))throw new b.DOMException(b.DOMException.INVALID_ACCESS_ERR);F=!B,G=!1,C={},q.call(this),c("readyState",n.OPENED),this.dispatchEvent("readystatechange")},setRequestHeader:function(e,f){var g=["accept-charset","accept-encoding","access-control-request-headers","access-control-request-method","connection","content-length","cookie","cookie2","content-transfer-encoding","date","expect","host","keep-alive","origin","referer","te","trailer","transfer-encoding","upgrade","user-agent","via"];if(c(&q
 uot;readyState")!==n.OPENED||G)throw new b.DOMException(b.DOMException.INVALID_STATE_ERR);if(/[\u0100-\uffff]/.test(e)||d.utf8_encode(e)!==e)throw new b.DOMException(b.DOMException.SYNTAX_ERR);return e=a.trim(e).toLowerCase(),!~a.inArray(e,g)&&!/^(proxy\-|sec\-)/.test(e)&&(C[e]?C[e]+=", "+f:C[e]=f,!0)},getAllResponseHeaders:function(){return O||""},getResponseHeader:function(b){return b=b.toLowerCase(),J||~a.inArray(b,["set-cookie","set-cookie2"])?null:O&&""!==O&&(y||(y={},a.each(O.split(/\r\n/),function(b){var c=b.split(/:\s+/);2===c.length&&(c[0]=a.trim(c[0]),y[c[0].toLowerCase()]={header:c[0],value:a.trim(c[1])})})),y.hasOwnProperty(b))?y[b].header+": "+y[b].value:null},overrideMimeType:function(d){var e,f;if(~a.inArray(c("readyState"),[n.LOADING,n.DONE]))throw new b.DOMException(b.DOMException.INVALID_STATE_ERR);if(d=a.trim(d.toLowerCase()),/;/.test(d)&&(e=d
 .match(/^([^;]+)(?:;\scharset\=)?(.*)$/))&&(d=e[1],e[2]&&(f=e[2])),!l.mimes[d])throw new b.DOMException(b.DOMException.SYNTAX_ERR);L=d,M=f},send:function(c,e){if(N="string"===a.typeOf(e)?{ruid:e}:e?e:{},this.readyState!==n.OPENED||G)throw new b.DOMException(b.DOMException.INVALID_STATE_ERR);if(c instanceof h)N.ruid=c.ruid,E=c.type||"application/octet-stream";else if(c instanceof j){if(c.hasBlob()){var f=c.getBlob();N.ruid=f.ruid,E=f.type||"application/octet-stream"}}else"string"==typeof c&&(D="UTF-8",E="text/plain;charset=UTF-8",c=d.utf8_encode(c));this.withCredentials||(this.withCredentials=N.required_caps&&N.required_caps.send_browser_cookies&&!K),H=!F&&this.upload.hasEventListener(),J=!1,I=!c,F||(G=!0),i.call(this,c)},abort:function(){if(J=!0,F=!1,~a.inArray(c("readyState"),[n.UNSENT,n.OPENED,n.DONE]))c("readyState",n.UNSENT);else{if(c("readyState&q
 uot;,n.DONE),G=!1,!x)throw new b.DOMException(b.DOMException.INVALID_STATE_ERR);x.getRuntime().exec.call(x,"XMLHttpRequest","abort",I),I=!0}},destroy:function(){x&&("function"===a.typeOf(x.destroy)&&x.destroy(),x=null),this.unbindAll(),this.upload&&(this.upload.unbindAll(),this.upload=null)}}),this.handleEventProps(p.concat(["readystatechange"])),this.upload.handleEventProps(p)}var o={100:"Continue",101:"Switching Protocols",102:"Processing",200:"OK",201:"Created",202:"Accepted",203:"Non-Authoritative Information",204:"No Content",205:"Reset Content",206:"Partial Content",207:"Multi-Status",226:"IM Used",300:"Multiple Choices",301:"Moved Permanently",302:"Found",303:"See Other",304:"Not Modified",305:"Use Proxy",306:"Reserved",307:&q
 uot;Temporary Redirect",400:"Bad Request",401:"Unauthorized",402:"Payment Required",403:"Forbidden",404:"Not Found",405:"Method Not Allowed",406:"Not Acceptable",407:"Proxy Authentication Required",408:"Request Timeout",409:"Conflict",410:"Gone",411:"Length Required",412:"Precondition Failed",413:"Request Entity Too Large",414:"Request-URI Too Long",415:"Unsupported Media Type",416:"Requested Range Not Satisfiable",417:"Expectation Failed",422:"Unprocessable Entity",423:"Locked",424:"Failed Dependency",426:"Upgrade Required",500:"Internal Server Error",501:"Not Implemented",502:"Bad Gateway",503:"Service Unavailable",504:"Gateway Timeout",505:"HTTP Version Not Supported",506:"Variant Also Negotiate
 s",507:"Insufficient Storage",510:"Not Extended"};m.prototype=c.instance;var p=["loadstart","progress","abort","error","load","timeout","loadend"];return n.UNSENT=0,n.OPENED=1,n.HEADERS_RECEIVED=2,n.LOADING=3,n.DONE=4,n.prototype=c.instance,n}),d("moxie/runtime/Transporter",["moxie/core/utils/Basic","moxie/core/utils/Encode","moxie/runtime/RuntimeClient","moxie/core/EventTarget"],function(a,b,c,d){function e(){function d(){k=l=0,j=this.result=null}function f(b,c){var d=this;i=c,d.bind("TransportingProgress",function(b){l=b.loaded,l<k&&a.inArray(d.state,[e.IDLE,e.DONE])===-1&&g.call(d)},999),d.bind("TransportingComplete",function(){l=k,d.state=e.DONE,j=null,d.result=i.exec.call(d,"Transporter","getAsBlob",b||"")},999),d.state=e.BUSY,d.trigger("TransportingStarted"
 ),g.call(d)}function g(){var a,c=this,d=k-l;m>d&&(m=d),a=b.btoa(j.substr(l,m)),i.exec.call(c,"Transporter","receive",a,k)}var h,i,j,k,l,m;c.call(this),a.extend(this,{uid:a.guid("uid_"),state:e.IDLE,result:null,transport:function(b,c,e){var g=this;if(e=a.extend({chunk_size:204798},e),(h=e.chunk_size%3)&&(e.chunk_size+=3-h),m=e.chunk_size,d.call(this),j=b,k=b.length,"string"===a.typeOf(e)||e.ruid)f.call(g,c,this.connectRuntime(e));else{var i=function(a,b){g.unbind("RuntimeInit",i),f.call(g,c,b)};this.bind("RuntimeInit",i),this.connectRuntime(e)}},abort:function(){var a=this;a.state=e.IDLE,i&&(i.exec.call(a,"Transporter","clear"),a.trigger("TransportingAborted")),d.call(a)},destroy:function(){this.unbindAll(),i=null,this.disconnectRuntime(),d.call(this)}})}return e.IDLE=0,e.BUSY=1,e.DONE=2,e.prototype=d.instance,e}),d("moxie/image/Image",["moxie/core/utils
 /Basic","moxie/core/utils/Dom","moxie/core/Exceptions","moxie/file/FileReaderSync","moxie/xhr/XMLHttpRequest","moxie/runtime/Runtime","moxie/runtime/RuntimeClient","moxie/runtime/Transporter","moxie/core/utils/Env","moxie/core/EventTarget","moxie/file/Blob","moxie/file/File","moxie/core/utils/Encode"],function(a,b,c,d,e,f,g,h,i,j,k,l,m){function n(){function d(a){a||(a=this.exec("Image","getInfo")),this.size=a.size,this.width=a.width,this.height=a.height,this.type=a.type,this.meta=a.meta,""===this.name&&(this.name=a.name)}function j(b){var d=a.typeOf(b);try{if(b instanceof n){if(!b.size)throw new c.DOMException(c.DOMException.INVALID_STATE_ERR);p.apply(this,arguments)}else if(b instanceof k){if(!~a.inArray(b.type,["image/jpeg","image/png"]))throw new c.ImageError(c.ImageError.WRONG_FORMAT);q.apply(this,
 arguments)}else if(a.inArray(d,["blob","file"])!==-1)j.call(this,new l(null,b),arguments[1]);else if("string"===d)"data:"===b.substr(0,5)?j.call(this,new k(null,{data:b}),arguments[1]):r.apply(this,arguments);else{if("node"!==d||"img"!==b.nodeName.toLowerCase())throw new c.DOMException(c.DOMException.TYPE_MISMATCH_ERR);j.call(this,b.src,arguments[1])}}catch(e){this.trigger("error",e.code)}}function p(b,c){var d=this.connectRuntime(b.ruid);this.ruid=d.uid,d.exec.call(this,"Image","loadFromImage",b,"undefined"===a.typeOf(c)||c)}function q(b,c){function d(a){e.ruid=a.uid,a.exec.call(e,"Image","loadFromBlob",b)}var e=this;e.name=b.name||"",b.isDetached()?(this.bind("RuntimeInit",function(a,b){d(b)}),c&&"string"==typeof c.required_caps&&(c.required_caps=f.parseCaps(c.required_caps)),this.connectRuntime(a.extend({required_cap
 s:{access_image_binary:!0,resize_image:!0}},c))):d(this.connectRuntime(b.ruid))}function r(a,b){var c,d=this;c=new e,c.open("get",a),c.responseType="blob",c.onprogress=function(a){d.trigger(a)},c.onload=function(){q.call(d,c.response,!0)},c.onerror=function(a){d.trigger(a)},c.onloadend=function(){c.destroy()},c.bind("RuntimeError",function(a,b){d.trigger("RuntimeError",b)}),c.send(null,b)}g.call(this),a.extend(this,{uid:a.guid("uid_"),ruid:null,name:"",size:0,width:0,height:0,type:"",meta:{},clone:function(){this.load.apply(this,arguments)},load:function(){j.apply(this,arguments)},downsize:function(b){var d={width:this.width,height:this.height,type:this.type||"image/jpeg",quality:90,crop:!1,preserveHeaders:!0,resample:!1};b="object"==typeof b?a.extend(d,b):a.extend(d,{width:arguments[0],height:arguments[1],crop:arguments[2],preserveHeaders:arguments[3]});try{if(!this.size)throw new c.DOMExcepti
 on(c.DOMException.INVALID_STATE_ERR);if(this.width>n.MAX_RESIZE_WIDTH||this.height>n.MAX_RESIZE_HEIGHT)throw new c.ImageError(c.ImageError.MAX_RESOLUTION_ERR);this.exec("Image","downsize",b.width,b.height,b.crop,b.preserveHeaders)}catch(e){this.trigger("error",e.code)}},crop:function(a,b,c){this.downsize(a,b,!0,c)},getAsCanvas:function(){if(!i.can("create_canvas"))throw new c.RuntimeError(c.RuntimeError.NOT_SUPPORTED_ERR);var a=this.connectRuntime(this.ruid);return a.exec.call(this,"Image","getAsCanvas")},getAsBlob:function(a,b){if(!this.size)throw new c.DOMException(c.DOMException.INVALID_STATE_ERR);return this.exec("Image","getAsBlob",a||"image/jpeg",b||90)},getAsDataURL:function(a,b){if(!this.size)throw new c.DOMException(c.DOMException.INVALID_STATE_ERR);return this.exec("Image","getAsDataURL",a||"image/jpeg",b||90)},getAsBinaryString:function(a,b){var c=
 this.getAsDataURL(a,b);return m.atob(c.substring(c.indexOf("base64,")+7))},embed:function(d,e){function f(b,e){var f=this;if(i.can("create_canvas")){var k=f.getAsCanvas();if(k)return d.appendChild(k),k=null,f.destroy(),void j.trigger("embedded")}var l=f.getAsDataURL(b,e);if(!l)throw new c.ImageError(c.ImageError.WRONG_FORMAT);if(i.can("use_data_uri_of",l.length))d.innerHTML='<img src="'+l+'" width="'+f.width+'" height="'+f.height+'" />',f.destroy(),j.trigger("embedded");else{var n=new h;n.bind("TransportingComplete",function(){g=j.connectRuntime(this.result.ruid),j.bind("Embedded",function(){a.extend(g.getShimContainer().style,{top:"0px",left:"0px",width:f.width+"px",height:f.height+"px"}),g=null},999),g.exec.call(j,"ImageView","display",this.result.uid,width,height),f.destroy()}),n.transport(m.atob(l.substring(l.indexO
 f("base64,")+7)),b,{required_caps:{display_media:!0},runtime_order:"flash,silverlight",container:d})}}var g,j=this;e=a.extend({width:this.width,height:this.height,type:this.type||"image/jpeg",quality:90},e||{});try{if(!(d=b.get(d)))throw new c.DOMException(c.DOMException.INVALID_NODE_TYPE_ERR);if(!this.size)throw new c.DOMException(c.DOMException.INVALID_STATE_ERR);this.width>n.MAX_RESIZE_WIDTH||this.height>n.MAX_RESIZE_HEIGHT;var k=new n;return k.bind("Resize",function(){f.call(this,e.type,e.quality)}),k.bind("Load",function(){k.downsize(e)}),this.meta.thumb&&this.meta.thumb.width>=e.width&&this.meta.thumb.height>=e.height?k.load(this.meta.thumb.data):k.clone(this,!1),k}catch(l){this.trigger("error",l.code)}},destroy:function(){this.ruid&&(this.getRuntime().exec.call(this,"Image","destroy"),this.disconnectRuntime()),this.unbindAll()}}),this.handleEventProps(o),this.bi
 nd("Load Resize",function(){d.call(this)},999)}var o=["progress","load","error","resize","embedded"];return n.MAX_RESIZE_WIDTH=8192,n.MAX_RESIZE_HEIGHT=8192,n.prototype=j.instance,n}),d("moxie/runtime/html5/Runtime",["moxie/core/utils/Basic","moxie/core/Exceptions","moxie/runtime/Runtime","moxie/core/utils/Env"],function(a,b,c,d){function e(b){var e=this,h=c.capTest,i=c.capTrue,j=a.extend({access_binary:h(window.FileReader||window.File&&window.File.getAsDataURL),access_image_binary:function(){return e.can("access_binary")&&!!g.Image},display_media:h(d.can("create_canvas")||d.can("use_data_uri_over32kb")),do_cors:h(window.XMLHttpRequest&&"withCredentials"in new XMLHttpRequest),drag_and_drop:h(function(){var a=document.createElement("div");return("draggable"in a||"ondragstart"in a&amp
 ;&"ondrop"in a)&&("IE"!==d.browser||d.verComp(d.version,9,">"))}()),filter_by_extension:h(function(){return"Chrome"===d.browser&&d.verComp(d.version,28,">=")||"IE"===d.browser&&d.verComp(d.version,10,">=")||"Safari"===d.browser&&d.verComp(d.version,7,">=")}()),return_response_headers:i,return_response_type:function(a){return!("json"!==a||!window.JSON)||d.can("return_response_type",a)},return_status_code:i,report_upload_progress:h(window.XMLHttpRequest&&(new XMLHttpRequest).upload),resize_image:function(){return e.can("access_binary")&&d.can("create_canvas")},select_file:function(){return d.can("use_fileinput")&&window.File},select_folder:function(){return e.can("select_file")&&"Chrome"===d.browser&&d.verComp(d.version,21,">=")
 },select_multiple:function(){return e.can("select_file")&&!("Safari"===d.browser&&"Windows"===d.os)&&!("iOS"===d.os&&d.verComp(d.osVersion,"7.0.0",">")&&d.verComp(d.osVersion,"8.0.0","<"))},send_binary_string:h(window.XMLHttpRequest&&((new XMLHttpRequest).sendAsBinary||window.Uint8Array&&window.ArrayBuffer)),send_custom_headers:h(window.XMLHttpRequest),send_multipart:function(){return!!(window.XMLHttpRequest&&(new XMLHttpRequest).upload&&window.FormData)||e.can("send_binary_string")},slice_blob:h(window.File&&(File.prototype.mozSlice||File.prototype.webkitSlice||File.prototype.slice)),stream_upload:function(){return e.can("slice_blob")&&e.can("send_multipart")},summon_file_dialog:function(){return e.can("select_file")&&("Firefox"===d.browser&&d.ve
 rComp(d.version,4,">=")||"Opera"===d.browser&&d.verComp(d.version,12,">=")||"IE"===d.browser&&d.verComp(d.version,10,">=")||!!~a.inArray(d.browser,["Chrome","Safari"]))},upload_filesize:i},arguments[2]);c.call(this,b,arguments[1]||f,j),a.extend(this,{init:function(){this.trigger("Init")},destroy:function(a){return function(){a.call(e),a=e=null}}(this.destroy)}),a.extend(this.getShim(),g)}var f="html5",g={};return c.addConstructor(f,e),g}),d("moxie/core/utils/Events",["moxie/core/utils/Basic"],function(a){function b(){this.returnValue=!1}function c(){this.cancelBubble=!0}var d={},e="moxie_"+a.guid(),f=function(f,g,h,i){var j,k;g=g.toLowerCase(),f.addEventListener?(j=h,f.addEventListener(g,j,!1)):f.attachEvent&&(j=function(){var a=window.event;a.target||(a.target=a.srcElement),a.preventDefault=b,a.stopPropagation=c,h(a)},f.attachEvent
 ("on"+g,j)),f[e]||(f[e]=a.guid()),d.hasOwnProperty(f[e])||(d[f[e]]={}),k=d[f[e]],k.hasOwnProperty(g)||(k[g]=[]),k[g].push({func:j,orig:h,key:i})},g=function(b,c,f){var g,h;if(c=c.toLowerCase(),b[e]&&d[b[e]]&&d[b[e]][c]){g=d[b[e]][c];for(var i=g.length-1;i>=0&&(g[i].orig!==f&&g[i].key!==f||(b.removeEventListener?b.removeEventListener(c,g[i].func,!1):b.detachEvent&&b.detachEvent("on"+c,g[i].func),g[i].orig=null,g[i].func=null,g.splice(i,1),f===h));i--);if(g.length||delete d[b[e]][c],a.isEmptyObj(d[b[e]])){delete d[b[e]];try{delete b[e]}catch(j){b[e]=h}}}},h=function(b,c){b&&b[e]&&a.each(d[b[e]],function(a,d){g(b,d,c)})};return{addEvent:f,removeEvent:g,removeAllEvents:h}}),d("moxie/runtime/html5/file/FileInput",["moxie/runtime/html5/Runtime","moxie/file/File","moxie/core/utils/Basic","moxie/core/utils/Dom","moxie/core/utils/Events","moxie/core/
 utils/Mime","moxie/core/utils/Env"],function(a,b,c,d,e,f,g){function h(){var a;c.extend(this,{init:function(h){var i,j,k,l,m,n,o=this,p=o.getRuntime();a=h,k=a.accept.mimes||f.extList2mimes(a.accept,p.can("filter_by_extension")),j=p.getShimContainer(),j.innerHTML='<input id="'+p.uid+'" type="file" style="font-size:999px;opacity:0;"'+(a.multiple&&p.can("select_multiple")?"multiple":"")+(a.directory&&p.can("select_folder")?"webkitdirectory directory":"")+(k?' accept="'+k.join(",")+'"':"")+" />",i=d.get(p.uid),c.extend(i.style,{position:"absolute",top:0,left:0,width:"100%",height:"100%"}),l=d.get(a.browse_button),p.can("summon_file_dialog")&&("static"===d.getStyle(l,"position")&&(l.style.position="relative"),m=parseInt(d.getStyl
 e(l,"z-index"),10)||1,l.style.zIndex=m,j.style.zIndex=m-1,e.addEvent(l,"click",function(a){var b=d.get(p.uid);b&&!b.disabled&&b.click(),a.preventDefault()},o.uid)),n=p.can("summon_file_dialog")?l:j,e.addEvent(n,"mouseover",function(){o.trigger("mouseenter")},o.uid),e.addEvent(n,"mouseout",function(){o.trigger("mouseleave")},o.uid),e.addEvent(n,"mousedown",function(){o.trigger("mousedown")},o.uid),e.addEvent(d.get(a.container),"mouseup",function(){o.trigger("mouseup")},o.uid),i.onchange=function q(d){if(o.files=[],c.each(this.files,function(c){var d="";return!(!a.directory||"."!=c.name)||(c.webkitRelativePath&&(d="/"+c.webkitRelativePath.replace(/^\//,"")),c=new b(p.uid,c),c.relativePath=d,void o.files.push(c))}),"IE"!==g.browser&&"IEMobile"!==g.browser)this.value="";else{var
  e=this.cloneNode(!0);this.parentNode.replaceChild(e,this),e.onchange=q}o.files.length&&o.trigger("change")},o.trigger({type:"ready",async:!0}),j=null},disable:function(a){var b,c=this.getRuntime();(b=d.get(c.uid))&&(b.disabled=!!a)},destroy:function(){var b=this.getRuntime(),c=b.getShim(),f=b.getShimContainer();e.removeAllEvents(f,this.uid),e.removeAllEvents(a&&d.get(a.container),this.uid),e.removeAllEvents(a&&d.get(a.browse_button),this.uid),f&&(f.innerHTML=""),c.removeInstance(this.uid),a=f=c=null}})}return a.FileInput=h}),d("moxie/runtime/html5/file/Blob",["moxie/runtime/html5/Runtime","moxie/file/Blob"],function(a,b){function c(){function a(a,b,c){var d;if(!window.File.prototype.slice)return(d=window.File.prototype.webkitSlice||window.File.prototype.mozSlice)?d.call(a,b,c):null;try{return a.slice(),a.slice(b,c)}catch(e){return a.slice(b,c-b)}}this.slice=function(){return new b(th
 is.getRuntime().uid,a.apply(this,arguments))}}return a.Blob=c}),d("moxie/runtime/html5/file/FileDrop",["moxie/runtime/html5/Runtime","moxie/file/File","moxie/core/utils/Basic","moxie/core/utils/Dom","moxie/core/utils/Events","moxie/core/utils/Mime"],function(a,b,c,d,e,f){function g(){function a(a){if(!a.dataTransfer||!a.dataTransfer.types)return!1;var b=c.toArray(a.dataTransfer.types||[]);return c.inArray("Files",b)!==-1||c.inArray("public.file-url",b)!==-1||c.inArray("application/x-moz-file",b)!==-1}function g(a,c){if(i(a)){var d=new b(o,a);d.relativePath=c||"",p.push(d)}}function h(a){for(var b=[],d=0;d<a.length;d++)[].push.apply(b,a[d].extensions.split(/\s*,\s*/));return c.inArray("*",b)===-1?b:[]}function i(a){if(!q.length)return!0;var b=f.getFileExtension(a.name);return!b||c.inArray(b,q)!==-1}function j(a,b){var d=[];c.each(a,function(a){var b=a.webkitGetAs
 Entry();b&&(b.isFile?g(a.getAsFile(),b.fullPath):d.push(b))}),d.length?k(d,b):b()}function k(a,b){var d=[];c.each(a,function(a){d.push(function(b){l(a,b)})}),c.inSeries(d,function(){b()})}function l(a,b){a.isFile?a.file(function(c){g(c,a.fullPath),b()},function(){b()}):a.isDirectory?m(a,b):b()}function m(a,b){function c(a){e.readEntries(function(b){b.length?([].push.apply(d,b),c(a)):a()},a)}var d=[],e=a.createReader();c(function(){k(d,b)})}var n,o,p=[],q=[];c.extend(this,{init:function(b){var d,f=this;n=b,o=f.ruid,q=h(n.accept),d=n.container,e.addEvent(d,"dragover",function(b){a(b)&&(b.preventDefault(),b.dataTransfer.dropEffect="copy")},f.uid),e.addEvent(d,"drop",function(b){a(b)&&(b.preventDefault(),p=[],b.dataTransfer.items&&b.dataTransfer.items[0].webkitGetAsEntry?j(b.dataTransfer.items,function(){f.files=p,f.trigger("drop")}):(c.each(b.dataTransfer.files,function(a){g(a)}),f.files=p,f.trigger("drop&quot
 ;)))},f.uid),e.addEvent(d,"dragenter",function(a){f.trigger("dragenter")},f.uid),e.addEvent(d,"dragleave",function(a){f.trigger("dragleave")},f.uid)},destroy:function(){e.removeAllEvents(n&&d.get(n.container),this.uid),o=p=q=n=null}})}return a.FileDrop=g}),d("moxie/runtime/html5/file/FileReader",["moxie/runtime/html5/Runtime","moxie/core/utils/Encode","moxie/core/utils/Basic"],function(a,b,c){function d(){function a(a){return b.atob(a.substring(a.indexOf("base64,")+7))}var d,e=!1;c.extend(this,{read:function(b,f){var g=this;g.result="",d=new window.FileReader,d.addEventListener("progress",function(a){g.trigger(a)}),d.addEventListener("load",function(b){g.result=e?a(d.result):d.result,g.trigger(b)}),d.addEventListener("error",function(a){g.trigger(a,d.error)}),d.addEventListener("loadend",function(a){d=null,g.trigger(a)}),"function&q
 uot;===c.typeOf(d[b])?(e=!1,d[b](f.getSource())):"readAsBinaryString"===b&&(e=!0,d.readAsDataURL(f.getSource()))},abort:function(){d&&d.abort()},destroy:function(){d=null}})}return a.FileReader=d}),d("moxie/runtime/html5/xhr/XMLHttpRequest",["moxie/runtime/html5/Runtime","moxie/core/utils/Basic","moxie/core/utils/Mime","moxie/core/utils/Url","moxie/file/File","moxie/file/Blob","moxie/xhr/FormData","moxie/core/Exceptions","moxie/core/utils/Env"],function(a,b,c,d,e,f,g,h,i){function j(){function a(a,b){var c,d,e=this;c=b.getBlob().getSource(),d=new window.FileReader,d.onload=function(){b.append(b.getBlobName(),new f(null,{type:c.type,data:d.result})),o.send.call(e,a,b)},d.readAsBinaryString(c)}function j(){return!window.XMLHttpRequest||"IE"===i.browser&&i.verComp(i.version,8,"<")?function(){for(var a=["Msxml2.XMLHTTP.6.0&quot
 ;,"Microsoft.XMLHTTP"],b=0;b<a.length;b++)try{return new ActiveXObject(a[b])}catch(c){}}():new window.XMLHttpRequest}function k(a){var b=a.responseXML,c=a.responseText;return"IE"===i.browser&&c&&b&&!b.documentElement&&/[^\/]+\/[^\+]+\+xml/.test(a.getResponseHeader("Content-Type"))&&(b=new window.ActiveXObject("Microsoft.XMLDOM"),b.async=!1,b.validateOnParse=!1,b.loadXML(c)),b&&("IE"===i.browser&&0!==b.parseError||!b.documentElement||"parsererror"===b.documentElement.tagName)?null:b}function l(a){var b="----moxieboundary"+(new Date).getTime(),c="--",d="\r\n",e="",g=this.getRuntime();if(!g.can("send_binary_string"))throw new h.RuntimeError(h.RuntimeError.NOT_SUPPORTED_ERR);return m.setRequestHeader("Content-Type","multipart/form-data; boundary="+b),a.each(function(a,g){e+=a instanceof f?c+b+d+'Conte
 nt-Disposition: form-data; name="'+g+'"; filename="'+unescape(encodeURIComponent(a.name||"blob"))+'"'+d+"Content-Type: "+(a.type||"application/octet-stream")+d+d+a.getSource()+d:c+b+d+'Content-Disposition: form-data; name="'+g+'"'+d+d+unescape(encodeURIComponent(a))+d}),e+=c+b+c+d}var m,n,o=this;b.extend(this,{send:function(c,e){var h=this,k="Mozilla"===i.browser&&i.verComp(i.version,4,">=")&&i.verComp(i.version,7,"<"),o="Android Browser"===i.browser,p=!1;if(n=c.url.replace(/^.+?\/([\w\-\.]+)$/,"$1").toLowerCase(),m=j(),m.open(c.method,c.url,c.async,c.user,c.password),e instanceof f)e.isDetached()&&(p=!0),e=e.getSource();else if(e instanceof g){if(e.hasBlob())if(e.getBlob().isDetached())e=l.call(h,e),p=!0;else if((k||o)&&"blob"===b.typeOf(e.getBlob().getSource())&&window.FileReader)return void a.call(h,c,e);if(e instanc
 eof g){var q=new window.FormData;e.each(function(a,b){a instanceof f?q.append(b,a.getSource()):q.append(b,a)}),e=q}}m.upload?(c.withCredentials&&(m.withCredentials=!0),m.addEventListener("load",function(a){h.trigger(a)}),m.addEventListener("error",function(a){h.trigger(a)}),m.addEventListener("progress",function(a){h.trigger(a)}),m.upload.addEventListener("progress",function(a){h.trigger({type:"UploadProgress",loaded:a.loaded,total:a.total})})):m.onreadystatechange=function(){switch(m.readyState){case 1:break;case 2:break;case 3:var a,b;try{d.hasSameOrigin(c.url)&&(a=m.getResponseHeader("Content-Length")||0),m.responseText&&(b=m.responseText.length)}catch(e){a=b=0}h.trigger({type:"progress",lengthComputable:!!a,total:parseInt(a,10),loaded:b});break;case 4:m.onreadystatechange=function(){},0===m.status?h.trigger("error"):h.trigger("load")}},b.isEmptyObj(c.headers)||b.each
 (c.headers,function(a,b){m.setRequestHeader(b,a)}),""!==c.responseType&&"responseType"in m&&("json"!==c.responseType||i.can("return_response_type","json")?m.responseType=c.responseType:m.responseType="text"),p?m.sendAsBinary?m.sendAsBinary(e):!function(){for(var a=new Uint8Array(e.length),b=0;b<e.length;b++)a[b]=255&e.charCodeAt(b);m.send(a.buffer)}():m.send(e),h.trigger("loadstart")},getStatus:function(){try{if(m)return m.status}catch(a){}return 0},getResponse:function(a){var b=this.getRuntime();try{switch(a){case"blob":var d=new e(b.uid,m.response),f=m.getResponseHeader("Content-Disposition");if(f){var g=f.match(/filename=([\'\"'])([^\1]+)\1/);g&&(n=g[2])}return d.name=n,d.type||(d.type=c.getFileMime(n)),d;case"json":return i.can("return_response_type","json")?m.response:200===m.status&&window.JSON?JSON.parse(m.response
 Text):null;case"document":return k(m);default:return""!==m.responseText?m.responseText:null}}catch(h){return null}},getAllResponseHeaders:function(){try{return m.getAllResponseHeaders()}catch(a){}return""},abort:function(){m&&m.abort()},destroy:function(){o=n=null}})}return a.XMLHttpRequest=j}),d("moxie/runtime/html5/utils/BinaryReader",["moxie/core/utils/Basic"],function(a){function b(a){a instanceof ArrayBuffer?c.apply(this,arguments):d.apply(this,arguments)}function c(b){var c=new DataView(b);a.extend(this,{readByteAt:function(a){return c.getUint8(a)},writeByteAt:function(a,b){c.setUint8(a,b)},SEGMENT:function(a,d,e){switch(arguments.length){case 2:return b.slice(a,a+d);case 1:return b.slice(a);case 3:if(null===e&&(e=new ArrayBuffer),e instanceof ArrayBuffer){var f=new Uint8Array(this.length()-d+e.byteLength);a>0&&f.set(new Uint8Array(b.slice(0,a)),0),f.set(new Uint8Array(e),a),f.set(new Uint8Array(b.sli
 ce(a+d)),a+e.byteLength),this.clear(),b=f.buffer,c=new DataView(b);
+break}default:return b}},length:function(){return b?b.byteLength:0},clear:function(){c=b=null}})}function d(b){function c(a,c,d){d=3===arguments.length?d:b.length-c-1,b=b.substr(0,c)+a+b.substr(d+c)}a.extend(this,{readByteAt:function(a){return b.charCodeAt(a)},writeByteAt:function(a,b){c(String.fromCharCode(b),a,1)},SEGMENT:function(a,d,e){switch(arguments.length){case 1:return b.substr(a);case 2:return b.substr(a,d);case 3:c(null!==e?e:"",a,d);break;default:return b}},length:function(){return b?b.length:0},clear:function(){b=null}})}return a.extend(b.prototype,{littleEndian:!1,read:function(a,b){var c,d,e;if(a+b>this.length())throw new Error("You are trying to read outside the source boundaries.");for(d=this.littleEndian?0:-8*(b-1),e=0,c=0;e<b;e++)c|=this.readByteAt(a+e)<<Math.abs(d+8*e);return c},write:function(a,b,c){var d,e;if(a>this.length())throw new Error("You are trying to write outside the source boundaries.");for(d=this.littleEn
 dian?0:-8*(c-1),e=0;e<c;e++)this.writeByteAt(a+e,b>>Math.abs(d+8*e)&255)},BYTE:function(a){return this.read(a,1)},SHORT:function(a){return this.read(a,2)},LONG:function(a){return this.read(a,4)},SLONG:function(a){var b=this.read(a,4);return b>2147483647?b-4294967296:b},CHAR:function(a){return String.fromCharCode(this.read(a,1))},STRING:function(a,b){return this.asArray("CHAR",a,b).join("")},asArray:function(a,b,c){for(var d=[],e=0;e<c;e++)d[e]=this[a](b+e);return d}}),b}),d("moxie/runtime/html5/image/JPEGHeaders",["moxie/runtime/html5/utils/BinaryReader","moxie/core/Exceptions"],function(a,b){return function c(d){var e,f,g,h=[],i=0;if(e=new a(d),65496!==e.SHORT(0))throw e.clear(),new b.ImageError(b.ImageError.WRONG_FORMAT);for(f=2;f<=e.length();)if(g=e.SHORT(f),g>=65488&&g<=65495)f+=2;else{if(65498===g||65497===g)break;i=e.SHORT(f+2)+2,g>=65505&&g<=65519&&h.push({hex:g,name:&q
 uot;APP"+(15&g),start:f,length:i,segment:e.SEGMENT(f,i)}),f+=i}return e.clear(),{headers:h,restore:function(b){var c,d,e;for(e=new a(b),f=65504==e.SHORT(2)?4+e.SHORT(4):2,d=0,c=h.length;d<c;d++)e.SEGMENT(f,0,h[d].segment),f+=h[d].length;return b=e.SEGMENT(),e.clear(),b},strip:function(b){var d,e,f,g;for(f=new c(b),e=f.headers,f.purge(),d=new a(b),g=e.length;g--;)d.SEGMENT(e[g].start,e[g].length,"");return b=d.SEGMENT(),d.clear(),b},get:function(a){for(var b=[],c=0,d=h.length;c<d;c++)h[c].name===a.toUpperCase()&&b.push(h[c].segment);return b},set:function(a,b){var c,d,e,f=[];for("string"==typeof b?f.push(b):f=b,c=d=0,e=h.length;c<e&&(h[c].name===a.toUpperCase()&&(h[c].segment=f[d],h[c].length=f[d].length,d++),!(d>=f.length));c++);},purge:function(){this.headers=h=[]}}}}),d("moxie/runtime/html5/image/ExifParser",["moxie/core/utils/Basic","moxie/runtime/html5/utils/BinaryReader","moxie/c
 ore/Exceptions"],function(a,c,d){function e(f){function g(c,e){var f,g,h,i,j,m,n,o,p=this,q=[],r={},s={1:"BYTE",7:"UNDEFINED",2:"ASCII",3:"SHORT",4:"LONG",5:"RATIONAL",9:"SLONG",10:"SRATIONAL"},t={BYTE:1,UNDEFINED:1,ASCII:1,SHORT:2,LONG:4,RATIONAL:8,SLONG:4,SRATIONAL:8};for(f=p.SHORT(c),g=0;g<f;g++)if(q=[],n=c+2+12*g,h=e[p.SHORT(n)],h!==b){if(i=s[p.SHORT(n+=2)],j=p.LONG(n+=2),m=t[i],!m)throw new d.ImageError(d.ImageError.INVALID_META_ERR);if(n+=4,m*j>4&&(n=p.LONG(n)+l.tiffHeader),n+m*j>=this.length())throw new d.ImageError(d.ImageError.INVALID_META_ERR);"ASCII"!==i?(q=p.asArray(i,n,j),o=1==j?q[0]:q,k.hasOwnProperty(h)&&"object"!=typeof o?r[h]=k[h][o]:r[h]=o):r[h]=a.trim(p.STRING(n,j).replace(/\0$/,""))}return r}function h(a,b,c){var d,e,f,g=0;if("string"==typeof b){var h=j[a.toLowerCase()];for(var i in h)if(h[i]===b){b=i;break}}d=l[a.t
 oLowerCase()+"IFD"],e=this.SHORT(d);for(var k=0;k<e;k++)if(f=d+12*k+2,this.SHORT(f)==b){g=f+8;break}if(!g)return!1;try{this.write(g,c,4)}catch(m){return!1}return!0}var i,j,k,l,m,n;if(c.call(this,f),j={tiff:{274:"Orientation",270:"ImageDescription",271:"Make",272:"Model",305:"Software",34665:"ExifIFDPointer",34853:"GPSInfoIFDPointer"},exif:{36864:"ExifVersion",40961:"ColorSpace",40962:"PixelXDimension",40963:"PixelYDimension",36867:"DateTimeOriginal",33434:"ExposureTime",33437:"FNumber",34855:"ISOSpeedRatings",37377:"ShutterSpeedValue",37378:"ApertureValue",37383:"MeteringMode",37384:"LightSource",37385:"Flash",37386:"FocalLength",41986:"ExposureMode",41987:"WhiteBalance",41990:"SceneCaptureType",41988:"DigitalZoomRatio",4199
 2:"Contrast",41993:"Saturation",41994:"Sharpness"},gps:{0:"GPSVersionID",1:"GPSLatitudeRef",2:"GPSLatitude",3:"GPSLongitudeRef",4:"GPSLongitude"},thumb:{513:"JPEGInterchangeFormat",514:"JPEGInterchangeFormatLength"}},k={ColorSpace:{1:"sRGB",0:"Uncalibrated"},MeteringMode:{0:"Unknown",1:"Average",2:"CenterWeightedAverage",3:"Spot",4:"MultiSpot",5:"Pattern",6:"Partial",255:"Other"},LightSource:{1:"Daylight",2:"Fliorescent",3:"Tungsten",4:"Flash",9:"Fine weather",10:"Cloudy weather",11:"Shade",12:"Daylight fluorescent (D 5700 - 7100K)",13:"Day white fluorescent (N 4600 -5400K)",14:"Cool white fluorescent (W 3900 - 4500K)",15:"White fluorescent (WW 3200 - 3700K)",17:"Standard l
 ight A",18:"Standard light B",19:"Standard light C",20:"D55",21:"D65",22:"D75",23:"D50",24:"ISO studio tungsten",255:"Other"},Flash:{0:"Flash did not fire",1:"Flash fired",5:"Strobe return light not detected",7:"Strobe return light detected",9:"Flash fired, compulsory flash mode",13:"Flash fired, compulsory flash mode, return light not detected",15:"Flash fired, compulsory flash mode, return light detected",16:"Flash did not fire, compulsory flash mode",24:"Flash did not fire, auto mode",25:"Flash fired, auto mode",29:"Flash fired, auto mode, return light not detected",31:"Flash fired, auto mode, return light detected",32:"No flash function",65:"Flash fired, red-eye reduction mode",69:"Flash fired, red-eye reduction mode, return light not detected",71:
 "Flash fired, red-eye reduction mode, return light detected",73:"Flash fired, compulsory flash mode, red-eye reduction mode",77:"Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected",79:"Flash fired, compulsory flash mode, red-eye reduction mode, return light detected",89:"Flash fired, auto mode, red-eye reduction mode",93:"Flash fired, auto mode, return light not detected, red-eye reduction mode",95:"Flash fired, auto mode, return light detected, red-eye reduction mode"},ExposureMode:{0:"Auto exposure",1:"Manual exposure",2:"Auto bracket"},WhiteBalance:{0:"Auto white balance",1:"Manual white balance"},SceneCaptureType:{0:"Standard",1:"Landscape",2:"Portrait",3:"Night scene"},Contrast:{0:"Normal",1:"Soft",2:"Hard"},Saturation:{0:"Normal",1:"Low satu
 ration",2:"High saturation"},Sharpness:{0:"Normal",1:"Soft",2:"Hard"},GPSLatitudeRef:{N:"North latitude",S:"South latitude"},GPSLongitudeRef:{E:"East longitude",W:"West longitude"}},l={tiffHeader:10},m=l.tiffHeader,i={clear:this.clear},a.extend(this,{read:function(){try{return e.prototype.read.apply(this,arguments)}catch(a){throw new d.ImageError(d.ImageError.INVALID_META_ERR)}},write:function(){try{return e.prototype.write.apply(this,arguments)}catch(a){throw new d.ImageError(d.ImageError.INVALID_META_ERR)}},UNDEFINED:function(){return this.BYTE.apply(this,arguments)},RATIONAL:function(a){return this.LONG(a)/this.LONG(a+4)},SRATIONAL:function(a){return this.SLONG(a)/this.SLONG(a+4)},ASCII:function(a){return this.CHAR(a)},TIFF:function(){return n||null},EXIF:function(){var b=null;if(l.exifIFD){try{b=g.call(this,l.exifIFD,j.exif)}catch(c){return null}if(b.ExifVersion&&"array"===a.ty
 peOf(b.ExifVersion)){for(var d=0,e="";d<b.ExifVersion.length;d++)e+=String.fromCharCode(b.ExifVersion[d]);b.ExifVersion=e}}return b},GPS:function(){var b=null;if(l.gpsIFD){try{b=g.call(this,l.gpsIFD,j.gps)}catch(c){return null}b.GPSVersionID&&"array"===a.typeOf(b.GPSVersionID)&&(b.GPSVersionID=b.GPSVersionID.join("."))}return b},thumb:function(){if(l.IFD1)try{var a=g.call(this,l.IFD1,j.thumb);if("JPEGInterchangeFormat"in a)return this.SEGMENT(l.tiffHeader+a.JPEGInterchangeFormat,a.JPEGInterchangeFormatLength)}catch(b){}return null},setExif:function(a,b){return("PixelXDimension"===a||"PixelYDimension"===a)&&h.call(this,"exif",a,b)},clear:function(){i.clear(),f=j=k=n=l=i=null}}),65505!==this.SHORT(0)||"EXIF\0"!==this.STRING(4,5).toUpperCase())throw new d.ImageError(d.ImageError.INVALID_META_ERR);if(this.littleEndian=18761==this.SHORT(m),42!==this.SHORT(m+=2))throw new d.ImageErro
 r(d.ImageError.INVALID_META_ERR);l.IFD0=l.tiffHeader+this.LONG(m+=2),n=g.call(this,l.IFD0,j.tiff),"ExifIFDPointer"in n&&(l.exifIFD=l.tiffHeader+n.ExifIFDPointer,delete n.ExifIFDPointer),"GPSInfoIFDPointer"in n&&(l.gpsIFD=l.tiffHeader+n.GPSInfoIFDPointer,delete n.GPSInfoIFDPointer),a.isEmptyObj(n)&&(n=null);var o=this.LONG(l.IFD0+12*this.SHORT(l.IFD0)+2);o&&(l.IFD1=l.tiffHeader+o)}return e.prototype=c.prototype,e}),d("moxie/runtime/html5/image/JPEG",["moxie/core/utils/Basic","moxie/core/Exceptions","moxie/runtime/html5/image/JPEGHeaders","moxie/runtime/html5/utils/BinaryReader","moxie/runtime/html5/image/ExifParser"],function(a,b,c,d,e){function f(f){function g(a){var b,c,d=0;for(a||(a=j);d<=a.length();){if(b=a.SHORT(d+=2),b>=65472&&b<=65475)return d+=5,{height:a.SHORT(d),width:a.SHORT(d+=2)};c=a.SHORT(d+=2),d+=c-2}return null}function h(){var a,b,c=l.thumb
 ();return c&&(a=new d(c),b=g(a),a.clear(),b)?(b.data=c,b):null}function i(){l&&k&&j&&(l.clear(),k.purge(),j.clear(),m=k=l=j=null)}var j,k,l,m;if(j=new d(f),65496!==j.SHORT(0))throw new b.ImageError(b.ImageError.WRONG_FORMAT);k=new c(f);try{l=new e(k.get("app1")[0])}catch(n){}m=g.call(this),a.extend(this,{type:"image/jpeg",size:j.length(),width:m&&m.width||0,height:m&&m.height||0,setExif:function(b,c){return!!l&&("object"===a.typeOf(b)?a.each(b,function(a,b){l.setExif(b,a)}):l.setExif(b,c),void k.set("app1",l.SEGMENT()))},writeHeaders:function(){return arguments.length?k.restore(arguments[0]):k.restore(f)},stripHeaders:function(a){return k.strip(a)},purge:function(){i.call(this)}}),l&&(this.meta={tiff:l.TIFF(),exif:l.EXIF(),gps:l.GPS(),thumb:h()})}return f}),d("moxie/runtime/html5/image/PNG",["moxie/core/Exceptions","moxie/core/utils/Basic","moxie
 /runtime/html5/utils/BinaryReader"],function(a,b,c){function d(d){function e(){var a,b;return a=g.call(this,8),"IHDR"==a.type?(b=a.start,{width:h.LONG(b),height:h.LONG(b+=4)}):null}function f(){h&&(h.clear(),d=k=i=j=h=null)}function g(a){var b,c,d,e;return b=h.LONG(a),c=h.STRING(a+=4,4),d=a+=4,e=h.LONG(a+b),{length:b,type:c,start:d,CRC:e}}var h,i,j,k;h=new c(d),function(){var b=0,c=0,d=[35152,20039,3338,6666];for(c=0;c<d.length;c++,b+=2)if(d[c]!=h.SHORT(b))throw new a.ImageError(a.ImageError.WRONG_FORMAT)}(),k=e.call(this),b.extend(this,{type:"image/png",size:h.length(),width:k.width,height:k.height,purge:function(){f.call(this)}}),f.call(this)}return d}),d("moxie/runtime/html5/image/ImageInfo",["moxie/core/utils/Basic","moxie/core/Exceptions","moxie/runtime/html5/image/JPEG","moxie/runtime/html5/image/PNG"],function(a,b,c,d){return function(e){var f,g=[c,d];f=function(){for(var a=0;a<g.length;a
 ++)try{return new g[a](e)}catch(c){}throw new b.ImageError(b.ImageError.WRONG_FORMAT)}(),a.extend(this,{type:"",size:0,width:0,height:0,setExif:function(){},writeHeaders:function(a){return a},stripHeaders:function(a){return a},purge:function(){e=null}}),a.extend(this,f),this.purge=function(){f.purge(),f=null}}}),d("moxie/runtime/html5/image/MegaPixel",[],function(){function a(a,d,e){var f=a.naturalWidth,g=a.naturalHeight,h=e.width,i=e.height,j=e.x||0,k=e.y||0,l=d.getContext("2d");b(a)&&(f/=2,g/=2);var m=1024,n=document.createElement("canvas");n.width=n.height=m;for(var o=n.getContext("2d"),p=c(a,f,g),q=0;q<g;){for(var r=q+m>g?g-q:m,s=0;s<f;){var t=s+m>f?f-s:m;o.clearRect(0,0,m,m),o.drawImage(a,-s,-q);var u=s*h/f+j<<0,v=Math.ceil(t*h/f),w=q*i/g/p+k<<0,x=Math.ceil(r*i/g/p);l.drawImage(n,0,0,t,r,u,w,v,x),s+=m}q+=m}n=o=null}function b(a){var b=a.naturalWidth,c=a.naturalHeight;if(b*c>1048576){var d=docum
 ent.createElement("canvas");d.width=d.height=1;var e=d.getContext("2d");return e.drawImage(a,-b+1,0),0===e.getImageData(0,0,1,1).data[3]}return!1}function c(a,b,c){var d=document.createElement("canvas");d.width=1,d.height=c;var e=d.getContext("2d");e.drawImage(a,0,0);for(var f=e.getImageData(0,0,1,c).data,g=0,h=c,i=c;i>g;){var j=f[4*(i-1)+3];0===j?h=i:g=i,i=h+g>>1}d=null;var k=i/c;return 0===k?1:k}return{isSubsampled:b,renderTo:a}}),d("moxie/runtime/html5/image/Image",["moxie/runtime/html5/Runtime","moxie/core/utils/Basic","moxie/core/Exceptions","moxie/core/utils/Encode","moxie/file/Blob","moxie/file/File","moxie/runtime/html5/image/ImageInfo","moxie/runtime/html5/image/MegaPixel","moxie/core/utils/Mime","moxie/core/utils/Env"],function(a,b,c,d,e,f,g,h,i,j){function k(){function a(){if(!u&&!s)throw new c.ImageError(c.
 DOMException.INVALID_STATE_ERR);return u||s}function k(a){return d.atob(a.substring(a.indexOf("base64,")+7))}function l(a,b){return"data:"+(b||"")+";base64,"+d.btoa(a)}function m(a){var b=this;s=new Image,s.onerror=function(){r.call(this),b.trigger("error",c.ImageError.WRONG_FORMAT)},s.onload=function(){b.trigger("load")},s.src="data:"==a.substr(0,5)?a:l(a,w.type)}function n(a,b){var d,e=this;return window.FileReader?(d=new FileReader,d.onload=function(){b(this.result)},d.onerror=function(){e.trigger("error",c.ImageError.WRONG_FORMAT)},d.readAsDataURL(a),void 0):b(a.getAsDataURL())}function o(c,d,e,f){var g,h,i,j,k,l=this,m=0,n=0;if(z=f,k=this.meta&&this.meta.tiff&&this.meta.tiff.Orientation||1,b.inArray(k,[5,6,7,8])!==-1){var o=c;c=d,d=o}return h=a(),e?(c=Math.min(c,h.width),d=Math.min(d,h.height),g=Math.max(c/h.width,d/h.height)):g=Math.min(c/h.width,d/h.height),g>1&&!e&&
 amp;f?void this.trigger("Resize"):(u||(u=document.createElement("canvas")),i=Math.round(h.width*g),j=Math.round(h.height*g),e?(u.width=c,u.height=d,i>c&&(m=Math.round((i-c)/2)),j>d&&(n=Math.round((j-d)/2))):(u.width=i,u.height=j),z||q(u.width,u.height,k),p.call(this,h,u,-m,-n,i,j),this.width=u.width,this.height=u.height,y=!0,void l.trigger("Resize"))}function p(a,b,c,d,e,f){if("iOS"===j.OS)h.renderTo(a,b,{width:e,height:f,x:c,y:d});else{var g=b.getContext("2d");g.drawImage(a,c,d,e,f)}}function q(a,b,c){switch(c){case 5:case 6:case 7:case 8:u.width=b,u.height=a;break;default:u.width=a,u.height=b}var d=u.getContext("2d");switch(c){case 2:d.translate(a,0),d.scale(-1,1);break;case 3:d.translate(a,b),d.rotate(Math.PI);break;case 4:d.translate(0,b),d.scale(1,-1);break;case 5:d.rotate(.5*Math.PI),d.scale(1,-1);break;case 6:d.rotate(.5*Math.PI),d.translate(0,-b);break;case 7:d.rotate(.5*Math.PI),d.translate(a,
 -b),d.scale(-1,1);break;case 8:d.rotate(-.5*Math.PI),d.translate(-a,0)}}function r(){t&&(t.purge(),t=null),v=s=u=w=null,y=!1}var s,t,u,v,w,x=this,y=!1,z=!0;b.extend(this,{loadFromBlob:function(a){var b=this,d=b.getRuntime(),e=!(arguments.length>1)||arguments[1];if(!d.can("access_binary"))throw new c.RuntimeError(c.RuntimeError.NOT_SUPPORTED_ERR);return w=a,a.isDetached()?(v=a.getSource(),void m.call(this,v)):void n.call(this,a.getSource(),function(a){e&&(v=k(a)),m.call(b,a)})},loadFromImage:function(a,b){this.meta=a.meta,w=new f(null,{name:a.name,size:a.size,type:a.type}),m.call(this,b?v=a.getAsBinaryString():a.getAsDataURL())},getInfo:function(){var b,c=this.getRuntime();return!t&&v&&c.can("access_image_binary")&&(t=new g(v)),b={width:a().width||0,height:a().height||0,type:w.type||i.getFileMime(w.name),size:v&&v.length||w.size||0,name:w.name||"",meta:t&&t.meta||this.meta||{}},!b.meta||!b.meta.t
 humb||b.meta.thumb.data instanceof e||(b.meta.thumb.data=new e(null,{type:"image/jpeg",data:b.meta.thumb.data})),b},downsize:function(){o.apply(this,arguments)},getAsCanvas:function(){return u&&(u.id=this.uid+"_canvas"),u},getAsBlob:function(a,b){return a!==this.type&&o.call(this,this.width,this.height,!1),new f(null,{name:w.name||"",type:a,data:x.getAsBinaryString.call(this,a,b)})},getAsDataURL:function(a){var b=arguments[1]||90;if(!y)return s.src;if("image/jpeg"!==a)return u.toDataURL("image/png");try{return u.toDataURL("image/jpeg",b/100)}catch(c){return u.toDataURL("image/jpeg")}},getAsBinaryString:function(a,b){if(!y)return v||(v=k(x.getAsDataURL(a,b))),v;if("image/jpeg"!==a)v=k(x.getAsDataURL(a,b));else{var c;b||(b=90);try{c=u.toDataURL("image/jpeg",b/100)}catch(d){c=u.toDataURL("image/jpeg")}v=k(c),t&&(v=t.stripHeaders(v),z&&(t.meta&&t.me
 ta.exif&&t.setExif({PixelXDimension:this.width,PixelYDimension:this.height}),v=t.writeHeaders(v)),t.purge(),t=null)}return y=!1,v},destroy:function(){x=null,r.call(this),this.getRuntime().getShim().removeInstance(this.uid)}})}return a.Image=k}),d("moxie/runtime/flash/Runtime",[],function(){return{}}),d("moxie/runtime/silverlight/Runtime",[],function(){return{}}),d("moxie/runtime/html4/Runtime",["moxie/core/utils/Basic","moxie/core/Exceptions","moxie/runtime/Runtime","moxie/core/utils/Env"],function(a,b,c,d){function e(b){var e=this,h=c.capTest,i=c.capTrue;c.call(this,b,f,{access_binary:h(window.FileReader||window.File&&File.getAsDataURL),access_image_binary:!1,display_media:h(g.Image&&(d.can("create_canvas")||d.can("use_data_uri_over32kb"))),do_cors:!1,drag_and_drop:!1,filter_by_extension:h(function(){return"Chrome"===d.browser&&d.verComp(d.version,28,&
 quot;>=")||"IE"===d.browser&&d.verComp(d.version,10,">=")||"Safari"===d.browser&&d.verComp(d.version,7,">=")}()),resize_image:function(){return g.Image&&e.can("access_binary")&&d.can("create_canvas")},report_upload_progress:!1,return_response_headers:!1,return_response_type:function(b){return!("json"!==b||!window.JSON)||!!~a.inArray(b,["text","document",""])},return_status_code:function(b){return!a.arrayDiff(b,[200,404])},select_file:function(){return d.can("use_fileinput")},select_multiple:!1,send_binary_string:!1,send_custom_headers:!1,send_multipart:!0,slice_blob:!1,stream_upload:function(){return e.can("select_file")},summon_file_dialog:function(){return e.can("select_file")&&("Firefox"===d.browser&&d.verComp(d.version,4,">=")||"Opera"===d.browser&&d
 .verComp(d.version,12,">=")||"IE"===d.browser&&d.verComp(d.version,10,">=")||!!~a.inArray(d.browser,["Chrome","Safari"]))},upload_filesize:i,use_http_method:function(b){return!a.arrayDiff(b,["GET","POST"])}}),a.extend(this,{init:function(){this.trigger("Init")},destroy:function(a){return function(){a.call(e),a=e=null}}(this.destroy)}),a.extend(this.getShim(),g)}var f="html4",g={};return c.addConstructor(f,e),g}),d("moxie/runtime/html4/file/FileInput",["moxie/runtime/html4/Runtime","moxie/file/File","moxie/core/utils/Basic","moxie/core/utils/Dom","moxie/core/utils/Events","moxie/core/utils/Mime","moxie/core/utils/Env"],function(a,b,c,d,e,f,g){function h(){function a(){var f,k,l,m,n,o,p=this,q=p.getRuntime();o=c.guid("uid_"),f=q.getShimContainer(),h&&(l=d.get(h+"_form"),l&
 &c.extend(l.style,{top:"100%"})),m=document.createElement("form"),m.setAttribute("id",o+"_form"),m.setAttribute("method","post"),m.setAttribute("enctype","multipart/form-data"),m.setAttribute("encoding","multipart/form-data"),c.extend(m.style,{overflow:"hidden",position:"absolute",top:0,left:0,width:"100%",height:"100%"}),n=document.createElement("input"),n.setAttribute("id",o),n.setAttribute("type","file"),n.setAttribute("name",i.name||"Filedata"),n.setAttribute("accept",j.join(",")),c.extend(n.style,{fontSize:"999px",opacity:0}),m.appendChild(n),f.appendChild(m),c.extend(n.style,{position:"absolute",top:0,left:0,width:"100%",height:"100%"}),"IE"===g.browser&&g.verComp(g.version,10,"<")&&
 amp;c.extend(n.style,{filter:"progid:DXImageTransform.Microsoft.Alpha(opacity=0)"}),n.onchange=function(){var c;if(this.value){if(this.files){if(c=this.files[0],0===c.size)return void m.parentNode.removeChild(m)}else c={name:this.value};c=new b(q.uid,c),this.onchange=function(){},a.call(p),p.files=[c],n.setAttribute("id",c.uid),m.setAttribute("id",c.uid+"_form"),p.trigger("change"),n=m=null}},q.can("summon_file_dialog")&&(k=d.get(i.browse_button),e.removeEvent(k,"click",p.uid),e.addEvent(k,"click",function(a){n&&!n.disabled&&n.click(),a.preventDefault()},p.uid)),h=o,f=l=k=null}var h,i,j=[];c.extend(this,{init:function(b){var c,g=this,h=g.getRuntime();i=b,j=b.accept.mimes||f.extList2mimes(b.accept,h.can("filter_by_extension")),c=h.getShimContainer(),function(){var a,f,i;a=d.get(b.browse_button),h.can("summon_file_dialog")&&("static"===d.getStyl
 e(a,"position")&&(a.style.position="relative"),f=parseInt(d.getStyle(a,"z-index"),10)||1,a.style.zIndex=f,c.style.zIndex=f-1),i=h.can("summon_file_dialog")?a:c,e.addEvent(i,"mouseover",function(){g.trigger("mouseenter")},g.uid),e.addEvent(i,"mouseout",function(){g.trigger("mouseleave")},g.uid),e.addEvent(i,"mousedown",function(){g.trigger("mousedown")},g.uid),e.addEvent(d.get(b.container),"mouseup",function(){g.trigger("mouseup")},g.uid),a=null}(),a.call(this),c=null,g.trigger({type:"ready",async:!0})},disable:function(a){var b;(b=d.get(h))&&(b.disabled=!!a)},destroy:function(){var a=this.getRuntime(),b=a.getShim(),c=a.getShimContainer();e.removeAllEvents(c,this.uid),e.removeAllEvents(i&&d.get(i.container),this.uid),e.removeAllEvents(i&&d.get(i.browse_button),this.uid),c&&(c.innerHTML=""),b.removeInstance(
 this.uid),h=j=i=c=b=null}})}return a.FileInput=h}),d("moxie/runtime/html4/file/FileReader",["moxie/runtime/html4/Runtime","moxie/runtime/html5/file/FileReader"],function(a,b){return a.FileReader=b}),d("moxie/runtime/html4/xhr/XMLHttpRequest",["moxie/runtime/html4/Runtime","moxie/core/utils/Basic","moxie/core/utils/Dom","moxie/core/utils/Url","moxie/core/Exceptions","moxie/core/utils/Events","moxie/file/Blob","moxie/xhr/FormData"],function(a,b,c,d,e,f,g,h){function i(){function a(a){var b,d,e,g,h=this,i=!1;if(k){if(b=k.id.replace(/_iframe$/,""),d=c.get(b+"_form")){for(e=d.getElementsByTagName("input"),g=e.length;g--;)switch(e[g].getAttribute("type")){case"hidden":e[g].parentNode.removeChild(e[g]);break;case"file":i=!0}e=[],i||d.parentNode.removeChild(d),d=null}setTimeout(function(){f.removeEvent(k,"loa
 d",h.uid),k.parentNode&&k.parentNode.removeChild(k);var b=h.getRuntime().getShimContainer();b.children.length||b.parentNode.removeChild(b),b=k=null,a()},1)}}var i,j,k;b.extend(this,{send:function(l,m){function n(){var c=t.getShimContainer()||document.body,e=document.createElement("div");e.innerHTML='<iframe id="'+o+'_iframe" name="'+o+'_iframe" src="javascript:&quot;&quot;" style="display:none"></iframe>',k=e.firstChild,c.appendChild(k),f.addEvent(k,"load",function(){var c;try{c=k.contentWindow.document||k.contentDocument||window.frames[k.id].document,/^4(0[0-9]|1[0-7]|2[2346])\s/.test(c.title)?i=c.title.replace(/^(\d+).*$/,"$1"):(i=200,j=b.trim(c.body.innerHTML),s.trigger({type:"progress",loaded:j.length,total:j.length}),r&&s.trigger({type:"uploadprogress",loaded:r.size||1025,total:r.size||1025}))}catch(e){if(!d.hasSameOrigin(l.url))return void a.call(s
 ,function(){s.trigger("error")});i=404}a.call(s,function(){s.trigger("load")})},s.uid)}var o,p,q,r,s=this,t=s.getRuntime();if(i=j=null,m instanceof h&&m.hasBlob()){if(r=m.getBlob(),o=r.uid,q=c.get(o),p=c.get(o+"_form"),!p)throw new e.DOMException(e.DOMException.NOT_FOUND_ERR)}else o=b.guid("uid_"),p=document.createElement("form"),p.setAttribute("id",o+"_form"),p.setAttribute("method",l.method),p.setAttribute("enctype","multipart/form-data"),p.setAttribute("encoding","multipart/form-data"),t.getShimContainer().appendChild(p);p.setAttribute("target",o+"_iframe"),m instanceof h&&m.each(function(a,c){if(a instanceof g)q&&q.setAttribute("name",c);else{var d=document.createElement("input");b.extend(d,{type:"hidden",name:c,value:a}),q?p.insertBefore(d,q):p.appendChild(d)}}),p.setAttribute("acti
 on",l.url),n(),p.submit(),s.trigger("loadstart")},getStatus:function(){return i},getResponse:function(a){if("json"===a&&"string"===b.typeOf(j)&&window.JSON)try{return JSON.parse(j.replace(/^\s*<pre[^>]*>/,"").replace(/<\/pre>\s*$/,""))}catch(c){return null}return j},abort:function(){var b=this;k&&k.contentWindow&&(k.contentWindow.stop?k.contentWindow.stop():k.contentWindow.document.execCommand?k.contentWindow.document.execCommand("Stop"):k.src="about:blank"),a.call(this,function(){b.dispatchEvent("abort")})}})}return a.XMLHttpRequest=i}),d("moxie/runtime/html4/image/Image",["moxie/runtime/html4/Runtime","moxie/runtime/html5/image/Image"],function(a,b){return a.Image=b}),f(["moxie/core/utils/Basic","moxie/core/utils/Env","moxie/core/I18n","moxie/core/utils/Mime","moxie/core/utils/
 Dom","moxie/core/Exceptions","moxie/core/EventTarget","moxie/runtime/Runtime","moxie/runtime/RuntimeClient","moxie/file/FileInput","moxie/core/utils/Encode","moxie/file/Blob","moxie/file/File","moxie/file/FileDrop","moxie/file/FileReader","moxie/core/utils/Url","moxie/runtime/RuntimeTarget","moxie/file/FileReaderSync","moxie/xhr/FormData","moxie/xhr/XMLHttpRequest","moxie/runtime/Transporter","moxie/image/Image","moxie/core/utils/Events"])}(this),function(a){"use strict";var b={},c=a.moxie.core.utils.Basic.inArray;return function d(a){var e,f;for(e in a)f=typeof a[e],"object"!==f||~c(e,["Exceptions","Env","Mime"])?"function"===f&&(b[e]=a[e]):d(a[e])}(a.moxie),b.Env=a.moxie.core.utils.Env,b.Mime=a.moxie.core.utils.Mime,b.Exceptions=a.m
 oxie.core.Exceptions,a.mOxie=b,a.o||(a.o=b),b}(this);
+
+/**
</ins><span class="cx" style="display: block; padding: 0 10px">  * Plupload - multi-runtime File Uploader
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * v2.1.8
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * v2.1.9
</ins><span class="cx" style="display: block; padding: 0 10px">  *
</span><span class="cx" style="display: block; padding: 0 10px">  * Copyright 2013, Moxiecode Systems AB
</span><span class="cx" style="display: block; padding: 0 10px">  * Released under GPL License.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -24,6 +30,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">  * License: http://www.plupload.com/license
</span><span class="cx" style="display: block; padding: 0 10px">  * Contributing: http://www.plupload.com/contributing
</span><span class="cx" style="display: block; padding: 0 10px">  *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Date: 2015-07-21
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Date: 2016-05-15
</ins><span class="cx" style="display: block; padding: 0 10px">  */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-;(function(e,t,n){function s(e){function r(e,t,r){var i={chunks:"slice_blob",jpgresize:"send_binary_string",pngresize:"send_binary_string",progress:"report_upload_progress",multi_selection:"select_multiple",dragdrop:"drag_and_drop",drop_element:"drag_and_drop",headers:"send_custom_headers",urlstream_upload:"send_binary_string",canSendBinary:"send_binary",triggerDialog:"summon_file_dialog"};i[e]?n[i[e]]=t:r||(n[e]=t)}var t=e.required_features,n={};if(typeof t=="string")o.each(t.split(/\s*,\s*/),function(e){r(e,!0)});else if(typeof t=="object")o.each(t,function(e,t){r(t,e)});else if(t===!0){e.chunk_size>0&&(n.slice_blob=!0);if(e.resize.enabled||!e.multipart)n.send_binary_string=!0;o.each(e,function(e,t){r(t,!!e,!0)})}return n}var r=e.setTimeout,i={},o
 ={VERSION:"2.1.8",STOPPED:1,STARTED:2,QUEUED:1,UPLOADING:2,FAILED:4,DONE:5,GENERIC_ERROR:-100,HTTP_ERROR:-200,IO_ERROR:-300,SECURITY_ERROR:-400,INIT_ERROR:-500,FILE_SIZE_ERROR:-600,FILE_EXTENSION_ERROR:-601,FILE_DUPLICATE_ERROR:-602,IMAGE_FORMAT_ERROR:-700,MEMORY_ERROR:-701,IMAGE_DIMENSIONS_ERROR:-702,mimeTypes:t.mimes,ua:t.ua,typeOf:t.typeOf,extend:t.extend,guid:t.guid,get:function(n){var r=[],i;t.typeOf(n)!=="array"&&(n=[n]);var s=n.length;while(s--)i=t.get(n[s]),i&&r.push(i);return r.length?r:null},each:t.each,getPos:t.getPos,getSize:t.getSize,xmlEncode:function(e){var t={"<":"lt",">":"gt","&":"amp",'"':"quot","'":"#39"},n=/[<>&\"\']/g;return e?(""+e).replace(n,function(e){return t[e]?"&"+t[e]+";":e}):e},toArray:t.toArray,inArray:t.inArray,addI18n:t.addI18n,translate:t.translate,isEmptyObj:t.i
 sEmptyObj,hasClass:t.hasClass,addClass:t.addClass,removeClass:t.removeClass,getStyle:t.getStyle,addEvent:t.addEvent,removeEvent:t.removeEvent,removeAllEvents:t.removeAllEvents,cleanName:function(e){var t,n;n=[/[\300-\306]/g,"A",/[\340-\346]/g,"a",/\307/g,"C",/\347/g,"c",/[\310-\313]/g,"E",/[\350-\353]/g,"e",/[\314-\317]/g,"I",/[\354-\357]/g,"i",/\321/g,"N",/\361/g,"n",/[\322-\330]/g,"O",/[\362-\370]/g,"o",/[\331-\334]/g,"U",/[\371-\374]/g,"u"];for(t=0;t<n.length;t+=2)e=e.replace(n[t],n[t+1]);return e=e.replace(/\s+/g,"_"),e=e.replace(/[^a-z0-9_\-\.]+/gi,""),e},buildUrl:function(e,t){var n="";return o.each(t,function(e,t){n+=(n?"&":"")+encodeURIComponent(t)+"="+encodeURIComponent(e)}),n&&(e+=(e.indexOf("?")>0?"&":"?")+n),e},formatSize:f
 unction(e){function t(e,t){return Math.round(e*Math.pow(10,t))/Math.pow(10,t)}if(e===n||/\D/.test(e))return o.translate("N/A");var r=Math.pow(1024,4);return e>r?t(e/r,1)+" "+o.translate("tb"):e>(r/=1024)?t(e/r,1)+" "+o.translate("gb"):e>(r/=1024)?t(e/r,1)+" "+o.translate("mb"):e>1024?Math.round(e/1024)+" "+o.translate("kb"):e+" "+o.translate("b")},parseSize:t.parseSizeStr,predictRuntime:function(e,n){var r,i;return r=new o.Uploader(e),i=t.Runtime.thatCan(r.getOption().required_features,n||e.runtimes),r.destroy(),i},addFileFilter:function(e,t){i[e]=t}};o.addFileFilter("mime_types",function(e,t,n){e.length&&!e.regexp.test(t.name)?(this.trigger("Error",{code:o.FILE_EXTENSION_ERROR,message:o.translate("File extension error."),file:t}),n(!1)):n(!0)}),o.addFileFilter("max_file_size",function(e,t,n){var r;e=o.parseSize(e),
 t.size!==r&&e&&t.size>e?(this.trigger("Error",{code:o.FILE_SIZE_ERROR,message:o.translate("File size error."),file:t}),n(!1)):n(!0)}),o.addFileFilter("prevent_duplicates",function(e,t,n){if(e){var r=this.files.length;while(r--)if(t.name===this.files[r].name&&t.size===this.files[r].size){this.trigger("Error",{code:o.FILE_DUPLICATE_ERROR,message:o.translate("Duplicate file error."),file:t}),n(!1);return}}n(!0)}),o.Uploader=function(e){function g(){var e,t=0,n;if(this.state==o.STARTED){for(n=0;n<f.length;n++)!e&&f[n].status==o.QUEUED?(e=f[n],this.trigger("BeforeUpload",e)&&(e.status=o.UPLOADING,this.trigger("UploadFile",e))):t++;t==f.length&&(this.state!==o.STOPPED&&(this.state=o.STOPPED,this.trigger("StateChanged")),this.trigger("UploadComplete",f))}}function y(e){e.percent=e.size>0?Math.ceil(e.loaded/e.size*100):100,b()}function b(
 ){var e,t;d.reset();for(e=0;e<f.length;e++)t=f[e],t.size!==n?(d.size+=t.origSize,d.loaded+=t.loaded*t.origSize/t.size):d.size=n,t.status==o.DONE?d.uploaded++:t.status==o.FAILED?d.failed++:d.queued++;d.size===n?d.percent=f.length>0?Math.ceil(d.uploaded/f.length*100):0:(d.bytesPerSec=Math.ceil(d.loaded/((+(new Date)-p||1)/1e3)),d.percent=d.size>0?Math.ceil(d.loaded/d.size*100):0)}function w(){var e=c[0]||h[0];return e?e.getRuntime().uid:!1}function E(e,n){if(e.ruid){var r=t.Runtime.getInfo(e.ruid);if(r)return r.can(n)}return!1}function S(){this.bind("FilesAdded FilesRemoved",function(e){e.trigger("QueueChanged"),e.refresh()}),this.bind("CancelUpload",O),this.bind("BeforeUpload",C),this.bind("UploadFile",k),this.bind("UploadProgress",L),this.bind("StateChanged",A),this.bind("QueueChanged",b),this.bind("Error",_),this.bind("FileUploaded",M),this.bind("Destroy",D)}functi
 on x(e,n){var r=this,i=0,s=[],u={runtime_order:e.runtimes,required_caps:e.required_features,preferred_caps:l,swf_url:e.flash_swf_url,xap_url:e.silverlight_xap_url};o.each(e.runtimes.split(/\s*,\s*/),function(t){e[t]&&(u[t]=e[t])}),e.browse_button&&o.each(e.browse_button,function(n){s.push(function(s){var a=new t.FileInput(o.extend({},u,{accept:e.filters.mime_types,name:e.file_data_name,multiple:e.multi_selection,container:e.container,browse_button:n}));a.onready=function(){var e=t.Runtime.getInfo(this.ruid);t.extend(r.features,{chunks:e.can("slice_blob"),multipart:e.can("send_multipart"),multi_selection:e.can("select_multiple")}),i++,c.push(this),s()},a.onchange=function(){r.addFile(this.files)},a.bind("mouseenter mouseleave mousedown mouseup",function(r){v||(e.browse_button_hover&&("mouseenter"===r.type?t.addClass(n,e.browse_button_hover):"mouseleave"===r.type&&t.removeClass(n,e.browse_butto
 n_hover)),e.browse_button_active&&("mousedown"===r.type?t.addClass(n,e.browse_button_active):"mouseup"===r.type&&t.removeClass(n,e.browse_button_active)))}),a.bind("mousedown",function(){r.trigger("Browse")}),a.bind("error runtimeerror",function(){a=null,s()}),a.init()})}),e.drop_element&&o.each(e.drop_element,function(e){s.push(function(n){var s=new t.FileDrop(o.extend({},u,{drop_zone:e}));s.onready=function(){var e=t.Runtime.getInfo(this.ruid);r.features.dragdrop=e.can("drag_and_drop"),i++,h.push(this),n()},s.ondrop=function(){r.addFile(this.files)},s.bind("error runtimeerror",function(){s=null,n()}),s.init()})}),t.inSeries(s,function(){typeof n=="function"&&n(i)})}function T(e,r,i){var s=new t.Image;try{s.onload=function(){if(r.width>this.width&&r.height>this.height&&r.quality===n&&r.preserve_headers&&!r.crop)return this.destroy(),i
 (e);s.downsize(r.width,r.height,r.crop,r.preserve_headers)},s.onresize=function(){i(this.getAsBlob(e.type,r.quality)),this.destroy()},s.onerror=function(){i(e)},s.load(e)}catch(o){i(e)}}function N(e,n,r){function f(e,t,n){var r=a[e];switch(e){case"max_file_size":e==="max_file_size"&&(a.max_file_size=a.filters.max_file_size=t);break;case"chunk_size":if(t=o.parseSize(t))a[e]=t,a.send_file_name=!0;break;case"multipart":a[e]=t,t||(a.send_file_name=!0);break;case"unique_names":a[e]=t,t&&(a.send_file_name=!0);break;case"filters":o.typeOf(t)==="array"&&(t={mime_types:t}),n?o.extend(a.filters,t):a.filters=t,t.mime_types&&(a.filters.mime_types.regexp=function(e){var t=[];return o.each(e,function(e){o.each(e.extensions.split(/,/),function(e){/^\s*\*\s*$/.test(e)?t.push("\\.*"):t.push("\\."+e.replace(new RegExp("["+"/^$.*+?|()[]{}\\".replace(/./g,"\
 \$&")+"]","g"),"\\$&"))})}),new RegExp("("+t.join("|")+")$","i")}(a.filters.mime_types));break;case"resize":n?o.extend(a.resize,t,{enabled:!0}):a.resize=t;break;case"prevent_duplicates":a.prevent_duplicates=a.filters.prevent_duplicates=!!t;break;case"browse_button":case"drop_element":t=o.get(t);case"container":case"runtimes":case"multi_selection":case"flash_swf_url":case"silverlight_xap_url":a[e]=t,n||(u=!0);break;default:a[e]=t}n||i.trigger("OptionChanged",e,t,r)}var i=this,u=!1;typeof e=="object"?o.each(e,function(e,t){f(t,e,r)}):f(e,n,r),r?(a.required_features=s(o.extend({},a)),l=s(o.extend({},a,{required_features:!0}))):u&&(i.trigger("Destroy"),x.call(i,a,function(e){e?(i.runtime=t.Runtime.getInfo(w()).type,i.trigger("Init",{runtime:i.runtime}),i.trigger("P
 ostInit")):i.trigger("Error",{code:o.INIT_ERROR,message:o.translate("Init error.")})}))}function C(e,t){if(e.settings.unique_names){var n=t.name.match(/\.([^.]+)$/),r="part";n&&(r=n[1]),t.target_name=t.id+"."+r}}function k(e,n){function h(){u-->0?r(p,1e3):(n.loaded=f,e.trigger("Error",{code:o.HTTP_ERROR,message:o.translate("HTTP Error."),file:n,response:m.responseText,status:m.status,responseHeaders:m.getAllResponseHeaders()}))}function p(){var d,v,g={},y;if(n.status!==o.UPLOADING||e.state===o.STOPPED)return;e.settings.send_file_name&&(g.name=n.target_name||n.name),s&&a.chunks&&c.size>s?(y=Math.min(s,c.size-f),d=c.slice(f,f+y)):(y=c.size,d=c),s&&a.chunks&&(e.settings.send_chunk_number?(g.chunk=Math.ceil(f/s),g.chunks=Math.ceil(c.size/s)):(g.offset=f,g.total=c.size)),m=new t.XMLHttpRequest,m.upload&&(m.upload.onprogress=function(t){n.loaded=Math.min(n.size,f+
 t.loaded),e.trigger("UploadProgress",n)}),m.onload=function(){if(m.status>=400){h();return}u=e.settings.max_retries,y<c.size?(d.destroy(),f+=y,n.loaded=Math.min(f,c.size),e.trigger("ChunkUploaded",n,{offset:n.loaded,total:c.size,response:m.responseText,status:m.status,responseHeaders:m.getAllResponseHeaders()}),t.Env.browser==="Android Browser"&&e.trigger("UploadProgress",n)):n.loaded=n.size,d=v=null,!f||f>=c.size?(n.size!=n.origSize&&(c.destroy(),c=null),e.trigger("UploadProgress",n),n.status=o.DONE,e.trigger("FileUploaded",n,{response:m.responseText,status:m.status,responseHeaders:m.getAllResponseHeaders()})):r(p,1)},m.onerror=function(){h()},m.onloadend=function(){this.destroy(),m=null},e.settings.multipart&&a.multipart?(m.open("post",i,!0),o.each(e.settings.headers,function(e,t){m.setRequestHeader(t,e)}),v=new t.FormData,o.each(o.extend(g,e.settings.multipart_params),function(e
 ,t){v.append(t,e)}),v.append(e.settings.file_data_name,d),m.send(v,{runtime_order:e.settings.runtimes,required_caps:e.settings.required_features,preferred_caps:l,swf_url:e.settings.flash_swf_url,xap_url:e.settings.silverlight_xap_url})):(i=o.buildUrl(e.settings.url,o.extend(g,e.settings.multipart_params)),m.open("post",i,!0),m.setRequestHeader("Content-Type","application/octet-stream"),o.each(e.settings.headers,function(e,t){m.setRequestHeader(t,e)}),m.send(d,{runtime_order:e.settings.runtimes,required_caps:e.settings.required_features,preferred_caps:l,swf_url:e.settings.flash_swf_url,xap_url:e.settings.silverlight_xap_url}))}var i=e.settings.url,s=e.settings.chunk_size,u=e.settings.max_retries,a=e.features,f=0,c;n.loaded&&(f=n.loaded=s?s*Math.floor(n.loaded/s):0),c=n.getSource(),e.settings.resize.enabled&&E(c,"send_binary_string")&&!!~t.inArray(c.type,["image/jpeg","image/png"])?T.call(this,c,e.sett
 ings.resize,function(e){c=e,n.size=e.size,p()}):p()}function L(e,t){y(t)}function A(e){if(e.state==o.STARTED)p=+(new Date);else if(e.state==o.STOPPED)for(var t=e.files.length-1;t>=0;t--)e.files[t].status==o.UPLOADING&&(e.files[t].status=o.QUEUED,b())}function O(){m&&m.abort()}function M(e){b(),r(function(){g.call(e)},1)}function _(e,t){t.code===o.INIT_ERROR?e.destroy():t.code===o.HTTP_ERROR&&(t.file.status=o.FAILED,y(t.file),e.state==o.STARTED&&(e.trigger("CancelUpload"),r(function(){g.call(e)},1)))}function D(e){e.stop(),o.each(f,function(e){e.destroy()}),f=[],c.length&&(o.each(c,function(e){e.destroy()}),c=[]),h.length&&(o.each(h,function(e){e.destroy()}),h=[]),l={},v=!1,p=m=null,d.reset()}var u=o.guid(),a,f=[],l={},c=[],h=[],p,d,v=!1,m;a={runtimes:t.Runtime.order,max_retries:0,chunk_size:0,multipart:!0,multi_selection:!0,file_data_name:"file",flash_swf_url:"js/Moxie.swf",silverlight_xap_url:"js/
 Moxie.xap",filters:{mime_types:[],prevent_duplicates:!1,max_file_size:0},resize:{enabled:!1,preserve_headers:!0,crop:!1},send_file_name:!0,send_chunk_number:!0},N.call(this,e,null,!0),d=new o.QueueProgress,o.extend(this,{id:u,uid:u,state:o.STOPPED,features:{},runtime:null,files:f,settings:a,total:d,init:function(){var e=this;typeof a.preinit=="function"?a.preinit(e):o.each(a.preinit,function(t,n){e.bind(n,t)}),S.call(this);if(!a.browse_button||!a.url){this.trigger("Error",{code:o.INIT_ERROR,message:o.translate("Init error.")});return}x.call(this,a,function(n){typeof a.init=="function"?a.init(e):o.each(a.init,function(t,n){e.bind(n,t)}),n?(e.runtime=t.Runtime.getInfo(w()).type,e.trigger("Init",{runtime:e.runtime}),e.trigger("PostInit")):e.trigger("Error",{code:o.INIT_ERROR,message:o.translate("Init error.")})})},setOption:function(e,t){N.call(this,e,t,!this.runtime)},getOption:function(e){return e?a[
 e]:a},refresh:function(){c.length&&o.each(c,function(e){e.trigger("Refresh")}),this.trigger("Refresh")},start:function(){this.state!=o.STARTED&&(this.state=o.STARTED,this.trigger("StateChanged"),g.call(this))},stop:function(){this.state!=o.STOPPED&&(this.state=o.STOPPED,this.trigger("StateChanged"),this.trigger("CancelUpload"))},disableBrowse:function(){v=arguments[0]!==n?arguments[0]:!0,c.length&&o.each(c,function(e){e.disable(v)}),this.trigger("DisableBrowse",v)},getFile:function(e){var t;for(t=f.length-1;t>=0;t--)if(f[t].id===e)return f[t]},addFile:function(e,n){function c(e,n){var r=[];t.each(s.settings.filters,function(t,n){i[n]&&r.push(function(r){i[n].call(s,t,e,function(e){r(!e)})})}),t.inSeries(r,n)}function h(e){var i=t.typeOf(e);if(e instanceof t.File){if(!e.ruid&&!e.isDetached()){if(!l)return!1;e.ruid=l,e.connectRuntime(l)}h(new o.File(e))}else e instanceof t.Bl
 ob?(h(e.getSource()),e.destroy()):e instanceof o.File?(n&&(e.name=n),u.push(function(t){c(e,function(n){n||(f.push(e),a.push(e),s.trigger("FileFiltered",e)),r(t,1)})})):t.inArray(i,["file","blob"])!==-1?h(new t.File(null,e)):i==="node"&&t.typeOf(e.files)==="filelist"?t.each(e.files,h):i==="array"&&(n=null,t.each(e,h))}var s=this,u=[],a=[],l;l=w(),h(e),u.length&&t.inSeries(u,function(){a.length&&s.trigger("FilesAdded",a)})},removeFile:function(e){var t=typeof e=="string"?e:e.id;for(var n=f.length-1;n>=0;n--)if(f[n].id===t)return this.splice(n,1)[0]},splice:function(e,t){var r=f.splice(e===n?0:e,t===n?f.length:t),i=!1;return this.state==o.STARTED&&(o.each(r,function(e){if(e.status===o.UPLOADING)return i=!0,!1}),i&&this.stop()),this.trigger("FilesRemoved",r),o.each(r,function(e){e.destroy()}),i&&this.start(),r},dispatchEvent:functi
 on(e){var t,n,r;e=e.toLowerCase(),t=this.hasEventListener(e);if(t){t.sort(function(e,t){return t.priority-e.priority}),n=[].slice.call(arguments),n.shift(),n.unshift(this);for(var i=0;i<t.length;i++)if(t[i].fn.apply(t[i].scope,n)===!1)return!1}return!0},bind:function(e,t,n,r){o.Uploader.prototype.bind.call(this,e,t,r,n)},destroy:function(){this.trigger("Destroy"),a=d=null,this.unbindAll()}})},o.Uploader.prototype=t.EventTarget.instance,o.File=function(){function n(n){o.extend(this,{id:o.guid(),name:n.name||n.fileName,type:n.type||"",size:n.size||n.fileSize,origSize:n.size||n.fileSize,loaded:0,percent:0,status:o.QUEUED,lastModifiedDate:n.lastModifiedDate||(new Date).toLocaleString(),getNative:function(){var e=this.getSource().getSource();return t.inArray(t.typeOf(e),["blob","file"])!==-1?e:null},getSource:function(){return e[this.id]?e[this.id]:null},destroy:function(){var t=this.getSource();t&&(t.destroy(),delete e[this.id])}}),e[th
 is.id]=n}var e={};return n}(),o.QueueProgress=function(){var e=this;e.size=0,e.loaded=0,e.uploaded=0,e.failed=0,e.queued=0,e.percent=0,e.bytesPerSec=0,e.reset=function(){e.size=e.loaded=e.uploaded=e.failed=e.queued=e.percent=e.bytesPerSec=0}},e.plupload=o})(window,mOxie);
</del><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+/**
+ * Modified for WordPress, Silverlight and Flash runtimes support was removed.
+ * See https://core.trac.wordpress.org/ticket/41755.
+ */
+!function(a,b,c){function d(a){function b(a,b,c){var e={chunks:"slice_blob",jpgresize:"send_binary_string",pngresize:"send_binary_string",progress:"report_upload_progress",multi_selection:"select_multiple",dragdrop:"drag_and_drop",drop_element:"drag_and_drop",headers:"send_custom_headers",urlstream_upload:"send_binary_string",canSendBinary:"send_binary",triggerDialog:"summon_file_dialog"};e[a]?d[e[a]]=b:c||(d[a]=b)}var c=a.required_features,d={};return"string"==typeof c?g.each(c.split(/\s*,\s*/),function(a){b(a,!0)}):"object"==typeof c?g.each(c,function(a,c){b(c,a)}):c===!0&&(a.chunk_size>0&&(d.slice_blob=!0),!a.resize.enabled&&a.multipart||(d.send_binary_string=!0),g.each(a,function(a,c){b(c,!!a,!0)})),a.runtimes="html5,html4",d}var e=a.setTimeout,f={},g={VERSION:"2.1.9",STOPPED:1,STARTED:2,QUEUED:1,UPLOADIN
 G:2,FAILED:4,DONE:5,GENERIC_ERROR:-100,HTTP_ERROR:-200,IO_ERROR:-300,SECURITY_ERROR:-400,INIT_ERROR:-500,FILE_SIZE_ERROR:-600,FILE_EXTENSION_ERROR:-601,FILE_DUPLICATE_ERROR:-602,IMAGE_FORMAT_ERROR:-700,MEMORY_ERROR:-701,IMAGE_DIMENSIONS_ERROR:-702,mimeTypes:b.mimes,ua:b.ua,typeOf:b.typeOf,extend:b.extend,guid:b.guid,getAll:function(a){var b,c=[];"array"!==g.typeOf(a)&&(a=[a]);for(var d=a.length;d--;)b=g.get(a[d]),b&&c.push(b);return c.length?c:null},get:b.get,each:b.each,getPos:b.getPos,getSize:b.getSize,xmlEncode:function(a){var b={"<":"lt",">":"gt","&":"amp",'"':"quot","'":"#39"},c=/[<>&\"\']/g;return a?(""+a).replace(c,function(a){return b[a]?"&"+b[a]+";":a}):a},toArray:b.toArray,inArray:b.inArray,addI18n:b.addI18n,translate:b.translate,isEmptyObj:b.isEmptyObj,hasClass:b.hasClass,addClass:b.addClass,rem
 oveClass:b.removeClass,getStyle:b.getStyle,addEvent:b.addEvent,removeEvent:b.removeEvent,removeAllEvents:b.removeAllEvents,cleanName:function(a){var b,c;for(c=[/[\300-\306]/g,"A",/[\340-\346]/g,"a",/\307/g,"C",/\347/g,"c",/[\310-\313]/g,"E",/[\350-\353]/g,"e",/[\314-\317]/g,"I",/[\354-\357]/g,"i",/\321/g,"N",/\361/g,"n",/[\322-\330]/g,"O",/[\362-\370]/g,"o",/[\331-\334]/g,"U",/[\371-\374]/g,"u"],b=0;b<c.length;b+=2)a=a.replace(c[b],c[b+1]);return a=a.replace(/\s+/g,"_"),a=a.replace(/[^a-z0-9_\-\.]+/gi,"")},buildUrl:function(a,b){var c="";return g.each(b,function(a,b){c+=(c?"&":"")+encodeURIComponent(b)+"="+encodeURIComponent(a)}),c&&(a+=(a.indexOf("?")>0?"&":"?")+c),a},formatSize:function(a){function b(a,b){return Math.round(a*Math.pow
 (10,b))/Math.pow(10,b)}if(a===c||/\D/.test(a))return g.translate("N/A");var d=Math.pow(1024,4);return a>d?b(a/d,1)+" "+g.translate("tb"):a>(d/=1024)?b(a/d,1)+" "+g.translate("gb"):a>(d/=1024)?b(a/d,1)+" "+g.translate("mb"):a>1024?Math.round(a/1024)+" "+g.translate("kb"):a+" "+g.translate("b")},parseSize:b.parseSizeStr,predictRuntime:function(a,c){var d,e;return d=new g.Uploader(a),e=b.Runtime.thatCan(d.getOption().required_features,c||a.runtimes),d.destroy(),e},addFileFilter:function(a,b){f[a]=b}};g.addFileFilter("mime_types",function(a,b,c){a.length&&!a.regexp.test(b.name)?(this.trigger("Error",{code:g.FILE_EXTENSION_ERROR,message:g.translate("File extension error."),file:b}),c(!1)):c(!0)}),g.addFileFilter("max_file_size",function(a,b,c){var d;a=g.parseSize(a),b.size!==d&&a&&b.size>a?(this.trigge
 r("Error",{code:g.FILE_SIZE_ERROR,message:g.translate("File size error."),file:b}),c(!1)):c(!0)}),g.addFileFilter("prevent_duplicates",function(a,b,c){if(a)for(var d=this.files.length;d--;)if(b.name===this.files[d].name&&b.size===this.files[d].size)return this.trigger("Error",{code:g.FILE_DUPLICATE_ERROR,message:g.translate("Duplicate file error."),file:b}),void c(!1);c(!0)}),g.Uploader=function(a){function h(){var a,b,c=0;if(this.state==g.STARTED){for(b=0;b<D.length;b++)a||D[b].status!=g.QUEUED?c++:(a=D[b],this.trigger("BeforeUpload",a)&&(a.status=g.UPLOADING,this.trigger("UploadFile",a)));c==D.length&&(this.state!==g.STOPPED&&(this.state=g.STOPPED,this.trigger("StateChanged")),this.trigger("UploadComplete",D))}}function i(a){a.percent=a.size>0?Math.ceil(a.loaded/a.size*100):100,j()}function j(){var a,b;for(A.reset(),a=0;a<D.length;a++)b=D[a],b.size!==c
 ?(A.size+=b.origSize,A.loaded+=b.loaded*b.origSize/b.size):A.size=c,b.status==g.DONE?A.uploaded++:b.status==g.FAILED?A.failed++:A.queued++;A.size===c?A.percent=D.length>0?Math.ceil(A.uploaded/D.length*100):0:(A.bytesPerSec=Math.ceil(A.loaded/((+new Date-z||1)/1e3)),A.percent=A.size>0?Math.ceil(A.loaded/A.size*100):0)}function k(){var a=F[0]||G[0];return!!a&&a.getRuntime().uid}function l(a,c){if(a.ruid){var d=b.Runtime.getInfo(a.ruid);if(d)return d.can(c)}return!1}function m(){this.bind("FilesAdded FilesRemoved",function(a){a.trigger("QueueChanged"),a.refresh()}),this.bind("CancelUpload",u),this.bind("BeforeUpload",q),this.bind("UploadFile",r),this.bind("UploadProgress",s),this.bind("StateChanged",t),this.bind("QueueChanged",j),this.bind("Error",w),this.bind("FileUploaded",v),this.bind("Destroy",x)}function n(a,c){var d=this,e=0,f=[],h={runtime_order:a.runtimes,
 required_caps:a.required_features,preferred_caps:E};g.each(a.runtimes.split(/\s*,\s*/),function(b){a[b]&&(h[b]=a[b])}),a.browse_button&&g.each(a.browse_button,function(c){f.push(function(f){var i=new b.FileInput(g.extend({},h,{accept:a.filters.mime_types,name:a.file_data_name,multiple:a.multi_selection,container:a.container,browse_button:c}));i.onready=function(){var a=b.Runtime.getInfo(this.ruid);b.extend(d.features,{chunks:a.can("slice_blob"),multipart:a.can("send_multipart"),multi_selection:a.can("select_multiple")}),e++,F.push(this),f()},i.onchange=function(){d.addFile(this.files)},i.bind("mouseenter mouseleave mousedown mouseup",function(d){H||(a.browse_button_hover&&("mouseenter"===d.type?b.addClass(c,a.browse_button_hover):"mouseleave"===d.type&&b.removeClass(c,a.browse_button_hover)),a.browse_button_active&&("mousedown"===d.type?b.addClass(c,a.browse_button_active):&
 quot;mouseup"===d.type&&b.removeClass(c,a.browse_button_active)))}),i.bind("mousedown",function(){d.trigger("Browse")}),i.bind("error runtimeerror",function(){i=null,f()}),i.init()})}),a.drop_element&&g.each(a.drop_element,function(a){f.push(function(c){var f=new b.FileDrop(g.extend({},h,{drop_zone:a}));f.onready=function(){var a=b.Runtime.getInfo(this.ruid);b.extend(d.features,{chunks:a.can("slice_blob"),multipart:a.can("send_multipart"),dragdrop:a.can("drag_and_drop")}),e++,G.push(this),c()},f.ondrop=function(){d.addFile(this.files)},f.bind("error runtimeerror",function(){f=null,c()}),f.init()})}),b.inSeries(f,function(){"function"==typeof c&&c(e)})}function o(a,d,e){var f=new b.Image;try{f.onload=function(){return d.width>this.width&&d.height>this.height&&d.quality===c&&d.preserve_headers&&!d.crop?(this.destroy(),e(a)):void f.downsize(
 d.width,d.height,d.crop,d.preserve_headers)},f.onresize=function(){e(this.getAsBlob(a.type,d.quality)),this.destroy()},f.onerror=function(){e(a)},f.load(a)}catch(g){e(a)}}function p(a,c,e){function f(a,b,c){var d=y[a];switch(a){case"max_file_size":"max_file_size"===a&&(y.max_file_size=y.filters.max_file_size=b);break;case"chunk_size":(b=g.parseSize(b))&&(y[a]=b,y.send_file_name=!0);break;case"multipart":y[a]=b,b||(y.send_file_name=!0);break;case"unique_names":y[a]=b,b&&(y.send_file_name=!0);break;case"filters":"array"===g.typeOf(b)&&(b={mime_types:b}),c?g.extend(y.filters,b):y.filters=b,b.mime_types&&(y.filters.mime_types.regexp=function(a){var b=[];return g.each(a,function(a){g.each(a.extensions.split(/,/),function(a){/^\s*\*\s*$/.test(a)?b.push("\\.*"):b.push("\\."+a.replace(new RegExp("["+"/^$.*+?|()[]{}\\".replace(/./g,"\\$&am
 p;")+"]","g"),"\\$&"))})}),new RegExp("("+b.join("|")+")$","i")}(y.filters.mime_types));break;case"resize":c?g.extend(y.resize,b,{enabled:!0}):y.resize=b;break;case"prevent_duplicates":y.prevent_duplicates=y.filters.prevent_duplicates=!!b;break;case"container":case"browse_button":case"drop_element":b="container"===a?g.get(b):g.getAll(b);case"runtimes":case"multi_selection":y[a]=b,c||(i=!0);break;default:y[a]=b}c||h.trigger("OptionChanged",a,b,d)}var h=this,i=!1;"object"==typeof a?g.each(a,function(a,b){f(b,a,e)}):f(a,c,e),e?(y.required_features=d(g.extend({},y)),E=d(g.extend({},y,{required_features:!0}))):i&&(h.trigger("Destroy"),n.call(h,y,function(a){a?(h.runtime=b.Runtime.getInfo(k()).type,h.trigger("Init",{runtime:h.runtime}),h.trigger("PostInit")):h.trigger("E
 rror",{code:g.INIT_ERROR,message:g.translate("Init error.")})}))}function q(a,b){if(a.settings.unique_names){var c=b.name.match(/\.([^.]+)$/),d="part";c&&(d=c[1]),b.target_name=b.id+"."+d}}function r(a,c){function d(){k-- >0?e(f,1e3):(c.loaded=n,a.trigger("Error",{code:g.HTTP_ERROR,message:g.translate("HTTP Error."),file:c,response:B.responseText,status:B.status,responseHeaders:B.getAllResponseHeaders()}))}function f(){var l,o,p,q={};c.status===g.UPLOADING&&a.state!==g.STOPPED&&(a.settings.send_file_name&&(q.name=c.target_name||c.name),j&&m.chunks&&h.size>j?(p=Math.min(j,h.size-n),l=h.slice(n,n+p)):(p=h.size,l=h),j&&m.chunks&&(a.settings.send_chunk_number?(q.chunk=Math.ceil(n/j),q.chunks=Math.ceil(h.size/j)):(q.offset=n,q.total=h.size)),B=new b.XMLHttpRequest,B.upload&&(B.upload.onprogress=function(b){c.loaded=Math.min(c.size,n+b.loaded),a.trigger(&quo
 t;UploadProgress",c)}),B.onload=function(){return B.status>=400?void d():(k=a.settings.max_retries,p<h.size?(l.destroy(),n+=p,c.loaded=Math.min(n,h.size),a.trigger("ChunkUploaded",c,{offset:c.loaded,total:h.size,response:B.responseText,status:B.status,responseHeaders:B.getAllResponseHeaders()}),"Android Browser"===b.Env.browser&&a.trigger("UploadProgress",c)):c.loaded=c.size,l=o=null,void(!n||n>=h.size?(c.size!=c.origSize&&(h.destroy(),h=null),a.trigger("UploadProgress",c),c.status=g.DONE,a.trigger("FileUploaded",c,{response:B.responseText,status:B.status,responseHeaders:B.getAllResponseHeaders()})):e(f,1)))},B.onerror=function(){d()},B.onloadend=function(){this.destroy(),B=null},a.settings.multipart&&m.multipart?(B.open("post",i,!0),g.each(a.settings.headers,function(a,b){B.setRequestHeader(b,a)}),o=new b.FormData,g.each(g.extend(q,a.settings.multipart_params),function(a,b){o.append(b,
 a)}),o.append(a.settings.file_data_name,l),B.send(o,{runtime_order:a.settings.runtimes,required_caps:a.settings.required_features,preferred_caps:E})):(i=g.buildUrl(a.settings.url,g.extend(q,a.settings.multipart_params)),B.open("post",i,!0),B.setRequestHeader("Content-Type","application/octet-stream"),g.each(a.settings.headers,function(a,b){B.setRequestHeader(b,a)}),B.send(l,{runtime_order:a.settings.runtimes,required_caps:a.settings.required_features,preferred_caps:E})))}var h,i=a.settings.url,j=a.settings.chunk_size,k=a.settings.max_retries,m=a.features,n=0;c.loaded&&(n=c.loaded=j?j*Math.floor(c.loaded/j):0),h=c.getSource(),a.settings.resize.enabled&&l(h,"send_binary_string")&&~b.inArray(h.type,["image/jpeg","image/png"])?o.call(this,h,a.settings.resize,function(a){h=a,c.size=a.size,f()}):f()}function s(a,b){i(b)}function t(a){if(a.state==g.STARTED)z=+new Date;else if(a.state==g.STOPPED)for(var b=a.
 files.length-1;b>=0;b--)a.files[b].status==g.UPLOADING&&(a.files[b].status=g.QUEUED,j())}function u(){B&&B.abort()}function v(a){j(),e(function(){h.call(a)},1)}function w(a,b){b.code===g.INIT_ERROR?a.destroy():b.code===g.HTTP_ERROR&&(b.file.status=g.FAILED,i(b.file),a.state==g.STARTED&&(a.trigger("CancelUpload"),e(function(){h.call(a)},1)))}function x(a){a.stop(),g.each(D,function(a){a.destroy()}),D=[],F.length&&(g.each(F,function(a){a.destroy()}),F=[]),G.length&&(g.each(G,function(a){a.destroy()}),G=[]),E={},H=!1,z=B=null,A.reset()}var y,z,A,B,C=g.guid(),D=[],E={},F=[],G=[],H=!1;y={runtimes:b.Runtime.order,max_retries:0,chunk_size:0,multipart:!0,multi_selection:!0,file_data_name:"file",filters:{mime_types:[],prevent_duplicates:!1,max_file_size:0},resize:{enabled:!1,preserve_headers:!0,crop:!1},send_file_name:!0,send_chunk_number:!0},p.call(this,a,null,!0),A=new g.QueueProgress,g.extend(this,{id:C,uid:C,state:g.S
 TOPPED,features:{},runtime:null,files:D,settings:y,total:A,init:function(){var a,c,d=this;return a=d.getOption("preinit"),"function"==typeof a?a(d):g.each(a,function(a,b){d.bind(b,a)}),m.call(d),g.each(["container","browse_button","drop_element"],function(a){if(null===d.getOption(a))return c={code:g.INIT_ERROR,message:g.translate("'%' specified, but cannot be found.")},!1}),c?d.trigger("Error",c):y.browse_button||y.drop_element?void n.call(d,y,function(a){var c=d.getOption("init");"function"==typeof c?c(d):g.each(c,function(a,b){d.bind(b,a)}),a?(d.runtime=b.Runtime.getInfo(k()).type,d.trigger("Init",{runtime:d.runtime}),d.trigger("PostInit")):d.trigger("Error",{code:g.INIT_ERROR,message:g.translate("Init error.")})}):d.trigger("Error",{code:g.INIT_ERROR,message:g.translate("You must specify either 'browse_button' or 'drop_element'.")})
 },setOption:function(a,b){p.call(this,a,b,!this.runtime)},getOption:function(a){return a?y[a]:y},refresh:function(){F.length&&g.each(F,function(a){a.trigger("Refresh")}),this.trigger("Refresh")},start:function(){this.state!=g.STARTED&&(this.state=g.STARTED,this.trigger("StateChanged"),h.call(this))},stop:function(){this.state!=g.STOPPED&&(this.state=g.STOPPED,this.trigger("StateChanged"),this.trigger("CancelUpload"))},disableBrowse:function(){H=arguments[0]===c||arguments[0],F.length&&g.each(F,function(a){a.disable(H)}),this.trigger("DisableBrowse",H)},getFile:function(a){var b;for(b=D.length-1;b>=0;b--)if(D[b].id===a)return D[b]},addFile:function(a,c){function d(a,c){var d=[];b.each(j.settings.filters,function(b,c){f[c]&&d.push(function(d){f[c].call(j,b,a,function(a){d(!a)})})}),b.inSeries(d,c)}function h(a){var f=b.typeOf(a);if(a instanceof b.File){if(!a.ruid&&!a.isDetach
 ed()){if(!i)return!1;a.ruid=i,a.connectRuntime(i)}h(new g.File(a))}else a instanceof b.Blob?(h(a.getSource()),a.destroy()):a instanceof g.File?(c&&(a.name=c),l.push(function(b){d(a,function(c){c||(D.push(a),m.push(a),j.trigger("FileFiltered",a)),e(b,1)})})):b.inArray(f,["file","blob"])!==-1?h(new b.File(null,a)):"node"===f&&"filelist"===b.typeOf(a.files)?b.each(a.files,h):"array"===f&&(c=null,b.each(a,h))}var i,j=this,l=[],m=[];i=k(),h(a),l.length&&b.inSeries(l,function(){m.length&&j.trigger("FilesAdded",m)})},removeFile:function(a){for(var b="string"==typeof a?a:a.id,c=D.length-1;c>=0;c--)if(D[c].id===b)return this.splice(c,1)[0]},splice:function(a,b){var d=D.splice(a===c?0:a,b===c?D.length:b),e=!1;return this.state==g.STARTED&&(g.each(d,function(a){if(a.status===g.UPLOADING)return e=!0,!1}),e&&this.stop()),this.trigger("FilesRemoved",
 d),g.each(d,function(a){a.destroy()}),e&&this.start(),d},dispatchEvent:function(a){var b,c;if(a=a.toLowerCase(),b=this.hasEventListener(a)){b.sort(function(a,b){return b.priority-a.priority}),c=[].slice.call(arguments),c.shift(),c.unshift(this);for(var d=0;d<b.length;d++)if(b[d].fn.apply(b[d].scope,c)===!1)return!1}return!0},bind:function(a,b,c,d){g.Uploader.prototype.bind.call(this,a,b,d,c)},destroy:function(){this.trigger("Destroy"),y=A=null,this.unbindAll()}})},g.Uploader.prototype=b.EventTarget.instance,g.File=function(){function a(a){g.extend(this,{id:g.guid(),name:a.name||a.fileName,type:a.type||"",size:a.size||a.fileSize,origSize:a.size||a.fileSize,loaded:0,percent:0,status:g.QUEUED,lastModifiedDate:a.lastModifiedDate||(new Date).toLocaleString(),getNative:function(){var a=this.getSource().getSource();return b.inArray(b.typeOf(a),["blob","file"])!==-1?a:null},getSource:function(){return c[this.id]?c[this.id]:null},destroy:fun
 ction(){var a=this.getSource();a&&(a.destroy(),delete c[this.id])}}),c[this.id]=a}var c={};return a}(),g.QueueProgress=function(){var a=this;a.size=0,a.loaded=0,a.uploaded=0,a.failed=0,a.queued=0,a.percent=0,a.bytesPerSec=0,a.reset=function(){a.size=a.loaded=a.uploaded=a.failed=a.queued=a.percent=a.bytesPerSec=0}},a.plupload=g}(window,mOxie);
</ins></span></pre></div>
<a id="trunksrcwpincludesjspluploadpluploadjs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/src/wp-includes/js/plupload/plupload.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/js/plupload/plupload.js                             (rev 0)
+++ trunk/src/wp-includes/js/plupload/plupload.js       2017-09-01 12:27:49 UTC (rev 41328)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,2379 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * Plupload - multi-runtime File Uploader
+ * v2.1.9
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ *
+ * Date: 2016-05-15
+ */
+/**
+ * Plupload.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+/**
+ * Modified for WordPress, Silverlight and Flash runtimes support was removed.
+ * See https://core.trac.wordpress.org/ticket/41755.
+ */
+
+/*global mOxie:true */
+
+;(function(window, o, undef) {
+
+var delay = window.setTimeout
+, fileFilters = {}
+;
+
+// convert plupload features to caps acceptable by mOxie
+function normalizeCaps(settings) {             
+       var features = settings.required_features, caps = {};
+
+       function resolve(feature, value, strict) {
+               // Feature notation is deprecated, use caps (this thing here is required for backward compatibility)
+               var map = { 
+                       chunks: 'slice_blob',
+                       jpgresize: 'send_binary_string',
+                       pngresize: 'send_binary_string',
+                       progress: 'report_upload_progress',
+                       multi_selection: 'select_multiple',
+                       dragdrop: 'drag_and_drop',
+                       drop_element: 'drag_and_drop',
+                       headers: 'send_custom_headers',
+                       urlstream_upload: 'send_binary_string',
+                       canSendBinary: 'send_binary',
+                       triggerDialog: 'summon_file_dialog'
+               };
+
+               if (map[feature]) {
+                       caps[map[feature]] = value;
+               } else if (!strict) {
+                       caps[feature] = value;
+               }
+       }
+
+       if (typeof(features) === 'string') {
+               plupload.each(features.split(/\s*,\s*/), function(feature) {
+                       resolve(feature, true);
+               });
+       } else if (typeof(features) === 'object') {
+               plupload.each(features, function(value, feature) {
+                       resolve(feature, value);
+               });
+       } else if (features === true) {
+               // check settings for required features
+               if (settings.chunk_size > 0) {
+                       caps.slice_blob = true;
+               }
+
+               if (settings.resize.enabled || !settings.multipart) {
+                       caps.send_binary_string = true;
+               }
+               
+               plupload.each(settings, function(value, feature) {
+                       resolve(feature, !!value, true); // strict check
+               });
+       }
+
+       // WP: only html runtimes.
+       settings.runtimes = 'html5,html4';
+
+       return caps;
+}
+
+/** 
+ * @module plupload    
+ * @static
+ */
+var plupload = {
+       /**
+        * Plupload version will be replaced on build.
+        *
+        * @property VERSION
+        * @for Plupload
+        * @static
+        * @final
+        */
+       VERSION : '2.1.9',
+
+       /**
+        * The state of the queue before it has started and after it has finished
+        *
+        * @property STOPPED
+        * @static
+        * @final
+        */
+       STOPPED : 1,
+
+       /**
+        * Upload process is running
+        *
+        * @property STARTED
+        * @static
+        * @final
+        */
+       STARTED : 2,
+
+       /**
+        * File is queued for upload
+        *
+        * @property QUEUED
+        * @static
+        * @final
+        */
+       QUEUED : 1,
+
+       /**
+        * File is being uploaded
+        *
+        * @property UPLOADING
+        * @static
+        * @final
+        */
+       UPLOADING : 2,
+
+       /**
+        * File has failed to be uploaded
+        *
+        * @property FAILED
+        * @static
+        * @final
+        */
+       FAILED : 4,
+
+       /**
+        * File has been uploaded successfully
+        *
+        * @property DONE
+        * @static
+        * @final
+        */
+       DONE : 5,
+
+       // Error constants used by the Error event
+
+       /**
+        * Generic error for example if an exception is thrown inside Silverlight.
+        *
+        * @property GENERIC_ERROR
+        * @static
+        * @final
+        */
+       GENERIC_ERROR : -100,
+
+       /**
+        * HTTP transport error. For example if the server produces a HTTP status other than 200.
+        *
+        * @property HTTP_ERROR
+        * @static
+        * @final
+        */
+       HTTP_ERROR : -200,
+
+       /**
+        * Generic I/O error. For example if it wasn't possible to open the file stream on local machine.
+        *
+        * @property IO_ERROR
+        * @static
+        * @final
+        */
+       IO_ERROR : -300,
+
+       /**
+        * @property SECURITY_ERROR
+        * @static
+        * @final
+        */
+       SECURITY_ERROR : -400,
+
+       /**
+        * Initialization error. Will be triggered if no runtime was initialized.
+        *
+        * @property INIT_ERROR
+        * @static
+        * @final
+        */
+       INIT_ERROR : -500,
+
+       /**
+        * File size error. If the user selects a file that is too large it will be blocked and an error of this type will be triggered.
+        *
+        * @property FILE_SIZE_ERROR
+        * @static
+        * @final
+        */
+       FILE_SIZE_ERROR : -600,
+
+       /**
+        * File extension error. If the user selects a file that isn't valid according to the filters setting.
+        *
+        * @property FILE_EXTENSION_ERROR
+        * @static
+        * @final
+        */
+       FILE_EXTENSION_ERROR : -601,
+
+       /**
+        * Duplicate file error. If prevent_duplicates is set to true and user selects the same file again.
+        *
+        * @property FILE_DUPLICATE_ERROR
+        * @static
+        * @final
+        */
+       FILE_DUPLICATE_ERROR : -602,
+
+       /**
+        * Runtime will try to detect if image is proper one. Otherwise will throw this error.
+        *
+        * @property IMAGE_FORMAT_ERROR
+        * @static
+        * @final
+        */
+       IMAGE_FORMAT_ERROR : -700,
+
+       /**
+        * While working on files runtime may run out of memory and will throw this error.
+        *
+        * @since 2.1.2
+        * @property MEMORY_ERROR
+        * @static
+        * @final
+        */
+       MEMORY_ERROR : -701,
+
+       /**
+        * Each runtime has an upper limit on a dimension of the image it can handle. If bigger, will throw this error.
+        *
+        * @property IMAGE_DIMENSIONS_ERROR
+        * @static
+        * @final
+        */
+       IMAGE_DIMENSIONS_ERROR : -702,
+
+       /**
+        * Mime type lookup table.
+        *
+        * @property mimeTypes
+        * @type Object
+        * @final
+        */
+       mimeTypes : o.mimes,
+
+       /**
+        * In some cases sniffing is the only way around :(
+        */
+       ua: o.ua,
+
+       /**
+        * Gets the true type of the built-in object (better version of typeof).
+        * @credits Angus Croll (http://javascriptweblog.wordpress.com/)
+        *
+        * @method typeOf
+        * @static
+        * @param {Object} o Object to check.
+        * @return {String} Object [[Class]]
+        */
+       typeOf: o.typeOf,
+
+       /**
+        * Extends the specified object with another object.
+        *
+        * @method extend
+        * @static
+        * @param {Object} target Object to extend.
+        * @param {Object..} obj Multiple objects to extend with.
+        * @return {Object} Same as target, the extended object.
+        */
+       extend : o.extend,
+
+       /**
+        * Generates an unique ID. This is 99.99% unique since it takes the current time and 5 random numbers.
+        * The only way a user would be able to get the same ID is if the two persons at the same exact millisecond manages
+        * to get 5 the same random numbers between 0-65535 it also uses a counter so each call will be guaranteed to be page unique.
+        * It's more probable for the earth to be hit with an asteriod. You can also if you want to be 100% sure set the plupload.guidPrefix property
+        * to an user unique key.
+        *
+        * @method guid
+        * @static
+        * @return {String} Virtually unique id.
+        */
+       guid : o.guid,
+
+       /**
+        * Get array of DOM Elements by their ids.
+        * 
+        * @method get
+        * @param {String} id Identifier of the DOM Element
+        * @return {Array}
+       */
+       getAll : function get(ids) {
+               var els = [], el;
+
+               if (plupload.typeOf(ids) !== 'array') {
+                       ids = [ids];
+               }
+
+               var i = ids.length;
+               while (i--) {
+                       el = plupload.get(ids[i]);
+                       if (el) {
+                               els.push(el);
+                       }
+               }
+
+               return els.length ? els : null;
+       },
+
+       /**
+       Get DOM element by id
+
+       @method get
+       @param {String} id Identifier of the DOM Element
+       @return {Node}
+       */
+       get: o.get,
+
+       /**
+        * Executes the callback function for each item in array/object. If you return false in the
+        * callback it will break the loop.
+        *
+        * @method each
+        * @static
+        * @param {Object} obj Object to iterate.
+        * @param {function} callback Callback function to execute for each item.
+        */
+       each : o.each,
+
+       /**
+        * Returns the absolute x, y position of an Element. The position will be returned in a object with x, y fields.
+        *
+        * @method getPos
+        * @static
+        * @param {Element} node HTML element or element id to get x, y position from.
+        * @param {Element} root Optional root element to stop calculations at.
+        * @return {object} Absolute position of the specified element object with x, y fields.
+        */
+       getPos : o.getPos,
+
+       /**
+        * Returns the size of the specified node in pixels.
+        *
+        * @method getSize
+        * @static
+        * @param {Node} node Node to get the size of.
+        * @return {Object} Object with a w and h property.
+        */
+       getSize : o.getSize,
+
+       /**
+        * Encodes the specified string.
+        *
+        * @method xmlEncode
+        * @static
+        * @param {String} s String to encode.
+        * @return {String} Encoded string.
+        */
+       xmlEncode : function(str) {
+               var xmlEncodeChars = {'<' : 'lt', '>' : 'gt', '&' : 'amp', '"' : 'quot', '\'' : '#39'}, xmlEncodeRegExp = /[<>&\"\']/g;
+
+               return str ? ('' + str).replace(xmlEncodeRegExp, function(chr) {
+                       return xmlEncodeChars[chr] ? '&' + xmlEncodeChars[chr] + ';' : chr;
+               }) : str;
+       },
+
+       /**
+        * Forces anything into an array.
+        *
+        * @method toArray
+        * @static
+        * @param {Object} obj Object with length field.
+        * @return {Array} Array object containing all items.
+        */
+       toArray : o.toArray,
+
+       /**
+        * Find an element in array and return its index if present, otherwise return -1.
+        *
+        * @method inArray
+        * @static
+        * @param {mixed} needle Element to find
+        * @param {Array} array
+        * @return {Int} Index of the element, or -1 if not found
+        */
+       inArray : o.inArray,
+
+       /**
+        * Extends the language pack object with new items.
+        *
+        * @method addI18n
+        * @static
+        * @param {Object} pack Language pack items to add.
+        * @return {Object} Extended language pack object.
+        */
+       addI18n : o.addI18n,
+
+       /**
+        * Translates the specified string by checking for the english string in the language pack lookup.
+        *
+        * @method translate
+        * @static
+        * @param {String} str String to look for.
+        * @return {String} Translated string or the input string if it wasn't found.
+        */
+       translate : o.translate,
+
+       /**
+        * Checks if object is empty.
+        *
+        * @method isEmptyObj
+        * @static
+        * @param {Object} obj Object to check.
+        * @return {Boolean}
+        */
+       isEmptyObj : o.isEmptyObj,
+
+       /**
+        * Checks if specified DOM element has specified class.
+        *
+        * @method hasClass
+        * @static
+        * @param {Object} obj DOM element like object to add handler to.
+        * @param {String} name Class name
+        */
+       hasClass : o.hasClass,
+
+       /**
+        * Adds specified className to specified DOM element.
+        *
+        * @method addClass
+        * @static
+        * @param {Object} obj DOM element like object to add handler to.
+        * @param {String} name Class name
+        */
+       addClass : o.addClass,
+
+       /**
+        * Removes specified className from specified DOM element.
+        *
+        * @method removeClass
+        * @static
+        * @param {Object} obj DOM element like object to add handler to.
+        * @param {String} name Class name
+        */
+       removeClass : o.removeClass,
+
+       /**
+        * Returns a given computed style of a DOM element.
+        *
+        * @method getStyle
+        * @static
+        * @param {Object} obj DOM element like object.
+        * @param {String} name Style you want to get from the DOM element
+        */
+       getStyle : o.getStyle,
+
+       /**
+        * Adds an event handler to the specified object and store reference to the handler
+        * in objects internal Plupload registry (@see removeEvent).
+        *
+        * @method addEvent
+        * @static
+        * @param {Object} obj DOM element like object to add handler to.
+        * @param {String} name Name to add event listener to.
+        * @param {Function} callback Function to call when event occurs.
+        * @param {String} (optional) key that might be used to add specifity to the event record.
+        */
+       addEvent : o.addEvent,
+
+       /**
+        * Remove event handler from the specified object. If third argument (callback)
+        * is not specified remove all events with the specified name.
+        *
+        * @method removeEvent
+        * @static
+        * @param {Object} obj DOM element to remove event listener(s) from.
+        * @param {String} name Name of event listener to remove.
+        * @param {Function|String} (optional) might be a callback or unique key to match.
+        */
+       removeEvent: o.removeEvent,
+
+       /**
+        * Remove all kind of events from the specified object
+        *
+        * @method removeAllEvents
+        * @static
+        * @param {Object} obj DOM element to remove event listeners from.
+        * @param {String} (optional) unique key to match, when removing events.
+        */
+       removeAllEvents: o.removeAllEvents,
+
+       /**
+        * Cleans the specified name from national characters (diacritics). The result will be a name with only a-z, 0-9 and _.
+        *
+        * @method cleanName
+        * @static
+        * @param {String} s String to clean up.
+        * @return {String} Cleaned string.
+        */
+       cleanName : function(name) {
+               var i, lookup;
+
+               // Replace diacritics
+               lookup = [
+                       /[\300-\306]/g, 'A', /[\340-\346]/g, 'a',
+                       /\307/g, 'C', /\347/g, 'c',
+                       /[\310-\313]/g, 'E', /[\350-\353]/g, 'e',
+                       /[\314-\317]/g, 'I', /[\354-\357]/g, 'i',
+                       /\321/g, 'N', /\361/g, 'n',
+                       /[\322-\330]/g, 'O', /[\362-\370]/g, 'o',
+                       /[\331-\334]/g, 'U', /[\371-\374]/g, 'u'
+               ];
+
+               for (i = 0; i < lookup.length; i += 2) {
+                       name = name.replace(lookup[i], lookup[i + 1]);
+               }
+
+               // Replace whitespace
+               name = name.replace(/\s+/g, '_');
+
+               // Remove anything else
+               name = name.replace(/[^a-z0-9_\-\.]+/gi, '');
+
+               return name;
+       },
+
+       /**
+        * Builds a full url out of a base URL and an object with items to append as query string items.
+        *
+        * @method buildUrl
+        * @static
+        * @param {String} url Base URL to append query string items to.
+        * @param {Object} items Name/value object to serialize as a querystring.
+        * @return {String} String with url + serialized query string items.
+        */
+       buildUrl : function(url, items) {
+               var query = '';
+
+               plupload.each(items, function(value, name) {
+                       query += (query ? '&' : '') + encodeURIComponent(name) + '=' + encodeURIComponent(value);
+               });
+
+               if (query) {
+                       url += (url.indexOf('?') > 0 ? '&' : '?') + query;
+               }
+
+               return url;
+       },
+
+       /**
+        * Formats the specified number as a size string for example 1024 becomes 1 KB.
+        *
+        * @method formatSize
+        * @static
+        * @param {Number} size Size to format as string.
+        * @return {String} Formatted size string.
+        */
+       formatSize : function(size) {
+
+               if (size === undef || /\D/.test(size)) {
+                       return plupload.translate('N/A');
+               }
+
+               function round(num, precision) {
+                       return Math.round(num * Math.pow(10, precision)) / Math.pow(10, precision);
+               }
+
+               var boundary = Math.pow(1024, 4);
+
+               // TB
+               if (size > boundary) {
+                       return round(size / boundary, 1) + " " + plupload.translate('tb');
+               }
+
+               // GB
+               if (size > (boundary/=1024)) {
+                       return round(size / boundary, 1) + " " + plupload.translate('gb');
+               }
+
+               // MB
+               if (size > (boundary/=1024)) {
+                       return round(size / boundary, 1) + " " + plupload.translate('mb');
+               }
+
+               // KB
+               if (size > 1024) {
+                       return Math.round(size / 1024) + " " + plupload.translate('kb');
+               }
+
+               return size + " " + plupload.translate('b');
+       },
+
+
+       /**
+        * Parses the specified size string into a byte value. For example 10kb becomes 10240.
+        *
+        * @method parseSize
+        * @static
+        * @param {String|Number} size String to parse or number to just pass through.
+        * @return {Number} Size in bytes.
+        */
+       parseSize : o.parseSizeStr,
+
+
+       /**
+        * A way to predict what runtime will be choosen in the current environment with the
+        * specified settings.
+        *
+        * @method predictRuntime
+        * @static
+        * @param {Object|String} config Plupload settings to check
+        * @param {String} [runtimes] Comma-separated list of runtimes to check against
+        * @return {String} Type of compatible runtime
+        */
+       predictRuntime : function(config, runtimes) {
+               var up, runtime;
+
+               up = new plupload.Uploader(config);
+               runtime = o.Runtime.thatCan(up.getOption().required_features, runtimes || config.runtimes);
+               up.destroy();
+               return runtime;
+       },
+
+       /**
+        * Registers a filter that will be executed for each file added to the queue.
+        * If callback returns false, file will not be added.
+        *
+        * Callback receives two arguments: a value for the filter as it was specified in settings.filters
+        * and a file to be filtered. Callback is executed in the context of uploader instance.
+        *
+        * @method addFileFilter
+        * @static
+        * @param {String} name Name of the filter by which it can be referenced in settings.filters
+        * @param {String} cb Callback - the actual routine that every added file must pass
+        */
+       addFileFilter: function(name, cb) {
+               fileFilters[name] = cb;
+       }
+};
+
+
+plupload.addFileFilter('mime_types', function(filters, file, cb) {
+       if (filters.length && !filters.regexp.test(file.name)) {
+               this.trigger('Error', {
+                       code : plupload.FILE_EXTENSION_ERROR,
+                       message : plupload.translate('File extension error.'),
+                       file : file
+               });
+               cb(false);
+       } else {
+               cb(true);
+       }
+});
+
+
+plupload.addFileFilter('max_file_size', function(maxSize, file, cb) {
+       var undef;
+
+       maxSize = plupload.parseSize(maxSize);
+
+       // Invalid file size
+       if (file.size !== undef && maxSize && file.size > maxSize) {
+               this.trigger('Error', {
+                       code : plupload.FILE_SIZE_ERROR,
+                       message : plupload.translate('File size error.'),
+                       file : file
+               });
+               cb(false);
+       } else {
+               cb(true);
+       }
+});
+
+
+plupload.addFileFilter('prevent_duplicates', function(value, file, cb) {
+       if (value) {
+               var ii = this.files.length;
+               while (ii--) {
+                       // Compare by name and size (size might be 0 or undefined, but still equivalent for both)
+                       if (file.name === this.files[ii].name && file.size === this.files[ii].size) {
+                               this.trigger('Error', {
+                                       code : plupload.FILE_DUPLICATE_ERROR,
+                                       message : plupload.translate('Duplicate file error.'),
+                                       file : file
+                               });
+                               cb(false);
+                               return;
+                       }
+               }
+       }
+       cb(true);
+});
+
+
+/**
+@class Uploader
+@constructor
+
+@param {Object} settings For detailed information about each option check documentation.
+       @param {String|DOMElement} settings.browse_button id of the DOM element or DOM element itself to use as file dialog trigger.
+       @param {String} settings.url URL of the server-side upload handler.
+       @param {Number|String} [settings.chunk_size=0] Chunk size in bytes to slice the file into. Shorcuts with b, kb, mb, gb, tb suffixes also supported. `e.g. 204800 or "204800b" or "200kb"`. By default - disabled.
+       @param {Boolean} [settings.send_chunk_number=true] Whether to send chunks and chunk numbers, or total and offset bytes.
+       @param {String|DOMElement} [settings.container] id of the DOM element or DOM element itself that will be used to wrap uploader structures. Defaults to immediate parent of the `browse_button` element.
+       @param {String|DOMElement} [settings.drop_element] id of the DOM element or DOM element itself to use as a drop zone for Drag-n-Drop.
+       @param {String} [settings.file_data_name="file"] Name for the file field in Multipart formated message.
+       @param {Object} [settings.filters={}] Set of file type filters.
+               @param {Array} [settings.filters.mime_types=[]] List of file types to accept, each one defined by title and list of extensions. `e.g. {title : "Image files", extensions : "jpg,jpeg,gif,png"}`. Dispatches `plupload.FILE_EXTENSION_ERROR`
+               @param {String|Number} [settings.filters.max_file_size=0] Maximum file size that the user can pick, in bytes. Optionally supports b, kb, mb, gb, tb suffixes. `e.g. "10mb" or "1gb"`. By default - not set. Dispatches `plupload.FILE_SIZE_ERROR`.
+               @param {Boolean} [settings.filters.prevent_duplicates=false] Do not let duplicates into the queue. Dispatches `plupload.FILE_DUPLICATE_ERROR`.
+       @param {String} [settings.flash_swf_url] URL of the Flash swf. (Not used in WordPress)
+       @param {Object} [settings.headers] Custom headers to send with the upload. Hash of name/value pairs.
+       @param {Number} [settings.max_retries=0] How many times to retry the chunk or file, before triggering Error event.
+       @param {Boolean} [settings.multipart=true] Whether to send file and additional parameters as Multipart formated message.
+       @param {Object} [settings.multipart_params] Hash of key/value pairs to send with every file upload.
+       @param {Boolean} [settings.multi_selection=true] Enable ability to select multiple files at once in file dialog.
+       @param {String|Object} [settings.required_features] Either comma-separated list or hash of required features that chosen runtime should absolutely possess.
+       @param {Object} [settings.resize] Enable resizng of images on client-side. Applies to `image/jpeg` and `image/png` only. `e.g. {width : 200, height : 200, quality : 90, crop: true}`
+               @param {Number} [settings.resize.width] If image is bigger, it will be resized.
+               @param {Number} [settings.resize.height] If image is bigger, it will be resized.
+               @param {Number} [settings.resize.quality=90] Compression quality for jpegs (1-100).
+               @param {Boolean} [settings.resize.crop=false] Whether to crop images to exact dimensions. By default they will be resized proportionally.
+       @param {String} [settings.runtimes="html5,html4"] Comma separated list of runtimes, that Plupload will try in turn, moving to the next if previous fails.
+       @param {String} [settings.silverlight_xap_url] URL of the Silverlight xap. (Not used in WordPress)
+       @param {Boolean} [settings.unique_names=false] If true will generate unique filenames for uploaded files.
+       @param {Boolean} [settings.send_file_name=true] Whether to send file name as additional argument - 'name' (required for chunked uploads and some other cases where file name cannot be sent via normal ways).
+*/
+plupload.Uploader = function(options) {
+       /**
+       Fires when the current RunTime has been initialized.
+       
+       @event Init
+       @param {plupload.Uploader} uploader Uploader instance sending the event.
+        */
+
+       /**
+       Fires after the init event incase you need to perform actions there.
+       
+       @event PostInit
+       @param {plupload.Uploader} uploader Uploader instance sending the event.
+        */
+
+       /**
+       Fires when the option is changed in via uploader.setOption().
+       
+       @event OptionChanged
+       @since 2.1
+       @param {plupload.Uploader} uploader Uploader instance sending the event.
+       @param {String} name Name of the option that was changed
+       @param {Mixed} value New value for the specified option
+       @param {Mixed} oldValue Previous value of the option
+        */
+
+       /**
+       Fires when the silverlight/flash or other shim needs to move.
+       
+       @event Refresh
+       @param {plupload.Uploader} uploader Uploader instance sending the event.
+        */
+
+       /**
+       Fires when the overall state is being changed for the upload queue.
+       
+       @event StateChanged
+       @param {plupload.Uploader} uploader Uploader instance sending the event.
+        */
+
+       /**
+       Fires when browse_button is clicked and browse dialog shows.
+       
+       @event Browse
+       @since 2.1.2
+       @param {plupload.Uploader} uploader Uploader instance sending the event.
+        */     
+
+       /**
+       Fires for every filtered file before it is added to the queue.
+       
+       @event FileFiltered
+       @since 2.1
+       @param {plupload.Uploader} uploader Uploader instance sending the event.
+       @param {plupload.File} file Another file that has to be added to the queue.
+        */
+
+       /**
+       Fires when the file queue is changed. In other words when files are added/removed to the files array of the uploader instance.
+       
+       @event QueueChanged
+       @param {plupload.Uploader} uploader Uploader instance sending the event.
+        */ 
+
+       /**
+       Fires after files were filtered and added to the queue.
+       
+       @event FilesAdded
+       @param {plupload.Uploader} uploader Uploader instance sending the event.
+       @param {Array} files Array of file objects that were added to queue by the user.
+        */
+
+       /**
+       Fires when file is removed from the queue.
+       
+       @event FilesRemoved
+       @param {plupload.Uploader} uploader Uploader instance sending the event.
+       @param {Array} files Array of files that got removed.
+        */
+
+       /**
+       Fires just before a file is uploaded. Can be used to cancel the upload for the specified file
+       by returning false from the handler.
+       
+       @event BeforeUpload
+       @param {plupload.Uploader} uploader Uploader instance sending the event.
+       @param {plupload.File} file File to be uploaded.
+        */
+
+       /**
+       Fires when a file is to be uploaded by the runtime.
+       
+       @event UploadFile
+       @param {plupload.Uploader} uploader Uploader instance sending the event.
+       @param {plupload.File} file File to be uploaded.
+        */
+
+       /**
+       Fires while a file is being uploaded. Use this event to update the current file upload progress.
+       
+       @event UploadProgress
+       @param {plupload.Uploader} uploader Uploader instance sending the event.
+       @param {plupload.File} file File that is currently being uploaded.
+        */     
+
+       /**
+       Fires when file chunk is uploaded.
+       
+       @event ChunkUploaded
+       @param {plupload.Uploader} uploader Uploader instance sending the event.
+       @param {plupload.File} file File that the chunk was uploaded for.
+       @param {Object} result Object with response properties.
+               @param {Number} result.offset The amount of bytes the server has received so far, including this chunk.
+               @param {Number} result.total The size of the file.
+               @param {String} result.response The response body sent by the server.
+               @param {Number} result.status The HTTP status code sent by the server.
+               @param {String} result.responseHeaders All the response headers as a single string.
+        */
+
+       /**
+       Fires when a file is successfully uploaded.
+       
+       @event FileUploaded
+       @param {plupload.Uploader} uploader Uploader instance sending the event.
+       @param {plupload.File} file File that was uploaded.
+       @param {Object} result Object with response properties.
+               @param {String} result.response The response body sent by the server.
+               @param {Number} result.status The HTTP status code sent by the server.
+               @param {String} result.responseHeaders All the response headers as a single string.
+        */
+
+       /**
+       Fires when all files in a queue are uploaded.
+       
+       @event UploadComplete
+       @param {plupload.Uploader} uploader Uploader instance sending the event.
+       @param {Array} files Array of file objects that was added to queue/selected by the user.
+        */
+
+       /**
+       Fires when a error occurs.
+       
+       @event Error
+       @param {plupload.Uploader} uploader Uploader instance sending the event.
+       @param {Object} error Contains code, message and sometimes file and other details.
+               @param {Number} error.code The plupload error code.
+               @param {String} error.message Description of the error (uses i18n).
+        */
+
+       /**
+       Fires when destroy method is called.
+       
+       @event Destroy
+       @param {plupload.Uploader} uploader Uploader instance sending the event.
+        */
+       var uid = plupload.guid()
+       , settings
+       , files = []
+       , preferred_caps = {}
+       , fileInputs = []
+       , fileDrops = []
+       , startTime
+       , total
+       , disabled = false
+       , xhr
+       ;
+
+
+       // Private methods
+       function uploadNext() {
+               var file, count = 0, i;
+
+               if (this.state == plupload.STARTED) {
+                       // Find first QUEUED file
+                       for (i = 0; i < files.length; i++) {
+                               if (!file && files[i].status == plupload.QUEUED) {
+                                       file = files[i];
+                                       if (this.trigger("BeforeUpload", file)) {
+                                               file.status = plupload.UPLOADING;
+                                               this.trigger("UploadFile", file);
+                                       }
+                               } else {
+                                       count++;
+                               }
+                       }
+
+                       // All files are DONE or FAILED
+                       if (count == files.length) {
+                               if (this.state !== plupload.STOPPED) {
+                                       this.state = plupload.STOPPED;
+                                       this.trigger("StateChanged");
+                               }
+                               this.trigger("UploadComplete", files);
+                       }
+               }
+       }
+
+
+       function calcFile(file) {
+               file.percent = file.size > 0 ? Math.ceil(file.loaded / file.size * 100) : 100;
+               calc();
+       }
+
+
+       function calc() {
+               var i, file;
+
+               // Reset stats
+               total.reset();
+
+               // Check status, size, loaded etc on all files
+               for (i = 0; i < files.length; i++) {
+                       file = files[i];
+
+                       if (file.size !== undef) {
+                               // We calculate totals based on original file size
+                               total.size += file.origSize;
+
+                               // Since we cannot predict file size after resize, we do opposite and
+                               // interpolate loaded amount to match magnitude of total
+                               total.loaded += file.loaded * file.origSize / file.size;
+                       } else {
+                               total.size = undef;
+                       }
+
+                       if (file.status == plupload.DONE) {
+                               total.uploaded++;
+                       } else if (file.status == plupload.FAILED) {
+                               total.failed++;
+                       } else {
+                               total.queued++;
+                       }
+               }
+
+               // If we couldn't calculate a total file size then use the number of files to calc percent
+               if (total.size === undef) {
+                       total.percent = files.length > 0 ? Math.ceil(total.uploaded / files.length * 100) : 0;
+               } else {
+                       total.bytesPerSec = Math.ceil(total.loaded / ((+new Date() - startTime || 1) / 1000.0));
+                       total.percent = total.size > 0 ? Math.ceil(total.loaded / total.size * 100) : 0;
+               }
+       }
+
+
+       function getRUID() {
+               var ctrl = fileInputs[0] || fileDrops[0];
+               if (ctrl) {
+                       return ctrl.getRuntime().uid;
+               }
+               return false;
+       }
+
+
+       function runtimeCan(file, cap) {
+               if (file.ruid) {
+                       var info = o.Runtime.getInfo(file.ruid);
+                       if (info) {
+                               return info.can(cap);
+                       }
+               }
+               return false;
+       }
+
+
+       function bindEventListeners() {
+               this.bind('FilesAdded FilesRemoved', function(up) {
+                       up.trigger('QueueChanged');
+                       up.refresh();
+               });
+
+               this.bind('CancelUpload', onCancelUpload);
+               
+               this.bind('BeforeUpload', onBeforeUpload);
+
+               this.bind('UploadFile', onUploadFile);
+
+               this.bind('UploadProgress', onUploadProgress);
+
+               this.bind('StateChanged', onStateChanged);
+
+               this.bind('QueueChanged', calc);
+
+               this.bind('Error', onError);
+
+               this.bind('FileUploaded', onFileUploaded);
+
+               this.bind('Destroy', onDestroy);
+       }
+
+
+       function initControls(settings, cb) {
+               var self = this, inited = 0, queue = [];
+
+               // common settings
+               var options = {
+                       runtime_order: settings.runtimes,
+                       required_caps: settings.required_features,
+                       preferred_caps: preferred_caps
+               };
+
+               // add runtime specific options if any
+               plupload.each(settings.runtimes.split(/\s*,\s*/), function(runtime) {
+                       if (settings[runtime]) {
+                               options[runtime] = settings[runtime];
+                       }
+               });
+
+               // initialize file pickers - there can be many
+               if (settings.browse_button) {
+                       plupload.each(settings.browse_button, function(el) {
+                               queue.push(function(cb) {
+                                       var fileInput = new o.FileInput(plupload.extend({}, options, {
+                                               accept: settings.filters.mime_types,
+                                               name: settings.file_data_name,
+                                               multiple: settings.multi_selection,
+                                               container: settings.container,
+                                               browse_button: el
+                                       }));
+
+                                       fileInput.onready = function() {
+                                               var info = o.Runtime.getInfo(this.ruid);
+
+                                               // for backward compatibility
+                                               o.extend(self.features, {
+                                                       chunks: info.can('slice_blob'),
+                                                       multipart: info.can('send_multipart'),
+                                                       multi_selection: info.can('select_multiple')
+                                               });
+
+                                               inited++;
+                                               fileInputs.push(this);
+                                               cb();
+                                       };
+
+                                       fileInput.onchange = function() {
+                                               self.addFile(this.files);
+                                       };
+
+                                       fileInput.bind('mouseenter mouseleave mousedown mouseup', function(e) {
+                                               if (!disabled) {
+                                                       if (settings.browse_button_hover) {
+                                                               if ('mouseenter' === e.type) {
+                                                                       o.addClass(el, settings.browse_button_hover);
+                                                               } else if ('mouseleave' === e.type) {
+                                                                       o.removeClass(el, settings.browse_button_hover);
+                                                               }
+                                                       }
+
+                                                       if (settings.browse_button_active) {
+                                                               if ('mousedown' === e.type) {
+                                                                       o.addClass(el, settings.browse_button_active);
+                                                               } else if ('mouseup' === e.type) {
+                                                                       o.removeClass(el, settings.browse_button_active);
+                                                               }
+                                                       }
+                                               }
+                                       });
+
+                                       fileInput.bind('mousedown', function() {
+                                               self.trigger('Browse');
+                                       });
+
+                                       fileInput.bind('error runtimeerror', function() {
+                                               fileInput = null;
+                                               cb();
+                                       });
+
+                                       fileInput.init();
+                               });
+                       });
+               }
+
+               // initialize drop zones
+               if (settings.drop_element) {
+                       plupload.each(settings.drop_element, function(el) {
+                               queue.push(function(cb) {
+                                       var fileDrop = new o.FileDrop(plupload.extend({}, options, {
+                                               drop_zone: el
+                                       }));
+
+                                       fileDrop.onready = function() {
+                                               var info = o.Runtime.getInfo(this.ruid);
+
+                                               // for backward compatibility
+                                               o.extend(self.features, {
+                                                       chunks: info.can('slice_blob'),
+                                                       multipart: info.can('send_multipart'),
+                                                       dragdrop: info.can('drag_and_drop')
+                                               });
+
+                                               inited++;
+                                               fileDrops.push(this);
+                                               cb();
+                                       };
+
+                                       fileDrop.ondrop = function() {
+                                               self.addFile(this.files);
+                                       };
+
+                                       fileDrop.bind('error runtimeerror', function() {
+                                               fileDrop = null;
+                                               cb();
+                                       });
+
+                                       fileDrop.init();
+                               });
+                       });
+               }
+
+
+               o.inSeries(queue, function() {
+                       if (typeof(cb) === 'function') {
+                               cb(inited);
+                       }
+               });
+       }
+
+
+       function resizeImage(blob, params, cb) {
+               var img = new o.Image();
+
+               try {
+                       img.onload = function() {
+                               // no manipulation required if...
+                               if (params.width > this.width &&
+                                       params.height > this.height &&
+                                       params.quality === undef &&
+                                       params.preserve_headers &&
+                                       !params.crop
+                               ) {
+                                       this.destroy();
+                                       return cb(blob);
+                               }
+                               // otherwise downsize
+                               img.downsize(params.width, params.height, params.crop, params.preserve_headers);
+                       };
+
+                       img.onresize = function() {
+                               cb(this.getAsBlob(blob.type, params.quality));
+                               this.destroy();
+                       };
+
+                       img.onerror = function() {
+                               cb(blob);
+                       };
+
+                       img.load(blob);
+               } catch(ex) {
+                       cb(blob);
+               }
+       }
+
+
+       function setOption(option, value, init) {
+               var self = this, reinitRequired = false;
+
+               function _setOption(option, value, init) {
+                       var oldValue = settings[option];
+
+                       switch (option) {
+                               case 'max_file_size':
+                                       if (option === 'max_file_size') {
+                                               settings.max_file_size = settings.filters.max_file_size = value;
+                                       }
+                                       break;
+
+                               case 'chunk_size':
+                                       if (value = plupload.parseSize(value)) {
+                                               settings[option] = value;
+                                               settings.send_file_name = true;
+                                       }
+                                       break;
+
+                               case 'multipart':
+                                       settings[option] = value;
+                                       if (!value) {
+                                               settings.send_file_name = true;
+                                       }
+                                       break;
+
+                               case 'unique_names':
+                                       settings[option] = value;
+                                       if (value) {
+                                               settings.send_file_name = true;
+                                       }
+                                       break;
+
+                               case 'filters':
+                                       // for sake of backward compatibility
+                                       if (plupload.typeOf(value) === 'array') {
+                                               value = {
+                                                       mime_types: value
+                                               };
+                                       }
+
+                                       if (init) {
+                                               plupload.extend(settings.filters, value);
+                                       } else {
+                                               settings.filters = value;
+                                       }
+
+                                       // if file format filters are being updated, regenerate the matching expressions
+                                       if (value.mime_types) {
+                                               settings.filters.mime_types.regexp = (function(filters) {
+                                                       var extensionsRegExp = [];
+
+                                                       plupload.each(filters, function(filter) {
+                                                               plupload.each(filter.extensions.split(/,/), function(ext) {
+                                                                       if (/^\s*\*\s*$/.test(ext)) {
+                                                                               extensionsRegExp.push('\\.*');
+                                                                       } else {
+                                                                               extensionsRegExp.push('\\.' + ext.replace(new RegExp('[' + ('/^$.*+?|()[]{}\\'.replace(/./g, '\\$&')) + ']', 'g'), '\\$&'));
+                                                                       }
+                                                               });
+                                                       });
+
+                                                       return new RegExp('(' + extensionsRegExp.join('|') + ')$', 'i');
+                                               }(settings.filters.mime_types));
+                                       }
+                                       break;
+       
+                               case 'resize':
+                                       if (init) {
+                                               plupload.extend(settings.resize, value, {
+                                                       enabled: true
+                                               });
+                                       } else {
+                                               settings.resize = value;
+                                       }
+                                       break;
+
+                               case 'prevent_duplicates':
+                                       settings.prevent_duplicates = settings.filters.prevent_duplicates = !!value;
+                                       break;
+
+                               // options that require reinitialisation
+                               case 'container':
+                               case 'browse_button':
+                               case 'drop_element':
+                                               value = 'container' === option
+                                                       ? plupload.get(value)
+                                                       : plupload.getAll(value)
+                                                       ; 
+                               
+                               case 'runtimes':
+                               case 'multi_selection':
+                                       settings[option] = value;
+                                       if (!init) {
+                                               reinitRequired = true;
+                                       }
+                                       break;
+
+                               default:
+                                       settings[option] = value;
+                       }
+
+                       if (!init) {
+                               self.trigger('OptionChanged', option, value, oldValue);
+                       }
+               }
+
+               if (typeof(option) === 'object') {
+                       plupload.each(option, function(value, option) {
+                               _setOption(option, value, init);
+                       });
+               } else {
+                       _setOption(option, value, init);
+               }
+
+               if (init) {
+                       // Normalize the list of required capabilities
+                       settings.required_features = normalizeCaps(plupload.extend({}, settings));
+
+                       // Come up with the list of capabilities that can affect default mode in a multi-mode runtimes
+                       preferred_caps = normalizeCaps(plupload.extend({}, settings, {
+                               required_features: true
+                       }));
+               } else if (reinitRequired) {
+                       self.trigger('Destroy');
+                       
+                       initControls.call(self, settings, function(inited) {
+                               if (inited) {
+                                       self.runtime = o.Runtime.getInfo(getRUID()).type;
+                                       self.trigger('Init', { runtime: self.runtime });
+                                       self.trigger('PostInit');
+                               } else {
+                                       self.trigger('Error', {
+                                               code : plupload.INIT_ERROR,
+                                               message : plupload.translate('Init error.')
+                                       });
+                               }
+                       });
+               }
+       }
+
+
+       // Internal event handlers
+       function onBeforeUpload(up, file) {
+               // Generate unique target filenames
+               if (up.settings.unique_names) {
+                       var matches = file.name.match(/\.([^.]+)$/), ext = "part";
+                       if (matches) {
+                               ext = matches[1];
+                       }
+                       file.target_name = file.id + '.' + ext;
+               }
+       }
+
+
+       function onUploadFile(up, file) {
+               var url = up.settings.url
+               , chunkSize = up.settings.chunk_size
+               , retries = up.settings.max_retries
+               , features = up.features
+               , offset = 0
+               , blob
+               ;
+
+               // make sure we start at a predictable offset
+               if (file.loaded) {
+                       offset = file.loaded = chunkSize ? chunkSize * Math.floor(file.loaded / chunkSize) : 0;
+               }
+
+               function handleError() {
+                       if (retries-- > 0) {
+                               delay(uploadNextChunk, 1000);
+                       } else {
+                               file.loaded = offset; // reset all progress
+
+                               up.trigger('Error', {
+                                       code : plupload.HTTP_ERROR,
+                                       message : plupload.translate('HTTP Error.'),
+                                       file : file,
+                                       response : xhr.responseText,
+                                       status : xhr.status,
+                                       responseHeaders: xhr.getAllResponseHeaders()
+                               });
+                       }
+               }
+
+               function uploadNextChunk() {
+                       var chunkBlob, formData, args = {}, curChunkSize;
+
+                       // make sure that file wasn't cancelled and upload is not stopped in general
+                       if (file.status !== plupload.UPLOADING || up.state === plupload.STOPPED) {
+                               return;
+                       }
+
+                       // send additional 'name' parameter only if required
+                       if (up.settings.send_file_name) {
+                               args.name = file.target_name || file.name;
+                       }
+
+                       if (chunkSize && features.chunks && blob.size > chunkSize) { // blob will be of type string if it was loaded in memory 
+                               curChunkSize = Math.min(chunkSize, blob.size - offset);
+                               chunkBlob = blob.slice(offset, offset + curChunkSize);
+                       } else {
+                               curChunkSize = blob.size;
+                               chunkBlob = blob;
+                       }
+
+                       // If chunking is enabled add corresponding args, no matter if file is bigger than chunk or smaller
+                       if (chunkSize && features.chunks) {
+                               // Setup query string arguments
+                               if (up.settings.send_chunk_number) {
+                                       args.chunk = Math.ceil(offset / chunkSize);
+                                       args.chunks = Math.ceil(blob.size / chunkSize);
+                               } else { // keep support for experimental chunk format, just in case
+                                       args.offset = offset;
+                                       args.total = blob.size;
+                               }
+                       }
+
+                       xhr = new o.XMLHttpRequest();
+
+                       // Do we have upload progress support
+                       if (xhr.upload) {
+                               xhr.upload.onprogress = function(e) {
+                                       file.loaded = Math.min(file.size, offset + e.loaded);
+                                       up.trigger('UploadProgress', file);
+                               };
+                       }
+
+                       xhr.onload = function() {
+                               // check if upload made itself through
+                               if (xhr.status >= 400) {
+                                       handleError();
+                                       return;
+                               }
+
+                               retries = up.settings.max_retries; // reset the counter
+
+                               // Handle chunk response
+                               if (curChunkSize < blob.size) {
+                                       chunkBlob.destroy();
+
+                                       offset += curChunkSize;
+                                       file.loaded = Math.min(offset, blob.size);
+
+                                       up.trigger('ChunkUploaded', file, {
+                                               offset : file.loaded,
+                                               total : blob.size,
+                                               response : xhr.responseText,
+                                               status : xhr.status,
+                                               responseHeaders: xhr.getAllResponseHeaders()
+                                       });
+
+                                       // stock Android browser doesn't fire upload progress events, but in chunking mode we can fake them
+                                       if (o.Env.browser === 'Android Browser') {
+                                               // doesn't harm in general, but is not required anywhere else
+                                               up.trigger('UploadProgress', file);
+                                       } 
+                               } else {
+                                       file.loaded = file.size;
+                               }
+
+                               chunkBlob = formData = null; // Free memory
+
+                               // Check if file is uploaded
+                               if (!offset || offset >= blob.size) {
+                                       // If file was modified, destory the copy
+                                       if (file.size != file.origSize) {
+                                               blob.destroy();
+                                               blob = null;
+                                       }
+
+                                       up.trigger('UploadProgress', file);
+
+                                       file.status = plupload.DONE;
+
+                                       up.trigger('FileUploaded', file, {
+                                               response : xhr.responseText,
+                                               status : xhr.status,
+                                               responseHeaders: xhr.getAllResponseHeaders()
+                                       });
+                               } else {
+                                       // Still chunks left
+                                       delay(uploadNextChunk, 1); // run detached, otherwise event handlers interfere
+                               }
+                       };
+
+                       xhr.onerror = function() {
+                               handleError();
+                       };
+
+                       xhr.onloadend = function() {
+                               this.destroy();
+                               xhr = null;
+                       };
+
+                       // Build multipart request
+                       if (up.settings.multipart && features.multipart) {
+                               xhr.open("post", url, true);
+
+                               // Set custom headers
+                               plupload.each(up.settings.headers, function(value, name) {
+                                       xhr.setRequestHeader(name, value);
+                               });
+
+                               formData = new o.FormData();
+
+                               // Add multipart params
+                               plupload.each(plupload.extend(args, up.settings.multipart_params), function(value, name) {
+                                       formData.append(name, value);
+                               });
+
+                               // Add file and send it
+                               formData.append(up.settings.file_data_name, chunkBlob);
+                               xhr.send(formData, {
+                                       runtime_order: up.settings.runtimes,
+                                       required_caps: up.settings.required_features,
+                                       preferred_caps: preferred_caps
+                               });
+                       } else {
+                               // if no multipart, send as binary stream
+                               url = plupload.buildUrl(up.settings.url, plupload.extend(args, up.settings.multipart_params));
+
+                               xhr.open("post", url, true);
+
+                               xhr.setRequestHeader('Content-Type', 'application/octet-stream'); // Binary stream header
+
+                               // Set custom headers
+                               plupload.each(up.settings.headers, function(value, name) {
+                                       xhr.setRequestHeader(name, value);
+                               });
+
+                               xhr.send(chunkBlob, {
+                                       runtime_order: up.settings.runtimes,
+                                       required_caps: up.settings.required_features,
+                                       preferred_caps: preferred_caps
+                               });
+                       }
+               }
+
+               blob = file.getSource();
+
+               // Start uploading chunks
+               if (up.settings.resize.enabled && runtimeCan(blob, 'send_binary_string') && !!~o.inArray(blob.type, ['image/jpeg', 'image/png'])) {
+                       // Resize if required
+                       resizeImage.call(this, blob, up.settings.resize, function(resizedBlob) {
+                               blob = resizedBlob;
+                               file.size = resizedBlob.size;
+                               uploadNextChunk();
+                       });
+               } else {
+                       uploadNextChunk();
+               }
+       }
+
+
+       function onUploadProgress(up, file) {
+               calcFile(file);
+       }
+
+
+       function onStateChanged(up) {
+               if (up.state == plupload.STARTED) {
+                       // Get start time to calculate bps
+                       startTime = (+new Date());
+               } else if (up.state == plupload.STOPPED) {
+                       // Reset currently uploading files
+                       for (var i = up.files.length - 1; i >= 0; i--) {
+                               if (up.files[i].status == plupload.UPLOADING) {
+                                       up.files[i].status = plupload.QUEUED;
+                                       calc();
+                               }
+                       }
+               }
+       }
+
+
+       function onCancelUpload() {
+               if (xhr) {
+                       xhr.abort();
+               }
+       }
+
+
+       function onFileUploaded(up) {
+               calc();
+
+               // Upload next file but detach it from the error event
+               // since other custom listeners might want to stop the queue
+               delay(function() {
+                       uploadNext.call(up);
+               }, 1);
+       }
+
+
+       function onError(up, err) {
+               if (err.code === plupload.INIT_ERROR) {
+                       up.destroy();
+               }
+               // Set failed status if an error occured on a file
+               else if (err.code === plupload.HTTP_ERROR) {
+                       err.file.status = plupload.FAILED;
+                       calcFile(err.file);
+
+                       // Upload next file but detach it from the error event
+                       // since other custom listeners might want to stop the queue
+                       if (up.state == plupload.STARTED) { // upload in progress
+                               up.trigger('CancelUpload');
+                               delay(function() {
+                                       uploadNext.call(up);
+                               }, 1);
+                       }
+               }
+       }
+
+
+       function onDestroy(up) {
+               up.stop();
+
+               // Purge the queue
+               plupload.each(files, function(file) {
+                       file.destroy();
+               });
+               files = [];
+
+               if (fileInputs.length) {
+                       plupload.each(fileInputs, function(fileInput) {
+                               fileInput.destroy();
+                       });
+                       fileInputs = [];
+               }
+
+               if (fileDrops.length) {
+                       plupload.each(fileDrops, function(fileDrop) {
+                               fileDrop.destroy();
+                       });
+                       fileDrops = [];
+               }
+
+               preferred_caps = {};
+               disabled = false;
+               startTime = xhr = null;
+               total.reset();
+       }
+
+
+       // Default settings
+       settings = {
+               runtimes: o.Runtime.order,
+               max_retries: 0,
+               chunk_size: 0,
+               multipart: true,
+               multi_selection: true,
+               file_data_name: 'file',
+               filters: {
+                       mime_types: [],
+                       prevent_duplicates: false,
+                       max_file_size: 0
+               },
+               resize: {
+                       enabled: false,
+                       preserve_headers: true,
+                       crop: false
+               },
+               send_file_name: true,
+               send_chunk_number: true
+       };
+
+       
+       setOption.call(this, options, null, true);
+
+       // Inital total state
+       total = new plupload.QueueProgress(); 
+
+       // Add public methods
+       plupload.extend(this, {
+
+               /**
+                * Unique id for the Uploader instance.
+                *
+                * @property id
+                * @type String
+                */
+               id : uid,
+               uid : uid, // mOxie uses this to differentiate between event targets
+
+               /**
+                * Current state of the total uploading progress. This one can either be plupload.STARTED or plupload.STOPPED.
+                * These states are controlled by the stop/start methods. The default value is STOPPED.
+                *
+                * @property state
+                * @type Number
+                */
+               state : plupload.STOPPED,
+
+               /**
+                * Map of features that are available for the uploader runtime. Features will be filled
+                * before the init event is called, these features can then be used to alter the UI for the end user.
+                * Some of the current features that might be in this map is: dragdrop, chunks, jpgresize, pngresize.
+                *
+                * @property features
+                * @type Object
+                */
+               features : {},
+
+               /**
+                * Current runtime name.
+                *
+                * @property runtime
+                * @type String
+                */
+               runtime : null,
+
+               /**
+                * Current upload queue, an array of File instances.
+                *
+                * @property files
+                * @type Array
+                * @see plupload.File
+                */
+               files : files,
+
+               /**
+                * Object with name/value settings.
+                *
+                * @property settings
+                * @type Object
+                */
+               settings : settings,
+
+               /**
+                * Total progess information. How many files has been uploaded, total percent etc.
+                *
+                * @property total
+                * @type plupload.QueueProgress
+                */
+               total : total,
+
+
+               /**
+                * Initializes the Uploader instance and adds internal event listeners.
+                *
+                * @method init
+                */
+               init : function() {
+                       var self = this, opt, preinitOpt, err;
+                       
+                       preinitOpt = self.getOption('preinit');
+                       if (typeof(preinitOpt) == "function") {
+                               preinitOpt(self);
+                       } else {
+                               plupload.each(preinitOpt, function(func, name) {
+                                       self.bind(name, func);
+                               });
+                       }
+
+                       bindEventListeners.call(self);
+
+                       // Check for required options
+                       plupload.each(['container', 'browse_button', 'drop_element'], function(el) {
+                               if (self.getOption(el) === null) {
+                                       err = {
+                                               code : plupload.INIT_ERROR,
+                                               message : plupload.translate("'%' specified, but cannot be found.")
+                                       }
+                                       return false;
+                               }
+                       });
+
+                       if (err) {
+                               return self.trigger('Error', err);
+                       }
+
+
+                       if (!settings.browse_button && !settings.drop_element) {
+                               return self.trigger('Error', {
+                                       code : plupload.INIT_ERROR,
+                                       message : plupload.translate("You must specify either 'browse_button' or 'drop_element'.")
+                               });
+                       }
+
+
+                       initControls.call(self, settings, function(inited) {
+                               var initOpt = self.getOption('init');
+                               if (typeof(initOpt) == "function") {
+                                       initOpt(self);
+                               } else {
+                                       plupload.each(initOpt, function(func, name) {
+                                               self.bind(name, func);
+                                       });
+                               }
+
+                               if (inited) {
+                                       self.runtime = o.Runtime.getInfo(getRUID()).type;
+                                       self.trigger('Init', { runtime: self.runtime });
+                                       self.trigger('PostInit');
+                               } else {
+                                       self.trigger('Error', {
+                                               code : plupload.INIT_ERROR,
+                                               message : plupload.translate('Init error.')
+                                       });
+                               }
+                       });
+               },
+
+               /**
+                * Set the value for the specified option(s).
+                *
+                * @method setOption
+                * @since 2.1
+                * @param {String|Object} option Name of the option to change or the set of key/value pairs
+                * @param {Mixed} [value] Value for the option (is ignored, if first argument is object)
+                */
+               setOption: function(option, value) {
+                       setOption.call(this, option, value, !this.runtime); // until runtime not set we do not need to reinitialize
+               },
+
+               /**
+                * Get the value for the specified option or the whole configuration, if not specified.
+                * 
+                * @method getOption
+                * @since 2.1
+                * @param {String} [option] Name of the option to get
+                * @return {Mixed} Value for the option or the whole set
+                */
+               getOption: function(option) {
+                       if (!option) {
+                               return settings;
+                       }
+                       return settings[option];
+               },
+
+               /**
+                * Refreshes the upload instance by dispatching out a refresh event to all runtimes.
+                * This would for example reposition flash/silverlight shims on the page.
+                *
+                * @method refresh
+                */
+               refresh : function() {
+                       if (fileInputs.length) {
+                               plupload.each(fileInputs, function(fileInput) {
+                                       fileInput.trigger('Refresh');
+                               });
+                       }
+                       this.trigger('Refresh');
+               },
+
+               /**
+                * Starts uploading the queued files.
+                *
+                * @method start
+                */
+               start : function() {
+                       if (this.state != plupload.STARTED) {
+                               this.state = plupload.STARTED;
+                               this.trigger('StateChanged');
+
+                               uploadNext.call(this);
+                       }
+               },
+
+               /**
+                * Stops the upload of the queued files.
+                *
+                * @method stop
+                */
+               stop : function() {
+                       if (this.state != plupload.STOPPED) {
+                               this.state = plupload.STOPPED;
+                               this.trigger('StateChanged');
+                               this.trigger('CancelUpload');
+                       }
+               },
+
+
+               /**
+                * Disables/enables browse button on request.
+                *
+                * @method disableBrowse
+                * @param {Boolean} disable Whether to disable or enable (default: true)
+                */
+               disableBrowse : function() {
+                       disabled = arguments[0] !== undef ? arguments[0] : true;
+
+                       if (fileInputs.length) {
+                               plupload.each(fileInputs, function(fileInput) {
+                                       fileInput.disable(disabled);
+                               });
+                       }
+
+                       this.trigger('DisableBrowse', disabled);
+               },
+
+               /**
+                * Returns the specified file object by id.
+                *
+                * @method getFile
+                * @param {String} id File id to look for.
+                * @return {plupload.File} File object or undefined if it wasn't found;
+                */
+               getFile : function(id) {
+                       var i;
+                       for (i = files.length - 1; i >= 0; i--) {
+                               if (files[i].id === id) {
+                                       return files[i];
+                               }
+                       }
+               },
+
+               /**
+                * Adds file to the queue programmatically. Can be native file, instance of Plupload.File,
+                * instance of mOxie.File, input[type="file"] element, or array of these. Fires FilesAdded, 
+                * if any files were added to the queue. Otherwise nothing happens.
+                *
+                * @method addFile
+                * @since 2.0
+                * @param {plupload.File|mOxie.File|File|Node|Array} file File or files to add to the queue.
+                * @param {String} [fileName] If specified, will be used as a name for the file
+                */
+               addFile : function(file, fileName) {
+                       var self = this
+                       , queue = [] 
+                       , filesAdded = []
+                       , ruid
+                       ;
+
+                       function filterFile(file, cb) {
+                               var queue = [];
+                               o.each(self.settings.filters, function(rule, name) {
+                                       if (fileFilters[name]) {
+                                               queue.push(function(cb) {
+                                                       fileFilters[name].call(self, rule, file, function(res) {
+                                                               cb(!res);
+                                                       });
+                                               });
+                                       }
+                               });
+                               o.inSeries(queue, cb);
+                       }
+
+                       /**
+                        * @method resolveFile
+                        * @private
+                        * @param {o.File|o.Blob|plupload.File|File|Blob|input[type="file"]} file
+                        */
+                       function resolveFile(file) {
+                               var type = o.typeOf(file);
+
+                               // o.File
+                               if (file instanceof o.File) { 
+                                       if (!file.ruid && !file.isDetached()) {
+                                               if (!ruid) { // weird case
+                                                       return false;
+                                               }
+                                               file.ruid = ruid;
+                                               file.connectRuntime(ruid);
+                                       }
+                                       resolveFile(new plupload.File(file));
+                               }
+                               // o.Blob 
+                               else if (file instanceof o.Blob) {
+                                       resolveFile(file.getSource());
+                                       file.destroy();
+                               } 
+                               // plupload.File - final step for other branches
+                               else if (file instanceof plupload.File) {
+                                       if (fileName) {
+                                               file.name = fileName;
+                                       }
+                                       
+                                       queue.push(function(cb) {
+                                               // run through the internal and user-defined filters, if any
+                                               filterFile(file, function(err) {
+                                                       if (!err) {
+                                                               // make files available for the filters by updating the main queue directly
+                                                               files.push(file);
+                                                               // collect the files that will be passed to FilesAdded event
+                                                               filesAdded.push(file); 
+
+                                                               self.trigger("FileFiltered", file);
+                                                       }
+                                                       delay(cb, 1); // do not build up recursions or eventually we might hit the limits
+                                               });
+                                       });
+                               } 
+                               // native File or blob
+                               else if (o.inArray(type, ['file', 'blob']) !== -1) {
+                                       resolveFile(new o.File(null, file));
+                               } 
+                               // input[type="file"]
+                               else if (type === 'node' && o.typeOf(file.files) === 'filelist') {
+                                       // if we are dealing with input[type="file"]
+                                       o.each(file.files, resolveFile);
+                               } 
+                               // mixed array of any supported types (see above)
+                               else if (type === 'array') {
+                                       fileName = null; // should never happen, but unset anyway to avoid funny situations
+                                       o.each(file, resolveFile);
+                               }
+                       }
+
+                       ruid = getRUID();
+                       
+                       resolveFile(file);
+
+                       if (queue.length) {
+                               o.inSeries(queue, function() {
+                                       // if any files left after filtration, trigger FilesAdded
+                                       if (filesAdded.length) {
+                                               self.trigger("FilesAdded", filesAdded);
+                                       }
+                               });
+                       }
+               },
+
+               /**
+                * Removes a specific file.
+                *
+                * @method removeFile
+                * @param {plupload.File|String} file File to remove from queue.
+                */
+               removeFile : function(file) {
+                       var id = typeof(file) === 'string' ? file : file.id;
+
+                       for (var i = files.length - 1; i >= 0; i--) {
+                               if (files[i].id === id) {
+                                       return this.splice(i, 1)[0];
+                               }
+                       }
+               },
+
+               /**
+                * Removes part of the queue and returns the files removed. This will also trigger the FilesRemoved and QueueChanged events.
+                *
+                * @method splice
+                * @param {Number} start (Optional) Start index to remove from.
+                * @param {Number} length (Optional) Lengh of items to remove.
+                * @return {Array} Array of files that was removed.
+                */
+               splice : function(start, length) {
+                       // Splice and trigger events
+                       var removed = files.splice(start === undef ? 0 : start, length === undef ? files.length : length);
+
+                       // if upload is in progress we need to stop it and restart after files are removed
+                       var restartRequired = false;
+                       if (this.state == plupload.STARTED) { // upload in progress
+                               plupload.each(removed, function(file) {
+                                       if (file.status === plupload.UPLOADING) {
+                                               restartRequired = true; // do not restart, unless file that is being removed is uploading
+                                               return false;
+                                       }
+                               });
+                               
+                               if (restartRequired) {
+                                       this.stop();
+                               }
+                       }
+
+                       this.trigger("FilesRemoved", removed);
+
+                       // Dispose any resources allocated by those files
+                       plupload.each(removed, function(file) {
+                               file.destroy();
+                       });
+                       
+                       if (restartRequired) {
+                               this.start();
+                       }
+
+                       return removed;
+               },
+
+               /**
+               Dispatches the specified event name and its arguments to all listeners.
+
+               @method trigger
+               @param {String} name Event name to fire.
+               @param {Object..} Multiple arguments to pass along to the listener functions.
+               */
+
+               // override the parent method to match Plupload-like event logic
+               dispatchEvent: function(type) {
+                       var list, args, result;
+                                               
+                       type = type.toLowerCase();
+                                                       
+                       list = this.hasEventListener(type);
+
+                       if (list) {
+                               // sort event list by priority
+                               list.sort(function(a, b) { return b.priority - a.priority; });
+                               
+                               // first argument should be current plupload.Uploader instance
+                               args = [].slice.call(arguments);
+                               args.shift();
+                               args.unshift(this);
+
+                               for (var i = 0; i < list.length; i++) {
+                                       // Fire event, break chain if false is returned
+                                       if (list[i].fn.apply(list[i].scope, args) === false) {
+                                               return false;
+                                       }
+                               }
+                       }
+                       return true;
+               },
+
+               /**
+               Check whether uploader has any listeners to the specified event.
+
+               @method hasEventListener
+               @param {String} name Event name to check for.
+               */
+
+
+               /**
+               Adds an event listener by name.
+
+               @method bind
+               @param {String} name Event name to listen for.
+               @param {function} fn Function to call ones the event gets fired.
+               @param {Object} [scope] Optional scope to execute the specified function in.
+               @param {Number} [priority=0] Priority of the event handler - handlers with higher priorities will be called first
+               */
+               bind: function(name, fn, scope, priority) {
+                       // adapt moxie EventTarget style to Plupload-like
+                       plupload.Uploader.prototype.bind.call(this, name, fn, priority, scope);
+               },
+
+               /**
+               Removes the specified event listener.
+
+               @method unbind
+               @param {String} name Name of event to remove.
+               @param {function} fn Function to remove from listener.
+               */
+
+               /**
+               Removes all event listeners.
+
+               @method unbindAll
+               */
+
+
+               /**
+                * Destroys Plupload instance and cleans after itself.
+                *
+                * @method destroy
+                */
+               destroy : function() {
+                       this.trigger('Destroy');
+                       settings = total = null; // purge these exclusively
+                       this.unbindAll();
+               }
+       });
+};
+
+plupload.Uploader.prototype = o.EventTarget.instance;
+
+/**
+ * Constructs a new file instance.
+ *
+ * @class File
+ * @constructor
+ * 
+ * @param {Object} file Object containing file properties
+ * @param {String} file.name Name of the file.
+ * @param {Number} file.size File size.
+ */
+plupload.File = (function() {
+       var filepool = {};
+
+       function PluploadFile(file) {
+
+               plupload.extend(this, {
+
+                       /**
+                        * File id this is a globally unique id for the specific file.
+                        *
+                        * @property id
+                        * @type String
+                        */
+                       id: plupload.guid(),
+
+                       /**
+                        * File name for example "myfile.gif".
+                        *
+                        * @property name
+                        * @type String
+                        */
+                       name: file.name || file.fileName,
+
+                       /**
+                        * File type, `e.g image/jpeg`
+                        *
+                        * @property type
+                        * @type String
+                        */
+                       type: file.type || '',
+
+                       /**
+                        * File size in bytes (may change after client-side manupilation).
+                        *
+                        * @property size
+                        * @type Number
+                        */
+                       size: file.size || file.fileSize,
+
+                       /**
+                        * Original file size in bytes.
+                        *
+                        * @property origSize
+                        * @type Number
+                        */
+                       origSize: file.size || file.fileSize,
+
+                       /**
+                        * Number of bytes uploaded of the files total size.
+                        *
+                        * @property loaded
+                        * @type Number
+                        */
+                       loaded: 0,
+
+                       /**
+                        * Number of percentage uploaded of the file.
+                        *
+                        * @property percent
+                        * @type Number
+                        */
+                       percent: 0,
+
+                       /**
+                        * Status constant matching the plupload states QUEUED, UPLOADING, FAILED, DONE.
+                        *
+                        * @property status
+                        * @type Number
+                        * @see plupload
+                        */
+                       status: plupload.QUEUED,
+
+                       /**
+                        * Date of last modification.
+                        *
+                        * @property lastModifiedDate
+                        * @type {String}
+                        */
+                       lastModifiedDate: file.lastModifiedDate || (new Date()).toLocaleString(), // Thu Aug 23 2012 19:40:00 GMT+0400 (GET)
+
+                       /**
+                        * Returns native window.File object, when it's available.
+                        *
+                        * @method getNative
+                        * @return {window.File} or null, if plupload.File is of different origin
+                        */
+                       getNative: function() {
+                               var file = this.getSource().getSource();
+                               return o.inArray(o.typeOf(file), ['blob', 'file']) !== -1 ? file : null;
+                       },
+
+                       /**
+                        * Returns mOxie.File - unified wrapper object that can be used across runtimes.
+                        *
+                        * @method getSource
+                        * @return {mOxie.File} or null
+                        */
+                       getSource: function() {
+                               if (!filepool[this.id]) {
+                                       return null;
+                               }
+                               return filepool[this.id];
+                       },
+
+                       /**
+                        * Destroys plupload.File object.
+                        *
+                        * @method destroy
+                        */
+                       destroy: function() {
+                               var src = this.getSource();
+                               if (src) {
+                                       src.destroy();
+                                       delete filepool[this.id];
+                               }
+                       }
+               });
+
+               filepool[this.id] = file;
+       }
+
+       return PluploadFile;
+}());
+
+
+/**
+ * Constructs a queue progress.
+ *
+ * @class QueueProgress
+ * @constructor
+ */
+ plupload.QueueProgress = function() {
+       var self = this; // Setup alias for self to reduce code size when it's compressed
+
+       /**
+        * Total queue file size.
+        *
+        * @property size
+        * @type Number
+        */
+       self.size = 0;
+
+       /**
+        * Total bytes uploaded.
+        *
+        * @property loaded
+        * @type Number
+        */
+       self.loaded = 0;
+
+       /**
+        * Number of files uploaded.
+        *
+        * @property uploaded
+        * @type Number
+        */
+       self.uploaded = 0;
+
+       /**
+        * Number of files failed to upload.
+        *
+        * @property failed
+        * @type Number
+        */
+       self.failed = 0;
+
+       /**
+        * Number of files yet to be uploaded.
+        *
+        * @property queued
+        * @type Number
+        */
+       self.queued = 0;
+
+       /**
+        * Total percent of the uploaded bytes.
+        *
+        * @property percent
+        * @type Number
+        */
+       self.percent = 0;
+
+       /**
+        * Bytes uploaded per second.
+        *
+        * @property bytesPerSec
+        * @type Number
+        */
+       self.bytesPerSec = 0;
+
+       /**
+        * Resets the progress to its initial values.
+        *
+        * @method reset
+        */
+       self.reset = function() {
+               self.size = self.loaded = self.uploaded = self.failed = self.queued = self.percent = self.bytesPerSec = 0;
+       };
+};
+
+window.plupload = plupload;
+
+}(window, mOxie));
</ins></span></pre></div>
<a id="trunksrcwpincludesjspluploadpluploadsilverlightxap"></a>
<div class="binary"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Deleted: trunk/src/wp-includes/js/plupload/plupload.silverlight.xap</h4>
<pre class="diff"><span>
<span class="cx">(Binary files differ)
</span></span></pre></div>
<a id="trunksrcwpincludesmediaphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/media.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/media.php   2017-09-01 08:49:50 UTC (rev 41327)
+++ trunk/src/wp-includes/media.php     2017-09-01 12:27:49 UTC (rev 41328)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3002,12 +3002,13 @@
</span><span class="cx" style="display: block; padding: 0 10px">                $extensions = array_merge( $extensions, explode( '|', $extension ) );
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /*
+        * Since 4.9 the `runtimes` setting is hardcoded in our version of Plupload to `html5,html4`,
+        * and the `flash_swf_url` and `silverlight_xap_url` are not used.
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         $defaults = array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                'runtimes'            => 'html5,flash,silverlight,html4',
</del><span class="cx" style="display: block; padding: 0 10px">                 'file_data_name'      => 'async-upload', // key passed to $_FILE.
</span><span class="cx" style="display: block; padding: 0 10px">                'url'                 => admin_url( 'async-upload.php', 'relative' ),
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                'flash_swf_url'       => includes_url( 'js/plupload/plupload.flash.swf' ),
-               'silverlight_xap_url' => includes_url( 'js/plupload/plupload.silverlight.xap' ),
</del><span class="cx" style="display: block; padding: 0 10px">                 'filters' => array(
</span><span class="cx" style="display: block; padding: 0 10px">                        'max_file_size'   => $max_upload_size . 'b',
</span><span class="cx" style="display: block; padding: 0 10px">                        'mime_types'      => array( array( 'extensions' => implode( ',', $extensions ) ) ),
</span></span></pre>
</div>
</div>

</body>
</html>