2007-10-01 [colin] 3.0.1cvs2-stable
[claws.git] / src / common / xmlprops.c
blob149e88570be188c8230c8b58e80b6a88e41e2c10
1 /*
2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 2002-2007 Match Grun and the Claws Mail team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 * General functions for saving properties to an XML file.
23 * The file is structured as follows:
25 * <property-list>
26 * <property name="first-name" value="Axle" >/
27 * <property name="last-name" value="Rose" >/
28 * </property-list>
30 * ***********************************************************************
34 #include <glib.h>
35 #include <stdio.h>
36 #include <string.h>
37 #include <stdlib.h>
39 #include "prefs.h"
40 #include "xml.h"
41 #include "mgutils.h"
42 #include "xmlprops.h"
44 /* Element tag names */
45 #define XMLS_ELTAG_PROP_LIST "property-list"
46 #define XMLS_ELTAG_PROPERTY "property"
48 /* Attribute tag names */
49 #define XMLS_ATTAG_NAME "name"
50 #define XMLS_ATTAG_VALUE "value"
53 * Create new props.
55 XmlProperty *xmlprops_create( void ) {
56 XmlProperty *props;
58 props = g_new0( XmlProperty, 1 );
59 props->path = NULL;
60 props->encoding = NULL;
61 props->propertyTable = g_hash_table_new( g_str_hash, g_str_equal );
62 props->retVal = MGU_SUCCESS;
63 return props;
67 * Properties - file path.
69 void xmlprops_set_path( XmlProperty *props, const gchar *value ) {
70 g_return_if_fail( props != NULL );
71 props->path = mgu_replace_string( props->path, value );
73 void xmlprops_set_encoding( XmlProperty *props, const gchar *value ) {
74 g_return_if_fail( props != NULL );
75 props->encoding = mgu_replace_string( props->encoding, value );
79 * Free hash table visitor function.
81 static gint xmlprops_free_entry_vis( gpointer key, gpointer value, gpointer data ) {
82 g_free( key );
83 g_free( value );
84 key = NULL;
85 value = NULL;
86 return TRUE;
90 * Clear all properties.
91 * Enter: props Property object.
93 void xmlprops_clear( XmlProperty *props ) {
94 g_return_if_fail( props != NULL );
95 g_hash_table_foreach_remove(
96 props->propertyTable, xmlprops_free_entry_vis, NULL );
100 * Free props.
101 * Enter: props Property object.
103 void xmlprops_free( XmlProperty *props ) {
104 g_return_if_fail( props != NULL );
106 /* Clear property table */
107 xmlprops_clear( props );
108 g_hash_table_destroy( props->propertyTable );
110 /* Free up internal objects */
111 g_free( props->path );
112 g_free( props->encoding );
114 props->path = NULL;
115 props->encoding = NULL;
116 props->propertyTable = NULL;
117 props->retVal = 0;
119 g_free( props );
122 static void xmlprops_write_elem_s( FILE *fp, gint lvl, gchar *name ) {
123 gint i;
124 for( i = 0; i < lvl; i++ ) fputs( " ", fp );
125 fputs( "<", fp );
126 fputs( name, fp );
129 static void xmlprops_write_elem_e( FILE *fp, gint lvl, gchar *name ) {
130 gint i;
131 for( i = 0; i < lvl; i++ ) fputs( " ", fp );
132 fputs( "</", fp );
133 fputs( name, fp );
134 fputs( ">\n", fp );
137 static void xmlprops_write_attr( FILE *fp, gchar *name, gchar *value ) {
138 fputs( " ", fp );
139 fputs( name, fp );
140 fputs( "=\"", fp );
141 xml_file_put_escape_str( fp, value );
142 fputs( "\"", fp );
145 static void xmlprops_write_vis( gpointer key, gpointer value, gpointer data ) {
146 FILE *fp = ( FILE * ) data;
148 xmlprops_write_elem_s( fp, 1, XMLS_ELTAG_PROPERTY );
149 xmlprops_write_attr( fp, XMLS_ATTAG_NAME, key );
150 xmlprops_write_attr( fp, XMLS_ATTAG_VALUE, value );
151 fputs( " />\n", fp );
154 static gint xmlprops_write_to( XmlProperty *props, const gchar *fileSpec ) {
155 PrefFile *pfile;
156 FILE *fp;
158 props->retVal = MGU_OPEN_FILE;
159 pfile = prefs_write_open( fileSpec );
160 if( pfile ) {
161 fp = pfile->fp;
162 fprintf( fp, "<?xml version=\"1.0\"" );
163 if( props->encoding && *props->encoding ) {
164 fprintf( fp, " encoding=\"%s\"", props->encoding );
166 fprintf( fp, " ?>\n" );
167 xmlprops_write_elem_s( fp, 0, XMLS_ELTAG_PROP_LIST );
168 fputs( ">\n", fp );
170 /* Output all properties */
171 g_hash_table_foreach( props->propertyTable, xmlprops_write_vis, fp );
173 xmlprops_write_elem_e( fp, 0, XMLS_ELTAG_PROP_LIST );
174 props->retVal = MGU_SUCCESS;
175 if( prefs_file_close( pfile ) < 0 ) {
176 props->retVal = MGU_ERROR_WRITE;
180 return props->retVal;
184 * Save properties to file.
185 * return: Status code.
187 gint xmlprops_save_file( XmlProperty *props ) {
188 g_return_val_if_fail( props != NULL, -1 );
190 props->retVal = MGU_NO_FILE;
191 if( props->path == NULL || *props->path == '\0' ) return props->retVal;
192 xmlprops_write_to( props, props->path );
194 if( props->retVal == MGU_SUCCESS ) {
197 return props->retVal;
200 static void xmlprops_print_vis( gpointer key, gpointer value, gpointer data ) {
201 FILE *stream = ( FILE * ) data;
203 fprintf( stream, "-\tname/value:\t%s / %s\n", (char *)key, (char *)value );
206 void xmlprops_print( XmlProperty *props, FILE *stream ) {
207 fprintf( stream, "Property File: %s\n", props->path );
208 g_hash_table_foreach( props->propertyTable, xmlprops_print_vis, stream );
209 fprintf( stream, "---\n" );
212 static void xmlprops_save_property(
213 XmlProperty *props, const gchar *name, const gchar *value )
215 gchar *key;
216 gchar *val;
218 if( strlen( name ) == 0 ) return;
219 if( strlen( value ) == 0 ) return;
220 if( g_hash_table_lookup( props->propertyTable, name ) ) return;
221 key = g_strdup( name );
222 val = g_strdup( value );
223 g_hash_table_insert( props->propertyTable, key, val );
226 #define ATTR_BUFSIZE 256
228 static void xmlprops_read_props( XmlProperty *props, XMLFile *file ) {
229 GList *attr;
230 gchar *name, *value;
231 gchar pName[ ATTR_BUFSIZE ];
232 gchar pValue[ ATTR_BUFSIZE ];
234 while( TRUE ) {
235 *pName = '\0';
236 *pValue = '\0';
237 if (! file->level ) break;
238 xml_parse_next_tag( file );
239 xml_get_current_tag( file );
240 if( xml_compare_tag( file, XMLS_ELTAG_PROPERTY ) ) {
241 attr = xml_get_current_tag_attr( file );
242 while( attr ) {
243 name = ( ( XMLAttr * ) attr->data )->name;
244 value = ( ( XMLAttr * ) attr->data )->value;
245 if( strcmp( name, XMLS_ATTAG_NAME ) == 0 ) {
246 strcpy( pName, value );
248 else if( strcmp( name, XMLS_ATTAG_VALUE ) == 0 ) {
249 strcpy( pValue, value );
251 attr = g_list_next( attr );
253 xmlprops_save_property( props, pName, pValue );
258 #undef ATTR_BUFSIZE
261 * Load properties from file.
262 * return: Status code.
264 gint xmlprops_load_file( XmlProperty *props ) {
265 XMLFile *file = NULL;
267 g_return_val_if_fail( props != NULL, -1 );
268 props->retVal = MGU_NO_FILE;
269 file = xml_open_file( props->path );
270 if( file == NULL ) {
271 return props->retVal;
274 props->retVal = MGU_BAD_FORMAT;
275 if( xml_get_dtd( file ) == 0 ) {
276 if( xml_parse_next_tag( file ) == 0 ) {
277 if( xml_compare_tag( file, XMLS_ELTAG_PROP_LIST ) ) {
278 xmlprops_read_props( props, file );
279 props->retVal = MGU_SUCCESS;
283 xml_close_file( file );
285 return props->retVal;
289 * Set property.
290 * Enter: props Property object.
291 * name Property name.
292 * value New value to save.
294 void xmlprops_set_property(
295 XmlProperty *props, const gchar *name, const gchar *value )
297 gchar *key = NULL;
298 gchar *val;
300 g_return_if_fail( props != NULL );
301 if( name == NULL || strlen( name ) == 0 ) return;
302 if( value == NULL || strlen( value ) == 0 ) return;
303 val = g_hash_table_lookup( props->propertyTable, name );
304 if( val == NULL ) {
305 key = g_strdup( name );
307 else {
308 g_free( val );
310 val = g_strdup( value );
311 g_hash_table_insert( props->propertyTable, key, val );
315 * Set property to integer value.
316 * Enter: props Property object.
317 * name Property name.
318 * value New value to save.
320 void xmlprops_set_property_i(
321 XmlProperty *props, const gchar *name, const gint value )
323 gchar buf[32];
325 g_return_if_fail( props != NULL );
326 sprintf( buf, "%d", value );
327 xmlprops_set_property( props, name, buf );
331 * Set property to boolean value.
332 * Enter: props Property object.
333 * name Property name.
334 * value New value to save.
336 void xmlprops_set_property_b(
337 XmlProperty *props, const gchar *name, const gboolean value )
339 g_return_if_fail( props != NULL );
340 if( value ) {
341 xmlprops_set_property( props, name, "y" );
343 else {
344 xmlprops_set_property( props, name, "n" );
349 * Get property.
350 * Enter: props Property object.
351 * name Property name.
352 * Return: value found, or NULL if none. Should be g_free() when done.
354 gchar *xmlprops_get_property( XmlProperty *props, const gchar *name ) {
355 gchar *val, *value;
357 value = NULL;
358 g_return_val_if_fail( props != NULL, value );
359 val = g_hash_table_lookup( props->propertyTable, name );
360 if( val ) {
361 value = g_strdup( val );
363 return value;
367 * Get property into a buffer.
368 * Enter: props Property object.
369 * name Property name.
370 * Return: value found, or NULL if none. Should be g_free() when done.
372 void xmlprops_get_property_s(
373 XmlProperty *props, const gchar *name, gchar *buffer ) {
374 gchar *val;
376 g_return_if_fail( props != NULL );
377 if( buffer == NULL ) return;
378 val = g_hash_table_lookup( props->propertyTable, name );
379 if( val ) {
380 strcpy( buffer, val );
385 * Get property as integer value.
386 * Enter: props Property object.
387 * name Property name.
388 * Return: value found, or zero if not found.
390 gint xmlprops_get_property_i( XmlProperty *props, const gchar *name ) {
391 gchar *val;
392 gchar *endptr;
393 gint value;
395 value = 0;
396 g_return_val_if_fail( props != NULL, value );
397 val = g_hash_table_lookup( props->propertyTable, name );
398 if( val ) {
399 endptr = NULL;
400 value = strtol( val, &endptr, 10 );
402 return value;
406 * Get property as boolean value.
407 * Enter: props Property object.
408 * name Property name.
409 * Return: value found, or FALSE if not found.
411 gboolean xmlprops_get_property_b( XmlProperty *props, const gchar *name ) {
412 gchar *val;
413 gboolean value;
415 value = FALSE;
416 g_return_val_if_fail( props != NULL, value );
417 val = g_hash_table_lookup( props->propertyTable, name );
418 if( val ) {
419 value = ( g_ascii_strcasecmp( val, "y" ) == 0 );
421 return value;
425 * End of Source.