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);
    }
}
示例#2
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;
}
示例#3
0
static void
query_unread_mails_cb (GObject *source_object,
    GAsyncResult *res,
    gpointer user_data)
{
  GError *error = NULL;
  WockyPorter *porter = WOCKY_PORTER (source_object);
  WockyStanza *reply = wocky_porter_send_iq_finish (porter, res, &error);
  GabbleConnection *conn = GABBLE_CONNECTION (user_data);

  if (reply == NULL ||
      wocky_stanza_extract_errors (reply, NULL, &error, NULL, NULL))
    {
      DEBUG ("Failed retreive unread emails information: %s", error->message);
      g_error_free (error);
    }
  else if (conn->mail_priv->interested)
    {
      WockyNode *node = wocky_node_get_child (
          wocky_stanza_get_top_node (reply), "mailbox");

      DEBUG ("Got unread mail details");

      if (node != NULL)
        store_unread_mails (conn, node);
    }
  /* else we no longer care about unread mail, so ignore it */

  tp_clear_object (&reply);

  return_from_request_inbox_url (conn);
}
示例#4
0
static gboolean
handle_senders (WockyNode *parent_node,
    GHashTable *mail)
{
  gboolean dirty = FALSE;
  WockyNode *node;

  node = wocky_node_get_child (parent_node, "senders");
  if (node != NULL)
    {
      GType addr_list_type = TP_ARRAY_TYPE_MAIL_ADDRESS_LIST;
      GPtrArray *senders, *old_senders;

      senders = g_ptr_array_new ();
      wocky_node_each_child (node, sender_each, senders);

      old_senders = tp_asv_get_boxed (mail, "senders", addr_list_type);

      if (old_senders == NULL || senders->len != old_senders->len)
            dirty = TRUE;

      tp_asv_take_boxed (mail, "senders", addr_list_type, senders);
    }

  return dirty;
}
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);
    }

}
示例#6
0
static gboolean
handle_subject (WockyNode *parent_node,
    GHashTable *mail)
{
  gboolean dirty = FALSE;
  WockyNode *node;

  node = wocky_node_get_child (parent_node, "subject");
  if (node != NULL)
    {
      if (tp_strdiff (node->content, tp_asv_get_string (mail, "subject")))
        {
          dirty = TRUE;
          tp_asv_set_string (mail, "subject", node->content);
        }
    }

  return dirty;
}
void
gabble_jingle_content_parse_description_info (GabbleJingleContent *c,
    WockyNode *content_node, GError **error)
{
  GabbleJingleContentPrivate *priv = c->priv;
  WockyNode *desc_node;
  desc_node = wocky_node_get_child (content_node, "description");
  if (desc_node == NULL)
    {
      SET_BAD_REQ ("invalid description-info action");
      return;
    }

  if (priv->created_by_us && priv->state < JINGLE_CONTENT_STATE_ACKNOWLEDGED)
    {
      /* The stream was created by us and the other side didn't acknowledge it
       * yet, thus we don't have their codec information, thus the
       * description-info isn't meaningful and can be ignored */
      DEBUG ("Ignoring description-info as we didn't receive the codecs yet");
      return;
    }

  parse_description (c, desc_node, error);
}
示例#8
0
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
iq_set_bind_XMPP_BIND (TestConnectorServer *self,
    WockyStanza *xml)
{
  TestConnectorServerPrivate *priv = self->priv;
  WockyXmppConnection *conn = priv->conn;
  WockyStanza *iq = NULL;
  BindProblem problems = priv->problem.connector->bind;
  BindProblem bp = BIND_PROBLEM_NONE;

  DEBUG("");
  if ((bp = problems & BIND_PROBLEM_INVALID)  ||
      (bp = problems & BIND_PROBLEM_DENIED)   ||
      (bp = problems & BIND_PROBLEM_CONFLICT) ||
      (bp = problems & BIND_PROBLEM_REJECTED))
    {
      const gchar *error = NULL;
      const gchar *etype = NULL;
      switch (bp)
        {
        case BIND_PROBLEM_INVALID:
          error = "bad-request";
          etype = "modify";
          break;
        case BIND_PROBLEM_DENIED:
          error = "not-allowed";
          etype = "cancel";
          break;
        case BIND_PROBLEM_CONFLICT:
          error = "conflict";
          etype = "cancel";
          break;
        default:
          error = "badger-badger-badger-mushroom";
          etype = "moomins";
        }
      iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ,
          WOCKY_STANZA_SUB_TYPE_ERROR,
          NULL, NULL,
          '(', "bind", ':', WOCKY_XMPP_NS_BIND,
          ')',
          '(', "error", '@', "type", etype,
          '(', error, ':', WOCKY_XMPP_NS_STANZAS,
          ')',
          ')',
          NULL);
    }
  else if (problems & BIND_PROBLEM_FAILED)
    {
      /* deliberately nonsensical response */
      iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ,
          WOCKY_STANZA_SUB_TYPE_SET,
          NULL, NULL,
          '(', "bind", ':', WOCKY_XMPP_NS_BIND,
          ')',
          NULL);
    }
  else if (problems & BIND_PROBLEM_NONSENSE)
    {
      /* deliberately nonsensical response */
      iq = wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE,
          WOCKY_STANZA_SUB_TYPE_NONE,
          NULL, NULL,
          '(', "bind", ':', WOCKY_XMPP_NS_BIND,
          ')',
          NULL);
    }
  else if (problems & BIND_PROBLEM_CLASH)
    {
      iq = error_stanza ("conflict", NULL, FALSE);
    }
  else
    {
      WockyNode *ciq = wocky_stanza_get_top_node (xml);
      WockyNode *bind =
        wocky_node_get_child_ns (ciq, "bind", WOCKY_XMPP_NS_BIND);
      WockyNode *res = wocky_node_get_child (bind, "resource");
      const gchar *uniq = NULL;
      gchar *jid = NULL;

      if (res != NULL)
        uniq = res->content;
      if (uniq == NULL)
        uniq = "a-made-up-resource";

      if (problems & BIND_PROBLEM_NO_JID)
        {
          iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ,
              WOCKY_STANZA_SUB_TYPE_RESULT, NULL, NULL,
              '(', "bind", ':', WOCKY_XMPP_NS_BIND,
              ')', NULL);
        }
      else
        {
          jid = g_strdup_printf ("[email protected]/%s", uniq);
          iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ,
              WOCKY_STANZA_SUB_TYPE_RESULT,
              NULL, NULL,
              '(', "bind", ':', WOCKY_XMPP_NS_BIND,
              '(', "jid", '$', jid, ')',
              ')',
              NULL);
          g_free (jid);
        }
    }

  server_enc_outstanding (self);
  wocky_xmpp_connection_send_stanza_async (conn, iq, priv->cancellable,
    iq_sent, self);
  g_object_unref (xml);
  g_object_unref (iq);
}
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_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);
}
示例#13
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);
}
示例#14
0
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;
}