respect https prefix
[k8lowj.git] / src / conf_xml.c
blob25dc4386e92e919fd10d96603df33e696051b9d4
1 /* logjam - a GTK client for LiveJournal.
2 * Copyright (C) 2000-2003 Evan Martin <evan@livejournal.com>
3 */
4 #include <stdlib.h>
5 #include <string.h>
7 #include <libxml/parser.h>
8 #include <libxml/tree.h>
10 #include "glib-all.h"
12 #include "conf.h"
13 #include "conf_xml.h"
14 #include "jam_xml.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) {
21 GSList *list = NULL;
22 GDir *dir;
23 const char *dirname;
24 char *path;
25 void *data;
26 dir = g_dir_open(base, 0, NULL);
27 if (!dir) return NULL;
28 dirname = g_dir_read_name(dir);
29 while (dirname) {
30 path = g_build_filename(base, dirname, NULL);
31 data = fn(path, arg);
32 if (data) list = g_slist_append(list, data);
33 g_free(path);
34 dirname = g_dir_read_name(dir);
36 g_dir_close(dir);
37 return list;
41 void *conf_parsedirxml (const char *dirname, void *(*fn) (xmlDocPtr, xmlNodePtr, void *), void *data) {
42 xmlDocPtr doc;
43 xmlNodePtr node;
44 void *ret;
45 char *path;
46 path = g_build_filename(dirname, "conf.xml", NULL);
47 if (!g_file_test(path, G_FILE_TEST_EXISTS)) {
48 g_free(path);
49 return NULL;
51 doc = xmlParseFile(path);
52 g_free(path);
53 if (doc == NULL) {
54 fprintf(stderr, _("error parsing configuration file.\n"));
55 return NULL;
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);
60 if (node == NULL) {
61 fprintf(stderr, _("empty document.\n"));
62 xmlFreeDoc(doc);
63 return NULL;
65 ret = fn(doc, node, data);
66 xmlFreeDoc(doc);
67 return ret;
71 /* we use a bunch of macro magic to make this simpler.
72 * (see xml_macros.h)
75 /* this should match the enum in conf.h */
76 static const char *geometry_names[] = {
77 "main",
78 "login",
79 "friends",
80 "friendgroups",
81 "console",
82 "manager",
83 "cffloat",
84 "offline",
85 "preview"
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) {
104 int i;
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);
110 break;
113 xmlFree(window);
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);
129 #ifdef HAVE_GTK
130 static void parseshowmeta (Options *options, xmlDocPtr doc, xmlNodePtr node) {
131 JamViewMeta meta;
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) {
143 READOPTION(netdump)
144 READOPTION(nofork)
145 READOPTION(useproxy)
146 READOPTION(useproxyauth)
147 #ifdef HAVE_GTK
148 # ifdef HAVE_GTKSPELL
149 READOPTION(usespellcheck)
150 # endif
151 READOPTION(revertusejournal)
152 READOPTION(autosave)
153 READOPTION(cfautostart)
154 READOPTION(cfusemask)
155 READOPTION(docklet)
156 READOPTION(cffloat)
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) {
173 xmlChar *typestr;
174 typestr = xmlGetProp(node, BAD_CAST "type");
175 if (!typestr) return;
176 lj_security_from_strings(&c->defaultsecurity, (char *)typestr, NULL);
177 xmlFree(typestr);
181 #ifdef HAVE_GTK
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")
188 return quiet_dlgs;
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;
204 char *hostspath;
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)
223 # ifdef HAVE_GTK
224 XML_GET_FUNC("quiet_dlgs", app.quiet_dlgs, parsequietdlgs)
225 # endif
226 XML_GET_END("conf_xml_read")
228 #ifdef HAVE_GTKSPELL
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);
236 g_free(hostspath);
237 if (hostname) {
238 c->lasthost = conf_host_by_name(c, hostname);
239 g_free(hostname);
241 return NULL;
245 int conf_read (Configuration *c, char *path) {
246 conf_parsedirxml(path, parseconf, c);
247 return 0;
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);
262 #ifdef HAVE_GTK
263 static void writeshowmeta (Options *options, xmlNodePtr node) {
264 int i;
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);
276 WRITEOPTION(nofork);
277 WRITEOPTION(useproxy);
278 WRITEOPTION(useproxyauth);
279 #ifdef HAVE_GTK
280 #ifdef HAVE_GTKSPELL
281 WRITEOPTION(usespellcheck);
282 #endif
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) {
301 GError *err = NULL;
302 xmlDocPtr doc;
303 xmlNodePtr root, node;
304 GSList *l;
305 int i;
306 char *path;
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);
312 g_error_free(err);
313 err = NULL;
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);
326 #ifdef HAVE_GTKSPELL
327 if (c->spell_language)
328 xmlAddTN(root, "spell_language", c->spell_language);
329 #endif
330 if (c->proxy) xmlAddTN(root, "proxy", c->proxy);
331 if (c->proxyuser) {
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) {
339 char buf[20];
340 g_snprintf(buf, 20, "%d", c->cfuserinterval);
341 xmlAddTN(root, "cfuserinterval", buf);
343 if (c->cfthreshold) {
344 char buf[20];
345 g_snprintf(buf, 20, "%d", c->cfthreshold);
346 xmlAddTN(root, "cfthreshold", buf);
348 #ifdef HAVE_GTK
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) {
357 char *type = NULL;
358 if (c->defaultsecurity.type == LJ_SECURITY_CUSTOM) c->defaultsecurity.type = LJ_SECURITY_PRIVATE;
359 lj_security_to_strings(&c->defaultsecurity, &type, NULL);
360 if (type) {
361 node = xmlNewChild(root, NULL, BAD_CAST "defaultsecurity", NULL);
362 xmlSetProp(node, BAD_CAST "type", BAD_CAST type);
363 g_free(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);
370 xmlFreeDoc(doc);
371 g_free(path);
372 return 0;