Blame libdjvu/GURL.cpp

Packit df99a1
//C-  -*- C++ -*-
Packit df99a1
//C- -------------------------------------------------------------------
Packit df99a1
//C- DjVuLibre-3.5
Packit df99a1
//C- Copyright (c) 2002  Leon Bottou and Yann Le Cun.
Packit df99a1
//C- Copyright (c) 2001  AT&T
Packit df99a1
//C-
Packit df99a1
//C- This software is subject to, and may be distributed under, the
Packit df99a1
//C- GNU General Public License, either Version 2 of the license,
Packit df99a1
//C- or (at your option) any later version. The license should have
Packit df99a1
//C- accompanied the software or you may obtain a copy of the license
Packit df99a1
//C- from the Free Software Foundation at http://www.fsf.org .
Packit df99a1
//C-
Packit df99a1
//C- This program is distributed in the hope that it will be useful,
Packit df99a1
//C- but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit df99a1
//C- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit df99a1
//C- GNU General Public License for more details.
Packit df99a1
//C- 
Packit df99a1
//C- DjVuLibre-3.5 is derived from the DjVu(r) Reference Library from
Packit df99a1
//C- Lizardtech Software.  Lizardtech Software has authorized us to
Packit df99a1
//C- replace the original DjVu(r) Reference Library notice by the following
Packit df99a1
//C- text (see doc/lizard2002.djvu and doc/lizardtech2007.djvu):
Packit df99a1
//C-
Packit df99a1
//C-  ------------------------------------------------------------------
Packit df99a1
//C- | DjVu (r) Reference Library (v. 3.5)
Packit df99a1
//C- | Copyright (c) 1999-2001 LizardTech, Inc. All Rights Reserved.
Packit df99a1
//C- | The DjVu Reference Library is protected by U.S. Pat. No.
Packit df99a1
//C- | 6,058,214 and patents pending.
Packit df99a1
//C- |
Packit df99a1
//C- | This software is subject to, and may be distributed under, the
Packit df99a1
//C- | GNU General Public License, either Version 2 of the license,
Packit df99a1
//C- | or (at your option) any later version. The license should have
Packit df99a1
//C- | accompanied the software or you may obtain a copy of the license
Packit df99a1
//C- | from the Free Software Foundation at http://www.fsf.org .
Packit df99a1
//C- |
Packit df99a1
//C- | The computer code originally released by LizardTech under this
Packit df99a1
//C- | license and unmodified by other parties is deemed "the LIZARDTECH
Packit df99a1
//C- | ORIGINAL CODE."  Subject to any third party intellectual property
Packit df99a1
//C- | claims, LizardTech grants recipient a worldwide, royalty-free, 
Packit df99a1
//C- | non-exclusive license to make, use, sell, or otherwise dispose of 
Packit df99a1
//C- | the LIZARDTECH ORIGINAL CODE or of programs derived from the 
Packit df99a1
//C- | LIZARDTECH ORIGINAL CODE in compliance with the terms of the GNU 
Packit df99a1
//C- | General Public License.   This grant only confers the right to 
Packit df99a1
//C- | infringe patent claims underlying the LIZARDTECH ORIGINAL CODE to 
Packit df99a1
//C- | the extent such infringement is reasonably necessary to enable 
Packit df99a1
//C- | recipient to make, have made, practice, sell, or otherwise dispose 
Packit df99a1
//C- | of the LIZARDTECH ORIGINAL CODE (or portions thereof) and not to 
Packit df99a1
//C- | any greater extent that may be necessary to utilize further 
Packit df99a1
//C- | modifications or combinations.
Packit df99a1
//C- |
Packit df99a1
//C- | The LIZARDTECH ORIGINAL CODE is provided "AS IS" WITHOUT WARRANTY
Packit df99a1
//C- | OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
Packit df99a1
//C- | TO ANY WARRANTY OF NON-INFRINGEMENT, OR ANY IMPLIED WARRANTY OF
Packit df99a1
//C- | MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
Packit df99a1
//C- +------------------------------------------------------------------
Packit df99a1
Packit df99a1
#ifdef HAVE_CONFIG_H
Packit df99a1
# include "config.h"
Packit df99a1
#endif
Packit df99a1
#if NEED_GNUG_PRAGMAS
Packit df99a1
# pragma implementation
Packit df99a1
#endif
Packit df99a1
Packit df99a1
// From: Leon Bottou, 1/31/2002
Packit df99a1
// This has been heavily changed by Lizardtech.
Packit df99a1
// They decided to use URLs for everyting, including
Packit df99a1
// the most basic file access.  The URL class now is a unholy 
Packit df99a1
// mixture of code for syntactically parsing the urls (which it was)
Packit df99a1
// and file status code (only for local file: urls).
Packit df99a1
Packit df99a1
#include "GException.h"
Packit df99a1
#include "GOS.h"
Packit df99a1
#include "GURL.h"
Packit df99a1
#include "debug.h"
Packit df99a1
Packit df99a1
#include <stddef.h>
Packit df99a1
#include <stdlib.h>
Packit df99a1
#include <stdio.h>
Packit df99a1
#include <ctype.h>
Packit df99a1
#include <math.h>
Packit df99a1
#include <string.h>
Packit df99a1
Packit df99a1
#ifdef _WIN32
Packit df99a1
# include <tchar.h>
Packit df99a1
# include <windows.h>
Packit df99a1
# include <direct.h>
Packit df99a1
#endif /* WIN32 */
Packit df99a1
Packit df99a1
// -- MAXPATHLEN
Packit df99a1
#ifndef MAXPATHLEN
Packit df99a1
# ifdef _MAX_PATH
Packit df99a1
#  define MAXPATHLEN _MAX_PATH
Packit df99a1
# else
Packit df99a1
#  define MAXPATHLEN 1024
Packit df99a1
# endif
Packit df99a1
#else
Packit df99a1
# if ( MAXPATHLEN < 1024 )
Packit df99a1
#  undef MAXPATHLEN
Packit df99a1
#  define MAXPATHLEN 1024
Packit df99a1
# endif
Packit df99a1
#endif
Packit df99a1
Packit df99a1
#if defined(UNIX) || defined(OS2)
Packit df99a1
# include <unistd.h>
Packit df99a1
# include <sys/types.h>
Packit df99a1
# include <sys/stat.h>
Packit df99a1
# include <errno.h>
Packit df99a1
# include <fcntl.h>
Packit df99a1
# include <pwd.h>
Packit df99a1
# include <stdio.h>
Packit df99a1
# ifdef AUTOCONF
Packit df99a1
#  ifdef TIME_WITH_SYS_TIME
Packit df99a1
#   include <sys/time.h>
Packit df99a1
#   include <time.h>
Packit df99a1
#  else
Packit df99a1
#   ifdef HAVE_SYS_TIME_H
Packit df99a1
#    include <sys/time.h>
Packit df99a1
#   else
Packit df99a1
#    include <time.h>
Packit df99a1
#   endif
Packit df99a1
#  endif
Packit df99a1
#  ifdef HAVE_DIRENT_H
Packit df99a1
#   include <dirent.h>
Packit df99a1
#   define NAMLEN(dirent) strlen((dirent)->d_name)
Packit df99a1
#  else
Packit df99a1
#   define dirent direct
Packit df99a1
#   define NAMLEN(dirent) (dirent)->d_namlen
Packit df99a1
#   ifdef HAVE_SYS_NDIR_H
Packit df99a1
#    include <sys/ndir.h>
Packit df99a1
#   endif
Packit df99a1
#   ifdef HAVE_SYS_DIR_H
Packit df99a1
#    include <sys/dir.h>
Packit df99a1
#   endif
Packit df99a1
#   ifdef HAVE_NDIR_H
Packit df99a1
#    include <ndir.h>
Packit df99a1
#   endif
Packit df99a1
#  endif
Packit df99a1
# else /* !AUTOCONF */ 
Packit df99a1
#  include <sys/time.h>
Packit df99a1
#  if defined(XENIX)
Packit df99a1
#   define USE_DIRECT
Packit df99a1
#   include <sys/ndir.h>
Packit df99a1
#  elif defined(OLDBSD)
Packit df99a1
#   define USE_DIRECT
Packit df99a1
#   include <sys/dir.h>
Packit df99a1
#  endif
Packit df99a1
#  ifdef USE_DIRECT
Packit df99a1
#   define dirent direct
Packit df99a1
#   define NAMLEN(dirent) (dirent)->d_namlen
Packit df99a1
#  else
Packit df99a1
#   include <dirent.h>
Packit df99a1
#   define NAMLEN(dirent) strlen((dirent)->d_name)
Packit df99a1
#  endif 
Packit df99a1
# endif /* !AUTOCONF */
Packit df99a1
#endif /* UNIX */
Packit df99a1
Packit df99a1
#ifdef macintosh
Packit df99a1
#include <unix.h>
Packit df99a1
#include <errno.h>
Packit df99a1
#include <unistd.h>
Packit df99a1
#endif
Packit df99a1
Packit df99a1
Packit df99a1
#ifdef HAVE_NAMESPACES
Packit df99a1
namespace DJVU {
Packit df99a1
# ifdef NOT_DEFINED // Just to fool emacs c++ mode
Packit df99a1
}
Packit df99a1
#endif
Packit df99a1
#endif
Packit df99a1
Packit df99a1
Packit df99a1
static const char djvuopts[]="DJVUOPTS";
Packit df99a1
static const char localhost[]="file://localhost/";
Packit df99a1
static const char backslash='\\';  
Packit df99a1
static const char colon=':';
Packit df99a1
static const char dot='.';
Packit df99a1
static const char filespecslashes[] = "file://";
Packit df99a1
static const char filespec[] = "file:";
Packit df99a1
static const char slash='/';
Packit df99a1
static const char percent='%';
Packit df99a1
static const char localhostspec1[] = "//localhost/";
Packit df99a1
static const char localhostspec2[] = "///";
Packit df99a1
static const char nillchar=0;
Packit df99a1
#if defined(UNIX)
Packit df99a1
  static const char tilde='~';
Packit df99a1
  static const char root[] = "/";
Packit df99a1
#elif defined(_WIN32) || defined(OS2)
Packit df99a1
  static const char root[] = "\\";
Packit df99a1
#elif defined(macintosh)
Packit df99a1
  static char const * const root = &nillchar; 
Packit df99a1
#else
Packit df99a1
#error "Define something here for your operating system"
Packit df99a1
#endif
Packit df99a1
Packit df99a1
Packit df99a1
static const int
Packit df99a1
pathname_start(const GUTF8String &url, const int protolength);
Packit df99a1
Packit df99a1
// hexval --
Packit df99a1
// -- Returns the hexvalue of a character.
Packit df99a1
//    Returns -1 if illegal;
Packit df99a1
Packit df99a1
static int 
Packit df99a1
hexval(char c)
Packit df99a1
{
Packit df99a1
  return ((c>='0' && c<='9')
Packit df99a1
    ?(c-'0')
Packit df99a1
    :((c>='A' && c<='F')
Packit df99a1
      ?(c-'A'+10)
Packit df99a1
      :((c>='a' && c<='f')
Packit df99a1
        ?(c-'a'+10):(-1))));
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
static bool
Packit df99a1
is_argument(const char * start)
Packit df99a1
      // Returns TRUE if 'start' points to the beginning of an argument
Packit df99a1
      // (either hash or CGI)
Packit df99a1
{
Packit df99a1
   // return (*start=='#' || *start=='?' || *start=='&' || *start==';');
Packit df99a1
   return (*start=='#' || *start=='?' );
Packit df99a1
}
Packit df99a1
Packit df99a1
static bool
Packit df99a1
is_argument_sep(const char * start)
Packit df99a1
      // Returns TRUE if 'start' points to the beginning of an argument
Packit df99a1
      // (either hash or CGI)
Packit df99a1
{
Packit df99a1
   return (*start=='&')||(*start == ';');
Packit df99a1
}
Packit df99a1
Packit df99a1
void
Packit df99a1
GURL::convert_slashes(void)
Packit df99a1
{
Packit df99a1
   GUTF8String xurl(get_string());
Packit df99a1
#if defined(_WIN32)
Packit df99a1
   const int protocol_length=protocol(xurl).length();
Packit df99a1
   for(char *ptr=(xurl.getbuf()+protocol_length);*ptr;ptr++)
Packit df99a1
     if(*ptr == backslash)
Packit df99a1
       *ptr=slash;
Packit df99a1
   url=xurl;
Packit df99a1
#endif
Packit df99a1
}
Packit df99a1
Packit df99a1
static void
Packit df99a1
collapse(char * ptr, const int chars)
Packit df99a1
      // Will remove the first 'chars' chars from the string and
Packit df99a1
      // move the rest toward the beginning. Will take into account
Packit df99a1
      // string length
Packit df99a1
{
Packit df99a1
   const int length=strlen(ptr);
Packit df99a1
   const char *srcptr=ptr+((chars>length)?length:chars);
Packit df99a1
   while((*(ptr++) = *(srcptr++)))
Packit df99a1
     EMPTY_LOOP;
Packit df99a1
}
Packit df99a1
Packit df99a1
GUTF8String
Packit df99a1
GURL::beautify_path(GUTF8String xurl)
Packit df99a1
{
Packit df99a1
Packit df99a1
  const int protocol_length=GURL::protocol(xurl).length();
Packit df99a1
   
Packit df99a1
  // Eats parts like ./ or ../ or ///
Packit df99a1
  char * buffer;
Packit df99a1
  GPBuffer<char> gbuffer(buffer,xurl.length()+1);
Packit df99a1
  strcpy(buffer, (const char *)xurl);
Packit df99a1
   
Packit df99a1
  // Find start point
Packit df99a1
  char * start=buffer+pathname_start(xurl,protocol_length);
Packit df99a1
Packit df99a1
  // Find end of the url (don't touch arguments)
Packit df99a1
  char * ptr;
Packit df99a1
  GUTF8String args;
Packit df99a1
  for(ptr=start;*ptr;ptr++)
Packit df99a1
  {
Packit df99a1
    if (is_argument(ptr))
Packit df99a1
    {
Packit df99a1
      args=ptr;
Packit df99a1
      *ptr=0;
Packit df99a1
      break;
Packit df99a1
    }
Packit df99a1
  }
Packit df99a1
Packit df99a1
  // Eat multiple slashes
Packit df99a1
  for(;(ptr=strstr(start, "////"));collapse(ptr, 3))
Packit df99a1
    EMPTY_LOOP;
Packit df99a1
  for(;(ptr=strstr(start, "//"));collapse(ptr, 1))
Packit df99a1
    EMPTY_LOOP;
Packit df99a1
  // Convert /./ stuff into plain /
Packit df99a1
  for(;(ptr=strstr(start, "/./"));collapse(ptr, 2))
Packit df99a1
    EMPTY_LOOP;
Packit df99a1
#if defined(_WIN32) || defined(OS2)
Packit df99a1
  if(!xurl.cmp(filespec,sizeof(filespec)-1))
Packit df99a1
  {
Packit df99a1
	int offset=1;
Packit df99a1
	if(start&&(start[0] == '/')&& 
Packit df99a1
           !xurl.cmp("file:////",sizeof("file:////")-1))
Packit df99a1
	{
Packit df99a1
	  collapse(start, 1);
Packit df99a1
	  offset=0;
Packit df99a1
	}
Packit df99a1
    for(ptr=start+offset;(ptr=strchr(ptr, '/'));)
Packit df99a1
	{
Packit df99a1
	  if(isalpha((++ptr)[0]))
Packit df99a1
	  {
Packit df99a1
	    if((ptr[1] == ':')&&(ptr[2]=='/'))
Packit df99a1
		{
Packit df99a1
		  char *buffer2;
Packit df99a1
                  GPBuffer<char> gbuffer2(buffer2,strlen(ptr)+1);
Packit df99a1
		  strcpy(buffer2,ptr);
Packit df99a1
		  gbuffer.resize(strlen(ptr)+sizeof(localhost));
Packit df99a1
		  strcpy(buffer,localhost);
Packit df99a1
		  strcat(buffer,buffer2);
Packit df99a1
		  ptr=(start=buffer+sizeof(localhost))+1;
Packit df99a1
		}
Packit df99a1
	  }
Packit df99a1
	}
Packit df99a1
  }
Packit df99a1
#endif
Packit df99a1
  // Process /../
Packit df99a1
  while((ptr=strstr(start, "/../")))
Packit df99a1
  {
Packit df99a1
    for(char * ptr1=ptr-1;(ptr1>=start);ptr1--)
Packit df99a1
    {
Packit df99a1
      if (*ptr1==slash)
Packit df99a1
      {
Packit df99a1
        collapse(ptr1, ptr-ptr1+3);
Packit df99a1
        break;
Packit df99a1
      }
Packit df99a1
    }
Packit df99a1
  }
Packit df99a1
Packit df99a1
  // Remove trailing /.
Packit df99a1
  ptr=start+strlen(start)-2;
Packit df99a1
  if((ptr>=start)&& (ptr == GUTF8String("/.")))
Packit df99a1
  {
Packit df99a1
    ptr[1]=0;
Packit df99a1
  }
Packit df99a1
  // Eat trailing /..
Packit df99a1
  ptr=start+strlen(start)-3;
Packit df99a1
  if((ptr >= start) && (ptr == GUTF8String("/..")))
Packit df99a1
  {
Packit df99a1
    for(char * ptr1=ptr-1;(ptr1>=start);ptr1--)
Packit df99a1
    {
Packit df99a1
      if (*ptr1==slash)
Packit df99a1
      {
Packit df99a1
        ptr1[1]=0;
Packit df99a1
        break;
Packit df99a1
      }
Packit df99a1
    }
Packit df99a1
  }
Packit df99a1
Packit df99a1
  // Done. Copy the buffer back into the URL and add arguments.
Packit df99a1
  xurl=buffer;
Packit df99a1
  return (xurl+args);
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
void
Packit df99a1
GURL::beautify_path(void)
Packit df99a1
{
Packit df99a1
  url=beautify_path(get_string());
Packit df99a1
}
Packit df99a1
Packit df99a1
void
Packit df99a1
GURL::init(const bool nothrow)
Packit df99a1
{
Packit df99a1
   GCriticalSectionLock lock(&class_lock);
Packit df99a1
   validurl=true;
Packit df99a1
   
Packit df99a1
   if (url.length())
Packit df99a1
   {
Packit df99a1
      GUTF8String proto=protocol();
Packit df99a1
      if (proto.length()<2)
Packit df99a1
      {
Packit df99a1
        validurl=false;
Packit df99a1
        if(!nothrow)
Packit df99a1
          G_THROW( ERR_MSG("GURL.no_protocol") "\t"+url);
Packit df99a1
        return;
Packit df99a1
      }
Packit df99a1
Packit df99a1
         // Below we have to make this complex test to detect URLs really
Packit df99a1
         // referring to *local* files. Surprisingly, file://hostname/dir/file
Packit df99a1
         // is also valid, but shouldn't be treated thru local FS.
Packit df99a1
      if (proto=="file" && url[5]==slash &&
Packit df99a1
          (url[6]!=slash || !url.cmp(localhost, sizeof(localhost))))
Packit df99a1
      {
Packit df99a1
            // Separate the arguments
Packit df99a1
         GUTF8String arg;
Packit df99a1
         {
Packit df99a1
           const char * const url_ptr=url;
Packit df99a1
           const char * ptr;
Packit df99a1
           for(ptr=url_ptr;*ptr&&!is_argument(ptr);ptr++)
Packit df99a1
           		EMPTY_LOOP;
Packit df99a1
           arg=ptr;
Packit df99a1
           url=url.substr(0,(size_t)(ptr-url_ptr));
Packit df99a1
         }
Packit df99a1
Packit df99a1
            // Do double conversion
Packit df99a1
         GUTF8String tmp=UTF8Filename();
Packit df99a1
         if (!tmp.length())
Packit df99a1
         {
Packit df99a1
           validurl=false;
Packit df99a1
           if(!nothrow)
Packit df99a1
             G_THROW( ERR_MSG("GURL.fail_to_file") );
Packit df99a1
           return;
Packit df99a1
         }
Packit df99a1
         url=GURL::Filename::UTF8(tmp).get_string();
Packit df99a1
         if (!url.length())
Packit df99a1
         {
Packit df99a1
           validurl=false;
Packit df99a1
           if(!nothrow)
Packit df99a1
             G_THROW( ERR_MSG("GURL.fail_to_URL") );
Packit df99a1
           return;
Packit df99a1
         }
Packit df99a1
            // Return the argument back
Packit df99a1
         url+=arg;
Packit df99a1
      }
Packit df99a1
      convert_slashes();
Packit df99a1
      beautify_path();
Packit df99a1
      parse_cgi_args();
Packit df99a1
   }
Packit df99a1
}
Packit df99a1
Packit df99a1
GURL::GURL(void) 
Packit df99a1
  : validurl(false) 
Packit df99a1
{
Packit df99a1
}
Packit df99a1
Packit df99a1
GURL::GURL(const char * url_in) 
Packit df99a1
  : url(url_in ? url_in : ""), validurl(false)
Packit df99a1
{
Packit df99a1
}
Packit df99a1
Packit df99a1
GURL::GURL(const GUTF8String & url_in)
Packit df99a1
  : url(url_in), validurl(false)
Packit df99a1
{
Packit df99a1
}
Packit df99a1
Packit df99a1
GURL::GURL(const GNativeString & url_in)
Packit df99a1
  : url(url_in.getNative2UTF8()), validurl(false)
Packit df99a1
{
Packit df99a1
#if defined(_WIN32) || defined(OS2)
Packit df99a1
  if(is_valid() && is_local_file_url())
Packit df99a1
  {
Packit df99a1
    GURL::Filename::UTF8 xurl(UTF8Filename());
Packit df99a1
    url=xurl.get_string(true);
Packit df99a1
    validurl=false;
Packit df99a1
  }
Packit df99a1
#endif
Packit df99a1
}
Packit df99a1
Packit df99a1
GURL::GURL(const GURL & url_in)
Packit df99a1
  : validurl(false)
Packit df99a1
{
Packit df99a1
  if(url_in.is_valid())
Packit df99a1
  {
Packit df99a1
    url=url_in.get_string();
Packit df99a1
    init();
Packit df99a1
  }else
Packit df99a1
  {
Packit df99a1
    url=url_in.url;
Packit df99a1
  }
Packit df99a1
}
Packit df99a1
Packit df99a1
GURL &
Packit df99a1
GURL::operator=(const GURL & url_in)
Packit df99a1
{
Packit df99a1
   GCriticalSectionLock lock(&class_lock);
Packit df99a1
   if(url_in.is_valid())
Packit df99a1
   {
Packit df99a1
     url=url_in.get_string();
Packit df99a1
     init(true);
Packit df99a1
   }else
Packit df99a1
   {
Packit df99a1
     url=url_in.url;
Packit df99a1
     validurl=false;
Packit df99a1
   }
Packit df99a1
   return *this;
Packit df99a1
}
Packit df99a1
Packit df99a1
GUTF8String
Packit df99a1
GURL::protocol(const GUTF8String& url)
Packit df99a1
{
Packit df99a1
  const char * const url_ptr=url;
Packit df99a1
  const char * ptr=url_ptr;
Packit df99a1
  for(char c=*ptr;
Packit df99a1
      c && isascii(c) && (isalnum(c) || c == '+' || c == '-' || c == '.');
Packit df99a1
      c=*(++ptr)) EMPTY_LOOP;
Packit df99a1
  if (ptr[0]==colon && ptr[1]=='/' && ptr[2]=='/')
Packit df99a1
    return GUTF8String(url_ptr, ptr-url_ptr);
Packit df99a1
  return GUTF8String();
Packit df99a1
}
Packit df99a1
Packit df99a1
GUTF8String
Packit df99a1
GURL::hash_argument(void) const
Packit df99a1
      // Returns the HASH argument (anything after '#' and before '?')
Packit df99a1
{
Packit df99a1
   const GUTF8String xurl(get_string());
Packit df99a1
Packit df99a1
   bool found=false;
Packit df99a1
   GUTF8String arg;
Packit df99a1
Packit df99a1
         // Break if CGI argument is found
Packit df99a1
   for(const char * start=xurl;*start&&(*start!='?');start++)
Packit df99a1
   {
Packit df99a1
      if (found)
Packit df99a1
      {
Packit df99a1
         arg+=*start;
Packit df99a1
      }else
Packit df99a1
      {
Packit df99a1
         found=(*start=='#');
Packit df99a1
      }
Packit df99a1
   }
Packit df99a1
   return decode_reserved(arg);
Packit df99a1
}
Packit df99a1
Packit df99a1
void
Packit df99a1
GURL::set_hash_argument(const GUTF8String &arg)
Packit df99a1
{
Packit df99a1
   const GUTF8String xurl(get_string());
Packit df99a1
Packit df99a1
   GUTF8String new_url;
Packit df99a1
   bool found=false;
Packit df99a1
   const char * ptr;
Packit df99a1
   for(ptr=xurl;*ptr;ptr++)
Packit df99a1
   {
Packit df99a1
      if (is_argument(ptr))
Packit df99a1
      {
Packit df99a1
         if (*ptr!='#')
Packit df99a1
         {
Packit df99a1
           break;
Packit df99a1
         }
Packit df99a1
         found=true;
Packit df99a1
      } else if (!found)
Packit df99a1
      {
Packit df99a1
         new_url+=*ptr;
Packit df99a1
      }
Packit df99a1
   }
Packit df99a1
Packit df99a1
   url=new_url+"#"+GURL::encode_reserved(arg)+ptr;
Packit df99a1
}
Packit df99a1
Packit df99a1
void
Packit df99a1
GURL::parse_cgi_args(void)
Packit df99a1
      // Will read CGI arguments from the URL into
Packit df99a1
      // cgi_name_arr and cgi_value_arr
Packit df99a1
{
Packit df99a1
   if(!validurl)
Packit df99a1
     init();
Packit df99a1
   GCriticalSectionLock lock1(&class_lock);
Packit df99a1
   cgi_name_arr.empty();
Packit df99a1
   cgi_value_arr.empty();
Packit df99a1
Packit df99a1
      // Search for the beginning of CGI arguments
Packit df99a1
   const char * start=url;
Packit df99a1
   while(*start)
Packit df99a1
   {
Packit df99a1
     if(*(start++)=='?')
Packit df99a1
     {
Packit df99a1
       break;
Packit df99a1
     }
Packit df99a1
   }
Packit df99a1
Packit df99a1
      // Now loop until we see all of them
Packit df99a1
   while(*start)
Packit df99a1
   {
Packit df99a1
      GUTF8String arg;        // Storage for another argument
Packit df99a1
      while(*start)        // Seek for the end of it
Packit df99a1
      {
Packit df99a1
         if (is_argument_sep(start))
Packit df99a1
         {
Packit df99a1
            start++;
Packit df99a1
            break;
Packit df99a1
         } else
Packit df99a1
         {
Packit df99a1
           arg+=*start++;
Packit df99a1
         }
Packit df99a1
      }
Packit df99a1
      if (arg.length())
Packit df99a1
      {
Packit df99a1
            // Got argument in 'arg'. Split it into 'name' and 'value'
Packit df99a1
         const char * ptr;
Packit df99a1
         const char * const arg_ptr=arg;
Packit df99a1
	 for(ptr=arg_ptr;*ptr&&(*ptr != '=');ptr++)
Packit df99a1
	   EMPTY_LOOP;
Packit df99a1
Packit df99a1
         GUTF8String name, value;
Packit df99a1
         if (*ptr)
Packit df99a1
         {
Packit df99a1
            name=GUTF8String(arg_ptr, (int)((ptr++)-arg_ptr));
Packit df99a1
            value=GUTF8String(ptr, arg.length()-name.length()-1);
Packit df99a1
         } else
Packit df99a1
         {
Packit df99a1
           name=arg;
Packit df99a1
         }
Packit df99a1
            
Packit df99a1
         int args=cgi_name_arr.size();
Packit df99a1
         cgi_name_arr.resize(args);
Packit df99a1
         cgi_value_arr.resize(args);
Packit df99a1
         cgi_name_arr[args]=decode_reserved(name);
Packit df99a1
         cgi_value_arr[args]=decode_reserved(value);
Packit df99a1
      }
Packit df99a1
   }
Packit df99a1
}
Packit df99a1
Packit df99a1
void
Packit df99a1
GURL::store_cgi_args(void)
Packit df99a1
      // Will store CGI arguments from the cgi_name_arr and cgi_value_arr
Packit df99a1
      // back into the URL
Packit df99a1
{
Packit df99a1
   if(!validurl)
Packit df99a1
     init();
Packit df99a1
   GCriticalSectionLock lock1(&class_lock);
Packit df99a1
Packit df99a1
   const char * const url_ptr=url;
Packit df99a1
   const char * ptr;
Packit df99a1
   for(ptr=url_ptr;*ptr&&(*ptr!='?');ptr++)
Packit df99a1
   		EMPTY_LOOP;
Packit df99a1
   
Packit df99a1
   GUTF8String new_url(url_ptr, ptr-url_ptr);
Packit df99a1
   
Packit df99a1
   for(int i=0;i
Packit df99a1
   {
Packit df99a1
      GUTF8String name=GURL::encode_reserved(cgi_name_arr[i]);
Packit df99a1
      GUTF8String value=GURL::encode_reserved(cgi_value_arr[i]);
Packit df99a1
      new_url+=(i?"&":"?")+name;
Packit df99a1
      if (value.length())
Packit df99a1
         new_url+="="+value;
Packit df99a1
   }
Packit df99a1
Packit df99a1
   url=new_url;
Packit df99a1
}
Packit df99a1
Packit df99a1
int
Packit df99a1
GURL::cgi_arguments(void) const
Packit df99a1
{
Packit df99a1
   if(!validurl)
Packit df99a1
      const_cast<GURL *>(this)->init();
Packit df99a1
   return cgi_name_arr.size();
Packit df99a1
}
Packit df99a1
Packit df99a1
int
Packit df99a1
GURL::djvu_cgi_arguments(void) const
Packit df99a1
{
Packit df99a1
   if(!validurl)
Packit df99a1
     const_cast<GURL *>(this)->init();
Packit df99a1
   GCriticalSectionLock lock((GCriticalSection *) &class_lock);
Packit df99a1
Packit df99a1
   int args=0;
Packit df99a1
   for(int i=0;i
Packit df99a1
   {
Packit df99a1
      if (cgi_name_arr[i].upcase()==djvuopts)
Packit df99a1
      {
Packit df99a1
         args=cgi_name_arr.size()-(i+1);
Packit df99a1
         break;
Packit df99a1
      }
Packit df99a1
   } 
Packit df99a1
   return args;
Packit df99a1
}
Packit df99a1
Packit df99a1
GUTF8String
Packit df99a1
GURL::cgi_name(int num) const
Packit df99a1
{
Packit df99a1
   if(!validurl) const_cast<GURL *>(this)->init();
Packit df99a1
   GCriticalSectionLock lock((GCriticalSection *) &class_lock);
Packit df99a1
   return (num
Packit df99a1
}
Packit df99a1
Packit df99a1
GUTF8String
Packit df99a1
GURL::djvu_cgi_name(int num) const
Packit df99a1
{
Packit df99a1
   if(!validurl) const_cast<GURL *>(this)->init();
Packit df99a1
   GCriticalSectionLock lock((GCriticalSection *) &class_lock);
Packit df99a1
Packit df99a1
   GUTF8String arg;
Packit df99a1
   for(int i=0;i
Packit df99a1
      if (cgi_name_arr[i].upcase()==djvuopts)
Packit df99a1
      {
Packit df99a1
         for(i++;i
Packit df99a1
            if (! num--)
Packit df99a1
            {
Packit df99a1
               arg=cgi_name_arr[i];
Packit df99a1
               break;
Packit df99a1
            }
Packit df99a1
         break;
Packit df99a1
      }
Packit df99a1
   return arg;
Packit df99a1
}
Packit df99a1
Packit df99a1
GUTF8String
Packit df99a1
GURL::cgi_value(int num) const
Packit df99a1
{
Packit df99a1
   if(!validurl) const_cast<GURL *>(this)->init();
Packit df99a1
   GCriticalSectionLock lock((GCriticalSection *) &class_lock);
Packit df99a1
   return (num
Packit df99a1
}
Packit df99a1
Packit df99a1
GUTF8String
Packit df99a1
GURL::djvu_cgi_value(int num) const
Packit df99a1
{
Packit df99a1
   if(!validurl) const_cast<GURL *>(this)->init();
Packit df99a1
   GCriticalSectionLock lock((GCriticalSection *) &class_lock);
Packit df99a1
Packit df99a1
   GUTF8String arg;
Packit df99a1
   for(int i=0;i
Packit df99a1
   {
Packit df99a1
      if (cgi_name_arr[i].upcase()==djvuopts)
Packit df99a1
      {
Packit df99a1
         for(i++;i
Packit df99a1
         {
Packit df99a1
            if (! num--)
Packit df99a1
            {
Packit df99a1
               arg=cgi_value_arr[i];
Packit df99a1
               break;
Packit df99a1
            }
Packit df99a1
         }
Packit df99a1
         break;
Packit df99a1
      }
Packit df99a1
   }
Packit df99a1
   return arg;
Packit df99a1
}
Packit df99a1
Packit df99a1
DArray<GUTF8String>
Packit df99a1
GURL::cgi_names(void) const
Packit df99a1
{
Packit df99a1
   if(!validurl) const_cast<GURL *>(this)->init();
Packit df99a1
   GCriticalSectionLock lock((GCriticalSection *) &class_lock);
Packit df99a1
   return cgi_name_arr;
Packit df99a1
}
Packit df99a1
Packit df99a1
DArray<GUTF8String>
Packit df99a1
GURL::cgi_values(void) const
Packit df99a1
{
Packit df99a1
   if(!validurl) const_cast<GURL *>(this)->init();
Packit df99a1
   GCriticalSectionLock lock((GCriticalSection *) &class_lock);
Packit df99a1
   return cgi_value_arr;
Packit df99a1
}
Packit df99a1
Packit df99a1
DArray<GUTF8String>
Packit df99a1
GURL::djvu_cgi_names(void) const
Packit df99a1
{
Packit df99a1
   if(!validurl) const_cast<GURL *>(this)->init();
Packit df99a1
   GCriticalSectionLock lock((GCriticalSection *) &class_lock);
Packit df99a1
Packit df99a1
   int i;
Packit df99a1
   DArray<GUTF8String> arr;
Packit df99a1
   for(i=0;(i
Packit df99a1
     (cgi_name_arr[i].upcase()!=djvuopts)
Packit df99a1
     ;i++)
Packit df99a1
     	EMPTY_LOOP;
Packit df99a1
Packit df99a1
   int size=cgi_name_arr.size()-(i+1);
Packit df99a1
   if (size>0)
Packit df99a1
   {
Packit df99a1
      arr.resize(size-1);
Packit df99a1
      for(i=0;i
Packit df99a1
         arr[i]=cgi_name_arr[cgi_name_arr.size()-arr.size()+i];
Packit df99a1
   }
Packit df99a1
Packit df99a1
   return arr;
Packit df99a1
}
Packit df99a1
Packit df99a1
DArray<GUTF8String>
Packit df99a1
GURL::djvu_cgi_values(void) const
Packit df99a1
{
Packit df99a1
   if(!validurl) const_cast<GURL *>(this)->init();
Packit df99a1
   GCriticalSectionLock lock((GCriticalSection *) &class_lock);
Packit df99a1
Packit df99a1
   int i;
Packit df99a1
   DArray<GUTF8String> arr;
Packit df99a1
   for(i=0;i
Packit df99a1
   		EMPTY_LOOP;
Packit df99a1
Packit df99a1
   int size=cgi_name_arr.size()-(i+1);
Packit df99a1
   if (size>0)
Packit df99a1
   {
Packit df99a1
      arr.resize(size-1);
Packit df99a1
      for(i=0;i
Packit df99a1
         arr[i]=cgi_value_arr[cgi_value_arr.size()-arr.size()+i];
Packit df99a1
   }
Packit df99a1
Packit df99a1
   return arr;
Packit df99a1
}
Packit df99a1
Packit df99a1
void
Packit df99a1
GURL::clear_all_arguments(void)
Packit df99a1
{
Packit df99a1
   clear_hash_argument();
Packit df99a1
   clear_cgi_arguments();
Packit df99a1
}
Packit df99a1
Packit df99a1
void
Packit df99a1
GURL::clear_hash_argument(void)
Packit df99a1
      // Clear anything after first '#' and before the following '?'
Packit df99a1
{
Packit df99a1
   if(!validurl) init();
Packit df99a1
   GCriticalSectionLock lock(&class_lock);
Packit df99a1
   bool found=false;
Packit df99a1
   GUTF8String new_url;
Packit df99a1
   for(const char * start=url;*start;start++)
Packit df99a1
   {
Packit df99a1
         // Break on first CGI arg.
Packit df99a1
      if (*start=='?')
Packit df99a1
      {
Packit df99a1
         new_url+=start;
Packit df99a1
         break;
Packit df99a1
      }
Packit df99a1
Packit df99a1
      if (!found)
Packit df99a1
      { 
Packit df99a1
        if (*start=='#')
Packit df99a1
          found=true;
Packit df99a1
        else
Packit df99a1
          new_url+=*start;
Packit df99a1
      }
Packit df99a1
   }
Packit df99a1
   url=new_url;
Packit df99a1
}
Packit df99a1
Packit df99a1
void
Packit df99a1
GURL::clear_cgi_arguments(void)
Packit df99a1
{
Packit df99a1
   if(!validurl)
Packit df99a1
     init();
Packit df99a1
   GCriticalSectionLock lock1(&class_lock);
Packit df99a1
Packit df99a1
      // Clear the arrays
Packit df99a1
   cgi_name_arr.empty();
Packit df99a1
   cgi_value_arr.empty();
Packit df99a1
Packit df99a1
      // And clear everything past the '?' sign in the URL
Packit df99a1
   const char * ptrurl = url;
Packit df99a1
   for(const char *ptr = ptrurl; *ptr; ptr++)
Packit df99a1
     if (*ptr=='?')
Packit df99a1
       {
Packit df99a1
         url.setat(ptr-ptrurl, 0);
Packit df99a1
         break;
Packit df99a1
       }
Packit df99a1
}
Packit df99a1
Packit df99a1
void
Packit df99a1
GURL::clear_djvu_cgi_arguments(void)
Packit df99a1
{
Packit df99a1
   if(!validurl) init();
Packit df99a1
      // First - modify the arrays
Packit df99a1
   GCriticalSectionLock lock(&class_lock);
Packit df99a1
   for(int i=0;i
Packit df99a1
   {
Packit df99a1
      if (cgi_name_arr[i].upcase()==djvuopts)
Packit df99a1
      {
Packit df99a1
         cgi_name_arr.resize(i-1);
Packit df99a1
         cgi_value_arr.resize(i-1);
Packit df99a1
         break;
Packit df99a1
      }
Packit df99a1
   }
Packit df99a1
Packit df99a1
      // And store them back into the URL
Packit df99a1
   store_cgi_args();
Packit df99a1
}
Packit df99a1
Packit df99a1
void
Packit df99a1
GURL::add_djvu_cgi_argument(const GUTF8String &name, const char * value)
Packit df99a1
{
Packit df99a1
   if(!validurl)
Packit df99a1
     init();
Packit df99a1
   GCriticalSectionLock lock1(&class_lock);
Packit df99a1
Packit df99a1
      // Check if we already have the "DJVUOPTS" argument
Packit df99a1
   bool have_djvuopts=false;
Packit df99a1
   for(int i=0;i
Packit df99a1
   {
Packit df99a1
      if (cgi_name_arr[i].upcase()==djvuopts)
Packit df99a1
      {
Packit df99a1
         have_djvuopts=true;
Packit df99a1
         break;
Packit df99a1
      }
Packit df99a1
   }
Packit df99a1
Packit df99a1
      // If there is no DJVUOPTS, insert it
Packit df99a1
   if (!have_djvuopts)
Packit df99a1
   {
Packit df99a1
      int pos=cgi_name_arr.size();
Packit df99a1
      cgi_name_arr.resize(pos);
Packit df99a1
      cgi_value_arr.resize(pos);
Packit df99a1
      cgi_name_arr[pos]=djvuopts;
Packit df99a1
   }
Packit df99a1
Packit df99a1
      // Add new argument to the array
Packit df99a1
   int pos=cgi_name_arr.size();
Packit df99a1
   cgi_name_arr.resize(pos);
Packit df99a1
   cgi_value_arr.resize(pos);
Packit df99a1
   cgi_name_arr[pos]=name;
Packit df99a1
   cgi_value_arr[pos]=value;
Packit df99a1
Packit df99a1
      // And update the URL
Packit df99a1
   store_cgi_args();
Packit df99a1
}
Packit df99a1
Packit df99a1
bool
Packit df99a1
GURL::is_local_file_url(void) const
Packit df99a1
{
Packit df99a1
   if(!validurl) const_cast<GURL *>(this)->init();
Packit df99a1
   GCriticalSectionLock lock((GCriticalSection *) &class_lock);
Packit df99a1
   return (protocol()=="file" && url[5]==slash);
Packit df99a1
}
Packit df99a1
Packit df99a1
static const int
Packit df99a1
pathname_start(const GUTF8String &url, const int protolength)
Packit df99a1
{
Packit df99a1
  const int length=url.length();
Packit df99a1
  int retval=0;
Packit df99a1
  if(protolength+1
Packit df99a1
  {
Packit df99a1
    retval=url.search(slash,((url[protolength+1] == '/')
Packit df99a1
      ?((url[protolength+2] == '/')?(protolength+3):(protolength+2))
Packit df99a1
      :(protolength+1)));
Packit df99a1
  }
Packit df99a1
  return (retval>0)?retval:length;
Packit df99a1
}
Packit df99a1
Packit df99a1
GUTF8String
Packit df99a1
GURL::pathname(void) const
Packit df99a1
{
Packit df99a1
  return (is_local_file_url())
Packit df99a1
    ?GURL::encode_reserved(UTF8Filename()) 
Packit df99a1
    :url.substr(pathname_start(url,protocol().length()),(unsigned int)(-1));
Packit df99a1
}
Packit df99a1
Packit df99a1
GURL
Packit df99a1
GURL::base(void) const
Packit df99a1
{
Packit df99a1
   const GUTF8String xurl(get_string());
Packit df99a1
   const int protocol_length=protocol(xurl).length();
Packit df99a1
   const char * const url_ptr=xurl;
Packit df99a1
   const char * ptr, * xslash;
Packit df99a1
   ptr=xslash=url_ptr+protocol_length+1;
Packit df99a1
   if(xslash[0] == '/')
Packit df99a1
   {
Packit df99a1
     xslash++;
Packit df99a1
     if(xslash[0] == '/')
Packit df99a1
       xslash++;
Packit df99a1
     for(ptr=xslash;ptr[0] && !is_argument(ptr);ptr++)
Packit df99a1
     {
Packit df99a1
       if ((ptr[0]==slash)&&ptr[1]&&!is_argument(ptr+1))
Packit df99a1
        xslash=ptr;
Packit df99a1
     }
Packit df99a1
     if(xslash[0] != '/')
Packit df99a1
     {
Packit df99a1
       xslash=ptr;
Packit df99a1
     }
Packit df99a1
   }
Packit df99a1
   return GURL::UTF8(GUTF8String(xurl,(int)(xslash-url_ptr))+"/"+ptr);
Packit df99a1
}
Packit df99a1
Packit df99a1
bool
Packit df99a1
GURL::operator==(const GURL & gurl2) const
Packit df99a1
{
Packit df99a1
  const GUTF8String g1(get_string());
Packit df99a1
  const GUTF8String g2(gurl2.get_string());
Packit df99a1
  const char *s1 = (const char*)g1;
Packit df99a1
  const char *s2 = (const char*)g2;
Packit df99a1
  int n1=0;
Packit df99a1
  int n2=0;
Packit df99a1
  while (s1[n1] && !is_argument(s1+n1))
Packit df99a1
    n1 += 1;
Packit df99a1
  while (s2[n2] && !is_argument(s2+n2))
Packit df99a1
    n2 += 1;
Packit df99a1
  if (n1 == n2)
Packit df99a1
    return !strcmp(s1+n1,s2+n2) && !strncmp(s1,s2,n1);
Packit df99a1
  if (n1 == n2+1 && s1[n2]=='/')
Packit df99a1
    return !strcmp(s1+n1,s2+n2) && !strncmp(s1,s2,n2);
Packit df99a1
  if (n2 == n1+1 && s2[n1]=='/')
Packit df99a1
    return !strcmp(s1+n1,s2+n2) && !strncmp(s1,s2,n1);    
Packit df99a1
  return false;
Packit df99a1
}
Packit df99a1
Packit df99a1
GUTF8String
Packit df99a1
GURL::name(void) const
Packit df99a1
{
Packit df99a1
   if(!validurl)
Packit df99a1
     const_cast<GURL *>(this)->init();
Packit df99a1
   GUTF8String retval;
Packit df99a1
   if(!is_empty())
Packit df99a1
   {
Packit df99a1
     const GUTF8String xurl(url);
Packit df99a1
     const int protocol_length=protocol(xurl).length();
Packit df99a1
     const char * ptr, * xslash=(const char *)xurl+protocol_length-1;
Packit df99a1
     for(ptr=(const char *)xurl+protocol_length;
Packit df99a1
       *ptr && !is_argument(ptr);ptr++)
Packit df99a1
	 {
Packit df99a1
       if (*ptr==slash)
Packit df99a1
          xslash=ptr;
Packit df99a1
	 }
Packit df99a1
     retval=GUTF8String(xslash+1, ptr-xslash-1);
Packit df99a1
   }
Packit df99a1
   return retval;
Packit df99a1
}
Packit df99a1
Packit df99a1
GUTF8String
Packit df99a1
GURL::fname(void) const
Packit df99a1
{
Packit df99a1
   if(!validurl)
Packit df99a1
     const_cast<GURL *>(this)->init();
Packit df99a1
   return decode_reserved(name());
Packit df99a1
}
Packit df99a1
Packit df99a1
GUTF8String
Packit df99a1
GURL::extension(void) const
Packit df99a1
{
Packit df99a1
   if(!validurl)
Packit df99a1
     const_cast<GURL *>(this)->init();
Packit df99a1
   GUTF8String xfilename=name();
Packit df99a1
   GUTF8String retval;
Packit df99a1
Packit df99a1
   for(int i=xfilename.length()-1;i>=0;i--)
Packit df99a1
   {
Packit df99a1
      if (xfilename[i]=='.')
Packit df99a1
      {
Packit df99a1
         retval=(const char*)xfilename+i+1;
Packit df99a1
         break;
Packit df99a1
      }
Packit df99a1
   } 
Packit df99a1
   return retval;
Packit df99a1
}
Packit df99a1
Packit df99a1
GUTF8String
Packit df99a1
GURL::decode_reserved(const GUTF8String &gurl)
Packit df99a1
{
Packit df99a1
  const char *url=gurl;
Packit df99a1
  char *res;
Packit df99a1
  GPBuffer<char> gres(res,gurl.length()+1);
Packit df99a1
  char *r=res;
Packit df99a1
  for(const char * ptr=url;*ptr;++ptr,++r)
Packit df99a1
  {
Packit df99a1
    if (*ptr!=percent)
Packit df99a1
    {
Packit df99a1
      r[0]=*ptr;
Packit df99a1
    }else
Packit df99a1
    {
Packit df99a1
      int c1,c2;
Packit df99a1
      if ( ((c1=hexval(ptr[1]))>=0)
Packit df99a1
        && ((c2=hexval(ptr[2]))>=0) )
Packit df99a1
      {
Packit df99a1
        r[0]=(c1<<4)|c2;
Packit df99a1
        ptr+=2;
Packit df99a1
      } else
Packit df99a1
      {
Packit df99a1
        r[0]=*ptr;
Packit df99a1
      }
Packit df99a1
    }
Packit df99a1
  }
Packit df99a1
  r[0]=0;
Packit df99a1
  GUTF8String retval(res);
Packit df99a1
  if(!retval.is_valid())
Packit df99a1
  {
Packit df99a1
    retval=GNativeString(res);
Packit df99a1
  }
Packit df99a1
  return retval;
Packit df99a1
}
Packit df99a1
Packit df99a1
GUTF8String
Packit df99a1
GURL::encode_reserved(const GUTF8String &gs)
Packit df99a1
{
Packit df99a1
  const char *s=(const char *)gs;
Packit df99a1
  // Potentially unsafe characters (cf. RFC1738 and RFC1808)
Packit df99a1
  static const char hex[] = "0123456789ABCDEF";
Packit df99a1
  
Packit df99a1
  unsigned char *retval;
Packit df99a1
  GPBuffer<unsigned char> gd(retval,strlen(s)*3+1);
Packit df99a1
  unsigned char *d=retval;
Packit df99a1
  for (; *s; s++,d++)
Packit df99a1
  {
Packit df99a1
    // Convert directory separator to slashes
Packit df99a1
#if defined(_WIN32) || defined(OS2)
Packit df99a1
    if (*s == backslash || *s== slash)
Packit df99a1
#else
Packit df99a1
#ifdef macintosh
Packit df99a1
    if (*s == colon )
Packit df99a1
#else
Packit df99a1
#ifdef UNIX
Packit df99a1
    if (*s == slash )
Packit df99a1
#else
Packit df99a1
#error "Define something here for your operating system"
Packit df99a1
#endif  
Packit df99a1
#endif
Packit df99a1
#endif
Packit df99a1
    {
Packit df99a1
      *d = slash; 
Packit df99a1
      continue;
Packit df99a1
    }
Packit df99a1
    unsigned char const ss=(unsigned char const)(*s);
Packit df99a1
    // WARNING: Whenever you modify this conversion code,
Packit df99a1
    // make sure, that the following functions are in sync:
Packit df99a1
    //   encode_reserved()
Packit df99a1
    //   decode_reserved()
Packit df99a1
    //   url_to_filename()
Packit df99a1
    //   filename_to_url()
Packit df99a1
    // unreserved characters
Packit df99a1
    if ( (ss>='a' && ss<='z') ||
Packit df99a1
         (ss>='A' && ss<='Z') ||
Packit df99a1
         (ss>='0' && ss<='9') ||
Packit df99a1
         (strchr("$-_.+!*'(),~:=", ss)) ) 
Packit df99a1
    {
Packit df99a1
      *d = ss;
Packit df99a1
      continue;
Packit df99a1
    }
Packit df99a1
    // escape sequence
Packit df99a1
    d[0] = percent;
Packit df99a1
    d[1] = hex[ (ss >> 4) & 0xf ];
Packit df99a1
    d[2] = hex[ (ss) & 0xf ];
Packit df99a1
    d+=2;
Packit df99a1
  }
Packit df99a1
  *d = 0;
Packit df99a1
  return retval;
Packit df99a1
}
Packit df99a1
Packit df99a1
// -------------------------------------------
Packit df99a1
// Functions for converting filenames and urls
Packit df99a1
// -------------------------------------------
Packit df99a1
Packit df99a1
static GUTF8String
Packit df99a1
url_from_UTF8filename(const GUTF8String &gfilename)
Packit df99a1
{
Packit df99a1
  if(GURL::UTF8(gfilename).is_valid())
Packit df99a1
  {
Packit df99a1
    DEBUG_MSG("Debug: URL as Filename: " << gfilename << "\n");
Packit df99a1
  } 
Packit df99a1
  const char *filename=gfilename;
Packit df99a1
  if(filename && (unsigned char)filename[0] == (unsigned char)0xEF
Packit df99a1
     && (unsigned char)filename[1] == (unsigned char)0xBB 
Packit df99a1
     && (unsigned char)filename[2] == (unsigned char)0xBF)
Packit df99a1
  {
Packit df99a1
    filename+=3;
Packit df99a1
  }
Packit df99a1
Packit df99a1
  // Special case for blank pages
Packit df99a1
  if(!filename || !filename[0])
Packit df99a1
  {
Packit df99a1
    return GUTF8String();
Packit df99a1
  } 
Packit df99a1
Packit df99a1
  // Normalize file name to url slash-and-escape syntax
Packit df99a1
  GUTF8String oname=GURL::expand_name(filename);
Packit df99a1
  GUTF8String nname=GURL::encode_reserved(oname);
Packit df99a1
Packit df99a1
  // Preprend "file://" to file name. If file is on the local
Packit df99a1
  // machine, include "localhost".
Packit df99a1
  GUTF8String url=filespecslashes;
Packit df99a1
  const char *cnname=nname;
Packit df99a1
  if (cnname[0] == slash)
Packit df99a1
  {
Packit df99a1
    if (cnname[1] == slash)
Packit df99a1
    {
Packit df99a1
      url += cnname+2;
Packit df99a1
    }else
Packit df99a1
    {
Packit df99a1
      url = localhost + nname;
Packit df99a1
    }
Packit df99a1
  }else
Packit df99a1
  {
Packit df99a1
    url += (localhostspec1+2) + nname;
Packit df99a1
  }
Packit df99a1
  return url;
Packit df99a1
}
Packit df99a1
Packit df99a1
GUTF8String 
Packit df99a1
GURL::get_string(const bool nothrow) const
Packit df99a1
{
Packit df99a1
  if(!validurl)
Packit df99a1
    const_cast<GURL *>(this)->init(nothrow);
Packit df99a1
  return url;
Packit df99a1
}
Packit df99a1
Packit df99a1
// -- Returns a url for accessing a given file.
Packit df99a1
//    If useragent is not provided, standard url will be created,
Packit df99a1
//    but will not be understood by some versions if IE.
Packit df99a1
GUTF8String 
Packit df99a1
GURL::get_string(const GUTF8String &useragent) const
Packit df99a1
{
Packit df99a1
  if(!validurl)
Packit df99a1
    const_cast<GURL *>(this)->init();
Packit df99a1
  GUTF8String retval(url);
Packit df99a1
  if(is_local_file_url()&&useragent.length())
Packit df99a1
  {
Packit df99a1
    if(useragent.search("MSIE") >= 0 || useragent.search("Microsoft")>=0)
Packit df99a1
    {
Packit df99a1
      retval=filespecslashes + expand_name(UTF8Filename());
Packit df99a1
    }
Packit df99a1
  }
Packit df99a1
  return retval;
Packit df99a1
}
Packit df99a1
Packit df99a1
GURL::UTF8::UTF8(const GUTF8String &xurl)
Packit df99a1
: GURL(xurl) {}
Packit df99a1
Packit df99a1
GURL::UTF8::UTF8(const GUTF8String &xurl,const GURL &codebase)
Packit df99a1
: GURL(xurl,codebase) {}
Packit df99a1
Packit df99a1
GURL::GURL(const GUTF8String &xurl,const GURL &codebase)
Packit df99a1
  : validurl(false)
Packit df99a1
{
Packit df99a1
  if(GURL::UTF8(xurl).is_valid())
Packit df99a1
    {
Packit df99a1
      url=xurl;
Packit df99a1
    }
Packit df99a1
  else
Packit df99a1
    {
Packit df99a1
      // split codebase
Packit df99a1
      const char *buffer = codebase;
Packit df99a1
      GUTF8String all(buffer);
Packit df99a1
      GUTF8String suffix;
Packit df99a1
      GUTF8String path;
Packit df99a1
      GUTF8String prefix;
Packit df99a1
      const int protocol_length=GURL::protocol(all).length();
Packit df99a1
      const char *start = buffer + pathname_start(all,protocol_length);
Packit df99a1
      if (start > buffer)
Packit df99a1
        prefix = GUTF8String(buffer, start-buffer);
Packit df99a1
      const char *ptr = start;
Packit df99a1
      while (*ptr && !is_argument(ptr))
Packit df99a1
        ptr++;
Packit df99a1
      if (*ptr)
Packit df99a1
        suffix = GUTF8String(ptr);
Packit df99a1
      if (ptr > start)
Packit df99a1
        path = GUTF8String(start, ptr-start);
Packit df99a1
      // append xurl to path
Packit df99a1
      const char *c = xurl;
Packit df99a1
      if(c[0] == slash)
Packit df99a1
        path = GURL::encode_reserved(xurl);
Packit df99a1
      else
Packit df99a1
        path = path + GUTF8String(slash)+GURL::encode_reserved(xurl);
Packit df99a1
      // construct url
Packit df99a1
      url = beautify_path(prefix + path + suffix);
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
GURL::Native::Native(const GNativeString &xurl)
Packit df99a1
: GURL(xurl) {}
Packit df99a1
Packit df99a1
GURL::Native::Native(const GNativeString &xurl,const GURL &codebase)
Packit df99a1
: GURL(xurl,codebase) {}
Packit df99a1
Packit df99a1
GURL::GURL(const GNativeString &xurl,const GURL &codebase)
Packit df99a1
  : validurl(false)
Packit df99a1
{
Packit df99a1
  GURL retval(xurl.getNative2UTF8(),codebase);
Packit df99a1
  if(retval.is_valid())
Packit df99a1
  {
Packit df99a1
#if defined(_WIN32)
Packit df99a1
    // Hack for IE to change \\ to /
Packit df99a1
    if(retval.is_local_file_url())
Packit df99a1
    {
Packit df99a1
      GURL::Filename::UTF8 retval2(retval.UTF8Filename());
Packit df99a1
      url=retval2.get_string(true);
Packit df99a1
      validurl=false;
Packit df99a1
    }else
Packit df99a1
#endif // WIN32
Packit df99a1
    {
Packit df99a1
      url=retval.get_string(true);
Packit df99a1
      validurl=false;
Packit df99a1
    }
Packit df99a1
  }
Packit df99a1
}
Packit df99a1
Packit df99a1
GURL::Filename::Filename(const GNativeString &gfilename)
Packit df99a1
{
Packit df99a1
  url=url_from_UTF8filename(gfilename.getNative2UTF8());
Packit df99a1
}
Packit df99a1
Packit df99a1
GURL::Filename::Native::Native(const GNativeString &gfilename)
Packit df99a1
: GURL::Filename(gfilename) {}
Packit df99a1
Packit df99a1
GURL::Filename::Filename(const GUTF8String &gfilename)
Packit df99a1
{
Packit df99a1
  url=url_from_UTF8filename(gfilename);
Packit df99a1
}
Packit df99a1
Packit df99a1
GURL::Filename::UTF8::UTF8(const GUTF8String &gfilename)
Packit df99a1
: GURL::Filename(gfilename) {}
Packit df99a1
Packit df99a1
// filename --
Packit df99a1
// -- Applies heuristic rules to convert a url into a valid file name.  
Packit df99a1
//    Returns a simple basename in case of failure.
Packit df99a1
GUTF8String 
Packit df99a1
GURL::UTF8Filename(void) const
Packit df99a1
{
Packit df99a1
  GUTF8String retval;
Packit df99a1
  if(! is_empty())
Packit df99a1
  {
Packit df99a1
    const char *url_ptr=url;
Packit df99a1
  
Packit df99a1
    // WARNING: Whenever you modify this conversion code,
Packit df99a1
    // make sure, that the following functions are in sync:
Packit df99a1
    //   encode_reserved()
Packit df99a1
    //   decode_reserved()
Packit df99a1
    //   url_to_filename()
Packit df99a1
    //   filename_to_url()
Packit df99a1
Packit df99a1
    GUTF8String urlcopy=decode_reserved(url);
Packit df99a1
    url_ptr = urlcopy;
Packit df99a1
Packit df99a1
    // All file urls are expected to start with filespec which is "file:"
Packit df99a1
    if (GStringRep::cmp(filespec, url_ptr, sizeof(filespec)-1))  //if not
Packit df99a1
      return GOS::basename(url_ptr);
Packit df99a1
    url_ptr += sizeof(filespec)-1;
Packit df99a1
  
Packit df99a1
#if defined(macintosh)
Packit df99a1
    //remove all leading slashes
Packit df99a1
    for(;*url_ptr==slash;url_ptr++)
Packit df99a1
      EMPTY_LOOP;
Packit df99a1
    // Remove possible localhost spec
Packit df99a1
    if ( !GStringRep::cmp(localhost, url_ptr, sizeof(localhost)-1) )
Packit df99a1
      url_ptr += sizeof(localhost)-1;
Packit df99a1
    //remove all leading slashes
Packit df99a1
    while(*url_ptr==slash)
Packit df99a1
      url_ptr++;
Packit df99a1
#else
Packit df99a1
    // Remove possible localhost spec
Packit df99a1
    if ( !GStringRep::cmp(localhostspec1, url_ptr, sizeof(localhostspec1)-1) )
Packit df99a1
      // RFC 1738 local host form
Packit df99a1
      url_ptr += sizeof(localhostspec1)-1;
Packit df99a1
    else if ( !GStringRep::cmp(localhostspec2, url_ptr, sizeof(localhostspec2)-1 ) )
Packit df99a1
      // RFC 1738 local host form
Packit df99a1
      url_ptr += sizeof(localhostspec2)-1;
Packit df99a1
    else if ( (strlen(url_ptr) > 4)   // "file://<letter>:/<path>"
Packit df99a1
        && (url_ptr[0] == slash)      // "file://<letter>|/<path>"
Packit df99a1
        && (url_ptr[1] == slash)
Packit df99a1
        && isalpha(url_ptr[2])
Packit df99a1
        && ( url_ptr[3] == colon || url_ptr[3] == '|' )
Packit df99a1
        && (url_ptr[4] == slash) )
Packit df99a1
      url_ptr += 2;
Packit df99a1
    else if ( (strlen(url_ptr)) > 2 // "file:/<path>"
Packit df99a1
        && (url_ptr[0] == slash)
Packit df99a1
        && (url_ptr[1] != slash) )
Packit df99a1
      url_ptr++;
Packit df99a1
#endif
Packit df99a1
Packit df99a1
    // Check if we are finished
Packit df99a1
#if defined(macintosh)
Packit df99a1
    {
Packit df99a1
      char *l_url;
Packit df99a1
      GPBuffer<char> gl_url(l_url,strlen(url_ptr)+1);
Packit df99a1
      const char *s;
Packit df99a1
      char *r;
Packit df99a1
      for ( s=url_ptr,r=l_url; *s; s++,r++)
Packit df99a1
      {
Packit df99a1
        *r=(*s == slash)?colon:*s;
Packit df99a1
      }
Packit df99a1
      *r=0;
Packit df99a1
      retval = expand_name(l_url,root);
Packit df99a1
    }
Packit df99a1
#else  
Packit df99a1
    retval = expand_name(url_ptr,root);
Packit df99a1
#endif
Packit df99a1
    
Packit df99a1
#if defined(_WIN32) || defined(OS2)
Packit df99a1
    if (url_ptr[0] && url_ptr[1]=='|' && url_ptr[2]== slash)
Packit df99a1
    {
Packit df99a1
      if ((url_ptr[0]>='a' && url_ptr[0]<='z') 
Packit df99a1
          || (url_ptr[0]>='A' && url_ptr[0]<='Z'))
Packit df99a1
      {
Packit df99a1
	GUTF8String drive;
Packit df99a1
	drive.format("%c%c%c", url_ptr[0],colon,backslash);
Packit df99a1
	retval = expand_name(url_ptr+3, drive);
Packit df99a1
      }
Packit df99a1
    }
Packit df99a1
#endif
Packit df99a1
  }
Packit df99a1
  // Return what we have
Packit df99a1
  return retval;
Packit df99a1
}
Packit df99a1
Packit df99a1
GNativeString 
Packit df99a1
GURL::NativeFilename(void) const
Packit df99a1
{
Packit df99a1
  return UTF8Filename().getUTF82Native();
Packit df99a1
}
Packit df99a1
Packit df99a1
#if defined(UNIX) || defined(macintosh) || defined(OS2)
Packit df99a1
static int
Packit df99a1
urlstat(const GURL &url,struct stat &buf)
Packit df99a1
{
Packit df99a1
  return ::stat(url.NativeFilename(),&buf;;
Packit df99a1
}
Packit df99a1
#endif
Packit df99a1
Packit df99a1
// is_file(url) --
Packit df99a1
// -- returns true if filename denotes a regular file.
Packit df99a1
bool
Packit df99a1
GURL::is_file(void) const
Packit df99a1
{
Packit df99a1
  bool retval=false;
Packit df99a1
  if(is_local_file_url())
Packit df99a1
  {
Packit df99a1
#if defined(UNIX) || defined(macintosh) || defined(OS2)
Packit df99a1
    struct stat buf;
Packit df99a1
    if (!urlstat(*this,buf))
Packit df99a1
    {
Packit df99a1
      retval=!(buf.st_mode & S_IFDIR);
Packit df99a1
    }
Packit df99a1
#elif defined(_WIN32)
Packit df99a1
    GUTF8String filename(UTF8Filename());
Packit df99a1
    if(filename.length() >= MAX_PATH)
Packit df99a1
      {
Packit df99a1
        if(!filename.cmp("\\\\",2))
Packit df99a1
          filename="\\\\?\\UNC"+filename.substr(1,-1);
Packit df99a1
        else
Packit df99a1
          filename="\\\\?\\"+filename;
Packit df99a1
      }
Packit df99a1
    wchar_t *wfilename;
Packit df99a1
    const size_t wfilename_size=filename.length()+1;
Packit df99a1
    GPBuffer<wchar_t> gwfilename(wfilename,wfilename_size);
Packit df99a1
    filename.ncopy(wfilename,wfilename_size);
Packit df99a1
    DWORD dwAttrib;
Packit df99a1
    dwAttrib = GetFileAttributesW(wfilename);
Packit df99a1
    if((dwAttrib|1) == 0xFFFFFFFF)
Packit df99a1
        dwAttrib = GetFileAttributesA(NativeFilename());
Packit df99a1
    retval=!( dwAttrib & FILE_ATTRIBUTE_DIRECTORY );
Packit df99a1
#else
Packit df99a1
# error "Define something here for your operating system"
Packit df99a1
#endif
Packit df99a1
  }
Packit df99a1
  return retval;
Packit df99a1
}
Packit df99a1
Packit df99a1
bool
Packit df99a1
GURL::is_local_path(void) const
Packit df99a1
{
Packit df99a1
  bool retval=false;
Packit df99a1
  if(is_local_file_url())
Packit df99a1
  {
Packit df99a1
#if defined(UNIX) || defined(macintosh) || defined(OS2)
Packit df99a1
    struct stat buf;
Packit df99a1
    retval=!urlstat(*this,buf);
Packit df99a1
#else
Packit df99a1
    GUTF8String filename(UTF8Filename());
Packit df99a1
    if(filename.length() >= MAX_PATH)
Packit df99a1
      {
Packit df99a1
        if(!filename.cmp("\\\\",2))
Packit df99a1
          filename="\\\\?\\UNC"+filename.substr(1,-1);
Packit df99a1
        else
Packit df99a1
          filename="\\\\?\\"+filename;
Packit df99a1
      }
Packit df99a1
    wchar_t *wfilename;
Packit df99a1
    const size_t wfilename_size=filename.length()+1;
Packit df99a1
    GPBuffer<wchar_t> gwfilename(wfilename,wfilename_size);
Packit df99a1
    filename.ncopy(wfilename,wfilename_size);
Packit df99a1
    DWORD dwAttrib;
Packit df99a1
    dwAttrib = GetFileAttributesW(wfilename);
Packit df99a1
    if((dwAttrib|1) == 0xFFFFFFFF)
Packit df99a1
        dwAttrib = GetFileAttributesA(NativeFilename());
Packit df99a1
    retval=( (dwAttrib|1) != 0xFFFFFFFF);
Packit df99a1
#endif
Packit df99a1
  }
Packit df99a1
  return retval;
Packit df99a1
}
Packit df99a1
Packit df99a1
// is_dir(url) --
Packit df99a1
// -- returns true if url denotes a directory.
Packit df99a1
bool 
Packit df99a1
GURL::is_dir(void) const
Packit df99a1
{
Packit df99a1
  bool retval=false;
Packit df99a1
  if(is_local_file_url())
Packit df99a1
  {
Packit df99a1
    // UNIX implementation
Packit df99a1
#if defined(UNIX) || defined(macintosh) || defined(OS2)
Packit df99a1
    struct stat buf;
Packit df99a1
    if (!urlstat(*this,buf))
Packit df99a1
    {
Packit df99a1
      retval=(buf.st_mode & S_IFDIR);
Packit df99a1
    }
Packit df99a1
#elif defined(_WIN32)   // (either Windows or WCE)
Packit df99a1
    GUTF8String filename(UTF8Filename());
Packit df99a1
    if(filename.length() >= MAX_PATH)
Packit df99a1
      {
Packit df99a1
        if(!filename.cmp("\\\\",2))
Packit df99a1
          filename="\\\\?\\UNC"+filename.substr(1,-1);
Packit df99a1
        else
Packit df99a1
          filename="\\\\?\\"+filename;
Packit df99a1
      }
Packit df99a1
    wchar_t *wfilename;
Packit df99a1
    const size_t wfilename_size=filename.length()+1;
Packit df99a1
    GPBuffer<wchar_t> gwfilename(wfilename,wfilename_size);
Packit df99a1
    filename.ncopy(wfilename,wfilename_size);
Packit df99a1
    DWORD dwAttrib;
Packit df99a1
    dwAttrib = GetFileAttributesW(wfilename);
Packit df99a1
    if((dwAttrib|1) == 0xFFFFFFFF)
Packit df99a1
        dwAttrib = GetFileAttributesA(NativeFilename());
Packit df99a1
    retval=((dwAttrib != 0xFFFFFFFF)&&( dwAttrib & FILE_ATTRIBUTE_DIRECTORY ));
Packit df99a1
#else
Packit df99a1
# error "Define something here for your operating system"
Packit df99a1
#endif
Packit df99a1
  }
Packit df99a1
  return retval;
Packit df99a1
}
Packit df99a1
Packit df99a1
// Follows symbolic links.
Packit df99a1
GURL 
Packit df99a1
GURL::follow_symlinks(void) const
Packit df99a1
{
Packit df99a1
  GURL ret = *this;
Packit df99a1
#if defined(S_IFLNK)
Packit df99a1
#if defined(UNIX) || defined(macintosh)
Packit df99a1
  int lnklen;
Packit df99a1
  char lnkbuf[MAXPATHLEN+1];
Packit df99a1
  struct stat buf;
Packit df99a1
  while ( (urlstat(ret, buf) >= 0) &&
Packit df99a1
          (buf.st_mode & S_IFLNK) &&
Packit df99a1
          ((lnklen = readlink(ret.NativeFilename(),lnkbuf,sizeof(lnkbuf))) > 0) )
Packit df99a1
    {
Packit df99a1
      lnkbuf[lnklen] = 0;
Packit df99a1
      GNativeString lnk(lnkbuf);
Packit df99a1
      ret = GURL(lnk, ret.base());
Packit df99a1
    }
Packit df99a1
#endif
Packit df99a1
#endif
Packit df99a1
  return ret;
Packit df99a1
}
Packit df99a1
Packit df99a1
int
Packit df99a1
GURL::mkdir() const
Packit df99a1
{
Packit df99a1
  if(! is_local_file_url())
Packit df99a1
    return -1;
Packit df99a1
  int retval=0;
Packit df99a1
  const GURL baseURL=base();
Packit df99a1
  if (baseURL.get_string() != url && !baseURL.is_dir())
Packit df99a1
    retval = baseURL.mkdir();
Packit df99a1
  if(!retval)
Packit df99a1
    {
Packit df99a1
#if defined(UNIX)
Packit df99a1
      if (is_dir())
Packit df99a1
        retval = 0;
Packit df99a1
      else 
Packit df99a1
        retval = ::mkdir(NativeFilename(), 0755);
Packit df99a1
#elif defined(_WIN32)
Packit df99a1
      if (is_dir())
Packit df99a1
        retval = 0;
Packit df99a1
      else 
Packit df99a1
        retval = CreateDirectoryA(NativeFilename(), NULL);
Packit df99a1
#else
Packit df99a1
# error "Define something here for your operating system"
Packit df99a1
#endif
Packit df99a1
    }
Packit df99a1
  return retval;
Packit df99a1
}
Packit df99a1
Packit df99a1
// deletefile
Packit df99a1
// -- deletes a file or directory
Packit df99a1
  
Packit df99a1
int
Packit df99a1
GURL::deletefile(void) const
Packit df99a1
{
Packit df99a1
  int retval = -1;
Packit df99a1
  if(is_local_file_url())
Packit df99a1
    {
Packit df99a1
#if defined(UNIX)
Packit df99a1
      if (is_dir())
Packit df99a1
        retval = ::rmdir(NativeFilename());
Packit df99a1
      else
Packit df99a1
        retval = ::unlink(NativeFilename());
Packit df99a1
#elif defined(_WIN32)
Packit df99a1
      if (is_dir())
Packit df99a1
        retval = ::RemoveDirectoryA(NativeFilename());
Packit df99a1
      else
Packit df99a1
        retval = ::DeleteFile(NativeFilename());
Packit df99a1
#else
Packit df99a1
# error "Define something here for your operating system"
Packit df99a1
#endif
Packit df99a1
  }
Packit df99a1
  return retval;
Packit df99a1
}
Packit df99a1
Packit df99a1
GList<GURL>
Packit df99a1
GURL::listdir(void) const
Packit df99a1
{
Packit df99a1
  GList<GURL> retval;
Packit df99a1
  if(is_dir())
Packit df99a1
  {
Packit df99a1
#if defined(UNIX) || defined(OS2)
Packit df99a1
    DIR * dir=opendir(NativeFilename());//MBCS cvt
Packit df99a1
    for(dirent *de=readdir(dir);de;de=readdir(dir))
Packit df99a1
    {
Packit df99a1
      const int len = NAMLEN(de);
Packit df99a1
      if (de->d_name[0]== dot  && len==1)
Packit df99a1
        continue;
Packit df99a1
      if (de->d_name[0]== dot  && de->d_name[1]== dot  && len==2)
Packit df99a1
        continue;
Packit df99a1
      retval.append(GURL::Native(de->d_name,*this));
Packit df99a1
    }
Packit df99a1
    closedir(dir);
Packit df99a1
#elif defined(_WIN32)
Packit df99a1
    GURL::UTF8 wildcard("*.*",*this);
Packit df99a1
    WIN32_FIND_DATA finddata;
Packit df99a1
    HANDLE handle = FindFirstFile(wildcard.NativeFilename(), &finddata);//MBCS cvt
Packit df99a1
    const GUTF8String gpathname=pathname();
Packit df99a1
    const GUTF8String gbase=base().pathname();
Packit df99a1
    if( handle != INVALID_HANDLE_VALUE)
Packit df99a1
    {
Packit df99a1
      do
Packit df99a1
      {
Packit df99a1
        GURL::UTF8 Entry(finddata.cFileName,*this);
Packit df99a1
        const GUTF8String gentry=Entry.pathname();
Packit df99a1
        if((gentry != gpathname) && (gentry != gbase))
Packit df99a1
          retval.append(Entry);
Packit df99a1
      } while( FindNextFile(handle, &finddata) );
Packit df99a1
Packit df99a1
      FindClose(handle);
Packit df99a1
    }
Packit df99a1
#else
Packit df99a1
# error "Define something here for your operating system"
Packit df99a1
#endif
Packit df99a1
  }
Packit df99a1
  return retval;
Packit df99a1
}
Packit df99a1
Packit df99a1
int
Packit df99a1
GURL::cleardir(const int timeout) const
Packit df99a1
{
Packit df99a1
  int retval=(-1);
Packit df99a1
  if(is_dir())
Packit df99a1
  {
Packit df99a1
    GList<GURL> dirlist=listdir();
Packit df99a1
    retval=0;
Packit df99a1
    for(GPosition pos=dirlist;pos&&!retval;++pos)
Packit df99a1
    {
Packit df99a1
      const GURL &Entry=dirlist[pos];
Packit df99a1
      if(Entry.is_dir())
Packit df99a1
      {
Packit df99a1
        if((retval=Entry.cleardir(timeout)) < 0)
Packit df99a1
        {
Packit df99a1
          break;
Packit df99a1
        }
Packit df99a1
      }
Packit df99a1
      if(((retval=Entry.deletefile())<0) && (timeout>0))
Packit df99a1
      {
Packit df99a1
        GOS::sleep(timeout);
Packit df99a1
        retval=Entry.deletefile();
Packit df99a1
      }
Packit df99a1
    }
Packit df99a1
  }
Packit df99a1
  return retval;
Packit df99a1
}
Packit df99a1
Packit df99a1
int
Packit df99a1
GURL::renameto(const GURL &newurl) const
Packit df99a1
{
Packit df99a1
  if (is_local_file_url() && newurl.is_local_file_url())
Packit df99a1
    return rename(NativeFilename(),newurl.NativeFilename());
Packit df99a1
  return -1;
Packit df99a1
}
Packit df99a1
Packit df99a1
// expand_name(filename[, fromdirname])
Packit df99a1
// -- returns the full path name of filename interpreted
Packit df99a1
//    relative to fromdirname.  Use current working dir when
Packit df99a1
//    fromdirname is null.
Packit df99a1
GUTF8String 
Packit df99a1
GURL::expand_name(const GUTF8String &xfname, const char *from)
Packit df99a1
{
Packit df99a1
  const char *fname=xfname;
Packit df99a1
  GUTF8String retval;
Packit df99a1
  const size_t maxlen=xfname.length()*9+MAXPATHLEN+10;
Packit df99a1
  char * const string_buffer = retval.getbuf(maxlen);
Packit df99a1
  // UNIX implementation
Packit df99a1
#if defined(UNIX)
Packit df99a1
  // Perform tilde expansion
Packit df99a1
  GUTF8String senv;
Packit df99a1
  if (fname && fname[0]==tilde)
Packit df99a1
  {
Packit df99a1
    int n;
Packit df99a1
    for(n=1;fname[n] && fname[n]!= slash;n++) 
Packit df99a1
      EMPTY_LOOP;
Packit df99a1
    struct passwd *pw=0;
Packit df99a1
    if (n!=1)
Packit df99a1
    {
Packit df99a1
      GUTF8String user(fname+1, n-1);
Packit df99a1
      pw=getpwnam(user);
Packit df99a1
    }else if ((senv=GOS::getenv("HOME")).length())
Packit df99a1
    {
Packit df99a1
      from=(const char *)senv;
Packit df99a1
      fname = fname + n;
Packit df99a1
    }else if ((senv=GOS::getenv("LOGNAME")).length())
Packit df99a1
    {
Packit df99a1
      pw = getpwnam((const char *)senv.getUTF82Native());
Packit df99a1
    }else
Packit df99a1
    {
Packit df99a1
      pw=getpwuid(getuid());
Packit df99a1
    }
Packit df99a1
    if (pw)
Packit df99a1
    {
Packit df99a1
      senv=GNativeString(pw->pw_dir).getNative2UTF8();
Packit df99a1
      from = (const char *)senv;
Packit df99a1
      fname = fname + n;
Packit df99a1
    }
Packit df99a1
    for(;fname[0] == slash; fname++)
Packit df99a1
      EMPTY_LOOP;
Packit df99a1
  }
Packit df99a1
  // Process absolute vs. relative path
Packit df99a1
  if (fname && fname[0]== slash)
Packit df99a1
  {
Packit df99a1
    string_buffer[0]=slash;
Packit df99a1
    string_buffer[1]=0;
Packit df99a1
  }else if (from)
Packit df99a1
  {
Packit df99a1
    strcpy(string_buffer, expand_name(from));
Packit df99a1
  }else
Packit df99a1
  {
Packit df99a1
    strcpy(string_buffer, GOS::cwd());
Packit df99a1
  }
Packit df99a1
  char *s = string_buffer + strlen(string_buffer);
Packit df99a1
  if(fname)
Packit df99a1
  {
Packit df99a1
    for(;fname[0]== slash;fname++)
Packit df99a1
      EMPTY_LOOP;
Packit df99a1
    // Process path components
Packit df99a1
    while(fname[0])
Packit df99a1
    {
Packit df99a1
      if (fname[0] == dot )
Packit df99a1
      {
Packit df99a1
        if (!fname[1] || fname[1]== slash)
Packit df99a1
        {
Packit df99a1
          fname++;
Packit df99a1
          continue;
Packit df99a1
        }else if (fname[1]== dot && (fname[2]== slash || !fname[2]))
Packit df99a1
        {
Packit df99a1
          fname +=2;
Packit df99a1
          for(;s>string_buffer+1 && *(s-1)== slash; s--)
Packit df99a1
            EMPTY_LOOP;
Packit df99a1
          for(;s>string_buffer+1 && *(s-1)!= slash; s--)
Packit df99a1
            EMPTY_LOOP;
Packit df99a1
          continue;
Packit df99a1
        }
Packit df99a1
      }
Packit df99a1
      if ((s==string_buffer)||(*(s-1)!= slash))
Packit df99a1
      {
Packit df99a1
        *s = slash;
Packit df99a1
        s++;
Packit df99a1
      }
Packit df99a1
      while (*fname &&(*fname!= slash))
Packit df99a1
      {
Packit df99a1
        *s = *fname++;
Packit df99a1
        if ((size_t)((++s)-string_buffer) > maxlen)
Packit df99a1
        {
Packit df99a1
          G_THROW( ERR_MSG("GURL.big_name") );
Packit df99a1
        }
Packit df99a1
      }
Packit df99a1
      *s = 0;
Packit df99a1
      for(;fname[0]== slash;fname++)
Packit df99a1
        EMPTY_LOOP;
Packit df99a1
    }
Packit df99a1
  }
Packit df99a1
  if (!fname || !fname[0])
Packit df99a1
  {
Packit df99a1
    for(;s>string_buffer+1 && *(s-1) == slash; s--)
Packit df99a1
      EMPTY_LOOP;
Packit df99a1
    *s = 0;
Packit df99a1
  }
Packit df99a1
#elif defined(_WIN32) // WIN32 implementation
Packit df99a1
  // Handle base
Packit df99a1
  strcpy(string_buffer, (char const *)(from ? expand_name(from) : GOS::cwd()));
Packit df99a1
  //  GNativeString native;
Packit df99a1
  if (fname)
Packit df99a1
  {
Packit df99a1
    char *s = string_buffer;
Packit df99a1
    char  drv[4];
Packit df99a1
    // Handle absolute part of fname
Packit df99a1
    //      Put absolute part of the file name in string_buffer, and
Packit df99a1
    //      the relative part pointed to by fname.
Packit df99a1
    if (fname[0]== slash || fname[0]== backslash)
Packit df99a1
    {
Packit df99a1
      if (fname[1]== slash || fname[1]== backslash)
Packit df99a1
      {       // Case "//abcd"
Packit df99a1
        s[0]=s[1]= backslash; s[2]=0;
Packit df99a1
      }
Packit df99a1
      else
Packit df99a1
      {       // Case "/abcd" or "/"
Packit df99a1
              //    File is at the root of the current drive. Delete the
Packit df99a1
              //    slash at the beginning of the filename and leave
Packit df99a1
              //    an explicit identification of the root of the drive in
Packit df99a1
              //    string_buffer.
Packit df99a1
        fname++;
Packit df99a1
        s[3] = '\0';
Packit df99a1
      }
Packit df99a1
    }
Packit df99a1
    else if (fname[0] && fname[1]==colon)
Packit df99a1
    {
Packit df99a1
      if (fname[2]!= slash && fname[2]!= backslash)
Packit df99a1
      {       // Case "x:abcd"
Packit df99a1
        if ( toupper((unsigned char)s[0]) != toupper((unsigned char)fname[0])
Packit df99a1
          || s[1]!=colon)
Packit df99a1
        {
Packit df99a1
          drv[0]=fname[0];
Packit df99a1
          drv[1]=colon;
Packit df99a1
          drv[2]= dot ;
Packit df99a1
          drv[3]=0;
Packit df99a1
          GetFullPathName(drv, maxlen, string_buffer, &s);
Packit df99a1
          strcpy(string_buffer,(const char *)GUTF8String(string_buffer).getNative2UTF8());
Packit df99a1
          s = string_buffer;
Packit df99a1
        }
Packit df99a1
        fname += 2;
Packit df99a1
      }
Packit df99a1
      else if (fname[3]!= slash && fname[3]!= backslash)
Packit df99a1
      {       // Case "x:/abcd"
Packit df99a1
        s[0]=toupper((unsigned char)fname[0]);
Packit df99a1
        s[1]=colon;
Packit df99a1
        s[2]=backslash;
Packit df99a1
        s[3]=0;
Packit df99a1
        fname += 3;
Packit df99a1
      }
Packit df99a1
      else
Packit df99a1
      {       // Case "x://abcd"
Packit df99a1
        s[0]=s[1]=backslash;
Packit df99a1
        s[2]=0;
Packit df99a1
        fname += 4;
Packit df99a1
      }
Packit df99a1
    }
Packit df99a1
    // Process path components
Packit df99a1
    while(*fname)
Packit df99a1
    {
Packit df99a1
      for(;*fname== slash || *fname==backslash;fname++)
Packit df99a1
        EMPTY_LOOP;
Packit df99a1
      if (fname[0]== dot )
Packit df99a1
      {
Packit df99a1
        if (fname[1]== slash || fname[1]==backslash || !fname[1])
Packit df99a1
        {
Packit df99a1
          fname++;
Packit df99a1
          continue;
Packit df99a1
        }
Packit df99a1
		else if ((fname[1] == dot)
Packit df99a1
                 && (fname[2]== slash || fname[2]==backslash || !fname[2]))
Packit df99a1
        {
Packit df99a1
          fname += 2;
Packit df99a1
          char *back=_tcsrchr(string_buffer,backslash);
Packit df99a1
          char *forward=_tcsrchr(string_buffer,slash);
Packit df99a1
          if(back>forward)
Packit df99a1
          {
Packit df99a1
            *back=0;
Packit df99a1
          }else if(forward)
Packit df99a1
          {
Packit df99a1
            *forward=0;
Packit df99a1
          }
Packit df99a1
          s = string_buffer;
Packit df99a1
          continue;
Packit df99a1
        }
Packit df99a1
      }
Packit df99a1
      char* s2=s;//MBCS DBCS
Packit df99a1
      for(;*s;s++) 
Packit df99a1
        EMPTY_LOOP;
Packit df99a1
	  if (s > string_buffer && s[-1] != slash && s[-1] != backslash)
Packit df99a1
        *s++ = backslash;
Packit df99a1
      while (*fname && (*fname!= slash) && (*fname!=backslash))
Packit df99a1
      {
Packit df99a1
        if (s > string_buffer + maxlen)
Packit df99a1
          G_THROW( ERR_MSG("GURL.big_name") );
Packit df99a1
        *s++ = *fname++;
Packit df99a1
      }
Packit df99a1
      *s = 0;
Packit df99a1
    }
Packit df99a1
  }
Packit df99a1
#else
Packit df99a1
# error "Define something here for your operating system"
Packit df99a1
#endif  
Packit df99a1
  return retval;
Packit df99a1
}
Packit df99a1
Packit df99a1
unsigned int
Packit df99a1
hash(const GURL & gurl)
Packit df99a1
{
Packit df99a1
  unsigned int retval;
Packit df99a1
  const GUTF8String s(gurl.get_string());
Packit df99a1
  const int len=s.length();
Packit df99a1
  if(len && (s[len-1] == '/')) // Don't include the trailing slash as part of the hash.
Packit df99a1
  {
Packit df99a1
	retval=hash(s.substr(0,len-1));
Packit df99a1
  }else
Packit df99a1
  {
Packit df99a1
    retval=hash(s);
Packit df99a1
  }
Packit df99a1
  return retval;
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
#ifdef HAVE_NAMESPACES
Packit df99a1
}
Packit df99a1
# ifndef NOT_USING_DJVU_NAMESPACE
Packit df99a1
using namespace DJVU;
Packit df99a1
# endif
Packit df99a1
#endif