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