/*- * $Id: rr-message-error.c,v 1.17 2002/12/20 11:57:11 jonas Exp $ * * See the file LICENSE for redistribution information. * If you have not received a copy of the license, please contact CodeFactory * by email at info@codefactory.se, or on the web at http://www.codefactory.se/ * You may also write to: CodeFactory AB, SE-903 47, Umeå, Sweden. * * Copyright (c) 2002 Jonas Borgström * Copyright (c) 2002 Daniel Lundin * Copyright (c) 2002 CodeFactory AB. All rights reserved. */ #include #include #include #include static GObjectClass *parent_class = NULL; static void finalize (GObject *object); static RRFrame *get_frame (RRMessage *stat, gsize max_size); static gboolean process_frame (RRMessage *message, RRFrame *frame, GError **error); static void finalize (GObject *object) { RRMessageError *err = (RRMessageError *)object; if (err->xml_lang) { g_free (err->xml_lang); } if (err->diagnostic) { g_free (err->diagnostic); } parent_class->finalize (object); } static void rr_message_error_init (GObject *object) { RRMessage *msg = (RRMessage *)object; msg->type = RR_FRAME_TYPE_ERR; } static void rr_message_error_class_init (GObjectClass *klass) { RRMessageClass *msg_class = (RRMessageClass *)klass; klass->finalize = finalize; msg_class->get_frame = get_frame; msg_class->process_frame = process_frame; parent_class = g_type_class_peek_parent (klass); } GType rr_message_error_get_type (void) { static GType rr_type = 0; if (!rr_type) { static GTypeInfo type_info = { sizeof (RRMessageErrorClass), NULL, NULL, (GClassInitFunc) rr_message_error_class_init, NULL, NULL, sizeof (RRMessageError), 16, (GInstanceInitFunc) rr_message_error_init }; rr_type = g_type_register_static (RR_TYPE_MESSAGE, "RRMessageError", &type_info, 0); } return rr_type; } RRMessageError * rr_message_error_new (gint code, const gchar *xml_lang, const gchar *diagnostic) { RRMessageError *err; RRBeepLang lang = RR_BEEP_LANG_DEFAULT; err = g_object_new (RR_TYPE_MESSAGE_ERROR, NULL); err->code = code; if (diagnostic && strlen (diagnostic)) { err->diagnostic = g_strdup (diagnostic); if (xml_lang) { err->xml_lang = g_strdup (xml_lang); } } else { if (xml_lang) { lang = rr_beep_error_get_supported_lang (xml_lang); err->xml_lang = rr_beep_error_get_lang_iso (lang); } err->diagnostic = rr_beep_error_get_message (code, lang); } return err; } RRMessageError * rr_message_error_new_from_gerror (GError *error, const gchar *xml_lang) { RRMessageError *err; err = rr_message_error_new (error->code, xml_lang, error->message); return err; } void rr_message_error_set_gerror (RRMessageError *err, GError **error) { g_set_error (error, RR_ERROR, err->code, err->diagnostic); } static gboolean process_frame (RRMessage *message, RRFrame *frame, GError **error) { RRMessageError *err; RRConnection *conn; xmlDocPtr doc; xmlNodePtr node; gboolean ret; xmlChar *str; const gchar *data; gint len; g_return_val_if_fail (RR_IS_MESSAGE_ERROR (message), FALSE); g_return_val_if_fail (RR_IS_FRAME (frame), FALSE); g_return_val_if_fail (RR_IS_CHANNEL (message->channel), FALSE); g_return_val_if_fail (RR_IS_CONNECTION (message->channel->connection), FALSE); conn = message->channel->connection; err = RR_MESSAGE_ERROR (message); data = rr_frame_mime_get_body (frame); len = rr_frame_mime_get_body_size (frame); doc = xmlParseMemory (data, len); if (doc == NULL) { g_set_error (error, RR_ERROR, RR_BEEP_CODE_SYNTAX_ERROR, "Invalid error message."); return FALSE; } node = xmlDocGetRootElement (doc); if (strcmp (node->name, "error") != 0) goto err; if ((str = xmlGetProp (node, "code")) == NULL) goto err; err->code = atoi (str); xmlFree (str); if (node->children) { xmlNode *child, *cdata_node = NULL; child = node->children; while (child) { if (child->type == XML_CDATA_SECTION_NODE && child->content) { cdata_node = child; break; } child = child->next; } if (cdata_node && child->content) err->diagnostic = g_strdup (cdata_node->content); else if (node->children->type == XML_TEXT_NODE && node->children->content) err->diagnostic = g_strdup (node->children->content); } ret = TRUE; goto end; err: g_set_error (error, RR_ERROR, RR_BEEP_CODE_PARAM_ERROR, RR_GERROR_DEFAULT_MESSAGE); ret = FALSE; end: xmlFreeDoc (doc); return ret; } static RRFrame * get_frame (RRMessage *message, gsize max_size) { RRMessageError *error = RR_MESSAGE_ERROR(message); RRFrame *frame; GString *str; g_assert (RR_IS_MESSAGE (error)); g_assert (max_size > 0); str = g_string_new (NULL); g_string_printf (str, RR_BEEP_MIME_HEADER "code); if (error->xml_lang) { g_string_append_printf (str, " xml:lang='%s'", error->xml_lang); } if (error->diagnostic) { g_string_append_printf (str, ">\r\n", error->diagnostic); } else { g_string_append (str, " />\r\n"); } if (str->len > max_size) { g_string_free (str, TRUE); return NULL; } frame = rr_frame_new (RR_FRAME_TYPE_ERR, message->channel->id, FALSE, message->msgno, str->len, 0, str->str, TRUE); g_string_free (str, FALSE); return frame; }