Check whether `-fgnu89-inline' is supported before using it.
[gnutls.git] / lib / gnutls_str.c
blobd566f99ce5d0a8daac0266fa500f0bfdbbedf493
1 /*
2 * Copyright (C) 2002, 2004, 2005, 2007, 2008 Free Software Foundation
4 * Author: Nikos Mavrogiannopoulos
6 * This file is part of GNUTLS.
8 * The GNUTLS library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; either version 2.1 of
11 * the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
21 * USA
25 #include <gnutls_int.h>
26 #include <gnutls_errors.h>
27 #include <gnutls_num.h>
28 #include <gnutls_str.h>
30 /* These function are like strcat, strcpy. They only
31 * do bound checking (they shouldn't cause buffer overruns),
32 * and they always produce null terminated strings.
34 * They should be used only with null terminated strings.
36 void
37 _gnutls_str_cat (char *dest, size_t dest_tot_size, const char *src)
39 size_t str_size = strlen (src);
40 size_t dest_size = strlen (dest);
42 if (dest_tot_size - dest_size > str_size)
44 strcat (dest, src);
46 else
48 if (dest_tot_size - dest_size > 0)
50 strncat (dest, src, (dest_tot_size - dest_size) - 1);
51 dest[dest_tot_size - 1] = 0;
56 void
57 _gnutls_str_cpy (char *dest, size_t dest_tot_size, const char *src)
59 size_t str_size = strlen (src);
61 if (dest_tot_size > str_size)
63 strcpy (dest, src);
65 else
67 if (dest_tot_size > 0)
69 strncpy (dest, src, (dest_tot_size) - 1);
70 dest[dest_tot_size - 1] = 0;
75 void
76 _gnutls_mem_cpy (char *dest, size_t dest_tot_size, const char *src,
77 size_t src_size)
80 if (dest_tot_size >= src_size)
82 memcpy (dest, src, src_size);
84 else
86 if (dest_tot_size > 0)
88 memcpy (dest, src, dest_tot_size);
93 void
94 _gnutls_string_init (gnutls_string * str,
95 gnutls_alloc_function alloc_func,
96 gnutls_realloc_function realloc_func,
97 gnutls_free_function free_func)
99 str->data = NULL;
100 str->max_length = 0;
101 str->length = 0;
103 str->alloc_func = alloc_func;
104 str->free_func = free_func;
105 str->realloc_func = realloc_func;
108 void
109 _gnutls_string_clear (gnutls_string * str)
111 if (str == NULL || str->data == NULL)
112 return;
113 str->free_func (str->data);
115 str->data = NULL;
116 str->max_length = 0;
117 str->length = 0;
120 /* This one does not copy the string.
122 gnutls_datum_t
123 _gnutls_string2datum (gnutls_string * str)
125 gnutls_datum_t ret;
127 ret.data = str->data;
128 ret.size = str->length;
130 return ret;
133 #define MIN_CHUNK 256
136 _gnutls_string_copy_str (gnutls_string * dest, const char *src)
138 size_t src_len = strlen (src);
140 if (dest->max_length >= src_len)
142 memcpy (dest->data, src, src_len);
143 dest->length = src_len;
145 return src_len;
147 else
149 dest->data = dest->realloc_func (dest->data, MAX (src_len, MIN_CHUNK));
150 if (dest->data == NULL)
152 gnutls_assert ();
153 return GNUTLS_E_MEMORY_ERROR;
155 dest->max_length = MAX (MIN_CHUNK, src_len);
157 memcpy (dest->data, src, src_len);
158 dest->length = src_len;
160 return src_len;
165 _gnutls_string_append_str (gnutls_string * dest, const char *src)
167 size_t src_len = strlen (src);
168 size_t tot_len = src_len + dest->length;
170 if (dest->max_length >= tot_len)
172 memcpy (&dest->data[dest->length], src, src_len);
173 dest->length = tot_len;
175 return tot_len;
177 else
179 size_t new_len =
180 MAX (src_len, MIN_CHUNK) + MAX (dest->max_length, MIN_CHUNK);
182 dest->data = dest->realloc_func (dest->data, new_len);
183 if (dest->data == NULL)
185 gnutls_assert ();
186 return GNUTLS_E_MEMORY_ERROR;
188 dest->max_length = new_len;
190 memcpy (&dest->data[dest->length], src, src_len);
191 dest->length = tot_len;
193 return tot_len;
198 _gnutls_string_append_data (gnutls_string * dest, const void *data,
199 size_t data_size)
201 size_t tot_len = data_size + dest->length;
203 if (dest->max_length >= tot_len)
205 memcpy (&dest->data[dest->length], data, data_size);
206 dest->length = tot_len;
208 return tot_len;
210 else
212 size_t new_len =
213 MAX (data_size, MIN_CHUNK) + MAX (dest->max_length, MIN_CHUNK);
215 dest->data = dest->realloc_func (dest->data, new_len);
216 if (dest->data == NULL)
218 gnutls_assert ();
219 return GNUTLS_E_MEMORY_ERROR;
221 dest->max_length = new_len;
223 memcpy (&dest->data[dest->length], data, data_size);
224 dest->length = tot_len;
226 return tot_len;
231 _gnutls_string_append_printf (gnutls_string * dest, const char *fmt, ...)
233 va_list args;
234 int len;
235 char *str;
237 va_start (args, fmt);
238 len = vasprintf (&str, fmt, args);
239 va_end (args);
241 if (len < 0 || !str)
242 return -1;
244 len = _gnutls_string_append_str (dest, str);
246 free (str);
248 return len;
251 /* Converts the given string (old) to hex. A buffer must be provided
252 * to hold the new hex string. The new string will be null terminated.
253 * If the buffer does not have enough space to hold the string, a
254 * truncated hex string is returned (always null terminated).
256 char *
257 _gnutls_bin2hex (const void *_old, size_t oldlen,
258 char *buffer, size_t buffer_size)
260 unsigned int i, j;
261 const opaque *old = _old;
263 for (i = j = 0; i < oldlen && j + 2 < buffer_size; j += 2)
265 sprintf (&buffer[j], "%.2x", old[i]);
266 i++;
268 buffer[j] = '\0';
270 return buffer;
274 * gnutls_hex2bin - convert hex string into binary buffer.
275 * @hex_data: string with data in hex format
276 * @hex_size: size of hex data
277 * @bin_data: output array with binary data
278 * @bin_size: when calling *@bin_size should hold size of @bin_data,
279 * on return will hold actual size of @bin_data.
281 * Convert a buffer with hex data to binary data.
283 * Returns: %GNUTLS_E_SUCCESS on success, otherwise an error.
286 gnutls_hex2bin (const char * hex_data,
287 size_t hex_size,
288 char * bin_data,
289 size_t * bin_size)
291 return _gnutls_hex2bin (hex_data, (int)hex_size, bin_data, bin_size);
295 _gnutls_hex2bin (const opaque * hex_data, int hex_size, opaque * bin_data,
296 size_t * bin_size)
298 int i, j;
299 opaque hex2_data[3];
300 unsigned long val;
302 /* FIXME: we don't handle whitespace.
304 hex_size /= 2;
306 if (*bin_size < (size_t) hex_size)
308 gnutls_assert ();
309 return GNUTLS_E_SHORT_MEMORY_BUFFER;
312 for (i = j = 0; j < hex_size; i += 2, j++)
314 hex2_data[0] = hex_data[i];
315 hex2_data[1] = hex_data[i + 1];
316 hex2_data[2] = 0;
317 val = strtoul ((char *) hex2_data, NULL, 16);
318 if (val == ULONG_MAX)
320 gnutls_assert ();
321 return GNUTLS_E_SRP_PWD_PARSING_ERROR;
323 bin_data[j] = val;
326 return 0;
330 /* compare hostname against certificate, taking account of wildcards
331 * return 1 on success or 0 on error
334 _gnutls_hostname_compare (const char *certname, const char *hostname)
336 const char *cmpstr1, *cmpstr2;
338 if (strlen (certname) == 0 || strlen (hostname) == 0)
339 return 0;
341 if (strlen (certname) > 2 && strncmp (certname, "*.", 2) == 0)
343 /* a wildcard certificate */
345 cmpstr1 = certname + 1;
347 /* find the first dot in hostname, compare from there on */
348 cmpstr2 = strchr (hostname, '.');
350 if (cmpstr2 == NULL)
352 /* error, the hostname we're connecting to is only a local part */
353 return 0;
356 if (strcasecmp (cmpstr1, cmpstr2) == 0)
358 return 1;
361 return 0;
364 if (strcasecmp (certname, hostname) == 0)
366 return 1;
369 return 0;