1 /* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * gsf-utils.c:
4  *
5  * Copyright (C) 2002-2006 Jody Goldberg (jody@gnome.org)
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of version 2.1 of the GNU Lesser General Public
9  * License as published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
19  * USA
20  */
21 
22 #include <gsf-config.h>
23 #include <gsf/gsf-utils.h>
24 #include <gsf/gsf.h>
25 
26 #include <gobject/gvaluecollector.h>
27 #include <glib/gi18n-lib.h>
28 
29 #include <ctype.h>
30 #include <string.h>
31 
32 /*
33  * Glib gets this wrong, really.  ARM's floating point format is a weird
34  * mixture.
35  */
36 #define G_ARMFLOAT_ENDIAN 56781234
37 #if defined(__arm__) && !defined(__ARM_EABI__) && (G_BYTE_ORDER == G_LITTLE_ENDIAN)
38 #define G_FLOAT_BYTE_ORDER G_ARMFLOAT_ENDIAN
39 #else
40 #define G_FLOAT_BYTE_ORDER G_BYTE_ORDER
41 #endif
42 
43 gboolean
gsf_debug_flag(const char * flag)44 gsf_debug_flag (const char *flag)
45 {
46 	GDebugKey key;
47 	key.key = (char *)flag;
48 	key.value = 1;
49 
50 	return g_parse_debug_string (g_getenv ("GSF_DEBUG"), &key, 1) != 0;
51 }
52 
53 
54 #ifdef _GSF_GTYPE_THREADING_FIXED
55 typedef GTypeModule      GsfDummyTypeModule;
56 typedef GTypeModuleClass GsfDummyTypeModuleClass;
57 static gboolean
gsf_dummy_type_module_load(GTypeModule * module)58 gsf_dummy_type_module_load (GTypeModule *module)
59 {
60 	gsf_init_dynamic (module);
61 	return TRUE;
62 }
63 static void
gsf_dummy_type_module_class_init(GTypeModuleClass * gtm_class)64 gsf_dummy_type_module_class_init (GTypeModuleClass *gtm_class)
65 {
66 	gtm_class->load = gsf_dummy_type_module_load;
67 }
68 static GSF_CLASS (GsfDummyTypeModule, gsf_dummy_type_module,
69 		  gsf_dummy_type_module_class_init, NULL,
70 		  G_TYPE_TYPE_MODULE)
71 
72 static GTypeModule *static_type_module = NULL;
73 #endif
74 
75 #ifdef G_OS_WIN32
76 #include <windows.h>
77 static HMODULE gsf_dll_hmodule;
78 BOOL WINAPI
79 DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved);
80 BOOL WINAPI
DllMain(HINSTANCE hinstDLL,DWORD fdwReason,G_GNUC_UNUSED LPVOID lpvReserved)81 DllMain (HINSTANCE hinstDLL, DWORD fdwReason, G_GNUC_UNUSED LPVOID lpvReserved)
82 {
83 	if (fdwReason == DLL_PROCESS_ATTACH) gsf_dll_hmodule = hinstDLL;
84 	return TRUE;
85 }
86 #endif
87 
88 /**
89  * gsf_init:
90  *
91  * Initializes the GSF library
92  **/
93 void
gsf_init(void)94 gsf_init (void)
95 {
96 	static gboolean libgsf_initialized = FALSE;
97 	if (libgsf_initialized)
98 		return;
99 
100 #ifdef ENABLE_NLS
101 #ifdef G_OS_WIN32
102 	{
103 		char *pkg_dir	  = g_win32_get_package_installation_directory_of_module (gsf_dll_hmodule);
104 		gchar *locale_dir = g_build_filename (pkg_dir, "lib/locale", NULL);
105 		bindtextdomain (GETTEXT_PACKAGE, locale_dir);
106 		g_free (locale_dir);
107 		g_free (pkg_dir);
108 	}
109 #else
110 	bindtextdomain (GETTEXT_PACKAGE, GSFLOCALEDIR);
111 #endif
112 	bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
113 #endif
114 
115 #ifdef _GSF_GTYPE_THREADING_FIXED
116 	if (NULL == static_type_module) {
117 		static_type_module = g_object_new (gsf_dummy_type_module_get_type(), NULL);
118 		g_assert (static_type_module != NULL);
119 		g_type_module_use (static_type_module);
120 		g_type_module_set_name (static_type_module, "libgsf-builtin");
121 	}
122 #else
123 	gsf_init_dynamic (NULL);
124 #endif
125 
126 	{
127 		/* Little-endian representation of M_PI.  */
128 		static const guint8 pibytes[8] = {
129 			0x18, 0x2d, 0x44, 0x54, 0xfb, 0x21, 0x09, 0x40
130 		};
131 
132 		/*
133 		 * If this fails, see
134 		 *   http://bugzilla.gnome.org/show_bug.cgi?id=350973
135 		 */
136 		double pi = gsf_le_get_double (pibytes);
137 		if (!(pi > 3.14 && pi < 3.15))
138 			g_error ("Compilation trouble with endianess.");
139 	}
140 }
141 
142 /**
143  * gsf_shutdown:
144  *
145  * De-intializes the GSF library
146  * Currently does nothing.
147  **/
148 void
gsf_shutdown(void)149 gsf_shutdown (void)
150 {
151 }
152 
153 #ifdef _GSF_GTYPE_THREADING_FIXED
154 #define REGISTER(prefix)						\
155 	do {								\
156 		prefix ## _register_type (module);			\
157 		types = g_slist_prepend (types,				\
158 			g_type_class_ref (prefix ## _get_type()));	\
159 	} while (0)
160 #else
161 /* Assign the value to avoid compiler warnings */
162 #define REGISTER(prefix)	g_type_ensure (prefix ## _get_type())
163 #endif
164 
165 /**
166  * gsf_init_dynamic:
167  * @module: #GTypeModule.
168  *
169  * Initializes the GSF library and associates it with a type module @mod.
170  **/
171 void
gsf_init_dynamic(GTypeModule * module)172 gsf_init_dynamic (GTypeModule *module)
173 {
174 #ifndef _GSF_GTYPE_THREADING_FIXED
175 	if (NULL != module) {
176 		g_warning ("glib's support of dynamic types is not thread safe.\n"
177 			   "Support for gsf_init_dynamic has been disabled until that is fixed");
178 	}
179 #endif
180 	REGISTER (gsf_input);
181 	/* REGISTER (gsf_input_bzip); */
182 	REGISTER (gsf_input_gzip);
183 	REGISTER (gsf_input_http);
184 	/* REGISTER (gsf_input_iochannel); */
185 	REGISTER (gsf_input_memory);
186 	REGISTER (gsf_input_proxy);
187 	REGISTER (gsf_input_stdio);
188 	REGISTER (gsf_input_textline);
189 
190 	REGISTER (gsf_infile);
191 	REGISTER (gsf_infile_msole);
192 	REGISTER (gsf_infile_msvba);
193 	REGISTER (gsf_infile_stdio);
194 	REGISTER (gsf_infile_tar);
195 	REGISTER (gsf_infile_zip);
196 
197 	REGISTER (gsf_output);
198 	REGISTER (gsf_output_bzip);
199 	REGISTER (gsf_output_csv_quoting_mode);
200 	REGISTER (gsf_output_csv);
201 	REGISTER (gsf_output_gzip);
202 	REGISTER (gsf_output_iconv);
203 	REGISTER (gsf_output_iochannel);
204 	REGISTER (gsf_output_memory);
205 	REGISTER (gsf_output_stdio);
206 
207 	REGISTER (gsf_outfile);
208 	REGISTER (gsf_outfile_msole);
209 	REGISTER (gsf_outfile_stdio);
210 	REGISTER (gsf_outfile_zip);
211 	REGISTER (gsf_outfile_open_pkg);
212 
213 	REGISTER (gsf_shared_memory);
214 	REGISTER (gsf_structured_blob);
215 	REGISTER (gsf_xml_out);
216 	REGISTER (gsf_blob);
217 	REGISTER (gsf_clip_data);
218 	REGISTER (gsf_doc_meta_data);
219 	REGISTER (gsf_docprop_vector);
220 }
221 
222 /**
223  * gsf_shutdown_dynamic:
224  * @module: currently unused
225  *
226  * De-intializes the GSF library from a type module.
227  * Currently does nothing.
228  **/
229 void
gsf_shutdown_dynamic(G_GNUC_UNUSED GTypeModule * module)230 gsf_shutdown_dynamic (G_GNUC_UNUSED GTypeModule *module)
231 {
232 }
233 
234 static void
gsf_mem_dump_full(guint8 const * ptr,size_t len,gsf_off_t offset)235 gsf_mem_dump_full (guint8 const *ptr, size_t len, gsf_off_t offset)
236 {
237 	static const char hexdigit[16] = "0123456789abcdef";
238 
239 	while (len > 0) {
240 		char hexpart[3 * 16 + 1], *phex = hexpart;
241 		char pic[17];
242 		size_t j;
243 		for (j = 0; j < 16; j++) {
244 			if (len > 0) {
245 				*phex++ = hexdigit[*ptr >> 4];
246 				*phex++ = hexdigit[*ptr & 0xf];
247 				pic[j] = (*ptr >= '!' && *ptr < 127 ? *ptr : '.');
248 				len--;
249 				ptr++;
250 			} else {
251 				*phex++ = 'X';
252 				*phex++ = 'X';
253 				pic[j] = '*';
254 			}
255 			*phex++ = ' ';
256 		}
257 		hexpart[3 * 16] = 0;
258 		pic[16] = 0 ;
259 
260 		g_print ("%8lx | %s| %s\n", (long)offset, hexpart, pic);
261 		offset += 16;
262 	}
263 }
264 
265 /**
266  * gsf_mem_dump:
267  * @ptr: memory area to be dumped.
268  * @len: how many bytes will be dumped.
269  *
270  * Dump @len bytes from the memory location given by @ptr.
271  **/
272 void
gsf_mem_dump(guint8 const * ptr,size_t len)273 gsf_mem_dump (guint8 const *ptr, size_t len)
274 {
275 	gsf_mem_dump_full (ptr, len, 0);
276 }
277 
278 /**
279  * gsf_input_dump:
280  * @input: a #GsfInput
281  * @dump_as_hex: If %TRUE, dump in hexidecmal format
282  *
283  * Dumps @input's contents to STDOUT, optionally in hex format.
284  */
285 void
gsf_input_dump(GsfInput * input,gboolean dump_as_hex)286 gsf_input_dump (GsfInput *input, gboolean dump_as_hex)
287 {
288 	gsf_off_t offset = 0, size;
289 
290 	/* read in small blocks to excercise things */
291 	size = gsf_input_size (GSF_INPUT (input));
292 	while (size > 0) {
293 		size_t count = (size > 0x1000) ? 0x1000 : size;
294 		guint8 const *data =
295 			gsf_input_read (GSF_INPUT (input), count, NULL);
296 		g_return_if_fail (data != NULL);
297 		if (dump_as_hex)
298 			gsf_mem_dump_full (data, count, offset);
299 		else
300 			fwrite (data, 1, count, stdout);
301 		size -= count;
302 		offset += count;
303 	}
304 	if (!dump_as_hex)
305 		fflush (stdout);
306 }
307 
308 /**
309  * gsf_le_get_guint64:
310  * @p: pointer to storage
311  *
312  * Interpret binary data as a guint64 (8 byte unsigned integer type) in little
313  * endian order.
314  *
315  * Returns: interpreted data
316  */
317 guint64
gsf_le_get_guint64(void const * p)318 gsf_le_get_guint64 (void const *p)
319 {
320 #if G_BYTE_ORDER == G_BIG_ENDIAN
321 	if (sizeof (guint64) == 8) {
322 		guint64 li;
323 		int     i;
324 		guint8 *t  = (guint8 *)&li;
325 		guint8 *p2 = (guint8 *)p;
326 		int     sd = sizeof (li);
327 
328 		for (i = 0; i < sd; i++)
329 			t[i] = p2[sd - 1 - i];
330 
331 		return li;
332 	} else {
333 		g_error ("Big endian machine, but weird size of guint64");
334 	}
335 #elif G_BYTE_ORDER == G_LITTLE_ENDIAN
336 	if (sizeof (guint64) == 8) {
337 		/*
338 		 * On i86, we could access directly, but Alphas require
339 		 * aligned access.
340 		 */
341 		guint64 data;
342 		memcpy (&data, p, sizeof (data));
343 		return data;
344 	} else {
345 		g_error ("Little endian machine, but weird size of guint64");
346 	}
347 #else
348 #error "Byte order not recognised -- out of luck"
349 #endif
350 }
351 
352 /**
353  * gsf_le_get_float:
354  * @p: pointer to storage
355  *
356  * Interpret binary data as a float in little endian order.
357  *
358  *
359  * Returns: interpreted data
360  */
361 float
gsf_le_get_float(void const * p)362 gsf_le_get_float (void const *p)
363 {
364 #if G_FLOAT_BYTE_ORDER == G_BIG_ENDIAN
365 	if (sizeof (float) == 4) {
366 		float   f;
367 		int     i;
368 		guint8 *t  = (guint8 *)&f;
369 		guint8 *p2 = (guint8 *)p;
370 		int     sd = sizeof (f);
371 
372 		for (i = 0; i < sd; i++)
373 			t[i] = p2[sd - 1 - i];
374 
375 		return f;
376 	} else {
377 		g_error ("Big endian machine, but weird size of floats");
378 	}
379 #elif (G_FLOAT_BYTE_ORDER == G_LITTLE_ENDIAN) || (G_FLOAT_BYTE_ORDER == G_ARMFLOAT_ENDIAN)
380 	if (sizeof (float) == 4) {
381 		/*
382 		 * On i86, we could access directly, but Alphas require
383 		 * aligned access.
384 		 */
385 		float data;
386 		memcpy (&data, p, sizeof (data));
387 		return data;
388 	} else {
389 		g_error ("Little endian machine, but weird size of floats");
390 	}
391 #else
392 #error "Floating-point byte order not recognised -- out of luck"
393 #endif
394 }
395 
396 /**
397  * gsf_le_set_float:
398  * @p: pointer to storage
399  * @f: float to be stored
400  *
401  * Store a value of type float in memory in little endian order.
402  */
403 void
gsf_le_set_float(void * p,float f)404 gsf_le_set_float (void *p, float f)
405 {
406 #if G_FLOAT_BYTE_ORDER == G_BIG_ENDIAN
407 	if (sizeof (float) == 4) {
408 		int     i;
409 		guint8 *t  = (guint8 *)&f;
410 		guint8 *p2 = (guint8 *)p;
411 		int     sd = sizeof (f);
412 
413 		for (i = 0; i < sd; i++)
414 			p2[sd - 1 - i] = t[i];
415 	} else {
416 		g_error ("Big endian machine, but weird size of floats");
417 	}
418 #elif (G_FLOAT_BYTE_ORDER == G_LITTLE_ENDIAN) || (G_FLOAT_BYTE_ORDER == G_ARMFLOAT_ENDIAN)
419 	if (sizeof (float) == 4) {
420 		/*
421 		 * On i86, we could access directly, but Alphas require
422 		 * aligned access.
423 		 */
424 		memcpy (p, &f, sizeof (f));
425 	} else {
426 		g_error ("Little endian machine, but weird size of floats");
427 	}
428 #else
429 #error "Floating-point byte order not recognised -- out of luck"
430 #endif
431 }
432 
433 /**
434  * gsf_le_get_double:
435  * @p: pointer to storage
436  *
437  * Interpret binary data as a double in little endian order.
438  *
439  * Returns: interpreted data
440  */
441 double
gsf_le_get_double(void const * p)442 gsf_le_get_double (void const *p)
443 {
444 #if G_FLOAT_BYTE_ORDER == G_ARMFLOAT_ENDIAN
445 	double data;
446 	memcpy ((char *)&data + 4, p, 4);
447 	memcpy ((char *)&data, (char const *)p + 4, 4);
448 	return data;
449 #elif G_FLOAT_BYTE_ORDER == G_BIG_ENDIAN
450 	if (sizeof (double) == 8) {
451 		double  d;
452 		int     i;
453 		guint8 *t  = (guint8 *)&d;
454 		guint8 *p2 = (guint8 *)p;
455 		int     sd = sizeof (d);
456 
457 		for (i = 0; i < sd; i++)
458 			t[i] = p2[sd - 1 - i];
459 
460 		return d;
461 	} else {
462 		g_error ("Big endian machine, but weird size of doubles");
463 	}
464 #elif G_FLOAT_BYTE_ORDER == G_LITTLE_ENDIAN
465 	if (sizeof (double) == 8) {
466 		/*
467 		 * On i86, we could access directly, but Alphas require
468 		 * aligned access.
469 		 */
470 		double data;
471 		memcpy (&data, p, sizeof (data));
472 		return data;
473 	} else {
474 		g_error ("Little endian machine, but weird size of doubles");
475 	}
476 #else
477 #error "Floating-point byte order not recognised -- out of luck"
478 #endif
479 }
480 
481 /**
482  * gsf_le_set_double:
483  * @p: pointer to storage
484  * @d: double to be stored
485  *
486  * Store a value of type double in memory in little endian order
487  */
488 void
gsf_le_set_double(void * p,double d)489 gsf_le_set_double (void *p, double d)
490 {
491 #if G_FLOAT_BYTE_ORDER == G_ARMFLOAT_ENDIAN
492 	memcpy (p, (char const *)&d + 4, 4);
493 	memcpy ((char *)p + 4, &d, 4);
494 #elif G_FLOAT_BYTE_ORDER == G_BIG_ENDIAN
495 	if (sizeof (double) == 8) {
496 		int     i;
497 		guint8 *t  = (guint8 *)&d;
498 		guint8 *p2 = (guint8 *)p;
499 		int     sd = sizeof (d);
500 
501 		for (i = 0; i < sd; i++)
502 			p2[sd - 1 - i] = t[i];
503 	} else {
504 		g_error ("Big endian machine, but weird size of doubles");
505 	}
506 #elif G_FLOAT_BYTE_ORDER == G_LITTLE_ENDIAN
507 	if (sizeof (double) == 8) {
508 		/*
509 		 * On i86, we could access directly, but Alphas require
510 		 * aligned access.
511 		 */
512 		memcpy (p, &d, sizeof (d));
513 	} else {
514 		g_error ("Little endian machine, but weird size of doubles");
515 	}
516 #else
517 #error "Floating-point byte order not recognised -- out of luck"
518 #endif
519 }
520 
521 /**
522  * gsf_extension_pointer:
523  * @path: A filename or file path.
524  *
525  * Extracts the extension from the end of a filename (the part after the final
526  * '.' in the filename).
527  *
528  * Returns: (transfer none): A pointer to the extension part of the
529  * filename, or a pointer to the end of the string if the filename
530  * does not have an extension.
531  */
532 char const *
gsf_extension_pointer(char const * path)533 gsf_extension_pointer (char const *path)
534 {
535 	char const *s, *end;
536 
537 	g_return_val_if_fail (path != NULL, NULL);
538 
539 	end = path + strlen (path);
540 	for (s = end; s > path; ) {
541 		s--;
542 		if (G_IS_DIR_SEPARATOR (*s))
543 			break;
544 		if (*s == '.')
545 			return s + 1;
546 	}
547 
548 	return end;
549 }
550 
551 /**
552  * gsf_iconv_close:
553  * @handle: handle to be closed.
554  *
555  * A utility wrapper to safely close an iconv handle.
556  **/
557 void
gsf_iconv_close(GIConv handle)558 gsf_iconv_close (GIConv handle)
559 {
560 	if (handle != NULL && handle != ((GIConv)-1))
561 		g_iconv_close (handle);
562 }
563 
564 /**
565  * gsf_filename_to_utf8:
566  * @filename: file name suitable for open(2).
567  * @quoted: if %TRUE, the resulting utf8 file name will be quoted
568  *    (unless it is invalid).
569  *
570  * A utility wrapper to make sure filenames are valid utf8.
571  * Caller must g_free the result.
572  *
573  * Returns: @filename using utf-8 encoding for display
574  **/
575 char *
gsf_filename_to_utf8(char const * filename,gboolean quoted)576 gsf_filename_to_utf8 (char const *filename, gboolean quoted)
577 {
578 	char *dname = g_filename_display_name (filename);
579 	char *result;
580 
581 	if (quoted) {
582 		result = g_strconcat ("\"", dname, "\"", NULL);
583 		g_free (dname);
584 	} else
585 		result = dname;
586 
587 	return result;
588 }
589 
590 /**
591  * gsf_base64_encode_close:
592  * @in: (array length=inlen): Data to be encoded
593  * @inlen: Length of data to be encoded
594  * @break_lines: Whether to use line breaks
595  * @out: (array): Encoded data.
596  * @state: (inout): holds the number of bits that are stored in @save
597  * @save: (inout): leftover bits that have not yet been decoded
598  *
599  * This funcion should be called to when finished encoding everything, to
600  * flush off the last little bit.
601  *
602  * Returns: a count of the number of bytes in the final block.
603  **/
604 size_t
gsf_base64_encode_close(guint8 const * in,size_t inlen,gboolean break_lines,guint8 * out,int * state,unsigned int * save)605 gsf_base64_encode_close (guint8 const *in, size_t inlen,
606 			 gboolean break_lines, guint8 *out, int *state, unsigned int *save)
607 {
608 	guint8 *outptr = out;
609 	if (inlen > 0)
610 		outptr += gsf_base64_encode_step (in, inlen, break_lines,
611 						  outptr, state, save);
612 	outptr += g_base64_encode_close (break_lines, outptr, state, save);
613 	return outptr-out;
614 }
615 
616 /**
617  * gsf_base64_encode_step:
618  * @in: (array): input stream
619  * @len: max length of data to decode
620  * @break_lines: Whether to use line breaks
621  * @out: (array): output stream
622  * @state: (inout): holds the number of bits that are stored in @save
623  * @save: (inout): leftover bits that have not yet been decoded
624  *
625  * Performs an 'encode step', only encodes blocks of 3 characters from @in into
626  * the output @out at a time, saves left-over state in @state and @save
627  * (initialise to 0 on first invocation).
628  *
629  * Returns: the number of bytes encoded
630  */
631 size_t
gsf_base64_encode_step(guint8 const * in,size_t len,gboolean break_lines,guint8 * out,int * state,unsigned int * save)632 gsf_base64_encode_step (guint8 const *in, size_t len,
633 			gboolean break_lines, guint8 *out, int *state, unsigned int *save)
634 {
635 	return g_base64_encode_step (in, len, break_lines, out, state, save);
636 }
637 
638 
639 /**
640  * gsf_base64_decode_step:
641  * @in: (array): input stream
642  * @len: max length of data to decode
643  * @out: (array): output stream
644  * @state: (inout): holds the number of bits that are stored in @save
645  * @save: (inout): leftover bits that have not yet been decoded
646  *
647  * Decodes a chunk of base64 encoded data
648  *
649  * Returns: the number of bytes converted
650  **/
651 size_t
gsf_base64_decode_step(guint8 const * in,size_t len,guint8 * out,int * state,guint * save)652 gsf_base64_decode_step (guint8 const *in, size_t len, guint8 *out,
653 			int *state, guint *save)
654 {
655 	return g_base64_decode_step (in, len, out, state, save);
656 }
657 
658 /**
659  * gsf_base64_encode_simple:
660  * @data: (array): data stream
661  * @len: max length of data to encode
662  *
663  * Encodes data from @data back into @data using base64 encoding.
664  *
665  * Returns: the number of bytes encoded
666  */
667 guint8 *
gsf_base64_encode_simple(guint8 const * data,size_t len)668 gsf_base64_encode_simple (guint8 const *data, size_t len)
669 {
670 	guint8 *out;
671 	int state = 0;
672 	guint save = 0;
673 	gboolean break_lines = TRUE;  /* This differs from g_base64_encode */
674 	size_t outlen = len * 4 / 3 + 5;
675 
676 	if (break_lines)
677 		outlen += outlen / 72 + 1;
678 	out = g_new (guint8, outlen);
679 	outlen = gsf_base64_encode_close (data, len, break_lines,
680 					  out, &state, &save);
681 	out[outlen] = '\0';
682 	return out;
683 }
684 
685 /**
686  * gsf_base64_decode_simple:
687  * @data: (array): data stream
688  * @len: max length of data to decode
689  *
690  * Decodes a chunk of base64 encoded data from @data back into @data.
691  *
692  * Returns: the number of bytes converted
693  */
694 size_t
gsf_base64_decode_simple(guint8 * data,size_t len)695 gsf_base64_decode_simple (guint8 *data, size_t len)
696 {
697 	int state = 0;
698 	guint save = 0;
699 	return gsf_base64_decode_step (data, len, data, &state, &save);
700 }
701 
702 
703 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
704 
705 /* Largely a copy of g_object_new_valist.  */
706 /**
707  * gsf_property_settings_collect_valist:
708  * @object_type: the GType for which the properties are being set.
709  * @p_n_params: a pointer to the number of properties collected.  (Used for
710  *   both input and output.)
711  * @p_params: a pointer to the GParameter array that holds the properties.
712  *   (Used for both input and output.  This may point to a %NULL pointer if
713  *   there are no properties collected yet.)
714  * @first_property_name: the name of the first property being set, or %NULL.
715  * @var_args: a va_list holding the remainder of the property names and
716  *   values, terminated by a %NULL.
717  *
718  * This function builds a GParameter array suitable for g_object_newv.
719  **/
720 void
gsf_property_settings_collect_valist(GType object_type,GParameter ** p_params,size_t * p_n_params,const gchar * first_property_name,va_list var_args)721 gsf_property_settings_collect_valist (GType object_type,
722 				      GParameter **p_params,
723 				      size_t *p_n_params,
724 				      const gchar *first_property_name,
725 				      va_list var_args)
726 {
727   GObjectClass *class;
728   GParameter *params = *p_params;
729   const gchar *name;
730   size_t n_params = *p_n_params;
731   size_t n_alloced_params = n_params;  /* We might have more.  */
732 
733   g_return_if_fail (G_TYPE_IS_OBJECT (object_type));
734 
735   class = g_type_class_ref (object_type);
736 
737   name = first_property_name;
738   while (name)
739     {
740       gchar *error = NULL;
741       GParamSpec *pspec = g_object_class_find_property (class, name);
742       if (!pspec)
743 	{
744 	  g_warning ("%s: object class `%s' has no property named `%s'",
745 		     G_STRFUNC,
746 		     g_type_name (object_type),
747 		     name);
748 	  break;
749 	}
750 
751       if (n_params >= n_alloced_params)
752 	{
753 	  n_alloced_params += 16;
754 	  params = g_renew (GParameter, params, n_alloced_params);
755 	}
756       params[n_params].name = name;
757       params[n_params].value.g_type = 0;
758       g_value_init (&params[n_params].value, G_PARAM_SPEC_VALUE_TYPE (pspec));
759       G_VALUE_COLLECT (&params[n_params].value, var_args, 0, &error);
760       if (error)
761 	{
762 	  g_warning ("%s: %s", G_STRFUNC, error);
763 	  g_free (error);
764           g_value_unset (&params[n_params].value);
765 	  break;
766 	}
767       n_params++;
768       name = va_arg (var_args, gchar*);
769     }
770 
771   g_type_class_unref (class);
772 
773   *p_params = params;
774   *p_n_params = n_params;
775 }
776 
777 /* This is a vararg version of gsf_property_settings_collect_valist.  */
778 void
gsf_property_settings_collect(GType object_type,GParameter ** p_params,size_t * p_n_params,const gchar * first_property_name,...)779 gsf_property_settings_collect (GType object_type,
780 			       GParameter **p_params,
781 			       size_t *p_n_params,
782 			       const gchar *first_property_name,
783 			       ...)
784 {
785   va_list var_args;
786   va_start (var_args, first_property_name);
787   gsf_property_settings_collect_valist (object_type, p_params, p_n_params, first_property_name, var_args);
788   va_end (var_args);
789 }
790 
791 /**
792  * gsf_property_settings_find:
793  * @name:
794  * @params: (array length=n_params):
795  * @n_params:
796  */
797 const GParameter *
gsf_property_settings_find(const char * name,const GParameter * params,size_t n_params)798 gsf_property_settings_find (const char *name,
799 			    const GParameter *params,
800 			    size_t n_params)
801 {
802 	size_t i;
803 
804 	for (i = 0; i < n_params; i++)
805 		if (g_str_equal (name, params[i].name))
806 			return params + i;
807 
808 	return NULL;
809 }
810 
811 /**
812  * gsf_property_settings_free:
813  * @params: (array length=n_params) (transfer full):
814  * @n_params:
815  */
816 void
gsf_property_settings_free(GParameter * params,size_t n_params)817 gsf_property_settings_free (GParameter *params,
818 			    size_t n_params)
819 {
820 	while (n_params--)
821 		g_value_unset (&params[n_params].value);
822 	g_free (params);
823 }
824 G_GNUC_END_IGNORE_DEPRECATIONS
825 
826 
827 
828 /* Errors */
829 
830 /**
831  * gsf_error_quark:
832  *
833  * Returns:  the #GQuark used to identify libgsf errors in #GError structures.
834  * 	Specific error codes come from the #GsfError enumeration.
835  **/
836 GQuark
gsf_error_quark(void)837 gsf_error_quark (void)
838 {
839 	static GQuark quark;
840 
841 	if (quark == 0)
842 		quark = g_quark_from_static_string ("gsf-error-quark");
843 
844 	return quark;
845 }
846