1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
4 * Copyright (C) John Stebbins 2008-2015 <stebbins@stebbins>
6 * appcast.c is free software.
8 * You may redistribute it and/or modify it under the terms of the
9 * GNU General Public License, as published by the Free Software
10 * Foundation; either version 2 of the License, or (at your option)
17 #include <glib/gstdio.h>
35 static tag_map_t tag_map
[] =
37 {"sparkle:releaseNotesLink", A_DESCRIPTION
},
38 {"enclosure", A_ENCLOSURE
},
41 #define TAG_MAP_SZ (sizeof(tag_map)/sizeof(tag_map_t))
58 const gchar
**attr_names
,
59 const gchar
**attr_values
)
63 if (attr_names
== NULL
) return NULL
;
64 for (ii
= 0; attr_names
[ii
] != NULL
; ii
++)
66 if (strcmp(name
, attr_names
[ii
]) == 0)
67 return attr_values
[ii
];
74 GMarkupParseContext
*ctx
,
76 const gchar
**attr_names
,
77 const gchar
**attr_values
,
81 parse_data_t
*pd
= (parse_data_t
*)ud
;
89 for (ii
= 0; ii
< TAG_MAP_SZ
; ii
++)
91 if (strcmp(tag
, tag_map
[ii
].tag
) == 0)
93 id
.id
= tag_map
[ii
].id
;
99 g_debug("Unrecognized start tag (%s)", tag
);
102 g_queue_push_head(pd
->tag_stack
, id
.pid
);
111 const gchar
*build
, *version
;
112 build
= lookup_attr_value(
113 "sparkle:version", attr_names
, attr_values
);
114 version
= lookup_attr_value(
115 "sparkle:shortVersionString", attr_names
, attr_values
);
117 pd
->build
= g_strdup(build
);
119 pd
->version
= g_strdup(version
);
126 GMarkupParseContext
*ctx
,
131 parse_data_t
*pd
= (parse_data_t
*)ud
;
140 for (ii
= 0; ii
< TAG_MAP_SZ
; ii
++)
142 if (strcmp(tag
, tag_map
[ii
].tag
) == 0)
148 if (ii
== TAG_MAP_SZ
)
150 g_debug("Unrecognized end tag (%s)", tag
);
153 start_id
.pid
= g_queue_pop_head(pd
->tag_stack
);
154 if (start_id
.id
!= id
)
155 g_warning("start tag != end tag: (%s %d) %d", tag
, start_id
.id
, id
);
171 GMarkupParseContext
*ctx
,
177 parse_data_t
*pd
= (parse_data_t
*)ud
;
184 start_id
.pid
= g_queue_peek_head(pd
->tag_stack
);
191 g_string_append(pd
->description
, text
);
196 if (pd
->value
) g_free(pd
->value
);
197 pd
->value
= g_strdup(text
);
204 GMarkupParseContext
*ctx
,
210 //parse_data_t *pd = (parse_data_t*)ud;
212 //g_debug("passthrough %s", text);
216 parse_error(GMarkupParseContext
*ctx
, GError
*error
, gpointer ud
)
218 g_warning("Resource parse error: %s", error
->message
);
221 // This is required or the parser crashes
223 destroy_notify(gpointer data
)
225 //g_debug("destroy parser");
229 ghb_appcast_parse(gchar
*buf
, gchar
**desc
, gchar
**build
, gchar
**version
)
231 GMarkupParseContext
*ctx
;
232 GMarkupParser parser
;
239 // Skip junk at beginning of buffer
240 start
= strstr(buf
, "<?xml ");
241 pd
.description
= g_string_new("");
246 pd
.tag_stack
= g_queue_new();
250 parser
.start_element
= start_element
;
251 parser
.end_element
= end_element
;
252 parser
.text
= text_data
;
253 parser
.passthrough
= passthrough
;
254 parser
.error
= parse_error
;
255 ctx
= g_markup_parse_context_new(
256 &parser
, G_MARKUP_TREAT_CDATA_AS_TEXT
, &pd
, destroy_notify
);
258 g_markup_parse_context_parse(ctx
, start
, len
, &err
);
259 g_markup_parse_context_end_parse(ctx
, &err
);
260 g_markup_parse_context_free(ctx
);
261 g_queue_free(pd
.tag_stack
);
262 *desc
= g_string_free(pd
.description
, FALSE
);
263 // work around a bug to leaves the CDATA closing brakets on the string
265 glitch
= g_strrstr(*desc
, "]]>");
269 *version
= pd
.version
;