WordPress.org

Make WordPress Core

Ticket #22974: plupload.safari.patch

File plupload.safari.patch, 76.0 KB (added by mario-siteground, 16 months 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