function URI_builder()
{
  var processing   = "PATH";
  var result       = "";
  var SCHEME       = "";
  var AUTHORITY    = "";
  var PATH         = "";
  var QUERY        = "";
  var FRAGMENT     = "";
  var PATH_part    = "";
  var i            = 0;
  var j            = 0;
  var _AUTHORITY_i = 0;
  var _PATH_i      = 0;
  var _QUERY_i     = 0;
  var _AUTHORITY   = new Array();
  var _PATH        = new Array();
  var PATH_pieces  = new Array();
  var _QUERY       = new Array();
  var name_value   = new Array();

/*
 * Collect components
 */

  for ( i = 0; i < arguments.length; i++ )
  {
    if ( arguments[i] == "SCHEME")
    {
      processing = "SCHEME";
      continue;
    }
    if ( arguments[i] == "AUTHORITY")
    {
      processing = "AUTHORITY";
      continue;
    }
    if ( arguments[i] == "PATH")
    {
      processing = "PATH";
      continue;
    }
    if ( arguments[i] == "QUERY")
    {
      processing = "QUERY";
      continue;
    }
    if ( arguments[i] == "FRAGMENT")
    {
      processing = "FRAGMENT";
      continue;
    }
    if ( processing )
    {
      if ( processing == "SCHEME" ) SCHEME = arguments[i];
      if ( processing == "AUTHORITY" )
      {
        _AUTHORITY[_AUTHORITY_i] = arguments[i];
        _AUTHORITY_i++;
      }
      if ( processing == "PATH" )
      {
        _PATH[_PATH_i] = arguments[i];
        _PATH_i++;
      }
      if ( processing == "QUERY" )
      {
        _QUERY[_QUERY_i] = arguments[i];
        _QUERY_i++;
      }
      if ( processing == "FRAGMENT" ) FRAGMENT = arguments[i];
    }
  }

/*
 * Process components
 */

  if ( SCHEME.indexOf(":") > -1 )
  {
    SCHEME = SCHEME.substring(0, SCHEME.indexOf(":"));
  }

  for ( i = 0; i < _AUTHORITY.length; i++ )
  {
    AUTHORITY ?
      AUTHORITY = AUTHORITY + "." + _AUTHORITY[i] :
      AUTHORITY = _AUTHORITY[i];
  }
  if ( AUTHORITY.charAt(0) == "/" && AUTHORITY.charAt(1) == "/" )
  {
    AUTHORITY = AUTHORITY.substring(2);
  }

  for ( i = 0; i < _PATH.length; i++ )
  {
    if ( _PATH[i].indexOf("/") > -1 )
    {
      PATH_pieces = _PATH[i].split("/");
      for ( j = 0; j < PATH_pieces.length; j++ )
      {
        if ( PATH_pieces[j].indexOf("%") > -1 )
        {
          PATH_pieces = unescape(PATH_pieces[j]);
        }
        PATH_part ?
          PATH_part = PATH_part + "/" + escape(PATH_pieces[j]) :
          PATH_part = escape(PATH_pieces[j]);
      }
        PATH ?
          PATH = PATH + "/" + PATH_part :
          PATH = PATH_part;
    }
    else
    {
      if ( _PATH[i].indexOf("%") > -1 ) _PATH[i] = unescape(_PATH[i]);
      PATH ?
        PATH = PATH + "/" + escape(_PATH[i]) :
        PATH = escape(_PATH[i]);
    }
  }
  if ( PATH.charAt(0) != "/" ) PATH = "/" + PATH;

  for ( i = 0; i < _QUERY.length; i++ )
  {
    name_value = _QUERY[i].split("=");
    if ( name_value[0].indexOf("%") > -1 )
    {
      name_value[0] = unescape(name_value[0]);
    }
    if ( name_value[1].indexOf("%") > -1 )
    {
      name_value[1] = unescape(name_value[1]);
    }
    QUERY ?
      QUERY = QUERY + ";" +
              escape(name_value[0]) + "=" + escape(name_value[1]) :
      QUERY = escape(name_value[0]) + "=" + escape(name_value[1]);
  }
  
//  if ( FRAGMENT.indexOf("%") > -1 ) FRAGMENT = unescape(FRAGMENT);
  if ( FRAGMENT.charAt(0) == "#" )
  {  
    FRAGMENT = FRAGMENT.substring(1) // escape(FRAGMENT.substring(1));
  }
  else
  {
    FRAGMENT = FRAGMENT // escape(FRAGMENT);
  }

/*
 * Assemble URI
 */

  if ( SCHEME )    result = SCHEME + ":";
  if ( AUTHORITY ) result ?
                     result = result + "//" + AUTHORITY :
                     result = "//" + AUTHORITY
  if ( PATH )      result ?
                     result = result + PATH :
                     result = PATH;
  if ( QUERY )     result ?
                     result = result + "?" + QUERY :
                     result = "?" + QUERY;
  if ( FRAGMENT )  result ?
                     result = result + "#" + FRAGMENT :
                     result = "#" + FRAGMENT;

/*
 * Return URI
 */

  return result;
}
