Mercurial > pidgin.yaz
comparison src/protocols/jabber/si.c @ 7395:b250288fa948
[gaim-migrate @ 7990]
this would be the non-working start of file transfer (the real way) for jabber
also approximately eleventy billion jabber tweaks
committer: Tailor Script <tailor@pidgin.im>
author | Nathan Walp <nwalp@pidgin.im> |
---|---|
date | Fri, 31 Oct 2003 02:43:58 +0000 |
parents | |
children | 8f4ce853e685 |
comparison
equal
deleted
inserted
replaced
7394:c6ff3c1fb1b3 | 7395:b250288fa948 |
---|---|
1 /* | |
2 * gaim - Jabber Protocol Plugin | |
3 * | |
4 * Copyright (C) 2003, Nathan Walp <faceprint@faceprint.com> | |
5 * | |
6 * This program is free software; you can redistribute it and/or modify | |
7 * it under the terms of the GNU General Public License as published by | |
8 * the Free Software Foundation; either version 2 of the License, or | |
9 * (at your option) any later version. | |
10 * | |
11 * This program is distributed in the hope that it will be useful, | |
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 * GNU General Public License for more details. | |
15 * | |
16 * You should have received a copy of the GNU General Public License | |
17 * along with this program; if not, write to the Free Software | |
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
19 * | |
20 */ | |
21 #include "internal.h" | |
22 #include "debug.h" | |
23 #include "ft.h" | |
24 #include "notify.h" | |
25 #include "util.h" | |
26 | |
27 #include "buddy.h" | |
28 #include "jabber.h" | |
29 #include "iq.h" | |
30 #include "si.h" | |
31 | |
32 #include "si.h" | |
33 | |
34 static GaimXfer *jabber_si_xfer_find_by_id(JabberStream *js, const char *id) | |
35 { | |
36 GList *xfers; | |
37 | |
38 if(!id) | |
39 return NULL; | |
40 | |
41 for(xfers = js->file_transfers; xfers; xfers = xfers->next) { | |
42 GaimXfer *xfer = xfers->data; | |
43 JabberSIXfer *jsx = xfer->data; | |
44 | |
45 if(!strcmp(jsx->id, id)) | |
46 return xfer; | |
47 } | |
48 | |
49 return NULL; | |
50 } | |
51 | |
52 static void | |
53 jabber_si_xfer_ibb_start(JabberStream *js, xmlnode *packet, gpointer data) { | |
54 GaimXfer *xfer = data; | |
55 JabberSIXfer *jsx = xfer->data; | |
56 | |
57 /* Make sure we didn't get an error back */ | |
58 | |
59 /* XXX: OK, here we need to set up a g_idle thing to send messages | |
60 * until our eyes bleed, but do it without interfering with normal | |
61 * gaim operations. When we're done, we have to send a <close> like | |
62 * we sent the <open> to start this damn thing. If we're really | |
63 * fortunate, Exodus or someone else will implement something to test | |
64 * against soon */ | |
65 } | |
66 | |
67 void jabber_si_parse(JabberStream *js, xmlnode *packet) | |
68 { | |
69 GaimXfer *xfer; | |
70 JabberSIXfer *jsx; | |
71 xmlnode *si, *feature, *x, *field, *value; | |
72 | |
73 si = xmlnode_get_child(packet, "si"); | |
74 | |
75 xfer = jabber_si_xfer_find_by_id(js, xmlnode_get_attrib(si, "id")); | |
76 | |
77 if(!xfer) | |
78 return; | |
79 | |
80 jsx = xfer->data; | |
81 | |
82 if(!(feature = xmlnode_get_child(si, "feature"))) | |
83 return; | |
84 | |
85 for(x = feature->child; x; x = x->next) { | |
86 const char *xmlns; | |
87 if(x->type != NODE_TYPE_TAG) | |
88 continue; | |
89 if(!(xmlns = xmlnode_get_attrib(x, "xmlns"))) | |
90 continue; | |
91 if(strcmp(xmlns, "jabber:x:data")) | |
92 continue; | |
93 for(field = x->child; field; field = field->next) { | |
94 const char *var; | |
95 if(field->type != NODE_TYPE_TAG) | |
96 continue; | |
97 if(!(var = xmlnode_get_attrib(field, "var"))) | |
98 continue; | |
99 if(!strcmp(var, "stream-method")) { | |
100 if((value = xmlnode_get_child(field, "value"))) { | |
101 char *val_data = xmlnode_get_data(value); | |
102 if(!val_data) | |
103 jsx->stream_method = STREAM_METHOD_UNKNOWN; | |
104 else if(!strcmp(val_data, | |
105 "http://jabber.org/protocol/bytestreams")) | |
106 jsx->stream_method = STREAM_METHOD_BYTESTREAMS; | |
107 else if(!strcmp(val_data, "http://jabber.org/protocol/ibb")) | |
108 jsx->stream_method = STREAM_METHOD_IBB; | |
109 else | |
110 jsx->stream_method = STREAM_METHOD_UNSUPPORTED; | |
111 g_free(val_data); | |
112 } | |
113 } | |
114 } | |
115 } | |
116 if(jsx->stream_method == STREAM_METHOD_UNKNOWN) { | |
117 /* XXX */ | |
118 } else if(jsx->stream_method == STREAM_METHOD_UNSUPPORTED) { | |
119 /* XXX */ | |
120 } else if(jsx->stream_method == STREAM_METHOD_BYTESTREAMS) { | |
121 /* XXX: open the port and stuff */ | |
122 char *buf; | |
123 xmlnode *query, *streamhost; | |
124 JabberIq *iq = jabber_iq_new_query(js, JABBER_IQ_SET, | |
125 "http://jabber.org/protocol/bytestreams"); | |
126 | |
127 buf = g_strdup_printf("%s/%s", xfer->who, jsx->resource); | |
128 xmlnode_set_attrib(iq->node, "to", buf); | |
129 g_free(buf); | |
130 | |
131 query = xmlnode_get_child(iq->node, "query"); | |
132 xmlnode_set_attrib(query, "sid", jsx->id); | |
133 streamhost = xmlnode_new_child(query, "streamhost"); | |
134 xmlnode_set_attrib(streamhost, "jid", | |
135 gaim_account_get_username(js->gc->account)); | |
136 xmlnode_set_attrib(streamhost, "host", xfer->local_ip); | |
137 buf = g_strdup_printf("%d", xfer->local_port); | |
138 xmlnode_set_attrib(streamhost, "port", buf); | |
139 g_free(buf); | |
140 jabber_iq_send(iq); | |
141 } else if(jsx->stream_method == STREAM_METHOD_IBB) { | |
142 char *buf; | |
143 xmlnode *open; | |
144 JabberIq *iq = jabber_iq_new(js, JABBER_IQ_SET); | |
145 buf = g_strdup_printf("%s/%s", xfer->who, jsx->resource); | |
146 xmlnode_set_attrib(iq->node, "to", buf); | |
147 g_free(buf); | |
148 | |
149 open = xmlnode_new_child(iq->node, "open"); | |
150 xmlnode_set_attrib(open, "xmlns", "http://jabber.org/protocol/ibb"); | |
151 xmlnode_set_attrib(open, "sid", jsx->id); | |
152 | |
153 jabber_iq_set_callback(iq, jabber_si_xfer_ibb_start, xfer); | |
154 | |
155 jabber_iq_send(iq); | |
156 | |
157 } | |
158 } | |
159 | |
160 static void jabber_si_xfer_send_request(GaimXfer *xfer) | |
161 { | |
162 JabberSIXfer *jsx = xfer->data; | |
163 JabberIq *iq; | |
164 xmlnode *si, *file, *feature, *x, *field, *option, *value; | |
165 char buf[32]; | |
166 char *to; | |
167 | |
168 xfer->filename = g_path_get_basename(xfer->local_filename); | |
169 | |
170 iq = jabber_iq_new(jsx->js, JABBER_IQ_SET); | |
171 to = g_strdup_printf("%s/%s", xfer->who, jsx->resource); | |
172 xmlnode_set_attrib(iq->node, "to", to); | |
173 g_free(to); | |
174 si = xmlnode_new_child(iq->node, "si"); | |
175 xmlnode_set_attrib(si, "xmlns", "http://jabber.org/protocol/si"); | |
176 jsx->id = jabber_get_next_id(jsx->js); | |
177 xmlnode_set_attrib(si, "id", jsx->id); | |
178 xmlnode_set_attrib(si, "profile", | |
179 "http://jabber.org/protocol/si/profile/file-transfer"); | |
180 | |
181 file = xmlnode_new_child(si, "file"); | |
182 xmlnode_set_attrib(file, "xmlns", | |
183 "http://jabber.org/protocol/si/profile/file-transfer"); | |
184 xmlnode_set_attrib(file, "name", xfer->filename); | |
185 g_snprintf(buf, sizeof(buf), "%d", xfer->size); | |
186 xmlnode_set_attrib(file, "size", buf); | |
187 /* maybe later we'll do hash and date attribs */ | |
188 | |
189 feature = xmlnode_new_child(si, "feature"); | |
190 xmlnode_set_attrib(feature, "xmlns", | |
191 "http://jabber.org/protocol/feature-neg"); | |
192 x = xmlnode_new_child(feature, "x"); | |
193 xmlnode_set_attrib(x, "xmlns", "jabber:x:data"); | |
194 xmlnode_set_attrib(x, "type", "form"); | |
195 field = xmlnode_new_child(x, "field"); | |
196 xmlnode_set_attrib(field, "var", "stream-method"); | |
197 xmlnode_set_attrib(field, "type", "list-single"); | |
198 option = xmlnode_new_child(field, "option"); | |
199 value = xmlnode_new_child(option, "value"); | |
200 xmlnode_insert_data(value, "http://jabber.org/protocol/bytestreams", | |
201 -1); | |
202 option = xmlnode_new_child(field, "option"); | |
203 value = xmlnode_new_child(option, "value"); | |
204 xmlnode_insert_data(value, "http://jabber.org/protocol/ibb", -1); | |
205 | |
206 jabber_iq_send(iq); | |
207 } | |
208 | |
209 void jabber_si_xfer_init(GaimXfer *xfer) | |
210 { | |
211 JabberSIXfer *jsx = xfer->data; | |
212 if(gaim_xfer_get_type(xfer) == GAIM_XFER_SEND) { | |
213 JabberBuddy *jb; | |
214 JabberBuddyResource *jbr = NULL; | |
215 GList *resources; | |
216 GList *xfer_resources = NULL; | |
217 | |
218 jb = jabber_buddy_find(jsx->js, xfer->who, TRUE); | |
219 if(!jb) | |
220 return; | |
221 | |
222 for(resources = jb->resources; resources; resources = resources->next) { | |
223 jbr = resources->data; | |
224 if(jbr->capabilities & JABBER_CAP_SI_FILE_XFER) | |
225 xfer_resources = g_list_append(xfer_resources, jbr); | |
226 } | |
227 | |
228 if(g_list_length(xfer_resources) == 1) { | |
229 jbr = xfer_resources->data; | |
230 jsx->resource = g_strdup(jbr->name); | |
231 jabber_si_xfer_send_request(xfer); | |
232 } else if(g_list_length(xfer_resources) == 0) { | |
233 char *buf = g_strdup_printf(_("Could not send %s to %s, protocol not supported."), xfer->filename, xfer->who); | |
234 gaim_notify_error(jsx->js->gc, _("File Send Failed"), | |
235 _("File Send Failed"), buf); | |
236 g_free(buf); | |
237 } else { | |
238 /* XXX: ask which resource to send to! */ | |
239 } | |
240 g_list_free(xfer_resources); | |
241 } | |
242 } | |
243 | |
244 void jabber_si_xfer_start(GaimXfer *xfer) | |
245 { | |
246 gaim_debug(GAIM_DEBUG_INFO, "jabber", "in jabber_si_xfer_start\n"); | |
247 } | |
248 | |
249 void jabber_si_xfer_end(GaimXfer *xfer) | |
250 { | |
251 gaim_debug(GAIM_DEBUG_INFO, "jabber", "in jabber_si_xfer_end\n"); | |
252 } | |
253 | |
254 void jabber_si_xfer_cancel_send(GaimXfer *xfer) | |
255 { | |
256 gaim_debug(GAIM_DEBUG_INFO, "jabber", "in jabber_si_xfer_cancel_send\n"); | |
257 } | |
258 | |
259 | |
260 void jabber_si_xfer_cancel_recv(GaimXfer *xfer) | |
261 { | |
262 gaim_debug(GAIM_DEBUG_INFO, "jabber", "in jabber_si_xfer_cancel_recv\n"); | |
263 } | |
264 | |
265 | |
266 void jabber_si_xfer_ack(GaimXfer *xfer, const char *buffer, size_t size) | |
267 { | |
268 gaim_debug(GAIM_DEBUG_INFO, "jabber", "in jabber_si_xfer_ack\n"); | |
269 } | |
270 |