17c478bd9Sstevel@tonic-gate /* 2*ffc33b84SSreedhar Chalamalasetti - Sun Microsystems - Bangalore India * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 37c478bd9Sstevel@tonic-gate * Use is subject to license terms. 47c478bd9Sstevel@tonic-gate */ 57c478bd9Sstevel@tonic-gate 67c478bd9Sstevel@tonic-gate /* 77c478bd9Sstevel@tonic-gate * The contents of this file are subject to the Netscape Public 87c478bd9Sstevel@tonic-gate * License Version 1.1 (the "License"); you may not use this file 97c478bd9Sstevel@tonic-gate * except in compliance with the License. You may obtain a copy of 107c478bd9Sstevel@tonic-gate * the License at http://www.mozilla.org/NPL/ 117c478bd9Sstevel@tonic-gate * 127c478bd9Sstevel@tonic-gate * Software distributed under the License is distributed on an "AS 137c478bd9Sstevel@tonic-gate * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or 147c478bd9Sstevel@tonic-gate * implied. See the License for the specific language governing 157c478bd9Sstevel@tonic-gate * rights and limitations under the License. 167c478bd9Sstevel@tonic-gate * 177c478bd9Sstevel@tonic-gate * The Original Code is Mozilla Communicator client code, released 187c478bd9Sstevel@tonic-gate * March 31, 1998. 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * The Initial Developer of the Original Code is Netscape 217c478bd9Sstevel@tonic-gate * Communications Corporation. Portions created by Netscape are 227c478bd9Sstevel@tonic-gate * Copyright (C) 1998-1999 Netscape Communications Corporation. All 237c478bd9Sstevel@tonic-gate * Rights Reserved. 247c478bd9Sstevel@tonic-gate * 257c478bd9Sstevel@tonic-gate * Contributor(s): 267c478bd9Sstevel@tonic-gate */ 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate /* 297c478bd9Sstevel@tonic-gate * LDAP tools fileurl.c -- functions for handling file URLs. 307c478bd9Sstevel@tonic-gate * Used by ldapmodify. 317c478bd9Sstevel@tonic-gate */ 327c478bd9Sstevel@tonic-gate 337c478bd9Sstevel@tonic-gate #include "ldaptool.h" 347c478bd9Sstevel@tonic-gate #include "fileurl.h" 357c478bd9Sstevel@tonic-gate #include <ctype.h> /* for isalpha() */ 367c478bd9Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD 377c478bd9Sstevel@tonic-gate #include <locale.h> 387c478bd9Sstevel@tonic-gate #endif /* SOLARIS_LDAP_CMD */ 397c478bd9Sstevel@tonic-gate 407c478bd9Sstevel@tonic-gate #ifndef SOLARIS_LDAP_CMD 417c478bd9Sstevel@tonic-gate #define gettext(s) s 427c478bd9Sstevel@tonic-gate #endif 437c478bd9Sstevel@tonic-gate 447c478bd9Sstevel@tonic-gate static int str_starts_with( const char *s, char *prefix ); 457c478bd9Sstevel@tonic-gate static void hex_unescape( char *s ); 467c478bd9Sstevel@tonic-gate static int unhex( char c ); 477c478bd9Sstevel@tonic-gate static void strcpy_escaped_and_convert( char *s1, char *s2 ); 487c478bd9Sstevel@tonic-gate static int berval_from_file( const char *path, struct berval *bvp, 497c478bd9Sstevel@tonic-gate int reporterrs ); 507c478bd9Sstevel@tonic-gate 517c478bd9Sstevel@tonic-gate /* 527c478bd9Sstevel@tonic-gate * Convert a file URL to a local path. 537c478bd9Sstevel@tonic-gate * 547c478bd9Sstevel@tonic-gate * If successful, LDAPTOOL_FILEURL_SUCCESS is returned and *localpathp is 557c478bd9Sstevel@tonic-gate * set point to an allocated string. If not, an different LDAPTOOL_FILEURL_ 567c478bd9Sstevel@tonic-gate * error code is returned. 577c478bd9Sstevel@tonic-gate * 587c478bd9Sstevel@tonic-gate * See RFCs 1738 and 2396 for a specification for file URLs... but 597c478bd9Sstevel@tonic-gate * Netscape Navigator seems to be a bit more lenient in what it will 607c478bd9Sstevel@tonic-gate * accept, especially on Windows). 617c478bd9Sstevel@tonic-gate * 627c478bd9Sstevel@tonic-gate * This function parses file URLs of these three forms: 637c478bd9Sstevel@tonic-gate * 647c478bd9Sstevel@tonic-gate * file:///path 657c478bd9Sstevel@tonic-gate * file:/path 667c478bd9Sstevel@tonic-gate * file://localhost/path 677c478bd9Sstevel@tonic-gate * file://host/path (rejected with a ...NONLOCAL error) 687c478bd9Sstevel@tonic-gate * 697c478bd9Sstevel@tonic-gate * On Windows, we convert leading drive letters of the form C| to C: 707c478bd9Sstevel@tonic-gate * and if a drive letter is present we strip off the slash that precedes 717c478bd9Sstevel@tonic-gate * path. Otherwise, the leading slash is returned. 727c478bd9Sstevel@tonic-gate * 737c478bd9Sstevel@tonic-gate */ 747c478bd9Sstevel@tonic-gate int 757c478bd9Sstevel@tonic-gate ldaptool_fileurl2path( const char *fileurl, char **localpathp ) 767c478bd9Sstevel@tonic-gate { 777c478bd9Sstevel@tonic-gate const char *path; 787c478bd9Sstevel@tonic-gate char *pathcopy; 797c478bd9Sstevel@tonic-gate 807c478bd9Sstevel@tonic-gate /* 817c478bd9Sstevel@tonic-gate * Make sure this is a file URL we can handle. 827c478bd9Sstevel@tonic-gate */ 837c478bd9Sstevel@tonic-gate if ( !str_starts_with( fileurl, "file:" )) { 847c478bd9Sstevel@tonic-gate return( LDAPTOOL_FILEURL_NOTAFILEURL ); 857c478bd9Sstevel@tonic-gate } 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate path = fileurl + 5; /* skip past "file:" scheme prefix */ 887c478bd9Sstevel@tonic-gate 897c478bd9Sstevel@tonic-gate if ( *path != '/' ) { 907c478bd9Sstevel@tonic-gate return( LDAPTOOL_FILEURL_MISSINGPATH ); 917c478bd9Sstevel@tonic-gate } 927c478bd9Sstevel@tonic-gate 937c478bd9Sstevel@tonic-gate ++path; /* skip past '/' at end of "file:/" */ 947c478bd9Sstevel@tonic-gate 957c478bd9Sstevel@tonic-gate if ( *path == '/' ) { 967c478bd9Sstevel@tonic-gate ++path; /* remainder is now host/path or /path */ 977c478bd9Sstevel@tonic-gate if ( *path != '/' ) { 987c478bd9Sstevel@tonic-gate /* 997c478bd9Sstevel@tonic-gate * Make sure it is for the local host. 1007c478bd9Sstevel@tonic-gate */ 1017c478bd9Sstevel@tonic-gate if ( str_starts_with( path, "localhost/" )) { 1027c478bd9Sstevel@tonic-gate path += 9; 1037c478bd9Sstevel@tonic-gate } else { 1047c478bd9Sstevel@tonic-gate return( LDAPTOOL_FILEURL_NONLOCAL ); 1057c478bd9Sstevel@tonic-gate } 1067c478bd9Sstevel@tonic-gate } 1077c478bd9Sstevel@tonic-gate } else { /* URL is of the form file:/path */ 1087c478bd9Sstevel@tonic-gate --path; 1097c478bd9Sstevel@tonic-gate } 1107c478bd9Sstevel@tonic-gate 1117c478bd9Sstevel@tonic-gate /* 1127c478bd9Sstevel@tonic-gate * The remainder is now of the form /path. On Windows, skip past the 1137c478bd9Sstevel@tonic-gate * leading slash if a drive letter is present. 1147c478bd9Sstevel@tonic-gate */ 1157c478bd9Sstevel@tonic-gate #ifdef _WINDOWS 1167c478bd9Sstevel@tonic-gate if ( isalpha( path[1] ) && ( path[2] == '|' || path[2] == ':' )) { 1177c478bd9Sstevel@tonic-gate ++path; 1187c478bd9Sstevel@tonic-gate } 1197c478bd9Sstevel@tonic-gate #endif /* _WINDOWS */ 1207c478bd9Sstevel@tonic-gate 1217c478bd9Sstevel@tonic-gate /* 1227c478bd9Sstevel@tonic-gate * Duplicate the path so we can safely alter it. 1237c478bd9Sstevel@tonic-gate * Unescape any %HH sequences. 1247c478bd9Sstevel@tonic-gate */ 1257c478bd9Sstevel@tonic-gate if (( pathcopy = strdup( path )) == NULL ) { 1267c478bd9Sstevel@tonic-gate return( LDAPTOOL_FILEURL_NOMEMORY ); 1277c478bd9Sstevel@tonic-gate } 1287c478bd9Sstevel@tonic-gate hex_unescape( pathcopy ); 1297c478bd9Sstevel@tonic-gate 1307c478bd9Sstevel@tonic-gate #ifdef _WINDOWS 1317c478bd9Sstevel@tonic-gate /* 1327c478bd9Sstevel@tonic-gate * Convert forward slashes to backslashes for Windows. Also, 1337c478bd9Sstevel@tonic-gate * if we see a drive letter / vertical bar combination (e.g., c|) 1347c478bd9Sstevel@tonic-gate * at the beginning of the path, replace the '|' with a ':'. 1357c478bd9Sstevel@tonic-gate */ 1367c478bd9Sstevel@tonic-gate { 1377c478bd9Sstevel@tonic-gate char *p; 1387c478bd9Sstevel@tonic-gate 1397c478bd9Sstevel@tonic-gate for ( p = pathcopy; *p != '\0'; ++p ) { 1407c478bd9Sstevel@tonic-gate if ( *p == '/' ) { 1417c478bd9Sstevel@tonic-gate *p = '\\'; 1427c478bd9Sstevel@tonic-gate } 1437c478bd9Sstevel@tonic-gate } 1447c478bd9Sstevel@tonic-gate } 1457c478bd9Sstevel@tonic-gate 1467c478bd9Sstevel@tonic-gate if ( isalpha( pathcopy[0] ) && pathcopy[1] == '|' ) { 1477c478bd9Sstevel@tonic-gate pathcopy[1] = ':'; 1487c478bd9Sstevel@tonic-gate } 1497c478bd9Sstevel@tonic-gate #endif /* _WINDOWS */ 1507c478bd9Sstevel@tonic-gate 1517c478bd9Sstevel@tonic-gate *localpathp = pathcopy; 1527c478bd9Sstevel@tonic-gate return( LDAPTOOL_FILEURL_SUCCESS ); 1537c478bd9Sstevel@tonic-gate } 1547c478bd9Sstevel@tonic-gate 1557c478bd9Sstevel@tonic-gate 1567c478bd9Sstevel@tonic-gate /* 1577c478bd9Sstevel@tonic-gate * Convert a local path to a file URL. 1587c478bd9Sstevel@tonic-gate * 1597c478bd9Sstevel@tonic-gate * If successful, LDAPTOOL_FILEURL_SUCCESS is returned and *urlp is 1607c478bd9Sstevel@tonic-gate * set point to an allocated string. If not, an different LDAPTOOL_FILEURL_ 1617c478bd9Sstevel@tonic-gate * error code is returned. At present, the only possible error is 1627c478bd9Sstevel@tonic-gate * LDAPTOOL_FILEURL_NOMEMORY. 1637c478bd9Sstevel@tonic-gate * 1647c478bd9Sstevel@tonic-gate * This function produces file URLs of the form file:path. 1657c478bd9Sstevel@tonic-gate * 1667c478bd9Sstevel@tonic-gate * On Windows, we convert leading drive letters to C|. 1677c478bd9Sstevel@tonic-gate * 1687c478bd9Sstevel@tonic-gate */ 1697c478bd9Sstevel@tonic-gate int 1707c478bd9Sstevel@tonic-gate ldaptool_path2fileurl( char *path, char **urlp ) 1717c478bd9Sstevel@tonic-gate { 1727c478bd9Sstevel@tonic-gate char *p, *url, *prefix ="file:"; 1737c478bd9Sstevel@tonic-gate 1747c478bd9Sstevel@tonic-gate if ( NULL == path ) { 1757c478bd9Sstevel@tonic-gate path = "/"; 1767c478bd9Sstevel@tonic-gate } 1777c478bd9Sstevel@tonic-gate 1787c478bd9Sstevel@tonic-gate /* 1797c478bd9Sstevel@tonic-gate * Allocate space for the URL, taking into account that path may 1807c478bd9Sstevel@tonic-gate * expand during the hex escaping process. 1817c478bd9Sstevel@tonic-gate */ 1827c478bd9Sstevel@tonic-gate if (( url = malloc( strlen( prefix ) + 3 * strlen( path ) + 1 )) == NULL ) { 1837c478bd9Sstevel@tonic-gate return( LDAPTOOL_FILEURL_NOMEMORY ); 1847c478bd9Sstevel@tonic-gate } 1857c478bd9Sstevel@tonic-gate 1867c478bd9Sstevel@tonic-gate strcpy( url, prefix ); 1877c478bd9Sstevel@tonic-gate p = url + strlen( prefix ); 1887c478bd9Sstevel@tonic-gate 1897c478bd9Sstevel@tonic-gate #ifdef _WINDOWS 1907c478bd9Sstevel@tonic-gate /* 1917c478bd9Sstevel@tonic-gate * On Windows, convert leading drive letters (e.g., C:) to the correct URL 1927c478bd9Sstevel@tonic-gate * syntax (e.g., C|). 1937c478bd9Sstevel@tonic-gate */ 1947c478bd9Sstevel@tonic-gate if ( isalpha( path[0] ) && path[1] == ':' ) { 1957c478bd9Sstevel@tonic-gate *p++ = path[0]; 1967c478bd9Sstevel@tonic-gate *p++ = '|'; 1977c478bd9Sstevel@tonic-gate path += 2; 1987c478bd9Sstevel@tonic-gate *p = '\0'; 1997c478bd9Sstevel@tonic-gate } 2007c478bd9Sstevel@tonic-gate #endif /* _WINDOWS */ 2017c478bd9Sstevel@tonic-gate 2027c478bd9Sstevel@tonic-gate /* 2037c478bd9Sstevel@tonic-gate * Append the path, encoding any URL-special characters using the %HH 2047c478bd9Sstevel@tonic-gate * convention. 2057c478bd9Sstevel@tonic-gate * On Windows, convert backwards slashes in the path to forward ones. 2067c478bd9Sstevel@tonic-gate */ 2077c478bd9Sstevel@tonic-gate strcpy_escaped_and_convert( p, path ); 2087c478bd9Sstevel@tonic-gate 2097c478bd9Sstevel@tonic-gate *urlp = url; 2107c478bd9Sstevel@tonic-gate return( LDAPTOOL_FILEURL_SUCCESS ); 2117c478bd9Sstevel@tonic-gate } 2127c478bd9Sstevel@tonic-gate 2137c478bd9Sstevel@tonic-gate 2147c478bd9Sstevel@tonic-gate /* 2157c478bd9Sstevel@tonic-gate * Populate *bvp from "value" of length "vlen." 2167c478bd9Sstevel@tonic-gate * 2177c478bd9Sstevel@tonic-gate * If recognize_url_syntax is non-zero, :<fileurl is recognized. 2187c478bd9Sstevel@tonic-gate * If always_try_file is recognized and no file URL was found, an 2197c478bd9Sstevel@tonic-gate * attempt is made to stat and read the value as if it were the name 2207c478bd9Sstevel@tonic-gate * of a file. 2217c478bd9Sstevel@tonic-gate * 2227c478bd9Sstevel@tonic-gate * If reporterrs is non-zero, specific error messages are printed to 2237c478bd9Sstevel@tonic-gate * stderr. 2247c478bd9Sstevel@tonic-gate * 2257c478bd9Sstevel@tonic-gate * If successful, LDAPTOOL_FILEURL_SUCCESS is returned and bvp->bv_len 2267c478bd9Sstevel@tonic-gate * and bvp->bv_val are set (the latter is set to malloc'd memory). 2277c478bd9Sstevel@tonic-gate * Upon failure, a different LDAPTOOL_FILEURL_ error code is returned. 2287c478bd9Sstevel@tonic-gate */ 2297c478bd9Sstevel@tonic-gate int 2307c478bd9Sstevel@tonic-gate ldaptool_berval_from_ldif_value( const char *value, int vlen, 2317c478bd9Sstevel@tonic-gate struct berval *bvp, int recognize_url_syntax, int always_try_file, 2327c478bd9Sstevel@tonic-gate int reporterrs ) 2337c478bd9Sstevel@tonic-gate { 2347c478bd9Sstevel@tonic-gate int rc = LDAPTOOL_FILEURL_SUCCESS; /* optimistic */ 2357c478bd9Sstevel@tonic-gate const char *url = NULL; 2367c478bd9Sstevel@tonic-gate struct stat fstats; 2377c478bd9Sstevel@tonic-gate 2387c478bd9Sstevel@tonic-gate /* recognize "attr :< url" syntax if LDIF version is >= 1 */ 2397c478bd9Sstevel@tonic-gate 2407c478bd9Sstevel@tonic-gate #ifdef notdef 2417c478bd9Sstevel@tonic-gate if ( ldaptool_verbose ) { 2427c478bd9Sstevel@tonic-gate fprintf( stderr, gettext("%s: ldaptool_berval_from_ldif_value: value: %s\n"), 2437c478bd9Sstevel@tonic-gate ldaptool_progname, value); 2447c478bd9Sstevel@tonic-gate } 2457c478bd9Sstevel@tonic-gate #endif 2467c478bd9Sstevel@tonic-gate 2477c478bd9Sstevel@tonic-gate if ( recognize_url_syntax && *value == '<' ) { 2487c478bd9Sstevel@tonic-gate for ( url = value + 1; isspace( *url ); ++url ) { 2497c478bd9Sstevel@tonic-gate ; /* NULL */ 2507c478bd9Sstevel@tonic-gate } 2517c478bd9Sstevel@tonic-gate 2527c478bd9Sstevel@tonic-gate if (strlen(url) > 7 && strncasecmp(url, "file://", 7) != 0) { 2537c478bd9Sstevel@tonic-gate /* 2547c478bd9Sstevel@tonic-gate * We only support file:// URLs for now. 2557c478bd9Sstevel@tonic-gate */ 2567c478bd9Sstevel@tonic-gate url = NULL; 2577c478bd9Sstevel@tonic-gate } 2587c478bd9Sstevel@tonic-gate } 2597c478bd9Sstevel@tonic-gate 2607c478bd9Sstevel@tonic-gate if ( NULL != url ) { 2617c478bd9Sstevel@tonic-gate char *path; 2627c478bd9Sstevel@tonic-gate 2637c478bd9Sstevel@tonic-gate rc = ldaptool_fileurl2path( url, &path ); 2647c478bd9Sstevel@tonic-gate switch( rc ) { 2657c478bd9Sstevel@tonic-gate case LDAPTOOL_FILEURL_NOTAFILEURL: 2667c478bd9Sstevel@tonic-gate if ( reporterrs ) fprintf( stderr, gettext("%s: unsupported URL \"%s\";" 2677c478bd9Sstevel@tonic-gate " use a file:// URL instead.\n"), ldaptool_progname, url ); 2687c478bd9Sstevel@tonic-gate break; 2697c478bd9Sstevel@tonic-gate 2707c478bd9Sstevel@tonic-gate case LDAPTOOL_FILEURL_MISSINGPATH: 2717c478bd9Sstevel@tonic-gate if ( reporterrs ) fprintf( stderr, 2727c478bd9Sstevel@tonic-gate gettext("%s: unable to process URL \"%s\" --" 2737c478bd9Sstevel@tonic-gate " missing path.\n"), ldaptool_progname, url ); 2747c478bd9Sstevel@tonic-gate break; 2757c478bd9Sstevel@tonic-gate 2767c478bd9Sstevel@tonic-gate case LDAPTOOL_FILEURL_NONLOCAL: 2777c478bd9Sstevel@tonic-gate if ( reporterrs ) fprintf( stderr, 2787c478bd9Sstevel@tonic-gate gettext("%s: unable to process URL \"%s\" -- only" 2797c478bd9Sstevel@tonic-gate " local file:// URLs are supported.\n"), 2807c478bd9Sstevel@tonic-gate ldaptool_progname, url ); 2817c478bd9Sstevel@tonic-gate break; 2827c478bd9Sstevel@tonic-gate 2837c478bd9Sstevel@tonic-gate case LDAPTOOL_FILEURL_NOMEMORY: 2847c478bd9Sstevel@tonic-gate if ( reporterrs ) perror( "ldaptool_fileurl2path" ); 2857c478bd9Sstevel@tonic-gate break; 2867c478bd9Sstevel@tonic-gate 2877c478bd9Sstevel@tonic-gate case LDAPTOOL_FILEURL_SUCCESS: 2887c478bd9Sstevel@tonic-gate if ( stat( path, &fstats ) != 0 ) { 2897c478bd9Sstevel@tonic-gate if ( reporterrs ) perror( path ); 2904bc0a2efScasper } else if (S_ISDIR(fstats.st_mode)) { 2917c478bd9Sstevel@tonic-gate if ( reporterrs ) fprintf( stderr, 2927c478bd9Sstevel@tonic-gate gettext("%s: %s is a directory, not a file\n"), 2937c478bd9Sstevel@tonic-gate ldaptool_progname, path ); 2947c478bd9Sstevel@tonic-gate rc = LDAPTOOL_FILEURL_FILEIOERROR; 2957c478bd9Sstevel@tonic-gate } else { 2967c478bd9Sstevel@tonic-gate rc = berval_from_file( path, bvp, reporterrs ); 2977c478bd9Sstevel@tonic-gate } 2987c478bd9Sstevel@tonic-gate free( path ); 2997c478bd9Sstevel@tonic-gate break; 3007c478bd9Sstevel@tonic-gate 3017c478bd9Sstevel@tonic-gate default: 3027c478bd9Sstevel@tonic-gate if ( reporterrs ) fprintf( stderr, 3037c478bd9Sstevel@tonic-gate gettext("%s: unable to process URL \"%s\"" 3047c478bd9Sstevel@tonic-gate " -- unknown error\n"), ldaptool_progname, url ); 3057c478bd9Sstevel@tonic-gate } 3067c478bd9Sstevel@tonic-gate } else if ( always_try_file && (stat( value, &fstats ) == 0) && 3074bc0a2efScasper !S_ISDIR(fstats.st_mode)) { /* get value from file */ 3087c478bd9Sstevel@tonic-gate rc = berval_from_file( value, bvp, reporterrs ); 3097c478bd9Sstevel@tonic-gate } else { 3107c478bd9Sstevel@tonic-gate bvp->bv_len = vlen; 3117c478bd9Sstevel@tonic-gate if (( bvp->bv_val = (char *)malloc( vlen + 1 )) == NULL ) { 3127c478bd9Sstevel@tonic-gate if ( reporterrs ) perror( "malloc" ); 3137c478bd9Sstevel@tonic-gate rc = LDAPTOOL_FILEURL_NOMEMORY; 3147c478bd9Sstevel@tonic-gate } else { 3157c478bd9Sstevel@tonic-gate SAFEMEMCPY( bvp->bv_val, value, vlen ); 3167c478bd9Sstevel@tonic-gate bvp->bv_val[ vlen ] = '\0'; 3177c478bd9Sstevel@tonic-gate } 3187c478bd9Sstevel@tonic-gate } 3197c478bd9Sstevel@tonic-gate 3207c478bd9Sstevel@tonic-gate return( rc ); 3217c478bd9Sstevel@tonic-gate } 3227c478bd9Sstevel@tonic-gate 3237c478bd9Sstevel@tonic-gate 3247c478bd9Sstevel@tonic-gate /* 3257c478bd9Sstevel@tonic-gate * Map an LDAPTOOL_FILEURL_ error code to an LDAP error code (crude). 3267c478bd9Sstevel@tonic-gate */ 3277c478bd9Sstevel@tonic-gate int 3287c478bd9Sstevel@tonic-gate ldaptool_fileurlerr2ldaperr( int lderr ) 3297c478bd9Sstevel@tonic-gate { 3307c478bd9Sstevel@tonic-gate int rc; 3317c478bd9Sstevel@tonic-gate 3327c478bd9Sstevel@tonic-gate switch( lderr ) { 3337c478bd9Sstevel@tonic-gate case LDAPTOOL_FILEURL_SUCCESS: 3347c478bd9Sstevel@tonic-gate rc = LDAP_SUCCESS; 3357c478bd9Sstevel@tonic-gate break; 3367c478bd9Sstevel@tonic-gate case LDAPTOOL_FILEURL_NOMEMORY: 3377c478bd9Sstevel@tonic-gate rc = LDAP_NO_MEMORY; 3387c478bd9Sstevel@tonic-gate break; 3397c478bd9Sstevel@tonic-gate default: 3407c478bd9Sstevel@tonic-gate rc = LDAP_PARAM_ERROR; 3417c478bd9Sstevel@tonic-gate } 3427c478bd9Sstevel@tonic-gate 3437c478bd9Sstevel@tonic-gate return( rc ); 3447c478bd9Sstevel@tonic-gate } 3457c478bd9Sstevel@tonic-gate 3467c478bd9Sstevel@tonic-gate 3477c478bd9Sstevel@tonic-gate /* 3487c478bd9Sstevel@tonic-gate * Populate *bvp with the contents of the file named by "path". 3497c478bd9Sstevel@tonic-gate * 3507c478bd9Sstevel@tonic-gate * If reporterrs is non-zero, specific error messages are printed to 3517c478bd9Sstevel@tonic-gate * stderr. 3527c478bd9Sstevel@tonic-gate * 3537c478bd9Sstevel@tonic-gate * If successful, LDAPTOOL_FILEURL_SUCCESS is returned and bvp->bv_len 3547c478bd9Sstevel@tonic-gate * and bvp->bv_val are set (the latter is set to malloc'd memory). 3557c478bd9Sstevel@tonic-gate * Upon failure, a different LDAPTOOL_FILEURL_ error code is returned. 3567c478bd9Sstevel@tonic-gate */ 3577c478bd9Sstevel@tonic-gate 3587c478bd9Sstevel@tonic-gate static int 3597c478bd9Sstevel@tonic-gate berval_from_file( const char *path, struct berval *bvp, int reporterrs ) 3607c478bd9Sstevel@tonic-gate { 3617c478bd9Sstevel@tonic-gate FILE *fp; 3627c478bd9Sstevel@tonic-gate long rlen; 3637c478bd9Sstevel@tonic-gate int eof; 3647c478bd9Sstevel@tonic-gate #if defined( XP_WIN32 ) 3657c478bd9Sstevel@tonic-gate char mode[20] = "r+b"; 3667c478bd9Sstevel@tonic-gate #else 3677c478bd9Sstevel@tonic-gate char mode[20] = "r"; 3687c478bd9Sstevel@tonic-gate #endif 3697c478bd9Sstevel@tonic-gate 3707c478bd9Sstevel@tonic-gate #ifdef SOLARIS_LDAP_CMD 3717c478bd9Sstevel@tonic-gate if (( fp = fopen( path, mode )) == NULL ) { 3727c478bd9Sstevel@tonic-gate #else 3737c478bd9Sstevel@tonic-gate if (( fp = ldaptool_open_file( path, mode )) == NULL ) { 3747c478bd9Sstevel@tonic-gate #endif /* SOLARIS_LDAP_CMD */ 3757c478bd9Sstevel@tonic-gate if ( reporterrs ) perror( path ); 3767c478bd9Sstevel@tonic-gate return( LDAPTOOL_FILEURL_FILEIOERROR ); 3777c478bd9Sstevel@tonic-gate } 3787c478bd9Sstevel@tonic-gate 3797c478bd9Sstevel@tonic-gate if ( fseek( fp, 0L, SEEK_END ) != 0 ) { 3807c478bd9Sstevel@tonic-gate if ( reporterrs ) perror( path ); 3817c478bd9Sstevel@tonic-gate fclose( fp ); 3827c478bd9Sstevel@tonic-gate return( LDAPTOOL_FILEURL_FILEIOERROR ); 3837c478bd9Sstevel@tonic-gate } 3847c478bd9Sstevel@tonic-gate 3857c478bd9Sstevel@tonic-gate bvp->bv_len = ftell( fp ); 3867c478bd9Sstevel@tonic-gate 3877c478bd9Sstevel@tonic-gate if (( bvp->bv_val = (char *)malloc( bvp->bv_len + 1 )) == NULL ) { 3887c478bd9Sstevel@tonic-gate if ( reporterrs ) perror( "malloc" ); 3897c478bd9Sstevel@tonic-gate fclose( fp ); 3907c478bd9Sstevel@tonic-gate return( LDAPTOOL_FILEURL_NOMEMORY ); 3917c478bd9Sstevel@tonic-gate } 3927c478bd9Sstevel@tonic-gate 3937c478bd9Sstevel@tonic-gate if ( fseek( fp, 0L, SEEK_SET ) != 0 ) { 3947c478bd9Sstevel@tonic-gate if ( reporterrs ) perror( path ); 3957c478bd9Sstevel@tonic-gate fclose( fp ); 3967c478bd9Sstevel@tonic-gate return( LDAPTOOL_FILEURL_FILEIOERROR ); 3977c478bd9Sstevel@tonic-gate } 3987c478bd9Sstevel@tonic-gate 3997c478bd9Sstevel@tonic-gate rlen = fread( bvp->bv_val, 1, bvp->bv_len, fp ); 4007c478bd9Sstevel@tonic-gate eof = feof( fp ); 4017c478bd9Sstevel@tonic-gate fclose( fp ); 4027c478bd9Sstevel@tonic-gate 4037c478bd9Sstevel@tonic-gate if ( rlen != (long)bvp->bv_len ) { 4047c478bd9Sstevel@tonic-gate if ( reporterrs ) perror( path ); 4057c478bd9Sstevel@tonic-gate free( bvp->bv_val ); 4067c478bd9Sstevel@tonic-gate return( LDAPTOOL_FILEURL_FILEIOERROR ); 4077c478bd9Sstevel@tonic-gate } 4087c478bd9Sstevel@tonic-gate 4097c478bd9Sstevel@tonic-gate bvp->bv_val[ bvp->bv_len ] = '\0'; 4107c478bd9Sstevel@tonic-gate return( LDAPTOOL_FILEURL_SUCCESS ); 4117c478bd9Sstevel@tonic-gate } 4127c478bd9Sstevel@tonic-gate 4137c478bd9Sstevel@tonic-gate 4147c478bd9Sstevel@tonic-gate /* 4157c478bd9Sstevel@tonic-gate * Return a non-zero value if the string s begins with prefix and zero if not. 4167c478bd9Sstevel@tonic-gate */ 4177c478bd9Sstevel@tonic-gate static int 4187c478bd9Sstevel@tonic-gate str_starts_with( const char *s, char *prefix ) 4197c478bd9Sstevel@tonic-gate { 4207c478bd9Sstevel@tonic-gate size_t prefix_len; 4217c478bd9Sstevel@tonic-gate 4227c478bd9Sstevel@tonic-gate if ( s == NULL || prefix == NULL ) { 4237c478bd9Sstevel@tonic-gate return( 0 ); 4247c478bd9Sstevel@tonic-gate } 4257c478bd9Sstevel@tonic-gate 4267c478bd9Sstevel@tonic-gate prefix_len = strlen( prefix ); 4277c478bd9Sstevel@tonic-gate if ( strlen( s ) < prefix_len ) { 4287c478bd9Sstevel@tonic-gate return( 0 ); 4297c478bd9Sstevel@tonic-gate } 4307c478bd9Sstevel@tonic-gate 4317c478bd9Sstevel@tonic-gate return( strncmp( s, prefix, prefix_len ) == 0 ); 4327c478bd9Sstevel@tonic-gate } 4337c478bd9Sstevel@tonic-gate 4347c478bd9Sstevel@tonic-gate 4357c478bd9Sstevel@tonic-gate /* 4367c478bd9Sstevel@tonic-gate * Remove URL hex escapes from s... done in place. The basic concept for 4377c478bd9Sstevel@tonic-gate * this routine is borrowed from the WWW library HTUnEscape() routine. 4387c478bd9Sstevel@tonic-gate * 4397c478bd9Sstevel@tonic-gate * A similar function called nsldapi_hex_unescape can be found in 4407c478bd9Sstevel@tonic-gate * ../../libraries/libldap/unescape.c 4417c478bd9Sstevel@tonic-gate */ 4427c478bd9Sstevel@tonic-gate static void 4437c478bd9Sstevel@tonic-gate hex_unescape( char *s ) 4447c478bd9Sstevel@tonic-gate { 4457c478bd9Sstevel@tonic-gate char *p; 4467c478bd9Sstevel@tonic-gate 4477c478bd9Sstevel@tonic-gate for ( p = s; *s != '\0'; ++s ) { 4487c478bd9Sstevel@tonic-gate if ( *s == '%' ) { 4497c478bd9Sstevel@tonic-gate if ( *++s != '\0' ) { 4507c478bd9Sstevel@tonic-gate *p = unhex( *s ) << 4; 4517c478bd9Sstevel@tonic-gate } 4527c478bd9Sstevel@tonic-gate if ( *++s != '\0' ) { 4537c478bd9Sstevel@tonic-gate *p++ += unhex( *s ); 4547c478bd9Sstevel@tonic-gate } 4557c478bd9Sstevel@tonic-gate } else { 4567c478bd9Sstevel@tonic-gate *p++ = *s; 4577c478bd9Sstevel@tonic-gate } 4587c478bd9Sstevel@tonic-gate } 4597c478bd9Sstevel@tonic-gate 4607c478bd9Sstevel@tonic-gate *p = '\0'; 4617c478bd9Sstevel@tonic-gate } 4627c478bd9Sstevel@tonic-gate 4637c478bd9Sstevel@tonic-gate 4647c478bd9Sstevel@tonic-gate /* 4657c478bd9Sstevel@tonic-gate * Return the integer equivalent of one hex digit (in c). 4667c478bd9Sstevel@tonic-gate * 4677c478bd9Sstevel@tonic-gate * A similar function can be found in ../../libraries/libldap/unescape.c 4687c478bd9Sstevel@tonic-gate */ 4697c478bd9Sstevel@tonic-gate static int 4707c478bd9Sstevel@tonic-gate unhex( char c ) 4717c478bd9Sstevel@tonic-gate { 4727c478bd9Sstevel@tonic-gate return( c >= '0' && c <= '9' ? c - '0' 4737c478bd9Sstevel@tonic-gate : c >= 'A' && c <= 'F' ? c - 'A' + 10 4747c478bd9Sstevel@tonic-gate : c - 'a' + 10 ); 4757c478bd9Sstevel@tonic-gate } 4767c478bd9Sstevel@tonic-gate 4777c478bd9Sstevel@tonic-gate 4787c478bd9Sstevel@tonic-gate #define HREF_CHAR_ACCEPTABLE( c ) (( c >= '-' && c <= '9' ) || \ 4797c478bd9Sstevel@tonic-gate ( c >= '@' && c <= 'Z' ) || \ 4807c478bd9Sstevel@tonic-gate ( c == '_' ) || \ 4817c478bd9Sstevel@tonic-gate ( c >= 'a' && c <= 'z' )) 4827c478bd9Sstevel@tonic-gate 4837c478bd9Sstevel@tonic-gate /* 4847c478bd9Sstevel@tonic-gate * Like strcat(), except if any URL-special characters are found in s2 4857c478bd9Sstevel@tonic-gate * they are escaped using the %HH convention and backslash characters are 4867c478bd9Sstevel@tonic-gate * converted to forward slashes on Windows. 4877c478bd9Sstevel@tonic-gate * 4887c478bd9Sstevel@tonic-gate * Maximum space needed in s1 is 3 * strlen( s2 ) + 1. 4897c478bd9Sstevel@tonic-gate * 4907c478bd9Sstevel@tonic-gate * A similar function that does not convert the slashes called 4917c478bd9Sstevel@tonic-gate * strcat_escaped() can be found in ../../libraries/libldap/tmplout.c 4927c478bd9Sstevel@tonic-gate */ 4937c478bd9Sstevel@tonic-gate static void 4947c478bd9Sstevel@tonic-gate strcpy_escaped_and_convert( char *s1, char *s2 ) 4957c478bd9Sstevel@tonic-gate { 4967c478bd9Sstevel@tonic-gate char *p, *q; 4977c478bd9Sstevel@tonic-gate char *hexdig = "0123456789ABCDEF"; 4987c478bd9Sstevel@tonic-gate 4997c478bd9Sstevel@tonic-gate p = s1 + strlen( s1 ); 5007c478bd9Sstevel@tonic-gate for ( q = s2; *q != '\0'; ++q ) { 5017c478bd9Sstevel@tonic-gate #ifdef _WINDOWS 5027c478bd9Sstevel@tonic-gate if ( *q == '\\' ) { 5037c478bd9Sstevel@tonic-gate *p++ = '/'; 5047c478bd9Sstevel@tonic-gate } else 5057c478bd9Sstevel@tonic-gate #endif /* _WINDOWS */ 5067c478bd9Sstevel@tonic-gate 5077c478bd9Sstevel@tonic-gate if ( HREF_CHAR_ACCEPTABLE( *q )) { 5087c478bd9Sstevel@tonic-gate *p++ = *q; 5097c478bd9Sstevel@tonic-gate } else { 5107c478bd9Sstevel@tonic-gate *p++ = '%'; 5117c478bd9Sstevel@tonic-gate *p++ = hexdig[ 0x0F & ((*(unsigned char*)q) >> 4) ]; 5127c478bd9Sstevel@tonic-gate *p++ = hexdig[ 0x0F & *q ]; 5137c478bd9Sstevel@tonic-gate } 5147c478bd9Sstevel@tonic-gate } 5157c478bd9Sstevel@tonic-gate 5167c478bd9Sstevel@tonic-gate *p = '\0'; 5177c478bd9Sstevel@tonic-gate } 518