Write a structure to the data file which specifies the iterations and
[pwmd.git] / src / xml.c
blob0b90f6e7f6e6053742dfb90fa192552764b388ab
1 /* vim:tw=78:ts=8:sw=4:set ft=c: */
2 /*
3 Copyright (C) 2006-2007 Ben Kibbey <bjk@luxsci.net>
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 2 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, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <unistd.h>
22 #include <err.h>
23 #include <errno.h>
24 #include <string.h>
25 #include <sys/stat.h>
26 #include <fcntl.h>
27 #include <ctype.h>
28 #include <glib.h>
29 #include <gcrypt.h>
31 #ifdef HAVE_CONFIG_H
32 #include <config.h>
33 #endif
35 #include "pwmd_error.h"
36 #include "xml.h"
38 gboolean valid_xml_element(const xmlChar *element)
40 const xmlChar *p;
42 if (!element || !*element || isdigit(*element))
43 return FALSE;
45 for (p = element; *p; p++) {
46 if (!isalnum(*p))
47 return FALSE;
50 if (xmlStrncasecmp(element, (xmlChar *)"?xml", 4) == 0)
51 return FALSE;
53 return TRUE;
56 gboolean new_account(xmlDocPtr doc, gchar *name)
58 xmlNodePtr root = xmlDocGetRootElement(doc);
59 xmlAttrPtr a;
60 xmlNodePtr n;
62 if (!name || !root)
63 return FALSE;
65 n = xmlNewNode(NULL, (xmlChar *)"account");
66 n = xmlAddChild(root, n);
67 a = xmlNewProp(n, (xmlChar *)"name", (xmlChar *)name);
68 return TRUE;
71 gchar *new_document()
73 gchar *buf;
74 const char *line =
75 "<?xml version=\"1.0\"?>\n"
76 "<!DOCTYPE accounts [\n"
77 "<!ELEMENT accounts (account*)>\n"
78 "<!ELEMENT account (username?, password?, smtp?, pop?, imap?)>\n"
79 "<!ATTLIST account name CDATA #REQUIRED>\n"
80 "<!ELEMENT username (#PCDATA)>\n"
81 "<!ELEMENT password (#PCDATA)>\n"
82 "<!ELEMENT smtp (hostname, port, ssl, sslfingerprint)>\n"
83 "<!ELEMENT pop (hostname, port, ssl, sslfingerprint)>\n"
84 "<!ELEMENT imap (hostname, port, ssl, sslfingerprint)>\n"
85 "<!ELEMENT hostname (#PCDATA)>\n"
86 "<!ELEMENT port (#PCDATA)>\n"
87 "<!ELEMENT ssl (#PCDATA)>\n"
88 "<!ELEMENT sslfingerprint (#PCDATA)>\n"
89 "]>\n"
90 "<accounts/>";
92 if ((buf = gcry_malloc(strlen(line) + 1)) == NULL)
93 return NULL;
95 strcpy(buf, line);
96 return buf;
99 gboolean list_accounts(xmlTextReaderPtr reader, gchar **dst, gint *pwmd_errno)
101 xmlNodePtr n;
102 gchar *line = NULL;
103 gchar **str = NULL;
104 gint i = 0;
107 * "fast forward" to the first account.
109 while (xmlTextReaderRead(reader) == 1) {
110 if ((n = xmlTextReaderCurrentNode(reader)) == NULL) {
111 *pwmd_errno = EPWMD_LIBXML_ERROR;
112 return FALSE;
115 if (xmlTextReaderDepth(reader) == 1 &&
116 xmlStrcmp(n->name, (xmlChar *)"account") == 0 &&
117 xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT) {
118 xmlChar *p = xmlTextReaderGetAttribute(reader, (xmlChar *)"name");
120 if (!p)
121 continue;
123 str = g_realloc(str, (i + 2) * sizeof(gchar *));
124 str[i++] = g_strdup((gchar *)p);
125 str[i] = NULL;
126 xmlFree(p);
130 if (!i || !str) {
131 *pwmd_errno = EPWMD_EMPTY_ELEMENT;
132 return FALSE;
135 line = g_strjoinv("\n", str);
136 g_strfreev(str);
137 *dst = line;
138 return TRUE;
141 gboolean find_account(xmlTextReaderPtr reader, gchar *name)
143 xmlNodePtr n;
145 while (xmlTextReaderRead(reader) == 1) {
146 if ((n = xmlTextReaderCurrentNode(reader)) == NULL)
147 return FALSE;
149 if (xmlTextReaderDepth(reader) == 1 &&
150 xmlStrcmp(n->name, (xmlChar *)"account") == 0 &&
151 xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT) {
152 xmlChar *p = xmlTextReaderGetAttribute(reader, (xmlChar *)"name");
154 // Shouldn't happen (DTD).
155 if (!p)
156 continue;
158 if (xmlStrcmp(p, (xmlChar *)name) == 0) {
159 xmlFree(p);
160 return TRUE;
163 xmlFree(p);
167 return FALSE;
170 gboolean find_element(xmlTextReaderPtr reader, gchar *e, gint more)
172 xmlNodePtr n;
174 while (xmlTextReaderRead(reader) == 1) {
175 if ((n = xmlTextReaderCurrentNode(reader)) == NULL)
176 return FALSE;
179 * Stop processing after the closing account element to prevent
180 * finding element names that may exist in another account.
182 if (xmlTextReaderDepth(reader) == 1 &&
183 xmlStrcmp(n->name, (xmlChar *)"account") == 0 &&
184 xmlTextReaderNodeType(reader) == XML_READER_TYPE_END_ELEMENT)
185 return FALSE;
187 if (xmlStrcmp(n->name, (xmlChar *)e) == 0 &&
188 xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT)
189 return TRUE;
192 return FALSE;
195 xmlNodePtr find_node(xmlNodePtr root, xmlChar *name)
197 xmlNodePtr n;
199 for (n = root->children; n; n = n->next) {
200 if (g_ascii_strcasecmp((gchar *)name, (gchar *)n->name) == 0)
201 return n;
204 return NULL;
207 gint open_xml(const gchar *data, gsize size, xmlDocPtr *doc,
208 xmlTextReaderPtr *reader)
210 if ((*doc = xmlReadMemory(data, size, NULL, "UTF-8",
211 XML_PARSE_NOBLANKS)) == NULL)
212 return 1;
214 if ((*reader = xmlReaderWalker(*doc)) == NULL)
215 return 2;
217 return 0;