Migrate certificates, icons, logs to XDG dirs
[pidgin-git.git] / libpurple / protocols / jabber / oob.c
blobf77797ce84bb95a6f0f9543d5754ad73451d42d2
1 /*
2 * purple - Jabber Protocol Plugin
4 * Purple is the legal property of its developers, whose names are too numerous
5 * to list here. Please refer to the COPYRIGHT file distributed with this
6 * source distribution.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
23 #include "internal.h"
24 #include "debug.h"
25 #include "xfer.h"
26 #include "http.h"
27 #include "util.h"
29 #include "jabber.h"
30 #include "iq.h"
31 #include "oob.h"
33 typedef struct _JabberOOBXfer {
34 JabberStream *js;
35 gchar *iq_id;
36 gchar *url;
37 PurpleHttpConnection *hc;
38 } JabberOOBXfer;
40 static void jabber_oob_xfer_init(PurpleXfer *xfer)
42 purple_xfer_start(xfer, -1, NULL, 0);
45 static void jabber_oob_xfer_free(PurpleXfer *xfer)
47 JabberOOBXfer *jox = purple_xfer_get_protocol_data(xfer);
49 purple_xfer_set_protocol_data(xfer, NULL);
50 jox->js->oob_file_transfers = g_list_remove(jox->js->oob_file_transfers,
51 xfer);
53 g_free(jox->iq_id);
54 g_free(jox->url);
55 g_free(jox);
58 static void jabber_oob_xfer_end(PurpleXfer *xfer)
60 JabberOOBXfer *jox = purple_xfer_get_protocol_data(xfer);
61 JabberIq *iq;
63 iq = jabber_iq_new(jox->js, JABBER_IQ_RESULT);
64 purple_xmlnode_set_attrib(iq->node, "to", purple_xfer_get_remote_user(xfer));
65 jabber_iq_set_id(iq, jox->iq_id);
67 jabber_iq_send(iq);
69 jabber_oob_xfer_free(xfer);
72 static void
73 jabber_oob_xfer_got(PurpleHttpConnection *hc, PurpleHttpResponse *response,
74 gpointer _xfer)
76 PurpleXfer *xfer = _xfer;
77 JabberOOBXfer *jox;
79 if (purple_xfer_is_cancelled(xfer))
80 return;
82 jox = purple_xfer_get_protocol_data(xfer);
83 jox->hc = NULL;
85 if (!purple_http_response_is_successful(response) ||
86 purple_xfer_get_bytes_remaining(xfer) > 0)
88 purple_xfer_set_status(xfer, PURPLE_XFER_STATUS_CANCEL_REMOTE);
89 purple_xfer_end(xfer);
90 } else {
91 purple_xfer_set_completed(xfer, TRUE);
92 purple_xfer_end(xfer);
96 static void
97 jabber_oob_xfer_progress_watcher(PurpleHttpConnection *hc,
98 gboolean reading_state, int processed, int total, gpointer _xfer)
100 PurpleXfer *xfer = _xfer;
102 if (!reading_state)
103 return;
105 purple_xfer_set_size(xfer, total);
106 purple_xfer_update_progress(xfer);
109 static gboolean
110 jabber_oob_xfer_writer(PurpleHttpConnection *http_conn,
111 PurpleHttpResponse *response, const gchar *buffer, size_t offset,
112 size_t length, gpointer _xfer)
114 PurpleXfer *xfer = _xfer;
116 return purple_xfer_write_file(xfer, (const guchar*)buffer, length);
119 static void jabber_oob_xfer_start(PurpleXfer *xfer)
121 PurpleHttpRequest *req;
122 JabberOOBXfer *jox = purple_xfer_get_protocol_data(xfer);
124 req = purple_http_request_new(jox->url);
125 purple_http_request_set_timeout(req, -1);
126 purple_http_request_set_max_len(req, -1);
127 purple_http_request_set_response_writer(req, jabber_oob_xfer_writer,
128 xfer);
129 jox->hc = purple_http_request(jox->js->gc, req, jabber_oob_xfer_got,
130 xfer);
132 purple_http_conn_set_progress_watcher(jox->hc,
133 jabber_oob_xfer_progress_watcher, xfer, -1);
136 static void jabber_oob_xfer_recv_error(PurpleXfer *xfer, const char *code) {
137 JabberOOBXfer *jox = purple_xfer_get_protocol_data(xfer);
138 JabberIq *iq;
139 PurpleXmlNode *y, *z;
141 iq = jabber_iq_new(jox->js, JABBER_IQ_ERROR);
142 purple_xmlnode_set_attrib(iq->node, "to", purple_xfer_get_remote_user(xfer));
143 jabber_iq_set_id(iq, jox->iq_id);
144 y = purple_xmlnode_new_child(iq->node, "error");
145 purple_xmlnode_set_attrib(y, "code", code);
146 if(!strcmp(code, "406")) {
147 z = purple_xmlnode_new_child(y, "not-acceptable");
148 purple_xmlnode_set_attrib(y, "type", "modify");
149 purple_xmlnode_set_namespace(z, NS_XMPP_STANZAS);
150 } else if(!strcmp(code, "404")) {
151 z = purple_xmlnode_new_child(y, "not-found");
152 purple_xmlnode_set_attrib(y, "type", "cancel");
153 purple_xmlnode_set_namespace(z, NS_XMPP_STANZAS);
155 jabber_iq_send(iq);
157 jabber_oob_xfer_free(xfer);
160 static void jabber_oob_xfer_recv_denied(PurpleXfer *xfer) {
161 jabber_oob_xfer_recv_error(xfer, "406");
164 static void jabber_oob_xfer_recv_cancelled(PurpleXfer *xfer) {
165 JabberOOBXfer *jox = purple_xfer_get_protocol_data(xfer);
167 purple_http_conn_cancel(jox->hc);
168 jabber_oob_xfer_recv_error(xfer, "404");
171 void jabber_oob_parse(JabberStream *js, const char *from, JabberIqType type,
172 const char *id, PurpleXmlNode *querynode) {
173 JabberOOBXfer *jox;
174 PurpleXfer *xfer;
175 const gchar *filename, *slash;
176 gchar *url;
177 PurpleXmlNode *urlnode;
179 if(type != JABBER_IQ_SET)
180 return;
182 if(!from)
183 return;
185 if(!(urlnode = purple_xmlnode_get_child(querynode, "url")))
186 return;
188 url = purple_xmlnode_get_data(urlnode);
189 if (!url)
190 return;
192 xfer = purple_xfer_new(purple_connection_get_account(js->gc),
193 PURPLE_XFER_TYPE_RECEIVE, from);
194 if (!xfer) {
195 g_free(url);
196 return;
199 jox = g_new0(JabberOOBXfer, 1);
200 jox->iq_id = g_strdup(id);
201 jox->js = js;
202 jox->url = url;
203 purple_xfer_set_protocol_data(xfer, jox);
205 slash = strrchr(url, '/');
206 if (slash == NULL)
207 filename = url;
208 else
209 filename = slash + 1;
210 purple_xfer_set_filename(xfer, filename);
212 purple_xfer_set_init_fnc(xfer, jabber_oob_xfer_init);
213 purple_xfer_set_end_fnc(xfer, jabber_oob_xfer_end);
214 purple_xfer_set_request_denied_fnc(xfer, jabber_oob_xfer_recv_denied);
215 purple_xfer_set_cancel_recv_fnc(xfer, jabber_oob_xfer_recv_cancelled);
216 purple_xfer_set_start_fnc(xfer, jabber_oob_xfer_start);
218 js->oob_file_transfers = g_list_append(js->oob_file_transfers, xfer);
220 purple_xfer_request(xfer);