Home | History | Annotate | Line # | Download | only in libldap
fetch.c revision 1.4
      1 /*	$NetBSD: fetch.c,v 1.4 2025/09/05 21:16:21 christos Exp $	*/
      2 
      3 /* fetch.c - routines for fetching data at URLs */
      4 /* $OpenLDAP$ */
      5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
      6  *
      7  * Copyright 1999-2024 The OpenLDAP Foundation.
      8  * Portions Copyright 1999-2003 Kurt D. Zeilenga.
      9  * All rights reserved.
     10  *
     11  * Redistribution and use in source and binary forms, with or without
     12  * modification, are permitted only as authorized by the OpenLDAP
     13  * Public License.
     14  *
     15  * A copy of this license is available in the file LICENSE in the
     16  * top-level directory of the distribution or, alternatively, at
     17  * <http://www.OpenLDAP.org/license.html>.
     18  */
     19 /* This work was initially developed by Kurt D. Zeilenga for
     20  * inclusion in OpenLDAP Software.
     21  */
     22 
     23 #include <sys/cdefs.h>
     24 __RCSID("$NetBSD: fetch.c,v 1.4 2025/09/05 21:16:21 christos Exp $");
     25 
     26 #include "portable.h"
     27 
     28 #include <stdio.h>
     29 
     30 #include <ac/stdlib.h>
     31 
     32 #include <ac/string.h>
     33 #include <ac/socket.h>
     34 #include <ac/time.h>
     35 
     36 #ifdef HAVE_FETCH
     37 #include <fetch.h>
     38 #endif
     39 
     40 #include "lber_pvt.h"
     41 #include "ldap_pvt.h"
     42 #include "ldap_config.h"
     43 #include "ldif.h"
     44 
     45 FILE *
     46 ldif_open_url(
     47 	LDAP_CONST char *urlstr )
     48 {
     49 	FILE *url;
     50 
     51 	if( strncasecmp( "file:", urlstr, sizeof("file:")-1 ) == 0 ) {
     52 		char *p;
     53 		urlstr += sizeof("file:")-1;
     54 
     55 		/* we don't check for LDAP_DIRSEP since URLs should contain '/' */
     56 		if ( urlstr[0] == '/' && urlstr[1] == '/' ) {
     57 			urlstr += 2;
     58 			/* path must be absolute if authority is present
     59 			 * technically, file://hostname/path is also legal but we don't
     60 			 * accept a non-empty hostname
     61 			 */
     62 			if ( urlstr[0] != '/' ) {
     63 #ifdef _WIN32
     64 				/* An absolute path in improper file://C:/foo/bar format */
     65 				if ( urlstr[1] != ':' )
     66 #endif
     67 				return NULL;
     68 			}
     69 #ifdef _WIN32
     70 			/* An absolute path in proper file:///C:/foo/bar format */
     71 			if ( urlstr[2] == ':' )
     72 				urlstr++;
     73 #endif
     74 		}
     75 
     76 		p = ber_strdup( urlstr );
     77 		if ( p == NULL )
     78 			return NULL;
     79 
     80 		/* But we should convert to LDAP_DIRSEP before use */
     81 		if ( LDAP_DIRSEP[0] != '/' ) {
     82 			char *s = p;
     83 			while (( s = strchr( s, '/' )))
     84 				*s++ = LDAP_DIRSEP[0];
     85 		}
     86 
     87 		ldap_pvt_hex_unescape( p );
     88 
     89 		url = fopen( p, "rb" );
     90 
     91 		ber_memfree( p );
     92 	} else {
     93 #ifdef HAVE_FETCH
     94 		url = fetchGetURL( (char*) urlstr, "" );
     95 #else
     96 		url = NULL;
     97 #endif
     98 	}
     99 	return url;
    100 }
    101 
    102 int
    103 ldif_fetch_url(
    104     LDAP_CONST char	*urlstr,
    105     char	**valuep,
    106     ber_len_t *vlenp )
    107 {
    108 	FILE *url;
    109 	char buffer[1024];
    110 	char *p = NULL;
    111 	size_t total;
    112 	size_t bytes;
    113 
    114 	*valuep = NULL;
    115 	*vlenp = 0;
    116 
    117 	url = ldif_open_url( urlstr );
    118 
    119 	if( url == NULL ) {
    120 		return -1;
    121 	}
    122 
    123 	total = 0;
    124 
    125 	while( (bytes = fread( buffer, 1, sizeof(buffer), url )) != 0 ) {
    126 		char *newp = ber_memrealloc( p, total + bytes + 1 );
    127 		if( newp == NULL ) {
    128 			ber_memfree( p );
    129 			fclose( url );
    130 			return -1;
    131 		}
    132 		p = newp;
    133 		AC_MEMCPY( &p[total], buffer, bytes );
    134 		total += bytes;
    135 	}
    136 
    137 	fclose( url );
    138 
    139 	if( total == 0 ) {
    140 		char *newp = ber_memrealloc( p, 1 );
    141 		if( newp == NULL ) {
    142 			ber_memfree( p );
    143 			return -1;
    144 		}
    145 		p = newp;
    146 	}
    147 
    148 	p[total] = '\0';
    149 	*valuep = p;
    150 	*vlenp = total;
    151 
    152 	return 0;
    153 }
    154