ahw3oS7AwaboMMPOhyRp/7SNVe
l+axofjk70YllJyJ22k4vuxcDlbHZVHlUIiIv0LVKz3l+bqeLrPK9HOSAgu+TGbrIP65y7WZf+a2
E/rKS03Z7lNGBjvGTq2TWoF+bCpLagVFjPIhpDGQh2xlnJ2lYJU6Un/10asIbvPuW/mIPX64b24D
5EI=
-----END CERTIFICATE-----
Hellenic Academic and Research Institutions RootCA 2011
=======================================================
-----BEGIN CERTIFICATE-----
MIIEMTCCAxmgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBlTELMAkGA1UEBhMCR1IxRDBCBgNVBAoT
O0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9y
aXR5MUAwPgYDVQQDEzdIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z
IFJvb3RDQSAyMDExMB4XDTExMTIwNjEzNDk1MloXDTMxMTIwMTEzNDk1MlowgZUxCzAJBgNVBAYT
AkdSMUQwQgYDVQQKEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z
IENlcnQuIEF1dGhvcml0eTFAMD4GA1UEAxM3SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNo
IEluc3RpdHV0aW9ucyBSb290Q0EgMjAxMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
AKlTAOMupvaO+mDYLZU++CwqVE7NuYRhlFhPjz2L5EPzdYmNUeTDN9KKiE15HrcS3UN4SoqS5tdI
1Q+kOilENbgH9mgdVc04UfCMJDGFr4PJfel3r+0ae50X+bOdOFAPplp5kYCvN66m0zH7tSYJnTxa
71HFK9+WXesyHgLacEnsbgzImjeN9/E2YEsmLIKe0HjzDQ9jpFEw4fkrJxIH2Oq9GGKYsFk3fb7u
8yBRQlqD75O6aRXxYp2fmTmCobd0LovUxQt7L/DICto9eQqakxylKHJzkUOap9FNhYS5qXSPFEDH
3N6sQWRstBmbAmNtJGSPRLIl6s5ddAxjMlyNh+UCAwEAAaOBiTCBhjAPBgNVHRMBAf8EBTADAQH/
MAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQUppFC/RNhSiOeCKQp5dgTBCPuQSUwRwYDVR0eBEAwPqA8
MAWCAy5ncjAFggMuZXUwBoIELmVkdTAGggQub3JnMAWBAy5ncjAFgQMuZXUwBoEELmVkdTAGgQQu
b3JnMA0GCSqGSIb3DQEBBQUAA4IBAQAf73lB4XtuP7KMhjdCSk4cNx6NZrokgclPEg8hwAOXhiVt
XdMiKahsog2p6z0GW5k6x8zDmjR/qw7IThzh+uTczQ2+vyT+bOdrwg3IBp5OjWEopmr95fZi6hg8
TqBTnbI6nOulnJEWtk2C4AwFSKls9cz4y51JtPACpf1wA+2KIaWuE4ZJwzNzvoc7dIsXRSZMFpGD
/md9zU1jZ/rzAxKWeAaNsWftjj++n08C9bMJL/NMh98qy5V8AcysNnq/onN694/BtZqhFLKPM58N
7yLcZnuEvUUXBj08yrl3NI/K6s8/MT7jiOOASSXIl7WdmplNsDz4SgCbZN2fOUvRJ9e4
-----END CERTIFICATE-----
Actalis Authentication Root CA
==============================
-----BEGIN CERTIFICATE-----
MIIFuzCCA6OgAwIBAgIIVwoRl0LE48wwDQYJKoZIhvcNAQELBQAwazELMAkGA1UEBhMCSVQxDjAM
BgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UE
AwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290IENBMB4XDTExMDkyMjExMjIwMloXDTMwMDky
MjExMjIwMlowazELMAkGA1UEBhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlz
IFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290
IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAp8bEpSmkLO/lGMWwUKNvUTufClrJ
wkg4CsIcoBh/kbWHuUA/3R1oHwiD1S0eiKD4j1aPbZkCkpAW1V8IbInX4ay8IMKx4INRimlNAJZa
by/ARH6jDuSRzVju3PvHHkVH3Se5CAGfpiEd9UEtL0z9KK3giq0itFZljoZUj5NDKd45RnijMCO6
zfB9E1fAXdKDa0hMxKufgFpbOr3JpyIe 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.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 || 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