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