static GArray* inf_adopted_session_get_xml_user_props(InfSession* session, InfXmlConnection* conn, const xmlNodePtr xml) { GArray* array; GParameter* parameter; InfAdoptedStateVector* vector; xmlChar* time; array = INF_SESSION_CLASS(parent_class)->get_xml_user_props( session, conn, xml ); /* Vector time */ time = inf_xml_util_get_attribute(xml, "time"); if(time != NULL) { vector = inf_adopted_state_vector_from_string((const gchar*)time, NULL); xmlFree(time); /* TODO: Error reporting for get_xml_user_props */ if(vector != NULL) { parameter = inf_session_get_user_property(array, "vector"); g_value_init(¶meter->value, INF_ADOPTED_TYPE_STATE_VECTOR); g_value_take_boxed(¶meter->value, vector); } } /* log-begin is not in the spec */ #if 0 /* Initial request log, only if ID is also given */ id_param = inf_session_lookup_user_property( (const GParameter*)array->data, array->len, "id" ); if(id_param != NULL && inf_xml_util_get_attribute_uint(xml, "log-begin", &log_begin, NULL)) { log = inf_adopted_request_log_new( g_value_get_uint(&id_param->value), log_begin ); parameter = inf_session_get_user_property(array, "request-log"); g_value_init(¶meter->value, INF_ADOPTED_TYPE_REQUEST_LOG); g_value_take_object(¶meter->value, log); } #endif return array; }
static void inf_adopted_session_set_xml_user_props(InfSession* session, const GParameter* params, guint n_params, xmlNodePtr xml) { const GParameter* time; InfAdoptedStateVector* vector; gchar* time_string; INF_SESSION_CLASS(parent_class)->set_xml_user_props( session, params, n_params, xml ); time = inf_session_lookup_user_property(params, n_params, "vector"); if(time != NULL) { vector = (InfAdoptedStateVector*)g_value_get_boxed(&time->value); time_string = inf_adopted_state_vector_to_string(vector); inf_xml_util_set_attribute(xml, "time", time_string); g_free(time_string); } /* log-begin is not in the spec */ #if 0 log = inf_session_lookup_user_property(params, n_params, "request-log"); if(log != NULL) { log_begin = inf_adopted_request_log_get_begin( INF_ADOPTED_REQUEST_LOG(g_value_get_object(&log->value)) ); inf_xml_util_set_attribute_uint(xml, "log-begin", log_begin); } #endif }
static gboolean inf_adopted_session_validate_user_props(InfSession* session, const GParameter* params, guint n_params, InfUser* exclude, GError** error) { const GParameter* time; gboolean result; result = INF_SESSION_CLASS(parent_class)->validate_user_props( session, params, n_params, exclude, error ); if(result == FALSE) return FALSE; time = inf_session_lookup_user_property(params, n_params, "vector"); if(time == NULL) { g_set_error( error, inf_adopted_session_error_quark, INF_ADOPTED_SESSION_ERROR_MISSING_STATE_VECTOR, "%s", _("'time' attribute in user message is missing") ); return FALSE; } return TRUE; }
static gboolean infc_session_proxy_handle_user_rejoin(InfcSessionProxy* proxy, InfXmlConnection* connection, xmlNodePtr xml, GError** error) { InfcSessionProxyPrivate* priv; InfSessionClass* session_class; GArray* array; InfUser* user; const GParameter* idparam; GParameter* param; guint id; gboolean result; guint i; priv = INFC_SESSION_PROXY_PRIVATE(proxy); session_class = INF_SESSION_GET_CLASS(priv->session); array = session_class->get_xml_user_props(priv->session, connection, xml); /* Find rejoining user first */ idparam = inf_session_lookup_user_property( (const GParameter*)array->data, array->len, "id" ); if(idparam == NULL) { g_set_error( error, inf_request_error_quark(), INF_REQUEST_ERROR_NO_SUCH_ATTRIBUTE, _("Request does not contain required attribute 'id'") ); goto error; } id = g_value_get_uint(&idparam->value); user = inf_user_table_lookup_user_by_id( inf_session_get_user_table(priv->session), id ); if(user == NULL) { g_set_error( error, inf_user_error_quark(), INF_USER_ERROR_NO_SUCH_USER, _("No such user with ID %u"), id ); goto error; } /* Set local flag if the join was requested by us (seq is present in * server response). */ param = inf_session_get_user_property(array, "flags"); g_assert(!G_IS_VALUE(¶m->value)); /* must not have been set already */ g_value_init(¶m->value, INF_TYPE_USER_FLAGS); if(xmlHasProp(xml, (const xmlChar*)"seq") != NULL) g_value_set_flags(¶m->value, INF_USER_LOCAL); else g_value_set_flags(¶m->value, 0); /* Set connection. If none was given, use publisher connection */ param = inf_session_get_user_property(array, "connection"); if(!G_IS_VALUE(¶m->value)) { g_value_init(¶m->value, INF_TYPE_XML_CONNECTION); g_value_set_object(¶m->value, G_OBJECT(connection)); } result = session_class->validate_user_props( priv->session, (const GParameter*)array->data, array->len, user, error ); if(result == FALSE) goto error; /* Set properties on the found user object, performing the rejoin */ g_object_freeze_notify(G_OBJECT(user)); for(i = 0; i < array->len; ++ i) { param = &g_array_index(array, GParameter, i); /* Don't set ID because the ID is the same anyway (we did the user lookup * by it). The "id" property is construct only anyway. */ if(strcmp(param->name, "id") != 0) g_object_set_property(G_OBJECT(user), param->name, ¶m->value); } /* TODO: Set user status to available, if the server did not send the * status property? Require the status property being set on a rejoin? * Make sure it is not unavailable? */ g_object_thaw_notify(G_OBJECT(user)); for(i = 0; i < array->len; ++ i) g_value_unset(&g_array_index(array, GParameter, i).value); g_array_free(array, TRUE); infc_session_proxy_succeed_user_request(proxy, xml, user); return TRUE; error: for(i = 0; i < array->len; ++ i) g_value_unset(&g_array_index(array, GParameter, i).value); g_array_free(array, TRUE); return FALSE; }