1 /* logjam - a GTK client for LiveJournal.
2 * Copyright (C) 2000-2003 Evan Martin <evan@livejournal.com>
7 #include <libxml/parser.h>
8 #include <libxml/tree.h>
16 #define xmlGetString jam_xmlGetString
17 #define xmlAddTN(node, name, value) xmlNewTextChild(node, NULL, BAD_CAST name, BAD_CAST value)
20 GSList
*conf_parsedirlist (const char *base
, void *(*fn
) (const char *, void *), void *arg
) {
26 dir
= g_dir_open(base
, 0, NULL
);
27 if (!dir
) return NULL
;
28 dirname
= g_dir_read_name(dir
);
30 path
= g_build_filename(base
, dirname
, NULL
);
32 if (data
) list
= g_slist_append(list
, data
);
34 dirname
= g_dir_read_name(dir
);
41 void *conf_parsedirxml (const char *dirname
, void *(*fn
) (xmlDocPtr
, xmlNodePtr
, void *), void *data
) {
46 path
= g_build_filename(dirname
, "conf.xml", NULL
);
47 if (!g_file_test(path
, G_FILE_TEST_EXISTS
)) {
51 doc
= xmlParseFile(path
);
54 fprintf(stderr
, _("error parsing configuration file.\n"));
57 /* we get the root element instead of the doc's first child
58 * because XML allows comments outside of the root element. */
59 node
= xmlDocGetRootElement(doc
);
61 fprintf(stderr
, _("empty document.\n"));
65 ret
= fn(doc
, node
, data
);
71 /* we use a bunch of macro magic to make this simpler.
75 /* this should match the enum in conf.h */
76 static const char *geometry_names
[] = {
89 static void parsegeometry (Geometry
*geom
, xmlDocPtr doc
, xmlNodePtr node
) {
90 for (node
= node
->xmlChildrenNode
; node
!= NULL
; node
= node
->next
) {
91 XML_GET_INT("x", geom
->x
)
92 XML_GET_INT("y", geom
->y
)
93 XML_GET_INT("width", geom
->width
)
94 XML_GET_INT("height", geom
->height
)
95 XML_GET_INT("panedpos", geom
->panedpos
)
96 XML_GET_END("parsegeometry")
101 static void parsegeometries (Configuration
*c
, xmlDocPtr doc
, xmlNodePtr node
) {
102 for (node
= node
->xmlChildrenNode
; node
!= NULL
; node
= node
->next
) {
103 if (xmlStrcmp(node
->name
, BAD_CAST
"geometry") == 0) {
105 xmlChar
*window
= xmlGetProp(node
, BAD_CAST
"window");
106 if (!window
) continue;
107 for (i
= 0; i
< GEOM_COUNT
; i
++) {
108 if (g_ascii_strcasecmp((char *)window
, geometry_names
[i
]) == 0) {
109 parsegeometry(&c
->geometries
[i
], doc
, node
);
119 static void *parsehostdir (const char *dirname
, void *data
) {
120 return conf_parsedirxml(dirname
, (conf_parsedirxml_fn
) jam_host_from_xml
, (void *)dirname
);
124 static GSList
*parsehostsdir (char *base
) {
125 return conf_parsedirlist(base
, parsehostdir
, NULL
);
130 static void parseshowmeta (Options
*options
, xmlDocPtr doc
, xmlNodePtr node
) {
132 for (node
= node
->xmlChildrenNode
; node
!= NULL
; node
= node
->next
) {
133 if (jam_view_meta_from_name((char *)node
->name
, &meta
)) options
->showmeta
[meta
] = TRUE
;
136 #endif /* HAVE_GTK */
139 static void parseoptions (Configuration
*c
, xmlDocPtr doc
, xmlNodePtr node
) {
140 Options
*options
= &c
->options
;
141 #define READOPTION(x) XML_GET_BOOL(#x, options->x)
142 for (node
= node
->xmlChildrenNode
; node
!= NULL
; node
= node
->next
) {
146 READOPTION(useproxyauth
)
148 # ifdef HAVE_GTKSPELL
149 READOPTION(usespellcheck
)
151 READOPTION(revertusejournal
)
153 READOPTION(cfautostart
)
154 READOPTION(cfusemask
)
157 READOPTION(cffloatraise
)
158 READOPTION(friends_hidestats
)
159 READOPTION(allowmultipleinstances
)
160 READOPTION(smartquotes
)
161 READOPTION(smartquotes_russian
)
162 XML_GET_IF("showmeta", parseshowmeta(options
, doc
, node
);)
163 /* backward compatibility. */
164 XML_GET_BOOL("cfautofloat", options
->cffloat
)
165 XML_GET_BOOL("cfautofloatraise", options
->cffloatraise
)
166 #endif /* HAVE_GTK */
167 XML_GET_END("parseoptions")
172 static void parsesecurity (Configuration
*c
, xmlDocPtr doc
, xmlNodePtr node
) {
174 typestr
= xmlGetProp(node
, BAD_CAST
"type");
175 if (!typestr
) return;
176 lj_security_from_strings(&c
->defaultsecurity
, (char *)typestr
, NULL
);
182 static GSList
*parsequietdlgs (xmlDocPtr doc
, xmlNodePtr node
) {
183 GSList
*quiet_dlgs
= NULL
;
184 for (node
= node
->xmlChildrenNode
; node
!= NULL
; node
= node
->next
) {
185 XML_GET_LIST("quiet_dlg", quiet_dlgs
, xmlGetString
)
186 XML_GET_END("parsequietdlgs")
190 #endif /* HAVE_GTK */
193 static void parseproxyauth (Configuration
*c
, xmlDocPtr doc
, xmlNodePtr node
) {
194 for (node
= node
->xmlChildrenNode
; node
!= NULL
; node
= node
->next
) {
195 XML_GET_STR("username", c
->proxyuser
)
196 XML_GET_STR("password", c
->proxypass
)
197 XML_GET_END("parseproxyauth")
202 static void *parseconf (xmlDocPtr doc
, xmlNodePtr node
, void *data
) {
203 char *hostname
= NULL
;
205 Configuration
*c
= data
;
206 #define XML_GET_CONF(key, func) XML_GET_IF(key, func(c, doc, node);)
207 node
= node
->xmlChildrenNode
;
208 for (; node
!= NULL
; node
= node
->next
) {
209 XML_GET_STR("currentserver", hostname
)
210 XML_GET_CONF("geometries", parsegeometries
)
211 XML_GET_CONF("options", parseoptions
)
212 XML_GET_CONF("defaultsecurity", parsesecurity
)
213 XML_GET_STR("uifont", c
->uifont
)
214 # ifdef HAVE_GTKSPELL
215 XML_GET_STR("spell_language", c
->spell_language
)
216 # endif /* HAVE_GTKSPELL */
217 XML_GET_STR("proxy", c
->proxy
)
218 XML_GET_CONF("proxyauth", parseproxyauth
)
219 XML_GET_STR("spawncommand", c
->spawn_command
)
220 XML_GET_STR("musiccommand", c
->music_command
)
221 XML_GET_INT("cfuserinterval", c
->cfuserinterval
)
222 XML_GET_INT("cfthreshold", c
->cfthreshold
)
224 XML_GET_FUNC("quiet_dlgs", app
.quiet_dlgs
, parsequietdlgs
)
226 XML_GET_END("conf_xml_read")
229 if (!c
->spell_language
|| strlen(c
->spell_language
) < 2) {
230 g_free(c
->spell_language
);
231 c
->spell_language
= g_strdup("en");
233 #endif /* HAVE_GTKSPELL */
234 hostspath
= g_build_filename(app
.conf_dir
, "servers", NULL
);
235 c
->hosts
= parsehostsdir(hostspath
);
238 c
->lasthost
= conf_host_by_name(c
, hostname
);
245 int conf_read (Configuration
*c
, char *path
) {
246 conf_parsedirxml(path
, parseconf
, c
);
251 static void writegeometry (Geometry
*geometry
, const char *name
, xmlNodePtr node
) {
252 node
= xmlNewChild(node
, NULL
, BAD_CAST
"geometry", NULL
);
253 xmlSetProp(node
, BAD_CAST
"window", BAD_CAST name
);
254 jam_xmlAddInt(node
, "x", geometry
->x
);
255 jam_xmlAddInt(node
, "y", geometry
->y
);
256 jam_xmlAddInt(node
, "width", geometry
->width
);
257 jam_xmlAddInt(node
, "height", geometry
->height
);
258 if (geometry
->panedpos
> 0) jam_xmlAddInt(node
, "panedpos", geometry
->panedpos
);
263 static void writeshowmeta (Options
*options
, xmlNodePtr node
) {
265 xmlNodePtr showmeta
= xmlNewChild(node
, NULL
, BAD_CAST
"showmeta", NULL
);
266 for (i
= JAM_VIEW_META_FIRST
; i
<= JAM_VIEW_META_LAST
; i
++) {
267 if (options
->showmeta
[i
]) xmlNewChild(showmeta
, NULL
, BAD_CAST
jam_view_meta_to_name(i
), NULL
);
270 #endif /* HAVE_GTK */
273 static void writeoptions (Options
*options
, xmlNodePtr node
) {
274 #define WRITEOPTION(x) if (options->x) xmlNewChild(node, NULL, BAD_CAST #x, NULL);
275 WRITEOPTION(netdump
);
277 WRITEOPTION(useproxy
);
278 WRITEOPTION(useproxyauth
);
281 WRITEOPTION(usespellcheck
);
283 WRITEOPTION(revertusejournal
);
284 WRITEOPTION(autosave
);
285 WRITEOPTION(cfautostart
);
286 WRITEOPTION(cfusemask
);
287 WRITEOPTION(docklet
);
288 WRITEOPTION(cffloatraise
);
289 WRITEOPTION(cffloat
);
290 WRITEOPTION(friends_hidestats
);
291 WRITEOPTION(allowmultipleinstances
);
292 WRITEOPTION(smartquotes
);
293 WRITEOPTION(smartquotes_russian
);
295 writeshowmeta(options
, node
);
296 #endif /* HAVE_GTK */
300 int conf_write (Configuration
*c
, char *base
) {
303 xmlNodePtr root
, node
;
307 jam_xmlNewDoc(&doc
, &root
, "configuration");
308 xmlSetProp(root
, BAD_CAST
"version", BAD_CAST
"1");
309 for (l
= c
->hosts
; l
!= NULL
; l
= l
->next
) {
310 if (!jam_host_write(l
->data
, &err
)) {
311 g_printerr("%s\n", err
->message
);
316 if (c
->lasthost
) xmlAddTN(root
, "currentserver", c
->lasthost
->name
);
317 node
= xmlNewChild(root
, NULL
, BAD_CAST
"geometries", NULL
);
318 for (i
= 0; i
< GEOM_COUNT
; i
++) {
319 if (c
->geometries
[i
].width
> 0) {
320 writegeometry(&c
->geometries
[i
], geometry_names
[i
], node
);
323 node
= xmlNewChild(root
, NULL
, BAD_CAST
"options", NULL
);
324 writeoptions(&c
->options
, node
);
325 if (c
->uifont
) xmlAddTN(root
, "uifont", c
->uifont
);
327 if (c
->spell_language
)
328 xmlAddTN(root
, "spell_language", c
->spell_language
);
330 if (c
->proxy
) xmlAddTN(root
, "proxy", c
->proxy
);
332 node
= xmlNewChild(root
, NULL
, BAD_CAST
"proxyauth", NULL
);
333 xmlAddTN(node
, "username", c
->proxyuser
);
334 xmlAddTN(node
, "password", c
->proxypass
);
336 if (c
->spawn_command
) xmlAddTN(root
, "spawncommand", c
->spawn_command
);
337 if (c
->music_command
) xmlAddTN(root
, "musiccommand", c
->music_command
);
338 if (c
->cfuserinterval
) {
340 g_snprintf(buf
, 20, "%d", c
->cfuserinterval
);
341 xmlAddTN(root
, "cfuserinterval", buf
);
343 if (c
->cfthreshold
) {
345 g_snprintf(buf
, 20, "%d", c
->cfthreshold
);
346 xmlAddTN(root
, "cfthreshold", buf
);
349 if (app
.quiet_dlgs
) {
350 xmlNodePtr xmlList
= xmlNewChild(root
, NULL
, BAD_CAST
"quiet_dlgs", NULL
);
351 for (l
= app
.quiet_dlgs
; l
!= NULL
; l
= l
->next
) {
352 xmlAddTN(xmlList
, "quiet_dlg", (char *)l
->data
);
355 #endif /* HAVE_GTK */
356 if (c
->defaultsecurity
.type
!= LJ_SECURITY_PUBLIC
) {
358 if (c
->defaultsecurity
.type
== LJ_SECURITY_CUSTOM
) c
->defaultsecurity
.type
= LJ_SECURITY_PRIVATE
;
359 lj_security_to_strings(&c
->defaultsecurity
, &type
, NULL
);
361 node
= xmlNewChild(root
, NULL
, BAD_CAST
"defaultsecurity", NULL
);
362 xmlSetProp(node
, BAD_CAST
"type", BAD_CAST type
);
366 path
= g_build_filename(base
, "conf.xml", NULL
);
367 if (xmlSaveFormatFile(path
, doc
, TRUE
) < 0) {
368 g_printerr("xmlSaveFormatFile error saving to %s.\n", path
);