/*-
* $Id: rr-greeting.c,v 1.24 2002/11/08 12:35:28 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 <jonas@codefactory.se>
* Copyright (c) 2002 Daniel Lundin <daniel@codefactory.se>
* Copyright (c) 2002 CodeFactory AB. All rights reserved.
*/
#include <librr/rr.h>
#include <libxml/xmlmemory.h>
#include <libxml/parser.h>
#include <string.h>
static GObjectClass *parent_class = NULL;
static RRFrame *get_frame (RRMessage *msg, gsize max_size);
static gboolean process_frame (RRMessage *msg, RRFrame *frame, GError **err);
static void finalize (GObject *object);
static void
rr_greeting_init (GObject *object)
{
RRMessage *msg = (RRMessage *)object;
msg->type = RR_FRAME_TYPE_RPY;
}
static void
rr_greeting_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_greeting_get_type (void)
{
static GType rr_type = 0;
if (!rr_type) {
static GTypeInfo type_info = {
sizeof (RRGreetingClass),
NULL,
NULL,
(GClassInitFunc) rr_greeting_class_init,
NULL,
NULL,
sizeof (RRGreeting),
16,
(GInstanceInitFunc) rr_greeting_init
};
rr_type = g_type_register_static (RR_TYPE_MESSAGE, "RRGreeting",
&type_info, 0);
}
return rr_type;
}
static void
finalize (GObject *object)
{
RRGreeting *greeting = (RRGreeting *)object;
if (greeting->localize)
g_free (greeting->localize);
if (greeting->features)
g_free (greeting->features);
g_slist_foreach (greeting->peer_profiles, (GFunc)g_free, NULL);
g_slist_free (greeting->peer_profiles);
parent_class->finalize (object);
}
RRGreeting *
rr_greeting_new (RRProfileRegistry *profreg, const gchar *localize,
const gchar *features)
{
RRGreeting *greeting;
greeting = g_object_new (RR_TYPE_GREETING, NULL);
greeting->profreg = profreg;
if (localize)
greeting->localize = g_strdup (localize);
if (features)
greeting->features = g_strdup (features);
return greeting;
}
static void
hash_profiles_greeting_str (gpointer key, gpointer value, gpointer user_data)
{
GString *buf = (GString *)user_data;
gchar *uri = (gchar *)key;
g_string_append_printf (buf, " <profile uri='%s' />\r\n", uri);
}
static gboolean
process_frame (RRMessage *message, RRFrame *frame, GError **error)
{
RRGreeting *greeting;
RRConnection *conn;
xmlDocPtr doc;
xmlNodePtr node;
gboolean ret;
const gchar *data;
gint len;
g_return_val_if_fail (RR_IS_GREETING (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;
greeting = RR_GREETING (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 greeting message.");
return FALSE;
}
node = xmlDocGetRootElement (doc);
if (strcmp (node->name, "greeting") != 0)
goto err;
node = node->children;
while (node) {
xmlChar *str;
gchar *uri;
/* Ignore none element nodes */
while (node && node->type != XML_ELEMENT_NODE)
node = node->next;
if (node == NULL)
break;
if (strcmp (node->name, "profile") != 0)
goto err;
if ((str = xmlGetProp (node, "uri")) == NULL)
goto err;
uri = g_strdup (str);
xmlFree (str);
greeting->peer_profiles = g_slist_append (greeting->peer_profiles,
uri);
node = node->next;
}
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 *msg, gsize max_size)
{
RRGreeting *greeting = (RRGreeting *)msg;
RRProfileRegistry *profreg;
RRFrame *frame;
GString *greetingstr;
GString *profilestr;
g_return_val_if_fail (RR_IS_GREETING (greeting), NULL);
greetingstr = g_string_new (RR_BEEP_MIME_HEADER);
profilestr = g_string_new (NULL);
profreg = greeting->profreg;
if (profreg && RR_IS_PROFILE_REGISTRY (profreg)) {
g_static_rw_lock_reader_lock (&(profreg->rwlock));
g_hash_table_foreach (profreg->profiles_by_uri,
hash_profiles_greeting_str,
profilestr);
g_static_rw_lock_reader_unlock (&(profreg->rwlock));
} else {
g_print ("greeting.get_frame: There is no profile registry. "
"How strange...\n");
}
g_string_append (greetingstr, "<greeting");
if (greeting->localize) {
g_string_append_printf (greetingstr, " localize=\"%s\"",
greeting->localize);
}
if (greeting->features) {
g_string_append_printf (greetingstr, " features=\"%s\"",
greeting->features);
}
if (profilestr->len > 0) {
g_string_append_printf (greetingstr,
">\r\n%s</greeting>\r\n",
profilestr->str);
} else {
g_string_append (greetingstr, " />\r\n");
}
if (max_size < greetingstr->len) {
g_string_free (greetingstr, TRUE);
g_string_free (profilestr, TRUE);
return NULL;
}
frame = rr_frame_new (RR_FRAME_TYPE_RPY, msg->channel->id, FALSE,
msg->msgno,
greetingstr->len, 0,
greetingstr->str, TRUE);
g_string_free (greetingstr, FALSE); /* Note: The string data is
referenced in the frame */
g_string_free (profilestr, TRUE);
return frame;
}
syntax highlighted by Code2HTML, v. 0.9.1