1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate * Copyright 2001-2002 Sun Microsystems, Inc. All rights reserved.
3*7c478bd9Sstevel@tonic-gate * Use is subject to license terms.
4*7c478bd9Sstevel@tonic-gate */
5*7c478bd9Sstevel@tonic-gate
6*7c478bd9Sstevel@tonic-gate
7*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
8*7c478bd9Sstevel@tonic-gate
9*7c478bd9Sstevel@tonic-gate /*
10*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the Netscape Public
11*7c478bd9Sstevel@tonic-gate * License Version 1.1 (the "License"); you may not use this file
12*7c478bd9Sstevel@tonic-gate * except in compliance with the License. You may obtain a copy of
13*7c478bd9Sstevel@tonic-gate * the License at http://www.mozilla.org/NPL/
14*7c478bd9Sstevel@tonic-gate *
15*7c478bd9Sstevel@tonic-gate * Software distributed under the License is distributed on an "AS
16*7c478bd9Sstevel@tonic-gate * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
17*7c478bd9Sstevel@tonic-gate * implied. See the License for the specific language governing
18*7c478bd9Sstevel@tonic-gate * rights and limitations under the License.
19*7c478bd9Sstevel@tonic-gate *
20*7c478bd9Sstevel@tonic-gate * The Original Code is Mozilla Communicator client code, released
21*7c478bd9Sstevel@tonic-gate * March 31, 1998.
22*7c478bd9Sstevel@tonic-gate *
23*7c478bd9Sstevel@tonic-gate * The Initial Developer of the Original Code is Netscape
24*7c478bd9Sstevel@tonic-gate * Communications Corporation. Portions created by Netscape are
25*7c478bd9Sstevel@tonic-gate * Copyright (C) 1998-1999 Netscape Communications Corporation. All
26*7c478bd9Sstevel@tonic-gate * Rights Reserved.
27*7c478bd9Sstevel@tonic-gate *
28*7c478bd9Sstevel@tonic-gate * Contributor(s):
29*7c478bd9Sstevel@tonic-gate */
30*7c478bd9Sstevel@tonic-gate
31*7c478bd9Sstevel@tonic-gate /* line64.c - routines for dealing with the slapd line format */
32*7c478bd9Sstevel@tonic-gate
33*7c478bd9Sstevel@tonic-gate #include <stdio.h>
34*7c478bd9Sstevel@tonic-gate #include <string.h>
35*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
36*7c478bd9Sstevel@tonic-gate #include <ctype.h>
37*7c478bd9Sstevel@tonic-gate #ifndef macintosh
38*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
39*7c478bd9Sstevel@tonic-gate #endif
40*7c478bd9Sstevel@tonic-gate #ifdef _WIN32
41*7c478bd9Sstevel@tonic-gate #include <windows.h>
42*7c478bd9Sstevel@tonic-gate #elif !defined( macintosh )
43*7c478bd9Sstevel@tonic-gate #include <sys/socket.h>
44*7c478bd9Sstevel@tonic-gate #endif
45*7c478bd9Sstevel@tonic-gate #include "ldaplog.h"
46*7c478bd9Sstevel@tonic-gate #include "ldif.h"
47*7c478bd9Sstevel@tonic-gate
48*7c478bd9Sstevel@tonic-gate #ifndef isascii
49*7c478bd9Sstevel@tonic-gate #define isascii( c ) (!((c) & ~0177))
50*7c478bd9Sstevel@tonic-gate #endif
51*7c478bd9Sstevel@tonic-gate
52*7c478bd9Sstevel@tonic-gate #define RIGHT2 0x03
53*7c478bd9Sstevel@tonic-gate #define RIGHT4 0x0f
54*7c478bd9Sstevel@tonic-gate #define CONTINUED_LINE_MARKER '\001'
55*7c478bd9Sstevel@tonic-gate
56*7c478bd9Sstevel@tonic-gate #define ISBLANK(c) ((c) == ' ' || (c) == '\t' || (c) == '\n') /* not "\r\v\f" */
57*7c478bd9Sstevel@tonic-gate
58*7c478bd9Sstevel@tonic-gate #define LDIF_OPT_ISSET( value, opt ) (((value) & (opt)) != 0 )
59*7c478bd9Sstevel@tonic-gate
60*7c478bd9Sstevel@tonic-gate static char nib2b64[0x40] =
61*7c478bd9Sstevel@tonic-gate "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
62*7c478bd9Sstevel@tonic-gate
63*7c478bd9Sstevel@tonic-gate static unsigned char b642nib[0x80] = {
64*7c478bd9Sstevel@tonic-gate 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
65*7c478bd9Sstevel@tonic-gate 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
66*7c478bd9Sstevel@tonic-gate 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
67*7c478bd9Sstevel@tonic-gate 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
68*7c478bd9Sstevel@tonic-gate 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
69*7c478bd9Sstevel@tonic-gate 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
70*7c478bd9Sstevel@tonic-gate 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
71*7c478bd9Sstevel@tonic-gate 0x3c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
72*7c478bd9Sstevel@tonic-gate 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
73*7c478bd9Sstevel@tonic-gate 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
74*7c478bd9Sstevel@tonic-gate 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
75*7c478bd9Sstevel@tonic-gate 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
76*7c478bd9Sstevel@tonic-gate 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
77*7c478bd9Sstevel@tonic-gate 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
78*7c478bd9Sstevel@tonic-gate 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
79*7c478bd9Sstevel@tonic-gate 0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff
80*7c478bd9Sstevel@tonic-gate };
81*7c478bd9Sstevel@tonic-gate
82*7c478bd9Sstevel@tonic-gate static int ldif_base64_encode_internal( unsigned char *src, char *dst, int srclen,
83*7c478bd9Sstevel@tonic-gate int lenused, int wraplen );
84*7c478bd9Sstevel@tonic-gate
85*7c478bd9Sstevel@tonic-gate /*
86*7c478bd9Sstevel@tonic-gate * str_parse_line - takes a line of the form "type:[:] value" and splits it
87*7c478bd9Sstevel@tonic-gate * into components "type" and "value". if a double colon separates type from
88*7c478bd9Sstevel@tonic-gate * value, then value is encoded in base 64, and parse_line un-decodes it
89*7c478bd9Sstevel@tonic-gate * (in place) before returning.
90*7c478bd9Sstevel@tonic-gate */
91*7c478bd9Sstevel@tonic-gate
92*7c478bd9Sstevel@tonic-gate int
str_parse_line(char * line,char ** type,char ** value,int * vlen)93*7c478bd9Sstevel@tonic-gate str_parse_line(
94*7c478bd9Sstevel@tonic-gate char *line,
95*7c478bd9Sstevel@tonic-gate char **type,
96*7c478bd9Sstevel@tonic-gate char **value,
97*7c478bd9Sstevel@tonic-gate int *vlen
98*7c478bd9Sstevel@tonic-gate )
99*7c478bd9Sstevel@tonic-gate {
100*7c478bd9Sstevel@tonic-gate char *p, *s, *d;
101*7c478bd9Sstevel@tonic-gate int b64;
102*7c478bd9Sstevel@tonic-gate
103*7c478bd9Sstevel@tonic-gate /* skip any leading space */
104*7c478bd9Sstevel@tonic-gate while ( ISBLANK( *line ) ) {
105*7c478bd9Sstevel@tonic-gate line++;
106*7c478bd9Sstevel@tonic-gate }
107*7c478bd9Sstevel@tonic-gate *type = line;
108*7c478bd9Sstevel@tonic-gate
109*7c478bd9Sstevel@tonic-gate for ( s = line; *s && *s != ':'; s++ )
110*7c478bd9Sstevel@tonic-gate ; /* NULL */
111*7c478bd9Sstevel@tonic-gate if ( *s == '\0' ) {
112*7c478bd9Sstevel@tonic-gate
113*7c478bd9Sstevel@tonic-gate /* Comment-out while we address calling libldif from ns-back-ldbm
114*7c478bd9Sstevel@tonic-gate on NT. 1 of 3 */
115*7c478bd9Sstevel@tonic-gate #if defined( _WIN32 )
116*7c478bd9Sstevel@tonic-gate /*
117*7c478bd9Sstevel@tonic-gate #endif
118*7c478bd9Sstevel@tonic-gate LDAPDebug( LDAP_DEBUG_PARSE, "str_parse_line: missing ':' "
119*7c478bd9Sstevel@tonic-gate "on line \"%s\"\n", line, 0, 0 );
120*7c478bd9Sstevel@tonic-gate #if defined( _WIN32 )
121*7c478bd9Sstevel@tonic-gate */
122*7c478bd9Sstevel@tonic-gate #endif
123*7c478bd9Sstevel@tonic-gate return( -1 );
124*7c478bd9Sstevel@tonic-gate }
125*7c478bd9Sstevel@tonic-gate
126*7c478bd9Sstevel@tonic-gate /* trim any space between type and : */
127*7c478bd9Sstevel@tonic-gate for ( p = s - 1; p > line && ISBLANK( *p ); p-- ) {
128*7c478bd9Sstevel@tonic-gate *p = '\0';
129*7c478bd9Sstevel@tonic-gate }
130*7c478bd9Sstevel@tonic-gate *s++ = '\0';
131*7c478bd9Sstevel@tonic-gate
132*7c478bd9Sstevel@tonic-gate /* check for double : - indicates base 64 encoded value */
133*7c478bd9Sstevel@tonic-gate if ( *s == ':' ) {
134*7c478bd9Sstevel@tonic-gate s++;
135*7c478bd9Sstevel@tonic-gate b64 = 1;
136*7c478bd9Sstevel@tonic-gate
137*7c478bd9Sstevel@tonic-gate /* single : - normally encoded value */
138*7c478bd9Sstevel@tonic-gate } else {
139*7c478bd9Sstevel@tonic-gate b64 = 0;
140*7c478bd9Sstevel@tonic-gate }
141*7c478bd9Sstevel@tonic-gate
142*7c478bd9Sstevel@tonic-gate /* skip space between : and value */
143*7c478bd9Sstevel@tonic-gate while ( ISBLANK( *s ) ) {
144*7c478bd9Sstevel@tonic-gate s++;
145*7c478bd9Sstevel@tonic-gate }
146*7c478bd9Sstevel@tonic-gate
147*7c478bd9Sstevel@tonic-gate /*
148*7c478bd9Sstevel@tonic-gate * If no value is present, return a zero-length string for
149*7c478bd9Sstevel@tonic-gate * *value, with *vlen set to zero.
150*7c478bd9Sstevel@tonic-gate */
151*7c478bd9Sstevel@tonic-gate if ( *s == '\0' ) {
152*7c478bd9Sstevel@tonic-gate *value = s;
153*7c478bd9Sstevel@tonic-gate *vlen = 0;
154*7c478bd9Sstevel@tonic-gate return( 0 );
155*7c478bd9Sstevel@tonic-gate }
156*7c478bd9Sstevel@tonic-gate
157*7c478bd9Sstevel@tonic-gate /* check for continued line markers that should be deleted */
158*7c478bd9Sstevel@tonic-gate for ( p = s, d = s; *p; p++ ) {
159*7c478bd9Sstevel@tonic-gate if ( *p != CONTINUED_LINE_MARKER )
160*7c478bd9Sstevel@tonic-gate *d++ = *p;
161*7c478bd9Sstevel@tonic-gate }
162*7c478bd9Sstevel@tonic-gate *d = '\0';
163*7c478bd9Sstevel@tonic-gate
164*7c478bd9Sstevel@tonic-gate *value = s;
165*7c478bd9Sstevel@tonic-gate if ( b64 ) {
166*7c478bd9Sstevel@tonic-gate if (( *vlen = ldif_base64_decode( s, (unsigned char *)s ))
167*7c478bd9Sstevel@tonic-gate < 0 ) {
168*7c478bd9Sstevel@tonic-gate /* Comment-out while we address calling libldif from ns-back-ldbm
169*7c478bd9Sstevel@tonic-gate on NT. 3 of 3 */
170*7c478bd9Sstevel@tonic-gate #if defined( _WIN32 )
171*7c478bd9Sstevel@tonic-gate /*
172*7c478bd9Sstevel@tonic-gate #endif
173*7c478bd9Sstevel@tonic-gate LDAPDebug( LDAP_DEBUG_ANY,
174*7c478bd9Sstevel@tonic-gate "str_parse_line: invalid base 64 char on line \"%s\"\n",
175*7c478bd9Sstevel@tonic-gate line, 0, 0 );
176*7c478bd9Sstevel@tonic-gate #if defined( _WIN32 )
177*7c478bd9Sstevel@tonic-gate */
178*7c478bd9Sstevel@tonic-gate #endif
179*7c478bd9Sstevel@tonic-gate return( -1 );
180*7c478bd9Sstevel@tonic-gate }
181*7c478bd9Sstevel@tonic-gate s[ *vlen ] = '\0';
182*7c478bd9Sstevel@tonic-gate } else {
183*7c478bd9Sstevel@tonic-gate *vlen = (int) (d - s);
184*7c478bd9Sstevel@tonic-gate }
185*7c478bd9Sstevel@tonic-gate
186*7c478bd9Sstevel@tonic-gate return( 0 );
187*7c478bd9Sstevel@tonic-gate }
188*7c478bd9Sstevel@tonic-gate
189*7c478bd9Sstevel@tonic-gate
190*7c478bd9Sstevel@tonic-gate /*
191*7c478bd9Sstevel@tonic-gate * ldif_base64_decode - take the BASE64-encoded characters in "src"
192*7c478bd9Sstevel@tonic-gate * (a zero-terminated string) and decode them into the the buffer "dst".
193*7c478bd9Sstevel@tonic-gate * "src" and "dst" can be the same if in-place decoding is desired.
194*7c478bd9Sstevel@tonic-gate * "dst" must be large enough to hold the decoded octets. No more than
195*7c478bd9Sstevel@tonic-gate * 3 * strlen( src ) / 4 bytes will be produced.
196*7c478bd9Sstevel@tonic-gate * "dst" may contain zero octets anywhere within it, but it is not
197*7c478bd9Sstevel@tonic-gate * zero-terminated by this function.
198*7c478bd9Sstevel@tonic-gate *
199*7c478bd9Sstevel@tonic-gate * The number of bytes copied to "dst" is returned if all goes well.
200*7c478bd9Sstevel@tonic-gate * -1 is returned if the BASE64 encoding in "src" is invalid.
201*7c478bd9Sstevel@tonic-gate */
202*7c478bd9Sstevel@tonic-gate
203*7c478bd9Sstevel@tonic-gate int
ldif_base64_decode(char * src,unsigned char * dst)204*7c478bd9Sstevel@tonic-gate ldif_base64_decode( char *src, unsigned char *dst )
205*7c478bd9Sstevel@tonic-gate {
206*7c478bd9Sstevel@tonic-gate char *p, *stop;
207*7c478bd9Sstevel@tonic-gate unsigned char nib, *byte;
208*7c478bd9Sstevel@tonic-gate int i, len;
209*7c478bd9Sstevel@tonic-gate
210*7c478bd9Sstevel@tonic-gate stop = strchr( src, '\0' );
211*7c478bd9Sstevel@tonic-gate byte = dst;
212*7c478bd9Sstevel@tonic-gate for ( p = src, len = 0; p < stop; p += 4, len += 3 ) {
213*7c478bd9Sstevel@tonic-gate for ( i = 0; i < 4; i++ ) {
214*7c478bd9Sstevel@tonic-gate if ( p[i] != '=' && (p[i] & 0x80 ||
215*7c478bd9Sstevel@tonic-gate b642nib[ p[i] & 0x7f ] > 0x3f) ) {
216*7c478bd9Sstevel@tonic-gate return( -1 );
217*7c478bd9Sstevel@tonic-gate }
218*7c478bd9Sstevel@tonic-gate }
219*7c478bd9Sstevel@tonic-gate
220*7c478bd9Sstevel@tonic-gate /* first digit */
221*7c478bd9Sstevel@tonic-gate nib = b642nib[ p[0] & 0x7f ];
222*7c478bd9Sstevel@tonic-gate byte[0] = nib << 2;
223*7c478bd9Sstevel@tonic-gate
224*7c478bd9Sstevel@tonic-gate /* second digit */
225*7c478bd9Sstevel@tonic-gate nib = b642nib[ p[1] & 0x7f ];
226*7c478bd9Sstevel@tonic-gate byte[0] |= nib >> 4;
227*7c478bd9Sstevel@tonic-gate
228*7c478bd9Sstevel@tonic-gate /* third digit */
229*7c478bd9Sstevel@tonic-gate if ( p[2] == '=' ) {
230*7c478bd9Sstevel@tonic-gate len += 1;
231*7c478bd9Sstevel@tonic-gate break;
232*7c478bd9Sstevel@tonic-gate }
233*7c478bd9Sstevel@tonic-gate byte[1] = (nib & RIGHT4) << 4;
234*7c478bd9Sstevel@tonic-gate nib = b642nib[ p[2] & 0x7f ];
235*7c478bd9Sstevel@tonic-gate byte[1] |= nib >> 2;
236*7c478bd9Sstevel@tonic-gate
237*7c478bd9Sstevel@tonic-gate /* fourth digit */
238*7c478bd9Sstevel@tonic-gate if ( p[3] == '=' ) {
239*7c478bd9Sstevel@tonic-gate len += 2;
240*7c478bd9Sstevel@tonic-gate break;
241*7c478bd9Sstevel@tonic-gate }
242*7c478bd9Sstevel@tonic-gate byte[2] = (nib & RIGHT2) << 6;
243*7c478bd9Sstevel@tonic-gate nib = b642nib[ p[3] & 0x7f ];
244*7c478bd9Sstevel@tonic-gate byte[2] |= nib;
245*7c478bd9Sstevel@tonic-gate
246*7c478bd9Sstevel@tonic-gate byte += 3;
247*7c478bd9Sstevel@tonic-gate }
248*7c478bd9Sstevel@tonic-gate
249*7c478bd9Sstevel@tonic-gate return( len );
250*7c478bd9Sstevel@tonic-gate }
251*7c478bd9Sstevel@tonic-gate
252*7c478bd9Sstevel@tonic-gate /*
253*7c478bd9Sstevel@tonic-gate * str_getline - return the next "line" (minus newline) of input from a
254*7c478bd9Sstevel@tonic-gate * string buffer of lines separated by newlines, terminated by \n\n
255*7c478bd9Sstevel@tonic-gate * or \0. this routine handles continued lines, bundling them into
256*7c478bd9Sstevel@tonic-gate * a single big line before returning. if a line begins with a white
257*7c478bd9Sstevel@tonic-gate * space character, it is a continuation of the previous line. the white
258*7c478bd9Sstevel@tonic-gate * space character (nb: only one char), and preceeding newline are changed
259*7c478bd9Sstevel@tonic-gate * into CONTINUED_LINE_MARKER chars, to be deleted later by the
260*7c478bd9Sstevel@tonic-gate * str_parse_line() routine above.
261*7c478bd9Sstevel@tonic-gate *
262*7c478bd9Sstevel@tonic-gate * it takes a pointer to a pointer to the buffer on the first call,
263*7c478bd9Sstevel@tonic-gate * which it updates and must be supplied on subsequent calls.
264*7c478bd9Sstevel@tonic-gate *
265*7c478bd9Sstevel@tonic-gate * XXX need to update this function to also support <CR><LF> as EOL.
266*7c478bd9Sstevel@tonic-gate * XXX supports <CR><LF> as of 07/29/1998 (richm)
267*7c478bd9Sstevel@tonic-gate */
268*7c478bd9Sstevel@tonic-gate
269*7c478bd9Sstevel@tonic-gate char *
str_getline(char ** next)270*7c478bd9Sstevel@tonic-gate str_getline( char **next )
271*7c478bd9Sstevel@tonic-gate {
272*7c478bd9Sstevel@tonic-gate char *l;
273*7c478bd9Sstevel@tonic-gate char c;
274*7c478bd9Sstevel@tonic-gate char *p;
275*7c478bd9Sstevel@tonic-gate
276*7c478bd9Sstevel@tonic-gate if ( *next == NULL || **next == '\n' || **next == '\0' ) {
277*7c478bd9Sstevel@tonic-gate return( NULL );
278*7c478bd9Sstevel@tonic-gate }
279*7c478bd9Sstevel@tonic-gate
280*7c478bd9Sstevel@tonic-gate while ( **next == '#' ) { /* skip comment lines */
281*7c478bd9Sstevel@tonic-gate if (( *next = strchr( *next, '\n' )) == NULL ) {
282*7c478bd9Sstevel@tonic-gate return( NULL );
283*7c478bd9Sstevel@tonic-gate }
284*7c478bd9Sstevel@tonic-gate (*next)++;
285*7c478bd9Sstevel@tonic-gate }
286*7c478bd9Sstevel@tonic-gate
287*7c478bd9Sstevel@tonic-gate l = *next;
288*7c478bd9Sstevel@tonic-gate while ( (*next = strchr( *next, '\n' )) != NULL ) {
289*7c478bd9Sstevel@tonic-gate p = *next - 1; /* pointer to character previous to the newline */
290*7c478bd9Sstevel@tonic-gate c = *(*next + 1); /* character after the newline */
291*7c478bd9Sstevel@tonic-gate if ( ISBLANK( c ) && c != '\n' ) {
292*7c478bd9Sstevel@tonic-gate /* DOS EOL is \r\n, so if the character before */
293*7c478bd9Sstevel@tonic-gate /* the \n is \r, continue it too */
294*7c478bd9Sstevel@tonic-gate if (*p == '\r')
295*7c478bd9Sstevel@tonic-gate *p = CONTINUED_LINE_MARKER;
296*7c478bd9Sstevel@tonic-gate **next = CONTINUED_LINE_MARKER;
297*7c478bd9Sstevel@tonic-gate *(*next+1) = CONTINUED_LINE_MARKER;
298*7c478bd9Sstevel@tonic-gate } else {
299*7c478bd9Sstevel@tonic-gate /* DOS EOL is \r\n, so if the character before */
300*7c478bd9Sstevel@tonic-gate /* the \n is \r, null it too */
301*7c478bd9Sstevel@tonic-gate if (*p == '\r')
302*7c478bd9Sstevel@tonic-gate *p = '\0';
303*7c478bd9Sstevel@tonic-gate *(*next)++ = '\0';
304*7c478bd9Sstevel@tonic-gate break;
305*7c478bd9Sstevel@tonic-gate }
306*7c478bd9Sstevel@tonic-gate (*next)++;
307*7c478bd9Sstevel@tonic-gate }
308*7c478bd9Sstevel@tonic-gate
309*7c478bd9Sstevel@tonic-gate return( l );
310*7c478bd9Sstevel@tonic-gate }
311*7c478bd9Sstevel@tonic-gate
312*7c478bd9Sstevel@tonic-gate
313*7c478bd9Sstevel@tonic-gate #define LDIF_SAFE_CHAR( c ) ( (c) != '\r' && (c) != '\n' )
314*7c478bd9Sstevel@tonic-gate #define LDIF_CONSERVATIVE_CHAR( c ) ( LDIF_SAFE_CHAR(c) && isascii((c)) \
315*7c478bd9Sstevel@tonic-gate && ( isprint((c)) || (c) == '\t' ))
316*7c478bd9Sstevel@tonic-gate #define LDIF_SAFE_INITCHAR( c ) ( LDIF_SAFE_CHAR(c) && (c) != ':' \
317*7c478bd9Sstevel@tonic-gate && (c) != ' ' && (c) != '<' )
318*7c478bd9Sstevel@tonic-gate #define LDIF_CONSERVATIVE_INITCHAR( c ) ( LDIF_SAFE_INITCHAR( c ) && \
319*7c478bd9Sstevel@tonic-gate ! ( isascii((c)) && isspace((c))))
320*7c478bd9Sstevel@tonic-gate #define LDIF_CONSERVATIVE_FINALCHAR( c ) ( (c) != ' ' )
321*7c478bd9Sstevel@tonic-gate
322*7c478bd9Sstevel@tonic-gate
323*7c478bd9Sstevel@tonic-gate void
ldif_put_type_and_value_with_options(char ** out,char * t,char * val,int vlen,unsigned long options)324*7c478bd9Sstevel@tonic-gate ldif_put_type_and_value_with_options( char **out, char *t, char *val,
325*7c478bd9Sstevel@tonic-gate int vlen, unsigned long options )
326*7c478bd9Sstevel@tonic-gate {
327*7c478bd9Sstevel@tonic-gate unsigned char *p, *byte, *stop;
328*7c478bd9Sstevel@tonic-gate char *save;
329*7c478bd9Sstevel@tonic-gate int b64, len, savelen, wraplen;
330*7c478bd9Sstevel@tonic-gate len = 0;
331*7c478bd9Sstevel@tonic-gate
332*7c478bd9Sstevel@tonic-gate if ( LDIF_OPT_ISSET( options, LDIF_OPT_NOWRAP )) {
333*7c478bd9Sstevel@tonic-gate wraplen = -1;
334*7c478bd9Sstevel@tonic-gate } else {
335*7c478bd9Sstevel@tonic-gate wraplen = LDIF_MAX_LINE_WIDTH;
336*7c478bd9Sstevel@tonic-gate }
337*7c478bd9Sstevel@tonic-gate
338*7c478bd9Sstevel@tonic-gate /* put the type + ": " */
339*7c478bd9Sstevel@tonic-gate for ( p = (unsigned char *) t; *p; p++, len++ ) {
340*7c478bd9Sstevel@tonic-gate *(*out)++ = *p;
341*7c478bd9Sstevel@tonic-gate }
342*7c478bd9Sstevel@tonic-gate *(*out)++ = ':';
343*7c478bd9Sstevel@tonic-gate len++;
344*7c478bd9Sstevel@tonic-gate if ( LDIF_OPT_ISSET( options, LDIF_OPT_VALUE_IS_URL )) {
345*7c478bd9Sstevel@tonic-gate *(*out)++ = '<'; /* add '<' for URLs */
346*7c478bd9Sstevel@tonic-gate len++;
347*7c478bd9Sstevel@tonic-gate }
348*7c478bd9Sstevel@tonic-gate save = *out;
349*7c478bd9Sstevel@tonic-gate savelen = len;
350*7c478bd9Sstevel@tonic-gate b64 = 0;
351*7c478bd9Sstevel@tonic-gate
352*7c478bd9Sstevel@tonic-gate stop = (unsigned char *)val;
353*7c478bd9Sstevel@tonic-gate if ( val && vlen > 0 ) {
354*7c478bd9Sstevel@tonic-gate *(*out)++ = ' ';
355*7c478bd9Sstevel@tonic-gate stop = (unsigned char *) (val + vlen);
356*7c478bd9Sstevel@tonic-gate if ( LDIF_OPT_ISSET( options, LDIF_OPT_MINIMAL_ENCODING )) {
357*7c478bd9Sstevel@tonic-gate if ( !LDIF_SAFE_INITCHAR( val[0] )) {
358*7c478bd9Sstevel@tonic-gate b64 = 1;
359*7c478bd9Sstevel@tonic-gate }
360*7c478bd9Sstevel@tonic-gate } else {
361*7c478bd9Sstevel@tonic-gate if ( !LDIF_CONSERVATIVE_INITCHAR( val[0] ) ||
362*7c478bd9Sstevel@tonic-gate !LDIF_CONSERVATIVE_FINALCHAR( val[vlen-1] )) {
363*7c478bd9Sstevel@tonic-gate b64 = 1;
364*7c478bd9Sstevel@tonic-gate }
365*7c478bd9Sstevel@tonic-gate }
366*7c478bd9Sstevel@tonic-gate }
367*7c478bd9Sstevel@tonic-gate
368*7c478bd9Sstevel@tonic-gate if ( !b64 ) {
369*7c478bd9Sstevel@tonic-gate for ( byte = (unsigned char *) val; byte < stop;
370*7c478bd9Sstevel@tonic-gate byte++, len++ ) {
371*7c478bd9Sstevel@tonic-gate if ( LDIF_OPT_ISSET( options,
372*7c478bd9Sstevel@tonic-gate LDIF_OPT_MINIMAL_ENCODING )) {
373*7c478bd9Sstevel@tonic-gate if ( !LDIF_SAFE_CHAR( *byte )) {
374*7c478bd9Sstevel@tonic-gate b64 = 1;
375*7c478bd9Sstevel@tonic-gate break;
376*7c478bd9Sstevel@tonic-gate }
377*7c478bd9Sstevel@tonic-gate } else if ( !LDIF_CONSERVATIVE_CHAR( *byte )) {
378*7c478bd9Sstevel@tonic-gate b64 = 1;
379*7c478bd9Sstevel@tonic-gate break;
380*7c478bd9Sstevel@tonic-gate }
381*7c478bd9Sstevel@tonic-gate
382*7c478bd9Sstevel@tonic-gate if ( wraplen != -1 && len > wraplen ) {
383*7c478bd9Sstevel@tonic-gate *(*out)++ = '\n';
384*7c478bd9Sstevel@tonic-gate *(*out)++ = ' ';
385*7c478bd9Sstevel@tonic-gate len = 1;
386*7c478bd9Sstevel@tonic-gate }
387*7c478bd9Sstevel@tonic-gate *(*out)++ = *byte;
388*7c478bd9Sstevel@tonic-gate }
389*7c478bd9Sstevel@tonic-gate }
390*7c478bd9Sstevel@tonic-gate
391*7c478bd9Sstevel@tonic-gate if ( b64 ) {
392*7c478bd9Sstevel@tonic-gate *out = save;
393*7c478bd9Sstevel@tonic-gate *(*out)++ = ':';
394*7c478bd9Sstevel@tonic-gate *(*out)++ = ' ';
395*7c478bd9Sstevel@tonic-gate len = ldif_base64_encode_internal( (unsigned char *)val, *out, vlen,
396*7c478bd9Sstevel@tonic-gate savelen + 2, wraplen );
397*7c478bd9Sstevel@tonic-gate *out += len;
398*7c478bd9Sstevel@tonic-gate }
399*7c478bd9Sstevel@tonic-gate
400*7c478bd9Sstevel@tonic-gate *(*out)++ = '\n';
401*7c478bd9Sstevel@tonic-gate }
402*7c478bd9Sstevel@tonic-gate
403*7c478bd9Sstevel@tonic-gate void
ldif_put_type_and_value(char ** out,char * t,char * val,int vlen)404*7c478bd9Sstevel@tonic-gate ldif_put_type_and_value( char **out, char *t, char *val, int vlen )
405*7c478bd9Sstevel@tonic-gate {
406*7c478bd9Sstevel@tonic-gate ldif_put_type_and_value_with_options( out, t, val, vlen, 0 );
407*7c478bd9Sstevel@tonic-gate }
408*7c478bd9Sstevel@tonic-gate
409*7c478bd9Sstevel@tonic-gate void
ldif_put_type_and_value_nowrap(char ** out,char * t,char * val,int vlen)410*7c478bd9Sstevel@tonic-gate ldif_put_type_and_value_nowrap( char **out, char *t, char *val, int vlen )
411*7c478bd9Sstevel@tonic-gate {
412*7c478bd9Sstevel@tonic-gate ldif_put_type_and_value_with_options( out, t, val, vlen, LDIF_OPT_NOWRAP );
413*7c478bd9Sstevel@tonic-gate }
414*7c478bd9Sstevel@tonic-gate
415*7c478bd9Sstevel@tonic-gate /*
416*7c478bd9Sstevel@tonic-gate * ldif_base64_encode_internal - encode "srclen" bytes in "src", place BASE64
417*7c478bd9Sstevel@tonic-gate * encoded bytes in "dst" and return the length of the BASE64
418*7c478bd9Sstevel@tonic-gate * encoded string. "dst" is also zero-terminated by this function.
419*7c478bd9Sstevel@tonic-gate *
420*7c478bd9Sstevel@tonic-gate * If "lenused" >= 0, newlines will be included in "dst" and "lenused" if
421*7c478bd9Sstevel@tonic-gate * appropriate. "lenused" should be a count of characters already used
422*7c478bd9Sstevel@tonic-gate * on the current line. The LDIF lines we create will contain at most
423*7c478bd9Sstevel@tonic-gate * "wraplen" characters on each line, unless "wraplen" is -1, in which
424*7c478bd9Sstevel@tonic-gate * case output line length is unlimited.
425*7c478bd9Sstevel@tonic-gate *
426*7c478bd9Sstevel@tonic-gate * If "lenused" < 0, no newlines will be included, and the LDIF_BASE64_LEN()
427*7c478bd9Sstevel@tonic-gate * macro can be used to determine how many bytes will be placed in "dst."
428*7c478bd9Sstevel@tonic-gate */
429*7c478bd9Sstevel@tonic-gate
430*7c478bd9Sstevel@tonic-gate static int
ldif_base64_encode_internal(unsigned char * src,char * dst,int srclen,int lenused,int wraplen)431*7c478bd9Sstevel@tonic-gate ldif_base64_encode_internal( unsigned char *src, char *dst, int srclen, int lenused, int wraplen )
432*7c478bd9Sstevel@tonic-gate {
433*7c478bd9Sstevel@tonic-gate unsigned char *byte, *stop;
434*7c478bd9Sstevel@tonic-gate unsigned char buf[3];
435*7c478bd9Sstevel@tonic-gate char *out;
436*7c478bd9Sstevel@tonic-gate unsigned long bits;
437*7c478bd9Sstevel@tonic-gate int i, pad, len;
438*7c478bd9Sstevel@tonic-gate
439*7c478bd9Sstevel@tonic-gate len = 0;
440*7c478bd9Sstevel@tonic-gate out = dst;
441*7c478bd9Sstevel@tonic-gate stop = src + srclen;
442*7c478bd9Sstevel@tonic-gate
443*7c478bd9Sstevel@tonic-gate /* convert to base 64 (3 bytes => 4 base 64 digits) */
444*7c478bd9Sstevel@tonic-gate for ( byte = src; byte < stop - 2; byte += 3 ) {
445*7c478bd9Sstevel@tonic-gate bits = (byte[0] & 0xff) << 16;
446*7c478bd9Sstevel@tonic-gate bits |= (byte[1] & 0xff) << 8;
447*7c478bd9Sstevel@tonic-gate bits |= (byte[2] & 0xff);
448*7c478bd9Sstevel@tonic-gate
449*7c478bd9Sstevel@tonic-gate for ( i = 0; i < 4; i++, bits <<= 6 ) {
450*7c478bd9Sstevel@tonic-gate if ( wraplen != -1 && lenused >= 0 && lenused++ > wraplen ) {
451*7c478bd9Sstevel@tonic-gate *out++ = '\n';
452*7c478bd9Sstevel@tonic-gate *out++ = ' ';
453*7c478bd9Sstevel@tonic-gate lenused = 2;
454*7c478bd9Sstevel@tonic-gate }
455*7c478bd9Sstevel@tonic-gate
456*7c478bd9Sstevel@tonic-gate /* get b64 digit from high order 6 bits */
457*7c478bd9Sstevel@tonic-gate *out++ = nib2b64[ (bits & 0xfc0000L) >> 18 ];
458*7c478bd9Sstevel@tonic-gate }
459*7c478bd9Sstevel@tonic-gate }
460*7c478bd9Sstevel@tonic-gate
461*7c478bd9Sstevel@tonic-gate /* add padding if necessary */
462*7c478bd9Sstevel@tonic-gate if ( byte < stop ) {
463*7c478bd9Sstevel@tonic-gate for ( i = 0; byte + i < stop; i++ ) {
464*7c478bd9Sstevel@tonic-gate buf[i] = byte[i];
465*7c478bd9Sstevel@tonic-gate }
466*7c478bd9Sstevel@tonic-gate for ( pad = 0; i < 3; i++, pad++ ) {
467*7c478bd9Sstevel@tonic-gate buf[i] = '\0';
468*7c478bd9Sstevel@tonic-gate }
469*7c478bd9Sstevel@tonic-gate byte = buf;
470*7c478bd9Sstevel@tonic-gate bits = (byte[0] & 0xff) << 16;
471*7c478bd9Sstevel@tonic-gate bits |= (byte[1] & 0xff) << 8;
472*7c478bd9Sstevel@tonic-gate bits |= (byte[2] & 0xff);
473*7c478bd9Sstevel@tonic-gate
474*7c478bd9Sstevel@tonic-gate for ( i = 0; i < 4; i++, bits <<= 6 ) {
475*7c478bd9Sstevel@tonic-gate if ( wraplen != -1 && lenused >= 0 && lenused++ > wraplen ) {
476*7c478bd9Sstevel@tonic-gate *out++ = '\n';
477*7c478bd9Sstevel@tonic-gate *out++ = ' ';
478*7c478bd9Sstevel@tonic-gate lenused = 2;
479*7c478bd9Sstevel@tonic-gate }
480*7c478bd9Sstevel@tonic-gate
481*7c478bd9Sstevel@tonic-gate if (( i == 3 && pad > 0 ) || ( i == 2 && pad == 2 )) {
482*7c478bd9Sstevel@tonic-gate /* Pad as appropriate */
483*7c478bd9Sstevel@tonic-gate *out++ = '=';
484*7c478bd9Sstevel@tonic-gate } else {
485*7c478bd9Sstevel@tonic-gate /* get b64 digit from low order 6 bits */
486*7c478bd9Sstevel@tonic-gate *out++ = nib2b64[ (bits & 0xfc0000L) >> 18 ];
487*7c478bd9Sstevel@tonic-gate }
488*7c478bd9Sstevel@tonic-gate }
489*7c478bd9Sstevel@tonic-gate }
490*7c478bd9Sstevel@tonic-gate
491*7c478bd9Sstevel@tonic-gate *out = '\0';
492*7c478bd9Sstevel@tonic-gate
493*7c478bd9Sstevel@tonic-gate return( out - dst );
494*7c478bd9Sstevel@tonic-gate }
495*7c478bd9Sstevel@tonic-gate
496*7c478bd9Sstevel@tonic-gate int
ldif_base64_encode(unsigned char * src,char * dst,int srclen,int lenused)497*7c478bd9Sstevel@tonic-gate ldif_base64_encode( unsigned char *src, char *dst, int srclen, int lenused )
498*7c478bd9Sstevel@tonic-gate {
499*7c478bd9Sstevel@tonic-gate return ldif_base64_encode_internal( src, dst, srclen, lenused, LDIF_MAX_LINE_WIDTH );
500*7c478bd9Sstevel@tonic-gate }
501*7c478bd9Sstevel@tonic-gate
502*7c478bd9Sstevel@tonic-gate int
ldif_base64_encode_nowrap(unsigned char * src,char * dst,int srclen,int lenused)503*7c478bd9Sstevel@tonic-gate ldif_base64_encode_nowrap( unsigned char *src, char *dst, int srclen, int lenused )
504*7c478bd9Sstevel@tonic-gate {
505*7c478bd9Sstevel@tonic-gate return ldif_base64_encode_internal( src, dst, srclen, lenused, -1 );
506*7c478bd9Sstevel@tonic-gate }
507*7c478bd9Sstevel@tonic-gate
508*7c478bd9Sstevel@tonic-gate
509*7c478bd9Sstevel@tonic-gate /*
510*7c478bd9Sstevel@tonic-gate * return malloc'd, zero-terminated LDIF line
511*7c478bd9Sstevel@tonic-gate */
512*7c478bd9Sstevel@tonic-gate char *
ldif_type_and_value_with_options(char * type,char * val,int vlen,unsigned long options)513*7c478bd9Sstevel@tonic-gate ldif_type_and_value_with_options( char *type, char *val, int vlen,
514*7c478bd9Sstevel@tonic-gate unsigned long options )
515*7c478bd9Sstevel@tonic-gate {
516*7c478bd9Sstevel@tonic-gate char *buf, *p;
517*7c478bd9Sstevel@tonic-gate int tlen;
518*7c478bd9Sstevel@tonic-gate
519*7c478bd9Sstevel@tonic-gate tlen = strlen( type );
520*7c478bd9Sstevel@tonic-gate if (( buf = (char *)malloc( LDIF_SIZE_NEEDED( tlen, vlen ) + 1 )) !=
521*7c478bd9Sstevel@tonic-gate NULL ) {
522*7c478bd9Sstevel@tonic-gate p = buf;
523*7c478bd9Sstevel@tonic-gate ldif_put_type_and_value_with_options( &p, type, val, vlen, options );
524*7c478bd9Sstevel@tonic-gate *p = '\0';
525*7c478bd9Sstevel@tonic-gate }
526*7c478bd9Sstevel@tonic-gate
527*7c478bd9Sstevel@tonic-gate return( buf );
528*7c478bd9Sstevel@tonic-gate }
529*7c478bd9Sstevel@tonic-gate
530*7c478bd9Sstevel@tonic-gate char *
ldif_type_and_value(char * type,char * val,int vlen)531*7c478bd9Sstevel@tonic-gate ldif_type_and_value( char *type, char *val, int vlen )
532*7c478bd9Sstevel@tonic-gate {
533*7c478bd9Sstevel@tonic-gate return ldif_type_and_value_with_options( type, val, vlen, 0 );
534*7c478bd9Sstevel@tonic-gate }
535*7c478bd9Sstevel@tonic-gate
536*7c478bd9Sstevel@tonic-gate char *
ldif_type_and_value_nowrap(char * type,char * val,int vlen)537*7c478bd9Sstevel@tonic-gate ldif_type_and_value_nowrap( char *type, char *val, int vlen )
538*7c478bd9Sstevel@tonic-gate {
539*7c478bd9Sstevel@tonic-gate return ldif_type_and_value_with_options( type, val, vlen, LDIF_OPT_NOWRAP );
540*7c478bd9Sstevel@tonic-gate }
541*7c478bd9Sstevel@tonic-gate
542*7c478bd9Sstevel@tonic-gate /*
543*7c478bd9Sstevel@tonic-gate * ldif_get_entry - read the next ldif entry from the FILE referenced
544*7c478bd9Sstevel@tonic-gate * by fp. return a pointer to a malloc'd, null-terminated buffer. also
545*7c478bd9Sstevel@tonic-gate * returned is the last line number read, in *lineno.
546*7c478bd9Sstevel@tonic-gate */
547*7c478bd9Sstevel@tonic-gate char *
ldif_get_entry(FILE * fp,int * lineno)548*7c478bd9Sstevel@tonic-gate ldif_get_entry( FILE *fp, int *lineno )
549*7c478bd9Sstevel@tonic-gate {
550*7c478bd9Sstevel@tonic-gate char line[BUFSIZ];
551*7c478bd9Sstevel@tonic-gate char *buf;
552*7c478bd9Sstevel@tonic-gate int max, cur, len, gotsome;
553*7c478bd9Sstevel@tonic-gate
554*7c478bd9Sstevel@tonic-gate buf = NULL;
555*7c478bd9Sstevel@tonic-gate max = cur = gotsome = 0;
556*7c478bd9Sstevel@tonic-gate while ( fgets( line, sizeof(line), fp ) != NULL ) {
557*7c478bd9Sstevel@tonic-gate if ( lineno != NULL ) {
558*7c478bd9Sstevel@tonic-gate (*lineno)++;
559*7c478bd9Sstevel@tonic-gate }
560*7c478bd9Sstevel@tonic-gate /* ldif entries are terminated by a \n on a line by itself */
561*7c478bd9Sstevel@tonic-gate if ( line[0] == '\0' || line[0] == '\n'
562*7c478bd9Sstevel@tonic-gate #if !defined( XP_WIN32 )
563*7c478bd9Sstevel@tonic-gate || ( line[0] == '\r' && line[1] == '\n' ) /* DOS format */
564*7c478bd9Sstevel@tonic-gate #endif
565*7c478bd9Sstevel@tonic-gate ) {
566*7c478bd9Sstevel@tonic-gate if ( gotsome ) {
567*7c478bd9Sstevel@tonic-gate break;
568*7c478bd9Sstevel@tonic-gate } else {
569*7c478bd9Sstevel@tonic-gate continue;
570*7c478bd9Sstevel@tonic-gate }
571*7c478bd9Sstevel@tonic-gate } else if ( line[0] == '#' ) {
572*7c478bd9Sstevel@tonic-gate continue;
573*7c478bd9Sstevel@tonic-gate }
574*7c478bd9Sstevel@tonic-gate gotsome = 1;
575*7c478bd9Sstevel@tonic-gate len = strlen( line );
576*7c478bd9Sstevel@tonic-gate #if !defined( XP_WIN32 )
577*7c478bd9Sstevel@tonic-gate /* DOS format */
578*7c478bd9Sstevel@tonic-gate if ( len > 0 && line[len-1] == '\r' ) {
579*7c478bd9Sstevel@tonic-gate --len;
580*7c478bd9Sstevel@tonic-gate line[len] = '\0';
581*7c478bd9Sstevel@tonic-gate } else if ( len > 1 && line[len-2] == '\r' && line[len-1] == '\n' ) {
582*7c478bd9Sstevel@tonic-gate --len;
583*7c478bd9Sstevel@tonic-gate line[len-1] = line[len];
584*7c478bd9Sstevel@tonic-gate line[len] = '\0';
585*7c478bd9Sstevel@tonic-gate }
586*7c478bd9Sstevel@tonic-gate #endif
587*7c478bd9Sstevel@tonic-gate while ( cur + (len + 1) > max ) {
588*7c478bd9Sstevel@tonic-gate if ( buf == NULL ) {
589*7c478bd9Sstevel@tonic-gate max += BUFSIZ;
590*7c478bd9Sstevel@tonic-gate buf = (char *) malloc( max );
591*7c478bd9Sstevel@tonic-gate } else {
592*7c478bd9Sstevel@tonic-gate max *= 2;
593*7c478bd9Sstevel@tonic-gate buf = (char *) realloc( buf, max );
594*7c478bd9Sstevel@tonic-gate }
595*7c478bd9Sstevel@tonic-gate if ( buf == NULL ) {
596*7c478bd9Sstevel@tonic-gate return( NULL );
597*7c478bd9Sstevel@tonic-gate }
598*7c478bd9Sstevel@tonic-gate }
599*7c478bd9Sstevel@tonic-gate
600*7c478bd9Sstevel@tonic-gate memcpy( buf + cur, line, len + 1 );
601*7c478bd9Sstevel@tonic-gate cur += len;
602*7c478bd9Sstevel@tonic-gate }
603*7c478bd9Sstevel@tonic-gate
604*7c478bd9Sstevel@tonic-gate return( buf );
605*7c478bd9Sstevel@tonic-gate }
606