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:
26 * <property name="first-name" value="Axle" >/
27 * <property name="last-name" value="Rose" >/
30 * ***********************************************************************
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"
55 XmlProperty
*xmlprops_create( void ) {
58 props
= g_new0( XmlProperty
, 1 );
60 props
->encoding
= NULL
;
61 props
->propertyTable
= g_hash_table_new( g_str_hash
, g_str_equal
);
62 props
->retVal
= MGU_SUCCESS
;
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
) {
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
);
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
);
115 props
->encoding
= NULL
;
116 props
->propertyTable
= NULL
;
122 static void xmlprops_write_elem_s( FILE *fp
, gint lvl
, gchar
*name
) {
124 for( i
= 0; i
< lvl
; i
++ ) fputs( " ", fp
);
129 static void xmlprops_write_elem_e( FILE *fp
, gint lvl
, gchar
*name
) {
131 for( i
= 0; i
< lvl
; i
++ ) fputs( " ", fp
);
137 static void xmlprops_write_attr( FILE *fp
, gchar
*name
, gchar
*value
) {
141 xml_file_put_escape_str( fp
, value
);
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
) {
158 props
->retVal
= MGU_OPEN_FILE
;
159 pfile
= prefs_write_open( fileSpec
);
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
);
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
)
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
) {
231 gchar pName
[ ATTR_BUFSIZE
];
232 gchar pValue
[ ATTR_BUFSIZE
];
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
);
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
);
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
);
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
;
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
)
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
);
305 key
= g_strdup( name
);
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
)
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
);
341 xmlprops_set_property( props
, name
, "y" );
344 xmlprops_set_property( props
, name
, "n" );
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
) {
358 g_return_val_if_fail( props
!= NULL
, value
);
359 val
= g_hash_table_lookup( props
->propertyTable
, name
);
361 value
= g_strdup( val
);
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
) {
376 g_return_if_fail( props
!= NULL
);
377 if( buffer
== NULL
) return;
378 val
= g_hash_table_lookup( props
->propertyTable
, name
);
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
) {
396 g_return_val_if_fail( props
!= NULL
, value
);
397 val
= g_hash_table_lookup( props
->propertyTable
, name
);
400 value
= strtol( val
, &endptr
, 10 );
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
) {
416 g_return_val_if_fail( props
!= NULL
, value
);
417 val
= g_hash_table_lookup( props
->propertyTable
, name
);
419 value
= ( g_ascii_strcasecmp( val
, "y" ) == 0 );