2 * purple - Jabber Protocol Plugin
4 * Copyright (C) 2003, Nathan Walp <faceprint@faceprint.com>
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.
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.
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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
30 typedef struct _JabberOOBXfer
{
47 static void jabber_oob_xfer_init(PurpleXfer
*xfer
)
49 JabberOOBXfer
*jox
= xfer
->data
;
50 purple_xfer_start(xfer
, -1, jox
->address
, jox
->port
);
53 static void jabber_oob_xfer_free(PurpleXfer
*xfer
)
55 JabberOOBXfer
*jox
= xfer
->data
;
56 jox
->js
->oob_file_transfers
= g_list_remove(jox
->js
->oob_file_transfers
,
59 g_string_free(jox
->headers
, TRUE
);
63 g_free(jox
->write_buffer
);
65 purple_input_remove(jox
->writeh
);
71 static void jabber_oob_xfer_end(PurpleXfer
*xfer
)
73 JabberOOBXfer
*jox
= xfer
->data
;
76 iq
= jabber_iq_new(jox
->js
, JABBER_IQ_RESULT
);
77 xmlnode_set_attrib(iq
->node
, "to", xfer
->who
);
78 jabber_iq_set_id(iq
, jox
->iq_id
);
82 jabber_oob_xfer_free(xfer
);
85 static void jabber_oob_xfer_request_send(gpointer data
, gint source
, PurpleInputCondition cond
) {
86 PurpleXfer
*xfer
= data
;
87 JabberOOBXfer
*jox
= xfer
->data
;
88 int len
, total_len
= strlen(jox
->write_buffer
);
90 len
= write(xfer
->fd
, jox
->write_buffer
+ jox
->written_len
,
91 total_len
- jox
->written_len
);
93 if(len
< 0 && errno
== EAGAIN
)
96 purple_debug(PURPLE_DEBUG_ERROR
, "jabber", "Write error on oob xfer!\n");
97 purple_input_remove(jox
->writeh
);
98 purple_xfer_cancel_local(xfer
);
100 jox
->written_len
+= len
;
102 if(jox
->written_len
== total_len
) {
103 purple_input_remove(jox
->writeh
);
104 g_free(jox
->write_buffer
);
105 jox
->write_buffer
= NULL
;
109 static void jabber_oob_xfer_start(PurpleXfer
*xfer
)
111 JabberOOBXfer
*jox
= xfer
->data
;
113 if(jox
->write_buffer
== NULL
) {
114 jox
->write_buffer
= g_strdup_printf(
115 "GET /%s HTTP/1.1\r\nHost: %s\r\n\r\n",
116 jox
->page
, jox
->address
);
117 jox
->written_len
= 0;
120 jox
->writeh
= purple_input_add(xfer
->fd
, PURPLE_INPUT_WRITE
,
121 jabber_oob_xfer_request_send
, xfer
);
123 jabber_oob_xfer_request_send(xfer
, xfer
->fd
, PURPLE_INPUT_WRITE
);
126 static gssize
jabber_oob_xfer_read(guchar
**buffer
, PurpleXfer
*xfer
) {
127 JabberOOBXfer
*jox
= xfer
->data
;
132 if((len
= read(xfer
->fd
, test
, sizeof(test
))) > 0) {
133 jox
->headers
= g_string_append_len(jox
->headers
, test
, len
);
134 if((tmp
= strstr(jox
->headers
->str
, "\r\n\r\n"))) {
136 lenstr
= strstr(jox
->headers
->str
, "Content-Length: ");
139 sscanf(lenstr
, "Content-Length: %d", &size
);
140 purple_xfer_set_size(xfer
, size
);
142 purple_xfer_set_read_fnc(xfer
, NULL
);
146 *buffer
= (unsigned char*) g_strdup(tmp
);
150 } else if (errno
!= EAGAIN
) {
151 purple_debug(PURPLE_DEBUG_ERROR
, "jabber", "Read error on oob xfer!\n");
152 purple_xfer_cancel_local(xfer
);
158 static void jabber_oob_xfer_recv_error(PurpleXfer
*xfer
, const char *code
) {
159 JabberOOBXfer
*jox
= xfer
->data
;
163 iq
= jabber_iq_new(jox
->js
, JABBER_IQ_ERROR
);
164 xmlnode_set_attrib(iq
->node
, "to", xfer
->who
);
165 jabber_iq_set_id(iq
, jox
->iq_id
);
166 y
= xmlnode_new_child(iq
->node
, "error");
167 xmlnode_set_attrib(y
, "code", code
);
168 if(!strcmp(code
, "406")) {
169 z
= xmlnode_new_child(y
, "not-acceptable");
170 xmlnode_set_attrib(y
, "type", "modify");
171 xmlnode_set_namespace(z
, "urn:ietf:params:xml:ns:xmpp-stanzas");
172 } else if(!strcmp(code
, "404")) {
173 z
= xmlnode_new_child(y
, "not-found");
174 xmlnode_set_attrib(y
, "type", "cancel");
175 xmlnode_set_namespace(z
, "urn:ietf:params:xml:ns:xmpp-stanzas");
179 jabber_oob_xfer_free(xfer
);
182 static void jabber_oob_xfer_recv_denied(PurpleXfer
*xfer
) {
183 jabber_oob_xfer_recv_error(xfer
, "406");
186 static void jabber_oob_xfer_recv_canceled(PurpleXfer
*xfer
) {
187 jabber_oob_xfer_recv_error(xfer
, "404");
190 void jabber_oob_parse(JabberStream
*js
, xmlnode
*packet
) {
196 xmlnode
*querynode
, *urlnode
;
198 if(!(type
= xmlnode_get_attrib(packet
, "type")) || strcmp(type
, "set"))
201 if(!(querynode
= xmlnode_get_child(packet
, "query")))
204 if(!(urlnode
= xmlnode_get_child(querynode
, "url")))
207 url
= xmlnode_get_data(urlnode
);
209 jox
= g_new0(JabberOOBXfer
, 1);
210 if (!purple_url_parse(url
, &jox
->address
, &jox
->port
, &jox
->page
, NULL
, NULL
)) {
216 jox
->headers
= g_string_new("");
217 jox
->iq_id
= g_strdup(xmlnode_get_attrib(packet
, "id"));
219 xfer
= purple_xfer_new(js
->gc
->account
, PURPLE_XFER_RECEIVE
,
220 xmlnode_get_attrib(packet
, "from"));
225 if(!(filename
= g_strdup(g_strrstr(jox
->page
, "/"))))
226 filename
= g_strdup(jox
->page
);
228 purple_xfer_set_filename(xfer
, filename
);
232 purple_xfer_set_init_fnc(xfer
, jabber_oob_xfer_init
);
233 purple_xfer_set_end_fnc(xfer
, jabber_oob_xfer_end
);
234 purple_xfer_set_request_denied_fnc(xfer
, jabber_oob_xfer_recv_denied
);
235 purple_xfer_set_cancel_recv_fnc(xfer
, jabber_oob_xfer_recv_canceled
);
236 purple_xfer_set_read_fnc(xfer
, jabber_oob_xfer_read
);
237 purple_xfer_set_start_fnc(xfer
, jabber_oob_xfer_start
);
239 js
->oob_file_transfers
= g_list_append(js
->oob_file_transfers
, xfer
);
241 purple_xfer_request(xfer
);