+/* Functions for a SAX parser to parse the XML failure from Amazon */
+
+/* Private structure for our "thunk", which tracks where the user is in the list
+ * * of keys. */
+struct failure_thunk {
+ gboolean want_text;
+
+ gboolean in_title;
+ gboolean in_body;
+ gboolean in_code;
+ gboolean in_message;
+ gint in_others;
+
+ gchar *text;
+ gsize text_len;
+
+ gchar *message;
+ gchar *error_name;
+};
+
+static void
+failure_start_element(GMarkupParseContext *context G_GNUC_UNUSED,
+ const gchar *element_name,
+ const gchar **attribute_names G_GNUC_UNUSED,
+ const gchar **attribute_values G_GNUC_UNUSED,
+ gpointer user_data,
+ GError **error G_GNUC_UNUSED)
+{
+ struct failure_thunk *thunk = (struct failure_thunk *)user_data;
+
+ if (g_ascii_strcasecmp(element_name, "title") == 0) {
+ thunk->in_title = 1;
+ thunk->in_others = 0;
+ thunk->want_text = 1;
+ } else if (g_ascii_strcasecmp(element_name, "body") == 0) {
+ thunk->in_body = 1;
+ thunk->in_others = 0;
+ thunk->want_text = 1;
+ } else if (g_ascii_strcasecmp(element_name, "code") == 0) {
+ thunk->in_code = 1;
+ thunk->in_others = 0;
+ thunk->want_text = 1;
+ } else if (g_ascii_strcasecmp(element_name, "message") == 0) {
+ thunk->in_message = 1;
+ thunk->in_others = 0;
+ thunk->want_text = 1;
+ } else {
+ thunk->in_others++;
+ }
+}
+
+static void
+failure_end_element(GMarkupParseContext *context G_GNUC_UNUSED,
+ const gchar *element_name,
+ gpointer user_data,
+ GError **error G_GNUC_UNUSED)
+{
+ struct failure_thunk *thunk = (struct failure_thunk *)user_data;
+
+ if (g_ascii_strcasecmp(element_name, "title") == 0) {
+ char *p = strchr(thunk->text, ' ');
+ if (p) {
+ p++;
+ if (*p) {
+ thunk->error_name = g_strdup(p);
+ }
+ }
+ g_free(thunk->text);
+ thunk->text = NULL;
+ thunk->in_title = 0;
+ } else if (g_ascii_strcasecmp(element_name, "body") == 0) {
+ thunk->message = thunk->text;
+ g_strstrip(thunk->message);
+ thunk->text = NULL;
+ thunk->in_body = 0;
+ } else if (g_ascii_strcasecmp(element_name, "code") == 0) {
+ thunk->error_name = thunk->text;
+ thunk->text = NULL;
+ thunk->in_code = 0;
+ } else if (g_ascii_strcasecmp(element_name, "message") == 0) {
+ thunk->message = thunk->text;
+ thunk->text = NULL;
+ thunk->in_message = 0;
+ } else {
+ thunk->in_others--;
+ }
+}
+
+static void
+failure_text(GMarkupParseContext *context G_GNUC_UNUSED,
+ const gchar *text,
+ gsize text_len,
+ gpointer user_data,
+ GError **error G_GNUC_UNUSED)
+{
+ struct failure_thunk *thunk = (struct failure_thunk *)user_data;
+
+ if (thunk->want_text && thunk->in_others == 0) {
+ char *new_text;
+
+ new_text = g_strndup(text, text_len);
+ if (thunk->text) {
+ strappend(thunk->text, new_text);
+ g_free(new_text);
+ } else {
+ thunk->text = new_text;
+ }
+ }
+}
+