WordPress.org

Make WordPress Core

Ticket #22974: plupload.safari.patch

File plupload.safari.patch, 76.0 KB (added by mario-siteground, 5 years ago)

standalone bug

  • wp-includes/js/plupload/plupload.html5.dev.js

     
     1/**
     2 * plupload.html5.js
     3 *
     4 * Copyright 2009, Moxiecode Systems AB
     5 * Released under GPL License.
     6 *
     7 * License: http://www.plupload.com/license
     8 * Contributing: http://www.plupload.com/contributing
     9 */
     10
     11// JSLint defined globals
     12/*global plupload:false, File:false, window:false, atob:false, FormData:false, FileReader:false, ArrayBuffer:false, Uint8Array:false, BlobBuilder:false, unescape:false */
     13
     14(function(window, document, plupload, undef) {
     15        var html5files = {}, // queue of original File objects
     16                fakeSafariDragDrop;
     17
     18        function readFileAsDataURL(file, callback) {
     19                var reader;
     20
     21                // Use FileReader if it's available
     22                if ("FileReader" in window) {
     23                        reader = new FileReader();
     24                        reader.readAsDataURL(file);
     25                        reader.onload = function() {
     26                                callback(reader.result);
     27                        };
     28                } else {
     29                        return callback(file.getAsDataURL());
     30                }
     31        }
     32
     33        function readFileAsBinary(file, callback) {
     34                var reader;
     35
     36                // Use FileReader if it's available
     37                if ("FileReader" in window) {
     38                        reader = new FileReader();
     39                        reader.readAsBinaryString(file);
     40                        reader.onload = function() {
     41                                callback(reader.result);
     42                        };
     43                } else {
     44                        return callback(file.getAsBinary());
     45                }
     46        }
     47
     48        function scaleImage(file, resize, mime, callback) {
     49                var canvas, context, img, scale,
     50                        up = this;
     51                       
     52                readFileAsDataURL(html5files[file.id], function(data) {
     53                        // Setup canvas and context
     54                        canvas = document.createElement("canvas");
     55                        canvas.style.display = 'none';
     56                        document.body.appendChild(canvas);
     57                        context = canvas.getContext('2d');
     58
     59                        // Load image
     60                        img = new Image();
     61                        img.onerror = img.onabort = function() {
     62                                // Failed to load, the image may be invalid
     63                                callback({success : false});
     64                        };
     65                        img.onload = function() {
     66                                var width, height, percentage, jpegHeaders, exifParser;
     67                               
     68                                if (!resize['width']) {
     69                                        resize['width'] = img.width;
     70                                }
     71                               
     72                                if (!resize['height']) {
     73                                        resize['height'] = img.height; 
     74                                }
     75                               
     76                                scale = Math.min(resize.width / img.width, resize.height / img.height);
     77
     78                                if (scale < 1 || (scale === 1 && mime === 'image/jpeg')) {
     79                                        width = Math.round(img.width * scale);
     80                                        height = Math.round(img.height * scale);
     81
     82                                        // Scale image and canvas
     83                                        canvas.width = width;
     84                                        canvas.height = height;
     85                                        context.drawImage(img, 0, 0, width, height);
     86                                       
     87                                        // Preserve JPEG headers
     88                                        if (mime === 'image/jpeg') {
     89                                                jpegHeaders = new JPEG_Headers(atob(data.substring(data.indexOf('base64,') + 7)));
     90                                                if (jpegHeaders['headers'] && jpegHeaders['headers'].length) {
     91                                                        exifParser = new ExifParser();                 
     92                                                                                       
     93                                                        if (exifParser.init(jpegHeaders.get('exif')[0])) {
     94                                                                // Set new width and height
     95                                                                exifParser.setExif('PixelXDimension', width);
     96                                                                exifParser.setExif('PixelYDimension', height);
     97                                                                                                                                                                                       
     98                                                                // Update EXIF header
     99                                                                jpegHeaders.set('exif', exifParser.getBinary());
     100                                                               
     101                                                                // trigger Exif events only if someone listens to them
     102                                                                if (up.hasEventListener('ExifData')) {
     103                                                                        up.trigger('ExifData', file, exifParser.EXIF());
     104                                                                }
     105                                                               
     106                                                                if (up.hasEventListener('GpsData')) {
     107                                                                        up.trigger('GpsData', file, exifParser.GPS());
     108                                                                }
     109                                                        }
     110                                                }
     111                                               
     112                                                if (resize['quality']) {                                                       
     113                                                        // Try quality property first
     114                                                        try {
     115                                                                data = canvas.toDataURL(mime, resize['quality'] / 100);
     116                                                        } catch (e) {
     117                                                                data = canvas.toDataURL(mime); 
     118                                                        }
     119                                                }
     120                                        } else {
     121                                                data = canvas.toDataURL(mime);
     122                                        }
     123
     124                                        // Remove data prefix information and grab the base64 encoded data and decode it
     125                                        data = data.substring(data.indexOf('base64,') + 7);
     126                                        data = atob(data);
     127
     128                                        // Restore JPEG headers if applicable
     129                                        if (jpegHeaders && jpegHeaders['headers'] && jpegHeaders['headers'].length) {
     130                                                data = jpegHeaders.restore(data);
     131                                                jpegHeaders.purge(); // free memory
     132                                        }
     133
     134                                        // Remove canvas and execute callback with decoded image data
     135                                        canvas.parentNode.removeChild(canvas);
     136                                        callback({success : true, data : data});
     137                                } else {
     138                                        // Image does not need to be resized
     139                                        callback({success : false});
     140                                }
     141                        };
     142
     143                        img.src = data;
     144                });
     145        }
     146
     147        /**
     148         * HMTL5 implementation. This runtime supports these features: dragdrop, jpgresize, pngresize.
     149         *
     150         * @static
     151         * @class plupload.runtimes.Html5
     152         * @extends plupload.Runtime
     153         */
     154        plupload.runtimes.Html5 = plupload.addRuntime("html5", {
     155                /**
     156                 * Returns a list of supported features for the runtime.
     157                 *
     158                 * @return {Object} Name/value object with supported features.
     159                 */
     160                getFeatures : function() {
     161                        var xhr, hasXhrSupport, hasProgress, canSendBinary, dataAccessSupport, sliceSupport;
     162
     163                        hasXhrSupport = hasProgress = dataAccessSupport = sliceSupport = false;
     164                       
     165                        if (window.XMLHttpRequest) {
     166                                xhr = new XMLHttpRequest();
     167                                hasProgress = !!xhr.upload;
     168                                hasXhrSupport = !!(xhr.sendAsBinary || xhr.upload);
     169                        }
     170
     171                        // Check for support for various features
     172                        if (hasXhrSupport) {
     173                                canSendBinary = !!(xhr.sendAsBinary || (window.Uint8Array && window.ArrayBuffer));
     174                               
     175                                // Set dataAccessSupport only for Gecko since BlobBuilder and XHR doesn't handle binary data correctly                         
     176                                dataAccessSupport = !!(File && (File.prototype.getAsDataURL || window.FileReader) && canSendBinary);
     177                                sliceSupport = !!(File && (File.prototype.mozSlice || File.prototype.webkitSlice || File.prototype.slice));
     178                        }
     179                       
     180                        // Getting safari version in order to fix fakeSarafiDrop - for 5.1.2 and 4.* or lower.
     181                        var version = navigator.userAgent.match(/Version\/(\d+(?:\.\d+)*)/);
     182                        version = version.length > 1 ? version[1] : version.substr(version.indexof('/') + 1);
     183                       
     184                        // sniff out Safari for Windows and fake drag/drop
     185                        fakeSafariDragDrop = plupload.ua.safari && plupload.ua.windows && ('5.1.2' == version || (/^[0-4](?:\.\d+)*/).test(version));
     186
     187                        return {
     188                                html5: hasXhrSupport, // This is a special one that we check inside the init call
     189                                dragdrop: (function() {
     190                                        // this comes directly from Modernizr: http://www.modernizr.com/
     191                                        var div = document.createElement('div');
     192                                        return ('draggable' in div) || ('ondragstart' in div && 'ondrop' in div);
     193                                }()),
     194                                jpgresize: dataAccessSupport,
     195                                pngresize: dataAccessSupport,
     196                                multipart: dataAccessSupport || !!window.FileReader || !!window.FormData,
     197                                canSendBinary: canSendBinary,
     198                                // gecko 2/5/6 can't send blob with FormData: https://bugzilla.mozilla.org/show_bug.cgi?id=649150
     199                                cantSendBlobInFormData: !!(plupload.ua.gecko && window.FormData && window.FileReader && !FileReader.prototype.readAsArrayBuffer),
     200                                progress: hasProgress,
     201                                chunks: sliceSupport,
     202                                // Safari on Windows has problems when selecting multiple files
     203                                multi_selection: !(plupload.ua.safari && plupload.ua.windows),
     204                                // WebKit and Gecko 2+ can trigger file dialog progrmmatically
     205                                triggerDialog: (plupload.ua.gecko && window.FormData || plupload.ua.webkit)
     206                        };
     207                },
     208
     209                /**
     210                 * Initializes the upload runtime.
     211                 *
     212                 * @method init
     213                 * @param {plupload.Uploader} uploader Uploader instance that needs to be initialized.
     214                 * @param {function} callback Callback to execute when the runtime initializes or fails to initialize. If it succeeds an object with a parameter name success will be set to true.
     215                 */
     216                init : function(uploader, callback) {
     217                        var features, xhr;
     218
     219                        function addSelectedFiles(native_files) {
     220                                var file, i, files = [], id, fileNames = {};
     221
     222                                // Add the selected files to the file queue
     223                                for (i = 0; i < native_files.length; i++) {
     224                                        file = native_files[i];
     225                                                                               
     226                                        // Safari on Windows will add first file from dragged set multiple times
     227                                        // @see: https://bugs.webkit.org/show_bug.cgi?id=37957
     228                                        if (fileNames[file.name]) {
     229                                                continue;
     230                                        }
     231                                        fileNames[file.name] = true;
     232
     233                                        // Store away gears blob internally
     234                                        id = plupload.guid();
     235                                        html5files[id] = file;
     236
     237                                        // Expose id, name and size
     238                                        files.push(new plupload.File(id, file.fileName || file.name, file.fileSize || file.size)); // fileName / fileSize depricated
     239                                }
     240
     241                                // Trigger FilesAdded event if we added any
     242                                if (files.length) {
     243                                        uploader.trigger("FilesAdded", files);
     244                                }
     245                        }
     246
     247                        // No HTML5 upload support
     248                        features = this.getFeatures();
     249                        if (!features.html5) {
     250                                callback({success : false});
     251                                return;
     252                        }
     253
     254                        uploader.bind("Init", function(up) {
     255                                var inputContainer, browseButton, mimes = [], i, y, filters = up.settings.filters, ext, type, container = document.body, inputFile;
     256
     257                                // Create input container and insert it at an absolute position within the browse button
     258                                inputContainer = document.createElement('div');
     259                                inputContainer.id = up.id + '_html5_container';
     260
     261                                plupload.extend(inputContainer.style, {
     262                                        position : 'absolute',
     263                                        background : uploader.settings.shim_bgcolor || 'transparent',
     264                                        width : '100px',
     265                                        height : '100px',
     266                                        overflow : 'hidden',
     267                                        zIndex : 99999,
     268                                        opacity : uploader.settings.shim_bgcolor ? '' : 0 // Force transparent if bgcolor is undefined
     269                                });
     270                                inputContainer.className = 'plupload html5';
     271
     272                                if (uploader.settings.container) {
     273                                        container = document.getElementById(uploader.settings.container);
     274                                        if (plupload.getStyle(container, 'position') === 'static') {
     275                                                container.style.position = 'relative';
     276                                        }
     277                                }
     278
     279                                container.appendChild(inputContainer);
     280                               
     281                                // Convert extensions to mime types list
     282                                no_type_restriction:
     283                                for (i = 0; i < filters.length; i++) {
     284                                        ext = filters[i].extensions.split(/,/);
     285
     286                                        for (y = 0; y < ext.length; y++) {
     287                                               
     288                                                // If there's an asterisk in the list, then accept attribute is not required
     289                                                if (ext[y] === '*') {
     290                                                        mimes = [];
     291                                                        break no_type_restriction;
     292                                                }
     293                                               
     294                                                type = plupload.mimeTypes[ext[y]];
     295
     296                                                if (type && plupload.inArray(type, mimes) === -1) {
     297                                                        mimes.push(type);
     298                                                }
     299                                        }
     300                                }
     301
     302
     303                                // Insert the input inside the input container
     304                                inputContainer.innerHTML = '<input id="' + uploader.id + '_html5" ' + ' style="font-size:999px"' +
     305                                                                                        ' type="file" accept="' + mimes.join(',') + '" ' +
     306                                                                                        (uploader.settings.multi_selection && uploader.features.multi_selection ? 'multiple="multiple"' : '') + ' />';
     307
     308                                inputContainer.scrollTop = 100;
     309                                inputFile = document.getElementById(uploader.id + '_html5');
     310                               
     311                                if (up.features.triggerDialog) {
     312                                        plupload.extend(inputFile.style, {
     313                                                position: 'absolute',
     314                                                width: '100%',
     315                                                height: '100%'
     316                                        });
     317                                } else {
     318                                        // shows arrow cursor instead of the text one, bit more logical
     319                                        plupload.extend(inputFile.style, {
     320                                                cssFloat: 'right',
     321                                                styleFloat: 'right'
     322                                        });
     323                                }
     324                               
     325                                inputFile.onchange = function() {
     326                                        // Add the selected files from file input
     327                                        addSelectedFiles(this.files);
     328                                       
     329                                        // Clearing the value enables the user to select the same file again if they want to
     330                                        this.value = '';
     331                                };
     332                               
     333                                /* Since we have to place input[type=file] on top of the browse_button for some browsers (FF, Opera),
     334                                browse_button loses interactivity, here we try to neutralize this issue highlighting browse_button
     335                                with a special classes
     336                                TODO: needs to be revised as things will change */
     337                                browseButton = document.getElementById(up.settings.browse_button);
     338                                if (browseButton) {                             
     339                                        var hoverClass = up.settings.browse_button_hover,
     340                                                activeClass = up.settings.browse_button_active,
     341                                                topElement = up.features.triggerDialog ? browseButton : inputContainer;
     342                                       
     343                                        if (hoverClass) {
     344                                                plupload.addEvent(topElement, 'mouseover', function() {
     345                                                        plupload.addClass(browseButton, hoverClass);   
     346                                                }, up.id);
     347                                                plupload.addEvent(topElement, 'mouseout', function() {
     348                                                        plupload.removeClass(browseButton, hoverClass);
     349                                                }, up.id);
     350                                        }
     351                                       
     352                                        if (activeClass) {
     353                                                plupload.addEvent(topElement, 'mousedown', function() {
     354                                                        plupload.addClass(browseButton, activeClass);   
     355                                                }, up.id);
     356                                                plupload.addEvent(document.body, 'mouseup', function() {
     357                                                        plupload.removeClass(browseButton, activeClass);       
     358                                                }, up.id);
     359                                        }
     360
     361                                        // Route click event to the input[type=file] element for supporting browsers
     362                                        if (up.features.triggerDialog) {
     363                                                plupload.addEvent(browseButton, 'click', function(e) {
     364                                                        var input = document.getElementById(up.id + '_html5');
     365                                                        if (input && !input.disabled) { // for some reason FF (up to 8.0.1 so far) lets to click disabled input[type=file]
     366                                                                input.click();
     367                                                        }
     368                                                        e.preventDefault();
     369                                                }, up.id);
     370                                        }
     371                                }
     372                        });
     373
     374                        // Add drop handler
     375                        uploader.bind("PostInit", function() {
     376                                var dropElm = document.getElementById(uploader.settings.drop_element);
     377
     378                                if (dropElm) {
     379                                        // Lets fake drag/drop on Safari by moving a input type file in front of the mouse pointer when we drag into the drop zone
     380                                        // TODO: Remove this logic once Safari has official drag/drop support
     381                                        if (fakeSafariDragDrop) {
     382                                                plupload.addEvent(dropElm, 'dragenter', function(e) {
     383                                                        var dropInputElm, dropPos, dropSize;
     384
     385                                                        // Get or create drop zone
     386                                                        dropInputElm = document.getElementById(uploader.id + "_drop");
     387                                                        if (!dropInputElm) {
     388                                                                dropInputElm = document.createElement("input");
     389                                                                dropInputElm.setAttribute('type', "file");
     390                                                                dropInputElm.setAttribute('id', uploader.id + "_drop");
     391                                                                dropInputElm.setAttribute('multiple', 'multiple');
     392
     393                                                                plupload.addEvent(dropInputElm, 'change', function() {
     394                                                                        // Add the selected files from file input
     395                                                                        addSelectedFiles(this.files);
     396                                                                                                                                               
     397                                                                        // Remove input element
     398                                                                        plupload.removeEvent(dropInputElm, 'change', uploader.id);
     399                                                                        dropInputElm.parentNode.removeChild(dropInputElm);                                                                     
     400                                                                }, uploader.id);
     401                                                               
     402                                                                dropElm.appendChild(dropInputElm);
     403                                                        }
     404
     405                                                        dropPos = plupload.getPos(dropElm, document.getElementById(uploader.settings.container));
     406                                                        dropSize = plupload.getSize(dropElm);
     407                                                       
     408                                                        if (plupload.getStyle(dropElm, 'position') === 'static') {
     409                                                                plupload.extend(dropElm.style, {
     410                                                                        position : 'relative'
     411                                                                });
     412                                                        }
     413             
     414                                                        plupload.extend(dropInputElm.style, {
     415                                                                position : 'absolute',
     416                                                                display : 'block',
     417                                                                top : 0,
     418                                                                left : 0,
     419                                                                width : dropSize.w + 'px',
     420                                                                height : dropSize.h + 'px',
     421                                                                opacity : 0
     422                                                        });                                                     
     423                                                }, uploader.id);
     424
     425                                                return;
     426                                        }
     427
     428                                        // Block browser default drag over
     429                                        plupload.addEvent(dropElm, 'dragover', function(e) {
     430                                                e.preventDefault();
     431                                        }, uploader.id);
     432
     433                                        // Attach drop handler and grab files
     434                                        plupload.addEvent(dropElm, 'drop', function(e) {
     435                                                var dataTransfer = e.dataTransfer;
     436
     437                                                // Add dropped files
     438                                                if (dataTransfer && dataTransfer.files) {
     439                                                        addSelectedFiles(dataTransfer.files);
     440                                                }
     441
     442                                                e.preventDefault();
     443                                        }, uploader.id);
     444                                }
     445                        });
     446
     447                        uploader.bind("Refresh", function(up) {
     448                                var browseButton, browsePos, browseSize, inputContainer, zIndex;
     449                                       
     450                                browseButton = document.getElementById(uploader.settings.browse_button);
     451                                if (browseButton) {
     452                                        browsePos = plupload.getPos(browseButton, document.getElementById(up.settings.container));
     453                                        browseSize = plupload.getSize(browseButton);
     454                                        inputContainer = document.getElementById(uploader.id + '_html5_container');
     455       
     456                                        plupload.extend(inputContainer.style, {
     457                                                top : browsePos.y + 'px',
     458                                                left : browsePos.x + 'px',
     459                                                width : browseSize.w + 'px',
     460                                                height : browseSize.h + 'px'
     461                                        });
     462                                       
     463                                        // for WebKit place input element underneath the browse button and route onclick event
     464                                        // TODO: revise when browser support for this feature will change
     465                                        if (uploader.features.triggerDialog) {
     466                                                if (plupload.getStyle(browseButton, 'position') === 'static') {
     467                                                        plupload.extend(browseButton.style, {
     468                                                                position : 'relative'
     469                                                        });
     470                                                }
     471                                               
     472                                                zIndex = parseInt(plupload.getStyle(browseButton, 'z-index'), 10);
     473                                                if (isNaN(zIndex)) {
     474                                                        zIndex = 0;
     475                                                }                                               
     476                                                       
     477                                                plupload.extend(browseButton.style, {
     478                                                        zIndex : zIndex
     479                                                });                                             
     480                                                                                       
     481                                                plupload.extend(inputContainer.style, {
     482                                                        zIndex : zIndex - 1
     483                                                });
     484                                        }                               
     485                                }
     486                        });
     487                       
     488                        uploader.bind("DisableBrowse", function(up, disabled) {
     489                                var input = document.getElementById(up.id + '_html5');
     490                                if (input) {
     491                                        input.disabled = disabled;     
     492                                }
     493                        });
     494                       
     495                        uploader.bind("CancelUpload", function() {
     496                                if (xhr.abort) {
     497                                        xhr.abort();   
     498                                }
     499                        });
     500
     501                        uploader.bind("UploadFile", function(up, file) {
     502                                var settings = up.settings, nativeFile, resize;
     503                                       
     504                                function w3cBlobSlice(blob, start, end) {
     505                                        var blobSlice;
     506                                       
     507                                        if (File.prototype.slice) {
     508                                                try {
     509                                                        blob.slice();   // depricated version will throw WRONG_ARGUMENTS_ERR exception
     510                                                        return blob.slice(start, end);
     511                                                } catch (e) {
     512                                                        // depricated slice method
     513                                                        return blob.slice(start, end - start);
     514                                                }
     515                                        // slice method got prefixed: https://bugzilla.mozilla.org/show_bug.cgi?id=649672       
     516                                        } else if (blobSlice = File.prototype.webkitSlice || File.prototype.mozSlice) {
     517                                                return blobSlice.call(blob, start, end);       
     518                                        } else {
     519                                                return null; // or throw some exception
     520                                        }
     521                                }       
     522
     523                                function sendBinaryBlob(blob) {
     524                                        var chunk = 0, loaded = 0,
     525                                                fr = ("FileReader" in window) ? new FileReader : null;
     526                                               
     527
     528                                        function uploadNextChunk() {
     529                                                var chunkBlob, br, chunks, args, chunkSize, curChunkSize, mimeType, url = up.settings.url;                                                                                                     
     530
     531                                               
     532                                                function prepareAndSend(bin) {
     533                                                        var multipartDeltaSize = 0,
     534                                                                boundary = '----pluploadboundary' + plupload.guid(), formData, dashdash = '--', crlf = '\r\n', multipartBlob = '';
     535                                                               
     536                                                        xhr = new XMLHttpRequest;
     537                                                                                                                       
     538                                                        // Do we have upload progress support
     539                                                        if (xhr.upload) {
     540                                                                xhr.upload.onprogress = function(e) {
     541                                                                        file.loaded = Math.min(file.size, loaded + e.loaded - multipartDeltaSize); // Loaded can be larger than file size due to multipart encoding
     542                                                                        up.trigger('UploadProgress', file);
     543                                                                };
     544                                                        }
     545       
     546                                                        xhr.onreadystatechange = function() {
     547                                                                var httpStatus, chunkArgs;
     548                                                                                                                                       
     549                                                                if (xhr.readyState == 4 && up.state !== plupload.STOPPED) {
     550                                                                        // Getting the HTTP status might fail on some Gecko versions
     551                                                                        try {
     552                                                                                httpStatus = xhr.status;
     553                                                                        } catch (ex) {
     554                                                                                httpStatus = 0;
     555                                                                        }
     556       
     557                                                                        // Is error status
     558                                                                        if (httpStatus >= 400) {
     559                                                                                up.trigger('Error', {
     560                                                                                        code : plupload.HTTP_ERROR,
     561                                                                                        message : plupload.translate('HTTP Error.'),
     562                                                                                        file : file,
     563                                                                                        status : httpStatus
     564                                                                                });
     565                                                                        } else {
     566                                                                                // Handle chunk response
     567                                                                                if (chunks) {
     568                                                                                        chunkArgs = {
     569                                                                                                chunk : chunk,
     570                                                                                                chunks : chunks,
     571                                                                                                response : xhr.responseText,
     572                                                                                                status : httpStatus
     573                                                                                        };
     574       
     575                                                                                        up.trigger('ChunkUploaded', file, chunkArgs);
     576                                                                                        loaded += curChunkSize;
     577       
     578                                                                                        // Stop upload
     579                                                                                        if (chunkArgs.cancelled) {
     580                                                                                                file.status = plupload.FAILED;
     581                                                                                                return;
     582                                                                                        }
     583       
     584                                                                                        file.loaded = Math.min(file.size, (chunk + 1) * chunkSize);
     585                                                                                } else {
     586                                                                                        file.loaded = file.size;
     587                                                                                }
     588       
     589                                                                                up.trigger('UploadProgress', file);
     590                                                                               
     591                                                                                bin = chunkBlob = formData = multipartBlob = null; // Free memory
     592                                                                               
     593                                                                                // Check if file is uploaded
     594                                                                                if (!chunks || ++chunk >= chunks) {
     595                                                                                        file.status = plupload.DONE;
     596                                                                                                                                                                               
     597                                                                                        up.trigger('FileUploaded', file, {
     598                                                                                                response : xhr.responseText,
     599                                                                                                status : httpStatus
     600                                                                                        });                                                                             
     601                                                                                } else {                                                                               
     602                                                                                        // Still chunks left
     603                                                                                        uploadNextChunk();
     604                                                                                }
     605                                                                        }                                                                                                                                       
     606                                                                }
     607                                                        };
     608                                                       
     609       
     610                                                        // Build multipart request
     611                                                        if (up.settings.multipart && features.multipart) {
     612                                                               
     613                                                                args.name = file.target_name || file.name;
     614                                                               
     615                                                                xhr.open("post", url, true);
     616                                                               
     617                                                                // Set custom headers
     618                                                                plupload.each(up.settings.headers, function(value, name) {
     619                                                                        xhr.setRequestHeader(name, value);
     620                                                                });
     621                                                               
     622                                                               
     623                                                                // if has FormData support like Chrome 6+, Safari 5+, Firefox 4, use it
     624                                                                if (typeof(bin) !== 'string' && !!window.FormData) {
     625                                                                        formData = new FormData();
     626       
     627                                                                        // Add multipart params
     628                                                                        plupload.each(plupload.extend(args, up.settings.multipart_params), function(value, name) {
     629                                                                                formData.append(name, value);
     630                                                                        });
     631       
     632                                                                        // Add file and send it
     633                                                                        formData.append(up.settings.file_data_name, bin);                                                               
     634                                                                        xhr.send(formData);
     635       
     636                                                                        return;
     637                                                                }  // if no FormData we can still try to send it directly as last resort (see below)
     638                                                               
     639                                                               
     640                                                                if (typeof(bin) === 'string') {
     641                                                                        // Trying to send the whole thing as binary...
     642               
     643                                                                        // multipart request
     644                                                                        xhr.setRequestHeader('Content-Type', 'multipart/form-data; boundary=' + boundary);
     645               
     646                                                                        // append multipart parameters
     647                                                                        plupload.each(plupload.extend(args, up.settings.multipart_params), function(value, name) {
     648                                                                                multipartBlob += dashdash + boundary + crlf +
     649                                                                                        'Content-Disposition: form-data; name="' + name + '"' + crlf + crlf;
     650               
     651                                                                                multipartBlob += unescape(encodeURIComponent(value)) + crlf;
     652                                                                        });
     653               
     654                                                                        mimeType = plupload.mimeTypes[file.name.replace(/^.+\.([^.]+)/, '$1').toLowerCase()] || 'application/octet-stream';
     655               
     656                                                                        // Build RFC2388 blob
     657                                                                        multipartBlob += dashdash + boundary + crlf +
     658                                                                                'Content-Disposition: form-data; name="' + up.settings.file_data_name + '"; filename="' + unescape(encodeURIComponent(file.name)) + '"' + crlf +
     659                                                                                'Content-Type: ' + mimeType + crlf + crlf +
     660                                                                                bin + crlf +
     661                                                                                dashdash + boundary + dashdash + crlf;
     662               
     663                                                                        multipartDeltaSize = multipartBlob.length - bin.length;
     664                                                                        bin = multipartBlob;
     665                                                               
     666                                                       
     667                                                                        if (xhr.sendAsBinary) { // Gecko
     668                                                                                xhr.sendAsBinary(bin);
     669                                                                        } else if (features.canSendBinary) { // WebKit with typed arrays support
     670                                                                                var ui8a = new Uint8Array(bin.length);
     671                                                                                for (var i = 0; i < bin.length; i++) {
     672                                                                                        ui8a[i] = (bin.charCodeAt(i) & 0xff);
     673                                                                                }
     674                                                                                xhr.send(ui8a.buffer);
     675                                                                        }
     676                                                                        return; // will return from here only if shouldn't send binary
     677                                                                }                                                       
     678                                                        }
     679                                                       
     680                                                        // if no multipart, or last resort, send as binary stream
     681                                                        url = plupload.buildUrl(up.settings.url, plupload.extend(args, up.settings.multipart_params));
     682                                                       
     683                                                        xhr.open("post", url, true);
     684                                                       
     685                                                        xhr.setRequestHeader('Content-Type', 'application/octet-stream'); // Binary stream header
     686                                                               
     687                                                        // Set custom headers
     688                                                        plupload.each(up.settings.headers, function(value, name) {
     689                                                                xhr.setRequestHeader(name, value);
     690                                                        });
     691                                                                                               
     692                                                        xhr.send(bin);
     693                                                } // prepareAndSend
     694
     695
     696                                                // File upload finished
     697                                                if (file.status == plupload.DONE || file.status == plupload.FAILED || up.state == plupload.STOPPED) {
     698                                                        return;
     699                                                }
     700
     701                                                // Standard arguments
     702                                                args = {name : file.target_name || file.name};
     703
     704                                                // Only add chunking args if needed
     705                                                if (settings.chunk_size && file.size > settings.chunk_size && (features.chunks || typeof(blob) == 'string')) { // blob will be of type string if it was loaded in memory
     706                                                        chunkSize = settings.chunk_size;
     707                                                        chunks = Math.ceil(file.size / chunkSize);
     708                                                        curChunkSize = Math.min(chunkSize, file.size - (chunk * chunkSize));
     709
     710                                                        // Blob is string so we need to fake chunking, this is not
     711                                                        // ideal since the whole file is loaded into memory
     712                                                        if (typeof(blob) == 'string') {
     713                                                                chunkBlob = blob.substring(chunk * chunkSize, chunk * chunkSize + curChunkSize);
     714                                                        } else {
     715                                                                // Slice the chunk
     716                                                                chunkBlob = w3cBlobSlice(blob, chunk * chunkSize, chunk * chunkSize + curChunkSize);
     717                                                        }
     718
     719                                                        // Setup query string arguments
     720                                                        args.chunk = chunk;
     721                                                        args.chunks = chunks;
     722                                                } else {
     723                                                        curChunkSize = file.size;
     724                                                        chunkBlob = blob;
     725                                                }
     726                                               
     727                                                // workaround Gecko 2,5,6 FormData+Blob bug: https://bugzilla.mozilla.org/show_bug.cgi?id=649150
     728                                                if (up.settings.multipart && features.multipart && typeof(chunkBlob) !== 'string' && fr && features.cantSendBlobInFormData && features.chunks && up.settings.chunk_size) { // Gecko 2,5,6
     729                                                        fr.onload = function() {
     730                                                                prepareAndSend(fr.result);
     731                                                        }
     732                                                        fr.readAsBinaryString(chunkBlob);
     733                                                } else {
     734                                                        prepareAndSend(chunkBlob);
     735                                                }
     736                                                       
     737                                        }
     738
     739                                        // Start uploading chunks
     740                                        uploadNextChunk();
     741                                }
     742
     743                                nativeFile = html5files[file.id];
     744                                                               
     745                                // Resize image if it's a supported format and resize is enabled
     746                                if (features.jpgresize && up.settings.resize && /\.(png|jpg|jpeg)$/i.test(file.name)) {
     747                                        scaleImage.call(up, file, up.settings.resize, /\.png$/i.test(file.name) ? 'image/png' : 'image/jpeg', function(res) {
     748                                                // If it was scaled send the scaled image if it failed then
     749                                                // send the raw image and let the server do the scaling
     750                                                if (res.success) {
     751                                                        file.size = res.data.length;
     752                                                        sendBinaryBlob(res.data);
     753                                                } else if (features.chunks) {
     754                                                        sendBinaryBlob(nativeFile);
     755                                                } else {
     756                                                        readFileAsBinary(nativeFile, sendBinaryBlob); // for browsers not supporting File.slice (e.g. FF3.6)
     757                                                }
     758                                        });
     759                                // if there's no way to slice file without preloading it in memory, preload it
     760                                } else if (!features.chunks && features.jpgresize) {
     761                                        readFileAsBinary(nativeFile, sendBinaryBlob);
     762                                } else {
     763                                        sendBinaryBlob(nativeFile);
     764                                }
     765                        });
     766                       
     767                       
     768                        uploader.bind('Destroy', function(up) {
     769                                var name, element, container = document.body,
     770                                        elements = {
     771                                                inputContainer: up.id + '_html5_container',
     772                                                inputFile: up.id + '_html5',
     773                                                browseButton: up.settings.browse_button,
     774                                                dropElm: up.settings.drop_element
     775                                        };
     776
     777                                // Unbind event handlers
     778                                for (name in elements) {
     779                                        element = document.getElementById(elements[name]);
     780                                        if (element) {
     781                                                plupload.removeAllEvents(element, up.id);
     782                                        }
     783                                }
     784                                plupload.removeAllEvents(document.body, up.id);
     785                               
     786                                if (up.settings.container) {
     787                                        container = document.getElementById(up.settings.container);
     788                                }
     789                               
     790                                // Remove mark-up
     791                                container.removeChild(document.getElementById(elements.inputContainer));
     792                        });
     793
     794                        callback({success : true});
     795                }
     796        });
     797       
     798        function BinaryReader() {
     799                var II = false, bin;
     800
     801                // Private functions
     802                function read(idx, size) {
     803                        var mv = II ? 0 : -8 * (size - 1), sum = 0, i;
     804
     805                        for (i = 0; i < size; i++) {
     806                                sum |= (bin.charCodeAt(idx + i) << Math.abs(mv + i*8));
     807                        }
     808
     809                        return sum;
     810                }
     811
     812                function putstr(segment, idx, length) {
     813                        var length = arguments.length === 3 ? length : bin.length - idx - 1;
     814                       
     815                        bin = bin.substr(0, idx) + segment + bin.substr(length + idx);
     816                }
     817
     818                function write(idx, num, size) {
     819                        var str = '', mv = II ? 0 : -8 * (size - 1), i;
     820
     821                        for (i = 0; i < size; i++) {
     822                                str += String.fromCharCode((num >> Math.abs(mv + i*8)) & 255);
     823                        }
     824
     825                        putstr(str, idx, size);
     826                }
     827
     828                // Public functions
     829                return {
     830                        II: function(order) {
     831                                if (order === undef) {
     832                                        return II;
     833                                } else {
     834                                        II = order;
     835                                }
     836                        },
     837
     838                        init: function(binData) {
     839                                II = false;
     840                                bin = binData;
     841                        },
     842
     843                        SEGMENT: function(idx, length, segment) {                               
     844                                switch (arguments.length) {
     845                                        case 1:
     846                                                return bin.substr(idx, bin.length - idx - 1);
     847                                        case 2:
     848                                                return bin.substr(idx, length);
     849                                        case 3:
     850                                                putstr(segment, idx, length);
     851                                                break;
     852                                        default: return bin;   
     853                                }
     854                        },
     855
     856                        BYTE: function(idx) {
     857                                return read(idx, 1);
     858                        },
     859
     860                        SHORT: function(idx) {
     861                                return read(idx, 2);
     862                        },
     863
     864                        LONG: function(idx, num) {
     865                                if (num === undef) {
     866                                        return read(idx, 4);
     867                                } else {
     868                                        write(idx, num, 4);
     869                                }
     870                        },
     871
     872                        SLONG: function(idx) { // 2's complement notation
     873                                var num = read(idx, 4);
     874
     875                                return (num > 2147483647 ? num - 4294967296 : num);
     876                        },
     877
     878                        STRING: function(idx, size) {
     879                                var str = '';
     880
     881                                for (size += idx; idx < size; idx++) {
     882                                        str += String.fromCharCode(read(idx, 1));
     883                                }
     884
     885                                return str;
     886                        }
     887                };
     888        }
     889       
     890        function JPEG_Headers(data) {
     891               
     892                var markers = {
     893                                0xFFE1: {
     894                                        app: 'EXIF',
     895                                        name: 'APP1',
     896                                        signature: "Exif\0"
     897                                },
     898                                0xFFE2: {
     899                                        app: 'ICC',
     900                                        name: 'APP2',
     901                                        signature: "ICC_PROFILE\0"
     902                                },
     903                                0xFFED: {
     904                                        app: 'IPTC',
     905                                        name: 'APP13',
     906                                        signature: "Photoshop 3.0\0"
     907                                }
     908                        },
     909                        headers = [], read, idx, marker = undef, length = 0, limit;
     910                       
     911               
     912                read = new BinaryReader();
     913                read.init(data);
     914                               
     915                // Check if data is jpeg
     916                if (read.SHORT(0) !== 0xFFD8) {
     917                        return;
     918                }
     919               
     920                idx = 2;
     921                limit = Math.min(1048576, data.length);
     922                       
     923                while (idx <= limit) {
     924                        marker = read.SHORT(idx);
     925                       
     926                        // omit RST (restart) markers
     927                        if (marker >= 0xFFD0 && marker <= 0xFFD7) {
     928                                idx += 2;
     929                                continue;
     930                        }
     931                       
     932                        // no headers allowed after SOS marker
     933                        if (marker === 0xFFDA || marker === 0xFFD9) {
     934                                break; 
     935                        }       
     936                       
     937                        length = read.SHORT(idx + 2) + 2;       
     938                       
     939                        if (markers[marker] &&
     940                                read.STRING(idx + 4, markers[marker].signature.length) === markers[marker].signature) {
     941                                headers.push({
     942                                        hex: marker,
     943                                        app: markers[marker].app.toUpperCase(),
     944                                        name: markers[marker].name.toUpperCase(),
     945                                        start: idx,
     946                                        length: length,
     947                                        segment: read.SEGMENT(idx, length)
     948                                });
     949                        }
     950                        idx += length;                 
     951                }
     952                                       
     953                read.init(null); // free memory
     954                                               
     955                return {
     956                       
     957                        headers: headers,
     958                       
     959                        restore: function(data) {
     960                                read.init(data);
     961                               
     962                                // Check if data is jpeg
     963                                var jpegHeaders = new JPEG_Headers(data);
     964                               
     965                                if (!jpegHeaders['headers']) {
     966                                        return false;
     967                                }       
     968                               
     969                                // Delete any existing headers that need to be replaced
     970                                for (var i = jpegHeaders['headers'].length; i > 0; i--) {
     971                                        var hdr = jpegHeaders['headers'][i - 1];
     972                                        read.SEGMENT(hdr.start, hdr.length, '')
     973                                }
     974                                jpegHeaders.purge();
     975                               
     976                                idx = read.SHORT(2) == 0xFFE0 ? 4 + read.SHORT(4) : 2;
     977                                                               
     978                                for (var i = 0, max = headers.length; i < max; i++) {
     979                                        read.SEGMENT(idx, 0, headers[i].segment);                                               
     980                                        idx += headers[i].length;
     981                                }
     982                               
     983                                return read.SEGMENT();
     984                        },
     985                       
     986                        get: function(app) {
     987                                var array = [];
     988                                                               
     989                                for (var i = 0, max = headers.length; i < max; i++) {
     990                                        if (headers[i].app === app.toUpperCase()) {
     991                                                array.push(headers[i].segment);
     992                                        }
     993                                }
     994                                return array;
     995                        },
     996                       
     997                        set: function(app, segment) {
     998                                var array = [];
     999                               
     1000                                if (typeof(segment) === 'string') {
     1001                                        array.push(segment);   
     1002                                } else {
     1003                                        array = segment;       
     1004                                }
     1005                               
     1006                                for (var i = ii = 0, max = headers.length; i < max; i++) {
     1007                                        if (headers[i].app === app.toUpperCase()) {
     1008                                                headers[i].segment = array[ii];
     1009                                                headers[i].length = array[ii].length;
     1010                                                ii++;
     1011                                        }
     1012                                        if (ii >= array.length) break;
     1013                                }
     1014                        },
     1015                       
     1016                        purge: function() {
     1017                                headers = [];
     1018                                read.init(null);
     1019                        }
     1020                };             
     1021        }
     1022       
     1023       
     1024        function ExifParser() {
     1025                // Private ExifParser fields
     1026                var data, tags, offsets = {}, tagDescs;
     1027
     1028                data = new BinaryReader();
     1029
     1030                tags = {
     1031                        tiff : {
     1032                                /*
     1033                                The image orientation viewed in terms of rows and columns.
     1034       
     1035                                1 - The 0th row is at the visual top of the image, and the 0th column is the visual left-hand side.
     1036                                2 - The 0th row is at the visual top of the image, and the 0th column is the visual left-hand side.
     1037                                3 - The 0th row is at the visual top of the image, and the 0th column is the visual right-hand side.
     1038                                4 - The 0th row is at the visual bottom of the image, and the 0th column is the visual right-hand side.
     1039                                5 - The 0th row is at the visual bottom of the image, and the 0th column is the visual left-hand side.
     1040                                6 - The 0th row is the visual left-hand side of the image, and the 0th column is the visual top.
     1041                                7 - The 0th row is the visual right-hand side of the image, and the 0th column is the visual top.
     1042                                8 - The 0th row is the visual right-hand side of the image, and the 0th column is the visual bottom.
     1043                                9 - The 0th row is the visual left-hand side of the image, and the 0th column is the visual bottom.
     1044                                */
     1045                                0x0112: 'Orientation',
     1046                                0x8769: 'ExifIFDPointer',
     1047                                0x8825: 'GPSInfoIFDPointer'
     1048                        },
     1049                        exif : {
     1050                                0x9000: 'ExifVersion',
     1051                                0xA001: 'ColorSpace',
     1052                                0xA002: 'PixelXDimension',
     1053                                0xA003: 'PixelYDimension',
     1054                                0x9003: 'DateTimeOriginal',
     1055                                0x829A: 'ExposureTime',
     1056                                0x829D: 'FNumber',
     1057                                0x8827: 'ISOSpeedRatings',
     1058                                0x9201: 'ShutterSpeedValue',
     1059                                0x9202: 'ApertureValue' ,
     1060                                0x9207: 'MeteringMode',
     1061                                0x9208: 'LightSource',
     1062                                0x9209: 'Flash',
     1063                                0xA402: 'ExposureMode',
     1064                                0xA403: 'WhiteBalance',
     1065                                0xA406: 'SceneCaptureType',
     1066                                0xA404: 'DigitalZoomRatio',
     1067                                0xA408: 'Contrast',
     1068                                0xA409: 'Saturation',
     1069                                0xA40A: 'Sharpness'
     1070                        },
     1071                        gps : {
     1072                                0x0000: 'GPSVersionID',
     1073                                0x0001: 'GPSLatitudeRef',
     1074                                0x0002: 'GPSLatitude',
     1075                                0x0003: 'GPSLongitudeRef',
     1076                                0x0004: 'GPSLongitude'
     1077                        }
     1078                };
     1079
     1080                tagDescs = {
     1081                        'ColorSpace': {
     1082                                1: 'sRGB',
     1083                                0: 'Uncalibrated'
     1084                        },
     1085
     1086                        'MeteringMode': {
     1087                                0: 'Unknown',
     1088                                1: 'Average',
     1089                                2: 'CenterWeightedAverage',
     1090                                3: 'Spot',
     1091                                4: 'MultiSpot',
     1092                                5: 'Pattern',
     1093                                6: 'Partial',
     1094                                255: 'Other'
     1095                        },
     1096
     1097                        'LightSource': {
     1098                                1: 'Daylight',
     1099                                2: 'Fliorescent',
     1100                                3: 'Tungsten',
     1101                                4: 'Flash',
     1102                                9: 'Fine weather',
     1103                                10: 'Cloudy weather',
     1104                                11: 'Shade',
     1105                                12: 'Daylight fluorescent (D 5700 - 7100K)',
     1106                                13: 'Day white fluorescent (N 4600 -5400K)',
     1107                                14: 'Cool white fluorescent (W 3900 - 4500K)',
     1108                                15: 'White fluorescent (WW 3200 - 3700K)',
     1109                                17: 'Standard light A',
     1110                                18: 'Standard light B',
     1111                                19: 'Standard light C',
     1112                                20: 'D55',
     1113                                21: 'D65',
     1114                                22: 'D75',
     1115                                23: 'D50',
     1116                                24: 'ISO studio tungsten',
     1117                                255: 'Other'
     1118                        },
     1119
     1120                        'Flash': {
     1121                                0x0000: 'Flash did not fire.',
     1122                                0x0001: 'Flash fired.',
     1123                                0x0005: 'Strobe return light not detected.',
     1124                                0x0007: 'Strobe return light detected.',
     1125                                0x0009: 'Flash fired, compulsory flash mode',
     1126                                0x000D: 'Flash fired, compulsory flash mode, return light not detected',
     1127                                0x000F: 'Flash fired, compulsory flash mode, return light detected',
     1128                                0x0010: 'Flash did not fire, compulsory flash mode',
     1129                                0x0018: 'Flash did not fire, auto mode',
     1130                                0x0019: 'Flash fired, auto mode',
     1131                                0x001D: 'Flash fired, auto mode, return light not detected',
     1132                                0x001F: 'Flash fired, auto mode, return light detected',
     1133                                0x0020: 'No flash function',
     1134                                0x0041: 'Flash fired, red-eye reduction mode',
     1135                                0x0045: 'Flash fired, red-eye reduction mode, return light not detected',
     1136                                0x0047: 'Flash fired, red-eye reduction mode, return light detected',
     1137                                0x0049: 'Flash fired, compulsory flash mode, red-eye reduction mode',
     1138                                0x004D: 'Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected',
     1139                                0x004F: 'Flash fired, compulsory flash mode, red-eye reduction mode, return light detected',
     1140                                0x0059: 'Flash fired, auto mode, red-eye reduction mode',
     1141                                0x005D: 'Flash fired, auto mode, return light not detected, red-eye reduction mode',
     1142                                0x005F: 'Flash fired, auto mode, return light detected, red-eye reduction mode'
     1143                        },
     1144
     1145                        'ExposureMode': {
     1146                                0: 'Auto exposure',
     1147                                1: 'Manual exposure',
     1148                                2: 'Auto bracket'
     1149                        },
     1150
     1151                        'WhiteBalance': {
     1152                                0: 'Auto white balance',
     1153                                1: 'Manual white balance'
     1154                        },
     1155
     1156                        'SceneCaptureType': {
     1157                                0: 'Standard',
     1158                                1: 'Landscape',
     1159                                2: 'Portrait',
     1160                                3: 'Night scene'
     1161                        },
     1162
     1163                        'Contrast': {
     1164                                0: 'Normal',
     1165                                1: 'Soft',
     1166                                2: 'Hard'
     1167                        },
     1168
     1169                        'Saturation': {
     1170                                0: 'Normal',
     1171                                1: 'Low saturation',
     1172                                2: 'High saturation'
     1173                        },
     1174
     1175                        'Sharpness': {
     1176                                0: 'Normal',
     1177                                1: 'Soft',
     1178                                2: 'Hard'
     1179                        },
     1180
     1181                        // GPS related
     1182                        'GPSLatitudeRef': {
     1183                                N: 'North latitude',
     1184                                S: 'South latitude'
     1185                        },
     1186
     1187                        'GPSLongitudeRef': {
     1188                                E: 'East longitude',
     1189                                W: 'West longitude'
     1190                        }
     1191                };
     1192
     1193                function extractTags(IFD_offset, tags2extract) {
     1194                        var length = data.SHORT(IFD_offset), i, ii,
     1195                                tag, type, count, tagOffset, offset, value, values = [], hash = {};
     1196
     1197                        for (i = 0; i < length; i++) {
     1198                                // Set binary reader pointer to beginning of the next tag
     1199                                offset = tagOffset = IFD_offset + 12 * i + 2;
     1200
     1201                                tag = tags2extract[data.SHORT(offset)];
     1202
     1203                                if (tag === undef) {
     1204                                        continue; // Not the tag we requested
     1205                                }
     1206
     1207                                type = data.SHORT(offset+=2);
     1208                                count = data.LONG(offset+=2);
     1209
     1210                                offset += 4;
     1211                                values = [];
     1212
     1213                                switch (type) {
     1214                                        case 1: // BYTE
     1215                                        case 7: // UNDEFINED
     1216                                                if (count > 4) {
     1217                                                        offset = data.LONG(offset) + offsets.tiffHeader;
     1218                                                }
     1219
     1220                                                for (ii = 0; ii < count; ii++) {
     1221                                                        values[ii] = data.BYTE(offset + ii);
     1222                                                }
     1223
     1224                                                break;
     1225
     1226                                        case 2: // STRING
     1227                                                if (count > 4) {
     1228                                                        offset = data.LONG(offset) + offsets.tiffHeader;
     1229                                                }
     1230
     1231                                                hash[tag] = data.STRING(offset, count - 1);
     1232
     1233                                                continue;
     1234
     1235                                        case 3: // SHORT
     1236                                                if (count > 2) {
     1237                                                        offset = data.LONG(offset) + offsets.tiffHeader;
     1238                                                }
     1239
     1240                                                for (ii = 0; ii < count; ii++) {
     1241                                                        values[ii] = data.SHORT(offset + ii*2);
     1242                                                }
     1243
     1244                                                break;
     1245
     1246                                        case 4: // LONG
     1247                                                if (count > 1) {
     1248                                                        offset = data.LONG(offset) + offsets.tiffHeader;
     1249                                                }
     1250
     1251                                                for (ii = 0; ii < count; ii++) {
     1252                                                        values[ii] = data.LONG(offset + ii*4);
     1253                                                }
     1254
     1255                                                break;
     1256
     1257                                        case 5: // RATIONAL
     1258                                                offset = data.LONG(offset) + offsets.tiffHeader;
     1259
     1260                                                for (ii = 0; ii < count; ii++) {
     1261                                                        values[ii] = data.LONG(offset + ii*4) / data.LONG(offset + ii*4 + 4);
     1262                                                }
     1263
     1264                                                break;
     1265
     1266                                        case 9: // SLONG
     1267                                                offset = data.LONG(offset) + offsets.tiffHeader;
     1268
     1269                                                for (ii = 0; ii < count; ii++) {
     1270                                                        values[ii] = data.SLONG(offset + ii*4);
     1271                                                }
     1272
     1273                                                break;
     1274
     1275                                        case 10: // SRATIONAL
     1276                                                offset = data.LONG(offset) + offsets.tiffHeader;
     1277
     1278                                                for (ii = 0; ii < count; ii++) {
     1279                                                        values[ii] = data.SLONG(offset + ii*4) / data.SLONG(offset + ii*4 + 4);
     1280                                                }
     1281
     1282                                                break;
     1283
     1284                                        default:
     1285                                                continue;
     1286                                }
     1287
     1288                                value = (count == 1 ? values[0] : values);
     1289
     1290                                if (tagDescs.hasOwnProperty(tag) && typeof value != 'object') {
     1291                                        hash[tag] = tagDescs[tag][value];
     1292                                } else {
     1293                                        hash[tag] = value;
     1294                                }
     1295                        }
     1296
     1297                        return hash;
     1298                }
     1299
     1300                function getIFDOffsets() {
     1301                        var Tiff = undef, idx = offsets.tiffHeader;
     1302
     1303                        // Set read order of multi-byte data
     1304                        data.II(data.SHORT(idx) == 0x4949);
     1305
     1306                        // Check if always present bytes are indeed present
     1307                        if (data.SHORT(idx+=2) !== 0x002A) {
     1308                                return false;
     1309                        }
     1310               
     1311                        offsets['IFD0'] = offsets.tiffHeader + data.LONG(idx += 2);
     1312                        Tiff = extractTags(offsets['IFD0'], tags.tiff);
     1313
     1314                        offsets['exifIFD'] = ('ExifIFDPointer' in Tiff ? offsets.tiffHeader + Tiff.ExifIFDPointer : undef);
     1315                        offsets['gpsIFD'] = ('GPSInfoIFDPointer' in Tiff ? offsets.tiffHeader + Tiff.GPSInfoIFDPointer : undef);
     1316
     1317                        return true;
     1318                }
     1319               
     1320                // At the moment only setting of simple (LONG) values, that do not require offset recalculation, is supported
     1321                function setTag(ifd, tag, value) {
     1322                        var offset, length, tagOffset, valueOffset = 0;
     1323                       
     1324                        // If tag name passed translate into hex key
     1325                        if (typeof(tag) === 'string') {
     1326                                var tmpTags = tags[ifd.toLowerCase()];
     1327                                for (hex in tmpTags) {
     1328                                        if (tmpTags[hex] === tag) {
     1329                                                tag = hex;
     1330                                                break; 
     1331                                        }
     1332                                }
     1333                        }
     1334                        offset = offsets[ifd.toLowerCase() + 'IFD'];
     1335                        length = data.SHORT(offset);
     1336                                               
     1337                        for (i = 0; i < length; i++) {
     1338                                tagOffset = offset + 12 * i + 2;
     1339
     1340                                if (data.SHORT(tagOffset) == tag) {
     1341                                        valueOffset = tagOffset + 8;
     1342                                        break;
     1343                                }
     1344                        }
     1345                       
     1346                        if (!valueOffset) return false;
     1347
     1348                       
     1349                        data.LONG(valueOffset, value);
     1350                        return true;
     1351                }
     1352               
     1353
     1354                // Public functions
     1355                return {
     1356                        init: function(segment) {
     1357                                // Reset internal data
     1358                                offsets = {
     1359                                        tiffHeader: 10
     1360                                };
     1361                               
     1362                                if (segment === undef || !segment.length) {
     1363                                        return false;
     1364                                }
     1365
     1366                                data.init(segment);
     1367
     1368                                // Check if that's APP1 and that it has EXIF
     1369                                if (data.SHORT(0) === 0xFFE1 && data.STRING(4, 5).toUpperCase() === "EXIF\0") {
     1370                                        return getIFDOffsets();
     1371                                }
     1372                                return false;
     1373                        },
     1374                       
     1375                        EXIF: function() {
     1376                                var Exif;
     1377                               
     1378                                // Populate EXIF hash
     1379                                Exif = extractTags(offsets.exifIFD, tags.exif);
     1380
     1381                                // Fix formatting of some tags
     1382                                if (Exif.ExifVersion && plupload.typeOf(Exif.ExifVersion) === 'array') {
     1383                                        for (var i = 0, exifVersion = ''; i < Exif.ExifVersion.length; i++) {
     1384                                                exifVersion += String.fromCharCode(Exif.ExifVersion[i]);       
     1385                                        }
     1386                                        Exif.ExifVersion = exifVersion;
     1387                                }
     1388
     1389                                return Exif;
     1390                        },
     1391
     1392                        GPS: function() {
     1393                                var GPS;
     1394                               
     1395                                GPS = extractTags(offsets.gpsIFD, tags.gps);
     1396                               
     1397                                // iOS devices (and probably some others) do not put in GPSVersionID tag (why?..)
     1398                                if (GPS.GPSVersionID) {
     1399                                        GPS.GPSVersionID = GPS.GPSVersionID.join('.');
     1400                                }
     1401
     1402                                return GPS;
     1403                        },
     1404                       
     1405                        setExif: function(tag, value) {
     1406                                // Right now only setting of width/height is possible
     1407                                if (tag !== 'PixelXDimension' && tag !== 'PixelYDimension') return false;
     1408                               
     1409                                return setTag('exif', tag, value);
     1410                        },
     1411
     1412
     1413                        getBinary: function() {
     1414                                return data.SEGMENT();
     1415                        }
     1416                };
     1417        };
     1418})(window, document, plupload);
     1419 No newline at end of file
  • wp-includes/js/plupload/plupload.html5.dev.js

  • wp-includes/js/plupload/plupload.html5.js

    Property changes on: wp-includes/js/plupload/plupload.html5.dev.js
    ___________________________________________________________________
    Added: svn:eol-style
    ## -0,0 +1 ##
    +native
    \ No newline at end of property
     
    1 (function(h,k,j,e){var c={},g;function m(o,p){var n;if("FileReader" in h){n=new FileReader();n.readAsDataURL(o);n.onload=function(){p(n.result)}}else{return p(o.getAsDataURL())}}function l(o,p){var n;if("FileReader" in h){n=new FileReader();n.readAsBinaryString(o);n.onload=function(){p(n.result)}}else{return p(o.getAsBinary())}}function d(r,p,n,v){var q,o,u,s,t=this;m(c[r.id],function(w){q=k.createElement("canvas");q.style.display="none";k.body.appendChild(q);o=q.getContext("2d");u=new Image();u.onerror=u.onabort=function(){v({success:false})};u.onload=function(){var B,x,z,y,A;if(!p.width){p.width=u.width}if(!p.height){p.height=u.height}s=Math.min(p.width/u.width,p.height/u.height);if(s<1||(s===1&&n==="image/jpeg")){B=Math.round(u.width*s);x=Math.round(u.height*s);q.width=B;q.height=x;o.drawImage(u,0,0,B,x);if(n==="image/jpeg"){y=new f(atob(w.substring(w.indexOf("base64,")+7)));if(y.headers&&y.headers.length){A=new a();if(A.init(y.get("exif")[0])){A.setExif("PixelXDimension",B);A.setExif("PixelYDimension",x);y.set("exif",A.getBinary());if(t.hasEventListener("ExifData")){t.trigger("ExifData",r,A.EXIF())}if(t.hasEventListener("GpsData")){t.trigger("GpsData",r,A.GPS())}}}if(p.quality){try{w=q.toDataURL(n,p.quality/100)}catch(C){w=q.toDataURL(n)}}}else{w=q.toDataURL(n)}w=w.substring(w.indexOf("base64,")+7);w=atob(w);if(y&&y.headers&&y.headers.length){w=y.restore(w);y.purge()}q.parentNode.removeChild(q);v({success:true,data:w})}else{v({success:false})}};u.src=w})}j.runtimes.Html5=j.addRuntime("html5",{getFeatures:function(){var s,o,r,q,p,n;o=r=p=n=false;if(h.XMLHttpRequest){s=new XMLHttpRequest();r=!!s.upload;o=!!(s.sendAsBinary||s.upload)}if(o){q=!!(s.sendAsBinary||(h.Uint8Array&&h.ArrayBuffer));p=!!(File&&(File.prototype.getAsDataURL||h.FileReader)&&q);n=!!(File&&(File.prototype.mozSlice||File.prototype.webkitSlice||File.prototype.slice))}g=j.ua.safari&&j.ua.windows;return{html5:o,dragdrop:(function(){var t=k.createElement("div");return("draggable" in t)||("ondragstart" in t&&"ondrop" in t)}()),jpgresize:p,pngresize:p,multipart:p||!!h.FileReader||!!h.FormData,canSendBinary:q,cantSendBlobInFormData:!!(j.ua.gecko&&h.FormData&&h.FileReader&&!FileReader.prototype.readAsArrayBuffer),progress:r,chunks:n,multi_selection:!(j.ua.safari&&j.ua.windows),triggerDialog:(j.ua.gecko&&h.FormData||j.ua.webkit)}},init:function(p,r){var n,q;function o(w){var u,t,v=[],x,s={};for(t=0;t<w.length;t++){u=w[t];if(s[u.name]){continue}s[u.name]=true;x=j.guid();c[x]=u;v.push(new j.File(x,u.fileName||u.name,u.fileSize||u.size))}if(v.length){p.trigger("FilesAdded",v)}}n=this.getFeatures();if(!n.html5){r({success:false});return}p.bind("Init",function(w){var G,F,C=[],v,D,t=w.settings.filters,u,B,s=k.body,E;G=k.createElement("div");G.id=w.id+"_html5_container";j.extend(G.style,{position:"absolute",background:p.settings.shim_bgcolor||"transparent",width:"100px",height:"100px",overflow:"hidden",zIndex:99999,opacity:p.settings.shim_bgcolor?"":0});G.className="plupload html5";if(p.settings.container){s=k.getElementById(p.settings.container);if(j.getStyle(s,"position")==="static"){s.style.position="relative"}}s.appendChild(G);no_type_restriction:for(v=0;v<t.length;v++){u=t[v].extensions.split(/,/);for(D=0;D<u.length;D++){if(u[D]==="*"){C=[];break no_type_restriction}B=j.mimeTypes[u[D]];if(B&&j.inArray(B,C)===-1){C.push(B)}}}G.innerHTML='<input id="'+p.id+'_html5"  style="font-size:999px" type="file" accept="'+C.join(",")+'" '+(p.settings.multi_selection&&p.features.multi_selection?'multiple="multiple"':"")+" />";G.scrollTop=100;E=k.getElementById(p.id+"_html5");if(w.features.triggerDialog){j.extend(E.style,{position:"absolute",width:"100%",height:"100%"})}else{j.extend(E.style,{cssFloat:"right",styleFloat:"right"})}E.onchange=function(){o(this.files);this.value=""};F=k.getElementById(w.settings.browse_button);if(F){var z=w.settings.browse_button_hover,A=w.settings.browse_button_active,x=w.features.triggerDialog?F:G;if(z){j.addEvent(x,"mouseover",function(){j.addClass(F,z)},w.id);j.addEvent(x,"mouseout",function(){j.removeClass(F,z)},w.id)}if(A){j.addEvent(x,"mousedown",function(){j.addClass(F,A)},w.id);j.addEvent(k.body,"mouseup",function(){j.removeClass(F,A)},w.id)}if(w.features.triggerDialog){j.addEvent(F,"click",function(H){var y=k.getElementById(w.id+"_html5");if(y&&!y.disabled){y.click()}H.preventDefault()},w.id)}}});p.bind("PostInit",function(){var s=k.getElementById(p.settings.drop_element);if(s){if(g){j.addEvent(s,"dragenter",function(w){var v,t,u;v=k.getElementById(p.id+"_drop");if(!v){v=k.createElement("input");v.setAttribute("type","file");v.setAttribute("id",p.id+"_drop");v.setAttribute("multiple","multiple");j.addEvent(v,"change",function(){o(this.files);j.removeEvent(v,"change",p.id);v.parentNode.removeChild(v)},p.id);s.appendChild(v)}t=j.getPos(s,k.getElementById(p.settings.container));u=j.getSize(s);if(j.getStyle(s,"position")==="static"){j.extend(s.style,{position:"relative"})}j.extend(v.style,{position:"absolute",display:"block",top:0,left:0,width:u.w+"px",height:u.h+"px",opacity:0})},p.id);return}j.addEvent(s,"dragover",function(t){t.preventDefault()},p.id);j.addEvent(s,"drop",function(u){var t=u.dataTransfer;if(t&&t.files){o(t.files)}u.preventDefault()},p.id)}});p.bind("Refresh",function(s){var t,u,v,x,w;t=k.getElementById(p.settings.browse_button);if(t){u=j.getPos(t,k.getElementById(s.settings.container));v=j.getSize(t);x=k.getElementById(p.id+"_html5_container");j.extend(x.style,{top:u.y+"px",left:u.x+"px",width:v.w+"px",height:v.h+"px"});if(p.features.triggerDialog){if(j.getStyle(t,"position")==="static"){j.extend(t.style,{position:"relative"})}w=parseInt(j.getStyle(t,"z-index"),10);if(isNaN(w)){w=0}j.extend(t.style,{zIndex:w});j.extend(x.style,{zIndex:w-1})}}});p.bind("DisableBrowse",function(s,u){var t=k.getElementById(s.id+"_html5");if(t){t.disabled=u}});p.bind("CancelUpload",function(){if(q&&q.abort){q.abort()}});p.bind("UploadFile",function(s,u){var v=s.settings,y,t;function x(A,D,z){var B;if(File.prototype.slice){try{A.slice();return A.slice(D,z)}catch(C){return A.slice(D,z-D)}}else{if(B=File.prototype.webkitSlice||File.prototype.mozSlice){return B.call(A,D,z)}else{return null}}}function w(A){var D=0,C=0,z=("FileReader" in h)?new FileReader:null;function B(){var I,M,K,L,H,J,F,E=s.settings.url;function G(V){var T=0,N="----pluploadboundary"+j.guid(),O,P="--",U="\r\n",R="";q=new XMLHttpRequest;if(q.upload){q.upload.onprogress=function(W){u.loaded=Math.min(u.size,C+W.loaded-T);s.trigger("UploadProgress",u)}}q.onreadystatechange=function(){var W,Y;if(q.readyState==4&&s.state!==j.STOPPED){try{W=q.status}catch(X){W=0}if(W>=400){s.trigger("Error",{code:j.HTTP_ERROR,message:j.translate("HTTP Error."),file:u,status:W})}else{if(K){Y={chunk:D,chunks:K,response:q.responseText,status:W};s.trigger("ChunkUploaded",u,Y);C+=J;if(Y.cancelled){u.status=j.FAILED;return}u.loaded=Math.min(u.size,(D+1)*H)}else{u.loaded=u.size}s.trigger("UploadProgress",u);V=I=O=R=null;if(!K||++D>=K){u.status=j.DONE;s.trigger("FileUploaded",u,{response:q.responseText,status:W})}else{B()}}}};if(s.settings.multipart&&n.multipart){L.name=u.target_name||u.name;q.open("post",E,true);j.each(s.settings.headers,function(X,W){q.setRequestHeader(W,X)});if(typeof(V)!=="string"&&!!h.FormData){O=new FormData();j.each(j.extend(L,s.settings.multipart_params),function(X,W){O.append(W,X)});O.append(s.settings.file_data_name,V);q.send(O);return}if(typeof(V)==="string"){q.setRequestHeader("Content-Type","multipart/form-data; boundary="+N);j.each(j.extend(L,s.settings.multipart_params),function(X,W){R+=P+N+U+'Content-Disposition: form-data; name="'+W+'"'+U+U;R+=unescape(encodeURIComponent(X))+U});F=j.mimeTypes[u.name.replace(/^.+\.([^.]+)/,"$1").toLowerCase()]||"application/octet-stream";R+=P+N+U+'Content-Disposition: form-data; name="'+s.settings.file_data_name+'"; filename="'+unescape(encodeURIComponent(u.name))+'"'+U+"Content-Type: "+F+U+U+V+U+P+N+P+U;T=R.length-V.length;V=R;if(q.sendAsBinary){q.sendAsBinary(V)}else{if(n.canSendBinary){var S=new Uint8Array(V.length);for(var Q=0;Q<V.length;Q++){S[Q]=(V.charCodeAt(Q)&255)}q.send(S.buffer)}}return}}E=j.buildUrl(s.settings.url,j.extend(L,s.settings.multipart_params));q.open("post",E,true);q.setRequestHeader("Content-Type","application/octet-stream");j.each(s.settings.headers,function(X,W){q.setRequestHeader(W,X)});q.send(V)}if(u.status==j.DONE||u.status==j.FAILED||s.state==j.STOPPED){return}L={name:u.target_name||u.name};if(v.chunk_size&&u.size>v.chunk_size&&(n.chunks||typeof(A)=="string")){H=v.chunk_size;K=Math.ceil(u.size/H);J=Math.min(H,u.size-(D*H));if(typeof(A)=="string"){I=A.substring(D*H,D*H+J)}else{I=x(A,D*H,D*H+J)}L.chunk=D;L.chunks=K}else{J=u.size;I=A}if(s.settings.multipart&&n.multipart&&typeof(I)!=="string"&&z&&n.cantSendBlobInFormData&&n.chunks&&s.settings.chunk_size){z.onload=function(){G(z.result)};z.readAsBinaryString(I)}else{G(I)}}B()}y=c[u.id];if(n.jpgresize&&s.settings.resize&&/\.(png|jpg|jpeg)$/i.test(u.name)){d.call(s,u,s.settings.resize,/\.png$/i.test(u.name)?"image/png":"image/jpeg",function(z){if(z.success){u.size=z.data.length;w(z.data)}else{if(n.chunks){w(y)}else{l(y,w)}}})}else{if(!n.chunks&&n.jpgresize){l(y,w)}else{w(y)}}});p.bind("Destroy",function(s){var u,v,t=k.body,w={inputContainer:s.id+"_html5_container",inputFile:s.id+"_html5",browseButton:s.settings.browse_button,dropElm:s.settings.drop_element};for(u in w){v=k.getElementById(w[u]);if(v){j.removeAllEvents(v,s.id)}}j.removeAllEvents(k.body,s.id);if(s.settings.container){t=k.getElementById(s.settings.container)}t.removeChild(k.getElementById(w.inputContainer))});r({success:true})}});function b(){var q=false,o;function r(t,v){var s=q?0:-8*(v-1),w=0,u;for(u=0;u<v;u++){w|=(o.charCodeAt(t+u)<<Math.abs(s+u*8))}return w}function n(u,s,t){var t=arguments.length===3?t:o.length-s-1;o=o.substr(0,s)+u+o.substr(t+s)}function p(t,u,w){var x="",s=q?0:-8*(w-1),v;for(v=0;v<w;v++){x+=String.fromCharCode((u>>Math.abs(s+v*8))&255)}n(x,t,w)}return{II:function(s){if(s===e){return q}else{q=s}},init:function(s){q=false;o=s},SEGMENT:function(s,u,t){switch(arguments.length){case 1:return o.substr(s,o.length-s-1);case 2:return o.substr(s,u);case 3:n(t,s,u);break;default:return o}},BYTE:function(s){return r(s,1)},SHORT:function(s){return r(s,2)},LONG:function(s,t){if(t===e){return r(s,4)}else{p(s,t,4)}},SLONG:function(s){var t=r(s,4);return(t>2147483647?t-4294967296:t)},STRING:function(s,t){var u="";for(t+=s;s<t;s++){u+=String.fromCharCode(r(s,1))}return u}}}function f(s){var u={65505:{app:"EXIF",name:"APP1",signature:"Exif\0"},65506:{app:"ICC",name:"APP2",signature:"ICC_PROFILE\0"},65517:{app:"IPTC",name:"APP13",signature:"Photoshop 3.0\0"}},t=[],r,n,p=e,q=0,o;r=new b();r.init(s);if(r.SHORT(0)!==65496){return}n=2;o=Math.min(1048576,s.length);while(n<=o){p=r.SHORT(n);if(p>=65488&&p<=65495){n+=2;continue}if(p===65498||p===65497){break}q=r.SHORT(n+2)+2;if(u[p]&&r.STRING(n+4,u[p].signature.length)===u[p].signature){t.push({hex:p,app:u[p].app.toUpperCase(),name:u[p].name.toUpperCase(),start:n,length:q,segment:r.SEGMENT(n,q)})}n+=q}r.init(null);return{headers:t,restore:function(y){r.init(y);var w=new f(y);if(!w.headers){return false}for(var x=w.headers.length;x>0;x--){var z=w.headers[x-1];r.SEGMENT(z.start,z.length,"")}w.purge();n=r.SHORT(2)==65504?4+r.SHORT(4):2;for(var x=0,v=t.length;x<v;x++){r.SEGMENT(n,0,t[x].segment);n+=t[x].length}return r.SEGMENT()},get:function(x){var y=[];for(var w=0,v=t.length;w<v;w++){if(t[w].app===x.toUpperCase()){y.push(t[w].segment)}}return y},set:function(y,x){var z=[];if(typeof(x)==="string"){z.push(x)}else{z=x}for(var w=ii=0,v=t.length;w<v;w++){if(t[w].app===y.toUpperCase()){t[w].segment=z[ii];t[w].length=z[ii].length;ii++}if(ii>=z.length){break}}},purge:function(){t=[];r.init(null)}}}function a(){var q,n,o={},t;q=new b();n={tiff:{274:"Orientation",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",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"}};t={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:{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 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"}};function p(u,C){var w=q.SHORT(u),z,F,G,B,A,v,x,D,E=[],y={};for(z=0;z<w;z++){x=v=u+12*z+2;G=C[q.SHORT(x)];if(G===e){continue}B=q.SHORT(x+=2);A=q.LONG(x+=2);x+=4;E=[];switch(B){case 1:case 7:if(A>4){x=q.LONG(x)+o.tiffHeader}for(F=0;F<A;F++){E[F]=q.BYTE(x+F)}break;case 2:if(A>4){x=q.LONG(x)+o.tiffHeader}y[G]=q.STRING(x,A-1);continue;case 3:if(A>2){x=q.LONG(x)+o.tiffHeader}for(F=0;F<A;F++){E[F]=q.SHORT(x+F*2)}break;case 4:if(A>1){x=q.LONG(x)+o.tiffHeader}for(F=0;F<A;F++){E[F]=q.LONG(x+F*4)}break;case 5:x=q.LONG(x)+o.tiffHeader;for(F=0;F<A;F++){E[F]=q.LONG(x+F*4)/q.LONG(x+F*4+4)}break;case 9:x=q.LONG(x)+o.tiffHeader;for(F=0;F<A;F++){E[F]=q.SLONG(x+F*4)}break;case 10:x=q.LONG(x)+o.tiffHeader;for(F=0;F<A;F++){E[F]=q.SLONG(x+F*4)/q.SLONG(x+F*4+4)}break;default:continue}D=(A==1?E[0]:E);if(t.hasOwnProperty(G)&&typeof D!="object"){y[G]=t[G][D]}else{y[G]=D}}return y}function s(){var v=e,u=o.tiffHeader;q.II(q.SHORT(u)==18761);if(q.SHORT(u+=2)!==42){return false}o.IFD0=o.tiffHeader+q.LONG(u+=2);v=p(o.IFD0,n.tiff);o.exifIFD=("ExifIFDPointer" in v?o.tiffHeader+v.ExifIFDPointer:e);o.gpsIFD=("GPSInfoIFDPointer" in v?o.tiffHeader+v.GPSInfoIFDPointer:e);return true}function r(w,u,z){var B,y,x,A=0;if(typeof(u)==="string"){var v=n[w.toLowerCase()];for(hex in v){if(v[hex]===u){u=hex;break}}}B=o[w.toLowerCase()+"IFD"];y=q.SHORT(B);for(i=0;i<y;i++){x=B+12*i+2;if(q.SHORT(x)==u){A=x+8;break}}if(!A){return false}q.LONG(A,z);return true}return{init:function(u){o={tiffHeader:10};if(u===e||!u.length){return false}q.init(u);if(q.SHORT(0)===65505&&q.STRING(4,5).toUpperCase()==="EXIF\0"){return s()}return false},EXIF:function(){var v;v=p(o.exifIFD,n.exif);if(v.ExifVersion&&j.typeOf(v.ExifVersion)==="array"){for(var w=0,u="";w<v.ExifVersion.length;w++){u+=String.fromCharCode(v.ExifVersion[w])}v.ExifVersion=u}return v},GPS:function(){var u;u=p(o.gpsIFD,n.gps);if(u.GPSVersionID){u.GPSVersionID=u.GPSVersionID.join(".")}return u},setExif:function(u,v){if(u!=="PixelXDimension"&&u!=="PixelYDimension"){return false}return r("exif",u,v)},getBinary:function(){return q.SEGMENT()}}}})(window,document,plupload);
    2  No newline at end of file
     1(function(h,k,j,e){var c={},g;function m(o,p){var n;if("FileReader" in h){n=new FileReader();n.readAsDataURL(o);n.onload=function(){p(n.result)}}else{return p(o.getAsDataURL())}}function l(o,p){var n;if("FileReader" in h){n=new FileReader();n.readAsBinaryString(o);n.onload=function(){p(n.result)}}else{return p(o.getAsBinary())}}function d(r,p,n,v){var q,o,u,s,t=this;m(c[r.id],function(w){q=k.createElement("canvas");q.style.display="none";k.body.appendChild(q);o=q.getContext("2d");u=new Image();u.onerror=u.onabort=function(){v({success:false})};u.onload=function(){var B,x,z,y,A;if(!p.width){p.width=u.width}if(!p.height){p.height=u.height}s=Math.min(p.width/u.width,p.height/u.height);if(s<1||(s===1&&n==="image/jpeg")){B=Math.round(u.width*s);x=Math.round(u.height*s);q.width=B;q.height=x;o.drawImage(u,0,0,B,x);if(n==="image/jpeg"){y=new f(atob(w.substring(w.indexOf("base64,")+7)));if(y.headers&&y.headers.length){A=new a();if(A.init(y.get("exif")[0])){A.setExif("PixelXDimension",B);A.setExif("PixelYDimension",x);y.set("exif",A.getBinary());if(t.hasEventListener("ExifData")){t.trigger("ExifData",r,A.EXIF())}if(t.hasEventListener("GpsData")){t.trigger("GpsData",r,A.GPS())}}}if(p.quality){try{w=q.toDataURL(n,p.quality/100)}catch(C){w=q.toDataURL(n)}}}else{w=q.toDataURL(n)}w=w.substring(w.indexOf("base64,")+7);w=atob(w);if(y&&y.headers&&y.headers.length){w=y.restore(w);y.purge()}q.parentNode.removeChild(q);v({success:true,data:w})}else{v({success:false})}};u.src=w})}j.runtimes.Html5=j.addRuntime("html5",{getFeatures:function(){var s,o,r,q,p,n;o=r=p=n=false;if(h.XMLHttpRequest){s=new XMLHttpRequest();r=!!s.upload;o=!!(s.sendAsBinary||s.upload)}if(o){q=!!(s.sendAsBinary||(h.Uint8Array&&h.ArrayBuffer));p=!!(File&&(File.prototype.getAsDataURL||h.FileReader)&&q);n=!!(File&&(File.prototype.mozSlice||File.prototype.webkitSlice||File.prototype.slice))}var v=navigator.userAgent.match(/Version\/(\d+(?:\.\d+)*)/);v=v.length>1?v[1]:v.substr(v.indexof('/')+1);g=j.ua.safari&&j.ua.windows&&('5.1.2'==v||(/^[0-4](?:\.\d+)*/).test(v));return{html5:o,dragdrop:(function(){var t=k.createElement("div");return("draggable" in t)||("ondragstart" in t&&"ondrop" in t)}()),jpgresize:p,pngresize:p,multipart:p||!!h.FileReader||!!h.FormData,canSendBinary:q,cantSendBlobInFormData:!!(j.ua.gecko&&h.FormData&&h.FileReader&&!FileReader.prototype.readAsArrayBuffer),progress:r,chunks:n,multi_selection:!(j.ua.safari&&j.ua.windows),triggerDialog:(j.ua.gecko&&h.FormData||j.ua.webkit)}},init:function(p,r){var n,q;function o(w){var u,t,v=[],x,s={};for(t=0;t<w.length;t++){u=w[t];if(s[u.name]){continue}s[u.name]=true;x=j.guid();c[x]=u;v.push(new j.File(x,u.fileName||u.name,u.fileSize||u.size))}if(v.length){p.trigger("FilesAdded",v)}}n=this.getFeatures();if(!n.html5){r({success:false});return}p.bind("Init",function(w){var G,F,C=[],v,D,t=w.settings.filters,u,B,s=k.body,E;G=k.createElement("div");G.id=w.id+"_html5_container";j.extend(G.style,{position:"absolute",background:p.settings.shim_bgcolor||"transparent",width:"100px",height:"100px",overflow:"hidden",zIndex:99999,opacity:p.settings.shim_bgcolor?"":0});G.className="plupload html5";if(p.settings.container){s=k.getElementById(p.settings.container);if(j.getStyle(s,"position")==="static"){s.style.position="relative"}}s.appendChild(G);no_type_restriction:for(v=0;v<t.length;v++){u=t[v].extensions.split(/,/);for(D=0;D<u.length;D++){if(u[D]==="*"){C=[];break no_type_restriction}B=j.mimeTypes[u[D]];if(B&&j.inArray(B,C)===-1){C.push(B)}}}G.innerHTML='<input id="'+p.id+'_html5"  style="font-size:999px" type="file" accept="'+C.join(",")+'" '+(p.settings.multi_selection&&p.features.multi_selection?'multiple="multiple"':"")+" />";G.scrollTop=100;E=k.getElementById(p.id+"_html5");if(w.features.triggerDialog){j.extend(E.style,{position:"absolute",width:"100%",height:"100%"})}else{j.extend(E.style,{cssFloat:"right",styleFloat:"right"})}E.onchange=function(){o(this.files);this.value=""};F=k.getElementById(w.settings.browse_button);if(F){var z=w.settings.browse_button_hover,A=w.settings.browse_button_active,x=w.features.triggerDialog?F:G;if(z){j.addEvent(x,"mouseover",function(){j.addClass(F,z)},w.id);j.addEvent(x,"mouseout",function(){j.removeClass(F,z)},w.id)}if(A){j.addEvent(x,"mousedown",function(){j.addClass(F,A)},w.id);j.addEvent(k.body,"mouseup",function(){j.removeClass(F,A)},w.id)}if(w.features.triggerDialog){j.addEvent(F,"click",function(H){var y=k.getElementById(w.id+"_html5");if(y&&!y.disabled){y.click()}H.preventDefault()},w.id)}}});p.bind("PostInit",function(){var s=k.getElementById(p.settings.drop_element);if(s){if(g){j.addEvent(s,"dragenter",function(w){var v,t,u;v=k.getElementById(p.id+"_drop");if(!v){v=k.createElement("input");v.setAttribute("type","file");v.setAttribute("id",p.id+"_drop");v.setAttribute("multiple","multiple");j.addEvent(v,"change",function(){o(this.files);j.removeEvent(v,"change",p.id);v.parentNode.removeChild(v)},p.id);s.appendChild(v)}t=j.getPos(s,k.getElementById(p.settings.container));u=j.getSize(s);if(j.getStyle(s,"position")==="static"){j.extend(s.style,{position:"relative"})}j.extend(v.style,{position:"absolute",display:"block",top:0,left:0,width:u.w+"px",height:u.h+"px",opacity:0})},p.id);return}j.addEvent(s,"dragover",function(t){t.preventDefault()},p.id);j.addEvent(s,"drop",function(u){var t=u.dataTransfer;if(t&&t.files){o(t.files)}u.preventDefault()},p.id)}});p.bind("Refresh",function(s){var t,u,v,x,w;t=k.getElementById(p.settings.browse_button);if(t){u=j.getPos(t,k.getElementById(s.settings.container));v=j.getSize(t);x=k.getElementById(p.id+"_html5_container");j.extend(x.style,{top:u.y+"px",left:u.x+"px",width:v.w+"px",height:v.h+"px"});if(p.features.triggerDialog){if(j.getStyle(t,"position")==="static"){j.extend(t.style,{position:"relative"})}w=parseInt(j.getStyle(t,"z-index"),10);if(isNaN(w)){w=0}j.extend(t.style,{zIndex:w});j.extend(x.style,{zIndex:w-1})}}});p.bind("DisableBrowse",function(s,u){var t=k.getElementById(s.id+"_html5");if(t){t.disabled=u}});p.bind("CancelUpload",function(){if(q&&q.abort){q.abort()}});p.bind("UploadFile",function(s,u){var v=s.settings,y,t;function x(A,D,z){var B;if(File.prototype.slice){try{A.slice();return A.slice(D,z)}catch(C){return A.slice(D,z-D)}}else{if(B=File.prototype.webkitSlice||File.prototype.mozSlice){return B.call(A,D,z)}else{return null}}}function w(A){var D=0,C=0,z=("FileReader" in h)?new FileReader:null;function B(){var I,M,K,L,H,J,F,E=s.settings.url;function G(V){var T=0,N="----pluploadboundary"+j.guid(),O,P="--",U="\r\n",R="";q=new XMLHttpRequest;if(q.upload){q.upload.onprogress=function(W){u.loaded=Math.min(u.size,C+W.loaded-T);s.trigger("UploadProgress",u)}}q.onreadystatechange=function(){var W,Y;if(q.readyState==4&&s.state!==j.STOPPED){try{W=q.status}catch(X){W=0}if(W>=400){s.trigger("Error",{code:j.HTTP_ERROR,message:j.translate("HTTP Error."),file:u,status:W})}else{if(K){Y={chunk:D,chunks:K,response:q.responseText,status:W};s.trigger("ChunkUploaded",u,Y);C+=J;if(Y.cancelled){u.status=j.FAILED;return}u.loaded=Math.min(u.size,(D+1)*H)}else{u.loaded=u.size}s.trigger("UploadProgress",u);V=I=O=R=null;if(!K||++D>=K){u.status=j.DONE;s.trigger("FileUploaded",u,{response:q.responseText,status:W})}else{B()}}}};if(s.settings.multipart&&n.multipart){L.name=u.target_name||u.name;q.open("post",E,true);j.each(s.settings.headers,function(X,W){q.setRequestHeader(W,X)});if(typeof(V)!=="string"&&!!h.FormData){O=new FormData();j.each(j.extend(L,s.settings.multipart_params),function(X,W){O.append(W,X)});O.append(s.settings.file_data_name,V);q.send(O);return}if(typeof(V)==="string"){q.setRequestHeader("Content-Type","multipart/form-data; boundary="+N);j.each(j.extend(L,s.settings.multipart_params),function(X,W){R+=P+N+U+'Content-Disposition: form-data; name="'+W+'"'+U+U;R+=unescape(encodeURIComponent(X))+U});F=j.mimeTypes[u.name.replace(/^.+\.([^.]+)/,"$1").toLowerCase()]||"application/octet-stream";R+=P+N+U+'Content-Disposition: form-data; name="'+s.settings.file_data_name+'"; filename="'+unescape(encodeURIComponent(u.name))+'"'+U+"Content-Type: "+F+U+U+V+U+P+N+P+U;T=R.length-V.length;V=R;if(q.sendAsBinary){q.sendAsBinary(V)}else{if(n.canSendBinary){var S=new Uint8Array(V.length);for(var Q=0;Q<V.length;Q++){S[Q]=(V.charCodeAt(Q)&255)}q.send(S.buffer)}}return}}E=j.buildUrl(s.settings.url,j.extend(L,s.settings.multipart_params));q.open("post",E,true);q.setRequestHeader("Content-Type","application/octet-stream");j.each(s.settings.headers,function(X,W){q.setRequestHeader(W,X)});q.send(V)}if(u.status==j.DONE||u.status==j.FAILED||s.state==j.STOPPED){return}L={name:u.target_name||u.name};if(v.chunk_size&&u.size>v.chunk_size&&(n.chunks||typeof(A)=="string")){H=v.chunk_size;K=Math.ceil(u.size/H);J=Math.min(H,u.size-(D*H));if(typeof(A)=="string"){I=A.substring(D*H,D*H+J)}else{I=x(A,D*H,D*H+J)}L.chunk=D;L.chunks=K}else{J=u.size;I=A}if(s.settings.multipart&&n.multipart&&typeof(I)!=="string"&&z&&n.cantSendBlobInFormData&&n.chunks&&s.settings.chunk_size){z.onload=function(){G(z.result)};z.readAsBinaryString(I)}else{G(I)}}B()}y=c[u.id];if(n.jpgresize&&s.settings.resize&&/\.(png|jpg|jpeg)$/i.test(u.name)){d.call(s,u,s.settings.resize,/\.png$/i.test(u.name)?"image/png":"image/jpeg",function(z){if(z.success){u.size=z.data.length;w(z.data)}else{if(n.chunks){w(y)}else{l(y,w)}}})}else{if(!n.chunks&&n.jpgresize){l(y,w)}else{w(y)}}});p.bind("Destroy",function(s){var u,v,t=k.body,w={inputContainer:s.id+"_html5_container",inputFile:s.id+"_html5",browseButton:s.settings.browse_button,dropElm:s.settings.drop_element};for(u in w){v=k.getElementById(w[u]);if(v){j.removeAllEvents(v,s.id)}}j.removeAllEvents(k.body,s.id);if(s.settings.container){t=k.getElementById(s.settings.container)}t.removeChild(k.getElementById(w.inputContainer))});r({success:true})}});function b(){var q=false,o;function r(t,v){var s=q?0:-8*(v-1),w=0,u;for(u=0;u<v;u++){w|=(o.charCodeAt(t+u)<<Math.abs(s+u*8))}return w}function n(u,s,t){var t=arguments.length===3?t:o.length-s-1;o=o.substr(0,s)+u+o.substr(t+s)}function p(t,u,w){var x="",s=q?0:-8*(w-1),v;for(v=0;v<w;v++){x+=String.fromCharCode((u>>Math.abs(s+v*8))&255)}n(x,t,w)}return{II:function(s){if(s===e){return q}else{q=s}},init:function(s){q=false;o=s},SEGMENT:function(s,u,t){switch(arguments.length){case 1:return o.substr(s,o.length-s-1);case 2:return o.substr(s,u);case 3:n(t,s,u);break;default:return o}},BYTE:function(s){return r(s,1)},SHORT:function(s){return r(s,2)},LONG:function(s,t){if(t===e){return r(s,4)}else{p(s,t,4)}},SLONG:function(s){var t=r(s,4);return(t>2147483647?t-4294967296:t)},STRING:function(s,t){var u="";for(t+=s;s<t;s++){u+=String.fromCharCode(r(s,1))}return u}}}function f(s){var u={65505:{app:"EXIF",name:"APP1",signature:"Exif\0"},65506:{app:"ICC",name:"APP2",signature:"ICC_PROFILE\0"},65517:{app:"IPTC",name:"APP13",signature:"Photoshop 3.0\0"}},t=[],r,n,p=e,q=0,o;r=new b();r.init(s);if(r.SHORT(0)!==65496){return}n=2;o=Math.min(1048576,s.length);while(n<=o){p=r.SHORT(n);if(p>=65488&&p<=65495){n+=2;continue}if(p===65498||p===65497){break}q=r.SHORT(n+2)+2;if(u[p]&&r.STRING(n+4,u[p].signature.length)===u[p].signature){t.push({hex:p,app:u[p].app.toUpperCase(),name:u[p].name.toUpperCase(),start:n,length:q,segment:r.SEGMENT(n,q)})}n+=q}r.init(null);return{headers:t,restore:function(y){r.init(y);var w=new f(y);if(!w.headers){return false}for(var x=w.headers.length;x>0;x--){var z=w.headers[x-1];r.SEGMENT(z.start,z.length,"")}w.purge();n=r.SHORT(2)==65504?4+r.SHORT(4):2;for(var x=0,v=t.length;x<v;x++){r.SEGMENT(n,0,t[x].segment);n+=t[x].length}return r.SEGMENT()},get:function(x){var y=[];for(var w=0,v=t.length;w<v;w++){if(t[w].app===x.toUpperCase()){y.push(t[w].segment)}}return y},set:function(y,x){var z=[];if(typeof(x)==="string"){z.push(x)}else{z=x}for(var w=ii=0,v=t.length;w<v;w++){if(t[w].app===y.toUpperCase()){t[w].segment=z[ii];t[w].length=z[ii].length;ii++}if(ii>=z.length){break}}},purge:function(){t=[];r.init(null)}}}function a(){var q,n,o={},t;q=new b();n={tiff:{274:"Orientation",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",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"}};t={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:{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 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"}};function p(u,C){var w=q.SHORT(u),z,F,G,B,A,v,x,D,E=[],y={};for(z=0;z<w;z++){x=v=u+12*z+2;G=C[q.SHORT(x)];if(G===e){continue}B=q.SHORT(x+=2);A=q.LONG(x+=2);x+=4;E=[];switch(B){case 1:case 7:if(A>4){x=q.LONG(x)+o.tiffHeader}for(F=0;F<A;F++){E[F]=q.BYTE(x+F)}break;case 2:if(A>4){x=q.LONG(x)+o.tiffHeader}y[G]=q.STRING(x,A-1);continue;case 3:if(A>2){x=q.LONG(x)+o.tiffHeader}for(F=0;F<A;F++){E[F]=q.SHORT(x+F*2)}break;case 4:if(A>1){x=q.LONG(x)+o.tiffHeader}for(F=0;F<A;F++){E[F]=q.LONG(x+F*4)}break;case 5:x=q.LONG(x)+o.tiffHeader;for(F=0;F<A;F++){E[F]=q.LONG(x+F*4)/q.LONG(x+F*4+4)}break;case 9:x=q.LONG(x)+o.tiffHeader;for(F=0;F<A;F++){E[F]=q.SLONG(x+F*4)}break;case 10:x=q.LONG(x)+o.tiffHeader;for(F=0;F<A;F++){E[F]=q.SLONG(x+F*4)/q.SLONG(x+F*4+4)}break;default:continue}D=(A==1?E[0]:E);if(t.hasOwnProperty(G)&&typeof D!="object"){y[G]=t[G][D]}else{y[G]=D}}return y}function s(){var v=e,u=o.tiffHeader;q.II(q.SHORT(u)==18761);if(q.SHORT(u+=2)!==42){return false}o.IFD0=o.tiffHeader+q.LONG(u+=2);v=p(o.IFD0,n.tiff);o.exifIFD=("ExifIFDPointer" in v?o.tiffHeader+v.ExifIFDPointer:e);o.gpsIFD=("GPSInfoIFDPointer" in v?o.tiffHeader+v.GPSInfoIFDPointer:e);return true}function r(w,u,z){var B,y,x,A=0;if(typeof(u)==="string"){var v=n[w.toLowerCase()];for(hex in v){if(v[hex]===u){u=hex;break}}}B=o[w.toLowerCase()+"IFD"];y=q.SHORT(B);for(i=0;i<y;i++){x=B+12*i+2;if(q.SHORT(x)==u){A=x+8;break}}if(!A){return false}q.LONG(A,z);return true}return{init:function(u){o={tiffHeader:10};if(u===e||!u.length){return false}q.init(u);if(q.SHORT(0)===65505&&q.STRING(4,5).toUpperCase()==="EXIF\0"){return s()}return false},EXIF:function(){var v;v=p(o.exifIFD,n.exif);if(v.ExifVersion&&j.typeOf(v.ExifVersion)==="array"){for(var w=0,u="";w<v.ExifVersion.length;w++){u+=String.fromCharCode(v.ExifVersion[w])}v.ExifVersion=u}return v},GPS:function(){var u;u=p(o.gpsIFD,n.gps);if(u.GPSVersionID){u.GPSVersionID=u.GPSVersionID.join(".")}return u},setExif:function(u,v){if(u!=="PixelXDimension"&&u!=="PixelYDimension"){return false}return r("exif",u,v)},getBinary:function(){return q.SEGMENT()}}}})(window,document,plupload);
     2 No newline at end of file