/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
/*
* LDAP tools fileurl.c -- functions for handling file URLs.
* Used by ldapmodify.
*/
#include "ldaptool.h"
#include "fileurl.h"
#include <ctype.h> /* for isalpha() */
#ifdef SOLARIS_LDAP_CMD
#include <locale.h>
#endif /* SOLARIS_LDAP_CMD */
#ifndef SOLARIS_LDAP_CMD
#define gettext(s) s
#endif
static int str_starts_with( const char *s, char *prefix );
static void hex_unescape( char *s );
static int unhex( char c );
int reporterrs );
/*
* Convert a file URL to a local path.
*
* If successful, LDAPTOOL_FILEURL_SUCCESS is returned and *localpathp is
* set point to an allocated string. If not, an different LDAPTOOL_FILEURL_
* error code is returned.
*
* See RFCs 1738 and 2396 for a specification for file URLs... but
* Netscape Navigator seems to be a bit more lenient in what it will
* accept, especially on Windows).
*
* This function parses file URLs of these three forms:
*
* file:///path
* file:/path
*
* On Windows, we convert leading drive letters of the form C| to C:
* and if a drive letter is present we strip off the slash that precedes
* path. Otherwise, the leading slash is returned.
*
*/
int
{
const char *path;
char *pathcopy;
/*
* Make sure this is a file URL we can handle.
*/
return( LDAPTOOL_FILEURL_NOTAFILEURL );
}
if ( *path != '/' ) {
return( LDAPTOOL_FILEURL_MISSINGPATH );
}
++path; /* skip past '/' at end of "file:/" */
if ( *path == '/' ) {
if ( *path != '/' ) {
/*
* Make sure it is for the local host.
*/
path += 9;
} else {
return( LDAPTOOL_FILEURL_NONLOCAL );
}
}
} else { /* URL is of the form file:/path */
--path;
}
/*
* The remainder is now of the form /path. On Windows, skip past the
* leading slash if a drive letter is present.
*/
#ifdef _WINDOWS
++path;
}
#endif /* _WINDOWS */
/*
* Duplicate the path so we can safely alter it.
* Unescape any %HH sequences.
*/
return( LDAPTOOL_FILEURL_NOMEMORY );
}
hex_unescape( pathcopy );
#ifdef _WINDOWS
/*
* Convert forward slashes to backslashes for Windows. Also,
* if we see a drive letter / vertical bar combination (e.g., c|)
* at the beginning of the path, replace the '|' with a ':'.
*/
{
char *p;
for ( p = pathcopy; *p != '\0'; ++p ) {
if ( *p == '/' ) {
*p = '\\';
}
}
}
}
#endif /* _WINDOWS */
*localpathp = pathcopy;
return( LDAPTOOL_FILEURL_SUCCESS );
}
/*
* Convert a local path to a file URL.
*
* If successful, LDAPTOOL_FILEURL_SUCCESS is returned and *urlp is
* set point to an allocated string. If not, an different LDAPTOOL_FILEURL_
* error code is returned. At present, the only possible error is
* LDAPTOOL_FILEURL_NOMEMORY.
*
* This function produces file URLs of the form file:path.
*
* On Windows, we convert leading drive letters to C|.
*
*/
int
{
path = "/";
}
/*
* Allocate space for the URL, taking into account that path may
* expand during the hex escaping process.
*/
return( LDAPTOOL_FILEURL_NOMEMORY );
}
#ifdef _WINDOWS
/*
* On Windows, convert leading drive letters (e.g., C:) to the correct URL
* syntax (e.g., C|).
*/
*p++ = path[0];
*p++ = '|';
path += 2;
*p = '\0';
}
#endif /* _WINDOWS */
/*
* Append the path, encoding any URL-special characters using the %HH
* convention.
* On Windows, convert backwards slashes in the path to forward ones.
*/
strcpy_escaped_and_convert( p, path );
return( LDAPTOOL_FILEURL_SUCCESS );
}
/*
* Populate *bvp from "value" of length "vlen."
*
* If recognize_url_syntax is non-zero, :<fileurl is recognized.
* If always_try_file is recognized and no file URL was found, an
* attempt is made to stat and read the value as if it were the name
* of a file.
*
* If reporterrs is non-zero, specific error messages are printed to
* stderr.
*
* If successful, LDAPTOOL_FILEURL_SUCCESS is returned and bvp->bv_len
* and bvp->bv_val are set (the latter is set to malloc'd memory).
* Upon failure, a different LDAPTOOL_FILEURL_ error code is returned.
*/
int
int reporterrs )
{
/* recognize "attr :< url" syntax if LDIF version is >= 1 */
#ifdef notdef
if ( ldaptool_verbose ) {
}
#endif
; /* NULL */
}
/*
* We only support file:// URLs for now.
*/
}
}
char *path;
switch( rc ) {
break;
gettext("%s: unable to process URL \"%s\" --"
break;
gettext("%s: unable to process URL \"%s\" -- only"
" local file:// URLs are supported.\n"),
ldaptool_progname, url );
break;
break;
case LDAPTOOL_FILEURL_SUCCESS:
gettext("%s: %s is a directory, not a file\n"),
} else {
}
break;
default:
gettext("%s: unable to process URL \"%s\""
}
} else {
} else {
}
}
return( rc );
}
/*
* Map an LDAPTOOL_FILEURL_ error code to an LDAP error code (crude).
*/
int
{
int rc;
switch( lderr ) {
case LDAPTOOL_FILEURL_SUCCESS:
rc = LDAP_SUCCESS;
break;
rc = LDAP_NO_MEMORY;
break;
default:
}
return( rc );
}
/*
* Populate *bvp with the contents of the file named by "path".
*
* If reporterrs is non-zero, specific error messages are printed to
* stderr.
*
* If successful, LDAPTOOL_FILEURL_SUCCESS is returned and bvp->bv_len
* and bvp->bv_val are set (the latter is set to malloc'd memory).
* Upon failure, a different LDAPTOOL_FILEURL_ error code is returned.
*/
static int
{
long rlen;
int eof;
#if defined( XP_WIN32 )
#else
#endif
#ifdef SOLARIS_LDAP_CMD
#else
#endif /* SOLARIS_LDAP_CMD */
return( LDAPTOOL_FILEURL_FILEIOERROR );
}
return( LDAPTOOL_FILEURL_FILEIOERROR );
}
return( LDAPTOOL_FILEURL_NOMEMORY );
}
return( LDAPTOOL_FILEURL_FILEIOERROR );
}
return( LDAPTOOL_FILEURL_FILEIOERROR );
}
return( LDAPTOOL_FILEURL_SUCCESS );
}
/*
* Return a non-zero value if the string s begins with prefix and zero if not.
*/
static int
{
return( 0 );
}
if ( strlen( s ) < prefix_len ) {
return( 0 );
}
}
/*
* Remove URL hex escapes from s... done in place. The basic concept for
* this routine is borrowed from the WWW library HTUnEscape() routine.
*
* A similar function called nsldapi_hex_unescape can be found in
* ../../libraries/libldap/unescape.c
*/
static void
hex_unescape( char *s )
{
char *p;
for ( p = s; *s != '\0'; ++s ) {
if ( *s == '%' ) {
if ( *++s != '\0' ) {
*p = unhex( *s ) << 4;
}
if ( *++s != '\0' ) {
*p++ += unhex( *s );
}
} else {
*p++ = *s;
}
}
*p = '\0';
}
/*
* Return the integer equivalent of one hex digit (in c).
*
* A similar function can be found in ../../libraries/libldap/unescape.c
*/
static int
unhex( char c )
{
return( c >= '0' && c <= '9' ? c - '0'
: c >= 'A' && c <= 'F' ? c - 'A' + 10
: c - 'a' + 10 );
}
( c >= '@' && c <= 'Z' ) || \
( c == '_' ) || \
( c >= 'a' && c <= 'z' ))
/*
* Like strcat(), except if any URL-special characters are found in s2
* they are escaped using the %HH convention and backslash characters are
* converted to forward slashes on Windows.
*
* Maximum space needed in s1 is 3 * strlen( s2 ) + 1.
*
* A similar function that does not convert the slashes called
*/
static void
{
char *p, *q;
for ( q = s2; *q != '\0'; ++q ) {
#ifdef _WINDOWS
if ( *q == '\\' ) {
*p++ = '/';
} else
#endif /* _WINDOWS */
if ( HREF_CHAR_ACCEPTABLE( *q )) {
*p++ = *q;
} else {
*p++ = '%';
*p++ = hexdig[ 0x0F & *q ];
}
}
*p = '\0';
}