4 * Copyright 2017 Michael Rasmussen <mir@datanom.net>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
26 #include <libxml/parser.h>
27 #include <libxml/xpath.h>
28 #include <libxml/xpathInternals.h>
32 static gboolean debug
= FALSE
;
34 static xmlDocPtr
getdoc(const gchar
* xml
) {
36 doc
= xmlParseMemory(xml
, strlen(xml
));
39 g_warning("Document not parsed successfully.");
46 static xmlXPathObjectPtr
getnodeset(xmlDocPtr doc
, xmlChar
*xpath
, const gchar
* prefix
, const gchar
* ns_url
) {
48 xmlXPathContextPtr context
;
49 xmlXPathObjectPtr result
= NULL
;
51 context
= xmlXPathNewContext(doc
);
52 if (context
== NULL
) {
53 g_warning("Error in xmlXPathNewContext");
57 if (prefix
&& ns_url
) {
58 xmlXPathRegisterNs(context
, (xmlChar
*)prefix
, (xmlChar
*)ns_url
);
61 result
= xmlXPathEvalExpression(xpath
, context
);
62 xmlXPathFreeContext(context
);
65 g_warning("Error in xmlXPathEvalExpression");
69 if(xmlXPathNodeSetIsEmpty(result
->nodesetval
)){
70 xmlXPathFreeObject(result
);
77 xmlNodePtr
find_node_by_name(xmlNodePtr rootnode
, const xmlChar
* nodename
, GSList
** nodes
) {
78 xmlNodePtr node
= rootnode
;
84 while (node
!= NULL
) {
86 if (!xmlStrcmp(node
->name
, nodename
)) {
88 *nodes
= g_slist_append(*nodes
, (gpointer
) node
);
92 } else if (node
->children
!= NULL
) {
93 xmlNodePtr intNode
= find_node_by_name(node
->children
, nodename
, nodes
);
94 if (intNode
!= NULL
) {
96 *nodes
= g_slist_append(*nodes
, (gpointer
) node
);
108 static GSList
* find_all_nodes_by_name(xmlDocPtr doc
, const gchar
* nodename
) {
109 GSList
* nodes
= NULL
;
111 find_node_by_name(doc
->children
, (const xmlChar
*) nodename
, &nodes
);
116 void dump_node(FILE* f
, xmlDocPtr doc
, xmlNodePtr node
) {
117 g_return_if_fail(f
&& doc
&& node
);
119 xmlElemDump(f
, doc
, node
);
123 void dump_nodes(gpointer data
, gpointer user_data
) {
124 g_return_if_fail(data
&& user_data
);
126 xmlNodePtr node
= (xmlNodePtr
) data
;
127 xmlDocPtr doc
= (xmlDocPtr
) user_data
;
129 dump_node(stderr
, doc
, node
);
132 void get_props(gpointer data
, gpointer user_data
) {
133 g_return_if_fail(data
&& user_data
);
135 xmlNodePtr node
= (xmlNodePtr
) data
;
136 Calendar
* cal
= (Calendar
*) user_data
;
138 xmlChar
* comp
= xmlGetProp(node
, (const xmlChar
*)"name");
140 Component c
= string_to_component((const gchar
*) comp
);
141 cal
->components
= g_slist_append(cal
->components
, GUINT_TO_POINTER(c
));
146 GSList
* find_element(const gchar
* element
, const gchar
* xml
, const gchar
* prefix
, const gchar
* ns_url
) {
147 GSList
* elements
= NULL
;
148 xmlChar
* keyword
= NULL
;
150 g_return_val_if_fail(element
&& xml
, NULL
);
152 xmlDocPtr doc
= getdoc(xml
);
154 xmlXPathObjectPtr result
= getnodeset(doc
, xmlCharStrdup(element
), prefix
, ns_url
);
157 xmlNodeSetPtr nodeset
= result
->nodesetval
;
158 for (int i
= 0; i
< nodeset
->nodeNr
; i
++) {
159 keyword
= xmlNodeListGetString(doc
, nodeset
->nodeTab
[i
]->xmlChildrenNode
, 1);
160 elements
= g_slist_append(elements
, (gpointer
) g_strdup((gchar
*) keyword
));
163 xmlXPathFreeObject(result
);
173 GSList
* find_node(const gchar
* node
, const gchar
* xml
) {
174 GSList
* nodes
= NULL
;
175 xmlDocPtr doc
= getdoc(xml
);
178 GSList
* n
= find_all_nodes_by_name(doc
, node
);
180 for (GSList
* l
= n
; l
; l
= g_slist_next(l
)) {
181 xmlNodePtr p
= (xmlNodePtr
) l
->data
;
182 nodes
= g_slist_append(nodes
, g_strdup((gchar
*) p
->name
));
193 GSList
* find_calendars(const gchar
* host_part
, const gchar
* xml
) {
197 xmlDocPtr doc
= getdoc(xml
);
200 GSList
* n
= find_all_nodes_by_name(doc
, "response");
201 for (GSList
* l
= n
; l
; l
= g_slist_next(l
)) {
202 xmlNodePtr p
= (xmlNodePtr
) l
->data
;
204 dump_node(stderr
, doc
, p
);
205 found
= find_node_by_name(p
, (const xmlChar
*)"resourcetype", NULL
);
207 found
= find_node_by_name(found
, (const xmlChar
*)"calendar", NULL
);
210 dump_node(stderr
, doc
, p
);
211 Calendar
* cal
= g_new0(Calendar
, 1);
212 ptr
= find_node_by_name(p
, (const xmlChar
*)"href", NULL
);
214 cal
->url
= g_strconcat(host_part
, ptr
->children
->content
, NULL
);
215 ptr
= find_node_by_name(p
, (const xmlChar
*)"displayname", NULL
);
217 cal
->displayname
= g_strdup((gchar
*)ptr
->children
->content
);
218 ptr
= find_node_by_name(p
, (const xmlChar
*)"getctag", NULL
);
220 cal
->ctag
= g_strdup((gchar
*)ptr
->children
->content
);
221 ptr
= find_node_by_name(p
, (const xmlChar
*)"supported-calendar-component-set", NULL
);
223 GSList
* comps
= NULL
;
224 find_node_by_name(ptr
, (const xmlChar
*)"comp", &comps
);
225 g_slist_foreach(comps
, (GFunc
)get_props
, (gpointer
) cal
);
228 list
= g_slist_append(list
, (gpointer
) cal
);
230 calendar_dump(stderr
, cal
);
240 void set_debug_mode(gboolean mode
) {