Index: /extensions/url_uploader/admin.php
===================================================================
--- /extensions/url_uploader/admin.php	(revision 19804)
+++ /extensions/url_uploader/admin.php	(revision 19804)
@@ -0,0 +1,213 @@
+<?php
+defined('URLUPLOADER_PATH') or die('Hacking attempt!');
+ 
+global $template, $page, $conf;
+
+load_language('plugin.lang', URLUPLOADER_PATH);
+
+// +-----------------------------------------------------------------------+
+// | URL Uploader tab                                                      |
+// +-----------------------------------------------------------------------+
+define('PHOTOS_ADD_BASE_URL', get_root_url().'admin.php?page=photos_add');
+
+include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
+include_once(PHPWG_ROOT_PATH.'admin/include/tabsheet.class.php');
+include_once(PHPWG_ROOT_PATH.'admin/include/functions_upload.inc.php');
+include_once(PHPWG_ROOT_PATH.'admin/include/image.class.php');
+
+$allowed_extensions = array('jpg','jpeg','png','gif');
+$allowed_mimes = array('image/jpeg', 'image/png', 'image/gif');
+
+$tabsheet = new tabsheet();
+$tabsheet->set_id('photos_add');
+$tabsheet->select('url_uploader');
+$tabsheet->assign();
+
+
+// +-----------------------------------------------------------------------+
+// |                             process form                              |
+// +-----------------------------------------------------------------------+
+if (isset($_GET['processed']))
+{
+  $category_id = $_POST['category'];
+  $image_ids = array();
+  $page['thumbnails'] = array();
+  
+  // SINGLE UPLOAD
+  if ($_GET['upload_mode'] == 'single')
+  {
+    $_POST = array_map('trim', $_POST);
+    
+    // check empty url
+    if (empty($_POST['file_url']))
+    {
+      $page['errors'][] = l10n('File URL is empty');
+    }
+    // check remote url
+    else if (!url_is_remote($_POST['file_url']))
+    {
+      $page['errors'][] = l10n('Invalid file URL');
+    }
+    // check file extension
+    else if (!in_array(strtolower(get_extension($_POST['file_url'])), $allowed_extensions))
+    {
+      $page['errors'][] = l10n('Invalid file type');
+    }
+    // continue...
+    else
+    {
+      $temp_filename = $conf['data_location'].basename($_POST['file_url']);
+      $file = fopen($temp_filename, 'w+');
+      $result = fetchRemote($_POST['file_url'], $file);
+      fclose($file);
+      
+      // download failed ?
+      if (!$result)
+      {
+        @unlink($temp_filename);
+        $page['errors'][] = l10n('Unable to download file');
+      }
+      // check mime-type
+      else if (!in_array(get_mime($temp_filename, $allowed_mimes[0]), $allowed_mimes))
+      {
+        @unlink($temp_filename);
+        $page['errors'][] = l10n('Invalid file type');
+      }
+      // continue...
+      else
+      {
+        $image_id = add_uploaded_file(
+          $temp_filename, 
+          basename($temp_filename), 
+          array($category_id), 
+          $_POST['level']
+          );
+        
+        if (!empty($_POST['photo_name']))
+        {
+          single_update(
+            IMAGES_TABLE,
+            array('name'=>$_POST['photo_name']),
+            array('id' => $image_id)
+            );
+        }
+        
+        $image_ids = array($image_id);
+      }
+    }
+  }
+  // MULTIPLE UPLOAD
+  else if ($_GET['upload_mode'] == 'multiple')
+  {
+    if (isset($_POST['onUploadError']) and is_array($_POST['onUploadError']) and count($_POST['onUploadError']) > 0)
+    {
+      array_push($page['errors'], sprintf(l10n('%d photos not imported'), count($_POST['onUploadError'])));
+      foreach ($_POST['onUploadError'] as $error)
+      {
+        array_push($page['errors'], $error);
+      }
+    }
+  
+    if (isset($_POST['imageIds']) and is_array($_POST['imageIds']) and count($_POST['imageIds']) > 0)
+    {
+      $image_ids = $_POST['imageIds'];
+    }
+  }
+
+  // DISPLAY RESULTS
+  foreach ($image_ids as $image_id)
+  {
+    $query = '
+SELECT id, file, path
+  FROM '.IMAGES_TABLE.'
+  WHERE id = '.$image_id.'
+;';
+    $image_infos = pwg_db_fetch_assoc(pwg_query($query));
+    
+    $thumbnail = array(
+      'file' =>  $image_infos['file'],
+      'src' =>   DerivativeImage::thumb_url($image_infos),
+      'title' => get_name_from_file($image_infos['file']),
+      'link' =>  get_root_url().'admin.php?page=photo-'.$image_id.'&amp;cat_id='.$category_id,
+      );
+
+    array_push($page['thumbnails'], $thumbnail);
+  }
+
+  if (!empty($page['thumbnails']))
+  {
+    // nb uploaded
+    array_push($page['infos'], sprintf(
+      l10n('%d photos uploaded'),
+      count($page['thumbnails'])
+      ));
+
+    // level
+    if (0 != $_POST['level'])
+    {
+      array_push($page['infos'], sprintf(
+        l10n('Privacy level set to "%s"'),
+        l10n(sprintf('Level %d', $_POST['level']))
+        ));
+    }
+
+    // new category count
+    $query = '
+SELECT COUNT(*)
+  FROM '.IMAGE_CATEGORY_TABLE.'
+  WHERE category_id = '.$category_id.'
+;';
+    list($count) = pwg_db_fetch_row(pwg_query($query));
+    $category_name = get_cat_display_name_from_id($category_id, 'admin.php?page=album-');
+    
+    array_push($page['infos'], sprintf(
+      l10n('Album "%s" now contains %d photos'),
+      '<em>'.$category_name.'</em>',
+      $count
+      ));
+    
+    $page['batch_link'] = PHOTOS_ADD_BASE_URL.'&batch='.implode(',', $image_ids);
+  }
+}
+
+
+// +-----------------------------------------------------------------------+
+// |                             prepare form                              |
+// +-----------------------------------------------------------------------+
+include(PHPWG_ROOT_PATH.'admin/include/photos_add_direct_prepare.inc.php');
+
+// upload mode
+$upload_modes = array('single', 'multiple');
+$upload_mode = isset($conf['url_uploader_mode']) ? $conf['url_uploader_mode'] : 'single';
+
+if ( isset($_GET['upload_mode']) and $_GET['upload_mode']!=$upload_mode and in_array($_GET['upload_mode'], $upload_modes) )
+{
+  $upload_mode = $_GET['upload_mode'];
+  conf_update_param('url_uploader_mode', $upload_mode);
+}
+
+// what is the upload switch mode
+$index_of_upload_mode = array_flip($upload_modes);
+$upload_mode_index = $index_of_upload_mode[$upload_mode];
+$upload_switch = $upload_modes[ ($upload_mode_index + 1) % 2 ];
+
+$template->assign(array(
+  'upload_mode' => $upload_mode,
+  'form_action' => URLUPLOADER_ADMIN.'&amp;upload_mode='.$upload_mode.'&amp;processed=1',
+  'switch_url' => URLUPLOADER_ADMIN.'&amp;upload_mode='.$upload_switch,
+  'another_upload_link' => URLUPLOADER_ADMIN.'&amp;upload_mode='.$upload_mode,
+  ));
+
+
+$template->set_filename('urluploader_content', realpath(URLUPLOADER_PATH . 'template/photos_add.tpl'));
+
+// template vars
+$template->assign(array(
+  'URLUPLOADER_PATH' => get_root_url() . URLUPLOADER_PATH,
+  'URLUPLOADER_ADMIN' => URLUPLOADER_ADMIN,
+  ));
+  
+// send page content
+$template->assign_var_from_handle('ADMIN_CONTENT', 'urluploader_content');
+
+?>
Index: /extensions/url_uploader/include/functions.inc.php
===================================================================
--- /extensions/url_uploader/include/functions.inc.php	(revision 19804)
+++ /extensions/url_uploader/include/functions.inc.php	(revision 19804)
@@ -0,0 +1,66 @@
+<?php
+defined('URLUPLOADER_PATH') or die('Hacking attempt!');
+
+/**
+ * admin plugins menu link
+ */
+function urluploader_admin_plugin_menu_links($menu) 
+{
+  array_push($menu, array(
+    'NAME' => l10n('URL Uploader'),
+    'URL' => URLUPLOADER_ADMIN,
+  ));
+  return $menu;
+}
+
+/**
+ * add a tab on photo properties page
+ */
+function urluploader_tabsheet_before_select($sheets, $id)
+{
+  if ($id == 'photos_add')
+  {
+    // insert new tab at 2nd position
+    $sheets = 
+      array_slice($sheets, 0, 1) +
+      array('url_uploader' => array(
+        'caption' => l10n('URL Uploader'),
+        'url' => URLUPLOADER_ADMIN,
+        )) +
+      array_slice($sheets, 1);
+  }
+  
+  return $sheets;
+}
+
+/*
+ * try to get the mime-type of a file
+ * as no method is totally reliable we can fallback to a default mime
+ */
+function get_mime($file, $default="application/octet-stream")
+{
+  if (function_exists("mime_content_type"))
+  {
+    $mime = mime_content_type($file);
+    if (!empty($mime)) return $mime;
+  }
+  
+  if (function_exists("finfo_file"))
+  {
+    $finfo = finfo_open(FILEINFO_MIME_TYPE);
+    $mime = finfo_file($finfo, $file);
+    finfo_close($finfo);
+    if (!empty($mime)) return $mime;
+  }
+  
+  if (!stristr(ini_get("disable_functions"), "shell_exec"))
+  {
+    $file = escapeshellarg($file);
+    $mime = shell_exec("file -bi " . $file);
+    if (!empty($mime)) return $mime;
+  }
+  
+  return $default;
+}
+
+?>
Index: /extensions/url_uploader/include/index.php
===================================================================
--- /extensions/url_uploader/include/index.php	(revision 19804)
+++ /extensions/url_uploader/include/index.php	(revision 19804)
@@ -0,0 +1,7 @@
+<?php
+$url = '../';
+header( 'Request-URI: '.$url );
+header( 'Content-Location: '.$url );
+header( 'Location: '.$url );
+exit();
+?>
Index: /extensions/url_uploader/include/ws_functions.inc.php
===================================================================
--- /extensions/url_uploader/include/ws_functions.inc.php	(revision 19804)
+++ /extensions/url_uploader/include/ws_functions.inc.php	(revision 19804)
@@ -0,0 +1,124 @@
+<?php
+defined('URLUPLOADER_PATH') or die('Hacking attempt!');
+
+function urluploader_ws_add_methods($arr)
+{
+  global $conf;
+  $service = &$arr[0];
+  
+  $service->addMethod(
+    'pwg.images.addRemote',
+    'ws_images_addRemote',
+    array(
+      'file_url' => array(),
+      'category' => array(),
+      'name' => array('default' => null),
+      'level' => array(
+        'default' => 0,
+        'maxValue' => $conf['available_permission_levels']
+        ),
+      ),
+    'Add image from remote URL.'
+    );
+}
+
+function ws_images_addRemote($params, &$service)
+{
+  global $conf;
+  
+  if (!is_admin())
+  {
+    return new PwgError(401, 'Access denied');
+  }
+  
+  $params = array_map('trim', $params);
+  
+  $allowed_extensions = array('jpg','jpeg','png','gif');
+  $allowed_mimes = array('image/jpeg', 'image/png', 'image/gif');
+  
+  // check empty url
+  if (empty($params['file_url']))
+  {
+    return new PwgError(WS_ERR_INVALID_PARAM, 'File URL is empty');
+  }
+  // check remote url
+  if (!url_is_remote($params['file_url']))
+  {
+    return new PwgError(WS_ERR_INVALID_PARAM, 'Invalid file URL');
+  }
+  // check file extension
+  if (!in_array(strtolower(get_extension($params['file_url'])), $allowed_extensions))
+  {
+    return new PwgError(WS_ERR_INVALID_PARAM, 'Invalid file type');
+  }
+
+  // download file
+  include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
+  
+  $temp_filename = $conf['data_location'].basename($params['file_url']);
+  $file = fopen($temp_filename, 'w+');
+  $result = fetchRemote($params['file_url'], $file);
+  fclose($file);
+  
+  // download failed ?
+  if (!$result)
+  {
+    @unlink($temp_filename);
+    return new PwgError(WS_ERR_INVALID_PARAM, 'Unable to download file');
+  }
+  // check mime-type
+  if (!in_array(get_mime($temp_filename, $allowed_mimes[0]), $allowed_mimes))
+  {
+    @unlink($temp_filename);
+    return new PwgError(WS_ERR_INVALID_PARAM, 'Invalid file type');
+  }
+
+  // add photo
+  include_once(PHPWG_ROOT_PATH.'admin/include/functions_upload.inc.php');
+  
+  $image_id = add_uploaded_file(
+    $temp_filename, 
+    basename($temp_filename), 
+    array($params['category']), 
+    $params['level']
+    );
+  
+  if (!empty($params['name']))
+  {
+    single_update(
+      IMAGES_TABLE,
+      array('name'=>$params['name']),
+      array('id' => $image_id)
+      );
+  }
+  
+  
+  // return infos
+  $query = '
+SELECT id, name, permalink
+  FROM '.CATEGORIES_TABLE.'
+  WHERE id = '.$params['category'].'
+;';
+  $category = pwg_db_fetch_assoc(pwg_query($query));
+
+  $url_params = array(
+    'image_id' => $image_id,
+    'section' => 'categories',
+    'category' => $category,
+    );
+    
+  $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,
+    'url' => make_picture_url($url_params),
+    'thumbnail_url' => preg_replace('#^'.PHPWG_ROOT_PATH.'#', './', DerivativeImage::thumb_url($image_infos)),
+    );
+}
+
+?>
Index: /extensions/url_uploader/index.php
===================================================================
--- /extensions/url_uploader/index.php	(revision 19804)
+++ /extensions/url_uploader/index.php	(revision 19804)
@@ -0,0 +1,7 @@
+<?php
+$url = '../';
+header( 'Request-URI: '.$url );
+header( 'Content-Location: '.$url );
+header( 'Location: '.$url );
+exit();
+?>
Index: /extensions/url_uploader/language/en_UK/description.txt
===================================================================
--- /extensions/url_uploader/language/en_UK/description.txt	(revision 19804)
+++ /extensions/url_uploader/language/en_UK/description.txt	(revision 19804)
@@ -0,0 +1,1 @@
+Add photos from remote URL (see Admin->Photos->Add)
Index: /extensions/url_uploader/language/en_UK/index.php
===================================================================
--- /extensions/url_uploader/language/en_UK/index.php	(revision 19804)
+++ /extensions/url_uploader/language/en_UK/index.php	(revision 19804)
@@ -0,0 +1,7 @@
+<?php
+$url = '../';
+header( 'Request-URI: '.$url );
+header( 'Content-Location: '.$url );
+header( 'Location: '.$url );
+exit();
+?>
Index: /extensions/url_uploader/language/en_UK/plugin.lang.php
===================================================================
--- /extensions/url_uploader/language/en_UK/plugin.lang.php	(revision 19804)
+++ /extensions/url_uploader/language/en_UK/plugin.lang.php	(revision 19804)
@@ -0,0 +1,15 @@
+<?php
+
+$lang['Invalid file URL'] = 'Invalid file URL';
+$lang['Invalid file type'] = 'Invalid file type';
+$lang['File URL is empty'] = 'File URL is empty';
+$lang['Unable to download file'] = 'Unable to download file';
+$lang['Pending'] = 'Pending';
+$lang['Delete this item'] = 'Delete this item';
+$lang['File URL'] = 'File URL';
+$lang['Want to upload many files? Try the <a href="%s">multiple uploader</a> instead.'] = 'Want to upload many files? Try the <a href="%s">multiple uploader</a> instead.';
+$lang['Multiple uploader doesn\'t work? Try the <a href="%s">single uploader</a> instead.'] = 'Multiple uploader doesn\'t work? Try the <a href="%s">single uploader</a> instead.';
+$lang['One link by line, separate photo name and url with a &laquo; | &raquo;. Photo name is optional.'] = 'One link by line, separate photo name and url with a &laquo; | &raquo;. Photo name is optional.';
+$lang['Add links'] = 'Add links';
+
+?>
Index: /extensions/url_uploader/language/fr_FR/description.txt
===================================================================
--- /extensions/url_uploader/language/fr_FR/description.txt	(revision 19804)
+++ /extensions/url_uploader/language/fr_FR/description.txt	(revision 19804)
@@ -0,0 +1,1 @@
+Ajoutez des photos depuis une URL (voir Admin->Photos->Ajouter)
Index: /extensions/url_uploader/language/fr_FR/index.php
===================================================================
--- /extensions/url_uploader/language/fr_FR/index.php	(revision 19804)
+++ /extensions/url_uploader/language/fr_FR/index.php	(revision 19804)
@@ -0,0 +1,7 @@
+<?php
+$url = '../';
+header( 'Request-URI: '.$url );
+header( 'Content-Location: '.$url );
+header( 'Location: '.$url );
+exit();
+?>
Index: /extensions/url_uploader/language/fr_FR/plugin.lang.php
===================================================================
--- /extensions/url_uploader/language/fr_FR/plugin.lang.php	(revision 19804)
+++ /extensions/url_uploader/language/fr_FR/plugin.lang.php	(revision 19804)
@@ -0,0 +1,15 @@
+<?php
+
+$lang['Invalid file URL'] = 'URL du fichier invalide';
+$lang['Invalid file type'] = 'Type de fichier invalide';
+$lang['File URL is empty'] = 'L\'URL du fichier est vide';
+$lang['Unable to download file'] = 'Impossible de télécharger le fichier';
+$lang['Pending'] = 'En attente';
+$lang['Delete this item'] = 'Supprimer ce lien';
+$lang['File URL'] = 'URL du fichier';
+$lang['Want to upload many files? Try the <a href="%s">multiple uploader</a> instead.'] = 'Vous voulez télécharger plus de fichiers ? Essayez le <a href="%s">formulaire multiple</a>.';
+$lang['Multiple uploader doesn\'t work? Try the <a href="%s">single uploader</a> instead.'] = 'Le formulaire multiple ne fonctionne pas ? Essayez le <a href="%s">formulaire simple</a>.';
+$lang['One link by line, separate photo name and url with a &laquo; | &raquo;. Photo name is optional.'] = 'Un seul lien par ligne, séparez le nom et l\'URL par un &laquo; | &raquo;. Le nom de la photo est optionel.';
+$lang['Add links'] = 'Ajouter les liens';
+
+?>
Index: /extensions/url_uploader/language/index.php
===================================================================
--- /extensions/url_uploader/language/index.php	(revision 19804)
+++ /extensions/url_uploader/language/index.php	(revision 19804)
@@ -0,0 +1,7 @@
+<?php
+$url = '../';
+header( 'Request-URI: '.$url );
+header( 'Content-Location: '.$url );
+header( 'Location: '.$url );
+exit();
+?>
Index: /extensions/url_uploader/main.inc.php
===================================================================
--- /extensions/url_uploader/main.inc.php	(revision 19804)
+++ /extensions/url_uploader/main.inc.php	(revision 19804)
@@ -0,0 +1,40 @@
+<?php 
+/*
+Plugin Name: URL Uploader
+Version: auto
+Description: Add photos from remote URL (see Admin->Photos->Add)
+Plugin URI: auto
+Author: Mistic
+Author URI: http://www.strangeplanet.fr
+*/
+
+defined('PHPWG_ROOT_PATH') or die('Hacking attempt!');
+
+
+// +-----------------------------------------------------------------------+
+// | Define plugin constants                                               |
+// +-----------------------------------------------------------------------+
+defined('URLUPLOADER_ID') or define('URLUPLOADER_ID', basename(dirname(__FILE__)));
+define('URLUPLOADER_PATH' ,   PHPWG_PLUGINS_PATH . URLUPLOADER_ID . '/');
+define('URLUPLOADER_ADMIN',   get_root_url() . 'admin.php?page=plugin-' . URLUPLOADER_ID);
+
+
+// +-----------------------------------------------------------------------+
+// | Add event handlers                                                    |
+// +-----------------------------------------------------------------------+
+if (defined('IN_ADMIN'))
+{
+  // admin plugins menu link
+  add_event_handler('get_admin_plugin_menu_links', 'urluploader_admin_plugin_menu_links');
+  
+  // new tab on photo page
+  add_event_handler('tabsheet_before_select', 'urluploader_tabsheet_before_select', EVENT_HANDLER_PRIORITY_NEUTRAL, 2);
+}
+
+// add API function
+add_event_handler('ws_add_methods', 'urluploader_ws_add_methods');
+
+include_once(URLUPLOADER_PATH . 'include/functions.inc.php');
+include_once(URLUPLOADER_PATH . 'include/ws_functions.inc.php');
+
+?>
Index: /extensions/url_uploader/maintain.inc.php
===================================================================
--- /extensions/url_uploader/maintain.inc.php	(revision 19804)
+++ /extensions/url_uploader/maintain.inc.php	(revision 19804)
@@ -0,0 +1,9 @@
+<?php
+defined('PHPWG_ROOT_PATH') or die('Hacking attempt!');
+
+function plugin_uninstall() 
+{
+  pwg_query('DELETE FROM `'. CONFIG_TABLE .'` WHERE param = "url_uploader_mode" LIMIT 1;');
+}
+
+?>
Index: /extensions/url_uploader/template/URI.min.js
===================================================================
--- /extensions/url_uploader/template/URI.min.js	(revision 19804)
+++ /extensions/url_uploader/template/URI.min.js	(revision 19804)
@@ -0,0 +1,73 @@
+/*! URI.js v1.8.2 http://medialize.github.com/URI.js/ */
+/* build contains: IPv6.js, punycode.js, SecondLevelDomains.js, URI.js, URITemplate.js */
+(function(f,g){"object"===typeof exports?module.exports=g():"function"===typeof define&&define.amd?define(g):f.IPv6=g()})(this,function(){return{best:function(f){f=f.toLowerCase().split(":");var g=f.length,j=8;""===f[0]&&""===f[1]&&""===f[2]?(f.shift(),f.shift()):""===f[0]&&""===f[1]?f.shift():""===f[g-1]&&""===f[g-2]&&f.pop();g=f.length;-1!==f[g-1].indexOf(".")&&(j=7);var d;for(d=0;d<g&&""!==f[d];d++);if(d<j)for(f.splice(d,1,"0000");f.length<j;)f.splice(d,0,"0000");for(d=0;d<j;d++){for(var g=f[d].split(""),
+m=0;3>m;m++)if("0"===g[0]&&1<g.length)g.splice(0,1);else break;f[d]=g.join("")}var g=-1,u=m=0,h=-1,c=!1;for(d=0;d<j;d++)c?"0"===f[d]?u+=1:(c=!1,u>m&&(g=h,m=u)):"0"==f[d]&&(c=!0,h=d,u=1);u>m&&(g=h,m=u);1<m&&f.splice(g,m,"");g=f.length;j="";""===f[0]&&(beststr=":");for(d=0;d<g;d++){j+=f[d];if(d===g-1)break;j+=":"}""===f[g-1]&&(j+=":");return j}}});
+(function(f){function g(a){throw RangeError(D[a]);}function j(a,b){for(var e=a.length;e--;)a[e]=b(a[e]);return a}function d(a){for(var b=[],e=0,d=a.length,t,c;e<d;)t=a.charCodeAt(e++),55296==(t&63488)&&e<d?(c=a.charCodeAt(e++),56320==(c&64512)?b.push(((t&1023)<<10)+(c&1023)+65536):b.push(t,c)):b.push(t);return b}function m(a){return j(a,function(a){var b="";65535<a&&(a-=65536,b+=A(a>>>10&1023|55296),a=56320|a&1023);return b+=A(a)}).join("")}function u(e,d,t){var c=0;e=t?x(e/b):e>>1;for(e+=x(e/d);e>
+y*s>>1;c+=l)e=x(e/y);return x(c+(y+1)*e/(e+a))}function h(a){var b=[],d=a.length,c,h=0,f=t,w=e,q,j,n,k,r;q=a.lastIndexOf(C);0>q&&(q=0);for(j=0;j<q;++j)128<=a.charCodeAt(j)&&g("not-basic"),b.push(a.charCodeAt(j));for(q=0<q?q+1:0;q<d;){j=h;c=1;for(n=l;;n+=l){q>=d&&g("invalid-input");k=a.charCodeAt(q++);k=10>k-48?k-22:26>k-65?k-65:26>k-97?k-97:l;(k>=l||k>x((p-h)/c))&&g("overflow");h+=k*c;r=n<=w?v:n>=w+s?s:n-w;if(k<r)break;k=l-r;c>x(p/k)&&g("overflow");c*=k}c=b.length+1;w=u(h-j,c,0==j);x(h/c)>p-f&&g("overflow");
+f+=x(h/c);h%=c;b.splice(h++,0,f)}return m(b)}function c(a){var b,c,h,f,w,q,k,j,n,r=[],m,z,y;a=d(a);m=a.length;b=t;c=0;w=e;for(q=0;q<m;++q)n=a[q],128>n&&r.push(A(n));for((h=f=r.length)&&r.push(C);h<m;){k=p;for(q=0;q<m;++q)n=a[q],n>=b&&n<k&&(k=n);z=h+1;k-b>x((p-c)/z)&&g("overflow");c+=(k-b)*z;b=k;for(q=0;q<m;++q)if(n=a[q],n<b&&++c>p&&g("overflow"),n==b){j=c;for(k=l;;k+=l){n=k<=w?v:k>=w+s?s:k-w;if(j<n)break;y=j-n;j=l-n;r.push(A(n+y%j+22+75*(26>n+y%j)-0));j=x(y/j)}r.push(A(j+22+75*(26>j)-0));w=u(c,z,
+h==f);c=0;++h}++c;++b}return r.join("")}var q,n="function"==typeof define&&"object"==typeof define.amd&&define.amd&&define,k="object"==typeof exports&&exports,r="object"==typeof module&&module,p=2147483647,l=36,v=1,s=26,a=38,b=700,e=72,t=128,C="-",w=/[^ -~]/,z=/^xn--/,D={overflow:"Overflow: input needs wider integers to process.","not-basic":"Illegal input >= 0x80 (not a basic code point)","invalid-input":"Invalid input"},y=l-v,x=Math.floor,A=String.fromCharCode,B;q={version:"1.1.1",ucs2:{decode:d,
+encode:m},decode:h,encode:c,toASCII:function(a){return j(a.split("."),function(a){return w.test(a)?"xn--"+c(a):a}).join(".")},toUnicode:function(a){return j(a.split("."),function(a){return z.test(a)?h(a.slice(4).toLowerCase()):a}).join(".")}};if(k)if(r&&r.exports==k)r.exports=q;else for(B in q)q.hasOwnProperty(B)&&(k[B]=q[B]);else n?define("punycode",q):f.punycode=q})(this);
+(function(f,g){"object"===typeof exports?module.exports=g():"function"===typeof define&&define.amd?define(g):f.SecondLevelDomains=g()})(this,function(){var f=Object.prototype.hasOwnProperty,g={list:{ac:"com|gov|mil|net|org",ae:"ac|co|gov|mil|name|net|org|pro|sch",af:"com|edu|gov|net|org",al:"com|edu|gov|mil|net|org",ao:"co|ed|gv|it|og|pb",ar:"com|edu|gob|gov|int|mil|net|org|tur",at:"ac|co|gv|or",au:"asn|com|csiro|edu|gov|id|net|org",ba:"co|com|edu|gov|mil|net|org|rs|unbi|unmo|unsa|untz|unze",bb:"biz|co|com|edu|gov|info|net|org|store|tv",
+bh:"biz|cc|com|edu|gov|info|net|org",bn:"com|edu|gov|net|org",bo:"com|edu|gob|gov|int|mil|net|org|tv",br:"adm|adv|agr|am|arq|art|ato|b|bio|blog|bmd|cim|cng|cnt|com|coop|ecn|edu|eng|esp|etc|eti|far|flog|fm|fnd|fot|fst|g12|ggf|gov|imb|ind|inf|jor|jus|lel|mat|med|mil|mus|net|nom|not|ntr|odo|org|ppg|pro|psc|psi|qsl|rec|slg|srv|tmp|trd|tur|tv|vet|vlog|wiki|zlg",bs:"com|edu|gov|net|org",bz:"du|et|om|ov|rg",ca:"ab|bc|mb|nb|nf|nl|ns|nt|nu|on|pe|qc|sk|yk",ck:"biz|co|edu|gen|gov|info|net|org",cn:"ac|ah|bj|com|cq|edu|fj|gd|gov|gs|gx|gz|ha|hb|he|hi|hl|hn|jl|js|jx|ln|mil|net|nm|nx|org|qh|sc|sd|sh|sn|sx|tj|tw|xj|xz|yn|zj",
+co:"com|edu|gov|mil|net|nom|org",cr:"ac|c|co|ed|fi|go|or|sa",cy:"ac|biz|com|ekloges|gov|ltd|name|net|org|parliament|press|pro|tm","do":"art|com|edu|gob|gov|mil|net|org|sld|web",dz:"art|asso|com|edu|gov|net|org|pol",ec:"com|edu|fin|gov|info|med|mil|net|org|pro",eg:"com|edu|eun|gov|mil|name|net|org|sci",er:"com|edu|gov|ind|mil|net|org|rochest|w",es:"com|edu|gob|nom|org",et:"biz|com|edu|gov|info|name|net|org",fj:"ac|biz|com|info|mil|name|net|org|pro",fk:"ac|co|gov|net|nom|org",fr:"asso|com|f|gouv|nom|prd|presse|tm",
+gg:"co|net|org",gh:"com|edu|gov|mil|org",gn:"ac|com|gov|net|org",gr:"com|edu|gov|mil|net|org",gt:"com|edu|gob|ind|mil|net|org",gu:"com|edu|gov|net|org",hk:"com|edu|gov|idv|net|org",id:"ac|co|go|mil|net|or|sch|web",il:"ac|co|gov|idf|k12|muni|net|org","in":"ac|co|edu|ernet|firm|gen|gov|i|ind|mil|net|nic|org|res",iq:"com|edu|gov|i|mil|net|org",ir:"ac|co|dnssec|gov|i|id|net|org|sch",it:"edu|gov",je:"co|net|org",jo:"com|edu|gov|mil|name|net|org|sch",jp:"ac|ad|co|ed|go|gr|lg|ne|or",ke:"ac|co|go|info|me|mobi|ne|or|sc",
+kh:"com|edu|gov|mil|net|org|per",ki:"biz|com|de|edu|gov|info|mob|net|org|tel",km:"asso|com|coop|edu|gouv|k|medecin|mil|nom|notaires|pharmaciens|presse|tm|veterinaire",kn:"edu|gov|net|org",kr:"ac|busan|chungbuk|chungnam|co|daegu|daejeon|es|gangwon|go|gwangju|gyeongbuk|gyeonggi|gyeongnam|hs|incheon|jeju|jeonbuk|jeonnam|k|kg|mil|ms|ne|or|pe|re|sc|seoul|ulsan",kw:"com|edu|gov|net|org",ky:"com|edu|gov|net|org",kz:"com|edu|gov|mil|net|org",lb:"com|edu|gov|net|org",lk:"assn|com|edu|gov|grp|hotel|int|ltd|net|ngo|org|sch|soc|web",
+lr:"com|edu|gov|net|org",lv:"asn|com|conf|edu|gov|id|mil|net|org",ly:"com|edu|gov|id|med|net|org|plc|sch",ma:"ac|co|gov|m|net|org|press",mc:"asso|tm",me:"ac|co|edu|gov|its|net|org|priv",mg:"com|edu|gov|mil|nom|org|prd|tm",mk:"com|edu|gov|inf|name|net|org|pro",ml:"com|edu|gov|net|org|presse",mn:"edu|gov|org",mo:"com|edu|gov|net|org",mt:"com|edu|gov|net|org",mv:"aero|biz|com|coop|edu|gov|info|int|mil|museum|name|net|org|pro",mw:"ac|co|com|coop|edu|gov|int|museum|net|org",mx:"com|edu|gob|net|org",my:"com|edu|gov|mil|name|net|org|sch",
+nf:"arts|com|firm|info|net|other|per|rec|store|web",ng:"biz|com|edu|gov|mil|mobi|name|net|org|sch",ni:"ac|co|com|edu|gob|mil|net|nom|org",np:"com|edu|gov|mil|net|org",nr:"biz|com|edu|gov|info|net|org",om:"ac|biz|co|com|edu|gov|med|mil|museum|net|org|pro|sch",pe:"com|edu|gob|mil|net|nom|org|sld",ph:"com|edu|gov|i|mil|net|ngo|org",pk:"biz|com|edu|fam|gob|gok|gon|gop|gos|gov|net|org|web",pl:"art|bialystok|biz|com|edu|gda|gdansk|gorzow|gov|info|katowice|krakow|lodz|lublin|mil|net|ngo|olsztyn|org|poznan|pwr|radom|slupsk|szczecin|torun|warszawa|waw|wroc|wroclaw|zgora",
+pr:"ac|biz|com|edu|est|gov|info|isla|name|net|org|pro|prof",ps:"com|edu|gov|net|org|plo|sec",pw:"belau|co|ed|go|ne|or",ro:"arts|com|firm|info|nom|nt|org|rec|store|tm|www",rs:"ac|co|edu|gov|in|org",sb:"com|edu|gov|net|org",sc:"com|edu|gov|net|org",sh:"co|com|edu|gov|net|nom|org",sl:"com|edu|gov|net|org",st:"co|com|consulado|edu|embaixada|gov|mil|net|org|principe|saotome|store",sv:"com|edu|gob|org|red",sz:"ac|co|org",tr:"av|bbs|bel|biz|com|dr|edu|gen|gov|info|k12|name|net|org|pol|tel|tsk|tv|web",tt:"aero|biz|cat|co|com|coop|edu|gov|info|int|jobs|mil|mobi|museum|name|net|org|pro|tel|travel",
+tw:"club|com|ebiz|edu|game|gov|idv|mil|net|org",mu:"ac|co|com|gov|net|or|org",mz:"ac|co|edu|gov|org",na:"co|com",nz:"ac|co|cri|geek|gen|govt|health|iwi|maori|mil|net|org|parliament|school",pa:"abo|ac|com|edu|gob|ing|med|net|nom|org|sld",pt:"com|edu|gov|int|net|nome|org|publ",py:"com|edu|gov|mil|net|org",qa:"com|edu|gov|mil|net|org",re:"asso|com|nom",ru:"ac|adygeya|altai|amur|arkhangelsk|astrakhan|bashkiria|belgorod|bir|bryansk|buryatia|cbg|chel|chelyabinsk|chita|chukotka|chuvashia|com|dagestan|e-burg|edu|gov|grozny|int|irkutsk|ivanovo|izhevsk|jar|joshkar-ola|kalmykia|kaluga|kamchatka|karelia|kazan|kchr|kemerovo|khabarovsk|khakassia|khv|kirov|koenig|komi|kostroma|kranoyarsk|kuban|kurgan|kursk|lipetsk|magadan|mari|mari-el|marine|mil|mordovia|mosreg|msk|murmansk|nalchik|net|nnov|nov|novosibirsk|nsk|omsk|orenburg|org|oryol|penza|perm|pp|pskov|ptz|rnd|ryazan|sakhalin|samara|saratov|simbirsk|smolensk|spb|stavropol|stv|surgut|tambov|tatarstan|tom|tomsk|tsaritsyn|tsk|tula|tuva|tver|tyumen|udm|udmurtia|ulan-ude|vladikavkaz|vladimir|vladivostok|volgograd|vologda|voronezh|vrn|vyatka|yakutia|yamal|yekaterinburg|yuzhno-sakhalinsk",
+rw:"ac|co|com|edu|gouv|gov|int|mil|net",sa:"com|edu|gov|med|net|org|pub|sch",sd:"com|edu|gov|info|med|net|org|tv",se:"a|ac|b|bd|c|d|e|f|g|h|i|k|l|m|n|o|org|p|parti|pp|press|r|s|t|tm|u|w|x|y|z",sg:"com|edu|gov|idn|net|org|per",sn:"art|com|edu|gouv|org|perso|univ",sy:"com|edu|gov|mil|net|news|org",th:"ac|co|go|in|mi|net|or",tj:"ac|biz|co|com|edu|go|gov|info|int|mil|name|net|nic|org|test|web",tn:"agrinet|com|defense|edunet|ens|fin|gov|ind|info|intl|mincom|nat|net|org|perso|rnrt|rns|rnu|tourism",tz:"ac|co|go|ne|or",
+ua:"biz|cherkassy|chernigov|chernovtsy|ck|cn|co|com|crimea|cv|dn|dnepropetrovsk|donetsk|dp|edu|gov|if|in|ivano-frankivsk|kh|kharkov|kherson|khmelnitskiy|kiev|kirovograd|km|kr|ks|kv|lg|lugansk|lutsk|lviv|me|mk|net|nikolaev|od|odessa|org|pl|poltava|pp|rovno|rv|sebastopol|sumy|te|ternopil|uzhgorod|vinnica|vn|zaporizhzhe|zhitomir|zp|zt",ug:"ac|co|go|ne|or|org|sc",uk:"ac|bl|british-library|co|cym|gov|govt|icnet|jet|lea|ltd|me|mil|mod|national-library-scotland|nel|net|nhs|nic|nls|org|orgn|parliament|plc|police|sch|scot|soc",
+us:"dni|fed|isa|kids|nsn",uy:"com|edu|gub|mil|net|org",ve:"co|com|edu|gob|info|mil|net|org|web",vi:"co|com|k12|net|org",vn:"ac|biz|com|edu|gov|health|info|int|name|net|org|pro",ye:"co|com|gov|ltd|me|net|org|plc",yu:"ac|co|edu|gov|org",za:"ac|agric|alt|bourse|city|co|cybernet|db|edu|gov|grondar|iaccess|imt|inca|landesign|law|mil|net|ngo|nis|nom|olivetti|org|pix|school|tm|web",zm:"ac|co|com|edu|gov|net|org|sch"},has_expression:null,is_expression:null,has:function(f){return!!f.match(g.has_expression)},
+is:function(f){return!!f.match(g.is_expression)},get:function(f){return(f=f.match(g.has_expression))&&f[1]||null},init:function(){var j="",d;for(d in g.list)f.call(g.list,d)&&(j+="|("+("("+g.list[d]+")."+d)+")");g.has_expression=RegExp("\\.("+j.substr(1)+")$","i");g.is_expression=RegExp("^("+j.substr(1)+")$","i")}};g.init();return g});
+(function(f,g){"object"===typeof exports?module.exports=g(require("./punycode"),require("./IPv6"),require("./SecondLevelDomains")):"function"===typeof define&&define.amd?define(["./punycode","./IPv6","./SecondLevelDomains"],g):f.URI=g(f.punycode,f.IPv6,f.SecondLevelDomains)})(this,function(f,g,j){function d(a,b){if(!(this instanceof d))return new d(a,b);void 0===a&&(a="undefined"!==typeof location?location.href+"":"");this.href(a);return void 0!==b?this.absoluteTo(b):this}function m(a){return a.replace(/([.*+?^=!:${}()|[\]\/\\])/g,
+"\\$1")}function u(a){return"[object Array]"===String(Object.prototype.toString.call(a))}function h(a){return encodeURIComponent(a).replace(/[!'()*]/g,escape).replace(/\*/g,"%2A")}var c=d.prototype,q=Object.prototype.hasOwnProperty;d._parts=function(){return{protocol:null,username:null,password:null,hostname:null,urn:null,port:null,path:null,query:null,fragment:null,duplicateQueryParameters:d.duplicateQueryParameters}};d.duplicateQueryParameters=!1;d.protocol_expression=/^[a-z][a-z0-9-+-]*$/i;d.idn_expression=
+/[^a-z0-9\.-]/i;d.punycode_expression=/(xn--)/i;d.ip4_expression=/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/;d.ip6_expression=/^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/;
+d.find_uri_expression=/\b((?:[a-z][\w-]+:(?:\/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?\u00ab\u00bb\u201c\u201d\u2018\u2019]))/ig;d.defaultPorts={http:"80",https:"443",ftp:"21",gopher:"70",ws:"80",wss:"443"};d.invalid_hostname_characters=/[^a-zA-Z0-9\.-]/;d.encode=h;d.decode=decodeURIComponent;d.iso8859=function(){d.encode=escape;d.decode=unescape};d.unicode=function(){d.encode=
+h;d.decode=decodeURIComponent};d.characters={pathname:{encode:{expression:/%(24|26|2B|2C|3B|3D|3A|40)/ig,map:{"%24":"$","%26":"&","%2B":"+","%2C":",","%3B":";","%3D":"=","%3A":":","%40":"@"}},decode:{expression:/[\/\?#]/g,map:{"/":"%2F","?":"%3F","#":"%23"}}},reserved:{encode:{expression:/%(21|23|24|26|27|28|29|2A|2B|2C|2F|3A|3B|3D|3F|40|5B|5D)/ig,map:{"%3A":":","%2F":"/","%3F":"?","%23":"#","%5B":"[","%5D":"]","%40":"@","%21":"!","%24":"$","%26":"&","%27":"'","%28":"(","%29":")","%2A":"*","%2B":"+",
+"%2C":",","%3B":";","%3D":"="}}}};d.encodeQuery=function(a){return d.encode(a+"").replace(/%20/g,"+")};d.decodeQuery=function(a){return d.decode((a+"").replace(/\+/g,"%20"))};d.recodePath=function(a){a=(a+"").split("/");for(var b=0,e=a.length;b<e;b++)a[b]=d.encodePathSegment(d.decode(a[b]));return a.join("/")};d.decodePath=function(a){a=(a+"").split("/");for(var b=0,e=a.length;b<e;b++)a[b]=d.decodePathSegment(a[b]);return a.join("/")};var n={encode:"encode",decode:"decode"},k,r=function(a,b){return function(e){return d[b](e+
+"").replace(d.characters[a][b].expression,function(e){return d.characters[a][b].map[e]})}};for(k in n)d[k+"PathSegment"]=r("pathname",n[k]);d.encodeReserved=r("reserved","encode");d.parse=function(a,b){var e;b||(b={});e=a.indexOf("#");-1<e&&(b.fragment=a.substring(e+1)||null,a=a.substring(0,e));e=a.indexOf("?");-1<e&&(b.query=a.substring(e+1)||null,a=a.substring(0,e));"//"===a.substring(0,2)?(b.protocol="",a=a.substring(2),a=d.parseAuthority(a,b)):(e=a.indexOf(":"),-1<e&&(b.protocol=a.substring(0,
+e),b.protocol&&!b.protocol.match(d.protocol_expression)?b.protocol=void 0:"file"===b.protocol?a=a.substring(e+3):"//"===a.substring(e+1,e+3)?(a=a.substring(e+3),a=d.parseAuthority(a,b)):(a=a.substring(e+1),b.urn=!0)));b.path=a;return b};d.parseHost=function(a,b){var e=a.indexOf("/"),d;-1===e&&(e=a.length);"["===a[0]?(d=a.indexOf("]"),b.hostname=a.substring(1,d)||null,b.port=a.substring(d+2,e)||null):a.indexOf(":")!==a.lastIndexOf(":")?(b.hostname=a.substring(0,e)||null,b.port=null):(d=a.substring(0,
+e).split(":"),b.hostname=d[0]||null,b.port=d[1]||null);b.hostname&&"/"!==a.substring(e)[0]&&(e++,a="/"+a);return a.substring(e)||"/"};d.parseAuthority=function(a,b){a=d.parseUserinfo(a,b);return d.parseHost(a,b)};d.parseUserinfo=function(a,b){var e=a.indexOf("@"),t=a.indexOf("/");-1<e&&(-1===t||e<t)?(t=a.substring(0,e).split(":"),b.username=t[0]?d.decode(t[0]):null,t.shift(),b.password=t[0]?d.decode(t.join(":")):null,a=a.substring(e+1)):(b.username=null,b.password=null);return a};d.parseQuery=function(a){if(!a)return{};
+a=a.replace(/&+/g,"&").replace(/^\?*&*|&+$/g,"");if(!a)return{};var b={};a=a.split("&");for(var e=a.length,t,c,h=0;h<e;h++)t=a[h].split("="),c=d.decodeQuery(t.shift()),t=t.length?d.decodeQuery(t.join("=")):null,b[c]?("string"===typeof b[c]&&(b[c]=[b[c]]),b[c].push(t)):b[c]=t;return b};d.build=function(a){var b="";a.protocol&&(b+=a.protocol+":");if(!a.urn&&(b||a.hostname))b+="//";b+=d.buildAuthority(a)||"";"string"===typeof a.path&&("/"!==a.path[0]&&"string"===typeof a.hostname&&(b+="/"),b+=a.path);
+"string"===typeof a.query&&a.query&&(b+="?"+a.query);"string"===typeof a.fragment&&a.fragment&&(b+="#"+a.fragment);return b};d.buildHost=function(a){var b="";if(a.hostname)d.ip6_expression.test(a.hostname)?b=a.port?b+("["+a.hostname+"]:"+a.port):b+a.hostname:(b+=a.hostname,a.port&&(b+=":"+a.port));else return"";return b};d.buildAuthority=function(a){return d.buildUserinfo(a)+d.buildHost(a)};d.buildUserinfo=function(a){var b="";a.username&&(b+=d.encode(a.username),a.password&&(b+=":"+d.encode(a.password)),
+b+="@");return b};d.buildQuery=function(a,b){var e="",c,h,f,g;for(h in a)if(q.call(a,h)&&h)if(u(a[h])){c={};f=0;for(g=a[h].length;f<g;f++)void 0!==a[h][f]&&void 0===c[a[h][f]+""]&&(e+="&"+d.buildQueryParameter(h,a[h][f]),!0!==b&&(c[a[h][f]+""]=!0))}else void 0!==a[h]&&(e+="&"+d.buildQueryParameter(h,a[h]));return e.substring(1)};d.buildQueryParameter=function(a,b){return d.encodeQuery(a)+(null!==b?"="+d.encodeQuery(b):"")};d.addQuery=function(a,b,e){if("object"===typeof b)for(var c in b)q.call(b,
+c)&&d.addQuery(a,c,b[c]);else if("string"===typeof b)void 0===a[b]?a[b]=e:("string"===typeof a[b]&&(a[b]=[a[b]]),u(e)||(e=[e]),a[b]=a[b].concat(e));else throw new TypeError("URI.addQuery() accepts an object, string as the name parameter");};d.removeQuery=function(a,b,e){var c;if(u(b)){e=0;for(c=b.length;e<c;e++)a[b[e]]=void 0}else if("object"===typeof b)for(c in b)q.call(b,c)&&d.removeQuery(a,c,b[c]);else if("string"===typeof b)if(void 0!==e)if(a[b]===e)a[b]=void 0;else{if(u(a[b])){c=a[b];var h={},
+f,g;if(u(e)){f=0;for(g=e.length;f<g;f++)h[e[f]]=!0}else h[e]=!0;f=0;for(g=c.length;f<g;f++)void 0!==h[c[f]]&&(c.splice(f,1),g--,f--);a[b]=c}}else a[b]=void 0;else throw new TypeError("URI.addQuery() accepts an object, string as the first parameter");};d.commonPath=function(a,b){var e=Math.min(a.length,b.length),d;for(d=0;d<e;d++)if(a[d]!==b[d]){d--;break}if(1>d)return a[0]===b[0]&&"/"===a[0]?"/":"";"/"!==a[d]&&(d=a.substring(0,d).lastIndexOf("/"));return a.substring(0,d+1)};d.withinString=function(a,
+b){return a.replace(d.find_uri_expression,b)};d.ensureValidHostname=function(a){if(a.match(d.invalid_hostname_characters)){if(!f)throw new TypeError("Hostname '"+a+"' contains characters other than [A-Z0-9.-] and Punycode.js is not available");if(f.toASCII(a).match(d.invalid_hostname_characters))throw new TypeError("Hostname '"+a+"' contains characters other than [A-Z0-9.-]");}};c.build=function(a){if(!0===a)this._deferred_build=!0;else if(void 0===a||this._deferred_build)this._string=d.build(this._parts),
+this._deferred_build=!1;return this};c.clone=function(){return new d(this)};c.toString=function(){return this.build(!1)._string};c.valueOf=function(){return this.toString()};n={protocol:"protocol",username:"username",password:"password",hostname:"hostname",port:"port"};r=function(a){return function(b,e){if(void 0===b)return this._parts[a]||"";this._parts[a]=b;this.build(!e);return this}};for(k in n)c[k]=r(n[k]);n={query:"?",fragment:"#"};r=function(a,b){return function(e,d){if(void 0===e)return this._parts[a]||
+"";null!==e&&(e+="",e[0]===b&&(e=e.substring(1)));this._parts[a]=e;this.build(!d);return this}};for(k in n)c[k]=r(k,n[k]);n={search:["?","query"],hash:["#","fragment"]};r=function(a,b){return function(e,d){var c=this[a](e,d);return"string"===typeof c&&c.length?b+c:c}};for(k in n)c[k]=r(n[k][1],n[k][0]);c.pathname=function(a,b){if(void 0===a||!0===a){var e=this._parts.path||(this._parts.urn?"":"/");return a?d.decodePath(e):e}this._parts.path=a?d.recodePath(a):"/";this.build(!b);return this};c.path=
+c.pathname;c.href=function(a,b){var e;if(void 0===a)return this.toString();this._string="";this._parts=d._parts();var c=a instanceof d,h="object"===typeof a&&(a.hostname||a.path);!c&&(h&&"[object Object]"!==Object.prototype.toString.call(a))&&(a=a.toString());if("string"===typeof a)this._parts=d.parse(a,this._parts);else if(c||h)for(e in c=c?a._parts:a,c)q.call(this._parts,e)&&(this._parts[e]=c[e]);else throw new TypeError("invalid input");this.build(!b);return this};c.is=function(a){var b=!1,e=!1,
+c=!1,h=!1,f=!1,g=!1,q=!1,k=!this._parts.urn;this._parts.hostname&&(k=!1,e=d.ip4_expression.test(this._parts.hostname),c=d.ip6_expression.test(this._parts.hostname),b=e||c,f=(h=!b)&&j&&j.has(this._parts.hostname),g=h&&d.idn_expression.test(this._parts.hostname),q=h&&d.punycode_expression.test(this._parts.hostname));switch(a.toLowerCase()){case "relative":return k;case "absolute":return!k;case "domain":case "name":return h;case "sld":return f;case "ip":return b;case "ip4":case "ipv4":case "inet4":return e;
+case "ip6":case "ipv6":case "inet6":return c;case "idn":return g;case "url":return!this._parts.urn;case "urn":return!!this._parts.urn;case "punycode":return q}return null};var p=c.protocol,l=c.port,v=c.hostname;c.protocol=function(a,b){if(void 0!==a&&a&&(a=a.replace(/:(\/\/)?$/,""),a.match(/[^a-zA-z0-9\.+-]/)))throw new TypeError("Protocol '"+a+"' contains characters other than [A-Z0-9.+-]");return p.call(this,a,b)};c.scheme=c.protocol;c.port=function(a,b){if(this._parts.urn)return void 0===a?"":
+this;if(void 0!==a&&(0===a&&(a=null),a&&(a+="",":"===a[0]&&(a=a.substring(1)),a.match(/[^0-9]/))))throw new TypeError("Port '"+a+"' contains characters other than [0-9]");return l.call(this,a,b)};c.hostname=function(a,b){if(this._parts.urn)return void 0===a?"":this;if(void 0!==a){var e={};d.parseHost(a,e);a=e.hostname}return v.call(this,a,b)};c.host=function(a,b){if(this._parts.urn)return void 0===a?"":this;if(void 0===a)return this._parts.hostname?d.buildHost(this._parts):"";d.parseHost(a,this._parts);
+this.build(!b);return this};c.authority=function(a,b){if(this._parts.urn)return void 0===a?"":this;if(void 0===a)return this._parts.hostname?d.buildAuthority(this._parts):"";d.parseAuthority(a,this._parts);this.build(!b);return this};c.userinfo=function(a,b){if(this._parts.urn)return void 0===a?"":this;if(void 0===a){if(!this._parts.username)return"";var e=d.buildUserinfo(this._parts);return e.substring(0,e.length-1)}"@"!==a[a.length-1]&&(a+="@");d.parseUserinfo(a,this._parts);this.build(!b);return this};
+c.resource=function(a,b){var e;if(void 0===a)return this.path()+this.search()+this.hash();e=d.parse(a);this._parts.path=e.path;this._parts.query=e.query;this._parts.fragment=e.fragment;this.build(!b);return this};c.subdomain=function(a,b){if(this._parts.urn)return void 0===a?"":this;if(void 0===a){if(!this._parts.hostname||this.is("IP"))return"";var e=this._parts.hostname.length-this.domain().length-1;return this._parts.hostname.substring(0,e)||""}e=this._parts.hostname.length-this.domain().length;
+e=this._parts.hostname.substring(0,e);e=RegExp("^"+m(e));a&&"."!==a[a.length-1]&&(a+=".");a&&d.ensureValidHostname(a);this._parts.hostname=this._parts.hostname.replace(e,a);this.build(!b);return this};c.domain=function(a,b){if(this._parts.urn)return void 0===a?"":this;"boolean"===typeof a&&(b=a,a=void 0);if(void 0===a){if(!this._parts.hostname||this.is("IP"))return"";var e=this._parts.hostname.match(/\./g);if(e&&2>e.length)return this._parts.hostname;e=this._parts.hostname.length-this.tld(b).length-
+1;e=this._parts.hostname.lastIndexOf(".",e-1)+1;return this._parts.hostname.substring(e)||""}if(!a)throw new TypeError("cannot set domain empty");d.ensureValidHostname(a);!this._parts.hostname||this.is("IP")?this._parts.hostname=a:(e=RegExp(m(this.domain())+"$"),this._parts.hostname=this._parts.hostname.replace(e,a));this.build(!b);return this};c.tld=function(a,b){if(this._parts.urn)return void 0===a?"":this;"boolean"===typeof a&&(b=a,a=void 0);if(void 0===a){if(!this._parts.hostname||this.is("IP"))return"";
+var e=this._parts.hostname.lastIndexOf("."),e=this._parts.hostname.substring(e+1);return!0!==b&&j&&j.list[e.toLowerCase()]?j.get(this._parts.hostname)||e:e}if(a)if(a.match(/[^a-zA-Z0-9-]/))if(j&&j.is(a))e=RegExp(m(this.tld())+"$"),this._parts.hostname=this._parts.hostname.replace(e,a);else throw new TypeError("TLD '"+a+"' contains characters other than [A-Z0-9]");else{if(!this._parts.hostname||this.is("IP"))throw new ReferenceError("cannot set TLD on non-domain host");e=RegExp(m(this.tld())+"$");
+this._parts.hostname=this._parts.hostname.replace(e,a)}else throw new TypeError("cannot set TLD empty");this.build(!b);return this};c.directory=function(a,b){if(this._parts.urn)return void 0===a?"":this;if(void 0===a||!0===a){if(!this._parts.path&&!this._parts.hostname)return"";if("/"===this._parts.path)return"/";var e=this._parts.path.length-this.filename().length-1,e=this._parts.path.substring(0,e)||(this._parts.hostname?"/":"");return a?d.decodePath(e):e}e=this._parts.path.length-this.filename().length;
+e=this._parts.path.substring(0,e);e=RegExp("^"+m(e));this.is("relative")||(a||(a="/"),"/"!==a[0]&&(a="/"+a));a&&"/"!==a[a.length-1]&&(a+="/");a=d.recodePath(a);this._parts.path=this._parts.path.replace(e,a);this.build(!b);return this};c.filename=function(a,b){if(this._parts.urn)return void 0===a?"":this;if(void 0===a||!0===a){if(!this._parts.path||"/"===this._parts.path)return"";var e=this._parts.path.lastIndexOf("/"),e=this._parts.path.substring(e+1);return a?d.decodePathSegment(e):e}e=!1;"/"===
+a[0]&&(a=a.substring(1));a.match(/\.?\//)&&(e=!0);var c=RegExp(m(this.filename())+"$");a=d.recodePath(a);this._parts.path=this._parts.path.replace(c,a);e?this.normalizePath(b):this.build(!b);return this};c.suffix=function(a,b){if(this._parts.urn)return void 0===a?"":this;if(void 0===a||!0===a){if(!this._parts.path||"/"===this._parts.path)return"";var e=this.filename(),c=e.lastIndexOf(".");if(-1===c)return"";e=e.substring(c+1);e=/^[a-z0-9%]+$/i.test(e)?e:"";return a?d.decodePathSegment(e):e}"."===
+a[0]&&(a=a.substring(1));if(e=this.suffix())c=a?RegExp(m(e)+"$"):RegExp(m("."+e)+"$");else{if(!a)return this;this._parts.path+="."+d.recodePath(a)}c&&(a=d.recodePath(a),this._parts.path=this._parts.path.replace(c,a));this.build(!b);return this};c.segment=function(a,b,e){var d=this._parts.urn?":":"/",c=this.path(),h="/"===c.substring(0,1),c=c.split(d);"number"!==typeof a&&(e=b,b=a,a=void 0);if(void 0!==a&&"number"!==typeof a)throw Error("Bad segment '"+a+"', must be 0-based integer");h&&c.shift();
+0>a&&(a=Math.max(c.length+a,0));if(void 0===b)return void 0===a?c:c[a];if(null===a||void 0===c[a])if(u(b))c=b;else{if(b||"string"===typeof b&&b.length)""===c[c.length-1]?c[c.length-1]=b:c.push(b)}else b||"string"===typeof b&&b.length?c[a]=b:c.splice(a,1);h&&c.unshift("");return this.path(c.join(d),e)};var s=c.query;c.query=function(a,b){return!0===a?d.parseQuery(this._parts.query):void 0!==a&&"string"!==typeof a?(this._parts.query=d.buildQuery(a,this._parts.duplicateQueryParameters),this.build(!b),
+this):s.call(this,a,b)};c.addQuery=function(a,b,e){var c=d.parseQuery(this._parts.query);d.addQuery(c,a,void 0===b?null:b);this._parts.query=d.buildQuery(c,this._parts.duplicateQueryParameters);"string"!==typeof a&&(e=b);this.build(!e);return this};c.removeQuery=function(a,b,e){var c=d.parseQuery(this._parts.query);d.removeQuery(c,a,b);this._parts.query=d.buildQuery(c,this._parts.duplicateQueryParameters);"string"!==typeof a&&(e=b);this.build(!e);return this};c.addSearch=c.addQuery;c.removeSearch=
+c.removeQuery;c.normalize=function(){return this._parts.urn?this.normalizeProtocol(!1).normalizeQuery(!1).normalizeFragment(!1).build():this.normalizeProtocol(!1).normalizeHostname(!1).normalizePort(!1).normalizePath(!1).normalizeQuery(!1).normalizeFragment(!1).build()};c.normalizeProtocol=function(a){"string"===typeof this._parts.protocol&&(this._parts.protocol=this._parts.protocol.toLowerCase(),this.build(!a));return this};c.normalizeHostname=function(a){this._parts.hostname&&(this.is("IDN")&&f?
+this._parts.hostname=f.toASCII(this._parts.hostname):this.is("IPv6")&&g&&(this._parts.hostname=g.best(this._parts.hostname)),this._parts.hostname=this._parts.hostname.toLowerCase(),this.build(!a));return this};c.normalizePort=function(a){"string"===typeof this._parts.protocol&&this._parts.port===d.defaultPorts[this._parts.protocol]&&(this._parts.port=null,this.build(!a));return this};c.normalizePath=function(a){if(this._parts.urn||!this._parts.path||"/"===this._parts.path)return this;var b,e,c=this._parts.path,
+h,f;"/"!==c[0]&&("."===c[0]&&(e=c.substring(0,c.indexOf("/"))),b=!0,c="/"+c);for(c=c.replace(/(\/(\.\/)+)|\/{2,}/g,"/");;){h=c.indexOf("/../");if(-1===h)break;else if(0===h){c=c.substring(3);break}f=c.substring(0,h).lastIndexOf("/");-1===f&&(f=h);c=c.substring(0,f)+c.substring(h+3)}b&&this.is("relative")&&(c=e?e+c:c.substring(1));c=d.recodePath(c);this._parts.path=c;this.build(!a);return this};c.normalizePathname=c.normalizePath;c.normalizeQuery=function(a){"string"===typeof this._parts.query&&(this._parts.query.length?
+this.query(d.parseQuery(this._parts.query)):this._parts.query=null,this.build(!a));return this};c.normalizeFragment=function(a){this._parts.fragment||(this._parts.fragment=null,this.build(!a));return this};c.normalizeSearch=c.normalizeQuery;c.normalizeHash=c.normalizeFragment;c.iso8859=function(){var a=d.encode,b=d.decode;d.encode=escape;d.decode=decodeURIComponent;this.normalize();d.encode=a;d.decode=b;return this};c.unicode=function(){var a=d.encode,b=d.decode;d.encode=h;d.decode=unescape;this.normalize();
+d.encode=a;d.decode=b;return this};c.readable=function(){var a=this.clone();a.username("").password("").normalize();var b="";a._parts.protocol&&(b+=a._parts.protocol+"://");a._parts.hostname&&(a.is("punycode")&&f?(b+=f.toUnicode(a._parts.hostname),a._parts.port&&(b+=":"+a._parts.port)):b+=a.host());a._parts.hostname&&(a._parts.path&&"/"!==a._parts.path[0])&&(b+="/");b+=a.path(!0);if(a._parts.query){for(var c="",h=0,g=a._parts.query.split("&"),q=g.length;h<q;h++){var k=(g[h]||"").split("="),c=c+("&"+
+d.decodeQuery(k[0]).replace(/&/g,"%26"));void 0!==k[1]&&(c+="="+d.decodeQuery(k[1]).replace(/&/g,"%26"))}b+="?"+c.substring(1)}return b+=a.hash()};c.absoluteTo=function(a){var b=this.clone(),c=["protocol","username","password","hostname","port"],h,f;if(this._parts.urn)throw Error("URNs do not have any generally defined hierachical components");if(this._parts.hostname)return b;a instanceof d||(a=new d(a));h=0;for(f;f=c[h];h++)b._parts[f]=a._parts[f];c=["query","path"];h=0;for(f;f=c[h];h++)!b._parts[f]&&
+a._parts[f]&&(b._parts[f]=a._parts[f]);"/"!==b.path()[0]&&(a=a.directory(),b._parts.path=(a?a+"/":"")+b._parts.path,b.normalizePath());b.build();return b};c.relativeTo=function(a){var b=this.clone(),c=["protocol","username","password","hostname","port"],h;if(this._parts.urn)throw Error("URNs do not have any generally defined hierachical components");a instanceof d||(a=new d(a));if("/"!==this.path()[0]||"/"!==a.path()[0])throw Error("Cannot calculate common path from non-relative URLs");h=d.commonPath(b.path(),
+a.path());if(!h||"/"===h)return b;for(var f=0,g;g=c[f];f++)b._parts[g]=null;a=a.directory();c=this.directory();if(a===c)return b._parts.path="./"+b.filename(),b.build();a.substring(h.length);c=c.substring(h.length);if(a+"/"===h)return c&&(c+="/"),b._parts.path="./"+c+b.filename(),b.build();c="../";h=RegExp("^"+m(h));for(a=a.replace(h,"/").match(/\//g).length-1;a--;)c+="../";b._parts.path=b._parts.path.replace(h,c);return b.build()};c.equals=function(a){var b=this.clone(),c=new d(a),h={},f={};a={};
+var g;b.normalize();c.normalize();if(b.toString()===c.toString())return!0;h=b.query();f=c.query();b.query("");c.query("");if(b.toString()!==c.toString()||h.length!==f.length)return!1;h=d.parseQuery(h);f=d.parseQuery(f);for(g in h)if(q.call(h,g)){if(u(h[g])){if(!u(f[g])||h[g].length!==f[g].length)return!1;h[g].sort();f[g].sort();b=0;for(c=h[g].length;b<c;b++)if(h[g][b]!==f[g][b])return!1}else if(h[g]!==f[g])return!1;a[g]=!0}for(g in f)if(q.call(f,g)&&!a[g])return!1;return!0};c.duplicateQueryParameters=
+function(a){this._parts.duplicateQueryParameters=!!a;return this};return d});
+(function(f,g){"object"===typeof exports?module.exports=g(require("./URI")):"function"===typeof define&&define.amd?define(["./URI"],g):f.URITemplate=g(f.URI)})(this,function(f){function g(d){if(g._cache[d])return g._cache[d];if(!(this instanceof g))return new g(d);this.expression=d;g._cache[d]=this;return this}function j(d){this.data=d;this.cache={}}var d=Object.prototype.hasOwnProperty,m=g.prototype,u={"":{prefix:"",separator:",",named:!1,empty_name_separator:!1,encode:"encode"},"+":{prefix:"",separator:",",
+named:!1,empty_name_separator:!1,encode:"encodeReserved"},"#":{prefix:"#",separator:",",named:!1,empty_name_separator:!1,encode:"encodeReserved"},".":{prefix:".",separator:".",named:!1,empty_name_separator:!1,encode:"encode"},"/":{prefix:"/",separator:"/",named:!1,empty_name_separator:!1,encode:"encode"},";":{prefix:";",separator:";",named:!0,empty_name_separator:!1,encode:"encode"},"?":{prefix:"?",separator:"&",named:!0,empty_name_separator:!0,encode:"encode"},"&":{prefix:"&",separator:"&",named:!0,
+empty_name_separator:!0,encode:"encode"}};g._cache={};g.EXPRESSION_PATTERN=/\{([^a-zA-Z0-9%_]?)([^\}]+)(\}|$)/g;g.VARIABLE_PATTERN=/^([^*:]+)((\*)|:(\d+))?$/;g.VARIABLE_NAME_PATTERN=/[^a-zA-Z0-9%_]/;g.expand=function(d,c){var f=u[d.operator],n=f.named?"Named":"Unnamed",k=d.variables,j=[],p,l,m;for(m=0;l=k[m];m++)p=c.get(l.name),p.val.length?j.push(g["expand"+n](p,f,l.explode,l.explode&&f.separator||",",l.maxlength,l.name)):p.type&&j.push("");return j.length?f.prefix+j.join(f.separator):""};g.expandNamed=
+function(d,c,g,n,k,j){var p="",l=c.encode;c=c.empty_name_separator;var m=!d[l].length,s=2===d.type?"":f[l](j),a,b,e;b=0;for(e=d.val.length;b<e;b++)k?(a=f[l](d.val[b][1].substring(0,k)),2===d.type&&(s=f[l](d.val[b][0].substring(0,k)))):m?(a=f[l](d.val[b][1]),2===d.type?(s=f[l](d.val[b][0]),d[l].push([s,a])):d[l].push([void 0,a])):(a=d[l][b][1],2===d.type&&(s=d[l][b][0])),p&&(p+=n),g?p+=s+(c||a?"=":"")+a:(b||(p+=f[l](j)+(c||a?"=":"")),2===d.type&&(p+=s+","),p+=a);return p};g.expandUnnamed=function(d,
+c,g,j,k){var r="",p=c.encode;c=c.empty_name_separator;var l=!d[p].length,m,s,a,b;a=0;for(b=d.val.length;a<b;a++)k?s=f[p](d.val[a][1].substring(0,k)):l?(s=f[p](d.val[a][1]),d[p].push([2===d.type?f[p](d.val[a][0]):void 0,s])):s=d[p][a][1],r&&(r+=j),2===d.type&&(m=k?f[p](d.val[a][0].substring(0,k)):d[p][a][0],r+=m,r=g?r+(c||s?"=":""):r+","),r+=s;return r};m.expand=function(d){var c="";(!this.parts||!this.parts.length)&&this.parse();d instanceof j||(d=new j(d));for(var f=0,n=this.parts.length;f<n;f++)c+=
+"string"===typeof this.parts[f]?this.parts[f]:g.expand(this.parts[f],d);return c};m.parse=function(){var d=this.expression,c=g.EXPRESSION_PATTERN,f=g.VARIABLE_PATTERN,j=g.VARIABLE_NAME_PATTERN,k=[],m=0,p,l,v;for(c.lastIndex=0;;){l=c.exec(d);if(null===l){k.push(d.substring(m));break}else k.push(d.substring(m,l.index)),m=l.index+l[0].length;if(u[l[1]]){if(!l[3])throw Error('Unclosed Expression "'+l[0]+'"');}else throw Error('Unknown Operator "'+l[1]+'" in "'+l[0]+'"');p=l[2].split(",");for(var s=0,
+a=p.length;s<a;s++){v=p[s].match(f);if(null===v)throw Error('Invalid Variable "'+p[s]+'" in "'+l[0]+'"');if(v[1].match(j))throw Error('Invalid Variable Name "'+v[1]+'" in "'+l[0]+'"');p[s]={name:v[1],explode:!!v[3],maxlength:v[4]&&parseInt(v[4],10)}}if(!p.length)throw Error('Expression Missing Variable(s) "'+l[0]+'"');k.push({expression:l[0],operator:l[1],variables:p})}k.length||k.push(d);this.parts=k;return this};j.prototype.get=function(f){var c=this.data,g={type:0,val:[],encode:[],encodeReserved:[]},
+j;if(void 0!==this.cache[f])return this.cache[f];this.cache[f]=g;c="[object Function]"===String(Object.prototype.toString.call(c))?c(f):"[object Function]"===String(Object.prototype.toString.call(c[f]))?c[f](f):c[f];if(!(void 0===c||null===c))if("[object Array]"===String(Object.prototype.toString.call(c))){j=0;for(f=c.length;j<f;j++)void 0!==c[j]&&null!==c[j]&&g.val.push([void 0,String(c[j])]);g.val.length&&(g.type=3)}else if("[object Object]"===String(Object.prototype.toString.call(c))){for(j in c)d.call(c,
+j)&&(void 0!==c[j]&&null!==c[j])&&g.val.push([j,String(c[j])]);g.val.length&&(g.type=2)}else g.type=1,g.val.push([void 0,String(c)]);return g};f.expand=function(d,c){var j=(new g(d)).expand(c);return new f(j)};return g});
Index: /extensions/url_uploader/template/createTextareaWithLines.js
===================================================================
--- /extensions/url_uploader/template/createTextareaWithLines.js	(revision 19804)
+++ /extensions/url_uploader/template/createTextareaWithLines.js	(revision 19804)
@@ -0,0 +1,48 @@
+function createTextAreaWithLines(id) {
+  var el = document.createElement('TEXTAREA');
+  var ta = document.getElementById(id);
+
+  el.style.resize = 'none';
+  ta.style.resize = 'none';
+  ta.wrap = 'off';
+
+  var string = '';
+  for (var no=1;no<1000;no++) {
+    if (string.length>0) string += '\n';
+    string += no;
+  }
+  
+  el.className      = 'textAreaWithLines';
+  el.style.height   = (ta.offsetHeight-3) + "px";
+  el.style.display  = "block";
+  el.style.width    = "25px";
+  el.style.position = "absolute";
+  el.style.overflow = 'hidden';
+  el.style.textAlign = 'right';
+  el.style.paddingRight = '0.2em';
+  el.innerHTML      = string;  //Firefox renders \n linebreak
+  el.innerText      = string; //IE6 renders \n line break
+  el.style.zIndex   = 0;
+  el.style.border   = "none";
+  el.style.background = "none";
+  
+  ta.style.marginLeft = "20px"
+  ta.style.zIndex   = 1;
+  ta.style.position = "relative";
+  ta.parentNode.insertBefore(el, ta.nextSibling);
+
+  setLine();
+  ta.onkeydown    = function() { setLine(); }
+  ta.onmousedown  = function() { setLine(); }
+  ta.onscroll     = function() { setLine(); }
+  ta.onblur       = function() { setLine(); }
+  ta.onfocus      = function() { setLine(); }
+  ta.onmouseover  = function() { setLine(); }
+  ta.onmouseup    = function() { setLine(); }
+
+  function setLine() {
+    el.scrollTop   = ta.scrollTop;
+    el.style.top   = (ta.offsetTop) + "px";
+    el.style.left  = (ta.offsetLeft - 27) + "px";
+  }
+}
Index: /extensions/url_uploader/template/index.php
===================================================================
--- /extensions/url_uploader/template/index.php	(revision 19804)
+++ /extensions/url_uploader/template/index.php	(revision 19804)
@@ -0,0 +1,7 @@
+<?php
+$url = '../';
+header( 'Request-URI: '.$url );
+header( 'Content-Location: '.$url );
+header( 'Location: '.$url );
+exit();
+?>
Index: /extensions/url_uploader/template/photos_add.tpl
===================================================================
--- /extensions/url_uploader/template/photos_add.tpl	(revision 19804)
+++ /extensions/url_uploader/template/photos_add.tpl	(revision 19804)
@@ -0,0 +1,451 @@
+{combine_css path=$URLUPLOADER_PATH|@cat:"template/style.css"}
+{combine_script id="URI" load="footer" path=$URLUPLOADER_PATH|@cat:"template/URI.min.js"}
+{combine_script id="createTextareaWithLines" load="footer" path=$URLUPLOADER_PATH|@cat:"template/createTextareaWithLines.js"}
+
+{if $upload_mode == 'multiple'}
+{combine_script id='jquery.ajaxmanager' load='footer' path='themes/default/js/plugins/jquery.ajaxmanager.js'}
+{combine_script id='jquery.jgrowl' load='footer' require='jquery' path='themes/default/js/plugins/jquery.jgrowl_minimized.js' }
+{combine_script id='jquery.ui.progressbar' load='footer'}
+{combine_css path="admin/themes/default/uploadify.jGrowl.css"}
+{/if}
+
+{include file='include/colorbox.inc.tpl'}
+{include file='include/add_album.inc.tpl'}
+
+
+{footer_script}
+var allowed_extensions = new Array('jpeg','jpg','png','gif');
+var errorHead   = '{'ERROR'|@translate|@escape:'javascript'}';
+var errorMsg    = '{'an error happened'|@translate|@escape:'javascript'}';
+
+var lang = new Array();
+lang['Invalid file URL'] = '{'Invalid file URL'|@translate|@escape:'javascript'}';
+lang['Invalid file type'] = '{'Invalid file type'|@translate|@escape:'javascript'}';
+lang['File URL is empty'] = '{'File URL is empty'|@translate|@escape:'javascript'}';
+lang['Unable to download file'] = '{'Unable to download file'|@translate|@escape:'javascript'}';
+lang['Pending'] = '{'Pending'|@translate|@escape:'javascript'}';
+lang['Delete this item'] = '{'Delete this item'|@translate|@escape:'javascript'}';
+
+{literal}
+jQuery("#hideErrors").click(function() {
+    jQuery("#formErrors").hide();
+    return false;
+  });
+  
+jQuery("#uploadWarningsSummary a.showInfo").click(function() {
+    jQuery("#uploadWarningsSummary").hide();
+    jQuery("#uploadWarnings").show();
+    return false;
+  });
+  
+jQuery("#showPermissions").click(function() {
+    jQuery(this).parent(".showFieldset").hide();
+    jQuery("#permissions").show();
+    return false;
+  });
+{/literal}
+
+
+{* <!-- MULTIPLE UPLOAD --> *}
+{if $upload_mode == 'multiple'}
+{literal}
+function checkUploadStart() {
+  var nbErrors = 0;
+  
+  jQuery("#formErrors").hide();
+  jQuery("#formErrors li").hide();
+
+  if (jQuery("#albumSelect option:selected").length == 0) {
+    jQuery("#formErrors #noAlbum").show();
+    nbErrors++;
+  }
+  
+  var nbFiles = jQuery("table#links tr.pending").length;
+  
+  if (nbFiles == 0) {
+    jQuery("#formErrors #noPhoto").show();
+    nbErrors++;
+  }
+
+  if (nbErrors != 0) {
+    jQuery("#formErrors").show();
+    return false;
+  }
+  else {
+    return true;
+  }
+}
+
+function trim (myString) {
+  return myString.replace(/^\s+/g,'').replace(/\s+$/g,'')
+}
+
+jQuery("input[name='add_links']").click(function() {
+  $input = jQuery("textarea#urls");
+  
+  if ($input.val() != "") {
+    jQuery("table#links").show();
+    
+    lines = $input.val().split('\n');
+    $input.val("");
+    
+    for (i in lines) {
+      line = lines[i].split('|');
+      item = new Array;
+      
+      // no name given
+      if (line.length == 1) {
+        uri = new URI(trim(line[0]));
+        item['name'] = "";
+      }
+      // name given
+      else {
+        uri = new URI(trim(line[1]));
+        item['name']= trim(line[0]);
+      }
+      
+      uri.fragment("");
+      item['url'] = uri.href();
+      item['short_url'] = item['url'];
+      
+      // shortened url for display
+      if (item['url'].length > 40) {
+        item['short_url'] = item['url'].substring(0, 17) + ' ... ' + item['url'].substring(item['url'].length-17);
+      }
+      
+      // check if consistent url
+      if (uri.is("relative")) {
+        item['status'] = 'error';
+        item['info'] = lang['Invalid file URL'];
+      }
+      else {
+        // check if good extension
+        if (allowed_extensions.indexOf(uri.suffix().toLowerCase()) == -1) {
+          item['status'] = 'error';
+          item['info'] = lang['Invalid file type'];
+        }
+        else {
+          item['status'] = 'pending';
+          item['info'] = lang['Pending'];
+        }
+      }
+      
+      // add link to table
+      jQuery("table#links tbody").append('<tr class="'+ item['status'] + '" data-name="'+ item['name'] +'" data-url="'+ item['url'] +'">'+
+        '<td>'+ item['name'] +'</td>'+
+        '<td><a href="'+ item['url'] +'">'+ item['short_url'] +'</a></td>'+
+        '<td>'+ item['info'] +'</td>'+
+        '<td><a class="delete" title="'+ lang['Delete this item'] +'">&nbsp;</a></td>'+
+      '</tr>');
+    }
+  }
+  
+  $input.focus();
+  return false;
+});
+
+jQuery("table#links").on("click", "a.delete", function() {
+  $(this).parents("tr").remove();
+  jQuery("textarea#urls").focus();
+});
+
+/* <!-- AJAX MANAGER --> */
+var import_done = 0;
+var import_selected = 0;
+var queuedManager = jQuery.manageAjax.create('queued', {
+  queue: true,  
+  maxRequests: 1
+});
+
+function performImport(file_url, category, name, level, $target) {
+  queuedManager.add({
+    type: 'GET',
+    dataType: 'json',
+    url: 'ws.php',
+    data: { method: 'pwg.images.addRemote', file_url: file_url, category: category, name: name, level: level, format: 'json' },
+    success: function(data) {
+      if (data['stat'] == 'ok') {
+        $target.remove();
+        jQuery("#uploadedPhotos").parent("fieldset").show();
+        jQuery("#uploadedPhotos").prepend('<img src="'+ data['result']['thumbnail_url'] +'" class="thumbnail"> ');
+        jQuery("#uploadForm").append('<input type="hidden" name="imageIds[]" value="'+ data['result']['image_id'] +'">');
+      }
+      else {
+        jQuery.jGrowl(name +' : '+ lang[data['message']], { 
+          theme: 'error', 
+          header: errorHead, 
+          sticky: true 
+          });
+          
+        $target.children("td:nth-child(3)").html(lang[data['message']]);
+        jQuery("#uploadForm").append('<input type="hidden" name="onUploadError[]" value="'+ file_url +' : '+ lang[data['message']] +'">');
+      }
+      
+      import_done++;
+      jQuery("#progressbar").progressbar({value: import_done});
+      jQuery("#progressCurrent").text(import_done);
+      
+      if (import_done == import_selected) {
+        $("#uploadForm").submit();
+      }
+    },
+    error: function(data) {
+      jQuery.jGrowl(name +' : '+ errorMsg, { 
+        theme: 'error', 
+        header: errorHead, 
+        sticky: true 
+        });
+      
+      $target.children("td:nth-child(3)").html(errorMsg);
+    }
+  });
+}
+
+jQuery("input[name='submit_upload']").click(function() {
+  if (!checkUploadStart()) {
+    return false;
+  }
+  
+  import_selected = jQuery("table#links tr.pending").length;
+  
+  jQuery("table#links a.delete").hide();
+  
+  jQuery("#progressbar").progressbar({max: import_selected, value:0});
+  jQuery("#progressMax").text(import_selected);
+  jQuery("#progressCurrent").text(0);
+  jQuery("#uploadProgress").show();
+  
+  jQuery("table#links tr.pending").each(function() {
+    performImport(
+      $(this).data('url'),
+      $("select[name=category] option:selected").val(),
+      $(this).data('name'),
+      $("select[name=level] option:selected").val(),
+      $(this)
+      );
+  });
+    
+  return false;
+});
+
+createTextAreaWithLines('urls');
+{/literal}
+
+
+{* <!-- SINGLE UPLOAD --> *}
+{else}
+{literal}
+function checkUploadStart() {
+  var nbErrors = 0;
+  
+  jQuery("#formErrors").hide();
+  jQuery("#formErrors li").hide();
+
+  if (jQuery("#albumSelect option:selected").length == 0) {
+    jQuery("#formErrors #noAlbum").show();
+    nbErrors++;
+  }
+  
+  if (jQuery("input[name='file_url']").val() == "") {
+    jQuery("#formErrors #urlEmpty").show();
+    nbErrors++;
+  }
+  else {
+    uri = new URI(jQuery("input[name='file_url']").val());
+    if (uri.is('relative')) {
+      jQuery("#formErrors #urlError").show();
+      nbErrors++;
+    }
+    else if (allowed_extensions.indexOf(uri.suffix().toLowerCase()) == -1) {
+      jQuery("#formErrors #typeError").show();
+      nbErrors++;
+    }
+  }
+
+  if (nbErrors != 0) {
+    jQuery("#formErrors").show();
+    return false;
+  }
+  else {
+    return true;
+  }
+}
+
+jQuery("input[name='submit_upload']").click(function() {
+  return checkUploadStart();
+});
+{/literal}
+{/if}
+
+{/footer_script}
+
+
+{html_head}{literal}
+<style type="text/css">
+a.delete {
+  background:url('admin/include/uploadify/cancel.png');
+}
+</style>
+{/literal}{/html_head}
+
+
+<div class="titrePage">
+  <h2>{'Upload Photos'|@translate} {$TABSHEET_TITLE}</h2>
+</div>
+
+<div id="photosAddContent">
+
+{if count($setup_errors) > 0}
+<div class="errors">
+  <ul>
+  {foreach from=$setup_errors item=error}
+    <li>{$error}</li>
+  {/foreach}
+  </ul>
+</div>
+{else}
+
+  {if count($setup_warnings) > 0}
+<div class="warnings">
+  <ul>
+    {foreach from=$setup_warnings item=warning}
+    <li>{$warning}</li>
+    {/foreach}
+  </ul>
+  <div class="hideButton" style="text-align:center"><a href="{$hide_warnings_link}">{'Hide'|@translate}</a></div>
+</div>
+  {/if}
+  
+{if !empty($thumbnails)}
+<fieldset>
+  <legend>{'Uploaded Photos'|@translate}</legend>
+  <div>
+  {foreach from=$thumbnails item=thumbnail}
+    <a href="{$thumbnail.link}" class="externalLink">
+      <img src="{$thumbnail.src}" alt="{$thumbnail.file}" title="{$thumbnail.title}" class="thumbnail">
+    </a>
+  {/foreach}
+  </div>
+  <p id="batchLink"><a href="{$batch_link}">{$batch_label}</a></p>
+</fieldset>
+<p style="margin:10px"><a href="{$another_upload_link}">{'Add another set of photos'|@translate}</a></p>
+{else}
+
+<div id="formErrors" class="errors" style="display:none">
+  <ul>
+    <li id="noAlbum">{'Select an album'|@translate}</li>
+    <li id="noPhoto">{'Select at least one photo'|@translate}</li>
+    <li id="urlEmpty">{'File URL is empty'|@translate}</li>
+    <li id="urlError">{'Invalid file URL'|@translate}</li>
+    <li id="typeError">{'Invalid file type'|@translate}</li>
+  </ul>
+  <div class="hideButton" style="text-align:center"><a href="#" id="hideErrors">{'Hide'|@translate}</a></div>
+</div>
+
+<form id="uploadForm" enctype="multipart/form-data" method="post" action="{$form_action}" class="properties">
+    <fieldset>
+      <legend>{'Drop into album'|@translate}</legend>
+
+      <span id="albumSelection"{if count($category_options) == 0} style="display:none"{/if}>
+      <select id="albumSelect" name="category">
+        {html_options options=$category_options selected=$category_options_selected}
+      </select>
+      <br>{'... or '|@translate}</span><a href="#" class="addAlbumOpen" title="{'create a new album'|@translate}">{'create a new album'|@translate}</a>
+      
+    </fieldset>
+
+    <fieldset>
+      <legend>{'Select files'|@translate}</legend>
+      
+      <p id="uploadWarningsSummary">
+        {'Allowed file types: %s.'|@translate|@sprintf:$upload_file_types}
+      {if isset($max_upload_resolution)}
+        {$max_upload_resolution}Mpx
+        <a class="showInfo" title="{'Learn more'|@translate}">i</a>
+      {/if}
+      </p>
+
+      <p id="uploadWarnings">
+        {'Allowed file types: %s.'|@translate|@sprintf:$upload_file_types}
+      {if isset($max_upload_resolution)}
+        {'Approximate maximum resolution: %dM pixels (that\'s %dx%d pixels).'|@translate|@sprintf:$max_upload_resolution:$max_upload_width:$max_upload_height}
+      {/if}
+      </p>
+
+{* <!-- SINGLE UPLOAD --> *}
+{if $upload_mode == 'single'}
+      <ul>
+        <li>
+          <label>
+            <span class="property">{'File URL'|@translate}</span>
+            <input type="text" name="file_url" size="70">
+          </label>
+        </li>
+        <li>
+          <label>
+            <span class="property">{'Photo name'|@translate}</span>
+            <input type="text" name="photo_name" size="40">
+          </label>
+        </li>
+      </ul>      
+      
+      <p id="uploadModeInfos">{'Want to upload many files? Try the <a href="%s">multiple uploader</a> instead.'|@translate|@sprintf:$switch_url}</p>
+
+{* <!-- MULTIPLE UPLOAD --> *}
+{else}
+
+      <table id="links" class="table2" style="display:none;">
+        <thead>
+          <tr class="throw">
+            <th style="width:150px;">{'Photo name'|@translate}</th>
+            <th>{'File URL'|@translate}</th>
+            <th style="width:150px;">{'Status'|@translate}</th>
+            <th style="width:20px;"></th>
+          </tr>
+        </thead>
+        <tbody>
+        </tbody>
+      </table>
+      
+      <p>
+        {'One link by line, separate photo name and url with a &laquo; | &raquo;. Photo name is optional.'|@translate}
+        <br>
+        <textarea id="urls"></textarea>
+      </p>
+      <input type="submit" name="add_links" value="{'Add links'|@translate}">
+      
+      <p id="uploadModeInfos">{'Multiple uploader doesn\'t work? Try the <a href="%s">single uploader</a> instead.'|@translate|@sprintf:$switch_url}</p>
+{/if}
+    </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>
+    
+    <p>
+      <input class="submit" type="submit" name="submit_upload" value="{'Start Upload'|@translate}">
+    </p>
+</form>
+
+<div id="uploadProgress" style="display:none">
+{'Photo %s of %s'|@translate|@sprintf:'<span id="progressCurrent">1</span>':'<span id="progressMax">10</span>'}
+<br>
+<div id="progressbar"></div>
+</div>
+
+<fieldset style="display:none">
+  <legend>{'Uploaded Photos'|@translate}</legend>
+  <div id="uploadedPhotos"></div>
+</fieldset>
+
+{/if} {* empty($thumbnails) *}
+{/if} {* $setup_errors *}
+
+<br>
+</div> <!-- photosAddContent -->
Index: /extensions/url_uploader/template/style.css
===================================================================
--- /extensions/url_uploader/template/style.css	(revision 19804)
+++ /extensions/url_uploader/template/style.css	(revision 19804)
@@ -0,0 +1,53 @@
+.showInfo {
+  position:static;
+  display:inline-block;
+  padding:1px 6px;
+  width:4px;
+  height:14px;
+  line-height:14px;
+  font-size:0.8em;
+}
+
+FORM.properties SPAN.property {
+  width:180px;
+}
+
+a.delete {
+  display:inline-block;
+  width:16px;
+  height:16px;
+  border:none;
+}
+
+table.table2 {
+  margin-bottom:10px;
+  width:100%;
+}
+.table2 .throw {
+  font-size:12px;
+}
+.table2 .throw th {
+  text-align:left !important;
+  line-height:20px;
+}
+.table2 tbody td {
+  height:18px;
+}
+.table2 tbody tr:not(:last-child) td:not(:last-child) {
+  border-bottom:1px solid rgba(0, 0, 0, 0.3);
+}
+.table2 tbody tr.error {
+  background:rgba(255, 0, 0, 0.3);
+}
+
+#urls {
+  width:630px;
+  height:140px;
+  margin-bottom:5px;
+  font-size:12px;
+  line-height:14px;
+}
+.textAreaWithLines {
+  font-size:12px;
+  line-height:14px;
+}
