Beispiel #1
0
static gboolean
im_factory_own_message_cb (
    WockyPorter *porter,
    WockyStanza *stanza,
    gpointer user_data)
{
  GabbleImFactory *self = GABBLE_IM_FACTORY (user_data);
  WockyNode *own_message, *body;
  const gchar *to;
  gboolean sent_locally;
  GabbleIMChannel *chan;

  /* Our stanza filter should guarantee that these are present. */
  own_message = wocky_node_get_child (wocky_stanza_get_top_node (stanza),
      "own-message");
  g_return_val_if_fail (own_message != NULL, FALSE);
  body = wocky_node_get_child (own_message, "body");
  g_return_val_if_fail (body != NULL, FALSE);

  to = wocky_node_get_attribute (own_message, "to");
  if (to == NULL)
    {
      DEBUG ("own-message missing to='' attribute; ignoring");
      return FALSE;
    }

  /* If self='true', the message was sent by the local user on this machine,
   * rather than by the local user on some other machine. We don't really have
   * a good way to show this in Messages. Also we don't get told the id='' of
   * the original message, which is annoying.
   */
  sent_locally = !tp_strdiff ("true",
      wocky_node_get_attribute (own_message, "self"));
  DEBUG ("this report is for a message to '%s', sent %s",
      to, sent_locally ? "locally" : "remotely");

  /* Don't create a channel for the sole purpose of reporting an own-message.
   * This is consistent with not creating a channel to report send errors
   * (given that both are delivery reports).
   */
  chan = get_channel_for_incoming_message (self, to, FALSE);
  if (chan != NULL)
    _gabble_im_channel_report_delivery (chan,
        TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL, 0, NULL, body->content,
        GABBLE_TEXT_CHANNEL_SEND_NO_ERROR, TP_DELIVERY_STATUS_ACCEPTED);
  else
    DEBUG ("no channel for '%s'; not spawning one just for the delivery report",
        to);

  wocky_porter_acknowledge_iq (porter, stanza, NULL);
  return TRUE;
}
Beispiel #2
0
/* Signals incoming delivery receipts. http://xmpp.org/extensions/xep-0184.html
 */
static gboolean
im_factory_receipt_cb (
    WockyPorter *porter,
    WockyStanza *message,
    gpointer user_data)
{
  GabbleImFactory *self = GABBLE_IM_FACTORY (user_data);
  WockyNode *received;
  const gchar *from, *received_id;
  GabbleIMChannel *channel;

  received = wocky_node_get_child_ns (wocky_stanza_get_top_node (message),
      "received", NS_RECEIPTS);
  g_return_val_if_fail (received != NULL, FALSE);

  received_id = wocky_node_get_attribute (received, "id");
  if (received_id == NULL)
    {
      STANZA_DEBUG (message, "but *what* did you receive?!");
      return TRUE;
    }

  from = wocky_stanza_get_from (message);
  channel = get_channel_for_incoming_message (self, from, FALSE);
  if (channel == NULL)
    {
      DEBUG ("no existing channel with '%s'; ignoring receipt", from);
      return TRUE;
    }

  gabble_im_channel_receive_receipt (channel, received_id);
  return TRUE;
}
void
gabble_jingle_content_parse_accept (GabbleJingleContent *c,
    WockyNode *content_node, gboolean google_mode, GError **error)
{
  GabbleJingleContentPrivate *priv = c->priv;
  const gchar *senders;
  WockyNode *trans_node, *desc_node;
  JingleDialect dialect = gabble_jingle_session_get_dialect (c->session);
  JingleContentSenders newsenders;

  desc_node = wocky_node_get_child (content_node, "description");
  trans_node = wocky_node_get_child (content_node, "transport");
  senders = wocky_node_get_attribute (content_node, "senders");

  if (GABBLE_IS_JINGLE_MEDIA_RTP (c) &&
      JINGLE_IS_GOOGLE_DIALECT (dialect) && trans_node == NULL)
    {
      DEBUG ("no transport node, assuming GTalk3 dialect");
      /* gtalk lj0.3 assumes google-p2p transport */
      g_object_set (c->session, "dialect", JINGLE_DIALECT_GTALK3, NULL);
    }

  if (senders == NULL)
    newsenders = get_default_senders (c);
  else
    newsenders = parse_senders (senders);

  if (newsenders == JINGLE_CONTENT_SENDERS_NONE)
    {
      SET_BAD_REQ ("invalid content senders");
      return;
    }

  if (newsenders != priv->senders)
    {
      DEBUG ("changing senders from %s to %s", produce_senders (priv->senders),
          produce_senders (newsenders));
      priv->senders = newsenders;
      g_object_notify ((GObject *) c, "senders");
    }

  parse_description (c, desc_node, error);
  if (*error != NULL)
      return;

  priv->state = JINGLE_CONTENT_STATE_ACKNOWLEDGED;
  g_object_notify ((GObject *) c, "state");

  if (trans_node != NULL)
    {
      gabble_jingle_transport_iface_parse_candidates (priv->transport,
        trans_node, NULL);
    }
}
GibberFileTransfer *
gibber_file_transfer_new_from_stanza (WockyStanza *stanza,
    WockyPorter *porter,
    WockyContact *contact,
    GError **error)
{
  const gchar *from;

  from = wocky_node_get_attribute (wocky_stanza_get_top_node (stanza), "from");

  return gibber_file_transfer_new_from_stanza_with_from (stanza, porter,
      contact, from, error);
}
Beispiel #5
0
static gboolean
sender_each (WockyNode *node,
    gpointer user_data)
{
  GPtrArray *senders = user_data;

  if (!tp_strdiff ("1", wocky_node_get_attribute (node, "unread")))
    {
      GValueArray *sender;
      const gchar *name;
      const gchar *address;

      name = wocky_node_get_attribute (node, "name");
      address = wocky_node_get_attribute (node, "address");

      sender = tp_value_array_build (2,
          G_TYPE_STRING, name ? name : "",
          G_TYPE_STRING, address ? address : "",
          G_TYPE_INVALID);

      g_ptr_array_add (senders, sender);
    }
  return TRUE;
}
void
gabble_jingle_content_update_senders (GabbleJingleContent *c,
    WockyNode *content_node, GError **error)
{
  GabbleJingleContentPrivate *priv = c->priv;
  JingleContentSenders senders;

  senders = parse_senders (wocky_node_get_attribute (content_node, "senders"));

  if (senders == JINGLE_CONTENT_SENDERS_NONE)
    {
      SET_BAD_REQ ("invalid content senders in stream");
      return;
    }

  priv->senders = senders;
  g_object_notify ((GObject *) c, "senders");
}
static gboolean
received_stanza_cb (WockyPorter *porter,
                    WockyStanza *stanza,
                    gpointer user_data)
{
  GibberFileTransfer *self = user_data;
  const gchar *id;

  id = wocky_node_get_attribute (wocky_stanza_get_top_node (stanza),
      "id");
  if (id != NULL && strcmp (id, self->id) == 0)
    {
      GIBBER_FILE_TRANSFER_GET_CLASS (self)->received_stanza (self, stanza);
      return TRUE;
    }

  return FALSE;
}
void
gabble_jingle_content_parse_info (GabbleJingleContent *c,
    WockyNode *content_node, GError **error)
{
  WockyNode *channel_node;
  WockyNode *complete_node;

  channel_node = wocky_node_get_child (content_node, "channel");
  complete_node = wocky_node_get_child (content_node, "complete");

  DEBUG ("parsing info message : %p - %p", channel_node, complete_node);
  if (channel_node)
    {
      const gchar *name;
      name = wocky_node_get_attribute (channel_node, "name");
      if (name != NULL)
        new_share_channel (c, name);
    }
  else if (complete_node)
    {
      g_signal_emit (c, signals[COMPLETED], 0);
    }

}
Beispiel #9
0
static gboolean
mail_thread_info_each (WockyNode *node,
    gpointer user_data)
{
  MailThreadCollector *collector = user_data;

  if (!tp_strdiff (node->name, "mail-thread-info"))
    {
      GHashTable *mail = NULL;
      const gchar *val_str;
      gchar *tid;
      gboolean dirty = FALSE;

      val_str = wocky_node_get_attribute (node, "tid");

      /* We absolutly need an ID */
      if (val_str == NULL)
        return TRUE;

      tid = g_strdup (val_str);

      if (collector->old_mails != NULL)
        {
          mail = g_hash_table_lookup (collector->old_mails, tid);
          g_hash_table_steal (collector->old_mails, tid);
        }

      if (mail == NULL)
        {
          mail = tp_asv_new ("id", G_TYPE_STRING, tid,
                             "url-data", G_TYPE_STRING, "",
                             NULL);
          dirty = TRUE;
        }

      val_str = wocky_node_get_attribute (node, "date");

      if (val_str != NULL)
        {
          gint64 date;

          date = (g_ascii_strtoll (val_str, NULL, 0) / 1000l);
          if (date != tp_asv_get_int64 (mail, "received-timestamp", NULL))
            dirty = TRUE;

          tp_asv_set_int64 (mail, "received-timestamp", date);
        }

      if (handle_senders (node, mail))
        dirty = TRUE;

      if (handle_subject (node, mail))
        dirty = TRUE;

      if (handle_snippet (node, mail))
        dirty = TRUE;

      /* gives tid ownership to unread_mails hash table */
      g_hash_table_insert (collector->conn->mail_priv->unread_mails, tid, mail);

      if (dirty)
        g_ptr_array_add (collector->mails_added, mail);
    }

  return TRUE;
}
void
gabble_jingle_content_parse_add (GabbleJingleContent *c,
    WockyNode *content_node, gboolean google_mode, GError **error)
{
  GabbleJingleContentPrivate *priv = c->priv;
  const gchar *name, *creator, *senders, *disposition;
  WockyNode *trans_node, *desc_node;
  GType transport_type = 0;
  GabbleJingleTransportIface *trans = NULL;
  JingleDialect dialect = gabble_jingle_session_get_dialect (c->session);

  priv->created_by_us = FALSE;

  desc_node = wocky_node_get_child (content_node, "description");
  trans_node = wocky_node_get_child (content_node, "transport");
  creator = wocky_node_get_attribute (content_node, "creator");
  name = wocky_node_get_attribute (content_node, "name");
  senders = wocky_node_get_attribute (content_node, "senders");

  g_assert (priv->transport_ns == NULL);

  if (google_mode)
    {
      if (creator == NULL)
          creator = "initiator";

      /* the google protocols don't give the contents names, so put in a dummy
       * value if none was set by the session*/
      if (priv->name == NULL)
        name = priv->name = g_strdup ("gtalk");
      else
        name = priv->name;

      if (trans_node == NULL)
        {
          /* gtalk lj0.3 assumes google-p2p transport */
          DEBUG ("detected GTalk3 dialect");

          dialect = JINGLE_DIALECT_GTALK3;
          g_object_set (c->session, "dialect", JINGLE_DIALECT_GTALK3, NULL);
          transport_type = gabble_jingle_factory_lookup_transport (
              gabble_jingle_session_get_factory (c->session),
              "");

          /* in practice we do support gtalk-p2p, so this can't happen */
          if (G_UNLIKELY (transport_type == 0))
            {
              SET_BAD_REQ ("gtalk-p2p transport unsupported");
              return;
            }

          priv->transport_ns = g_strdup ("");
        }
    }
  else
    {
      if (creator == NULL &&
          gabble_jingle_session_peer_has_cap (c->session,
              QUIRK_GOOGLE_WEBMAIL_CLIENT))
        {
          if (gabble_jingle_content_creator_is_initiator (c))
            creator = "initiator";
          else
            creator = "responder";

          DEBUG ("Working around GMail omitting creator=''; assuming '%s'",
              creator);
        }

      if ((trans_node == NULL) || (creator == NULL) || (name == NULL))
        {
          SET_BAD_REQ ("missing required content attributes or elements");
          return;
        }

      /* In proper protocols the name comes from the stanza */
      g_assert (priv->name == NULL);
      priv->name = g_strdup (name);
    }

  /* if we didn't set it to google-p2p implicitly already, detect it */
  if (transport_type == 0)
    {
      const gchar *ns = wocky_node_get_ns (trans_node);

      transport_type = gabble_jingle_factory_lookup_transport (
          gabble_jingle_session_get_factory (c->session), ns);

      if (transport_type == 0)
        {
          SET_BAD_REQ ("unsupported content transport");
          return;
        }

      priv->transport_ns = g_strdup (ns);
    }

  if (senders == NULL)
    priv->senders = get_default_senders (c);
  else
    priv->senders = parse_senders (senders);

  if (priv->senders == JINGLE_CONTENT_SENDERS_NONE)
    {
      SET_BAD_REQ ("invalid content senders");
      return;
    }

  parse_description (c, desc_node, error);
  if (*error != NULL)
      return;

  disposition = wocky_node_get_attribute (content_node, "disposition");
  if (disposition == NULL)
      disposition = "session";

  if (wocky_strdiff (disposition, priv->disposition))
    {
      g_free (priv->disposition);
      priv->disposition = g_strdup (disposition);
    }

  DEBUG ("content creating new transport type %s", g_type_name (transport_type));

  trans = gabble_jingle_transport_iface_new (transport_type,
      c, priv->transport_ns);

  g_signal_connect (trans, "new-candidates",
      (GCallback) new_transport_candidates_cb, c);

  /* Depending on transport, there may be initial candidates specified here */
  if (trans_node != NULL)
    {
      gabble_jingle_transport_iface_parse_candidates (trans, trans_node, error);
      if (*error)
        {
          g_object_unref (trans);
          return;
        }
    }

  g_assert (priv->transport == NULL);
  priv->transport = trans;
  transport_created (c);

  g_assert (priv->creator == NULL);
  priv->creator = g_strdup (creator);

  priv->state = JINGLE_CONTENT_STATE_NEW;

  /* GTalk4 seems to require "transport-accept" for acknowledging
   * the transport type. wjt confirms that this is apparently necessary for
   * incoming calls to work.
   */
  if (dialect == JINGLE_DIALECT_GTALK4)
    priv->gtalk4_event_id = g_idle_add (send_gtalk4_transport_accept, c);

  return;
}
static void
iq_set_query_JABBER_AUTH (TestConnectorServer *self,
    WockyStanza *xml)
{
  TestConnectorServerPrivate *priv = self->priv;
  WockyXmppConnection *conn = priv->conn;
  WockyStanza *iq = NULL;
  WockyNode *env = wocky_stanza_get_top_node (xml);
  WockyNode *qry = wocky_node_get_child (env, "query");
  JabberProblem problems = priv->problem.connector->jabber;
  JabberProblem jp = JABBER_PROBLEM_NONE;
  WockyNode *username = wocky_node_get_child (qry, "username");
  WockyNode *password = wocky_node_get_child (qry, "password");
  WockyNode *resource = wocky_node_get_child (qry, "resource");
  WockyNode *sha1hash = wocky_node_get_child (qry, "digest");
  const gchar *id = wocky_node_get_attribute (env, "id");

  DEBUG ("");
  if (username == NULL || resource == NULL)
    problems |= JABBER_PROBLEM_AUTH_PARTIAL;
  else if (password != NULL)
    {
      if (wocky_strdiff (priv->user, username->content) ||
          wocky_strdiff (priv->pass, password->content))
        problems |= JABBER_PROBLEM_AUTH_REJECT;
    }
  else if (sha1hash != NULL)
    {
      gchar *hsrc = g_strconcat (INITIAL_STREAM_ID, priv->pass, NULL);
      gchar *sha1 = g_compute_checksum_for_string (G_CHECKSUM_SHA1, hsrc, -1);
      DEBUG ("checksum: %s vs %s", sha1, sha1hash->content);
      if (wocky_strdiff (priv->user, username->content) ||
          wocky_strdiff (sha1, sha1hash->content))
        problems |= JABBER_PROBLEM_AUTH_REJECT;

      g_free (hsrc);
      g_free (sha1);
    }
  else
    problems |= JABBER_PROBLEM_AUTH_PARTIAL;

  if ((jp = problems & JABBER_PROBLEM_AUTH_REJECT)  ||
      (jp = problems & JABBER_PROBLEM_AUTH_BIND)    ||
      (jp = problems & JABBER_PROBLEM_AUTH_PARTIAL) ||
      (jp = problems & JABBER_PROBLEM_AUTH_FAILED))
    {
      const gchar *error = NULL;
      const gchar *etype = NULL;
      const gchar *ecode = NULL;

      switch (jp)
        {
          case JABBER_PROBLEM_AUTH_REJECT:
            error = "not-authorized";
            etype = "auth";
            ecode = "401";
            break;
          case JABBER_PROBLEM_AUTH_BIND:
            error = "conflict";
            etype = "cancel";
            ecode = "409";
            break;
          case JABBER_PROBLEM_AUTH_PARTIAL:
            error = "not-acceptable";
            etype = "modify";
            ecode = "406";
            break;
          default:
            error = "bad-request";
            etype = "modify";
            ecode = "500";
            break;
        }

      DEBUG ("error: %s/%s", error, etype);
      iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ,
          WOCKY_STANZA_SUB_TYPE_ERROR,
          NULL, NULL,
          '@', "id", id,
          '(', "error",
          '@', "type", etype,
          '@', "code", ecode,
          '(', error, ':', WOCKY_XMPP_NS_STANZAS,
          ')',
          ')',
          NULL);
    }
  else if (problems & JABBER_PROBLEM_AUTH_STRANGE)
    {
      DEBUG ("auth WEIRD");
      iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ,
          WOCKY_STANZA_SUB_TYPE_SET,
          NULL, NULL,
          '@', "id", id,
          '(', "surstromming", ':', WOCKY_XMPP_NS_BIND,
          ')',
          NULL);
    }
  else if (problems & JABBER_PROBLEM_AUTH_NONSENSE)
    {
      DEBUG ("auth NONSENSE");
      iq = wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE,
          WOCKY_STANZA_SUB_TYPE_NONE,
          NULL, NULL,
          '@', "id", id,
          '(', "surstromming", ':', WOCKY_XMPP_NS_BIND,
          ')',
          NULL);
    }
  else
    {
      DEBUG ("auth OK");
      iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ,
          WOCKY_STANZA_SUB_TYPE_RESULT,
          NULL, NULL,
          '@', "id", id,
          NULL);
    }

  server_enc_outstanding (self);
  wocky_xmpp_connection_send_stanza_async (conn, iq, priv->cancellable,
    iq_sent, self);
  g_object_unref (iq);
  g_object_unref (xml);
}
static void
iq_get_query_JABBER_AUTH (TestConnectorServer *self,
    WockyStanza *xml)
{
  TestConnectorServerPrivate *priv = self->priv;
  WockyXmppConnection *conn = priv->conn;
  WockyStanza *iq = NULL;
  WockyNode *env = wocky_stanza_get_top_node (xml);
  const gchar *id = wocky_node_get_attribute (env, "id");
  WockyNode *query = wocky_node_get_child (env, "query");
  WockyNode *user  = (query != NULL) ?
    wocky_node_get_child (query, "username") : NULL;
  const gchar *name = (user != NULL) ? user->content : NULL;

  DEBUG ("");
  if (priv->problem.connector->jabber & JABBER_PROBLEM_AUTH_NIH)
    {
      iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ,
          WOCKY_STANZA_SUB_TYPE_ERROR,
          NULL, NULL,
          '@', "id", id,
          '(', "error", '@', "type", "cancel",
          '(', "service-unavailable",
          ':', WOCKY_XMPP_NS_STANZAS,
          ')',
          ')',
          NULL);
    }
  else if (name == NULL || *name == '\0')
    {
      iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ,
          WOCKY_STANZA_SUB_TYPE_ERROR,
          NULL, NULL,
          '@', "id", id,
          '(', "error", '@', "type", "modify",
            '(', "not-acceptable",
              ':', WOCKY_XMPP_NS_STANZAS,
            ')',
            '(', "text", ':', WOCKY_XMPP_NS_STANZAS,
              '$',
                "You must include the username in the initial IQ get to work "
                "around a bug in jabberd 1.4. See "
                "https://bugs.freedesktop.org/show_bug.cgi?id=24013",
            ')',
          ')',
          NULL);
    }
  else if (priv->mech != NULL)
    {
      iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ,
          WOCKY_STANZA_SUB_TYPE_RESULT,
          NULL, NULL,
          '@', "id", id,
          '(', "query", ':', WOCKY_JABBER_NS_AUTH,
          '(', "username", ')',
          '(', priv->mech, ')',
          '(', "resource", ')',
          ')',
          NULL);
    }
  else
    {
      iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ,
          WOCKY_STANZA_SUB_TYPE_RESULT,
          NULL, NULL,
          '@', "id", id,
          '(', "query", ':', WOCKY_JABBER_NS_AUTH,
          '(', "username", ')',
          '(', "password", ')',
          '(', "resource", ')',
          '(', "digest", ')',
          ')',
          NULL);
    }

  DEBUG ("responding to iq get");
  server_enc_outstanding (self);
  wocky_xmpp_connection_send_stanza_async (conn, iq,
    priv->cancellable, iq_sent, self);
  DEBUG ("sent iq get response");
  g_object_unref (xml);
  g_object_unref (iq);
}
static void
iq_get_query_XEP77_REGISTER (TestConnectorServer *self,
    WockyStanza *xml)
{
  TestConnectorServerPrivate *priv = self->priv;
  WockyXmppConnection *conn = priv->conn;
  WockyStanza *iq = NULL;
  WockyNode *env = wocky_stanza_get_top_node (xml);
  WockyNode *query = NULL;
  const gchar *id = wocky_node_get_attribute (env, "id");

  DEBUG ("");
  if (priv->problem.connector->xep77 & XEP77_PROBLEM_NOT_AVAILABLE)
    {
      iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ,
          WOCKY_STANZA_SUB_TYPE_ERROR,
          NULL, NULL,
          '@', "id", id,
          '(', "error", '@', "type", "cancel",
          '(', "service-unavailable",
          ':', WOCKY_XMPP_NS_STANZAS,
          ')',
          ')',
          NULL);
    }
  else if (priv->problem.connector->xep77 & XEP77_PROBLEM_QUERY_NONSENSE)
    {
      iq = wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE,
          WOCKY_STANZA_SUB_TYPE_NONE,
          NULL, NULL,
          '@', "id", id,
          '(', "plankton", ':', WOCKY_XEP77_NS_REGISTER,
          ')',
          NULL);
    }
  else if (priv->problem.connector->xep77 & XEP77_PROBLEM_QUERY_ALREADY)
    {
      iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ,
          WOCKY_STANZA_SUB_TYPE_RESULT,
          NULL, NULL,
          '@', "id", id,
          '(', "query", ':', WOCKY_XEP77_NS_REGISTER,
          '(', "registered", ')',
          '(', "username", '$', "foo", ')',
          '(', "password", '$', "bar", ')',
          ')',
          NULL);
    }
  else
    {
      iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ,
          WOCKY_STANZA_SUB_TYPE_RESULT,
          NULL, NULL,
          '@', "id", id,
          '(', "query", ':', WOCKY_XEP77_NS_REGISTER,
            '*', &query,
          ')',
          NULL);

      if (!(priv->problem.connector->xep77 & XEP77_PROBLEM_NO_ARGS))
        {
          wocky_node_add_child (query, "username");
          wocky_node_add_child (query, "password");

          if (priv->problem.connector->xep77 & XEP77_PROBLEM_EMAIL_ARG)
            wocky_node_add_child (query, "email");
          if (priv->problem.connector->xep77 & XEP77_PROBLEM_STRANGE_ARG)
            wocky_node_add_child (query, "wildebeest");
        }
    }

  server_enc_outstanding (self);
  wocky_xmpp_connection_send_stanza_async (conn, iq, NULL, iq_sent, self);
  g_object_unref (xml);
  g_object_unref (iq);
}
/* ************************************************************************* */
static void
iq_set_query_XEP77_REGISTER (TestConnectorServer *self,
    WockyStanza *xml)
{
  TestConnectorServerPrivate *priv = self->priv;
  WockyXmppConnection *conn = priv->conn;
  WockyStanza *iq = NULL;
  WockyNode *env = wocky_stanza_get_top_node (xml);
  WockyNode *query = wocky_node_get_child (env, "query");
  const gchar *id = wocky_node_get_attribute (env, "id");
  gpointer cb = iq_sent;

  DEBUG ("");

  if (priv->problem.connector->xep77 & XEP77_PROBLEM_ALREADY)
    {
      iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ,
          WOCKY_STANZA_SUB_TYPE_RESULT,
          NULL, NULL,
          '@', "id", id,
          '(', "query", ':', WOCKY_XEP77_NS_REGISTER,
          '(', "registered", ')',
          '(', "username", '$', "foo", ')',
          '(', "password", '$', "bar", ')',
          ')',
          NULL);
    }
  else if (priv->problem.connector->xep77 & XEP77_PROBLEM_FAIL_CONFLICT)
    {
      iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ,
          WOCKY_STANZA_SUB_TYPE_ERROR,
          NULL, NULL,
          '@', "id", id,
          '(', "error", '@', "type", "cancel",
          '(', "conflict",
          ':', WOCKY_XMPP_NS_STANZAS,
          ')',
          ')',
          NULL);
    }
  else if (priv->problem.connector->xep77 & XEP77_PROBLEM_FAIL_REJECTED)
    {
      iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ,
          WOCKY_STANZA_SUB_TYPE_ERROR,
          NULL, NULL,
          '@', "id", id,
          '(', "error", '@', "type", "modify",
          '(', "not-acceptable",
          ':', WOCKY_XMPP_NS_STANZAS,
          ')',
          ')',
          NULL);
    }
  else
    {
      if (wocky_node_get_child (query, "remove") == NULL)
        {
          iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ,
              WOCKY_STANZA_SUB_TYPE_RESULT,
              NULL, NULL,
              '@', "id", id,
              NULL);
        }
      else
        {
          XEP77Problem problem = priv->problem.connector->xep77;
          XEP77Problem p = XEP77_PROBLEM_NONE;

          DEBUG ("handling CANCEL");

          if ((p = problem & XEP77_PROBLEM_CANCEL_REJECTED) ||
              (p = problem & XEP77_PROBLEM_CANCEL_DISABLED) ||
              (p = problem & XEP77_PROBLEM_CANCEL_FAILED))
            {
              const gchar *error = NULL;
              const gchar *etype = NULL;
              const gchar *ecode = NULL;

              switch (p)
                {
                  case XEP77_PROBLEM_CANCEL_REJECTED:
                    error = "bad-request";
                    etype = "modify";
                    ecode = "400";
                    break;
                  case XEP77_PROBLEM_CANCEL_DISABLED:
                    error = "not-allowed";
                    etype = "cancel";
                    ecode = "405";
                    break;
                  default:
                    error = "forbidden";
                    etype = "cancel";
                    ecode = "401";
                }

              DEBUG ("error: %s/%s", error, etype);
              iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ,
                  WOCKY_STANZA_SUB_TYPE_ERROR,
                  NULL, NULL,
                  '@', "id", id,
                  '(', "error",
                  '@', "type", etype,
                  '@', "code", ecode,
                  '(', error, ':', WOCKY_XMPP_NS_STANZAS,
                  ')',
                  ')',
                  NULL);
            }
          else
            {
              if (priv->problem.connector->xep77 & XEP77_PROBLEM_CANCEL_STREAM)
                {
                  iq = error_stanza ("not-authorized", NULL, FALSE);
                  cb = finished;
                }
              else
                {
                  cb = iq_sent_unregistered;
                  iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ,
                      WOCKY_STANZA_SUB_TYPE_RESULT,
                      NULL, NULL,
                      '@', "id", id,
                      NULL);
                }
            }
        }
    }

  server_enc_outstanding (self);
  wocky_xmpp_connection_send_stanza_async (conn, iq,
    priv->cancellable, cb, self);
  g_object_unref (xml);
  g_object_unref (iq);
}
Beispiel #15
0
static void
parse_description (WockyJingleContent *content,
    WockyNode *desc_node, GError **error)
{
  GabbleJingleShare *self = GABBLE_JINGLE_SHARE (content);
  GabbleJingleSharePrivate *priv = self->priv;
  WockyNodeIter i;
  WockyNode *manifest_node = NULL;
  WockyNode *protocol_node = NULL;
  WockyNode *http_node = NULL;
  WockyNode *node;

  DEBUG ("parse description called");

  if (priv->manifest != NULL)
    {
      DEBUG ("Not parsing description, we already have a manifest");
      return;
    }

  manifest_node = wocky_node_get_child (desc_node, "manifest");

  if (manifest_node == NULL)
    {
      g_set_error (error, WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST,
          "description missing <manifest/> node");
      return;
    }

  protocol_node = wocky_node_get_child (desc_node, "protocol");
  if (protocol_node != NULL)
    http_node = wocky_node_get_child (protocol_node, "http");

  free_manifest (self);
  priv->manifest = g_slice_new0 (GabbleJingleShareManifest);

  /* Build the manifest */
  wocky_node_iter_init (&i, manifest_node, NULL, NULL);
  while (wocky_node_iter_next (&i, &node))
    {
      WockyNode *name = NULL;
      WockyNode *image = NULL;
      gboolean folder;
      const gchar *size;
      GabbleJingleShareManifestEntry *m = NULL;

      if (!wocky_strdiff (node->name, "folder"))
        folder = TRUE;
      else if (!wocky_strdiff (node->name, "file"))
        folder = FALSE;
      else
        continue;

      name = wocky_node_get_child (node, "name");
      if (name == NULL)
        continue;

      m = g_slice_new0 (GabbleJingleShareManifestEntry);
      m->folder = folder;
      m->name = g_strdup (name->content);

      size = wocky_node_get_attribute (node, "size");
      if (size)
        m->size = g_ascii_strtoull (size, NULL, 10);

      image = wocky_node_get_child (node, "image");
      if (image)
        {
          const gchar *width;
          const gchar *height;

          m->image = TRUE;

          width = wocky_node_get_attribute (image, "width");
          if (width)
            m->image_width = g_ascii_strtoull (width, NULL, 10);

          height =wocky_node_get_attribute (image, "height");
          if (height)
            m->image_height = g_ascii_strtoull (height, NULL, 10);
        }
      priv->manifest->entries = g_list_prepend (priv->manifest->entries, m);
    }

  /* Get the source and preview url paths from the protocol/http node */
  if (http_node != NULL)
    {
      /* clear the previously set values */
      wocky_node_iter_init (&i, http_node, "url", NULL);
      while (wocky_node_iter_next (&i, &node))
        {
          const gchar *name = wocky_node_get_attribute (node, "name");
          if (name == NULL)
            continue;

          if (!wocky_strdiff (name, "source-path"))
            {
              const gchar *url = node->content;
              priv->manifest->source_url = g_strdup (url);
            }

          if (!wocky_strdiff (name, "preview-path"))
            {
              const gchar *url = node->content;
              priv->manifest->preview_url = g_strdup (url);
            }
        }
    }

  /* Build the filename/filesize property values based on the new manifest */
  g_free (priv->filename);
  priv->filename = NULL;
  priv->filesize = 0;

  if (g_list_length (priv->manifest->entries) > 0)
    {
      if (g_list_length (priv->manifest->entries) == 1)
        {
          GabbleJingleShareManifestEntry *m = priv->manifest->entries->data;

          if (m->folder)
            priv->filename = g_strdup_printf ("%s.tar", m->name);
          else
            priv->filename = g_strdup (m->name);

          priv->filesize = m->size;
        }
      else
        {
          GList *li;
          gchar *temp;

          priv->filename = g_strdup ("");
          for (li = priv->manifest->entries; li; li = li->next)
            {
              GabbleJingleShareManifestEntry *m = li->data;

              temp = priv->filename;
              priv->filename = g_strdup_printf ("%s%s%s%s",  temp, m->name,
                  m->folder? ".tar":"", li->next == NULL? "": "-");
              g_free (temp);

              priv->filesize += m->size;
            }
          temp = priv->filename;
          priv->filename = g_strdup_printf ("%s.tar", temp);
          g_free (temp);
        }
    }
  _wocky_jingle_content_set_media_ready (content);
}
static void
got_jingle_info_stanza (
    GabbleJingleInfo *self,
    WockyStanza *stanza)
{
  WockyNode *node, *query_node;

  query_node = wocky_node_get_child_ns (
      wocky_stanza_get_top_node (stanza), "query", NS_GOOGLE_JINGLE_INFO);

  if (query_node == NULL)
    return;

  if (self->priv->get_stun_from_jingle)
    node = wocky_node_get_child (query_node, "stun");
  else
    node = NULL;

  if (node != NULL)
    {
      node = wocky_node_get_child (node, "server");

      if (node != NULL)
        {
          const gchar *server;
          const gchar *port_attr;
          guint port = 0;

          server = wocky_node_get_attribute (node, "host");
          port_attr = wocky_node_get_attribute (node, "udp");

          if (port_attr != NULL)
            port = atoi (port_attr);

          if (server != NULL &&
              port_attr != NULL && port > 0 && port <= G_MAXUINT16)
            {
              DEBUG ("jingle info: got stun server %s, port %u", server,
                  port);
              gabble_jingle_info_take_stun_server (self,
                  g_strdup (server), port, FALSE);
            }
        }
    }

#ifdef ENABLE_GOOGLE_RELAY
  node = wocky_node_get_child (query_node, "relay");

  if (node != NULL)
    {
      WockyNode *subnode = wocky_node_get_child (node, "token");

      if (subnode != NULL)
        {
          const gchar *token = subnode->content;

          if (token != NULL)
            {
              DEBUG ("jingle info: got Google relay token %s", token);
              g_free (self->priv->relay_token);
              self->priv->relay_token = g_strdup (token);
            }
        }

      subnode = wocky_node_get_child (node, "server");

      if (subnode != NULL)
        {
          const gchar *server;
          const gchar *port;

          server = wocky_node_get_attribute (subnode, "host");

          if (server != NULL)
            {
              DEBUG ("jingle info: got relay server %s", server);
              g_free (self->priv->relay_server);
              self->priv->relay_server = g_strdup (server);
            }

          if (test_mode)
            {
              /* this is not part of the real protocol, but we can't listen on
               * port 80 in an unprivileged regression test */
              port = wocky_node_get_attribute (subnode,
                  "gabble-test-http-port");

              if (port != NULL)
                {
                  DEBUG ("jingle info: diverting 'Google' HTTP requests to "
                      "port %s", port);
                  self->priv->relay_http_port = atoi (port);
                }
            }

          /* FIXME: these are not really actually used anywhere at
           * the moment, because we get the same info when creating
           * relay session. */
          port = wocky_node_get_attribute (subnode, "udp");

          if (port != NULL)
            {
              DEBUG ("jingle info: got relay udp port %s", port);
              self->priv->relay_udp = atoi (port);
            }

          port = wocky_node_get_attribute (subnode, "tcp");

          if (port != NULL)
            {
              DEBUG ("jingle info: got relay tcp port %s", port);
              self->priv->relay_tcp = atoi (port);
            }

          port = wocky_node_get_attribute (subnode, "tcpssl");

          if (port != NULL)
            {
              DEBUG ("jingle info: got relay tcpssl port %s", port);
              self->priv->relay_ssltcp = atoi (port);
            }

        }

    }
#endif  /* ENABLE_GOOGLE_RELAY */
}
static void
parse_candidates (WockyJingleTransportIface *obj,
    WockyNode *transport_node, GError **error)
{
  WockyJingleTransportIceUdp *t = WOCKY_JINGLE_TRANSPORT_ICEUDP (obj);
  WockyJingleTransportIceUdpPrivate *priv = t->priv;
  gboolean node_contains_a_candidate = FALSE;
  GList *candidates = NULL;
  WockyNodeIter i;
  WockyNode *node;

  DEBUG ("called");

  wocky_node_iter_init (&i, transport_node, "candidate", NULL);
  while (wocky_node_iter_next (&i, &node))
    {
      const gchar *id, *address, *user, *pass, *str;
      guint port, net, gen, component = 1;
      gdouble pref;
      WockyJingleTransportProtocol proto;
      WockyJingleCandidateType ctype;
      WockyJingleCandidate *c;

      node_contains_a_candidate = TRUE;

      id = wocky_node_get_attribute (node, "foundation");
      if (id == NULL)
        {
          DEBUG ("candidate doesn't contain foundation");
          continue;
        }

      address = wocky_node_get_attribute (node, "ip");
      if (address == NULL)
        {
          DEBUG ("candidate doesn't contain ip");
          continue;
        }

      str = wocky_node_get_attribute (node, "port");
      if (str == NULL)
        {
          DEBUG ("candidate doesn't contain port");
          continue;
        }
      port = atoi (str);

      str = wocky_node_get_attribute (node, "protocol");
      if (str == NULL)
        {
          DEBUG ("candidate doesn't contain protocol");
          continue;
        }

      if (!wocky_strdiff (str, "udp"))
        {
          proto = WOCKY_JINGLE_TRANSPORT_PROTOCOL_UDP;
        }
      else
        {
          /* unknown protocol */
          DEBUG ("unknown protocol: %s", str);
          continue;
        }

      str = wocky_node_get_attribute (node, "priority");
      if (str == NULL)
        {
          DEBUG ("candidate doesn't contain priority");
          continue;
        }
      pref = g_ascii_strtod (str, NULL);

      str = wocky_node_get_attribute (node, "type");
      if (str == NULL)
        {
          DEBUG ("candidate doesn't contain type");
          continue;
        }

      if (!wocky_strdiff (str, "host"))
        {
          ctype = WOCKY_JINGLE_CANDIDATE_TYPE_LOCAL;
        }
      else if (!wocky_strdiff (str, "srflx") || !wocky_strdiff (str, "prflx"))
        {
          /* FIXME Strictly speaking a prflx candidate should be a different
           * type, but the TP spec has now way to distinguish and it doesn't
           * matter much anyway.. */
          ctype = WOCKY_JINGLE_CANDIDATE_TYPE_STUN;
        }
      else if (!wocky_strdiff (str, "relay"))
        {
          ctype = WOCKY_JINGLE_CANDIDATE_TYPE_RELAY;
        }
      else
        {
          /* unknown candidate type */
          DEBUG ("unknown candidate type: %s", str);
          continue;
        }

      user = wocky_node_get_attribute (transport_node, "ufrag");
      if (user == NULL)
        {
          DEBUG ("transport doesn't contain ufrag");
          continue;
        }

      pass = wocky_node_get_attribute (transport_node, "pwd");
      if (pass == NULL)
        {
          DEBUG ("transport doesn't contain pwd");
          continue;
        }

      str = wocky_node_get_attribute (node, "network");
      if (str == NULL)
        {
          DEBUG ("candidate doesn't contain network");
          continue;
        }
      net = atoi (str);

      str = wocky_node_get_attribute (node, "generation");
      if (str == NULL)
        {
          DEBUG ("candidate doesn't contain generation");
          continue;
        }
      gen = atoi (str);

      str = wocky_node_get_attribute (node, "component");
      if (str == NULL)
        {
          DEBUG ("candidate doesn't contain component");
          continue;
        }
      component = atoi (str);

      if (priv->ufrag == NULL || strcmp (priv->ufrag, user))
        {
          g_free (priv->ufrag);
          priv->ufrag = g_strdup (user);
        }

      if (priv->pwd == NULL || strcmp (priv->pwd, pass))
        {
          g_free (priv->pwd);
          priv->pwd = g_strdup (pass);
        }

      c = wocky_jingle_candidate_new (proto, ctype, id, component,
          address, port, gen, pref, user, pass, net);

      candidates = g_list_append (candidates, c);
    }

  if (candidates == NULL)
    {
      if (node_contains_a_candidate)
        {
          DEBUG_NODE (transport_node,
              "couldn't parse any of the given candidates");
          g_set_error (error, WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST,
              "could not parse any of the given candidates");
        }
      else
        {
          DEBUG ("no candidates in this stanza");
        }
    }
  else
    {
      DEBUG ("emitting %d new remote candidates", g_list_length (candidates));

      g_signal_emit (obj, signals[NEW_CANDIDATES], 0, candidates);

      priv->remote_candidates = g_list_concat (priv->remote_candidates,
          candidates);
    }
}
static void
parse_candidates (GabbleJingleTransportIface *obj,
    WockyNode *transport_node, GError **error)
{
  GabbleJingleTransportGoogle *t = GABBLE_JINGLE_TRANSPORT_GOOGLE (obj);
  GabbleJingleTransportGooglePrivate *priv = t->priv;
  GList *candidates = NULL;
  WockyNodeIter i;
  WockyNode *node;

  wocky_node_iter_init (&i, transport_node, "candidate", NULL);
  while (wocky_node_iter_next (&i, &node))
    {
      const gchar *name, *address, *user, *pass, *str;
      guint port, net, gen, component;
      int pref;
      JingleTransportProtocol proto;
      JingleCandidateType ctype;
      JingleCandidate *c;

      name = wocky_node_get_attribute (node, "name");
      if (name == NULL)
          break;

      if (!g_hash_table_lookup_extended (priv->component_names, name,
              NULL, NULL))
        {
          DEBUG ("component name %s unknown to this transport", name);
          continue;
        }

      component = GPOINTER_TO_INT (g_hash_table_lookup (priv->component_names,
              name));
      address = wocky_node_get_attribute (node, "address");
      if (address == NULL)
          break;

      str = wocky_node_get_attribute (node, "port");
      if (str == NULL)
          break;
      port = atoi (str);

      str = wocky_node_get_attribute (node, "protocol");
      if (str == NULL)
          break;

      if (!wocky_strdiff (str, "udp"))
        {
          proto = JINGLE_TRANSPORT_PROTOCOL_UDP;
        }
      else if (!wocky_strdiff (str, "tcp"))
        {
          /* candiates on port 443 must be "ssltcp" */
          if (port == 443)
              break;

          proto = JINGLE_TRANSPORT_PROTOCOL_TCP;
        }
      else if (!wocky_strdiff (str, "ssltcp"))
        {
          /* "ssltcp" must use port 443 */
          if (port != 443)
              break;

          /* we really don't care about "ssltcp" otherwise */
          proto = JINGLE_TRANSPORT_PROTOCOL_TCP;
        }
      else
        {
          /* unknown protocol */
          DEBUG ("unknown protocol: %s", str);
          break;
        }

      str = wocky_node_get_attribute (node, "preference");
      if (str == NULL)
          break;

      pref = g_ascii_strtod (str, NULL) * 65536;

      str = wocky_node_get_attribute (node, "type");
      if (str == NULL)
          break;

      if (!wocky_strdiff (str, "local"))
        {
          ctype = JINGLE_CANDIDATE_TYPE_LOCAL;
        }
      else if (!wocky_strdiff (str, "stun"))
        {
          ctype = JINGLE_CANDIDATE_TYPE_STUN;
        }
      else if (!wocky_strdiff (str, "relay"))
        {
          ctype = JINGLE_CANDIDATE_TYPE_RELAY;
        }
      else
        {
          /* unknown candidate type */
          DEBUG ("unknown candidate type: %s", str);
          break;
        }

      user = wocky_node_get_attribute (node, "username");
      if (user == NULL)
          break;

      pass = wocky_node_get_attribute (node, "password");
      if (pass == NULL)
          break;

      str = wocky_node_get_attribute (node, "network");
      if (str == NULL)
          break;
      net = atoi (str);

      str = wocky_node_get_attribute (node, "generation");
      if (str == NULL)
          break;
      gen = atoi (str);

      str = wocky_node_get_attribute (node, "component");
      if (str != NULL)
          component = atoi (str);

      c = jingle_candidate_new (proto, ctype, NULL, component,
          address, port, gen, pref, user, pass, net);

      candidates = g_list_append (candidates, c);
    }

  if (wocky_node_iter_next (&i, NULL))
    {
      DEBUG ("not all nodes were processed, reporting error");
      /* rollback these */
      jingle_transport_free_candidates (candidates);
      g_set_error (error, WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST,
          "invalid candidate");
      return;
    }

  DEBUG ("emitting %d new remote candidates", g_list_length (candidates));

  g_signal_emit (obj, signals[NEW_CANDIDATES], 0, candidates);

  /* append them to the known remote candidates */
  priv->remote_candidates = g_list_concat (priv->remote_candidates, candidates);
}
Beispiel #19
0
static void
store_unread_mails (GabbleConnection *conn,
    WockyNode *mailbox)
{
  GabbleConnectionMailNotificationPrivate *priv = conn->mail_priv;
  GHashTableIter iter;
  GPtrArray *mails_removed;
  MailThreadCollector collector;
  const gchar *url, *unread_count;

  collector.conn = conn;
  collector.old_mails = priv->unread_mails;
  priv->unread_mails = g_hash_table_new_full (g_str_hash, g_str_equal,
      g_free, (GDestroyNotify) g_hash_table_unref);
  collector.mails_added = g_ptr_array_new ();

  url = wocky_node_get_attribute (mailbox, "url");
  g_free (priv->inbox_url);

  /* Use empty string to differentiate pending request from server failing to
     provide an URL.*/
  if (url != NULL)
    priv->inbox_url = g_strdup (url);
  else
    priv->inbox_url = g_strdup ("");

  /* Store new mails */
  wocky_node_each_child (mailbox, mail_thread_info_each, &collector);

  /* Generate the list of removed thread IDs */
  mails_removed = g_ptr_array_new_with_free_func (g_free);

  if (collector.old_mails != NULL)
    {
      gpointer key;

      g_hash_table_iter_init (&iter, collector.old_mails);

      while (g_hash_table_iter_next (&iter, &key, NULL))
        {
          gchar *tid = key;
          g_ptr_array_add (mails_removed, g_strdup (tid));
        }

      g_hash_table_unref (collector.old_mails);
    }
  g_ptr_array_add (mails_removed, NULL);

  unread_count = wocky_node_get_attribute (mailbox, "total-matched");

  if (unread_count != NULL)
    priv->unread_count = (guint)g_ascii_strtoll (unread_count, NULL, 0);
  else
    priv->unread_count = g_hash_table_size (priv->unread_mails);

  tp_svc_connection_interface_mail_notification_emit_unread_mails_changed (
      conn, priv->unread_count, collector.mails_added,
      (const char **)mails_removed->pdata);

  g_ptr_array_free (collector.mails_added, TRUE);
  g_ptr_array_free (mails_removed, TRUE);
}