Index: /trunk/admin/themes/default/template/photos_add_direct.tpl
===================================================================
--- /trunk/admin/themes/default/template/photos_add_direct.tpl	(revision 28544)
+++ /trunk/admin/themes/default/template/photos_add_direct.tpl	(revision 28545)
@@ -1,9 +1,9 @@
-{if $upload_mode eq 'multiple'}
-{combine_script id='jquery.jgrowl' load='footer' require='jquery' path='themes/default/js/plugins/jquery.jgrowl_minimized.js' }
-{combine_script id='jquery.uploadify' load='footer' require='jquery' path='admin/include/uploadify/jquery.uploadify.v3.0.0.min.js' }
+{combine_script id='jquery.jgrowl' load='footer' require='jquery' path='themes/default/js/plugins/jquery.jgrowl_minimized.js'}
+{combine_script id='jquery.plupload' load='footer' require='jquery' path='themes/default/js/plugins/plupload/plupload.full.min.js'}
+{combine_script id='jquery.plupload.queue' load='footer' require='jquery' path='themes/default/js/plugins/plupload/jquery.plupload.queue/jquery.plupload.queue.min.js'}
 {combine_script id='jquery.ui.progressbar' load='footer'}
+
 {combine_css path="themes/default/js/plugins/jquery.jgrowl.css"}
-{combine_css path="admin/include/uploadify/uploadify.css"}
-{/if}
+{combine_css path="themes/default/js/plugins/plupload/jquery.plupload.queue/css/jquery.plupload.queue.css"}
 
 {include file='include/colorbox.inc.tpl'}
@@ -36,4 +36,10 @@
 jQuery('[data-add-album]').pwgAddAlbum({ cache: categoriesCache });
 
+var uploadify_path = '{$uploadify_path}';
+var upload_id = '{$upload_id}';
+var session_id = '{$session_id}';
+var pwg_token = '{$pwg_token}';
+var buttonText = "{'Select files'|@translate}";
+var sizeLimit = Math.round({$upload_max_filesize} / 1024); /* in KBytes */
 
 {literal}
@@ -113,135 +119,71 @@
   });
 
+	jQuery("#uploader").pluploadQueue({
+		// General settings
+		// runtimes : 'html5,flash,silverlight,html4',
+		runtimes : 'html5',
+
+		// url : '../upload.php',
+		url : 'ws.php?method=pwg.images.upload&format=json',
+
+		// User can upload no more then 20 files in one go (sets multiple_queues to false)
+		max_file_count: 100,
+		
+		chunk_size: '500kb',
+		
+		filters : {
+			// Maximum file size
+			max_file_size : '1000mb',
+			// Specify what files to browse for
+			mime_types: [
+				{title : "Image files", extensions : "jpeg,jpg,gif,png"},
+				{title : "Zip files", extensions : "zip"}
+			]
+		},
+
+		// Rename files by clicking on their titles
+		// rename: true,
+		
+		// Sort files
+		sortable: true,
+
+		// Enable ability to drag'n'drop files onto the widget (currently only HTML5 supports that)
+		dragdrop: true,
+
+    init : {
+      BeforeUpload: function(up, file) {
+        console.log('[BeforeUpload]', file);
+
+        // You can override settings before the file is uploaded
+        // up.setOption('url', 'upload.php?id=' + file.id);
+        up.setOption(
+          'multipart_params',
+          {
+            category : jQuery("select[name=category] option:selected").val(),
+            level : jQuery("select[name=level] option:selected").val(),
+            pwg_token : pwg_token
+            // name : file.name
+          }
+        );
+      },
+
+      FileUploaded: function(up, file, info) {
+        // Called when file has finished uploading
+        console.log('[FileUploaded] File:', file, "Info:", info);
+      
+        var data = jQuery.parseJSON(info.response);
+      
+        jQuery("#uploadedPhotos").parent("fieldset").show();
+      
+        html = '<a href="admin.php?page=photo-'+data.result.image_id+'" target="_blank">';
+        html += '<img src="'+data.result.src+'" class="thumbnail">';
+        html += '</a> ';
+      
+        jQuery("#uploadedPhotos").prepend(html);
+      }
+    }
+	});
+
 {/literal}
-{if $upload_mode eq 'html'}
-{literal}
-  function addUploadBox() {
-    var uploadBox = '<p class="file"><input type="file" size="60" name="image_upload[]"></p>';
-    jQuery(uploadBox).appendTo("#uploadBoxes");
-  }
-
-  addUploadBox();
-
-  jQuery("#addUploadBox A").click(function () {
-    addUploadBox();
-  });
-
-  jQuery("#uploadForm").submit(function() {
-    return checkUploadStart();
-  });
-{/literal}
-{elseif $upload_mode eq 'multiple'}
-
-var uploadify_path = '{$uploadify_path}';
-var upload_id = '{$upload_id}';
-var session_id = '{$session_id}';
-var pwg_token = '{$pwg_token}';
-var buttonText = "{'Select files'|@translate}";
-var sizeLimit = Math.round({$upload_max_filesize} / 1024); /* in KBytes */
-
-{literal}
-  jQuery("#uploadify").uploadify({
-    'uploader'       : uploadify_path + '/uploadify.php',
-    'langFile'       : uploadify_path + '/uploadifyLang_en.js',
-    'swf'            : uploadify_path + '/uploadify.swf',
-    'checkExisting'  : false,
-
-    buttonCursor     : 'pointer',
-    'buttonText'     : buttonText,
-    'width'          : 300,
-    'cancelImage'    : uploadify_path + '/cancel.png',
-    'queueID'        : 'fileQueue',
-    'auto'           : false,
-    'multi'          : true,
-    'fileTypeDesc'   : 'Photo files',
-    'fileTypeExts'   : '*.jpg;*.JPG;*.jpeg;*.JPEG;*.png;*.PNG;*.gif;*.GIF;{/literal}{if $tif_enabled}*.tif;*.TIF;*.tiff;*.TIFF{/if}{literal}',
-    'fileSizeLimit'  : sizeLimit,
-    'progressData'   : 'percentage',
-    requeueErrors   : false,
-    'onSelect'       : function(event,ID,fileObj) {
-      jQuery("#fileQueue").show();
-    },
-    'onQueueComplete'  : function(stats) {
-      jQuery("input[name=submit_upload]").click();
-    },
-    onUploadError: function (file,errorCode,errorMsg,errorString,swfuploadifyQueue) {
-      /* uploadify calls the onUploadError trigger when the user cancels a file! */
-      /* There no error so we skip it to avoid panic.                            */
-      if ("Cancelled" == errorString) {
-        return false;
-      }
-
-      var msg = file.name+', '+errorString;
-
-      /* Let's put the error message in the form to display once the form is     */
-      /* performed, it makes support easier when user can copy/paste the error   */
-      /* thrown.                                                                 */
-      jQuery("#uploadForm").append('<input type="hidden" name="onUploadError[]" value="'+msg+'">');
-
-      jQuery.jGrowl(
-        '<p></p>onUploadError '+msg,
-        {
-          theme:  'error',
-          header: 'ERROR',
-          life:   4000,
-          sticky: false
-        }
-      );
-
-      return false;
-    },
-    onUploadSuccess: function (file,data,response) {
-      var data = jQuery.parseJSON(data);
-      jQuery("#uploadedPhotos").parent("fieldset").show();
-
-      /* Let's display the thumbnail of the uploaded photo, no need to wait the  */
-      /* end of the queue                                                        */
-      jQuery("#uploadedPhotos").prepend('<img src="'+data.thumbnail_url+'" class="thumbnail"> ');
-    },
-    onUploadComplete: function(file,swfuploadifyQueue) {
-      var max = parseInt(jQuery("#progressMax").text());
-      var next = parseInt(jQuery("#progressCurrent").text())+1;
-      var addToProgressBar = 2;
-      if (next <= max) {
-        jQuery("#progressCurrent").text(next);
-      }
-      else {
-        addToProgressBar = 1;
-      }
-
-      jQuery("#progressbar").progressbar({
-        value: jQuery("#progressbar").progressbar("option", "value") + addToProgressBar
-      });
-    }
-  });
-
-  jQuery("input[type=button]").click(function() {
-    if (!checkUploadStart()) {
-      return false;
-    }
-
-    jQuery("#uploadify").uploadifySettings(
-      'postData',
-      {
-        'category_id' : jQuery("select[name=category]").val(),
-        'level' : jQuery("select[name=level] option:selected").val(),
-        'upload_id' : upload_id,
-        'session_id' : session_id,
-        'pwg_token' : pwg_token
-      }
-    );
-
-    nb_files = jQuery(".uploadifyQueueItem").size();
-    jQuery("#progressMax").text(nb_files);
-    jQuery("#progressbar").progressbar({max: nb_files*2, value:1});
-    jQuery("#progressCurrent").text(1);
-
-    jQuery("#uploadProgress").show();
-
-    jQuery("#uploadify").uploadifyUpload();
-  });
-
-{/literal}
-{/if}
 });
 {/footer_script}
@@ -314,4 +256,14 @@
     </fieldset>
 
+    <p class="showFieldset"><a id="showPermissions" href="#">{'Manage Permissions'|@translate}</a></p>
+
+    <fieldset id="permissions" style="display:none">
+      <legend>{'Who can see these photos?'|@translate}</legend>
+
+      <select name="level" size="1">
+        {html_options options=$level_options selected=$level_options_selected}
+      </select>
+    </fieldset>
+
     <fieldset>
       <legend>{'Select files'|@translate}</legend>
@@ -330,43 +282,10 @@
 
 
-
-{if $upload_mode eq 'html'}
-      <div id="uploadBoxes"></div>
-      <div id="addUploadBox">
-        <a href="javascript:">{'+ Add an upload box'|@translate}</a>
-      </div>
-
-    <p id="uploadModeInfos">{'You are using the Browser uploader. Try the <a href="%s">Flash uploader</a> instead.'|@translate:$switch_url}</p>
-
-{elseif $upload_mode eq 'multiple'}
-    <div id="uploadify">You've got a problem with your JavaScript</div> 
-
-    <div id="fileQueue" style="display:none"></div>
-
-    <p id="uploadModeInfos">{'You are using the Flash uploader. Problems? Try the <a href="%s">Browser uploader</a> instead.'|@translate:$switch_url}</p>
-
-{/if}
+	<div id="uploader">
+		<p>Your browser doesn't have Flash, Silverlight or HTML5 support.</p>
+	</div>
+
     </fieldset>
 
-    <p class="showFieldset"><a id="showPermissions" href="#">{'Manage Permissions'|@translate}</a></p>
-
-    <fieldset id="permissions" style="display:none">
-      <legend>{'Who can see these photos?'|@translate}</legend>
-
-      <select name="level" size="1">
-        {html_options options=$level_options selected=$level_options_selected}
-      </select>
-    </fieldset>
-
-{if $upload_mode eq 'html'}
-    <p>
-      <input class="submit" type="submit" name="submit_upload" value="{'Start Upload'|@translate}">
-    </p>
-{elseif $upload_mode eq 'multiple'}
-    <p style="margin-bottom:1em">
-      <input class="submit" type="button" value="{'Start Upload'|@translate}">
-      <input type="submit" name="submit_upload" style="display:none">
-    </p>
-{/if}
 </form>
 
Index: /trunk/admin/themes/default/theme.css
===================================================================
--- /trunk/admin/themes/default/theme.css	(revision 28544)
+++ /trunk/admin/themes/default/theme.css	(revision 28545)
@@ -573,9 +573,4 @@
 #photosAddContent {
   text-align:left;
-}
-
-#photosAddContent FIELDSET {
-  width:650px;
-  margin:0 auto 20px auto;
 }
 
@@ -999,5 +994,5 @@
 p#uploadModeInfos {text-align:left;margin-top:1em;font-size:90%;color:#999;}
 
-#photosAddContent p.showFieldset {text-align:left;margin: 0 auto 10px auto;width: 650px;}
+#photosAddContent p.showFieldset {text-align:left;margin: 1em;}
 
 #uploadProgress {width:650px; margin:10px auto;font-size:90%;}
Index: /trunk/include/ws_functions/pwg.images.php
===================================================================
--- /trunk/include/ws_functions/pwg.images.php	(revision 28544)
+++ /trunk/include/ws_functions/pwg.images.php	(revision 28545)
@@ -1245,4 +1245,144 @@
 /**
  * API method
+ * Adds a image (simple way)
+ * @param mixed[] $params
+ *    @option int[] category
+ *    @option string name (optional)
+ *    @option string author (optional)
+ *    @option string comment (optional)
+ *    @option int level
+ *    @option string|string[] tags
+ *    @option int image_id (optional)
+ */
+function ws_images_upload($params, $service)
+{
+  global $conf;
+
+  if (get_pwg_token() != $params['pwg_token'])
+  {
+    return new PwgError(403, 'Invalid security token');
+  }
+
+  // usleep(100000);
+
+  // if (!isset($_FILES['image']))
+  // {
+  //   return new PwgError(405, 'The image (file) is missing');
+  // }
+  
+  // file_put_contents('/tmp/plupload.log', "[".date('c')."] ".__FUNCTION__."\n\n", FILE_APPEND);
+  // file_put_contents('/tmp/plupload.log', '$_FILES = '.var_export($_FILES, true)."\n", FILE_APPEND);
+  // file_put_contents('/tmp/plupload.log', '$_POST = '.var_export($_POST, true)."\n", FILE_APPEND);
+
+  $upload_dir = $conf['upload_dir'].'/buffer';
+
+  // create the upload directory tree if not exists
+  if (!mkgetdir($upload_dir, MKGETDIR_DEFAULT&~MKGETDIR_DIE_ON_ERROR))
+  {
+    return new PwgError(500, 'error during buffer directory creation');
+  }
+
+  // Get a file name
+  if (isset($_REQUEST["name"]))
+  {
+    $fileName = $_REQUEST["name"];
+  }
+  elseif (!empty($_FILES))
+  {
+    $fileName = $_FILES["file"]["name"];
+  }
+  else
+  {
+    $fileName = uniqid("file_");
+  }
+
+  $filePath = $upload_dir.DIRECTORY_SEPARATOR.$fileName;
+
+  // Chunking might be enabled
+  $chunk = isset($_REQUEST["chunk"]) ? intval($_REQUEST["chunk"]) : 0;
+  $chunks = isset($_REQUEST["chunks"]) ? intval($_REQUEST["chunks"]) : 0;
+
+  file_put_contents('/tmp/plupload.log', "[".date('c')."] ".__FUNCTION__.', '.$fileName.' '.($chunk+1).'/'.$chunks."\n", FILE_APPEND);
+
+  single_insert(
+    'plupload',
+    array(
+      'received_on' => date('c'),
+      'filename' => $fileName,
+      'chunk' => $chunk+1,
+      'chunks' => $chunks,
+      )
+    );
+
+
+  // Open temp file
+  if (!$out = @fopen("{$filePath}.part", $chunks ? "ab" : "wb"))
+  {
+    die('{"jsonrpc" : "2.0", "error" : {"code": 102, "message": "Failed to open output stream."}, "id" : "id"}');
+  }
+
+  if (!empty($_FILES))
+  {
+    if ($_FILES["file"]["error"] || !is_uploaded_file($_FILES["file"]["tmp_name"]))
+    {
+      die('{"jsonrpc" : "2.0", "error" : {"code": 103, "message": "Failed to move uploaded file."}, "id" : "id"}');
+    }
+
+    // Read binary input stream and append it to temp file
+    if (!$in = @fopen($_FILES["file"]["tmp_name"], "rb"))
+    {
+      die('{"jsonrpc" : "2.0", "error" : {"code": 101, "message": "Failed to open input stream."}, "id" : "id"}');
+    }
+  }
+  else
+  {
+    if (!$in = @fopen("php://input", "rb"))
+    {
+      die('{"jsonrpc" : "2.0", "error" : {"code": 101, "message": "Failed to open input stream."}, "id" : "id"}');
+    }
+  }
+
+  while ($buff = fread($in, 4096))
+  {
+    fwrite($out, $buff);
+  }
+
+  @fclose($out);
+  @fclose($in);
+
+  // Check if file has been uploaded
+  if (!$chunks || $chunk == $chunks - 1)
+  {
+    // Strip the temp .part suffix off 
+    rename("{$filePath}.part", $filePath);
+  
+    include_once(PHPWG_ROOT_PATH.'admin/include/functions_upload.inc.php');
+    
+    $image_id = add_uploaded_file(
+      $filePath,
+      $params['name'],
+      $params['category'],
+      $params['level'],
+      null // image_id = not provided, this is a new photo
+      );
+    
+    $query = '
+SELECT
+    id,
+    path
+  FROM '.IMAGES_TABLE.'
+  WHERE id = '.$image_id.'
+;';
+    $image_infos = pwg_db_fetch_assoc(pwg_query($query));
+
+    return array(
+      'image_id' => $image_id,
+      'src' => DerivativeImage::thumb_url($image_infos),
+      );
+  }
+}
+
+/**
+ * API method
  * Check if an image exists by it's name or md5 sum
  * @param mixed[] $params
Index: /trunk/themes/default/js/plugins/plupload/i18n/ar.js
===================================================================
--- /trunk/themes/default/js/plugins/plupload/i18n/ar.js	(revision 28545)
+++ /trunk/themes/default/js/plugins/plupload/i18n/ar.js	(revision 28545)
@@ -0,0 +1,2 @@
+// Arabic (ar)
+plupload.addI18n({"Stop Upload":"أيقاف التحميل","Upload URL might be wrong or doesn't exist.":"عنوان التحميل ربما يكون خاطئ أو  غير متوفر","tb":"تيرابايت","Size":"الحجم","Close":"أغلاق","Init error.":"خطأ في تهيئة","Add files to the upload queue and click the start button.":"أضف ملفات إلى القائمة إنتظار التحميل ثم أضغط على زر البداية","Filename":"أسم الملف","Image format either wrong or not supported.":"صيغة الصورة أما خطاء أو غير مدعومه","Status":"الحالة","HTTP Error.":"خطأ في  برتوكول نقل الملفات","Start Upload":"أبدا التحميل","mb":"ميجابايت","kb":"كيلوبايت","Duplicate file error.":"خطاء في تكرار الملف","File size error.":"خطأ في حجم الملف","N/A":"لا شي","gb":"جيجابايت","Error: Invalid file extension:":"خطاء : أمتداد الملف غير صالح :","Select files":"أختر الملفات","%s already present in the queue.":"%s الملف موجود بالفعل في قائمة الانتظار","File: %s":"ملف: %s","b":"بايت","Uploaded %d/%d files":"تحميل %d/%d ملف","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"العناصر المقبوله لتحميل هي %d ملف في هذا الوقت. الملفات الاضافية أزيلة.","%d files queued":"%d الملفات في قائمة الانتظار","File: %s, size: %d, max file size: %d":"ملف: %s, أقصى حجم للملف: %d, حجم: %d","Drag files here.":"سحب الملف هنا","Runtime ran out of available memory.":"الذاكرة المتوفره أنتهت لمدة التشغيل","File count error.":"خطاء في عد الملفات","File extension error.":"خطأ في أمتداد الملف","Error: File too large:":" خطاء : حجم الملف كبير :","Add Files":"أضف ملفات"});
Index: /trunk/themes/default/js/plugins/plupload/i18n/az.js
===================================================================
--- /trunk/themes/default/js/plugins/plupload/i18n/az.js	(revision 28545)
+++ /trunk/themes/default/js/plugins/plupload/i18n/az.js	(revision 28545)
@@ -0,0 +1,2 @@
+// Azerbaijani (az)
+plupload.addI18n({"Stop Upload":"Yükləməni saxla","Upload URL might be wrong or doesn't exist.":"Yükləmə ünvanı səhvdir və ya mövcud deyil","tb":"tb","Size":"Həcm","Close":"Bağla","Init error.":"Init error.","Add files to the upload queue and click the start button.":"Faylları əlavə edin və yüklə düyməsinə klikləyin.","Filename":"Faylın adı","Image format either wrong or not supported.":"Şəklin formatı uyğun deyil və ya dəstəklənmir.","Status":"Status","HTTP Error.":"HTTP xətası.","Start Upload":"Yüklə","mb":"mb","kb":"kb","Duplicate file error.":"Bu fayl artıq növbədə var.","File size error.":"Fayl həcmi xətası.","N/A":"N/A","gb":"gb","Error: Invalid file extension:":"Xəta: Yanlış fayl uzantısı:","Select files":"Faylları seçin","%s already present in the queue.":"%s artıq növbədə var.","File: %s":"Fayl: %s","b":"b","Uploaded %d/%d files":"%d/%d fayl yüklənib","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Upload element accepts only %d file(s) at a time. Extra files were stripped.","%d files queued":"Növbədə %d fayl var","File: %s, size: %d, max file size: %d":"Fayl: %s, həcm: %d, max fayl həcmi: %d","Drag files here.":"Faylları bura çəkin.","Runtime ran out of available memory.":"Runtime ran out of available memory.","File count error.":"Fayl sayı çox böyükdür.","File extension error.":"Fayl uzantısı xətası.","Error: File too large:":"Xəta:Fayl həcmi çox böyükdür.","Add Files":"Fayl əlavə et"});
Index: /trunk/themes/default/js/plugins/plupload/i18n/bs.js
===================================================================
--- /trunk/themes/default/js/plugins/plupload/i18n/bs.js	(revision 28545)
+++ /trunk/themes/default/js/plugins/plupload/i18n/bs.js	(revision 28545)
@@ -0,0 +1,2 @@
+// Bosnian (bs)
+plupload.addI18n({"Stop Upload":"Prekini dodavanje","Upload URL might be wrong or doesn't exist.":"URL za dodavanje je neispravan ili ne postoji.","tb":"tb","Size":"Veličina","Close":"Zatvori","Init error.":"Inicijalizacijska greška.","Add files to the upload queue and click the start button.":"Dodajte datoteke u red i kliknite na dugme za pokretanje.","Filename":"Naziv datoteke","Image format either wrong or not supported.":"Format slike je neispravan ili nije podržan.","Status":"Status","HTTP Error.":"HTTP greška.","Start Upload":"Započni dodavanje","mb":"mb","kb":"kb","Duplicate file error.":"Dupla datoteka.","File size error.":"Greška u veličini datoteke.","N/A":"N/A","gb":"gb","Error: Invalid file extension:":"Greška! Neispravan ekstenzija datoteke:","Select files":"Odaberite datoteke","%s already present in the queue.":"%s se već nalazi u redu.","File: %s":"Datoteka: %s","b":"b","Uploaded %d/%d files":"Dodano %d/%d datoteka","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Dodavanje trenutno dozvoljava samo %d datoteka istovremeno. Dodatne datoteke su uklonjene.","%d files queued":"%d datoteka čeka","File: %s, size: %d, max file size: %d":"Datoteka: %s, veličina: %d, maksimalna veličina: %d","Drag files here.":"Dovucite datoteke ovdje.","Runtime ran out of available memory.":"Nema više dostupne memorije.","File count error.":"Greška u brojanju datoeka.","File extension error.":"Greška u ekstenziji datoteke.","Error: File too large:":"Greška! Datoteka je prevelika:","Add Files":"Dodaj datoteke"});
Index: /trunk/themes/default/js/plugins/plupload/i18n/cs.js
===================================================================
--- /trunk/themes/default/js/plugins/plupload/i18n/cs.js	(revision 28545)
+++ /trunk/themes/default/js/plugins/plupload/i18n/cs.js	(revision 28545)
@@ -0,0 +1,2 @@
+// Czech (cs)
+plupload.addI18n({"Stop Upload":"Zastavit nahrávání","Upload URL might be wrong or doesn't exist.":"URL uploadu je možná špatně, nebo neexistuje.","tb":"tb","Size":"Velikost","Close":"Zavřít","Init error.":"Chyba inicializace.","Add files to the upload queue and click the start button.":"Přidejte soubory do fronty a pak spusťte nahrávání.","Filename":"Název souboru","Image format either wrong or not supported.":"Špatný, nebo nepodporovaný formát obrázku.","Status":"Stav","HTTP Error.":"Chyba HTTP.","Start Upload":"Spustit nahrávání","mb":"mb","kb":"kb","Duplicate file error.":"Chyba - duplikovaný soubor.","File size error.":"Chyba velikosti souboru.","N/A":"N/A","gb":"gb","Error: Invalid file extension:":"Chyba: Neplatná koncovka souboru:","Select files":"Vyberte soubory","%s already present in the queue.":"%s je již zařazen ve frontě.","File: %s":"Soubor: %s","b":"b","Uploaded %d/%d files":"Nahráno %d/%d souborů","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Upload akceptuje pouze %d soubor(ů) najednou. Další soubory byly odstraněny.","%d files queued":"%d souborů ve frontě","File: %s, size: %d, max file size: %d":"Soubor: %s, velikost: %d, maximální velikost souboru: %d","Drag files here.":"Sem přetáhněte soubory.","Runtime ran out of available memory.":"Běh skriptu přesáhl dostupnou paměť.","File count error.":"Chyba v počtu souborů.","File extension error.":"Chyba přípony souboru.","Error: File too large:":"Chyba: Soubor je příliš veliký:","Add Files":"Přidat soubory"});
Index: /trunk/themes/default/js/plugins/plupload/i18n/cy.js
===================================================================
--- /trunk/themes/default/js/plugins/plupload/i18n/cy.js	(revision 28545)
+++ /trunk/themes/default/js/plugins/plupload/i18n/cy.js	(revision 28545)
@@ -0,0 +1,2 @@
+// Welsh (cy)
+plupload.addI18n({"Stop Upload":"Atal Lanlwytho","Upload URL might be wrong or doesn't exist.":"URL y lanlwythiad ynb anghywir neu ddim yn bodoli.","tb":"tb","Size":"Maint","Close":"Cau","Init error.":"Gwall cych.","Add files to the upload queue and click the start button.":"Ychwanegwch ffeiliau i'r ciw lanlwytho a chlicio'r botwm dechrau.","Filename":"Enw'r ffeil","Image format either wrong or not supported.":"Fformat delwedd yn anghywir neu heb ei gynnal.","Status":"Statws","HTTP Error.":"Gwall HTTP.","Start Upload":"Dechrau Lanlwytho","mb":"mb","kb":"kb","Duplicate file error.":"Gwall ffeil ddyblyg.","File size error.":"Gwall maint ffeil.","N/A":"Dd/A","gb":"gb","Error: Invalid file extension:":"Gwall: estyniad ffeil annilys:","Select files":"Dewis ffeiliau","%s already present in the queue.":"%s yn y ciw yn barod.","File: %s":"Ffeil: %s","b":"b","Uploaded %d/%d files":"Lanlwythwyd  %d/%d ffeil","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Mae'r elfen lanlwytho yn derbyn %d ffeil ar y tro. Caiff ffeiliau ychwanegol eu tynnu.","%d files queued":"%d ffeil mewn ciw","File: %s, size: %d, max file size: %d":"Ffeil: %s, maint: %d, maint mwyaf ffeil: %d","Drag files here.":"Llusgwch ffeiliau yma.","Runtime ran out of available memory.":"Allan o gof.","File count error.":"Gwall cyfri ffeiliau.","File extension error.":"Gwall estyniad ffeil.","Error: File too large:":"Gwall: Ffeil yn rhy fawr:","Add Files":"Ychwanegu Ffeiliau"});
Index: /trunk/themes/default/js/plugins/plupload/i18n/da.js
===================================================================
--- /trunk/themes/default/js/plugins/plupload/i18n/da.js	(revision 28545)
+++ /trunk/themes/default/js/plugins/plupload/i18n/da.js	(revision 28545)
@@ -0,0 +1,2 @@
+// Danish (da)
+plupload.addI18n({"Stop Upload":"Stop upload","Upload URL might be wrong or doesn't exist.":"Upload URL kan være forkert eller ikke eksisterende.","tb":"tb","Size":"Størrelse","Close":"Luk","Init error.":"Opstarts fejl.","Add files to the upload queue and click the start button.":"Tilføj filer til køen og klik Start upload knappen.","Filename":"Filnavn","Image format either wrong or not supported.":"Billede format er enten forkert eller ikke understøttet.","Status":"Status","HTTP Error.":"HTTP fejl.","Start Upload":"Start upload","mb":"mb","kb":"kb","Duplicate file error.":"Filen findes allerede.","File size error.":"Filstørrelse fejl.","N/A":"N/A","gb":"gb","Error: Invalid file extension:":"Fejl: Ugyldigt fil format:","Select files":"Vælg filer","%s already present in the queue.":"%s findes allerede i køen.","File: %s":"Fil: %s","b":"b","Uploaded %d/%d files":"Uploaded %d/%d filer","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Upload accepterer kun %d fil(er) af gangen. Ekstra filer blev skippet.","%d files queued":"%d filer i kø","File: %s, size: %d, max file size: %d":"Fil: %s, størrelse: %d, maks. filstørrelse: %d","Drag files here.":"Træk filer her.","Runtime ran out of available memory.":"Runtime mangler tilgængelige hukommelse.","File count error.":"Fil antal fejl.","File extension error.":"Fil format fejl.","Error: File too large:":"Fejl: Filen er for stor:","Add Files":"Tilføj filer"});
Index: /trunk/themes/default/js/plugins/plupload/i18n/de.js
===================================================================
--- /trunk/themes/default/js/plugins/plupload/i18n/de.js	(revision 28545)
+++ /trunk/themes/default/js/plugins/plupload/i18n/de.js	(revision 28545)
@@ -0,0 +1,2 @@
+// German (de)
+plupload.addI18n({"Stop Upload":"Hochladen stoppen","Upload URL might be wrong or doesn't exist.":"Upload-URL ist falsch oder existiert nicht.","tb":"TB","Size":"Größe","Close":"Schließen","Init error.":"Initialisierungsfehler","Add files to the upload queue and click the start button.":"Dateien hinzufügen und auf 'Hochladen' klicken.","Filename":"Dateiname","Image format either wrong or not supported.":"Bildformat falsch oder nicht unterstützt.","Status":"Status","HTTP Error.":"HTTP-Fehler","Start Upload":"Hochladen beginnen","mb":"MB","kb":"KB","Duplicate file error.":"Datei bereits hochgeladen","File size error.":"Fehler bei Dateigröße","N/A":"Nicht verfügbar","gb":"GB","Error: Invalid file extension:":"Fehler: Ungültige Dateiendung:","Select files":"Dateien auswählen","%s already present in the queue.":"%s ist bereits in der Warteschlange","File: %s":"Datei: %s","b":"B","Uploaded %d/%d files":"%d/%d Dateien wurden hochgeladen","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Pro Durchgang können nur %d Datei(en) akzeptiert werden. Überzählige Dateien wurden ignoriert.","%d files queued":"%d Dateien in der Warteschlange","File: %s, size: %d, max file size: %d":"Datei: %s, Größe: %d, maximale Dateigröße: %d","Drag files here.":"Dateien hier hin ziehen.","Runtime ran out of available memory.":"Nicht genügend Speicher verfügbar.","File count error.":"Fehlerhafte Dateianzahl.","File extension error.":"Fehler bei Dateiendung","Error: File too large:":"Fehler: Datei zu groß:","Add Files":"Dateien hinzufügen"});
Index: /trunk/themes/default/js/plugins/plupload/i18n/el.js
===================================================================
--- /trunk/themes/default/js/plugins/plupload/i18n/el.js	(revision 28545)
+++ /trunk/themes/default/js/plugins/plupload/i18n/el.js	(revision 28545)
@@ -0,0 +1,2 @@
+// Greek (el)
+plupload.addI18n({"Stop Upload":"Ακύρωση Μεταφόρτωσης","Upload URL might be wrong or doesn't exist.":"Το URL μεταφόρτωσης είναι λάθος ή δεν υπάρχει.","tb":"tb","Size":"Μέγεθος","Close":"Κλείσιμο","Init error.":"Σφάλμα αρχικοποίησης.","Add files to the upload queue and click the start button.":"Προσθέστε αρχεία στην ουρά μεταφόρτωσης και πατήστε το κουμπί εκκίνησης.","Filename":"Όνομα Αρχείου","Image format either wrong or not supported.":"Ο τύπος εικόνας είναι λάθος ή δεν υποστηρίζεται.","Status":"Κατάσταση","HTTP Error.":"Σφάλμα HTTP.","Start Upload":"Εκκίνηση Μεταφόρτωσης","mb":"mb","kb":"kb","Duplicate file error.":"Το αρχείο έχει ξαναπροστεθεί.","File size error.":"Σφάλμα με το μέγεθος του αρχείου.","N/A":"Δεν ισχύει","gb":"gb","Error: Invalid file extension:":"Σφάλμα: Μη έγκυρος τύπος αρχείου:","Select files":"Επιλέξτε Αρχεία","%s already present in the queue.":"Το «%s» βρίσκεται ήδη στην ουρά.","File: %s":"Αρχείο: %s","b":"b","Uploaded %d/%d files":"Μεταφορτώθηκαν %d/%d αρχεία","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Μπορείτε να μεταφορτώσετε μεχρι και %d αρχείο/α κάθε φορά. Τα επιπλέον αρχεία αφαιρέθηκαν.","%d files queued":"%d αρχεία στην ουρά","File: %s, size: %d, max file size: %d":"Αρχείο: %s, μέγεθος: %d, μέγιστο μέγεθος αρχείου: %d","Drag files here.":"Σύρετε αρχεία εδώ","Runtime ran out of available memory.":"Δεν υπάρχει αρκετή διαθέσιμη μνήμη.","File count error.":"Σφάλμα με τον αριθμό αρχείων.","File extension error.":"Σφάλμα με τον τύπο αρχείου.","Error: File too large:":"Σφάλμα: Πολύ μεγάλο αρχείο:","Add Files":"Προσθέστε Αρχεία"});
Index: /trunk/themes/default/js/plugins/plupload/i18n/en.js
===================================================================
--- /trunk/themes/default/js/plugins/plupload/i18n/en.js	(revision 28545)
+++ /trunk/themes/default/js/plugins/plupload/i18n/en.js	(revision 28545)
@@ -0,0 +1,2 @@
+// English (en)
+plupload.addI18n({"Stop Upload":"Stop Upload","Upload URL might be wrong or doesn't exist.":"Upload URL might be wrong or doesn't exist.","tb":"tb","Size":"Size","Close":"Close","Init error.":"Init error.","Add files to the upload queue and click the start button.":"Add files to the upload queue and click the start button.","Filename":"Filename","Image format either wrong or not supported.":"Image format either wrong or not supported.","Status":"Status","HTTP Error.":"HTTP Error.","Start Upload":"Start Upload","mb":"mb","kb":"kb","Duplicate file error.":"Duplicate file error.","File size error.":"File size error.","N/A":"N/A","gb":"gb","Error: Invalid file extension:":"Error: Invalid file extension:","Select files":"Select files","%s already present in the queue.":"%s already present in the queue.","File: %s":"File: %s","b":"b","Uploaded %d/%d files":"Uploaded %d/%d files","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Upload element accepts only %d file(s) at a time. Extra files were stripped.","%d files queued":"%d files queued","File: %s, size: %d, max file size: %d":"File: %s, size: %d, max file size: %d","Drag files here.":"Drag files here.","Runtime ran out of available memory.":"Runtime ran out of available memory.","File count error.":"File count error.","File extension error.":"File extension error.","Error: File too large:":"Error: File too large:","Add Files":"Add Files"});
Index: /trunk/themes/default/js/plugins/plupload/i18n/es.js
===================================================================
--- /trunk/themes/default/js/plugins/plupload/i18n/es.js	(revision 28545)
+++ /trunk/themes/default/js/plugins/plupload/i18n/es.js	(revision 28545)
@@ -0,0 +1,2 @@
+// Spanish (es)
+plupload.addI18n({"Stop Upload":"Detener Subida.","Upload URL might be wrong or doesn't exist.":"URL de carga inexistente.","tb":"TB","Size":"Tamaño","Close":"Cerrar","Init error.":"Error de inicialización.","Add files to the upload queue and click the start button.":"Agregue archivos a la lista de subida y pulse clic en el botón de Iniciar carga","Filename":"Nombre de archivo","Image format either wrong or not supported.":"Formato de imagen no soportada.","Status":"Estado","HTTP Error.":"Error de HTTP.","Start Upload":"Iniciar carga","mb":"MB","kb":"KB","Duplicate file error.":"Error, archivo duplicado","File size error.":"Error de tamaño de archivo.","N/A":"No disponible","gb":"GB","Error: Invalid file extension:":"Error: Extensión de archivo inválida:","Select files":"Elija archivos","%s already present in the queue.":"%s ya se encuentra en la lista.","File: %s":"Archivo: %s","b":"B","Uploaded %d/%d files":"Subidos %d/%d archivos","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Se aceptan sólo %d archivo(s) al tiempo. Más, no se tienen en cuenta.","%d files queued":"%d archivos en cola.","File: %s, size: %d, max file size: %d":"Archivo: %s, tamaño: %d, tamaño máximo de archivo: %d","Drag files here.":"Arrastre archivos aquí","Runtime ran out of available memory.":"No hay memoria disponible.","File count error.":"Error en contador de archivos.","File extension error.":"Error de extensión de archivo.","Error: File too large:":"Error: archivo demasiado grande:","Add Files":"Agregar archivos"});
Index: /trunk/themes/default/js/plugins/plupload/i18n/et.js
===================================================================
--- /trunk/themes/default/js/plugins/plupload/i18n/et.js	(revision 28545)
+++ /trunk/themes/default/js/plugins/plupload/i18n/et.js	(revision 28545)
@@ -0,0 +1,2 @@
+// Estonian (et)
+plupload.addI18n({"Stop Upload":"Stop Upload","Upload URL might be wrong or doesn't exist.":"Üleslaadimise URL võib olla vale või seda pole.","tb":"","Size":"Suurus","Close":"Sulge","Init error.":"Lähtestamise viga.","Add files to the upload queue and click the start button.":"Lisa failid üleslaadimise järjekorda ja klõpsa alustamise nupule.","Filename":"Failinimi","Image format either wrong or not supported.":"Image format either wrong or not supported.","Status":"Olek","HTTP Error.":"HTTP ühenduse viga.","Start Upload":"Start Upload","mb":"","kb":"","Duplicate file error.":"","File size error.":"Failisuuruse viga.","N/A":"N/A","gb":"","Error: Invalid file extension:":"Error: Invalid file extension:","Select files":"Vali faile","%s already present in the queue.":"","File: %s":"Fail: %s","b":"","Uploaded %d/%d files":"Üles laaditud %d/%d","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Üleslaadimise element saab vastu võtta ainult %d faili ühe korraga. Ülejäänud failid jäetakse laadimata.","%d files queued":"Järjekorras on %d faili","File: %s, size: %d, max file size: %d":"","Drag files here.":"Lohista failid siia.","Runtime ran out of available memory.":"Runtime ran out of available memory.","File count error.":"Failide arvu viga.","File extension error.":"Faililaiendi viga.","Error: File too large:":"Error: File too large:","Add Files":"Add Files"});
Index: /trunk/themes/default/js/plugins/plupload/i18n/fa.js
===================================================================
--- /trunk/themes/default/js/plugins/plupload/i18n/fa.js	(revision 28545)
+++ /trunk/themes/default/js/plugins/plupload/i18n/fa.js	(revision 28545)
@@ -0,0 +1,2 @@
+// Persian (fa)
+plupload.addI18n({"Stop Upload":"توقف انتقال","Upload URL might be wrong or doesn't exist.":"Upload URL might be wrong or doesn't exist.","tb":"ترابایت","Size":"سایز","Close":"بستن","Init error.":"خطا در استارت اسکریپت","Add files to the upload queue and click the start button.":"اضافه کنید فایل ها را به صف آپلود و دکمه شروع را کلیک کنید.","Filename":"نام فایل","Image format either wrong or not supported.":"Image format either wrong or not supported.","Status":"وضعیت","HTTP Error.":"HTTP خطای","Start Upload":"شروع انتقال","mb":"مگابایت","kb":"کیلوبایت","Duplicate file error.":"خطای فایل تکراری","File size error.":"خطای سایز فایل","N/A":"N/A","gb":"گیگابایت","Error: Invalid file extension:":"Error: Invalid file extension:","Select files":"انتخاب فایل","%s already present in the queue.":"%s در لیست آپلود وجود دارد.","File: %s":" فایل ها : %s","b":"بایت","Uploaded %d/%d files":"منتقل شد %d/%d از فایلها","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"عنصر بارگذار فقط %d فایل رو در یک زمان  می پذیرد. سایر فایل ها مجرد از این موضوع هستند.","%d files queued":"%d فایل در صف","File: %s, size: %d, max file size: %d":"فایل: %s, اندازه: %d, محدودیت اندازه فایل: %d","Drag files here.":"بکشید فایل ها رو به اینجا","Runtime ran out of available memory.":"Runtime ran out of available memory.","File count error.":"خطای تعداد فایل","File extension error.":"خطا پیشوند فایل","Error: File too large:":"Error: File too large:","Add Files":"افزودن فایل"});
Index: /trunk/themes/default/js/plugins/plupload/i18n/fi.js
===================================================================
--- /trunk/themes/default/js/plugins/plupload/i18n/fi.js	(revision 28545)
+++ /trunk/themes/default/js/plugins/plupload/i18n/fi.js	(revision 28545)
@@ -0,0 +1,2 @@
+// Finnish (fi)
+plupload.addI18n({"Stop Upload":"Pysäytä lähetys","Upload URL might be wrong or doesn't exist.":"Lähetyksen URL-osoite saattaa olla väärä tai sitä ei ole olemassa.","tb":"TB","Size":"Koko","Close":"Sulje","Init error.":"Init virhe.","Add files to the upload queue and click the start button.":"Lisää tiedostoja lähetysjonoon ja klikkaa aloita-nappia.","Filename":"Tiedostonimi","Image format either wrong or not supported.":"Kuvaformaatti on joko väärä tai ei tuettu.","Status":"Tila","HTTP Error.":"HTTP-virhe.","Start Upload":"Aloita lähetys","mb":"MB","kb":"kB","Duplicate file error.":"Tuplatiedostovirhe.","File size error.":"Tiedostokokovirhe.","N/A":"N/A","gb":"GB","Error: Invalid file extension:":"Virhe: Virheellinen tiedostopääte:","Select files":"Valitse tiedostoja","%s already present in the queue.":"%s on jo jonossa.","File: %s":"Tiedosto: %s","b":"B","Uploaded %d/%d files":"Lähetetty %d/%d tiedostoa","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Vain %d tiedosto(a) voidaan lähettää kerralla. Ylimääräiset tiedostot ohitettiin.","%d files queued":"%d tiedostoa jonossa","File: %s, size: %d, max file size: %d":"Tiedosto: %s, koko: %d, suurin sallittu tiedostokoko: %d","Drag files here.":"Raahaa tiedostot tähän.","Runtime ran out of available memory.":"Toiminnon käytettävissä oleva muisti loppui kesken.","File count error.":"Tiedostolaskentavirhe.","File extension error.":"Tiedostopäätevirhe.","Error: File too large:":"Virhe: Liian suuri tiedosto:","Add Files":"Lisää tiedostoja"});
Index: /trunk/themes/default/js/plugins/plupload/i18n/fr.js
===================================================================
--- /trunk/themes/default/js/plugins/plupload/i18n/fr.js	(revision 28545)
+++ /trunk/themes/default/js/plugins/plupload/i18n/fr.js	(revision 28545)
@@ -0,0 +1,2 @@
+// French (fr)
+plupload.addI18n({"Stop Upload":"Arrêter l'envoi.","Upload URL might be wrong or doesn't exist.":"L'URL d'envoi est soit erronée soit n'existe pas.","tb":"To","Size":"Taille","Close":"Fermer","Init error.":"Erreur d'initialisation.","Add files to the upload queue and click the start button.":"Ajoutez des fichiers à la file d'attente de téléchargement et appuyez sur le bouton 'Démarrer l'envoi'","Filename":"Nom du fichier","Image format either wrong or not supported.":"Le format d'image est soit erroné soit pas géré.","Status":"État","HTTP Error.":"Erreur HTTP.","Start Upload":"Démarrer l'envoi","mb":"Mo","kb":"Ko","Duplicate file error.":"Erreur: Fichier déjà sélectionné.","File size error.":"Erreur de taille de fichier.","N/A":"Non applicable","gb":"Go","Error: Invalid file extension:":"Erreur: Extension de fichier non valide:","Select files":"Sélectionnez les fichiers","%s already present in the queue.":"%s déjà présent dans la file d'attente.","File: %s":"Fichier: %s","b":"o","Uploaded %d/%d files":"%d fichiers sur %d ont été envoyés","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Que %d fichier(s) peuvent être envoyé(s) à la fois. Les fichiers supplémentaires ont été ignorés.","%d files queued":"%d fichiers en attente","File: %s, size: %d, max file size: %d":"Fichier: %s, taille: %d, taille max. d'un fichier: %d","Drag files here.":"Déposez les fichiers ici.","Runtime ran out of available memory.":"Le traitement a manqué de mémoire disponible.","File count error.":"Erreur: Nombre de fichiers.","File extension error.":"Erreur d'extension de fichier","Error: File too large:":"Erreur: Fichier trop volumineux:","Add Files":"Ajouter des fichiers"});
Index: /trunk/themes/default/js/plugins/plupload/i18n/he.js
===================================================================
--- /trunk/themes/default/js/plugins/plupload/i18n/he.js	(revision 28545)
+++ /trunk/themes/default/js/plugins/plupload/i18n/he.js	(revision 28545)
@@ -0,0 +1,2 @@
+// Hebrew (he)
+plupload.addI18n({"Stop Upload":"בטל העלאה","Upload URL might be wrong or doesn't exist.":"כתובת URL שגויה או לא קיימת.","tb":"tb","Size":"גודל","Close":"סגור","Init error.":"שגיאת איתחול","Add files to the upload queue and click the start button.":"הוסף קבצים לרשימה ולחץ על כפתור שליחה להתחלת פעולות העלאה","Filename":"שם קובץ","Image format either wrong or not supported.":"תמונה פגומה או סוג תמונה לא נתמך","Status":"אחוז","HTTP Error.":"שגיאת פרוטוקול","Start Upload":"שליחה","mb":"MB","kb":"KB","Duplicate file error.":"קובץ כפול","File size error.":"גודל קובץ חורג מהמותר","N/A":"שגיאה","gb":"GB","Error: Invalid file extension:":"שגיאה: סוג קובץ לא נתמך:","Select files":"בחר קבצים","%s already present in the queue.":"%sקובץ נמצא כבר ברשימת הקבצים.","File: %s":"קובץ: %s","b":"B","Uploaded %d/%d files":"מעלה: %d/%d","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"אלמנטי ההעלאה מקבלים רק %d קובץ(ים) בפעם אחת. קבצים נוספים הוסרו.","%d files queued":"%d קבצים נותרו","File: %s, size: %d, max file size: %d":"קובץ: %s, גודל: %d, גודל מקסימלי: %d","Drag files here.":"גרור קבצים לכאן","Runtime ran out of available memory.":"שגיאת מחסור בזיכרון","File count error.":"שגיאת מספר קבצים","File extension error.":"קובץ זה לא נתמך","Error: File too large:":"שגיאה: קובץ חורג מהגודל המותר:","Add Files":"הוסף קבצים"});
Index: /trunk/themes/default/js/plugins/plupload/i18n/hr.js
===================================================================
--- /trunk/themes/default/js/plugins/plupload/i18n/hr.js	(revision 28545)
+++ /trunk/themes/default/js/plugins/plupload/i18n/hr.js	(revision 28545)
@@ -0,0 +1,2 @@
+// Croatian (hr)
+plupload.addI18n({"Stop Upload":"Zaustavi upload.","Upload URL might be wrong or doesn't exist.":"Upload URL might be wrong or doesn't exist.","tb":"tb","Size":"Veličina","Close":"Zatvori","Init error.":"Greška inicijalizacije.","Add files to the upload queue and click the start button.":"Dodajte datoteke u listu i kliknite Upload.","Filename":"Ime datoteke","Image format either wrong or not supported.":"Image format either wrong or not supported.","Status":"Status","HTTP Error.":"HTTP greška.","Start Upload":"Pokreni upload.","mb":"mb","kb":"kb","Duplicate file error.":"Pogreška dvostruke datoteke.","File size error.":"Greška veličine datoteke.","N/A":"N/A","gb":"gb","Error: Invalid file extension:":"Pogreška: Nevažeći nastavak datoteke:","Select files":"Odaberite datoteke:","%s already present in the queue.":"%s  je već prisutan  u listi čekanja.","File: %s":"Datoteka: %s","b":"b","Uploaded %d/%d files":"Uploadano %d/%d datoteka","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Upload element accepts only %d file(s) at a time. Extra files were stripped.","%d files queued":"%d datoteka na čekanju.","File: %s, size: %d, max file size: %d":"Datoteka: %s, veličina: %d, maksimalna veličina: %d","Drag files here.":"Dovucite datoteke ovdje","Runtime ran out of available memory.":"Runtime aplikaciji  je ponestalo memorije.","File count error.":"Pogreška u broju datoteka.","File extension error.":"Pogreška u nastavku datoteke.","Error: File too large:":"Pogreška: Datoteka je prevelika:","Add Files":"Dodaj datoteke"});
Index: /trunk/themes/default/js/plugins/plupload/i18n/hu.js
===================================================================
--- /trunk/themes/default/js/plugins/plupload/i18n/hu.js	(revision 28545)
+++ /trunk/themes/default/js/plugins/plupload/i18n/hu.js	(revision 28545)
@@ -0,0 +1,2 @@
+// Hungarian (hu)
+plupload.addI18n({"Stop Upload":"Feltöltés leállítása","Upload URL might be wrong or doesn't exist.":"A feltöltő URL hibás vagy nem létezik.","tb":"TB","Size":"Méret","Close":"Bezárás","Init error.":"Init hiba.","Add files to the upload queue and click the start button.":"A fájlok feltöltési sorhoz való hozzáadása után az Indítás gombra kell kattintani.","Filename":"Fájlnév","Image format either wrong or not supported.":"Rossz vagy nem támogatott képformátum.","Status":"Állapot","HTTP Error.":"HTTP-hiba.","Start Upload":"Feltöltés indítása","mb":"MB","kb":"kB","Duplicate file error.":"Duplikáltfájl-hiba.","File size error.":"Hibás fájlméret.","N/A":"Nem elérhető","gb":"GB","Error: Invalid file extension:":"Hiba: érvénytelen fájlkiterjesztés:","Select files":"Fájlok kiválasztása","%s already present in the queue.":"%s már szerepel a listában.","File: %s":"Fájl: %s","b":"b","Uploaded %d/%d files":"Feltöltött fájlok: %d/%d","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"A feltöltés egyszerre csak %d fájlt fogad el, a többi fájl nem lesz feltöltve.","%d files queued":"%d fájl sorbaállítva","File: %s, size: %d, max file size: %d":"Fájl: %s, méret: %d, legnagyobb fájlméret: %d","Drag files here.":"Ide lehet húzni a fájlokat.","Runtime ran out of available memory.":"Futásidőben elfogyott a rendelkezésre álló memória.","File count error.":"A fájlok számával kapcsolatos hiba.","File extension error.":"Hibás fájlkiterjesztés.","Error: File too large:":"Hiba: a fájl túl nagy:","Add Files":"Fájlok hozzáadása"});
Index: /trunk/themes/default/js/plugins/plupload/i18n/hy.js
===================================================================
--- /trunk/themes/default/js/plugins/plupload/i18n/hy.js	(revision 28545)
+++ /trunk/themes/default/js/plugins/plupload/i18n/hy.js	(revision 28545)
@@ -0,0 +1,2 @@
+// Armenian (hy)
+plupload.addI18n({"Stop Upload":"Կանգնեցնել","Upload URL might be wrong or doesn't exist.":"Ավեցաված URL-ը սխալ է կամ գոյություն չունի։","tb":"տբ","Size":"Չափ","Close":"Փակել","Init error.":"Ստեղծման սխալ","Add files to the upload queue and click the start button.":"Ավելացրեք ֆայլեր ցուցակում և սեղմեք \"Վերբեռնել\"։","Filename":"Ֆայլի անուն","Image format either wrong or not supported.":"Նկարի ֆորմատը սխալ է կամ չի ընդունվում։","Status":"","HTTP Error.":"HTTP սխալ","Start Upload":"Վերբեռնել","mb":"մբ","kb":"կբ","Duplicate file error.":"Ֆայլի կրկնման սխալ","File size error.":"Ֆայլի չափի սխալ","N/A":"N/A","gb":"գբ","Error: Invalid file extension:":"Սխալ։ Ֆայլի ընդլայնումը սխալ է։","Select files":"Ընտրեք ֆայլերը","%s already present in the queue.":"%s ֆայլը արդեն ավելացված է ցուցակում.","File: %s":"Ֆայլ: %s","b":"բ","Uploaded %d/%d files":"Վերբեռնվել են %d/%d ֆայլերը","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"","%d files queued":"ցուցակում կա %d ֆայլ","File: %s, size: %d, max file size: %d":"Ֆայլ: %s, չափ: %d, ֆայլի մաքսիմում չափ: %d","Drag files here.":"Տեղափոխեք ֆայլերը այստեղ","Runtime ran out of available memory.":"","File count error.":"Ֆայլերի քանակի սխալ","File extension error.":"Ֆայլի ընդլայնման սխալ","Error: File too large:":"Սխալ։ Ֆայլի չափը մեծ է։","Add Files":"Ավելացնել ֆայլեր"});
Index: /trunk/themes/default/js/plugins/plupload/i18n/id.js
===================================================================
--- /trunk/themes/default/js/plugins/plupload/i18n/id.js	(revision 28545)
+++ /trunk/themes/default/js/plugins/plupload/i18n/id.js	(revision 28545)
@@ -0,0 +1,2 @@
+// Indonesian (id)
+plupload.addI18n({"Stop Upload":"Hentikan Upload","Upload URL might be wrong or doesn't exist.":"Alamat URL untuk upload tidak benar atau tidak ada","tb":"tb","Size":"Ukuran","Close":"Tutup","Init error.":"Kesalahan pada Init","Add files to the upload queue and click the start button.":"Tambahkan file kedalam antrian upload dan klik tombol Mulai","Filename":"Nama File","Image format either wrong or not supported.":"Kesalahan pada jenis gambar atau jenis file tidak didukung","Status":"Status","HTTP Error.":"HTTP Bermasalah","Start Upload":"Mulai Upload","mb":"mb","kb":"kb","Duplicate file error.":"Terjadi duplikasi file","File size error.":"Kesalahan pada ukuran file","N/A":"N/A","gb":"gb","Error: Invalid file extension:":"Kesalahan: Ekstensi file tidak dikenal","Select files":"Pilih file","%s already present in the queue.":"%s sudah ada dalam daftar antrian","File: %s":"File: %s","b":"b","Uploaded %d/%d files":"File terupload %d/%d","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Tempat untuk upload hanya menerima %d file(s) dalam setiap upload. File lainnya tidak akan disertakan","%d files queued":"%d file dalam antrian","File: %s, size: %d, max file size: %d":"File: %s, ukuran: %d, maksimum ukuran file: %d","Drag files here.":"Tarik file kesini","Runtime ran out of available memory.":"Tidak cukup memori","File count error.":"Kesalahan pada jumlah file","File extension error.":"Kesalahan pada ekstensi file","Error: File too large:":"Kesalahan: File terlalu besar","Add Files":"Tambah File"});
Index: /trunk/themes/default/js/plugins/plupload/i18n/it.js
===================================================================
--- /trunk/themes/default/js/plugins/plupload/i18n/it.js	(revision 28545)
+++ /trunk/themes/default/js/plugins/plupload/i18n/it.js	(revision 28545)
@@ -0,0 +1,2 @@
+// Italian (it)
+plupload.addI18n({"Stop Upload":"Ferma Upload","Upload URL might be wrong or doesn't exist.":"URL di Upload errata o non esistente","tb":"tb","Size":"Dimensione","Close":"Chiudi","Init error.":"Errore inizializzazione.","Add files to the upload queue and click the start button.":"Aggiungi i file alla coda di caricamento e clicca il pulsante di avvio.","Filename":"Nome file","Image format either wrong or not supported.":"Formato immagine errato o non supportato.","Status":"Stato","HTTP Error.":"Errore HTTP.","Start Upload":"Inizia Upload","mb":"mb","kb":"kb","Duplicate file error.":"Errore file duplicato.","File size error.":"Errore dimensione file.","N/A":"N/D","gb":"gb","Error: Invalid file extension:":"Errore: Estensione file non valida:","Select files":"Seleziona i files","%s already present in the queue.":"%s già presente nella coda.","File: %s":"File: %s","b":"byte","Uploaded %d/%d files":"Caricati %d/%d file","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Upload element accepts only %d file(s) at a time. Extra files were stripped.","%d files queued":"%d file in coda","File: %s, size: %d, max file size: %d":"File: %s, dimensione: %d, dimensione max file: %d","Drag files here.":"Trascina i files qui.","Runtime ran out of available memory.":"Runtime ha esaurito la memoria disponibile.","File count error.":"File count error.","File extension error.":"Errore estensione file.","Error: File too large:":"Errore: File troppo grande:","Add Files":"Aggiungi file"});
Index: /trunk/themes/default/js/plugins/plupload/i18n/ja.js
===================================================================
--- /trunk/themes/default/js/plugins/plupload/i18n/ja.js	(revision 28545)
+++ /trunk/themes/default/js/plugins/plupload/i18n/ja.js	(revision 28545)
@@ -0,0 +1,2 @@
+// Japanese (ja)
+plupload.addI18n({"Stop Upload":"アップロード停止","Upload URL might be wrong or doesn't exist.":"アップロード先の URL が存在しません","tb":"TB","Size":"サイズ","Close":"閉じる","Init error.":"イニシャライズエラー","Add files to the upload queue and click the start button.":"ファイルをアップロードキューに追加してスタートボタンをクリックしてください","Filename":"ファイル名","Image format either wrong or not supported.":"画像形式が間違っているかサポートされていません","Status":"ステータス","HTTP Error.":"HTTP エラー","Start Upload":"アップロード開始","mb":"MB","kb":"KB","Duplicate file error.":"重複ファイルエラー","File size error.":"ファイルサイズエラー","N/A":"N/A","gb":"GB","Error: Invalid file extension:":"エラー: ファイルの拡張子が無効です：","Select files":"ファイル選択","%s already present in the queue.":"%s 既にキューに存在しています","File: %s":"ファイル: %s","b":"B","Uploaded %d/%d files":"アップロード中 %d/%d ファイル","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"アップロード可能なファイル数は %d です 余分なファイルは削除されました","%d files queued":"%d ファイルが追加されました","File: %s, size: %d, max file size: %d":"ファイル: %s, サイズ: %d, 最大ファイルサイズ: %d","Drag files here.":"ここにファイルをドラッグ","Runtime ran out of available memory.":"ランタイムが使用するメモリが不足しました","File count error.":"ファイル数エラー","File extension error.":"ファイル拡張子エラー","Error: File too large:":"エラー: ファイルが大きすぎます:","Add Files":"ファイルを追加"});
Index: /trunk/themes/default/js/plugins/plupload/i18n/ka.js
===================================================================
--- /trunk/themes/default/js/plugins/plupload/i18n/ka.js	(revision 28545)
+++ /trunk/themes/default/js/plugins/plupload/i18n/ka.js	(revision 28545)
@@ -0,0 +1,2 @@
+// Georgian (ka)
+plupload.addI18n({"Stop Upload":"ატვირთვის შეჩერება","Upload URL might be wrong or doesn't exist.":"ატვირთვის მისამართი არასწორია ან არ არსებობს.","tb":"ტბ","Size":"ზომა","Close":"დავხუროთ","Init error.":"ინიციალიზაციის შეცდომა.","Add files to the upload queue and click the start button.":"დაამატეთ ფაილები და დააჭირეთ ღილაკს - ატვირთვა.","Filename":"ფაილის სახელი","Image format either wrong or not supported.":"ფაილის ფორმატი არ არის მხარდაჭერილი ან არასწორია.","Status":"სტატუსი","HTTP Error.":"HTTP შეცდომა.","Start Upload":"ატვირთვა","mb":"მბ","kb":"კბ","Duplicate file error.":"ესეთი ფაილი უკვე დამატებულია.","File size error.":"ფაილის ზომა დაშვებულზე დიდია.","N/A":"N/A","gb":"გბ","Error: Invalid file extension:":"შეცდომა: ფაილს აქვს არასწორი გაფართოება.","Select files":"ფაილების მონიშვნა","%s already present in the queue.":"%s უკვე დამატებულია.","File: %s":"ფაილი: %s","b":"ბ","Uploaded %d/%d files":"ატვირთულია %d/%d ფაილი","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"ერთდროულად დაშვებულია მხოლოდ %d ფაილის დამატება.","%d files queued":"რიგშია %d ფაილი","File: %s, size: %d, max file size: %d":"ფაილი: %s, ზომა: %d, მაქსიმალური დაშვებული ზომა: %d","Drag files here.":"ჩააგდეთ ფაილები აქ.","Runtime ran out of available memory.":"ხელმისაწვდომი მეხსიერება გადაივსო.","File count error.":"აღმოჩენილია ზედმეტი ფაილები.","File extension error.":"ფაილის ფორმატი დაშვებული არ არის.","Error: File too large:":"შეცდომა: ფაილი ზედმეტად დიდია.","Add Files":"დაამატეთ ფაილები"});
Index: /trunk/themes/default/js/plugins/plupload/i18n/kk.js
===================================================================
--- /trunk/themes/default/js/plugins/plupload/i18n/kk.js	(revision 28545)
+++ /trunk/themes/default/js/plugins/plupload/i18n/kk.js	(revision 28545)
@@ -0,0 +1,2 @@
+// Kazakh (kk)
+plupload.addI18n({"Stop Upload":"Жүктеуді тоқтату","Upload URL might be wrong or doesn't exist.":"Жүктеуді қабылдаушы URL қате не мүлдем көрсетілмеген.","tb":"тб","Size":"Өлшемі","Close":"Жабу","Init error.":"Инициализация қатесі.","Add files to the upload queue and click the start button.":"Жүктеу кезегіне файлдар қосып, Бастау кнопкасын басыңыз.","Filename":"Файл аты","Image format either wrong or not supported.":"Сурет форматы қате немесе оның қолдауы жоқ.","Status":"Күйі","HTTP Error.":"HTTP қатесі.","Start Upload":"Жүктеуді бастау","mb":"мб","kb":"кб","Duplicate file error.":"Файл қайталамасының қатесі.","File size error.":"Файл өлшемінің қатесі.","N/A":"Қ/Ж","gb":"гб","Error: Invalid file extension:":"Қате: Файл кеңейтілуі қате:","Select files":"Файлдар таңдаңыз","%s already present in the queue.":"%s файлы кезекте бұрыннан бар.","File: %s":"Файл: %s","b":"б","Uploaded %d/%d files":"Жүктелген: %d/%d файл","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Жүктеу элементі бір кезде %d файл ғана жүктей алады. Артық файлдар жүктелмейді.","%d files queued":"%d файл кезекке қойылды","File: %s, size: %d, max file size: %d":"Файл: %s, өлшемі: %d, макс. файл өлшемі: %d","Drag files here.":"Файлдарды мына жерге тастаңыз.","Runtime ran out of available memory.":"Орындау кезінде жады жетпей қалды.","File count error.":"Файл санының қатесі.","File extension error.":"Файл кеңейтілуінің қатесі.","Error: File too large:":"Қате: Файл мөлшері тым үлкен:","Add Files":"Файл қосу"});
Index: /trunk/themes/default/js/plugins/plupload/i18n/km.js
===================================================================
--- /trunk/themes/default/js/plugins/plupload/i18n/km.js	(revision 28545)
+++ /trunk/themes/default/js/plugins/plupload/i18n/km.js	(revision 28545)
@@ -0,0 +1,2 @@
+// Khmer (km)
+plupload.addI18n({"Stop Upload":"បញ្ឈប់​ការ​ផ្ទុក​ឡើង","Upload URL might be wrong or doesn't exist.":"URL ផ្ទុក​ឡើង​អាច​ខុស ឬ​ក៏​គ្មាន។","tb":"tb","Size":"ទំហំ","Close":"បិទ","Init error.":"កំហុស Init។","Add files to the upload queue and click the start button.":"បន្ថែម​ឯកសារ​ទៅ​ក្នុង​ជួរ​លំដាប់​ផ្ទុក​ឡើង ហើយ​ចុច​ប៊ូតុង​ចាប់​ផ្ដើម។","Filename":"ឈ្មោះ​ឯកសារ","Image format either wrong or not supported.":"ទ្រង់​ទ្រាយ​រូបភាព​អាច​ខុស ឬ​ក៏​មិន​ស្គាល់​តែ​ម្ដង។","Status":"ស្ថានភាព","HTTP Error.":"កំហុស HTTP ។","Start Upload":"ចាប់​ផ្ដើម​ផ្ទុក​ឡើង","mb":"mb","kb":"kb","Duplicate file error.":"កំហុស​ឯកសារ​ស្ទួន​គ្នា។","File size error.":"កំហុស​ទំហំ​ឯកសារ។","N/A":"គ្មាន","gb":"gb","Error: Invalid file extension:":"កំហុស៖ កន្ទុយ​ឯកសារ​មិន​ត្រឹម​ត្រូវ៖","Select files":"ជ្រើស​ឯកសារ","%s already present in the queue.":"មាន %s នៅ​ក្នុង​ជួរ​លំដាប់​ហើយ។","File: %s":"ឯកសារ៖ %s","b":"b","Uploaded %d/%d files":"បាន​ផ្ទុក​ឡើង​ឯកសារ %d/%d","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"ការ​ផ្ទុក​ឡើង​ទទួល​ឯកសារ​បាន​តែ %d ប៉ុណ្ណោះ​ក្នុង​ពេល​តែ​មួយ។ ឯកសារ​ផ្សេង​ទៀត​នឹង​ត្រូវ​ដក​ចេញ។","%d files queued":"បាន​ដាក់​ឯកសារ %d បន្ត​គ្នា","File: %s, size: %d, max file size: %d":"ឯកសារ៖ %s, size: %d, ទំហំ​ឯកសារ​អតិបរមា៖ %d","Drag files here.":"អូស​ឯកសារ​មក​ទីនេះ។","Runtime ran out of available memory.":"ពេល​ដំណើរ​ការ​អស់​អង្គ​ចងចាំ​ទំនេរ​ហើយ។","File count error.":"កំហុស​ការ​រាប់​ឯកសារ។","File extension error.":"កំហុស​កន្ទុយ​ឯកសារ។","Error: File too large:":"កំហុស៖ ឯកសារ​ធំ​ពេក៖","Add Files":"បន្ថែម​ឯកសារ"});
Index: /trunk/themes/default/js/plugins/plupload/i18n/ko.js
===================================================================
--- /trunk/themes/default/js/plugins/plupload/i18n/ko.js	(revision 28545)
+++ /trunk/themes/default/js/plugins/plupload/i18n/ko.js	(revision 28545)
@@ -0,0 +1,2 @@
+// Korean (ko)
+plupload.addI18n({"Stop Upload":"업로드 중지","Upload URL might be wrong or doesn't exist.":"업로드할 URL이 존재하지 않습니다.","tb":"tb","Size":"크기","Close":"닫기","Init error.":"초기화 오류.","Add files to the upload queue and click the start button.":"파일을 업로드 큐에 추가한 후 시작 버튼을 클릭하십시오.","Filename":"파일명","Image format either wrong or not supported.":"지원되지 않는 이미지 형식입니다.","Status":"상태","HTTP Error.":"HTTP 오류.","Start Upload":"업로드 시작","mb":"mb","kb":"kb","Duplicate file error.":"파일 중복 오류.","File size error.":"파일 크기 오류.","N/A":"N/A","gb":"gb","Error: Invalid file extension:":"오류: 허용되지 않은 확장자입니다.","Select files":"파일 선택","%s already present in the queue.":"%s 파일이 이미 대기열에 존재합니다.","File: %s":"파일: %s","b":"b","Uploaded %d/%d files":"%d / %d 파일 업로드 완료","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"업로드 가능한 파일의 수는 %d 입니다. 불필요한 파일은 삭제되었습니다.","%d files queued":"%d 파일이 추가됨","File: %s, size: %d, max file size: %d":"파일: %s, 크기: %d, 최대 파일 크기: %d","Drag files here.":"이곳에 파일을 드래그 하세요.","Runtime ran out of available memory.":"런타임 메모리가 부족합니다.","File count error.":"파일 갯수 오류.","File extension error.":"파일 확장자 오류.","Error: File too large:":"오류: 파일 크기가 너무 큽니다.","Add Files":"파일 추가"});
Index: /trunk/themes/default/js/plugins/plupload/i18n/lt.js
===================================================================
--- /trunk/themes/default/js/plugins/plupload/i18n/lt.js	(revision 28545)
+++ /trunk/themes/default/js/plugins/plupload/i18n/lt.js	(revision 28545)
@@ -0,0 +1,2 @@
+// Lithuanian (lt)
+plupload.addI18n({"Stop Upload":"Stabdyti įkėlimą","Upload URL might be wrong or doesn't exist.":"Klaidinga arba neegzistuojanti įkėlimo nuoroda.","tb":"tb","Size":"Dydis","Close":"Uždaryti","Init error.":"Įkrovimo klaida.","Add files to the upload queue and click the start button.":"Pridėkite bylas į įkėlimo eilę ir paspauskite starto mygtuką.","Filename":"Bylos pavadinimas","Image format either wrong or not supported.":"Paveiksliuko formatas klaidingas arba nebepalaikomas.","Status":"Statusas","HTTP Error.":"HTTP klaida.","Start Upload":"Pradėti įkėlimą","mb":"mb","kb":"kb","Duplicate file error.":"Pasikartojanti byla.","File size error.":"Netinkamas bylos dydis.","N/A":"N/A","gb":"gb","Error: Invalid file extension:":"Klaida: Netinkamas bylos plėtinys:","Select files":"Žymėti bylas","%s already present in the queue.":"%s jau yra eilėje.","File: %s":"Byla: %s","b":"b","Uploaded %d/%d files":"Įkelta bylų: %d/%d","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Vienu metu galima įkelti tik %d bylas(ų). Papildomos bylos buvo pašalintos.","%d files queued":"%d bylų eilėje","File: %s, size: %d, max file size: %d":"Byla: %s, dydis: %d, galimas dydis: %d","Drag files here.":"Padėti bylas čia.","Runtime ran out of available memory.":"Išeikvota darbinė atmintis.","File count error.":"Netinkamas bylų kiekis.","File extension error.":"Netinkamas pletinys.","Error: File too large:":"Klaida: Byla per didelė:","Add Files":"Pridėti bylas"});
Index: /trunk/themes/default/js/plugins/plupload/i18n/lv.js
===================================================================
--- /trunk/themes/default/js/plugins/plupload/i18n/lv.js	(revision 28545)
+++ /trunk/themes/default/js/plugins/plupload/i18n/lv.js	(revision 28545)
@@ -0,0 +1,2 @@
+// Latvian (lv)
+plupload.addI18n({"Stop Upload":"Apturēt augšupielādi","Upload URL might be wrong or doesn't exist.":"Augšupielādes saite neeksistē vai ir nepareiza.","tb":"terrabaiti","Size":"Izmērs","Close":"Aizvērt","Init error.":"Inicializācijas kļūda.","Add files to the upload queue and click the start button.":"Pieveinojiet failus rindai un klikšķiniet uz pogu \"Sākt augšupielādi\".","Filename":"Faila nosaukums","Image format either wrong or not supported.":"Attēla formāts ir nepareizs vai arī netiek atbalstīts.","Status":"Statuss","HTTP Error.":"HTTP kļūda.","Start Upload":"Sākt augšupielādi","mb":"megabaiti","kb":"kilobaiti","Duplicate file error.":"Atkārtota faila kļūda","File size error.":"Faila izmēra kļūda.","N/A":"N/A","gb":"gigabaiti","Error: Invalid file extension:":"Kļūda: Nepareizs faila paplašinājums:","Select files":"Izvēlieties failus","%s already present in the queue.":"%s jau ir atrodams rindā.","File: %s":"Fails: %s","b":"baiti","Uploaded %d/%d files":"Augšupielādēti %d/%d faili","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Iespējams ielādēt tikai %d failus vienā reizē. Atlikušie faili netika pievienoti","%d files queued":"%d faili pievienoti rindai","File: %s, size: %d, max file size: %d":"Fails: %s, izmērs: %d, max faila izmērs: %d","Drag files here.":"Ievelciet failus šeit","Runtime ran out of available memory.":"Pietrūkst izmantojamās atmiņas.","File count error.":"Failu skaita kļūda","File extension error.":"Faila paplašinājuma kļūda.","Error: File too large:":"Kļūda: Fails pārāk liels:","Add Files":"Pievienot failus"});
Index: /trunk/themes/default/js/plugins/plupload/i18n/mn.js
===================================================================
--- /trunk/themes/default/js/plugins/plupload/i18n/mn.js	(revision 28545)
+++ /trunk/themes/default/js/plugins/plupload/i18n/mn.js	(revision 28545)
@@ -0,0 +1,2 @@
+// Mongolian (mn)
+plupload.addI18n({"Stop Upload":"","Upload URL might be wrong or doesn't exist.":"","tb":"","Size":"","Close":"","Init error.":"","Add files to the upload queue and click the start button.":"","Filename":"","Image format either wrong or not supported.":"","Status":"","HTTP Error.":"","Start Upload":"","mb":"","kb":"","Duplicate file error.":"","File size error.":"","N/A":"","gb":"","Error: Invalid file extension:":"","Select files":"","%s already present in the queue.":"","File: %s":"","b":"","Uploaded %d/%d files":"","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"","%d files queued":"","File: %s, size: %d, max file size: %d":"","Drag files here.":"","Runtime ran out of available memory.":"","File count error.":"","File extension error.":"","Error: File too large:":"","Add Files":""});
Index: /trunk/themes/default/js/plugins/plupload/i18n/ms.js
===================================================================
--- /trunk/themes/default/js/plugins/plupload/i18n/ms.js	(revision 28545)
+++ /trunk/themes/default/js/plugins/plupload/i18n/ms.js	(revision 28545)
@@ -0,0 +1,2 @@
+// Malay (ms)
+plupload.addI18n({"Stop Upload":"Berhenti Muat naik","Upload URL might be wrong or doesn't exist.":"URL muat naik mungkin salah atau tidak wujud.","tb":"tb","Size":"saiz","Close":"Tutup","Init error.":"Ralat perlaksanaan.","Add files to the upload queue and click the start button.":"Tambah fail ke dalam giliran muat naik dan klik butang Muat Naik.","Filename":"Nama fail","Image format either wrong or not supported.":"Format imej sama ada salah atau tidak disokong.","Status":"Status","HTTP Error.":"Ralat HTTP.","Start Upload":"Muat Naik","mb":"mb","kb":"kb","Duplicate file error.":"Ralat menggandakan fail.","File size error.":"Ralat saiz fail.","N/A":"N/A","gb":"gb","Error: Invalid file extension:":"Ralat: Sambungan fail tidak sah:","Select files":"Pilih fail","%s already present in the queue.":"%s telah ada dalam barisan.","File: %s":"Fail: %s","b":"b","Uploaded %d/%d files":"%d/%d telah dimuat naik","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Element muat naik hanya menerima %d fail(-fail) pada satu masa. Fail tambahan telah digugurkan.","%d files queued":"%d fail dalam barisan","File: %s, size: %d, max file size: %d":"Fail: %s, saiz: %d, saiz maks fail: %d","Drag files here.":"Seret fail ke sini.","Runtime ran out of available memory.":"Ruang ingatan masa larian tidak mencukupi.","File count error.":"Ralat bilangan fail.","File extension error.":"Ralat sambungan fail.","Error: File too large:":"Ralat: Fail terlalu bersar:","Add Files":"Tambah Fail"});
Index: /trunk/themes/default/js/plugins/plupload/i18n/nl.js
===================================================================
--- /trunk/themes/default/js/plugins/plupload/i18n/nl.js	(revision 28545)
+++ /trunk/themes/default/js/plugins/plupload/i18n/nl.js	(revision 28545)
@@ -0,0 +1,2 @@
+// Dutch (nl)
+plupload.addI18n({"Stop Upload":"Stop Upload","Upload URL might be wrong or doesn't exist.":"Upload URL is verkeerd of bestaat niet.","tb":"tb","Size":"Grootte","Close":"Sluiten","Init error.":"Initialisatie error.","Add files to the upload queue and click the start button.":"Voeg bestanden toe aan de wachtrij en druk op 'Start'.","Filename":"Bestandsnaam","Image format either wrong or not supported.":"bestandsextensie is verkeerd of niet ondersteund.","Status":"Status","HTTP Error.":"HTTP Error.","Start Upload":"Start Upload","mb":"mb","kb":"kb","Duplicate file error.":"Bestand bestaat al.","File size error.":"Bestandsgrootte error.","N/A":"Niet beschikbaar","gb":"gb","Error: Invalid file extension:":"Error: Ongeldige bestandsextensie:","Select files":"Selecteer bestand(en):","%s already present in the queue.":"%s is al aan de wachtrij toegevoegd.","File: %s":"Bestand: %s","b":"b","Uploaded %d/%d files":"%d/%d bestanden ge-upload","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Upload accepteert alleen %d bestand(en) tegelijk. Extra bestanden zijn verwijderd.","%d files queued":"%d bestand(en) in de wachtrij","File: %s, size: %d, max file size: %d":"Bestand: %s, grootte: %d, maximale bestandsgrootte: %d","Drag files here.":"Sleep bestanden hierheen.","Runtime ran out of available memory.":"Het maximum bruikbare geheugen is overschreden.","File count error.":"Teveel bestand(en) error.","File extension error.":"Ongeldig bestandsextensie.","Error: File too large:":"Error: Bestand te groot:","Add Files":"Bestand(en) toevoegen"});
Index: /trunk/themes/default/js/plugins/plupload/i18n/pl.js
===================================================================
--- /trunk/themes/default/js/plugins/plupload/i18n/pl.js	(revision 28545)
+++ /trunk/themes/default/js/plugins/plupload/i18n/pl.js	(revision 28545)
@@ -0,0 +1,2 @@
+// Polish (pl)
+plupload.addI18n({"Stop Upload":"Przerwij transfer.","Upload URL might be wrong or doesn't exist.":"Adres URL moze bys nieprawidlowy lub moze nieistniec","tb":"tb","Size":"Rozmiar","Close":"Zamknij","Init error.":"Błąd inicjalizacji.","Add files to the upload queue and click the start button.":"Dodaj pliki i kliknij 'Rozpocznij transfer'.","Filename":"Nazwa pliku","Image format either wrong or not supported.":"Format zdjecia jest zly lub nieobslugiwany","Status":"Status","HTTP Error.":"Błąd HTTP.","Start Upload":"Wyslij","mb":"mb","kb":"kb","Duplicate file error.":"Blad: duplikacja pliku.","File size error.":"Plik jest zbyt duży.","N/A":"Nie dostępne","gb":"gb","Error: Invalid file extension:":"Blad: Nieprawidlowe rozszerzenie pliku:","Select files":"Wybierz pliki:","%s already present in the queue.":"%s juz wystepuje w kolejce.","File: %s":"Plik: %s","b":"b","Uploaded %d/%d files":"Wysłano %d/%d plików","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Upload element accepts only %d file(s) at a time. Extra files were stripped.","%d files queued":"%d plików w kolejce.","File: %s, size: %d, max file size: %d":"Plik: %s, rozmiar: %d, maksymalny rozmiar pliku: %d","Drag files here.":"Przeciągnij tu pliki","Runtime ran out of available memory.":"Wyczerpano pamiec RAM.","File count error.":"Blad liczenia pliku.","File extension error.":"Nieobsługiwany format pliku.","Error: File too large:":"Blad: Plik za duzy:","Add Files":"Dodaj pliki"});
Index: /trunk/themes/default/js/plugins/plupload/i18n/pt_BR.js
===================================================================
--- /trunk/themes/default/js/plugins/plupload/i18n/pt_BR.js	(revision 28545)
+++ /trunk/themes/default/js/plugins/plupload/i18n/pt_BR.js	(revision 28545)
@@ -0,0 +1,2 @@
+// Portuguese (Brazil) (pt_BR)
+plupload.addI18n({"Stop Upload":"Parar o envio","Upload URL might be wrong or doesn't exist.":"URL de envio está errada ou não existe","tb":"TB","Size":"Tamanho","Close":"Fechar","Init error.":"Erro inicializando.","Add files to the upload queue and click the start button.":"Adicione os arquivos abaixo e clique no botão \"Iniciar o envio\".","Filename":"Nome do arquivo","Image format either wrong or not supported.":"Image format either wrong or not supported.","Status":"Status","HTTP Error.":"Erro HTTP.","Start Upload":"Iniciar o envio","mb":"MB","kb":"KB","Duplicate file error.":"Erro: Arquivo duplicado.","File size error.":"Tamanho de arquivo não permitido.","N/A":"N/D","gb":"GB","Error: Invalid file extension:":"Error: Invalid file extension:","Select files":"Escolha os arquivos","%s already present in the queue.":"%s já presentes na fila.","File: %s":"Arquivo: %s","b":"Bytes","Uploaded %d/%d files":"Enviado(s) %d/%d arquivo(s)","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Só são aceitos %d arquivos por vez. O que passou disso foi descartado.","%d files queued":"%d arquivo(s)","File: %s, size: %d, max file size: %d":"Arquivo: %s, Tamanho: %d , Tamanho Máximo do Arquivo: %d","Drag files here.":"Arraste os arquivos pra cá","Runtime ran out of available memory.":"Runtime ran out of available memory.","File count error.":"Erro na contagem dos arquivos","File extension error.":"Tipo de arquivo não permitido.","Error: File too large:":"Error: File too large:","Add Files":"Adicionar arquivo(s)"});
Index: /trunk/themes/default/js/plugins/plupload/i18n/ro.js
===================================================================
--- /trunk/themes/default/js/plugins/plupload/i18n/ro.js	(revision 28545)
+++ /trunk/themes/default/js/plugins/plupload/i18n/ro.js	(revision 28545)
@@ -0,0 +1,2 @@
+// Romanian (ro)
+plupload.addI18n({"Stop Upload":"Oprește încărcarea","Upload URL might be wrong or doesn't exist.":"Upload URL might be wrong or doesn't exist.","tb":"tb","Size":"Mărime","Close":"Închide","Init error.":"Eroare inițializare.","Add files to the upload queue and click the start button.":"Adaugă fișiere în lista apoi apasă butonul \"Începe încărcarea\".","Filename":"Nume fișier","Image format either wrong or not supported.":"Formatul de imagine ori este greșit ori nu este suportat.","Status":"Stare","HTTP Error.":"Eroare HTTP","Start Upload":"Începe încărcarea","mb":"mb","kb":"kb","Duplicate file error.":"Eroare duplicat fișier.","File size error.":"Eroare dimensiune fișier.","N/A":"N/A","gb":"gb","Error: Invalid file extension:":"Eroare: Extensia fișierului este invalidă:","Select files":"Selectează fișierele","%s already present in the queue.":"%s există deja în lista de așteptare.","File: %s":"Fișier: %s","b":"b","Uploaded %d/%d files":"Fișiere încărcate %d/%d","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Upload element accepts only %d file(s) at a time. Extra files were stripped.","%d files queued":"%d fișiere listate","File: %s, size: %d, max file size: %d":"Fișier: %s, mărime: %d, mărime maximă: %d","Drag files here.":"Trage aici fișierele.","Runtime ran out of available memory.":"Runtime ran out of available memory.","File count error.":"Eroare numărare fișiere.","File extension error.":"Eroare extensie fișier.","Error: File too large:":"Eroare: Fișierul este prea mare:","Add Files":"Adaugă fișiere"});
Index: /trunk/themes/default/js/plugins/plupload/i18n/ru.js
===================================================================
--- /trunk/themes/default/js/plugins/plupload/i18n/ru.js	(revision 28545)
+++ /trunk/themes/default/js/plugins/plupload/i18n/ru.js	(revision 28545)
@@ -0,0 +1,2 @@
+// Russian (ru)
+plupload.addI18n({"Stop Upload":"Остановить Загрузку","Upload URL might be wrong or doesn't exist.":"Адрес заргузки неправильный или он не существует.","tb":"тб","Size":"Размер","Close":"Закрыть","Init error.":"Ошибка инициализации.","Add files to the upload queue and click the start button.":"Добавьте файлы в очередь и нажмите кнопку \"Загрузить файлы\".","Filename":"Имя файла","Image format either wrong or not supported.":"Формат картинки неправильный или он не поддерживается.","Status":"Статус","HTTP Error.":"Ошибка HTTP.","Start Upload":"Начать загрузку","mb":"мб","kb":"кб","Duplicate file error.":"Такой файл уже присутствует в очереди.","File size error.":"Неправильный размер файла.","N/A":"N/A","gb":"гб","Error: Invalid file extension:":"Ошибка: У файла неправильное расширение:","Select files":"Выберите файлы","%s already present in the queue.":"%s уже присутствует в очереди.","File: %s":"Файл: %s","b":"б","Uploaded %d/%d files":"Загружено %d/%d файлов","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Загрузочный элемент за раз принимает только %d файл(ов). Лишние файлы были отброшены.","%d files queued":"В очереди %d файл(ов)","File: %s, size: %d, max file size: %d":"Файл:  %s, размер: %d, макс. размер файла: %d","Drag files here.":"Перетащите файлы сюда.","Runtime ran out of available memory.":"Рабочая среда превысила лимит достуной памяти.","File count error.":"Слишком много файлов.","File extension error.":"Неправильное расширение файла.","Error: File too large:":"Ошибка: Файл слишком большой:","Add Files":"Добавьте файлы"});
Index: /trunk/themes/default/js/plugins/plupload/i18n/sk.js
===================================================================
--- /trunk/themes/default/js/plugins/plupload/i18n/sk.js	(revision 28545)
+++ /trunk/themes/default/js/plugins/plupload/i18n/sk.js	(revision 28545)
@@ -0,0 +1,2 @@
+// Slovak (sk)
+plupload.addI18n({"Stop Upload":"Zastaviť nahrávanie","Upload URL might be wrong or doesn't exist.":"URL pre nahratie nie je správna alebo neexistuje.","tb":"tb","Size":"Veľkosť","Close":"Zatvoriť","Init error.":"Chyba inicializácie.","Add files to the upload queue and click the start button.":"Pridajte súbory do zoznamu a potom spustite nahrávanie.","Filename":"Názov súboru","Image format either wrong or not supported.":"Formát obrázku je nesprávny alebo nie je podporovaný.","Status":"Stav","HTTP Error.":"HTTP Chyba.","Start Upload":"Spustiť nahrávanie","mb":"mb","kb":"kb","Duplicate file error.":"Duplicitný súbor.","File size error.":"Súbor je príliš veľký.","N/A":"N/A","gb":"gb","Error: Invalid file extension:":"Error: Nesprávny typ súboru:","Select files":"Vyberte súbory","%s already present in the queue.":"%s sa už nachádza v zozname.","File: %s":"Súbor: %s","b":"b","Uploaded %d/%d files":"Nahraných %d/%d súborov","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Upload element accepts only %d file(s) at a time. Extra files were stripped.","%d files queued":"%d súborov pridaných do zoznamu","File: %s, size: %d, max file size: %d":"Súbor: %s, veľkosť: %d, max. veľkosť súboru: %d","Drag files here.":"Sem pretiahnite súbory.","Runtime ran out of available memory.":"Runtime ran out of available memory.","File count error.":"Nesprávny počet súborov.","File extension error.":"Chybný typ súboru.","Error: File too large:":"Chyba: Súbor je príliš veľký:","Add Files":"Pridať súbory"});
Index: /trunk/themes/default/js/plugins/plupload/i18n/sq.js
===================================================================
--- /trunk/themes/default/js/plugins/plupload/i18n/sq.js	(revision 28545)
+++ /trunk/themes/default/js/plugins/plupload/i18n/sq.js	(revision 28545)
@@ -0,0 +1,2 @@
+// Albanian (sq)
+plupload.addI18n({"Stop Upload":"","Upload URL might be wrong or doesn't exist.":"","tb":"TB","Size":"","Close":"","Init error.":"Init gabim.","Add files to the upload queue and click the start button.":"","Filename":"","Image format either wrong or not supported.":"","Status":"","HTTP Error.":"HTTP Gabim.","Start Upload":"","mb":"MB","kb":"KB","Duplicate file error.":"Gabim i dublikatës të dosjes.","File size error.":"Gabim i madhësisë së dosjes.","N/A":"Nuk është në dispozicion","gb":"GB","Error: Invalid file extension:":"","Select files":"Zhgjidhni dosjet.","%s already present in the queue.":"","File: %s":"","b":"B","Uploaded %d/%d files":"","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"","%d files queued":"","File: %s, size: %d, max file size: %d":"","Drag files here.":"","Runtime ran out of available memory.":"","File count error.":"","File extension error.":"Gabim i zgerimit të dosjes.","Error: File too large:":"","Add Files":""});
Index: /trunk/themes/default/js/plugins/plupload/i18n/sr.js
===================================================================
--- /trunk/themes/default/js/plugins/plupload/i18n/sr.js	(revision 28545)
+++ /trunk/themes/default/js/plugins/plupload/i18n/sr.js	(revision 28545)
@@ -0,0 +1,2 @@
+// Serbian (sr)
+plupload.addI18n({"Stop Upload":"Stop Upload","Upload URL might be wrong or doesn't exist.":"Upload URL might be wrong or doesn't exist.","tb":"","Size":"Veličina","Close":"Close","Init error.":"Init error.","Add files to the upload queue and click the start button.":"Dodajte fajlove u listu i kliknite na dugme Start.","Filename":"Naziv fajla","Image format either wrong or not supported.":"Image format either wrong or not supported.","Status":"Status","HTTP Error.":"HTTP Error.","Start Upload":"Počni upload","mb":"","kb":"","Duplicate file error.":"","File size error.":"File size error.","N/A":"N/A","gb":"","Error: Invalid file extension:":"Error: Invalid file extension:","Select files":"Izaberite fajlove","%s already present in the queue.":"","File: %s":"File: %s","b":"","Uploaded %d/%d files":"Snimljeno %d/%d fajlova","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Upload element accepts only %d file(s) at a time. Extra files were stripped.","%d files queued":"%d files queued","File: %s, size: %d, max file size: %d":"","Drag files here.":"Prevucite fajlove ovde.","Runtime ran out of available memory.":"Runtime ran out of available memory.","File count error.":"File count error.","File extension error.":"File extension error.","Error: File too large:":"Error: File too large:","Add Files":"Dodaj fajlove"});
Index: /trunk/themes/default/js/plugins/plupload/i18n/sr_RS.js
===================================================================
--- /trunk/themes/default/js/plugins/plupload/i18n/sr_RS.js	(revision 28545)
+++ /trunk/themes/default/js/plugins/plupload/i18n/sr_RS.js	(revision 28545)
@@ -0,0 +1,2 @@
+// Serbian (Serbia) (sr_RS)
+plupload.addI18n({"Stop Upload":"","Upload URL might be wrong or doesn't exist.":"","tb":"","Size":"","Close":"","Init error.":"","Add files to the upload queue and click the start button.":"","Filename":"","Image format either wrong or not supported.":"","Status":"","HTTP Error.":"","Start Upload":"","mb":"","kb":"","Duplicate file error.":"","File size error.":"","N/A":"","gb":"","Error: Invalid file extension:":"","Select files":"","%s already present in the queue.":"","File: %s":"","b":"","Uploaded %d/%d files":"","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"","%d files queued":"","File: %s, size: %d, max file size: %d":"","Drag files here.":"","Runtime ran out of available memory.":"","File count error.":"","File extension error.":"","Error: File too large:":"","Add Files":""});
Index: /trunk/themes/default/js/plugins/plupload/i18n/sv.js
===================================================================
--- /trunk/themes/default/js/plugins/plupload/i18n/sv.js	(revision 28545)
+++ /trunk/themes/default/js/plugins/plupload/i18n/sv.js	(revision 28545)
@@ -0,0 +1,2 @@
+// Swedish (sv)
+plupload.addI18n({"Stop Upload":"Avbryt","Upload URL might be wrong or doesn't exist.":"URL:en va fel eller existerar inte.","tb":"tb","Size":"Storlek","Close":"Stäng","Init error.":"Problem vid initialisering.","Add files to the upload queue and click the start button.":"Lägg till filer till kön och tryck på start.","Filename":"Filnamn","Image format either wrong or not supported.":"Bildformatet är fel eller så finns inte stöd för det.","Status":"Status","HTTP Error.":"HTTP problem.","Start Upload":"Starta","mb":"mb","kb":"kb","Duplicate file error.":"Problem med dubbla filer.","File size error.":"Problem med filstorlek.","N/A":"N/A","gb":"gb","Error: Invalid file extension:":"Fel: Ej godkänd filändelse.","Select files":"Välj filer","%s already present in the queue.":"%s är redan tillagd.","File: %s":"Fil: %s","b":"b","Uploaded %d/%d files":"Laddade upp %d/%d filer","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Det går bara lägga till %d filer åt gången, allt utöver detta togs bort.","%d files queued":"%d filer i kö","File: %s, size: %d, max file size: %d":"Fil: %s, storlek: %d, max storlek: %d","Drag files here.":"Dra filer hit","Runtime ran out of available memory.":"Slut på minne.","File count error.":"Räknefel.","File extension error.":"Problem med filändelse.","Error: File too large:":"Fel: Filen är för stor:","Add Files":"Lägg till"});
Index: /trunk/themes/default/js/plugins/plupload/i18n/th_TH.js
===================================================================
--- /trunk/themes/default/js/plugins/plupload/i18n/th_TH.js	(revision 28545)
+++ /trunk/themes/default/js/plugins/plupload/i18n/th_TH.js	(revision 28545)
@@ -0,0 +1,2 @@
+// Thai (Thailand) (th_TH)
+plupload.addI18n({"Stop Upload":"หยุดอัพโหลด","Upload URL might be wrong or doesn't exist.":"URL ของการอัพโหลดอาจจะผิดหรือไม่มีอยู่","tb":"เทราไบต์","Size":"ขนาด","Close":"ปิด","Init error.":"Init เกิดข้อผิดพลาด","Add files to the upload queue and click the start button.":"เพิ่มไฟล์ไปยังคิวอัพโหลดและคลิกที่ปุ่มเริ่ม","Filename":"ชื่อไฟล์","Image format either wrong or not supported.":"รูปแบบรูปภาพทั้งสองผิดหรือไม่รองรับ","Status":"สถานะ","HTTP Error.":"HTTP เกิดข้อผิดพลาด","Start Upload":"เริ่มอัพโหลด","mb":"เมกะไบต์","kb":"กิโลไบต์","Duplicate file error.":"ไฟล์ที่ซ้ำกันเกิดข้อผิดพลาด","File size error.":"ขนาดไฟล์เกิดข้อผิดพลาด","N/A":"N/A","gb":"กิกะไบต์","Error: Invalid file extension:":"ข้อผิดพลาด: นามสกุลไฟล์ไม่ถูกต้อง:","Select files":"เลือกไฟล์","%s already present in the queue.":"%s อยู่ในคิวแล้ว","File: %s":"ไฟล์: %s","b":"ไบต์","Uploaded %d/%d files":"อัพโหลดแล้ว %d/%d ไฟล์","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"การอัพโหลดจะยอมรับเฉพาะ %d ไฟล์(s) ในช่วงเวลาเดียวกัน เมื่อไฟล์พิเศษถูกปลดออก","%d files queued":"%d ไฟล์ที่อยู่ในคิว","File: %s, size: %d, max file size: %d":"ไฟล์: %s, ขนาด: %d, ขนาดไฟล์สูงสุด: %d","Drag files here.":"ลากไฟล์มาที่นี่","Runtime ran out of available memory.":"รันไทม์วิ่งออกมาจากหน่วยความจำ","File count error.":"การนับไฟล์เกิดข้อผิดพลาด","File extension error.":"นามสกุลไฟล์เกิดข้อผิดพลาด","Error: File too large:":"ข้อผิดพลาด: ไฟล์ใหญ่เกินไป:","Add Files":"เพิ่มไฟล์"});
Index: /trunk/themes/default/js/plugins/plupload/i18n/tr.js
===================================================================
--- /trunk/themes/default/js/plugins/plupload/i18n/tr.js	(revision 28545)
+++ /trunk/themes/default/js/plugins/plupload/i18n/tr.js	(revision 28545)
@@ -0,0 +1,2 @@
+// Turkish (tr)
+plupload.addI18n({"Stop Upload":"Yüklemeyi durdur","Upload URL might be wrong or doesn't exist.":"URL yok ya da hatalı olabilir.","tb":"tb","Size":"Boyut","Close":"Kapat","Init error.":"Başlangıç hatası.","Add files to the upload queue and click the start button.":"Dosyaları kuyruğa ekleyin ve başlatma butonuna tıklayın.","Filename":"Dosya adı","Image format either wrong or not supported.":"Resim formatı yanlış ya da desteklenmiyor.","Status":"Durum","HTTP Error.":"HTTP hatası.","Start Upload":"Yüklemeyi başlat","mb":"mb","kb":"kb","Duplicate file error.":"Yinelenen dosya hatası.","File size error.":"Dosya boyutu hatası.","N/A":"-","gb":"gb","Error: Invalid file extension:":"Hata: Geçersiz dosya uzantısı:","Select files":"Dosyaları seç","%s already present in the queue.":"%s kuyrukta zaten mevcut.","File: %s":"Dosya: %s","b":"bayt","Uploaded %d/%d files":"%d/%d dosya yüklendi","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Yükleme elemanı aynı anda %d dosya kabul eder. Ekstra dosyalar işleme konulmaz.","%d files queued":"Kuyrukta %d dosya var.","File: %s, size: %d, max file size: %d":"Dosya: %s, boyut: %d, maksimum dosya boyutu: %d","Drag files here.":"Dosyaları buraya bırakın.","Runtime ran out of available memory.":"İşlem için yeterli bellek yok.","File count error.":"Dosya sayım hatası.","File extension error.":"Dosya uzantısı hatası.","Error: File too large:":"Hata: Dosya çok büyük:","Add Files":"Dosya ekle"});
Index: /trunk/themes/default/js/plugins/plupload/i18n/uk_UA.js
===================================================================
--- /trunk/themes/default/js/plugins/plupload/i18n/uk_UA.js	(revision 28545)
+++ /trunk/themes/default/js/plugins/plupload/i18n/uk_UA.js	(revision 28545)
@@ -0,0 +1,2 @@
+// Ukrainian (Ukraine) (uk_UA)
+plupload.addI18n({"Stop Upload":"Зупинити завантаження","Upload URL might be wrong or doesn't exist.":"Адреса завантаження неправильна або не існує.","tb":"тб","Size":"Розмір","Close":"Закрити","Init error.":"Помилка ініціалізації.","Add files to the upload queue and click the start button.":"Додайте файли в чергу та натисніть кнопку \"Завантажити файли\".","Filename":"Назва файлу","Image format either wrong or not supported.":"Формат картинки не правильний або не підтримується.","Status":"Статус","HTTP Error.":"Помилка HTTP.","Start Upload":"Почати завантаження","mb":"мб","kb":"кб","Duplicate file error.":"Такий файл вже присутній в черзі.","File size error.":"Неправильний розмір файлу.","N/A":"Н/Д","gb":"гб","Error: Invalid file extension:":"Помилка: У файлу неправильне розширення:","Select files":"Оберіть файли","%s already present in the queue.":"%s вже присутній у черзі.","File: %s":"Файл: %s","b":"б","Uploaded %d/%d files":"Завантажено %d/%d файлів","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Завантажувальний елемент приймає лише %d файл(ів) одночасно. Зайві файли було відкинуто.","%d files queued":"В черзі %d файл(ів)","File: %s, size: %d, max file size: %d":"Файл:  %s, розмір: %d, макс. розмір файлу: %d","Drag files here.":"Перетягніть файли сюди.","Runtime ran out of available memory.":"Робоче середовище перевищило ліміт доступної пам'яті.","File count error.":"Занадто багато файлів.","File extension error.":"Неправильне розширення файлу.","Error: File too large:":"Помилка: Файл занадто великий:","Add Files":"Додати файли"});
Index: /trunk/themes/default/js/plugins/plupload/i18n/zh_CN.js
===================================================================
--- /trunk/themes/default/js/plugins/plupload/i18n/zh_CN.js	(revision 28545)
+++ /trunk/themes/default/js/plugins/plupload/i18n/zh_CN.js	(revision 28545)
@@ -0,0 +1,2 @@
+// Chinese (China) (zh_CN)
+plupload.addI18n({"Stop Upload":"停止上传","Upload URL might be wrong or doesn't exist.":"上传的URL可能是错误的或不存在。","tb":"tb","Size":"大小","Close":"关闭","Init error.":"初始化错误。","Add files to the upload queue and click the start button.":"将文件添加到上传队列，然后点击”开始上传“按钮。","Filename":"文件名","Image format either wrong or not supported.":"图片格式错误或者不支持。","Status":"状态","HTTP Error.":"HTTP 错误。","Start Upload":"开始上传","mb":"mb","kb":"kb","Duplicate file error.":"重复文件错误。","File size error.":"文件大小错误。","N/A":"N/A","gb":"gb","Error: Invalid file extension:":"错误：无效的文件扩展名:","Select files":"选择文件","%s already present in the queue.":"%s 已经在当前队列里。","File: %s":"文件: %s","b":"b","Uploaded %d/%d files":"已上传 %d/%d 个文件","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"每次只接受同时上传 %d 个文件，多余的文件将会被删除。","%d files queued":"%d 个文件加入到队列","File: %s, size: %d, max file size: %d":"文件: %s, 大小: %d, 最大文件大小: %d","Drag files here.":"把文件拖到这里。","Runtime ran out of available memory.":"运行时已消耗所有可用内存。","File count error.":"文件数量错误。","File extension error.":"文件扩展名错误。","Error: File too large:":"错误: 文件太大:","Add Files":"增加文件"});
Index: /trunk/themes/default/js/plugins/plupload/i18n/zh_TW.js
===================================================================
--- /trunk/themes/default/js/plugins/plupload/i18n/zh_TW.js	(revision 28545)
+++ /trunk/themes/default/js/plugins/plupload/i18n/zh_TW.js	(revision 28545)
@@ -0,0 +1,2 @@
+// Chinese (Taiwan) (zh_TW)
+plupload.addI18n({"Stop Upload":"停止上傳","Upload URL might be wrong or doesn't exist.":"檔案URL可能有誤或者不存在。","tb":"tb","Size":"大小","Close":"關閉","Init error.":"初始化錯誤。","Add files to the upload queue and click the start button.":"將檔案加入上傳序列，然後點選”開始上傳“按鈕。","Filename":"檔案名稱","Image format either wrong or not supported.":"圖片格式錯誤或者不支援。","Status":"狀態","HTTP Error.":"HTTP 錯誤。","Start Upload":"開始上傳","mb":"mb","kb":"kb","Duplicate file error.":"錯誤：檔案重複。","File size error.":"錯誤：檔案大小超過限制。","N/A":"N/A","gb":"gb","Error: Invalid file extension:":"錯誤：不接受的檔案格式:","Select files":"選擇檔案","%s already present in the queue.":"%s 已經存在目前的檔案序列。","File: %s":"檔案: %s","b":"b","Uploaded %d/%d files":"已上傳 %d/%d 個文件","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"每次只能上傳 %d 個檔案，超過限制數量的檔案將被忽略。","%d files queued":"%d 個檔案加入到序列","File: %s, size: %d, max file size: %d":"檔案: %s, 大小: %d, 檔案大小上限: %d","Drag files here.":"把檔案拖曳到這裡。","Runtime ran out of available memory.":"執行時耗盡了所有可用的記憶體。","File count error.":"檔案數量錯誤。","File extension error.":"檔案副檔名錯誤。","Error: File too large:":"錯誤: 檔案大小太大:","Add Files":"增加檔案"});
Index: /trunk/themes/default/js/plugins/plupload/jquery.plupload.queue/css/jquery.plupload.queue.css
===================================================================
--- /trunk/themes/default/js/plugins/plupload/jquery.plupload.queue/css/jquery.plupload.queue.css	(revision 28545)
+++ /trunk/themes/default/js/plugins/plupload/jquery.plupload.queue/css/jquery.plupload.queue.css	(revision 28545)
@@ -0,0 +1,185 @@
+/* 
+   Plupload
+------------------------------------------------------------------- */
+
+.plupload_wrapper * {
+	box-sizing: content-box;
+}
+
+.plupload_button {
+	display: -moz-inline-box; /* FF < 3*/
+	display: inline-block;
+	font: normal 12px sans-serif;
+	text-decoration: none;
+    color: #42454a;
+    border: 1px solid #bababa;
+    padding: 2px 8px 3px 20px;
+	margin-right: 4px;
+    background: #f3f3f3 url('../img/buttons.png') no-repeat 0 center;
+	outline: 0;
+
+    /* Optional rounded corners for browsers that support it */
+    -moz-border-radius: 3px;
+    -khtml-border-radius: 3px;
+    -webkit-border-radius: 3px;
+    border-radius: 3px;
+}
+
+.plupload_button:hover {
+	color: #000;
+	text-decoration: none;
+}
+
+.plupload_disabled, a.plupload_disabled:hover {
+    color: #737373;
+    border-color: #c5c5c5;
+    background: #ededed url('../img/buttons-disabled.png') no-repeat 0 center;
+	cursor: default;
+}
+
+.plupload_add {
+	background-position: -181px center;
+}
+
+.plupload_wrapper {
+	font: normal 11px Verdana,sans-serif;
+	width: 100%;
+}
+
+.plupload_container {
+	padding: 8px;
+	background: url('../img/transp50.png');
+	/*-moz-border-radius: 5px;*/
+}
+
+.plupload_container input {
+	border: 1px solid #DDD;
+	font: normal 11px Verdana,sans-serif;
+	width: 98%;
+}
+
+.plupload_header {background: #2A2C2E url('../img/backgrounds.gif') repeat-x;}
+.plupload_header_content {
+	background: url('../img/backgrounds.gif') no-repeat 0 -317px;
+	min-height: 56px;
+	padding-left: 60px;
+	color: #FFF;
+}
+.plupload_header_title {
+	font: normal 18px sans-serif;
+	padding: 6px 0 3px;
+}
+.plupload_header_text {
+	font: normal 12px sans-serif;
+}
+
+.plupload_filelist {
+	margin: 0;
+	padding: 0;
+	list-style: none;
+}
+
+.plupload_scroll .plupload_filelist {
+	height: 185px;
+	background: #F5F5F5;
+	overflow-y: scroll;
+}
+
+.plupload_filelist li {
+	padding: 10px 8px;
+	background: #F5F5F5 url('../img/backgrounds.gif') repeat-x 0 -156px;
+	border-bottom: 1px solid #DDD;
+}
+
+.plupload_filelist_header, .plupload_filelist_footer {
+	background: #DFDFDF;
+	padding: 8px 8px;
+	color: #42454A;
+}
+.plupload_filelist_header {	
+	border-top: 1px solid #EEE;
+	border-bottom: 1px solid #CDCDCD;
+}
+
+.plupload_filelist_footer {border-top: 1px solid #FFF; height: 22px; line-height: 20px; vertical-align: middle;}
+.plupload_file_name {float: left; overflow: hidden}
+.plupload_file_status {color: #777;}
+.plupload_file_status span {color: #42454A;}
+.plupload_file_size, .plupload_file_status, .plupload_progress {
+	float: right;
+	width: 80px;
+}
+.plupload_file_size, .plupload_file_status, .plupload_file_action {text-align: right;}
+
+.plupload_filelist .plupload_file_name {
+	width: 205px;
+	white-space: nowrap;
+	text-overflow: ellipsis;
+}
+
+.plupload_file_action {
+	float: right;
+	width: 16px;
+	height: 16px;
+	margin-left: 15px;
+}
+
+.plupload_file_action * {
+	display: none;
+	width: 16px;
+	height: 16px;
+}
+
+li.plupload_uploading {background: #ECF3DC url('../img/backgrounds.gif') repeat-x 0 -238px;}
+li.plupload_done {color:#AAA}
+
+li.plupload_delete a {
+	background: url('../img/delete.gif');
+}
+
+li.plupload_failed a {
+	background: url('../img/error.gif');
+	cursor: default;
+}
+
+li.plupload_done a {
+	background: url('../img/done.gif');
+	cursor: default;
+}
+
+.plupload_progress, .plupload_upload_status {
+	display: none;
+}
+
+.plupload_progress_container {
+	margin-top: 3px;
+	border: 1px solid #CCC;
+	background: #FFF;
+	padding: 1px;
+}
+.plupload_progress_bar {
+	width: 0px;
+	height: 7px;
+	background: #CDEB8B;
+}
+
+.plupload_scroll .plupload_filelist_header .plupload_file_action, .plupload_scroll .plupload_filelist_footer .plupload_file_action {
+	margin-right: 17px;
+}
+
+/* Floats */
+
+.plupload_clear,.plupload_clearer {clear: both;}
+.plupload_clearer, .plupload_progress_bar {
+	display: block;
+	font-size: 0;
+	line-height: 0;	
+}
+
+li.plupload_droptext {
+	background: transparent;
+	text-align: center;
+	vertical-align: middle;
+	border: 0;
+	line-height: 165px;
+}
Index: /trunk/themes/default/js/plugins/plupload/jquery.plupload.queue/jquery.plupload.queue.js
===================================================================
--- /trunk/themes/default/js/plugins/plupload/jquery.plupload.queue/jquery.plupload.queue.js	(revision 28545)
+++ /trunk/themes/default/js/plugins/plupload/jquery.plupload.queue/jquery.plupload.queue.js	(revision 28545)
@@ -0,0 +1,428 @@
+/**
+ * jquery.plupload.queue.js
+ *
+ * Copyright 2009, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+/* global jQuery:true, alert:true */
+
+/**
+jQuery based implementation of the Plupload API - multi-runtime file uploading API.
+
+To use the widget you must include _jQuery_. It is not meant to be extended in any way and is provided to be
+used as it is.
+
+@example
+	<!-- Instantiating: -->
+	<div id="uploader">
+		<p>Your browser doesn't have Flash, Silverlight or HTML5 support.</p>
+	</div>
+
+	<script>
+		$('#uploader').pluploadQueue({
+			url : '../upload.php',
+			filters : [
+				{title : "Image files", extensions : "jpg,gif,png"}
+			],
+			rename: true,
+			flash_swf_url : '../../js/Moxie.swf',
+			silverlight_xap_url : '../../js/Moxie.xap',
+		});
+	</script>
+
+@example
+	// Retrieving a reference to plupload.Uploader object
+	var uploader = $('#uploader').pluploadQueue();
+
+	uploader.bind('FilesAdded', function() {
+		
+		// Autostart
+		setTimeout(uploader.start, 1); // "detach" from the main thread
+	});
+
+@class pluploadQueue
+@constructor
+@param {Object} settings For detailed information about each option check documentation.
+	@param {String} settings.url URL of the server-side upload handler.
+	@param {Number|String} [settings.chunk_size=0] Chunk size in bytes to slice the file into. Shorcuts with b, kb, mb, gb, tb suffixes also supported. `e.g. 204800 or "204800b" or "200kb"`. By default - disabled.
+	@param {String} [settings.file_data_name="file"] Name for the file field in Multipart formated message.
+	@param {Array} [settings.filters=[]] Set of file type filters, each one defined by hash of title and extensions. `e.g. {title : "Image files", extensions : "jpg,jpeg,gif,png"}`. Dispatches `plupload.FILE_EXTENSION_ERROR`
+	@param {String} [settings.flash_swf_url] URL of the Flash swf.
+	@param {Object} [settings.headers] Custom headers to send with the upload. Hash of name/value pairs.
+	@param {Number|String} [settings.max_file_size] Maximum file size that the user can pick, in bytes. Optionally supports b, kb, mb, gb, tb suffixes. `e.g. "10mb" or "1gb"`. By default - not set. Dispatches `plupload.FILE_SIZE_ERROR`.
+	@param {Number} [settings.max_retries=0] How many times to retry the chunk or file, before triggering Error event.
+	@param {Boolean} [settings.multipart=true] Whether to send file and additional parameters as Multipart formated message.
+	@param {Object} [settings.multipart_params] Hash of key/value pairs to send with every file upload.
+	@param {Boolean} [settings.multi_selection=true] Enable ability to select multiple files at once in file dialog.
+	@param {Boolean} [settings.prevent_duplicates=false] Do not let duplicates into the queue. Dispatches `plupload.FILE_DUPLICATE_ERROR`.
+	@param {String|Object} [settings.required_features] Either comma-separated list or hash of required features that chosen runtime should absolutely possess.
+	@param {Object} [settings.resize] Enable resizng of images on client-side. Applies to `image/jpeg` and `image/png` only. `e.g. {width : 200, height : 200, quality : 90, crop: true}`
+		@param {Number} [settings.resize.width] If image is bigger, it will be resized.
+		@param {Number} [settings.resize.height] If image is bigger, it will be resized.
+		@param {Number} [settings.resize.quality=90] Compression quality for jpegs (1-100).
+		@param {Boolean} [settings.resize.crop=false] Whether to crop images to exact dimensions. By default they will be resized proportionally.
+	@param {String} [settings.runtimes="html5,flash,silverlight,html4"] Comma separated list of runtimes, that Plupload will try in turn, moving to the next if previous fails.
+	@param {String} [settings.silverlight_xap_url] URL of the Silverlight xap.
+	@param {Boolean} [settings.unique_names=false] If true will generate unique filenames for uploaded files.
+
+	@param {Boolean} [settings.dragdrop=true] Enable ability to add file to the queue by drag'n'dropping them from the desktop.
+	@param {Boolean} [settings.rename=false] Enable ability to rename files in the queue.
+	@param {Boolean} [settings.multiple_queues=true] Re-activate the widget after each upload procedure.
+*/
+;(function($, o) {
+	var uploaders = {};
+
+	function _(str) {
+		return plupload.translate(str) || str;
+	}
+
+	function renderUI(id, target) {
+		// Remove all existing non plupload items
+		target.contents().each(function(i, node) {
+			node = $(node);
+
+			if (!node.is('.plupload')) {
+				node.remove();
+			}
+		});
+
+		target.prepend(
+			'<div class="plupload_wrapper plupload_scroll">' +
+				'<div id="' + id + '_container" class="plupload_container">' +
+					'<div class="plupload">' +
+						'<div class="plupload_header">' +
+							'<div class="plupload_header_content">' +
+								'<div class="plupload_header_title">' + _('Select files') + '</div>' +
+								'<div class="plupload_header_text">' + _('Add files to the upload queue and click the start button.') + '</div>' +
+							'</div>' +
+						'</div>' +
+
+						'<div class="plupload_content">' +
+							'<div class="plupload_filelist_header">' +
+								'<div class="plupload_file_name">' + _('Filename') + '</div>' +
+								'<div class="plupload_file_action">&nbsp;</div>' +
+								'<div class="plupload_file_status"><span>' + _('Status') + '</span></div>' +
+								'<div class="plupload_file_size">' + _('Size') + '</div>' +
+								'<div class="plupload_clearer">&nbsp;</div>' +
+							'</div>' +
+
+							'<ul id="' + id + '_filelist" class="plupload_filelist"></ul>' +
+
+							'<div class="plupload_filelist_footer">' +
+								'<div class="plupload_file_name">' +
+									'<div class="plupload_buttons">' +
+										'<a href="#" class="plupload_button plupload_add" id="' + id + '_browse">' + _('Add Files') + '</a>' +
+										'<a href="#" class="plupload_button plupload_start">' + _('Start Upload') + '</a>' +
+									'</div>' +
+									'<span class="plupload_upload_status"></span>' +
+								'</div>' +
+								'<div class="plupload_file_action"></div>' +
+								'<div class="plupload_file_status"><span class="plupload_total_status">0%</span></div>' +
+								'<div class="plupload_file_size"><span class="plupload_total_file_size">0 b</span></div>' +
+								'<div class="plupload_progress">' +
+									'<div class="plupload_progress_container">' +
+										'<div class="plupload_progress_bar"></div>' +
+									'</div>' +
+								'</div>' +
+								'<div class="plupload_clearer">&nbsp;</div>' +
+							'</div>' +
+						'</div>' +
+					'</div>' +
+				'</div>' +
+				'<input type="hidden" id="' + id + '_count" name="' + id + '_count" value="0" />' +
+			'</div>'
+		);
+	}
+
+	$.fn.pluploadQueue = function(settings) {
+		if (settings) {
+			this.each(function() {
+				var uploader, target, id, contents_bak;
+
+				target = $(this);
+				id = target.attr('id');
+
+				if (!id) {
+					id = plupload.guid();
+					target.attr('id', id);
+				}
+
+				contents_bak = target.html();
+				renderUI(id, target);
+
+				settings = $.extend({
+					dragdrop : true,
+					browse_button : id + '_browse',
+					container : id
+				}, settings);
+
+				// Enable drag/drop (see PostInit handler as well)
+				if (settings.dragdrop) {
+					settings.drop_element = id + '_filelist';
+				}
+
+				uploader = new plupload.Uploader(settings);
+
+				uploaders[id] = uploader;
+
+				function handleStatus(file) {
+					var actionClass;
+
+					if (file.status == plupload.DONE) {
+						actionClass = 'plupload_done';
+					}
+
+					if (file.status == plupload.FAILED) {
+						actionClass = 'plupload_failed';
+					}
+
+					if (file.status == plupload.QUEUED) {
+						actionClass = 'plupload_delete';
+					}
+
+					if (file.status == plupload.UPLOADING) {
+						actionClass = 'plupload_uploading';
+					}
+
+					var icon = $('#' + file.id).attr('class', actionClass).find('a').css('display', 'block');
+					if (file.hint) {
+						icon.attr('title', file.hint);	
+					}
+				}
+
+				function updateTotalProgress() {
+					$('span.plupload_total_status', target).html(uploader.total.percent + '%');
+					$('div.plupload_progress_bar', target).css('width', uploader.total.percent + '%');
+					$('span.plupload_upload_status', target).html(
+						o.sprintf(_('Uploaded %d/%d files'), uploader.total.uploaded, uploader.files.length)
+					);
+				}
+
+				function updateList() {
+					var fileList = $('ul.plupload_filelist', target).html(''), inputCount = 0, inputHTML;
+
+					$.each(uploader.files, function(i, file) {
+						inputHTML = '';
+
+						if (file.status == plupload.DONE) {
+							if (file.target_name) {
+								inputHTML += '<input type="hidden" name="' + id + '_' + inputCount + '_tmpname" value="' + plupload.xmlEncode(file.target_name) + '" />';
+							}
+
+							inputHTML += '<input type="hidden" name="' + id + '_' + inputCount + '_name" value="' + plupload.xmlEncode(file.name) + '" />';
+							inputHTML += '<input type="hidden" name="' + id + '_' + inputCount + '_status" value="' + (file.status == plupload.DONE ? 'done' : 'failed') + '" />';
+	
+							inputCount++;
+
+							$('#' + id + '_count').val(inputCount);
+						}
+
+						fileList.append(
+							'<li id="' + file.id + '">' +
+								'<div class="plupload_file_name"><span>' + file.name + '</span></div>' +
+								'<div class="plupload_file_action"><a href="#"></a></div>' +
+								'<div class="plupload_file_status">' + file.percent + '%</div>' +
+								'<div class="plupload_file_size">' + plupload.formatSize(file.size) + '</div>' +
+								'<div class="plupload_clearer">&nbsp;</div>' +
+								inputHTML +
+							'</li>'
+						);
+
+						handleStatus(file);
+
+						$('#' + file.id + '.plupload_delete a').click(function(e) {
+							$('#' + file.id).remove();
+							uploader.removeFile(file);
+
+							e.preventDefault();
+						});
+					});
+
+					$('span.plupload_total_file_size', target).html(plupload.formatSize(uploader.total.size));
+
+					if (uploader.total.queued === 0) {
+						$('span.plupload_add_text', target).html(_('Add Files'));
+					} else {
+						$('span.plupload_add_text', target).html(o.sprintf(_('%d files queued'), uploader.total.queued));
+					}
+
+					$('a.plupload_start', target).toggleClass('plupload_disabled', uploader.files.length == (uploader.total.uploaded + uploader.total.failed));
+
+					// Scroll to end of file list
+					fileList[0].scrollTop = fileList[0].scrollHeight;
+
+					updateTotalProgress();
+
+					// Re-add drag message if there is no files
+					if (!uploader.files.length && uploader.features.dragdrop && uploader.settings.dragdrop) {
+						$('#' + id + '_filelist').append('<li class="plupload_droptext">' + _("Drag files here.") + '</li>');
+					}
+				}
+
+				function destroy() {
+					delete uploaders[id];
+					uploader.destroy();
+					target.html(contents_bak);
+					uploader = target = contents_bak = null;
+				}
+
+				uploader.bind("UploadFile", function(up, file) {
+					$('#' + file.id).addClass('plupload_current_file');
+				});
+
+				uploader.bind('Init', function(up, res) {
+					// Enable rename support
+					if (!settings.unique_names && settings.rename) {
+						target.on('click', '#' + id + '_filelist div.plupload_file_name span', function(e) {
+							var targetSpan = $(e.target), file, parts, name, ext = "";
+
+							// Get file name and split out name and extension
+							file = up.getFile(targetSpan.parents('li')[0].id);
+							name = file.name;
+							parts = /^(.+)(\.[^.]+)$/.exec(name);
+							if (parts) {
+								name = parts[1];
+								ext = parts[2];
+							}
+
+							// Display input element
+							targetSpan.hide().after('<input type="text" />');
+							targetSpan.next().val(name).focus().blur(function() {
+								targetSpan.show().next().remove();
+							}).keydown(function(e) {
+								var targetInput = $(this);
+
+								if (e.keyCode == 13) {
+									e.preventDefault();
+
+									// Rename file and glue extension back on
+									file.name = targetInput.val() + ext;
+									targetSpan.html(file.name);
+									targetInput.blur();
+								}
+							});
+						});
+					}
+
+					$('#' + id + '_container').attr('title', 'Using runtime: ' + res.runtime);
+
+					$('a.plupload_start', target).click(function(e) {
+						if (!$(this).hasClass('plupload_disabled')) {
+							uploader.start();
+						}
+
+						e.preventDefault();
+					});
+
+					$('a.plupload_stop', target).click(function(e) {
+						e.preventDefault();
+						uploader.stop();
+					});
+
+					$('a.plupload_start', target).addClass('plupload_disabled');
+				});
+
+				uploader.bind("Error", function(up, err) {
+					var file = err.file, message;
+
+					if (file) {
+						message = err.message;
+
+						if (err.details) {
+							message += " (" + err.details + ")";
+						}
+
+						if (err.code == plupload.FILE_SIZE_ERROR) {
+							alert(_("Error: File too large:") + " " + file.name);
+						}
+
+						if (err.code == plupload.FILE_EXTENSION_ERROR) {
+							alert(_("Error: Invalid file extension:") + " " + file.name);
+						}
+						
+						file.hint = message;
+						$('#' + file.id).attr('class', 'plupload_failed').find('a').css('display', 'block').attr('title', message);
+					}
+
+					if (err.code === plupload.INIT_ERROR) {
+						setTimeout(function() {
+							destroy();
+						}, 1);
+					}
+				});
+
+				uploader.bind("PostInit", function(up) {
+					// features are populated only after input components are fully instantiated
+					if (up.settings.dragdrop && up.features.dragdrop) {
+						$('#' + id + '_filelist').append('<li class="plupload_droptext">' + _("Drag files here.") + '</li>');
+					}
+				});
+
+				uploader.init();
+
+				uploader.bind('StateChanged', function() {
+					if (uploader.state === plupload.STARTED) {
+						$('li.plupload_delete a,div.plupload_buttons', target).hide();
+						uploader.disableBrowse(true);
+
+						$('span.plupload_upload_status,div.plupload_progress,a.plupload_stop', target).css('display', 'block');
+						$('span.plupload_upload_status', target).html('Uploaded ' + uploader.total.uploaded + '/' + uploader.files.length + ' files');
+
+						if (settings.multiple_queues) {
+							$('span.plupload_total_status,span.plupload_total_file_size', target).show();
+						}
+					} else {
+						updateList();
+						$('a.plupload_stop,div.plupload_progress', target).hide();
+						$('a.plupload_delete', target).css('display', 'block');
+
+						if (settings.multiple_queues && uploader.total.uploaded + uploader.total.failed == uploader.files.length) {
+							$(".plupload_buttons,.plupload_upload_status", target).css("display", "inline");
+							uploader.disableBrowse(false);
+
+							$(".plupload_start", target).addClass("plupload_disabled");
+							$('span.plupload_total_status,span.plupload_total_file_size', target).hide();
+						}
+					}
+				});
+
+				uploader.bind('FilesAdded', updateList);
+
+				uploader.bind('FilesRemoved', function() {
+					// since the whole file list is redrawn for every change in the queue
+					// we need to scroll back to the file removal point to avoid annoying
+					// scrolling to the bottom bug (see #926)
+					var scrollTop = $('#' + id + '_filelist').scrollTop();
+					updateList();
+					$('#' + id + '_filelist').scrollTop(scrollTop);
+				});
+
+				uploader.bind('FileUploaded', function(up, file) {
+					handleStatus(file);
+				});
+
+				uploader.bind("UploadProgress", function(up, file) {
+					// Set file specific progress
+					$('#' + file.id + ' div.plupload_file_status', target).html(file.percent + '%');
+
+					handleStatus(file);
+					updateTotalProgress();
+				});
+
+				// Call setup function
+				if (settings.setup) {
+					settings.setup(uploader);
+				}
+			});
+
+			return this;
+		} else {
+			// Get uploader instance for specified element
+			return uploaders[$(this[0]).attr('id')];
+		}
+	};
+})(jQuery, mOxie);
Index: /trunk/themes/default/js/plugins/plupload/jquery.plupload.queue/jquery.plupload.queue.min.js
===================================================================
--- /trunk/themes/default/js/plugins/plupload/jquery.plupload.queue/jquery.plupload.queue.min.js	(revision 28545)
+++ /trunk/themes/default/js/plugins/plupload/jquery.plupload.queue/jquery.plupload.queue.min.js	(revision 28545)
@@ -0,0 +1,1 @@
+;(function(e,t){function r(e){return plupload.translate(e)||e}function i(t,n){n.contents().each(function(t,n){n=e(n),n.is(".plupload")||n.remove()}),n.prepend('<div class="plupload_wrapper plupload_scroll"><div id="'+t+'_container" class="plupload_container">'+'<div class="plupload">'+'<div class="plupload_header">'+'<div class="plupload_header_content">'+'<div class="plupload_header_title">'+r("Select files")+"</div>"+'<div class="plupload_header_text">'+r("Add files to the upload queue and click the start button.")+"</div>"+"</div>"+"</div>"+'<div class="plupload_content">'+'<div class="plupload_filelist_header">'+'<div class="plupload_file_name">'+r("Filename")+"</div>"+'<div class="plupload_file_action">&nbsp;</div>'+'<div class="plupload_file_status"><span>'+r("Status")+"</span></div>"+'<div class="plupload_file_size">'+r("Size")+"</div>"+'<div class="plupload_clearer">&nbsp;</div>'+"</div>"+'<ul id="'+t+'_filelist" class="plupload_filelist"></ul>'+'<div class="plupload_filelist_footer">'+'<div class="plupload_file_name">'+'<div class="plupload_buttons">'+'<a href="#" class="plupload_button plupload_add" id="'+t+'_browse">'+r("Add Files")+"</a>"+'<a href="#" class="plupload_button plupload_start">'+r("Start Upload")+"</a>"+"</div>"+'<span class="plupload_upload_status"></span>'+"</div>"+'<div class="plupload_file_action"></div>'+'<div class="plupload_file_status"><span class="plupload_total_status">0%</span></div>'+'<div class="plupload_file_size"><span class="plupload_total_file_size">0 b</span></div>'+'<div class="plupload_progress">'+'<div class="plupload_progress_container">'+'<div class="plupload_progress_bar"></div>'+"</div>"+"</div>"+'<div class="plupload_clearer">&nbsp;</div>'+"</div>"+"</div>"+"</div>"+"</div>"+'<input type="hidden" id="'+t+'_count" name="'+t+'_count" value="0" />'+"</div>")}var n={};e.fn.pluploadQueue=function(s){return s?(this.each(function(){function c(t){var n;t.status==plupload.DONE&&(n="plupload_done"),t.status==plupload.FAILED&&(n="plupload_failed"),t.status==plupload.QUEUED&&(n="plupload_delete"),t.status==plupload.UPLOADING&&(n="plupload_uploading");var r=e("#"+t.id).attr("class",n).find("a").css("display","block");t.hint&&r.attr("title",t.hint)}function h(){e("span.plupload_total_status",a).html(u.total.percent+"%"),e("div.plupload_progress_bar",a).css("width",u.total.percent+"%"),e("span.plupload_upload_status",a).html(t.sprintf(r("Uploaded %d/%d files"),u.total.uploaded,u.files.length))}function p(){var n=e("ul.plupload_filelist",a).html(""),i=0,s;e.each(u.files,function(t,r){s="",r.status==plupload.DONE&&(r.target_name&&(s+='<input type="hidden" name="'+f+"_"+i+'_tmpname" value="'+plupload.xmlEncode(r.target_name)+'" />'),s+='<input type="hidden" name="'+f+"_"+i+'_name" value="'+plupload.xmlEncode(r.name)+'" />',s+='<input type="hidden" name="'+f+"_"+i+'_status" value="'+(r.status==plupload.DONE?"done":"failed")+'" />',i++,e("#"+f+"_count").val(i)),n.append('<li id="'+r.id+'">'+'<div class="plupload_file_name"><span>'+r.name+"</span></div>"+'<div class="plupload_file_action"><a href="#"></a></div>'+'<div class="plupload_file_status">'+r.percent+"%</div>"+'<div class="plupload_file_size">'+plupload.formatSize(r.size)+"</div>"+'<div class="plupload_clearer">&nbsp;</div>'+s+"</li>"),c(r),e("#"+r.id+".plupload_delete a").click(function(t){e("#"+r.id).remove(),u.removeFile(r),t.preventDefault()})}),e("span.plupload_total_file_size",a).html(plupload.formatSize(u.total.size)),u.total.queued===0?e("span.plupload_add_text",a).html(r("Add Files")):e("span.plupload_add_text",a).html(t.sprintf(r("%d files queued"),u.total.queued)),e("a.plupload_start",a).toggleClass("plupload_disabled",u.files.length==u.total.uploaded+u.total.failed),n[0].scrollTop=n[0].scrollHeight,h(),!u.files.length&&u.features.dragdrop&&u.settings.dragdrop&&e("#"+f+"_filelist").append('<li class="plupload_droptext">'+r("Drag files here.")+"</li>")}function d(){delete n[f],u.destroy(),a.html(l),u=a=l=null}var u,a,f,l;a=e(this),f=a.attr("id"),f||(f=plupload.guid(),a.attr("id",f)),l=a.html(),i(f,a),s=e.extend({dragdrop:!0,browse_button:f+"_browse",container:f},s),s.dragdrop&&(s.drop_element=f+"_filelist"),u=new plupload.Uploader(s),n[f]=u,u.bind("UploadFile",function(t,n){e("#"+n.id).addClass("plupload_current_file")}),u.bind("Init",function(t,n){!s.unique_names&&s.rename&&a.on("click","#"+f+"_filelist div.plupload_file_name span",function(n){var r=e(n.target),i,s,o,u="";i=t.getFile(r.parents("li")[0].id),o=i.name,s=/^(.+)(\.[^.]+)$/.exec(o),s&&(o=s[1],u=s[2]),r.hide().after('<input type="text" />'),r.next().val(o).focus().blur(function(){r.show().next().remove()}).keydown(function(t){var n=e(this);t.keyCode==13&&(t.preventDefault(),i.name=n.val()+u,r.html(i.name),n.blur())})}),e("#"+f+"_container").attr("title","Using runtime: "+n.runtime),e("a.plupload_start",a).click(function(t){e(this).hasClass("plupload_disabled")||u.start(),t.preventDefault()}),e("a.plupload_stop",a).click(function(e){e.preventDefault(),u.stop()}),e("a.plupload_start",a).addClass("plupload_disabled")}),u.bind("Error",function(t,n){var i=n.file,s;i&&(s=n.message,n.details&&(s+=" ("+n.details+")"),n.code==plupload.FILE_SIZE_ERROR&&alert(r("Error: File too large:")+" "+i.name),n.code==plupload.FILE_EXTENSION_ERROR&&alert(r("Error: Invalid file extension:")+" "+i.name),i.hint=s,e("#"+i.id).attr("class","plupload_failed").find("a").css("display","block").attr("title",s)),n.code===plupload.INIT_ERROR&&setTimeout(function(){d()},1)}),u.bind("PostInit",function(t){t.settings.dragdrop&&t.features.dragdrop&&e("#"+f+"_filelist").append('<li class="plupload_droptext">'+r("Drag files here.")+"</li>")}),u.init(),u.bind("StateChanged",function(){u.state===plupload.STARTED?(e("li.plupload_delete a,div.plupload_buttons",a).hide(),u.disableBrowse(!0),e("span.plupload_upload_status,div.plupload_progress,a.plupload_stop",a).css("display","block"),e("span.plupload_upload_status",a).html("Uploaded "+u.total.uploaded+"/"+u.files.length+" files"),s.multiple_queues&&e("span.plupload_total_status,span.plupload_total_file_size",a).show()):(p(),e("a.plupload_stop,div.plupload_progress",a).hide(),e("a.plupload_delete",a).css("display","block"),s.multiple_queues&&u.total.uploaded+u.total.failed==u.files.length&&(e(".plupload_buttons,.plupload_upload_status",a).css("display","inline"),u.disableBrowse(!1),e(".plupload_start",a).addClass("plupload_disabled"),e("span.plupload_total_status,span.plupload_total_file_size",a).hide()))}),u.bind("FilesAdded",p),u.bind("FilesRemoved",function(){var t=e("#"+f+"_filelist").scrollTop();p(),e("#"+f+"_filelist").scrollTop(t)}),u.bind("FileUploaded",function(e,t){c(t)}),u.bind("UploadProgress",function(t,n){e("#"+n.id+" div.plupload_file_status",a).html(n.percent+"%"),c(n),h()}),s.setup&&s.setup(u)}),this):n[e(this[0]).attr("id")]}})(jQuery,mOxie);
Index: /trunk/themes/default/js/plugins/plupload/jquery.ui.plupload/css/jquery.ui.plupload.css
===================================================================
--- /trunk/themes/default/js/plugins/plupload/jquery.ui.plupload/css/jquery.ui.plupload.css	(revision 28545)
+++ /trunk/themes/default/js/plugins/plupload/jquery.ui.plupload/css/jquery.ui.plupload.css	(revision 28545)
@@ -0,0 +1,371 @@
+/*
+   Plupload
+------------------------------------------------------------------- */
+
+.plupload_wrapper * {
+	box-sizing: content-box;
+}
+
+.plupload_button {
+	cursor: pointer;
+	outline: none;
+}
+
+.plupload_wrapper {
+	font: normal 11px Verdana,sans-serif;
+	width: 100%;
+	min-width: 520px;
+	line-height: 12px;
+}
+
+.plupload_container {
+	_height: 300px;
+	min-height: 300px;
+	position: relative;
+}
+
+.plupload_filelist_footer {border-width: 1px 0 0 0}
+.plupload_file {border-width: 0 0 1px 0}
+.plupload_container .plupload_header {border-width: 0 0 1px 0; position: relative;}
+
+.plupload_delete .ui-icon, 
+.plupload_done .ui-icon,
+.plupload_failed .ui-icon {
+	cursor:pointer;	
+}
+
+.plupload_header_content {
+	height: 56px;
+	padding: 0 160px 0 60px;
+	position: relative;
+}
+
+.plupload_logo {
+  display:none;
+	width: 40px;
+	height: 40px;
+	background: url('../img/plupload.png') no-repeat 0 0;
+	position: absolute;
+	top: 8px;
+	left: 8px;
+}
+
+.plupload_header_content_bw .plupload_logo {
+	background-position: -40px 0;
+}
+
+.plupload_header_title {
+	font: normal 18px sans-serif;
+	line-height: 19px;
+	padding: 6px 0 3px;
+}
+
+.plupload_header_text {
+	font: normal 12px sans-serif;
+}
+
+.plupload_view_switch {
+	position: absolute;
+	right: 16px;
+	bottom: 8px;
+	margin: 0;
+	display: none;
+}
+
+.plupload_view_switch .ui-button {
+	margin-right: -0.31em;
+}
+
+.plupload_content {
+	position: absolute;
+	top: 86px;
+	bottom: 44px;
+	left: 0;
+	right: 0;
+	overflow-y: auto;
+	width: 100%;
+}
+
+.plupload_filelist {
+	border-collapse: collapse;
+	border-left: none;
+	border-right: none;
+	margin: 0;
+	padding: 0;
+	width: 100%;
+	-moz-user-select: none;
+	-webkit-user-select: none;
+	user-select: none;
+}
+
+.plupload_filelist_content {
+	padding: 0;
+	margin: 0;
+}
+
+.plupload_cell {padding: 8px 6px;}
+
+.plupload_file {
+	list-style: none;
+	display: block;
+	position: relative;
+	overflow: hidden;
+	line-height: 12px;
+}
+
+.plupload_file_thumb {
+	position: relative;
+	background-image: none;
+	background-color: #eee;
+}
+
+.plupload_file_loading .plupload_file_thumb {
+	background: #eee url(../img/loading.gif) center no-repeat;
+}
+
+.plupload_file_name {
+	overflow: hidden;
+	text-overflow: ellipsis;
+	white-space: nowrap;
+}
+
+.plupload_filelist_header {
+	border-top: none;
+}
+
+.plupload_filelist_footer {
+	position: absolute;
+	bottom: 0;
+	left: 0;
+	right: 0;
+}
+
+.plupload_buttons { 
+	position: relative;
+}
+
+/* list view */
+.plupload_view_list .plupload_file {
+	border-left: none;
+	border-right: none;
+	border-top: none;
+	height: 29px;
+	width: 100% !important;
+	/* fix IE6 vertical white-space bug */
+	_float: left;
+	_clear: left;
+}
+
+.plupload_view_list div.plupload_file_size, 
+.plupload_view_list div.plupload_file_status,
+.plupload_view_list div.plupload_file_action {
+	padding: 8px 6px;
+	position: absolute;
+	top: 0;
+	right: 0;
+}
+
+.plupload_view_list div.plupload_file_name {
+	margin-right: 156px;
+	padding: 8px 6px;
+	_width: 75%;
+}
+
+.plupload_view_list div.plupload_file_size {
+	right: 28px;
+}
+
+.plupload_view_list div.plupload_file_status {
+	right: 82px;
+}
+
+.plupload_view_list .plupload_file_rename {
+	margin-left: -2px;
+}
+
+.plupload_view_list .plupload_file_size, 
+.plupload_view_list .plupload_file_status,
+.plupload_filelist_footer .plupload_file_size, 
+.plupload_filelist_footer .plupload_file_status {
+	text-align: right; 
+	width: 52px;
+}
+
+.plupload_view_list .plupload_file_thumb {
+	position: absolute;
+	top: -999px;
+}
+
+.plupload_view_list .plupload_file_progress {
+	display: none;
+}
+
+
+/* thumbs view */
+.plupload_view_thumbs .plupload_content {
+	top: 57px;
+}
+
+.plupload_view_thumbs .plupload_filelist_header {
+	display: none;
+}
+
+.plupload_view_thumbs .plupload_file {
+	padding: 16px;
+	margin: 10px;
+	border: 1px solid #fff;
+	float: left;
+}
+
+.plupload_view_thumbs .plupload_file_thumb,
+.plupload_view_thumbs .plupload_file_dummy {
+	text-align: center;
+	overflow: hidden;
+}
+
+.plupload_view_thumbs .plupload_file_dummy {
+	font-size: 21px;
+	font-weight: bold;
+	text-transform: lowercase;
+	overflow: hidden;
+	border: none;
+	position: absolute;
+	top: 0;
+	left: 0;
+	width: 100%;
+	height: 100%;
+}
+
+.plupload_view_thumbs div.plupload_file_action {
+	position: absolute;
+	top: 0;
+	right: 0;
+}
+
+.plupload_view_thumbs div.plupload_file_name {
+	padding: 0;
+	font-weight: bold;
+}
+
+.plupload_view_thumbs .plupload_file_rename {
+	padding: 1px 0;
+	width: 100% !important;
+}
+
+.plupload_view_thumbs div.plupload_file_size {
+	font-size: 0.8em;
+	font-weight: normal;
+}
+
+.plupload_view_thumbs div.plupload_file_status {
+	position: relative;	
+	height: 3px;
+	overflow: hidden;
+	text-indent: -999px;
+	margin-bottom: 3px;
+}
+
+.plupload_view_thumbs div.plupload_file_progress {
+	border: none;
+	height: 100%;
+}
+
+.plupload .ui-sortable-helper,
+.plupload .ui-sortable .plupload_file {
+	cursor:move;	
+}
+
+.plupload_file_action {width: 16px;}
+.plupload_file_name {
+	overflow: hidden;
+	padding-left: 10px;
+}
+
+.plupload_file_rename {
+	border: none;
+	font: normal 11px Verdana, sans-serif;
+	padding: 1px 2px;
+	line-height: 11px;
+	height: 11px;
+}
+
+.plupload_progress {width: 60px;}
+.plupload_progress_container {padding: 1px;}
+
+
+/* Floats */
+
+.plupload_right {float: right;}
+.plupload_left {float: left;}
+.plupload_clear,.plupload_clearer {clear: both;}
+.plupload_clearer, .plupload_progress_bar {
+	display: block;
+	font-size: 0;
+	line-height: 0;
+}
+.plupload_clearer {height: 0;}
+
+/* Misc */
+.plupload_hidden {display: none !important;}
+
+.plupload_droptext {
+	position: absolute;
+	top: 0;
+	left: 0;
+	right: 0;
+	bottom: 0;
+	background: transparent;
+	text-align: center;
+	vertical-align: middle;
+	border: 0;
+	line-height: 160px;
+	display: none;
+}
+
+.plupload_dropbox .plupload_droptext {
+	display: block;
+}
+
+.plupload_buttons, .plupload_upload_status {float: left}
+
+.plupload_message {
+	position: absolute;
+	top: -1px;
+	left: -1px;	
+	height: 100%;
+	width: 100%;
+}
+
+.plupload_message p {
+	padding:0.7em;
+	margin:0;
+}
+
+.plupload_message strong {
+	font-weight: bold;	
+}
+
+plupload_message i {
+	font-style: italic;	
+}
+
+.plupload_message p span.ui-icon {
+	float: left;
+	margin-right: 0.3em;	
+}
+
+.plupload_header_content .ui-state-error,
+.plupload_header_content .ui-state-highlight {
+	border:none;	
+}
+
+.plupload_message_close {
+	position:absolute;
+	top:5px;
+	right:5px;
+	cursor:pointer;	
+}
+
+.plupload .ui-sortable-placeholder {
+	height:35px;
+}
Index: /trunk/themes/default/js/plugins/plupload/jquery.ui.plupload/css/jquery.ui.plupload.css.orig
===================================================================
--- /trunk/themes/default/js/plugins/plupload/jquery.ui.plupload/css/jquery.ui.plupload.css.orig	(revision 28545)
+++ /trunk/themes/default/js/plugins/plupload/jquery.ui.plupload/css/jquery.ui.plupload.css.orig	(revision 28545)
@@ -0,0 +1,370 @@
+/*
+   Plupload
+------------------------------------------------------------------- */
+
+.plupload_wrapper * {
+	box-sizing: content-box;
+}
+
+.plupload_button {
+	cursor: pointer;
+	outline: none;
+}
+
+.plupload_wrapper {
+	font: normal 11px Verdana,sans-serif;
+	width: 100%;
+	min-width: 520px;
+	line-height: 12px;
+}
+
+.plupload_container {
+	_height: 300px;
+	min-height: 300px;
+	position: relative;
+}
+
+.plupload_filelist_footer {border-width: 1px 0 0 0}
+.plupload_file {border-width: 0 0 1px 0}
+.plupload_container .plupload_header {border-width: 0 0 1px 0; position: relative;}
+
+.plupload_delete .ui-icon, 
+.plupload_done .ui-icon,
+.plupload_failed .ui-icon {
+	cursor:pointer;	
+}
+
+.plupload_header_content {
+	height: 56px;
+	padding: 0 160px 0 60px;
+	position: relative;
+}
+
+.plupload_logo {
+	width: 40px;
+	height: 40px;
+	background: url('../img/plupload.png') no-repeat 0 0;
+	position: absolute;
+	top: 8px;
+	left: 8px;
+}
+
+.plupload_header_content_bw .plupload_logo {
+	background-position: -40px 0;
+}
+
+.plupload_header_title {
+	font: normal 18px sans-serif;
+	line-height: 19px;
+	padding: 6px 0 3px;
+}
+
+.plupload_header_text {
+	font: normal 12px sans-serif;
+}
+
+.plupload_view_switch {
+	position: absolute;
+	right: 16px;
+	bottom: 8px;
+	margin: 0;
+	display: none;
+}
+
+.plupload_view_switch .ui-button {
+	margin-right: -0.31em;
+}
+
+.plupload_content {
+	position: absolute;
+	top: 86px;
+	bottom: 44px;
+	left: 0;
+	right: 0;
+	overflow-y: auto;
+	width: 100%;
+}
+
+.plupload_filelist {
+	border-collapse: collapse;
+	border-left: none;
+	border-right: none;
+	margin: 0;
+	padding: 0;
+	width: 100%;
+	-moz-user-select: none;
+	-webkit-user-select: none;
+	user-select: none;
+}
+
+.plupload_filelist_content {
+	padding: 0;
+	margin: 0;
+}
+
+.plupload_cell {padding: 8px 6px;}
+
+.plupload_file {
+	list-style: none;
+	display: block;
+	position: relative;
+	overflow: hidden;
+	line-height: 12px;
+}
+
+.plupload_file_thumb {
+	position: relative;
+	background-image: none;
+	background-color: #eee;
+}
+
+.plupload_file_loading .plupload_file_thumb {
+	background: #eee url(../img/loading.gif) center no-repeat;
+}
+
+.plupload_file_name {
+	overflow: hidden;
+	text-overflow: ellipsis;
+	white-space: nowrap;
+}
+
+.plupload_filelist_header {
+	border-top: none;
+}
+
+.plupload_filelist_footer {
+	position: absolute;
+	bottom: 0;
+	left: 0;
+	right: 0;
+}
+
+.plupload_buttons { 
+	position: relative;
+}
+
+/* list view */
+.plupload_view_list .plupload_file {
+	border-left: none;
+	border-right: none;
+	border-top: none;
+	height: 29px;
+	width: 100% !important;
+	/* fix IE6 vertical white-space bug */
+	_float: left;
+	_clear: left;
+}
+
+.plupload_view_list div.plupload_file_size, 
+.plupload_view_list div.plupload_file_status,
+.plupload_view_list div.plupload_file_action {
+	padding: 8px 6px;
+	position: absolute;
+	top: 0;
+	right: 0;
+}
+
+.plupload_view_list div.plupload_file_name {
+	margin-right: 156px;
+	padding: 8px 6px;
+	_width: 75%;
+}
+
+.plupload_view_list div.plupload_file_size {
+	right: 28px;
+}
+
+.plupload_view_list div.plupload_file_status {
+	right: 82px;
+}
+
+.plupload_view_list .plupload_file_rename {
+	margin-left: -2px;
+}
+
+.plupload_view_list .plupload_file_size, 
+.plupload_view_list .plupload_file_status,
+.plupload_filelist_footer .plupload_file_size, 
+.plupload_filelist_footer .plupload_file_status {
+	text-align: right; 
+	width: 52px;
+}
+
+.plupload_view_list .plupload_file_thumb {
+	position: absolute;
+	top: -999px;
+}
+
+.plupload_view_list .plupload_file_progress {
+	display: none;
+}
+
+
+/* thumbs view */
+.plupload_view_thumbs .plupload_content {
+	top: 57px;
+}
+
+.plupload_view_thumbs .plupload_filelist_header {
+	display: none;
+}
+
+.plupload_view_thumbs .plupload_file {
+	padding: 16px;
+	margin: 10px;
+	border: 1px solid #fff;
+	float: left;
+}
+
+.plupload_view_thumbs .plupload_file_thumb,
+.plupload_view_thumbs .plupload_file_dummy {
+	text-align: center;
+	overflow: hidden;
+}
+
+.plupload_view_thumbs .plupload_file_dummy {
+	font-size: 21px;
+	font-weight: bold;
+	text-transform: lowercase;
+	overflow: hidden;
+	border: none;
+	position: absolute;
+	top: 0;
+	left: 0;
+	width: 100%;
+	height: 100%;
+}
+
+.plupload_view_thumbs div.plupload_file_action {
+	position: absolute;
+	top: 0;
+	right: 0;
+}
+
+.plupload_view_thumbs div.plupload_file_name {
+	padding: 0;
+	font-weight: bold;
+}
+
+.plupload_view_thumbs .plupload_file_rename {
+	padding: 1px 0;
+	width: 100% !important;
+}
+
+.plupload_view_thumbs div.plupload_file_size {
+	font-size: 0.8em;
+	font-weight: normal;
+}
+
+.plupload_view_thumbs div.plupload_file_status {
+	position: relative;	
+	height: 3px;
+	overflow: hidden;
+	text-indent: -999px;
+	margin-bottom: 3px;
+}
+
+.plupload_view_thumbs div.plupload_file_progress {
+	border: none;
+	height: 100%;
+}
+
+.plupload .ui-sortable-helper,
+.plupload .ui-sortable .plupload_file {
+	cursor:move;	
+}
+
+.plupload_file_action {width: 16px;}
+.plupload_file_name {
+	overflow: hidden;
+	padding-left: 10px;
+}
+
+.plupload_file_rename {
+	border: none;
+	font: normal 11px Verdana, sans-serif;
+	padding: 1px 2px;
+	line-height: 11px;
+	height: 11px;
+}
+
+.plupload_progress {width: 60px;}
+.plupload_progress_container {padding: 1px;}
+
+
+/* Floats */
+
+.plupload_right {float: right;}
+.plupload_left {float: left;}
+.plupload_clear,.plupload_clearer {clear: both;}
+.plupload_clearer, .plupload_progress_bar {
+	display: block;
+	font-size: 0;
+	line-height: 0;
+}
+.plupload_clearer {height: 0;}
+
+/* Misc */
+.plupload_hidden {display: none !important;}
+
+.plupload_droptext {
+	position: absolute;
+	top: 0;
+	left: 0;
+	right: 0;
+	bottom: 0;
+	background: transparent;
+	text-align: center;
+	vertical-align: middle;
+	border: 0;
+	line-height: 160px;
+	display: none;
+}
+
+.plupload_dropbox .plupload_droptext {
+	display: block;
+}
+
+.plupload_buttons, .plupload_upload_status {float: left}
+
+.plupload_message {
+	position: absolute;
+	top: -1px;
+	left: -1px;	
+	height: 100%;
+	width: 100%;
+}
+
+.plupload_message p {
+	padding:0.7em;
+	margin:0;
+}
+
+.plupload_message strong {
+	font-weight: bold;	
+}
+
+plupload_message i {
+	font-style: italic;	
+}
+
+.plupload_message p span.ui-icon {
+	float: left;
+	margin-right: 0.3em;	
+}
+
+.plupload_header_content .ui-state-error,
+.plupload_header_content .ui-state-highlight {
+	border:none;	
+}
+
+.plupload_message_close {
+	position:absolute;
+	top:5px;
+	right:5px;
+	cursor:pointer;	
+}
+
+.plupload .ui-sortable-placeholder {
+	height:35px;
+}
Index: /trunk/themes/default/js/plugins/plupload/jquery.ui.plupload/jquery.ui.plupload.js
===================================================================
--- /trunk/themes/default/js/plugins/plupload/jquery.ui.plupload/jquery.ui.plupload.js	(revision 28545)
+++ /trunk/themes/default/js/plugins/plupload/jquery.ui.plupload/jquery.ui.plupload.js	(revision 28545)
@@ -0,0 +1,1323 @@
+/**
+ * jquery.ui.plupload.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ *
+ * Depends:
+ *	jquery.ui.core.js
+ *	jquery.ui.widget.js
+ *	jquery.ui.button.js
+ *	jquery.ui.progressbar.js
+ *	
+ * Optionally:
+ *	jquery.ui.sortable.js
+ */
+
+ /* global jQuery:true */
+
+/**
+jQuery UI based implementation of the Plupload API - multi-runtime file uploading API.
+
+To use the widget you must include _jQuery_ and _jQuery UI_ bundle (including `ui.core`, `ui.widget`, `ui.button`, 
+`ui.progressbar` and `ui.sortable`).
+
+In general the widget is designed the way that you do not usually need to do anything to it after you instantiate it. 
+But! You still can intervenue, to some extent, in case you need to. Although, due to the fact that widget is based on 
+_jQuery UI_ widget factory, there are some specifics. See examples below for more details.
+
+@example
+	<!-- Instantiating: -->
+	<div id="uploader">
+		<p>Your browser doesn't have Flash, Silverlight or HTML5 support.</p>
+	</div>
+
+	<script>
+		$('#uploader').plupload({
+			url : '../upload.php',
+			filters : [
+				{title : "Image files", extensions : "jpg,gif,png"}
+			],
+			rename: true,
+			sortable: true,
+			flash_swf_url : '../../js/Moxie.swf',
+			silverlight_xap_url : '../../js/Moxie.xap',
+		});
+	</script>
+
+@example
+	// Invoking methods:
+	$('#uploader').plupload(options);
+
+	// Display welcome message in the notification area
+	$('#uploader').plupload('notify', 'info', "This might be obvious, but you need to click 'Add Files' to add some files.");
+
+@example
+	// Subscribing to the events...
+	// ... on initialization:
+	$('#uploader').plupload({ 
+		...
+		viewchanged: function(event, args) {
+			// stuff ...
+		}
+	});
+	// ... or after initialization
+	$('#uploader').on("viewchanged", function(event, args) {
+		// stuff ...
+	});
+
+@class UI.Plupload
+@constructor
+@param {Object} settings For detailed information about each option check documentation.
+	@param {String} settings.url URL of the server-side upload handler.
+	@param {Number|String} [settings.chunk_size=0] Chunk size in bytes to slice the file into. Shorcuts with b, kb, mb, gb, tb suffixes also supported. `e.g. 204800 or "204800b" or "200kb"`. By default - disabled.
+	@param {String} [settings.file_data_name="file"] Name for the file field in Multipart formated message.
+	@param {Object} [settings.filters={}] Set of file type filters.
+		@param {Array} [settings.filters.mime_types=[]] List of file types to accept, each one defined by title and list of extensions. `e.g. {title : "Image files", extensions : "jpg,jpeg,gif,png"}`. Dispatches `plupload.FILE_EXTENSION_ERROR`
+		@param {String|Number} [settings.filters.max_file_size=0] Maximum file size that the user can pick, in bytes. Optionally supports b, kb, mb, gb, tb suffixes. `e.g. "10mb" or "1gb"`. By default - not set. Dispatches `plupload.FILE_SIZE_ERROR`.
+		@param {Boolean} [settings.filters.prevent_duplicates=false] Do not let duplicates into the queue. Dispatches `plupload.FILE_DUPLICATE_ERROR`.
+		@param {Number} [settings.filters.max_file_count=0] Limit the number of files that can reside in the queue at the same time (default is 0 - no limit).
+	@param {String} [settings.flash_swf_url] URL of the Flash swf.
+	@param {Object} [settings.headers] Custom headers to send with the upload. Hash of name/value pairs.
+	@param {Number|String} [settings.max_file_size] Maximum file size that the user can pick, in bytes. Optionally supports b, kb, mb, gb, tb suffixes. `e.g. "10mb" or "1gb"`. By default - not set. Dispatches `plupload.FILE_SIZE_ERROR`.
+	@param {Number} [settings.max_retries=0] How many times to retry the chunk or file, before triggering Error event.
+	@param {Boolean} [settings.multipart=true] Whether to send file and additional parameters as Multipart formated message.
+	@param {Object} [settings.multipart_params] Hash of key/value pairs to send with every file upload.
+	@param {Boolean} [settings.multi_selection=true] Enable ability to select multiple files at once in file dialog.
+	@param {Boolean} [settings.prevent_duplicates=false] Do not let duplicates into the queue. Dispatches `plupload.FILE_DUPLICATE_ERROR`.
+	@param {String|Object} [settings.required_features] Either comma-separated list or hash of required features that chosen runtime should absolutely possess.
+	@param {Object} [settings.resize] Enable resizng of images on client-side. Applies to `image/jpeg` and `image/png` only. `e.g. {width : 200, height : 200, quality : 90, crop: true}`
+		@param {Number} [settings.resize.width] If image is bigger, it will be resized.
+		@param {Number} [settings.resize.height] If image is bigger, it will be resized.
+		@param {Number} [settings.resize.quality=90] Compression quality for jpegs (1-100).
+		@param {Boolean} [settings.resize.crop=false] Whether to crop images to exact dimensions. By default they will be resized proportionally.
+	@param {String} [settings.runtimes="html5,flash,silverlight,html4"] Comma separated list of runtimes, that Plupload will try in turn, moving to the next if previous fails.
+	@param {String} [settings.silverlight_xap_url] URL of the Silverlight xap.
+	@param {Boolean} [settings.unique_names=false] If true will generate unique filenames for uploaded files.
+
+	@param {Boolean} [settings.autostart=false] Whether to auto start uploading right after file selection.
+	@param {Boolean} [settings.dragdrop=true] Enable ability to add file to the queue by drag'n'dropping them from the desktop.
+	@param {Boolean} [settings.rename=false] Enable ability to rename files in the queue.
+	@param {Boolean} [settings.sortable=false] Enable ability to sort files in the queue, changing their uploading priority.
+	@param {Object} [settings.buttons] Control the visibility of functional buttons. 
+		@param {Boolean} [settings.buttons.browse=true] Display browse button.
+		@param {Boolean} [settings.buttons.start=true] Display start button.
+		@param {Boolean} [settings.buttons.stop=true] Display stop button. 
+	@param {Object} [settings.views] Control various views of the file queue.
+		@param {Boolean} [settings.views.list=true] Enable list view.
+		@param {Boolean} [settings.views.thumbs=false] Enable thumbs view.
+		@param {String} [settings.views.default='list'] Default view.
+		@param {Boolean} [settings.views.remember=true] Whether to remember the current view (requires jQuery Cookie plugin).
+	@param {Boolean} [settings.multiple_queues=true] Re-activate the widget after each upload procedure.
+*/
+;(function(window, document, plupload, o, $) {
+
+/**
+Dispatched when the widget is initialized and ready.
+
+@event ready
+@param {plupload.Uploader} uploader Uploader instance sending the event.
+*/
+
+/**
+Dispatched when file dialog is closed.
+
+@event selected
+@param {plupload.Uploader} uploader Uploader instance sending the event.
+@param {Array} files Array of selected files represented by plupload.File objects
+*/
+
+/**
+Dispatched when file dialog is closed.
+
+@event removed
+@param {plupload.Uploader} uploader Uploader instance sending the event.
+@param {Array} files Array of removed files represented by plupload.File objects
+*/
+
+/**
+Dispatched when upload is started.
+
+@event start
+@param {plupload.Uploader} uploader Uploader instance sending the event.
+*/
+
+/**
+Dispatched when upload is stopped.
+
+@event stop
+@param {plupload.Uploader} uploader Uploader instance sending the event.
+*/
+
+/**
+Dispatched during the upload process.
+
+@event progress
+@param {plupload.Uploader} uploader Uploader instance sending the event.
+@param {plupload.File} file File that is being uploaded (includes loaded and percent properties among others).
+	@param {Number} size Total file size in bytes.
+	@param {Number} loaded Number of bytes uploaded of the files total size.
+	@param {Number} percent Number of percentage uploaded of the file.
+*/
+
+/**
+Dispatched when file is uploaded.
+
+@event uploaded
+@param {plupload.Uploader} uploader Uploader instance sending the event.
+@param {plupload.File} file File that was uploaded.
+	@param {Enum} status Status constant matching the plupload states QUEUED, UPLOADING, FAILED, DONE.
+*/
+
+/**
+Dispatched when upload of the whole queue is complete.
+
+@event complete
+@param {plupload.Uploader} uploader Uploader instance sending the event.
+@param {Array} files Array of uploaded files represented by plupload.File objects
+*/
+
+/**
+Dispatched when the view is changed, e.g. from `list` to `thumbs` or vice versa.
+
+@event viewchanged
+@param {plupload.Uploader} uploader Uploader instance sending the event.
+@param {String} type Current view type.
+*/
+
+/**
+Dispatched when error of some kind is detected.
+
+@event error
+@param {plupload.Uploader} uploader Uploader instance sending the event.
+@param {String} error Error message.
+@param {plupload.File} file File that was uploaded.
+	@param {Enum} status Status constant matching the plupload states QUEUED, UPLOADING, FAILED, DONE.
+*/
+
+var uploaders = {};	
+	
+function _(str) {
+	return plupload.translate(str) || str;
+}
+
+function renderUI(obj) {		
+	obj.id = obj.attr('id');
+
+	obj.html(
+		'<div class="plupload_wrapper">' +
+			'<div class="ui-widget-content plupload_container">' +
+				'<div class="ui-state-default ui-widget-header plupload_header">' +
+					'<div class="plupload_header_content">' +
+						'<div class="plupload_logo"> </div>' +
+						'<div class="plupload_header_title">' + _("Select files") + '</div>' +
+						'<div class="plupload_header_text">' + _("Add files to the upload queue and click the start button.") + '</div>' +
+						'<div class="plupload_view_switch">' +
+							'<input type="radio" id="'+obj.id+'_view_list" name="view_mode_'+obj.id+'" checked="checked" /><label class="plupload_button" for="'+obj.id+'_view_list" data-view="list">' + _('List') + '</label>' +
+							'<input type="radio" id="'+obj.id+'_view_thumbs" name="view_mode_'+obj.id+'" /><label class="plupload_button"  for="'+obj.id+'_view_thumbs" data-view="thumbs">' + _('Thumbnails') + '</label>' +
+						'</div>' +
+					'</div>' +
+				'</div>' +
+
+				'<table class="plupload_filelist plupload_filelist_header ui-widget-header">' +
+				'<tr>' +
+					'<td class="plupload_cell plupload_file_name">' + _('Filename') + '</td>' +
+					'<td class="plupload_cell plupload_file_status">' + _('Status') + '</td>' +
+					'<td class="plupload_cell plupload_file_size">' + _('Size') + '</td>' +
+					'<td class="plupload_cell plupload_file_action">&nbsp;</td>' +
+				'</tr>' +
+				'</table>' +
+
+				'<div class="plupload_content">' +
+					'<div class="plupload_droptext">' + _("Drag files here.") + '</div>' +
+					'<ul class="plupload_filelist_content"> </ul>' +
+					'<div class="plupload_clearer">&nbsp;</div>' +
+				'</div>' +
+					
+				'<table class="plupload_filelist plupload_filelist_footer ui-widget-header">' +
+				'<tr>' +
+					'<td class="plupload_cell plupload_file_name">' +
+						'<div class="plupload_buttons"><!-- Visible -->' +
+							'<a class="plupload_button plupload_add">' + _("Add Files") + '</a>&nbsp;' +
+							'<a class="plupload_button plupload_start">' + _("Start Upload") + '</a>&nbsp;' +
+							'<a class="plupload_button plupload_stop plupload_hidden">'+_("Stop Upload") + '</a>&nbsp;' +
+						'</div>' +
+
+						'<div class="plupload_started plupload_hidden"><!-- Hidden -->' +
+							'<div class="plupload_progress plupload_right">' +
+								'<div class="plupload_progress_container"></div>' +
+							'</div>' +
+
+							'<div class="plupload_cell plupload_upload_status"></div>' +
+
+							'<div class="plupload_clearer">&nbsp;</div>' +
+						'</div>' +
+					'</td>' +
+					'<td class="plupload_file_status"><span class="plupload_total_status">0%</span></td>' +
+					'<td class="plupload_file_size"><span class="plupload_total_file_size">0 kb</span></td>' +
+					'<td class="plupload_file_action"></td>' +
+				'</tr>' +
+				'</table>' +
+
+			'</div>' +
+			'<input class="plupload_count" value="0" type="hidden">' +
+		'</div>'
+	);
+}
+
+
+$.widget("ui.plupload", {
+
+	widgetEventPrefix: '',
+	
+	contents_bak: '',
+		
+	options: {
+		browse_button_hover: 'ui-state-hover',
+		browse_button_active: 'ui-state-active',
+
+		filters: {},
+		
+		// widget specific
+		buttons: {
+			browse: true,
+			start: true,
+			stop: true	
+		},
+		
+		views: {
+			list: true,
+			thumbs: false,
+			active: 'list',
+			remember: true // requires: https://github.com/carhartl/jquery-cookie, otherwise disabled even if set to true
+		},
+
+		thumb_width: 100,
+		thumb_height: 60,
+
+		multiple_queues: true, // re-use widget by default
+		dragdrop : true, 
+		autostart: false,
+		sortable: false,
+		rename: false
+	},
+	
+	FILE_COUNT_ERROR: -9001,
+	
+	_create: function() {
+		var id = this.element.attr('id');
+		if (!id) {
+			id = plupload.guid();
+			this.element.attr('id', id);
+		}
+		this.id = id;
+				
+		// backup the elements initial state
+		this.contents_bak = this.element.html();
+		renderUI(this.element);
+		
+		// container, just in case
+		this.container = $('.plupload_container', this.element).attr('id', id + '_container');	
+
+		this.content = $('.plupload_content', this.element);
+		
+		if ($.fn.resizable) {
+			this.container.resizable({ 
+				handles: 's',
+				minHeight: 300
+			});
+		}
+		
+		// list of files, may become sortable
+		this.filelist = $('.plupload_filelist_content', this.container)
+			.attr({
+				id: id + '_filelist',
+				unselectable: 'on'
+			});
+		
+
+		// buttons
+		this.browse_button = $('.plupload_add', this.container).attr('id', id + '_browse');
+		this.start_button = $('.plupload_start', this.container).attr('id', id + '_start');
+		this.stop_button = $('.plupload_stop', this.container).attr('id', id + '_stop');
+		this.thumbs_switcher = $('#' + id + '_view_thumbs');
+		this.list_switcher = $('#' + id + '_view_list');
+		
+		if ($.ui.button) {
+			this.browse_button.button({
+				icons: { primary: 'ui-icon-circle-plus' },
+				disabled: true
+			});
+			
+			this.start_button.button({
+				icons: { primary: 'ui-icon-circle-arrow-e' },
+				disabled: true
+			});
+			
+			this.stop_button.button({
+				icons: { primary: 'ui-icon-circle-close' }
+			});
+      
+			this.list_switcher.button({
+				text: false,
+				icons: { secondary: "ui-icon-grip-dotted-horizontal" }
+			});
+
+			this.thumbs_switcher.button({
+				text: false,
+				icons: { secondary: "ui-icon-image" }
+			});
+		}
+		
+		// progressbar
+		this.progressbar = $('.plupload_progress_container', this.container);		
+		
+		if ($.ui.progressbar) {
+			this.progressbar.progressbar();
+		}
+		
+		// counter
+		this.counter = $('.plupload_count', this.element)
+			.attr({
+				id: id + '_count',
+				name: id + '_count'
+			});
+					
+		// initialize uploader instance
+		this._initUploader();
+	},
+
+	_initUploader: function() {
+		var self = this
+		, id = this.id
+		, uploader
+		, options = { 
+			container: id + '_buttons',
+			browse_button: id + '_browse'
+		}
+		;
+
+		$('.plupload_buttons', this.element).attr('id', id + '_buttons');
+
+		if (self.options.dragdrop) {
+			this.filelist.parent().attr('id', this.id + '_dropbox');
+			options.drop_element = this.id + '_dropbox';
+		}
+
+		this.filelist.on('click', function(e) {
+			if ($(e.target).hasClass('plupload_action_icon')) {
+				self.removeFile($(e.target).closest('.plupload_file').attr('id'));
+				e.preventDefault();
+			}
+		});
+
+		uploader = this.uploader = uploaders[id] = new plupload.Uploader($.extend(this.options, options));
+
+		if (self.options.views.thumbs) {
+			uploader.settings.required_features.display_media = true;
+		}
+
+		// for backward compatibility
+		if (self.options.max_file_count) {
+			plupload.extend(uploader.getOption('filters'), {
+				max_file_count: self.options.max_file_count
+			});
+		}
+
+		plupload.addFileFilter('max_file_count', function(maxCount, file, cb) {
+			if (maxCount <= this.files.length - (this.total.uploaded + this.total.failed)) {
+				self.browse_button.button('disable');
+				this.disableBrowse();
+				
+				this.trigger('Error', {
+					code : self.FILE_COUNT_ERROR,
+					message : _("File count error."),
+					file : file
+				});
+				cb(false);
+			} else {
+				cb(true);
+			}
+		});
+
+
+		uploader.bind('Error', function(up, err) {			
+			var message, details = "";
+
+			message = '<strong>' + err.message + '</strong>';
+				
+			switch (err.code) {
+				case plupload.FILE_EXTENSION_ERROR:
+					details = o.sprintf(_("File: %s"), err.file.name);
+					break;
+				
+				case plupload.FILE_SIZE_ERROR:
+					details = o.sprintf(_("File: %s, size: %d, max file size: %d"), err.file.name,  plupload.formatSize(err.file.size), plupload.formatSize(plupload.parseSize(up.getOption('filters').max_file_size)));
+					break;
+
+				case plupload.FILE_DUPLICATE_ERROR:
+					details = o.sprintf(_("%s already present in the queue."), err.file.name);
+					break;
+					
+				case self.FILE_COUNT_ERROR:
+					details = o.sprintf(_("Upload element accepts only %d file(s) at a time. Extra files were stripped."), up.getOption('filters').max_file_count || 0);
+					break;
+				
+				case plupload.IMAGE_FORMAT_ERROR :
+					details = _("Image format either wrong or not supported.");
+					break;	
+				
+				case plupload.IMAGE_MEMORY_ERROR :
+					details = _("Runtime ran out of available memory.");
+					break;
+				
+				/* // This needs a review
+				case plupload.IMAGE_DIMENSIONS_ERROR :
+					details = o.sprintf(_('Resoultion out of boundaries! <b>%s</b> runtime supports images only up to %wx%hpx.'), up.runtime, up.features.maxWidth, up.features.maxHeight);
+					break;	*/
+											
+				case plupload.HTTP_ERROR:
+					details = _("Upload URL might be wrong or doesn't exist.");
+					break;
+			}
+
+			message += " <br /><i>" + details + "</i>";
+
+			self._trigger('error', null, { up: up, error: err } );
+
+			// do not show UI if no runtime can be initialized
+			if (err.code === plupload.INIT_ERROR) {
+				setTimeout(function() {
+					self.destroy();
+				}, 1);
+			} else {
+				self.notify('error', message);
+			}
+		});
+
+		
+		uploader.bind('PostInit', function(up) {	
+			// all buttons are optional, so they can be disabled and hidden
+			if (!self.options.buttons.browse) {
+				self.browse_button.button('disable').hide();
+				up.disableBrowse(true);
+			} else {
+				self.browse_button.button('enable');
+			}
+			
+			if (!self.options.buttons.start) {
+				self.start_button.button('disable').hide();
+			} 
+			
+			if (!self.options.buttons.stop) {
+				self.stop_button.button('disable').hide();
+			}
+				
+			if (!self.options.unique_names && self.options.rename) {
+				self._enableRenaming();	
+			}
+
+			if (self.options.dragdrop && up.features.dragdrop) {
+				self.filelist.parent().addClass('plupload_dropbox');
+			}
+
+			self._enableViewSwitcher();
+			
+			self.start_button.click(function(e) {
+				if (!$(this).button('option', 'disabled')) {
+					self.start();
+				}
+				e.preventDefault();
+			});
+
+			self.stop_button.click(function(e) {
+				self.stop();
+				e.preventDefault();
+			});
+
+			self._trigger('ready', null, { up: up });
+		});
+		
+		// uploader internal events must run first 
+		uploader.init();
+
+		uploader.bind('FileFiltered', function(up, file) {
+			self._addFiles(file);
+		});
+		
+		uploader.bind('FilesAdded', function(up, files) {
+			self._trigger('selected', null, { up: up, files: files } );
+
+			// re-enable sortable
+			if (self.options.sortable && $.ui.sortable) {
+				self._enableSortingList();	
+			}
+
+			self._trigger('updatelist', null, { filelist: self.filelist });
+			
+			if (self.options.autostart) {
+				// set a little delay to make sure that QueueChanged triggered by the core has time to complete
+				setTimeout(function() {
+					self.start();
+				}, 10);
+			}
+		});
+		
+		uploader.bind('FilesRemoved', function(up, files) {
+			// destroy sortable if enabled
+			if ($.ui.sortable && self.options.sortable) {
+				$('tbody', self.filelist).sortable('destroy');	
+			}
+
+			$.each(files, function(i, file) {
+				$('#' + file.id).toggle("highlight", function() {
+					$(this).remove();
+				});
+			});
+			
+			if (up.files.length) {
+				// re-initialize sortable
+				if (self.options.sortable && $.ui.sortable) {
+					self._enableSortingList();	
+				}
+			}
+
+			self._trigger('updatelist', null, { filelist: self.filelist });
+			self._trigger('removed', null, { up: up, files: files } );
+		});
+		
+		uploader.bind('QueueChanged StateChanged', function() {
+			self._handleState();
+		});
+		
+		uploader.bind('UploadFile', function(up, file) {
+			self._handleFileStatus(file);
+		});
+		
+		uploader.bind('FileUploaded', function(up, file) {
+			self._handleFileStatus(file);
+			self._trigger('uploaded', null, { up: up, file: file } );
+		});
+		
+		uploader.bind('UploadProgress', function(up, file) {
+			self._handleFileStatus(file);
+			self._updateTotalProgress();
+			self._trigger('progress', null, { up: up, file: file } );
+		});
+		
+		uploader.bind('UploadComplete', function(up, files) {
+			self._addFormFields();		
+			self._trigger('complete', null, { up: up, files: files } );
+		});
+	},
+
+	
+	_setOption: function(key, value) {
+		var self = this;
+
+		if (key == 'buttons' && typeof(value) == 'object') {	
+			value = $.extend(self.options.buttons, value);
+			
+			if (!value.browse) {
+				self.browse_button.button('disable').hide();
+				self.uploader.disableBrowse(true);
+			} else {
+				self.browse_button.button('enable').show();
+				self.uploader.disableBrowse(false);
+			}
+			
+			if (!value.start) {
+				self.start_button.button('disable').hide();
+			} else {
+				self.start_button.button('enable').show();
+			}
+			
+			if (!value.stop) {
+				self.stop_button.button('disable').hide();
+			} else {
+				self.start_button.button('enable').show();	
+			}
+		}
+		
+		self.uploader.settings[key] = value;	
+	},
+
+	
+	/**
+	Start upload. Triggers `start` event.
+
+	@method start
+	*/
+	start: function() {
+		this.uploader.start();
+		this._trigger('start', null, { up: this.uploader });
+	},
+
+	
+	/**
+	Stop upload. Triggers `stop` event.
+
+	@method stop
+	*/
+	stop: function() {
+		this.uploader.stop();
+		this._trigger('stop', null, { up: this.uploader });
+	},
+
+
+	/**
+	Enable browse button.
+
+	@method enable
+	*/
+	enable: function() {
+		this.browse_button.button('enable');
+		this.uploader.disableBrowse(false);
+	},
+
+
+	/**
+	Disable browse button.
+
+	@method disable
+	*/
+	disable: function() {
+		this.browse_button.button('disable');
+		this.uploader.disableBrowse(true);
+	},
+
+	
+	/**
+	Retrieve file by it's unique id.
+
+	@method getFile
+	@param {String} id Unique id of the file
+	@return {plupload.File}
+	*/
+	getFile: function(id) {
+		var file;
+		
+		if (typeof id === 'number') {
+			file = this.uploader.files[id];	
+		} else {
+			file = this.uploader.getFile(id);	
+		}
+		return file;
+	},
+
+	/**
+	Return array of files currently in the queue.
+	
+	@method getFiles
+	@return {Array} Array of files in the queue represented by plupload.File objects
+	*/
+	getFiles: function() {
+		return this.uploader.files;
+	},
+
+	
+	/**
+	Remove the file from the queue.
+
+	@method removeFile
+	@param {plupload.File|String} file File to remove, might be specified directly or by it's unique id
+	*/
+	removeFile: function(file) {
+		if (plupload.typeOf(file) === 'string') {
+			file = this.getFile(file);
+		}
+		this.uploader.removeFile(file);
+	},
+
+	
+	/**
+	Clear the file queue.
+
+	@method clearQueue
+	*/
+	clearQueue: function() {
+		this.uploader.splice();
+	},
+
+
+	/**
+	Retrieve internal plupload.Uploader object (usually not required).
+
+	@method getUploader
+	@return {plupload.Uploader}
+	*/
+	getUploader: function() {
+		return this.uploader;
+	},
+
+
+	/**
+	Trigger refresh procedure, specifically browse_button re-measure and re-position operations.
+	Might get handy, when UI Widget is placed within the popup, that is constantly hidden and shown
+	again - without calling this method after each show operation, dialog trigger might get displaced
+	and disfunctional.
+
+	@method refresh
+	*/
+	refresh: function() {
+		this.uploader.refresh();
+	},
+
+
+	/**
+	Display a message in notification area.
+
+	@method notify
+	@param {Enum} type Type of the message, either `error` or `info`
+	@param {String} message The text message to display.
+	*/
+	notify: function(type, message) {
+		var popup = $(
+			'<div class="plupload_message">' + 
+				'<span class="plupload_message_close ui-icon ui-icon-circle-close" title="'+_('Close')+'"></span>' +
+				'<p><span class="ui-icon"></span>' + message + '</p>' +
+			'</div>'
+		);
+					
+		popup
+			.addClass('ui-state-' + (type === 'error' ? 'error' : 'highlight'))
+			.find('p .ui-icon')
+				.addClass('ui-icon-' + (type === 'error' ? 'alert' : 'info'))
+				.end()
+			.find('.plupload_message_close')
+				.click(function() {
+					popup.remove();	
+				})
+				.end();
+		
+		$('.plupload_header', this.container).append(popup);
+	},
+
+	
+	/**
+	Destroy the widget, the uploader, free associated resources and bring back original html.
+
+	@method destroy
+	*/
+	destroy: function() {		
+		// destroy uploader instance
+		this.uploader.destroy();
+
+		// unbind all button events
+		$('.plupload_button', this.element).unbind();
+		
+		// destroy buttons
+		if ($.ui.button) {
+			$('.plupload_add, .plupload_start, .plupload_stop', this.container)
+				.button('destroy');
+		}
+		
+		// destroy progressbar
+		if ($.ui.progressbar) {
+			this.progressbar.progressbar('destroy');	
+		}
+		
+		// destroy sortable behavior
+		if ($.ui.sortable && this.options.sortable) {
+			$('tbody', this.filelist).sortable('destroy');
+		}
+		
+		// restore the elements initial state
+		this.element
+			.empty()
+			.html(this.contents_bak);
+		this.contents_bak = '';
+
+		$.Widget.prototype.destroy.apply(this);
+	},
+	
+	
+	_handleState: function() {
+		var up = this.uploader
+		, filesPending = up.files.length - (up.total.uploaded + up.total.failed)
+		, maxCount = up.getOption('filters').max_file_count || 0
+		;
+						
+		if (plupload.STARTED === up.state) {			
+			$([])
+				.add(this.stop_button)
+				.add('.plupload_started')
+					.removeClass('plupload_hidden');
+
+			this.start_button.button('disable');
+
+			if (!this.options.multiple_queues) {
+				this.browse_button.button('disable');
+				up.disableBrowse();
+			}
+							
+			$('.plupload_upload_status', this.element).html(o.sprintf(_('Uploaded %d/%d files'), up.total.uploaded, up.files.length));
+			$('.plupload_header_content', this.element).addClass('plupload_header_content_bw');
+		} 
+		else if (plupload.STOPPED === up.state) {
+			$([])
+				.add(this.stop_button)
+				.add('.plupload_started')
+					.addClass('plupload_hidden');
+
+			if (filesPending) {
+				this.start_button.button('enable');
+			} else {
+				this.start_button.button('disable');
+			}
+			
+			if (this.options.multiple_queues) {
+				$('.plupload_header_content', this.element).removeClass('plupload_header_content_bw');
+			} 
+
+			// if max_file_count defined, only that many files can be queued at once
+			if (this.options.multiple_queues && maxCount && maxCount > filesPending) {
+				this.browse_button.button('enable');
+				up.disableBrowse(false);
+			}
+
+			this._updateTotalProgress();
+		}
+
+		if (up.total.queued === 0) {
+			$('.ui-button-text', this.browse_button).html(_('Add Files'));
+		} else {
+			$('.ui-button-text', this.browse_button).html(o.sprintf(_('%d files queued'), up.total.queued));
+		}
+
+		up.refresh();
+	},
+
+	
+	_handleFileStatus: function(file) {
+		var $file = $('#' + file.id), actionClass, iconClass;
+		
+		// since this method might be called asynchronously, file row might not yet be rendered
+		if (!$file.length) {
+			return;	
+		}
+
+		switch (file.status) {
+			case plupload.DONE: 
+				actionClass = 'plupload_done';
+				iconClass = 'plupload_action_icon ui-icon ui-icon-circle-check';
+				break;
+			
+			case plupload.FAILED:
+				actionClass = 'ui-state-error plupload_failed';
+				iconClass = 'plupload_action_icon ui-icon ui-icon-alert';
+				break;
+
+			case plupload.QUEUED:
+				actionClass = 'plupload_delete';
+				iconClass = 'plupload_action_icon ui-icon ui-icon-circle-minus';
+				break;
+
+			case plupload.UPLOADING:
+				actionClass = 'ui-state-highlight plupload_uploading';
+				iconClass = 'plupload_action_icon ui-icon ui-icon-circle-arrow-w';
+				
+				// scroll uploading file into the view if its bottom boundary is out of it
+				var scroller = $('.plupload_scroll', this.container)
+				, scrollTop = scroller.scrollTop()
+				, scrollerHeight = scroller.height()
+				, rowOffset = $file.position().top + $file.height()
+				;
+					
+				if (scrollerHeight < rowOffset) {
+					scroller.scrollTop(scrollTop + rowOffset - scrollerHeight);
+				}		
+
+				// Set file specific progress
+				$file
+					.find('.plupload_file_percent')
+						.html(file.percent + '%')
+						.end()
+					.find('.plupload_file_progress')
+						.css('width', file.percent + '%')
+						.end()
+					.find('.plupload_file_size')
+						.html(plupload.formatSize(file.size));			
+				break;
+		}
+		actionClass += ' ui-state-default plupload_file';
+
+		$file
+			.attr('class', actionClass)
+			.find('.plupload_action_icon')
+				.attr('class', iconClass);
+	},
+	
+	
+	_updateTotalProgress: function() {
+		var up = this.uploader;
+
+		// Scroll to end of file list
+		this.filelist[0].scrollTop = this.filelist[0].scrollHeight;
+		
+		this.progressbar.progressbar('value', up.total.percent);
+		
+		this.element
+			.find('.plupload_total_status')
+				.html(up.total.percent + '%')
+				.end()
+			.find('.plupload_total_file_size')
+				.html(plupload.formatSize(up.total.size))
+				.end()
+			.find('.plupload_upload_status')
+				.html(o.sprintf(_('Uploaded %d/%d files'), up.total.uploaded, up.files.length));
+	},
+
+
+	_displayThumbs: function() {
+		var self = this
+		, tw, th // thumb width/height
+		, cols
+		, num = 0 // number of simultaneously visible thumbs
+		, thumbs = [] // array of thumbs to preload at any given moment
+		, loading = false
+		;
+
+		if (!this.options.views.thumbs) {
+			return;
+		}
+
+
+		function onLast(el, eventName, cb) {
+			var timer;
+			
+			el.on(eventName, function() {
+				clearTimeout(timer);
+				timer = setTimeout(function() {
+					clearTimeout(timer);
+					cb();
+				}, 300);
+			});
+		}
+
+
+		// calculate number of simultaneously visible thumbs
+		function measure() {
+			if (!tw || !th) {
+				var wrapper = $('.plupload_file:eq(0)', self.filelist);
+				tw = wrapper.outerWidth(true);
+				th = wrapper.outerHeight(true);
+			}
+
+			var aw = self.content.width(), ah = self.content.height();
+			cols = Math.floor(aw / tw);
+			num =  cols * (Math.ceil(ah / th) + 1);
+		}
+
+
+		function pickThumbsToLoad() {
+			// calculate index of virst visible thumb
+			var startIdx = Math.floor(self.content.scrollTop() / th) * cols;
+			// get potentially visible thumbs that are not yet visible
+			thumbs = $('.plupload_file', self.filelist)
+				.slice(startIdx, startIdx + num)
+				.filter('.plupload_file_loading')
+				.get();
+		}
+		
+
+		function init() {
+			function mpl() { // measure, pick, load
+				if (self.view_mode !== 'thumbs') {
+					return;
+				}
+				measure();
+				pickThumbsToLoad();
+				lazyLoad();
+			}
+
+			if ($.fn.resizable) {
+				onLast(self.container, 'resize', mpl);
+			}
+
+			onLast(self.window, 'resize', mpl);
+			onLast(self.content, 'scroll',  mpl);
+
+			self.element.on('viewchanged selected', mpl);
+
+			mpl();
+		}
+
+
+		function preloadThumb(file, cb) {
+			var img = new o.Image();
+
+			img.onload = function() {
+				var thumb = $('#' + file.id + ' .plupload_file_thumb', self.filelist).html('');
+				this.embed(thumb[0], { 
+					width:  self.options.thumb_width, 
+					height: self.options.thumb_height, 
+					crop: true,
+					swf_url: o.resolveUrl(self.options.flash_swf_url),
+					xap_url: o.resolveUrl(self.options.silverlight_xap_url)
+				});
+			};
+
+			img.bind("embedded error", function() {
+				$('#' + file.id, self.filelist).removeClass('plupload_file_loading');
+				this.destroy();
+				setTimeout(cb, 1); // detach, otherwise ui might hang (in SilverLight for example)
+			});
+
+			img.load(file.getSource());
+		}
+
+
+		function lazyLoad() {
+			if (self.view_mode !== 'thumbs' || loading) {
+				return;
+			}	
+
+			pickThumbsToLoad();
+			if (!thumbs.length) {
+				return;
+			}
+
+			loading = true;
+
+			preloadThumb(self.getFile($(thumbs.shift()).attr('id')), function() {
+				loading = false;
+				lazyLoad();
+			});
+		}
+
+		// this has to run only once to measure structures and bind listeners
+		this.element.on('selected', function onselected() {
+			self.element.off('selected', onselected);
+			init();
+		});
+	},
+
+
+	_addFiles: function(files) {
+		var self = this, file_html, html = '';
+
+		file_html = '<li class="plupload_file ui-state-default plupload_file_loading plupload_delete" id="%id%" style="width:%thumb_width%px;">' +
+			'<div class="plupload_file_thumb" style="width:%thumb_width%px;height:%thumb_height%px;">' +
+				'<div class="plupload_file_dummy ui-widget-content" style="line-height:%thumb_height%px;"><span class="ui-state-disabled">%ext% </span></div>' +
+			'</div>' +
+			'<div class="plupload_file_status">' +
+				'<div class="plupload_file_progress ui-widget-header" style="width: 0%"> </div>' + 
+				'<span class="plupload_file_percent">%percent% </span>' +
+			'</div>' +
+			'<div class="plupload_file_name" title="%name%">' +
+				'<span class="plupload_file_name_wrapper">%name% </span>' +
+			'</div>' +						
+			'<div class="plupload_file_action">' +
+				'<div class="plupload_action_icon ui-icon ui-icon-circle-minus"> </div>' +
+			'</div>' +
+			'<div class="plupload_file_size">%size% </div>' +
+			'<div class="plupload_file_fields"> </div>' +
+		'</li>';
+
+		if (plupload.typeOf(files) !== 'array') {
+			files = [files];
+		}
+
+		$.each(files, function(i, file) {
+			var ext = o.Mime.getFileExtension(file.name) || 'none';
+
+			html += file_html.replace(/%(\w+)%/g, function($0, $1) {
+				switch ($1) {
+					case 'thumb_width':
+					case 'thumb_height':
+						return self.options[$1];
+					
+					case 'size':
+						return plupload.formatSize(file.size);
+
+					case 'ext':
+						return ext;
+
+					default:
+						return file[$1] || '';
+				}
+			});
+		});
+
+		self.filelist.append(html);
+	},
+
+
+	_addFormFields: function() {
+		var self = this;
+
+		// re-add from fresh
+		$('.plupload_file_fields', this.filelist).html('');
+
+		plupload.each(this.uploader.files, function(file, count) {
+			var fields = ''
+			, id = self.id + '_' + count
+			;
+
+			if (file.target_name) {
+				fields += '<input type="hidden" name="' + id + '_tmpname" value="'+plupload.xmlEncode(file.target_name)+'" />';
+			}
+			fields += '<input type="hidden" name="' + id + '_name" value="'+plupload.xmlEncode(file.name)+'" />';
+			fields += '<input type="hidden" name="' + id + '_status" value="' + (file.status === plupload.DONE ? 'done' : 'failed') + '" />';
+
+			$('#' + file.id).find('.plupload_file_fields').html(fields);
+		});
+
+		this.counter.val(this.uploader.files.length);
+	},
+	
+
+	_viewChanged: function(view) {
+		// update or write a new cookie
+		if (this.options.views.remember && $.cookie) {
+			$.cookie('plupload_ui_view', view, { expires: 7, path: '/' });
+		} 
+	
+		// ugly fix for IE6 - make content area stretchable
+		if (o.Env.browser === 'IE' && o.Env.version < 7) {
+			this.content.attr('style', 'height:expression(document.getElementById("' + this.id + '_container' + '").clientHeight - ' + (view === 'list' ? 132 : 102) + ')');
+		}
+
+		this.container.removeClass('plupload_view_list plupload_view_thumbs').addClass('plupload_view_' + view); 
+		this.view_mode = view;
+		this._trigger('viewchanged', null, { view: view });
+	},
+
+
+	_enableViewSwitcher: function() {
+		var self = this
+		, view
+		, switcher = $('.plupload_view_switch', this.container)
+		, buttons
+		, button
+		;
+
+		plupload.each(['list', 'thumbs'], function(view) {
+			if (!self.options.views[view]) {
+				switcher.find('[for="' + self.id + '_view_' + view + '"], #'+ self.id +'_view_' + view).remove();
+			}
+		});
+
+		// check if any visible left
+		buttons = switcher.find('.plupload_button');
+
+		if (buttons.length === 1) {
+			switcher.hide();
+			view = buttons.eq(0).data('view');
+			this._viewChanged(view);
+		} else if ($.ui.button && buttons.length > 1) {
+			if (this.options.views.remember && $.cookie) {
+				view = $.cookie('plupload_ui_view');
+			}
+
+			// if wierd case, bail out to default
+			if (!~plupload.inArray(view, ['list', 'thumbs'])) {
+				view = this.options.views.active;
+			}
+
+			switcher
+				.show()
+				.buttonset()
+				.find('.ui-button')
+					.click(function(e) {
+						view = $(this).data('view');
+						self._viewChanged(view);
+						e.preventDefault(); // avoid auto scrolling to widget in IE and FF (see #850)
+					});
+
+			// if view not active - happens when switcher wasn't clicked manually
+			button = switcher.find('[for="' + self.id + '_view_'+view+'"]');
+			if (button.length) {
+				button.trigger('click');
+			}
+		} else {
+			switcher.show();
+			this._viewChanged(this.options.views.active);
+		}
+
+		// initialize thumb viewer if requested
+		if (this.options.views.thumbs) {
+			this._displayThumbs();
+		}
+	},
+	
+	
+	_enableRenaming: function() {
+		var self = this;
+
+		this.filelist.dblclick(function(e) {
+			var nameSpan = $(e.target), nameInput, file, parts, name, ext = "";
+
+			if (!nameSpan.hasClass('plupload_file_name_wrapper')) {
+				return;
+			}
+		
+			// Get file name and split out name and extension
+			file = self.uploader.getFile(nameSpan.closest('.plupload_file')[0].id);
+			name = file.name;
+			parts = /^(.+)(\.[^.]+)$/.exec(name);
+			if (parts) {
+				name = parts[1];
+				ext = parts[2];
+			}
+
+			// Display input element
+			nameInput = $('<input class="plupload_file_rename" type="text" />').width(nameSpan.width()).insertAfter(nameSpan.hide());
+			nameInput.val(name).blur(function() {
+				nameSpan.show().parent().scrollLeft(0).end().next().remove();
+			}).keydown(function(e) {
+				var nameInput = $(this);
+
+				if ($.inArray(e.keyCode, [13, 27]) !== -1) {
+					e.preventDefault();
+
+					// Rename file and glue extension back on
+					if (e.keyCode === 13) {
+						file.name = nameInput.val() + ext;
+						nameSpan.html(file.name);
+					}
+					nameInput.blur();
+				}
+			})[0].focus();
+		});
+	},
+	
+	
+	_enableSortingList: function() {
+		var self = this;
+		
+		if ($('.plupload_file', this.filelist).length < 2) {
+			return;	
+		}
+
+		// destroy sortable if enabled
+		$('tbody', this.filelist).sortable('destroy');	
+		
+		// enable		
+		this.filelist.sortable({
+			items: '.plupload_delete',
+			
+			cancel: 'object, .plupload_clearer',
+
+			stop: function() {
+				var files = [];
+				
+				$.each($(this).sortable('toArray'), function(i, id) {
+					files[files.length] = self.uploader.getFile(id);
+				});				
+				
+				files.unshift(files.length);
+				files.unshift(0);
+				
+				// re-populate files array				
+				Array.prototype.splice.apply(self.uploader.files, files);	
+			}
+		});		
+	}
+});
+
+} (window, document, plupload, mOxie, jQuery));
Index: /trunk/themes/default/js/plugins/plupload/jquery.ui.plupload/jquery.ui.plupload.min.js
===================================================================
--- /trunk/themes/default/js/plugins/plupload/jquery.ui.plupload/jquery.ui.plupload.min.js	(revision 28545)
+++ /trunk/themes/default/js/plugins/plupload/jquery.ui.plupload/jquery.ui.plupload.min.js	(revision 28545)
@@ -0,0 +1,1 @@
+;(function(e,t,n,r,i){function o(e){return n.translate(e)||e}function u(e){e.id=e.attr("id"),e.html('<div class="plupload_wrapper"><div class="ui-widget-content plupload_container"><div class="ui-state-default ui-widget-header plupload_header"><div class="plupload_header_content"><div class="plupload_logo"> </div><div class="plupload_header_title">'+o("Select files")+"</div>"+'<div class="plupload_header_text">'+o("Add files to the upload queue and click the start button.")+"</div>"+'<div class="plupload_view_switch">'+'<input type="radio" id="'+e.id+'_view_list" name="view_mode_'+e.id+'" checked="checked" /><label class="plupload_button" for="'+e.id+'_view_list" data-view="list">'+o("List")+"</label>"+'<input type="radio" id="'+e.id+'_view_thumbs" name="view_mode_'+e.id+'" /><label class="plupload_button"  for="'+e.id+'_view_thumbs" data-view="thumbs">'+o("Thumbnails")+"</label>"+"</div>"+"</div>"+"</div>"+'<table class="plupload_filelist plupload_filelist_header ui-widget-header">'+"<tr>"+'<td class="plupload_cell plupload_file_name">'+o("Filename")+"</td>"+'<td class="plupload_cell plupload_file_status">'+o("Status")+"</td>"+'<td class="plupload_cell plupload_file_size">'+o("Size")+"</td>"+'<td class="plupload_cell plupload_file_action">&nbsp;</td>'+"</tr>"+"</table>"+'<div class="plupload_content">'+'<div class="plupload_droptext">'+o("Drag files here.")+"</div>"+'<ul class="plupload_filelist_content"> </ul>'+'<div class="plupload_clearer">&nbsp;</div>'+"</div>"+'<table class="plupload_filelist plupload_filelist_footer ui-widget-header">'+"<tr>"+'<td class="plupload_cell plupload_file_name">'+'<div class="plupload_buttons"><!-- Visible -->'+'<a class="plupload_button plupload_add">'+o("Add Files")+"</a>&nbsp;"+'<a class="plupload_button plupload_start">'+o("Start Upload")+"</a>&nbsp;"+'<a class="plupload_button plupload_stop plupload_hidden">'+o("Stop Upload")+"</a>&nbsp;"+"</div>"+'<div class="plupload_started plupload_hidden"><!-- Hidden -->'+'<div class="plupload_progress plupload_right">'+'<div class="plupload_progress_container"></div>'+"</div>"+'<div class="plupload_cell plupload_upload_status"></div>'+'<div class="plupload_clearer">&nbsp;</div>'+"</div>"+"</td>"+'<td class="plupload_file_status"><span class="plupload_total_status">0%</span></td>'+'<td class="plupload_file_size"><span class="plupload_total_file_size">0 kb</span></td>'+'<td class="plupload_file_action"></td>'+"</tr>"+"</table>"+"</div>"+'<input class="plupload_count" value="0" type="hidden">'+"</div>")}var s={};i.widget("ui.plupload",{widgetEventPrefix:"",contents_bak:"",options:{browse_button_hover:"ui-state-hover",browse_button_active:"ui-state-active",filters:{},buttons:{browse:!0,start:!0,stop:!0},views:{list:!0,thumbs:!1,active:"list",remember:!0},thumb_width:100,thumb_height:60,multiple_queues:!0,dragdrop:!0,autostart:!1,sortable:!1,rename:!1},FILE_COUNT_ERROR:-9001,_create:function(){var e=this.element.attr("id");e||(e=n.guid(),this.element.attr("id",e)),this.id=e,this.contents_bak=this.element.html(),u(this.element),this.container=i(".plupload_container",this.element).attr("id",e+"_container"),this.content=i(".plupload_content",this.element),i.fn.resizable&&this.container.resizable({handles:"s",minHeight:300}),this.filelist=i(".plupload_filelist_content",this.container).attr({id:e+"_filelist",unselectable:"on"}),this.browse_button=i(".plupload_add",this.container).attr("id",e+"_browse"),this.start_button=i(".plupload_start",this.container).attr("id",e+"_start"),this.stop_button=i(".plupload_stop",this.container).attr("id",e+"_stop"),this.thumbs_switcher=i("#"+e+"_view_thumbs"),this.list_switcher=i("#"+e+"_view_list"),i.ui.button&&(this.browse_button.button({icons:{primary:"ui-icon-circle-plus"},disabled:!0}),this.start_button.button({icons:{primary:"ui-icon-circle-arrow-e"},disabled:!0}),this.stop_button.button({icons:{primary:"ui-icon-circle-close"}}),this.list_switcher.button({text:!1,icons:{secondary:"ui-icon-grip-dotted-horizontal"}}),this.thumbs_switcher.button({text:!1,icons:{secondary:"ui-icon-image"}})),this.progressbar=i(".plupload_progress_container",this.container),i.ui.progressbar&&this.progressbar.progressbar(),this.counter=i(".plupload_count",this.element).attr({id:e+"_count",name:e+"_count"}),this._initUploader()},_initUploader:function(){var e=this,t=this.id,u,a={container:t+"_buttons",browse_button:t+"_browse"};i(".plupload_buttons",this.element).attr("id",t+"_buttons"),e.options.dragdrop&&(this.filelist.parent().attr("id",this.id+"_dropbox"),a.drop_element=this.id+"_dropbox"),this.filelist.on("click",function(t){i(t.target).hasClass("plupload_action_icon")&&(e.removeFile(i(t.target).closest(".plupload_file").attr("id")),t.preventDefault())}),u=this.uploader=s[t]=new n.Uploader(i.extend(this.options,a)),e.options.views.thumbs&&(u.settings.required_features.display_media=!0),e.options.max_file_count&&n.extend(u.getOption("filters"),{max_file_count:e.options.max_file_count}),n.addFileFilter("max_file_count",function(t,n,r){t<=this.files.length-(this.total.uploaded+this.total.failed)?(e.browse_button.button("disable"),this.disableBrowse(),this.trigger("Error",{code:e.FILE_COUNT_ERROR,message:o("File count error."),file:n}),r(!1)):r(!0)}),u.bind("Error",function(t,i){var s,u="";s="<strong>"+i.message+"</strong>";switch(i.code){case n.FILE_EXTENSION_ERROR:u=r.sprintf(o("File: %s"),i.file.name);break;case n.FILE_SIZE_ERROR:u=r.sprintf(o("File: %s, size: %d, max file size: %d"),i.file.name,n.formatSize(i.file.size),n.formatSize(n.parseSize(t.getOption("filters").max_file_size)));break;case n.FILE_DUPLICATE_ERROR:u=r.sprintf(o("%s already present in the queue."),i.file.name);break;case e.FILE_COUNT_ERROR:u=r.sprintf(o("Upload element accepts only %d file(s) at a time. Extra files were stripped."),t.getOption("filters").max_file_count||0);break;case n.IMAGE_FORMAT_ERROR:u=o("Image format either wrong or not supported.");break;case n.IMAGE_MEMORY_ERROR:u=o("Runtime ran out of available memory.");break;case n.HTTP_ERROR:u=o("Upload URL might be wrong or doesn't exist.")}s+=" <br /><i>"+u+"</i>",e._trigger("error",null,{up:t,error:i}),i.code===n.INIT_ERROR?setTimeout(function(){e.destroy()},1):e.notify("error",s)}),u.bind("PostInit",function(t){e.options.buttons.browse?e.browse_button.button("enable"):(e.browse_button.button("disable").hide(),t.disableBrowse(!0)),e.options.buttons.start||e.start_button.button("disable").hide(),e.options.buttons.stop||e.stop_button.button("disable").hide(),!e.options.unique_names&&e.options.rename&&e._enableRenaming(),e.options.dragdrop&&t.features.dragdrop&&e.filelist.parent().addClass("plupload_dropbox"),e._enableViewSwitcher(),e.start_button.click(function(t){i(this).button("option","disabled")||e.start(),t.preventDefault()}),e.stop_button.click(function(t){e.stop(),t.preventDefault()}),e._trigger("ready",null,{up:t})}),u.init(),u.bind("FileFiltered",function(t,n){e._addFiles(n)}),u.bind("FilesAdded",function(t,n){e._trigger("selected",null,{up:t,files:n}),e.options.sortable&&i.ui.sortable&&e._enableSortingList(),e._trigger("updatelist",null,{filelist:e.filelist}),e.options.autostart&&setTimeout(function(){e.start()},10)}),u.bind("FilesRemoved",function(t,n){i.ui.sortable&&e.options.sortable&&i("tbody",e.filelist).sortable("destroy"),i.each(n,function(e,t){i("#"+t.id).toggle("highlight",function(){i(this).remove()})}),t.files.length&&e.options.sortable&&i.ui.sortable&&e._enableSortingList(),e._trigger("updatelist",null,{filelist:e.filelist}),e._trigger("removed",null,{up:t,files:n})}),u.bind("QueueChanged StateChanged",function(){e._handleState()}),u.bind("UploadFile",function(t,n){e._handleFileStatus(n)}),u.bind("FileUploaded",function(t,n){e._handleFileStatus(n),e._trigger("uploaded",null,{up:t,file:n})}),u.bind("UploadProgress",function(t,n){e._handleFileStatus(n),e._updateTotalProgress(),e._trigger("progress",null,{up:t,file:n})}),u.bind("UploadComplete",function(t,n){e._addFormFields(),e._trigger("complete",null,{up:t,files:n})})},_setOption:function(e,t){var n=this;e=="buttons"&&typeof t=="object"&&(t=i.extend(n.options.buttons,t),t.browse?(n.browse_button.button("enable").show(),n.uploader.disableBrowse(!1)):(n.browse_button.button("disable").hide(),n.uploader.disableBrowse(!0)),t.start?n.start_button.button("enable").show():n.start_button.button("disable").hide(),t.stop?n.start_button.button("enable").show():n.stop_button.button("disable").hide()),n.uploader.settings[e]=t},start:function(){this.uploader.start(),this._trigger("start",null,{up:this.uploader})},stop:function(){this.uploader.stop(),this._trigger("stop",null,{up:this.uploader})},enable:function(){this.browse_button.button("enable"),this.uploader.disableBrowse(!1)},disable:function(){this.browse_button.button("disable"),this.uploader.disableBrowse(!0)},getFile:function(e){var t;return typeof e=="number"?t=this.uploader.files[e]:t=this.uploader.getFile(e),t},getFiles:function(){return this.uploader.files},removeFile:function(e){n.typeOf(e)==="string"&&(e=this.getFile(e)),this.uploader.removeFile(e)},clearQueue:function(){this.uploader.splice()},getUploader:function(){return this.uploader},refresh:function(){this.uploader.refresh()},notify:function(e,t){var n=i('<div class="plupload_message"><span class="plupload_message_close ui-icon ui-icon-circle-close" title="'+o("Close")+'"></span>'+'<p><span class="ui-icon"></span>'+t+"</p>"+"</div>");n.addClass("ui-state-"+(e==="error"?"error":"highlight")).find("p .ui-icon").addClass("ui-icon-"+(e==="error"?"alert":"info")).end().find(".plupload_message_close").click(function(){n.remove()}).end(),i(".plupload_header",this.container).append(n)},destroy:function(){this.uploader.destroy(),i(".plupload_button",this.element).unbind(),i.ui.button&&i(".plupload_add, .plupload_start, .plupload_stop",this.container).button("destroy"),i.ui.progressbar&&this.progressbar.progressbar("destroy"),i.ui.sortable&&this.options.sortable&&i("tbody",this.filelist).sortable("destroy"),this.element.empty().html(this.contents_bak),this.contents_bak="",i.Widget.prototype.destroy.apply(this)},_handleState:function(){var e=this.uploader,t=e.files.length-(e.total.uploaded+e.total.failed),s=e.getOption("filters").max_file_count||0;n.STARTED===e.state?(i([]).add(this.stop_button).add(".plupload_started").removeClass("plupload_hidden"),this.start_button.button("disable"),this.options.multiple_queues||(this.browse_button.button("disable"),e.disableBrowse()),i(".plupload_upload_status",this.element).html(r.sprintf(o("Uploaded %d/%d files"),e.total.uploaded,e.files.length)),i(".plupload_header_content",this.element).addClass("plupload_header_content_bw")):n.STOPPED===e.state&&(i([]).add(this.stop_button).add(".plupload_started").addClass("plupload_hidden"),t?this.start_button.button("enable"):this.start_button.button("disable"),this.options.multiple_queues&&i(".plupload_header_content",this.element).removeClass("plupload_header_content_bw"),this.options.multiple_queues&&s&&s>t&&(this.browse_button.button("enable"),e.disableBrowse(!1)),this._updateTotalProgress()),e.total.queued===0?i(".ui-button-text",this.browse_button).html(o("Add Files")):i(".ui-button-text",this.browse_button).html(r.sprintf(o("%d files queued"),e.total.queued)),e.refresh()},_handleFileStatus:function(e){var t=i("#"+e.id),r,s;if(!t.length)return;switch(e.status){case n.DONE:r="plupload_done",s="plupload_action_icon ui-icon ui-icon-circle-check";break;case n.FAILED:r="ui-state-error plupload_failed",s="plupload_action_icon ui-icon ui-icon-alert";break;case n.QUEUED:r="plupload_delete",s="plupload_action_icon ui-icon ui-icon-circle-minus";break;case n.UPLOADING:r="ui-state-highlight plupload_uploading",s="plupload_action_icon ui-icon ui-icon-circle-arrow-w";var o=i(".plupload_scroll",this.container),u=o.scrollTop(),a=o.height(),f=t.position().top+t.height();a<f&&o.scrollTop(u+f-a),t.find(".plupload_file_percent").html(e.percent+"%").end().find(".plupload_file_progress").css("width",e.percent+"%").end().find(".plupload_file_size").html(n.formatSize(e.size))}r+=" ui-state-default plupload_file",t.attr("class",r).find(".plupload_action_icon").attr("class",s)},_updateTotalProgress:function(){var e=this.uploader;this.filelist[0].scrollTop=this.filelist[0].scrollHeight,this.progressbar.progressbar("value",e.total.percent),this.element.find(".plupload_total_status").html(e.total.percent+"%").end().find(".plupload_total_file_size").html(n.formatSize(e.total.size)).end().find(".plupload_upload_status").html(r.sprintf(o("Uploaded %d/%d files"),e.total.uploaded,e.files.length))},_displayThumbs:function(){function f(e,t,n){var r;e.on(t,function(){clearTimeout(r),r=setTimeout(function(){clearTimeout(r),n()},300)})}function l(){if(!t||!n){var r=i(".plupload_file:eq(0)",e.filelist);t=r.outerWidth(!0),n=r.outerHeight(!0)}var u=e.content.width(),a=e.content.height();s=Math.floor(u/t),o=s*(Math.ceil(a/n)+1)}function c(){var t=Math.floor(e.content.scrollTop()/n)*s;u=i(".plupload_file",e.filelist).slice(t,t+o).filter(".plupload_file_loading").get()}function h(){function t(){if(e.view_mode!=="thumbs")return;l(),c(),d()}i.fn.resizable&&f(e.container,"resize",t),f(e.window,"resize",t),f(e.content,"scroll",t),e.element.on("viewchanged selected",t),t()}function p(t,n){var s=new r.Image;s.onload=function(){var n=i("#"+t.id+" .plupload_file_thumb",e.filelist).html("");this.embed(n[0],{width:e.options.thumb_width,height:e.options.thumb_height,crop:!0,swf_url:r.resolveUrl(e.options.flash_swf_url),xap_url:r.resolveUrl(e.options.silverlight_xap_url)})},s.bind("embedded error",function(){i("#"+t.id,e.filelist).removeClass("plupload_file_loading"),this.destroy(),setTimeout(n,1)}),s.load(t.getSource())}function d(){if(e.view_mode!=="thumbs"||a)return;c();if(!u.length)return;a=!0,p(e.getFile(i(u.shift()).attr("id")),function(){a=!1,d()})}var e=this,t,n,s,o=0,u=[],a=!1;if(!this.options.views.thumbs)return;this.element.on("selected",function v(){e.element.off("selected",v),h()})},_addFiles:function(e){var t=this,s,o="";s='<li class="plupload_file ui-state-default plupload_file_loading plupload_delete" id="%id%" style="width:%thumb_width%px;"><div class="plupload_file_thumb" style="width:%thumb_width%px;height:%thumb_height%px;"><div class="plupload_file_dummy ui-widget-content" style="line-height:%thumb_height%px;"><span class="ui-state-disabled">%ext% </span></div></div><div class="plupload_file_status"><div class="plupload_file_progress ui-widget-header" style="width: 0%"> </div><span class="plupload_file_percent">%percent% </span></div><div class="plupload_file_name" title="%name%"><span class="plupload_file_name_wrapper">%name% </span></div><div class="plupload_file_action"><div class="plupload_action_icon ui-icon ui-icon-circle-minus"> </div></div><div class="plupload_file_size">%size% </div><div class="plupload_file_fields"> </div></li>',n.typeOf(e)!=="array"&&(e=[e]),i.each(e,function(e,i){var u=r.Mime.getFileExtension(i.name)||"none";o+=s.replace(/%(\w+)%/g,function(e,r){switch(r){case"thumb_width":case"thumb_height":return t.options[r];case"size":return n.formatSize(i.size);case"ext":return u;default:return i[r]||""}})}),t.filelist.append(o)},_addFormFields:function(){var e=this;i(".plupload_file_fields",this.filelist).html(""),n.each(this.uploader.files,function(t,r){var s="",o=e.id+"_"+r;t.target_name&&(s+='<input type="hidden" name="'+o+'_tmpname" value="'+n.xmlEncode(t.target_name)+'" />'),s+='<input type="hidden" name="'+o+'_name" value="'+n.xmlEncode(t.name)+'" />',s+='<input type="hidden" name="'+o+'_status" value="'+(t.status===n.DONE?"done":"failed")+'" />',i("#"+t.id).find(".plupload_file_fields").html(s)}),this.counter.val(this.uploader.files.length)},_viewChanged:function(e){this.options.views.remember&&i.cookie&&i.cookie("plupload_ui_view",e,{expires:7,path:"/"}),r.Env.browser==="IE"&&r.Env.version<7&&this.content.attr("style",'height:expression(document.getElementById("'+this.id+"_container"+'").clientHeight - '+(e==="list"?132:102)+")"),this.container.removeClass("plupload_view_list plupload_view_thumbs").addClass("plupload_view_"+e),this.view_mode=e,this._trigger("viewchanged",null,{view:e})},_enableViewSwitcher:function(){var e=this,t,r=i(".plupload_view_switch",this.container),s,o;n.each(["list","thumbs"],function(t){e.options.views[t]||r.find('[for="'+e.id+"_view_"+t+'"], #'+e.id+"_view_"+t).remove()}),s=r.find(".plupload_button"),s.length===1?(r.hide(),t=s.eq(0).data("view"),this._viewChanged(t)):i.ui.button&&s.length>1?(this.options.views.remember&&i.cookie&&(t=i.cookie("plupload_ui_view")),~n.inArray(t,["list","thumbs"])||(t=this.options.views.active),r.show().buttonset().find(".ui-button").click(function(n){t=i(this).data("view"),e._viewChanged(t),n.preventDefault()}),o=r.find('[for="'+e.id+"_view_"+t+'"]'),o.length&&o.trigger("click")):(r.show(),this._viewChanged(this.options.views.active)),this.options.views.thumbs&&this._displayThumbs()},_enableRenaming:function(){var e=this;this.filelist.dblclick(function(t){var n=i(t.target),r,s,o,u,a="";if(!n.hasClass("plupload_file_name_wrapper"))return;s=e.uploader.getFile(n.closest(".plupload_file")[0].id),u=s.name,o=/^(.+)(\.[^.]+)$/.exec(u),o&&(u=o[1],a=o[2]),r=i('<input class="plupload_file_rename" type="text" />').width(n.width()).insertAfter(n.hide()),r.val(u).blur(function(){n.show().parent().scrollLeft(0).end().next().remove()}).keydown(function(e){var t=i(this);i.inArray(e.keyCode,[13,27])!==-1&&(e.preventDefault(),e.keyCode===13&&(s.name=t.val()+a,n.html(s.name)),t.blur())})[0].focus()})},_enableSortingList:function(){var e=this;if(i(".plupload_file",this.filelist).length<2)return;i("tbody",this.filelist).sortable("destroy"),this.filelist.sortable({items:".plupload_delete",cancel:"object, .plupload_clearer",stop:function(){var t=[];i.each(i(this).sortable("toArray"),function(n,r){t[t.length]=e.uploader.getFile(r)}),t.unshift(t.length),t.unshift(0),Array.prototype.splice.apply(e.uploader.files,t)}})}})})(window,document,plupload,mOxie,jQuery);
Index: /trunk/themes/default/js/plugins/plupload/moxie.js
===================================================================
--- /trunk/themes/default/js/plugins/plupload/moxie.js	(revision 28545)
+++ /trunk/themes/default/js/plugins/plupload/moxie.js	(revision 28545)
@@ -0,0 +1,10726 @@
+/**
+ * mOxie - multi-runtime File API & XMLHttpRequest L2 Polyfill
+ * v1.2.1
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ *
+ * Date: 2014-05-14
+ */
+/**
+ * Compiled inline version. (Library mode)
+ */
+
+/*jshint smarttabs:true, undef:true, latedef:true, curly:true, bitwise:true, camelcase:true */
+/*globals $code */
+
+(function(exports, undefined) {
+	"use strict";
+
+	var modules = {};
+
+	function require(ids, callback) {
+		var module, defs = [];
+
+		for (var i = 0; i < ids.length; ++i) {
+			module = modules[ids[i]] || resolve(ids[i]);
+			if (!module) {
+				throw 'module definition dependecy not found: ' + ids[i];
+			}
+
+			defs.push(module);
+		}
+
+		callback.apply(null, defs);
+	}
+
+	function define(id, dependencies, definition) {
+		if (typeof id !== 'string') {
+			throw 'invalid module definition, module id must be defined and be a string';
+		}
+
+		if (dependencies === undefined) {
+			throw 'invalid module definition, dependencies must be specified';
+		}
+
+		if (definition === undefined) {
+			throw 'invalid module definition, definition function must be specified';
+		}
+
+		require(dependencies, function() {
+			modules[id] = definition.apply(null, arguments);
+		});
+	}
+
+	function defined(id) {
+		return !!modules[id];
+	}
+
+	function resolve(id) {
+		var target = exports;
+		var fragments = id.split(/[.\/]/);
+
+		for (var fi = 0; fi < fragments.length; ++fi) {
+			if (!target[fragments[fi]]) {
+				return;
+			}
+
+			target = target[fragments[fi]];
+		}
+
+		return target;
+	}
+
+	function expose(ids) {
+		for (var i = 0; i < ids.length; i++) {
+			var target = exports;
+			var id = ids[i];
+			var fragments = id.split(/[.\/]/);
+
+			for (var fi = 0; fi < fragments.length - 1; ++fi) {
+				if (target[fragments[fi]] === undefined) {
+					target[fragments[fi]] = {};
+				}
+
+				target = target[fragments[fi]];
+			}
+
+			target[fragments[fragments.length - 1]] = modules[id];
+		}
+	}
+
+// Included from: src/javascript/core/utils/Basic.js
+
+/**
+ * Basic.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+define('moxie/core/utils/Basic', [], function() {
+	/**
+	Gets the true type of the built-in object (better version of typeof).
+	@author Angus Croll (http://javascriptweblog.wordpress.com/)
+
+	@method typeOf
+	@for Utils
+	@static
+	@param {Object} o Object to check.
+	@return {String} Object [[Class]]
+	*/
+	var typeOf = function(o) {
+		var undef;
+
+		if (o === undef) {
+			return 'undefined';
+		} else if (o === null) {
+			return 'null';
+		} else if (o.nodeType) {
+			return 'node';
+		}
+
+		// the snippet below is awesome, however it fails to detect null, undefined and arguments types in IE lte 8
+		return ({}).toString.call(o).match(/\s([a-z|A-Z]+)/)[1].toLowerCase();
+	};
+		
+	/**
+	Extends the specified object with another object.
+
+	@method extend
+	@static
+	@param {Object} target Object to extend.
+	@param {Object} [obj]* Multiple objects to extend with.
+	@return {Object} Same as target, the extended object.
+	*/
+	var extend = function(target) {
+		var undef;
+
+		each(arguments, function(arg, i) {
+			if (i > 0) {
+				each(arg, function(value, key) {
+					if (value !== undef) {
+						if (typeOf(target[key]) === typeOf(value) && !!~inArray(typeOf(value), ['array', 'object'])) {
+							extend(target[key], value);
+						} else {
+							target[key] = value;
+						}
+					}
+				});
+			}
+		});
+		return target;
+	};
+		
+	/**
+	Executes the callback function for each item in array/object. If you return false in the
+	callback it will break the loop.
+
+	@method each
+	@static
+	@param {Object} obj Object to iterate.
+	@param {function} callback Callback function to execute for each item.
+	*/
+	var each = function(obj, callback) {
+		var length, key, i, undef;
+
+		if (obj) {
+			try {
+				length = obj.length;
+			} catch(ex) {
+				length = undef;
+			}
+
+			if (length === undef) {
+				// Loop object items
+				for (key in obj) {
+					if (obj.hasOwnProperty(key)) {
+						if (callback(obj[key], key) === false) {
+							return;
+						}
+					}
+				}
+			} else {
+				// Loop array items
+				for (i = 0; i < length; i++) {
+					if (callback(obj[i], i) === false) {
+						return;
+					}
+				}
+			}
+		}
+	};
+
+	/**
+	Checks if object is empty.
+	
+	@method isEmptyObj
+	@static
+	@param {Object} o Object to check.
+	@return {Boolean}
+	*/
+	var isEmptyObj = function(obj) {
+		var prop;
+
+		if (!obj || typeOf(obj) !== 'object') {
+			return true;
+		}
+
+		for (prop in obj) {
+			return false;
+		}
+
+		return true;
+	};
+
+	/**
+	Recieve an array of functions (usually async) to call in sequence, each  function
+	receives a callback as first argument that it should call, when it completes. Finally,
+	after everything is complete, main callback is called. Passing truthy value to the
+	callback as a first argument will interrupt the sequence and invoke main callback
+	immediately.
+
+	@method inSeries
+	@static
+	@param {Array} queue Array of functions to call in sequence
+	@param {Function} cb Main callback that is called in the end, or in case of error
+	*/
+	var inSeries = function(queue, cb) {
+		var i = 0, length = queue.length;
+
+		if (typeOf(cb) !== 'function') {
+			cb = function() {};
+		}
+
+		if (!queue || !queue.length) {
+			cb();
+		}
+
+		function callNext(i) {
+			if (typeOf(queue[i]) === 'function') {
+				queue[i](function(error) {
+					/*jshint expr:true */
+					++i < length && !error ? callNext(i) : cb(error);
+				});
+			}
+		}
+		callNext(i);
+	};
+
+
+	/**
+	Recieve an array of functions (usually async) to call in parallel, each  function
+	receives a callback as first argument that it should call, when it completes. After 
+	everything is complete, main callback is called. Passing truthy value to the
+	callback as a first argument will interrupt the process and invoke main callback
+	immediately.
+
+	@method inParallel
+	@static
+	@param {Array} queue Array of functions to call in sequence
+	@param {Function} cb Main callback that is called in the end, or in case of erro
+	*/
+	var inParallel = function(queue, cb) {
+		var count = 0, num = queue.length, cbArgs = new Array(num);
+
+		each(queue, function(fn, i) {
+			fn(function(error) {
+				if (error) {
+					return cb(error);
+				}
+				
+				var args = [].slice.call(arguments);
+				args.shift(); // strip error - undefined or not
+
+				cbArgs[i] = args;
+				count++;
+
+				if (count === num) {
+					cbArgs.unshift(null);
+					cb.apply(this, cbArgs);
+				} 
+			});
+		});
+	};
+	
+	
+	/**
+	Find an element in array and return it's index if present, otherwise return -1.
+	
+	@method inArray
+	@static
+	@param {Mixed} needle Element to find
+	@param {Array} array
+	@return {Int} Index of the element, or -1 if not found
+	*/
+	var inArray = function(needle, array) {
+		if (array) {
+			if (Array.prototype.indexOf) {
+				return Array.prototype.indexOf.call(array, needle);
+			}
+		
+			for (var i = 0, length = array.length; i < length; i++) {
+				if (array[i] === needle) {
+					return i;
+				}
+			}
+		}
+		return -1;
+	};
+
+
+	/**
+	Returns elements of first array if they are not present in second. And false - otherwise.
+
+	@private
+	@method arrayDiff
+	@param {Array} needles
+	@param {Array} array
+	@return {Array|Boolean}
+	*/
+	var arrayDiff = function(needles, array) {
+		var diff = [];
+
+		if (typeOf(needles) !== 'array') {
+			needles = [needles];
+		}
+
+		if (typeOf(array) !== 'array') {
+			array = [array];
+		}
+
+		for (var i in needles) {
+			if (inArray(needles[i], array) === -1) {
+				diff.push(needles[i]);
+			}	
+		}
+		return diff.length ? diff : false;
+	};
+
+
+	/**
+	Find intersection of two arrays.
+
+	@private
+	@method arrayIntersect
+	@param {Array} array1
+	@param {Array} array2
+	@return {Array} Intersection of two arrays or null if there is none
+	*/
+	var arrayIntersect = function(array1, array2) {
+		var result = [];
+		each(array1, function(item) {
+			if (inArray(item, array2) !== -1) {
+				result.push(item);
+			}
+		});
+		return result.length ? result : null;
+	};
+	
+	
+	/**
+	Forces anything into an array.
+	
+	@method toArray
+	@static
+	@param {Object} obj Object with length field.
+	@return {Array} Array object containing all items.
+	*/
+	var toArray = function(obj) {
+		var i, arr = [];
+
+		for (i = 0; i < obj.length; i++) {
+			arr[i] = obj[i];
+		}
+
+		return arr;
+	};
+	
+			
+	/**
+	Generates an unique ID. This is 99.99% unique since it takes the current time and 5 random numbers.
+	The only way a user would be able to get the same ID is if the two persons at the same exact milisecond manages
+	to get 5 the same random numbers between 0-65535 it also uses a counter so each call will be guaranteed to be page unique.
+	It's more probable for the earth to be hit with an ansteriod. Y
+	
+	@method guid
+	@static
+	@param {String} prefix to prepend (by default 'o' will be prepended).
+	@method guid
+	@return {String} Virtually unique id.
+	*/
+	var guid = (function() {
+		var counter = 0;
+		
+		return function(prefix) {
+			var guid = new Date().getTime().toString(32), i;
+
+			for (i = 0; i < 5; i++) {
+				guid += Math.floor(Math.random() * 65535).toString(32);
+			}
+			
+			return (prefix || 'o_') + guid + (counter++).toString(32);
+		};
+	}());
+	
+
+	/**
+	Trims white spaces around the string
+	
+	@method trim
+	@static
+	@param {String} str
+	@return {String}
+	*/
+	var trim = function(str) {
+		if (!str) {
+			return str;
+		}
+		return String.prototype.trim ? String.prototype.trim.call(str) : str.toString().replace(/^\s*/, '').replace(/\s*$/, '');
+	};
+
+
+	/**
+	Parses the specified size string into a byte value. For example 10kb becomes 10240.
+	
+	@method parseSizeStr
+	@static
+	@param {String/Number} size String to parse or number to just pass through.
+	@return {Number} Size in bytes.
+	*/
+	var parseSizeStr = function(size) {
+		if (typeof(size) !== 'string') {
+			return size;
+		}
+		
+		var muls = {
+				t: 1099511627776,
+				g: 1073741824,
+				m: 1048576,
+				k: 1024
+			},
+			mul;
+
+		size = /^([0-9]+)([mgk]?)$/.exec(size.toLowerCase().replace(/[^0-9mkg]/g, ''));
+		mul = size[2];
+		size = +size[1];
+		
+		if (muls.hasOwnProperty(mul)) {
+			size *= muls[mul];
+		}
+		return size;
+	};
+	
+
+	return {
+		guid: guid,
+		typeOf: typeOf,
+		extend: extend,
+		each: each,
+		isEmptyObj: isEmptyObj,
+		inSeries: inSeries,
+		inParallel: inParallel,
+		inArray: inArray,
+		arrayDiff: arrayDiff,
+		arrayIntersect: arrayIntersect,
+		toArray: toArray,
+		trim: trim,
+		parseSizeStr: parseSizeStr
+	};
+});
+
+// Included from: src/javascript/core/I18n.js
+
+/**
+ * I18n.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+define("moxie/core/I18n", [
+	"moxie/core/utils/Basic"
+], function(Basic) {
+	var i18n = {};
+
+	return {
+		/**
+		 * Extends the language pack object with new items.
+		 *
+		 * @param {Object} pack Language pack items to add.
+		 * @return {Object} Extended language pack object.
+		 */
+		addI18n: function(pack) {
+			return Basic.extend(i18n, pack);
+		},
+
+		/**
+		 * Translates the specified string by checking for the english string in the language pack lookup.
+		 *
+		 * @param {String} str String to look for.
+		 * @return {String} Translated string or the input string if it wasn't found.
+		 */
+		translate: function(str) {
+			return i18n[str] || str;
+		},
+
+		/**
+		 * Shortcut for translate function
+		 *
+		 * @param {String} str String to look for.
+		 * @return {String} Translated string or the input string if it wasn't found.
+		 */
+		_: function(str) {
+			return this.translate(str);
+		},
+
+		/**
+		 * Pseudo sprintf implementation - simple way to replace tokens with specified values.
+		 *
+		 * @param {String} str String with tokens
+		 * @return {String} String with replaced tokens
+		 */
+		sprintf: function(str) {
+			var args = [].slice.call(arguments, 1);
+
+			return str.replace(/%[a-z]/g, function() {
+				var value = args.shift();
+				return Basic.typeOf(value) !== 'undefined' ? value : '';
+			});
+		}
+	};
+});
+
+// Included from: src/javascript/core/utils/Mime.js
+
+/**
+ * Mime.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+define("moxie/core/utils/Mime", [
+	"moxie/core/utils/Basic",
+	"moxie/core/I18n"
+], function(Basic, I18n) {
+	
+	var mimeData = "" +
+		"application/msword,doc dot," +
+		"application/pdf,pdf," +
+		"application/pgp-signature,pgp," +
+		"application/postscript,ps ai eps," +
+		"application/rtf,rtf," +
+		"application/vnd.ms-excel,xls xlb," +
+		"application/vnd.ms-powerpoint,ppt pps pot," +
+		"application/zip,zip," +
+		"application/x-shockwave-flash,swf swfl," +
+		"application/vnd.openxmlformats-officedocument.wordprocessingml.document,docx," +
+		"application/vnd.openxmlformats-officedocument.wordprocessingml.template,dotx," +
+		"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,xlsx," +
+		"application/vnd.openxmlformats-officedocument.presentationml.presentation,pptx," +
+		"application/vnd.openxmlformats-officedocument.presentationml.template,potx," +
+		"application/vnd.openxmlformats-officedocument.presentationml.slideshow,ppsx," +
+		"application/x-javascript,js," +
+		"application/json,json," +
+		"audio/mpeg,mp3 mpga mpega mp2," +
+		"audio/x-wav,wav," +
+		"audio/x-m4a,m4a," +
+		"audio/ogg,oga ogg," +
+		"audio/aiff,aiff aif," +
+		"audio/flac,flac," +
+		"audio/aac,aac," +
+		"audio/ac3,ac3," +
+		"audio/x-ms-wma,wma," +
+		"image/bmp,bmp," +
+		"image/gif,gif," +
+		"image/jpeg,jpg jpeg jpe," +
+		"image/photoshop,psd," +
+		"image/png,png," +
+		"image/svg+xml,svg svgz," +
+		"image/tiff,tiff tif," +
+		"text/plain,asc txt text diff log," +
+		"text/html,htm html xhtml," +
+		"text/css,css," +
+		"text/csv,csv," +
+		"text/rtf,rtf," +
+		"video/mpeg,mpeg mpg mpe m2v," +
+		"video/quicktime,qt mov," +
+		"video/mp4,mp4," +
+		"video/x-m4v,m4v," +
+		"video/x-flv,flv," +
+		"video/x-ms-wmv,wmv," +
+		"video/avi,avi," +
+		"video/webm,webm," +
+		"video/3gpp,3gpp 3gp," +
+		"video/3gpp2,3g2," +
+		"video/vnd.rn-realvideo,rv," +
+		"video/ogg,ogv," + 
+		"video/x-matroska,mkv," +
+		"application/vnd.oasis.opendocument.formula-template,otf," +
+		"application/octet-stream,exe";
+	
+	
+	var Mime = {
+
+		mimes: {},
+
+		extensions: {},
+
+		// Parses the default mime types string into a mimes and extensions lookup maps
+		addMimeType: function (mimeData) {
+			var items = mimeData.split(/,/), i, ii, ext;
+			
+			for (i = 0; i < items.length; i += 2) {
+				ext = items[i + 1].split(/ /);
+
+				// extension to mime lookup
+				for (ii = 0; ii < ext.length; ii++) {
+					this.mimes[ext[ii]] = items[i];
+				}
+				// mime to extension lookup
+				this.extensions[items[i]] = ext;
+			}
+		},
+
+
+		extList2mimes: function (filters, addMissingExtensions) {
+			var self = this, ext, i, ii, type, mimes = [];
+			
+			// convert extensions to mime types list
+			for (i = 0; i < filters.length; i++) {
+				ext = filters[i].extensions.split(/\s*,\s*/);
+
+				for (ii = 0; ii < ext.length; ii++) {
+					
+					// if there's an asterisk in the list, then accept attribute is not required
+					if (ext[ii] === '*') {
+						return [];
+					}
+					
+					type = self.mimes[ext[ii]];
+					if (!type) {
+						if (addMissingExtensions && /^\w+$/.test(ext[ii])) {
+							mimes.push('.' + ext[ii]);
+						} else {
+							return []; // accept all
+						}
+					} else if (Basic.inArray(type, mimes) === -1) {
+						mimes.push(type);
+					}
+				}
+			}
+			return mimes;
+		},
+
+
+		mimes2exts: function(mimes) {
+			var self = this, exts = [];
+			
+			Basic.each(mimes, function(mime) {
+				if (mime === '*') {
+					exts = [];
+					return false;
+				}
+
+				// check if this thing looks like mime type
+				var m = mime.match(/^(\w+)\/(\*|\w+)$/);
+				if (m) {
+					if (m[2] === '*') { 
+						// wildcard mime type detected
+						Basic.each(self.extensions, function(arr, mime) {
+							if ((new RegExp('^' + m[1] + '/')).test(mime)) {
+								[].push.apply(exts, self.extensions[mime]);
+							}
+						});
+					} else if (self.extensions[mime]) {
+						[].push.apply(exts, self.extensions[mime]);
+					}
+				}
+			});
+			return exts;
+		},
+
+
+		mimes2extList: function(mimes) {
+			var accept = [], exts = [];
+
+			if (Basic.typeOf(mimes) === 'string') {
+				mimes = Basic.trim(mimes).split(/\s*,\s*/);
+			}
+
+			exts = this.mimes2exts(mimes);
+			
+			accept.push({
+				title: I18n.translate('Files'),
+				extensions: exts.length ? exts.join(',') : '*'
+			});
+			
+			// save original mimes string
+			accept.mimes = mimes;
+
+			return accept;
+		},
+
+
+		getFileExtension: function(fileName) {
+			var matches = fileName && fileName.match(/\.([^.]+)$/);
+			if (matches) {
+				return matches[1].toLowerCase();
+			}
+			return '';
+		},
+
+		getFileMime: function(fileName) {
+			return this.mimes[this.getFileExtension(fileName)] || '';
+		}
+	};
+
+	Mime.addMimeType(mimeData);
+
+	return Mime;
+});
+
+// Included from: src/javascript/core/utils/Env.js
+
+/**
+ * Env.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+define("moxie/core/utils/Env", [
+	"moxie/core/utils/Basic"
+], function(Basic) {
+	
+	// UAParser.js v0.6.2
+	// Lightweight JavaScript-based User-Agent string parser
+	// https://github.com/faisalman/ua-parser-js
+	//
+	// Copyright © 2012-2013 Faisalman <fyzlman@gmail.com>
+	// Dual licensed under GPLv2 & MIT
+
+	var UAParser = (function (undefined) {
+
+	    //////////////
+	    // Constants
+	    /////////////
+
+
+	    var EMPTY       = '',
+	        UNKNOWN     = '?',
+	        FUNC_TYPE   = 'function',
+	        UNDEF_TYPE  = 'undefined',
+	        OBJ_TYPE    = 'object',
+	        MAJOR       = 'major',
+	        MODEL       = 'model',
+	        NAME        = 'name',
+	        TYPE        = 'type',
+	        VENDOR      = 'vendor',
+	        VERSION     = 'version',
+	        ARCHITECTURE= 'architecture',
+	        CONSOLE     = 'console',
+	        MOBILE      = 'mobile',
+	        TABLET      = 'tablet';
+
+
+	    ///////////
+	    // Helper
+	    //////////
+
+
+	    var util = {
+	        has : function (str1, str2) {
+	            return str2.toLowerCase().indexOf(str1.toLowerCase()) !== -1;
+	        },
+	        lowerize : function (str) {
+	            return str.toLowerCase();
+	        }
+	    };
+
+
+	    ///////////////
+	    // Map helper
+	    //////////////
+
+
+	    var mapper = {
+
+	        rgx : function () {
+
+	            // loop through all regexes maps
+	            for (var result, i = 0, j, k, p, q, matches, match, args = arguments; i < args.length; i += 2) {
+
+	                var regex = args[i],       // even sequence (0,2,4,..)
+	                    props = args[i + 1];   // odd sequence (1,3,5,..)
+
+	                // construct object barebones
+	                if (typeof(result) === UNDEF_TYPE) {
+	                    result = {};
+	                    for (p in props) {
+	                        q = props[p];
+	                        if (typeof(q) === OBJ_TYPE) {
+	                            result[q[0]] = undefined;
+	                        } else {
+	                            result[q] = undefined;
+	                        }
+	                    }
+	                }
+
+	                // try matching uastring with regexes
+	                for (j = k = 0; j < regex.length; j++) {
+	                    matches = regex[j].exec(this.getUA());
+	                    if (!!matches) {
+	                        for (p = 0; p < props.length; p++) {
+	                            match = matches[++k];
+	                            q = props[p];
+	                            // check if given property is actually array
+	                            if (typeof(q) === OBJ_TYPE && q.length > 0) {
+	                                if (q.length == 2) {
+	                                    if (typeof(q[1]) == FUNC_TYPE) {
+	                                        // assign modified match
+	                                        result[q[0]] = q[1].call(this, match);
+	                                    } else {
+	                                        // assign given value, ignore regex match
+	                                        result[q[0]] = q[1];
+	                                    }
+	                                } else if (q.length == 3) {
+	                                    // check whether function or regex
+	                                    if (typeof(q[1]) === FUNC_TYPE && !(q[1].exec && q[1].test)) {
+	                                        // call function (usually string mapper)
+	                                        result[q[0]] = match ? q[1].call(this, match, q[2]) : undefined;
+	                                    } else {
+	                                        // sanitize match using given regex
+	                                        result[q[0]] = match ? match.replace(q[1], q[2]) : undefined;
+	                                    }
+	                                } else if (q.length == 4) {
+	                                        result[q[0]] = match ? q[3].call(this, match.replace(q[1], q[2])) : undefined;
+	                                }
+	                            } else {
+	                                result[q] = match ? match : undefined;
+	                            }
+	                        }
+	                        break;
+	                    }
+	                }
+
+	                if(!!matches) break; // break the loop immediately if match found
+	            }
+	            return result;
+	        },
+
+	        str : function (str, map) {
+
+	            for (var i in map) {
+	                // check if array
+	                if (typeof(map[i]) === OBJ_TYPE && map[i].length > 0) {
+	                    for (var j = 0; j < map[i].length; j++) {
+	                        if (util.has(map[i][j], str)) {
+	                            return (i === UNKNOWN) ? undefined : i;
+	                        }
+	                    }
+	                } else if (util.has(map[i], str)) {
+	                    return (i === UNKNOWN) ? undefined : i;
+	                }
+	            }
+	            return str;
+	        }
+	    };
+
+
+	    ///////////////
+	    // String map
+	    //////////////
+
+
+	    var maps = {
+
+	        browser : {
+	            oldsafari : {
+	                major : {
+	                    '1' : ['/8', '/1', '/3'],
+	                    '2' : '/4',
+	                    '?' : '/'
+	                },
+	                version : {
+	                    '1.0'   : '/8',
+	                    '1.2'   : '/1',
+	                    '1.3'   : '/3',
+	                    '2.0'   : '/412',
+	                    '2.0.2' : '/416',
+	                    '2.0.3' : '/417',
+	                    '2.0.4' : '/419',
+	                    '?'     : '/'
+	                }
+	            }
+	        },
+
+	        device : {
+	            sprint : {
+	                model : {
+	                    'Evo Shift 4G' : '7373KT'
+	                },
+	                vendor : {
+	                    'HTC'       : 'APA',
+	                    'Sprint'    : 'Sprint'
+	                }
+	            }
+	        },
+
+	        os : {
+	            windows : {
+	                version : {
+	                    'ME'        : '4.90',
+	                    'NT 3.11'   : 'NT3.51',
+	                    'NT 4.0'    : 'NT4.0',
+	                    '2000'      : 'NT 5.0',
+	                    'XP'        : ['NT 5.1', 'NT 5.2'],
+	                    'Vista'     : 'NT 6.0',
+	                    '7'         : 'NT 6.1',
+	                    '8'         : 'NT 6.2',
+	                    '8.1'       : 'NT 6.3',
+	                    'RT'        : 'ARM'
+	                }
+	            }
+	        }
+	    };
+
+
+	    //////////////
+	    // Regex map
+	    /////////////
+
+
+	    var regexes = {
+
+	        browser : [[
+
+	            // Presto based
+	            /(opera\smini)\/((\d+)?[\w\.-]+)/i,                                 // Opera Mini
+	            /(opera\s[mobiletab]+).+version\/((\d+)?[\w\.-]+)/i,                // Opera Mobi/Tablet
+	            /(opera).+version\/((\d+)?[\w\.]+)/i,                               // Opera > 9.80
+	            /(opera)[\/\s]+((\d+)?[\w\.]+)/i                                    // Opera < 9.80
+	            
+	            ], [NAME, VERSION, MAJOR], [
+
+	            /\s(opr)\/((\d+)?[\w\.]+)/i                                         // Opera Webkit
+	            ], [[NAME, 'Opera'], VERSION, MAJOR], [
+
+	            // Mixed
+	            /(kindle)\/((\d+)?[\w\.]+)/i,                                       // Kindle
+	            /(lunascape|maxthon|netfront|jasmine|blazer)[\/\s]?((\d+)?[\w\.]+)*/i,
+	                                                                                // Lunascape/Maxthon/Netfront/Jasmine/Blazer
+
+	            // Trident based
+	            /(avant\s|iemobile|slim|baidu)(?:browser)?[\/\s]?((\d+)?[\w\.]*)/i,
+	                                                                                // Avant/IEMobile/SlimBrowser/Baidu
+	            /(?:ms|\()(ie)\s((\d+)?[\w\.]+)/i,                                  // Internet Explorer
+
+	            // Webkit/KHTML based
+	            /(rekonq)((?:\/)[\w\.]+)*/i,                                        // Rekonq
+	            /(chromium|flock|rockmelt|midori|epiphany|silk|skyfire|ovibrowser|bolt|iron)\/((\d+)?[\w\.-]+)/i
+	                                                                                // Chromium/Flock/RockMelt/Midori/Epiphany/Silk/Skyfire/Bolt/Iron
+	            ], [NAME, VERSION, MAJOR], [
+
+	            /(trident).+rv[:\s]((\d+)?[\w\.]+).+like\sgecko/i                   // IE11
+	            ], [[NAME, 'IE'], VERSION, MAJOR], [
+
+	            /(yabrowser)\/((\d+)?[\w\.]+)/i                                     // Yandex
+	            ], [[NAME, 'Yandex'], VERSION, MAJOR], [
+
+	            /(comodo_dragon)\/((\d+)?[\w\.]+)/i                                 // Comodo Dragon
+	            ], [[NAME, /_/g, ' '], VERSION, MAJOR], [
+
+	            /(chrome|omniweb|arora|[tizenoka]{5}\s?browser)\/v?((\d+)?[\w\.]+)/i
+	                                                                                // Chrome/OmniWeb/Arora/Tizen/Nokia
+	            ], [NAME, VERSION, MAJOR], [
+
+	            /(dolfin)\/((\d+)?[\w\.]+)/i                                        // Dolphin
+	            ], [[NAME, 'Dolphin'], VERSION, MAJOR], [
+
+	            /((?:android.+)crmo|crios)\/((\d+)?[\w\.]+)/i                       // Chrome for Android/iOS
+	            ], [[NAME, 'Chrome'], VERSION, MAJOR], [
+
+	            /((?:android.+))version\/((\d+)?[\w\.]+)\smobile\ssafari/i          // Android Browser
+	            ], [[NAME, 'Android Browser'], VERSION, MAJOR], [
+
+	            /version\/((\d+)?[\w\.]+).+?mobile\/\w+\s(safari)/i                 // Mobile Safari
+	            ], [VERSION, MAJOR, [NAME, 'Mobile Safari']], [
+
+	            /version\/((\d+)?[\w\.]+).+?(mobile\s?safari|safari)/i              // Safari & Safari Mobile
+	            ], [VERSION, MAJOR, NAME], [
+
+	            /webkit.+?(mobile\s?safari|safari)((\/[\w\.]+))/i                   // Safari < 3.0
+	            ], [NAME, [MAJOR, mapper.str, maps.browser.oldsafari.major], [VERSION, mapper.str, maps.browser.oldsafari.version]], [
+
+	            /(konqueror)\/((\d+)?[\w\.]+)/i,                                    // Konqueror
+	            /(webkit|khtml)\/((\d+)?[\w\.]+)/i
+	            ], [NAME, VERSION, MAJOR], [
+
+	            // Gecko based
+	            /(navigator|netscape)\/((\d+)?[\w\.-]+)/i                           // Netscape
+	            ], [[NAME, 'Netscape'], VERSION, MAJOR], [
+	            /(swiftfox)/i,                                                      // Swiftfox
+	            /(icedragon|iceweasel|camino|chimera|fennec|maemo\sbrowser|minimo|conkeror)[\/\s]?((\d+)?[\w\.\+]+)/i,
+	                                                                                // IceDragon/Iceweasel/Camino/Chimera/Fennec/Maemo/Minimo/Conkeror
+	            /(firefox|seamonkey|k-meleon|icecat|iceape|firebird|phoenix)\/((\d+)?[\w\.-]+)/i,
+	                                                                                // Firefox/SeaMonkey/K-Meleon/IceCat/IceApe/Firebird/Phoenix
+	            /(mozilla)\/((\d+)?[\w\.]+).+rv\:.+gecko\/\d+/i,                    // Mozilla
+
+	            // Other
+	            /(uc\s?browser|polaris|lynx|dillo|icab|doris|amaya|w3m|netsurf|qqbrowser)[\/\s]?((\d+)?[\w\.]+)/i,
+	                                                                                // UCBrowser/Polaris/Lynx/Dillo/iCab/Doris/Amaya/w3m/NetSurf/QQBrowser
+	            /(links)\s\(((\d+)?[\w\.]+)/i,                                      // Links
+	            /(gobrowser)\/?((\d+)?[\w\.]+)*/i,                                  // GoBrowser
+	            /(ice\s?browser)\/v?((\d+)?[\w\._]+)/i,                             // ICE Browser
+	            /(mosaic)[\/\s]((\d+)?[\w\.]+)/i                                    // Mosaic
+	            ], [NAME, VERSION, MAJOR]
+	        ],
+
+	        engine : [[
+
+	            /(presto)\/([\w\.]+)/i,                                             // Presto
+	            /(webkit|trident|netfront|netsurf|amaya|lynx|w3m)\/([\w\.]+)/i,     // WebKit/Trident/NetFront/NetSurf/Amaya/Lynx/w3m
+	            /(khtml|tasman|links)[\/\s]\(?([\w\.]+)/i,                          // KHTML/Tasman/Links
+	            /(icab)[\/\s]([23]\.[\d\.]+)/i                                      // iCab
+	            ], [NAME, VERSION], [
+
+	            /rv\:([\w\.]+).*(gecko)/i                                           // Gecko
+	            ], [VERSION, NAME]
+	        ],
+
+	        os : [[
+
+	            // Windows based
+	            /(windows)\snt\s6\.2;\s(arm)/i,                                     // Windows RT
+	            /(windows\sphone(?:\sos)*|windows\smobile|windows)[\s\/]?([ntce\d\.\s]+\w)/i
+	            ], [NAME, [VERSION, mapper.str, maps.os.windows.version]], [
+	            /(win(?=3|9|n)|win\s9x\s)([nt\d\.]+)/i
+	            ], [[NAME, 'Windows'], [VERSION, mapper.str, maps.os.windows.version]], [
+
+	            // Mobile/Embedded OS
+	            /\((bb)(10);/i                                                      // BlackBerry 10
+	            ], [[NAME, 'BlackBerry'], VERSION], [
+	            /(blackberry)\w*\/?([\w\.]+)*/i,                                    // Blackberry
+	            /(tizen)\/([\w\.]+)/i,                                              // Tizen
+	            /(android|webos|palm\os|qnx|bada|rim\stablet\sos|meego)[\/\s-]?([\w\.]+)*/i
+	                                                                                // Android/WebOS/Palm/QNX/Bada/RIM/MeeGo
+	            ], [NAME, VERSION], [
+	            /(symbian\s?os|symbos|s60(?=;))[\/\s-]?([\w\.]+)*/i                 // Symbian
+	            ], [[NAME, 'Symbian'], VERSION],[
+	            /mozilla.+\(mobile;.+gecko.+firefox/i                               // Firefox OS
+	            ], [[NAME, 'Firefox OS'], VERSION], [
+
+	            // Console
+	            /(nintendo|playstation)\s([wids3portablevu]+)/i,                    // Nintendo/Playstation
+
+	            // GNU/Linux based
+	            /(mint)[\/\s\(]?(\w+)*/i,                                           // Mint
+	            /(joli|[kxln]?ubuntu|debian|[open]*suse|gentoo|arch|slackware|fedora|mandriva|centos|pclinuxos|redhat|zenwalk)[\/\s-]?([\w\.-]+)*/i,
+	                                                                                // Joli/Ubuntu/Debian/SUSE/Gentoo/Arch/Slackware
+	                                                                                // Fedora/Mandriva/CentOS/PCLinuxOS/RedHat/Zenwalk
+	            /(hurd|linux)\s?([\w\.]+)*/i,                                       // Hurd/Linux
+	            /(gnu)\s?([\w\.]+)*/i                                               // GNU
+	            ], [NAME, VERSION], [
+
+	            /(cros)\s[\w]+\s([\w\.]+\w)/i                                       // Chromium OS
+	            ], [[NAME, 'Chromium OS'], VERSION],[
+
+	            // Solaris
+	            /(sunos)\s?([\w\.]+\d)*/i                                           // Solaris
+	            ], [[NAME, 'Solaris'], VERSION], [
+
+	            // BSD based
+	            /\s([frentopc-]{0,4}bsd|dragonfly)\s?([\w\.]+)*/i                   // FreeBSD/NetBSD/OpenBSD/PC-BSD/DragonFly
+	            ], [NAME, VERSION],[
+
+	            /(ip[honead]+)(?:.*os\s*([\w]+)*\slike\smac|;\sopera)/i             // iOS
+	            ], [[NAME, 'iOS'], [VERSION, /_/g, '.']], [
+
+	            /(mac\sos\sx)\s?([\w\s\.]+\w)*/i                                    // Mac OS
+	            ], [NAME, [VERSION, /_/g, '.']], [
+
+	            // Other
+	            /(haiku)\s(\w+)/i,                                                  // Haiku
+	            /(aix)\s((\d)(?=\.|\)|\s)[\w\.]*)*/i,                               // AIX
+	            /(macintosh|mac(?=_powerpc)|plan\s9|minix|beos|os\/2|amigaos|morphos|risc\sos)/i,
+	                                                                                // Plan9/Minix/BeOS/OS2/AmigaOS/MorphOS/RISCOS
+	            /(unix)\s?([\w\.]+)*/i                                              // UNIX
+	            ], [NAME, VERSION]
+	        ]
+	    };
+
+
+	    /////////////////
+	    // Constructor
+	    ////////////////
+
+
+	    var UAParser = function (uastring) {
+
+	        var ua = uastring || ((window && window.navigator && window.navigator.userAgent) ? window.navigator.userAgent : EMPTY);
+
+	        this.getBrowser = function () {
+	            return mapper.rgx.apply(this, regexes.browser);
+	        };
+	        this.getEngine = function () {
+	            return mapper.rgx.apply(this, regexes.engine);
+	        };
+	        this.getOS = function () {
+	            return mapper.rgx.apply(this, regexes.os);
+	        };
+	        this.getResult = function() {
+	            return {
+	                ua      : this.getUA(),
+	                browser : this.getBrowser(),
+	                engine  : this.getEngine(),
+	                os      : this.getOS()
+	            };
+	        };
+	        this.getUA = function () {
+	            return ua;
+	        };
+	        this.setUA = function (uastring) {
+	            ua = uastring;
+	            return this;
+	        };
+	        this.setUA(ua);
+	    };
+
+	    return new UAParser().getResult();
+	})();
+
+
+	function version_compare(v1, v2, operator) {
+	  // From: http://phpjs.org/functions
+	  // +      original by: Philippe Jausions (http://pear.php.net/user/jausions)
+	  // +      original by: Aidan Lister (http://aidanlister.com/)
+	  // + reimplemented by: Kankrelune (http://www.webfaktory.info/)
+	  // +      improved by: Brett Zamir (http://brett-zamir.me)
+	  // +      improved by: Scott Baker
+	  // +      improved by: Theriault
+	  // *        example 1: version_compare('8.2.5rc', '8.2.5a');
+	  // *        returns 1: 1
+	  // *        example 2: version_compare('8.2.50', '8.2.52', '<');
+	  // *        returns 2: true
+	  // *        example 3: version_compare('5.3.0-dev', '5.3.0');
+	  // *        returns 3: -1
+	  // *        example 4: version_compare('4.1.0.52','4.01.0.51');
+	  // *        returns 4: 1
+
+	  // Important: compare must be initialized at 0.
+	  var i = 0,
+	    x = 0,
+	    compare = 0,
+	    // vm maps textual PHP versions to negatives so they're less than 0.
+	    // PHP currently defines these as CASE-SENSITIVE. It is important to
+	    // leave these as negatives so that they can come before numerical versions
+	    // and as if no letters were there to begin with.
+	    // (1alpha is < 1 and < 1.1 but > 1dev1)
+	    // If a non-numerical value can't be mapped to this table, it receives
+	    // -7 as its value.
+	    vm = {
+	      'dev': -6,
+	      'alpha': -5,
+	      'a': -5,
+	      'beta': -4,
+	      'b': -4,
+	      'RC': -3,
+	      'rc': -3,
+	      '#': -2,
+	      'p': 1,
+	      'pl': 1
+	    },
+	    // This function will be called to prepare each version argument.
+	    // It replaces every _, -, and + with a dot.
+	    // It surrounds any nonsequence of numbers/dots with dots.
+	    // It replaces sequences of dots with a single dot.
+	    //    version_compare('4..0', '4.0') == 0
+	    // Important: A string of 0 length needs to be converted into a value
+	    // even less than an unexisting value in vm (-7), hence [-8].
+	    // It's also important to not strip spaces because of this.
+	    //   version_compare('', ' ') == 1
+	    prepVersion = function (v) {
+	      v = ('' + v).replace(/[_\-+]/g, '.');
+	      v = v.replace(/([^.\d]+)/g, '.$1.').replace(/\.{2,}/g, '.');
+	      return (!v.length ? [-8] : v.split('.'));
+	    },
+	    // This converts a version component to a number.
+	    // Empty component becomes 0.
+	    // Non-numerical component becomes a negative number.
+	    // Numerical component becomes itself as an integer.
+	    numVersion = function (v) {
+	      return !v ? 0 : (isNaN(v) ? vm[v] || -7 : parseInt(v, 10));
+	    };
+
+	  v1 = prepVersion(v1);
+	  v2 = prepVersion(v2);
+	  x = Math.max(v1.length, v2.length);
+	  for (i = 0; i < x; i++) {
+	    if (v1[i] == v2[i]) {
+	      continue;
+	    }
+	    v1[i] = numVersion(v1[i]);
+	    v2[i] = numVersion(v2[i]);
+	    if (v1[i] < v2[i]) {
+	      compare = -1;
+	      break;
+	    } else if (v1[i] > v2[i]) {
+	      compare = 1;
+	      break;
+	    }
+	  }
+	  if (!operator) {
+	    return compare;
+	  }
+
+	  // Important: operator is CASE-SENSITIVE.
+	  // "No operator" seems to be treated as "<."
+	  // Any other values seem to make the function return null.
+	  switch (operator) {
+	  case '>':
+	  case 'gt':
+	    return (compare > 0);
+	  case '>=':
+	  case 'ge':
+	    return (compare >= 0);
+	  case '<=':
+	  case 'le':
+	    return (compare <= 0);
+	  case '==':
+	  case '=':
+	  case 'eq':
+	    return (compare === 0);
+	  case '<>':
+	  case '!=':
+	  case 'ne':
+	    return (compare !== 0);
+	  case '':
+	  case '<':
+	  case 'lt':
+	    return (compare < 0);
+	  default:
+	    return null;
+	  }
+	}
+
+
+	var can = (function() {
+		var caps = {
+				define_property: (function() {
+					/* // currently too much extra code required, not exactly worth it
+					try { // as of IE8, getters/setters are supported only on DOM elements
+						var obj = {};
+						if (Object.defineProperty) {
+							Object.defineProperty(obj, 'prop', {
+								enumerable: true,
+								configurable: true
+							});
+							return true;
+						}
+					} catch(ex) {}
+
+					if (Object.prototype.__defineGetter__ && Object.prototype.__defineSetter__) {
+						return true;
+					}*/
+					return false;
+				}()),
+
+				create_canvas: (function() {
+					// On the S60 and BB Storm, getContext exists, but always returns undefined
+					// so we actually have to call getContext() to verify
+					// github.com/Modernizr/Modernizr/issues/issue/97/
+					var el = document.createElement('canvas');
+					return !!(el.getContext && el.getContext('2d'));
+				}()),
+
+				return_response_type: function(responseType) {
+					try {
+						if (Basic.inArray(responseType, ['', 'text', 'document']) !== -1) {
+							return true;
+						} else if (window.XMLHttpRequest) {
+							var xhr = new XMLHttpRequest();
+							xhr.open('get', '/'); // otherwise Gecko throws an exception
+							if ('responseType' in xhr) {
+								xhr.responseType = responseType;
+								// as of 23.0.1271.64, Chrome switched from throwing exception to merely logging it to the console (why? o why?)
+								if (xhr.responseType !== responseType) {
+									return false;
+								}
+								return true;
+							}
+						}
+					} catch (ex) {}
+					return false;
+				},
+
+				// ideas for this heavily come from Modernizr (http://modernizr.com/)
+				use_data_uri: (function() {
+					var du = new Image();
+
+					du.onload = function() {
+						caps.use_data_uri = (du.width === 1 && du.height === 1);
+					};
+					
+					setTimeout(function() {
+						du.src = "data:image/gif;base64,R0lGODlhAQABAIAAAP8AAAAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==";
+					}, 1);
+					return false;
+				}()),
+
+				use_data_uri_over32kb: function() { // IE8
+					return caps.use_data_uri && (Env.browser !== 'IE' || Env.version >= 9);
+				},
+
+				use_data_uri_of: function(bytes) {
+					return (caps.use_data_uri && bytes < 33000 || caps.use_data_uri_over32kb());
+				},
+
+				use_fileinput: function() {
+					var el = document.createElement('input');
+					el.setAttribute('type', 'file');
+					return !el.disabled;
+				}
+			};
+
+		return function(cap) {
+			var args = [].slice.call(arguments);
+			args.shift(); // shift of cap
+			return Basic.typeOf(caps[cap]) === 'function' ? caps[cap].apply(this, args) : !!caps[cap];
+		};
+	}());
+
+
+	var Env = {
+		can: can,
+		
+		browser: UAParser.browser.name,
+		version: parseFloat(UAParser.browser.major),
+		os: UAParser.os.name, // everybody intuitively types it in a lowercase for some reason
+		osVersion: UAParser.os.version,
+
+		verComp: version_compare,
+		
+		swf_url: "../flash/Moxie.swf",
+		xap_url: "../silverlight/Moxie.xap",
+		global_event_dispatcher: "moxie.core.EventTarget.instance.dispatchEvent"
+	};
+
+	// for backward compatibility
+	// @deprecated Use `Env.os` instead
+	Env.OS = Env.os;
+
+	return Env;
+});
+
+// Included from: src/javascript/core/utils/Dom.js
+
+/**
+ * Dom.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+define('moxie/core/utils/Dom', ['moxie/core/utils/Env'], function(Env) {
+
+	/**
+	Get DOM Element by it's id.
+
+	@method get
+	@for Utils
+	@param {String} id Identifier of the DOM Element
+	@return {DOMElement}
+	*/
+	var get = function(id) {
+		if (typeof id !== 'string') {
+			return id;
+		}
+		return document.getElementById(id);
+	};
+
+	/**
+	Checks if specified DOM element has specified class.
+
+	@method hasClass
+	@static
+	@param {Object} obj DOM element like object to add handler to.
+	@param {String} name Class name
+	*/
+	var hasClass = function(obj, name) {
+		if (!obj.className) {
+			return false;
+		}
+
+		var regExp = new RegExp("(^|\\s+)"+name+"(\\s+|$)");
+		return regExp.test(obj.className);
+	};
+
+	/**
+	Adds specified className to specified DOM element.
+
+	@method addClass
+	@static
+	@param {Object} obj DOM element like object to add handler to.
+	@param {String} name Class name
+	*/
+	var addClass = function(obj, name) {
+		if (!hasClass(obj, name)) {
+			obj.className = !obj.className ? name : obj.className.replace(/\s+$/, '') + ' ' + name;
+		}
+	};
+
+	/**
+	Removes specified className from specified DOM element.
+
+	@method removeClass
+	@static
+	@param {Object} obj DOM element like object to add handler to.
+	@param {String} name Class name
+	*/
+	var removeClass = function(obj, name) {
+		if (obj.className) {
+			var regExp = new RegExp("(^|\\s+)"+name+"(\\s+|$)");
+			obj.className = obj.className.replace(regExp, function($0, $1, $2) {
+				return $1 === ' ' && $2 === ' ' ? ' ' : '';
+			});
+		}
+	};
+
+	/**
+	Returns a given computed style of a DOM element.
+
+	@method getStyle
+	@static
+	@param {Object} obj DOM element like object.
+	@param {String} name Style you want to get from the DOM element
+	*/
+	var getStyle = function(obj, name) {
+		if (obj.currentStyle) {
+			return obj.currentStyle[name];
+		} else if (window.getComputedStyle) {
+			return window.getComputedStyle(obj, null)[name];
+		}
+	};
+
+
+	/**
+	Returns the absolute x, y position of an Element. The position will be returned in a object with x, y fields.
+
+	@method getPos
+	@static
+	@param {Element} node HTML element or element id to get x, y position from.
+	@param {Element} root Optional root element to stop calculations at.
+	@return {object} Absolute position of the specified element object with x, y fields.
+	*/
+	var getPos = function(node, root) {
+		var x = 0, y = 0, parent, doc = document, nodeRect, rootRect;
+
+		node = node;
+		root = root || doc.body;
+
+		// Returns the x, y cordinate for an element on IE 6 and IE 7
+		function getIEPos(node) {
+			var bodyElm, rect, x = 0, y = 0;
+
+			if (node) {
+				rect = node.getBoundingClientRect();
+				bodyElm = doc.compatMode === "CSS1Compat" ? doc.documentElement : doc.body;
+				x = rect.left + bodyElm.scrollLeft;
+				y = rect.top + bodyElm.scrollTop;
+			}
+
+			return {
+				x : x,
+				y : y
+			};
+		}
+
+		// Use getBoundingClientRect on IE 6 and IE 7 but not on IE 8 in standards mode
+		if (node && node.getBoundingClientRect && Env.browser === 'IE' && (!doc.documentMode || doc.documentMode < 8)) {
+			nodeRect = getIEPos(node);
+			rootRect = getIEPos(root);
+
+			return {
+				x : nodeRect.x - rootRect.x,
+				y : nodeRect.y - rootRect.y
+			};
+		}
+
+		parent = node;
+		while (parent && parent != root && parent.nodeType) {
+			x += parent.offsetLeft || 0;
+			y += parent.offsetTop || 0;
+			parent = parent.offsetParent;
+		}
+
+		parent = node.parentNode;
+		while (parent && parent != root && parent.nodeType) {
+			x -= parent.scrollLeft || 0;
+			y -= parent.scrollTop || 0;
+			parent = parent.parentNode;
+		}
+
+		return {
+			x : x,
+			y : y
+		};
+	};
+
+	/**
+	Returns the size of the specified node in pixels.
+
+	@method getSize
+	@static
+	@param {Node} node Node to get the size of.
+	@return {Object} Object with a w and h property.
+	*/
+	var getSize = function(node) {
+		return {
+			w : node.offsetWidth || node.clientWidth,
+			h : node.offsetHeight || node.clientHeight
+		};
+	};
+
+	return {
+		get: get,
+		hasClass: hasClass,
+		addClass: addClass,
+		removeClass: removeClass,
+		getStyle: getStyle,
+		getPos: getPos,
+		getSize: getSize
+	};
+});
+
+// Included from: src/javascript/core/Exceptions.js
+
+/**
+ * Exceptions.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+define('moxie/core/Exceptions', [
+	'moxie/core/utils/Basic'
+], function(Basic) {
+	function _findKey(obj, value) {
+		var key;
+		for (key in obj) {
+			if (obj[key] === value) {
+				return key;
+			}
+		}
+		return null;
+	}
+
+	return {
+		RuntimeError: (function() {
+			var namecodes = {
+				NOT_INIT_ERR: 1,
+				NOT_SUPPORTED_ERR: 9,
+				JS_ERR: 4
+			};
+
+			function RuntimeError(code) {
+				this.code = code;
+				this.name = _findKey(namecodes, code);
+				this.message = this.name + ": RuntimeError " + this.code;
+			}
+			
+			Basic.extend(RuntimeError, namecodes);
+			RuntimeError.prototype = Error.prototype;
+			return RuntimeError;
+		}()),
+		
+		OperationNotAllowedException: (function() {
+			
+			function OperationNotAllowedException(code) {
+				this.code = code;
+				this.name = 'OperationNotAllowedException';
+			}
+			
+			Basic.extend(OperationNotAllowedException, {
+				NOT_ALLOWED_ERR: 1
+			});
+			
+			OperationNotAllowedException.prototype = Error.prototype;
+			
+			return OperationNotAllowedException;
+		}()),
+
+		ImageError: (function() {
+			var namecodes = {
+				WRONG_FORMAT: 1,
+				MAX_RESOLUTION_ERR: 2
+			};
+
+			function ImageError(code) {
+				this.code = code;
+				this.name = _findKey(namecodes, code);
+				this.message = this.name + ": ImageError " + this.code;
+			}
+			
+			Basic.extend(ImageError, namecodes);
+			ImageError.prototype = Error.prototype;
+
+			return ImageError;
+		}()),
+
+		FileException: (function() {
+			var namecodes = {
+				NOT_FOUND_ERR: 1,
+				SECURITY_ERR: 2,
+				ABORT_ERR: 3,
+				NOT_READABLE_ERR: 4,
+				ENCODING_ERR: 5,
+				NO_MODIFICATION_ALLOWED_ERR: 6,
+				INVALID_STATE_ERR: 7,
+				SYNTAX_ERR: 8
+			};
+
+			function FileException(code) {
+				this.code = code;
+				this.name = _findKey(namecodes, code);
+				this.message = this.name + ": FileException " + this.code;
+			}
+			
+			Basic.extend(FileException, namecodes);
+			FileException.prototype = Error.prototype;
+			return FileException;
+		}()),
+		
+		DOMException: (function() {
+			var namecodes = {
+				INDEX_SIZE_ERR: 1,
+				DOMSTRING_SIZE_ERR: 2,
+				HIERARCHY_REQUEST_ERR: 3,
+				WRONG_DOCUMENT_ERR: 4,
+				INVALID_CHARACTER_ERR: 5,
+				NO_DATA_ALLOWED_ERR: 6,
+				NO_MODIFICATION_ALLOWED_ERR: 7,
+				NOT_FOUND_ERR: 8,
+				NOT_SUPPORTED_ERR: 9,
+				INUSE_ATTRIBUTE_ERR: 10,
+				INVALID_STATE_ERR: 11,
+				SYNTAX_ERR: 12,
+				INVALID_MODIFICATION_ERR: 13,
+				NAMESPACE_ERR: 14,
+				INVALID_ACCESS_ERR: 15,
+				VALIDATION_ERR: 16,
+				TYPE_MISMATCH_ERR: 17,
+				SECURITY_ERR: 18,
+				NETWORK_ERR: 19,
+				ABORT_ERR: 20,
+				URL_MISMATCH_ERR: 21,
+				QUOTA_EXCEEDED_ERR: 22,
+				TIMEOUT_ERR: 23,
+				INVALID_NODE_TYPE_ERR: 24,
+				DATA_CLONE_ERR: 25
+			};
+
+			function DOMException(code) {
+				this.code = code;
+				this.name = _findKey(namecodes, code);
+				this.message = this.name + ": DOMException " + this.code;
+			}
+			
+			Basic.extend(DOMException, namecodes);
+			DOMException.prototype = Error.prototype;
+			return DOMException;
+		}()),
+		
+		EventException: (function() {
+			function EventException(code) {
+				this.code = code;
+				this.name = 'EventException';
+			}
+			
+			Basic.extend(EventException, {
+				UNSPECIFIED_EVENT_TYPE_ERR: 0
+			});
+			
+			EventException.prototype = Error.prototype;
+			
+			return EventException;
+		}())
+	};
+});
+
+// Included from: src/javascript/core/EventTarget.js
+
+/**
+ * EventTarget.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+define('moxie/core/EventTarget', [
+	'moxie/core/Exceptions',
+	'moxie/core/utils/Basic'
+], function(x, Basic) {
+	/**
+	Parent object for all event dispatching components and objects
+
+	@class EventTarget
+	@constructor EventTarget
+	*/
+	function EventTarget() {
+		// hash of event listeners by object uid
+		var eventpool = {};
+				
+		Basic.extend(this, {
+			
+			/**
+			Unique id of the event dispatcher, usually overriden by children
+
+			@property uid
+			@type String
+			*/
+			uid: null,
+			
+			/**
+			Can be called from within a child  in order to acquire uniqie id in automated manner
+
+			@method init
+			*/
+			init: function() {
+				if (!this.uid) {
+					this.uid = Basic.guid('uid_');
+				}
+			},
+
+			/**
+			Register a handler to a specific event dispatched by the object
+
+			@method addEventListener
+			@param {String} type Type or basically a name of the event to subscribe to
+			@param {Function} fn Callback function that will be called when event happens
+			@param {Number} [priority=0] Priority of the event handler - handlers with higher priorities will be called first
+			@param {Object} [scope=this] A scope to invoke event handler in
+			*/
+			addEventListener: function(type, fn, priority, scope) {
+				var self = this, list;
+				
+				type = Basic.trim(type);
+				
+				if (/\s/.test(type)) {
+					// multiple event types were passed for one handler
+					Basic.each(type.split(/\s+/), function(type) {
+						self.addEventListener(type, fn, priority, scope);
+					});
+					return;
+				}
+				
+				type = type.toLowerCase();
+				priority = parseInt(priority, 10) || 0;
+				
+				list = eventpool[this.uid] && eventpool[this.uid][type] || [];
+				list.push({fn : fn, priority : priority, scope : scope || this});
+				
+				if (!eventpool[this.uid]) {
+					eventpool[this.uid] = {};
+				}
+				eventpool[this.uid][type] = list;
+			},
+			
+			/**
+			Check if any handlers were registered to the specified event
+
+			@method hasEventListener
+			@param {String} type Type or basically a name of the event to check
+			@return {Mixed} Returns a handler if it was found and false, if - not
+			*/
+			hasEventListener: function(type) {
+				return type ? !!(eventpool[this.uid] && eventpool[this.uid][type]) : !!eventpool[this.uid];
+			},
+			
+			/**
+			Unregister the handler from the event, or if former was not specified - unregister all handlers
+
+			@method removeEventListener
+			@param {String} type Type or basically a name of the event
+			@param {Function} [fn] Handler to unregister
+			*/
+			removeEventListener: function(type, fn) {
+				type = type.toLowerCase();
+	
+				var list = eventpool[this.uid] && eventpool[this.uid][type], i;
+	
+				if (list) {
+					if (fn) {
+						for (i = list.length - 1; i >= 0; i--) {
+							if (list[i].fn === fn) {
+								list.splice(i, 1);
+								break;
+							}
+						}
+					} else {
+						list = [];
+					}
+	
+					// delete event list if it has become empty
+					if (!list.length) {
+						delete eventpool[this.uid][type];
+						
+						// and object specific entry in a hash if it has no more listeners attached
+						if (Basic.isEmptyObj(eventpool[this.uid])) {
+							delete eventpool[this.uid];
+						}
+					}
+				}
+			},
+			
+			/**
+			Remove all event handlers from the object
+
+			@method removeAllEventListeners
+			*/
+			removeAllEventListeners: function() {
+				if (eventpool[this.uid]) {
+					delete eventpool[this.uid];
+				}
+			},
+			
+			/**
+			Dispatch the event
+
+			@method dispatchEvent
+			@param {String/Object} Type of event or event object to dispatch
+			@param {Mixed} [...] Variable number of arguments to be passed to a handlers
+			@return {Boolean} true by default and false if any handler returned false
+			*/
+			dispatchEvent: function(type) {
+				var uid, list, args, tmpEvt, evt = {}, result = true, undef;
+				
+				if (Basic.typeOf(type) !== 'string') {
+					// we can't use original object directly (because of Silverlight)
+					tmpEvt = type;
+
+					if (Basic.typeOf(tmpEvt.type) === 'string') {
+						type = tmpEvt.type;
+
+						if (tmpEvt.total !== undef && tmpEvt.loaded !== undef) { // progress event
+							evt.total = tmpEvt.total;
+							evt.loaded = tmpEvt.loaded;
+						}
+						evt.async = tmpEvt.async || false;
+					} else {
+						throw new x.EventException(x.EventException.UNSPECIFIED_EVENT_TYPE_ERR);
+					}
+				}
+				
+				// check if event is meant to be dispatched on an object having specific uid
+				if (type.indexOf('::') !== -1) {
+					(function(arr) {
+						uid = arr[0];
+						type = arr[1];
+					}(type.split('::')));
+				} else {
+					uid = this.uid;
+				}
+				
+				type = type.toLowerCase();
+								
+				list = eventpool[uid] && eventpool[uid][type];
+
+				if (list) {
+					// sort event list by prority
+					list.sort(function(a, b) { return b.priority - a.priority; });
+					
+					args = [].slice.call(arguments);
+					
+					// first argument will be pseudo-event object
+					args.shift();
+					evt.type = type;
+					args.unshift(evt);
+
+					// Dispatch event to all listeners
+					var queue = [];
+					Basic.each(list, function(handler) {
+						// explicitly set the target, otherwise events fired from shims do not get it
+						args[0].target = handler.scope;
+						// if event is marked as async, detach the handler
+						if (evt.async) {
+							queue.push(function(cb) {
+								setTimeout(function() {
+									cb(handler.fn.apply(handler.scope, args) === false);
+								}, 1);
+							});
+						} else {
+							queue.push(function(cb) {
+								cb(handler.fn.apply(handler.scope, args) === false); // if handler returns false stop propagation
+							});
+						}
+					});
+					if (queue.length) {
+						Basic.inSeries(queue, function(err) {
+							result = !err;
+						});
+					}
+				}
+				return result;
+			},
+			
+			/**
+			Alias for addEventListener
+
+			@method bind
+			@protected
+			*/
+			bind: function() {
+				this.addEventListener.apply(this, arguments);
+			},
+			
+			/**
+			Alias for removeEventListener
+
+			@method unbind
+			@protected
+			*/
+			unbind: function() {
+				this.removeEventListener.apply(this, arguments);
+			},
+			
+			/**
+			Alias for removeAllEventListeners
+
+			@method unbindAll
+			@protected
+			*/
+			unbindAll: function() {
+				this.removeAllEventListeners.apply(this, arguments);
+			},
+			
+			/**
+			Alias for dispatchEvent
+
+			@method trigger
+			@protected
+			*/
+			trigger: function() {
+				return this.dispatchEvent.apply(this, arguments);
+			},
+			
+			
+			/**
+			Converts properties of on[event] type to corresponding event handlers,
+			is used to avoid extra hassle around the process of calling them back
+
+			@method convertEventPropsToHandlers
+			@private
+			*/
+			convertEventPropsToHandlers: function(handlers) {
+				var h;
+						
+				if (Basic.typeOf(handlers) !== 'array') {
+					handlers = [handlers];
+				}
+
+				for (var i = 0; i < handlers.length; i++) {
+					h = 'on' + handlers[i];
+					
+					if (Basic.typeOf(this[h]) === 'function') {
+						this.addEventListener(handlers[i], this[h]);
+					} else if (Basic.typeOf(this[h]) === 'undefined') {
+						this[h] = null; // object must have defined event properties, even if it doesn't make use of them
+					}
+				}
+			}
+			
+		});
+	}
+
+	EventTarget.instance = new EventTarget(); 
+
+	return EventTarget;
+});
+
+// Included from: src/javascript/core/utils/Encode.js
+
+/**
+ * Encode.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+define('moxie/core/utils/Encode', [], function() {
+
+	/**
+	Encode string with UTF-8
+
+	@method utf8_encode
+	@for Utils
+	@static
+	@param {String} str String to encode
+	@return {String} UTF-8 encoded string
+	*/
+	var utf8_encode = function(str) {
+		return unescape(encodeURIComponent(str));
+	};
+	
+	/**
+	Decode UTF-8 encoded string
+
+	@method utf8_decode
+	@static
+	@param {String} str String to decode
+	@return {String} Decoded string
+	*/
+	var utf8_decode = function(str_data) {
+		return decodeURIComponent(escape(str_data));
+	};
+	
+	/**
+	Decode Base64 encoded string (uses browser's default method if available),
+	from: https://raw.github.com/kvz/phpjs/master/functions/url/base64_decode.js
+
+	@method atob
+	@static
+	@param {String} data String to decode
+	@return {String} Decoded string
+	*/
+	var atob = function(data, utf8) {
+		if (typeof(window.atob) === 'function') {
+			return utf8 ? utf8_decode(window.atob(data)) : window.atob(data);
+		}
+
+		// http://kevin.vanzonneveld.net
+		// +   original by: Tyler Akins (http://rumkin.com)
+		// +   improved by: Thunder.m
+		// +      input by: Aman Gupta
+		// +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
+		// +   bugfixed by: Onno Marsman
+		// +   bugfixed by: Pellentesque Malesuada
+		// +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
+		// +      input by: Brett Zamir (http://brett-zamir.me)
+		// +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
+		// *     example 1: base64_decode('S2V2aW4gdmFuIFpvbm5ldmVsZA==');
+		// *     returns 1: 'Kevin van Zonneveld'
+		// mozilla has this native
+		// - but breaks in 2.0.0.12!
+		//if (typeof this.window.atob == 'function') {
+		//    return atob(data);
+		//}
+		var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
+		var o1, o2, o3, h1, h2, h3, h4, bits, i = 0,
+			ac = 0,
+			dec = "",
+			tmp_arr = [];
+
+		if (!data) {
+			return data;
+		}
+
+		data += '';
+
+		do { // unpack four hexets into three octets using index points in b64
+			h1 = b64.indexOf(data.charAt(i++));
+			h2 = b64.indexOf(data.charAt(i++));
+			h3 = b64.indexOf(data.charAt(i++));
+			h4 = b64.indexOf(data.charAt(i++));
+
+			bits = h1 << 18 | h2 << 12 | h3 << 6 | h4;
+
+			o1 = bits >> 16 & 0xff;
+			o2 = bits >> 8 & 0xff;
+			o3 = bits & 0xff;
+
+			if (h3 == 64) {
+				tmp_arr[ac++] = String.fromCharCode(o1);
+			} else if (h4 == 64) {
+				tmp_arr[ac++] = String.fromCharCode(o1, o2);
+			} else {
+				tmp_arr[ac++] = String.fromCharCode(o1, o2, o3);
+			}
+		} while (i < data.length);
+
+		dec = tmp_arr.join('');
+
+		return utf8 ? utf8_decode(dec) : dec;
+	};
+	
+	/**
+	Base64 encode string (uses browser's default method if available),
+	from: https://raw.github.com/kvz/phpjs/master/functions/url/base64_encode.js
+
+	@method btoa
+	@static
+	@param {String} data String to encode
+	@return {String} Base64 encoded string
+	*/
+	var btoa = function(data, utf8) {
+		if (utf8) {
+			utf8_encode(data);
+		}
+
+		if (typeof(window.btoa) === 'function') {
+			return window.btoa(data);
+		}
+
+		// http://kevin.vanzonneveld.net
+		// +   original by: Tyler Akins (http://rumkin.com)
+		// +   improved by: Bayron Guevara
+		// +   improved by: Thunder.m
+		// +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
+		// +   bugfixed by: Pellentesque Malesuada
+		// +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
+		// +   improved by: Rafał Kukawski (http://kukawski.pl)
+		// *     example 1: base64_encode('Kevin van Zonneveld');
+		// *     returns 1: 'S2V2aW4gdmFuIFpvbm5ldmVsZA=='
+		// mozilla has this native
+		// - but breaks in 2.0.0.12!
+		var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
+		var o1, o2, o3, h1, h2, h3, h4, bits, i = 0,
+			ac = 0,
+			enc = "",
+			tmp_arr = [];
+
+		if (!data) {
+			return data;
+		}
+
+		do { // pack three octets into four hexets
+			o1 = data.charCodeAt(i++);
+			o2 = data.charCodeAt(i++);
+			o3 = data.charCodeAt(i++);
+
+			bits = o1 << 16 | o2 << 8 | o3;
+
+			h1 = bits >> 18 & 0x3f;
+			h2 = bits >> 12 & 0x3f;
+			h3 = bits >> 6 & 0x3f;
+			h4 = bits & 0x3f;
+
+			// use hexets to index into b64, and append result to encoded string
+			tmp_arr[ac++] = b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4);
+		} while (i < data.length);
+
+		enc = tmp_arr.join('');
+
+		var r = data.length % 3;
+
+		return (r ? enc.slice(0, r - 3) : enc) + '==='.slice(r || 3);
+	};
+
+
+	return {
+		utf8_encode: utf8_encode,
+		utf8_decode: utf8_decode,
+		atob: atob,
+		btoa: btoa
+	};
+});
+
+// Included from: src/javascript/runtime/Runtime.js
+
+/**
+ * Runtime.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+define('moxie/runtime/Runtime', [
+	"moxie/core/utils/Basic",
+	"moxie/core/utils/Dom",
+	"moxie/core/EventTarget"
+], function(Basic, Dom, EventTarget) {
+	var runtimeConstructors = {}, runtimes = {};
+
+	/**
+	Common set of methods and properties for every runtime instance
+
+	@class Runtime
+
+	@param {Object} options
+	@param {String} type Sanitized name of the runtime
+	@param {Object} [caps] Set of capabilities that differentiate specified runtime
+	@param {Object} [modeCaps] Set of capabilities that do require specific operational mode
+	@param {String} [preferredMode='browser'] Preferred operational mode to choose if no required capabilities were requested
+	*/
+	function Runtime(options, type, caps, modeCaps, preferredMode) {
+		/**
+		Dispatched when runtime is initialized and ready.
+		Results in RuntimeInit on a connected component.
+
+		@event Init
+		*/
+
+		/**
+		Dispatched when runtime fails to initialize.
+		Results in RuntimeError on a connected component.
+
+		@event Error
+		*/
+
+		var self = this
+		, _shim
+		, _uid = Basic.guid(type + '_')
+		, defaultMode = preferredMode || 'browser'
+		;
+
+		options = options || {};
+
+		// register runtime in private hash
+		runtimes[_uid] = this;
+
+		/**
+		Default set of capabilities, which can be redifined later by specific runtime
+
+		@private
+		@property caps
+		@type Object
+		*/
+		caps = Basic.extend({
+			// Runtime can: 
+			// provide access to raw binary data of the file
+			access_binary: false,
+			// provide access to raw binary data of the image (image extension is optional) 
+			access_image_binary: false,
+			// display binary data as thumbs for example
+			display_media: false,
+			// make cross-domain requests
+			do_cors: false,
+			// accept files dragged and dropped from the desktop
+			drag_and_drop: false,
+			// filter files in selection dialog by their extensions
+			filter_by_extension: true,
+			// resize image (and manipulate it raw data of any file in general)
+			resize_image: false,
+			// periodically report how many bytes of total in the file were uploaded (loaded)
+			report_upload_progress: false,
+			// provide access to the headers of http response 
+			return_response_headers: false,
+			// support response of specific type, which should be passed as an argument
+			// e.g. runtime.can('return_response_type', 'blob')
+			return_response_type: false,
+			// return http status code of the response
+			return_status_code: true,
+			// send custom http header with the request
+			send_custom_headers: false,
+			// pick up the files from a dialog
+			select_file: false,
+			// select whole folder in file browse dialog
+			select_folder: false,
+			// select multiple files at once in file browse dialog
+			select_multiple: true,
+			// send raw binary data, that is generated after image resizing or manipulation of other kind
+			send_binary_string: false,
+			// send cookies with http request and therefore retain session
+			send_browser_cookies: true,
+			// send data formatted as multipart/form-data
+			send_multipart: true,
+			// slice the file or blob to smaller parts
+			slice_blob: false,
+			// upload file without preloading it to memory, stream it out directly from disk
+			stream_upload: false,
+			// programmatically trigger file browse dialog
+			summon_file_dialog: false,
+			// upload file of specific size, size should be passed as argument
+			// e.g. runtime.can('upload_filesize', '500mb')
+			upload_filesize: true,
+			// initiate http request with specific http method, method should be passed as argument
+			// e.g. runtime.can('use_http_method', 'put')
+			use_http_method: true
+		}, caps);
+			
+	
+		// default to the mode that is compatible with preferred caps
+		if (options.preferred_caps) {
+			defaultMode = Runtime.getMode(modeCaps, options.preferred_caps, defaultMode);
+		}
+		
+		// small extension factory here (is meant to be extended with actual extensions constructors)
+		_shim = (function() {
+			var objpool = {};
+			return {
+				exec: function(uid, comp, fn, args) {
+					if (_shim[comp]) {
+						if (!objpool[uid]) {
+							objpool[uid] = {
+								context: this,
+								instance: new _shim[comp]()
+							};
+						}
+						if (objpool[uid].instance[fn]) {
+							return objpool[uid].instance[fn].apply(this, args);
+						}
+					}
+				},
+
+				removeInstance: function(uid) {
+					delete objpool[uid];
+				},
+
+				removeAllInstances: function() {
+					var self = this;
+					Basic.each(objpool, function(obj, uid) {
+						if (Basic.typeOf(obj.instance.destroy) === 'function') {
+							obj.instance.destroy.call(obj.context);
+						}
+						self.removeInstance(uid);
+					});
+				}
+			};
+		}());
+
+
+		// public methods
+		Basic.extend(this, {
+			/**
+			Specifies whether runtime instance was initialized or not
+
+			@property initialized
+			@type {Boolean}
+			@default false
+			*/
+			initialized: false, // shims require this flag to stop initialization retries
+
+			/**
+			Unique ID of the runtime
+
+			@property uid
+			@type {String}
+			*/
+			uid: _uid,
+
+			/**
+			Runtime type (e.g. flash, html5, etc)
+
+			@property type
+			@type {String}
+			*/
+			type: type,
+
+			/**
+			Runtime (not native one) may operate in browser or client mode.
+
+			@property mode
+			@private
+			@type {String|Boolean} current mode or false, if none possible
+			*/
+			mode: Runtime.getMode(modeCaps, (options.required_caps), defaultMode),
+
+			/**
+			id of the DOM container for the runtime (if available)
+
+			@property shimid
+			@type {String}
+			*/
+			shimid: _uid + '_container',
+
+			/**
+			Number of connected clients. If equal to zero, runtime can be destroyed
+
+			@property clients
+			@type {Number}
+			*/
+			clients: 0,
+
+			/**
+			Runtime initialization options
+
+			@property options
+			@type {Object}
+			*/
+			options: options,
+
+			/**
+			Checks if the runtime has specific capability
+
+			@method can
+			@param {String} cap Name of capability to check
+			@param {Mixed} [value] If passed, capability should somehow correlate to the value
+			@param {Object} [refCaps] Set of capabilities to check the specified cap against (defaults to internal set)
+			@return {Boolean} true if runtime has such capability and false, if - not
+			*/
+			can: function(cap, value) {
+				var refCaps = arguments[2] || caps;
+
+				// if cap var is a comma-separated list of caps, convert it to object (key/value)
+				if (Basic.typeOf(cap) === 'string' && Basic.typeOf(value) === 'undefined') {
+					cap = Runtime.parseCaps(cap);
+				}
+
+				if (Basic.typeOf(cap) === 'object') {
+					for (var key in cap) {
+						if (!this.can(key, cap[key], refCaps)) {
+							return false;
+						}
+					}
+					return true;
+				}
+
+				// check the individual cap
+				if (Basic.typeOf(refCaps[cap]) === 'function') {
+					return refCaps[cap].call(this, value);
+				} else {
+					return (value === refCaps[cap]);
+				}
+			},
+
+			/**
+			Returns container for the runtime as DOM element
+
+			@method getShimContainer
+			@return {DOMElement}
+			*/
+			getShimContainer: function() {
+				var container, shimContainer = Dom.get(this.shimid);
+
+				// if no container for shim, create one
+				if (!shimContainer) {
+					container = this.options.container ? Dom.get(this.options.container) : document.body;
+
+					// create shim container and insert it at an absolute position into the outer container
+					shimContainer = document.createElement('div');
+					shimContainer.id = this.shimid;
+					shimContainer.className = 'moxie-shim moxie-shim-' + this.type;
+
+					Basic.extend(shimContainer.style, {
+						position: 'absolute',
+						top: '0px',
+						left: '0px',
+						width: '1px',
+						height: '1px',
+						overflow: 'hidden'
+					});
+
+					container.appendChild(shimContainer);
+					container = null;
+				}
+
+				return shimContainer;
+			},
+
+			/**
+			Returns runtime as DOM element (if appropriate)
+
+			@method getShim
+			@return {DOMElement}
+			*/
+			getShim: function() {
+				return _shim;
+			},
+
+			/**
+			Invokes a method within the runtime itself (might differ across the runtimes)
+
+			@method shimExec
+			@param {Mixed} []
+			@protected
+			@return {Mixed} Depends on the action and component
+			*/
+			shimExec: function(component, action) {
+				var args = [].slice.call(arguments, 2);
+				return self.getShim().exec.call(this, this.uid, component, action, args);
+			},
+
+			/**
+			Operaional interface that is used by components to invoke specific actions on the runtime
+			(is invoked in the scope of component)
+
+			@method exec
+			@param {Mixed} []*
+			@protected
+			@return {Mixed} Depends on the action and component
+			*/
+			exec: function(component, action) { // this is called in the context of component, not runtime
+				var args = [].slice.call(arguments, 2);
+
+				if (self[component] && self[component][action]) {
+					return self[component][action].apply(this, args);
+				}
+				return self.shimExec.apply(this, arguments);
+			},
+
+			/**
+			Destroys the runtime (removes all events and deletes DOM structures)
+
+			@method destroy
+			*/
+			destroy: function() {
+				if (!self) {
+					return; // obviously already destroyed
+				}
+
+				var shimContainer = Dom.get(this.shimid);
+				if (shimContainer) {
+					shimContainer.parentNode.removeChild(shimContainer);
+				}
+
+				if (_shim) {
+					_shim.removeAllInstances();
+				}
+
+				this.unbindAll();
+				delete runtimes[this.uid];
+				this.uid = null; // mark this runtime as destroyed
+				_uid = self = _shim = shimContainer = null;
+			}
+		});
+
+		// once we got the mode, test against all caps
+		if (this.mode && options.required_caps && !this.can(options.required_caps)) {
+			this.mode = false;
+		}	
+	}
+
+
+	/**
+	Default order to try different runtime types
+
+	@property order
+	@type String
+	@static
+	*/
+	Runtime.order = 'html5,flash,silverlight,html4';
+
+
+	/**
+	Retrieves runtime from private hash by it's uid
+
+	@method getRuntime
+	@private
+	@static
+	@param {String} uid Unique identifier of the runtime
+	@return {Runtime|Boolean} Returns runtime, if it exists and false, if - not
+	*/
+	Runtime.getRuntime = function(uid) {
+		return runtimes[uid] ? runtimes[uid] : false;
+	};
+
+
+	/**
+	Register constructor for the Runtime of new (or perhaps modified) type
+
+	@method addConstructor
+	@static
+	@param {String} type Runtime type (e.g. flash, html5, etc)
+	@param {Function} construct Constructor for the Runtime type
+	*/
+	Runtime.addConstructor = function(type, constructor) {
+		constructor.prototype = EventTarget.instance;
+		runtimeConstructors[type] = constructor;
+	};
+
+
+	/**
+	Get the constructor for the specified type.
+
+	method getConstructor
+	@static
+	@param {String} type Runtime type (e.g. flash, html5, etc)
+	@return {Function} Constructor for the Runtime type
+	*/
+	Runtime.getConstructor = function(type) {
+		return runtimeConstructors[type] || null;
+	};
+
+
+	/**
+	Get info about the runtime (uid, type, capabilities)
+
+	@method getInfo
+	@static
+	@param {String} uid Unique identifier of the runtime
+	@return {Mixed} Info object or null if runtime doesn't exist
+	*/
+	Runtime.getInfo = function(uid) {
+		var runtime = Runtime.getRuntime(uid);
+
+		if (runtime) {
+			return {
+				uid: runtime.uid,
+				type: runtime.type,
+				mode: runtime.mode,
+				can: function() {
+					return runtime.can.apply(runtime, arguments);
+				}
+			};
+		}
+		return null;
+	};
+
+
+	/**
+	Convert caps represented by a comma-separated string to the object representation.
+
+	@method parseCaps
+	@static
+	@param {String} capStr Comma-separated list of capabilities
+	@return {Object}
+	*/
+	Runtime.parseCaps = function(capStr) {
+		var capObj = {};
+
+		if (Basic.typeOf(capStr) !== 'string') {
+			return capStr || {};
+		}
+
+		Basic.each(capStr.split(','), function(key) {
+			capObj[key] = true; // we assume it to be - true
+		});
+
+		return capObj;
+	};
+
+	/**
+	Test the specified runtime for specific capabilities.
+
+	@method can
+	@static
+	@param {String} type Runtime type (e.g. flash, html5, etc)
+	@param {String|Object} caps Set of capabilities to check
+	@return {Boolean} Result of the test
+	*/
+	Runtime.can = function(type, caps) {
+		var runtime
+		, constructor = Runtime.getConstructor(type)
+		, mode
+		;
+		if (constructor) {
+			runtime = new constructor({
+				required_caps: caps
+			});
+			mode = runtime.mode;
+			runtime.destroy();
+			return !!mode;
+		}
+		return false;
+	};
+
+
+	/**
+	Figure out a runtime that supports specified capabilities.
+
+	@method thatCan
+	@static
+	@param {String|Object} caps Set of capabilities to check
+	@param {String} [runtimeOrder] Comma-separated list of runtimes to check against
+	@return {String} Usable runtime identifier or null
+	*/
+	Runtime.thatCan = function(caps, runtimeOrder) {
+		var types = (runtimeOrder || Runtime.order).split(/\s*,\s*/);
+		for (var i in types) {
+			if (Runtime.can(types[i], caps)) {
+				return types[i];
+			}
+		}
+		return null;
+	};
+
+
+	/**
+	Figure out an operational mode for the specified set of capabilities.
+
+	@method getMode
+	@static
+	@param {Object} modeCaps Set of capabilities that depend on particular runtime mode
+	@param {Object} [requiredCaps] Supplied set of capabilities to find operational mode for
+	@param {String|Boolean} [defaultMode='browser'] Default mode to use 
+	@return {String|Boolean} Compatible operational mode
+	*/
+	Runtime.getMode = function(modeCaps, requiredCaps, defaultMode) {
+		var mode = null;
+
+		if (Basic.typeOf(defaultMode) === 'undefined') { // only if not specified
+			defaultMode = 'browser';
+		}
+
+		if (requiredCaps && !Basic.isEmptyObj(modeCaps)) {
+			// loop over required caps and check if they do require the same mode
+			Basic.each(requiredCaps, function(value, cap) {
+				if (modeCaps.hasOwnProperty(cap)) {
+					var capMode = modeCaps[cap](value);
+
+					// make sure we always have an array
+					if (typeof(capMode) === 'string') {
+						capMode = [capMode];
+					}
+					
+					if (!mode) {
+						mode = capMode;
+					} else if (!(mode = Basic.arrayIntersect(mode, capMode))) {
+						// if cap requires conflicting mode - runtime cannot fulfill required caps
+						return (mode = false);
+					}
+				}
+			});
+
+			if (mode) {
+				return Basic.inArray(defaultMode, mode) !== -1 ? defaultMode : mode[0];
+			} else if (mode === false) {
+				return false;
+			}
+		}
+		return defaultMode; 
+	};
+
+
+	/**
+	Capability check that always returns true
+
+	@private
+	@static
+	@return {True}
+	*/
+	Runtime.capTrue = function() {
+		return true;
+	};
+
+	/**
+	Capability check that always returns false
+
+	@private
+	@static
+	@return {False}
+	*/
+	Runtime.capFalse = function() {
+		return false;
+	};
+
+	/**
+	Evaluate the expression to boolean value and create a function that always returns it.
+
+	@private
+	@static
+	@param {Mixed} expr Expression to evaluate
+	@return {Function} Function returning the result of evaluation
+	*/
+	Runtime.capTest = function(expr) {
+		return function() {
+			return !!expr;
+		};
+	};
+
+	return Runtime;
+});
+
+// Included from: src/javascript/runtime/RuntimeClient.js
+
+/**
+ * RuntimeClient.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+define('moxie/runtime/RuntimeClient', [
+	'moxie/core/Exceptions',
+	'moxie/core/utils/Basic',
+	'moxie/runtime/Runtime'
+], function(x, Basic, Runtime) {
+	/**
+	Set of methods and properties, required by a component to acquire ability to connect to a runtime
+
+	@class RuntimeClient
+	*/
+	return function RuntimeClient() {
+		var runtime;
+
+		Basic.extend(this, {
+			/**
+			Connects to the runtime specified by the options. Will either connect to existing runtime or create a new one.
+			Increments number of clients connected to the specified runtime.
+
+			@method connectRuntime
+			@param {Mixed} options Can be a runtme uid or a set of key-value pairs defining requirements and pre-requisites
+			*/
+			connectRuntime: function(options) {
+				var comp = this, ruid;
+
+				function initialize(items) {
+					var type, constructor;
+
+					// if we ran out of runtimes
+					if (!items.length) {
+						comp.trigger('RuntimeError', new x.RuntimeError(x.RuntimeError.NOT_INIT_ERR));
+						runtime = null;
+						return;
+					}
+
+					type = items.shift();
+					constructor = Runtime.getConstructor(type);
+					if (!constructor) {
+						initialize(items);
+						return;
+					}
+
+					// try initializing the runtime
+					runtime = new constructor(options);
+
+					runtime.bind('Init', function() {
+						// mark runtime as initialized
+						runtime.initialized = true;
+
+						// jailbreak ...
+						setTimeout(function() {
+							runtime.clients++;
+							// this will be triggered on component
+							comp.trigger('RuntimeInit', runtime);
+						}, 1);
+					});
+
+					runtime.bind('Error', function() {
+						runtime.destroy(); // runtime cannot destroy itself from inside at a right moment, thus we do it here
+						initialize(items);
+					});
+
+					/*runtime.bind('Exception', function() { });*/
+
+					// check if runtime managed to pick-up operational mode
+					if (!runtime.mode) {
+						runtime.trigger('Error');
+						return;
+					}
+
+					runtime.init();
+				}
+
+				// check if a particular runtime was requested
+				if (Basic.typeOf(options) === 'string') {
+					ruid = options;
+				} else if (Basic.typeOf(options.ruid) === 'string') {
+					ruid = options.ruid;
+				}
+
+				if (ruid) {
+					runtime = Runtime.getRuntime(ruid);
+					if (runtime) {
+						runtime.clients++;
+						return runtime;
+					} else {
+						// there should be a runtime and there's none - weird case
+						throw new x.RuntimeError(x.RuntimeError.NOT_INIT_ERR);
+					}
+				}
+
+				// initialize a fresh one, that fits runtime list and required features best
+				initialize((options.runtime_order || Runtime.order).split(/\s*,\s*/));
+			},
+
+			/**
+			Returns the runtime to which the client is currently connected.
+
+			@method getRuntime
+			@return {Runtime} Runtime or null if client is not connected
+			*/
+			getRuntime: function() {
+				if (runtime && runtime.uid) {
+					return runtime;
+				}
+				runtime = null; // make sure we do not leave zombies rambling around
+				return null;
+			},
+
+			/**
+			Disconnects from the runtime. Decrements number of clients connected to the specified runtime.
+
+			@method disconnectRuntime
+			*/
+			disconnectRuntime: function() {
+				if (runtime && --runtime.clients <= 0) {
+					runtime.destroy();
+					runtime = null;
+				}
+			}
+
+		});
+	};
+
+
+});
+
+// Included from: src/javascript/file/Blob.js
+
+/**
+ * Blob.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+define('moxie/file/Blob', [
+	'moxie/core/utils/Basic',
+	'moxie/core/utils/Encode',
+	'moxie/runtime/RuntimeClient'
+], function(Basic, Encode, RuntimeClient) {
+	
+	var blobpool = {};
+
+	/**
+	@class Blob
+	@constructor
+	@param {String} ruid Unique id of the runtime, to which this blob belongs to
+	@param {Object} blob Object "Native" blob object, as it is represented in the runtime
+	*/
+	function Blob(ruid, blob) {
+
+		function _sliceDetached(start, end, type) {
+			var blob, data = blobpool[this.uid];
+
+			if (Basic.typeOf(data) !== 'string' || !data.length) {
+				return null; // or throw exception
+			}
+
+			blob = new Blob(null, {
+				type: type,
+				size: end - start
+			});
+			blob.detach(data.substr(start, blob.size));
+
+			return blob;
+		}
+
+		RuntimeClient.call(this);
+
+		if (ruid) {	
+			this.connectRuntime(ruid);
+		}
+
+		if (!blob) {
+			blob = {};
+		} else if (Basic.typeOf(blob) === 'string') { // dataUrl or binary string
+			blob = { data: blob };
+		}
+
+		Basic.extend(this, {
+			
+			/**
+			Unique id of the component
+
+			@property uid
+			@type {String}
+			*/
+			uid: blob.uid || Basic.guid('uid_'),
+			
+			/**
+			Unique id of the connected runtime, if falsy, then runtime will have to be initialized 
+			before this Blob can be used, modified or sent
+
+			@property ruid
+			@type {String}
+			*/
+			ruid: ruid,
+	
+			/**
+			Size of blob
+
+			@property size
+			@type {Number}
+			@default 0
+			*/
+			size: blob.size || 0,
+			
+			/**
+			Mime type of blob
+
+			@property type
+			@type {String}
+			@default ''
+			*/
+			type: blob.type || '',
+			
+			/**
+			@method slice
+			@param {Number} [start=0]
+			*/
+			slice: function(start, end, type) {		
+				if (this.isDetached()) {
+					return _sliceDetached.apply(this, arguments);
+				}
+				return this.getRuntime().exec.call(this, 'Blob', 'slice', this.getSource(), start, end, type);
+			},
+
+			/**
+			Returns "native" blob object (as it is represented in connected runtime) or null if not found
+
+			@method getSource
+			@return {Blob} Returns "native" blob object or null if not found
+			*/
+			getSource: function() {
+				if (!blobpool[this.uid]) {
+					return null;	
+				}
+				return blobpool[this.uid];
+			},
+
+			/** 
+			Detaches blob from any runtime that it depends on and initialize with standalone value
+
+			@method detach
+			@protected
+			@param {DOMString} [data=''] Standalone value
+			*/
+			detach: function(data) {
+				if (this.ruid) {
+					this.getRuntime().exec.call(this, 'Blob', 'destroy');
+					this.disconnectRuntime();
+					this.ruid = null;
+				}
+
+				data = data || '';
+
+				// if dataUrl, convert to binary string
+				var matches = data.match(/^data:([^;]*);base64,/);
+				if (matches) {
+					this.type = matches[1];
+					data = Encode.atob(data.substring(data.indexOf('base64,') + 7));
+				}
+
+				this.size = data.length;
+
+				blobpool[this.uid] = data;
+			},
+
+			/**
+			Checks if blob is standalone (detached of any runtime)
+			
+			@method isDetached
+			@protected
+			@return {Boolean}
+			*/
+			isDetached: function() {
+				return !this.ruid && Basic.typeOf(blobpool[this.uid]) === 'string';
+			},
+			
+			/** 
+			Destroy Blob and free any resources it was using
+
+			@method destroy
+			*/
+			destroy: function() {
+				this.detach();
+				delete blobpool[this.uid];
+			}
+		});
+
+		
+		if (blob.data) {
+			this.detach(blob.data); // auto-detach if payload has been passed
+		} else {
+			blobpool[this.uid] = blob;	
+		}
+	}
+	
+	return Blob;
+});
+
+// Included from: src/javascript/file/File.js
+
+/**
+ * File.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+define('moxie/file/File', [
+	'moxie/core/utils/Basic',
+	'moxie/core/utils/Mime',
+	'moxie/file/Blob'
+], function(Basic, Mime, Blob) {
+	/**
+	@class File
+	@extends Blob
+	@constructor
+	@param {String} ruid Unique id of the runtime, to which this blob belongs to
+	@param {Object} file Object "Native" file object, as it is represented in the runtime
+	*/
+	function File(ruid, file) {
+		var name, type;
+
+		if (!file) { // avoid extra errors in case we overlooked something
+			file = {};
+		}
+
+		// figure out the type
+		if (file.type && file.type !== '') {
+			type = file.type;
+		} else {
+			type = Mime.getFileMime(file.name);
+		}
+
+		// sanitize file name or generate new one
+		if (file.name) {
+			name = file.name.replace(/\\/g, '/');
+			name = name.substr(name.lastIndexOf('/') + 1);
+		} else {
+			var prefix = type.split('/')[0];
+			name = Basic.guid((prefix !== '' ? prefix : 'file') + '_');
+			
+			if (Mime.extensions[type]) {
+				name += '.' + Mime.extensions[type][0]; // append proper extension if possible
+			}
+		}
+
+		Blob.apply(this, arguments);
+		
+		Basic.extend(this, {
+			/**
+			File mime type
+
+			@property type
+			@type {String}
+			@default ''
+			*/
+			type: type || '',
+
+			/**
+			File name
+
+			@property name
+			@type {String}
+			@default UID
+			*/
+			name: name || Basic.guid('file_'),
+			
+			/**
+			Date of last modification
+
+			@property lastModifiedDate
+			@type {String}
+			@default now
+			*/
+			lastModifiedDate: file.lastModifiedDate || (new Date()).toLocaleString() // Thu Aug 23 2012 19:40:00 GMT+0400 (GET)
+		});
+	}
+
+	File.prototype = Blob.prototype;
+
+	return File;
+});
+
+// Included from: src/javascript/file/FileInput.js
+
+/**
+ * FileInput.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+define('moxie/file/FileInput', [
+	'moxie/core/utils/Basic',
+	'moxie/core/utils/Mime',
+	'moxie/core/utils/Dom',
+	'moxie/core/Exceptions',
+	'moxie/core/EventTarget',
+	'moxie/core/I18n',
+	'moxie/file/File',
+	'moxie/runtime/Runtime',
+	'moxie/runtime/RuntimeClient'
+], function(Basic, Mime, Dom, x, EventTarget, I18n, File, Runtime, RuntimeClient) {
+	/**
+	Provides a convenient way to create cross-browser file-picker. Generates file selection dialog on click,
+	converts selected files to _File_ objects, to be used in conjunction with _Image_, preloaded in memory
+	with _FileReader_ or uploaded to a server through _XMLHttpRequest_.
+
+	@class FileInput
+	@constructor
+	@extends EventTarget
+	@uses RuntimeClient
+	@param {Object|String|DOMElement} options If options is string or node, argument is considered as _browse\_button_.
+		@param {String|DOMElement} options.browse_button DOM Element to turn into file picker.
+		@param {Array} [options.accept] Array of mime types to accept. By default accepts all.
+		@param {String} [options.file='file'] Name of the file field (not the filename).
+		@param {Boolean} [options.multiple=false] Enable selection of multiple files.
+		@param {Boolean} [options.directory=false] Turn file input into the folder input (cannot be both at the same time).
+		@param {String|DOMElement} [options.container] DOM Element to use as a container for file-picker. Defaults to parentNode 
+		for _browse\_button_.
+		@param {Object|String} [options.required_caps] Set of required capabilities, that chosen runtime must support.
+
+	@example
+		<div id="container">
+			<a id="file-picker" href="javascript:;">Browse...</a>
+		</div>
+
+		<script>
+			var fileInput = new mOxie.FileInput({
+				browse_button: 'file-picker', // or document.getElementById('file-picker')
+				container: 'container',
+				accept: [
+					{title: "Image files", extensions: "jpg,gif,png"} // accept only images
+				],
+				multiple: true // allow multiple file selection
+			});
+
+			fileInput.onchange = function(e) {
+				// do something to files array
+				console.info(e.target.files); // or this.files or fileInput.files
+			};
+
+			fileInput.init(); // initialize
+		</script>
+	*/
+	var dispatches = [
+		/**
+		Dispatched when runtime is connected and file-picker is ready to be used.
+
+		@event ready
+		@param {Object} event
+		*/
+		'ready',
+
+		/**
+		Dispatched right after [ready](#event_ready) event, and whenever [refresh()](#method_refresh) is invoked. 
+		Check [corresponding documentation entry](#method_refresh) for more info.
+
+		@event refresh
+		@param {Object} event
+		*/
+
+		/**
+		Dispatched when selection of files in the dialog is complete.
+
+		@event change
+		@param {Object} event
+		*/
+		'change',
+
+		'cancel', // TODO: might be useful
+
+		/**
+		Dispatched when mouse cursor enters file-picker area. Can be used to style element
+		accordingly.
+
+		@event mouseenter
+		@param {Object} event
+		*/
+		'mouseenter',
+
+		/**
+		Dispatched when mouse cursor leaves file-picker area. Can be used to style element
+		accordingly.
+
+		@event mouseleave
+		@param {Object} event
+		*/
+		'mouseleave',
+
+		/**
+		Dispatched when functional mouse button is pressed on top of file-picker area.
+
+		@event mousedown
+		@param {Object} event
+		*/
+		'mousedown',
+
+		/**
+		Dispatched when functional mouse button is released on top of file-picker area.
+
+		@event mouseup
+		@param {Object} event
+		*/
+		'mouseup'
+	];
+
+	function FileInput(options) {
+		var self = this,
+			container, browseButton, defaults;
+
+		// if flat argument passed it should be browse_button id
+		if (Basic.inArray(Basic.typeOf(options), ['string', 'node']) !== -1) {
+			options = { browse_button : options };
+		}
+
+		// this will help us to find proper default container
+		browseButton = Dom.get(options.browse_button);
+		if (!browseButton) {
+			// browse button is required
+			throw new x.DOMException(x.DOMException.NOT_FOUND_ERR);
+		}
+
+		// figure out the options
+		defaults = {
+			accept: [{
+				title: I18n.translate('All Files'),
+				extensions: '*'
+			}],
+			name: 'file',
+			multiple: false,
+			required_caps: false,
+			container: browseButton.parentNode || document.body
+		};
+		
+		options = Basic.extend({}, defaults, options);
+
+		// convert to object representation
+		if (typeof(options.required_caps) === 'string') {
+			options.required_caps = Runtime.parseCaps(options.required_caps);
+		}
+					
+		// normalize accept option (could be list of mime types or array of title/extensions pairs)
+		if (typeof(options.accept) === 'string') {
+			options.accept = Mime.mimes2extList(options.accept);
+		}
+
+		container = Dom.get(options.container);
+		// make sure we have container
+		if (!container) {
+			container = document.body;
+		}
+
+		// make container relative, if it's not
+		if (Dom.getStyle(container, 'position') === 'static') {
+			container.style.position = 'relative';
+		}
+
+		container = browseButton = null; // IE
+						
+		RuntimeClient.call(self);
+		
+		Basic.extend(self, {
+			/**
+			Unique id of the component
+
+			@property uid
+			@protected
+			@readOnly
+			@type {String}
+			@default UID
+			*/
+			uid: Basic.guid('uid_'),
+			
+			/**
+			Unique id of the connected runtime, if any.
+
+			@property ruid
+			@protected
+			@type {String}
+			*/
+			ruid: null,
+
+			/**
+			Unique id of the runtime container. Useful to get hold of it for various manipulations.
+
+			@property shimid
+			@protected
+			@type {String}
+			*/
+			shimid: null,
+			
+			/**
+			Array of selected mOxie.File objects
+
+			@property files
+			@type {Array}
+			@default null
+			*/
+			files: null,
+
+			/**
+			Initializes the file-picker, connects it to runtime and dispatches event ready when done.
+
+			@method init
+			*/
+			init: function() {
+				self.convertEventPropsToHandlers(dispatches);
+
+				self.bind('RuntimeInit', function(e, runtime) {
+					self.ruid = runtime.uid;
+					self.shimid = runtime.shimid;
+
+					self.bind("Ready", function() {
+						self.trigger("Refresh");
+					}, 999);
+
+					self.bind("Change", function() {
+						var files = runtime.exec.call(self, 'FileInput', 'getFiles');
+
+						self.files = [];
+
+						Basic.each(files, function(file) {
+							// ignore empty files (IE10 for example hangs if you try to send them via XHR)
+							if (file.size === 0) {
+								return true; 
+							}
+							self.files.push(new File(self.ruid, file));
+						});
+					}, 999);
+
+					// re-position and resize shim container
+					self.bind('Refresh', function() {
+						var pos, size, browseButton, shimContainer;
+						
+						browseButton = Dom.get(options.browse_button);
+						shimContainer = Dom.get(runtime.shimid); // do not use runtime.getShimContainer(), since it will create container if it doesn't exist
+
+						if (browseButton) {
+							pos = Dom.getPos(browseButton, Dom.get(options.container));
+							size = Dom.getSize(browseButton);
+
+							if (shimContainer) {
+								Basic.extend(shimContainer.style, {
+									top     : pos.y + 'px',
+									left    : pos.x + 'px',
+									width   : size.w + 'px',
+									height  : size.h + 'px'
+								});
+							}
+						}
+						shimContainer = browseButton = null;
+					});
+					
+					runtime.exec.call(self, 'FileInput', 'init', options);
+				});
+
+				// runtime needs: options.required_features, options.runtime_order and options.container
+				self.connectRuntime(Basic.extend({}, options, {
+					required_caps: {
+						select_file: true
+					}
+				}));
+			},
+
+			/**
+			Disables file-picker element, so that it doesn't react to mouse clicks.
+
+			@method disable
+			@param {Boolean} [state=true] Disable component if - true, enable if - false
+			*/
+			disable: function(state) {
+				var runtime = this.getRuntime();
+				if (runtime) {
+					runtime.exec.call(this, 'FileInput', 'disable', Basic.typeOf(state) === 'undefined' ? true : state);
+				}
+			},
+
+
+			/**
+			Reposition and resize dialog trigger to match the position and size of browse_button element.
+
+			@method refresh
+			*/
+			refresh: function() {
+				self.trigger("Refresh");
+			},
+
+
+			/**
+			Destroy component.
+
+			@method destroy
+			*/
+			destroy: function() {
+				var runtime = this.getRuntime();
+				if (runtime) {
+					runtime.exec.call(this, 'FileInput', 'destroy');
+					this.disconnectRuntime();
+				}
+
+				if (Basic.typeOf(this.files) === 'array') {
+					// no sense in leaving associated files behind
+					Basic.each(this.files, function(file) {
+						file.destroy();
+					});
+				} 
+				this.files = null;
+			}
+		});
+	}
+
+	FileInput.prototype = EventTarget.instance;
+
+	return FileInput;
+});
+
+// Included from: src/javascript/file/FileDrop.js
+
+/**
+ * FileDrop.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+define('moxie/file/FileDrop', [
+	'moxie/core/I18n',
+	'moxie/core/utils/Dom',
+	'moxie/core/Exceptions',
+	'moxie/core/utils/Basic',
+	'moxie/file/File',
+	'moxie/runtime/RuntimeClient',
+	'moxie/core/EventTarget',
+	'moxie/core/utils/Mime'
+], function(I18n, Dom, x, Basic, File, RuntimeClient, EventTarget, Mime) {
+	/**
+	Turn arbitrary DOM element to a drop zone accepting files. Converts selected files to _File_ objects, to be used 
+	in conjunction with _Image_, preloaded in memory with _FileReader_ or uploaded to a server through 
+	_XMLHttpRequest_.
+
+	@example
+		<div id="drop_zone">
+			Drop files here
+		</div>
+		<br />
+		<div id="filelist"></div>
+
+		<script type="text/javascript">
+			var fileDrop = new mOxie.FileDrop('drop_zone'), fileList = mOxie.get('filelist');
+
+			fileDrop.ondrop = function() {
+				mOxie.each(this.files, function(file) {
+					fileList.innerHTML += '<div>' + file.name + '</div>';
+				});
+			};
+
+			fileDrop.init();
+		</script>
+
+	@class FileDrop
+	@constructor
+	@extends EventTarget
+	@uses RuntimeClient
+	@param {Object|String} options If options has typeof string, argument is considered as options.drop_zone
+		@param {String|DOMElement} options.drop_zone DOM Element to turn into a drop zone
+		@param {Array} [options.accept] Array of mime types to accept. By default accepts all
+		@param {Object|String} [options.required_caps] Set of required capabilities, that chosen runtime must support
+	*/
+	var dispatches = [
+		/**
+		Dispatched when runtime is connected and drop zone is ready to accept files.
+
+		@event ready
+		@param {Object} event
+		*/
+		'ready', 
+
+		/**
+		Dispatched when dragging cursor enters the drop zone.
+
+		@event dragenter
+		@param {Object} event
+		*/
+		'dragenter',
+
+		/**
+		Dispatched when dragging cursor leaves the drop zone.
+
+		@event dragleave
+		@param {Object} event
+		*/
+		'dragleave', 
+
+		/**
+		Dispatched when file is dropped onto the drop zone.
+
+		@event drop
+		@param {Object} event
+		*/
+		'drop', 
+
+		/**
+		Dispatched if error occurs.
+
+		@event error
+		@param {Object} event
+		*/
+		'error'
+	];
+
+	function FileDrop(options) {
+		var self = this, defaults;
+
+		// if flat argument passed it should be drop_zone id
+		if (typeof(options) === 'string') {
+			options = { drop_zone : options };
+		}
+
+		// figure out the options
+		defaults = {
+			accept: [{
+				title: I18n.translate('All Files'),
+				extensions: '*'
+			}],
+			required_caps: {
+				drag_and_drop: true
+			}
+		};
+		
+		options = typeof(options) === 'object' ? Basic.extend({}, defaults, options) : defaults;
+
+		// this will help us to find proper default container
+		options.container = Dom.get(options.drop_zone) || document.body;
+
+		// make container relative, if it is not
+		if (Dom.getStyle(options.container, 'position') === 'static') {
+			options.container.style.position = 'relative';
+		}
+					
+		// normalize accept option (could be list of mime types or array of title/extensions pairs)
+		if (typeof(options.accept) === 'string') {
+			options.accept = Mime.mimes2extList(options.accept);
+		}
+
+		RuntimeClient.call(self);
+
+		Basic.extend(self, {
+			uid: Basic.guid('uid_'),
+
+			ruid: null,
+
+			files: null,
+
+			init: function() {
+	
+				self.convertEventPropsToHandlers(dispatches);
+		
+				self.bind('RuntimeInit', function(e, runtime) {
+					self.ruid = runtime.uid;
+
+					self.bind("Drop", function() {
+						var files = runtime.exec.call(self, 'FileDrop', 'getFiles');
+
+						self.files = [];
+
+						Basic.each(files, function(file) {
+							self.files.push(new File(self.ruid, file));
+						});
+					}, 999);
+
+					runtime.exec.call(self, 'FileDrop', 'init', options);
+
+					self.dispatchEvent('ready');
+				});
+							
+				// runtime needs: options.required_features, options.runtime_order and options.container
+				self.connectRuntime(options); // throws RuntimeError
+			},
+
+			destroy: function() {
+				var runtime = this.getRuntime();
+				if (runtime) {
+					runtime.exec.call(this, 'FileDrop', 'destroy');
+					this.disconnectRuntime();
+				}
+				this.files = null;
+			}
+		});
+	}
+
+	FileDrop.prototype = EventTarget.instance;
+
+	return FileDrop;
+});
+
+// Included from: src/javascript/runtime/RuntimeTarget.js
+
+/**
+ * RuntimeTarget.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+define('moxie/runtime/RuntimeTarget', [
+	'moxie/core/utils/Basic',
+	'moxie/runtime/RuntimeClient',
+	"moxie/core/EventTarget"
+], function(Basic, RuntimeClient, EventTarget) {
+	/**
+	Instance of this class can be used as a target for the events dispatched by shims,
+	when allowing them onto components is for either reason inappropriate
+
+	@class RuntimeTarget
+	@constructor
+	@protected
+	@extends EventTarget
+	*/
+	function RuntimeTarget() {
+		this.uid = Basic.guid('uid_');
+		
+		RuntimeClient.call(this);
+
+		this.destroy = function() {
+			this.disconnectRuntime();
+			this.unbindAll();
+		};
+	}
+
+	RuntimeTarget.prototype = EventTarget.instance;
+
+	return RuntimeTarget;
+});
+
+// Included from: src/javascript/file/FileReader.js
+
+/**
+ * FileReader.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+define('moxie/file/FileReader', [
+	'moxie/core/utils/Basic',
+	'moxie/core/utils/Encode',
+	'moxie/core/Exceptions',
+	'moxie/core/EventTarget',
+	'moxie/file/Blob',
+	'moxie/file/File',
+	'moxie/runtime/RuntimeTarget'
+], function(Basic, Encode, x, EventTarget, Blob, File, RuntimeTarget) {
+	/**
+	Utility for preloading o.Blob/o.File objects in memory. By design closely follows [W3C FileReader](http://www.w3.org/TR/FileAPI/#dfn-filereader)
+	interface. Where possible uses native FileReader, where - not falls back to shims.
+
+	@class FileReader
+	@constructor FileReader
+	@extends EventTarget
+	@uses RuntimeClient
+	*/
+	var dispatches = [
+
+		/** 
+		Dispatched when the read starts.
+
+		@event loadstart
+		@param {Object} event
+		*/
+		'loadstart', 
+
+		/** 
+		Dispatched while reading (and decoding) blob, and reporting partial Blob data (progess.loaded/progress.total).
+
+		@event progress
+		@param {Object} event
+		*/
+		'progress', 
+
+		/** 
+		Dispatched when the read has successfully completed.
+
+		@event load
+		@param {Object} event
+		*/
+		'load', 
+
+		/** 
+		Dispatched when the read has been aborted. For instance, by invoking the abort() method.
+
+		@event abort
+		@param {Object} event
+		*/
+		'abort', 
+
+		/** 
+		Dispatched when the read has failed.
+
+		@event error
+		@param {Object} event
+		*/
+		'error', 
+
+		/** 
+		Dispatched when the request has completed (either in success or failure).
+
+		@event loadend
+		@param {Object} event
+		*/
+		'loadend'
+	];
+	
+	function FileReader() {
+		var self = this, _fr;
+				
+		Basic.extend(this, {
+			/**
+			UID of the component instance.
+
+			@property uid
+			@type {String}
+			*/
+			uid: Basic.guid('uid_'),
+
+			/**
+			Contains current state of FileReader object. Can take values of FileReader.EMPTY, FileReader.LOADING
+			and FileReader.DONE.
+
+			@property readyState
+			@type {Number}
+			@default FileReader.EMPTY
+			*/
+			readyState: FileReader.EMPTY,
+			
+			/**
+			Result of the successful read operation.
+
+			@property result
+			@type {String}
+			*/
+			result: null,
+			
+			/**
+			Stores the error of failed asynchronous read operation.
+
+			@property error
+			@type {DOMError}
+			*/
+			error: null,
+			
+			/**
+			Initiates reading of File/Blob object contents to binary string.
+
+			@method readAsBinaryString
+			@param {Blob|File} blob Object to preload
+			*/
+			readAsBinaryString: function(blob) {
+				_read.call(this, 'readAsBinaryString', blob);
+			},
+			
+			/**
+			Initiates reading of File/Blob object contents to dataURL string.
+
+			@method readAsDataURL
+			@param {Blob|File} blob Object to preload
+			*/
+			readAsDataURL: function(blob) {
+				_read.call(this, 'readAsDataURL', blob);
+			},
+			
+			/**
+			Initiates reading of File/Blob object contents to string.
+
+			@method readAsText
+			@param {Blob|File} blob Object to preload
+			*/
+			readAsText: function(blob) {
+				_read.call(this, 'readAsText', blob);
+			},
+			
+			/**
+			Aborts preloading process.
+
+			@method abort
+			*/
+			abort: function() {
+				this.result = null;
+				
+				if (Basic.inArray(this.readyState, [FileReader.EMPTY, FileReader.DONE]) !== -1) {
+					return;
+				} else if (this.readyState === FileReader.LOADING) {
+					this.readyState = FileReader.DONE;
+				}
+
+				if (_fr) {
+					_fr.getRuntime().exec.call(this, 'FileReader', 'abort');
+				}
+				
+				this.trigger('abort');
+				this.trigger('loadend');
+			},
+
+			/**
+			Destroy component and release resources.
+
+			@method destroy
+			*/
+			destroy: function() {
+				this.abort();
+
+				if (_fr) {
+					_fr.getRuntime().exec.call(this, 'FileReader', 'destroy');
+					_fr.disconnectRuntime();
+				}
+
+				self = _fr = null;
+			}
+		});
+		
+		
+		function _read(op, blob) {
+			_fr = new RuntimeTarget();
+
+			function error(err) {
+				self.readyState = FileReader.DONE;
+				self.error = err;
+				self.trigger('error');
+				loadEnd();
+			}
+
+			function loadEnd() {
+				_fr.destroy();
+				_fr = null;
+				self.trigger('loadend');
+			}
+
+			function exec(runtime) {
+				_fr.bind('Error', function(e, err) {
+					error(err);
+				});
+
+				_fr.bind('Progress', function(e) {
+					self.result = runtime.exec.call(_fr, 'FileReader', 'getResult');
+					self.trigger(e);
+				});
+				
+				_fr.bind('Load', function(e) {
+					self.readyState = FileReader.DONE;
+					self.result = runtime.exec.call(_fr, 'FileReader', 'getResult');
+					self.trigger(e);
+					loadEnd();
+				});
+
+				runtime.exec.call(_fr, 'FileReader', 'read', op, blob);
+			}
+
+			this.convertEventPropsToHandlers(dispatches);
+
+			if (this.readyState === FileReader.LOADING) {
+				return error(new x.DOMException(x.DOMException.INVALID_STATE_ERR));
+			}
+
+			this.readyState = FileReader.LOADING;
+			this.trigger('loadstart');
+
+			// if source is o.Blob/o.File
+			if (blob instanceof Blob) {
+				if (blob.isDetached()) {
+					var src = blob.getSource();
+					switch (op) {
+						case 'readAsText':
+						case 'readAsBinaryString':
+							this.result = src;
+							break;
+						case 'readAsDataURL':
+							this.result = 'data:' + blob.type + ';base64,' + Encode.btoa(src);
+							break;
+					}
+					this.readyState = FileReader.DONE;
+					this.trigger('load');
+					loadEnd();
+				} else {
+					exec(_fr.connectRuntime(blob.ruid));
+				}
+			} else {
+				error(new x.DOMException(x.DOMException.NOT_FOUND_ERR));
+			}
+		}
+	}
+	
+	/**
+	Initial FileReader state
+
+	@property EMPTY
+	@type {Number}
+	@final
+	@static
+	@default 0
+	*/
+	FileReader.EMPTY = 0;
+
+	/**
+	FileReader switches to this state when it is preloading the source
+
+	@property LOADING
+	@type {Number}
+	@final
+	@static
+	@default 1
+	*/
+	FileReader.LOADING = 1;
+
+	/**
+	Preloading is complete, this is a final state
+
+	@property DONE
+	@type {Number}
+	@final
+	@static
+	@default 2
+	*/
+	FileReader.DONE = 2;
+
+	FileReader.prototype = EventTarget.instance;
+
+	return FileReader;
+});
+
+// Included from: src/javascript/core/utils/Url.js
+
+/**
+ * Url.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+define('moxie/core/utils/Url', [], function() {
+	/**
+	Parse url into separate components and fill in absent parts with parts from current url,
+	based on https://raw.github.com/kvz/phpjs/master/functions/url/parse_url.js
+
+	@method parseUrl
+	@for Utils
+	@static
+	@param {String} url Url to parse (defaults to empty string if undefined)
+	@return {Object} Hash containing extracted uri components
+	*/
+	var parseUrl = function(url, currentUrl) {
+		var key = ['source', 'scheme', 'authority', 'userInfo', 'user', 'pass', 'host', 'port', 'relative', 'path', 'directory', 'file', 'query', 'fragment']
+		, i = key.length
+		, ports = {
+			http: 80,
+			https: 443
+		}
+		, uri = {}
+		, regex = /^(?:([^:\/?#]+):)?(?:\/\/()(?:(?:()(?:([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?))?()(?:(()(?:(?:[^?#\/]*\/)*)()(?:[^?#]*))(?:\\?([^#]*))?(?:#(.*))?)/
+		, m = regex.exec(url || '')
+		;
+					
+		while (i--) {
+			if (m[i]) {
+				uri[key[i]] = m[i];
+			}
+		}
+
+		// when url is relative, we set the origin and the path ourselves
+		if (!uri.scheme) {
+			// come up with defaults
+			if (!currentUrl || typeof(currentUrl) === 'string') {
+				currentUrl = parseUrl(currentUrl || document.location.href);
+			}
+
+			uri.scheme = currentUrl.scheme;
+			uri.host = currentUrl.host;
+			uri.port = currentUrl.port;
+
+			var path = '';
+			// for urls without trailing slash we need to figure out the path
+			if (/^[^\/]/.test(uri.path)) {
+				path = currentUrl.path;
+				// if path ends with a filename, strip it
+				if (!/(\/|\/[^\.]+)$/.test(path)) {
+					path = path.replace(/\/[^\/]+$/, '/');
+				} else {
+					path += '/';
+				}
+			}
+			uri.path = path + (uri.path || ''); // site may reside at domain.com or domain.com/subdir
+		}
+
+		if (!uri.port) {
+			uri.port = ports[uri.scheme] || 80;
+		} 
+		
+		uri.port = parseInt(uri.port, 10);
+
+		if (!uri.path) {
+			uri.path = "/";
+		}
+
+		delete uri.source;
+
+		return uri;
+	};
+
+	/**
+	Resolve url - among other things will turn relative url to absolute
+
+	@method resolveUrl
+	@static
+	@param {String} url Either absolute or relative
+	@return {String} Resolved, absolute url
+	*/
+	var resolveUrl = function(url) {
+		var ports = { // we ignore default ports
+			http: 80,
+			https: 443
+		}
+		, urlp = parseUrl(url)
+		;
+
+		return urlp.scheme + '://' + urlp.host + (urlp.port !== ports[urlp.scheme] ? ':' + urlp.port : '') + urlp.path + (urlp.query ? urlp.query : '');
+	};
+
+	/**
+	Check if specified url has the same origin as the current document
+
+	@method hasSameOrigin
+	@param {String|Object} url
+	@return {Boolean}
+	*/
+	var hasSameOrigin = function(url) {
+		function origin(url) {
+			return [url.scheme, url.host, url.port].join('/');
+		}
+			
+		if (typeof url === 'string') {
+			url = parseUrl(url);
+		}	
+		
+		return origin(parseUrl()) === origin(url);
+	};
+
+	return {
+		parseUrl: parseUrl,
+		resolveUrl: resolveUrl,
+		hasSameOrigin: hasSameOrigin
+	};
+});
+
+// Included from: src/javascript/file/FileReaderSync.js
+
+/**
+ * FileReaderSync.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+define('moxie/file/FileReaderSync', [
+	'moxie/core/utils/Basic',
+	'moxie/runtime/RuntimeClient',
+	'moxie/core/utils/Encode'
+], function(Basic, RuntimeClient, Encode) {
+	/**
+	Synchronous FileReader implementation. Something like this is available in WebWorkers environment, here
+	it can be used to read only preloaded blobs/files and only below certain size (not yet sure what that'd be,
+	but probably < 1mb). Not meant to be used directly by user.
+
+	@class FileReaderSync
+	@private
+	@constructor
+	*/
+	return function() {
+		RuntimeClient.call(this);
+
+		Basic.extend(this, {
+			uid: Basic.guid('uid_'),
+
+			readAsBinaryString: function(blob) {
+				return _read.call(this, 'readAsBinaryString', blob);
+			},
+			
+			readAsDataURL: function(blob) {
+				return _read.call(this, 'readAsDataURL', blob);
+			},
+			
+			/*readAsArrayBuffer: function(blob) {
+				return _read.call(this, 'readAsArrayBuffer', blob);
+			},*/
+			
+			readAsText: function(blob) {
+				return _read.call(this, 'readAsText', blob);
+			}
+		});
+
+		function _read(op, blob) {
+			if (blob.isDetached()) {
+				var src = blob.getSource();
+				switch (op) {
+					case 'readAsBinaryString':
+						return src;
+					case 'readAsDataURL':
+						return 'data:' + blob.type + ';base64,' + Encode.btoa(src);
+					case 'readAsText':
+						var txt = '';
+						for (var i = 0, length = src.length; i < length; i++) {
+							txt += String.fromCharCode(src[i]);
+						}
+						return txt;
+				}
+			} else {
+				var result = this.connectRuntime(blob.ruid).exec.call(this, 'FileReaderSync', 'read', op, blob);
+				this.disconnectRuntime();
+				return result;
+			}
+		}
+	};
+});
+
+// Included from: src/javascript/xhr/FormData.js
+
+/**
+ * FormData.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+define("moxie/xhr/FormData", [
+	"moxie/core/Exceptions",
+	"moxie/core/utils/Basic",
+	"moxie/file/Blob"
+], function(x, Basic, Blob) {
+	/**
+	FormData
+
+	@class FormData
+	@constructor
+	*/
+	function FormData() {
+		var _blob, _fields = [];
+
+		Basic.extend(this, {
+			/**
+			Append another key-value pair to the FormData object
+
+			@method append
+			@param {String} name Name for the new field
+			@param {String|Blob|Array|Object} value Value for the field
+			*/
+			append: function(name, value) {
+				var self = this, valueType = Basic.typeOf(value);
+
+				// according to specs value might be either Blob or String
+				if (value instanceof Blob) {
+					_blob = {
+						name: name,
+						value: value // unfortunately we can only send single Blob in one FormData
+					};
+				} else if ('array' === valueType) {
+					name += '[]';
+
+					Basic.each(value, function(value) {
+						self.append(name, value);
+					});
+				} else if ('object' === valueType) {
+					Basic.each(value, function(value, key) {
+						self.append(name + '[' + key + ']', value);
+					});
+				} else if ('null' === valueType || 'undefined' === valueType || 'number' === valueType && isNaN(value)) {
+					self.append(name, "false");
+				} else {
+					_fields.push({
+						name: name,
+						value: value.toString()
+					});
+				}
+			},
+
+			/**
+			Checks if FormData contains Blob.
+
+			@method hasBlob
+			@return {Boolean}
+			*/
+			hasBlob: function() {
+				return !!this.getBlob();
+			},
+
+			/**
+			Retrieves blob.
+
+			@method getBlob
+			@return {Object} Either Blob if found or null
+			*/
+			getBlob: function() {
+				return _blob && _blob.value || null;
+			},
+
+			/**
+			Retrieves blob field name.
+
+			@method getBlobName
+			@return {String} Either Blob field name or null
+			*/
+			getBlobName: function() {
+				return _blob && _blob.name || null;
+			},
+
+			/**
+			Loop over the fields in FormData and invoke the callback for each of them.
+
+			@method each
+			@param {Function} cb Callback to call for each field
+			*/
+			each: function(cb) {
+				Basic.each(_fields, function(field) {
+					cb(field.value, field.name);
+				});
+
+				if (_blob) {
+					cb(_blob.value, _blob.name);
+				}
+			},
+
+			destroy: function() {
+				_blob = null;
+				_fields = [];
+			}
+		});
+	}
+
+	return FormData;
+});
+
+// Included from: src/javascript/xhr/XMLHttpRequest.js
+
+/**
+ * XMLHttpRequest.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+define("moxie/xhr/XMLHttpRequest", [
+	"moxie/core/utils/Basic",
+	"moxie/core/Exceptions",
+	"moxie/core/EventTarget",
+	"moxie/core/utils/Encode",
+	"moxie/core/utils/Url",
+	"moxie/runtime/Runtime",
+	"moxie/runtime/RuntimeTarget",
+	"moxie/file/Blob",
+	"moxie/file/FileReaderSync",
+	"moxie/xhr/FormData",
+	"moxie/core/utils/Env",
+	"moxie/core/utils/Mime"
+], function(Basic, x, EventTarget, Encode, Url, Runtime, RuntimeTarget, Blob, FileReaderSync, FormData, Env, Mime) {
+
+	var httpCode = {
+		100: 'Continue',
+		101: 'Switching Protocols',
+		102: 'Processing',
+
+		200: 'OK',
+		201: 'Created',
+		202: 'Accepted',
+		203: 'Non-Authoritative Information',
+		204: 'No Content',
+		205: 'Reset Content',
+		206: 'Partial Content',
+		207: 'Multi-Status',
+		226: 'IM Used',
+
+		300: 'Multiple Choices',
+		301: 'Moved Permanently',
+		302: 'Found',
+		303: 'See Other',
+		304: 'Not Modified',
+		305: 'Use Proxy',
+		306: 'Reserved',
+		307: 'Temporary Redirect',
+
+		400: 'Bad Request',
+		401: 'Unauthorized',
+		402: 'Payment Required',
+		403: 'Forbidden',
+		404: 'Not Found',
+		405: 'Method Not Allowed',
+		406: 'Not Acceptable',
+		407: 'Proxy Authentication Required',
+		408: 'Request Timeout',
+		409: 'Conflict',
+		410: 'Gone',
+		411: 'Length Required',
+		412: 'Precondition Failed',
+		413: 'Request Entity Too Large',
+		414: 'Request-URI Too Long',
+		415: 'Unsupported Media Type',
+		416: 'Requested Range Not Satisfiable',
+		417: 'Expectation Failed',
+		422: 'Unprocessable Entity',
+		423: 'Locked',
+		424: 'Failed Dependency',
+		426: 'Upgrade Required',
+
+		500: 'Internal Server Error',
+		501: 'Not Implemented',
+		502: 'Bad Gateway',
+		503: 'Service Unavailable',
+		504: 'Gateway Timeout',
+		505: 'HTTP Version Not Supported',
+		506: 'Variant Also Negotiates',
+		507: 'Insufficient Storage',
+		510: 'Not Extended'
+	};
+
+	function XMLHttpRequestUpload() {
+		this.uid = Basic.guid('uid_');
+	}
+	
+	XMLHttpRequestUpload.prototype = EventTarget.instance;
+
+	/**
+	Implementation of XMLHttpRequest
+
+	@class XMLHttpRequest
+	@constructor
+	@uses RuntimeClient
+	@extends EventTarget
+	*/
+	var dispatches = ['loadstart', 'progress', 'abort', 'error', 'load', 'timeout', 'loadend']; // & readystatechange (for historical reasons)
+	
+	var NATIVE = 1, RUNTIME = 2;
+					
+	function XMLHttpRequest() {
+		var self = this,
+			// this (together with _p() @see below) is here to gracefully upgrade to setter/getter syntax where possible
+			props = {
+				/**
+				The amount of milliseconds a request can take before being terminated. Initially zero. Zero means there is no timeout.
+
+				@property timeout
+				@type Number
+				@default 0
+				*/
+				timeout: 0,
+
+				/**
+				Current state, can take following values:
+				UNSENT (numeric value 0)
+				The object has been constructed.
+
+				OPENED (numeric value 1)
+				The open() method has been successfully invoked. During this state request headers can be set using setRequestHeader() and the request can be made using the send() method.
+
+				HEADERS_RECEIVED (numeric value 2)
+				All redirects (if any) have been followed and all HTTP headers of the final response have been received. Several response members of the object are now available.
+
+				LOADING (numeric value 3)
+				The response entity body is being received.
+
+				DONE (numeric value 4)
+
+				@property readyState
+				@type Number
+				@default 0 (UNSENT)
+				*/
+				readyState: XMLHttpRequest.UNSENT,
+
+				/**
+				True when user credentials are to be included in a cross-origin request. False when they are to be excluded
+				in a cross-origin request and when cookies are to be ignored in its response. Initially false.
+
+				@property withCredentials
+				@type Boolean
+				@default false
+				*/
+				withCredentials: false,
+
+				/**
+				Returns the HTTP status code.
+
+				@property status
+				@type Number
+				@default 0
+				*/
+				status: 0,
+
+				/**
+				Returns the HTTP status text.
+
+				@property statusText
+				@type String
+				*/
+				statusText: "",
+
+				/**
+				Returns the response type. Can be set to change the response type. Values are:
+				the empty string (default), "arraybuffer", "blob", "document", "json", and "text".
+				
+				@property responseType
+				@type String
+				*/
+				responseType: "",
+
+				/**
+				Returns the document response entity body.
+				
+				Throws an "InvalidStateError" exception if responseType is not the empty string or "document".
+
+				@property responseXML
+				@type Document
+				*/
+				responseXML: null,
+
+				/**
+				Returns the text response entity body.
+				
+				Throws an "InvalidStateError" exception if responseType is not the empty string or "text".
+
+				@property responseText
+				@type String
+				*/
+				responseText: null,
+
+				/**
+				Returns the response entity body (http://www.w3.org/TR/XMLHttpRequest/#response-entity-body).
+				Can become: ArrayBuffer, Blob, Document, JSON, Text
+				
+				@property response
+				@type Mixed
+				*/
+				response: null
+			},
+
+			_async = true,
+			_url,
+			_method,
+			_headers = {},
+			_user,
+			_password,
+			_encoding = null,
+			_mimeType = null,
+
+			// flags
+			_sync_flag = false,
+			_send_flag = false,
+			_upload_events_flag = false,
+			_upload_complete_flag = false,
+			_error_flag = false,
+			_same_origin_flag = false,
+
+			// times
+			_start_time,
+			_timeoutset_time,
+
+			_finalMime = null,
+			_finalCharset = null,
+
+			_options = {},
+			_xhr,
+			_responseHeaders = '',
+			_responseHeadersBag
+			;
+
+		
+		Basic.extend(this, props, {
+			/**
+			Unique id of the component
+
+			@property uid
+			@type String
+			*/
+			uid: Basic.guid('uid_'),
+			
+			/**
+			Target for Upload events
+
+			@property upload
+			@type XMLHttpRequestUpload
+			*/
+			upload: new XMLHttpRequestUpload(),
+			
+
+			/**
+			Sets the request method, request URL, synchronous flag, request username, and request password.
+
+			Throws a "SyntaxError" exception if one of the following is true:
+
+			method is not a valid HTTP method.
+			url cannot be resolved.
+			url contains the "user:password" format in the userinfo production.
+			Throws a "SecurityError" exception if method is a case-insensitive match for CONNECT, TRACE or TRACK.
+
+			Throws an "InvalidAccessError" exception if one of the following is true:
+
+			Either user or password is passed as argument and the origin of url does not match the XMLHttpRequest origin.
+			There is an associated XMLHttpRequest document and either the timeout attribute is not zero,
+			the withCredentials attribute is true, or the responseType attribute is not the empty string.
+
+
+			@method open
+			@param {String} method HTTP method to use on request
+			@param {String} url URL to request
+			@param {Boolean} [async=true] If false request will be done in synchronous manner. Asynchronous by default.
+			@param {String} [user] Username to use in HTTP authentication process on server-side
+			@param {String} [password] Password to use in HTTP authentication process on server-side
+			*/
+			open: function(method, url, async, user, password) {
+				var urlp;
+				
+				// first two arguments are required
+				if (!method || !url) {
+					throw new x.DOMException(x.DOMException.SYNTAX_ERR);
+				}
+				
+				// 2 - check if any code point in method is higher than U+00FF or after deflating method it does not match the method
+				if (/[\u0100-\uffff]/.test(method) || Encode.utf8_encode(method) !== method) {
+					throw new x.DOMException(x.DOMException.SYNTAX_ERR);
+				}
+
+				// 3
+				if (!!~Basic.inArray(method.toUpperCase(), ['CONNECT', 'DELETE', 'GET', 'HEAD', 'OPTIONS', 'POST', 'PUT', 'TRACE', 'TRACK'])) {
+					_method = method.toUpperCase();
+				}
+				
+				
+				// 4 - allowing these methods poses a security risk
+				if (!!~Basic.inArray(_method, ['CONNECT', 'TRACE', 'TRACK'])) {
+					throw new x.DOMException(x.DOMException.SECURITY_ERR);
+				}
+
+				// 5
+				url = Encode.utf8_encode(url);
+				
+				// 6 - Resolve url relative to the XMLHttpRequest base URL. If the algorithm returns an error, throw a "SyntaxError".
+				urlp = Url.parseUrl(url);
+
+				_same_origin_flag = Url.hasSameOrigin(urlp);
+																
+				// 7 - manually build up absolute url
+				_url = Url.resolveUrl(url);
+		
+				// 9-10, 12-13
+				if ((user || password) && !_same_origin_flag) {
+					throw new x.DOMException(x.DOMException.INVALID_ACCESS_ERR);
+				}
+
+				_user = user || urlp.user;
+				_password = password || urlp.pass;
+				
+				// 11
+				_async = async || true;
+				
+				if (_async === false && (_p('timeout') || _p('withCredentials') || _p('responseType') !== "")) {
+					throw new x.DOMException(x.DOMException.INVALID_ACCESS_ERR);
+				}
+				
+				// 14 - terminate abort()
+				
+				// 15 - terminate send()
+
+				// 18
+				_sync_flag = !_async;
+				_send_flag = false;
+				_headers = {};
+				_reset.call(this);
+
+				// 19
+				_p('readyState', XMLHttpRequest.OPENED);
+				
+				// 20
+				this.convertEventPropsToHandlers(['readystatechange']); // unify event handlers
+				this.dispatchEvent('readystatechange');
+			},
+			
+			/**
+			Appends an header to the list of author request headers, or if header is already
+			in the list of author request headers, combines its value with value.
+
+			Throws an "InvalidStateError" exception if the state is not OPENED or if the send() flag is set.
+			Throws a "SyntaxError" exception if header is not a valid HTTP header field name or if value
+			is not a valid HTTP header field value.
+			
+			@method setRequestHeader
+			@param {String} header
+			@param {String|Number} value
+			*/
+			setRequestHeader: function(header, value) {
+				var uaHeaders = [ // these headers are controlled by the user agent
+						"accept-charset",
+						"accept-encoding",
+						"access-control-request-headers",
+						"access-control-request-method",
+						"connection",
+						"content-length",
+						"cookie",
+						"cookie2",
+						"content-transfer-encoding",
+						"date",
+						"expect",
+						"host",
+						"keep-alive",
+						"origin",
+						"referer",
+						"te",
+						"trailer",
+						"transfer-encoding",
+						"upgrade",
+						"user-agent",
+						"via"
+					];
+				
+				// 1-2
+				if (_p('readyState') !== XMLHttpRequest.OPENED || _send_flag) {
+					throw new x.DOMException(x.DOMException.INVALID_STATE_ERR);
+				}
+
+				// 3
+				if (/[\u0100-\uffff]/.test(header) || Encode.utf8_encode(header) !== header) {
+					throw new x.DOMException(x.DOMException.SYNTAX_ERR);
+				}
+
+				// 4
+				/* this step is seemingly bypassed in browsers, probably to allow various unicode characters in header values
+				if (/[\u0100-\uffff]/.test(value) || Encode.utf8_encode(value) !== value) {
+					throw new x.DOMException(x.DOMException.SYNTAX_ERR);
+				}*/
+
+				header = Basic.trim(header).toLowerCase();
+				
+				// setting of proxy-* and sec-* headers is prohibited by spec
+				if (!!~Basic.inArray(header, uaHeaders) || /^(proxy\-|sec\-)/.test(header)) {
+					return false;
+				}
+
+				// camelize
+				// browsers lowercase header names (at least for custom ones)
+				// header = header.replace(/\b\w/g, function($1) { return $1.toUpperCase(); });
+				
+				if (!_headers[header]) {
+					_headers[header] = value;
+				} else {
+					// http://tools.ietf.org/html/rfc2616#section-4.2 (last paragraph)
+					_headers[header] += ', ' + value;
+				}
+				return true;
+			},
+
+			/**
+			Returns all headers from the response, with the exception of those whose field name is Set-Cookie or Set-Cookie2.
+
+			@method getAllResponseHeaders
+			@return {String} reponse headers or empty string
+			*/
+			getAllResponseHeaders: function() {
+				return _responseHeaders || '';
+			},
+
+			/**
+			Returns the header field value from the response of which the field name matches header, 
+			unless the field name is Set-Cookie or Set-Cookie2.
+
+			@method getResponseHeader
+			@param {String} header
+			@return {String} value(s) for the specified header or null
+			*/
+			getResponseHeader: function(header) {
+				header = header.toLowerCase();
+
+				if (_error_flag || !!~Basic.inArray(header, ['set-cookie', 'set-cookie2'])) {
+					return null;
+				}
+
+				if (_responseHeaders && _responseHeaders !== '') {
+					// if we didn't parse response headers until now, do it and keep for later
+					if (!_responseHeadersBag) {
+						_responseHeadersBag = {};
+						Basic.each(_responseHeaders.split(/\r\n/), function(line) {
+							var pair = line.split(/:\s+/);
+							if (pair.length === 2) { // last line might be empty, omit
+								pair[0] = Basic.trim(pair[0]); // just in case
+								_responseHeadersBag[pair[0].toLowerCase()] = { // simply to retain header name in original form
+									header: pair[0],
+									value: Basic.trim(pair[1])
+								};
+							}
+						});
+					}
+					if (_responseHeadersBag.hasOwnProperty(header)) {
+						return _responseHeadersBag[header].header + ': ' + _responseHeadersBag[header].value;
+					}
+				}
+				return null;
+			},
+			
+			/**
+			Sets the Content-Type header for the response to mime.
+			Throws an "InvalidStateError" exception if the state is LOADING or DONE.
+			Throws a "SyntaxError" exception if mime is not a valid media type.
+
+			@method overrideMimeType
+			@param String mime Mime type to set
+			*/
+			overrideMimeType: function(mime) {
+				var matches, charset;
+			
+				// 1
+				if (!!~Basic.inArray(_p('readyState'), [XMLHttpRequest.LOADING, XMLHttpRequest.DONE])) {
+					throw new x.DOMException(x.DOMException.INVALID_STATE_ERR);
+				}
+
+				// 2
+				mime = Basic.trim(mime.toLowerCase());
+
+				if (/;/.test(mime) && (matches = mime.match(/^([^;]+)(?:;\scharset\=)?(.*)$/))) {
+					mime = matches[1];
+					if (matches[2]) {
+						charset = matches[2];
+					}
+				}
+
+				if (!Mime.mimes[mime]) {
+					throw new x.DOMException(x.DOMException.SYNTAX_ERR);
+				}
+
+				// 3-4
+				_finalMime = mime;
+				_finalCharset = charset;
+			},
+			
+			/**
+			Initiates the request. The optional argument provides the request entity body.
+			The argument is ignored if request method is GET or HEAD.
+
+			Throws an "InvalidStateError" exception if the state is not OPENED or if the send() flag is set.
+
+			@method send
+			@param {Blob|Document|String|FormData} [data] Request entity body
+			@param {Object} [options] Set of requirements and pre-requisities for runtime initialization
+			*/
+			send: function(data, options) {					
+				if (Basic.typeOf(options) === 'string') {
+					_options = { ruid: options };
+				} else if (!options) {
+					_options = {};
+				} else {
+					_options = options;
+				}
+													
+				this.convertEventPropsToHandlers(dispatches);
+				this.upload.convertEventPropsToHandlers(dispatches);
+															
+				// 1-2
+				if (this.readyState !== XMLHttpRequest.OPENED || _send_flag) {
+					throw new x.DOMException(x.DOMException.INVALID_STATE_ERR);
+				}
+				
+				// 3					
+				// sending Blob
+				if (data instanceof Blob) {
+					_options.ruid = data.ruid;
+					_mimeType = data.type || 'application/octet-stream';
+				}
+				
+				// FormData
+				else if (data instanceof FormData) {
+					if (data.hasBlob()) {
+						var blob = data.getBlob();
+						_options.ruid = blob.ruid;
+						_mimeType = blob.type || 'application/octet-stream';
+					}
+				}
+				
+				// DOMString
+				else if (typeof data === 'string') {
+					_encoding = 'UTF-8';
+					_mimeType = 'text/plain;charset=UTF-8';
+					
+					// data should be converted to Unicode and encoded as UTF-8
+					data = Encode.utf8_encode(data);
+				}
+
+				// if withCredentials not set, but requested, set it automatically
+				if (!this.withCredentials) {
+					this.withCredentials = (_options.required_caps && _options.required_caps.send_browser_cookies) && !_same_origin_flag;
+				}
+
+				// 4 - storage mutex
+				// 5
+				_upload_events_flag = (!_sync_flag && this.upload.hasEventListener()); // DSAP
+				// 6
+				_error_flag = false;
+				// 7
+				_upload_complete_flag = !data;
+				// 8 - Asynchronous steps
+				if (!_sync_flag) {
+					// 8.1
+					_send_flag = true;
+					// 8.2
+					// this.dispatchEvent('loadstart'); // will be dispatched either by native or runtime xhr
+					// 8.3
+					//if (!_upload_complete_flag) {
+						// this.upload.dispatchEvent('loadstart');	// will be dispatched either by native or runtime xhr
+					//}
+				}
+				// 8.5 - Return the send() method call, but continue running the steps in this algorithm.
+				_doXHR.call(this, data);
+			},
+			
+			/**
+			Cancels any network activity.
+			
+			@method abort
+			*/
+			abort: function() {
+				_error_flag = true;
+				_sync_flag = false;
+
+				if (!~Basic.inArray(_p('readyState'), [XMLHttpRequest.UNSENT, XMLHttpRequest.OPENED, XMLHttpRequest.DONE])) {
+					_p('readyState', XMLHttpRequest.DONE);
+					_send_flag = false;
+
+					if (_xhr) {
+						_xhr.getRuntime().exec.call(_xhr, 'XMLHttpRequest', 'abort', _upload_complete_flag);
+					} else {
+						throw new x.DOMException(x.DOMException.INVALID_STATE_ERR);
+					}
+
+					_upload_complete_flag = true;
+				} else {
+					_p('readyState', XMLHttpRequest.UNSENT);
+				}
+			},
+
+			destroy: function() {
+				if (_xhr) {
+					if (Basic.typeOf(_xhr.destroy) === 'function') {
+						_xhr.destroy();
+					}
+					_xhr = null;
+				}
+
+				this.unbindAll();
+
+				if (this.upload) {
+					this.upload.unbindAll();
+					this.upload = null;
+				}
+			}
+		});
+
+		/* this is nice, but maybe too lengthy
+
+		// if supported by JS version, set getters/setters for specific properties
+		o.defineProperty(this, 'readyState', {
+			configurable: false,
+
+			get: function() {
+				return _p('readyState');
+			}
+		});
+
+		o.defineProperty(this, 'timeout', {
+			configurable: false,
+
+			get: function() {
+				return _p('timeout');
+			},
+
+			set: function(value) {
+
+				if (_sync_flag) {
+					throw new x.DOMException(x.DOMException.INVALID_ACCESS_ERR);
+				}
+
+				// timeout still should be measured relative to the start time of request
+				_timeoutset_time = (new Date).getTime();
+
+				_p('timeout', value);
+			}
+		});
+
+		// the withCredentials attribute has no effect when fetching same-origin resources
+		o.defineProperty(this, 'withCredentials', {
+			configurable: false,
+
+			get: function() {
+				return _p('withCredentials');
+			},
+
+			set: function(value) {
+				// 1-2
+				if (!~o.inArray(_p('readyState'), [XMLHttpRequest.UNSENT, XMLHttpRequest.OPENED]) || _send_flag) {
+					throw new x.DOMException(x.DOMException.INVALID_STATE_ERR);
+				}
+
+				// 3-4
+				if (_anonymous_flag || _sync_flag) {
+					throw new x.DOMException(x.DOMException.INVALID_ACCESS_ERR);
+				}
+
+				// 5
+				_p('withCredentials', value);
+			}
+		});
+
+		o.defineProperty(this, 'status', {
+			configurable: false,
+
+			get: function() {
+				return _p('status');
+			}
+		});
+
+		o.defineProperty(this, 'statusText', {
+			configurable: false,
+
+			get: function() {
+				return _p('statusText');
+			}
+		});
+
+		o.defineProperty(this, 'responseType', {
+			configurable: false,
+
+			get: function() {
+				return _p('responseType');
+			},
+
+			set: function(value) {
+				// 1
+				if (!!~o.inArray(_p('readyState'), [XMLHttpRequest.LOADING, XMLHttpRequest.DONE])) {
+					throw new x.DOMException(x.DOMException.INVALID_STATE_ERR);
+				}
+
+				// 2
+				if (_sync_flag) {
+					throw new x.DOMException(x.DOMException.INVALID_ACCESS_ERR);
+				}
+
+				// 3
+				_p('responseType', value.toLowerCase());
+			}
+		});
+
+		o.defineProperty(this, 'responseText', {
+			configurable: false,
+
+			get: function() {
+				// 1
+				if (!~o.inArray(_p('responseType'), ['', 'text'])) {
+					throw new x.DOMException(x.DOMException.INVALID_STATE_ERR);
+				}
+
+				// 2-3
+				if (_p('readyState') !== XMLHttpRequest.DONE && _p('readyState') !== XMLHttpRequest.LOADING || _error_flag) {
+					throw new x.DOMException(x.DOMException.INVALID_STATE_ERR);
+				}
+
+				return _p('responseText');
+			}
+		});
+
+		o.defineProperty(this, 'responseXML', {
+			configurable: false,
+
+			get: function() {
+				// 1
+				if (!~o.inArray(_p('responseType'), ['', 'document'])) {
+					throw new x.DOMException(x.DOMException.INVALID_STATE_ERR);
+				}
+
+				// 2-3
+				if (_p('readyState') !== XMLHttpRequest.DONE || _error_flag) {
+					throw new x.DOMException(x.DOMException.INVALID_STATE_ERR);
+				}
+
+				return _p('responseXML');
+			}
+		});
+
+		o.defineProperty(this, 'response', {
+			configurable: false,
+
+			get: function() {
+				if (!!~o.inArray(_p('responseType'), ['', 'text'])) {
+					if (_p('readyState') !== XMLHttpRequest.DONE && _p('readyState') !== XMLHttpRequest.LOADING || _error_flag) {
+						return '';
+					}
+				}
+
+				if (_p('readyState') !== XMLHttpRequest.DONE || _error_flag) {
+					return null;
+				}
+
+				return _p('response');
+			}
+		});
+
+		*/
+
+		function _p(prop, value) {
+			if (!props.hasOwnProperty(prop)) {
+				return;
+			}
+			if (arguments.length === 1) { // get
+				return Env.can('define_property') ? props[prop] : self[prop];
+			} else { // set
+				if (Env.can('define_property')) {
+					props[prop] = value;
+				} else {
+					self[prop] = value;
+				}
+			}
+		}
+		
+		/*
+		function _toASCII(str, AllowUnassigned, UseSTD3ASCIIRules) {
+			// TODO: http://tools.ietf.org/html/rfc3490#section-4.1
+			return str.toLowerCase();
+		}
+		*/
+		
+		
+		function _doXHR(data) {
+			var self = this;
+			
+			_start_time = new Date().getTime();
+
+			_xhr = new RuntimeTarget();
+
+			function loadEnd() {
+				if (_xhr) { // it could have been destroyed by now
+					_xhr.destroy();
+					_xhr = null;
+				}
+				self.dispatchEvent('loadend');
+				self = null;
+			}
+
+			function exec(runtime) {
+				_xhr.bind('LoadStart', function(e) {
+					_p('readyState', XMLHttpRequest.LOADING);
+					self.dispatchEvent('readystatechange');
+
+					self.dispatchEvent(e);
+					
+					if (_upload_events_flag) {
+						self.upload.dispatchEvent(e);
+					}
+				});
+				
+				_xhr.bind('Progress', function(e) {
+					if (_p('readyState') !== XMLHttpRequest.LOADING) {
+						_p('readyState', XMLHttpRequest.LOADING); // LoadStart unreliable (in Flash for example)
+						self.dispatchEvent('readystatechange');
+					}
+					self.dispatchEvent(e);
+				});
+				
+				_xhr.bind('UploadProgress', function(e) {
+					if (_upload_events_flag) {
+						self.upload.dispatchEvent({
+							type: 'progress',
+							lengthComputable: false,
+							total: e.total,
+							loaded: e.loaded
+						});
+					}
+				});
+				
+				_xhr.bind('Load', function(e) {
+					_p('readyState', XMLHttpRequest.DONE);
+					_p('status', Number(runtime.exec.call(_xhr, 'XMLHttpRequest', 'getStatus') || 0));
+					_p('statusText', httpCode[_p('status')] || "");
+					
+					_p('response', runtime.exec.call(_xhr, 'XMLHttpRequest', 'getResponse', _p('responseType')));
+
+					if (!!~Basic.inArray(_p('responseType'), ['text', ''])) {
+						_p('responseText', _p('response'));
+					} else if (_p('responseType') === 'document') {
+						_p('responseXML', _p('response'));
+					}
+
+					_responseHeaders = runtime.exec.call(_xhr, 'XMLHttpRequest', 'getAllResponseHeaders');
+
+					self.dispatchEvent('readystatechange');
+					
+					if (_p('status') > 0) { // status 0 usually means that server is unreachable
+						if (_upload_events_flag) {
+							self.upload.dispatchEvent(e);
+						}
+						self.dispatchEvent(e);
+					} else {
+						_error_flag = true;
+						self.dispatchEvent('error');
+					}
+					loadEnd();
+				});
+
+				_xhr.bind('Abort', function(e) {
+					self.dispatchEvent(e);
+					loadEnd();
+				});
+				
+				_xhr.bind('Error', function(e) {
+					_error_flag = true;
+					_p('readyState', XMLHttpRequest.DONE);
+					self.dispatchEvent('readystatechange');
+					_upload_complete_flag = true;
+					self.dispatchEvent(e);
+					loadEnd();
+				});
+
+				runtime.exec.call(_xhr, 'XMLHttpRequest', 'send', {
+					url: _url,
+					method: _method,
+					async: _async,
+					user: _user,
+					password: _password,
+					headers: _headers,
+					mimeType: _mimeType,
+					encoding: _encoding,
+					responseType: self.responseType,
+					withCredentials: self.withCredentials,
+					options: _options
+				}, data);
+			}
+
+			// clarify our requirements
+			if (typeof(_options.required_caps) === 'string') {
+				_options.required_caps = Runtime.parseCaps(_options.required_caps);
+			}
+
+			_options.required_caps = Basic.extend({}, _options.required_caps, {
+				return_response_type: self.responseType
+			});
+
+			if (data instanceof FormData) {
+				_options.required_caps.send_multipart = true;
+			}
+
+			if (!_same_origin_flag) {
+				_options.required_caps.do_cors = true;
+			}
+			
+
+			if (_options.ruid) { // we do not need to wait if we can connect directly
+				exec(_xhr.connectRuntime(_options));
+			} else {
+				_xhr.bind('RuntimeInit', function(e, runtime) {
+					exec(runtime);
+				});
+				_xhr.bind('RuntimeError', function(e, err) {
+					self.dispatchEvent('RuntimeError', err);
+				});
+				_xhr.connectRuntime(_options);
+			}
+		}
+	
+		
+		function _reset() {
+			_p('responseText', "");
+			_p('responseXML', null);
+			_p('response', null);
+			_p('status', 0);
+			_p('statusText', "");
+			_start_time = _timeoutset_time = null;
+		}
+	}
+
+	XMLHttpRequest.UNSENT = 0;
+	XMLHttpRequest.OPENED = 1;
+	XMLHttpRequest.HEADERS_RECEIVED = 2;
+	XMLHttpRequest.LOADING = 3;
+	XMLHttpRequest.DONE = 4;
+	
+	XMLHttpRequest.prototype = EventTarget.instance;
+
+	return XMLHttpRequest;
+});
+
+// Included from: src/javascript/runtime/Transporter.js
+
+/**
+ * Transporter.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+define("moxie/runtime/Transporter", [
+	"moxie/core/utils/Basic",
+	"moxie/core/utils/Encode",
+	"moxie/runtime/RuntimeClient",
+	"moxie/core/EventTarget"
+], function(Basic, Encode, RuntimeClient, EventTarget) {
+	function Transporter() {
+		var mod, _runtime, _data, _size, _pos, _chunk_size;
+
+		RuntimeClient.call(this);
+
+		Basic.extend(this, {
+			uid: Basic.guid('uid_'),
+
+			state: Transporter.IDLE,
+
+			result: null,
+
+			transport: function(data, type, options) {
+				var self = this;
+
+				options = Basic.extend({
+					chunk_size: 204798
+				}, options);
+
+				// should divide by three, base64 requires this
+				if ((mod = options.chunk_size % 3)) {
+					options.chunk_size += 3 - mod;
+				}
+
+				_chunk_size = options.chunk_size;
+
+				_reset.call(this);
+				_data = data;
+				_size = data.length;
+
+				if (Basic.typeOf(options) === 'string' || options.ruid) {
+					_run.call(self, type, this.connectRuntime(options));
+				} else {
+					// we require this to run only once
+					var cb = function(e, runtime) {
+						self.unbind("RuntimeInit", cb);
+						_run.call(self, type, runtime);
+					};
+					this.bind("RuntimeInit", cb);
+					this.connectRuntime(options);
+				}
+			},
+
+			abort: function() {
+				var self = this;
+
+				self.state = Transporter.IDLE;
+				if (_runtime) {
+					_runtime.exec.call(self, 'Transporter', 'clear');
+					self.trigger("TransportingAborted");
+				}
+
+				_reset.call(self);
+			},
+
+
+			destroy: function() {
+				this.unbindAll();
+				_runtime = null;
+				this.disconnectRuntime();
+				_reset.call(this);
+			}
+		});
+
+		function _reset() {
+			_size = _pos = 0;
+			_data = this.result = null;
+		}
+
+		function _run(type, runtime) {
+			var self = this;
+
+			_runtime = runtime;
+
+			//self.unbind("RuntimeInit");
+
+			self.bind("TransportingProgress", function(e) {
+				_pos = e.loaded;
+
+				if (_pos < _size && Basic.inArray(self.state, [Transporter.IDLE, Transporter.DONE]) === -1) {
+					_transport.call(self);
+				}
+			}, 999);
+
+			self.bind("TransportingComplete", function() {
+				_pos = _size;
+				self.state = Transporter.DONE;
+				_data = null; // clean a bit
+				self.result = _runtime.exec.call(self, 'Transporter', 'getAsBlob', type || '');
+			}, 999);
+
+			self.state = Transporter.BUSY;
+			self.trigger("TransportingStarted");
+			_transport.call(self);
+		}
+
+		function _transport() {
+			var self = this,
+				chunk,
+				bytesLeft = _size - _pos;
+
+			if (_chunk_size > bytesLeft) {
+				_chunk_size = bytesLeft;
+			}
+
+			chunk = Encode.btoa(_data.substr(_pos, _chunk_size));
+			_runtime.exec.call(self, 'Transporter', 'receive', chunk, _size);
+		}
+	}
+
+	Transporter.IDLE = 0;
+	Transporter.BUSY = 1;
+	Transporter.DONE = 2;
+
+	Transporter.prototype = EventTarget.instance;
+
+	return Transporter;
+});
+
+// Included from: src/javascript/image/Image.js
+
+/**
+ * Image.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+define("moxie/image/Image", [
+	"moxie/core/utils/Basic",
+	"moxie/core/utils/Dom",
+	"moxie/core/Exceptions",
+	"moxie/file/FileReaderSync",
+	"moxie/xhr/XMLHttpRequest",
+	"moxie/runtime/Runtime",
+	"moxie/runtime/RuntimeClient",
+	"moxie/runtime/Transporter",
+	"moxie/core/utils/Env",
+	"moxie/core/EventTarget",
+	"moxie/file/Blob",
+	"moxie/file/File",
+	"moxie/core/utils/Encode"
+], function(Basic, Dom, x, FileReaderSync, XMLHttpRequest, Runtime, RuntimeClient, Transporter, Env, EventTarget, Blob, File, Encode) {
+	/**
+	Image preloading and manipulation utility. Additionally it provides access to image meta info (Exif, GPS) and raw binary data.
+
+	@class Image
+	@constructor
+	@extends EventTarget
+	*/
+	var dispatches = [
+		'progress',
+
+		/**
+		Dispatched when loading is complete.
+
+		@event load
+		@param {Object} event
+		*/
+		'load',
+
+		'error',
+
+		/**
+		Dispatched when resize operation is complete.
+		
+		@event resize
+		@param {Object} event
+		*/
+		'resize',
+
+		/**
+		Dispatched when visual representation of the image is successfully embedded
+		into the corresponsing container.
+
+		@event embedded
+		@param {Object} event
+		*/
+		'embedded'
+	];
+
+	function Image() {
+		RuntimeClient.call(this);
+
+		Basic.extend(this, {
+			/**
+			Unique id of the component
+
+			@property uid
+			@type {String}
+			*/
+			uid: Basic.guid('uid_'),
+
+			/**
+			Unique id of the connected runtime, if any.
+
+			@property ruid
+			@type {String}
+			*/
+			ruid: null,
+
+			/**
+			Name of the file, that was used to create an image, if available. If not equals to empty string.
+
+			@property name
+			@type {String}
+			@default ""
+			*/
+			name: "",
+
+			/**
+			Size of the image in bytes. Actual value is set only after image is preloaded.
+
+			@property size
+			@type {Number}
+			@default 0
+			*/
+			size: 0,
+
+			/**
+			Width of the image. Actual value is set only after image is preloaded.
+
+			@property width
+			@type {Number}
+			@default 0
+			*/
+			width: 0,
+
+			/**
+			Height of the image. Actual value is set only after image is preloaded.
+
+			@property height
+			@type {Number}
+			@default 0
+			*/
+			height: 0,
+
+			/**
+			Mime type of the image. Currently only image/jpeg and image/png are supported. Actual value is set only after image is preloaded.
+
+			@property type
+			@type {String}
+			@default ""
+			*/
+			type: "",
+
+			/**
+			Holds meta info (Exif, GPS). Is populated only for image/jpeg. Actual value is set only after image is preloaded.
+
+			@property meta
+			@type {Object}
+			@default {}
+			*/
+			meta: {},
+
+			/**
+			Alias for load method, that takes another mOxie.Image object as a source (see load).
+
+			@method clone
+			@param {Image} src Source for the image
+			@param {Boolean} [exact=false] Whether to activate in-depth clone mode
+			*/
+			clone: function() {
+				this.load.apply(this, arguments);
+			},
+
+			/**
+			Loads image from various sources. Currently the source for new image can be: mOxie.Image, mOxie.Blob/mOxie.File, 
+			native Blob/File, dataUrl or URL. Depending on the type of the source, arguments - differ. When source is URL, 
+			Image will be downloaded from remote destination and loaded in memory.
+
+			@example
+				var img = new mOxie.Image();
+				img.onload = function() {
+					var blob = img.getAsBlob();
+					
+					var formData = new mOxie.FormData();
+					formData.append('file', blob);
+
+					var xhr = new mOxie.XMLHttpRequest();
+					xhr.onload = function() {
+						// upload complete
+					};
+					xhr.open('post', 'upload.php');
+					xhr.send(formData);
+				};
+				img.load("http://www.moxiecode.com/images/mox-logo.jpg"); // notice file extension (.jpg)
+			
+
+			@method load
+			@param {Image|Blob|File|String} src Source for the image
+			@param {Boolean|Object} [mixed]
+			*/
+			load: function() {
+				// this is here because to bind properly we need an uid first, which is created above
+				this.bind('Load Resize', function() {
+					_updateInfo.call(this);
+				}, 999);
+
+				this.convertEventPropsToHandlers(dispatches);
+
+				_load.apply(this, arguments);
+			},
+
+			/**
+			Downsizes the image to fit the specified width/height. If crop is supplied, image will be cropped to exact dimensions.
+
+			@method downsize
+			@param {Number} width Resulting width
+			@param {Number} [height=width] Resulting height (optional, if not supplied will default to width)
+			@param {Boolean} [crop=false] Whether to crop the image to exact dimensions
+			@param {Boolean} [preserveHeaders=true] Whether to preserve meta headers (on JPEGs after resize)
+			*/
+			downsize: function(opts) {
+				var defaults = {
+					width: this.width,
+					height: this.height,
+					crop: false,
+					preserveHeaders: true
+				};
+
+				if (typeof(opts) === 'object') {
+					opts = Basic.extend(defaults, opts);
+				} else {
+					opts = Basic.extend(defaults, {
+						width: arguments[0],
+						height: arguments[1],
+						crop: arguments[2],
+						preserveHeaders: arguments[3]
+					});
+				}
+
+				try {
+					if (!this.size) { // only preloaded image objects can be used as source
+						throw new x.DOMException(x.DOMException.INVALID_STATE_ERR);
+					}
+
+					// no way to reliably intercept the crash due to high resolution, so we simply avoid it
+					if (this.width > Image.MAX_RESIZE_WIDTH || this.height > Image.MAX_RESIZE_HEIGHT) {
+						throw new x.ImageError(x.ImageError.MAX_RESOLUTION_ERR);
+					}
+
+					this.getRuntime().exec.call(this, 'Image', 'downsize', opts.width, opts.height, opts.crop, opts.preserveHeaders);
+				} catch(ex) {
+					// for now simply trigger error event
+					this.trigger('error', ex.code);
+				}
+			},
+
+			/**
+			Alias for downsize(width, height, true). (see downsize)
+			
+			@method crop
+			@param {Number} width Resulting width
+			@param {Number} [height=width] Resulting height (optional, if not supplied will default to width)
+			@param {Boolean} [preserveHeaders=true] Whether to preserve meta headers (on JPEGs after resize)
+			*/
+			crop: function(width, height, preserveHeaders) {
+				this.downsize(width, height, true, preserveHeaders);
+			},
+
+			getAsCanvas: function() {
+				if (!Env.can('create_canvas')) {
+					throw new x.RuntimeError(x.RuntimeError.NOT_SUPPORTED_ERR);
+				}
+
+				var runtime = this.connectRuntime(this.ruid);
+				return runtime.exec.call(this, 'Image', 'getAsCanvas');
+			},
+
+			/**
+			Retrieves image in it's current state as mOxie.Blob object. Cannot be run on empty or image in progress (throws
+			DOMException.INVALID_STATE_ERR).
+
+			@method getAsBlob
+			@param {String} [type="image/jpeg"] Mime type of resulting blob. Can either be image/jpeg or image/png
+			@param {Number} [quality=90] Applicable only together with mime type image/jpeg
+			@return {Blob} Image as Blob
+			*/
+			getAsBlob: function(type, quality) {
+				if (!this.size) {
+					throw new x.DOMException(x.DOMException.INVALID_STATE_ERR);
+				}
+
+				if (!type) {
+					type = 'image/jpeg';
+				}
+
+				if (type === 'image/jpeg' && !quality) {
+					quality = 90;
+				}
+
+				return this.getRuntime().exec.call(this, 'Image', 'getAsBlob', type, quality);
+			},
+
+			/**
+			Retrieves image in it's current state as dataURL string. Cannot be run on empty or image in progress (throws
+			DOMException.INVALID_STATE_ERR).
+
+			@method getAsDataURL
+			@param {String} [type="image/jpeg"] Mime type of resulting blob. Can either be image/jpeg or image/png
+			@param {Number} [quality=90] Applicable only together with mime type image/jpeg
+			@return {String} Image as dataURL string
+			*/
+			getAsDataURL: function(type, quality) {
+				if (!this.size) {
+					throw new x.DOMException(x.DOMException.INVALID_STATE_ERR);
+				}
+				return this.getRuntime().exec.call(this, 'Image', 'getAsDataURL', type, quality);
+			},
+
+			/**
+			Retrieves image in it's current state as binary string. Cannot be run on empty or image in progress (throws
+			DOMException.INVALID_STATE_ERR).
+
+			@method getAsBinaryString
+			@param {String} [type="image/jpeg"] Mime type of resulting blob. Can either be image/jpeg or image/png
+			@param {Number} [quality=90] Applicable only together with mime type image/jpeg
+			@return {String} Image as binary string
+			*/
+			getAsBinaryString: function(type, quality) {
+				var dataUrl = this.getAsDataURL(type, quality);
+				return Encode.atob(dataUrl.substring(dataUrl.indexOf('base64,') + 7));
+			},
+
+			/**
+			Embeds a visual representation of the image into the specified node. Depending on the runtime, 
+			it might be a canvas, an img node or a thrid party shim object (Flash or SilverLight - very rare, 
+			can be used in legacy browsers that do not have canvas or proper dataURI support).
+
+			@method embed
+			@param {DOMElement} el DOM element to insert the image object into
+			@param {Object} [options]
+				@param {Number} [options.width] The width of an embed (defaults to the image width)
+				@param {Number} [options.height] The height of an embed (defaults to the image height)
+				@param {String} [type="image/jpeg"] Mime type
+				@param {Number} [quality=90] Quality of an embed, if mime type is image/jpeg
+				@param {Boolean} [crop=false] Whether to crop an embed to the specified dimensions
+			*/
+			embed: function(el) {
+				var self = this
+				, imgCopy
+				, type, quality, crop
+				, options = arguments[1] || {}
+				, width = this.width
+				, height = this.height
+				, runtime // this has to be outside of all the closures to contain proper runtime
+				;
+
+				function onResize() {
+					// if possible, embed a canvas element directly
+					if (Env.can('create_canvas')) {
+						var canvas = imgCopy.getAsCanvas();
+						if (canvas) {
+							el.appendChild(canvas);
+							canvas = null;
+							imgCopy.destroy();
+							self.trigger('embedded');
+							return;
+						}
+					}
+
+					var dataUrl = imgCopy.getAsDataURL(type, quality);
+					if (!dataUrl) {
+						throw new x.ImageError(x.ImageError.WRONG_FORMAT);
+					}
+
+					if (Env.can('use_data_uri_of', dataUrl.length)) {
+						el.innerHTML = '<img src="' + dataUrl + '" width="' + imgCopy.width + '" height="' + imgCopy.height + '" />';
+						imgCopy.destroy();
+						self.trigger('embedded');
+					} else {
+						var tr = new Transporter();
+
+						tr.bind("TransportingComplete", function() {
+							runtime = self.connectRuntime(this.result.ruid);
+
+							self.bind("Embedded", function() {
+								// position and size properly
+								Basic.extend(runtime.getShimContainer().style, {
+									//position: 'relative',
+									top: '0px',
+									left: '0px',
+									width: imgCopy.width + 'px',
+									height: imgCopy.height + 'px'
+								});
+
+								// some shims (Flash/SilverLight) reinitialize, if parent element is hidden, reordered or it's
+								// position type changes (in Gecko), but since we basically need this only in IEs 6/7 and
+								// sometimes 8 and they do not have this problem, we can comment this for now
+								/*tr.bind("RuntimeInit", function(e, runtime) {
+									tr.destroy();
+									runtime.destroy();
+									onResize.call(self); // re-feed our image data
+								});*/
+
+								runtime = null;
+							}, 999);
+
+							runtime.exec.call(self, "ImageView", "display", this.result.uid, width, height);
+							imgCopy.destroy();
+						});
+
+						tr.transport(Encode.atob(dataUrl.substring(dataUrl.indexOf('base64,') + 7)), type, Basic.extend({}, options, {
+							required_caps: {
+								display_media: true
+							},
+							runtime_order: 'flash,silverlight',
+							container: el
+						}));
+					}
+				}
+
+				try {
+					if (!(el = Dom.get(el))) {
+						throw new x.DOMException(x.DOMException.INVALID_NODE_TYPE_ERR);
+					}
+
+					if (!this.size) { // only preloaded image objects can be used as source
+						throw new x.DOMException(x.DOMException.INVALID_STATE_ERR);
+					}
+
+					if (this.width > Image.MAX_RESIZE_WIDTH || this.height > Image.MAX_RESIZE_HEIGHT) {
+						throw new x.ImageError(x.ImageError.MAX_RESOLUTION_ERR);
+					}
+
+					type = options.type || this.type || 'image/jpeg';
+					quality = options.quality || 90;
+					crop = Basic.typeOf(options.crop) !== 'undefined' ? options.crop : false;
+
+					// figure out dimensions for the thumb
+					if (options.width) {
+						width = options.width;
+						height = options.height || width;
+					} else {
+						// if container element has measurable dimensions, use them
+						var dimensions = Dom.getSize(el);
+						if (dimensions.w && dimensions.h) { // both should be > 0
+							width = dimensions.w;
+							height = dimensions.h;
+						}
+					}
+
+					imgCopy = new Image();
+
+					imgCopy.bind("Resize", function() {
+						onResize.call(self);
+					});
+
+					imgCopy.bind("Load", function() {
+						imgCopy.downsize(width, height, crop, false);
+					});
+
+					imgCopy.clone(this, false);
+
+					return imgCopy;
+				} catch(ex) {
+					// for now simply trigger error event
+					this.trigger('error', ex.code);
+				}
+			},
+
+			/**
+			Properly destroys the image and frees resources in use. If any. Recommended way to dispose mOxie.Image object.
+
+			@method destroy
+			*/
+			destroy: function() {
+				if (this.ruid) {
+					this.getRuntime().exec.call(this, 'Image', 'destroy');
+					this.disconnectRuntime();
+				}
+				this.unbindAll();
+			}
+		});
+
+
+		function _updateInfo(info) {
+			if (!info) {
+				info = this.getRuntime().exec.call(this, 'Image', 'getInfo');
+			}
+
+			this.size = info.size;
+			this.width = info.width;
+			this.height = info.height;
+			this.type = info.type;
+			this.meta = info.meta;
+
+			// update file name, only if empty
+			if (this.name === '') {
+				this.name = info.name;
+			}
+		}
+		
+
+		function _load(src) {
+			var srcType = Basic.typeOf(src);
+
+			try {
+				// if source is Image
+				if (src instanceof Image) {
+					if (!src.size) { // only preloaded image objects can be used as source
+						throw new x.DOMException(x.DOMException.INVALID_STATE_ERR);
+					}
+					_loadFromImage.apply(this, arguments);
+				}
+				// if source is o.Blob/o.File
+				else if (src instanceof Blob) {
+					if (!~Basic.inArray(src.type, ['image/jpeg', 'image/png'])) {
+						throw new x.ImageError(x.ImageError.WRONG_FORMAT);
+					}
+					_loadFromBlob.apply(this, arguments);
+				}
+				// if native blob/file
+				else if (Basic.inArray(srcType, ['blob', 'file']) !== -1) {
+					_load.call(this, new File(null, src), arguments[1]);
+				}
+				// if String
+				else if (srcType === 'string') {
+					// if dataUrl String
+					if (/^data:[^;]*;base64,/.test(src)) {
+						_load.call(this, new Blob(null, { data: src }), arguments[1]);
+					}
+					// else assume Url, either relative or absolute
+					else {
+						_loadFromUrl.apply(this, arguments);
+					}
+				}
+				// if source seems to be an img node
+				else if (srcType === 'node' && src.nodeName.toLowerCase() === 'img') {
+					_load.call(this, src.src, arguments[1]);
+				}
+				else {
+					throw new x.DOMException(x.DOMException.TYPE_MISMATCH_ERR);
+				}
+			} catch(ex) {
+				// for now simply trigger error event
+				this.trigger('error', ex.code);
+			}
+		}
+
+
+		function _loadFromImage(img, exact) {
+			var runtime = this.connectRuntime(img.ruid);
+			this.ruid = runtime.uid;
+			runtime.exec.call(this, 'Image', 'loadFromImage', img, (Basic.typeOf(exact) === 'undefined' ? true : exact));
+		}
+
+
+		function _loadFromBlob(blob, options) {
+			var self = this;
+
+			self.name = blob.name || '';
+
+			function exec(runtime) {
+				self.ruid = runtime.uid;
+				runtime.exec.call(self, 'Image', 'loadFromBlob', blob);
+			}
+
+			if (blob.isDetached()) {
+				this.bind('RuntimeInit', function(e, runtime) {
+					exec(runtime);
+				});
+
+				// convert to object representation
+				if (options && typeof(options.required_caps) === 'string') {
+					options.required_caps = Runtime.parseCaps(options.required_caps);
+				}
+
+				this.connectRuntime(Basic.extend({
+					required_caps: {
+						access_image_binary: true,
+						resize_image: true
+					}
+				}, options));
+			} else {
+				exec(this.connectRuntime(blob.ruid));
+			}
+		}
+
+
+		function _loadFromUrl(url, options) {
+			var self = this, xhr;
+
+			xhr = new XMLHttpRequest();
+
+			xhr.open('get', url);
+			xhr.responseType = 'blob';
+
+			xhr.onprogress = function(e) {
+				self.trigger(e);
+			};
+
+			xhr.onload = function() {
+				_loadFromBlob.call(self, xhr.response, true);
+			};
+
+			xhr.onerror = function(e) {
+				self.trigger(e);
+			};
+
+			xhr.onloadend = function() {
+				xhr.destroy();
+			};
+
+			xhr.bind('RuntimeError', function(e, err) {
+				self.trigger('RuntimeError', err);
+			});
+
+			xhr.send(null, options);
+		}
+	}
+
+	// virtual world will crash on you if image has a resolution higher than this:
+	Image.MAX_RESIZE_WIDTH = 6500;
+	Image.MAX_RESIZE_HEIGHT = 6500; 
+
+	Image.prototype = EventTarget.instance;
+
+	return Image;
+});
+
+// Included from: src/javascript/runtime/html5/Runtime.js
+
+/**
+ * Runtime.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+/*global File:true */
+
+/**
+Defines constructor for HTML5 runtime.
+
+@class moxie/runtime/html5/Runtime
+@private
+*/
+define("moxie/runtime/html5/Runtime", [
+	"moxie/core/utils/Basic",
+	"moxie/core/Exceptions",
+	"moxie/runtime/Runtime",
+	"moxie/core/utils/Env"
+], function(Basic, x, Runtime, Env) {
+	
+	var type = "html5", extensions = {};
+	
+	function Html5Runtime(options) {
+		var I = this
+		, Test = Runtime.capTest
+		, True = Runtime.capTrue
+		;
+
+		var caps = Basic.extend({
+				access_binary: Test(window.FileReader || window.File && window.File.getAsDataURL),
+				access_image_binary: function() {
+					return I.can('access_binary') && !!extensions.Image;
+				},
+				display_media: Test(Env.can('create_canvas') || Env.can('use_data_uri_over32kb')),
+				do_cors: Test(window.XMLHttpRequest && 'withCredentials' in new XMLHttpRequest()),
+				drag_and_drop: Test(function() {
+					// this comes directly from Modernizr: http://www.modernizr.com/
+					var div = document.createElement('div');
+					// IE has support for drag and drop since version 5, but doesn't support dropping files from desktop
+					return (('draggable' in div) || ('ondragstart' in div && 'ondrop' in div)) && (Env.browser !== 'IE' || Env.version > 9);
+				}()),
+				filter_by_extension: Test(function() { // if you know how to feature-detect this, please suggest
+					return (Env.browser === 'Chrome' && Env.version >= 28) || (Env.browser === 'IE' && Env.version >= 10);
+				}()),
+				return_response_headers: True,
+				return_response_type: function(responseType) {
+					if (responseType === 'json' && !!window.JSON) { // we can fake this one even if it's not supported
+						return true;
+					} 
+					return Env.can('return_response_type', responseType);
+				},
+				return_status_code: True,
+				report_upload_progress: Test(window.XMLHttpRequest && new XMLHttpRequest().upload),
+				resize_image: function() {
+					return I.can('access_binary') && Env.can('create_canvas');
+				},
+				select_file: function() {
+					return Env.can('use_fileinput') && window.File;
+				},
+				select_folder: function() {
+					return I.can('select_file') && Env.browser === 'Chrome' && Env.version >= 21;
+				},
+				select_multiple: function() {
+					// it is buggy on Safari Windows and iOS
+					return I.can('select_file') && 
+						!(Env.browser === 'Safari' && Env.os === 'Windows') && 
+						!(Env.os === 'iOS' && Env.verComp(Env.osVersion, "7.0.4", '<'));
+				},
+				send_binary_string: Test(window.XMLHttpRequest && (new XMLHttpRequest().sendAsBinary || (window.Uint8Array && window.ArrayBuffer))),
+				send_custom_headers: Test(window.XMLHttpRequest),
+				send_multipart: function() {
+					return !!(window.XMLHttpRequest && new XMLHttpRequest().upload && window.FormData) || I.can('send_binary_string');
+				},
+				slice_blob: Test(window.File && (File.prototype.mozSlice || File.prototype.webkitSlice || File.prototype.slice)),
+				stream_upload: function(){
+					return I.can('slice_blob') && I.can('send_multipart');
+				},
+				summon_file_dialog: Test(function() { // yeah... some dirty sniffing here...
+					return (Env.browser === 'Firefox' && Env.version >= 4) ||
+						(Env.browser === 'Opera' && Env.version >= 12) ||
+						(Env.browser === 'IE' && Env.version >= 10) ||
+						!!~Basic.inArray(Env.browser, ['Chrome', 'Safari']);
+				}()),
+				upload_filesize: True
+			}, 
+			arguments[2]
+		);
+
+		Runtime.call(this, options, (arguments[1] || type), caps);
+
+
+		Basic.extend(this, {
+
+			init : function() {
+				this.trigger("Init");
+			},
+
+			destroy: (function(destroy) { // extend default destroy method
+				return function() {
+					destroy.call(I);
+					destroy = I = null;
+				};
+			}(this.destroy))
+		});
+
+		Basic.extend(this.getShim(), extensions);
+	}
+
+	Runtime.addConstructor(type, Html5Runtime);
+
+	return extensions;
+});
+
+// Included from: src/javascript/runtime/html5/file/Blob.js
+
+/**
+ * Blob.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+/**
+@class moxie/runtime/html5/file/Blob
+@private
+*/
+define("moxie/runtime/html5/file/Blob", [
+	"moxie/runtime/html5/Runtime",
+	"moxie/file/Blob"
+], function(extensions, Blob) {
+
+	function HTML5Blob() {
+		function w3cBlobSlice(blob, start, end) {
+			var blobSlice;
+
+			if (window.File.prototype.slice) {
+				try {
+					blob.slice();	// depricated version will throw WRONG_ARGUMENTS_ERR exception
+					return blob.slice(start, end);
+				} catch (e) {
+					// depricated slice method
+					return blob.slice(start, end - start);
+				}
+			// slice method got prefixed: https://bugzilla.mozilla.org/show_bug.cgi?id=649672
+			} else if ((blobSlice = window.File.prototype.webkitSlice || window.File.prototype.mozSlice)) {
+				return blobSlice.call(blob, start, end);
+			} else {
+				return null; // or throw some exception
+			}
+		}
+
+		this.slice = function() {
+			return new Blob(this.getRuntime().uid, w3cBlobSlice.apply(this, arguments));
+		};
+	}
+
+	return (extensions.Blob = HTML5Blob);
+});
+
+// Included from: src/javascript/core/utils/Events.js
+
+/**
+ * Events.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+define('moxie/core/utils/Events', [
+	'moxie/core/utils/Basic'
+], function(Basic) {
+	var eventhash = {}, uid = 'moxie_' + Basic.guid();
+	
+	// IE W3C like event funcs
+	function preventDefault() {
+		this.returnValue = false;
+	}
+
+	function stopPropagation() {
+		this.cancelBubble = true;
+	}
+
+	/**
+	Adds an event handler to the specified object and store reference to the handler
+	in objects internal Plupload registry (@see removeEvent).
+	
+	@method addEvent
+	@for Utils
+	@static
+	@param {Object} obj DOM element like object to add handler to.
+	@param {String} name Name to add event listener to.
+	@param {Function} callback Function to call when event occurs.
+	@param {String} [key] that might be used to add specifity to the event record.
+	*/
+	var addEvent = function(obj, name, callback, key) {
+		var func, events;
+					
+		name = name.toLowerCase();
+
+		// Add event listener
+		if (obj.addEventListener) {
+			func = callback;
+			
+			obj.addEventListener(name, func, false);
+		} else if (obj.attachEvent) {
+			func = function() {
+				var evt = window.event;
+
+				if (!evt.target) {
+					evt.target = evt.srcElement;
+				}
+
+				evt.preventDefault = preventDefault;
+				evt.stopPropagation = stopPropagation;
+
+				callback(evt);
+			};
+
+			obj.attachEvent('on' + name, func);
+		}
+		
+		// Log event handler to objects internal mOxie registry
+		if (!obj[uid]) {
+			obj[uid] = Basic.guid();
+		}
+		
+		if (!eventhash.hasOwnProperty(obj[uid])) {
+			eventhash[obj[uid]] = {};
+		}
+		
+		events = eventhash[obj[uid]];
+		
+		if (!events.hasOwnProperty(name)) {
+			events[name] = [];
+		}
+				
+		events[name].push({
+			func: func,
+			orig: callback, // store original callback for IE
+			key: key
+		});
+	};
+	
+	
+	/**
+	Remove event handler from the specified object. If third argument (callback)
+	is not specified remove all events with the specified name.
+	
+	@method removeEvent
+	@static
+	@param {Object} obj DOM element to remove event listener(s) from.
+	@param {String} name Name of event listener to remove.
+	@param {Function|String} [callback] might be a callback or unique key to match.
+	*/
+	var removeEvent = function(obj, name, callback) {
+		var type, undef;
+		
+		name = name.toLowerCase();
+		
+		if (obj[uid] && eventhash[obj[uid]] && eventhash[obj[uid]][name]) {
+			type = eventhash[obj[uid]][name];
+		} else {
+			return;
+		}
+			
+		for (var i = type.length - 1; i >= 0; i--) {
+			// undefined or not, key should match
+			if (type[i].orig === callback || type[i].key === callback) {
+				if (obj.removeEventListener) {
+					obj.removeEventListener(name, type[i].func, false);
+				} else if (obj.detachEvent) {
+					obj.detachEvent('on'+name, type[i].func);
+				}
+				
+				type[i].orig = null;
+				type[i].func = null;
+				type.splice(i, 1);
+				
+				// If callback was passed we are done here, otherwise proceed
+				if (callback !== undef) {
+					break;
+				}
+			}
+		}
+		
+		// If event array got empty, remove it
+		if (!type.length) {
+			delete eventhash[obj[uid]][name];
+		}
+		
+		// If mOxie registry has become empty, remove it
+		if (Basic.isEmptyObj(eventhash[obj[uid]])) {
+			delete eventhash[obj[uid]];
+			
+			// IE doesn't let you remove DOM object property with - delete
+			try {
+				delete obj[uid];
+			} catch(e) {
+				obj[uid] = undef;
+			}
+		}
+	};
+	
+	
+	/**
+	Remove all kind of events from the specified object
+	
+	@method removeAllEvents
+	@static
+	@param {Object} obj DOM element to remove event listeners from.
+	@param {String} [key] unique key to match, when removing events.
+	*/
+	var removeAllEvents = function(obj, key) {		
+		if (!obj || !obj[uid]) {
+			return;
+		}
+		
+		Basic.each(eventhash[obj[uid]], function(events, name) {
+			removeEvent(obj, name, key);
+		});
+	};
+
+	return {
+		addEvent: addEvent,
+		removeEvent: removeEvent,
+		removeAllEvents: removeAllEvents
+	};
+});
+
+// Included from: src/javascript/runtime/html5/file/FileInput.js
+
+/**
+ * FileInput.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+/**
+@class moxie/runtime/html5/file/FileInput
+@private
+*/
+define("moxie/runtime/html5/file/FileInput", [
+	"moxie/runtime/html5/Runtime",
+	"moxie/core/utils/Basic",
+	"moxie/core/utils/Dom",
+	"moxie/core/utils/Events",
+	"moxie/core/utils/Mime",
+	"moxie/core/utils/Env"
+], function(extensions, Basic, Dom, Events, Mime, Env) {
+	
+	function FileInput() {
+		var _files = [], _options;
+
+		Basic.extend(this, {
+			init: function(options) {
+				var comp = this, I = comp.getRuntime(), input, shimContainer, mimes, browseButton, zIndex, top;
+
+				_options = options;
+				_files = [];
+
+				// figure out accept string
+				mimes = _options.accept.mimes || Mime.extList2mimes(_options.accept, I.can('filter_by_extension'));
+
+				shimContainer = I.getShimContainer();
+
+				shimContainer.innerHTML = '<input id="' + I.uid +'" type="file" style="font-size:999px;opacity:0;"' +
+					(_options.multiple && I.can('select_multiple') ? 'multiple' : '') + 
+					(_options.directory && I.can('select_folder') ? 'webkitdirectory directory' : '') + // Chrome 11+
+					(mimes ? ' accept="' + mimes.join(',') + '"' : '') + ' />';
+
+				input = Dom.get(I.uid);
+
+				// prepare file input to be placed underneath the browse_button element
+				Basic.extend(input.style, {
+					position: 'absolute',
+					top: 0,
+					left: 0,
+					width: '100%',
+					height: '100%'
+				});
+
+
+				browseButton = Dom.get(_options.browse_button);
+
+				// Route click event to the input[type=file] element for browsers that support such behavior
+				if (I.can('summon_file_dialog')) {
+					if (Dom.getStyle(browseButton, 'position') === 'static') {
+						browseButton.style.position = 'relative';
+					}
+
+					zIndex = parseInt(Dom.getStyle(browseButton, 'z-index'), 10) || 1;
+
+					browseButton.style.zIndex = zIndex;
+					shimContainer.style.zIndex = zIndex - 1;
+
+					Events.addEvent(browseButton, 'click', function(e) {
+						var input = Dom.get(I.uid);
+						if (input && !input.disabled) { // for some reason FF (up to 8.0.1 so far) lets to click disabled input[type=file]
+							input.click();
+						}
+						e.preventDefault();
+					}, comp.uid);
+				}
+
+				/* Since we have to place input[type=file] on top of the browse_button for some browsers,
+				browse_button loses interactivity, so we restore it here */
+				top = I.can('summon_file_dialog') ? browseButton : shimContainer;
+
+				Events.addEvent(top, 'mouseover', function() {
+					comp.trigger('mouseenter');
+				}, comp.uid);
+
+				Events.addEvent(top, 'mouseout', function() {
+					comp.trigger('mouseleave');
+				}, comp.uid);
+
+				Events.addEvent(top, 'mousedown', function() {
+					comp.trigger('mousedown');
+				}, comp.uid);
+
+				Events.addEvent(Dom.get(_options.container), 'mouseup', function() {
+					comp.trigger('mouseup');
+				}, comp.uid);
+
+
+				input.onchange = function onChange() { // there should be only one handler for this
+					_files = [];
+
+					if (_options.directory) {
+						// folders are represented by dots, filter them out (Chrome 11+)
+						Basic.each(this.files, function(file) {
+							if (file.name !== ".") { // if it doesn't looks like a folder
+								_files.push(file);
+							}
+						});
+					} else {
+						_files = [].slice.call(this.files);
+					}
+
+					// clearing the value enables the user to select the same file again if they want to
+					if (Env.browser !== 'IE' && Env.browser !== 'IEMobile') {
+						this.value = '';
+					} else {
+						// in IE input[type="file"] is read-only so the only way to reset it is to re-insert it
+						var clone = this.cloneNode(true);
+						this.parentNode.replaceChild(clone, this);
+						clone.onchange = onChange;
+					}
+					comp.trigger('change');
+				};
+
+				// ready event is perfectly asynchronous
+				comp.trigger({
+					type: 'ready',
+					async: true
+				});
+
+				shimContainer = null;
+			},
+
+			getFiles: function() {
+				return _files;
+			},
+
+			disable: function(state) {
+				var I = this.getRuntime(), input;
+
+				if ((input = Dom.get(I.uid))) {
+					input.disabled = !!state;
+				}
+			},
+
+			destroy: function() {
+				var I = this.getRuntime()
+				, shim = I.getShim()
+				, shimContainer = I.getShimContainer()
+				;
+				
+				Events.removeAllEvents(shimContainer, this.uid);
+				Events.removeAllEvents(_options && Dom.get(_options.container), this.uid);
+				Events.removeAllEvents(_options && Dom.get(_options.browse_button), this.uid);
+				
+				if (shimContainer) {
+					shimContainer.innerHTML = '';
+				}
+
+				shim.removeInstance(this.uid);
+
+				_files = _options = shimContainer = shim = null;
+			}
+		});
+	}
+
+	return (extensions.FileInput = FileInput);
+});
+
+// Included from: src/javascript/runtime/html5/file/FileDrop.js
+
+/**
+ * FileDrop.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+/**
+@class moxie/runtime/html5/file/FileDrop
+@private
+*/
+define("moxie/runtime/html5/file/FileDrop", [
+	"moxie/runtime/html5/Runtime",
+	"moxie/core/utils/Basic",
+	"moxie/core/utils/Dom",
+	"moxie/core/utils/Events",
+	"moxie/core/utils/Mime"
+], function(extensions, Basic, Dom, Events, Mime) {
+	
+	function FileDrop() {
+		var _files = [], _allowedExts = [], _options;
+
+		Basic.extend(this, {
+			init: function(options) {
+				var comp = this, dropZone;
+
+				_options = options;
+				_allowedExts = _extractExts(_options.accept);
+				dropZone = _options.container;
+
+				Events.addEvent(dropZone, 'dragover', function(e) {
+					if (!_hasFiles(e)) {
+						return;
+					}
+					e.preventDefault();
+					e.dataTransfer.dropEffect = 'copy';
+				}, comp.uid);
+
+				Events.addEvent(dropZone, 'drop', function(e) {
+					if (!_hasFiles(e)) {
+						return;
+					}
+					e.preventDefault();
+
+					_files = [];
+
+					// Chrome 21+ accepts folders via Drag'n'Drop
+					if (e.dataTransfer.items && e.dataTransfer.items[0].webkitGetAsEntry) {
+						_readItems(e.dataTransfer.items, function() {
+							comp.trigger("drop");
+						});
+					} else {
+						Basic.each(e.dataTransfer.files, function(file) {
+							if (_isAcceptable(file)) {
+								_files.push(file);
+							}
+						});
+						comp.trigger("drop");
+					}
+				}, comp.uid);
+
+				Events.addEvent(dropZone, 'dragenter', function(e) {
+					comp.trigger("dragenter");
+				}, comp.uid);
+
+				Events.addEvent(dropZone, 'dragleave', function(e) {
+					comp.trigger("dragleave");
+				}, comp.uid);
+			},
+
+			getFiles: function() {
+				return _files;
+			},
+
+			destroy: function() {
+				Events.removeAllEvents(_options && Dom.get(_options.container), this.uid);
+				_files = _allowedExts = _options = null;
+			}
+		});
+
+
+		function _hasFiles(e) {
+			if (!e.dataTransfer || !e.dataTransfer.types) { // e.dataTransfer.files is not available in Gecko during dragover
+				return false;
+			}
+
+			var types = Basic.toArray(e.dataTransfer.types || []);
+
+			return Basic.inArray("Files", types) !== -1 ||
+				Basic.inArray("public.file-url", types) !== -1 || // Safari < 5
+				Basic.inArray("application/x-moz-file", types) !== -1 // Gecko < 1.9.2 (< Firefox 3.6)
+				;
+		}
+
+		
+		function _extractExts(accept) {
+			var exts = [];
+			for (var i = 0; i < accept.length; i++) {
+				[].push.apply(exts, accept[i].extensions.split(/\s*,\s*/));
+			}
+			return Basic.inArray('*', exts) === -1 ? exts : [];
+		}
+
+
+		function _isAcceptable(file) {
+			if (!_allowedExts.length) {
+				return true;
+			}
+			var ext = Mime.getFileExtension(file.name);
+			return !ext || Basic.inArray(ext, _allowedExts) !== -1;
+		}
+
+
+		function _readItems(items, cb) {
+			var entries = [];
+			Basic.each(items, function(item) {
+				var entry = item.webkitGetAsEntry();
+				// Address #998 (https://code.google.com/p/chromium/issues/detail?id=332579)
+				if (entry) {
+					// file() fails on OSX when the filename contains a special character (e.g. umlaut): see #61
+					if (entry.isFile) {
+						var file = item.getAsFile();
+						if (_isAcceptable(file)) {
+							_files.push(file);
+						}
+					} else {
+						entries.push(entry);
+					}
+				}
+			});
+
+			if (entries.length) {
+				_readEntries(entries, cb);
+			} else {
+				cb();
+			}
+		}
+
+
+		function _readEntries(entries, cb) {
+			var queue = [];
+			Basic.each(entries, function(entry) {
+				queue.push(function(cbcb) {
+					_readEntry(entry, cbcb);
+				});
+			});
+			Basic.inSeries(queue, function() {
+				cb();
+			});
+		}
+
+
+		function _readEntry(entry, cb) {
+			if (entry.isFile) {
+				entry.file(function(file) {
+					if (_isAcceptable(file)) {
+						_files.push(file);
+					}
+					cb();
+				}, function() {
+					// fire an error event maybe
+					cb();
+				});
+			} else if (entry.isDirectory) {
+				_readDirEntry(entry, cb);
+			} else {
+				cb(); // not file, not directory? what then?..
+			}
+		}
+
+
+		function _readDirEntry(dirEntry, cb) {
+			var entries = [], dirReader = dirEntry.createReader();
+
+			// keep quering recursively till no more entries
+			function getEntries(cbcb) {
+				dirReader.readEntries(function(moreEntries) {
+					if (moreEntries.length) {
+						[].push.apply(entries, moreEntries);
+						getEntries(cbcb);
+					} else {
+						cbcb();
+					}
+				}, cbcb);
+			}
+
+			// ...and you thought FileReader was crazy...
+			getEntries(function() {
+				_readEntries(entries, cb);
+			}); 
+		}
+	}
+
+	return (extensions.FileDrop = FileDrop);
+});
+
+// Included from: src/javascript/runtime/html5/file/FileReader.js
+
+/**
+ * FileReader.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+/**
+@class moxie/runtime/html5/file/FileReader
+@private
+*/
+define("moxie/runtime/html5/file/FileReader", [
+	"moxie/runtime/html5/Runtime",
+	"moxie/core/utils/Encode",
+	"moxie/core/utils/Basic"
+], function(extensions, Encode, Basic) {
+	
+	function FileReader() {
+		var _fr, _convertToBinary = false;
+
+		Basic.extend(this, {
+
+			read: function(op, blob) {
+				var target = this;
+
+				_fr = new window.FileReader();
+
+				_fr.addEventListener('progress', function(e) {
+					target.trigger(e);
+				});
+
+				_fr.addEventListener('load', function(e) {
+					target.trigger(e);
+				});
+
+				_fr.addEventListener('error', function(e) {
+					target.trigger(e, _fr.error);
+				});
+
+				_fr.addEventListener('loadend', function() {
+					_fr = null;
+				});
+
+				if (Basic.typeOf(_fr[op]) === 'function') {
+					_convertToBinary = false;
+					_fr[op](blob.getSource());
+				} else if (op === 'readAsBinaryString') { // readAsBinaryString is depricated in general and never existed in IE10+
+					_convertToBinary = true;
+					_fr.readAsDataURL(blob.getSource());
+				}
+			},
+
+			getResult: function() {
+				return _fr && _fr.result ? (_convertToBinary ? _toBinary(_fr.result) : _fr.result) : null;
+			},
+
+			abort: function() {
+				if (_fr) {
+					_fr.abort();
+				}
+			},
+
+			destroy: function() {
+				_fr = null;
+			}
+		});
+
+		function _toBinary(str) {
+			return Encode.atob(str.substring(str.indexOf('base64,') + 7));
+		}
+	}
+
+	return (extensions.FileReader = FileReader);
+});
+
+// Included from: src/javascript/runtime/html5/xhr/XMLHttpRequest.js
+
+/**
+ * XMLHttpRequest.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+/*global ActiveXObject:true */
+
+/**
+@class moxie/runtime/html5/xhr/XMLHttpRequest
+@private
+*/
+define("moxie/runtime/html5/xhr/XMLHttpRequest", [
+	"moxie/runtime/html5/Runtime",
+	"moxie/core/utils/Basic",
+	"moxie/core/utils/Mime",
+	"moxie/core/utils/Url",
+	"moxie/file/File",
+	"moxie/file/Blob",
+	"moxie/xhr/FormData",
+	"moxie/core/Exceptions",
+	"moxie/core/utils/Env"
+], function(extensions, Basic, Mime, Url, File, Blob, FormData, x, Env) {
+	
+	function XMLHttpRequest() {
+		var self = this
+		, _xhr
+		, _filename
+		;
+
+		Basic.extend(this, {
+			send: function(meta, data) {
+				var target = this
+				, isGecko2_5_6 = (Env.browser === 'Mozilla' && Env.version >= 4 && Env.version < 7)
+				, isAndroidBrowser = Env.browser === 'Android Browser'
+				, mustSendAsBinary = false
+				;
+
+				// extract file name
+				_filename = meta.url.replace(/^.+?\/([\w\-\.]+)$/, '$1').toLowerCase();
+
+				_xhr = _getNativeXHR();
+				_xhr.open(meta.method, meta.url, meta.async, meta.user, meta.password);
+
+
+				// prepare data to be sent
+				if (data instanceof Blob) {
+					if (data.isDetached()) {
+						mustSendAsBinary = true;
+					}
+					data = data.getSource();
+				} else if (data instanceof FormData) {
+
+					if (data.hasBlob()) {
+						if (data.getBlob().isDetached()) {
+							data = _prepareMultipart.call(target, data); // _xhr must be instantiated and be in OPENED state
+							mustSendAsBinary = true;
+						} else if ((isGecko2_5_6 || isAndroidBrowser) && Basic.typeOf(data.getBlob().getSource()) === 'blob' && window.FileReader) {
+							// Gecko 2/5/6 can't send blob in FormData: https://bugzilla.mozilla.org/show_bug.cgi?id=649150
+							// Android browsers (default one and Dolphin) seem to have the same issue, see: #613
+							_preloadAndSend.call(target, meta, data);
+							return; // _preloadAndSend will reinvoke send() with transmutated FormData =%D
+						}	
+					}
+
+					// transfer fields to real FormData
+					if (data instanceof FormData) { // if still a FormData, e.g. not mangled by _prepareMultipart()
+						var fd = new window.FormData();
+						data.each(function(value, name) {
+							if (value instanceof Blob) {
+								fd.append(name, value.getSource());
+							} else {
+								fd.append(name, value);
+							}
+						});
+						data = fd;
+					}
+				}
+
+
+				// if XHR L2
+				if (_xhr.upload) {
+					if (meta.withCredentials) {
+						_xhr.withCredentials = true;
+					}
+
+					_xhr.addEventListener('load', function(e) {
+						target.trigger(e);
+					});
+
+					_xhr.addEventListener('error', function(e) {
+						target.trigger(e);
+					});
+
+					// additionally listen to progress events
+					_xhr.addEventListener('progress', function(e) {
+						target.trigger(e);
+					});
+
+					_xhr.upload.addEventListener('progress', function(e) {
+						target.trigger({
+							type: 'UploadProgress',
+							loaded: e.loaded,
+							total: e.total
+						});
+					});
+				// ... otherwise simulate XHR L2
+				} else {
+					_xhr.onreadystatechange = function onReadyStateChange() {
+						
+						// fake Level 2 events
+						switch (_xhr.readyState) {
+							
+							case 1: // XMLHttpRequest.OPENED
+								// readystatechanged is fired twice for OPENED state (in IE and Mozilla) - neu
+								break;
+							
+							// looks like HEADERS_RECEIVED (state 2) is not reported in Opera (or it's old versions) - neu
+							case 2: // XMLHttpRequest.HEADERS_RECEIVED
+								break;
+								
+							case 3: // XMLHttpRequest.LOADING 
+								// try to fire progress event for not XHR L2
+								var total, loaded;
+								
+								try {
+									if (Url.hasSameOrigin(meta.url)) { // Content-Length not accessible for cross-domain on some browsers
+										total = _xhr.getResponseHeader('Content-Length') || 0; // old Safari throws an exception here
+									}
+
+									if (_xhr.responseText) { // responseText was introduced in IE7
+										loaded = _xhr.responseText.length;
+									}
+								} catch(ex) {
+									total = loaded = 0;
+								}
+
+								target.trigger({
+									type: 'progress',
+									lengthComputable: !!total,
+									total: parseInt(total, 10),
+									loaded: loaded
+								});
+								break;
+								
+							case 4: // XMLHttpRequest.DONE
+								// release readystatechange handler (mostly for IE)
+								_xhr.onreadystatechange = function() {};
+
+								// usually status 0 is returned when server is unreachable, but FF also fails to status 0 for 408 timeout
+								if (_xhr.status === 0) {
+									target.trigger('error');
+								} else {
+									target.trigger('load');
+								}							
+								break;
+						}
+					};
+				}
+				
+
+				// set request headers
+				if (!Basic.isEmptyObj(meta.headers)) {
+					Basic.each(meta.headers, function(value, header) {
+						_xhr.setRequestHeader(header, value);
+					});
+				}
+
+				// request response type
+				if ("" !== meta.responseType && 'responseType' in _xhr) {
+					if ('json' === meta.responseType && !Env.can('return_response_type', 'json')) { // we can fake this one
+						_xhr.responseType = 'text';
+					} else {
+						_xhr.responseType = meta.responseType;
+					}
+				}
+
+				// send ...
+				if (!mustSendAsBinary) {
+					_xhr.send(data);
+				} else {
+					if (_xhr.sendAsBinary) { // Gecko
+						_xhr.sendAsBinary(data);
+					} else { // other browsers having support for typed arrays
+						(function() {
+							// mimic Gecko's sendAsBinary
+							var ui8a = new Uint8Array(data.length);
+							for (var i = 0; i < data.length; i++) {
+								ui8a[i] = (data.charCodeAt(i) & 0xff);
+							}
+							_xhr.send(ui8a.buffer);
+						}());
+					}
+				}
+
+				target.trigger('loadstart');
+			},
+
+			getStatus: function() {
+				// according to W3C spec it should return 0 for readyState < 3, but instead it throws an exception
+				try {
+					if (_xhr) {
+						return _xhr.status;
+					}
+				} catch(ex) {}
+				return 0;
+			},
+
+			getResponse: function(responseType) {
+				var I = this.getRuntime();
+
+				try {
+					switch (responseType) {
+						case 'blob':
+							var file = new File(I.uid, _xhr.response);
+							
+							// try to extract file name from content-disposition if possible (might be - not, if CORS for example)	
+							var disposition = _xhr.getResponseHeader('Content-Disposition');
+							if (disposition) {
+								// extract filename from response header if available
+								var match = disposition.match(/filename=([\'\"'])([^\1]+)\1/);
+								if (match) {
+									_filename = match[2];
+								}
+							}
+							file.name = _filename;
+
+							// pre-webkit Opera doesn't set type property on the blob response
+							if (!file.type) {
+								file.type = Mime.getFileMime(_filename);
+							}
+							return file;
+
+						case 'json':
+							if (!Env.can('return_response_type', 'json')) {
+								return _xhr.status === 200 && !!window.JSON ? JSON.parse(_xhr.responseText) : null;
+							}
+							return _xhr.response;
+
+						case 'document':
+							return _getDocument(_xhr);
+
+						default:
+							return _xhr.responseText !== '' ? _xhr.responseText : null; // against the specs, but for consistency across the runtimes
+					}
+				} catch(ex) {
+					return null;
+				}				
+			},
+
+			getAllResponseHeaders: function() {
+				try {
+					return _xhr.getAllResponseHeaders();
+				} catch(ex) {}
+				return '';
+			},
+
+			abort: function() {
+				if (_xhr) {
+					_xhr.abort();
+				}
+			},
+
+			destroy: function() {
+				self = _filename = null;
+			}
+		});
+
+
+		// here we go... ugly fix for ugly bug
+		function _preloadAndSend(meta, data) {
+			var target = this, blob, fr;
+				
+			// get original blob
+			blob = data.getBlob().getSource();
+			
+			// preload blob in memory to be sent as binary string
+			fr = new window.FileReader();
+			fr.onload = function() {
+				// overwrite original blob
+				data.append(data.getBlobName(), new Blob(null, {
+					type: blob.type,
+					data: fr.result
+				}));
+				// invoke send operation again
+				self.send.call(target, meta, data);
+			};
+			fr.readAsBinaryString(blob);
+		}
+
+		
+		function _getNativeXHR() {
+			if (window.XMLHttpRequest && !(Env.browser === 'IE' && Env.version < 8)) { // IE7 has native XHR but it's buggy
+				return new window.XMLHttpRequest();
+			} else {
+				return (function() {
+					var progIDs = ['Msxml2.XMLHTTP.6.0', 'Microsoft.XMLHTTP']; // if 6.0 available, use it, otherwise failback to default 3.0
+					for (var i = 0; i < progIDs.length; i++) {
+						try {
+							return new ActiveXObject(progIDs[i]);
+						} catch (ex) {}
+					}
+				})();
+			}
+		}
+		
+		// @credits Sergey Ilinsky	(http://www.ilinsky.com/)
+		function _getDocument(xhr) {
+			var rXML = xhr.responseXML;
+			var rText = xhr.responseText;
+			
+			// Try parsing responseText (@see: http://www.ilinsky.com/articles/XMLHttpRequest/#bugs-ie-responseXML-content-type)
+			if (Env.browser === 'IE' && rText && rXML && !rXML.documentElement && /[^\/]+\/[^\+]+\+xml/.test(xhr.getResponseHeader("Content-Type"))) {
+				rXML = new window.ActiveXObject("Microsoft.XMLDOM");
+				rXML.async = false;
+				rXML.validateOnParse = false;
+				rXML.loadXML(rText);
+			}
+	
+			// Check if there is no error in document
+			if (rXML) {
+				if ((Env.browser === 'IE' && rXML.parseError !== 0) || !rXML.documentElement || rXML.documentElement.tagName === "parsererror") {
+					return null;
+				}
+			}
+			return rXML;
+		}
+
+
+		function _prepareMultipart(fd) {
+			var boundary = '----moxieboundary' + new Date().getTime()
+			, dashdash = '--'
+			, crlf = '\r\n'
+			, multipart = ''
+			, I = this.getRuntime()
+			;
+
+			if (!I.can('send_binary_string')) {
+				throw new x.RuntimeError(x.RuntimeError.NOT_SUPPORTED_ERR);
+			}
+
+			_xhr.setRequestHeader('Content-Type', 'multipart/form-data; boundary=' + boundary);
+
+			// append multipart parameters
+			fd.each(function(value, name) {
+				// Firefox 3.6 failed to convert multibyte characters to UTF-8 in sendAsBinary(), 
+				// so we try it here ourselves with: unescape(encodeURIComponent(value))
+				if (value instanceof Blob) {
+					// Build RFC2388 blob
+					multipart += dashdash + boundary + crlf +
+						'Content-Disposition: form-data; name="' + name + '"; filename="' + unescape(encodeURIComponent(value.name || 'blob')) + '"' + crlf +
+						'Content-Type: ' + (value.type || 'application/octet-stream') + crlf + crlf +
+						value.getSource() + crlf;
+				} else {
+					multipart += dashdash + boundary + crlf +
+						'Content-Disposition: form-data; name="' + name + '"' + crlf + crlf +
+						unescape(encodeURIComponent(value)) + crlf;
+				}
+			});
+
+			multipart += dashdash + boundary + dashdash + crlf;
+
+			return multipart;
+		}
+	}
+
+	return (extensions.XMLHttpRequest = XMLHttpRequest);
+});
+
+// Included from: src/javascript/runtime/html5/utils/BinaryReader.js
+
+/**
+ * BinaryReader.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+/**
+@class moxie/runtime/html5/utils/BinaryReader
+@private
+*/
+define("moxie/runtime/html5/utils/BinaryReader", [], function() {
+	return function() {
+		var II = false, bin;
+
+		// Private functions
+		function read(idx, size) {
+			var mv = II ? 0 : -8 * (size - 1), sum = 0, i;
+
+			for (i = 0; i < size; i++) {
+				sum |= (bin.charCodeAt(idx + i) << Math.abs(mv + i*8));
+			}
+
+			return sum;
+		}
+
+		function putstr(segment, idx, length) {
+			length = arguments.length === 3 ? length : bin.length - idx - 1;
+			bin = bin.substr(0, idx) + segment + bin.substr(length + idx);
+		}
+
+		function write(idx, num, size) {
+			var str = '', mv = II ? 0 : -8 * (size - 1), i;
+
+			for (i = 0; i < size; i++) {
+				str += String.fromCharCode((num >> Math.abs(mv + i*8)) & 255);
+			}
+
+			putstr(str, idx, size);
+		}
+
+		// Public functions
+		return {
+			II: function(order) {
+				if (order === undefined) {
+					return II;
+				} else {
+					II = order;
+				}
+			},
+
+			init: function(binData) {
+				II = false;
+				bin = binData;
+			},
+
+			SEGMENT: function(idx, length, segment) {
+				switch (arguments.length) {
+					case 1:
+						return bin.substr(idx, bin.length - idx - 1);
+					case 2:
+						return bin.substr(idx, length);
+					case 3:
+						putstr(segment, idx, length);
+						break;
+					default: return bin;
+				}
+			},
+
+			BYTE: function(idx) {
+				return read(idx, 1);
+			},
+
+			SHORT: function(idx) {
+				return read(idx, 2);
+			},
+
+			LONG: function(idx, num) {
+				if (num === undefined) {
+					return read(idx, 4);
+				} else {
+					write(idx, num, 4);
+				}
+			},
+
+			SLONG: function(idx) { // 2's complement notation
+				var num = read(idx, 4);
+
+				return (num > 2147483647 ? num - 4294967296 : num);
+			},
+
+			STRING: function(idx, size) {
+				var str = '';
+
+				for (size += idx; idx < size; idx++) {
+					str += String.fromCharCode(read(idx, 1));
+				}
+
+				return str;
+			}
+		};
+	};
+});
+
+// Included from: src/javascript/runtime/html5/image/JPEGHeaders.js
+
+/**
+ * JPEGHeaders.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+ 
+/**
+@class moxie/runtime/html5/image/JPEGHeaders
+@private
+*/
+define("moxie/runtime/html5/image/JPEGHeaders", [
+	"moxie/runtime/html5/utils/BinaryReader"
+], function(BinaryReader) {
+	
+	return function JPEGHeaders(data) {
+		var headers = [], read, idx, marker, length = 0;
+
+		read = new BinaryReader();
+		read.init(data);
+
+		// Check if data is jpeg
+		if (read.SHORT(0) !== 0xFFD8) {
+			return;
+		}
+
+		idx = 2;
+
+		while (idx <= data.length) {
+			marker = read.SHORT(idx);
+
+			// omit RST (restart) markers
+			if (marker >= 0xFFD0 && marker <= 0xFFD7) {
+				idx += 2;
+				continue;
+			}
+
+			// no headers allowed after SOS marker
+			if (marker === 0xFFDA || marker === 0xFFD9) {
+				break;
+			}
+
+			length = read.SHORT(idx + 2) + 2;
+
+			// APPn marker detected
+			if (marker >= 0xFFE1 && marker <= 0xFFEF) {
+				headers.push({
+					hex: marker,
+					name: 'APP' + (marker & 0x000F),
+					start: idx,
+					length: length,
+					segment: read.SEGMENT(idx, length)
+				});
+			}
+
+			idx += length;
+		}
+
+		read.init(null); // free memory
+
+		return {
+			headers: headers,
+
+			restore: function(data) {
+				var max, i;
+
+				read.init(data);
+
+				idx = read.SHORT(2) == 0xFFE0 ? 4 + read.SHORT(4) : 2;
+
+				for (i = 0, max = headers.length; i < max; i++) {
+					read.SEGMENT(idx, 0, headers[i].segment);
+					idx += headers[i].length;
+				}
+
+				data = read.SEGMENT();
+				read.init(null);
+				return data;
+			},
+
+			strip: function(data) {
+				var headers, jpegHeaders, i;
+
+				jpegHeaders = new JPEGHeaders(data);
+				headers = jpegHeaders.headers;
+				jpegHeaders.purge();
+
+				read.init(data);
+
+				i = headers.length;
+				while (i--) {
+					read.SEGMENT(headers[i].start, headers[i].length, '');
+				}
+				
+				data = read.SEGMENT();
+				read.init(null);
+				return data;
+			},
+
+			get: function(name) {
+				var array = [];
+
+				for (var i = 0, max = headers.length; i < max; i++) {
+					if (headers[i].name === name.toUpperCase()) {
+						array.push(headers[i].segment);
+					}
+				}
+				return array;
+			},
+
+			set: function(name, segment) {
+				var array = [], i, ii, max;
+
+				if (typeof(segment) === 'string') {
+					array.push(segment);
+				} else {
+					array = segment;
+				}
+
+				for (i = ii = 0, max = headers.length; i < max; i++) {
+					if (headers[i].name === name.toUpperCase()) {
+						headers[i].segment = array[ii];
+						headers[i].length = array[ii].length;
+						ii++;
+					}
+					if (ii >= array.length) {
+						break;
+					}
+				}
+			},
+
+			purge: function() {
+				headers = [];
+				read.init(null);
+				read = null;
+			}
+		};
+	};
+});
+
+// Included from: src/javascript/runtime/html5/image/ExifParser.js
+
+/**
+ * ExifParser.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+/**
+@class moxie/runtime/html5/image/ExifParser
+@private
+*/
+define("moxie/runtime/html5/image/ExifParser", [
+	"moxie/core/utils/Basic",
+	"moxie/runtime/html5/utils/BinaryReader"
+], function(Basic, BinaryReader) {
+	
+	return function ExifParser() {
+		// Private ExifParser fields
+		var data, tags, Tiff, offsets = {}, tagDescs;
+
+		data = new BinaryReader();
+
+		tags = {
+			tiff : {
+				/*
+				The image orientation viewed in terms of rows and columns.
+
+				1 = The 0th row is at the visual top of the image, and the 0th column is the visual left-hand side.
+				2 = The 0th row is at the visual top of the image, and the 0th column is the visual right-hand side.
+				3 = The 0th row is at the visual bottom of the image, and the 0th column is the visual right-hand side.
+				4 = The 0th row is at the visual bottom of the image, and the 0th column is the visual left-hand side.
+				5 = The 0th row is the visual left-hand side of the image, and the 0th column is the visual top.
+				6 = The 0th row is the visual right-hand side of the image, and the 0th column is the visual top.
+				7 = The 0th row is the visual right-hand side of the image, and the 0th column is the visual bottom.
+				8 = The 0th row is the visual left-hand side of the image, and the 0th column is the visual bottom.
+				*/
+				0x0112: 'Orientation',
+				0x010E: 'ImageDescription',
+				0x010F: 'Make',
+				0x0110: 'Model',
+				0x0131: 'Software',
+				0x8769: 'ExifIFDPointer',
+				0x8825:	'GPSInfoIFDPointer'
+			},
+			exif : {
+				0x9000: 'ExifVersion',
+				0xA001: 'ColorSpace',
+				0xA002: 'PixelXDimension',
+				0xA003: 'PixelYDimension',
+				0x9003: 'DateTimeOriginal',
+				0x829A: 'ExposureTime',
+				0x829D: 'FNumber',
+				0x8827: 'ISOSpeedRatings',
+				0x9201: 'ShutterSpeedValue',
+				0x9202: 'ApertureValue'	,
+				0x9207: 'MeteringMode',
+				0x9208: 'LightSource',
+				0x9209: 'Flash',
+				0x920A: 'FocalLength',
+				0xA402: 'ExposureMode',
+				0xA403: 'WhiteBalance',
+				0xA406: 'SceneCaptureType',
+				0xA404: 'DigitalZoomRatio',
+				0xA408: 'Contrast',
+				0xA409: 'Saturation',
+				0xA40A: 'Sharpness'
+			},
+			gps : {
+				0x0000: 'GPSVersionID',
+				0x0001: 'GPSLatitudeRef',
+				0x0002: 'GPSLatitude',
+				0x0003: 'GPSLongitudeRef',
+				0x0004: 'GPSLongitude'
+			}
+		};
+
+		tagDescs = {
+			'ColorSpace': {
+				1: 'sRGB',
+				0: 'Uncalibrated'
+			},
+
+			'MeteringMode': {
+				0: 'Unknown',
+				1: 'Average',
+				2: 'CenterWeightedAverage',
+				3: 'Spot',
+				4: 'MultiSpot',
+				5: 'Pattern',
+				6: 'Partial',
+				255: 'Other'
+			},
+
+			'LightSource': {
+				1: 'Daylight',
+				2: 'Fliorescent',
+				3: 'Tungsten',
+				4: 'Flash',
+				9: 'Fine weather',
+				10: 'Cloudy weather',
+				11: 'Shade',
+				12: 'Daylight fluorescent (D 5700 - 7100K)',
+				13: 'Day white fluorescent (N 4600 -5400K)',
+				14: 'Cool white fluorescent (W 3900 - 4500K)',
+				15: 'White fluorescent (WW 3200 - 3700K)',
+				17: 'Standard light A',
+				18: 'Standard light B',
+				19: 'Standard light C',
+				20: 'D55',
+				21: 'D65',
+				22: 'D75',
+				23: 'D50',
+				24: 'ISO studio tungsten',
+				255: 'Other'
+			},
+
+			'Flash': {
+				0x0000: 'Flash did not fire.',
+				0x0001: 'Flash fired.',
+				0x0005: 'Strobe return light not detected.',
+				0x0007: 'Strobe return light detected.',
+				0x0009: 'Flash fired, compulsory flash mode',
+				0x000D: 'Flash fired, compulsory flash mode, return light not detected',
+				0x000F: 'Flash fired, compulsory flash mode, return light detected',
+				0x0010: 'Flash did not fire, compulsory flash mode',
+				0x0018: 'Flash did not fire, auto mode',
+				0x0019: 'Flash fired, auto mode',
+				0x001D: 'Flash fired, auto mode, return light not detected',
+				0x001F: 'Flash fired, auto mode, return light detected',
+				0x0020: 'No flash function',
+				0x0041: 'Flash fired, red-eye reduction mode',
+				0x0045: 'Flash fired, red-eye reduction mode, return light not detected',
+				0x0047: 'Flash fired, red-eye reduction mode, return light detected',
+				0x0049: 'Flash fired, compulsory flash mode, red-eye reduction mode',
+				0x004D: 'Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected',
+				0x004F: 'Flash fired, compulsory flash mode, red-eye reduction mode, return light detected',
+				0x0059: 'Flash fired, auto mode, red-eye reduction mode',
+				0x005D: 'Flash fired, auto mode, return light not detected, red-eye reduction mode',
+				0x005F: 'Flash fired, auto mode, return light detected, red-eye reduction mode'
+			},
+
+			'ExposureMode': {
+				0: 'Auto exposure',
+				1: 'Manual exposure',
+				2: 'Auto bracket'
+			},
+
+			'WhiteBalance': {
+				0: 'Auto white balance',
+				1: 'Manual white balance'
+			},
+
+			'SceneCaptureType': {
+				0: 'Standard',
+				1: 'Landscape',
+				2: 'Portrait',
+				3: 'Night scene'
+			},
+
+			'Contrast': {
+				0: 'Normal',
+				1: 'Soft',
+				2: 'Hard'
+			},
+
+			'Saturation': {
+				0: 'Normal',
+				1: 'Low saturation',
+				2: 'High saturation'
+			},
+
+			'Sharpness': {
+				0: 'Normal',
+				1: 'Soft',
+				2: 'Hard'
+			},
+
+			// GPS related
+			'GPSLatitudeRef': {
+				N: 'North latitude',
+				S: 'South latitude'
+			},
+
+			'GPSLongitudeRef': {
+				E: 'East longitude',
+				W: 'West longitude'
+			}
+		};
+
+		function extractTags(IFD_offset, tags2extract) {
+			var length = data.SHORT(IFD_offset), i, ii,
+				tag, type, count, tagOffset, offset, value, values = [], hash = {};
+
+			for (i = 0; i < length; i++) {
+				// Set binary reader pointer to beginning of the next tag
+				offset = tagOffset = IFD_offset + 12 * i + 2;
+
+				tag = tags2extract[data.SHORT(offset)];
+
+				if (tag === undefined) {
+					continue; // Not the tag we requested
+				}
+
+				type = data.SHORT(offset+=2);
+				count = data.LONG(offset+=2);
+
+				offset += 4;
+				values = [];
+
+				switch (type) {
+					case 1: // BYTE
+					case 7: // UNDEFINED
+						if (count > 4) {
+							offset = data.LONG(offset) + offsets.tiffHeader;
+						}
+
+						for (ii = 0; ii < count; ii++) {
+							values[ii] = data.BYTE(offset + ii);
+						}
+
+						break;
+
+					case 2: // STRING
+						if (count > 4) {
+							offset = data.LONG(offset) + offsets.tiffHeader;
+						}
+
+						hash[tag] = data.STRING(offset, count - 1);
+
+						continue;
+
+					case 3: // SHORT
+						if (count > 2) {
+							offset = data.LONG(offset) + offsets.tiffHeader;
+						}
+
+						for (ii = 0; ii < count; ii++) {
+							values[ii] = data.SHORT(offset + ii*2);
+						}
+
+						break;
+
+					case 4: // LONG
+						if (count > 1) {
+							offset = data.LONG(offset) + offsets.tiffHeader;
+						}
+
+						for (ii = 0; ii < count; ii++) {
+							values[ii] = data.LONG(offset + ii*4);
+						}
+
+						break;
+
+					case 5: // RATIONAL
+						offset = data.LONG(offset) + offsets.tiffHeader;
+
+						for (ii = 0; ii < count; ii++) {
+							values[ii] = data.LONG(offset + ii*4) / data.LONG(offset + ii*4 + 4);
+						}
+
+						break;
+
+					case 9: // SLONG
+						offset = data.LONG(offset) + offsets.tiffHeader;
+
+						for (ii = 0; ii < count; ii++) {
+							values[ii] = data.SLONG(offset + ii*4);
+						}
+
+						break;
+
+					case 10: // SRATIONAL
+						offset = data.LONG(offset) + offsets.tiffHeader;
+
+						for (ii = 0; ii < count; ii++) {
+							values[ii] = data.SLONG(offset + ii*4) / data.SLONG(offset + ii*4 + 4);
+						}
+
+						break;
+
+					default:
+						continue;
+				}
+
+				value = (count == 1 ? values[0] : values);
+
+				if (tagDescs.hasOwnProperty(tag) && typeof value != 'object') {
+					hash[tag] = tagDescs[tag][value];
+				} else {
+					hash[tag] = value;
+				}
+			}
+
+			return hash;
+		}
+
+		function getIFDOffsets() {
+			var idx = offsets.tiffHeader;
+
+			// Set read order of multi-byte data
+			data.II(data.SHORT(idx) == 0x4949);
+
+			// Check if always present bytes are indeed present
+			if (data.SHORT(idx+=2) !== 0x002A) {
+				return false;
+			}
+
+			offsets.IFD0 = offsets.tiffHeader + data.LONG(idx += 2);
+			Tiff = extractTags(offsets.IFD0, tags.tiff);
+
+			if ('ExifIFDPointer' in Tiff) {
+				offsets.exifIFD = offsets.tiffHeader + Tiff.ExifIFDPointer;
+				delete Tiff.ExifIFDPointer;
+			}
+
+			if ('GPSInfoIFDPointer' in Tiff) {
+				offsets.gpsIFD = offsets.tiffHeader + Tiff.GPSInfoIFDPointer;
+				delete Tiff.GPSInfoIFDPointer;
+			}
+			return true;
+		}
+
+		// At the moment only setting of simple (LONG) values, that do not require offset recalculation, is supported
+		function setTag(ifd, tag, value) {
+			var offset, length, tagOffset, valueOffset = 0;
+
+			// If tag name passed translate into hex key
+			if (typeof(tag) === 'string') {
+				var tmpTags = tags[ifd.toLowerCase()];
+				for (var hex in tmpTags) {
+					if (tmpTags[hex] === tag) {
+						tag = hex;
+						break;
+					}
+				}
+			}
+			offset = offsets[ifd.toLowerCase() + 'IFD'];
+			length = data.SHORT(offset);
+
+			for (var i = 0; i < length; i++) {
+				tagOffset = offset + 12 * i + 2;
+
+				if (data.SHORT(tagOffset) == tag) {
+					valueOffset = tagOffset + 8;
+					break;
+				}
+			}
+
+			if (!valueOffset) {
+				return false;
+			}
+
+			data.LONG(valueOffset, value);
+			return true;
+		}
+
+
+		// Public functions
+		return {
+			init: function(segment) {
+				// Reset internal data
+				offsets = {
+					tiffHeader: 10
+				};
+
+				if (segment === undefined || !segment.length) {
+					return false;
+				}
+
+				data.init(segment);
+
+				// Check if that's APP1 and that it has EXIF
+				if (data.SHORT(0) === 0xFFE1 && data.STRING(4, 5).toUpperCase() === "EXIF\0") {
+					return getIFDOffsets();
+				}
+				return false;
+			},
+
+			TIFF: function() {
+				return Tiff;
+			},
+
+			EXIF: function() {
+				var Exif;
+
+				// Populate EXIF hash
+				Exif = extractTags(offsets.exifIFD, tags.exif);
+
+				// Fix formatting of some tags
+				if (Exif.ExifVersion && Basic.typeOf(Exif.ExifVersion) === 'array') {
+					for (var i = 0, exifVersion = ''; i < Exif.ExifVersion.length; i++) {
+						exifVersion += String.fromCharCode(Exif.ExifVersion[i]);
+					}
+					Exif.ExifVersion = exifVersion;
+				}
+
+				return Exif;
+			},
+
+			GPS: function() {
+				var GPS;
+
+				GPS = extractTags(offsets.gpsIFD, tags.gps);
+
+				// iOS devices (and probably some others) do not put in GPSVersionID tag (why?..)
+				if (GPS.GPSVersionID && Basic.typeOf(GPS.GPSVersionID) === 'array') {
+					GPS.GPSVersionID = GPS.GPSVersionID.join('.');
+				}
+
+				return GPS;
+			},
+
+			setExif: function(tag, value) {
+				// Right now only setting of width/height is possible
+				if (tag !== 'PixelXDimension' && tag !== 'PixelYDimension') {return false;}
+
+				return setTag('exif', tag, value);
+			},
+
+
+			getBinary: function() {
+				return data.SEGMENT();
+			},
+
+			purge: function() {
+				data.init(null);
+				data = Tiff = null;
+				offsets = {};
+			}
+		};
+	};
+});
+
+// Included from: src/javascript/runtime/html5/image/JPEG.js
+
+/**
+ * JPEG.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+/**
+@class moxie/runtime/html5/image/JPEG
+@private
+*/
+define("moxie/runtime/html5/image/JPEG", [
+	"moxie/core/utils/Basic",
+	"moxie/core/Exceptions",
+	"moxie/runtime/html5/image/JPEGHeaders",
+	"moxie/runtime/html5/utils/BinaryReader",
+	"moxie/runtime/html5/image/ExifParser"
+], function(Basic, x, JPEGHeaders, BinaryReader, ExifParser) {
+	
+	function JPEG(binstr) {
+		var _binstr, _br, _hm, _ep, _info, hasExif;
+
+		function _getDimensions() {
+			var idx = 0, marker, length;
+
+			// examine all through the end, since some images might have very large APP segments
+			while (idx <= _binstr.length) {
+				marker = _br.SHORT(idx += 2);
+
+				if (marker >= 0xFFC0 && marker <= 0xFFC3) { // SOFn
+					idx += 5; // marker (2 bytes) + length (2 bytes) + Sample precision (1 byte)
+					return {
+						height: _br.SHORT(idx),
+						width: _br.SHORT(idx += 2)
+					};
+				}
+				length = _br.SHORT(idx += 2);
+				idx += length - 2;
+			}
+			return null;
+		}
+
+		_binstr = binstr;
+
+		_br = new BinaryReader();
+		_br.init(_binstr);
+
+		// check if it is jpeg
+		if (_br.SHORT(0) !== 0xFFD8) {
+			throw new x.ImageError(x.ImageError.WRONG_FORMAT);
+		}
+
+		// backup headers
+		_hm = new JPEGHeaders(binstr);
+
+		// extract exif info
+		_ep = new ExifParser();
+		hasExif = !!_ep.init(_hm.get('app1')[0]);
+
+		// get dimensions
+		_info = _getDimensions.call(this);
+
+		Basic.extend(this, {
+			type: 'image/jpeg',
+
+			size: _binstr.length,
+
+			width: _info && _info.width || 0,
+
+			height: _info && _info.height || 0,
+
+			setExif: function(tag, value) {
+				if (!hasExif) {
+					return false; // or throw an exception
+				}
+
+				if (Basic.typeOf(tag) === 'object') {
+					Basic.each(tag, function(value, tag) {
+						_ep.setExif(tag, value);
+					});
+				} else {
+					_ep.setExif(tag, value);
+				}
+
+				// update internal headers
+				_hm.set('app1', _ep.getBinary());
+			},
+
+			writeHeaders: function() {
+				if (!arguments.length) {
+					// if no arguments passed, update headers internally
+					return (_binstr = _hm.restore(_binstr));
+				}
+				return _hm.restore(arguments[0]);
+			},
+
+			stripHeaders: function(binstr) {
+				return _hm.strip(binstr);
+			},
+
+			purge: function() {
+				_purge.call(this);
+			}
+		});
+
+		if (hasExif) {
+			this.meta = {
+				tiff: _ep.TIFF(),
+				exif: _ep.EXIF(),
+				gps: _ep.GPS()
+			};
+		}
+
+		function _purge() {
+			if (!_ep || !_hm || !_br) { 
+				return; // ignore any repeating purge requests
+			}
+			_ep.purge();
+			_hm.purge();
+			_br.init(null);
+			_binstr = _info = _hm = _ep = _br = null;
+		}
+	}
+
+	return JPEG;
+});
+
+// Included from: src/javascript/runtime/html5/image/PNG.js
+
+/**
+ * PNG.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+/**
+@class moxie/runtime/html5/image/PNG
+@private
+*/
+define("moxie/runtime/html5/image/PNG", [
+	"moxie/core/Exceptions",
+	"moxie/core/utils/Basic",
+	"moxie/runtime/html5/utils/BinaryReader"
+], function(x, Basic, BinaryReader) {
+	
+	function PNG(binstr) {
+		var _binstr, _br, _hm, _ep, _info;
+
+		_binstr = binstr;
+
+		_br = new BinaryReader();
+		_br.init(_binstr);
+
+		// check if it's png
+		(function() {
+			var idx = 0, i = 0
+			, signature = [0x8950, 0x4E47, 0x0D0A, 0x1A0A]
+			;
+
+			for (i = 0; i < signature.length; i++, idx += 2) {
+				if (signature[i] != _br.SHORT(idx)) {
+					throw new x.ImageError(x.ImageError.WRONG_FORMAT);
+				}
+			}
+		}());
+
+		function _getDimensions() {
+			var chunk, idx;
+
+			chunk = _getChunkAt.call(this, 8);
+
+			if (chunk.type == 'IHDR') {
+				idx = chunk.start;
+				return {
+					width: _br.LONG(idx),
+					height: _br.LONG(idx += 4)
+				};
+			}
+			return null;
+		}
+
+		function _purge() {
+			if (!_br) {
+				return; // ignore any repeating purge requests
+			}
+			_br.init(null);
+			_binstr = _info = _hm = _ep = _br = null;
+		}
+
+		_info = _getDimensions.call(this);
+
+		Basic.extend(this, {
+			type: 'image/png',
+
+			size: _binstr.length,
+
+			width: _info.width,
+
+			height: _info.height,
+
+			purge: function() {
+				_purge.call(this);
+			}
+		});
+
+		// for PNG we can safely trigger purge automatically, as we do not keep any data for later
+		_purge.call(this);
+
+		function _getChunkAt(idx) {
+			var length, type, start, CRC;
+
+			length = _br.LONG(idx);
+			type = _br.STRING(idx += 4, 4);
+			start = idx += 4;
+			CRC = _br.LONG(idx + length);
+
+			return {
+				length: length,
+				type: type,
+				start: start,
+				CRC: CRC
+			};
+		}
+	}
+
+	return PNG;
+});
+
+// Included from: src/javascript/runtime/html5/image/ImageInfo.js
+
+/**
+ * ImageInfo.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+/**
+@class moxie/runtime/html5/image/ImageInfo
+@private
+*/
+define("moxie/runtime/html5/image/ImageInfo", [
+	"moxie/core/utils/Basic",
+	"moxie/core/Exceptions",
+	"moxie/runtime/html5/image/JPEG",
+	"moxie/runtime/html5/image/PNG"
+], function(Basic, x, JPEG, PNG) {
+	/**
+	Optional image investigation tool for HTML5 runtime. Provides the following features:
+	- ability to distinguish image type (JPEG or PNG) by signature
+	- ability to extract image width/height directly from it's internals, without preloading in memory (fast)
+	- ability to extract APP headers from JPEGs (Exif, GPS, etc)
+	- ability to replace width/height tags in extracted JPEG headers
+	- ability to restore APP headers, that were for example stripped during image manipulation
+
+	@class ImageInfo
+	@constructor
+	@param {String} binstr Image source as binary string
+	*/
+	return function(binstr) {
+		var _cs = [JPEG, PNG], _img;
+
+		// figure out the format, throw: ImageError.WRONG_FORMAT if not supported
+		_img = (function() {
+			for (var i = 0; i < _cs.length; i++) {
+				try {
+					return new _cs[i](binstr);
+				} catch (ex) {
+					// console.info(ex);
+				}
+			}
+			throw new x.ImageError(x.ImageError.WRONG_FORMAT);
+		}());
+
+		Basic.extend(this, {
+			/**
+			Image Mime Type extracted from it's depths
+
+			@property type
+			@type {String}
+			@default ''
+			*/
+			type: '',
+
+			/**
+			Image size in bytes
+
+			@property size
+			@type {Number}
+			@default 0
+			*/
+			size: 0,
+
+			/**
+			Image width extracted from image source
+
+			@property width
+			@type {Number}
+			@default 0
+			*/
+			width: 0,
+
+			/**
+			Image height extracted from image source
+
+			@property height
+			@type {Number}
+			@default 0
+			*/
+			height: 0,
+
+			/**
+			Sets Exif tag. Currently applicable only for width and height tags. Obviously works only with JPEGs.
+
+			@method setExif
+			@param {String} tag Tag to set
+			@param {Mixed} value Value to assign to the tag
+			*/
+			setExif: function() {},
+
+			/**
+			Restores headers to the source.
+
+			@method writeHeaders
+			@param {String} data Image source as binary string
+			@return {String} Updated binary string
+			*/
+			writeHeaders: function(data) {
+				return data;
+			},
+
+			/**
+			Strip all headers from the source.
+
+			@method stripHeaders
+			@param {String} data Image source as binary string
+			@return {String} Updated binary string
+			*/
+			stripHeaders: function(data) {
+				return data;
+			},
+
+			/**
+			Dispose resources.
+
+			@method purge
+			*/
+			purge: function() {}
+		});
+
+		Basic.extend(this, _img);
+
+		this.purge = function() {
+			_img.purge();
+			_img = null;
+		};
+	};
+});
+
+// Included from: src/javascript/runtime/html5/image/MegaPixel.js
+
+/**
+(The MIT License)
+
+Copyright (c) 2012 Shinichi Tomita <shinichi.tomita@gmail.com>;
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+'Software'), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+/**
+ * Mega pixel image rendering library for iOS6 Safari
+ *
+ * Fixes iOS6 Safari's image file rendering issue for large size image (over mega-pixel),
+ * which causes unexpected subsampling when drawing it in canvas.
+ * By using this library, you can safely render the image with proper stretching.
+ *
+ * Copyright (c) 2012 Shinichi Tomita <shinichi.tomita@gmail.com>
+ * Released under the MIT license
+ */
+
+/**
+@class moxie/runtime/html5/image/MegaPixel
+@private
+*/
+define("moxie/runtime/html5/image/MegaPixel", [], function() {
+
+	/**
+	 * Rendering image element (with resizing) into the canvas element
+	 */
+	function renderImageToCanvas(img, canvas, options) {
+		var iw = img.naturalWidth, ih = img.naturalHeight;
+		var width = options.width, height = options.height;
+		var x = options.x || 0, y = options.y || 0;
+		var ctx = canvas.getContext('2d');
+		if (detectSubsampling(img)) {
+			iw /= 2;
+			ih /= 2;
+		}
+		var d = 1024; // size of tiling canvas
+		var tmpCanvas = document.createElement('canvas');
+		tmpCanvas.width = tmpCanvas.height = d;
+		var tmpCtx = tmpCanvas.getContext('2d');
+		var vertSquashRatio = detectVerticalSquash(img, iw, ih);
+		var sy = 0;
+		while (sy < ih) {
+			var sh = sy + d > ih ? ih - sy : d;
+			var sx = 0;
+			while (sx < iw) {
+				var sw = sx + d > iw ? iw - sx : d;
+				tmpCtx.clearRect(0, 0, d, d);
+				tmpCtx.drawImage(img, -sx, -sy);
+				var dx = (sx * width / iw + x) << 0;
+				var dw = Math.ceil(sw * width / iw);
+				var dy = (sy * height / ih / vertSquashRatio + y) << 0;
+				var dh = Math.ceil(sh * height / ih / vertSquashRatio);
+				ctx.drawImage(tmpCanvas, 0, 0, sw, sh, dx, dy, dw, dh);
+				sx += d;
+			}
+			sy += d;
+		}
+		tmpCanvas = tmpCtx = null;
+	}
+
+	/**
+	 * Detect subsampling in loaded image.
+	 * In iOS, larger images than 2M pixels may be subsampled in rendering.
+	 */
+	function detectSubsampling(img) {
+		var iw = img.naturalWidth, ih = img.naturalHeight;
+		if (iw * ih > 1024 * 1024) { // subsampling may happen over megapixel image
+			var canvas = document.createElement('canvas');
+			canvas.width = canvas.height = 1;
+			var ctx = canvas.getContext('2d');
+			ctx.drawImage(img, -iw + 1, 0);
+			// subsampled image becomes half smaller in rendering size.
+			// check alpha channel value to confirm image is covering edge pixel or not.
+			// if alpha value is 0 image is not covering, hence subsampled.
+			return ctx.getImageData(0, 0, 1, 1).data[3] === 0;
+		} else {
+			return false;
+		}
+	}
+
+
+	/**
+	 * Detecting vertical squash in loaded image.
+	 * Fixes a bug which squash image vertically while drawing into canvas for some images.
+	 */
+	function detectVerticalSquash(img, iw, ih) {
+		var canvas = document.createElement('canvas');
+		canvas.width = 1;
+		canvas.height = ih;
+		var ctx = canvas.getContext('2d');
+		ctx.drawImage(img, 0, 0);
+		var data = ctx.getImageData(0, 0, 1, ih).data;
+		// search image edge pixel position in case it is squashed vertically.
+		var sy = 0;
+		var ey = ih;
+		var py = ih;
+		while (py > sy) {
+			var alpha = data[(py - 1) * 4 + 3];
+			if (alpha === 0) {
+				ey = py;
+			} else {
+			sy = py;
+			}
+			py = (ey + sy) >> 1;
+		}
+		canvas = null;
+		var ratio = (py / ih);
+		return (ratio === 0) ? 1 : ratio;
+	}
+
+	return {
+		isSubsampled: detectSubsampling,
+		renderTo: renderImageToCanvas
+	};
+});
+
+// Included from: src/javascript/runtime/html5/image/Image.js
+
+/**
+ * Image.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+/**
+@class moxie/runtime/html5/image/Image
+@private
+*/
+define("moxie/runtime/html5/image/Image", [
+	"moxie/runtime/html5/Runtime",
+	"moxie/core/utils/Basic",
+	"moxie/core/Exceptions",
+	"moxie/core/utils/Encode",
+	"moxie/file/File",
+	"moxie/runtime/html5/image/ImageInfo",
+	"moxie/runtime/html5/image/MegaPixel",
+	"moxie/core/utils/Mime",
+	"moxie/core/utils/Env"
+], function(extensions, Basic, x, Encode, File, ImageInfo, MegaPixel, Mime, Env) {
+	
+	function HTML5Image() {
+		var me = this
+		, _img, _imgInfo, _canvas, _binStr, _blob
+		, _modified = false // is set true whenever image is modified
+		, _preserveHeaders = true
+		;
+
+		Basic.extend(this, {
+			loadFromBlob: function(blob) {
+				var comp = this, I = comp.getRuntime()
+				, asBinary = arguments.length > 1 ? arguments[1] : true
+				;
+
+				if (!I.can('access_binary')) {
+					throw new x.RuntimeError(x.RuntimeError.NOT_SUPPORTED_ERR);
+				}
+
+				_blob = blob;
+
+				if (blob.isDetached()) {
+					_binStr = blob.getSource();
+					_preload.call(this, _binStr);
+					return;
+				} else {
+					_readAsDataUrl.call(this, blob.getSource(), function(dataUrl) {
+						if (asBinary) {
+							_binStr = _toBinary(dataUrl);
+						}
+						_preload.call(comp, dataUrl);
+					});
+				}
+			},
+
+			loadFromImage: function(img, exact) {
+				this.meta = img.meta;
+
+				_blob = new File(null, {
+					name: img.name,
+					size: img.size,
+					type: img.type
+				});
+
+				_preload.call(this, exact ? (_binStr = img.getAsBinaryString()) : img.getAsDataURL());
+			},
+
+			getInfo: function() {
+				var I = this.getRuntime(), info;
+
+				if (!_imgInfo && _binStr && I.can('access_image_binary')) {
+					_imgInfo = new ImageInfo(_binStr);
+				}
+
+				info = {
+					width: _getImg().width || 0,
+					height: _getImg().height || 0,
+					type: _blob.type || Mime.getFileMime(_blob.name),
+					size: _binStr && _binStr.length || _blob.size || 0,
+					name: _blob.name || '',
+					meta: _imgInfo && _imgInfo.meta || this.meta || {}
+				};
+
+				return info;
+			},
+
+			downsize: function() {
+				_downsize.apply(this, arguments);
+			},
+
+			getAsCanvas: function() {
+				if (_canvas) {
+					_canvas.id = this.uid + '_canvas';
+				}
+				return _canvas;
+			},
+
+			getAsBlob: function(type, quality) {
+				if (type !== this.type) {
+					// if different mime type requested prepare image for conversion
+					_downsize.call(this, this.width, this.height, false);
+				}
+				return new File(null, {
+					name: _blob.name || '',
+					type: type,
+					data: me.getAsBinaryString.call(this, type, quality)
+				});
+			},
+
+			getAsDataURL: function(type) {
+				var quality = arguments[1] || 90;
+
+				// if image has not been modified, return the source right away
+				if (!_modified) {
+					return _img.src;
+				}
+
+				if ('image/jpeg' !== type) {
+					return _canvas.toDataURL('image/png');
+				} else {
+					try {
+						// older Geckos used to result in an exception on quality argument
+						return _canvas.toDataURL('image/jpeg', quality/100);
+					} catch (ex) {
+						return _canvas.toDataURL('image/jpeg');
+					}
+				}
+			},
+
+			getAsBinaryString: function(type, quality) {
+				// if image has not been modified, return the source right away
+				if (!_modified) {
+					// if image was not loaded from binary string
+					if (!_binStr) {
+						_binStr = _toBinary(me.getAsDataURL(type, quality));
+					}
+					return _binStr;
+				}
+
+				if ('image/jpeg' !== type) {
+					_binStr = _toBinary(me.getAsDataURL(type, quality));
+				} else {
+					var dataUrl;
+
+					// if jpeg
+					if (!quality) {
+						quality = 90;
+					}
+
+					try {
+						// older Geckos used to result in an exception on quality argument
+						dataUrl = _canvas.toDataURL('image/jpeg', quality/100);
+					} catch (ex) {
+						dataUrl = _canvas.toDataURL('image/jpeg');
+					}
+
+					_binStr = _toBinary(dataUrl);
+
+					if (_imgInfo) {
+						_binStr = _imgInfo.stripHeaders(_binStr);
+
+						if (_preserveHeaders) {
+							// update dimensions info in exif
+							if (_imgInfo.meta && _imgInfo.meta.exif) {
+								_imgInfo.setExif({
+									PixelXDimension: this.width,
+									PixelYDimension: this.height
+								});
+							}
+
+							// re-inject the headers
+							_binStr = _imgInfo.writeHeaders(_binStr);
+						}
+
+						// will be re-created from fresh on next getInfo call
+						_imgInfo.purge();
+						_imgInfo = null;
+					}
+				}
+
+				_modified = false;
+
+				return _binStr;
+			},
+
+			destroy: function() {
+				me = null;
+				_purge.call(this);
+				this.getRuntime().getShim().removeInstance(this.uid);
+			}
+		});
+
+
+		function _getImg() {
+			if (!_canvas && !_img) {
+				throw new x.ImageError(x.DOMException.INVALID_STATE_ERR);
+			}
+			return _canvas || _img;
+		}
+
+
+		function _toBinary(str) {
+			return Encode.atob(str.substring(str.indexOf('base64,') + 7));
+		}
+
+
+		function _toDataUrl(str, type) {
+			return 'data:' + (type || '') + ';base64,' + Encode.btoa(str);
+		}
+
+
+		function _preload(str) {
+			var comp = this;
+
+			_img = new Image();
+			_img.onerror = function() {
+				_purge.call(this);
+				comp.trigger('error', x.ImageError.WRONG_FORMAT);
+			};
+			_img.onload = function() {
+				comp.trigger('load');
+			};
+
+			_img.src = /^data:[^;]*;base64,/.test(str) ? str : _toDataUrl(str, _blob.type);
+		}
+
+
+		function _readAsDataUrl(file, callback) {
+			var comp = this, fr;
+
+			// use FileReader if it's available
+			if (window.FileReader) {
+				fr = new FileReader();
+				fr.onload = function() {
+					callback(this.result);
+				};
+				fr.onerror = function() {
+					comp.trigger('error', x.ImageError.WRONG_FORMAT);
+				};
+				fr.readAsDataURL(file);
+			} else {
+				return callback(file.getAsDataURL());
+			}
+		}
+
+		function _downsize(width, height, crop, preserveHeaders) {
+			var self = this
+			, scale
+			, mathFn
+			, x = 0
+			, y = 0
+			, img
+			, destWidth
+			, destHeight
+			, orientation
+			;
+
+			_preserveHeaders = preserveHeaders; // we will need to check this on export (see getAsBinaryString())
+
+			// take into account orientation tag
+			orientation = (this.meta && this.meta.tiff && this.meta.tiff.Orientation) || 1;
+
+			if (Basic.inArray(orientation, [5,6,7,8]) !== -1) { // values that require 90 degree rotation
+				// swap dimensions
+				var tmp = width;
+				width = height;
+				height = tmp;
+			}
+
+			img = _getImg();
+
+			// unify dimensions
+			if (!crop) {
+				scale = Math.min(width/img.width, height/img.height);
+			} else {
+				// one of the dimensions may exceed the actual image dimensions - we need to take the smallest value
+				width = Math.min(width, img.width);
+				height = Math.min(height, img.height);
+
+				scale = Math.max(width/img.width, height/img.height);
+			}
+		
+			// we only downsize here
+			if (scale > 1 && !crop && preserveHeaders) {
+				this.trigger('Resize');
+				return;
+			}
+
+			// prepare canvas if necessary
+			if (!_canvas) {
+				_canvas = document.createElement("canvas");
+			}
+
+			// calculate dimensions of proportionally resized image
+			destWidth = Math.round(img.width * scale);	
+			destHeight = Math.round(img.height * scale);
+
+			// scale image and canvas
+			if (crop) {
+				_canvas.width = width;
+				_canvas.height = height;
+
+				// if dimensions of the resulting image still larger than canvas, center it
+				if (destWidth > width) {
+					x = Math.round((destWidth - width) / 2);
+				}
+
+				if (destHeight > height) {
+					y = Math.round((destHeight - height) / 2);
+				}
+			} else {
+				_canvas.width = destWidth;
+				_canvas.height = destHeight;
+			}
+
+			// rotate if required, according to orientation tag
+			if (!_preserveHeaders) {
+				_rotateToOrientaion(_canvas.width, _canvas.height, orientation);
+			}
+
+			_drawToCanvas.call(this, img, _canvas, -x, -y, destWidth, destHeight);
+
+			this.width = _canvas.width;
+			this.height = _canvas.height;
+
+			_modified = true;
+			self.trigger('Resize');
+		}
+
+
+		function _drawToCanvas(img, canvas, x, y, w, h) {
+			if (Env.OS === 'iOS') { 
+				// avoid squish bug in iOS6
+				MegaPixel.renderTo(img, canvas, { width: w, height: h, x: x, y: y });
+			} else {
+				var ctx = canvas.getContext('2d');
+				ctx.drawImage(img, x, y, w, h);
+			}
+		}
+
+
+		/**
+		* Transform canvas coordination according to specified frame size and orientation
+		* Orientation value is from EXIF tag
+		* @author Shinichi Tomita <shinichi.tomita@gmail.com>
+		*/
+		function _rotateToOrientaion(width, height, orientation) {
+			switch (orientation) {
+				case 5:
+				case 6:
+				case 7:
+				case 8:
+					_canvas.width = height;
+					_canvas.height = width;
+					break;
+				default:
+					_canvas.width = width;
+					_canvas.height = height;
+			}
+
+			/**
+			1 = The 0th row is at the visual top of the image, and the 0th column is the visual left-hand side.
+			2 = The 0th row is at the visual top of the image, and the 0th column is the visual right-hand side.
+			3 = The 0th row is at the visual bottom of the image, and the 0th column is the visual right-hand side.
+			4 = The 0th row is at the visual bottom of the image, and the 0th column is the visual left-hand side.
+			5 = The 0th row is the visual left-hand side of the image, and the 0th column is the visual top.
+			6 = The 0th row is the visual right-hand side of the image, and the 0th column is the visual top.
+			7 = The 0th row is the visual right-hand side of the image, and the 0th column is the visual bottom.
+			8 = The 0th row is the visual left-hand side of the image, and the 0th column is the visual bottom.
+			*/
+
+			var ctx = _canvas.getContext('2d');
+			switch (orientation) {
+				case 2:
+					// horizontal flip
+					ctx.translate(width, 0);
+					ctx.scale(-1, 1);
+					break;
+				case 3:
+					// 180 rotate left
+					ctx.translate(width, height);
+					ctx.rotate(Math.PI);
+					break;
+				case 4:
+					// vertical flip
+					ctx.translate(0, height);
+					ctx.scale(1, -1);
+					break;
+				case 5:
+					// vertical flip + 90 rotate right
+					ctx.rotate(0.5 * Math.PI);
+					ctx.scale(1, -1);
+					break;
+				case 6:
+					// 90 rotate right
+					ctx.rotate(0.5 * Math.PI);
+					ctx.translate(0, -height);
+					break;
+				case 7:
+					// horizontal flip + 90 rotate right
+					ctx.rotate(0.5 * Math.PI);
+					ctx.translate(width, -height);
+					ctx.scale(-1, 1);
+					break;
+				case 8:
+					// 90 rotate left
+					ctx.rotate(-0.5 * Math.PI);
+					ctx.translate(-width, 0);
+					break;
+			}
+		}
+
+
+		function _purge() {
+			if (_imgInfo) {
+				_imgInfo.purge();
+				_imgInfo = null;
+			}
+			_binStr = _img = _canvas = _blob = null;
+			_modified = false;
+		}
+	}
+
+	return (extensions.Image = HTML5Image);
+});
+
+// Included from: src/javascript/runtime/flash/Runtime.js
+
+/**
+ * Runtime.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+/*global ActiveXObject:true */
+
+/**
+Defines constructor for Flash runtime.
+
+@class moxie/runtime/flash/Runtime
+@private
+*/
+define("moxie/runtime/flash/Runtime", [
+	"moxie/core/utils/Basic",
+	"moxie/core/utils/Env",
+	"moxie/core/utils/Dom",
+	"moxie/core/Exceptions",
+	"moxie/runtime/Runtime"
+], function(Basic, Env, Dom, x, Runtime) {
+	
+	var type = 'flash', extensions = {};
+
+	/**
+	Get the version of the Flash Player
+
+	@method getShimVersion
+	@private
+	@return {Number} Flash Player version
+	*/
+	function getShimVersion() {
+		var version;
+
+		try {
+			version = navigator.plugins['Shockwave Flash'];
+			version = version.description;
+		} catch (e1) {
+			try {
+				version = new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version');
+			} catch (e2) {
+				version = '0.0';
+			}
+		}
+		version = version.match(/\d+/g);
+		return parseFloat(version[0] + '.' + version[1]);
+	}
+
+	/**
+	Constructor for the Flash Runtime
+
+	@class FlashRuntime
+	@extends Runtime
+	*/
+	function FlashRuntime(options) {
+		var I = this, initTimer;
+
+		options = Basic.extend({ swf_url: Env.swf_url }, options);
+
+		Runtime.call(this, options, type, {
+			access_binary: function(value) {
+				return value && I.mode === 'browser';
+			},
+			access_image_binary: function(value) {
+				return value && I.mode === 'browser';
+			},
+			display_media: Runtime.capTrue,
+			do_cors: Runtime.capTrue,
+			drag_and_drop: false,
+			report_upload_progress: function() {
+				return I.mode === 'client';
+			},
+			resize_image: Runtime.capTrue,
+			return_response_headers: false,
+			return_response_type: function(responseType) {
+				if (responseType === 'json' && !!window.JSON) {
+					return true;
+				} 
+				return !Basic.arrayDiff(responseType, ['', 'text', 'document']) || I.mode === 'browser';
+			},
+			return_status_code: function(code) {
+				return I.mode === 'browser' || !Basic.arrayDiff(code, [200, 404]);
+			},
+			select_file: Runtime.capTrue,
+			select_multiple: Runtime.capTrue,
+			send_binary_string: function(value) {
+				return value && I.mode === 'browser';
+			},
+			send_browser_cookies: function(value) {
+				return value && I.mode === 'browser';
+			},
+			send_custom_headers: function(value) {
+				return value && I.mode === 'browser';
+			},
+			send_multipart: Runtime.capTrue,
+			slice_blob: function(value) {
+				return value && I.mode === 'browser';
+			},
+			stream_upload: function(value) {
+				return value && I.mode === 'browser';
+			},
+			summon_file_dialog: false,
+			upload_filesize: function(size) {
+				return Basic.parseSizeStr(size) <= 2097152 || I.mode === 'client';
+			},
+			use_http_method: function(methods) {
+				return !Basic.arrayDiff(methods, ['GET', 'POST']);
+			}
+		}, { 
+			// capabilities that require specific mode
+			access_binary: function(value) {
+				return value ? 'browser' : 'client';
+			},
+			access_image_binary: function(value) {
+				return value ? 'browser' : 'client';
+			},
+			report_upload_progress: function(value) {
+				return value ? 'browser' : 'client';
+			},
+			return_response_type: function(responseType) {
+				return Basic.arrayDiff(responseType, ['', 'text', 'json', 'document']) ? 'browser' : ['client', 'browser'];
+			},
+			return_status_code: function(code) {
+				return Basic.arrayDiff(code, [200, 404]) ? 'browser' : ['client', 'browser'];
+			},
+			send_binary_string: function(value) {
+				return value ? 'browser' : 'client';
+			},
+			send_browser_cookies: function(value) {
+				return value ? 'browser' : 'client';
+			},
+			send_custom_headers: function(value) {
+				return value ? 'browser' : 'client';
+			},
+			stream_upload: function(value) {
+				return value ? 'client' : 'browser';
+			},
+			upload_filesize: function(size) {
+				return Basic.parseSizeStr(size) >= 2097152 ? 'client' : 'browser';
+			}
+		}, 'client');
+
+
+		// minimal requirement for Flash Player version
+		if (getShimVersion() < 10) {
+			this.mode = false; // with falsy mode, runtime won't operable, no matter what the mode was before
+		}
+
+
+		Basic.extend(this, {
+
+			getShim: function() {
+				return Dom.get(this.uid);
+			},
+
+			shimExec: function(component, action) {
+				var args = [].slice.call(arguments, 2);
+				return I.getShim().exec(this.uid, component, action, args);
+			},
+
+			init: function() {
+				var html, el, container;
+
+				container = this.getShimContainer();
+
+				// if not the minimal height, shims are not initialized in older browsers (e.g FF3.6, IE6,7,8, Safari 4.0,5.0, etc)
+				Basic.extend(container.style, {
+					position: 'absolute',
+					top: '-8px',
+					left: '-8px',
+					width: '9px',
+					height: '9px',
+					overflow: 'hidden'
+				});
+
+				// insert flash object
+				html = '<object id="' + this.uid + '" type="application/x-shockwave-flash" data="' +  options.swf_url + '" ';
+
+				if (Env.browser === 'IE') {
+					html += 'classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" ';
+				}
+
+				html += 'width="100%" height="100%" style="outline:0">'  +
+					'<param name="movie" value="' + options.swf_url + '" />' +
+					'<param name="flashvars" value="uid=' + escape(this.uid) + '&target=' + Env.global_event_dispatcher + '" />' +
+					'<param name="wmode" value="transparent" />' +
+					'<param name="allowscriptaccess" value="always" />' +
+				'</object>';
+
+				if (Env.browser === 'IE') {
+					el = document.createElement('div');
+					container.appendChild(el);
+					el.outerHTML = html;
+					el = container = null; // just in case
+				} else {
+					container.innerHTML = html;
+				}
+
+				// Init is dispatched by the shim
+				initTimer = setTimeout(function() {
+					if (I && !I.initialized) { // runtime might be already destroyed by this moment
+						I.trigger("Error", new x.RuntimeError(x.RuntimeError.NOT_INIT_ERR));
+					}
+				}, 5000);
+			},
+
+			destroy: (function(destroy) { // extend default destroy method
+				return function() {
+					destroy.call(I);
+					clearTimeout(initTimer); // initialization check might be still onwait
+					options = initTimer = destroy = I = null;
+				};
+			}(this.destroy))
+
+		}, extensions);
+	}
+
+	Runtime.addConstructor(type, FlashRuntime);
+
+	return extensions;
+});
+
+// Included from: src/javascript/runtime/flash/file/Blob.js
+
+/**
+ * Blob.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+/**
+@class moxie/runtime/flash/file/Blob
+@private
+*/
+define("moxie/runtime/flash/file/Blob", [
+	"moxie/runtime/flash/Runtime",
+	"moxie/file/Blob"
+], function(extensions, Blob) {
+
+	var FlashBlob = {
+		slice: function(blob, start, end, type) {
+			var self = this.getRuntime();
+
+			if (start < 0) {
+				start = Math.max(blob.size + start, 0);
+			} else if (start > 0) {
+				start = Math.min(start, blob.size);
+			}
+
+			if (end < 0) {
+				end = Math.max(blob.size + end, 0);
+			} else if (end > 0) {
+				end = Math.min(end, blob.size);
+			}
+
+			blob = self.shimExec.call(this, 'Blob', 'slice', start, end, type || '');
+
+			if (blob) {
+				blob = new Blob(self.uid, blob);
+			}
+			return blob;
+		}
+	};
+
+	return (extensions.Blob = FlashBlob);
+});
+
+// Included from: src/javascript/runtime/flash/file/FileInput.js
+
+/**
+ * FileInput.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+/**
+@class moxie/runtime/flash/file/FileInput
+@private
+*/
+define("moxie/runtime/flash/file/FileInput", [
+	"moxie/runtime/flash/Runtime"
+], function(extensions) {
+	
+	var FileInput = {		
+		init: function(options) {
+			this.getRuntime().shimExec.call(this, 'FileInput', 'init', {
+				name: options.name,
+				accept: options.accept,
+				multiple: options.multiple
+			});
+			this.trigger('ready');
+		}
+	};
+
+	return (extensions.FileInput = FileInput);
+});
+
+// Included from: src/javascript/runtime/flash/file/FileReader.js
+
+/**
+ * FileReader.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+/**
+@class moxie/runtime/flash/file/FileReader
+@private
+*/
+define("moxie/runtime/flash/file/FileReader", [
+	"moxie/runtime/flash/Runtime",
+	"moxie/core/utils/Encode"
+], function(extensions, Encode) {
+
+	var _result = '';
+
+	function _formatData(data, op) {
+		switch (op) {
+			case 'readAsText':
+				return Encode.atob(data, 'utf8');
+			case 'readAsBinaryString':
+				return Encode.atob(data);
+			case 'readAsDataURL':
+				return data;
+		}
+		return null;
+	}
+
+	var FileReader = {
+		read: function(op, blob) {
+			var target = this, self = target.getRuntime();
+
+			// special prefix for DataURL read mode
+			if (op === 'readAsDataURL') {
+				_result = 'data:' + (blob.type || '') + ';base64,';
+			}
+
+			target.bind('Progress', function(e, data) {
+				if (data) {
+					_result += _formatData(data, op);
+				}
+			});
+
+			return self.shimExec.call(this, 'FileReader', 'readAsBase64', blob.uid);
+		},
+
+		getResult: function() {
+			return _result;
+		},
+
+		destroy: function() {
+			_result = null;
+		}
+	};
+
+	return (extensions.FileReader = FileReader);
+});
+
+// Included from: src/javascript/runtime/flash/file/FileReaderSync.js
+
+/**
+ * FileReaderSync.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+/**
+@class moxie/runtime/flash/file/FileReaderSync
+@private
+*/
+define("moxie/runtime/flash/file/FileReaderSync", [
+	"moxie/runtime/flash/Runtime",
+	"moxie/core/utils/Encode"
+], function(extensions, Encode) {
+	
+	function _formatData(data, op) {
+		switch (op) {
+			case 'readAsText':
+				return Encode.atob(data, 'utf8');
+			case 'readAsBinaryString':
+				return Encode.atob(data);
+			case 'readAsDataURL':
+				return data;
+		}
+		return null;
+	}
+
+	var FileReaderSync = {
+		read: function(op, blob) {
+			var result, self = this.getRuntime();
+
+			result = self.shimExec.call(this, 'FileReaderSync', 'readAsBase64', blob.uid);
+			if (!result) {
+				return null; // or throw ex
+			}
+
+			// special prefix for DataURL read mode
+			if (op === 'readAsDataURL') {
+				result = 'data:' + (blob.type || '') + ';base64,' + result;
+			}
+
+			return _formatData(result, op, blob.type);
+		}
+	};
+
+	return (extensions.FileReaderSync = FileReaderSync);
+});
+
+// Included from: src/javascript/runtime/flash/xhr/XMLHttpRequest.js
+
+/**
+ * XMLHttpRequest.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+/**
+@class moxie/runtime/flash/xhr/XMLHttpRequest
+@private
+*/
+define("moxie/runtime/flash/xhr/XMLHttpRequest", [
+	"moxie/runtime/flash/Runtime",
+	"moxie/core/utils/Basic",
+	"moxie/file/Blob",
+	"moxie/file/File",
+	"moxie/file/FileReaderSync",
+	"moxie/xhr/FormData",
+	"moxie/runtime/Transporter"
+], function(extensions, Basic, Blob, File, FileReaderSync, FormData, Transporter) {
+	
+	var XMLHttpRequest = {
+
+		send: function(meta, data) {
+			var target = this, self = target.getRuntime();
+
+			function send() {
+				meta.transport = self.mode;
+				self.shimExec.call(target, 'XMLHttpRequest', 'send', meta, data);
+			}
+
+
+			function appendBlob(name, blob) {
+				self.shimExec.call(target, 'XMLHttpRequest', 'appendBlob', name, blob.uid);
+				data = null;
+				send();
+			}
+
+
+			function attachBlob(blob, cb) {
+				var tr = new Transporter();
+
+				tr.bind("TransportingComplete", function() {
+					cb(this.result);
+				});
+
+				tr.transport(blob.getSource(), blob.type, {
+					ruid: self.uid
+				});
+			}
+
+			// copy over the headers if any
+			if (!Basic.isEmptyObj(meta.headers)) {
+				Basic.each(meta.headers, function(value, header) {
+					self.shimExec.call(target, 'XMLHttpRequest', 'setRequestHeader', header, value.toString()); // Silverlight doesn't accept integers into the arguments of type object
+				});
+			}
+
+			// transfer over multipart params and blob itself
+			if (data instanceof FormData) {
+				var blobField;
+				data.each(function(value, name) {
+					if (value instanceof Blob) {
+						blobField = name;
+					} else {
+						self.shimExec.call(target, 'XMLHttpRequest', 'append', name, value);
+					}
+				});
+
+				if (!data.hasBlob()) {
+					data = null;
+					send();
+				} else {
+					var blob = data.getBlob();
+					if (blob.isDetached()) {
+						attachBlob(blob, function(attachedBlob) {
+							blob.destroy();
+							appendBlob(blobField, attachedBlob);		
+						});
+					} else {
+						appendBlob(blobField, blob);
+					}
+				}
+			} else if (data instanceof Blob) {
+				if (data.isDetached()) {
+					attachBlob(data, function(attachedBlob) {
+						data.destroy();
+						data = attachedBlob.uid;
+						send();
+					});
+				} else {
+					data = data.uid;
+					send();
+				}
+			} else {
+				send();
+			}
+		},
+
+		getResponse: function(responseType) {
+			var frs, blob, self = this.getRuntime();
+
+			blob = self.shimExec.call(this, 'XMLHttpRequest', 'getResponseAsBlob');
+
+			if (blob) {
+				blob = new File(self.uid, blob);
+
+				if ('blob' === responseType) {
+					return blob;
+				}
+
+				try { 
+					frs = new FileReaderSync();
+
+					if (!!~Basic.inArray(responseType, ["", "text"])) {
+						return frs.readAsText(blob);
+					} else if ('json' === responseType && !!window.JSON) {
+						return JSON.parse(frs.readAsText(blob));
+					}
+				} finally {
+					blob.destroy();
+				}
+			}
+			return null;
+		},
+
+		abort: function(upload_complete_flag) {
+			var self = this.getRuntime();
+
+			self.shimExec.call(this, 'XMLHttpRequest', 'abort');
+
+			this.dispatchEvent('readystatechange');
+			// this.dispatchEvent('progress');
+			this.dispatchEvent('abort');
+
+			//if (!upload_complete_flag) {
+				// this.dispatchEvent('uploadprogress');
+			//}
+		}
+	};
+
+	return (extensions.XMLHttpRequest = XMLHttpRequest);
+});
+
+// Included from: src/javascript/runtime/flash/runtime/Transporter.js
+
+/**
+ * Transporter.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+/**
+@class moxie/runtime/flash/runtime/Transporter
+@private
+*/
+define("moxie/runtime/flash/runtime/Transporter", [
+	"moxie/runtime/flash/Runtime",
+	"moxie/file/Blob"
+], function(extensions, Blob) {
+
+	var Transporter = {
+		getAsBlob: function(type) {
+			var self = this.getRuntime()
+			, blob = self.shimExec.call(this, 'Transporter', 'getAsBlob', type)
+			;
+			if (blob) {
+				return new Blob(self.uid, blob);
+			}
+			return null;
+		}
+	};
+
+	return (extensions.Transporter = Transporter);
+});
+
+// Included from: src/javascript/runtime/flash/image/Image.js
+
+/**
+ * Image.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+/**
+@class moxie/runtime/flash/image/Image
+@private
+*/
+define("moxie/runtime/flash/image/Image", [
+	"moxie/runtime/flash/Runtime",
+	"moxie/core/utils/Basic",
+	"moxie/runtime/Transporter",
+	"moxie/file/Blob",
+	"moxie/file/FileReaderSync"
+], function(extensions, Basic, Transporter, Blob, FileReaderSync) {
+	
+	var Image = {
+		loadFromBlob: function(blob) {
+			var comp = this, self = comp.getRuntime();
+
+			function exec(srcBlob) {
+				self.shimExec.call(comp, 'Image', 'loadFromBlob', srcBlob.uid);
+				comp = self = null;
+			}
+
+			if (blob.isDetached()) { // binary string
+				var tr = new Transporter();
+				tr.bind("TransportingComplete", function() {
+					exec(tr.result.getSource());
+				});
+				tr.transport(blob.getSource(), blob.type, { ruid: self.uid });
+			} else {
+				exec(blob.getSource());
+			}
+		},
+
+		loadFromImage: function(img) {
+			var self = this.getRuntime();
+			return self.shimExec.call(this, 'Image', 'loadFromImage', img.uid);
+		},
+
+		getAsBlob: function(type, quality) {
+			var self = this.getRuntime()
+			, blob = self.shimExec.call(this, 'Image', 'getAsBlob', type, quality)
+			;
+			if (blob) {
+				return new Blob(self.uid, blob);
+			}
+			return null;
+		},
+
+		getAsDataURL: function() {
+			var self = this.getRuntime()
+			, blob = self.Image.getAsBlob.apply(this, arguments)
+			, frs
+			;
+			if (!blob) {
+				return null;
+			}
+			frs = new FileReaderSync();
+			return frs.readAsDataURL(blob);
+		}
+	};
+
+	return (extensions.Image = Image);
+});
+
+// Included from: src/javascript/runtime/silverlight/Runtime.js
+
+/**
+ * RunTime.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+/*global ActiveXObject:true */
+
+/**
+Defines constructor for Silverlight runtime.
+
+@class moxie/runtime/silverlight/Runtime
+@private
+*/
+define("moxie/runtime/silverlight/Runtime", [
+	"moxie/core/utils/Basic",
+	"moxie/core/utils/Env",
+	"moxie/core/utils/Dom",
+	"moxie/core/Exceptions",
+	"moxie/runtime/Runtime"
+], function(Basic, Env, Dom, x, Runtime) {
+	
+	var type = "silverlight", extensions = {};
+
+	function isInstalled(version) {
+		var isVersionSupported = false, control = null, actualVer,
+			actualVerArray, reqVerArray, requiredVersionPart, actualVersionPart, index = 0;
+
+		try {
+			try {
+				control = new ActiveXObject('AgControl.AgControl');
+
+				if (control.IsVersionSupported(version)) {
+					isVersionSupported = true;
+				}
+
+				control = null;
+			} catch (e) {
+				var plugin = navigator.plugins["Silverlight Plug-In"];
+
+				if (plugin) {
+					actualVer = plugin.description;
+
+					if (actualVer === "1.0.30226.2") {
+						actualVer = "2.0.30226.2";
+					}
+
+					actualVerArray = actualVer.split(".");
+
+					while (actualVerArray.length > 3) {
+						actualVerArray.pop();
+					}
+
+					while ( actualVerArray.length < 4) {
+						actualVerArray.push(0);
+					}
+
+					reqVerArray = version.split(".");
+
+					while (reqVerArray.length > 4) {
+						reqVerArray.pop();
+					}
+
+					do {
+						requiredVersionPart = parseInt(reqVerArray[index], 10);
+						actualVersionPart = parseInt(actualVerArray[index], 10);
+						index++;
+					} while (index < reqVerArray.length && requiredVersionPart === actualVersionPart);
+
+					if (requiredVersionPart <= actualVersionPart && !isNaN(requiredVersionPart)) {
+						isVersionSupported = true;
+					}
+				}
+			}
+		} catch (e2) {
+			isVersionSupported = false;
+		}
+
+		return isVersionSupported;
+	}
+
+	/**
+	Constructor for the Silverlight Runtime
+
+	@class SilverlightRuntime
+	@extends Runtime
+	*/
+	function SilverlightRuntime(options) {
+		var I = this, initTimer;
+
+		options = Basic.extend({ xap_url: Env.xap_url }, options);
+
+		Runtime.call(this, options, type, {
+			access_binary: Runtime.capTrue,
+			access_image_binary: Runtime.capTrue,
+			display_media: Runtime.capTrue,
+			do_cors: Runtime.capTrue,
+			drag_and_drop: false,
+			report_upload_progress: Runtime.capTrue,
+			resize_image: Runtime.capTrue,
+			return_response_headers: function(value) {
+				return value && I.mode === 'client';
+			},
+			return_response_type: function(responseType) {
+				if (responseType !== 'json') {
+					return true;
+				} else {
+					return !!window.JSON;
+				}
+			},
+			return_status_code: function(code) {
+				return I.mode === 'client' || !Basic.arrayDiff(code, [200, 404]);
+			},
+			select_file: Runtime.capTrue,
+			select_multiple: Runtime.capTrue,
+			send_binary_string: Runtime.capTrue,
+			send_browser_cookies: function(value) {
+				return value && I.mode === 'browser';
+			},
+			send_custom_headers: function(value) {
+				return value && I.mode === 'client';
+			},
+			send_multipart: Runtime.capTrue,
+			slice_blob: Runtime.capTrue,
+			stream_upload: true,
+			summon_file_dialog: false,
+			upload_filesize: Runtime.capTrue,
+			use_http_method: function(methods) {
+				return I.mode === 'client' || !Basic.arrayDiff(methods, ['GET', 'POST']);
+			}
+		}, { 
+			// capabilities that require specific mode
+			return_response_headers: function(value) {
+				return value ? 'client' : 'browser';
+			},
+			return_status_code: function(code) {
+				return Basic.arrayDiff(code, [200, 404]) ? 'client' : ['client', 'browser'];
+			},
+			send_browser_cookies: function(value) {
+				return value ? 'browser' : 'client';
+			},
+			send_custom_headers: function(value) {
+				return value ? 'client' : 'browser';
+			},
+			use_http_method: function(methods) {
+				return Basic.arrayDiff(methods, ['GET', 'POST']) ? 'client' : ['client', 'browser'];
+			}
+		});
+
+
+		// minimal requirement
+		if (!isInstalled('2.0.31005.0') || Env.browser === 'Opera') {
+			this.mode = false;
+		}
+
+
+		Basic.extend(this, {
+			getShim: function() {
+				return Dom.get(this.uid).content.Moxie;
+			},
+
+			shimExec: function(component, action) {
+				var args = [].slice.call(arguments, 2);
+				return I.getShim().exec(this.uid, component, action, args);
+			},
+
+			init : function() {
+				var container;
+
+				container = this.getShimContainer();
+
+				container.innerHTML = '<object id="' + this.uid + '" data="data:application/x-silverlight," type="application/x-silverlight-2" width="100%" height="100%" style="outline:none;">' +
+					'<param name="source" value="' + options.xap_url + '"/>' +
+					'<param name="background" value="Transparent"/>' +
+					'<param name="windowless" value="true"/>' +
+					'<param name="enablehtmlaccess" value="true"/>' +
+					'<param name="initParams" value="uid=' + this.uid + ',target=' + Env.global_event_dispatcher + '"/>' +
+				'</object>';
+
+				// Init is dispatched by the shim
+				initTimer = setTimeout(function() {
+					if (I && !I.initialized) { // runtime might be already destroyed by this moment
+						I.trigger("Error", new x.RuntimeError(x.RuntimeError.NOT_INIT_ERR));
+					}
+				}, Env.OS !== 'Windows'? 10000 : 5000); // give it more time to initialize in non Windows OS (like Mac)
+			},
+
+			destroy: (function(destroy) { // extend default destroy method
+				return function() {
+					destroy.call(I);
+					clearTimeout(initTimer); // initialization check might be still onwait
+					options = initTimer = destroy = I = null;
+				};
+			}(this.destroy))
+
+		}, extensions);
+	}
+
+	Runtime.addConstructor(type, SilverlightRuntime); 
+
+	return extensions;
+});
+
+// Included from: src/javascript/runtime/silverlight/file/Blob.js
+
+/**
+ * Blob.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+/**
+@class moxie/runtime/silverlight/file/Blob
+@private
+*/
+define("moxie/runtime/silverlight/file/Blob", [
+	"moxie/runtime/silverlight/Runtime",
+	"moxie/core/utils/Basic",
+	"moxie/runtime/flash/file/Blob"
+], function(extensions, Basic, Blob) {
+	return (extensions.Blob = Basic.extend({}, Blob));
+});
+
+// Included from: src/javascript/runtime/silverlight/file/FileInput.js
+
+/**
+ * FileInput.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+/**
+@class moxie/runtime/silverlight/file/FileInput
+@private
+*/
+define("moxie/runtime/silverlight/file/FileInput", [
+	"moxie/runtime/silverlight/Runtime"
+], function(extensions) {
+	
+	var FileInput = {
+		init: function(options) {
+
+			function toFilters(accept) {
+				var filter = '';
+				for (var i = 0; i < accept.length; i++) {
+					filter += (filter !== '' ? '|' : '') + accept[i].title + " | *." + accept[i].extensions.replace(/,/g, ';*.');
+				}
+				return filter;
+			}
+			
+			this.getRuntime().shimExec.call(this, 'FileInput', 'init', toFilters(options.accept), options.name, options.multiple);
+			this.trigger('ready');
+		}
+	};
+
+	return (extensions.FileInput = FileInput);
+});
+
+// Included from: src/javascript/runtime/silverlight/file/FileDrop.js
+
+/**
+ * FileDrop.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+/**
+@class moxie/runtime/silverlight/file/FileDrop
+@private
+*/
+define("moxie/runtime/silverlight/file/FileDrop", [
+	"moxie/runtime/silverlight/Runtime",
+	"moxie/core/utils/Dom", 
+	"moxie/core/utils/Events"
+], function(extensions, Dom, Events) {
+
+	// not exactly useful, since works only in safari (...crickets...)
+	var FileDrop = {
+		init: function() {
+			var comp = this, self = comp.getRuntime(), dropZone;
+
+			dropZone = self.getShimContainer();
+
+			Events.addEvent(dropZone, 'dragover', function(e) {
+				e.preventDefault();
+				e.stopPropagation();
+				e.dataTransfer.dropEffect = 'copy';
+			}, comp.uid);
+
+			Events.addEvent(dropZone, 'dragenter', function(e) {
+				e.preventDefault();
+				var flag = Dom.get(self.uid).dragEnter(e);
+				// If handled, then stop propagation of event in DOM
+				if (flag) {
+					e.stopPropagation();
+				}
+			}, comp.uid);
+
+			Events.addEvent(dropZone, 'drop', function(e) {
+				e.preventDefault();
+				var flag = Dom.get(self.uid).dragDrop(e);
+				// If handled, then stop propagation of event in DOM
+				if (flag) {
+					e.stopPropagation();
+				}
+			}, comp.uid);
+
+			return self.shimExec.call(this, 'FileDrop', 'init');
+		}
+	};
+
+	return (extensions.FileDrop = FileDrop);
+});
+
+// Included from: src/javascript/runtime/silverlight/file/FileReader.js
+
+/**
+ * FileReader.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+/**
+@class moxie/runtime/silverlight/file/FileReader
+@private
+*/
+define("moxie/runtime/silverlight/file/FileReader", [
+	"moxie/runtime/silverlight/Runtime",
+	"moxie/core/utils/Basic",
+	"moxie/runtime/flash/file/FileReader"
+], function(extensions, Basic, FileReader) {
+	return (extensions.FileReader = Basic.extend({}, FileReader));
+});
+
+// Included from: src/javascript/runtime/silverlight/file/FileReaderSync.js
+
+/**
+ * FileReaderSync.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+/**
+@class moxie/runtime/silverlight/file/FileReaderSync
+@private
+*/
+define("moxie/runtime/silverlight/file/FileReaderSync", [
+	"moxie/runtime/silverlight/Runtime",
+	"moxie/core/utils/Basic",
+	"moxie/runtime/flash/file/FileReaderSync"
+], function(extensions, Basic, FileReaderSync) {
+	return (extensions.FileReaderSync = Basic.extend({}, FileReaderSync));
+});
+
+// Included from: src/javascript/runtime/silverlight/xhr/XMLHttpRequest.js
+
+/**
+ * XMLHttpRequest.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+/**
+@class moxie/runtime/silverlight/xhr/XMLHttpRequest
+@private
+*/
+define("moxie/runtime/silverlight/xhr/XMLHttpRequest", [
+	"moxie/runtime/silverlight/Runtime",
+	"moxie/core/utils/Basic",
+	"moxie/runtime/flash/xhr/XMLHttpRequest"
+], function(extensions, Basic, XMLHttpRequest) {
+	return (extensions.XMLHttpRequest = Basic.extend({}, XMLHttpRequest));
+});
+
+// Included from: src/javascript/runtime/silverlight/runtime/Transporter.js
+
+/**
+ * Transporter.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+/**
+@class moxie/runtime/silverlight/runtime/Transporter
+@private
+*/
+define("moxie/runtime/silverlight/runtime/Transporter", [
+	"moxie/runtime/silverlight/Runtime",
+	"moxie/core/utils/Basic",
+	"moxie/runtime/flash/runtime/Transporter"
+], function(extensions, Basic, Transporter) {
+	return (extensions.Transporter = Basic.extend({}, Transporter));
+});
+
+// Included from: src/javascript/runtime/silverlight/image/Image.js
+
+/**
+ * Image.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+ 
+/**
+@class moxie/runtime/silverlight/image/Image
+@private
+*/
+define("moxie/runtime/silverlight/image/Image", [
+	"moxie/runtime/silverlight/Runtime",
+	"moxie/core/utils/Basic",
+	"moxie/runtime/flash/image/Image"
+], function(extensions, Basic, Image) {
+	return (extensions.Image = Basic.extend({}, Image, {
+
+		getInfo: function() {
+			var self = this.getRuntime()
+			, grps = ['tiff', 'exif', 'gps']
+			, info = { meta: {} }
+			, rawInfo = self.shimExec.call(this, 'Image', 'getInfo')
+			;
+
+			if (rawInfo.meta) {
+				Basic.each(grps, function(grp) {
+					var meta = rawInfo.meta[grp]
+					, tag
+					, i
+					, length
+					, value
+					;
+					if (meta && meta.keys) {
+						info.meta[grp] = {};
+						for (i = 0, length = meta.keys.length; i < length; i++) {
+							tag = meta.keys[i];
+							value = meta[tag];
+							if (value) {
+								// convert numbers
+								if (/^(\d|[1-9]\d+)$/.test(value)) { // integer (make sure doesn't start with zero)
+									value = parseInt(value, 10);
+								} else if (/^\d*\.\d+$/.test(value)) { // double
+									value = parseFloat(value);
+								}
+								info.meta[grp][tag] = value;
+							}
+						}
+					}
+				});
+			}
+
+			info.width = parseInt(rawInfo.width, 10);
+			info.height = parseInt(rawInfo.height, 10);
+			info.size = parseInt(rawInfo.size, 10);
+			info.type = rawInfo.type;
+			info.name = rawInfo.name;
+
+			return info;
+		}
+	}));
+});
+
+// Included from: src/javascript/runtime/html4/Runtime.js
+
+/**
+ * Runtime.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+/*global File:true */
+
+/**
+Defines constructor for HTML4 runtime.
+
+@class moxie/runtime/html4/Runtime
+@private
+*/
+define("moxie/runtime/html4/Runtime", [
+	"moxie/core/utils/Basic",
+	"moxie/core/Exceptions",
+	"moxie/runtime/Runtime",
+	"moxie/core/utils/Env"
+], function(Basic, x, Runtime, Env) {
+	
+	var type = 'html4', extensions = {};
+
+	function Html4Runtime(options) {
+		var I = this
+		, Test = Runtime.capTest
+		, True = Runtime.capTrue
+		;
+
+		Runtime.call(this, options, type, {
+			access_binary: Test(window.FileReader || window.File && File.getAsDataURL),
+			access_image_binary: false,
+			display_media: Test(extensions.Image && (Env.can('create_canvas') || Env.can('use_data_uri_over32kb'))),
+			do_cors: false,
+			drag_and_drop: false,
+			filter_by_extension: Test(function() { // if you know how to feature-detect this, please suggest
+				return (Env.browser === 'Chrome' && Env.version >= 28) || (Env.browser === 'IE' && Env.version >= 10);
+			}()),
+			resize_image: function() {
+				return extensions.Image && I.can('access_binary') && Env.can('create_canvas');
+			},
+			report_upload_progress: false,
+			return_response_headers: false,
+			return_response_type: function(responseType) {
+				if (responseType === 'json' && !!window.JSON) {
+					return true;
+				} 
+				return !!~Basic.inArray(responseType, ['text', 'document', '']);
+			},
+			return_status_code: function(code) {
+				return !Basic.arrayDiff(code, [200, 404]);
+			},
+			select_file: function() {
+				return Env.can('use_fileinput');
+			},
+			select_multiple: false,
+			send_binary_string: false,
+			send_custom_headers: false,
+			send_multipart: true,
+			slice_blob: false,
+			stream_upload: function() {
+				return I.can('select_file');
+			},
+			summon_file_dialog: Test(function() { // yeah... some dirty sniffing here...
+				return (Env.browser === 'Firefox' && Env.version >= 4) ||
+					(Env.browser === 'Opera' && Env.version >= 12) ||
+					!!~Basic.inArray(Env.browser, ['Chrome', 'Safari']);
+			}()),
+			upload_filesize: True,
+			use_http_method: function(methods) {
+				return !Basic.arrayDiff(methods, ['GET', 'POST']);
+			}
+		});
+
+
+		Basic.extend(this, {
+			init : function() {
+				this.trigger("Init");
+			},
+
+			destroy: (function(destroy) { // extend default destroy method
+				return function() {
+					destroy.call(I);
+					destroy = I = null;
+				};
+			}(this.destroy))
+		});
+
+		Basic.extend(this.getShim(), extensions);
+	}
+
+	Runtime.addConstructor(type, Html4Runtime);
+
+	return extensions;
+});
+
+// Included from: src/javascript/runtime/html4/file/FileInput.js
+
+/**
+ * FileInput.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+/**
+@class moxie/runtime/html4/file/FileInput
+@private
+*/
+define("moxie/runtime/html4/file/FileInput", [
+	"moxie/runtime/html4/Runtime",
+	"moxie/core/utils/Basic",
+	"moxie/core/utils/Dom",
+	"moxie/core/utils/Events",
+	"moxie/core/utils/Mime",
+	"moxie/core/utils/Env"
+], function(extensions, Basic, Dom, Events, Mime, Env) {
+	
+	function FileInput() {
+		var _uid, _files = [], _mimes = [], _options;
+
+		function addInput() {
+			var comp = this, I = comp.getRuntime(), shimContainer, browseButton, currForm, form, input, uid;
+
+			uid = Basic.guid('uid_');
+
+			shimContainer = I.getShimContainer(); // we get new ref everytime to avoid memory leaks in IE
+
+			if (_uid) { // move previous form out of the view
+				currForm = Dom.get(_uid + '_form');
+				if (currForm) {
+					Basic.extend(currForm.style, { top: '100%' });
+				}
+			}
+
+			// build form in DOM, since innerHTML version not able to submit file for some reason
+			form = document.createElement('form');
+			form.setAttribute('id', uid + '_form');
+			form.setAttribute('method', 'post');
+			form.setAttribute('enctype', 'multipart/form-data');
+			form.setAttribute('encoding', 'multipart/form-data');
+
+			Basic.extend(form.style, {
+				overflow: 'hidden',
+				position: 'absolute',
+				top: 0,
+				left: 0,
+				width: '100%',
+				height: '100%'
+			});
+
+			input = document.createElement('input');
+			input.setAttribute('id', uid);
+			input.setAttribute('type', 'file');
+			input.setAttribute('name', _options.name || 'Filedata');
+			input.setAttribute('accept', _mimes.join(','));
+
+			Basic.extend(input.style, {
+				fontSize: '999px',
+				opacity: 0
+			});
+
+			form.appendChild(input);
+			shimContainer.appendChild(form);
+
+			// prepare file input to be placed underneath the browse_button element
+			Basic.extend(input.style, {
+				position: 'absolute',
+				top: 0,
+				left: 0,
+				width: '100%',
+				height: '100%'
+			});
+
+			if (Env.browser === 'IE' && Env.version < 10) {
+				Basic.extend(input.style, {
+					filter : "progid:DXImageTransform.Microsoft.Alpha(opacity=0)"
+				});
+			}
+
+			input.onchange = function() { // there should be only one handler for this
+				var file;
+
+				if (!this.value) {
+					return;
+				}
+
+				if (this.files) {
+					file = this.files[0];
+				} else {
+					file = {
+						name: this.value
+					};
+				}
+
+				_files = [file];
+
+				this.onchange = function() {}; // clear event handler
+				addInput.call(comp);
+
+				// after file is initialized as o.File, we need to update form and input ids
+				comp.bind('change', function onChange() {
+					var input = Dom.get(uid), form = Dom.get(uid + '_form'), file;
+
+					comp.unbind('change', onChange);
+
+					if (comp.files.length && input && form) {
+						file = comp.files[0];
+
+						input.setAttribute('id', file.uid);
+						form.setAttribute('id', file.uid + '_form');
+
+						// set upload target
+						form.setAttribute('target', file.uid + '_iframe');
+					}
+					input = form = null;
+				}, 998);
+
+				input = form = null;
+				comp.trigger('change');
+			};
+
+
+			// route click event to the input
+			if (I.can('summon_file_dialog')) {
+				browseButton = Dom.get(_options.browse_button);
+				Events.removeEvent(browseButton, 'click', comp.uid);
+				Events.addEvent(browseButton, 'click', function(e) {
+					if (input && !input.disabled) { // for some reason FF (up to 8.0.1 so far) lets to click disabled input[type=file]
+						input.click();
+					}
+					e.preventDefault();
+				}, comp.uid);
+			}
+
+			_uid = uid;
+
+			shimContainer = currForm = browseButton = null;
+		}
+
+		Basic.extend(this, {
+			init: function(options) {
+				var comp = this, I = comp.getRuntime(), shimContainer;
+
+				// figure out accept string
+				_options = options;
+				_mimes = options.accept.mimes || Mime.extList2mimes(options.accept, I.can('filter_by_extension'));
+
+				shimContainer = I.getShimContainer();
+
+				(function() {
+					var browseButton, zIndex, top;
+
+					browseButton = Dom.get(options.browse_button);
+
+					// Route click event to the input[type=file] element for browsers that support such behavior
+					if (I.can('summon_file_dialog')) {
+						if (Dom.getStyle(browseButton, 'position') === 'static') {
+							browseButton.style.position = 'relative';
+						}
+
+						zIndex = parseInt(Dom.getStyle(browseButton, 'z-index'), 10) || 1;
+
+						browseButton.style.zIndex = zIndex;
+						shimContainer.style.zIndex = zIndex - 1;
+					}
+
+					/* Since we have to place input[type=file] on top of the browse_button for some browsers,
+					browse_button loses interactivity, so we restore it here */
+					top = I.can('summon_file_dialog') ? browseButton : shimContainer;
+
+					Events.addEvent(top, 'mouseover', function() {
+						comp.trigger('mouseenter');
+					}, comp.uid);
+
+					Events.addEvent(top, 'mouseout', function() {
+						comp.trigger('mouseleave');
+					}, comp.uid);
+
+					Events.addEvent(top, 'mousedown', function() {
+						comp.trigger('mousedown');
+					}, comp.uid);
+
+					Events.addEvent(Dom.get(options.container), 'mouseup', function() {
+						comp.trigger('mouseup');
+					}, comp.uid);
+
+					browseButton = null;
+				}());
+
+				addInput.call(this);
+
+				shimContainer = null;
+
+				// trigger ready event asynchronously
+				comp.trigger({
+					type: 'ready',
+					async: true
+				});
+			},
+
+			getFiles: function() {
+				return _files;
+			},
+
+			disable: function(state) {
+				var input;
+
+				if ((input = Dom.get(_uid))) {
+					input.disabled = !!state;
+				}
+			},
+
+			destroy: function() {
+				var I = this.getRuntime()
+				, shim = I.getShim()
+				, shimContainer = I.getShimContainer()
+				;
+				
+				Events.removeAllEvents(shimContainer, this.uid);
+				Events.removeAllEvents(_options && Dom.get(_options.container), this.uid);
+				Events.removeAllEvents(_options && Dom.get(_options.browse_button), this.uid);
+				
+				if (shimContainer) {
+					shimContainer.innerHTML = '';
+				}
+
+				shim.removeInstance(this.uid);
+
+				_uid = _files = _mimes = _options = shimContainer = shim = null;
+			}
+		});
+	}
+
+	return (extensions.FileInput = FileInput);
+});
+
+// Included from: src/javascript/runtime/html4/file/FileReader.js
+
+/**
+ * FileReader.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+/**
+@class moxie/runtime/html4/file/FileReader
+@private
+*/
+define("moxie/runtime/html4/file/FileReader", [
+	"moxie/runtime/html4/Runtime",
+	"moxie/runtime/html5/file/FileReader"
+], function(extensions, FileReader) {
+	return (extensions.FileReader = FileReader);
+});
+
+// Included from: src/javascript/runtime/html4/xhr/XMLHttpRequest.js
+
+/**
+ * XMLHttpRequest.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+/**
+@class moxie/runtime/html4/xhr/XMLHttpRequest
+@private
+*/
+define("moxie/runtime/html4/xhr/XMLHttpRequest", [
+	"moxie/runtime/html4/Runtime",
+	"moxie/core/utils/Basic",
+	"moxie/core/utils/Dom",
+	"moxie/core/utils/Url",
+	"moxie/core/Exceptions",
+	"moxie/core/utils/Events",
+	"moxie/file/Blob",
+	"moxie/xhr/FormData"
+], function(extensions, Basic, Dom, Url, x, Events, Blob, FormData) {
+	
+	function XMLHttpRequest() {
+		var _status, _response, _iframe;
+
+		function cleanup(cb) {
+			var target = this, uid, form, inputs, i, hasFile = false;
+
+			if (!_iframe) {
+				return;
+			}
+
+			uid = _iframe.id.replace(/_iframe$/, '');
+
+			form = Dom.get(uid + '_form');
+			if (form) {
+				inputs = form.getElementsByTagName('input');
+				i = inputs.length;
+
+				while (i--) {
+					switch (inputs[i].getAttribute('type')) {
+						case 'hidden':
+							inputs[i].parentNode.removeChild(inputs[i]);
+							break;
+						case 'file':
+							hasFile = true; // flag the case for later
+							break;
+					}
+				}
+				inputs = [];
+
+				if (!hasFile) { // we need to keep the form for sake of possible retries
+					form.parentNode.removeChild(form);
+				}
+				form = null;
+			}
+
+			// without timeout, request is marked as canceled (in console)
+			setTimeout(function() {
+				Events.removeEvent(_iframe, 'load', target.uid);
+				if (_iframe.parentNode) { // #382
+					_iframe.parentNode.removeChild(_iframe);
+				}
+
+				// check if shim container has any other children, if - not, remove it as well
+				var shimContainer = target.getRuntime().getShimContainer();
+				if (!shimContainer.children.length) {
+					shimContainer.parentNode.removeChild(shimContainer);
+				}
+
+				shimContainer = _iframe = null;
+				cb();
+			}, 1);
+		}
+
+		Basic.extend(this, {
+			send: function(meta, data) {
+				var target = this, I = target.getRuntime(), uid, form, input, blob;
+
+				_status = _response = null;
+
+				function createIframe() {
+					var container = I.getShimContainer() || document.body
+					, temp = document.createElement('div')
+					;
+
+					// IE 6 won't be able to set the name using setAttribute or iframe.name
+					temp.innerHTML = '<iframe id="' + uid + '_iframe" name="' + uid + '_iframe" src="javascript:&quot;&quot;" style="display:none"></iframe>';
+					_iframe = temp.firstChild;
+					container.appendChild(_iframe);
+
+					/* _iframe.onreadystatechange = function() {
+						console.info(_iframe.readyState);
+					};*/
+
+					Events.addEvent(_iframe, 'load', function() { // _iframe.onload doesn't work in IE lte 8
+						var el;
+
+						try {
+							el = _iframe.contentWindow.document || _iframe.contentDocument || window.frames[_iframe.id].document;
+
+							// try to detect some standard error pages
+							if (/^4(0[0-9]|1[0-7]|2[2346])\s/.test(el.title)) { // test if title starts with 4xx HTTP error
+								_status = el.title.replace(/^(\d+).*$/, '$1');
+							} else {
+								_status = 200;
+								// get result
+								_response = Basic.trim(el.body.innerHTML);
+
+								// we need to fire these at least once
+								target.trigger({
+									type: 'progress',
+									loaded: _response.length,
+									total: _response.length
+								});
+
+								if (blob) { // if we were uploading a file
+									target.trigger({
+										type: 'uploadprogress',
+										loaded: blob.size || 1025,
+										total: blob.size || 1025
+									});
+								}
+							}
+						} catch (ex) {
+							if (Url.hasSameOrigin(meta.url)) {
+								// if response is sent with error code, iframe in IE gets redirected to res://ieframe.dll/http_x.htm
+								// which obviously results to cross domain error (wtf?)
+								_status = 404;
+							} else {
+								cleanup.call(target, function() {
+									target.trigger('error');
+								});
+								return;
+							}
+						}	
+					
+						cleanup.call(target, function() {
+							target.trigger('load');
+						});
+					}, target.uid);
+				} // end createIframe
+
+				// prepare data to be sent and convert if required
+				if (data instanceof FormData && data.hasBlob()) {
+					blob = data.getBlob();
+					uid = blob.uid;
+					input = Dom.get(uid);
+					form = Dom.get(uid + '_form');
+					if (!form) {
+						throw new x.DOMException(x.DOMException.NOT_FOUND_ERR);
+					}
+				} else {
+					uid = Basic.guid('uid_');
+
+					form = document.createElement('form');
+					form.setAttribute('id', uid + '_form');
+					form.setAttribute('method', meta.method);
+					form.setAttribute('enctype', 'multipart/form-data');
+					form.setAttribute('encoding', 'multipart/form-data');
+					form.setAttribute('target', uid + '_iframe');
+
+					I.getShimContainer().appendChild(form);
+				}
+
+				if (data instanceof FormData) {
+					data.each(function(value, name) {
+						if (value instanceof Blob) {
+							if (input) {
+								input.setAttribute('name', name);
+							}
+						} else {
+							var hidden = document.createElement('input');
+
+							Basic.extend(hidden, {
+								type : 'hidden',
+								name : name,
+								value : value
+							});
+
+							// make sure that input[type="file"], if it's there, comes last
+							if (input) {
+								form.insertBefore(hidden, input);
+							} else {
+								form.appendChild(hidden);
+							}
+						}
+					});
+				}
+
+				// set destination url
+				form.setAttribute("action", meta.url);
+
+				createIframe();
+				form.submit();
+				target.trigger('loadstart');
+			},
+
+			getStatus: function() {
+				return _status;
+			},
+
+			getResponse: function(responseType) {
+				if ('json' === responseType) {
+					// strip off <pre>..</pre> tags that might be enclosing the response
+					if (Basic.typeOf(_response) === 'string' && !!window.JSON) {
+						try {
+							return JSON.parse(_response.replace(/^\s*<pre[^>]*>/, '').replace(/<\/pre>\s*$/, ''));
+						} catch (ex) {
+							return null;
+						}
+					} 
+				} else if ('document' === responseType) {
+
+				}
+				return _response;
+			},
+
+			abort: function() {
+				var target = this;
+
+				if (_iframe && _iframe.contentWindow) {
+					if (_iframe.contentWindow.stop) { // FireFox/Safari/Chrome
+						_iframe.contentWindow.stop();
+					} else if (_iframe.contentWindow.document.execCommand) { // IE
+						_iframe.contentWindow.document.execCommand('Stop');
+					} else {
+						_iframe.src = "about:blank";
+					}
+				}
+
+				cleanup.call(this, function() {
+					// target.dispatchEvent('readystatechange');
+					target.dispatchEvent('abort');
+				});
+			}
+		});
+	}
+
+	return (extensions.XMLHttpRequest = XMLHttpRequest);
+});
+
+// Included from: src/javascript/runtime/html4/image/Image.js
+
+/**
+ * Image.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+/**
+@class moxie/runtime/html4/image/Image
+@private
+*/
+define("moxie/runtime/html4/image/Image", [
+	"moxie/runtime/html4/Runtime",
+	"moxie/runtime/html5/image/Image"
+], function(extensions, Image) {
+	return (extensions.Image = Image);
+});
+
+expose(["moxie/core/utils/Basic","moxie/core/I18n","moxie/core/utils/Mime","moxie/core/utils/Env","moxie/core/utils/Dom","moxie/core/Exceptions","moxie/core/EventTarget","moxie/core/utils/Encode","moxie/runtime/Runtime","moxie/runtime/RuntimeClient","moxie/file/Blob","moxie/file/File","moxie/file/FileInput","moxie/file/FileDrop","moxie/runtime/RuntimeTarget","moxie/file/FileReader","moxie/core/utils/Url","moxie/file/FileReaderSync","moxie/xhr/FormData","moxie/xhr/XMLHttpRequest","moxie/runtime/Transporter","moxie/image/Image","moxie/core/utils/Events"]);
+})(this);/**
+ * o.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+/*global moxie:true */
+
+/**
+Globally exposed namespace with the most frequently used public classes and handy methods.
+
+@class o
+@static
+@private
+*/
+(function(exports) {
+	"use strict";
+
+	var o = {}, inArray = exports.moxie.core.utils.Basic.inArray;
+
+	// directly add some public classes
+	// (we do it dynamically here, since for custom builds we cannot know beforehand what modules were included)
+	(function addAlias(ns) {
+		var name, itemType;
+		for (name in ns) {
+			itemType = typeof(ns[name]);
+			if (itemType === 'object' && !~inArray(name, ['Exceptions', 'Env', 'Mime'])) {
+				addAlias(ns[name]);
+			} else if (itemType === 'function') {
+				o[name] = ns[name];
+			}
+		}
+	})(exports.moxie);
+
+	// add some manually
+	o.Env = exports.moxie.core.utils.Env;
+	o.Mime = exports.moxie.core.utils.Mime;
+	o.Exceptions = exports.moxie.core.Exceptions;
+
+	// expose globally
+	exports.mOxie = o;
+	if (!exports.o) {
+		exports.o = o;
+	}
+	return o;
+})(this);
Index: /trunk/themes/default/js/plugins/plupload/moxie.min.js
===================================================================
--- /trunk/themes/default/js/plugins/plupload/moxie.min.js	(revision 28545)
+++ /trunk/themes/default/js/plugins/plupload/moxie.min.js	(revision 28545)
@@ -0,0 +1,15 @@
+/**
+ * mOxie - multi-runtime File API & XMLHttpRequest L2 Polyfill
+ * v1.2.1
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ *
+ * Date: 2014-05-14
+ */
+!function(e,t){"use strict";function n(e,t){for(var n,i=[],r=0;r<e.length;++r){if(n=s[e[r]]||o(e[r]),!n)throw"module definition dependecy not found: "+e[r];i.push(n)}t.apply(null,i)}function i(e,i,r){if("string"!=typeof e)throw"invalid module definition, module id must be defined and be a string";if(i===t)throw"invalid module definition, dependencies must be specified";if(r===t)throw"invalid module definition, definition function must be specified";n(i,function(){s[e]=r.apply(null,arguments)})}function r(e){return!!s[e]}function o(t){for(var n=e,i=t.split(/[.\/]/),r=0;r<i.length;++r){if(!n[i[r]])return;n=n[i[r]]}return n}function a(n){for(var i=0;i<n.length;i++){for(var r=e,o=n[i],a=o.split(/[.\/]/),u=0;u<a.length-1;++u)r[a[u]]===t&&(r[a[u]]={}),r=r[a[u]];r[a[a.length-1]]=s[o]}}var s={},u="moxie/core/utils/Basic",c="moxie/core/I18n",l="moxie/core/utils/Mime",d="moxie/core/utils/Env",f="moxie/core/utils/Dom",h="moxie/core/Exceptions",p="moxie/core/EventTarget",m="moxie/core/utils/Encode",g="moxie/runtime/Runtime",v="moxie/runtime/RuntimeClient",y="moxie/file/Blob",w="moxie/file/File",E="moxie/file/FileInput",_="moxie/file/FileDrop",x="moxie/runtime/RuntimeTarget",b="moxie/file/FileReader",R="moxie/core/utils/Url",T="moxie/file/FileReaderSync",A="moxie/xhr/FormData",S="moxie/xhr/XMLHttpRequest",O="moxie/runtime/Transporter",I="moxie/image/Image",D="moxie/runtime/html5/Runtime",N="moxie/runtime/html5/file/Blob",L="moxie/core/utils/Events",M="moxie/runtime/html5/file/FileInput",C="moxie/runtime/html5/file/FileDrop",F="moxie/runtime/html5/file/FileReader",H="moxie/runtime/html5/xhr/XMLHttpRequest",P="moxie/runtime/html5/utils/BinaryReader",k="moxie/runtime/html5/image/JPEGHeaders",U="moxie/runtime/html5/image/ExifParser",B="moxie/runtime/html5/image/JPEG",z="moxie/runtime/html5/image/PNG",G="moxie/runtime/html5/image/ImageInfo",q="moxie/runtime/html5/image/MegaPixel",X="moxie/runtime/html5/image/Image",j="moxie/runtime/flash/Runtime",V="moxie/runtime/flash/file/Blob",W="moxie/runtime/flash/file/FileInput",Y="moxie/runtime/flash/file/FileReader",$="moxie/runtime/flash/file/FileReaderSync",J="moxie/runtime/flash/xhr/XMLHttpRequest",Z="moxie/runtime/flash/runtime/Transporter",K="moxie/runtime/flash/image/Image",Q="moxie/runtime/silverlight/Runtime",et="moxie/runtime/silverlight/file/Blob",tt="moxie/runtime/silverlight/file/FileInput",nt="moxie/runtime/silverlight/file/FileDrop",it="moxie/runtime/silverlight/file/FileReader",rt="moxie/runtime/silverlight/file/FileReaderSync",ot="moxie/runtime/silverlight/xhr/XMLHttpRequest",at="moxie/runtime/silverlight/runtime/Transporter",st="moxie/runtime/silverlight/image/Image",ut="moxie/runtime/html4/Runtime",ct="moxie/runtime/html4/file/FileInput",lt="moxie/runtime/html4/file/FileReader",dt="moxie/runtime/html4/xhr/XMLHttpRequest",ft="moxie/runtime/html4/image/Image";i(u,[],function(){var e=function(e){var t;return e===t?"undefined":null===e?"null":e.nodeType?"node":{}.toString.call(e).match(/\s([a-z|A-Z]+)/)[1].toLowerCase()},t=function(i){var r;return n(arguments,function(o,s){s>0&&n(o,function(n,o){n!==r&&(e(i[o])===e(n)&&~a(e(n),["array","object"])?t(i[o],n):i[o]=n)})}),i},n=function(e,t){var n,i,r,o;if(e){try{n=e.length}catch(a){n=o}if(n===o){for(i in e)if(e.hasOwnProperty(i)&&t(e[i],i)===!1)return}else for(r=0;n>r;r++)if(t(e[r],r)===!1)return}},i=function(t){var n;if(!t||"object"!==e(t))return!0;for(n in t)return!1;return!0},r=function(t,n){function i(r){"function"===e(t[r])&&t[r](function(e){++r<o&&!e?i(r):n(e)})}var r=0,o=t.length;"function"!==e(n)&&(n=function(){}),t&&t.length||n(),i(r)},o=function(e,t){var i=0,r=e.length,o=new Array(r);n(e,function(e,n){e(function(e){if(e)return t(e);var a=[].slice.call(arguments);a.shift(),o[n]=a,i++,i===r&&(o.unshift(null),t.apply(this,o))})})},a=function(e,t){if(t){if(Array.prototype.indexOf)return Array.prototype.indexOf.call(t,e);for(var n=0,i=t.length;i>n;n++)if(t[n]===e)return n}return-1},s=function(t,n){var i=[];"array"!==e(t)&&(t=[t]),"array"!==e(n)&&(n=[n]);for(var r in t)-1===a(t[r],n)&&i.push(t[r]);return i.length?i:!1},u=function(e,t){var i=[];return n(e,function(e){-1!==a(e,t)&&i.push(e)}),i.length?i:null},c=function(e){var t,n=[];for(t=0;t<e.length;t++)n[t]=e[t];return n},l=function(){var e=0;return function(t){var n=(new Date).getTime().toString(32),i;for(i=0;5>i;i++)n+=Math.floor(65535*Math.random()).toString(32);return(t||"o_")+n+(e++).toString(32)}}(),d=function(e){return e?String.prototype.trim?String.prototype.trim.call(e):e.toString().replace(/^\s*/,"").replace(/\s*$/,""):e},f=function(e){if("string"!=typeof e)return e;var t={t:1099511627776,g:1073741824,m:1048576,k:1024},n;return e=/^([0-9]+)([mgk]?)$/.exec(e.toLowerCase().replace(/[^0-9mkg]/g,"")),n=e[2],e=+e[1],t.hasOwnProperty(n)&&(e*=t[n]),e};return{guid:l,typeOf:e,extend:t,each:n,isEmptyObj:i,inSeries:r,inParallel:o,inArray:a,arrayDiff:s,arrayIntersect:u,toArray:c,trim:d,parseSizeStr:f}}),i(c,[u],function(e){var t={};return{addI18n:function(n){return e.extend(t,n)},translate:function(e){return t[e]||e},_:function(e){return this.translate(e)},sprintf:function(t){var n=[].slice.call(arguments,1);return t.replace(/%[a-z]/g,function(){var t=n.shift();return"undefined"!==e.typeOf(t)?t:""})}}}),i(l,[u,c],function(e,t){var n="application/msword,doc dot,application/pdf,pdf,application/pgp-signature,pgp,application/postscript,ps ai eps,application/rtf,rtf,application/vnd.ms-excel,xls xlb,application/vnd.ms-powerpoint,ppt pps pot,application/zip,zip,application/x-shockwave-flash,swf swfl,application/vnd.openxmlformats-officedocument.wordprocessingml.document,docx,application/vnd.openxmlformats-officedocument.wordprocessingml.template,dotx,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,xlsx,application/vnd.openxmlformats-officedocument.presentationml.presentation,pptx,application/vnd.openxmlformats-officedocument.presentationml.template,potx,application/vnd.openxmlformats-officedocument.presentationml.slideshow,ppsx,application/x-javascript,js,application/json,json,audio/mpeg,mp3 mpga mpega mp2,audio/x-wav,wav,audio/x-m4a,m4a,audio/ogg,oga ogg,audio/aiff,aiff aif,audio/flac,flac,audio/aac,aac,audio/ac3,ac3,audio/x-ms-wma,wma,image/bmp,bmp,image/gif,gif,image/jpeg,jpg jpeg jpe,image/photoshop,psd,image/png,png,image/svg+xml,svg svgz,image/tiff,tiff tif,text/plain,asc txt text diff log,text/html,htm html xhtml,text/css,css,text/csv,csv,text/rtf,rtf,video/mpeg,mpeg mpg mpe m2v,video/quicktime,qt mov,video/mp4,mp4,video/x-m4v,m4v,video/x-flv,flv,video/x-ms-wmv,wmv,video/avi,avi,video/webm,webm,video/3gpp,3gpp 3gp,video/3gpp2,3g2,video/vnd.rn-realvideo,rv,video/ogg,ogv,video/x-matroska,mkv,application/vnd.oasis.opendocument.formula-template,otf,application/octet-stream,exe",i={mimes:{},extensions:{},addMimeType:function(e){var t=e.split(/,/),n,i,r;for(n=0;n<t.length;n+=2){for(r=t[n+1].split(/ /),i=0;i<r.length;i++)this.mimes[r[i]]=t[n];this.extensions[t[n]]=r}},extList2mimes:function(t,n){var i=this,r,o,a,s,u=[];for(o=0;o<t.length;o++)for(r=t[o].extensions.split(/\s*,\s*/),a=0;a<r.length;a++){if("*"===r[a])return[];if(s=i.mimes[r[a]])-1===e.inArray(s,u)&&u.push(s);else{if(!n||!/^\w+$/.test(r[a]))return[];u.push("."+r[a])}}return u},mimes2exts:function(t){var n=this,i=[];return e.each(t,function(t){if("*"===t)return i=[],!1;var r=t.match(/^(\w+)\/(\*|\w+)$/);r&&("*"===r[2]?e.each(n.extensions,function(e,t){new RegExp("^"+r[1]+"/").test(t)&&[].push.apply(i,n.extensions[t])}):n.extensions[t]&&[].push.apply(i,n.extensions[t]))}),i},mimes2extList:function(n){var i=[],r=[];return"string"===e.typeOf(n)&&(n=e.trim(n).split(/\s*,\s*/)),r=this.mimes2exts(n),i.push({title:t.translate("Files"),extensions:r.length?r.join(","):"*"}),i.mimes=n,i},getFileExtension:function(e){var t=e&&e.match(/\.([^.]+)$/);return t?t[1].toLowerCase():""},getFileMime:function(e){return this.mimes[this.getFileExtension(e)]||""}};return i.addMimeType(n),i}),i(d,[u],function(e){function t(e,t,n){var i=0,r=0,o=0,a={dev:-6,alpha:-5,a:-5,beta:-4,b:-4,RC:-3,rc:-3,"#":-2,p:1,pl:1},s=function(e){return e=(""+e).replace(/[_\-+]/g,"."),e=e.replace(/([^.\d]+)/g,".$1.").replace(/\.{2,}/g,"."),e.length?e.split("."):[-8]},u=function(e){return e?isNaN(e)?a[e]||-7:parseInt(e,10):0};for(e=s(e),t=s(t),r=Math.max(e.length,t.length),i=0;r>i;i++)if(e[i]!=t[i]){if(e[i]=u(e[i]),t[i]=u(t[i]),e[i]<t[i]){o=-1;break}if(e[i]>t[i]){o=1;break}}if(!n)return o;switch(n){case">":case"gt":return o>0;case">=":case"ge":return o>=0;case"<=":case"le":return 0>=o;case"==":case"=":case"eq":return 0===o;case"<>":case"!=":case"ne":return 0!==o;case"":case"<":case"lt":return 0>o;default:return null}}var n=function(e){var t="",n="?",i="function",r="undefined",o="object",a="major",s="model",u="name",c="type",l="vendor",d="version",f="architecture",h="console",p="mobile",m="tablet",g={has:function(e,t){return-1!==t.toLowerCase().indexOf(e.toLowerCase())},lowerize:function(e){return e.toLowerCase()}},v={rgx:function(){for(var t,n=0,a,s,u,c,l,d,f=arguments;n<f.length;n+=2){var h=f[n],p=f[n+1];if(typeof t===r){t={};for(u in p)c=p[u],typeof c===o?t[c[0]]=e:t[c]=e}for(a=s=0;a<h.length;a++)if(l=h[a].exec(this.getUA())){for(u=0;u<p.length;u++)d=l[++s],c=p[u],typeof c===o&&c.length>0?2==c.length?t[c[0]]=typeof c[1]==i?c[1].call(this,d):c[1]:3==c.length?t[c[0]]=typeof c[1]!==i||c[1].exec&&c[1].test?d?d.replace(c[1],c[2]):e:d?c[1].call(this,d,c[2]):e:4==c.length&&(t[c[0]]=d?c[3].call(this,d.replace(c[1],c[2])):e):t[c]=d?d:e;break}if(l)break}return t},str:function(t,i){for(var r in i)if(typeof i[r]===o&&i[r].length>0){for(var a=0;a<i[r].length;a++)if(g.has(i[r][a],t))return r===n?e:r}else if(g.has(i[r],t))return r===n?e:r;return t}},y={browser:{oldsafari:{major:{1:["/8","/1","/3"],2:"/4","?":"/"},version:{"1.0":"/8",1.2:"/1",1.3:"/3","2.0":"/412","2.0.2":"/416","2.0.3":"/417","2.0.4":"/419","?":"/"}}},device:{sprint:{model:{"Evo Shift 4G":"7373KT"},vendor:{HTC:"APA",Sprint:"Sprint"}}},os:{windows:{version:{ME:"4.90","NT 3.11":"NT3.51","NT 4.0":"NT4.0",2000:"NT 5.0",XP:["NT 5.1","NT 5.2"],Vista:"NT 6.0",7:"NT 6.1",8:"NT 6.2",8.1:"NT 6.3",RT:"ARM"}}}},w={browser:[[/(opera\smini)\/((\d+)?[\w\.-]+)/i,/(opera\s[mobiletab]+).+version\/((\d+)?[\w\.-]+)/i,/(opera).+version\/((\d+)?[\w\.]+)/i,/(opera)[\/\s]+((\d+)?[\w\.]+)/i],[u,d,a],[/\s(opr)\/((\d+)?[\w\.]+)/i],[[u,"Opera"],d,a],[/(kindle)\/((\d+)?[\w\.]+)/i,/(lunascape|maxthon|netfront|jasmine|blazer)[\/\s]?((\d+)?[\w\.]+)*/i,/(avant\s|iemobile|slim|baidu)(?:browser)?[\/\s]?((\d+)?[\w\.]*)/i,/(?:ms|\()(ie)\s((\d+)?[\w\.]+)/i,/(rekonq)((?:\/)[\w\.]+)*/i,/(chromium|flock|rockmelt|midori|epiphany|silk|skyfire|ovibrowser|bolt|iron)\/((\d+)?[\w\.-]+)/i],[u,d,a],[/(trident).+rv[:\s]((\d+)?[\w\.]+).+like\sgecko/i],[[u,"IE"],d,a],[/(yabrowser)\/((\d+)?[\w\.]+)/i],[[u,"Yandex"],d,a],[/(comodo_dragon)\/((\d+)?[\w\.]+)/i],[[u,/_/g," "],d,a],[/(chrome|omniweb|arora|[tizenoka]{5}\s?browser)\/v?((\d+)?[\w\.]+)/i],[u,d,a],[/(dolfin)\/((\d+)?[\w\.]+)/i],[[u,"Dolphin"],d,a],[/((?:android.+)crmo|crios)\/((\d+)?[\w\.]+)/i],[[u,"Chrome"],d,a],[/((?:android.+))version\/((\d+)?[\w\.]+)\smobile\ssafari/i],[[u,"Android Browser"],d,a],[/version\/((\d+)?[\w\.]+).+?mobile\/\w+\s(safari)/i],[d,a,[u,"Mobile Safari"]],[/version\/((\d+)?[\w\.]+).+?(mobile\s?safari|safari)/i],[d,a,u],[/webkit.+?(mobile\s?safari|safari)((\/[\w\.]+))/i],[u,[a,v.str,y.browser.oldsafari.major],[d,v.str,y.browser.oldsafari.version]],[/(konqueror)\/((\d+)?[\w\.]+)/i,/(webkit|khtml)\/((\d+)?[\w\.]+)/i],[u,d,a],[/(navigator|netscape)\/((\d+)?[\w\.-]+)/i],[[u,"Netscape"],d,a],[/(swiftfox)/i,/(icedragon|iceweasel|camino|chimera|fennec|maemo\sbrowser|minimo|conkeror)[\/\s]?((\d+)?[\w\.\+]+)/i,/(firefox|seamonkey|k-meleon|icecat|iceape|firebird|phoenix)\/((\d+)?[\w\.-]+)/i,/(mozilla)\/((\d+)?[\w\.]+).+rv\:.+gecko\/\d+/i,/(uc\s?browser|polaris|lynx|dillo|icab|doris|amaya|w3m|netsurf|qqbrowser)[\/\s]?((\d+)?[\w\.]+)/i,/(links)\s\(((\d+)?[\w\.]+)/i,/(gobrowser)\/?((\d+)?[\w\.]+)*/i,/(ice\s?browser)\/v?((\d+)?[\w\._]+)/i,/(mosaic)[\/\s]((\d+)?[\w\.]+)/i],[u,d,a]],engine:[[/(presto)\/([\w\.]+)/i,/(webkit|trident|netfront|netsurf|amaya|lynx|w3m)\/([\w\.]+)/i,/(khtml|tasman|links)[\/\s]\(?([\w\.]+)/i,/(icab)[\/\s]([23]\.[\d\.]+)/i],[u,d],[/rv\:([\w\.]+).*(gecko)/i],[d,u]],os:[[/(windows)\snt\s6\.2;\s(arm)/i,/(windows\sphone(?:\sos)*|windows\smobile|windows)[\s\/]?([ntce\d\.\s]+\w)/i],[u,[d,v.str,y.os.windows.version]],[/(win(?=3|9|n)|win\s9x\s)([nt\d\.]+)/i],[[u,"Windows"],[d,v.str,y.os.windows.version]],[/\((bb)(10);/i],[[u,"BlackBerry"],d],[/(blackberry)\w*\/?([\w\.]+)*/i,/(tizen)\/([\w\.]+)/i,/(android|webos|palm\os|qnx|bada|rim\stablet\sos|meego)[\/\s-]?([\w\.]+)*/i],[u,d],[/(symbian\s?os|symbos|s60(?=;))[\/\s-]?([\w\.]+)*/i],[[u,"Symbian"],d],[/mozilla.+\(mobile;.+gecko.+firefox/i],[[u,"Firefox OS"],d],[/(nintendo|playstation)\s([wids3portablevu]+)/i,/(mint)[\/\s\(]?(\w+)*/i,/(joli|[kxln]?ubuntu|debian|[open]*suse|gentoo|arch|slackware|fedora|mandriva|centos|pclinuxos|redhat|zenwalk)[\/\s-]?([\w\.-]+)*/i,/(hurd|linux)\s?([\w\.]+)*/i,/(gnu)\s?([\w\.]+)*/i],[u,d],[/(cros)\s[\w]+\s([\w\.]+\w)/i],[[u,"Chromium OS"],d],[/(sunos)\s?([\w\.]+\d)*/i],[[u,"Solaris"],d],[/\s([frentopc-]{0,4}bsd|dragonfly)\s?([\w\.]+)*/i],[u,d],[/(ip[honead]+)(?:.*os\s*([\w]+)*\slike\smac|;\sopera)/i],[[u,"iOS"],[d,/_/g,"."]],[/(mac\sos\sx)\s?([\w\s\.]+\w)*/i],[u,[d,/_/g,"."]],[/(haiku)\s(\w+)/i,/(aix)\s((\d)(?=\.|\)|\s)[\w\.]*)*/i,/(macintosh|mac(?=_powerpc)|plan\s9|minix|beos|os\/2|amigaos|morphos|risc\sos)/i,/(unix)\s?([\w\.]+)*/i],[u,d]]},E=function(e){var n=e||(window&&window.navigator&&window.navigator.userAgent?window.navigator.userAgent:t);this.getBrowser=function(){return v.rgx.apply(this,w.browser)},this.getEngine=function(){return v.rgx.apply(this,w.engine)},this.getOS=function(){return v.rgx.apply(this,w.os)},this.getResult=function(){return{ua:this.getUA(),browser:this.getBrowser(),engine:this.getEngine(),os:this.getOS()}},this.getUA=function(){return n},this.setUA=function(e){return n=e,this},this.setUA(n)};return(new E).getResult()}(),i=function(){var t={define_property:function(){return!1}(),create_canvas:function(){var e=document.createElement("canvas");return!(!e.getContext||!e.getContext("2d"))}(),return_response_type:function(t){try{if(-1!==e.inArray(t,["","text","document"]))return!0;if(window.XMLHttpRequest){var n=new XMLHttpRequest;if(n.open("get","/"),"responseType"in n)return n.responseType=t,n.responseType!==t?!1:!0}}catch(i){}return!1},use_data_uri:function(){var e=new Image;return e.onload=function(){t.use_data_uri=1===e.width&&1===e.height},setTimeout(function(){e.src="data:image/gif;base64,R0lGODlhAQABAIAAAP8AAAAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw=="},1),!1}(),use_data_uri_over32kb:function(){return t.use_data_uri&&("IE"!==r.browser||r.version>=9)},use_data_uri_of:function(e){return t.use_data_uri&&33e3>e||t.use_data_uri_over32kb()},use_fileinput:function(){var e=document.createElement("input");return e.setAttribute("type","file"),!e.disabled}};return function(n){var i=[].slice.call(arguments);return i.shift(),"function"===e.typeOf(t[n])?t[n].apply(this,i):!!t[n]}}(),r={can:i,browser:n.browser.name,version:parseFloat(n.browser.major),os:n.os.name,osVersion:n.os.version,verComp:t,swf_url:"../flash/Moxie.swf",xap_url:"../silverlight/Moxie.xap",global_event_dispatcher:"moxie.core.EventTarget.instance.dispatchEvent"};return r.OS=r.os,r}),i(f,[d],function(e){var t=function(e){return"string"!=typeof e?e:document.getElementById(e)},n=function(e,t){if(!e.className)return!1;var n=new RegExp("(^|\\s+)"+t+"(\\s+|$)");return n.test(e.className)},i=function(e,t){n(e,t)||(e.className=e.className?e.className.replace(/\s+$/,"")+" "+t:t)},r=function(e,t){if(e.className){var n=new RegExp("(^|\\s+)"+t+"(\\s+|$)");e.className=e.className.replace(n,function(e,t,n){return" "===t&&" "===n?" ":""})}},o=function(e,t){return e.currentStyle?e.currentStyle[t]:window.getComputedStyle?window.getComputedStyle(e,null)[t]:void 0},a=function(t,n){function i(e){var t,n,i=0,r=0;return e&&(n=e.getBoundingClientRect(),t="CSS1Compat"===s.compatMode?s.documentElement:s.body,i=n.left+t.scrollLeft,r=n.top+t.scrollTop),{x:i,y:r}}var r=0,o=0,a,s=document,u,c;if(t=t,n=n||s.body,t&&t.getBoundingClientRect&&"IE"===e.browser&&(!s.documentMode||s.documentMode<8))return u=i(t),c=i(n),{x:u.x-c.x,y:u.y-c.y};for(a=t;a&&a!=n&&a.nodeType;)r+=a.offsetLeft||0,o+=a.offsetTop||0,a=a.offsetParent;for(a=t.parentNode;a&&a!=n&&a.nodeType;)r-=a.scrollLeft||0,o-=a.scrollTop||0,a=a.parentNode;return{x:r,y:o}},s=function(e){return{w:e.offsetWidth||e.clientWidth,h:e.offsetHeight||e.clientHeight}};return{get:t,hasClass:n,addClass:i,removeClass:r,getStyle:o,getPos:a,getSize:s}}),i(h,[u],function(e){function t(e,t){var n;for(n in e)if(e[n]===t)return n;return null}return{RuntimeError:function(){function n(e){this.code=e,this.name=t(i,e),this.message=this.name+": RuntimeError "+this.code}var i={NOT_INIT_ERR:1,NOT_SUPPORTED_ERR:9,JS_ERR:4};return e.extend(n,i),n.prototype=Error.prototype,n}(),OperationNotAllowedException:function(){function t(e){this.code=e,this.name="OperationNotAllowedException"}return e.extend(t,{NOT_ALLOWED_ERR:1}),t.prototype=Error.prototype,t}(),ImageError:function(){function n(e){this.code=e,this.name=t(i,e),this.message=this.name+": ImageError "+this.code}var i={WRONG_FORMAT:1,MAX_RESOLUTION_ERR:2};return e.extend(n,i),n.prototype=Error.prototype,n}(),FileException:function(){function n(e){this.code=e,this.name=t(i,e),this.message=this.name+": FileException "+this.code}var i={NOT_FOUND_ERR:1,SECURITY_ERR:2,ABORT_ERR:3,NOT_READABLE_ERR:4,ENCODING_ERR:5,NO_MODIFICATION_ALLOWED_ERR:6,INVALID_STATE_ERR:7,SYNTAX_ERR:8};return e.extend(n,i),n.prototype=Error.prototype,n}(),DOMException:function(){function n(e){this.code=e,this.name=t(i,e),this.message=this.name+": DOMException "+this.code}var i={INDEX_SIZE_ERR:1,DOMSTRING_SIZE_ERR:2,HIERARCHY_REQUEST_ERR:3,WRONG_DOCUMENT_ERR:4,INVALID_CHARACTER_ERR:5,NO_DATA_ALLOWED_ERR:6,NO_MODIFICATION_ALLOWED_ERR:7,NOT_FOUND_ERR:8,NOT_SUPPORTED_ERR:9,INUSE_ATTRIBUTE_ERR:10,INVALID_STATE_ERR:11,SYNTAX_ERR:12,INVALID_MODIFICATION_ERR:13,NAMESPACE_ERR:14,INVALID_ACCESS_ERR:15,VALIDATION_ERR:16,TYPE_MISMATCH_ERR:17,SECURITY_ERR:18,NETWORK_ERR:19,ABORT_ERR:20,URL_MISMATCH_ERR:21,QUOTA_EXCEEDED_ERR:22,TIMEOUT_ERR:23,INVALID_NODE_TYPE_ERR:24,DATA_CLONE_ERR:25};return e.extend(n,i),n.prototype=Error.prototype,n}(),EventException:function(){function t(e){this.code=e,this.name="EventException"}return e.extend(t,{UNSPECIFIED_EVENT_TYPE_ERR:0}),t.prototype=Error.prototype,t}()}}),i(p,[h,u],function(e,t){function n(){var n={};t.extend(this,{uid:null,init:function(){this.uid||(this.uid=t.guid("uid_"))},addEventListener:function(e,i,r,o){var a=this,s;return e=t.trim(e),/\s/.test(e)?void t.each(e.split(/\s+/),function(e){a.addEventListener(e,i,r,o)}):(e=e.toLowerCase(),r=parseInt(r,10)||0,s=n[this.uid]&&n[this.uid][e]||[],s.push({fn:i,priority:r,scope:o||this}),n[this.uid]||(n[this.uid]={}),void(n[this.uid][e]=s))},hasEventListener:function(e){return e?!(!n[this.uid]||!n[this.uid][e]):!!n[this.uid]},removeEventListener:function(e,i){e=e.toLowerCase();var r=n[this.uid]&&n[this.uid][e],o;if(r){if(i){for(o=r.length-1;o>=0;o--)if(r[o].fn===i){r.splice(o,1);break}}else r=[];r.length||(delete n[this.uid][e],t.isEmptyObj(n[this.uid])&&delete n[this.uid])}},removeAllEventListeners:function(){n[this.uid]&&delete n[this.uid]},dispatchEvent:function(i){var r,o,a,s,u={},c=!0,l;if("string"!==t.typeOf(i)){if(s=i,"string"!==t.typeOf(s.type))throw new e.EventException(e.EventException.UNSPECIFIED_EVENT_TYPE_ERR);i=s.type,s.total!==l&&s.loaded!==l&&(u.total=s.total,u.loaded=s.loaded),u.async=s.async||!1}if(-1!==i.indexOf("::")?!function(e){r=e[0],i=e[1]}(i.split("::")):r=this.uid,i=i.toLowerCase(),o=n[r]&&n[r][i]){o.sort(function(e,t){return t.priority-e.priority}),a=[].slice.call(arguments),a.shift(),u.type=i,a.unshift(u);var d=[];t.each(o,function(e){a[0].target=e.scope,d.push(u.async?function(t){setTimeout(function(){t(e.fn.apply(e.scope,a)===!1)},1)}:function(t){t(e.fn.apply(e.scope,a)===!1)})}),d.length&&t.inSeries(d,function(e){c=!e})}return c},bind:function(){this.addEventListener.apply(this,arguments)},unbind:function(){this.removeEventListener.apply(this,arguments)},unbindAll:function(){this.removeAllEventListeners.apply(this,arguments)},trigger:function(){return this.dispatchEvent.apply(this,arguments)},convertEventPropsToHandlers:function(e){var n;"array"!==t.typeOf(e)&&(e=[e]);for(var i=0;i<e.length;i++)n="on"+e[i],"function"===t.typeOf(this[n])?this.addEventListener(e[i],this[n]):"undefined"===t.typeOf(this[n])&&(this[n]=null)}})}return n.instance=new n,n}),i(m,[],function(){var e=function(e){return unescape(encodeURIComponent(e))},t=function(e){return decodeURIComponent(escape(e))},n=function(e,n){if("function"==typeof window.atob)return n?t(window.atob(e)):window.atob(e);var i="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",r,o,a,s,u,c,l,d,f=0,h=0,p="",m=[];if(!e)return e;e+="";do s=i.indexOf(e.charAt(f++)),u=i.indexOf(e.charAt(f++)),c=i.indexOf(e.charAt(f++)),l=i.indexOf(e.charAt(f++)),d=s<<18|u<<12|c<<6|l,r=d>>16&255,o=d>>8&255,a=255&d,m[h++]=64==c?String.fromCharCode(r):64==l?String.fromCharCode(r,o):String.fromCharCode(r,o,a);while(f<e.length);return p=m.join(""),n?t(p):p},i=function(t,n){if(n&&e(t),"function"==typeof window.btoa)return window.btoa(t);var i="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",r,o,a,s,u,c,l,d,f=0,h=0,p="",m=[];if(!t)return t;do r=t.charCodeAt(f++),o=t.charCodeAt(f++),a=t.charCodeAt(f++),d=r<<16|o<<8|a,s=d>>18&63,u=d>>12&63,c=d>>6&63,l=63&d,m[h++]=i.charAt(s)+i.charAt(u)+i.charAt(c)+i.charAt(l);while(f<t.length);p=m.join("");var g=t.length%3;return(g?p.slice(0,g-3):p)+"===".slice(g||3)};return{utf8_encode:e,utf8_decode:t,atob:n,btoa:i}}),i(g,[u,f,p],function(e,t,n){function i(n,r,a,s,u){var c=this,l,d=e.guid(r+"_"),f=u||"browser";n=n||{},o[d]=this,a=e.extend({access_binary:!1,access_image_binary:!1,display_media:!1,do_cors:!1,drag_and_drop:!1,filter_by_extension:!0,resize_image:!1,report_upload_progress:!1,return_response_headers:!1,return_response_type:!1,return_status_code:!0,send_custom_headers:!1,select_file:!1,select_folder:!1,select_multiple:!0,send_binary_string:!1,send_browser_cookies:!0,send_multipart:!0,slice_blob:!1,stream_upload:!1,summon_file_dialog:!1,upload_filesize:!0,use_http_method:!0},a),n.preferred_caps&&(f=i.getMode(s,n.preferred_caps,f)),l=function(){var t={};return{exec:function(e,n,i,r){return l[n]&&(t[e]||(t[e]={context:this,instance:new l[n]}),t[e].instance[i])?t[e].instance[i].apply(this,r):void 0},removeInstance:function(e){delete t[e]},removeAllInstances:function(){var n=this;e.each(t,function(t,i){"function"===e.typeOf(t.instance.destroy)&&t.instance.destroy.call(t.context),n.removeInstance(i)})}}}(),e.extend(this,{initialized:!1,uid:d,type:r,mode:i.getMode(s,n.required_caps,f),shimid:d+"_container",clients:0,options:n,can:function(t,n){var r=arguments[2]||a;if("string"===e.typeOf(t)&&"undefined"===e.typeOf(n)&&(t=i.parseCaps(t)),"object"===e.typeOf(t)){for(var o in t)if(!this.can(o,t[o],r))return!1;return!0}return"function"===e.typeOf(r[t])?r[t].call(this,n):n===r[t]},getShimContainer:function(){var n,i=t.get(this.shimid);return i||(n=this.options.container?t.get(this.options.container):document.body,i=document.createElement("div"),i.id=this.shimid,i.className="moxie-shim moxie-shim-"+this.type,e.extend(i.style,{position:"absolute",top:"0px",left:"0px",width:"1px",height:"1px",overflow:"hidden"}),n.appendChild(i),n=null),i},getShim:function(){return l},shimExec:function(e,t){var n=[].slice.call(arguments,2);return c.getShim().exec.call(this,this.uid,e,t,n)},exec:function(e,t){var n=[].slice.call(arguments,2);return c[e]&&c[e][t]?c[e][t].apply(this,n):c.shimExec.apply(this,arguments)},destroy:function(){if(c){var e=t.get(this.shimid);e&&e.parentNode.removeChild(e),l&&l.removeAllInstances(),this.unbindAll(),delete o[this.uid],this.uid=null,d=c=l=e=null}}}),this.mode&&n.required_caps&&!this.can(n.required_caps)&&(this.mode=!1)}var r={},o={};return i.order="html5,flash,silverlight,html4",i.getRuntime=function(e){return o[e]?o[e]:!1},i.addConstructor=function(e,t){t.prototype=n.instance,r[e]=t},i.getConstructor=function(e){return r[e]||null},i.getInfo=function(e){var t=i.getRuntime(e);return t?{uid:t.uid,type:t.type,mode:t.mode,can:function(){return t.can.apply(t,arguments)}}:null},i.parseCaps=function(t){var n={};return"string"!==e.typeOf(t)?t||{}:(e.each(t.split(","),function(e){n[e]=!0}),n)},i.can=function(e,t){var n,r=i.getConstructor(e),o;return r?(n=new r({required_caps:t}),o=n.mode,n.destroy(),!!o):!1},i.thatCan=function(e,t){var n=(t||i.order).split(/\s*,\s*/);for(var r in n)if(i.can(n[r],e))return n[r];return null},i.getMode=function(t,n,i){var r=null;if("undefined"===e.typeOf(i)&&(i="browser"),n&&!e.isEmptyObj(t)){if(e.each(n,function(n,i){if(t.hasOwnProperty(i)){var o=t[i](n);if("string"==typeof o&&(o=[o]),r){if(!(r=e.arrayIntersect(r,o)))return r=!1}else r=o}}),r)return-1!==e.inArray(i,r)?i:r[0];if(r===!1)return!1}return i},i.capTrue=function(){return!0},i.capFalse=function(){return!1},i.capTest=function(e){return function(){return!!e}},i}),i(v,[h,u,g],function(e,t,n){return function i(){var i;t.extend(this,{connectRuntime:function(r){function o(t){var s,u;return t.length?(s=t.shift(),(u=n.getConstructor(s))?(i=new u(r),i.bind("Init",function(){i.initialized=!0,setTimeout(function(){i.clients++,a.trigger("RuntimeInit",i)},1)}),i.bind("Error",function(){i.destroy(),o(t)}),i.mode?void i.init():void i.trigger("Error")):void o(t)):(a.trigger("RuntimeError",new e.RuntimeError(e.RuntimeError.NOT_INIT_ERR)),void(i=null))}var a=this,s;if("string"===t.typeOf(r)?s=r:"string"===t.typeOf(r.ruid)&&(s=r.ruid),s){if(i=n.getRuntime(s))return i.clients++,i;throw new e.RuntimeError(e.RuntimeError.NOT_INIT_ERR)}o((r.runtime_order||n.order).split(/\s*,\s*/))},getRuntime:function(){return i&&i.uid?i:(i=null,null)},disconnectRuntime:function(){i&&--i.clients<=0&&(i.destroy(),i=null)}})}}),i(y,[u,m,v],function(e,t,n){function i(o,a){function s(t,n,o){var a,s=r[this.uid];return"string"===e.typeOf(s)&&s.length?(a=new i(null,{type:o,size:n-t}),a.detach(s.substr(t,a.size)),a):null}n.call(this),o&&this.connectRuntime(o),a?"string"===e.typeOf(a)&&(a={data:a}):a={},e.extend(this,{uid:a.uid||e.guid("uid_"),ruid:o,size:a.size||0,type:a.type||"",slice:function(e,t,n){return this.isDetached()?s.apply(this,arguments):this.getRuntime().exec.call(this,"Blob","slice",this.getSource(),e,t,n)},getSource:function(){return r[this.uid]?r[this.uid]:null},detach:function(e){this.ruid&&(this.getRuntime().exec.call(this,"Blob","destroy"),this.disconnectRuntime(),this.ruid=null),e=e||"";var n=e.match(/^data:([^;]*);base64,/);n&&(this.type=n[1],e=t.atob(e.substring(e.indexOf("base64,")+7))),this.size=e.length,r[this.uid]=e},isDetached:function(){return!this.ruid&&"string"===e.typeOf(r[this.uid])},destroy:function(){this.detach(),delete r[this.uid]}}),a.data?this.detach(a.data):r[this.uid]=a}var r={};return i}),i(w,[u,l,y],function(e,t,n){function i(i,r){var o,a;if(r||(r={}),a=r.type&&""!==r.type?r.type:t.getFileMime(r.name),r.name)o=r.name.replace(/\\/g,"/"),o=o.substr(o.lastIndexOf("/")+1);else{var s=a.split("/")[0];o=e.guid((""!==s?s:"file")+"_"),t.extensions[a]&&(o+="."+t.extensions[a][0])}n.apply(this,arguments),e.extend(this,{type:a||"",name:o||e.guid("file_"),lastModifiedDate:r.lastModifiedDate||(new Date).toLocaleString()})}return i.prototype=n.prototype,i}),i(E,[u,l,f,h,p,c,w,g,v],function(e,t,n,i,r,o,a,s,u){function c(r){var c=this,d,f,h;if(-1!==e.inArray(e.typeOf(r),["string","node"])&&(r={browse_button:r}),f=n.get(r.browse_button),!f)throw new i.DOMException(i.DOMException.NOT_FOUND_ERR);h={accept:[{title:o.translate("All Files"),extensions:"*"}],name:"file",multiple:!1,required_caps:!1,container:f.parentNode||document.body},r=e.extend({},h,r),"string"==typeof r.required_caps&&(r.required_caps=s.parseCaps(r.required_caps)),"string"==typeof r.accept&&(r.accept=t.mimes2extList(r.accept)),d=n.get(r.container),d||(d=document.body),"static"===n.getStyle(d,"position")&&(d.style.position="relative"),d=f=null,u.call(c),e.extend(c,{uid:e.guid("uid_"),ruid:null,shimid:null,files:null,init:function(){c.convertEventPropsToHandlers(l),c.bind("RuntimeInit",function(t,i){c.ruid=i.uid,c.shimid=i.shimid,c.bind("Ready",function(){c.trigger("Refresh")},999),c.bind("Change",function(){var t=i.exec.call(c,"FileInput","getFiles");c.files=[],e.each(t,function(e){return 0===e.size?!0:void c.files.push(new a(c.ruid,e))})},999),c.bind("Refresh",function(){var t,o,a,s;a=n.get(r.browse_button),s=n.get(i.shimid),a&&(t=n.getPos(a,n.get(r.container)),o=n.getSize(a),s&&e.extend(s.style,{top:t.y+"px",left:t.x+"px",width:o.w+"px",height:o.h+"px"})),s=a=null}),i.exec.call(c,"FileInput","init",r)}),c.connectRuntime(e.extend({},r,{required_caps:{select_file:!0}}))},disable:function(t){var n=this.getRuntime();n&&n.exec.call(this,"FileInput","disable","undefined"===e.typeOf(t)?!0:t)},refresh:function(){c.trigger("Refresh")},destroy:function(){var t=this.getRuntime();t&&(t.exec.call(this,"FileInput","destroy"),this.disconnectRuntime()),"array"===e.typeOf(this.files)&&e.each(this.files,function(e){e.destroy()}),this.files=null}})}var l=["ready","change","cancel","mouseenter","mouseleave","mousedown","mouseup"];return c.prototype=r.instance,c}),i(_,[c,f,h,u,w,v,p,l],function(e,t,n,i,r,o,a,s){function u(n){var a=this,u;"string"==typeof n&&(n={drop_zone:n}),u={accept:[{title:e.translate("All Files"),extensions:"*"}],required_caps:{drag_and_drop:!0}},n="object"==typeof n?i.extend({},u,n):u,n.container=t.get(n.drop_zone)||document.body,"static"===t.getStyle(n.container,"position")&&(n.container.style.position="relative"),"string"==typeof n.accept&&(n.accept=s.mimes2extList(n.accept)),o.call(a),i.extend(a,{uid:i.guid("uid_"),ruid:null,files:null,init:function(){a.convertEventPropsToHandlers(c),a.bind("RuntimeInit",function(e,t){a.ruid=t.uid,a.bind("Drop",function(){var e=t.exec.call(a,"FileDrop","getFiles");a.files=[],i.each(e,function(e){a.files.push(new r(a.ruid,e))})},999),t.exec.call(a,"FileDrop","init",n),a.dispatchEvent("ready")}),a.connectRuntime(n)},destroy:function(){var e=this.getRuntime();e&&(e.exec.call(this,"FileDrop","destroy"),this.disconnectRuntime()),this.files=null}})}var c=["ready","dragenter","dragleave","drop","error"];return u.prototype=a.instance,u}),i(x,[u,v,p],function(e,t,n){function i(){this.uid=e.guid("uid_"),t.call(this),this.destroy=function(){this.disconnectRuntime(),this.unbindAll()}}return i.prototype=n.instance,i}),i(b,[u,m,h,p,y,w,x],function(e,t,n,i,r,o,a){function s(){function i(e,i){function l(e){o.readyState=s.DONE,o.error=e,o.trigger("error"),d()}function d(){c.destroy(),c=null,o.trigger("loadend")}function f(t){c.bind("Error",function(e,t){l(t)}),c.bind("Progress",function(e){o.result=t.exec.call(c,"FileReader","getResult"),o.trigger(e)}),c.bind("Load",function(e){o.readyState=s.DONE,o.result=t.exec.call(c,"FileReader","getResult"),o.trigger(e),d()}),t.exec.call(c,"FileReader","read",e,i)}if(c=new a,this.convertEventPropsToHandlers(u),this.readyState===s.LOADING)return l(new n.DOMException(n.DOMException.INVALID_STATE_ERR));if(this.readyState=s.LOADING,this.trigger("loadstart"),i instanceof r)if(i.isDetached()){var h=i.getSource();switch(e){case"readAsText":case"readAsBinaryString":this.result=h;break;case"readAsDataURL":this.result="data:"+i.type+";base64,"+t.btoa(h)}this.readyState=s.DONE,this.trigger("load"),d()}else f(c.connectRuntime(i.ruid));else l(new n.DOMException(n.DOMException.NOT_FOUND_ERR))}var o=this,c;e.extend(this,{uid:e.guid("uid_"),readyState:s.EMPTY,result:null,error:null,readAsBinaryString:function(e){i.call(this,"readAsBinaryString",e)},readAsDataURL:function(e){i.call(this,"readAsDataURL",e)},readAsText:function(e){i.call(this,"readAsText",e)},abort:function(){this.result=null,-1===e.inArray(this.readyState,[s.EMPTY,s.DONE])&&(this.readyState===s.LOADING&&(this.readyState=s.DONE),c&&c.getRuntime().exec.call(this,"FileReader","abort"),this.trigger("abort"),this.trigger("loadend"))
+},destroy:function(){this.abort(),c&&(c.getRuntime().exec.call(this,"FileReader","destroy"),c.disconnectRuntime()),o=c=null}})}var u=["loadstart","progress","load","abort","error","loadend"];return s.EMPTY=0,s.LOADING=1,s.DONE=2,s.prototype=i.instance,s}),i(R,[],function(){var e=function(t,n){for(var i=["source","scheme","authority","userInfo","user","pass","host","port","relative","path","directory","file","query","fragment"],r=i.length,o={http:80,https:443},a={},s=/^(?:([^:\/?#]+):)?(?:\/\/()(?:(?:()(?:([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?))?()(?:(()(?:(?:[^?#\/]*\/)*)()(?:[^?#]*))(?:\\?([^#]*))?(?:#(.*))?)/,u=s.exec(t||"");r--;)u[r]&&(a[i[r]]=u[r]);if(!a.scheme){n&&"string"!=typeof n||(n=e(n||document.location.href)),a.scheme=n.scheme,a.host=n.host,a.port=n.port;var c="";/^[^\/]/.test(a.path)&&(c=n.path,/(\/|\/[^\.]+)$/.test(c)?c+="/":c=c.replace(/\/[^\/]+$/,"/")),a.path=c+(a.path||"")}return a.port||(a.port=o[a.scheme]||80),a.port=parseInt(a.port,10),a.path||(a.path="/"),delete a.source,a},t=function(t){var n={http:80,https:443},i=e(t);return i.scheme+"://"+i.host+(i.port!==n[i.scheme]?":"+i.port:"")+i.path+(i.query?i.query:"")},n=function(t){function n(e){return[e.scheme,e.host,e.port].join("/")}return"string"==typeof t&&(t=e(t)),n(e())===n(t)};return{parseUrl:e,resolveUrl:t,hasSameOrigin:n}}),i(T,[u,v,m],function(e,t,n){return function(){function i(e,t){if(!t.isDetached()){var i=this.connectRuntime(t.ruid).exec.call(this,"FileReaderSync","read",e,t);return this.disconnectRuntime(),i}var r=t.getSource();switch(e){case"readAsBinaryString":return r;case"readAsDataURL":return"data:"+t.type+";base64,"+n.btoa(r);case"readAsText":for(var o="",a=0,s=r.length;s>a;a++)o+=String.fromCharCode(r[a]);return o}}t.call(this),e.extend(this,{uid:e.guid("uid_"),readAsBinaryString:function(e){return i.call(this,"readAsBinaryString",e)},readAsDataURL:function(e){return i.call(this,"readAsDataURL",e)},readAsText:function(e){return i.call(this,"readAsText",e)}})}}),i(A,[h,u,y],function(e,t,n){function i(){var e,i=[];t.extend(this,{append:function(r,o){var a=this,s=t.typeOf(o);o instanceof n?e={name:r,value:o}:"array"===s?(r+="[]",t.each(o,function(e){a.append(r,e)})):"object"===s?t.each(o,function(e,t){a.append(r+"["+t+"]",e)}):"null"===s||"undefined"===s||"number"===s&&isNaN(o)?a.append(r,"false"):i.push({name:r,value:o.toString()})},hasBlob:function(){return!!this.getBlob()},getBlob:function(){return e&&e.value||null},getBlobName:function(){return e&&e.name||null},each:function(n){t.each(i,function(e){n(e.value,e.name)}),e&&n(e.value,e.name)},destroy:function(){e=null,i=[]}})}return i}),i(S,[u,h,p,m,R,g,x,y,T,A,d,l],function(e,t,n,i,r,o,a,s,u,c,l,d){function f(){this.uid=e.guid("uid_")}function h(){function n(e,t){return y.hasOwnProperty(e)?1===arguments.length?l.can("define_property")?y[e]:v[e]:void(l.can("define_property")?y[e]=t:v[e]=t):void 0}function u(t){function i(){k&&(k.destroy(),k=null),s.dispatchEvent("loadend"),s=null}function r(r){k.bind("LoadStart",function(e){n("readyState",h.LOADING),s.dispatchEvent("readystatechange"),s.dispatchEvent(e),I&&s.upload.dispatchEvent(e)}),k.bind("Progress",function(e){n("readyState")!==h.LOADING&&(n("readyState",h.LOADING),s.dispatchEvent("readystatechange")),s.dispatchEvent(e)}),k.bind("UploadProgress",function(e){I&&s.upload.dispatchEvent({type:"progress",lengthComputable:!1,total:e.total,loaded:e.loaded})}),k.bind("Load",function(t){n("readyState",h.DONE),n("status",Number(r.exec.call(k,"XMLHttpRequest","getStatus")||0)),n("statusText",p[n("status")]||""),n("response",r.exec.call(k,"XMLHttpRequest","getResponse",n("responseType"))),~e.inArray(n("responseType"),["text",""])?n("responseText",n("response")):"document"===n("responseType")&&n("responseXML",n("response")),U=r.exec.call(k,"XMLHttpRequest","getAllResponseHeaders"),s.dispatchEvent("readystatechange"),n("status")>0?(I&&s.upload.dispatchEvent(t),s.dispatchEvent(t)):(N=!0,s.dispatchEvent("error")),i()}),k.bind("Abort",function(e){s.dispatchEvent(e),i()}),k.bind("Error",function(e){N=!0,n("readyState",h.DONE),s.dispatchEvent("readystatechange"),D=!0,s.dispatchEvent(e),i()}),r.exec.call(k,"XMLHttpRequest","send",{url:E,method:_,async:w,user:b,password:R,headers:x,mimeType:A,encoding:T,responseType:s.responseType,withCredentials:s.withCredentials,options:P},t)}var s=this;M=(new Date).getTime(),k=new a,"string"==typeof P.required_caps&&(P.required_caps=o.parseCaps(P.required_caps)),P.required_caps=e.extend({},P.required_caps,{return_response_type:s.responseType}),t instanceof c&&(P.required_caps.send_multipart=!0),L||(P.required_caps.do_cors=!0),P.ruid?r(k.connectRuntime(P)):(k.bind("RuntimeInit",function(e,t){r(t)}),k.bind("RuntimeError",function(e,t){s.dispatchEvent("RuntimeError",t)}),k.connectRuntime(P))}function g(){n("responseText",""),n("responseXML",null),n("response",null),n("status",0),n("statusText",""),M=C=null}var v=this,y={timeout:0,readyState:h.UNSENT,withCredentials:!1,status:0,statusText:"",responseType:"",responseXML:null,responseText:null,response:null},w=!0,E,_,x={},b,R,T=null,A=null,S=!1,O=!1,I=!1,D=!1,N=!1,L=!1,M,C,F=null,H=null,P={},k,U="",B;e.extend(this,y,{uid:e.guid("uid_"),upload:new f,open:function(o,a,s,u,c){var l;if(!o||!a)throw new t.DOMException(t.DOMException.SYNTAX_ERR);if(/[\u0100-\uffff]/.test(o)||i.utf8_encode(o)!==o)throw new t.DOMException(t.DOMException.SYNTAX_ERR);if(~e.inArray(o.toUpperCase(),["CONNECT","DELETE","GET","HEAD","OPTIONS","POST","PUT","TRACE","TRACK"])&&(_=o.toUpperCase()),~e.inArray(_,["CONNECT","TRACE","TRACK"]))throw new t.DOMException(t.DOMException.SECURITY_ERR);if(a=i.utf8_encode(a),l=r.parseUrl(a),L=r.hasSameOrigin(l),E=r.resolveUrl(a),(u||c)&&!L)throw new t.DOMException(t.DOMException.INVALID_ACCESS_ERR);if(b=u||l.user,R=c||l.pass,w=s||!0,w===!1&&(n("timeout")||n("withCredentials")||""!==n("responseType")))throw new t.DOMException(t.DOMException.INVALID_ACCESS_ERR);S=!w,O=!1,x={},g.call(this),n("readyState",h.OPENED),this.convertEventPropsToHandlers(["readystatechange"]),this.dispatchEvent("readystatechange")},setRequestHeader:function(r,o){var a=["accept-charset","accept-encoding","access-control-request-headers","access-control-request-method","connection","content-length","cookie","cookie2","content-transfer-encoding","date","expect","host","keep-alive","origin","referer","te","trailer","transfer-encoding","upgrade","user-agent","via"];if(n("readyState")!==h.OPENED||O)throw new t.DOMException(t.DOMException.INVALID_STATE_ERR);if(/[\u0100-\uffff]/.test(r)||i.utf8_encode(r)!==r)throw new t.DOMException(t.DOMException.SYNTAX_ERR);return r=e.trim(r).toLowerCase(),~e.inArray(r,a)||/^(proxy\-|sec\-)/.test(r)?!1:(x[r]?x[r]+=", "+o:x[r]=o,!0)},getAllResponseHeaders:function(){return U||""},getResponseHeader:function(t){return t=t.toLowerCase(),N||~e.inArray(t,["set-cookie","set-cookie2"])?null:U&&""!==U&&(B||(B={},e.each(U.split(/\r\n/),function(t){var n=t.split(/:\s+/);2===n.length&&(n[0]=e.trim(n[0]),B[n[0].toLowerCase()]={header:n[0],value:e.trim(n[1])})})),B.hasOwnProperty(t))?B[t].header+": "+B[t].value:null},overrideMimeType:function(i){var r,o;if(~e.inArray(n("readyState"),[h.LOADING,h.DONE]))throw new t.DOMException(t.DOMException.INVALID_STATE_ERR);if(i=e.trim(i.toLowerCase()),/;/.test(i)&&(r=i.match(/^([^;]+)(?:;\scharset\=)?(.*)$/))&&(i=r[1],r[2]&&(o=r[2])),!d.mimes[i])throw new t.DOMException(t.DOMException.SYNTAX_ERR);F=i,H=o},send:function(n,r){if(P="string"===e.typeOf(r)?{ruid:r}:r?r:{},this.convertEventPropsToHandlers(m),this.upload.convertEventPropsToHandlers(m),this.readyState!==h.OPENED||O)throw new t.DOMException(t.DOMException.INVALID_STATE_ERR);if(n instanceof s)P.ruid=n.ruid,A=n.type||"application/octet-stream";else if(n instanceof c){if(n.hasBlob()){var o=n.getBlob();P.ruid=o.ruid,A=o.type||"application/octet-stream"}}else"string"==typeof n&&(T="UTF-8",A="text/plain;charset=UTF-8",n=i.utf8_encode(n));this.withCredentials||(this.withCredentials=P.required_caps&&P.required_caps.send_browser_cookies&&!L),I=!S&&this.upload.hasEventListener(),N=!1,D=!n,S||(O=!0),u.call(this,n)},abort:function(){if(N=!0,S=!1,~e.inArray(n("readyState"),[h.UNSENT,h.OPENED,h.DONE]))n("readyState",h.UNSENT);else{if(n("readyState",h.DONE),O=!1,!k)throw new t.DOMException(t.DOMException.INVALID_STATE_ERR);k.getRuntime().exec.call(k,"XMLHttpRequest","abort",D),D=!0}},destroy:function(){k&&("function"===e.typeOf(k.destroy)&&k.destroy(),k=null),this.unbindAll(),this.upload&&(this.upload.unbindAll(),this.upload=null)}})}var p={100:"Continue",101:"Switching Protocols",102:"Processing",200:"OK",201:"Created",202:"Accepted",203:"Non-Authoritative Information",204:"No Content",205:"Reset Content",206:"Partial Content",207:"Multi-Status",226:"IM Used",300:"Multiple Choices",301:"Moved Permanently",302:"Found",303:"See Other",304:"Not Modified",305:"Use Proxy",306:"Reserved",307:"Temporary Redirect",400:"Bad Request",401:"Unauthorized",402:"Payment Required",403:"Forbidden",404:"Not Found",405:"Method Not Allowed",406:"Not Acceptable",407:"Proxy Authentication Required",408:"Request Timeout",409:"Conflict",410:"Gone",411:"Length Required",412:"Precondition Failed",413:"Request Entity Too Large",414:"Request-URI Too Long",415:"Unsupported Media Type",416:"Requested Range Not Satisfiable",417:"Expectation Failed",422:"Unprocessable Entity",423:"Locked",424:"Failed Dependency",426:"Upgrade Required",500:"Internal Server Error",501:"Not Implemented",502:"Bad Gateway",503:"Service Unavailable",504:"Gateway Timeout",505:"HTTP Version Not Supported",506:"Variant Also Negotiates",507:"Insufficient Storage",510:"Not Extended"};f.prototype=n.instance;var m=["loadstart","progress","abort","error","load","timeout","loadend"],g=1,v=2;return h.UNSENT=0,h.OPENED=1,h.HEADERS_RECEIVED=2,h.LOADING=3,h.DONE=4,h.prototype=n.instance,h}),i(O,[u,m,v,p],function(e,t,n,i){function r(){function i(){l=d=0,c=this.result=null}function o(t,n){var i=this;u=n,i.bind("TransportingProgress",function(t){d=t.loaded,l>d&&-1===e.inArray(i.state,[r.IDLE,r.DONE])&&a.call(i)},999),i.bind("TransportingComplete",function(){d=l,i.state=r.DONE,c=null,i.result=u.exec.call(i,"Transporter","getAsBlob",t||"")},999),i.state=r.BUSY,i.trigger("TransportingStarted"),a.call(i)}function a(){var e=this,n,i=l-d;f>i&&(f=i),n=t.btoa(c.substr(d,f)),u.exec.call(e,"Transporter","receive",n,l)}var s,u,c,l,d,f;n.call(this),e.extend(this,{uid:e.guid("uid_"),state:r.IDLE,result:null,transport:function(t,n,r){var a=this;if(r=e.extend({chunk_size:204798},r),(s=r.chunk_size%3)&&(r.chunk_size+=3-s),f=r.chunk_size,i.call(this),c=t,l=t.length,"string"===e.typeOf(r)||r.ruid)o.call(a,n,this.connectRuntime(r));else{var u=function(e,t){a.unbind("RuntimeInit",u),o.call(a,n,t)};this.bind("RuntimeInit",u),this.connectRuntime(r)}},abort:function(){var e=this;e.state=r.IDLE,u&&(u.exec.call(e,"Transporter","clear"),e.trigger("TransportingAborted")),i.call(e)},destroy:function(){this.unbindAll(),u=null,this.disconnectRuntime(),i.call(this)}})}return r.IDLE=0,r.BUSY=1,r.DONE=2,r.prototype=i.instance,r}),i(I,[u,f,h,T,S,g,v,O,d,p,y,w,m],function(e,t,n,i,r,o,a,s,u,c,l,d,f){function h(){function i(e){e||(e=this.getRuntime().exec.call(this,"Image","getInfo")),this.size=e.size,this.width=e.width,this.height=e.height,this.type=e.type,this.meta=e.meta,""===this.name&&(this.name=e.name)}function c(t){var i=e.typeOf(t);try{if(t instanceof h){if(!t.size)throw new n.DOMException(n.DOMException.INVALID_STATE_ERR);m.apply(this,arguments)}else if(t instanceof l){if(!~e.inArray(t.type,["image/jpeg","image/png"]))throw new n.ImageError(n.ImageError.WRONG_FORMAT);g.apply(this,arguments)}else if(-1!==e.inArray(i,["blob","file"]))c.call(this,new d(null,t),arguments[1]);else if("string"===i)/^data:[^;]*;base64,/.test(t)?c.call(this,new l(null,{data:t}),arguments[1]):v.apply(this,arguments);else{if("node"!==i||"img"!==t.nodeName.toLowerCase())throw new n.DOMException(n.DOMException.TYPE_MISMATCH_ERR);c.call(this,t.src,arguments[1])}}catch(r){this.trigger("error",r.code)}}function m(t,n){var i=this.connectRuntime(t.ruid);this.ruid=i.uid,i.exec.call(this,"Image","loadFromImage",t,"undefined"===e.typeOf(n)?!0:n)}function g(t,n){function i(e){r.ruid=e.uid,e.exec.call(r,"Image","loadFromBlob",t)}var r=this;r.name=t.name||"",t.isDetached()?(this.bind("RuntimeInit",function(e,t){i(t)}),n&&"string"==typeof n.required_caps&&(n.required_caps=o.parseCaps(n.required_caps)),this.connectRuntime(e.extend({required_caps:{access_image_binary:!0,resize_image:!0}},n))):i(this.connectRuntime(t.ruid))}function v(e,t){var n=this,i;i=new r,i.open("get",e),i.responseType="blob",i.onprogress=function(e){n.trigger(e)},i.onload=function(){g.call(n,i.response,!0)},i.onerror=function(e){n.trigger(e)},i.onloadend=function(){i.destroy()},i.bind("RuntimeError",function(e,t){n.trigger("RuntimeError",t)}),i.send(null,t)}a.call(this),e.extend(this,{uid:e.guid("uid_"),ruid:null,name:"",size:0,width:0,height:0,type:"",meta:{},clone:function(){this.load.apply(this,arguments)},load:function(){this.bind("Load Resize",function(){i.call(this)},999),this.convertEventPropsToHandlers(p),c.apply(this,arguments)},downsize:function(t){var i={width:this.width,height:this.height,crop:!1,preserveHeaders:!0};t="object"==typeof t?e.extend(i,t):e.extend(i,{width:arguments[0],height:arguments[1],crop:arguments[2],preserveHeaders:arguments[3]});try{if(!this.size)throw new n.DOMException(n.DOMException.INVALID_STATE_ERR);if(this.width>h.MAX_RESIZE_WIDTH||this.height>h.MAX_RESIZE_HEIGHT)throw new n.ImageError(n.ImageError.MAX_RESOLUTION_ERR);this.getRuntime().exec.call(this,"Image","downsize",t.width,t.height,t.crop,t.preserveHeaders)}catch(r){this.trigger("error",r.code)}},crop:function(e,t,n){this.downsize(e,t,!0,n)},getAsCanvas:function(){if(!u.can("create_canvas"))throw new n.RuntimeError(n.RuntimeError.NOT_SUPPORTED_ERR);var e=this.connectRuntime(this.ruid);return e.exec.call(this,"Image","getAsCanvas")},getAsBlob:function(e,t){if(!this.size)throw new n.DOMException(n.DOMException.INVALID_STATE_ERR);return e||(e="image/jpeg"),"image/jpeg"!==e||t||(t=90),this.getRuntime().exec.call(this,"Image","getAsBlob",e,t)},getAsDataURL:function(e,t){if(!this.size)throw new n.DOMException(n.DOMException.INVALID_STATE_ERR);return this.getRuntime().exec.call(this,"Image","getAsDataURL",e,t)},getAsBinaryString:function(e,t){var n=this.getAsDataURL(e,t);return f.atob(n.substring(n.indexOf("base64,")+7))},embed:function(i){function r(){if(u.can("create_canvas")){var t=a.getAsCanvas();if(t)return i.appendChild(t),t=null,a.destroy(),void o.trigger("embedded")}var r=a.getAsDataURL(c,l);if(!r)throw new n.ImageError(n.ImageError.WRONG_FORMAT);if(u.can("use_data_uri_of",r.length))i.innerHTML='<img src="'+r+'" width="'+a.width+'" height="'+a.height+'" />',a.destroy(),o.trigger("embedded");else{var d=new s;d.bind("TransportingComplete",function(){v=o.connectRuntime(this.result.ruid),o.bind("Embedded",function(){e.extend(v.getShimContainer().style,{top:"0px",left:"0px",width:a.width+"px",height:a.height+"px"}),v=null},999),v.exec.call(o,"ImageView","display",this.result.uid,m,g),a.destroy()}),d.transport(f.atob(r.substring(r.indexOf("base64,")+7)),c,e.extend({},p,{required_caps:{display_media:!0},runtime_order:"flash,silverlight",container:i}))}}var o=this,a,c,l,d,p=arguments[1]||{},m=this.width,g=this.height,v;try{if(!(i=t.get(i)))throw new n.DOMException(n.DOMException.INVALID_NODE_TYPE_ERR);if(!this.size)throw new n.DOMException(n.DOMException.INVALID_STATE_ERR);if(this.width>h.MAX_RESIZE_WIDTH||this.height>h.MAX_RESIZE_HEIGHT)throw new n.ImageError(n.ImageError.MAX_RESOLUTION_ERR);if(c=p.type||this.type||"image/jpeg",l=p.quality||90,d="undefined"!==e.typeOf(p.crop)?p.crop:!1,p.width)m=p.width,g=p.height||m;else{var y=t.getSize(i);y.w&&y.h&&(m=y.w,g=y.h)}return a=new h,a.bind("Resize",function(){r.call(o)}),a.bind("Load",function(){a.downsize(m,g,d,!1)}),a.clone(this,!1),a}catch(w){this.trigger("error",w.code)}},destroy:function(){this.ruid&&(this.getRuntime().exec.call(this,"Image","destroy"),this.disconnectRuntime()),this.unbindAll()}})}var p=["progress","load","error","resize","embedded"];return h.MAX_RESIZE_WIDTH=6500,h.MAX_RESIZE_HEIGHT=6500,h.prototype=c.instance,h}),i(D,[u,h,g,d],function(e,t,n,i){function r(t){var r=this,s=n.capTest,u=n.capTrue,c=e.extend({access_binary:s(window.FileReader||window.File&&window.File.getAsDataURL),access_image_binary:function(){return r.can("access_binary")&&!!a.Image},display_media:s(i.can("create_canvas")||i.can("use_data_uri_over32kb")),do_cors:s(window.XMLHttpRequest&&"withCredentials"in new XMLHttpRequest),drag_and_drop:s(function(){var e=document.createElement("div");return("draggable"in e||"ondragstart"in e&&"ondrop"in e)&&("IE"!==i.browser||i.version>9)}()),filter_by_extension:s(function(){return"Chrome"===i.browser&&i.version>=28||"IE"===i.browser&&i.version>=10}()),return_response_headers:u,return_response_type:function(e){return"json"===e&&window.JSON?!0:i.can("return_response_type",e)},return_status_code:u,report_upload_progress:s(window.XMLHttpRequest&&(new XMLHttpRequest).upload),resize_image:function(){return r.can("access_binary")&&i.can("create_canvas")},select_file:function(){return i.can("use_fileinput")&&window.File},select_folder:function(){return r.can("select_file")&&"Chrome"===i.browser&&i.version>=21},select_multiple:function(){return!(!r.can("select_file")||"Safari"===i.browser&&"Windows"===i.os||"iOS"===i.os&&i.verComp(i.osVersion,"7.0.4","<"))},send_binary_string:s(window.XMLHttpRequest&&((new XMLHttpRequest).sendAsBinary||window.Uint8Array&&window.ArrayBuffer)),send_custom_headers:s(window.XMLHttpRequest),send_multipart:function(){return!!(window.XMLHttpRequest&&(new XMLHttpRequest).upload&&window.FormData)||r.can("send_binary_string")},slice_blob:s(window.File&&(File.prototype.mozSlice||File.prototype.webkitSlice||File.prototype.slice)),stream_upload:function(){return r.can("slice_blob")&&r.can("send_multipart")},summon_file_dialog:s(function(){return"Firefox"===i.browser&&i.version>=4||"Opera"===i.browser&&i.version>=12||"IE"===i.browser&&i.version>=10||!!~e.inArray(i.browser,["Chrome","Safari"])}()),upload_filesize:u},arguments[2]);n.call(this,t,arguments[1]||o,c),e.extend(this,{init:function(){this.trigger("Init")},destroy:function(e){return function(){e.call(r),e=r=null}}(this.destroy)}),e.extend(this.getShim(),a)}var o="html5",a={};return n.addConstructor(o,r),a}),i(N,[D,y],function(e,t){function n(){function e(e,t,n){var i;if(!window.File.prototype.slice)return(i=window.File.prototype.webkitSlice||window.File.prototype.mozSlice)?i.call(e,t,n):null;try{return e.slice(),e.slice(t,n)}catch(r){return e.slice(t,n-t)}}this.slice=function(){return new t(this.getRuntime().uid,e.apply(this,arguments))}}return e.Blob=n}),i(L,[u],function(e){function t(){this.returnValue=!1}function n(){this.cancelBubble=!0}var i={},r="moxie_"+e.guid(),o=function(o,a,s,u){var c,l;a=a.toLowerCase(),o.addEventListener?(c=s,o.addEventListener(a,c,!1)):o.attachEvent&&(c=function(){var e=window.event;e.target||(e.target=e.srcElement),e.preventDefault=t,e.stopPropagation=n,s(e)},o.attachEvent("on"+a,c)),o[r]||(o[r]=e.guid()),i.hasOwnProperty(o[r])||(i[o[r]]={}),l=i[o[r]],l.hasOwnProperty(a)||(l[a]=[]),l[a].push({func:c,orig:s,key:u})},a=function(t,n,o){var a,s;if(n=n.toLowerCase(),t[r]&&i[t[r]]&&i[t[r]][n]){a=i[t[r]][n];for(var u=a.length-1;u>=0&&(a[u].orig!==o&&a[u].key!==o||(t.removeEventListener?t.removeEventListener(n,a[u].func,!1):t.detachEvent&&t.detachEvent("on"+n,a[u].func),a[u].orig=null,a[u].func=null,a.splice(u,1),o===s));u--);if(a.length||delete i[t[r]][n],e.isEmptyObj(i[t[r]])){delete i[t[r]];try{delete t[r]}catch(c){t[r]=s}}}},s=function(t,n){t&&t[r]&&e.each(i[t[r]],function(e,i){a(t,i,n)})};return{addEvent:o,removeEvent:a,removeAllEvents:s}}),i(M,[D,u,f,L,l,d],function(e,t,n,i,r,o){function a(){var e=[],a;t.extend(this,{init:function(s){var u=this,c=u.getRuntime(),l,d,f,h,p,m;a=s,e=[],f=a.accept.mimes||r.extList2mimes(a.accept,c.can("filter_by_extension")),d=c.getShimContainer(),d.innerHTML='<input id="'+c.uid+'" type="file" style="font-size:999px;opacity:0;"'+(a.multiple&&c.can("select_multiple")?"multiple":"")+(a.directory&&c.can("select_folder")?"webkitdirectory directory":"")+(f?' accept="'+f.join(",")+'"':"")+" />",l=n.get(c.uid),t.extend(l.style,{position:"absolute",top:0,left:0,width:"100%",height:"100%"}),h=n.get(a.browse_button),c.can("summon_file_dialog")&&("static"===n.getStyle(h,"position")&&(h.style.position="relative"),p=parseInt(n.getStyle(h,"z-index"),10)||1,h.style.zIndex=p,d.style.zIndex=p-1,i.addEvent(h,"click",function(e){var t=n.get(c.uid);t&&!t.disabled&&t.click(),e.preventDefault()},u.uid)),m=c.can("summon_file_dialog")?h:d,i.addEvent(m,"mouseover",function(){u.trigger("mouseenter")},u.uid),i.addEvent(m,"mouseout",function(){u.trigger("mouseleave")},u.uid),i.addEvent(m,"mousedown",function(){u.trigger("mousedown")},u.uid),i.addEvent(n.get(a.container),"mouseup",function(){u.trigger("mouseup")},u.uid),l.onchange=function g(){if(e=[],a.directory?t.each(this.files,function(t){"."!==t.name&&e.push(t)}):e=[].slice.call(this.files),"IE"!==o.browser&&"IEMobile"!==o.browser)this.value="";else{var n=this.cloneNode(!0);this.parentNode.replaceChild(n,this),n.onchange=g}u.trigger("change")},u.trigger({type:"ready",async:!0}),d=null},getFiles:function(){return e},disable:function(e){var t=this.getRuntime(),i;(i=n.get(t.uid))&&(i.disabled=!!e)},destroy:function(){var t=this.getRuntime(),r=t.getShim(),o=t.getShimContainer();i.removeAllEvents(o,this.uid),i.removeAllEvents(a&&n.get(a.container),this.uid),i.removeAllEvents(a&&n.get(a.browse_button),this.uid),o&&(o.innerHTML=""),r.removeInstance(this.uid),e=a=o=r=null}})}return e.FileInput=a}),i(C,[D,u,f,L,l],function(e,t,n,i,r){function o(){function e(e){if(!e.dataTransfer||!e.dataTransfer.types)return!1;var n=t.toArray(e.dataTransfer.types||[]);return-1!==t.inArray("Files",n)||-1!==t.inArray("public.file-url",n)||-1!==t.inArray("application/x-moz-file",n)}function o(e){for(var n=[],i=0;i<e.length;i++)[].push.apply(n,e[i].extensions.split(/\s*,\s*/));return-1===t.inArray("*",n)?n:[]}function a(e){if(!f.length)return!0;var n=r.getFileExtension(e.name);return!n||-1!==t.inArray(n,f)}function s(e,n){var i=[];t.each(e,function(e){var t=e.webkitGetAsEntry();if(t)if(t.isFile){var n=e.getAsFile();a(n)&&d.push(n)}else i.push(t)}),i.length?u(i,n):n()}function u(e,n){var i=[];t.each(e,function(e){i.push(function(t){c(e,t)})}),t.inSeries(i,function(){n()})}function c(e,t){e.isFile?e.file(function(e){a(e)&&d.push(e),t()},function(){t()}):e.isDirectory?l(e,t):t()}function l(e,t){function n(e){r.readEntries(function(t){t.length?([].push.apply(i,t),n(e)):e()},e)}var i=[],r=e.createReader();n(function(){u(i,t)})}var d=[],f=[],h;t.extend(this,{init:function(n){var r=this,u;h=n,f=o(h.accept),u=h.container,i.addEvent(u,"dragover",function(t){e(t)&&(t.preventDefault(),t.dataTransfer.dropEffect="copy")},r.uid),i.addEvent(u,"drop",function(n){e(n)&&(n.preventDefault(),d=[],n.dataTransfer.items&&n.dataTransfer.items[0].webkitGetAsEntry?s(n.dataTransfer.items,function(){r.trigger("drop")}):(t.each(n.dataTransfer.files,function(e){a(e)&&d.push(e)}),r.trigger("drop")))},r.uid),i.addEvent(u,"dragenter",function(e){r.trigger("dragenter")},r.uid),i.addEvent(u,"dragleave",function(e){r.trigger("dragleave")},r.uid)},getFiles:function(){return d},destroy:function(){i.removeAllEvents(h&&n.get(h.container),this.uid),d=f=h=null}})}return e.FileDrop=o}),i(F,[D,m,u],function(e,t,n){function i(){function e(e){return t.atob(e.substring(e.indexOf("base64,")+7))}var i,r=!1;n.extend(this,{read:function(e,t){var o=this;i=new window.FileReader,i.addEventListener("progress",function(e){o.trigger(e)}),i.addEventListener("load",function(e){o.trigger(e)}),i.addEventListener("error",function(e){o.trigger(e,i.error)}),i.addEventListener("loadend",function(){i=null}),"function"===n.typeOf(i[e])?(r=!1,i[e](t.getSource())):"readAsBinaryString"===e&&(r=!0,i.readAsDataURL(t.getSource()))},getResult:function(){return i&&i.result?r?e(i.result):i.result:null},abort:function(){i&&i.abort()},destroy:function(){i=null}})}return e.FileReader=i}),i(H,[D,u,l,R,w,y,A,h,d],function(e,t,n,i,r,o,a,s,u){function c(){function e(e,t){var n=this,i,r;i=t.getBlob().getSource(),r=new window.FileReader,r.onload=function(){t.append(t.getBlobName(),new o(null,{type:i.type,data:r.result})),f.send.call(n,e,t)},r.readAsBinaryString(i)}function c(){return!window.XMLHttpRequest||"IE"===u.browser&&u.version<8?function(){for(var e=["Msxml2.XMLHTTP.6.0","Microsoft.XMLHTTP"],t=0;t<e.length;t++)try{return new ActiveXObject(e[t])}catch(n){}}():new window.XMLHttpRequest}function l(e){var t=e.responseXML,n=e.responseText;return"IE"===u.browser&&n&&t&&!t.documentElement&&/[^\/]+\/[^\+]+\+xml/.test(e.getResponseHeader("Content-Type"))&&(t=new window.ActiveXObject("Microsoft.XMLDOM"),t.async=!1,t.validateOnParse=!1,t.loadXML(n)),t&&("IE"===u.browser&&0!==t.parseError||!t.documentElement||"parsererror"===t.documentElement.tagName)?null:t}function d(e){var t="----moxieboundary"+(new Date).getTime(),n="--",i="\r\n",r="",a=this.getRuntime();if(!a.can("send_binary_string"))throw new s.RuntimeError(s.RuntimeError.NOT_SUPPORTED_ERR);return h.setRequestHeader("Content-Type","multipart/form-data; boundary="+t),e.each(function(e,a){r+=e instanceof o?n+t+i+'Content-Disposition: form-data; name="'+a+'"; filename="'+unescape(encodeURIComponent(e.name||"blob"))+'"'+i+"Content-Type: "+(e.type||"application/octet-stream")+i+i+e.getSource()+i:n+t+i+'Content-Disposition: form-data; name="'+a+'"'+i+i+unescape(encodeURIComponent(e))+i}),r+=n+t+n+i}var f=this,h,p;t.extend(this,{send:function(n,r){var s=this,l="Mozilla"===u.browser&&u.version>=4&&u.version<7,f="Android Browser"===u.browser,m=!1;if(p=n.url.replace(/^.+?\/([\w\-\.]+)$/,"$1").toLowerCase(),h=c(),h.open(n.method,n.url,n.async,n.user,n.password),r instanceof o)r.isDetached()&&(m=!0),r=r.getSource();else if(r instanceof a){if(r.hasBlob())if(r.getBlob().isDetached())r=d.call(s,r),m=!0;else if((l||f)&&"blob"===t.typeOf(r.getBlob().getSource())&&window.FileReader)return void e.call(s,n,r);if(r instanceof a){var g=new window.FormData;r.each(function(e,t){e instanceof o?g.append(t,e.getSource()):g.append(t,e)}),r=g}}h.upload?(n.withCredentials&&(h.withCredentials=!0),h.addEventListener("load",function(e){s.trigger(e)}),h.addEventListener("error",function(e){s.trigger(e)}),h.addEventListener("progress",function(e){s.trigger(e)}),h.upload.addEventListener("progress",function(e){s.trigger({type:"UploadProgress",loaded:e.loaded,total:e.total})})):h.onreadystatechange=function v(){switch(h.readyState){case 1:break;case 2:break;case 3:var e,t;try{i.hasSameOrigin(n.url)&&(e=h.getResponseHeader("Content-Length")||0),h.responseText&&(t=h.responseText.length)}catch(r){e=t=0}s.trigger({type:"progress",lengthComputable:!!e,total:parseInt(e,10),loaded:t});break;case 4:h.onreadystatechange=function(){},s.trigger(0===h.status?"error":"load")}},t.isEmptyObj(n.headers)||t.each(n.headers,function(e,t){h.setRequestHeader(t,e)}),""!==n.responseType&&"responseType"in h&&(h.responseType="json"!==n.responseType||u.can("return_response_type","json")?n.responseType:"text"),m?h.sendAsBinary?h.sendAsBinary(r):!function(){for(var e=new Uint8Array(r.length),t=0;t<r.length;t++)e[t]=255&r.charCodeAt(t);h.send(e.buffer)}():h.send(r),s.trigger("loadstart")},getStatus:function(){try{if(h)return h.status}catch(e){}return 0},getResponse:function(e){var t=this.getRuntime();try{switch(e){case"blob":var i=new r(t.uid,h.response),o=h.getResponseHeader("Content-Disposition");if(o){var a=o.match(/filename=([\'\"'])([^\1]+)\1/);a&&(p=a[2])}return i.name=p,i.type||(i.type=n.getFileMime(p)),i;case"json":return u.can("return_response_type","json")?h.response:200===h.status&&window.JSON?JSON.parse(h.responseText):null;case"document":return l(h);default:return""!==h.responseText?h.responseText:null}}catch(s){return null}},getAllResponseHeaders:function(){try{return h.getAllResponseHeaders()}catch(e){}return""},abort:function(){h&&h.abort()},destroy:function(){f=p=null}})}return e.XMLHttpRequest=c}),i(P,[],function(){return function(){function e(e,t){var n=r?0:-8*(t-1),i=0,a;for(a=0;t>a;a++)i|=o.charCodeAt(e+a)<<Math.abs(n+8*a);return i}function n(e,t,n){n=3===arguments.length?n:o.length-t-1,o=o.substr(0,t)+e+o.substr(n+t)}function i(e,t,i){var o="",a=r?0:-8*(i-1),s;for(s=0;i>s;s++)o+=String.fromCharCode(t>>Math.abs(a+8*s)&255);n(o,e,i)}var r=!1,o;return{II:function(e){return e===t?r:void(r=e)},init:function(e){r=!1,o=e},SEGMENT:function(e,t,i){switch(arguments.length){case 1:return o.substr(e,o.length-e-1);case 2:return o.substr(e,t);case 3:n(i,e,t);break;default:return o}},BYTE:function(t){return e(t,1)},SHORT:function(t){return e(t,2)},LONG:function(n,r){return r===t?e(n,4):void i(n,r,4)},SLONG:function(t){var n=e(t,4);return n>2147483647?n-4294967296:n},STRING:function(t,n){var i="";for(n+=t;n>t;t++)i+=String.fromCharCode(e(t,1));return i}}}}),i(k,[P],function(e){return function t(n){var i=[],r,o,a,s=0;if(r=new e,r.init(n),65496===r.SHORT(0)){for(o=2;o<=n.length;)if(a=r.SHORT(o),a>=65488&&65495>=a)o+=2;else{if(65498===a||65497===a)break;s=r.SHORT(o+2)+2,a>=65505&&65519>=a&&i.push({hex:a,name:"APP"+(15&a),start:o,length:s,segment:r.SEGMENT(o,s)}),o+=s}return r.init(null),{headers:i,restore:function(e){var t,n;for(r.init(e),o=65504==r.SHORT(2)?4+r.SHORT(4):2,n=0,t=i.length;t>n;n++)r.SEGMENT(o,0,i[n].segment),o+=i[n].length;return e=r.SEGMENT(),r.init(null),e},strip:function(e){var n,i,o;for(i=new t(e),n=i.headers,i.purge(),r.init(e),o=n.length;o--;)r.SEGMENT(n[o].start,n[o].length,"");return e=r.SEGMENT(),r.init(null),e},get:function(e){for(var t=[],n=0,r=i.length;r>n;n++)i[n].name===e.toUpperCase()&&t.push(i[n].segment);return t},set:function(e,t){var n=[],r,o,a;for("string"==typeof t?n.push(t):n=t,r=o=0,a=i.length;a>r&&(i[r].name===e.toUpperCase()&&(i[r].segment=n[o],i[r].length=n[o].length,o++),!(o>=n.length));r++);},purge:function(){i=[],r.init(null),r=null}}}}}),i(U,[u,P],function(e,n){return function i(){function i(e,n){var i=a.SHORT(e),r,o,s,u,d,f,h,p,m=[],g={};for(r=0;i>r;r++)if(h=f=e+12*r+2,s=n[a.SHORT(h)],s!==t){switch(u=a.SHORT(h+=2),d=a.LONG(h+=2),h+=4,m=[],u){case 1:case 7:for(d>4&&(h=a.LONG(h)+c.tiffHeader),o=0;d>o;o++)m[o]=a.BYTE(h+o);break;case 2:d>4&&(h=a.LONG(h)+c.tiffHeader),g[s]=a.STRING(h,d-1);continue;case 3:for(d>2&&(h=a.LONG(h)+c.tiffHeader),o=0;d>o;o++)m[o]=a.SHORT(h+2*o);break;case 4:for(d>1&&(h=a.LONG(h)+c.tiffHeader),o=0;d>o;o++)m[o]=a.LONG(h+4*o);break;case 5:for(h=a.LONG(h)+c.tiffHeader,o=0;d>o;o++)m[o]=a.LONG(h+4*o)/a.LONG(h+4*o+4);break;case 9:for(h=a.LONG(h)+c.tiffHeader,o=0;d>o;o++)m[o]=a.SLONG(h+4*o);break;case 10:for(h=a.LONG(h)+c.tiffHeader,o=0;d>o;o++)m[o]=a.SLONG(h+4*o)/a.SLONG(h+4*o+4);break;default:continue}p=1==d?m[0]:m,g[s]=l.hasOwnProperty(s)&&"object"!=typeof p?l[s][p]:p}return g}function r(){var e=c.tiffHeader;return a.II(18761==a.SHORT(e)),42!==a.SHORT(e+=2)?!1:(c.IFD0=c.tiffHeader+a.LONG(e+=2),u=i(c.IFD0,s.tiff),"ExifIFDPointer"in u&&(c.exifIFD=c.tiffHeader+u.ExifIFDPointer,delete u.ExifIFDPointer),"GPSInfoIFDPointer"in u&&(c.gpsIFD=c.tiffHeader+u.GPSInfoIFDPointer,delete u.GPSInfoIFDPointer),!0)}function o(e,t,n){var i,r,o,u=0;if("string"==typeof t){var l=s[e.toLowerCase()];for(var d in l)if(l[d]===t){t=d;break}}i=c[e.toLowerCase()+"IFD"],r=a.SHORT(i);for(var f=0;r>f;f++)if(o=i+12*f+2,a.SHORT(o)==t){u=o+8;break}return u?(a.LONG(u,n),!0):!1}var a,s,u,c={},l;return a=new n,s={tiff:{274:"Orientation",270:"ImageDescription",271:"Make",272:"Model",305:"Software",34665:"ExifIFDPointer",34853:"GPSInfoIFDPointer"},exif:{36864:"ExifVersion",40961:"ColorSpace",40962:"PixelXDimension",40963:"PixelYDimension",36867:"DateTimeOriginal",33434:"ExposureTime",33437:"FNumber",34855:"ISOSpeedRatings",37377:"ShutterSpeedValue",37378:"ApertureValue",37383:"MeteringMode",37384:"LightSource",37385:"Flash",37386:"FocalLength",41986:"ExposureMode",41987:"WhiteBalance",41990:"SceneCaptureType",41988:"DigitalZoomRatio",41992:"Contrast",41993:"Saturation",41994:"Sharpness"},gps:{0:"GPSVersionID",1:"GPSLatitudeRef",2:"GPSLatitude",3:"GPSLongitudeRef",4:"GPSLongitude"}},l={ColorSpace:{1:"sRGB",0:"Uncalibrated"},MeteringMode:{0:"Unknown",1:"Average",2:"CenterWeightedAverage",3:"Spot",4:"MultiSpot",5:"Pattern",6:"Partial",255:"Other"},LightSource:{1:"Daylight",2:"Fliorescent",3:"Tungsten",4:"Flash",9:"Fine weather",10:"Cloudy weather",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"}},{init:function(e){return c={tiffHeader:10},e!==t&&e.length?(a.init(e),65505===a.SHORT(0)&&"EXIF\x00"===a.STRING(4,5).toUpperCase()?r():!1):!1
+},TIFF:function(){return u},EXIF:function(){var t;if(t=i(c.exifIFD,s.exif),t.ExifVersion&&"array"===e.typeOf(t.ExifVersion)){for(var n=0,r="";n<t.ExifVersion.length;n++)r+=String.fromCharCode(t.ExifVersion[n]);t.ExifVersion=r}return t},GPS:function(){var t;return t=i(c.gpsIFD,s.gps),t.GPSVersionID&&"array"===e.typeOf(t.GPSVersionID)&&(t.GPSVersionID=t.GPSVersionID.join(".")),t},setExif:function(e,t){return"PixelXDimension"!==e&&"PixelYDimension"!==e?!1:o("exif",e,t)},getBinary:function(){return a.SEGMENT()},purge:function(){a.init(null),a=u=null,c={}}}}}),i(B,[u,h,k,P,U],function(e,t,n,i,r){function o(o){function a(){for(var e=0,t,n;e<=u.length;){if(t=c.SHORT(e+=2),t>=65472&&65475>=t)return e+=5,{height:c.SHORT(e),width:c.SHORT(e+=2)};n=c.SHORT(e+=2),e+=n-2}return null}function s(){d&&l&&c&&(d.purge(),l.purge(),c.init(null),u=f=l=d=c=null)}var u,c,l,d,f,h;if(u=o,c=new i,c.init(u),65496!==c.SHORT(0))throw new t.ImageError(t.ImageError.WRONG_FORMAT);l=new n(o),d=new r,h=!!d.init(l.get("app1")[0]),f=a.call(this),e.extend(this,{type:"image/jpeg",size:u.length,width:f&&f.width||0,height:f&&f.height||0,setExif:function(t,n){return h?("object"===e.typeOf(t)?e.each(t,function(e,t){d.setExif(t,e)}):d.setExif(t,n),void l.set("app1",d.getBinary())):!1},writeHeaders:function(){return arguments.length?l.restore(arguments[0]):u=l.restore(u)},stripHeaders:function(e){return l.strip(e)},purge:function(){s.call(this)}}),h&&(this.meta={tiff:d.TIFF(),exif:d.EXIF(),gps:d.GPS()})}return o}),i(z,[h,u,P],function(e,t,n){function i(i){function r(){var e,t;return e=a.call(this,8),"IHDR"==e.type?(t=e.start,{width:u.LONG(t),height:u.LONG(t+=4)}):null}function o(){u&&(u.init(null),s=d=c=l=u=null)}function a(e){var t,n,i,r;return t=u.LONG(e),n=u.STRING(e+=4,4),i=e+=4,r=u.LONG(e+t),{length:t,type:n,start:i,CRC:r}}var s,u,c,l,d;s=i,u=new n,u.init(s),function(){var t=0,n=0,i=[35152,20039,3338,6666];for(n=0;n<i.length;n++,t+=2)if(i[n]!=u.SHORT(t))throw new e.ImageError(e.ImageError.WRONG_FORMAT)}(),d=r.call(this),t.extend(this,{type:"image/png",size:s.length,width:d.width,height:d.height,purge:function(){o.call(this)}}),o.call(this)}return i}),i(G,[u,h,B,z],function(e,t,n,i){return function(r){var o=[n,i],a;a=function(){for(var e=0;e<o.length;e++)try{return new o[e](r)}catch(n){}throw new t.ImageError(t.ImageError.WRONG_FORMAT)}(),e.extend(this,{type:"",size:0,width:0,height:0,setExif:function(){},writeHeaders:function(e){return e},stripHeaders:function(e){return e},purge:function(){}}),e.extend(this,a),this.purge=function(){a.purge(),a=null}}}),i(q,[],function(){function e(e,i,r){var o=e.naturalWidth,a=e.naturalHeight,s=r.width,u=r.height,c=r.x||0,l=r.y||0,d=i.getContext("2d");t(e)&&(o/=2,a/=2);var f=1024,h=document.createElement("canvas");h.width=h.height=f;for(var p=h.getContext("2d"),m=n(e,o,a),g=0;a>g;){for(var v=g+f>a?a-g:f,y=0;o>y;){var w=y+f>o?o-y:f;p.clearRect(0,0,f,f),p.drawImage(e,-y,-g);var E=y*s/o+c<<0,_=Math.ceil(w*s/o),x=g*u/a/m+l<<0,b=Math.ceil(v*u/a/m);d.drawImage(h,0,0,w,v,E,x,_,b),y+=f}g+=f}h=p=null}function t(e){var t=e.naturalWidth,n=e.naturalHeight;if(t*n>1048576){var i=document.createElement("canvas");i.width=i.height=1;var r=i.getContext("2d");return r.drawImage(e,-t+1,0),0===r.getImageData(0,0,1,1).data[3]}return!1}function n(e,t,n){var i=document.createElement("canvas");i.width=1,i.height=n;var r=i.getContext("2d");r.drawImage(e,0,0);for(var o=r.getImageData(0,0,1,n).data,a=0,s=n,u=n;u>a;){var c=o[4*(u-1)+3];0===c?s=u:a=u,u=s+a>>1}i=null;var l=u/n;return 0===l?1:l}return{isSubsampled:t,renderTo:e}}),i(X,[D,u,h,m,w,G,q,l,d],function(e,t,n,i,r,o,a,s,u){function c(){function e(){if(!E&&!y)throw new n.ImageError(n.DOMException.INVALID_STATE_ERR);return E||y}function c(e){return i.atob(e.substring(e.indexOf("base64,")+7))}function l(e,t){return"data:"+(t||"")+";base64,"+i.btoa(e)}function d(e){var t=this;y=new Image,y.onerror=function(){g.call(this),t.trigger("error",n.ImageError.WRONG_FORMAT)},y.onload=function(){t.trigger("load")},y.src=/^data:[^;]*;base64,/.test(e)?e:l(e,x.type)}function f(e,t){var i=this,r;return window.FileReader?(r=new FileReader,r.onload=function(){t(this.result)},r.onerror=function(){i.trigger("error",n.ImageError.WRONG_FORMAT)},r.readAsDataURL(e),void 0):t(e.getAsDataURL())}function h(n,i,r,o){var a=this,s,u,c=0,l=0,d,f,h,g;if(R=o,g=this.meta&&this.meta.tiff&&this.meta.tiff.Orientation||1,-1!==t.inArray(g,[5,6,7,8])){var v=n;n=i,i=v}return d=e(),r?(n=Math.min(n,d.width),i=Math.min(i,d.height),s=Math.max(n/d.width,i/d.height)):s=Math.min(n/d.width,i/d.height),s>1&&!r&&o?void this.trigger("Resize"):(E||(E=document.createElement("canvas")),f=Math.round(d.width*s),h=Math.round(d.height*s),r?(E.width=n,E.height=i,f>n&&(c=Math.round((f-n)/2)),h>i&&(l=Math.round((h-i)/2))):(E.width=f,E.height=h),R||m(E.width,E.height,g),p.call(this,d,E,-c,-l,f,h),this.width=E.width,this.height=E.height,b=!0,void a.trigger("Resize"))}function p(e,t,n,i,r,o){if("iOS"===u.OS)a.renderTo(e,t,{width:r,height:o,x:n,y:i});else{var s=t.getContext("2d");s.drawImage(e,n,i,r,o)}}function m(e,t,n){switch(n){case 5:case 6:case 7:case 8:E.width=t,E.height=e;break;default:E.width=e,E.height=t}var i=E.getContext("2d");switch(n){case 2:i.translate(e,0),i.scale(-1,1);break;case 3:i.translate(e,t),i.rotate(Math.PI);break;case 4:i.translate(0,t),i.scale(1,-1);break;case 5:i.rotate(.5*Math.PI),i.scale(1,-1);break;case 6:i.rotate(.5*Math.PI),i.translate(0,-t);break;case 7:i.rotate(.5*Math.PI),i.translate(e,-t),i.scale(-1,1);break;case 8:i.rotate(-.5*Math.PI),i.translate(-e,0)}}function g(){w&&(w.purge(),w=null),_=y=E=x=null,b=!1}var v=this,y,w,E,_,x,b=!1,R=!0;t.extend(this,{loadFromBlob:function(e){var t=this,i=t.getRuntime(),r=arguments.length>1?arguments[1]:!0;if(!i.can("access_binary"))throw new n.RuntimeError(n.RuntimeError.NOT_SUPPORTED_ERR);return x=e,e.isDetached()?(_=e.getSource(),void d.call(this,_)):void f.call(this,e.getSource(),function(e){r&&(_=c(e)),d.call(t,e)})},loadFromImage:function(e,t){this.meta=e.meta,x=new r(null,{name:e.name,size:e.size,type:e.type}),d.call(this,t?_=e.getAsBinaryString():e.getAsDataURL())},getInfo:function(){var t=this.getRuntime(),n;return!w&&_&&t.can("access_image_binary")&&(w=new o(_)),n={width:e().width||0,height:e().height||0,type:x.type||s.getFileMime(x.name),size:_&&_.length||x.size||0,name:x.name||"",meta:w&&w.meta||this.meta||{}}},downsize:function(){h.apply(this,arguments)},getAsCanvas:function(){return E&&(E.id=this.uid+"_canvas"),E},getAsBlob:function(e,t){return e!==this.type&&h.call(this,this.width,this.height,!1),new r(null,{name:x.name||"",type:e,data:v.getAsBinaryString.call(this,e,t)})},getAsDataURL:function(e){var t=arguments[1]||90;if(!b)return y.src;if("image/jpeg"!==e)return E.toDataURL("image/png");try{return E.toDataURL("image/jpeg",t/100)}catch(n){return E.toDataURL("image/jpeg")}},getAsBinaryString:function(e,t){if(!b)return _||(_=c(v.getAsDataURL(e,t))),_;if("image/jpeg"!==e)_=c(v.getAsDataURL(e,t));else{var n;t||(t=90);try{n=E.toDataURL("image/jpeg",t/100)}catch(i){n=E.toDataURL("image/jpeg")}_=c(n),w&&(_=w.stripHeaders(_),R&&(w.meta&&w.meta.exif&&w.setExif({PixelXDimension:this.width,PixelYDimension:this.height}),_=w.writeHeaders(_)),w.purge(),w=null)}return b=!1,_},destroy:function(){v=null,g.call(this),this.getRuntime().getShim().removeInstance(this.uid)}})}return e.Image=c}),i(j,[u,d,f,h,g],function(e,t,n,i,r){function o(){var e;try{e=navigator.plugins["Shockwave Flash"],e=e.description}catch(t){try{e=new ActiveXObject("ShockwaveFlash.ShockwaveFlash").GetVariable("$version")}catch(n){e="0.0"}}return e=e.match(/\d+/g),parseFloat(e[0]+"."+e[1])}function a(a){var c=this,l;a=e.extend({swf_url:t.swf_url},a),r.call(this,a,s,{access_binary:function(e){return e&&"browser"===c.mode},access_image_binary:function(e){return e&&"browser"===c.mode},display_media:r.capTrue,do_cors:r.capTrue,drag_and_drop:!1,report_upload_progress:function(){return"client"===c.mode},resize_image:r.capTrue,return_response_headers:!1,return_response_type:function(t){return"json"===t&&window.JSON?!0:!e.arrayDiff(t,["","text","document"])||"browser"===c.mode},return_status_code:function(t){return"browser"===c.mode||!e.arrayDiff(t,[200,404])},select_file:r.capTrue,select_multiple:r.capTrue,send_binary_string:function(e){return e&&"browser"===c.mode},send_browser_cookies:function(e){return e&&"browser"===c.mode},send_custom_headers:function(e){return e&&"browser"===c.mode},send_multipart:r.capTrue,slice_blob:function(e){return e&&"browser"===c.mode},stream_upload:function(e){return e&&"browser"===c.mode},summon_file_dialog:!1,upload_filesize:function(t){return e.parseSizeStr(t)<=2097152||"client"===c.mode},use_http_method:function(t){return!e.arrayDiff(t,["GET","POST"])}},{access_binary:function(e){return e?"browser":"client"},access_image_binary:function(e){return e?"browser":"client"},report_upload_progress:function(e){return e?"browser":"client"},return_response_type:function(t){return e.arrayDiff(t,["","text","json","document"])?"browser":["client","browser"]},return_status_code:function(t){return e.arrayDiff(t,[200,404])?"browser":["client","browser"]},send_binary_string:function(e){return e?"browser":"client"},send_browser_cookies:function(e){return e?"browser":"client"},send_custom_headers:function(e){return e?"browser":"client"},stream_upload:function(e){return e?"client":"browser"},upload_filesize:function(t){return e.parseSizeStr(t)>=2097152?"client":"browser"}},"client"),o()<10&&(this.mode=!1),e.extend(this,{getShim:function(){return n.get(this.uid)},shimExec:function(e,t){var n=[].slice.call(arguments,2);return c.getShim().exec(this.uid,e,t,n)},init:function(){var n,r,o;o=this.getShimContainer(),e.extend(o.style,{position:"absolute",top:"-8px",left:"-8px",width:"9px",height:"9px",overflow:"hidden"}),n='<object id="'+this.uid+'" type="application/x-shockwave-flash" data="'+a.swf_url+'" ',"IE"===t.browser&&(n+='classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" '),n+='width="100%" height="100%" style="outline:0"><param name="movie" value="'+a.swf_url+'" /><param name="flashvars" value="uid='+escape(this.uid)+"&target="+t.global_event_dispatcher+'" /><param name="wmode" value="transparent" /><param name="allowscriptaccess" value="always" /></object>',"IE"===t.browser?(r=document.createElement("div"),o.appendChild(r),r.outerHTML=n,r=o=null):o.innerHTML=n,l=setTimeout(function(){c&&!c.initialized&&c.trigger("Error",new i.RuntimeError(i.RuntimeError.NOT_INIT_ERR))},5e3)},destroy:function(e){return function(){e.call(c),clearTimeout(l),a=l=e=c=null}}(this.destroy)},u)}var s="flash",u={};return r.addConstructor(s,a),u}),i(V,[j,y],function(e,t){var n={slice:function(e,n,i,r){var o=this.getRuntime();return 0>n?n=Math.max(e.size+n,0):n>0&&(n=Math.min(n,e.size)),0>i?i=Math.max(e.size+i,0):i>0&&(i=Math.min(i,e.size)),e=o.shimExec.call(this,"Blob","slice",n,i,r||""),e&&(e=new t(o.uid,e)),e}};return e.Blob=n}),i(W,[j],function(e){var t={init:function(e){this.getRuntime().shimExec.call(this,"FileInput","init",{name:e.name,accept:e.accept,multiple:e.multiple}),this.trigger("ready")}};return e.FileInput=t}),i(Y,[j,m],function(e,t){function n(e,n){switch(n){case"readAsText":return t.atob(e,"utf8");case"readAsBinaryString":return t.atob(e);case"readAsDataURL":return e}return null}var i="",r={read:function(e,t){var r=this,o=r.getRuntime();return"readAsDataURL"===e&&(i="data:"+(t.type||"")+";base64,"),r.bind("Progress",function(t,r){r&&(i+=n(r,e))}),o.shimExec.call(this,"FileReader","readAsBase64",t.uid)},getResult:function(){return i},destroy:function(){i=null}};return e.FileReader=r}),i($,[j,m],function(e,t){function n(e,n){switch(n){case"readAsText":return t.atob(e,"utf8");case"readAsBinaryString":return t.atob(e);case"readAsDataURL":return e}return null}var i={read:function(e,t){var i,r=this.getRuntime();return(i=r.shimExec.call(this,"FileReaderSync","readAsBase64",t.uid))?("readAsDataURL"===e&&(i="data:"+(t.type||"")+";base64,"+i),n(i,e,t.type)):null}};return e.FileReaderSync=i}),i(J,[j,u,y,w,T,A,O],function(e,t,n,i,r,o,a){var s={send:function(e,i){function r(){e.transport=l.mode,l.shimExec.call(c,"XMLHttpRequest","send",e,i)}function s(e,t){l.shimExec.call(c,"XMLHttpRequest","appendBlob",e,t.uid),i=null,r()}function u(e,t){var n=new a;n.bind("TransportingComplete",function(){t(this.result)}),n.transport(e.getSource(),e.type,{ruid:l.uid})}var c=this,l=c.getRuntime();if(t.isEmptyObj(e.headers)||t.each(e.headers,function(e,t){l.shimExec.call(c,"XMLHttpRequest","setRequestHeader",t,e.toString())}),i instanceof o){var d;if(i.each(function(e,t){e instanceof n?d=t:l.shimExec.call(c,"XMLHttpRequest","append",t,e)}),i.hasBlob()){var f=i.getBlob();f.isDetached()?u(f,function(e){f.destroy(),s(d,e)}):s(d,f)}else i=null,r()}else i instanceof n?i.isDetached()?u(i,function(e){i.destroy(),i=e.uid,r()}):(i=i.uid,r()):r()},getResponse:function(e){var n,o,a=this.getRuntime();if(o=a.shimExec.call(this,"XMLHttpRequest","getResponseAsBlob")){if(o=new i(a.uid,o),"blob"===e)return o;try{if(n=new r,~t.inArray(e,["","text"]))return n.readAsText(o);if("json"===e&&window.JSON)return JSON.parse(n.readAsText(o))}finally{o.destroy()}}return null},abort:function(e){var t=this.getRuntime();t.shimExec.call(this,"XMLHttpRequest","abort"),this.dispatchEvent("readystatechange"),this.dispatchEvent("abort")}};return e.XMLHttpRequest=s}),i(Z,[j,y],function(e,t){var n={getAsBlob:function(e){var n=this.getRuntime(),i=n.shimExec.call(this,"Transporter","getAsBlob",e);return i?new t(n.uid,i):null}};return e.Transporter=n}),i(K,[j,u,O,y,T],function(e,t,n,i,r){var o={loadFromBlob:function(e){function t(e){r.shimExec.call(i,"Image","loadFromBlob",e.uid),i=r=null}var i=this,r=i.getRuntime();if(e.isDetached()){var o=new n;o.bind("TransportingComplete",function(){t(o.result.getSource())}),o.transport(e.getSource(),e.type,{ruid:r.uid})}else t(e.getSource())},loadFromImage:function(e){var t=this.getRuntime();return t.shimExec.call(this,"Image","loadFromImage",e.uid)},getAsBlob:function(e,t){var n=this.getRuntime(),r=n.shimExec.call(this,"Image","getAsBlob",e,t);return r?new i(n.uid,r):null},getAsDataURL:function(){var e=this.getRuntime(),t=e.Image.getAsBlob.apply(this,arguments),n;return t?(n=new r,n.readAsDataURL(t)):null}};return e.Image=o}),i(Q,[u,d,f,h,g],function(e,t,n,i,r){function o(e){var t=!1,n=null,i,r,o,a,s,u=0;try{try{n=new ActiveXObject("AgControl.AgControl"),n.IsVersionSupported(e)&&(t=!0),n=null}catch(c){var l=navigator.plugins["Silverlight Plug-In"];if(l){for(i=l.description,"1.0.30226.2"===i&&(i="2.0.30226.2"),r=i.split(".");r.length>3;)r.pop();for(;r.length<4;)r.push(0);for(o=e.split(".");o.length>4;)o.pop();do a=parseInt(o[u],10),s=parseInt(r[u],10),u++;while(u<o.length&&a===s);s>=a&&!isNaN(a)&&(t=!0)}}}catch(d){t=!1}return t}function a(a){var c=this,l;a=e.extend({xap_url:t.xap_url},a),r.call(this,a,s,{access_binary:r.capTrue,access_image_binary:r.capTrue,display_media:r.capTrue,do_cors:r.capTrue,drag_and_drop:!1,report_upload_progress:r.capTrue,resize_image:r.capTrue,return_response_headers:function(e){return e&&"client"===c.mode},return_response_type:function(e){return"json"!==e?!0:!!window.JSON},return_status_code:function(t){return"client"===c.mode||!e.arrayDiff(t,[200,404])},select_file:r.capTrue,select_multiple:r.capTrue,send_binary_string:r.capTrue,send_browser_cookies:function(e){return e&&"browser"===c.mode},send_custom_headers:function(e){return e&&"client"===c.mode},send_multipart:r.capTrue,slice_blob:r.capTrue,stream_upload:!0,summon_file_dialog:!1,upload_filesize:r.capTrue,use_http_method:function(t){return"client"===c.mode||!e.arrayDiff(t,["GET","POST"])}},{return_response_headers:function(e){return e?"client":"browser"},return_status_code:function(t){return e.arrayDiff(t,[200,404])?"client":["client","browser"]},send_browser_cookies:function(e){return e?"browser":"client"},send_custom_headers:function(e){return e?"client":"browser"},use_http_method:function(t){return e.arrayDiff(t,["GET","POST"])?"client":["client","browser"]}}),o("2.0.31005.0")&&"Opera"!==t.browser||(this.mode=!1),e.extend(this,{getShim:function(){return n.get(this.uid).content.Moxie},shimExec:function(e,t){var n=[].slice.call(arguments,2);return c.getShim().exec(this.uid,e,t,n)},init:function(){var e;e=this.getShimContainer(),e.innerHTML='<object id="'+this.uid+'" data="data:application/x-silverlight," type="application/x-silverlight-2" width="100%" height="100%" style="outline:none;"><param name="source" value="'+a.xap_url+'"/><param name="background" value="Transparent"/><param name="windowless" value="true"/><param name="enablehtmlaccess" value="true"/><param name="initParams" value="uid='+this.uid+",target="+t.global_event_dispatcher+'"/></object>',l=setTimeout(function(){c&&!c.initialized&&c.trigger("Error",new i.RuntimeError(i.RuntimeError.NOT_INIT_ERR))},"Windows"!==t.OS?1e4:5e3)},destroy:function(e){return function(){e.call(c),clearTimeout(l),a=l=e=c=null}}(this.destroy)},u)}var s="silverlight",u={};return r.addConstructor(s,a),u}),i(et,[Q,u,V],function(e,t,n){return e.Blob=t.extend({},n)}),i(tt,[Q],function(e){var t={init:function(e){function t(e){for(var t="",n=0;n<e.length;n++)t+=(""!==t?"|":"")+e[n].title+" | *."+e[n].extensions.replace(/,/g,";*.");return t}this.getRuntime().shimExec.call(this,"FileInput","init",t(e.accept),e.name,e.multiple),this.trigger("ready")}};return e.FileInput=t}),i(nt,[Q,f,L],function(e,t,n){var i={init:function(){var e=this,i=e.getRuntime(),r;return r=i.getShimContainer(),n.addEvent(r,"dragover",function(e){e.preventDefault(),e.stopPropagation(),e.dataTransfer.dropEffect="copy"},e.uid),n.addEvent(r,"dragenter",function(e){e.preventDefault();var n=t.get(i.uid).dragEnter(e);n&&e.stopPropagation()},e.uid),n.addEvent(r,"drop",function(e){e.preventDefault();var n=t.get(i.uid).dragDrop(e);n&&e.stopPropagation()},e.uid),i.shimExec.call(this,"FileDrop","init")}};return e.FileDrop=i}),i(it,[Q,u,Y],function(e,t,n){return e.FileReader=t.extend({},n)}),i(rt,[Q,u,$],function(e,t,n){return e.FileReaderSync=t.extend({},n)}),i(ot,[Q,u,J],function(e,t,n){return e.XMLHttpRequest=t.extend({},n)}),i(at,[Q,u,Z],function(e,t,n){return e.Transporter=t.extend({},n)}),i(st,[Q,u,K],function(e,t,n){return e.Image=t.extend({},n,{getInfo:function(){var e=this.getRuntime(),n=["tiff","exif","gps"],i={meta:{}},r=e.shimExec.call(this,"Image","getInfo");return r.meta&&t.each(n,function(e){var t=r.meta[e],n,o,a,s;if(t&&t.keys)for(i.meta[e]={},o=0,a=t.keys.length;a>o;o++)n=t.keys[o],s=t[n],s&&(/^(\d|[1-9]\d+)$/.test(s)?s=parseInt(s,10):/^\d*\.\d+$/.test(s)&&(s=parseFloat(s)),i.meta[e][n]=s)}),i.width=parseInt(r.width,10),i.height=parseInt(r.height,10),i.size=parseInt(r.size,10),i.type=r.type,i.name=r.name,i}})}),i(ut,[u,h,g,d],function(e,t,n,i){function r(t){var r=this,s=n.capTest,u=n.capTrue;n.call(this,t,o,{access_binary:s(window.FileReader||window.File&&File.getAsDataURL),access_image_binary:!1,display_media:s(a.Image&&(i.can("create_canvas")||i.can("use_data_uri_over32kb"))),do_cors:!1,drag_and_drop:!1,filter_by_extension:s(function(){return"Chrome"===i.browser&&i.version>=28||"IE"===i.browser&&i.version>=10}()),resize_image:function(){return a.Image&&r.can("access_binary")&&i.can("create_canvas")},report_upload_progress:!1,return_response_headers:!1,return_response_type:function(t){return"json"===t&&window.JSON?!0:!!~e.inArray(t,["text","document",""])},return_status_code:function(t){return!e.arrayDiff(t,[200,404])},select_file:function(){return i.can("use_fileinput")},select_multiple:!1,send_binary_string:!1,send_custom_headers:!1,send_multipart:!0,slice_blob:!1,stream_upload:function(){return r.can("select_file")},summon_file_dialog:s(function(){return"Firefox"===i.browser&&i.version>=4||"Opera"===i.browser&&i.version>=12||!!~e.inArray(i.browser,["Chrome","Safari"])}()),upload_filesize:u,use_http_method:function(t){return!e.arrayDiff(t,["GET","POST"])}}),e.extend(this,{init:function(){this.trigger("Init")},destroy:function(e){return function(){e.call(r),e=r=null}}(this.destroy)}),e.extend(this.getShim(),a)}var o="html4",a={};return n.addConstructor(o,r),a}),i(ct,[ut,u,f,L,l,d],function(e,t,n,i,r,o){function a(){function e(){var r=this,l=r.getRuntime(),d,f,h,p,m,g;g=t.guid("uid_"),d=l.getShimContainer(),a&&(h=n.get(a+"_form"),h&&t.extend(h.style,{top:"100%"})),p=document.createElement("form"),p.setAttribute("id",g+"_form"),p.setAttribute("method","post"),p.setAttribute("enctype","multipart/form-data"),p.setAttribute("encoding","multipart/form-data"),t.extend(p.style,{overflow:"hidden",position:"absolute",top:0,left:0,width:"100%",height:"100%"}),m=document.createElement("input"),m.setAttribute("id",g),m.setAttribute("type","file"),m.setAttribute("name",c.name||"Filedata"),m.setAttribute("accept",u.join(",")),t.extend(m.style,{fontSize:"999px",opacity:0}),p.appendChild(m),d.appendChild(p),t.extend(m.style,{position:"absolute",top:0,left:0,width:"100%",height:"100%"}),"IE"===o.browser&&o.version<10&&t.extend(m.style,{filter:"progid:DXImageTransform.Microsoft.Alpha(opacity=0)"}),m.onchange=function(){var t;this.value&&(t=this.files?this.files[0]:{name:this.value},s=[t],this.onchange=function(){},e.call(r),r.bind("change",function i(){var e=n.get(g),t=n.get(g+"_form"),o;r.unbind("change",i),r.files.length&&e&&t&&(o=r.files[0],e.setAttribute("id",o.uid),t.setAttribute("id",o.uid+"_form"),t.setAttribute("target",o.uid+"_iframe")),e=t=null},998),m=p=null,r.trigger("change"))},l.can("summon_file_dialog")&&(f=n.get(c.browse_button),i.removeEvent(f,"click",r.uid),i.addEvent(f,"click",function(e){m&&!m.disabled&&m.click(),e.preventDefault()},r.uid)),a=g,d=h=f=null}var a,s=[],u=[],c;t.extend(this,{init:function(t){var o=this,a=o.getRuntime(),s;c=t,u=t.accept.mimes||r.extList2mimes(t.accept,a.can("filter_by_extension")),s=a.getShimContainer(),function(){var e,r,u;e=n.get(t.browse_button),a.can("summon_file_dialog")&&("static"===n.getStyle(e,"position")&&(e.style.position="relative"),r=parseInt(n.getStyle(e,"z-index"),10)||1,e.style.zIndex=r,s.style.zIndex=r-1),u=a.can("summon_file_dialog")?e:s,i.addEvent(u,"mouseover",function(){o.trigger("mouseenter")},o.uid),i.addEvent(u,"mouseout",function(){o.trigger("mouseleave")},o.uid),i.addEvent(u,"mousedown",function(){o.trigger("mousedown")},o.uid),i.addEvent(n.get(t.container),"mouseup",function(){o.trigger("mouseup")},o.uid),e=null}(),e.call(this),s=null,o.trigger({type:"ready",async:!0})},getFiles:function(){return s},disable:function(e){var t;(t=n.get(a))&&(t.disabled=!!e)},destroy:function(){var e=this.getRuntime(),t=e.getShim(),r=e.getShimContainer();i.removeAllEvents(r,this.uid),i.removeAllEvents(c&&n.get(c.container),this.uid),i.removeAllEvents(c&&n.get(c.browse_button),this.uid),r&&(r.innerHTML=""),t.removeInstance(this.uid),a=s=u=c=r=t=null}})}return e.FileInput=a}),i(lt,[ut,F],function(e,t){return e.FileReader=t}),i(dt,[ut,u,f,R,h,L,y,A],function(e,t,n,i,r,o,a,s){function u(){function e(e){var t=this,i,r,a,s,u=!1;if(l){if(i=l.id.replace(/_iframe$/,""),r=n.get(i+"_form")){for(a=r.getElementsByTagName("input"),s=a.length;s--;)switch(a[s].getAttribute("type")){case"hidden":a[s].parentNode.removeChild(a[s]);break;case"file":u=!0}a=[],u||r.parentNode.removeChild(r),r=null}setTimeout(function(){o.removeEvent(l,"load",t.uid),l.parentNode&&l.parentNode.removeChild(l);var n=t.getRuntime().getShimContainer();n.children.length||n.parentNode.removeChild(n),n=l=null,e()},1)}}var u,c,l;t.extend(this,{send:function(d,f){function h(){var n=m.getShimContainer()||document.body,r=document.createElement("div");r.innerHTML='<iframe id="'+g+'_iframe" name="'+g+'_iframe" src="javascript:&quot;&quot;" style="display:none"></iframe>',l=r.firstChild,n.appendChild(l),o.addEvent(l,"load",function(){var n;try{n=l.contentWindow.document||l.contentDocument||window.frames[l.id].document,/^4(0[0-9]|1[0-7]|2[2346])\s/.test(n.title)?u=n.title.replace(/^(\d+).*$/,"$1"):(u=200,c=t.trim(n.body.innerHTML),p.trigger({type:"progress",loaded:c.length,total:c.length}),w&&p.trigger({type:"uploadprogress",loaded:w.size||1025,total:w.size||1025}))}catch(r){if(!i.hasSameOrigin(d.url))return void e.call(p,function(){p.trigger("error")});u=404}e.call(p,function(){p.trigger("load")})},p.uid)}var p=this,m=p.getRuntime(),g,v,y,w;if(u=c=null,f instanceof s&&f.hasBlob()){if(w=f.getBlob(),g=w.uid,y=n.get(g),v=n.get(g+"_form"),!v)throw new r.DOMException(r.DOMException.NOT_FOUND_ERR)}else g=t.guid("uid_"),v=document.createElement("form"),v.setAttribute("id",g+"_form"),v.setAttribute("method",d.method),v.setAttribute("enctype","multipart/form-data"),v.setAttribute("encoding","multipart/form-data"),v.setAttribute("target",g+"_iframe"),m.getShimContainer().appendChild(v);f instanceof s&&f.each(function(e,n){if(e instanceof a)y&&y.setAttribute("name",n);else{var i=document.createElement("input");t.extend(i,{type:"hidden",name:n,value:e}),y?v.insertBefore(i,y):v.appendChild(i)}}),v.setAttribute("action",d.url),h(),v.submit(),p.trigger("loadstart")},getStatus:function(){return u},getResponse:function(e){if("json"===e&&"string"===t.typeOf(c)&&window.JSON)try{return JSON.parse(c.replace(/^\s*<pre[^>]*>/,"").replace(/<\/pre>\s*$/,""))}catch(n){return null}return c},abort:function(){var t=this;l&&l.contentWindow&&(l.contentWindow.stop?l.contentWindow.stop():l.contentWindow.document.execCommand?l.contentWindow.document.execCommand("Stop"):l.src="about:blank"),e.call(this,function(){t.dispatchEvent("abort")})}})}return e.XMLHttpRequest=u}),i(ft,[ut,X],function(e,t){return e.Image=t}),a([u,c,l,d,f,h,p,m,g,v,y,w,E,_,x,b,R,T,A,S,O,I,L])}(this);;(function(e){"use strict";var t={},n=e.moxie.core.utils.Basic.inArray;return function r(e){var i,s;for(i in e)s=typeof e[i],s==="object"&&!~n(i,["Exceptions","Env","Mime"])?r(e[i]):s==="function"&&(t[i]=e[i])}(e.moxie),t.Env=e.moxie.core.utils.Env,t.Mime=e.moxie.core.utils.Mime,t.Exceptions=e.moxie.core.Exceptions,e.mOxie=t,e.o||(e.o=t),t})(this);
Index: /trunk/themes/default/js/plugins/plupload/plupload.dev.js
===================================================================
--- /trunk/themes/default/js/plugins/plupload/plupload.dev.js	(revision 28545)
+++ /trunk/themes/default/js/plugins/plupload/plupload.dev.js	(revision 28545)
@@ -0,0 +1,2315 @@
+/**
+ * Plupload - multi-runtime File Uploader
+ * v2.1.2
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ *
+ * Date: 2014-05-14
+ */
+/**
+ * Plupload.js
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+/*global mOxie:true */
+
+;(function(window, o, undef) {
+
+var delay = window.setTimeout
+, fileFilters = {}
+;
+
+// convert plupload features to caps acceptable by mOxie
+function normalizeCaps(settings) {		
+	var features = settings.required_features, caps = {};
+
+	function resolve(feature, value, strict) {
+		// Feature notation is deprecated, use caps (this thing here is required for backward compatibility)
+		var map = { 
+			chunks: 'slice_blob',
+			jpgresize: 'send_binary_string',
+			pngresize: 'send_binary_string',
+			progress: 'report_upload_progress',
+			multi_selection: 'select_multiple',
+			dragdrop: 'drag_and_drop',
+			drop_element: 'drag_and_drop',
+			headers: 'send_custom_headers',
+			urlstream_upload: 'send_binary_string',
+			canSendBinary: 'send_binary',
+			triggerDialog: 'summon_file_dialog'
+		};
+
+		if (map[feature]) {
+			caps[map[feature]] = value;
+		} else if (!strict) {
+			caps[feature] = value;
+		}
+	}
+
+	if (typeof(features) === 'string') {
+		plupload.each(features.split(/\s*,\s*/), function(feature) {
+			resolve(feature, true);
+		});
+	} else if (typeof(features) === 'object') {
+		plupload.each(features, function(value, feature) {
+			resolve(feature, value);
+		});
+	} else if (features === true) {
+		// check settings for required features
+		if (settings.chunk_size > 0) {
+			caps.slice_blob = true;
+		}
+
+		if (settings.resize.enabled || !settings.multipart) {
+			caps.send_binary_string = true;
+		}
+		
+		plupload.each(settings, function(value, feature) {
+			resolve(feature, !!value, true); // strict check
+		});
+	}
+	
+	return caps;
+}
+
+/** 
+ * @module plupload	
+ * @static
+ */
+var plupload = {
+	/**
+	 * Plupload version will be replaced on build.
+	 *
+	 * @property VERSION
+	 * @for Plupload
+	 * @static
+	 * @final
+	 */
+	VERSION : '2.1.2',
+
+	/**
+	 * Inital state of the queue and also the state ones it's finished all it's uploads.
+	 *
+	 * @property STOPPED
+	 * @static
+	 * @final
+	 */
+	STOPPED : 1,
+
+	/**
+	 * Upload process is running
+	 *
+	 * @property STARTED
+	 * @static
+	 * @final
+	 */
+	STARTED : 2,
+
+	/**
+	 * File is queued for upload
+	 *
+	 * @property QUEUED
+	 * @static
+	 * @final
+	 */
+	QUEUED : 1,
+
+	/**
+	 * File is being uploaded
+	 *
+	 * @property UPLOADING
+	 * @static
+	 * @final
+	 */
+	UPLOADING : 2,
+
+	/**
+	 * File has failed to be uploaded
+	 *
+	 * @property FAILED
+	 * @static
+	 * @final
+	 */
+	FAILED : 4,
+
+	/**
+	 * File has been uploaded successfully
+	 *
+	 * @property DONE
+	 * @static
+	 * @final
+	 */
+	DONE : 5,
+
+	// Error constants used by the Error event
+
+	/**
+	 * Generic error for example if an exception is thrown inside Silverlight.
+	 *
+	 * @property GENERIC_ERROR
+	 * @static
+	 * @final
+	 */
+	GENERIC_ERROR : -100,
+
+	/**
+	 * HTTP transport error. For example if the server produces a HTTP status other than 200.
+	 *
+	 * @property HTTP_ERROR
+	 * @static
+	 * @final
+	 */
+	HTTP_ERROR : -200,
+
+	/**
+	 * Generic I/O error. For example if it wasn't possible to open the file stream on local machine.
+	 *
+	 * @property IO_ERROR
+	 * @static
+	 * @final
+	 */
+	IO_ERROR : -300,
+
+	/**
+	 * @property SECURITY_ERROR
+	 * @static
+	 * @final
+	 */
+	SECURITY_ERROR : -400,
+
+	/**
+	 * Initialization error. Will be triggered if no runtime was initialized.
+	 *
+	 * @property INIT_ERROR
+	 * @static
+	 * @final
+	 */
+	INIT_ERROR : -500,
+
+	/**
+	 * File size error. If the user selects a file that is too large it will be blocked and an error of this type will be triggered.
+	 *
+	 * @property FILE_SIZE_ERROR
+	 * @static
+	 * @final
+	 */
+	FILE_SIZE_ERROR : -600,
+
+	/**
+	 * File extension error. If the user selects a file that isn't valid according to the filters setting.
+	 *
+	 * @property FILE_EXTENSION_ERROR
+	 * @static
+	 * @final
+	 */
+	FILE_EXTENSION_ERROR : -601,
+
+	/**
+	 * Duplicate file error. If prevent_duplicates is set to true and user selects the same file again.
+	 *
+	 * @property FILE_DUPLICATE_ERROR
+	 * @static
+	 * @final
+	 */
+	FILE_DUPLICATE_ERROR : -602,
+
+	/**
+	 * Runtime will try to detect if image is proper one. Otherwise will throw this error.
+	 *
+	 * @property IMAGE_FORMAT_ERROR
+	 * @static
+	 * @final
+	 */
+	IMAGE_FORMAT_ERROR : -700,
+
+	/**
+	 * While working on files runtime may run out of memory and will throw this error.
+	 *
+	 * @since 2.1.2
+	 * @property MEMORY_ERROR
+	 * @static
+	 * @final
+	 */
+	MEMORY_ERROR : -701,
+
+	/**
+	 * Each runtime has an upper limit on a dimension of the image it can handle. If bigger, will throw this error.
+	 *
+	 * @property IMAGE_DIMENSIONS_ERROR
+	 * @static
+	 * @final
+	 */
+	IMAGE_DIMENSIONS_ERROR : -702,
+
+	/**
+	 * Mime type lookup table.
+	 *
+	 * @property mimeTypes
+	 * @type Object
+	 * @final
+	 */
+	mimeTypes : o.mimes,
+
+	/**
+	 * In some cases sniffing is the only way around :(
+	 */
+	ua: o.ua,
+
+	/**
+	 * Gets the true type of the built-in object (better version of typeof).
+	 * @credits Angus Croll (http://javascriptweblog.wordpress.com/)
+	 *
+	 * @method typeOf
+	 * @static
+	 * @param {Object} o Object to check.
+	 * @return {String} Object [[Class]]
+	 */
+	typeOf: o.typeOf,
+
+	/**
+	 * Extends the specified object with another object.
+	 *
+	 * @method extend
+	 * @static
+	 * @param {Object} target Object to extend.
+	 * @param {Object..} obj Multiple objects to extend with.
+	 * @return {Object} Same as target, the extended object.
+	 */
+	extend : o.extend,
+
+	/**
+	 * Generates an unique ID. This is 99.99% unique since it takes the current time and 5 random numbers.
+	 * The only way a user would be able to get the same ID is if the two persons at the same exact milisecond manages
+	 * to get 5 the same random numbers between 0-65535 it also uses a counter so each call will be guaranteed to be page unique.
+	 * It's more probable for the earth to be hit with an ansteriod. You can also if you want to be 100% sure set the plupload.guidPrefix property
+	 * to an user unique key.
+	 *
+	 * @method guid
+	 * @static
+	 * @return {String} Virtually unique id.
+	 */
+	guid : o.guid,
+
+	/**
+	 * Get array of DOM Elements by their ids.
+	 * 
+	 * @method get
+	 * @for Utils
+	 * @param {String} id Identifier of the DOM Element
+	 * @return {Array}
+	*/
+	get : function get(ids) {
+		var els = [], el;
+
+		if (o.typeOf(ids) !== 'array') {
+			ids = [ids];
+		}
+
+		var i = ids.length;
+		while (i--) {
+			el = o.get(ids[i]);
+			if (el) {
+				els.push(el);
+			}
+		}
+
+		return els.length ? els : null;
+	},
+
+	/**
+	 * Executes the callback function for each item in array/object. If you return false in the
+	 * callback it will break the loop.
+	 *
+	 * @method each
+	 * @static
+	 * @param {Object} obj Object to iterate.
+	 * @param {function} callback Callback function to execute for each item.
+	 */
+	each : o.each,
+
+	/**
+	 * Returns the absolute x, y position of an Element. The position will be returned in a object with x, y fields.
+	 *
+	 * @method getPos
+	 * @static
+	 * @param {Element} node HTML element or element id to get x, y position from.
+	 * @param {Element} root Optional root element to stop calculations at.
+	 * @return {object} Absolute position of the specified element object with x, y fields.
+	 */
+	getPos : o.getPos,
+
+	/**
+	 * Returns the size of the specified node in pixels.
+	 *
+	 * @method getSize
+	 * @static
+	 * @param {Node} node Node to get the size of.
+	 * @return {Object} Object with a w and h property.
+	 */
+	getSize : o.getSize,
+
+	/**
+	 * Encodes the specified string.
+	 *
+	 * @method xmlEncode
+	 * @static
+	 * @param {String} s String to encode.
+	 * @return {String} Encoded string.
+	 */
+	xmlEncode : function(str) {
+		var xmlEncodeChars = {'<' : 'lt', '>' : 'gt', '&' : 'amp', '"' : 'quot', '\'' : '#39'}, xmlEncodeRegExp = /[<>&\"\']/g;
+
+		return str ? ('' + str).replace(xmlEncodeRegExp, function(chr) {
+			return xmlEncodeChars[chr] ? '&' + xmlEncodeChars[chr] + ';' : chr;
+		}) : str;
+	},
+
+	/**
+	 * Forces anything into an array.
+	 *
+	 * @method toArray
+	 * @static
+	 * @param {Object} obj Object with length field.
+	 * @return {Array} Array object containing all items.
+	 */
+	toArray : o.toArray,
+
+	/**
+	 * Find an element in array and return it's index if present, otherwise return -1.
+	 *
+	 * @method inArray
+	 * @static
+	 * @param {mixed} needle Element to find
+	 * @param {Array} array
+	 * @return {Int} Index of the element, or -1 if not found
+	 */
+	inArray : o.inArray,
+
+	/**
+	 * Extends the language pack object with new items.
+	 *
+	 * @method addI18n
+	 * @static
+	 * @param {Object} pack Language pack items to add.
+	 * @return {Object} Extended language pack object.
+	 */
+	addI18n : o.addI18n,
+
+	/**
+	 * Translates the specified string by checking for the english string in the language pack lookup.
+	 *
+	 * @method translate
+	 * @static
+	 * @param {String} str String to look for.
+	 * @return {String} Translated string or the input string if it wasn't found.
+	 */
+	translate : o.translate,
+
+	/**
+	 * Checks if object is empty.
+	 *
+	 * @method isEmptyObj
+	 * @static
+	 * @param {Object} obj Object to check.
+	 * @return {Boolean}
+	 */
+	isEmptyObj : o.isEmptyObj,
+
+	/**
+	 * Checks if specified DOM element has specified class.
+	 *
+	 * @method hasClass
+	 * @static
+	 * @param {Object} obj DOM element like object to add handler to.
+	 * @param {String} name Class name
+	 */
+	hasClass : o.hasClass,
+
+	/**
+	 * Adds specified className to specified DOM element.
+	 *
+	 * @method addClass
+	 * @static
+	 * @param {Object} obj DOM element like object to add handler to.
+	 * @param {String} name Class name
+	 */
+	addClass : o.addClass,
+
+	/**
+	 * Removes specified className from specified DOM element.
+	 *
+	 * @method removeClass
+	 * @static
+	 * @param {Object} obj DOM element like object to add handler to.
+	 * @param {String} name Class name
+	 */
+	removeClass : o.removeClass,
+
+	/**
+	 * Returns a given computed style of a DOM element.
+	 *
+	 * @method getStyle
+	 * @static
+	 * @param {Object} obj DOM element like object.
+	 * @param {String} name Style you want to get from the DOM element
+	 */
+	getStyle : o.getStyle,
+
+	/**
+	 * Adds an event handler to the specified object and store reference to the handler
+	 * in objects internal Plupload registry (@see removeEvent).
+	 *
+	 * @method addEvent
+	 * @static
+	 * @param {Object} obj DOM element like object to add handler to.
+	 * @param {String} name Name to add event listener to.
+	 * @param {Function} callback Function to call when event occurs.
+	 * @param {String} (optional) key that might be used to add specifity to the event record.
+	 */
+	addEvent : o.addEvent,
+
+	/**
+	 * Remove event handler from the specified object. If third argument (callback)
+	 * is not specified remove all events with the specified name.
+	 *
+	 * @method removeEvent
+	 * @static
+	 * @param {Object} obj DOM element to remove event listener(s) from.
+	 * @param {String} name Name of event listener to remove.
+	 * @param {Function|String} (optional) might be a callback or unique key to match.
+	 */
+	removeEvent: o.removeEvent,
+
+	/**
+	 * Remove all kind of events from the specified object
+	 *
+	 * @method removeAllEvents
+	 * @static
+	 * @param {Object} obj DOM element to remove event listeners from.
+	 * @param {String} (optional) unique key to match, when removing events.
+	 */
+	removeAllEvents: o.removeAllEvents,
+
+	/**
+	 * Cleans the specified name from national characters (diacritics). The result will be a name with only a-z, 0-9 and _.
+	 *
+	 * @method cleanName
+	 * @static
+	 * @param {String} s String to clean up.
+	 * @return {String} Cleaned string.
+	 */
+	cleanName : function(name) {
+		var i, lookup;
+
+		// Replace diacritics
+		lookup = [
+			/[\300-\306]/g, 'A', /[\340-\346]/g, 'a',
+			/\307/g, 'C', /\347/g, 'c',
+			/[\310-\313]/g, 'E', /[\350-\353]/g, 'e',
+			/[\314-\317]/g, 'I', /[\354-\357]/g, 'i',
+			/\321/g, 'N', /\361/g, 'n',
+			/[\322-\330]/g, 'O', /[\362-\370]/g, 'o',
+			/[\331-\334]/g, 'U', /[\371-\374]/g, 'u'
+		];
+
+		for (i = 0; i < lookup.length; i += 2) {
+			name = name.replace(lookup[i], lookup[i + 1]);
+		}
+
+		// Replace whitespace
+		name = name.replace(/\s+/g, '_');
+
+		// Remove anything else
+		name = name.replace(/[^a-z0-9_\-\.]+/gi, '');
+
+		return name;
+	},
+
+	/**
+	 * Builds a full url out of a base URL and an object with items to append as query string items.
+	 *
+	 * @method buildUrl
+	 * @static
+	 * @param {String} url Base URL to append query string items to.
+	 * @param {Object} items Name/value object to serialize as a querystring.
+	 * @return {String} String with url + serialized query string items.
+	 */
+	buildUrl : function(url, items) {
+		var query = '';
+
+		plupload.each(items, function(value, name) {
+			query += (query ? '&' : '') + encodeURIComponent(name) + '=' + encodeURIComponent(value);
+		});
+
+		if (query) {
+			url += (url.indexOf('?') > 0 ? '&' : '?') + query;
+		}
+
+		return url;
+	},
+
+	/**
+	 * Formats the specified number as a size string for example 1024 becomes 1 KB.
+	 *
+	 * @method formatSize
+	 * @static
+	 * @param {Number} size Size to format as string.
+	 * @return {String} Formatted size string.
+	 */
+	formatSize : function(size) {
+
+		if (size === undef || /\D/.test(size)) {
+			return plupload.translate('N/A');
+		}
+
+		function round(num, precision) {
+			return Math.round(num * Math.pow(10, precision)) / Math.pow(10, precision);
+		}
+
+		var boundary = Math.pow(1024, 4);
+
+		// TB
+		if (size > boundary) {
+			return round(size / boundary, 1) + " " + plupload.translate('tb');
+		}
+
+		// GB
+		if (size > (boundary/=1024)) {
+			return round(size / boundary, 1) + " " + plupload.translate('gb');
+		}
+
+		// MB
+		if (size > (boundary/=1024)) {
+			return round(size / boundary, 1) + " " + plupload.translate('mb');
+		}
+
+		// KB
+		if (size > 1024) {
+			return Math.round(size / 1024) + " " + plupload.translate('kb');
+		}
+
+		return size + " " + plupload.translate('b');
+	},
+
+
+	/**
+	 * Parses the specified size string into a byte value. For example 10kb becomes 10240.
+	 *
+	 * @method parseSize
+	 * @static
+	 * @param {String|Number} size String to parse or number to just pass through.
+	 * @return {Number} Size in bytes.
+	 */
+	parseSize : o.parseSizeStr,
+
+
+	/**
+	 * A way to predict what runtime will be choosen in the current environment with the
+	 * specified settings.
+	 *
+	 * @method predictRuntime
+	 * @static
+	 * @param {Object|String} config Plupload settings to check
+	 * @param {String} [runtimes] Comma-separated list of runtimes to check against
+	 * @return {String} Type of compatible runtime
+	 */
+	predictRuntime : function(config, runtimes) {
+		var up, runtime;
+
+		up = new plupload.Uploader(config);
+		runtime = o.Runtime.thatCan(up.getOption().required_features, runtimes || config.runtimes);
+		up.destroy();
+		return runtime;
+	},
+
+	/**
+	 * Registers a filter that will be executed for each file added to the queue.
+	 * If callback returns false, file will not be added.
+	 *
+	 * Callback receives two arguments: a value for the filter as it was specified in settings.filters
+	 * and a file to be filtered. Callback is executed in the context of uploader instance.
+	 *
+	 * @method addFileFilter
+	 * @static
+	 * @param {String} name Name of the filter by which it can be referenced in settings.filters
+	 * @param {String} cb Callback - the actual routine that every added file must pass
+	 */
+	addFileFilter: function(name, cb) {
+		fileFilters[name] = cb;
+	}
+};
+
+
+plupload.addFileFilter('mime_types', function(filters, file, cb) {
+	if (filters.length && !filters.regexp.test(file.name)) {
+		this.trigger('Error', {
+			code : plupload.FILE_EXTENSION_ERROR,
+			message : plupload.translate('File extension error.'),
+			file : file
+		});
+		cb(false);
+	} else {
+		cb(true);
+	}
+});
+
+
+plupload.addFileFilter('max_file_size', function(maxSize, file, cb) {
+	var undef;
+
+	maxSize = plupload.parseSize(maxSize);
+
+	// Invalid file size
+	if (file.size !== undef && maxSize && file.size > maxSize) {
+		this.trigger('Error', {
+			code : plupload.FILE_SIZE_ERROR,
+			message : plupload.translate('File size error.'),
+			file : file
+		});
+		cb(false);
+	} else {
+		cb(true);
+	}
+});
+
+
+plupload.addFileFilter('prevent_duplicates', function(value, file, cb) {
+	if (value) {
+		var ii = this.files.length;
+		while (ii--) {
+			// Compare by name and size (size might be 0 or undefined, but still equivalent for both)
+			if (file.name === this.files[ii].name && file.size === this.files[ii].size) {
+				this.trigger('Error', {
+					code : plupload.FILE_DUPLICATE_ERROR,
+					message : plupload.translate('Duplicate file error.'),
+					file : file
+				});
+				cb(false);
+				return;
+			}
+		}
+	}
+	cb(true);
+});
+
+
+/**
+@class Uploader
+@constructor
+
+@param {Object} settings For detailed information about each option check documentation.
+	@param {String|DOMElement} settings.browse_button id of the DOM element or DOM element itself to use as file dialog trigger.
+	@param {String} settings.url URL of the server-side upload handler.
+	@param {Number|String} [settings.chunk_size=0] Chunk size in bytes to slice the file into. Shorcuts with b, kb, mb, gb, tb suffixes also supported. `e.g. 204800 or "204800b" or "200kb"`. By default - disabled.
+	@param {Boolean} [settings.send_chunk_number=true] Whether to send chunks and chunk numbers, or total and offset bytes.
+	@param {String} [settings.container] id of the DOM element to use as a container for uploader structures. Defaults to document.body.
+	@param {String|DOMElement} [settings.drop_element] id of the DOM element or DOM element itself to use as a drop zone for Drag-n-Drop.
+	@param {String} [settings.file_data_name="file"] Name for the file field in Multipart formated message.
+	@param {Object} [settings.filters={}] Set of file type filters.
+		@param {Array} [settings.filters.mime_types=[]] List of file types to accept, each one defined by title and list of extensions. `e.g. {title : "Image files", extensions : "jpg,jpeg,gif,png"}`. Dispatches `plupload.FILE_EXTENSION_ERROR`
+		@param {String|Number} [settings.filters.max_file_size=0] Maximum file size that the user can pick, in bytes. Optionally supports b, kb, mb, gb, tb suffixes. `e.g. "10mb" or "1gb"`. By default - not set. Dispatches `plupload.FILE_SIZE_ERROR`.
+		@param {Boolean} [settings.filters.prevent_duplicates=false] Do not let duplicates into the queue. Dispatches `plupload.FILE_DUPLICATE_ERROR`.
+	@param {String} [settings.flash_swf_url] URL of the Flash swf.
+	@param {Object} [settings.headers] Custom headers to send with the upload. Hash of name/value pairs.
+	@param {Number} [settings.max_retries=0] How many times to retry the chunk or file, before triggering Error event.
+	@param {Boolean} [settings.multipart=true] Whether to send file and additional parameters as Multipart formated message.
+	@param {Object} [settings.multipart_params] Hash of key/value pairs to send with every file upload.
+	@param {Boolean} [settings.multi_selection=true] Enable ability to select multiple files at once in file dialog.
+	@param {String|Object} [settings.required_features] Either comma-separated list or hash of required features that chosen runtime should absolutely possess.
+	@param {Object} [settings.resize] Enable resizng of images on client-side. Applies to `image/jpeg` and `image/png` only. `e.g. {width : 200, height : 200, quality : 90, crop: true}`
+		@param {Number} [settings.resize.width] If image is bigger, it will be resized.
+		@param {Number} [settings.resize.height] If image is bigger, it will be resized.
+		@param {Number} [settings.resize.quality=90] Compression quality for jpegs (1-100).
+		@param {Boolean} [settings.resize.crop=false] Whether to crop images to exact dimensions. By default they will be resized proportionally.
+	@param {String} [settings.runtimes="html5,flash,silverlight,html4"] Comma separated list of runtimes, that Plupload will try in turn, moving to the next if previous fails.
+	@param {String} [settings.silverlight_xap_url] URL of the Silverlight xap.
+	@param {Boolean} [settings.unique_names=false] If true will generate unique filenames for uploaded files.
+	@param {Boolean} [settings.send_file_name=true] Whether to send file name as additional argument - 'name' (required for chunked uploads and some other cases where file name cannot be sent via normal ways).
+*/
+plupload.Uploader = function(options) {
+	/**
+	 * Fires when the current RunTime has been initialized.
+	 *
+	 * @event Init
+	 * @param {plupload.Uploader} uploader Uploader instance sending the event.
+	 */
+
+	/**
+	 * Fires after the init event incase you need to perform actions there.
+	 *
+	 * @event PostInit
+	 * @param {plupload.Uploader} uploader Uploader instance sending the event.
+	 */
+
+	/**
+	 * Fires when the option is changed in via uploader.setOption().
+	 *
+	 * @event OptionChanged
+	 * @since 2.1
+	 * @param {plupload.Uploader} uploader Uploader instance sending the event.
+	 * @param {String} name Name of the option that was changed
+	 * @param {Mixed} value New value for the specified option
+	 * @param {Mixed} oldValue Previous value of the option
+	 */
+
+	/**
+	 * Fires when the silverlight/flash or other shim needs to move.
+	 *
+	 * @event Refresh
+	 * @param {plupload.Uploader} uploader Uploader instance sending the event.
+	 */
+
+	/**
+	 * Fires when the overall state is being changed for the upload queue.
+	 *
+	 * @event StateChanged
+	 * @param {plupload.Uploader} uploader Uploader instance sending the event.
+	 */
+
+	/**
+	 * Fires when browse_button is clicked and browse dialog shows.
+	 *
+	 * @event Browse
+	 * @since 2.1.2
+	 * @param {plupload.Uploader} uploader Uploader instance sending the event.
+	 */	
+
+	/**
+	 * Fires for every filtered file before it is added to the queue.
+	 * 
+	 * @event FileFiltered
+	 * @since 2.1
+	 * @param {plupload.Uploader} uploader Uploader instance sending the event.
+	 * @param {plupload.File} file Another file that has to be added to the queue.
+	 */
+
+	/**
+	 * Fires when the file queue is changed. In other words when files are added/removed to the files array of the uploader instance.
+	 *
+	 * @event QueueChanged
+	 * @param {plupload.Uploader} uploader Uploader instance sending the event.
+	 */ 
+
+	/**
+	 * Fires after files were filtered and added to the queue.
+	 *
+	 * @event FilesAdded
+	 * @param {plupload.Uploader} uploader Uploader instance sending the event.
+	 * @param {Array} files Array of file objects that were added to queue by the user.
+	 */
+
+	/**
+	 * Fires when file is removed from the queue.
+	 *
+	 * @event FilesRemoved
+	 * @param {plupload.Uploader} uploader Uploader instance sending the event.
+	 * @param {Array} files Array of files that got removed.
+	 */
+
+	/**
+	 * Fires when just before a file is uploaded. This event enables you to override settings
+	 * on the uploader instance before the file is uploaded.
+	 *
+	 * @event BeforeUpload
+	 * @param {plupload.Uploader} uploader Uploader instance sending the event.
+	 * @param {plupload.File} file File to be uploaded.
+	 */
+
+	/**
+	 * Fires when a file is to be uploaded by the runtime.
+	 *
+	 * @event UploadFile
+	 * @param {plupload.Uploader} uploader Uploader instance sending the event.
+	 * @param {plupload.File} file File to be uploaded.
+	 */
+
+	/**
+	 * Fires while a file is being uploaded. Use this event to update the current file upload progress.
+	 *
+	 * @event UploadProgress
+	 * @param {plupload.Uploader} uploader Uploader instance sending the event.
+	 * @param {plupload.File} file File that is currently being uploaded.
+	 */	
+
+	/**
+	 * Fires when file chunk is uploaded.
+	 *
+	 * @event ChunkUploaded
+	 * @param {plupload.Uploader} uploader Uploader instance sending the event.
+	 * @param {plupload.File} file File that the chunk was uploaded for.
+	 * @param {Object} response Object with response properties.
+	 */
+
+	/**
+	 * Fires when a file is successfully uploaded.
+	 *
+	 * @event FileUploaded
+	 * @param {plupload.Uploader} uploader Uploader instance sending the event.
+	 * @param {plupload.File} file File that was uploaded.
+	 * @param {Object} response Object with response properties.
+	 */
+
+	/**
+	 * Fires when all files in a queue are uploaded.
+	 *
+	 * @event UploadComplete
+	 * @param {plupload.Uploader} uploader Uploader instance sending the event.
+	 * @param {Array} files Array of file objects that was added to queue/selected by the user.
+	 */
+
+	/**
+	 * Fires when a error occurs.
+	 *
+	 * @event Error
+	 * @param {plupload.Uploader} uploader Uploader instance sending the event.
+	 * @param {Object} error Contains code, message and sometimes file and other details.
+	 */
+
+	/**
+	 * Fires when destroy method is called.
+	 *
+	 * @event Destroy
+	 * @param {plupload.Uploader} uploader Uploader instance sending the event.
+	 */
+	var uid = plupload.guid()
+	, settings
+	, files = []
+	, preferred_caps = {}
+	, fileInputs = []
+	, fileDrops = []
+	, startTime
+	, total
+	, disabled = false
+	, xhr
+	;
+
+
+	// Private methods
+	function uploadNext() {
+		var file, count = 0, i;
+
+		if (this.state == plupload.STARTED) {
+			// Find first QUEUED file
+			for (i = 0; i < files.length; i++) {
+				if (!file && files[i].status == plupload.QUEUED) {
+					file = files[i];
+					if (this.trigger("BeforeUpload", file)) {
+						file.status = plupload.UPLOADING;
+						this.trigger("UploadFile", file);
+					}
+				} else {
+					count++;
+				}
+			}
+
+			// All files are DONE or FAILED
+			if (count == files.length) {
+				if (this.state !== plupload.STOPPED) {
+					this.state = plupload.STOPPED;
+					this.trigger("StateChanged");
+				}
+				this.trigger("UploadComplete", files);
+			}
+		}
+	}
+
+
+	function calcFile(file) {
+		file.percent = file.size > 0 ? Math.ceil(file.loaded / file.size * 100) : 100;
+		calc();
+	}
+
+
+	function calc() {
+		var i, file;
+
+		// Reset stats
+		total.reset();
+
+		// Check status, size, loaded etc on all files
+		for (i = 0; i < files.length; i++) {
+			file = files[i];
+
+			if (file.size !== undef) {
+				// We calculate totals based on original file size
+				total.size += file.origSize;
+
+				// Since we cannot predict file size after resize, we do opposite and
+				// interpolate loaded amount to match magnitude of total
+				total.loaded += file.loaded * file.origSize / file.size;
+			} else {
+				total.size = undef;
+			}
+
+			if (file.status == plupload.DONE) {
+				total.uploaded++;
+			} else if (file.status == plupload.FAILED) {
+				total.failed++;
+			} else {
+				total.queued++;
+			}
+		}
+
+		// If we couldn't calculate a total file size then use the number of files to calc percent
+		if (total.size === undef) {
+			total.percent = files.length > 0 ? Math.ceil(total.uploaded / files.length * 100) : 0;
+		} else {
+			total.bytesPerSec = Math.ceil(total.loaded / ((+new Date() - startTime || 1) / 1000.0));
+			total.percent = total.size > 0 ? Math.ceil(total.loaded / total.size * 100) : 0;
+		}
+	}
+
+
+	function getRUID() {
+		var ctrl = fileInputs[0] || fileDrops[0];
+		if (ctrl) {
+			return ctrl.getRuntime().uid;
+		}
+		return false;
+	}
+
+
+	function runtimeCan(file, cap) {
+		if (file.ruid) {
+			var info = o.Runtime.getInfo(file.ruid);
+			if (info) {
+				return info.can(cap);
+			}
+		}
+		return false;
+	}
+
+
+	function bindEventListeners() {
+		this.bind('FilesAdded FilesRemoved', function(up) {
+			up.trigger('QueueChanged');
+			up.refresh();
+		});
+
+		this.bind('CancelUpload', onCancelUpload);
+		
+		this.bind('BeforeUpload', onBeforeUpload);
+
+		this.bind('UploadFile', onUploadFile);
+
+		this.bind('UploadProgress', onUploadProgress);
+
+		this.bind('StateChanged', onStateChanged);
+
+		this.bind('QueueChanged', calc);
+
+		this.bind('Error', onError);
+
+		this.bind('FileUploaded', onFileUploaded);
+
+		this.bind('Destroy', onDestroy);
+	}
+
+
+	function initControls(settings, cb) {
+		var self = this, inited = 0, queue = [];
+
+		// common settings
+		var options = {
+			runtime_order: settings.runtimes,
+			required_caps: settings.required_features,
+			preferred_caps: preferred_caps,
+			swf_url: settings.flash_swf_url,
+			xap_url: settings.silverlight_xap_url
+		};
+
+		// add runtime specific options if any
+		plupload.each(settings.runtimes.split(/\s*,\s*/), function(runtime) {
+			if (settings[runtime]) {
+				options[runtime] = settings[runtime];
+			}
+		});
+
+		// initialize file pickers - there can be many
+		if (settings.browse_button) {
+			plupload.each(settings.browse_button, function(el) {
+				queue.push(function(cb) {
+					var fileInput = new o.FileInput(plupload.extend({}, options, {
+						accept: settings.filters.mime_types,
+						name: settings.file_data_name,
+						multiple: settings.multi_selection,
+						container: settings.container,
+						browse_button: el
+					}));
+
+					fileInput.onready = function() {
+						var info = o.Runtime.getInfo(this.ruid);
+
+						// for backward compatibility
+						o.extend(self.features, {
+							chunks: info.can('slice_blob'),
+							multipart: info.can('send_multipart'),
+							multi_selection: info.can('select_multiple')
+						});
+
+						inited++;
+						fileInputs.push(this);
+						cb();
+					};
+
+					fileInput.onchange = function() {
+						self.addFile(this.files);
+					};
+
+					fileInput.bind('mouseenter mouseleave mousedown mouseup', function(e) {
+						if (!disabled) {
+							if (settings.browse_button_hover) {
+								if ('mouseenter' === e.type) {
+									o.addClass(el, settings.browse_button_hover);
+								} else if ('mouseleave' === e.type) {
+									o.removeClass(el, settings.browse_button_hover);
+								}
+							}
+
+							if (settings.browse_button_active) {
+								if ('mousedown' === e.type) {
+									o.addClass(el, settings.browse_button_active);
+								} else if ('mouseup' === e.type) {
+									o.removeClass(el, settings.browse_button_active);
+								}
+							}
+						}
+					});
+
+					fileInput.bind('mousedown', function() {
+						self.trigger('Browse');
+					});
+
+					fileInput.bind('error runtimeerror', function() {
+						fileInput = null;
+						cb();
+					});
+
+					fileInput.init();
+				});
+			});
+		}
+
+		// initialize drop zones
+		if (settings.drop_element) {
+			plupload.each(settings.drop_element, function(el) {
+				queue.push(function(cb) {
+					var fileDrop = new o.FileDrop(plupload.extend({}, options, {
+						drop_zone: el
+					}));
+
+					fileDrop.onready = function() {
+						var info = o.Runtime.getInfo(this.ruid);
+
+						self.features.dragdrop = info.can('drag_and_drop'); // for backward compatibility
+
+						inited++;
+						fileDrops.push(this);
+						cb();
+					};
+
+					fileDrop.ondrop = function() {
+						self.addFile(this.files);
+					};
+
+					fileDrop.bind('error runtimeerror', function() {
+						fileDrop = null;
+						cb();
+					});
+
+					fileDrop.init();
+				});
+			});
+		}
+
+
+		o.inSeries(queue, function() {
+			if (typeof(cb) === 'function') {
+				cb(inited);
+			}
+		});
+	}
+
+
+	function resizeImage(blob, params, cb) {
+		var img = new o.Image();
+
+		try {
+			img.onload = function() {
+				// no manipulation required if...
+				if (params.width > this.width &&
+					params.height > this.height &&
+					params.quality === undef &&
+					params.preserve_headers &&
+					!params.crop
+				) {
+					this.destroy();
+					return cb(blob);
+				}
+				// otherwise downsize
+				img.downsize(params.width, params.height, params.crop, params.preserve_headers);
+			};
+
+			img.onresize = function() {
+				cb(this.getAsBlob(blob.type, params.quality));
+				this.destroy();
+			};
+
+			img.onerror = function() {
+				cb(blob);
+			};
+
+			img.load(blob);
+		} catch(ex) {
+			cb(blob);
+		}
+	}
+
+
+	function setOption(option, value, init) {
+		var self = this, reinitRequired = false;
+
+		function _setOption(option, value, init) {
+			var oldValue = settings[option];
+
+			switch (option) {
+				case 'max_file_size':
+					if (option === 'max_file_size') {
+						settings.max_file_size = settings.filters.max_file_size = value;
+					}
+					break;
+
+				case 'chunk_size':
+					if (value = plupload.parseSize(value)) {
+						settings[option] = value;
+						settings.send_file_name = true;
+					}
+					break;
+
+				case 'multipart':
+					settings[option] = value;
+					if (!value) {
+						settings.send_file_name = true;
+					}
+					break;
+
+				case 'unique_names':
+					settings[option] = value;
+					if (value) {
+						settings.send_file_name = true;
+					}
+					break;
+
+				case 'filters':
+					// for sake of backward compatibility
+					if (plupload.typeOf(value) === 'array') {
+						value = {
+							mime_types: value
+						};
+					}
+
+					if (init) {
+						plupload.extend(settings.filters, value);
+					} else {
+						settings.filters = value;
+					}
+
+					// if file format filters are being updated, regenerate the matching expressions
+					if (value.mime_types) {
+						settings.filters.mime_types.regexp = (function(filters) {
+							var extensionsRegExp = [];
+
+							plupload.each(filters, function(filter) {
+								plupload.each(filter.extensions.split(/,/), function(ext) {
+									if (/^\s*\*\s*$/.test(ext)) {
+										extensionsRegExp.push('\\.*');
+									} else {
+										extensionsRegExp.push('\\.' + ext.replace(new RegExp('[' + ('/^$.*+?|()[]{}\\'.replace(/./g, '\\$&')) + ']', 'g'), '\\$&'));
+									}
+								});
+							});
+
+							return new RegExp('(' + extensionsRegExp.join('|') + ')$', 'i');
+						}(settings.filters.mime_types));
+					}
+					break;
+	
+				case 'resize':
+					if (init) {
+						plupload.extend(settings.resize, value, {
+							enabled: true
+						});
+					} else {
+						settings.resize = value;
+					}
+					break;
+
+				case 'prevent_duplicates':
+					settings.prevent_duplicates = settings.filters.prevent_duplicates = !!value;
+					break;
+
+				case 'browse_button':
+				case 'drop_element':
+						value = plupload.get(value);
+
+				case 'container':
+				case 'runtimes':
+				case 'multi_selection':
+				case 'flash_swf_url':
+				case 'silverlight_xap_url':
+					settings[option] = value;
+					if (!init) {
+						reinitRequired = true;
+					}
+					break;
+
+				default:
+					settings[option] = value;
+			}
+
+			if (!init) {
+				self.trigger('OptionChanged', option, value, oldValue);
+			}
+		}
+
+		if (typeof(option) === 'object') {
+			plupload.each(option, function(value, option) {
+				_setOption(option, value, init);
+			});
+		} else {
+			_setOption(option, value, init);
+		}
+
+		if (init) {
+			// Normalize the list of required capabilities
+			settings.required_features = normalizeCaps(plupload.extend({}, settings));
+
+			// Come up with the list of capabilities that can affect default mode in a multi-mode runtimes
+			preferred_caps = normalizeCaps(plupload.extend({}, settings, {
+				required_features: true
+			}));
+		} else if (reinitRequired) {
+			self.trigger('Destroy');
+			
+			initControls.call(self, settings, function(inited) {
+				if (inited) {
+					self.runtime = o.Runtime.getInfo(getRUID()).type;
+					self.trigger('Init', { runtime: self.runtime });
+					self.trigger('PostInit');
+				} else {
+					self.trigger('Error', {
+						code : plupload.INIT_ERROR,
+						message : plupload.translate('Init error.')
+					});
+				}
+			});
+		}
+	}
+
+
+	// Internal event handlers
+	function onBeforeUpload(up, file) {
+		// Generate unique target filenames
+		if (up.settings.unique_names) {
+			var matches = file.name.match(/\.([^.]+)$/), ext = "part";
+			if (matches) {
+				ext = matches[1];
+			}
+			file.target_name = file.id + '.' + ext;
+		}
+	}
+
+
+	function onUploadFile(up, file) {
+		var url = up.settings.url
+		, chunkSize = up.settings.chunk_size
+		, retries = up.settings.max_retries
+		, features = up.features
+		, offset = 0
+		, blob
+		;
+
+		// make sure we start at a predictable offset
+		if (file.loaded) {
+			offset = file.loaded = chunkSize ? chunkSize * Math.floor(file.loaded / chunkSize) : 0;
+		}
+
+		function handleError() {
+			if (retries-- > 0) {
+				delay(uploadNextChunk, 1000);
+			} else {
+				file.loaded = offset; // reset all progress
+
+				up.trigger('Error', {
+					code : plupload.HTTP_ERROR,
+					message : plupload.translate('HTTP Error.'),
+					file : file,
+					response : xhr.responseText,
+					status : xhr.status,
+					responseHeaders: xhr.getAllResponseHeaders()
+				});
+			}
+		}
+
+		function uploadNextChunk() {
+			var chunkBlob, formData, args = {}, curChunkSize;
+
+			// make sure that file wasn't cancelled and upload is not stopped in general
+			if (file.status !== plupload.UPLOADING || up.state === plupload.STOPPED) {
+				return;
+			}
+
+			// send additional 'name' parameter only if required
+			if (up.settings.send_file_name) {
+				args.name = file.target_name || file.name;
+			}
+
+			if (chunkSize && features.chunks && blob.size > chunkSize) { // blob will be of type string if it was loaded in memory 
+				curChunkSize = Math.min(chunkSize, blob.size - offset);
+				chunkBlob = blob.slice(offset, offset + curChunkSize);
+			} else {
+				curChunkSize = blob.size;
+				chunkBlob = blob;
+			}
+
+			// If chunking is enabled add corresponding args, no matter if file is bigger than chunk or smaller
+			if (chunkSize && features.chunks) {
+				// Setup query string arguments
+				if (up.settings.send_chunk_number) {
+					args.chunk = Math.ceil(offset / chunkSize);
+					args.chunks = Math.ceil(blob.size / chunkSize);
+				} else { // keep support for experimental chunk format, just in case
+					args.offset = offset;
+					args.total = blob.size;
+				}
+			}
+
+			xhr = new o.XMLHttpRequest();
+
+			// Do we have upload progress support
+			if (xhr.upload) {
+				xhr.upload.onprogress = function(e) {
+					file.loaded = Math.min(file.size, offset + e.loaded);
+					up.trigger('UploadProgress', file);
+				};
+			}
+
+			xhr.onload = function() {
+				// check if upload made itself through
+				if (xhr.status >= 400) {
+					handleError();
+					return;
+				}
+
+				retries = up.settings.max_retries; // reset the counter
+
+				// Handle chunk response
+				if (curChunkSize < blob.size) {
+					chunkBlob.destroy();
+
+					offset += curChunkSize;
+					file.loaded = Math.min(offset, blob.size);
+
+					up.trigger('ChunkUploaded', file, {
+						offset : file.loaded,
+						total : blob.size,
+						response : xhr.responseText,
+						status : xhr.status,
+						responseHeaders: xhr.getAllResponseHeaders()
+					});
+
+					// stock Android browser doesn't fire upload progress events, but in chunking mode we can fake them
+					if (o.Env.browser === 'Android Browser') {
+						// doesn't harm in general, but is not required anywhere else
+						up.trigger('UploadProgress', file);
+					} 
+				} else {
+					file.loaded = file.size;
+				}
+
+				chunkBlob = formData = null; // Free memory
+
+				// Check if file is uploaded
+				if (!offset || offset >= blob.size) {
+					// If file was modified, destory the copy
+					if (file.size != file.origSize) {
+						blob.destroy();
+						blob = null;
+					}
+
+					up.trigger('UploadProgress', file);
+
+					file.status = plupload.DONE;
+
+					up.trigger('FileUploaded', file, {
+						response : xhr.responseText,
+						status : xhr.status,
+						responseHeaders: xhr.getAllResponseHeaders()
+					});
+				} else {
+					// Still chunks left
+					delay(uploadNextChunk, 1); // run detached, otherwise event handlers interfere
+				}
+			};
+
+			xhr.onerror = function() {
+				handleError();
+			};
+
+			xhr.onloadend = function() {
+				this.destroy();
+				xhr = null;
+			};
+
+			// Build multipart request
+			if (up.settings.multipart && features.multipart) {
+				xhr.open("post", url, true);
+
+				// Set custom headers
+				plupload.each(up.settings.headers, function(value, name) {
+					xhr.setRequestHeader(name, value);
+				});
+
+				formData = new o.FormData();
+
+				// Add multipart params
+				plupload.each(plupload.extend(args, up.settings.multipart_params), function(value, name) {
+					formData.append(name, value);
+				});
+
+				// Add file and send it
+				formData.append(up.settings.file_data_name, chunkBlob);
+				xhr.send(formData, {
+					runtime_order: up.settings.runtimes,
+					required_caps: up.settings.required_features,
+					preferred_caps: preferred_caps,
+					swf_url: up.settings.flash_swf_url,
+					xap_url: up.settings.silverlight_xap_url
+				});
+			} else {
+				// if no multipart, send as binary stream
+				url = plupload.buildUrl(up.settings.url, plupload.extend(args, up.settings.multipart_params));
+
+				xhr.open("post", url, true);
+
+				xhr.setRequestHeader('Content-Type', 'application/octet-stream'); // Binary stream header
+
+				// Set custom headers
+				plupload.each(up.settings.headers, function(value, name) {
+					xhr.setRequestHeader(name, value);
+				});
+
+				xhr.send(chunkBlob, {
+					runtime_order: up.settings.runtimes,
+					required_caps: up.settings.required_features,
+					preferred_caps: preferred_caps,
+					swf_url: up.settings.flash_swf_url,
+					xap_url: up.settings.silverlight_xap_url
+				});
+			}
+		}
+
+		blob = file.getSource();
+
+		// Start uploading chunks
+		if (up.settings.resize.enabled && runtimeCan(blob, 'send_binary_string') && !!~o.inArray(blob.type, ['image/jpeg', 'image/png'])) {
+			// Resize if required
+			resizeImage.call(this, blob, up.settings.resize, function(resizedBlob) {
+				blob = resizedBlob;
+				file.size = resizedBlob.size;
+				uploadNextChunk();
+			});
+		} else {
+			uploadNextChunk();
+		}
+	}
+
+
+	function onUploadProgress(up, file) {
+		calcFile(file);
+	}
+
+
+	function onStateChanged(up) {
+		if (up.state == plupload.STARTED) {
+			// Get start time to calculate bps
+			startTime = (+new Date());
+		} else if (up.state == plupload.STOPPED) {
+			// Reset currently uploading files
+			for (var i = up.files.length - 1; i >= 0; i--) {
+				if (up.files[i].status == plupload.UPLOADING) {
+					up.files[i].status = plupload.QUEUED;
+					calc();
+				}
+			}
+		}
+	}
+
+
+	function onCancelUpload() {
+		if (xhr) {
+			xhr.abort();
+		}
+	}
+
+
+	function onFileUploaded(up) {
+		calc();
+
+		// Upload next file but detach it from the error event
+		// since other custom listeners might want to stop the queue
+		delay(function() {
+			uploadNext.call(up);
+		}, 1);
+	}
+
+
+	function onError(up, err) {
+		if (err.code === plupload.INIT_ERROR) {
+			up.destroy();
+		}
+		// Set failed status if an error occured on a file
+		else if (err.file) {
+			err.file.status = plupload.FAILED;
+			calcFile(err.file);
+
+			// Upload next file but detach it from the error event
+			// since other custom listeners might want to stop the queue
+			if (up.state == plupload.STARTED) { // upload in progress
+				up.trigger('CancelUpload');
+				delay(function() {
+					uploadNext.call(up);
+				}, 1);
+			}
+		}
+	}
+
+
+	function onDestroy(up) {
+		up.stop();
+
+		// Purge the queue
+		plupload.each(files, function(file) {
+			file.destroy();
+		});
+		files = [];
+
+		if (fileInputs.length) {
+			plupload.each(fileInputs, function(fileInput) {
+				fileInput.destroy();
+			});
+			fileInputs = [];
+		}
+
+		if (fileDrops.length) {
+			plupload.each(fileDrops, function(fileDrop) {
+				fileDrop.destroy();
+			});
+			fileDrops = [];
+		}
+
+		preferred_caps = {};
+		disabled = false;
+		startTime = xhr = null;
+		total.reset();
+	}
+
+
+	// Default settings
+	settings = {
+		runtimes: o.Runtime.order,
+		max_retries: 0,
+		chunk_size: 0,
+		multipart: true,
+		multi_selection: true,
+		file_data_name: 'file',
+		flash_swf_url: 'js/Moxie.swf',
+		silverlight_xap_url: 'js/Moxie.xap',
+		filters: {
+			mime_types: [],
+			prevent_duplicates: false,
+			max_file_size: 0
+		},
+		resize: {
+			enabled: false,
+			preserve_headers: true,
+			crop: false
+		},
+		send_file_name: true,
+		send_chunk_number: true
+	};
+
+	
+	setOption.call(this, options, null, true);
+
+	// Inital total state
+	total = new plupload.QueueProgress(); 
+
+	// Add public methods
+	plupload.extend(this, {
+
+		/**
+		 * Unique id for the Uploader instance.
+		 *
+		 * @property id
+		 * @type String
+		 */
+		id : uid,
+		uid : uid, // mOxie uses this to differentiate between event targets
+
+		/**
+		 * Current state of the total uploading progress. This one can either be plupload.STARTED or plupload.STOPPED.
+		 * These states are controlled by the stop/start methods. The default value is STOPPED.
+		 *
+		 * @property state
+		 * @type Number
+		 */
+		state : plupload.STOPPED,
+
+		/**
+		 * Map of features that are available for the uploader runtime. Features will be filled
+		 * before the init event is called, these features can then be used to alter the UI for the end user.
+		 * Some of the current features that might be in this map is: dragdrop, chunks, jpgresize, pngresize.
+		 *
+		 * @property features
+		 * @type Object
+		 */
+		features : {},
+
+		/**
+		 * Current runtime name.
+		 *
+		 * @property runtime
+		 * @type String
+		 */
+		runtime : null,
+
+		/**
+		 * Current upload queue, an array of File instances.
+		 *
+		 * @property files
+		 * @type Array
+		 * @see plupload.File
+		 */
+		files : files,
+
+		/**
+		 * Object with name/value settings.
+		 *
+		 * @property settings
+		 * @type Object
+		 */
+		settings : settings,
+
+		/**
+		 * Total progess information. How many files has been uploaded, total percent etc.
+		 *
+		 * @property total
+		 * @type plupload.QueueProgress
+		 */
+		total : total,
+
+
+		/**
+		 * Initializes the Uploader instance and adds internal event listeners.
+		 *
+		 * @method init
+		 */
+		init : function() {
+			var self = this;
+
+			if (typeof(settings.preinit) == "function") {
+				settings.preinit(self);
+			} else {
+				plupload.each(settings.preinit, function(func, name) {
+					self.bind(name, func);
+				});
+			}
+
+			bindEventListeners.call(this);
+
+			// Check for required options
+			if (!settings.browse_button || !settings.url) {
+				this.trigger('Error', {
+					code : plupload.INIT_ERROR,
+					message : plupload.translate('Init error.')
+				});
+				return;
+			}
+
+			initControls.call(this, settings, function(inited) {
+				if (typeof(settings.init) == "function") {
+					settings.init(self);
+				} else {
+					plupload.each(settings.init, function(func, name) {
+						self.bind(name, func);
+					});
+				}
+
+				if (inited) {
+					self.runtime = o.Runtime.getInfo(getRUID()).type;
+					self.trigger('Init', { runtime: self.runtime });
+					self.trigger('PostInit');
+				} else {
+					self.trigger('Error', {
+						code : plupload.INIT_ERROR,
+						message : plupload.translate('Init error.')
+					});
+				}
+			});
+		},
+
+		/**
+		 * Set the value for the specified option(s).
+		 *
+		 * @method setOption
+		 * @since 2.1
+		 * @param {String|Object} option Name of the option to change or the set of key/value pairs
+		 * @param {Mixed} [value] Value for the option (is ignored, if first argument is object)
+		 */
+		setOption: function(option, value) {
+			setOption.call(this, option, value, !this.runtime); // until runtime not set we do not need to reinitialize
+		},
+
+		/**
+		 * Get the value for the specified option or the whole configuration, if not specified.
+		 * 
+		 * @method getOption
+		 * @since 2.1
+		 * @param {String} [option] Name of the option to get
+		 * @return {Mixed} Value for the option or the whole set
+		 */
+		getOption: function(option) {
+			if (!option) {
+				return settings;
+			}
+			return settings[option];
+		},
+
+		/**
+		 * Refreshes the upload instance by dispatching out a refresh event to all runtimes.
+		 * This would for example reposition flash/silverlight shims on the page.
+		 *
+		 * @method refresh
+		 */
+		refresh : function() {
+			if (fileInputs.length) {
+				plupload.each(fileInputs, function(fileInput) {
+					fileInput.trigger('Refresh');
+				});
+			}
+			this.trigger('Refresh');
+		},
+
+		/**
+		 * Starts uploading the queued files.
+		 *
+		 * @method start
+		 */
+		start : function() {
+			if (this.state != plupload.STARTED) {
+				this.state = plupload.STARTED;
+				this.trigger('StateChanged');
+
+				uploadNext.call(this);
+			}
+		},
+
+		/**
+		 * Stops the upload of the queued files.
+		 *
+		 * @method stop
+		 */
+		stop : function() {
+			if (this.state != plupload.STOPPED) {
+				this.state = plupload.STOPPED;
+				this.trigger('StateChanged');
+				this.trigger('CancelUpload');
+			}
+		},
+
+
+		/**
+		 * Disables/enables browse button on request.
+		 *
+		 * @method disableBrowse
+		 * @param {Boolean} disable Whether to disable or enable (default: true)
+		 */
+		disableBrowse : function() {
+			disabled = arguments[0] !== undef ? arguments[0] : true;
+
+			if (fileInputs.length) {
+				plupload.each(fileInputs, function(fileInput) {
+					fileInput.disable(disabled);
+				});
+			}
+
+			this.trigger('DisableBrowse', disabled);
+		},
+
+		/**
+		 * Returns the specified file object by id.
+		 *
+		 * @method getFile
+		 * @param {String} id File id to look for.
+		 * @return {plupload.File} File object or undefined if it wasn't found;
+		 */
+		getFile : function(id) {
+			var i;
+			for (i = files.length - 1; i >= 0; i--) {
+				if (files[i].id === id) {
+					return files[i];
+				}
+			}
+		},
+
+		/**
+		 * Adds file to the queue programmatically. Can be native file, instance of Plupload.File,
+		 * instance of mOxie.File, input[type="file"] element, or array of these. Fires FilesAdded, 
+		 * if any files were added to the queue. Otherwise nothing happens.
+		 *
+		 * @method addFile
+		 * @since 2.0
+		 * @param {plupload.File|mOxie.File|File|Node|Array} file File or files to add to the queue.
+		 * @param {String} [fileName] If specified, will be used as a name for the file
+		 */
+		addFile : function(file, fileName) {
+			var self = this
+			, queue = [] 
+			, filesAdded = []
+			, ruid
+			;
+
+			function filterFile(file, cb) {
+				var queue = [];
+				o.each(self.settings.filters, function(rule, name) {
+					if (fileFilters[name]) {
+						queue.push(function(cb) {
+							fileFilters[name].call(self, rule, file, function(res) {
+								cb(!res);
+							});
+						});
+					}
+				});
+				o.inSeries(queue, cb);
+			}
+
+			/**
+			 * @method resolveFile
+			 * @private
+			 * @param {o.File|o.Blob|plupload.File|File|Blob|input[type="file"]} file
+			 */
+			function resolveFile(file) {
+				var type = o.typeOf(file);
+
+				// o.File
+				if (file instanceof o.File) { 
+					if (!file.ruid && !file.isDetached()) {
+						if (!ruid) { // weird case
+							return false;
+						}
+						file.ruid = ruid;
+						file.connectRuntime(ruid);
+					}
+					resolveFile(new plupload.File(file));
+				}
+				// o.Blob 
+				else if (file instanceof o.Blob) {
+					resolveFile(file.getSource());
+					file.destroy();
+				} 
+				// plupload.File - final step for other branches
+				else if (file instanceof plupload.File) {
+					if (fileName) {
+						file.name = fileName;
+					}
+					
+					queue.push(function(cb) {
+						// run through the internal and user-defined filters, if any
+						filterFile(file, function(err) {
+							if (!err) {
+								// make files available for the filters by updating the main queue directly
+								files.push(file);
+								// collect the files that will be passed to FilesAdded event
+								filesAdded.push(file); 
+
+								self.trigger("FileFiltered", file);
+							}
+							delay(cb, 1); // do not build up recursions or eventually we might hit the limits
+						});
+					});
+				} 
+				// native File or blob
+				else if (o.inArray(type, ['file', 'blob']) !== -1) {
+					resolveFile(new o.File(null, file));
+				} 
+				// input[type="file"]
+				else if (type === 'node' && o.typeOf(file.files) === 'filelist') {
+					// if we are dealing with input[type="file"]
+					o.each(file.files, resolveFile);
+				} 
+				// mixed array of any supported types (see above)
+				else if (type === 'array') {
+					fileName = null; // should never happen, but unset anyway to avoid funny situations
+					o.each(file, resolveFile);
+				}
+			}
+
+			ruid = getRUID();
+			
+			resolveFile(file);
+
+			if (queue.length) {
+				o.inSeries(queue, function() {
+					// if any files left after filtration, trigger FilesAdded
+					if (filesAdded.length) {
+						self.trigger("FilesAdded", filesAdded);
+					}
+				});
+			}
+		},
+
+		/**
+		 * Removes a specific file.
+		 *
+		 * @method removeFile
+		 * @param {plupload.File|String} file File to remove from queue.
+		 */
+		removeFile : function(file) {
+			var id = typeof(file) === 'string' ? file : file.id;
+
+			for (var i = files.length - 1; i >= 0; i--) {
+				if (files[i].id === id) {
+					return this.splice(i, 1)[0];
+				}
+			}
+		},
+
+		/**
+		 * Removes part of the queue and returns the files removed. This will also trigger the FilesRemoved and QueueChanged events.
+		 *
+		 * @method splice
+		 * @param {Number} start (Optional) Start index to remove from.
+		 * @param {Number} length (Optional) Lengh of items to remove.
+		 * @return {Array} Array of files that was removed.
+		 */
+		splice : function(start, length) {
+			// Splice and trigger events
+			var removed = files.splice(start === undef ? 0 : start, length === undef ? files.length : length);
+
+			// if upload is in progress we need to stop it and restart after files are removed
+			var restartRequired = false;
+			if (this.state == plupload.STARTED) { // upload in progress
+				plupload.each(removed, function(file) {
+					if (file.status === plupload.UPLOADING) {
+						restartRequired = true; // do not restart, unless file that is being removed is uploading
+						return false;
+					}
+				});
+				
+				if (restartRequired) {
+					this.stop();
+				}
+			}
+
+			this.trigger("FilesRemoved", removed);
+
+			// Dispose any resources allocated by those files
+			plupload.each(removed, function(file) {
+				file.destroy();
+			});
+			
+			if (restartRequired) {
+				this.start();
+			}
+
+			return removed;
+		},
+
+		/**
+		 * Dispatches the specified event name and it's arguments to all listeners.
+		 *
+		 *
+		 * @method trigger
+		 * @param {String} name Event name to fire.
+		 * @param {Object..} Multiple arguments to pass along to the listener functions.
+		 */
+
+		/**
+		 * Check whether uploader has any listeners to the specified event.
+		 *
+		 * @method hasEventListener
+		 * @param {String} name Event name to check for.
+		 */
+
+
+		/**
+		 * Adds an event listener by name.
+		 *
+		 * @method bind
+		 * @param {String} name Event name to listen for.
+		 * @param {function} func Function to call ones the event gets fired.
+		 * @param {Object} scope Optional scope to execute the specified function in.
+		 */
+		bind : function(name, func, scope) {
+			var self = this;
+			// adapt moxie EventTarget style to Plupload-like
+			plupload.Uploader.prototype.bind.call(this, name, function() {
+				var args = [].slice.call(arguments);
+				args.splice(0, 1, self); // replace event object with uploader instance
+				return func.apply(this, args);
+			}, 0, scope);
+		},
+
+		/**
+		 * Removes the specified event listener.
+		 *
+		 * @method unbind
+		 * @param {String} name Name of event to remove.
+		 * @param {function} func Function to remove from listener.
+		 */
+
+		/**
+		 * Removes all event listeners.
+		 *
+		 * @method unbindAll
+		 */
+
+
+		/**
+		 * Destroys Plupload instance and cleans after itself.
+		 *
+		 * @method destroy
+		 */
+		destroy : function() {
+			this.trigger('Destroy');
+			settings = total = null; // purge these exclusively
+			this.unbindAll();
+		}
+	});
+};
+
+plupload.Uploader.prototype = o.EventTarget.instance;
+
+/**
+ * Constructs a new file instance.
+ *
+ * @class File
+ * @constructor
+ * 
+ * @param {Object} file Object containing file properties
+ * @param {String} file.name Name of the file.
+ * @param {Number} file.size File size.
+ */
+plupload.File = (function() {
+	var filepool = {};
+
+	function PluploadFile(file) {
+
+		plupload.extend(this, {
+
+			/**
+			 * File id this is a globally unique id for the specific file.
+			 *
+			 * @property id
+			 * @type String
+			 */
+			id: plupload.guid(),
+
+			/**
+			 * File name for example "myfile.gif".
+			 *
+			 * @property name
+			 * @type String
+			 */
+			name: file.name || file.fileName,
+
+			/**
+			 * File type, `e.g image/jpeg`
+			 *
+			 * @property type
+			 * @type String
+			 */
+			type: file.type || '',
+
+			/**
+			 * File size in bytes (may change after client-side manupilation).
+			 *
+			 * @property size
+			 * @type Number
+			 */
+			size: file.size || file.fileSize,
+
+			/**
+			 * Original file size in bytes.
+			 *
+			 * @property origSize
+			 * @type Number
+			 */
+			origSize: file.size || file.fileSize,
+
+			/**
+			 * Number of bytes uploaded of the files total size.
+			 *
+			 * @property loaded
+			 * @type Number
+			 */
+			loaded: 0,
+
+			/**
+			 * Number of percentage uploaded of the file.
+			 *
+			 * @property percent
+			 * @type Number
+			 */
+			percent: 0,
+
+			/**
+			 * Status constant matching the plupload states QUEUED, UPLOADING, FAILED, DONE.
+			 *
+			 * @property status
+			 * @type Number
+			 * @see plupload
+			 */
+			status: plupload.QUEUED,
+
+			/**
+			 * Date of last modification.
+			 *
+			 * @property lastModifiedDate
+			 * @type {String}
+			 */
+			lastModifiedDate: file.lastModifiedDate || (new Date()).toLocaleString(), // Thu Aug 23 2012 19:40:00 GMT+0400 (GET)
+
+			/**
+			 * Returns native window.File object, when it's available.
+			 *
+			 * @method getNative
+			 * @return {window.File} or null, if plupload.File is of different origin
+			 */
+			getNative: function() {
+				var file = this.getSource().getSource();
+				return o.inArray(o.typeOf(file), ['blob', 'file']) !== -1 ? file : null;
+			},
+
+			/**
+			 * Returns mOxie.File - unified wrapper object that can be used across runtimes.
+			 *
+			 * @method getSource
+			 * @return {mOxie.File} or null
+			 */
+			getSource: function() {
+				if (!filepool[this.id]) {
+					return null;
+				}
+				return filepool[this.id];
+			},
+
+			/**
+			 * Destroys plupload.File object.
+			 *
+			 * @method destroy
+			 */
+			destroy: function() {
+				var src = this.getSource();
+				if (src) {
+					src.destroy();
+					delete filepool[this.id];
+				}
+			}
+		});
+
+		filepool[this.id] = file;
+	}
+
+	return PluploadFile;
+}());
+
+
+/**
+ * Constructs a queue progress.
+ *
+ * @class QueueProgress
+ * @constructor
+ */
+ plupload.QueueProgress = function() {
+	var self = this; // Setup alias for self to reduce code size when it's compressed
+
+	/**
+	 * Total queue file size.
+	 *
+	 * @property size
+	 * @type Number
+	 */
+	self.size = 0;
+
+	/**
+	 * Total bytes uploaded.
+	 *
+	 * @property loaded
+	 * @type Number
+	 */
+	self.loaded = 0;
+
+	/**
+	 * Number of files uploaded.
+	 *
+	 * @property uploaded
+	 * @type Number
+	 */
+	self.uploaded = 0;
+
+	/**
+	 * Number of files failed to upload.
+	 *
+	 * @property failed
+	 * @type Number
+	 */
+	self.failed = 0;
+
+	/**
+	 * Number of files yet to be uploaded.
+	 *
+	 * @property queued
+	 * @type Number
+	 */
+	self.queued = 0;
+
+	/**
+	 * Total percent of the uploaded bytes.
+	 *
+	 * @property percent
+	 * @type Number
+	 */
+	self.percent = 0;
+
+	/**
+	 * Bytes uploaded per second.
+	 *
+	 * @property bytesPerSec
+	 * @type Number
+	 */
+	self.bytesPerSec = 0;
+
+	/**
+	 * Resets the progress to it's initial values.
+	 *
+	 * @method reset
+	 */
+	self.reset = function() {
+		self.size = self.loaded = self.uploaded = self.failed = self.queued = self.percent = self.bytesPerSec = 0;
+	};
+};
+
+window.plupload = plupload;
+
+}(window, mOxie));
Index: /trunk/themes/default/js/plugins/plupload/plupload.full.min.js
===================================================================
--- /trunk/themes/default/js/plugins/plupload/plupload.full.min.js	(revision 28545)
+++ /trunk/themes/default/js/plugins/plupload/plupload.full.min.js	(revision 28545)
@@ -0,0 +1,28 @@
+/**
+ * mOxie - multi-runtime File API & XMLHttpRequest L2 Polyfill
+ * v1.2.1
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ *
+ * Date: 2014-05-14
+ */
+!function(e,t){"use strict";function n(e,t){for(var n,i=[],r=0;r<e.length;++r){if(n=s[e[r]]||o(e[r]),!n)throw"module definition dependecy not found: "+e[r];i.push(n)}t.apply(null,i)}function i(e,i,r){if("string"!=typeof e)throw"invalid module definition, module id must be defined and be a string";if(i===t)throw"invalid module definition, dependencies must be specified";if(r===t)throw"invalid module definition, definition function must be specified";n(i,function(){s[e]=r.apply(null,arguments)})}function r(e){return!!s[e]}function o(t){for(var n=e,i=t.split(/[.\/]/),r=0;r<i.length;++r){if(!n[i[r]])return;n=n[i[r]]}return n}function a(n){for(var i=0;i<n.length;i++){for(var r=e,o=n[i],a=o.split(/[.\/]/),u=0;u<a.length-1;++u)r[a[u]]===t&&(r[a[u]]={}),r=r[a[u]];r[a[a.length-1]]=s[o]}}var s={},u="moxie/core/utils/Basic",c="moxie/core/I18n",l="moxie/core/utils/Mime",d="moxie/core/utils/Env",f="moxie/core/utils/Dom",h="moxie/core/Exceptions",p="moxie/core/EventTarget",m="moxie/core/utils/Encode",g="moxie/runtime/Runtime",v="moxie/runtime/RuntimeClient",y="moxie/file/Blob",w="moxie/file/File",E="moxie/file/FileInput",_="moxie/file/FileDrop",x="moxie/runtime/RuntimeTarget",b="moxie/file/FileReader",R="moxie/core/utils/Url",T="moxie/file/FileReaderSync",A="moxie/xhr/FormData",S="moxie/xhr/XMLHttpRequest",O="moxie/runtime/Transporter",I="moxie/image/Image",D="moxie/runtime/html5/Runtime",N="moxie/runtime/html5/file/Blob",L="moxie/core/utils/Events",M="moxie/runtime/html5/file/FileInput",C="moxie/runtime/html5/file/FileDrop",F="moxie/runtime/html5/file/FileReader",H="moxie/runtime/html5/xhr/XMLHttpRequest",P="moxie/runtime/html5/utils/BinaryReader",k="moxie/runtime/html5/image/JPEGHeaders",U="moxie/runtime/html5/image/ExifParser",B="moxie/runtime/html5/image/JPEG",z="moxie/runtime/html5/image/PNG",G="moxie/runtime/html5/image/ImageInfo",q="moxie/runtime/html5/image/MegaPixel",X="moxie/runtime/html5/image/Image",j="moxie/runtime/flash/Runtime",V="moxie/runtime/flash/file/Blob",W="moxie/runtime/flash/file/FileInput",Y="moxie/runtime/flash/file/FileReader",$="moxie/runtime/flash/file/FileReaderSync",J="moxie/runtime/flash/xhr/XMLHttpRequest",Z="moxie/runtime/flash/runtime/Transporter",K="moxie/runtime/flash/image/Image",Q="moxie/runtime/silverlight/Runtime",et="moxie/runtime/silverlight/file/Blob",tt="moxie/runtime/silverlight/file/FileInput",nt="moxie/runtime/silverlight/file/FileDrop",it="moxie/runtime/silverlight/file/FileReader",rt="moxie/runtime/silverlight/file/FileReaderSync",ot="moxie/runtime/silverlight/xhr/XMLHttpRequest",at="moxie/runtime/silverlight/runtime/Transporter",st="moxie/runtime/silverlight/image/Image",ut="moxie/runtime/html4/Runtime",ct="moxie/runtime/html4/file/FileInput",lt="moxie/runtime/html4/file/FileReader",dt="moxie/runtime/html4/xhr/XMLHttpRequest",ft="moxie/runtime/html4/image/Image";i(u,[],function(){var e=function(e){var t;return e===t?"undefined":null===e?"null":e.nodeType?"node":{}.toString.call(e).match(/\s([a-z|A-Z]+)/)[1].toLowerCase()},t=function(i){var r;return n(arguments,function(o,s){s>0&&n(o,function(n,o){n!==r&&(e(i[o])===e(n)&&~a(e(n),["array","object"])?t(i[o],n):i[o]=n)})}),i},n=function(e,t){var n,i,r,o;if(e){try{n=e.length}catch(a){n=o}if(n===o){for(i in e)if(e.hasOwnProperty(i)&&t(e[i],i)===!1)return}else for(r=0;n>r;r++)if(t(e[r],r)===!1)return}},i=function(t){var n;if(!t||"object"!==e(t))return!0;for(n in t)return!1;return!0},r=function(t,n){function i(r){"function"===e(t[r])&&t[r](function(e){++r<o&&!e?i(r):n(e)})}var r=0,o=t.length;"function"!==e(n)&&(n=function(){}),t&&t.length||n(),i(r)},o=function(e,t){var i=0,r=e.length,o=new Array(r);n(e,function(e,n){e(function(e){if(e)return t(e);var a=[].slice.call(arguments);a.shift(),o[n]=a,i++,i===r&&(o.unshift(null),t.apply(this,o))})})},a=function(e,t){if(t){if(Array.prototype.indexOf)return Array.prototype.indexOf.call(t,e);for(var n=0,i=t.length;i>n;n++)if(t[n]===e)return n}return-1},s=function(t,n){var i=[];"array"!==e(t)&&(t=[t]),"array"!==e(n)&&(n=[n]);for(var r in t)-1===a(t[r],n)&&i.push(t[r]);return i.length?i:!1},u=function(e,t){var i=[];return n(e,function(e){-1!==a(e,t)&&i.push(e)}),i.length?i:null},c=function(e){var t,n=[];for(t=0;t<e.length;t++)n[t]=e[t];return n},l=function(){var e=0;return function(t){var n=(new Date).getTime().toString(32),i;for(i=0;5>i;i++)n+=Math.floor(65535*Math.random()).toString(32);return(t||"o_")+n+(e++).toString(32)}}(),d=function(e){return e?String.prototype.trim?String.prototype.trim.call(e):e.toString().replace(/^\s*/,"").replace(/\s*$/,""):e},f=function(e){if("string"!=typeof e)return e;var t={t:1099511627776,g:1073741824,m:1048576,k:1024},n;return e=/^([0-9]+)([mgk]?)$/.exec(e.toLowerCase().replace(/[^0-9mkg]/g,"")),n=e[2],e=+e[1],t.hasOwnProperty(n)&&(e*=t[n]),e};return{guid:l,typeOf:e,extend:t,each:n,isEmptyObj:i,inSeries:r,inParallel:o,inArray:a,arrayDiff:s,arrayIntersect:u,toArray:c,trim:d,parseSizeStr:f}}),i(c,[u],function(e){var t={};return{addI18n:function(n){return e.extend(t,n)},translate:function(e){return t[e]||e},_:function(e){return this.translate(e)},sprintf:function(t){var n=[].slice.call(arguments,1);return t.replace(/%[a-z]/g,function(){var t=n.shift();return"undefined"!==e.typeOf(t)?t:""})}}}),i(l,[u,c],function(e,t){var n="application/msword,doc dot,application/pdf,pdf,application/pgp-signature,pgp,application/postscript,ps ai eps,application/rtf,rtf,application/vnd.ms-excel,xls xlb,application/vnd.ms-powerpoint,ppt pps pot,application/zip,zip,application/x-shockwave-flash,swf swfl,application/vnd.openxmlformats-officedocument.wordprocessingml.document,docx,application/vnd.openxmlformats-officedocument.wordprocessingml.template,dotx,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,xlsx,application/vnd.openxmlformats-officedocument.presentationml.presentation,pptx,application/vnd.openxmlformats-officedocument.presentationml.template,potx,application/vnd.openxmlformats-officedocument.presentationml.slideshow,ppsx,application/x-javascript,js,application/json,json,audio/mpeg,mp3 mpga mpega mp2,audio/x-wav,wav,audio/x-m4a,m4a,audio/ogg,oga ogg,audio/aiff,aiff aif,audio/flac,flac,audio/aac,aac,audio/ac3,ac3,audio/x-ms-wma,wma,image/bmp,bmp,image/gif,gif,image/jpeg,jpg jpeg jpe,image/photoshop,psd,image/png,png,image/svg+xml,svg svgz,image/tiff,tiff tif,text/plain,asc txt text diff log,text/html,htm html xhtml,text/css,css,text/csv,csv,text/rtf,rtf,video/mpeg,mpeg mpg mpe m2v,video/quicktime,qt mov,video/mp4,mp4,video/x-m4v,m4v,video/x-flv,flv,video/x-ms-wmv,wmv,video/avi,avi,video/webm,webm,video/3gpp,3gpp 3gp,video/3gpp2,3g2,video/vnd.rn-realvideo,rv,video/ogg,ogv,video/x-matroska,mkv,application/vnd.oasis.opendocument.formula-template,otf,application/octet-stream,exe",i={mimes:{},extensions:{},addMimeType:function(e){var t=e.split(/,/),n,i,r;for(n=0;n<t.length;n+=2){for(r=t[n+1].split(/ /),i=0;i<r.length;i++)this.mimes[r[i]]=t[n];this.extensions[t[n]]=r}},extList2mimes:function(t,n){var i=this,r,o,a,s,u=[];for(o=0;o<t.length;o++)for(r=t[o].extensions.split(/\s*,\s*/),a=0;a<r.length;a++){if("*"===r[a])return[];if(s=i.mimes[r[a]])-1===e.inArray(s,u)&&u.push(s);else{if(!n||!/^\w+$/.test(r[a]))return[];u.push("."+r[a])}}return u},mimes2exts:function(t){var n=this,i=[];return e.each(t,function(t){if("*"===t)return i=[],!1;var r=t.match(/^(\w+)\/(\*|\w+)$/);r&&("*"===r[2]?e.each(n.extensions,function(e,t){new RegExp("^"+r[1]+"/").test(t)&&[].push.apply(i,n.extensions[t])}):n.extensions[t]&&[].push.apply(i,n.extensions[t]))}),i},mimes2extList:function(n){var i=[],r=[];return"string"===e.typeOf(n)&&(n=e.trim(n).split(/\s*,\s*/)),r=this.mimes2exts(n),i.push({title:t.translate("Files"),extensions:r.length?r.join(","):"*"}),i.mimes=n,i},getFileExtension:function(e){var t=e&&e.match(/\.([^.]+)$/);return t?t[1].toLowerCase():""},getFileMime:function(e){return this.mimes[this.getFileExtension(e)]||""}};return i.addMimeType(n),i}),i(d,[u],function(e){function t(e,t,n){var i=0,r=0,o=0,a={dev:-6,alpha:-5,a:-5,beta:-4,b:-4,RC:-3,rc:-3,"#":-2,p:1,pl:1},s=function(e){return e=(""+e).replace(/[_\-+]/g,"."),e=e.replace(/([^.\d]+)/g,".$1.").replace(/\.{2,}/g,"."),e.length?e.split("."):[-8]},u=function(e){return e?isNaN(e)?a[e]||-7:parseInt(e,10):0};for(e=s(e),t=s(t),r=Math.max(e.length,t.length),i=0;r>i;i++)if(e[i]!=t[i]){if(e[i]=u(e[i]),t[i]=u(t[i]),e[i]<t[i]){o=-1;break}if(e[i]>t[i]){o=1;break}}if(!n)return o;switch(n){case">":case"gt":return o>0;case">=":case"ge":return o>=0;case"<=":case"le":return 0>=o;case"==":case"=":case"eq":return 0===o;case"<>":case"!=":case"ne":return 0!==o;case"":case"<":case"lt":return 0>o;default:return null}}var n=function(e){var t="",n="?",i="function",r="undefined",o="object",a="major",s="model",u="name",c="type",l="vendor",d="version",f="architecture",h="console",p="mobile",m="tablet",g={has:function(e,t){return-1!==t.toLowerCase().indexOf(e.toLowerCase())},lowerize:function(e){return e.toLowerCase()}},v={rgx:function(){for(var t,n=0,a,s,u,c,l,d,f=arguments;n<f.length;n+=2){var h=f[n],p=f[n+1];if(typeof t===r){t={};for(u in p)c=p[u],typeof c===o?t[c[0]]=e:t[c]=e}for(a=s=0;a<h.length;a++)if(l=h[a].exec(this.getUA())){for(u=0;u<p.length;u++)d=l[++s],c=p[u],typeof c===o&&c.length>0?2==c.length?t[c[0]]=typeof c[1]==i?c[1].call(this,d):c[1]:3==c.length?t[c[0]]=typeof c[1]!==i||c[1].exec&&c[1].test?d?d.replace(c[1],c[2]):e:d?c[1].call(this,d,c[2]):e:4==c.length&&(t[c[0]]=d?c[3].call(this,d.replace(c[1],c[2])):e):t[c]=d?d:e;break}if(l)break}return t},str:function(t,i){for(var r in i)if(typeof i[r]===o&&i[r].length>0){for(var a=0;a<i[r].length;a++)if(g.has(i[r][a],t))return r===n?e:r}else if(g.has(i[r],t))return r===n?e:r;return t}},y={browser:{oldsafari:{major:{1:["/8","/1","/3"],2:"/4","?":"/"},version:{"1.0":"/8",1.2:"/1",1.3:"/3","2.0":"/412","2.0.2":"/416","2.0.3":"/417","2.0.4":"/419","?":"/"}}},device:{sprint:{model:{"Evo Shift 4G":"7373KT"},vendor:{HTC:"APA",Sprint:"Sprint"}}},os:{windows:{version:{ME:"4.90","NT 3.11":"NT3.51","NT 4.0":"NT4.0",2000:"NT 5.0",XP:["NT 5.1","NT 5.2"],Vista:"NT 6.0",7:"NT 6.1",8:"NT 6.2",8.1:"NT 6.3",RT:"ARM"}}}},w={browser:[[/(opera\smini)\/((\d+)?[\w\.-]+)/i,/(opera\s[mobiletab]+).+version\/((\d+)?[\w\.-]+)/i,/(opera).+version\/((\d+)?[\w\.]+)/i,/(opera)[\/\s]+((\d+)?[\w\.]+)/i],[u,d,a],[/\s(opr)\/((\d+)?[\w\.]+)/i],[[u,"Opera"],d,a],[/(kindle)\/((\d+)?[\w\.]+)/i,/(lunascape|maxthon|netfront|jasmine|blazer)[\/\s]?((\d+)?[\w\.]+)*/i,/(avant\s|iemobile|slim|baidu)(?:browser)?[\/\s]?((\d+)?[\w\.]*)/i,/(?:ms|\()(ie)\s((\d+)?[\w\.]+)/i,/(rekonq)((?:\/)[\w\.]+)*/i,/(chromium|flock|rockmelt|midori|epiphany|silk|skyfire|ovibrowser|bolt|iron)\/((\d+)?[\w\.-]+)/i],[u,d,a],[/(trident).+rv[:\s]((\d+)?[\w\.]+).+like\sgecko/i],[[u,"IE"],d,a],[/(yabrowser)\/((\d+)?[\w\.]+)/i],[[u,"Yandex"],d,a],[/(comodo_dragon)\/((\d+)?[\w\.]+)/i],[[u,/_/g," "],d,a],[/(chrome|omniweb|arora|[tizenoka]{5}\s?browser)\/v?((\d+)?[\w\.]+)/i],[u,d,a],[/(dolfin)\/((\d+)?[\w\.]+)/i],[[u,"Dolphin"],d,a],[/((?:android.+)crmo|crios)\/((\d+)?[\w\.]+)/i],[[u,"Chrome"],d,a],[/((?:android.+))version\/((\d+)?[\w\.]+)\smobile\ssafari/i],[[u,"Android Browser"],d,a],[/version\/((\d+)?[\w\.]+).+?mobile\/\w+\s(safari)/i],[d,a,[u,"Mobile Safari"]],[/version\/((\d+)?[\w\.]+).+?(mobile\s?safari|safari)/i],[d,a,u],[/webkit.+?(mobile\s?safari|safari)((\/[\w\.]+))/i],[u,[a,v.str,y.browser.oldsafari.major],[d,v.str,y.browser.oldsafari.version]],[/(konqueror)\/((\d+)?[\w\.]+)/i,/(webkit|khtml)\/((\d+)?[\w\.]+)/i],[u,d,a],[/(navigator|netscape)\/((\d+)?[\w\.-]+)/i],[[u,"Netscape"],d,a],[/(swiftfox)/i,/(icedragon|iceweasel|camino|chimera|fennec|maemo\sbrowser|minimo|conkeror)[\/\s]?((\d+)?[\w\.\+]+)/i,/(firefox|seamonkey|k-meleon|icecat|iceape|firebird|phoenix)\/((\d+)?[\w\.-]+)/i,/(mozilla)\/((\d+)?[\w\.]+).+rv\:.+gecko\/\d+/i,/(uc\s?browser|polaris|lynx|dillo|icab|doris|amaya|w3m|netsurf|qqbrowser)[\/\s]?((\d+)?[\w\.]+)/i,/(links)\s\(((\d+)?[\w\.]+)/i,/(gobrowser)\/?((\d+)?[\w\.]+)*/i,/(ice\s?browser)\/v?((\d+)?[\w\._]+)/i,/(mosaic)[\/\s]((\d+)?[\w\.]+)/i],[u,d,a]],engine:[[/(presto)\/([\w\.]+)/i,/(webkit|trident|netfront|netsurf|amaya|lynx|w3m)\/([\w\.]+)/i,/(khtml|tasman|links)[\/\s]\(?([\w\.]+)/i,/(icab)[\/\s]([23]\.[\d\.]+)/i],[u,d],[/rv\:([\w\.]+).*(gecko)/i],[d,u]],os:[[/(windows)\snt\s6\.2;\s(arm)/i,/(windows\sphone(?:\sos)*|windows\smobile|windows)[\s\/]?([ntce\d\.\s]+\w)/i],[u,[d,v.str,y.os.windows.version]],[/(win(?=3|9|n)|win\s9x\s)([nt\d\.]+)/i],[[u,"Windows"],[d,v.str,y.os.windows.version]],[/\((bb)(10);/i],[[u,"BlackBerry"],d],[/(blackberry)\w*\/?([\w\.]+)*/i,/(tizen)\/([\w\.]+)/i,/(android|webos|palm\os|qnx|bada|rim\stablet\sos|meego)[\/\s-]?([\w\.]+)*/i],[u,d],[/(symbian\s?os|symbos|s60(?=;))[\/\s-]?([\w\.]+)*/i],[[u,"Symbian"],d],[/mozilla.+\(mobile;.+gecko.+firefox/i],[[u,"Firefox OS"],d],[/(nintendo|playstation)\s([wids3portablevu]+)/i,/(mint)[\/\s\(]?(\w+)*/i,/(joli|[kxln]?ubuntu|debian|[open]*suse|gentoo|arch|slackware|fedora|mandriva|centos|pclinuxos|redhat|zenwalk)[\/\s-]?([\w\.-]+)*/i,/(hurd|linux)\s?([\w\.]+)*/i,/(gnu)\s?([\w\.]+)*/i],[u,d],[/(cros)\s[\w]+\s([\w\.]+\w)/i],[[u,"Chromium OS"],d],[/(sunos)\s?([\w\.]+\d)*/i],[[u,"Solaris"],d],[/\s([frentopc-]{0,4}bsd|dragonfly)\s?([\w\.]+)*/i],[u,d],[/(ip[honead]+)(?:.*os\s*([\w]+)*\slike\smac|;\sopera)/i],[[u,"iOS"],[d,/_/g,"."]],[/(mac\sos\sx)\s?([\w\s\.]+\w)*/i],[u,[d,/_/g,"."]],[/(haiku)\s(\w+)/i,/(aix)\s((\d)(?=\.|\)|\s)[\w\.]*)*/i,/(macintosh|mac(?=_powerpc)|plan\s9|minix|beos|os\/2|amigaos|morphos|risc\sos)/i,/(unix)\s?([\w\.]+)*/i],[u,d]]},E=function(e){var n=e||(window&&window.navigator&&window.navigator.userAgent?window.navigator.userAgent:t);this.getBrowser=function(){return v.rgx.apply(this,w.browser)},this.getEngine=function(){return v.rgx.apply(this,w.engine)},this.getOS=function(){return v.rgx.apply(this,w.os)},this.getResult=function(){return{ua:this.getUA(),browser:this.getBrowser(),engine:this.getEngine(),os:this.getOS()}},this.getUA=function(){return n},this.setUA=function(e){return n=e,this},this.setUA(n)};return(new E).getResult()}(),i=function(){var t={define_property:function(){return!1}(),create_canvas:function(){var e=document.createElement("canvas");return!(!e.getContext||!e.getContext("2d"))}(),return_response_type:function(t){try{if(-1!==e.inArray(t,["","text","document"]))return!0;if(window.XMLHttpRequest){var n=new XMLHttpRequest;if(n.open("get","/"),"responseType"in n)return n.responseType=t,n.responseType!==t?!1:!0}}catch(i){}return!1},use_data_uri:function(){var e=new Image;return e.onload=function(){t.use_data_uri=1===e.width&&1===e.height},setTimeout(function(){e.src="data:image/gif;base64,R0lGODlhAQABAIAAAP8AAAAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw=="},1),!1}(),use_data_uri_over32kb:function(){return t.use_data_uri&&("IE"!==r.browser||r.version>=9)},use_data_uri_of:function(e){return t.use_data_uri&&33e3>e||t.use_data_uri_over32kb()},use_fileinput:function(){var e=document.createElement("input");return e.setAttribute("type","file"),!e.disabled}};return function(n){var i=[].slice.call(arguments);return i.shift(),"function"===e.typeOf(t[n])?t[n].apply(this,i):!!t[n]}}(),r={can:i,browser:n.browser.name,version:parseFloat(n.browser.major),os:n.os.name,osVersion:n.os.version,verComp:t,swf_url:"../flash/Moxie.swf",xap_url:"../silverlight/Moxie.xap",global_event_dispatcher:"moxie.core.EventTarget.instance.dispatchEvent"};return r.OS=r.os,r}),i(f,[d],function(e){var t=function(e){return"string"!=typeof e?e:document.getElementById(e)},n=function(e,t){if(!e.className)return!1;var n=new RegExp("(^|\\s+)"+t+"(\\s+|$)");return n.test(e.className)},i=function(e,t){n(e,t)||(e.className=e.className?e.className.replace(/\s+$/,"")+" "+t:t)},r=function(e,t){if(e.className){var n=new RegExp("(^|\\s+)"+t+"(\\s+|$)");e.className=e.className.replace(n,function(e,t,n){return" "===t&&" "===n?" ":""})}},o=function(e,t){return e.currentStyle?e.currentStyle[t]:window.getComputedStyle?window.getComputedStyle(e,null)[t]:void 0},a=function(t,n){function i(e){var t,n,i=0,r=0;return e&&(n=e.getBoundingClientRect(),t="CSS1Compat"===s.compatMode?s.documentElement:s.body,i=n.left+t.scrollLeft,r=n.top+t.scrollTop),{x:i,y:r}}var r=0,o=0,a,s=document,u,c;if(t=t,n=n||s.body,t&&t.getBoundingClientRect&&"IE"===e.browser&&(!s.documentMode||s.documentMode<8))return u=i(t),c=i(n),{x:u.x-c.x,y:u.y-c.y};for(a=t;a&&a!=n&&a.nodeType;)r+=a.offsetLeft||0,o+=a.offsetTop||0,a=a.offsetParent;for(a=t.parentNode;a&&a!=n&&a.nodeType;)r-=a.scrollLeft||0,o-=a.scrollTop||0,a=a.parentNode;return{x:r,y:o}},s=function(e){return{w:e.offsetWidth||e.clientWidth,h:e.offsetHeight||e.clientHeight}};return{get:t,hasClass:n,addClass:i,removeClass:r,getStyle:o,getPos:a,getSize:s}}),i(h,[u],function(e){function t(e,t){var n;for(n in e)if(e[n]===t)return n;return null}return{RuntimeError:function(){function n(e){this.code=e,this.name=t(i,e),this.message=this.name+": RuntimeError "+this.code}var i={NOT_INIT_ERR:1,NOT_SUPPORTED_ERR:9,JS_ERR:4};return e.extend(n,i),n.prototype=Error.prototype,n}(),OperationNotAllowedException:function(){function t(e){this.code=e,this.name="OperationNotAllowedException"}return e.extend(t,{NOT_ALLOWED_ERR:1}),t.prototype=Error.prototype,t}(),ImageError:function(){function n(e){this.code=e,this.name=t(i,e),this.message=this.name+": ImageError "+this.code}var i={WRONG_FORMAT:1,MAX_RESOLUTION_ERR:2};return e.extend(n,i),n.prototype=Error.prototype,n}(),FileException:function(){function n(e){this.code=e,this.name=t(i,e),this.message=this.name+": FileException "+this.code}var i={NOT_FOUND_ERR:1,SECURITY_ERR:2,ABORT_ERR:3,NOT_READABLE_ERR:4,ENCODING_ERR:5,NO_MODIFICATION_ALLOWED_ERR:6,INVALID_STATE_ERR:7,SYNTAX_ERR:8};return e.extend(n,i),n.prototype=Error.prototype,n}(),DOMException:function(){function n(e){this.code=e,this.name=t(i,e),this.message=this.name+": DOMException "+this.code}var i={INDEX_SIZE_ERR:1,DOMSTRING_SIZE_ERR:2,HIERARCHY_REQUEST_ERR:3,WRONG_DOCUMENT_ERR:4,INVALID_CHARACTER_ERR:5,NO_DATA_ALLOWED_ERR:6,NO_MODIFICATION_ALLOWED_ERR:7,NOT_FOUND_ERR:8,NOT_SUPPORTED_ERR:9,INUSE_ATTRIBUTE_ERR:10,INVALID_STATE_ERR:11,SYNTAX_ERR:12,INVALID_MODIFICATION_ERR:13,NAMESPACE_ERR:14,INVALID_ACCESS_ERR:15,VALIDATION_ERR:16,TYPE_MISMATCH_ERR:17,SECURITY_ERR:18,NETWORK_ERR:19,ABORT_ERR:20,URL_MISMATCH_ERR:21,QUOTA_EXCEEDED_ERR:22,TIMEOUT_ERR:23,INVALID_NODE_TYPE_ERR:24,DATA_CLONE_ERR:25};return e.extend(n,i),n.prototype=Error.prototype,n}(),EventException:function(){function t(e){this.code=e,this.name="EventException"}return e.extend(t,{UNSPECIFIED_EVENT_TYPE_ERR:0}),t.prototype=Error.prototype,t}()}}),i(p,[h,u],function(e,t){function n(){var n={};t.extend(this,{uid:null,init:function(){this.uid||(this.uid=t.guid("uid_"))},addEventListener:function(e,i,r,o){var a=this,s;return e=t.trim(e),/\s/.test(e)?void t.each(e.split(/\s+/),function(e){a.addEventListener(e,i,r,o)}):(e=e.toLowerCase(),r=parseInt(r,10)||0,s=n[this.uid]&&n[this.uid][e]||[],s.push({fn:i,priority:r,scope:o||this}),n[this.uid]||(n[this.uid]={}),void(n[this.uid][e]=s))},hasEventListener:function(e){return e?!(!n[this.uid]||!n[this.uid][e]):!!n[this.uid]},removeEventListener:function(e,i){e=e.toLowerCase();var r=n[this.uid]&&n[this.uid][e],o;if(r){if(i){for(o=r.length-1;o>=0;o--)if(r[o].fn===i){r.splice(o,1);break}}else r=[];r.length||(delete n[this.uid][e],t.isEmptyObj(n[this.uid])&&delete n[this.uid])}},removeAllEventListeners:function(){n[this.uid]&&delete n[this.uid]},dispatchEvent:function(i){var r,o,a,s,u={},c=!0,l;if("string"!==t.typeOf(i)){if(s=i,"string"!==t.typeOf(s.type))throw new e.EventException(e.EventException.UNSPECIFIED_EVENT_TYPE_ERR);i=s.type,s.total!==l&&s.loaded!==l&&(u.total=s.total,u.loaded=s.loaded),u.async=s.async||!1}if(-1!==i.indexOf("::")?!function(e){r=e[0],i=e[1]}(i.split("::")):r=this.uid,i=i.toLowerCase(),o=n[r]&&n[r][i]){o.sort(function(e,t){return t.priority-e.priority}),a=[].slice.call(arguments),a.shift(),u.type=i,a.unshift(u);var d=[];t.each(o,function(e){a[0].target=e.scope,d.push(u.async?function(t){setTimeout(function(){t(e.fn.apply(e.scope,a)===!1)},1)}:function(t){t(e.fn.apply(e.scope,a)===!1)})}),d.length&&t.inSeries(d,function(e){c=!e})}return c},bind:function(){this.addEventListener.apply(this,arguments)},unbind:function(){this.removeEventListener.apply(this,arguments)},unbindAll:function(){this.removeAllEventListeners.apply(this,arguments)},trigger:function(){return this.dispatchEvent.apply(this,arguments)},convertEventPropsToHandlers:function(e){var n;"array"!==t.typeOf(e)&&(e=[e]);for(var i=0;i<e.length;i++)n="on"+e[i],"function"===t.typeOf(this[n])?this.addEventListener(e[i],this[n]):"undefined"===t.typeOf(this[n])&&(this[n]=null)}})}return n.instance=new n,n}),i(m,[],function(){var e=function(e){return unescape(encodeURIComponent(e))},t=function(e){return decodeURIComponent(escape(e))},n=function(e,n){if("function"==typeof window.atob)return n?t(window.atob(e)):window.atob(e);var i="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",r,o,a,s,u,c,l,d,f=0,h=0,p="",m=[];if(!e)return e;e+="";do s=i.indexOf(e.charAt(f++)),u=i.indexOf(e.charAt(f++)),c=i.indexOf(e.charAt(f++)),l=i.indexOf(e.charAt(f++)),d=s<<18|u<<12|c<<6|l,r=d>>16&255,o=d>>8&255,a=255&d,m[h++]=64==c?String.fromCharCode(r):64==l?String.fromCharCode(r,o):String.fromCharCode(r,o,a);while(f<e.length);return p=m.join(""),n?t(p):p},i=function(t,n){if(n&&e(t),"function"==typeof window.btoa)return window.btoa(t);var i="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",r,o,a,s,u,c,l,d,f=0,h=0,p="",m=[];if(!t)return t;do r=t.charCodeAt(f++),o=t.charCodeAt(f++),a=t.charCodeAt(f++),d=r<<16|o<<8|a,s=d>>18&63,u=d>>12&63,c=d>>6&63,l=63&d,m[h++]=i.charAt(s)+i.charAt(u)+i.charAt(c)+i.charAt(l);while(f<t.length);p=m.join("");var g=t.length%3;return(g?p.slice(0,g-3):p)+"===".slice(g||3)};return{utf8_encode:e,utf8_decode:t,atob:n,btoa:i}}),i(g,[u,f,p],function(e,t,n){function i(n,r,a,s,u){var c=this,l,d=e.guid(r+"_"),f=u||"browser";n=n||{},o[d]=this,a=e.extend({access_binary:!1,access_image_binary:!1,display_media:!1,do_cors:!1,drag_and_drop:!1,filter_by_extension:!0,resize_image:!1,report_upload_progress:!1,return_response_headers:!1,return_response_type:!1,return_status_code:!0,send_custom_headers:!1,select_file:!1,select_folder:!1,select_multiple:!0,send_binary_string:!1,send_browser_cookies:!0,send_multipart:!0,slice_blob:!1,stream_upload:!1,summon_file_dialog:!1,upload_filesize:!0,use_http_method:!0},a),n.preferred_caps&&(f=i.getMode(s,n.preferred_caps,f)),l=function(){var t={};return{exec:function(e,n,i,r){return l[n]&&(t[e]||(t[e]={context:this,instance:new l[n]}),t[e].instance[i])?t[e].instance[i].apply(this,r):void 0},removeInstance:function(e){delete t[e]},removeAllInstances:function(){var n=this;e.each(t,function(t,i){"function"===e.typeOf(t.instance.destroy)&&t.instance.destroy.call(t.context),n.removeInstance(i)})}}}(),e.extend(this,{initialized:!1,uid:d,type:r,mode:i.getMode(s,n.required_caps,f),shimid:d+"_container",clients:0,options:n,can:function(t,n){var r=arguments[2]||a;if("string"===e.typeOf(t)&&"undefined"===e.typeOf(n)&&(t=i.parseCaps(t)),"object"===e.typeOf(t)){for(var o in t)if(!this.can(o,t[o],r))return!1;return!0}return"function"===e.typeOf(r[t])?r[t].call(this,n):n===r[t]},getShimContainer:function(){var n,i=t.get(this.shimid);return i||(n=this.options.container?t.get(this.options.container):document.body,i=document.createElement("div"),i.id=this.shimid,i.className="moxie-shim moxie-shim-"+this.type,e.extend(i.style,{position:"absolute",top:"0px",left:"0px",width:"1px",height:"1px",overflow:"hidden"}),n.appendChild(i),n=null),i},getShim:function(){return l},shimExec:function(e,t){var n=[].slice.call(arguments,2);return c.getShim().exec.call(this,this.uid,e,t,n)},exec:function(e,t){var n=[].slice.call(arguments,2);return c[e]&&c[e][t]?c[e][t].apply(this,n):c.shimExec.apply(this,arguments)},destroy:function(){if(c){var e=t.get(this.shimid);e&&e.parentNode.removeChild(e),l&&l.removeAllInstances(),this.unbindAll(),delete o[this.uid],this.uid=null,d=c=l=e=null}}}),this.mode&&n.required_caps&&!this.can(n.required_caps)&&(this.mode=!1)}var r={},o={};return i.order="html5,flash,silverlight,html4",i.getRuntime=function(e){return o[e]?o[e]:!1},i.addConstructor=function(e,t){t.prototype=n.instance,r[e]=t},i.getConstructor=function(e){return r[e]||null},i.getInfo=function(e){var t=i.getRuntime(e);return t?{uid:t.uid,type:t.type,mode:t.mode,can:function(){return t.can.apply(t,arguments)}}:null},i.parseCaps=function(t){var n={};return"string"!==e.typeOf(t)?t||{}:(e.each(t.split(","),function(e){n[e]=!0}),n)},i.can=function(e,t){var n,r=i.getConstructor(e),o;return r?(n=new r({required_caps:t}),o=n.mode,n.destroy(),!!o):!1},i.thatCan=function(e,t){var n=(t||i.order).split(/\s*,\s*/);for(var r in n)if(i.can(n[r],e))return n[r];return null},i.getMode=function(t,n,i){var r=null;if("undefined"===e.typeOf(i)&&(i="browser"),n&&!e.isEmptyObj(t)){if(e.each(n,function(n,i){if(t.hasOwnProperty(i)){var o=t[i](n);if("string"==typeof o&&(o=[o]),r){if(!(r=e.arrayIntersect(r,o)))return r=!1}else r=o}}),r)return-1!==e.inArray(i,r)?i:r[0];if(r===!1)return!1}return i},i.capTrue=function(){return!0},i.capFalse=function(){return!1},i.capTest=function(e){return function(){return!!e}},i}),i(v,[h,u,g],function(e,t,n){return function i(){var i;t.extend(this,{connectRuntime:function(r){function o(t){var s,u;return t.length?(s=t.shift(),(u=n.getConstructor(s))?(i=new u(r),i.bind("Init",function(){i.initialized=!0,setTimeout(function(){i.clients++,a.trigger("RuntimeInit",i)},1)}),i.bind("Error",function(){i.destroy(),o(t)}),i.mode?void i.init():void i.trigger("Error")):void o(t)):(a.trigger("RuntimeError",new e.RuntimeError(e.RuntimeError.NOT_INIT_ERR)),void(i=null))}var a=this,s;if("string"===t.typeOf(r)?s=r:"string"===t.typeOf(r.ruid)&&(s=r.ruid),s){if(i=n.getRuntime(s))return i.clients++,i;throw new e.RuntimeError(e.RuntimeError.NOT_INIT_ERR)}o((r.runtime_order||n.order).split(/\s*,\s*/))},getRuntime:function(){return i&&i.uid?i:(i=null,null)},disconnectRuntime:function(){i&&--i.clients<=0&&(i.destroy(),i=null)}})}}),i(y,[u,m,v],function(e,t,n){function i(o,a){function s(t,n,o){var a,s=r[this.uid];return"string"===e.typeOf(s)&&s.length?(a=new i(null,{type:o,size:n-t}),a.detach(s.substr(t,a.size)),a):null}n.call(this),o&&this.connectRuntime(o),a?"string"===e.typeOf(a)&&(a={data:a}):a={},e.extend(this,{uid:a.uid||e.guid("uid_"),ruid:o,size:a.size||0,type:a.type||"",slice:function(e,t,n){return this.isDetached()?s.apply(this,arguments):this.getRuntime().exec.call(this,"Blob","slice",this.getSource(),e,t,n)},getSource:function(){return r[this.uid]?r[this.uid]:null},detach:function(e){this.ruid&&(this.getRuntime().exec.call(this,"Blob","destroy"),this.disconnectRuntime(),this.ruid=null),e=e||"";var n=e.match(/^data:([^;]*);base64,/);n&&(this.type=n[1],e=t.atob(e.substring(e.indexOf("base64,")+7))),this.size=e.length,r[this.uid]=e},isDetached:function(){return!this.ruid&&"string"===e.typeOf(r[this.uid])},destroy:function(){this.detach(),delete r[this.uid]}}),a.data?this.detach(a.data):r[this.uid]=a}var r={};return i}),i(w,[u,l,y],function(e,t,n){function i(i,r){var o,a;if(r||(r={}),a=r.type&&""!==r.type?r.type:t.getFileMime(r.name),r.name)o=r.name.replace(/\\/g,"/"),o=o.substr(o.lastIndexOf("/")+1);else{var s=a.split("/")[0];o=e.guid((""!==s?s:"file")+"_"),t.extensions[a]&&(o+="."+t.extensions[a][0])}n.apply(this,arguments),e.extend(this,{type:a||"",name:o||e.guid("file_"),lastModifiedDate:r.lastModifiedDate||(new Date).toLocaleString()})}return i.prototype=n.prototype,i}),i(E,[u,l,f,h,p,c,w,g,v],function(e,t,n,i,r,o,a,s,u){function c(r){var c=this,d,f,h;if(-1!==e.inArray(e.typeOf(r),["string","node"])&&(r={browse_button:r}),f=n.get(r.browse_button),!f)throw new i.DOMException(i.DOMException.NOT_FOUND_ERR);h={accept:[{title:o.translate("All Files"),extensions:"*"}],name:"file",multiple:!1,required_caps:!1,container:f.parentNode||document.body},r=e.extend({},h,r),"string"==typeof r.required_caps&&(r.required_caps=s.parseCaps(r.required_caps)),"string"==typeof r.accept&&(r.accept=t.mimes2extList(r.accept)),d=n.get(r.container),d||(d=document.body),"static"===n.getStyle(d,"position")&&(d.style.position="relative"),d=f=null,u.call(c),e.extend(c,{uid:e.guid("uid_"),ruid:null,shimid:null,files:null,init:function(){c.convertEventPropsToHandlers(l),c.bind("RuntimeInit",function(t,i){c.ruid=i.uid,c.shimid=i.shimid,c.bind("Ready",function(){c.trigger("Refresh")},999),c.bind("Change",function(){var t=i.exec.call(c,"FileInput","getFiles");c.files=[],e.each(t,function(e){return 0===e.size?!0:void c.files.push(new a(c.ruid,e))})},999),c.bind("Refresh",function(){var t,o,a,s;a=n.get(r.browse_button),s=n.get(i.shimid),a&&(t=n.getPos(a,n.get(r.container)),o=n.getSize(a),s&&e.extend(s.style,{top:t.y+"px",left:t.x+"px",width:o.w+"px",height:o.h+"px"})),s=a=null}),i.exec.call(c,"FileInput","init",r)}),c.connectRuntime(e.extend({},r,{required_caps:{select_file:!0}}))},disable:function(t){var n=this.getRuntime();n&&n.exec.call(this,"FileInput","disable","undefined"===e.typeOf(t)?!0:t)},refresh:function(){c.trigger("Refresh")},destroy:function(){var t=this.getRuntime();t&&(t.exec.call(this,"FileInput","destroy"),this.disconnectRuntime()),"array"===e.typeOf(this.files)&&e.each(this.files,function(e){e.destroy()}),this.files=null}})}var l=["ready","change","cancel","mouseenter","mouseleave","mousedown","mouseup"];return c.prototype=r.instance,c}),i(_,[c,f,h,u,w,v,p,l],function(e,t,n,i,r,o,a,s){function u(n){var a=this,u;"string"==typeof n&&(n={drop_zone:n}),u={accept:[{title:e.translate("All Files"),extensions:"*"}],required_caps:{drag_and_drop:!0}},n="object"==typeof n?i.extend({},u,n):u,n.container=t.get(n.drop_zone)||document.body,"static"===t.getStyle(n.container,"position")&&(n.container.style.position="relative"),"string"==typeof n.accept&&(n.accept=s.mimes2extList(n.accept)),o.call(a),i.extend(a,{uid:i.guid("uid_"),ruid:null,files:null,init:function(){a.convertEventPropsToHandlers(c),a.bind("RuntimeInit",function(e,t){a.ruid=t.uid,a.bind("Drop",function(){var e=t.exec.call(a,"FileDrop","getFiles");a.files=[],i.each(e,function(e){a.files.push(new r(a.ruid,e))})},999),t.exec.call(a,"FileDrop","init",n),a.dispatchEvent("ready")}),a.connectRuntime(n)},destroy:function(){var e=this.getRuntime();e&&(e.exec.call(this,"FileDrop","destroy"),this.disconnectRuntime()),this.files=null}})}var c=["ready","dragenter","dragleave","drop","error"];return u.prototype=a.instance,u}),i(x,[u,v,p],function(e,t,n){function i(){this.uid=e.guid("uid_"),t.call(this),this.destroy=function(){this.disconnectRuntime(),this.unbindAll()}}return i.prototype=n.instance,i}),i(b,[u,m,h,p,y,w,x],function(e,t,n,i,r,o,a){function s(){function i(e,i){function l(e){o.readyState=s.DONE,o.error=e,o.trigger("error"),d()}function d(){c.destroy(),c=null,o.trigger("loadend")}function f(t){c.bind("Error",function(e,t){l(t)}),c.bind("Progress",function(e){o.result=t.exec.call(c,"FileReader","getResult"),o.trigger(e)}),c.bind("Load",function(e){o.readyState=s.DONE,o.result=t.exec.call(c,"FileReader","getResult"),o.trigger(e),d()}),t.exec.call(c,"FileReader","read",e,i)}if(c=new a,this.convertEventPropsToHandlers(u),this.readyState===s.LOADING)return l(new n.DOMException(n.DOMException.INVALID_STATE_ERR));if(this.readyState=s.LOADING,this.trigger("loadstart"),i instanceof r)if(i.isDetached()){var h=i.getSource();switch(e){case"readAsText":case"readAsBinaryString":this.result=h;break;case"readAsDataURL":this.result="data:"+i.type+";base64,"+t.btoa(h)}this.readyState=s.DONE,this.trigger("load"),d()}else f(c.connectRuntime(i.ruid));else l(new n.DOMException(n.DOMException.NOT_FOUND_ERR))}var o=this,c;e.extend(this,{uid:e.guid("uid_"),readyState:s.EMPTY,result:null,error:null,readAsBinaryString:function(e){i.call(this,"readAsBinaryString",e)},readAsDataURL:function(e){i.call(this,"readAsDataURL",e)},readAsText:function(e){i.call(this,"readAsText",e)},abort:function(){this.result=null,-1===e.inArray(this.readyState,[s.EMPTY,s.DONE])&&(this.readyState===s.LOADING&&(this.readyState=s.DONE),c&&c.getRuntime().exec.call(this,"FileReader","abort"),this.trigger("abort"),this.trigger("loadend"))
+},destroy:function(){this.abort(),c&&(c.getRuntime().exec.call(this,"FileReader","destroy"),c.disconnectRuntime()),o=c=null}})}var u=["loadstart","progress","load","abort","error","loadend"];return s.EMPTY=0,s.LOADING=1,s.DONE=2,s.prototype=i.instance,s}),i(R,[],function(){var e=function(t,n){for(var i=["source","scheme","authority","userInfo","user","pass","host","port","relative","path","directory","file","query","fragment"],r=i.length,o={http:80,https:443},a={},s=/^(?:([^:\/?#]+):)?(?:\/\/()(?:(?:()(?:([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?))?()(?:(()(?:(?:[^?#\/]*\/)*)()(?:[^?#]*))(?:\\?([^#]*))?(?:#(.*))?)/,u=s.exec(t||"");r--;)u[r]&&(a[i[r]]=u[r]);if(!a.scheme){n&&"string"!=typeof n||(n=e(n||document.location.href)),a.scheme=n.scheme,a.host=n.host,a.port=n.port;var c="";/^[^\/]/.test(a.path)&&(c=n.path,/(\/|\/[^\.]+)$/.test(c)?c+="/":c=c.replace(/\/[^\/]+$/,"/")),a.path=c+(a.path||"")}return a.port||(a.port=o[a.scheme]||80),a.port=parseInt(a.port,10),a.path||(a.path="/"),delete a.source,a},t=function(t){var n={http:80,https:443},i=e(t);return i.scheme+"://"+i.host+(i.port!==n[i.scheme]?":"+i.port:"")+i.path+(i.query?i.query:"")},n=function(t){function n(e){return[e.scheme,e.host,e.port].join("/")}return"string"==typeof t&&(t=e(t)),n(e())===n(t)};return{parseUrl:e,resolveUrl:t,hasSameOrigin:n}}),i(T,[u,v,m],function(e,t,n){return function(){function i(e,t){if(!t.isDetached()){var i=this.connectRuntime(t.ruid).exec.call(this,"FileReaderSync","read",e,t);return this.disconnectRuntime(),i}var r=t.getSource();switch(e){case"readAsBinaryString":return r;case"readAsDataURL":return"data:"+t.type+";base64,"+n.btoa(r);case"readAsText":for(var o="",a=0,s=r.length;s>a;a++)o+=String.fromCharCode(r[a]);return o}}t.call(this),e.extend(this,{uid:e.guid("uid_"),readAsBinaryString:function(e){return i.call(this,"readAsBinaryString",e)},readAsDataURL:function(e){return i.call(this,"readAsDataURL",e)},readAsText:function(e){return i.call(this,"readAsText",e)}})}}),i(A,[h,u,y],function(e,t,n){function i(){var e,i=[];t.extend(this,{append:function(r,o){var a=this,s=t.typeOf(o);o instanceof n?e={name:r,value:o}:"array"===s?(r+="[]",t.each(o,function(e){a.append(r,e)})):"object"===s?t.each(o,function(e,t){a.append(r+"["+t+"]",e)}):"null"===s||"undefined"===s||"number"===s&&isNaN(o)?a.append(r,"false"):i.push({name:r,value:o.toString()})},hasBlob:function(){return!!this.getBlob()},getBlob:function(){return e&&e.value||null},getBlobName:function(){return e&&e.name||null},each:function(n){t.each(i,function(e){n(e.value,e.name)}),e&&n(e.value,e.name)},destroy:function(){e=null,i=[]}})}return i}),i(S,[u,h,p,m,R,g,x,y,T,A,d,l],function(e,t,n,i,r,o,a,s,u,c,l,d){function f(){this.uid=e.guid("uid_")}function h(){function n(e,t){return y.hasOwnProperty(e)?1===arguments.length?l.can("define_property")?y[e]:v[e]:void(l.can("define_property")?y[e]=t:v[e]=t):void 0}function u(t){function i(){k&&(k.destroy(),k=null),s.dispatchEvent("loadend"),s=null}function r(r){k.bind("LoadStart",function(e){n("readyState",h.LOADING),s.dispatchEvent("readystatechange"),s.dispatchEvent(e),I&&s.upload.dispatchEvent(e)}),k.bind("Progress",function(e){n("readyState")!==h.LOADING&&(n("readyState",h.LOADING),s.dispatchEvent("readystatechange")),s.dispatchEvent(e)}),k.bind("UploadProgress",function(e){I&&s.upload.dispatchEvent({type:"progress",lengthComputable:!1,total:e.total,loaded:e.loaded})}),k.bind("Load",function(t){n("readyState",h.DONE),n("status",Number(r.exec.call(k,"XMLHttpRequest","getStatus")||0)),n("statusText",p[n("status")]||""),n("response",r.exec.call(k,"XMLHttpRequest","getResponse",n("responseType"))),~e.inArray(n("responseType"),["text",""])?n("responseText",n("response")):"document"===n("responseType")&&n("responseXML",n("response")),U=r.exec.call(k,"XMLHttpRequest","getAllResponseHeaders"),s.dispatchEvent("readystatechange"),n("status")>0?(I&&s.upload.dispatchEvent(t),s.dispatchEvent(t)):(N=!0,s.dispatchEvent("error")),i()}),k.bind("Abort",function(e){s.dispatchEvent(e),i()}),k.bind("Error",function(e){N=!0,n("readyState",h.DONE),s.dispatchEvent("readystatechange"),D=!0,s.dispatchEvent(e),i()}),r.exec.call(k,"XMLHttpRequest","send",{url:E,method:_,async:w,user:b,password:R,headers:x,mimeType:A,encoding:T,responseType:s.responseType,withCredentials:s.withCredentials,options:P},t)}var s=this;M=(new Date).getTime(),k=new a,"string"==typeof P.required_caps&&(P.required_caps=o.parseCaps(P.required_caps)),P.required_caps=e.extend({},P.required_caps,{return_response_type:s.responseType}),t instanceof c&&(P.required_caps.send_multipart=!0),L||(P.required_caps.do_cors=!0),P.ruid?r(k.connectRuntime(P)):(k.bind("RuntimeInit",function(e,t){r(t)}),k.bind("RuntimeError",function(e,t){s.dispatchEvent("RuntimeError",t)}),k.connectRuntime(P))}function g(){n("responseText",""),n("responseXML",null),n("response",null),n("status",0),n("statusText",""),M=C=null}var v=this,y={timeout:0,readyState:h.UNSENT,withCredentials:!1,status:0,statusText:"",responseType:"",responseXML:null,responseText:null,response:null},w=!0,E,_,x={},b,R,T=null,A=null,S=!1,O=!1,I=!1,D=!1,N=!1,L=!1,M,C,F=null,H=null,P={},k,U="",B;e.extend(this,y,{uid:e.guid("uid_"),upload:new f,open:function(o,a,s,u,c){var l;if(!o||!a)throw new t.DOMException(t.DOMException.SYNTAX_ERR);if(/[\u0100-\uffff]/.test(o)||i.utf8_encode(o)!==o)throw new t.DOMException(t.DOMException.SYNTAX_ERR);if(~e.inArray(o.toUpperCase(),["CONNECT","DELETE","GET","HEAD","OPTIONS","POST","PUT","TRACE","TRACK"])&&(_=o.toUpperCase()),~e.inArray(_,["CONNECT","TRACE","TRACK"]))throw new t.DOMException(t.DOMException.SECURITY_ERR);if(a=i.utf8_encode(a),l=r.parseUrl(a),L=r.hasSameOrigin(l),E=r.resolveUrl(a),(u||c)&&!L)throw new t.DOMException(t.DOMException.INVALID_ACCESS_ERR);if(b=u||l.user,R=c||l.pass,w=s||!0,w===!1&&(n("timeout")||n("withCredentials")||""!==n("responseType")))throw new t.DOMException(t.DOMException.INVALID_ACCESS_ERR);S=!w,O=!1,x={},g.call(this),n("readyState",h.OPENED),this.convertEventPropsToHandlers(["readystatechange"]),this.dispatchEvent("readystatechange")},setRequestHeader:function(r,o){var a=["accept-charset","accept-encoding","access-control-request-headers","access-control-request-method","connection","content-length","cookie","cookie2","content-transfer-encoding","date","expect","host","keep-alive","origin","referer","te","trailer","transfer-encoding","upgrade","user-agent","via"];if(n("readyState")!==h.OPENED||O)throw new t.DOMException(t.DOMException.INVALID_STATE_ERR);if(/[\u0100-\uffff]/.test(r)||i.utf8_encode(r)!==r)throw new t.DOMException(t.DOMException.SYNTAX_ERR);return r=e.trim(r).toLowerCase(),~e.inArray(r,a)||/^(proxy\-|sec\-)/.test(r)?!1:(x[r]?x[r]+=", "+o:x[r]=o,!0)},getAllResponseHeaders:function(){return U||""},getResponseHeader:function(t){return t=t.toLowerCase(),N||~e.inArray(t,["set-cookie","set-cookie2"])?null:U&&""!==U&&(B||(B={},e.each(U.split(/\r\n/),function(t){var n=t.split(/:\s+/);2===n.length&&(n[0]=e.trim(n[0]),B[n[0].toLowerCase()]={header:n[0],value:e.trim(n[1])})})),B.hasOwnProperty(t))?B[t].header+": "+B[t].value:null},overrideMimeType:function(i){var r,o;if(~e.inArray(n("readyState"),[h.LOADING,h.DONE]))throw new t.DOMException(t.DOMException.INVALID_STATE_ERR);if(i=e.trim(i.toLowerCase()),/;/.test(i)&&(r=i.match(/^([^;]+)(?:;\scharset\=)?(.*)$/))&&(i=r[1],r[2]&&(o=r[2])),!d.mimes[i])throw new t.DOMException(t.DOMException.SYNTAX_ERR);F=i,H=o},send:function(n,r){if(P="string"===e.typeOf(r)?{ruid:r}:r?r:{},this.convertEventPropsToHandlers(m),this.upload.convertEventPropsToHandlers(m),this.readyState!==h.OPENED||O)throw new t.DOMException(t.DOMException.INVALID_STATE_ERR);if(n instanceof s)P.ruid=n.ruid,A=n.type||"application/octet-stream";else if(n instanceof c){if(n.hasBlob()){var o=n.getBlob();P.ruid=o.ruid,A=o.type||"application/octet-stream"}}else"string"==typeof n&&(T="UTF-8",A="text/plain;charset=UTF-8",n=i.utf8_encode(n));this.withCredentials||(this.withCredentials=P.required_caps&&P.required_caps.send_browser_cookies&&!L),I=!S&&this.upload.hasEventListener(),N=!1,D=!n,S||(O=!0),u.call(this,n)},abort:function(){if(N=!0,S=!1,~e.inArray(n("readyState"),[h.UNSENT,h.OPENED,h.DONE]))n("readyState",h.UNSENT);else{if(n("readyState",h.DONE),O=!1,!k)throw new t.DOMException(t.DOMException.INVALID_STATE_ERR);k.getRuntime().exec.call(k,"XMLHttpRequest","abort",D),D=!0}},destroy:function(){k&&("function"===e.typeOf(k.destroy)&&k.destroy(),k=null),this.unbindAll(),this.upload&&(this.upload.unbindAll(),this.upload=null)}})}var p={100:"Continue",101:"Switching Protocols",102:"Processing",200:"OK",201:"Created",202:"Accepted",203:"Non-Authoritative Information",204:"No Content",205:"Reset Content",206:"Partial Content",207:"Multi-Status",226:"IM Used",300:"Multiple Choices",301:"Moved Permanently",302:"Found",303:"See Other",304:"Not Modified",305:"Use Proxy",306:"Reserved",307:"Temporary Redirect",400:"Bad Request",401:"Unauthorized",402:"Payment Required",403:"Forbidden",404:"Not Found",405:"Method Not Allowed",406:"Not Acceptable",407:"Proxy Authentication Required",408:"Request Timeout",409:"Conflict",410:"Gone",411:"Length Required",412:"Precondition Failed",413:"Request Entity Too Large",414:"Request-URI Too Long",415:"Unsupported Media Type",416:"Requested Range Not Satisfiable",417:"Expectation Failed",422:"Unprocessable Entity",423:"Locked",424:"Failed Dependency",426:"Upgrade Required",500:"Internal Server Error",501:"Not Implemented",502:"Bad Gateway",503:"Service Unavailable",504:"Gateway Timeout",505:"HTTP Version Not Supported",506:"Variant Also Negotiates",507:"Insufficient Storage",510:"Not Extended"};f.prototype=n.instance;var m=["loadstart","progress","abort","error","load","timeout","loadend"],g=1,v=2;return h.UNSENT=0,h.OPENED=1,h.HEADERS_RECEIVED=2,h.LOADING=3,h.DONE=4,h.prototype=n.instance,h}),i(O,[u,m,v,p],function(e,t,n,i){function r(){function i(){l=d=0,c=this.result=null}function o(t,n){var i=this;u=n,i.bind("TransportingProgress",function(t){d=t.loaded,l>d&&-1===e.inArray(i.state,[r.IDLE,r.DONE])&&a.call(i)},999),i.bind("TransportingComplete",function(){d=l,i.state=r.DONE,c=null,i.result=u.exec.call(i,"Transporter","getAsBlob",t||"")},999),i.state=r.BUSY,i.trigger("TransportingStarted"),a.call(i)}function a(){var e=this,n,i=l-d;f>i&&(f=i),n=t.btoa(c.substr(d,f)),u.exec.call(e,"Transporter","receive",n,l)}var s,u,c,l,d,f;n.call(this),e.extend(this,{uid:e.guid("uid_"),state:r.IDLE,result:null,transport:function(t,n,r){var a=this;if(r=e.extend({chunk_size:204798},r),(s=r.chunk_size%3)&&(r.chunk_size+=3-s),f=r.chunk_size,i.call(this),c=t,l=t.length,"string"===e.typeOf(r)||r.ruid)o.call(a,n,this.connectRuntime(r));else{var u=function(e,t){a.unbind("RuntimeInit",u),o.call(a,n,t)};this.bind("RuntimeInit",u),this.connectRuntime(r)}},abort:function(){var e=this;e.state=r.IDLE,u&&(u.exec.call(e,"Transporter","clear"),e.trigger("TransportingAborted")),i.call(e)},destroy:function(){this.unbindAll(),u=null,this.disconnectRuntime(),i.call(this)}})}return r.IDLE=0,r.BUSY=1,r.DONE=2,r.prototype=i.instance,r}),i(I,[u,f,h,T,S,g,v,O,d,p,y,w,m],function(e,t,n,i,r,o,a,s,u,c,l,d,f){function h(){function i(e){e||(e=this.getRuntime().exec.call(this,"Image","getInfo")),this.size=e.size,this.width=e.width,this.height=e.height,this.type=e.type,this.meta=e.meta,""===this.name&&(this.name=e.name)}function c(t){var i=e.typeOf(t);try{if(t instanceof h){if(!t.size)throw new n.DOMException(n.DOMException.INVALID_STATE_ERR);m.apply(this,arguments)}else if(t instanceof l){if(!~e.inArray(t.type,["image/jpeg","image/png"]))throw new n.ImageError(n.ImageError.WRONG_FORMAT);g.apply(this,arguments)}else if(-1!==e.inArray(i,["blob","file"]))c.call(this,new d(null,t),arguments[1]);else if("string"===i)/^data:[^;]*;base64,/.test(t)?c.call(this,new l(null,{data:t}),arguments[1]):v.apply(this,arguments);else{if("node"!==i||"img"!==t.nodeName.toLowerCase())throw new n.DOMException(n.DOMException.TYPE_MISMATCH_ERR);c.call(this,t.src,arguments[1])}}catch(r){this.trigger("error",r.code)}}function m(t,n){var i=this.connectRuntime(t.ruid);this.ruid=i.uid,i.exec.call(this,"Image","loadFromImage",t,"undefined"===e.typeOf(n)?!0:n)}function g(t,n){function i(e){r.ruid=e.uid,e.exec.call(r,"Image","loadFromBlob",t)}var r=this;r.name=t.name||"",t.isDetached()?(this.bind("RuntimeInit",function(e,t){i(t)}),n&&"string"==typeof n.required_caps&&(n.required_caps=o.parseCaps(n.required_caps)),this.connectRuntime(e.extend({required_caps:{access_image_binary:!0,resize_image:!0}},n))):i(this.connectRuntime(t.ruid))}function v(e,t){var n=this,i;i=new r,i.open("get",e),i.responseType="blob",i.onprogress=function(e){n.trigger(e)},i.onload=function(){g.call(n,i.response,!0)},i.onerror=function(e){n.trigger(e)},i.onloadend=function(){i.destroy()},i.bind("RuntimeError",function(e,t){n.trigger("RuntimeError",t)}),i.send(null,t)}a.call(this),e.extend(this,{uid:e.guid("uid_"),ruid:null,name:"",size:0,width:0,height:0,type:"",meta:{},clone:function(){this.load.apply(this,arguments)},load:function(){this.bind("Load Resize",function(){i.call(this)},999),this.convertEventPropsToHandlers(p),c.apply(this,arguments)},downsize:function(t){var i={width:this.width,height:this.height,crop:!1,preserveHeaders:!0};t="object"==typeof t?e.extend(i,t):e.extend(i,{width:arguments[0],height:arguments[1],crop:arguments[2],preserveHeaders:arguments[3]});try{if(!this.size)throw new n.DOMException(n.DOMException.INVALID_STATE_ERR);if(this.width>h.MAX_RESIZE_WIDTH||this.height>h.MAX_RESIZE_HEIGHT)throw new n.ImageError(n.ImageError.MAX_RESOLUTION_ERR);this.getRuntime().exec.call(this,"Image","downsize",t.width,t.height,t.crop,t.preserveHeaders)}catch(r){this.trigger("error",r.code)}},crop:function(e,t,n){this.downsize(e,t,!0,n)},getAsCanvas:function(){if(!u.can("create_canvas"))throw new n.RuntimeError(n.RuntimeError.NOT_SUPPORTED_ERR);var e=this.connectRuntime(this.ruid);return e.exec.call(this,"Image","getAsCanvas")},getAsBlob:function(e,t){if(!this.size)throw new n.DOMException(n.DOMException.INVALID_STATE_ERR);return e||(e="image/jpeg"),"image/jpeg"!==e||t||(t=90),this.getRuntime().exec.call(this,"Image","getAsBlob",e,t)},getAsDataURL:function(e,t){if(!this.size)throw new n.DOMException(n.DOMException.INVALID_STATE_ERR);return this.getRuntime().exec.call(this,"Image","getAsDataURL",e,t)},getAsBinaryString:function(e,t){var n=this.getAsDataURL(e,t);return f.atob(n.substring(n.indexOf("base64,")+7))},embed:function(i){function r(){if(u.can("create_canvas")){var t=a.getAsCanvas();if(t)return i.appendChild(t),t=null,a.destroy(),void o.trigger("embedded")}var r=a.getAsDataURL(c,l);if(!r)throw new n.ImageError(n.ImageError.WRONG_FORMAT);if(u.can("use_data_uri_of",r.length))i.innerHTML='<img src="'+r+'" width="'+a.width+'" height="'+a.height+'" />',a.destroy(),o.trigger("embedded");else{var d=new s;d.bind("TransportingComplete",function(){v=o.connectRuntime(this.result.ruid),o.bind("Embedded",function(){e.extend(v.getShimContainer().style,{top:"0px",left:"0px",width:a.width+"px",height:a.height+"px"}),v=null},999),v.exec.call(o,"ImageView","display",this.result.uid,m,g),a.destroy()}),d.transport(f.atob(r.substring(r.indexOf("base64,")+7)),c,e.extend({},p,{required_caps:{display_media:!0},runtime_order:"flash,silverlight",container:i}))}}var o=this,a,c,l,d,p=arguments[1]||{},m=this.width,g=this.height,v;try{if(!(i=t.get(i)))throw new n.DOMException(n.DOMException.INVALID_NODE_TYPE_ERR);if(!this.size)throw new n.DOMException(n.DOMException.INVALID_STATE_ERR);if(this.width>h.MAX_RESIZE_WIDTH||this.height>h.MAX_RESIZE_HEIGHT)throw new n.ImageError(n.ImageError.MAX_RESOLUTION_ERR);if(c=p.type||this.type||"image/jpeg",l=p.quality||90,d="undefined"!==e.typeOf(p.crop)?p.crop:!1,p.width)m=p.width,g=p.height||m;else{var y=t.getSize(i);y.w&&y.h&&(m=y.w,g=y.h)}return a=new h,a.bind("Resize",function(){r.call(o)}),a.bind("Load",function(){a.downsize(m,g,d,!1)}),a.clone(this,!1),a}catch(w){this.trigger("error",w.code)}},destroy:function(){this.ruid&&(this.getRuntime().exec.call(this,"Image","destroy"),this.disconnectRuntime()),this.unbindAll()}})}var p=["progress","load","error","resize","embedded"];return h.MAX_RESIZE_WIDTH=6500,h.MAX_RESIZE_HEIGHT=6500,h.prototype=c.instance,h}),i(D,[u,h,g,d],function(e,t,n,i){function r(t){var r=this,s=n.capTest,u=n.capTrue,c=e.extend({access_binary:s(window.FileReader||window.File&&window.File.getAsDataURL),access_image_binary:function(){return r.can("access_binary")&&!!a.Image},display_media:s(i.can("create_canvas")||i.can("use_data_uri_over32kb")),do_cors:s(window.XMLHttpRequest&&"withCredentials"in new XMLHttpRequest),drag_and_drop:s(function(){var e=document.createElement("div");return("draggable"in e||"ondragstart"in e&&"ondrop"in e)&&("IE"!==i.browser||i.version>9)}()),filter_by_extension:s(function(){return"Chrome"===i.browser&&i.version>=28||"IE"===i.browser&&i.version>=10}()),return_response_headers:u,return_response_type:function(e){return"json"===e&&window.JSON?!0:i.can("return_response_type",e)},return_status_code:u,report_upload_progress:s(window.XMLHttpRequest&&(new XMLHttpRequest).upload),resize_image:function(){return r.can("access_binary")&&i.can("create_canvas")},select_file:function(){return i.can("use_fileinput")&&window.File},select_folder:function(){return r.can("select_file")&&"Chrome"===i.browser&&i.version>=21},select_multiple:function(){return!(!r.can("select_file")||"Safari"===i.browser&&"Windows"===i.os||"iOS"===i.os&&i.verComp(i.osVersion,"7.0.4","<"))},send_binary_string:s(window.XMLHttpRequest&&((new XMLHttpRequest).sendAsBinary||window.Uint8Array&&window.ArrayBuffer)),send_custom_headers:s(window.XMLHttpRequest),send_multipart:function(){return!!(window.XMLHttpRequest&&(new XMLHttpRequest).upload&&window.FormData)||r.can("send_binary_string")},slice_blob:s(window.File&&(File.prototype.mozSlice||File.prototype.webkitSlice||File.prototype.slice)),stream_upload:function(){return r.can("slice_blob")&&r.can("send_multipart")},summon_file_dialog:s(function(){return"Firefox"===i.browser&&i.version>=4||"Opera"===i.browser&&i.version>=12||"IE"===i.browser&&i.version>=10||!!~e.inArray(i.browser,["Chrome","Safari"])}()),upload_filesize:u},arguments[2]);n.call(this,t,arguments[1]||o,c),e.extend(this,{init:function(){this.trigger("Init")},destroy:function(e){return function(){e.call(r),e=r=null}}(this.destroy)}),e.extend(this.getShim(),a)}var o="html5",a={};return n.addConstructor(o,r),a}),i(N,[D,y],function(e,t){function n(){function e(e,t,n){var i;if(!window.File.prototype.slice)return(i=window.File.prototype.webkitSlice||window.File.prototype.mozSlice)?i.call(e,t,n):null;try{return e.slice(),e.slice(t,n)}catch(r){return e.slice(t,n-t)}}this.slice=function(){return new t(this.getRuntime().uid,e.apply(this,arguments))}}return e.Blob=n}),i(L,[u],function(e){function t(){this.returnValue=!1}function n(){this.cancelBubble=!0}var i={},r="moxie_"+e.guid(),o=function(o,a,s,u){var c,l;a=a.toLowerCase(),o.addEventListener?(c=s,o.addEventListener(a,c,!1)):o.attachEvent&&(c=function(){var e=window.event;e.target||(e.target=e.srcElement),e.preventDefault=t,e.stopPropagation=n,s(e)},o.attachEvent("on"+a,c)),o[r]||(o[r]=e.guid()),i.hasOwnProperty(o[r])||(i[o[r]]={}),l=i[o[r]],l.hasOwnProperty(a)||(l[a]=[]),l[a].push({func:c,orig:s,key:u})},a=function(t,n,o){var a,s;if(n=n.toLowerCase(),t[r]&&i[t[r]]&&i[t[r]][n]){a=i[t[r]][n];for(var u=a.length-1;u>=0&&(a[u].orig!==o&&a[u].key!==o||(t.removeEventListener?t.removeEventListener(n,a[u].func,!1):t.detachEvent&&t.detachEvent("on"+n,a[u].func),a[u].orig=null,a[u].func=null,a.splice(u,1),o===s));u--);if(a.length||delete i[t[r]][n],e.isEmptyObj(i[t[r]])){delete i[t[r]];try{delete t[r]}catch(c){t[r]=s}}}},s=function(t,n){t&&t[r]&&e.each(i[t[r]],function(e,i){a(t,i,n)})};return{addEvent:o,removeEvent:a,removeAllEvents:s}}),i(M,[D,u,f,L,l,d],function(e,t,n,i,r,o){function a(){var e=[],a;t.extend(this,{init:function(s){var u=this,c=u.getRuntime(),l,d,f,h,p,m;a=s,e=[],f=a.accept.mimes||r.extList2mimes(a.accept,c.can("filter_by_extension")),d=c.getShimContainer(),d.innerHTML='<input id="'+c.uid+'" type="file" style="font-size:999px;opacity:0;"'+(a.multiple&&c.can("select_multiple")?"multiple":"")+(a.directory&&c.can("select_folder")?"webkitdirectory directory":"")+(f?' accept="'+f.join(",")+'"':"")+" />",l=n.get(c.uid),t.extend(l.style,{position:"absolute",top:0,left:0,width:"100%",height:"100%"}),h=n.get(a.browse_button),c.can("summon_file_dialog")&&("static"===n.getStyle(h,"position")&&(h.style.position="relative"),p=parseInt(n.getStyle(h,"z-index"),10)||1,h.style.zIndex=p,d.style.zIndex=p-1,i.addEvent(h,"click",function(e){var t=n.get(c.uid);t&&!t.disabled&&t.click(),e.preventDefault()},u.uid)),m=c.can("summon_file_dialog")?h:d,i.addEvent(m,"mouseover",function(){u.trigger("mouseenter")},u.uid),i.addEvent(m,"mouseout",function(){u.trigger("mouseleave")},u.uid),i.addEvent(m,"mousedown",function(){u.trigger("mousedown")},u.uid),i.addEvent(n.get(a.container),"mouseup",function(){u.trigger("mouseup")},u.uid),l.onchange=function g(){if(e=[],a.directory?t.each(this.files,function(t){"."!==t.name&&e.push(t)}):e=[].slice.call(this.files),"IE"!==o.browser&&"IEMobile"!==o.browser)this.value="";else{var n=this.cloneNode(!0);this.parentNode.replaceChild(n,this),n.onchange=g}u.trigger("change")},u.trigger({type:"ready",async:!0}),d=null},getFiles:function(){return e},disable:function(e){var t=this.getRuntime(),i;(i=n.get(t.uid))&&(i.disabled=!!e)},destroy:function(){var t=this.getRuntime(),r=t.getShim(),o=t.getShimContainer();i.removeAllEvents(o,this.uid),i.removeAllEvents(a&&n.get(a.container),this.uid),i.removeAllEvents(a&&n.get(a.browse_button),this.uid),o&&(o.innerHTML=""),r.removeInstance(this.uid),e=a=o=r=null}})}return e.FileInput=a}),i(C,[D,u,f,L,l],function(e,t,n,i,r){function o(){function e(e){if(!e.dataTransfer||!e.dataTransfer.types)return!1;var n=t.toArray(e.dataTransfer.types||[]);return-1!==t.inArray("Files",n)||-1!==t.inArray("public.file-url",n)||-1!==t.inArray("application/x-moz-file",n)}function o(e){for(var n=[],i=0;i<e.length;i++)[].push.apply(n,e[i].extensions.split(/\s*,\s*/));return-1===t.inArray("*",n)?n:[]}function a(e){if(!f.length)return!0;var n=r.getFileExtension(e.name);return!n||-1!==t.inArray(n,f)}function s(e,n){var i=[];t.each(e,function(e){var t=e.webkitGetAsEntry();if(t)if(t.isFile){var n=e.getAsFile();a(n)&&d.push(n)}else i.push(t)}),i.length?u(i,n):n()}function u(e,n){var i=[];t.each(e,function(e){i.push(function(t){c(e,t)})}),t.inSeries(i,function(){n()})}function c(e,t){e.isFile?e.file(function(e){a(e)&&d.push(e),t()},function(){t()}):e.isDirectory?l(e,t):t()}function l(e,t){function n(e){r.readEntries(function(t){t.length?([].push.apply(i,t),n(e)):e()},e)}var i=[],r=e.createReader();n(function(){u(i,t)})}var d=[],f=[],h;t.extend(this,{init:function(n){var r=this,u;h=n,f=o(h.accept),u=h.container,i.addEvent(u,"dragover",function(t){e(t)&&(t.preventDefault(),t.dataTransfer.dropEffect="copy")},r.uid),i.addEvent(u,"drop",function(n){e(n)&&(n.preventDefault(),d=[],n.dataTransfer.items&&n.dataTransfer.items[0].webkitGetAsEntry?s(n.dataTransfer.items,function(){r.trigger("drop")}):(t.each(n.dataTransfer.files,function(e){a(e)&&d.push(e)}),r.trigger("drop")))},r.uid),i.addEvent(u,"dragenter",function(e){r.trigger("dragenter")},r.uid),i.addEvent(u,"dragleave",function(e){r.trigger("dragleave")},r.uid)},getFiles:function(){return d},destroy:function(){i.removeAllEvents(h&&n.get(h.container),this.uid),d=f=h=null}})}return e.FileDrop=o}),i(F,[D,m,u],function(e,t,n){function i(){function e(e){return t.atob(e.substring(e.indexOf("base64,")+7))}var i,r=!1;n.extend(this,{read:function(e,t){var o=this;i=new window.FileReader,i.addEventListener("progress",function(e){o.trigger(e)}),i.addEventListener("load",function(e){o.trigger(e)}),i.addEventListener("error",function(e){o.trigger(e,i.error)}),i.addEventListener("loadend",function(){i=null}),"function"===n.typeOf(i[e])?(r=!1,i[e](t.getSource())):"readAsBinaryString"===e&&(r=!0,i.readAsDataURL(t.getSource()))},getResult:function(){return i&&i.result?r?e(i.result):i.result:null},abort:function(){i&&i.abort()},destroy:function(){i=null}})}return e.FileReader=i}),i(H,[D,u,l,R,w,y,A,h,d],function(e,t,n,i,r,o,a,s,u){function c(){function e(e,t){var n=this,i,r;i=t.getBlob().getSource(),r=new window.FileReader,r.onload=function(){t.append(t.getBlobName(),new o(null,{type:i.type,data:r.result})),f.send.call(n,e,t)},r.readAsBinaryString(i)}function c(){return!window.XMLHttpRequest||"IE"===u.browser&&u.version<8?function(){for(var e=["Msxml2.XMLHTTP.6.0","Microsoft.XMLHTTP"],t=0;t<e.length;t++)try{return new ActiveXObject(e[t])}catch(n){}}():new window.XMLHttpRequest}function l(e){var t=e.responseXML,n=e.responseText;return"IE"===u.browser&&n&&t&&!t.documentElement&&/[^\/]+\/[^\+]+\+xml/.test(e.getResponseHeader("Content-Type"))&&(t=new window.ActiveXObject("Microsoft.XMLDOM"),t.async=!1,t.validateOnParse=!1,t.loadXML(n)),t&&("IE"===u.browser&&0!==t.parseError||!t.documentElement||"parsererror"===t.documentElement.tagName)?null:t}function d(e){var t="----moxieboundary"+(new Date).getTime(),n="--",i="\r\n",r="",a=this.getRuntime();if(!a.can("send_binary_string"))throw new s.RuntimeError(s.RuntimeError.NOT_SUPPORTED_ERR);return h.setRequestHeader("Content-Type","multipart/form-data; boundary="+t),e.each(function(e,a){r+=e instanceof o?n+t+i+'Content-Disposition: form-data; name="'+a+'"; filename="'+unescape(encodeURIComponent(e.name||"blob"))+'"'+i+"Content-Type: "+(e.type||"application/octet-stream")+i+i+e.getSource()+i:n+t+i+'Content-Disposition: form-data; name="'+a+'"'+i+i+unescape(encodeURIComponent(e))+i}),r+=n+t+n+i}var f=this,h,p;t.extend(this,{send:function(n,r){var s=this,l="Mozilla"===u.browser&&u.version>=4&&u.version<7,f="Android Browser"===u.browser,m=!1;if(p=n.url.replace(/^.+?\/([\w\-\.]+)$/,"$1").toLowerCase(),h=c(),h.open(n.method,n.url,n.async,n.user,n.password),r instanceof o)r.isDetached()&&(m=!0),r=r.getSource();else if(r instanceof a){if(r.hasBlob())if(r.getBlob().isDetached())r=d.call(s,r),m=!0;else if((l||f)&&"blob"===t.typeOf(r.getBlob().getSource())&&window.FileReader)return void e.call(s,n,r);if(r instanceof a){var g=new window.FormData;r.each(function(e,t){e instanceof o?g.append(t,e.getSource()):g.append(t,e)}),r=g}}h.upload?(n.withCredentials&&(h.withCredentials=!0),h.addEventListener("load",function(e){s.trigger(e)}),h.addEventListener("error",function(e){s.trigger(e)}),h.addEventListener("progress",function(e){s.trigger(e)}),h.upload.addEventListener("progress",function(e){s.trigger({type:"UploadProgress",loaded:e.loaded,total:e.total})})):h.onreadystatechange=function v(){switch(h.readyState){case 1:break;case 2:break;case 3:var e,t;try{i.hasSameOrigin(n.url)&&(e=h.getResponseHeader("Content-Length")||0),h.responseText&&(t=h.responseText.length)}catch(r){e=t=0}s.trigger({type:"progress",lengthComputable:!!e,total:parseInt(e,10),loaded:t});break;case 4:h.onreadystatechange=function(){},s.trigger(0===h.status?"error":"load")}},t.isEmptyObj(n.headers)||t.each(n.headers,function(e,t){h.setRequestHeader(t,e)}),""!==n.responseType&&"responseType"in h&&(h.responseType="json"!==n.responseType||u.can("return_response_type","json")?n.responseType:"text"),m?h.sendAsBinary?h.sendAsBinary(r):!function(){for(var e=new Uint8Array(r.length),t=0;t<r.length;t++)e[t]=255&r.charCodeAt(t);h.send(e.buffer)}():h.send(r),s.trigger("loadstart")},getStatus:function(){try{if(h)return h.status}catch(e){}return 0},getResponse:function(e){var t=this.getRuntime();try{switch(e){case"blob":var i=new r(t.uid,h.response),o=h.getResponseHeader("Content-Disposition");if(o){var a=o.match(/filename=([\'\"'])([^\1]+)\1/);a&&(p=a[2])}return i.name=p,i.type||(i.type=n.getFileMime(p)),i;case"json":return u.can("return_response_type","json")?h.response:200===h.status&&window.JSON?JSON.parse(h.responseText):null;case"document":return l(h);default:return""!==h.responseText?h.responseText:null}}catch(s){return null}},getAllResponseHeaders:function(){try{return h.getAllResponseHeaders()}catch(e){}return""},abort:function(){h&&h.abort()},destroy:function(){f=p=null}})}return e.XMLHttpRequest=c}),i(P,[],function(){return function(){function e(e,t){var n=r?0:-8*(t-1),i=0,a;for(a=0;t>a;a++)i|=o.charCodeAt(e+a)<<Math.abs(n+8*a);return i}function n(e,t,n){n=3===arguments.length?n:o.length-t-1,o=o.substr(0,t)+e+o.substr(n+t)}function i(e,t,i){var o="",a=r?0:-8*(i-1),s;for(s=0;i>s;s++)o+=String.fromCharCode(t>>Math.abs(a+8*s)&255);n(o,e,i)}var r=!1,o;return{II:function(e){return e===t?r:void(r=e)},init:function(e){r=!1,o=e},SEGMENT:function(e,t,i){switch(arguments.length){case 1:return o.substr(e,o.length-e-1);case 2:return o.substr(e,t);case 3:n(i,e,t);break;default:return o}},BYTE:function(t){return e(t,1)},SHORT:function(t){return e(t,2)},LONG:function(n,r){return r===t?e(n,4):void i(n,r,4)},SLONG:function(t){var n=e(t,4);return n>2147483647?n-4294967296:n},STRING:function(t,n){var i="";for(n+=t;n>t;t++)i+=String.fromCharCode(e(t,1));return i}}}}),i(k,[P],function(e){return function t(n){var i=[],r,o,a,s=0;if(r=new e,r.init(n),65496===r.SHORT(0)){for(o=2;o<=n.length;)if(a=r.SHORT(o),a>=65488&&65495>=a)o+=2;else{if(65498===a||65497===a)break;s=r.SHORT(o+2)+2,a>=65505&&65519>=a&&i.push({hex:a,name:"APP"+(15&a),start:o,length:s,segment:r.SEGMENT(o,s)}),o+=s}return r.init(null),{headers:i,restore:function(e){var t,n;for(r.init(e),o=65504==r.SHORT(2)?4+r.SHORT(4):2,n=0,t=i.length;t>n;n++)r.SEGMENT(o,0,i[n].segment),o+=i[n].length;return e=r.SEGMENT(),r.init(null),e},strip:function(e){var n,i,o;for(i=new t(e),n=i.headers,i.purge(),r.init(e),o=n.length;o--;)r.SEGMENT(n[o].start,n[o].length,"");return e=r.SEGMENT(),r.init(null),e},get:function(e){for(var t=[],n=0,r=i.length;r>n;n++)i[n].name===e.toUpperCase()&&t.push(i[n].segment);return t},set:function(e,t){var n=[],r,o,a;for("string"==typeof t?n.push(t):n=t,r=o=0,a=i.length;a>r&&(i[r].name===e.toUpperCase()&&(i[r].segment=n[o],i[r].length=n[o].length,o++),!(o>=n.length));r++);},purge:function(){i=[],r.init(null),r=null}}}}}),i(U,[u,P],function(e,n){return function i(){function i(e,n){var i=a.SHORT(e),r,o,s,u,d,f,h,p,m=[],g={};for(r=0;i>r;r++)if(h=f=e+12*r+2,s=n[a.SHORT(h)],s!==t){switch(u=a.SHORT(h+=2),d=a.LONG(h+=2),h+=4,m=[],u){case 1:case 7:for(d>4&&(h=a.LONG(h)+c.tiffHeader),o=0;d>o;o++)m[o]=a.BYTE(h+o);break;case 2:d>4&&(h=a.LONG(h)+c.tiffHeader),g[s]=a.STRING(h,d-1);continue;case 3:for(d>2&&(h=a.LONG(h)+c.tiffHeader),o=0;d>o;o++)m[o]=a.SHORT(h+2*o);break;case 4:for(d>1&&(h=a.LONG(h)+c.tiffHeader),o=0;d>o;o++)m[o]=a.LONG(h+4*o);break;case 5:for(h=a.LONG(h)+c.tiffHeader,o=0;d>o;o++)m[o]=a.LONG(h+4*o)/a.LONG(h+4*o+4);break;case 9:for(h=a.LONG(h)+c.tiffHeader,o=0;d>o;o++)m[o]=a.SLONG(h+4*o);break;case 10:for(h=a.LONG(h)+c.tiffHeader,o=0;d>o;o++)m[o]=a.SLONG(h+4*o)/a.SLONG(h+4*o+4);break;default:continue}p=1==d?m[0]:m,g[s]=l.hasOwnProperty(s)&&"object"!=typeof p?l[s][p]:p}return g}function r(){var e=c.tiffHeader;return a.II(18761==a.SHORT(e)),42!==a.SHORT(e+=2)?!1:(c.IFD0=c.tiffHeader+a.LONG(e+=2),u=i(c.IFD0,s.tiff),"ExifIFDPointer"in u&&(c.exifIFD=c.tiffHeader+u.ExifIFDPointer,delete u.ExifIFDPointer),"GPSInfoIFDPointer"in u&&(c.gpsIFD=c.tiffHeader+u.GPSInfoIFDPointer,delete u.GPSInfoIFDPointer),!0)}function o(e,t,n){var i,r,o,u=0;if("string"==typeof t){var l=s[e.toLowerCase()];for(var d in l)if(l[d]===t){t=d;break}}i=c[e.toLowerCase()+"IFD"],r=a.SHORT(i);for(var f=0;r>f;f++)if(o=i+12*f+2,a.SHORT(o)==t){u=o+8;break}return u?(a.LONG(u,n),!0):!1}var a,s,u,c={},l;return a=new n,s={tiff:{274:"Orientation",270:"ImageDescription",271:"Make",272:"Model",305:"Software",34665:"ExifIFDPointer",34853:"GPSInfoIFDPointer"},exif:{36864:"ExifVersion",40961:"ColorSpace",40962:"PixelXDimension",40963:"PixelYDimension",36867:"DateTimeOriginal",33434:"ExposureTime",33437:"FNumber",34855:"ISOSpeedRatings",37377:"ShutterSpeedValue",37378:"ApertureValue",37383:"MeteringMode",37384:"LightSource",37385:"Flash",37386:"FocalLength",41986:"ExposureMode",41987:"WhiteBalance",41990:"SceneCaptureType",41988:"DigitalZoomRatio",41992:"Contrast",41993:"Saturation",41994:"Sharpness"},gps:{0:"GPSVersionID",1:"GPSLatitudeRef",2:"GPSLatitude",3:"GPSLongitudeRef",4:"GPSLongitude"}},l={ColorSpace:{1:"sRGB",0:"Uncalibrated"},MeteringMode:{0:"Unknown",1:"Average",2:"CenterWeightedAverage",3:"Spot",4:"MultiSpot",5:"Pattern",6:"Partial",255:"Other"},LightSource:{1:"Daylight",2:"Fliorescent",3:"Tungsten",4:"Flash",9:"Fine weather",10:"Cloudy weather",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"}},{init:function(e){return c={tiffHeader:10},e!==t&&e.length?(a.init(e),65505===a.SHORT(0)&&"EXIF\x00"===a.STRING(4,5).toUpperCase()?r():!1):!1
+},TIFF:function(){return u},EXIF:function(){var t;if(t=i(c.exifIFD,s.exif),t.ExifVersion&&"array"===e.typeOf(t.ExifVersion)){for(var n=0,r="";n<t.ExifVersion.length;n++)r+=String.fromCharCode(t.ExifVersion[n]);t.ExifVersion=r}return t},GPS:function(){var t;return t=i(c.gpsIFD,s.gps),t.GPSVersionID&&"array"===e.typeOf(t.GPSVersionID)&&(t.GPSVersionID=t.GPSVersionID.join(".")),t},setExif:function(e,t){return"PixelXDimension"!==e&&"PixelYDimension"!==e?!1:o("exif",e,t)},getBinary:function(){return a.SEGMENT()},purge:function(){a.init(null),a=u=null,c={}}}}}),i(B,[u,h,k,P,U],function(e,t,n,i,r){function o(o){function a(){for(var e=0,t,n;e<=u.length;){if(t=c.SHORT(e+=2),t>=65472&&65475>=t)return e+=5,{height:c.SHORT(e),width:c.SHORT(e+=2)};n=c.SHORT(e+=2),e+=n-2}return null}function s(){d&&l&&c&&(d.purge(),l.purge(),c.init(null),u=f=l=d=c=null)}var u,c,l,d,f,h;if(u=o,c=new i,c.init(u),65496!==c.SHORT(0))throw new t.ImageError(t.ImageError.WRONG_FORMAT);l=new n(o),d=new r,h=!!d.init(l.get("app1")[0]),f=a.call(this),e.extend(this,{type:"image/jpeg",size:u.length,width:f&&f.width||0,height:f&&f.height||0,setExif:function(t,n){return h?("object"===e.typeOf(t)?e.each(t,function(e,t){d.setExif(t,e)}):d.setExif(t,n),void l.set("app1",d.getBinary())):!1},writeHeaders:function(){return arguments.length?l.restore(arguments[0]):u=l.restore(u)},stripHeaders:function(e){return l.strip(e)},purge:function(){s.call(this)}}),h&&(this.meta={tiff:d.TIFF(),exif:d.EXIF(),gps:d.GPS()})}return o}),i(z,[h,u,P],function(e,t,n){function i(i){function r(){var e,t;return e=a.call(this,8),"IHDR"==e.type?(t=e.start,{width:u.LONG(t),height:u.LONG(t+=4)}):null}function o(){u&&(u.init(null),s=d=c=l=u=null)}function a(e){var t,n,i,r;return t=u.LONG(e),n=u.STRING(e+=4,4),i=e+=4,r=u.LONG(e+t),{length:t,type:n,start:i,CRC:r}}var s,u,c,l,d;s=i,u=new n,u.init(s),function(){var t=0,n=0,i=[35152,20039,3338,6666];for(n=0;n<i.length;n++,t+=2)if(i[n]!=u.SHORT(t))throw new e.ImageError(e.ImageError.WRONG_FORMAT)}(),d=r.call(this),t.extend(this,{type:"image/png",size:s.length,width:d.width,height:d.height,purge:function(){o.call(this)}}),o.call(this)}return i}),i(G,[u,h,B,z],function(e,t,n,i){return function(r){var o=[n,i],a;a=function(){for(var e=0;e<o.length;e++)try{return new o[e](r)}catch(n){}throw new t.ImageError(t.ImageError.WRONG_FORMAT)}(),e.extend(this,{type:"",size:0,width:0,height:0,setExif:function(){},writeHeaders:function(e){return e},stripHeaders:function(e){return e},purge:function(){}}),e.extend(this,a),this.purge=function(){a.purge(),a=null}}}),i(q,[],function(){function e(e,i,r){var o=e.naturalWidth,a=e.naturalHeight,s=r.width,u=r.height,c=r.x||0,l=r.y||0,d=i.getContext("2d");t(e)&&(o/=2,a/=2);var f=1024,h=document.createElement("canvas");h.width=h.height=f;for(var p=h.getContext("2d"),m=n(e,o,a),g=0;a>g;){for(var v=g+f>a?a-g:f,y=0;o>y;){var w=y+f>o?o-y:f;p.clearRect(0,0,f,f),p.drawImage(e,-y,-g);var E=y*s/o+c<<0,_=Math.ceil(w*s/o),x=g*u/a/m+l<<0,b=Math.ceil(v*u/a/m);d.drawImage(h,0,0,w,v,E,x,_,b),y+=f}g+=f}h=p=null}function t(e){var t=e.naturalWidth,n=e.naturalHeight;if(t*n>1048576){var i=document.createElement("canvas");i.width=i.height=1;var r=i.getContext("2d");return r.drawImage(e,-t+1,0),0===r.getImageData(0,0,1,1).data[3]}return!1}function n(e,t,n){var i=document.createElement("canvas");i.width=1,i.height=n;var r=i.getContext("2d");r.drawImage(e,0,0);for(var o=r.getImageData(0,0,1,n).data,a=0,s=n,u=n;u>a;){var c=o[4*(u-1)+3];0===c?s=u:a=u,u=s+a>>1}i=null;var l=u/n;return 0===l?1:l}return{isSubsampled:t,renderTo:e}}),i(X,[D,u,h,m,w,G,q,l,d],function(e,t,n,i,r,o,a,s,u){function c(){function e(){if(!E&&!y)throw new n.ImageError(n.DOMException.INVALID_STATE_ERR);return E||y}function c(e){return i.atob(e.substring(e.indexOf("base64,")+7))}function l(e,t){return"data:"+(t||"")+";base64,"+i.btoa(e)}function d(e){var t=this;y=new Image,y.onerror=function(){g.call(this),t.trigger("error",n.ImageError.WRONG_FORMAT)},y.onload=function(){t.trigger("load")},y.src=/^data:[^;]*;base64,/.test(e)?e:l(e,x.type)}function f(e,t){var i=this,r;return window.FileReader?(r=new FileReader,r.onload=function(){t(this.result)},r.onerror=function(){i.trigger("error",n.ImageError.WRONG_FORMAT)},r.readAsDataURL(e),void 0):t(e.getAsDataURL())}function h(n,i,r,o){var a=this,s,u,c=0,l=0,d,f,h,g;if(R=o,g=this.meta&&this.meta.tiff&&this.meta.tiff.Orientation||1,-1!==t.inArray(g,[5,6,7,8])){var v=n;n=i,i=v}return d=e(),r?(n=Math.min(n,d.width),i=Math.min(i,d.height),s=Math.max(n/d.width,i/d.height)):s=Math.min(n/d.width,i/d.height),s>1&&!r&&o?void this.trigger("Resize"):(E||(E=document.createElement("canvas")),f=Math.round(d.width*s),h=Math.round(d.height*s),r?(E.width=n,E.height=i,f>n&&(c=Math.round((f-n)/2)),h>i&&(l=Math.round((h-i)/2))):(E.width=f,E.height=h),R||m(E.width,E.height,g),p.call(this,d,E,-c,-l,f,h),this.width=E.width,this.height=E.height,b=!0,void a.trigger("Resize"))}function p(e,t,n,i,r,o){if("iOS"===u.OS)a.renderTo(e,t,{width:r,height:o,x:n,y:i});else{var s=t.getContext("2d");s.drawImage(e,n,i,r,o)}}function m(e,t,n){switch(n){case 5:case 6:case 7:case 8:E.width=t,E.height=e;break;default:E.width=e,E.height=t}var i=E.getContext("2d");switch(n){case 2:i.translate(e,0),i.scale(-1,1);break;case 3:i.translate(e,t),i.rotate(Math.PI);break;case 4:i.translate(0,t),i.scale(1,-1);break;case 5:i.rotate(.5*Math.PI),i.scale(1,-1);break;case 6:i.rotate(.5*Math.PI),i.translate(0,-t);break;case 7:i.rotate(.5*Math.PI),i.translate(e,-t),i.scale(-1,1);break;case 8:i.rotate(-.5*Math.PI),i.translate(-e,0)}}function g(){w&&(w.purge(),w=null),_=y=E=x=null,b=!1}var v=this,y,w,E,_,x,b=!1,R=!0;t.extend(this,{loadFromBlob:function(e){var t=this,i=t.getRuntime(),r=arguments.length>1?arguments[1]:!0;if(!i.can("access_binary"))throw new n.RuntimeError(n.RuntimeError.NOT_SUPPORTED_ERR);return x=e,e.isDetached()?(_=e.getSource(),void d.call(this,_)):void f.call(this,e.getSource(),function(e){r&&(_=c(e)),d.call(t,e)})},loadFromImage:function(e,t){this.meta=e.meta,x=new r(null,{name:e.name,size:e.size,type:e.type}),d.call(this,t?_=e.getAsBinaryString():e.getAsDataURL())},getInfo:function(){var t=this.getRuntime(),n;return!w&&_&&t.can("access_image_binary")&&(w=new o(_)),n={width:e().width||0,height:e().height||0,type:x.type||s.getFileMime(x.name),size:_&&_.length||x.size||0,name:x.name||"",meta:w&&w.meta||this.meta||{}}},downsize:function(){h.apply(this,arguments)},getAsCanvas:function(){return E&&(E.id=this.uid+"_canvas"),E},getAsBlob:function(e,t){return e!==this.type&&h.call(this,this.width,this.height,!1),new r(null,{name:x.name||"",type:e,data:v.getAsBinaryString.call(this,e,t)})},getAsDataURL:function(e){var t=arguments[1]||90;if(!b)return y.src;if("image/jpeg"!==e)return E.toDataURL("image/png");try{return E.toDataURL("image/jpeg",t/100)}catch(n){return E.toDataURL("image/jpeg")}},getAsBinaryString:function(e,t){if(!b)return _||(_=c(v.getAsDataURL(e,t))),_;if("image/jpeg"!==e)_=c(v.getAsDataURL(e,t));else{var n;t||(t=90);try{n=E.toDataURL("image/jpeg",t/100)}catch(i){n=E.toDataURL("image/jpeg")}_=c(n),w&&(_=w.stripHeaders(_),R&&(w.meta&&w.meta.exif&&w.setExif({PixelXDimension:this.width,PixelYDimension:this.height}),_=w.writeHeaders(_)),w.purge(),w=null)}return b=!1,_},destroy:function(){v=null,g.call(this),this.getRuntime().getShim().removeInstance(this.uid)}})}return e.Image=c}),i(j,[u,d,f,h,g],function(e,t,n,i,r){function o(){var e;try{e=navigator.plugins["Shockwave Flash"],e=e.description}catch(t){try{e=new ActiveXObject("ShockwaveFlash.ShockwaveFlash").GetVariable("$version")}catch(n){e="0.0"}}return e=e.match(/\d+/g),parseFloat(e[0]+"."+e[1])}function a(a){var c=this,l;a=e.extend({swf_url:t.swf_url},a),r.call(this,a,s,{access_binary:function(e){return e&&"browser"===c.mode},access_image_binary:function(e){return e&&"browser"===c.mode},display_media:r.capTrue,do_cors:r.capTrue,drag_and_drop:!1,report_upload_progress:function(){return"client"===c.mode},resize_image:r.capTrue,return_response_headers:!1,return_response_type:function(t){return"json"===t&&window.JSON?!0:!e.arrayDiff(t,["","text","document"])||"browser"===c.mode},return_status_code:function(t){return"browser"===c.mode||!e.arrayDiff(t,[200,404])},select_file:r.capTrue,select_multiple:r.capTrue,send_binary_string:function(e){return e&&"browser"===c.mode},send_browser_cookies:function(e){return e&&"browser"===c.mode},send_custom_headers:function(e){return e&&"browser"===c.mode},send_multipart:r.capTrue,slice_blob:function(e){return e&&"browser"===c.mode},stream_upload:function(e){return e&&"browser"===c.mode},summon_file_dialog:!1,upload_filesize:function(t){return e.parseSizeStr(t)<=2097152||"client"===c.mode},use_http_method:function(t){return!e.arrayDiff(t,["GET","POST"])}},{access_binary:function(e){return e?"browser":"client"},access_image_binary:function(e){return e?"browser":"client"},report_upload_progress:function(e){return e?"browser":"client"},return_response_type:function(t){return e.arrayDiff(t,["","text","json","document"])?"browser":["client","browser"]},return_status_code:function(t){return e.arrayDiff(t,[200,404])?"browser":["client","browser"]},send_binary_string:function(e){return e?"browser":"client"},send_browser_cookies:function(e){return e?"browser":"client"},send_custom_headers:function(e){return e?"browser":"client"},stream_upload:function(e){return e?"client":"browser"},upload_filesize:function(t){return e.parseSizeStr(t)>=2097152?"client":"browser"}},"client"),o()<10&&(this.mode=!1),e.extend(this,{getShim:function(){return n.get(this.uid)},shimExec:function(e,t){var n=[].slice.call(arguments,2);return c.getShim().exec(this.uid,e,t,n)},init:function(){var n,r,o;o=this.getShimContainer(),e.extend(o.style,{position:"absolute",top:"-8px",left:"-8px",width:"9px",height:"9px",overflow:"hidden"}),n='<object id="'+this.uid+'" type="application/x-shockwave-flash" data="'+a.swf_url+'" ',"IE"===t.browser&&(n+='classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" '),n+='width="100%" height="100%" style="outline:0"><param name="movie" value="'+a.swf_url+'" /><param name="flashvars" value="uid='+escape(this.uid)+"&target="+t.global_event_dispatcher+'" /><param name="wmode" value="transparent" /><param name="allowscriptaccess" value="always" /></object>',"IE"===t.browser?(r=document.createElement("div"),o.appendChild(r),r.outerHTML=n,r=o=null):o.innerHTML=n,l=setTimeout(function(){c&&!c.initialized&&c.trigger("Error",new i.RuntimeError(i.RuntimeError.NOT_INIT_ERR))},5e3)},destroy:function(e){return function(){e.call(c),clearTimeout(l),a=l=e=c=null}}(this.destroy)},u)}var s="flash",u={};return r.addConstructor(s,a),u}),i(V,[j,y],function(e,t){var n={slice:function(e,n,i,r){var o=this.getRuntime();return 0>n?n=Math.max(e.size+n,0):n>0&&(n=Math.min(n,e.size)),0>i?i=Math.max(e.size+i,0):i>0&&(i=Math.min(i,e.size)),e=o.shimExec.call(this,"Blob","slice",n,i,r||""),e&&(e=new t(o.uid,e)),e}};return e.Blob=n}),i(W,[j],function(e){var t={init:function(e){this.getRuntime().shimExec.call(this,"FileInput","init",{name:e.name,accept:e.accept,multiple:e.multiple}),this.trigger("ready")}};return e.FileInput=t}),i(Y,[j,m],function(e,t){function n(e,n){switch(n){case"readAsText":return t.atob(e,"utf8");case"readAsBinaryString":return t.atob(e);case"readAsDataURL":return e}return null}var i="",r={read:function(e,t){var r=this,o=r.getRuntime();return"readAsDataURL"===e&&(i="data:"+(t.type||"")+";base64,"),r.bind("Progress",function(t,r){r&&(i+=n(r,e))}),o.shimExec.call(this,"FileReader","readAsBase64",t.uid)},getResult:function(){return i},destroy:function(){i=null}};return e.FileReader=r}),i($,[j,m],function(e,t){function n(e,n){switch(n){case"readAsText":return t.atob(e,"utf8");case"readAsBinaryString":return t.atob(e);case"readAsDataURL":return e}return null}var i={read:function(e,t){var i,r=this.getRuntime();return(i=r.shimExec.call(this,"FileReaderSync","readAsBase64",t.uid))?("readAsDataURL"===e&&(i="data:"+(t.type||"")+";base64,"+i),n(i,e,t.type)):null}};return e.FileReaderSync=i}),i(J,[j,u,y,w,T,A,O],function(e,t,n,i,r,o,a){var s={send:function(e,i){function r(){e.transport=l.mode,l.shimExec.call(c,"XMLHttpRequest","send",e,i)}function s(e,t){l.shimExec.call(c,"XMLHttpRequest","appendBlob",e,t.uid),i=null,r()}function u(e,t){var n=new a;n.bind("TransportingComplete",function(){t(this.result)}),n.transport(e.getSource(),e.type,{ruid:l.uid})}var c=this,l=c.getRuntime();if(t.isEmptyObj(e.headers)||t.each(e.headers,function(e,t){l.shimExec.call(c,"XMLHttpRequest","setRequestHeader",t,e.toString())}),i instanceof o){var d;if(i.each(function(e,t){e instanceof n?d=t:l.shimExec.call(c,"XMLHttpRequest","append",t,e)}),i.hasBlob()){var f=i.getBlob();f.isDetached()?u(f,function(e){f.destroy(),s(d,e)}):s(d,f)}else i=null,r()}else i instanceof n?i.isDetached()?u(i,function(e){i.destroy(),i=e.uid,r()}):(i=i.uid,r()):r()},getResponse:function(e){var n,o,a=this.getRuntime();if(o=a.shimExec.call(this,"XMLHttpRequest","getResponseAsBlob")){if(o=new i(a.uid,o),"blob"===e)return o;try{if(n=new r,~t.inArray(e,["","text"]))return n.readAsText(o);if("json"===e&&window.JSON)return JSON.parse(n.readAsText(o))}finally{o.destroy()}}return null},abort:function(e){var t=this.getRuntime();t.shimExec.call(this,"XMLHttpRequest","abort"),this.dispatchEvent("readystatechange"),this.dispatchEvent("abort")}};return e.XMLHttpRequest=s}),i(Z,[j,y],function(e,t){var n={getAsBlob:function(e){var n=this.getRuntime(),i=n.shimExec.call(this,"Transporter","getAsBlob",e);return i?new t(n.uid,i):null}};return e.Transporter=n}),i(K,[j,u,O,y,T],function(e,t,n,i,r){var o={loadFromBlob:function(e){function t(e){r.shimExec.call(i,"Image","loadFromBlob",e.uid),i=r=null}var i=this,r=i.getRuntime();if(e.isDetached()){var o=new n;o.bind("TransportingComplete",function(){t(o.result.getSource())}),o.transport(e.getSource(),e.type,{ruid:r.uid})}else t(e.getSource())},loadFromImage:function(e){var t=this.getRuntime();return t.shimExec.call(this,"Image","loadFromImage",e.uid)},getAsBlob:function(e,t){var n=this.getRuntime(),r=n.shimExec.call(this,"Image","getAsBlob",e,t);return r?new i(n.uid,r):null},getAsDataURL:function(){var e=this.getRuntime(),t=e.Image.getAsBlob.apply(this,arguments),n;return t?(n=new r,n.readAsDataURL(t)):null}};return e.Image=o}),i(Q,[u,d,f,h,g],function(e,t,n,i,r){function o(e){var t=!1,n=null,i,r,o,a,s,u=0;try{try{n=new ActiveXObject("AgControl.AgControl"),n.IsVersionSupported(e)&&(t=!0),n=null}catch(c){var l=navigator.plugins["Silverlight Plug-In"];if(l){for(i=l.description,"1.0.30226.2"===i&&(i="2.0.30226.2"),r=i.split(".");r.length>3;)r.pop();for(;r.length<4;)r.push(0);for(o=e.split(".");o.length>4;)o.pop();do a=parseInt(o[u],10),s=parseInt(r[u],10),u++;while(u<o.length&&a===s);s>=a&&!isNaN(a)&&(t=!0)}}}catch(d){t=!1}return t}function a(a){var c=this,l;a=e.extend({xap_url:t.xap_url},a),r.call(this,a,s,{access_binary:r.capTrue,access_image_binary:r.capTrue,display_media:r.capTrue,do_cors:r.capTrue,drag_and_drop:!1,report_upload_progress:r.capTrue,resize_image:r.capTrue,return_response_headers:function(e){return e&&"client"===c.mode},return_response_type:function(e){return"json"!==e?!0:!!window.JSON},return_status_code:function(t){return"client"===c.mode||!e.arrayDiff(t,[200,404])},select_file:r.capTrue,select_multiple:r.capTrue,send_binary_string:r.capTrue,send_browser_cookies:function(e){return e&&"browser"===c.mode},send_custom_headers:function(e){return e&&"client"===c.mode},send_multipart:r.capTrue,slice_blob:r.capTrue,stream_upload:!0,summon_file_dialog:!1,upload_filesize:r.capTrue,use_http_method:function(t){return"client"===c.mode||!e.arrayDiff(t,["GET","POST"])}},{return_response_headers:function(e){return e?"client":"browser"},return_status_code:function(t){return e.arrayDiff(t,[200,404])?"client":["client","browser"]},send_browser_cookies:function(e){return e?"browser":"client"},send_custom_headers:function(e){return e?"client":"browser"},use_http_method:function(t){return e.arrayDiff(t,["GET","POST"])?"client":["client","browser"]}}),o("2.0.31005.0")&&"Opera"!==t.browser||(this.mode=!1),e.extend(this,{getShim:function(){return n.get(this.uid).content.Moxie},shimExec:function(e,t){var n=[].slice.call(arguments,2);return c.getShim().exec(this.uid,e,t,n)},init:function(){var e;e=this.getShimContainer(),e.innerHTML='<object id="'+this.uid+'" data="data:application/x-silverlight," type="application/x-silverlight-2" width="100%" height="100%" style="outline:none;"><param name="source" value="'+a.xap_url+'"/><param name="background" value="Transparent"/><param name="windowless" value="true"/><param name="enablehtmlaccess" value="true"/><param name="initParams" value="uid='+this.uid+",target="+t.global_event_dispatcher+'"/></object>',l=setTimeout(function(){c&&!c.initialized&&c.trigger("Error",new i.RuntimeError(i.RuntimeError.NOT_INIT_ERR))},"Windows"!==t.OS?1e4:5e3)},destroy:function(e){return function(){e.call(c),clearTimeout(l),a=l=e=c=null}}(this.destroy)},u)}var s="silverlight",u={};return r.addConstructor(s,a),u}),i(et,[Q,u,V],function(e,t,n){return e.Blob=t.extend({},n)}),i(tt,[Q],function(e){var t={init:function(e){function t(e){for(var t="",n=0;n<e.length;n++)t+=(""!==t?"|":"")+e[n].title+" | *."+e[n].extensions.replace(/,/g,";*.");return t}this.getRuntime().shimExec.call(this,"FileInput","init",t(e.accept),e.name,e.multiple),this.trigger("ready")}};return e.FileInput=t}),i(nt,[Q,f,L],function(e,t,n){var i={init:function(){var e=this,i=e.getRuntime(),r;return r=i.getShimContainer(),n.addEvent(r,"dragover",function(e){e.preventDefault(),e.stopPropagation(),e.dataTransfer.dropEffect="copy"},e.uid),n.addEvent(r,"dragenter",function(e){e.preventDefault();var n=t.get(i.uid).dragEnter(e);n&&e.stopPropagation()},e.uid),n.addEvent(r,"drop",function(e){e.preventDefault();var n=t.get(i.uid).dragDrop(e);n&&e.stopPropagation()},e.uid),i.shimExec.call(this,"FileDrop","init")}};return e.FileDrop=i}),i(it,[Q,u,Y],function(e,t,n){return e.FileReader=t.extend({},n)}),i(rt,[Q,u,$],function(e,t,n){return e.FileReaderSync=t.extend({},n)}),i(ot,[Q,u,J],function(e,t,n){return e.XMLHttpRequest=t.extend({},n)}),i(at,[Q,u,Z],function(e,t,n){return e.Transporter=t.extend({},n)}),i(st,[Q,u,K],function(e,t,n){return e.Image=t.extend({},n,{getInfo:function(){var e=this.getRuntime(),n=["tiff","exif","gps"],i={meta:{}},r=e.shimExec.call(this,"Image","getInfo");return r.meta&&t.each(n,function(e){var t=r.meta[e],n,o,a,s;if(t&&t.keys)for(i.meta[e]={},o=0,a=t.keys.length;a>o;o++)n=t.keys[o],s=t[n],s&&(/^(\d|[1-9]\d+)$/.test(s)?s=parseInt(s,10):/^\d*\.\d+$/.test(s)&&(s=parseFloat(s)),i.meta[e][n]=s)}),i.width=parseInt(r.width,10),i.height=parseInt(r.height,10),i.size=parseInt(r.size,10),i.type=r.type,i.name=r.name,i}})}),i(ut,[u,h,g,d],function(e,t,n,i){function r(t){var r=this,s=n.capTest,u=n.capTrue;n.call(this,t,o,{access_binary:s(window.FileReader||window.File&&File.getAsDataURL),access_image_binary:!1,display_media:s(a.Image&&(i.can("create_canvas")||i.can("use_data_uri_over32kb"))),do_cors:!1,drag_and_drop:!1,filter_by_extension:s(function(){return"Chrome"===i.browser&&i.version>=28||"IE"===i.browser&&i.version>=10}()),resize_image:function(){return a.Image&&r.can("access_binary")&&i.can("create_canvas")},report_upload_progress:!1,return_response_headers:!1,return_response_type:function(t){return"json"===t&&window.JSON?!0:!!~e.inArray(t,["text","document",""])},return_status_code:function(t){return!e.arrayDiff(t,[200,404])},select_file:function(){return i.can("use_fileinput")},select_multiple:!1,send_binary_string:!1,send_custom_headers:!1,send_multipart:!0,slice_blob:!1,stream_upload:function(){return r.can("select_file")},summon_file_dialog:s(function(){return"Firefox"===i.browser&&i.version>=4||"Opera"===i.browser&&i.version>=12||!!~e.inArray(i.browser,["Chrome","Safari"])}()),upload_filesize:u,use_http_method:function(t){return!e.arrayDiff(t,["GET","POST"])}}),e.extend(this,{init:function(){this.trigger("Init")},destroy:function(e){return function(){e.call(r),e=r=null}}(this.destroy)}),e.extend(this.getShim(),a)}var o="html4",a={};return n.addConstructor(o,r),a}),i(ct,[ut,u,f,L,l,d],function(e,t,n,i,r,o){function a(){function e(){var r=this,l=r.getRuntime(),d,f,h,p,m,g;g=t.guid("uid_"),d=l.getShimContainer(),a&&(h=n.get(a+"_form"),h&&t.extend(h.style,{top:"100%"})),p=document.createElement("form"),p.setAttribute("id",g+"_form"),p.setAttribute("method","post"),p.setAttribute("enctype","multipart/form-data"),p.setAttribute("encoding","multipart/form-data"),t.extend(p.style,{overflow:"hidden",position:"absolute",top:0,left:0,width:"100%",height:"100%"}),m=document.createElement("input"),m.setAttribute("id",g),m.setAttribute("type","file"),m.setAttribute("name",c.name||"Filedata"),m.setAttribute("accept",u.join(",")),t.extend(m.style,{fontSize:"999px",opacity:0}),p.appendChild(m),d.appendChild(p),t.extend(m.style,{position:"absolute",top:0,left:0,width:"100%",height:"100%"}),"IE"===o.browser&&o.version<10&&t.extend(m.style,{filter:"progid:DXImageTransform.Microsoft.Alpha(opacity=0)"}),m.onchange=function(){var t;this.value&&(t=this.files?this.files[0]:{name:this.value},s=[t],this.onchange=function(){},e.call(r),r.bind("change",function i(){var e=n.get(g),t=n.get(g+"_form"),o;r.unbind("change",i),r.files.length&&e&&t&&(o=r.files[0],e.setAttribute("id",o.uid),t.setAttribute("id",o.uid+"_form"),t.setAttribute("target",o.uid+"_iframe")),e=t=null},998),m=p=null,r.trigger("change"))},l.can("summon_file_dialog")&&(f=n.get(c.browse_button),i.removeEvent(f,"click",r.uid),i.addEvent(f,"click",function(e){m&&!m.disabled&&m.click(),e.preventDefault()},r.uid)),a=g,d=h=f=null}var a,s=[],u=[],c;t.extend(this,{init:function(t){var o=this,a=o.getRuntime(),s;c=t,u=t.accept.mimes||r.extList2mimes(t.accept,a.can("filter_by_extension")),s=a.getShimContainer(),function(){var e,r,u;e=n.get(t.browse_button),a.can("summon_file_dialog")&&("static"===n.getStyle(e,"position")&&(e.style.position="relative"),r=parseInt(n.getStyle(e,"z-index"),10)||1,e.style.zIndex=r,s.style.zIndex=r-1),u=a.can("summon_file_dialog")?e:s,i.addEvent(u,"mouseover",function(){o.trigger("mouseenter")},o.uid),i.addEvent(u,"mouseout",function(){o.trigger("mouseleave")},o.uid),i.addEvent(u,"mousedown",function(){o.trigger("mousedown")},o.uid),i.addEvent(n.get(t.container),"mouseup",function(){o.trigger("mouseup")},o.uid),e=null}(),e.call(this),s=null,o.trigger({type:"ready",async:!0})},getFiles:function(){return s},disable:function(e){var t;(t=n.get(a))&&(t.disabled=!!e)},destroy:function(){var e=this.getRuntime(),t=e.getShim(),r=e.getShimContainer();i.removeAllEvents(r,this.uid),i.removeAllEvents(c&&n.get(c.container),this.uid),i.removeAllEvents(c&&n.get(c.browse_button),this.uid),r&&(r.innerHTML=""),t.removeInstance(this.uid),a=s=u=c=r=t=null}})}return e.FileInput=a}),i(lt,[ut,F],function(e,t){return e.FileReader=t}),i(dt,[ut,u,f,R,h,L,y,A],function(e,t,n,i,r,o,a,s){function u(){function e(e){var t=this,i,r,a,s,u=!1;if(l){if(i=l.id.replace(/_iframe$/,""),r=n.get(i+"_form")){for(a=r.getElementsByTagName("input"),s=a.length;s--;)switch(a[s].getAttribute("type")){case"hidden":a[s].parentNode.removeChild(a[s]);break;case"file":u=!0}a=[],u||r.parentNode.removeChild(r),r=null}setTimeout(function(){o.removeEvent(l,"load",t.uid),l.parentNode&&l.parentNode.removeChild(l);var n=t.getRuntime().getShimContainer();n.children.length||n.parentNode.removeChild(n),n=l=null,e()},1)}}var u,c,l;t.extend(this,{send:function(d,f){function h(){var n=m.getShimContainer()||document.body,r=document.createElement("div");r.innerHTML='<iframe id="'+g+'_iframe" name="'+g+'_iframe" src="javascript:&quot;&quot;" style="display:none"></iframe>',l=r.firstChild,n.appendChild(l),o.addEvent(l,"load",function(){var n;try{n=l.contentWindow.document||l.contentDocument||window.frames[l.id].document,/^4(0[0-9]|1[0-7]|2[2346])\s/.test(n.title)?u=n.title.replace(/^(\d+).*$/,"$1"):(u=200,c=t.trim(n.body.innerHTML),p.trigger({type:"progress",loaded:c.length,total:c.length}),w&&p.trigger({type:"uploadprogress",loaded:w.size||1025,total:w.size||1025}))}catch(r){if(!i.hasSameOrigin(d.url))return void e.call(p,function(){p.trigger("error")});u=404}e.call(p,function(){p.trigger("load")})},p.uid)}var p=this,m=p.getRuntime(),g,v,y,w;if(u=c=null,f instanceof s&&f.hasBlob()){if(w=f.getBlob(),g=w.uid,y=n.get(g),v=n.get(g+"_form"),!v)throw new r.DOMException(r.DOMException.NOT_FOUND_ERR)}else g=t.guid("uid_"),v=document.createElement("form"),v.setAttribute("id",g+"_form"),v.setAttribute("method",d.method),v.setAttribute("enctype","multipart/form-data"),v.setAttribute("encoding","multipart/form-data"),v.setAttribute("target",g+"_iframe"),m.getShimContainer().appendChild(v);f instanceof s&&f.each(function(e,n){if(e instanceof a)y&&y.setAttribute("name",n);else{var i=document.createElement("input");t.extend(i,{type:"hidden",name:n,value:e}),y?v.insertBefore(i,y):v.appendChild(i)}}),v.setAttribute("action",d.url),h(),v.submit(),p.trigger("loadstart")},getStatus:function(){return u},getResponse:function(e){if("json"===e&&"string"===t.typeOf(c)&&window.JSON)try{return JSON.parse(c.replace(/^\s*<pre[^>]*>/,"").replace(/<\/pre>\s*$/,""))}catch(n){return null}return c},abort:function(){var t=this;l&&l.contentWindow&&(l.contentWindow.stop?l.contentWindow.stop():l.contentWindow.document.execCommand?l.contentWindow.document.execCommand("Stop"):l.src="about:blank"),e.call(this,function(){t.dispatchEvent("abort")})}})}return e.XMLHttpRequest=u}),i(ft,[ut,X],function(e,t){return e.Image=t}),a([u,c,l,d,f,h,p,m,g,v,y,w,E,_,x,b,R,T,A,S,O,I,L])}(this);;(function(e){"use strict";var t={},n=e.moxie.core.utils.Basic.inArray;return function r(e){var i,s;for(i in e)s=typeof e[i],s==="object"&&!~n(i,["Exceptions","Env","Mime"])?r(e[i]):s==="function"&&(t[i]=e[i])}(e.moxie),t.Env=e.moxie.core.utils.Env,t.Mime=e.moxie.core.utils.Mime,t.Exceptions=e.moxie.core.Exceptions,e.mOxie=t,e.o||(e.o=t),t})(this);
+/**
+ * Plupload - multi-runtime File Uploader
+ * v2.1.2
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ *
+ * Date: 2014-05-14
+ */
+;(function(e,t,n){function s(e){function r(e,t,r){var i={chunks:"slice_blob",jpgresize:"send_binary_string",pngresize:"send_binary_string",progress:"report_upload_progress",multi_selection:"select_multiple",dragdrop:"drag_and_drop",drop_element:"drag_and_drop",headers:"send_custom_headers",urlstream_upload:"send_binary_string",canSendBinary:"send_binary",triggerDialog:"summon_file_dialog"};i[e]?n[i[e]]=t:r||(n[e]=t)}var t=e.required_features,n={};if(typeof t=="string")o.each(t.split(/\s*,\s*/),function(e){r(e,!0)});else if(typeof t=="object")o.each(t,function(e,t){r(t,e)});else if(t===!0){e.chunk_size>0&&(n.slice_blob=!0);if(e.resize.enabled||!e.multipart)n.send_binary_string=!0;o.each(e,function(e,t){r(t,!!e,!0)})}return n}var r=e.setTimeout,i={},o={VERSION:"2.1.2",STOPPED:1,STARTED:2,QUEUED:1,UPLOADING:2,FAILED:4,DONE:5,GENERIC_ERROR:-100,HTTP_ERROR:-200,IO_ERROR:-300,SECURITY_ERROR:-400,INIT_ERROR:-500,FILE_SIZE_ERROR:-600,FILE_EXTENSION_ERROR:-601,FILE_DUPLICATE_ERROR:-602,IMAGE_FORMAT_ERROR:-700,MEMORY_ERROR:-701,IMAGE_DIMENSIONS_ERROR:-702,mimeTypes:t.mimes,ua:t.ua,typeOf:t.typeOf,extend:t.extend,guid:t.guid,get:function(n){var r=[],i;t.typeOf(n)!=="array"&&(n=[n]);var s=n.length;while(s--)i=t.get(n[s]),i&&r.push(i);return r.length?r:null},each:t.each,getPos:t.getPos,getSize:t.getSize,xmlEncode:function(e){var t={"<":"lt",">":"gt","&":"amp",'"':"quot","'":"#39"},n=/[<>&\"\']/g;return e?(""+e).replace(n,function(e){return t[e]?"&"+t[e]+";":e}):e},toArray:t.toArray,inArray:t.inArray,addI18n:t.addI18n,translate:t.translate,isEmptyObj:t.isEmptyObj,hasClass:t.hasClass,addClass:t.addClass,removeClass:t.removeClass,getStyle:t.getStyle,addEvent:t.addEvent,removeEvent:t.removeEvent,removeAllEvents:t.removeAllEvents,cleanName:function(e){var t,n;n=[/[\300-\306]/g,"A",/[\340-\346]/g,"a",/\307/g,"C",/\347/g,"c",/[\310-\313]/g,"E",/[\350-\353]/g,"e",/[\314-\317]/g,"I",/[\354-\357]/g,"i",/\321/g,"N",/\361/g,"n",/[\322-\330]/g,"O",/[\362-\370]/g,"o",/[\331-\334]/g,"U",/[\371-\374]/g,"u"];for(t=0;t<n.length;t+=2)e=e.replace(n[t],n[t+1]);return e=e.replace(/\s+/g,"_"),e=e.replace(/[^a-z0-9_\-\.]+/gi,""),e},buildUrl:function(e,t){var n="";return o.each(t,function(e,t){n+=(n?"&":"")+encodeURIComponent(t)+"="+encodeURIComponent(e)}),n&&(e+=(e.indexOf("?")>0?"&":"?")+n),e},formatSize:function(e){function t(e,t){return Math.round(e*Math.pow(10,t))/Math.pow(10,t)}if(e===n||/\D/.test(e))return o.translate("N/A");var r=Math.pow(1024,4);return e>r?t(e/r,1)+" "+o.translate("tb"):e>(r/=1024)?t(e/r,1)+" "+o.translate("gb"):e>(r/=1024)?t(e/r,1)+" "+o.translate("mb"):e>1024?Math.round(e/1024)+" "+o.translate("kb"):e+" "+o.translate("b")},parseSize:t.parseSizeStr,predictRuntime:function(e,n){var r,i;return r=new o.Uploader(e),i=t.Runtime.thatCan(r.getOption().required_features,n||e.runtimes),r.destroy(),i},addFileFilter:function(e,t){i[e]=t}};o.addFileFilter("mime_types",function(e,t,n){e.length&&!e.regexp.test(t.name)?(this.trigger("Error",{code:o.FILE_EXTENSION_ERROR,message:o.translate("File extension error."),file:t}),n(!1)):n(!0)}),o.addFileFilter("max_file_size",function(e,t,n){var r;e=o.parseSize(e),t.size!==r&&e&&t.size>e?(this.trigger("Error",{code:o.FILE_SIZE_ERROR,message:o.translate("File size error."),file:t}),n(!1)):n(!0)}),o.addFileFilter("prevent_duplicates",function(e,t,n){if(e){var r=this.files.length;while(r--)if(t.name===this.files[r].name&&t.size===this.files[r].size){this.trigger("Error",{code:o.FILE_DUPLICATE_ERROR,message:o.translate("Duplicate file error."),file:t}),n(!1);return}}n(!0)}),o.Uploader=function(e){function g(){var e,t=0,n;if(this.state==o.STARTED){for(n=0;n<f.length;n++)!e&&f[n].status==o.QUEUED?(e=f[n],this.trigger("BeforeUpload",e)&&(e.status=o.UPLOADING,this.trigger("UploadFile",e))):t++;t==f.length&&(this.state!==o.STOPPED&&(this.state=o.STOPPED,this.trigger("StateChanged")),this.trigger("UploadComplete",f))}}function y(e){e.percent=e.size>0?Math.ceil(e.loaded/e.size*100):100,b()}function b(){var e,t;d.reset();for(e=0;e<f.length;e++)t=f[e],t.size!==n?(d.size+=t.origSize,d.loaded+=t.loaded*t.origSize/t.size):d.size=n,t.status==o.DONE?d.uploaded++:t.status==o.FAILED?d.failed++:d.queued++;d.size===n?d.percent=f.length>0?Math.ceil(d.uploaded/f.length*100):0:(d.bytesPerSec=Math.ceil(d.loaded/((+(new Date)-p||1)/1e3)),d.percent=d.size>0?Math.ceil(d.loaded/d.size*100):0)}function w(){var e=c[0]||h[0];return e?e.getRuntime().uid:!1}function E(e,n){if(e.ruid){var r=t.Runtime.getInfo(e.ruid);if(r)return r.can(n)}return!1}function S(){this.bind("FilesAdded FilesRemoved",function(e){e.trigger("QueueChanged"),e.refresh()}),this.bind("CancelUpload",O),this.bind("BeforeUpload",C),this.bind("UploadFile",k),this.bind("UploadProgress",L),this.bind("StateChanged",A),this.bind("QueueChanged",b),this.bind("Error",_),this.bind("FileUploaded",M),this.bind("Destroy",D)}function x(e,n){var r=this,i=0,s=[],u={runtime_order:e.runtimes,required_caps:e.required_features,preferred_caps:l,swf_url:e.flash_swf_url,xap_url:e.silverlight_xap_url};o.each(e.runtimes.split(/\s*,\s*/),function(t){e[t]&&(u[t]=e[t])}),e.browse_button&&o.each(e.browse_button,function(n){s.push(function(s){var a=new t.FileInput(o.extend({},u,{accept:e.filters.mime_types,name:e.file_data_name,multiple:e.multi_selection,container:e.container,browse_button:n}));a.onready=function(){var e=t.Runtime.getInfo(this.ruid);t.extend(r.features,{chunks:e.can("slice_blob"),multipart:e.can("send_multipart"),multi_selection:e.can("select_multiple")}),i++,c.push(this),s()},a.onchange=function(){r.addFile(this.files)},a.bind("mouseenter mouseleave mousedown mouseup",function(r){v||(e.browse_button_hover&&("mouseenter"===r.type?t.addClass(n,e.browse_button_hover):"mouseleave"===r.type&&t.removeClass(n,e.browse_button_hover)),e.browse_button_active&&("mousedown"===r.type?t.addClass(n,e.browse_button_active):"mouseup"===r.type&&t.removeClass(n,e.browse_button_active)))}),a.bind("mousedown",function(){r.trigger("Browse")}),a.bind("error runtimeerror",function(){a=null,s()}),a.init()})}),e.drop_element&&o.each(e.drop_element,function(e){s.push(function(n){var s=new t.FileDrop(o.extend({},u,{drop_zone:e}));s.onready=function(){var e=t.Runtime.getInfo(this.ruid);r.features.dragdrop=e.can("drag_and_drop"),i++,h.push(this),n()},s.ondrop=function(){r.addFile(this.files)},s.bind("error runtimeerror",function(){s=null,n()}),s.init()})}),t.inSeries(s,function(){typeof n=="function"&&n(i)})}function T(e,r,i){var s=new t.Image;try{s.onload=function(){if(r.width>this.width&&r.height>this.height&&r.quality===n&&r.preserve_headers&&!r.crop)return this.destroy(),i(e);s.downsize(r.width,r.height,r.crop,r.preserve_headers)},s.onresize=function(){i(this.getAsBlob(e.type,r.quality)),this.destroy()},s.onerror=function(){i(e)},s.load(e)}catch(o){i(e)}}function N(e,n,r){function f(e,t,n){var r=a[e];switch(e){case"max_file_size":e==="max_file_size"&&(a.max_file_size=a.filters.max_file_size=t);break;case"chunk_size":if(t=o.parseSize(t))a[e]=t,a.send_file_name=!0;break;case"multipart":a[e]=t,t||(a.send_file_name=!0);break;case"unique_names":a[e]=t,t&&(a.send_file_name=!0);break;case"filters":o.typeOf(t)==="array"&&(t={mime_types:t}),n?o.extend(a.filters,t):a.filters=t,t.mime_types&&(a.filters.mime_types.regexp=function(e){var t=[];return o.each(e,function(e){o.each(e.extensions.split(/,/),function(e){/^\s*\*\s*$/.test(e)?t.push("\\.*"):t.push("\\."+e.replace(new RegExp("["+"/^$.*+?|()[]{}\\".replace(/./g,"\\$&")+"]","g"),"\\$&"))})}),new RegExp("("+t.join("|")+")$","i")}(a.filters.mime_types));break;case"resize":n?o.extend(a.resize,t,{enabled:!0}):a.resize=t;break;case"prevent_duplicates":a.prevent_duplicates=a.filters.prevent_duplicates=!!t;break;case"browse_button":case"drop_element":t=o.get(t);case"container":case"runtimes":case"multi_selection":case"flash_swf_url":case"silverlight_xap_url":a[e]=t,n||(u=!0);break;default:a[e]=t}n||i.trigger("OptionChanged",e,t,r)}var i=this,u=!1;typeof e=="object"?o.each(e,function(e,t){f(t,e,r)}):f(e,n,r),r?(a.required_features=s(o.extend({},a)),l=s(o.extend({},a,{required_features:!0}))):u&&(i.trigger("Destroy"),x.call(i,a,function(e){e?(i.runtime=t.Runtime.getInfo(w()).type,i.trigger("Init",{runtime:i.runtime}),i.trigger("PostInit")):i.trigger("Error",{code:o.INIT_ERROR,message:o.translate("Init error.")})}))}function C(e,t){if(e.settings.unique_names){var n=t.name.match(/\.([^.]+)$/),r="part";n&&(r=n[1]),t.target_name=t.id+"."+r}}function k(e,n){function h(){u-->0?r(p,1e3):(n.loaded=f,e.trigger("Error",{code:o.HTTP_ERROR,message:o.translate("HTTP Error."),file:n,response:m.responseText,status:m.status,responseHeaders:m.getAllResponseHeaders()}))}function p(){var d,v,g={},y;if(n.status!==o.UPLOADING||e.state===o.STOPPED)return;e.settings.send_file_name&&(g.name=n.target_name||n.name),s&&a.chunks&&c.size>s?(y=Math.min(s,c.size-f),d=c.slice(f,f+y)):(y=c.size,d=c),s&&a.chunks&&(e.settings.send_chunk_number?(g.chunk=Math.ceil(f/s),g.chunks=Math.ceil(c.size/s)):(g.offset=f,g.total=c.size)),m=new t.XMLHttpRequest,m.upload&&(m.upload.onprogress=function(t){n.loaded=Math.min(n.size,f+t.loaded),e.trigger("UploadProgress",n)}),m.onload=function(){if(m.status>=400){h();return}u=e.settings.max_retries,y<c.size?(d.destroy(),f+=y,n.loaded=Math.min(f,c.size),e.trigger("ChunkUploaded",n,{offset:n.loaded,total:c.size,response:m.responseText,status:m.status,responseHeaders:m.getAllResponseHeaders()}),t.Env.browser==="Android Browser"&&e.trigger("UploadProgress",n)):n.loaded=n.size,d=v=null,!f||f>=c.size?(n.size!=n.origSize&&(c.destroy(),c=null),e.trigger("UploadProgress",n),n.status=o.DONE,e.trigger("FileUploaded",n,{response:m.responseText,status:m.status,responseHeaders:m.getAllResponseHeaders()})):r(p,1)},m.onerror=function(){h()},m.onloadend=function(){this.destroy(),m=null},e.settings.multipart&&a.multipart?(m.open("post",i,!0),o.each(e.settings.headers,function(e,t){m.setRequestHeader(t,e)}),v=new t.FormData,o.each(o.extend(g,e.settings.multipart_params),function(e,t){v.append(t,e)}),v.append(e.settings.file_data_name,d),m.send(v,{runtime_order:e.settings.runtimes,required_caps:e.settings.required_features,preferred_caps:l,swf_url:e.settings.flash_swf_url,xap_url:e.settings.silverlight_xap_url})):(i=o.buildUrl(e.settings.url,o.extend(g,e.settings.multipart_params)),m.open("post",i,!0),m.setRequestHeader("Content-Type","application/octet-stream"),o.each(e.settings.headers,function(e,t){m.setRequestHeader(t,e)}),m.send(d,{runtime_order:e.settings.runtimes,required_caps:e.settings.required_features,preferred_caps:l,swf_url:e.settings.flash_swf_url,xap_url:e.settings.silverlight_xap_url}))}var i=e.settings.url,s=e.settings.chunk_size,u=e.settings.max_retries,a=e.features,f=0,c;n.loaded&&(f=n.loaded=s?s*Math.floor(n.loaded/s):0),c=n.getSource(),e.settings.resize.enabled&&E(c,"send_binary_string")&&!!~t.inArray(c.type,["image/jpeg","image/png"])?T.call(this,c,e.settings.resize,function(e){c=e,n.size=e.size,p()}):p()}function L(e,t){y(t)}function A(e){if(e.state==o.STARTED)p=+(new Date);else if(e.state==o.STOPPED)for(var t=e.files.length-1;t>=0;t--)e.files[t].status==o.UPLOADING&&(e.files[t].status=o.QUEUED,b())}function O(){m&&m.abort()}function M(e){b(),r(function(){g.call(e)},1)}function _(e,t){t.code===o.INIT_ERROR?e.destroy():t.file&&(t.file.status=o.FAILED,y(t.file),e.state==o.STARTED&&(e.trigger("CancelUpload"),r(function(){g.call(e)},1)))}function D(e){e.stop(),o.each(f,function(e){e.destroy()}),f=[],c.length&&(o.each(c,function(e){e.destroy()}),c=[]),h.length&&(o.each(h,function(e){e.destroy()}),h=[]),l={},v=!1,p=m=null,d.reset()}var u=o.guid(),a,f=[],l={},c=[],h=[],p,d,v=!1,m;a={runtimes:t.Runtime.order,max_retries:0,chunk_size:0,multipart:!0,multi_selection:!0,file_data_name:"file",flash_swf_url:"js/Moxie.swf",silverlight_xap_url:"js/Moxie.xap",filters:{mime_types:[],prevent_duplicates:!1,max_file_size:0},resize:{enabled:!1,preserve_headers:!0,crop:!1},send_file_name:!0,send_chunk_number:!0},N.call(this,e,null,!0),d=new o.QueueProgress,o.extend(this,{id:u,uid:u,state:o.STOPPED,features:{},runtime:null,files:f,settings:a,total:d,init:function(){var e=this;typeof a.preinit=="function"?a.preinit(e):o.each(a.preinit,function(t,n){e.bind(n,t)}),S.call(this);if(!a.browse_button||!a.url){this.trigger("Error",{code:o.INIT_ERROR,message:o.translate("Init error.")});return}x.call(this,a,function(n){typeof a.init=="function"?a.init(e):o.each(a.init,function(t,n){e.bind(n,t)}),n?(e.runtime=t.Runtime.getInfo(w()).type,e.trigger("Init",{runtime:e.runtime}),e.trigger("PostInit")):e.trigger("Error",{code:o.INIT_ERROR,message:o.translate("Init error.")})})},setOption:function(e,t){N.call(this,e,t,!this.runtime)},getOption:function(e){return e?a[e]:a},refresh:function(){c.length&&o.each(c,function(e){e.trigger("Refresh")}),this.trigger("Refresh")},start:function(){this.state!=o.STARTED&&(this.state=o.STARTED,this.trigger("StateChanged"),g.call(this))},stop:function(){this.state!=o.STOPPED&&(this.state=o.STOPPED,this.trigger("StateChanged"),this.trigger("CancelUpload"))},disableBrowse:function(){v=arguments[0]!==n?arguments[0]:!0,c.length&&o.each(c,function(e){e.disable(v)}),this.trigger("DisableBrowse",v)},getFile:function(e){var t;for(t=f.length-1;t>=0;t--)if(f[t].id===e)return f[t]},addFile:function(e,n){function c(e,n){var r=[];t.each(s.settings.filters,function(t,n){i[n]&&r.push(function(r){i[n].call(s,t,e,function(e){r(!e)})})}),t.inSeries(r,n)}function h(e){var i=t.typeOf(e);if(e instanceof t.File){if(!e.ruid&&!e.isDetached()){if(!l)return!1;e.ruid=l,e.connectRuntime(l)}h(new o.File(e))}else e instanceof t.Blob?(h(e.getSource()),e.destroy()):e instanceof o.File?(n&&(e.name=n),u.push(function(t){c(e,function(n){n||(f.push(e),a.push(e),s.trigger("FileFiltered",e)),r(t,1)})})):t.inArray(i,["file","blob"])!==-1?h(new t.File(null,e)):i==="node"&&t.typeOf(e.files)==="filelist"?t.each(e.files,h):i==="array"&&(n=null,t.each(e,h))}var s=this,u=[],a=[],l;l=w(),h(e),u.length&&t.inSeries(u,function(){a.length&&s.trigger("FilesAdded",a)})},removeFile:function(e){var t=typeof e=="string"?e:e.id;for(var n=f.length-1;n>=0;n--)if(f[n].id===t)return this.splice(n,1)[0]},splice:function(e,t){var r=f.splice(e===n?0:e,t===n?f.length:t),i=!1;return this.state==o.STARTED&&(o.each(r,function(e){if(e.status===o.UPLOADING)return i=!0,!1}),i&&this.stop()),this.trigger("FilesRemoved",r),o.each(r,function(e){e.destroy()}),i&&this.start(),r},bind:function(e,t,n){var r=this;o.Uploader.prototype.bind.call(this,e,function(){var e=[].slice.call(arguments);return e.splice(0,1,r),t.apply(this,e)},0,n)},destroy:function(){this.trigger("Destroy"),a=d=null,this.unbindAll()}})},o.Uploader.prototype=t.EventTarget.instance,o.File=function(){function n(n){o.extend(this,{id:o.guid(),name:n.name||n.fileName,type:n.type||"",size:n.size||n.fileSize,origSize:n.size||n.fileSize,loaded:0,percent:0,status:o.QUEUED,lastModifiedDate:n.lastModifiedDate||(new Date).toLocaleString(),getNative:function(){var e=this.getSource().getSource();return t.inArray(t.typeOf(e),["blob","file"])!==-1?e:null},getSource:function(){return e[this.id]?e[this.id]:null},destroy:function(){var t=this.getSource();t&&(t.destroy(),delete e[this.id])}}),e[this.id]=n}var e={};return n}(),o.QueueProgress=function(){var e=this;e.size=0,e.loaded=0,e.uploaded=0,e.failed=0,e.queued=0,e.percent=0,e.bytesPerSec=0,e.reset=function(){e.size=e.loaded=e.uploaded=e.failed=e.queued=e.percent=e.bytesPerSec=0}},e.plupload=o})(window,mOxie);
Index: /trunk/themes/default/js/plugins/plupload/plupload.min.js
===================================================================
--- /trunk/themes/default/js/plugins/plupload/plupload.min.js	(revision 28545)
+++ /trunk/themes/default/js/plugins/plupload/plupload.min.js	(revision 28545)
@@ -0,0 +1,13 @@
+/**
+ * Plupload - multi-runtime File Uploader
+ * v2.1.2
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ *
+ * Date: 2014-05-14
+ */
+;(function(e,t,n){function s(e){function r(e,t,r){var i={chunks:"slice_blob",jpgresize:"send_binary_string",pngresize:"send_binary_string",progress:"report_upload_progress",multi_selection:"select_multiple",dragdrop:"drag_and_drop",drop_element:"drag_and_drop",headers:"send_custom_headers",urlstream_upload:"send_binary_string",canSendBinary:"send_binary",triggerDialog:"summon_file_dialog"};i[e]?n[i[e]]=t:r||(n[e]=t)}var t=e.required_features,n={};if(typeof t=="string")o.each(t.split(/\s*,\s*/),function(e){r(e,!0)});else if(typeof t=="object")o.each(t,function(e,t){r(t,e)});else if(t===!0){e.chunk_size>0&&(n.slice_blob=!0);if(e.resize.enabled||!e.multipart)n.send_binary_string=!0;o.each(e,function(e,t){r(t,!!e,!0)})}return n}var r=e.setTimeout,i={},o={VERSION:"2.1.2",STOPPED:1,STARTED:2,QUEUED:1,UPLOADING:2,FAILED:4,DONE:5,GENERIC_ERROR:-100,HTTP_ERROR:-200,IO_ERROR:-300,SECURITY_ERROR:-400,INIT_ERROR:-500,FILE_SIZE_ERROR:-600,FILE_EXTENSION_ERROR:-601,FILE_DUPLICATE_ERROR:-602,IMAGE_FORMAT_ERROR:-700,MEMORY_ERROR:-701,IMAGE_DIMENSIONS_ERROR:-702,mimeTypes:t.mimes,ua:t.ua,typeOf:t.typeOf,extend:t.extend,guid:t.guid,get:function(n){var r=[],i;t.typeOf(n)!=="array"&&(n=[n]);var s=n.length;while(s--)i=t.get(n[s]),i&&r.push(i);return r.length?r:null},each:t.each,getPos:t.getPos,getSize:t.getSize,xmlEncode:function(e){var t={"<":"lt",">":"gt","&":"amp",'"':"quot","'":"#39"},n=/[<>&\"\']/g;return e?(""+e).replace(n,function(e){return t[e]?"&"+t[e]+";":e}):e},toArray:t.toArray,inArray:t.inArray,addI18n:t.addI18n,translate:t.translate,isEmptyObj:t.isEmptyObj,hasClass:t.hasClass,addClass:t.addClass,removeClass:t.removeClass,getStyle:t.getStyle,addEvent:t.addEvent,removeEvent:t.removeEvent,removeAllEvents:t.removeAllEvents,cleanName:function(e){var t,n;n=[/[\300-\306]/g,"A",/[\340-\346]/g,"a",/\307/g,"C",/\347/g,"c",/[\310-\313]/g,"E",/[\350-\353]/g,"e",/[\314-\317]/g,"I",/[\354-\357]/g,"i",/\321/g,"N",/\361/g,"n",/[\322-\330]/g,"O",/[\362-\370]/g,"o",/[\331-\334]/g,"U",/[\371-\374]/g,"u"];for(t=0;t<n.length;t+=2)e=e.replace(n[t],n[t+1]);return e=e.replace(/\s+/g,"_"),e=e.replace(/[^a-z0-9_\-\.]+/gi,""),e},buildUrl:function(e,t){var n="";return o.each(t,function(e,t){n+=(n?"&":"")+encodeURIComponent(t)+"="+encodeURIComponent(e)}),n&&(e+=(e.indexOf("?")>0?"&":"?")+n),e},formatSize:function(e){function t(e,t){return Math.round(e*Math.pow(10,t))/Math.pow(10,t)}if(e===n||/\D/.test(e))return o.translate("N/A");var r=Math.pow(1024,4);return e>r?t(e/r,1)+" "+o.translate("tb"):e>(r/=1024)?t(e/r,1)+" "+o.translate("gb"):e>(r/=1024)?t(e/r,1)+" "+o.translate("mb"):e>1024?Math.round(e/1024)+" "+o.translate("kb"):e+" "+o.translate("b")},parseSize:t.parseSizeStr,predictRuntime:function(e,n){var r,i;return r=new o.Uploader(e),i=t.Runtime.thatCan(r.getOption().required_features,n||e.runtimes),r.destroy(),i},addFileFilter:function(e,t){i[e]=t}};o.addFileFilter("mime_types",function(e,t,n){e.length&&!e.regexp.test(t.name)?(this.trigger("Error",{code:o.FILE_EXTENSION_ERROR,message:o.translate("File extension error."),file:t}),n(!1)):n(!0)}),o.addFileFilter("max_file_size",function(e,t,n){var r;e=o.parseSize(e),t.size!==r&&e&&t.size>e?(this.trigger("Error",{code:o.FILE_SIZE_ERROR,message:o.translate("File size error."),file:t}),n(!1)):n(!0)}),o.addFileFilter("prevent_duplicates",function(e,t,n){if(e){var r=this.files.length;while(r--)if(t.name===this.files[r].name&&t.size===this.files[r].size){this.trigger("Error",{code:o.FILE_DUPLICATE_ERROR,message:o.translate("Duplicate file error."),file:t}),n(!1);return}}n(!0)}),o.Uploader=function(e){function g(){var e,t=0,n;if(this.state==o.STARTED){for(n=0;n<f.length;n++)!e&&f[n].status==o.QUEUED?(e=f[n],this.trigger("BeforeUpload",e)&&(e.status=o.UPLOADING,this.trigger("UploadFile",e))):t++;t==f.length&&(this.state!==o.STOPPED&&(this.state=o.STOPPED,this.trigger("StateChanged")),this.trigger("UploadComplete",f))}}function y(e){e.percent=e.size>0?Math.ceil(e.loaded/e.size*100):100,b()}function b(){var e,t;d.reset();for(e=0;e<f.length;e++)t=f[e],t.size!==n?(d.size+=t.origSize,d.loaded+=t.loaded*t.origSize/t.size):d.size=n,t.status==o.DONE?d.uploaded++:t.status==o.FAILED?d.failed++:d.queued++;d.size===n?d.percent=f.length>0?Math.ceil(d.uploaded/f.length*100):0:(d.bytesPerSec=Math.ceil(d.loaded/((+(new Date)-p||1)/1e3)),d.percent=d.size>0?Math.ceil(d.loaded/d.size*100):0)}function w(){var e=c[0]||h[0];return e?e.getRuntime().uid:!1}function E(e,n){if(e.ruid){var r=t.Runtime.getInfo(e.ruid);if(r)return r.can(n)}return!1}function S(){this.bind("FilesAdded FilesRemoved",function(e){e.trigger("QueueChanged"),e.refresh()}),this.bind("CancelUpload",O),this.bind("BeforeUpload",C),this.bind("UploadFile",k),this.bind("UploadProgress",L),this.bind("StateChanged",A),this.bind("QueueChanged",b),this.bind("Error",_),this.bind("FileUploaded",M),this.bind("Destroy",D)}function x(e,n){var r=this,i=0,s=[],u={runtime_order:e.runtimes,required_caps:e.required_features,preferred_caps:l,swf_url:e.flash_swf_url,xap_url:e.silverlight_xap_url};o.each(e.runtimes.split(/\s*,\s*/),function(t){e[t]&&(u[t]=e[t])}),e.browse_button&&o.each(e.browse_button,function(n){s.push(function(s){var a=new t.FileInput(o.extend({},u,{accept:e.filters.mime_types,name:e.file_data_name,multiple:e.multi_selection,container:e.container,browse_button:n}));a.onready=function(){var e=t.Runtime.getInfo(this.ruid);t.extend(r.features,{chunks:e.can("slice_blob"),multipart:e.can("send_multipart"),multi_selection:e.can("select_multiple")}),i++,c.push(this),s()},a.onchange=function(){r.addFile(this.files)},a.bind("mouseenter mouseleave mousedown mouseup",function(r){v||(e.browse_button_hover&&("mouseenter"===r.type?t.addClass(n,e.browse_button_hover):"mouseleave"===r.type&&t.removeClass(n,e.browse_button_hover)),e.browse_button_active&&("mousedown"===r.type?t.addClass(n,e.browse_button_active):"mouseup"===r.type&&t.removeClass(n,e.browse_button_active)))}),a.bind("mousedown",function(){r.trigger("Browse")}),a.bind("error runtimeerror",function(){a=null,s()}),a.init()})}),e.drop_element&&o.each(e.drop_element,function(e){s.push(function(n){var s=new t.FileDrop(o.extend({},u,{drop_zone:e}));s.onready=function(){var e=t.Runtime.getInfo(this.ruid);r.features.dragdrop=e.can("drag_and_drop"),i++,h.push(this),n()},s.ondrop=function(){r.addFile(this.files)},s.bind("error runtimeerror",function(){s=null,n()}),s.init()})}),t.inSeries(s,function(){typeof n=="function"&&n(i)})}function T(e,r,i){var s=new t.Image;try{s.onload=function(){if(r.width>this.width&&r.height>this.height&&r.quality===n&&r.preserve_headers&&!r.crop)return this.destroy(),i(e);s.downsize(r.width,r.height,r.crop,r.preserve_headers)},s.onresize=function(){i(this.getAsBlob(e.type,r.quality)),this.destroy()},s.onerror=function(){i(e)},s.load(e)}catch(o){i(e)}}function N(e,n,r){function f(e,t,n){var r=a[e];switch(e){case"max_file_size":e==="max_file_size"&&(a.max_file_size=a.filters.max_file_size=t);break;case"chunk_size":if(t=o.parseSize(t))a[e]=t,a.send_file_name=!0;break;case"multipart":a[e]=t,t||(a.send_file_name=!0);break;case"unique_names":a[e]=t,t&&(a.send_file_name=!0);break;case"filters":o.typeOf(t)==="array"&&(t={mime_types:t}),n?o.extend(a.filters,t):a.filters=t,t.mime_types&&(a.filters.mime_types.regexp=function(e){var t=[];return o.each(e,function(e){o.each(e.extensions.split(/,/),function(e){/^\s*\*\s*$/.test(e)?t.push("\\.*"):t.push("\\."+e.replace(new RegExp("["+"/^$.*+?|()[]{}\\".replace(/./g,"\\$&")+"]","g"),"\\$&"))})}),new RegExp("("+t.join("|")+")$","i")}(a.filters.mime_types));break;case"resize":n?o.extend(a.resize,t,{enabled:!0}):a.resize=t;break;case"prevent_duplicates":a.prevent_duplicates=a.filters.prevent_duplicates=!!t;break;case"browse_button":case"drop_element":t=o.get(t);case"container":case"runtimes":case"multi_selection":case"flash_swf_url":case"silverlight_xap_url":a[e]=t,n||(u=!0);break;default:a[e]=t}n||i.trigger("OptionChanged",e,t,r)}var i=this,u=!1;typeof e=="object"?o.each(e,function(e,t){f(t,e,r)}):f(e,n,r),r?(a.required_features=s(o.extend({},a)),l=s(o.extend({},a,{required_features:!0}))):u&&(i.trigger("Destroy"),x.call(i,a,function(e){e?(i.runtime=t.Runtime.getInfo(w()).type,i.trigger("Init",{runtime:i.runtime}),i.trigger("PostInit")):i.trigger("Error",{code:o.INIT_ERROR,message:o.translate("Init error.")})}))}function C(e,t){if(e.settings.unique_names){var n=t.name.match(/\.([^.]+)$/),r="part";n&&(r=n[1]),t.target_name=t.id+"."+r}}function k(e,n){function h(){u-->0?r(p,1e3):(n.loaded=f,e.trigger("Error",{code:o.HTTP_ERROR,message:o.translate("HTTP Error."),file:n,response:m.responseText,status:m.status,responseHeaders:m.getAllResponseHeaders()}))}function p(){var d,v,g={},y;if(n.status!==o.UPLOADING||e.state===o.STOPPED)return;e.settings.send_file_name&&(g.name=n.target_name||n.name),s&&a.chunks&&c.size>s?(y=Math.min(s,c.size-f),d=c.slice(f,f+y)):(y=c.size,d=c),s&&a.chunks&&(e.settings.send_chunk_number?(g.chunk=Math.ceil(f/s),g.chunks=Math.ceil(c.size/s)):(g.offset=f,g.total=c.size)),m=new t.XMLHttpRequest,m.upload&&(m.upload.onprogress=function(t){n.loaded=Math.min(n.size,f+t.loaded),e.trigger("UploadProgress",n)}),m.onload=function(){if(m.status>=400){h();return}u=e.settings.max_retries,y<c.size?(d.destroy(),f+=y,n.loaded=Math.min(f,c.size),e.trigger("ChunkUploaded",n,{offset:n.loaded,total:c.size,response:m.responseText,status:m.status,responseHeaders:m.getAllResponseHeaders()}),t.Env.browser==="Android Browser"&&e.trigger("UploadProgress",n)):n.loaded=n.size,d=v=null,!f||f>=c.size?(n.size!=n.origSize&&(c.destroy(),c=null),e.trigger("UploadProgress",n),n.status=o.DONE,e.trigger("FileUploaded",n,{response:m.responseText,status:m.status,responseHeaders:m.getAllResponseHeaders()})):r(p,1)},m.onerror=function(){h()},m.onloadend=function(){this.destroy(),m=null},e.settings.multipart&&a.multipart?(m.open("post",i,!0),o.each(e.settings.headers,function(e,t){m.setRequestHeader(t,e)}),v=new t.FormData,o.each(o.extend(g,e.settings.multipart_params),function(e,t){v.append(t,e)}),v.append(e.settings.file_data_name,d),m.send(v,{runtime_order:e.settings.runtimes,required_caps:e.settings.required_features,preferred_caps:l,swf_url:e.settings.flash_swf_url,xap_url:e.settings.silverlight_xap_url})):(i=o.buildUrl(e.settings.url,o.extend(g,e.settings.multipart_params)),m.open("post",i,!0),m.setRequestHeader("Content-Type","application/octet-stream"),o.each(e.settings.headers,function(e,t){m.setRequestHeader(t,e)}),m.send(d,{runtime_order:e.settings.runtimes,required_caps:e.settings.required_features,preferred_caps:l,swf_url:e.settings.flash_swf_url,xap_url:e.settings.silverlight_xap_url}))}var i=e.settings.url,s=e.settings.chunk_size,u=e.settings.max_retries,a=e.features,f=0,c;n.loaded&&(f=n.loaded=s?s*Math.floor(n.loaded/s):0),c=n.getSource(),e.settings.resize.enabled&&E(c,"send_binary_string")&&!!~t.inArray(c.type,["image/jpeg","image/png"])?T.call(this,c,e.settings.resize,function(e){c=e,n.size=e.size,p()}):p()}function L(e,t){y(t)}function A(e){if(e.state==o.STARTED)p=+(new Date);else if(e.state==o.STOPPED)for(var t=e.files.length-1;t>=0;t--)e.files[t].status==o.UPLOADING&&(e.files[t].status=o.QUEUED,b())}function O(){m&&m.abort()}function M(e){b(),r(function(){g.call(e)},1)}function _(e,t){t.code===o.INIT_ERROR?e.destroy():t.file&&(t.file.status=o.FAILED,y(t.file),e.state==o.STARTED&&(e.trigger("CancelUpload"),r(function(){g.call(e)},1)))}function D(e){e.stop(),o.each(f,function(e){e.destroy()}),f=[],c.length&&(o.each(c,function(e){e.destroy()}),c=[]),h.length&&(o.each(h,function(e){e.destroy()}),h=[]),l={},v=!1,p=m=null,d.reset()}var u=o.guid(),a,f=[],l={},c=[],h=[],p,d,v=!1,m;a={runtimes:t.Runtime.order,max_retries:0,chunk_size:0,multipart:!0,multi_selection:!0,file_data_name:"file",flash_swf_url:"js/Moxie.swf",silverlight_xap_url:"js/Moxie.xap",filters:{mime_types:[],prevent_duplicates:!1,max_file_size:0},resize:{enabled:!1,preserve_headers:!0,crop:!1},send_file_name:!0,send_chunk_number:!0},N.call(this,e,null,!0),d=new o.QueueProgress,o.extend(this,{id:u,uid:u,state:o.STOPPED,features:{},runtime:null,files:f,settings:a,total:d,init:function(){var e=this;typeof a.preinit=="function"?a.preinit(e):o.each(a.preinit,function(t,n){e.bind(n,t)}),S.call(this);if(!a.browse_button||!a.url){this.trigger("Error",{code:o.INIT_ERROR,message:o.translate("Init error.")});return}x.call(this,a,function(n){typeof a.init=="function"?a.init(e):o.each(a.init,function(t,n){e.bind(n,t)}),n?(e.runtime=t.Runtime.getInfo(w()).type,e.trigger("Init",{runtime:e.runtime}),e.trigger("PostInit")):e.trigger("Error",{code:o.INIT_ERROR,message:o.translate("Init error.")})})},setOption:function(e,t){N.call(this,e,t,!this.runtime)},getOption:function(e){return e?a[e]:a},refresh:function(){c.length&&o.each(c,function(e){e.trigger("Refresh")}),this.trigger("Refresh")},start:function(){this.state!=o.STARTED&&(this.state=o.STARTED,this.trigger("StateChanged"),g.call(this))},stop:function(){this.state!=o.STOPPED&&(this.state=o.STOPPED,this.trigger("StateChanged"),this.trigger("CancelUpload"))},disableBrowse:function(){v=arguments[0]!==n?arguments[0]:!0,c.length&&o.each(c,function(e){e.disable(v)}),this.trigger("DisableBrowse",v)},getFile:function(e){var t;for(t=f.length-1;t>=0;t--)if(f[t].id===e)return f[t]},addFile:function(e,n){function c(e,n){var r=[];t.each(s.settings.filters,function(t,n){i[n]&&r.push(function(r){i[n].call(s,t,e,function(e){r(!e)})})}),t.inSeries(r,n)}function h(e){var i=t.typeOf(e);if(e instanceof t.File){if(!e.ruid&&!e.isDetached()){if(!l)return!1;e.ruid=l,e.connectRuntime(l)}h(new o.File(e))}else e instanceof t.Blob?(h(e.getSource()),e.destroy()):e instanceof o.File?(n&&(e.name=n),u.push(function(t){c(e,function(n){n||(f.push(e),a.push(e),s.trigger("FileFiltered",e)),r(t,1)})})):t.inArray(i,["file","blob"])!==-1?h(new t.File(null,e)):i==="node"&&t.typeOf(e.files)==="filelist"?t.each(e.files,h):i==="array"&&(n=null,t.each(e,h))}var s=this,u=[],a=[],l;l=w(),h(e),u.length&&t.inSeries(u,function(){a.length&&s.trigger("FilesAdded",a)})},removeFile:function(e){var t=typeof e=="string"?e:e.id;for(var n=f.length-1;n>=0;n--)if(f[n].id===t)return this.splice(n,1)[0]},splice:function(e,t){var r=f.splice(e===n?0:e,t===n?f.length:t),i=!1;return this.state==o.STARTED&&(o.each(r,function(e){if(e.status===o.UPLOADING)return i=!0,!1}),i&&this.stop()),this.trigger("FilesRemoved",r),o.each(r,function(e){e.destroy()}),i&&this.start(),r},bind:function(e,t,n){var r=this;o.Uploader.prototype.bind.call(this,e,function(){var e=[].slice.call(arguments);return e.splice(0,1,r),t.apply(this,e)},0,n)},destroy:function(){this.trigger("Destroy"),a=d=null,this.unbindAll()}})},o.Uploader.prototype=t.EventTarget.instance,o.File=function(){function n(n){o.extend(this,{id:o.guid(),name:n.name||n.fileName,type:n.type||"",size:n.size||n.fileSize,origSize:n.size||n.fileSize,loaded:0,percent:0,status:o.QUEUED,lastModifiedDate:n.lastModifiedDate||(new Date).toLocaleString(),getNative:function(){var e=this.getSource().getSource();return t.inArray(t.typeOf(e),["blob","file"])!==-1?e:null},getSource:function(){return e[this.id]?e[this.id]:null},destroy:function(){var t=this.getSource();t&&(t.destroy(),delete e[this.id])}}),e[this.id]=n}var e={};return n}(),o.QueueProgress=function(){var e=this;e.size=0,e.loaded=0,e.uploaded=0,e.failed=0,e.queued=0,e.percent=0,e.bytesPerSec=0,e.reset=function(){e.size=e.loaded=e.uploaded=e.failed=e.queued=e.percent=e.bytesPerSec=0}},e.plupload=o})(window,mOxie);
Index: /trunk/ws.php
===================================================================
--- /trunk/ws.php	(revision 28544)
+++ /trunk/ws.php	(revision 28545)
@@ -466,4 +466,28 @@
 
   $service->addMethod(
+      'pwg.images.upload',
+      'ws_images_upload',
+      array(
+        'name' => array('default' => null),
+        'category' => array(
+          'default'=>null,
+          'flags'=>WS_PARAM_FORCE_ARRAY,
+          'type'=>WS_TYPE_ID
+          ),
+        'level' => array(
+          'default' => 0,
+          'maxValue' => max($conf['available_permission_levels']),
+          'type' => WS_TYPE_INT|WS_TYPE_POSITIVE
+          ),
+        'pwg_token' => array(),
+        ),
+      'Add an image.
+<br>Use the <b>$_FILES[image]</b> field for uploading file.
+<br>Set the form encoding to "form-data".',
+      $ws_functions_root . 'pwg.images.php',
+      array('admin_only'=>true, 'post_only'=>true)
+    );
+  
+  $service->addMethod(
       'pwg.images.delete',
       'ws_images_delete',
