Beispiel #1
0
void Gobby::UserJoin::on_user_join_finished(InfUser* user,
                                            const GError* error)
{
	if(m_request != NULL)
	{
		g_signal_handlers_disconnect_by_func(
			G_OBJECT(m_request),
			(gpointer)G_CALLBACK(on_user_join_finished_static),
			this);
		g_object_unref(m_request);
		m_request = NULL;
	}

	if(error == NULL)
	{
		user_join_complete(user, error);
	}
	else if(error->domain == inf_user_error_quark() &&
	        error->code == INF_USER_ERROR_NAME_IN_USE)
	{
		// If name is in use retry with alternative user name
		++m_retry_index;
		attempt_user_join();
	}
	else
	{
		user_join_complete(user, error);
	}
}
void Gobby::UserJoinCommands::UserJoinInfo::
	on_user_join_finished(InfUser* user, const GError* error)
{
	if(m_request != NULL)
	{
		g_object_unref(m_request);
		m_request = NULL;
	}

	if(error == NULL)
	{
		user_join_complete(user);
	}
	else if(error->domain == inf_user_error_quark() &&
	        error->code == INF_USER_ERROR_NAME_IN_USE)
	{
		// If name is in use retry with alternative user name
		++m_retry_index;
		attempt_user_join();
	}
	else if(error->domain == inf_request_error_quark() &&
	        error->code == INF_REQUEST_ERROR_NOT_AUTHORIZED)
	{
		set_permission_denied_text(m_view);
		finish();
	}
	else
	{
		set_error_text(m_view, error->message);
		finish();
	}
}
Beispiel #3
0
/**
 * inf_user_status_from_string:
 * @string: A string representation of a #InfUserStatus.
 * @status: A pointer to a #InfUserStatus value, or %NULL.
 * @error: Location to store error information, if any.
 *
 * This function does the opposite of inf_user_status_to_string(). It turns
 * the given string back to a #InfUserStatus, storing the result in @status
 * if @status is non-%NULL. If @string is invalid, then @status is left
 * untouched, @error is set and %FALSE is returned. Otherwise, the function
 * returns %TRUE.
 *
 * Returns: When an error occured during the conversion, %FALSE is returned,
 * and %TRUE otherwise.
 */
gboolean
inf_user_status_from_string(const gchar* string,
                            InfUserStatus* status,
                            GError** error)
{
  InfUserStatus tmp_status;

  if(strcmp(string, "active") == 0)
    tmp_status = INF_USER_ACTIVE;
  else if(strcmp(string, "inactive") == 0)
    tmp_status = INF_USER_INACTIVE;
  else if(strcmp(string, "unavailable") == 0)
    tmp_status = INF_USER_UNAVAILABLE;
  else
  {
    g_set_error(
      error,
      inf_user_error_quark(),
      INF_USER_ERROR_INVALID_STATUS,
      _("Invalid user status: '%s'"),
      string
    );

    return FALSE;
  }

  if(status) *status = tmp_status;
  return TRUE;
}
Beispiel #4
0
static void
on_join_failed(InfcRequest* request,
               const GError* error,
               gpointer user_data)
{
  InfTestGtkBrowserWindow* test;
  gchar* new_name;

  test = (InfTestGtkBrowserWindow*)user_data;

  if(error->domain == inf_user_error_quark() &&
     error->code == INF_USER_ERROR_NAME_IN_USE)
  {
    new_name = g_strdup_printf("%s%d", g_get_user_name(), 2);
    request_join(test, new_name);
    g_free(new_name);
  }
  else
  {
    set_error(test, "User join failed", error->message);
  }
}
Beispiel #5
0
static GError*
infc_session_proxy_translate_error_impl(InfcSessionProxy* proxy,
                                        GQuark domain,
                                        guint code)
{
  GError* error;
  const gchar* error_msg;

  if(domain == inf_request_error_quark())
    error_msg = inf_request_strerror(code);
  else if(domain == inf_user_error_quark())
    error_msg = inf_user_strerror(code);
  else
    error_msg = NULL;

  error = NULL;
  if(error_msg != NULL)
  {
    g_set_error(&error, domain, code, "%s", error_msg);
  }
  else
  {
    /* TODO: Check whether a human-readable error string was sent (that
     * we cannot translate then, of course). */
    g_set_error(
      &error,
      inf_request_error_quark(),
      INF_REQUEST_ERROR_UNKNOWN_DOMAIN,
      _("Error comes from unknown error domain '%s' (code %u)"),
      g_quark_to_string(domain),
      (guint)code
    );
  }

  return error;
}
static void
on_join_user_request_failed (InfcRequest  *request,
                             const GError *error,
                             gpointer      data)
{
	if (error->domain == inf_user_error_quark () &&
	    error->code == INF_USER_ERROR_NAME_IN_USE)
	{
		gchar *new_name;
		ChatData *cdata = (ChatData *)data;

		new_name = gedit_collaboration_generate_new_name (
			cdata->user,
			&cdata->name_failed_counter);

		request_join (cdata, new_name);

		g_free (new_name);
	}
	else if (error)
	{
		g_warning ("%s", error->message);
	}
}
static InfCommunicationScope
inf_adopted_session_process_xml_run(InfSession* session,
                                    InfXmlConnection* connection,
                                    const xmlNodePtr xml,
                                    GError** error)
{
  InfAdoptedSessionPrivate* priv;
  InfAdoptedSessionClass* session_class;
  InfAdoptedRequest* request;
  InfAdoptedUser* user;

  gboolean has_num;
  guint num;
  GError* local_error;
  InfAdoptedRequest* copy_req;
  guint i;

  priv = INF_ADOPTED_SESSION_PRIVATE(session);

  if(strcmp((const char*)xml->name, "request") == 0)
  {
    session_class = INF_ADOPTED_SESSION_GET_CLASS(session);
    g_assert(session_class->xml_to_request != NULL);

    user = inf_adopted_session_user_from_request_xml(
      INF_ADOPTED_SESSION(session),
      xml,
      error
    );

    if(user == NULL)
      return INF_COMMUNICATION_SCOPE_PTP;

    if(inf_user_get_status(INF_USER(user)) == INF_USER_UNAVAILABLE ||
       inf_user_get_connection(INF_USER(user)) != connection)
    {
      g_set_error(
        error,
        inf_user_error_quark(),
        INF_USER_ERROR_NOT_JOINED,
        "%s",
        _("User did not join from this connection")
      );

      return INF_COMMUNICATION_SCOPE_PTP;
    }

    local_error = NULL;
    has_num = inf_xml_util_get_attribute_uint(xml, "num", &num, &local_error);
    if(local_error != NULL)
    {
      g_propagate_error(error, local_error);
      return INF_COMMUNICATION_SCOPE_PTP;
    }
    
    request = session_class->xml_to_request(
      INF_ADOPTED_SESSION(session),
      xml,
      inf_adopted_user_get_vector(user),
      FALSE,
      error
    );

    if(request == NULL)
      return INF_COMMUNICATION_SCOPE_PTP;

    inf_adopted_algorithm_receive_request(priv->algorithm, request);

    /* Apply the request more than once if num is given. This is mostly used
     * for multiple undos and redos, but is in general allowed for any
     * request. */
    if(has_num)
    {
      for(i = 1; i < num; ++i)
      {
        /* TODO: This is a bit of a hack since requests are normally
         * immutable. It avoids an additional vector copy here though. */
        copy_req = inf_adopted_request_copy(request);

        inf_adopted_state_vector_add(
          inf_adopted_request_get_vector(copy_req),
          inf_user_get_id(INF_USER(user)),
          i
        );

        inf_adopted_algorithm_receive_request(priv->algorithm, copy_req);
        g_object_unref(copy_req);
      }
    }

    g_object_unref(request);

    /* Requests can always be forwarded since user is given. */
    return INF_COMMUNICATION_SCOPE_GROUP;
  }

  return INF_SESSION_CLASS(parent_class)->process_xml_run(
    session,
    connection,
    xml,
    error
  );
}
Beispiel #8
0
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(&param->value)); /* must not have been set already */

  g_value_init(&param->value, INF_TYPE_USER_FLAGS);
  if(xmlHasProp(xml, (const xmlChar*)"seq") != NULL)
    g_value_set_flags(&param->value, INF_USER_LOCAL);
  else
    g_value_set_flags(&param->value, 0);

  /* Set connection. If none was given, use publisher connection */
  param = inf_session_get_user_property(array, "connection");
  if(!G_IS_VALUE(&param->value))
  {
    g_value_init(&param->value, INF_TYPE_XML_CONNECTION);
    g_value_set_object(&param->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, &param->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;
}