comparison libpurple/ft.c @ 31188:35224e759210

propagate from branch 'im.pidgin.pidgin' (head d5a2e2287440ac7134c201e66921754bd4187ba9) to branch 'im.pidgin.pidgin.openq' (head 98848d977bb3de3cf530c951d157fe8139482675)
author SHiNE CsyFeK <csyfek@gmail.com>
date Tue, 12 Jan 2010 14:22:02 +0000
parents 07ec4a569da1
children a41724547756 dcd52d2b1b97
comparison
equal deleted inserted replaced
31187:befc616a0bf5 31188:35224e759210
67 PurpleXferPrivData *priv = data; 67 PurpleXferPrivData *priv = data;
68 68
69 g_free(priv); 69 g_free(priv);
70 } 70 }
71 71
72 static const gchar *
73 purple_xfer_status_type_to_string(PurpleXferStatusType type)
74 {
75 static const struct {
76 PurpleXferStatusType type;
77 const char *name;
78 } type_names[] = {
79 { PURPLE_XFER_STATUS_UNKNOWN, "unknown" },
80 { PURPLE_XFER_STATUS_NOT_STARTED, "not started" },
81 { PURPLE_XFER_STATUS_ACCEPTED, "accepted" },
82 { PURPLE_XFER_STATUS_STARTED, "started" },
83 { PURPLE_XFER_STATUS_DONE, "done" },
84 { PURPLE_XFER_STATUS_CANCEL_LOCAL, "cancelled locally" },
85 { PURPLE_XFER_STATUS_CANCEL_REMOTE, "cancelled remotely" }
86 };
87 int i;
88
89 for (i = 0; i < G_N_ELEMENTS(type_names); ++i)
90 if (type_names[i].type == type)
91 return type_names[i].name;
92
93 return "invalid state";
94 }
95
72 GList * 96 GList *
73 purple_xfers_get_all() 97 purple_xfers_get_all()
74 { 98 {
75 return xfers; 99 return xfers;
76 } 100 }
107 131
108 if (ui_ops != NULL && ui_ops->new_xfer != NULL) 132 if (ui_ops != NULL && ui_ops->new_xfer != NULL)
109 ui_ops->new_xfer(xfer); 133 ui_ops->new_xfer(xfer);
110 134
111 xfers = g_list_prepend(xfers, xfer); 135 xfers = g_list_prepend(xfers, xfer);
136
137 if (purple_debug_is_verbose())
138 purple_debug_info("xfer", "new %p [%d]\n", xfer, xfer->ref);
139
112 return xfer; 140 return xfer;
113 } 141 }
114 142
115 static void 143 static void
116 purple_xfer_destroy(PurpleXfer *xfer) 144 purple_xfer_destroy(PurpleXfer *xfer)
117 { 145 {
118 PurpleXferUiOps *ui_ops; 146 PurpleXferUiOps *ui_ops;
119 147
120 g_return_if_fail(xfer != NULL); 148 g_return_if_fail(xfer != NULL);
149
150 if (purple_debug_is_verbose())
151 purple_debug_info("xfer", "destroyed %p [%d]\n", xfer, xfer->ref);
121 152
122 /* Close the file browser, if it's open */ 153 /* Close the file browser, if it's open */
123 purple_request_close_with_handle(xfer); 154 purple_request_close_with_handle(xfer);
124 155
125 if (purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_STARTED) 156 if (purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_STARTED)
146 purple_xfer_ref(PurpleXfer *xfer) 177 purple_xfer_ref(PurpleXfer *xfer)
147 { 178 {
148 g_return_if_fail(xfer != NULL); 179 g_return_if_fail(xfer != NULL);
149 180
150 xfer->ref++; 181 xfer->ref++;
182
183 if (purple_debug_is_verbose())
184 purple_debug_info("xfer", "ref'd %p [%d]\n", xfer, xfer->ref);
151 } 185 }
152 186
153 void 187 void
154 purple_xfer_unref(PurpleXfer *xfer) 188 purple_xfer_unref(PurpleXfer *xfer)
155 { 189 {
156 g_return_if_fail(xfer != NULL); 190 g_return_if_fail(xfer != NULL);
157 g_return_if_fail(xfer->ref > 0); 191 g_return_if_fail(xfer->ref > 0);
158 192
159 xfer->ref--; 193 xfer->ref--;
194
195 if (purple_debug_is_verbose())
196 purple_debug_info("xfer", "unref'd %p [%d]\n", xfer, xfer->ref);
160 197
161 if (xfer->ref == 0) 198 if (xfer->ref == 0)
162 purple_xfer_destroy(xfer); 199 purple_xfer_destroy(xfer);
163 } 200 }
164 201
165 static void 202 static void
166 purple_xfer_set_status(PurpleXfer *xfer, PurpleXferStatusType status) 203 purple_xfer_set_status(PurpleXfer *xfer, PurpleXferStatusType status)
167 { 204 {
168 g_return_if_fail(xfer != NULL); 205 g_return_if_fail(xfer != NULL);
206
207 if (purple_debug_is_verbose())
208 purple_debug_info("xfer", "Changing status of xfer %p from %s to %s\n",
209 xfer, purple_xfer_status_type_to_string(xfer->status),
210 purple_xfer_status_type_to_string(status));
169 211
170 if (xfer->status == status) 212 if (xfer->status == status)
171 return; 213 return;
172 214
173 xfer->status = status; 215 xfer->status = status;
227 return; 269 return;
228 270
229 escaped = g_markup_escape_text(message, -1); 271 escaped = g_markup_escape_text(message, -1);
230 272
231 if (is_error) 273 if (is_error)
232 flags = PURPLE_MESSAGE_ERROR; 274 flags |= PURPLE_MESSAGE_ERROR;
233 275
234 purple_conversation_write(conv, NULL, escaped, flags, time(NULL)); 276 purple_conversation_write(conv, NULL, escaped, flags, time(NULL));
235 g_free(escaped); 277 g_free(escaped);
236 } 278 }
237 279
266 308
267 static void 309 static void
268 purple_xfer_choose_file_ok_cb(void *user_data, const char *filename) 310 purple_xfer_choose_file_ok_cb(void *user_data, const char *filename)
269 { 311 {
270 PurpleXfer *xfer; 312 PurpleXfer *xfer;
313 PurpleXferType type;
271 struct stat st; 314 struct stat st;
272 gchar *dir; 315 gchar *dir;
273 316
274 xfer = (PurpleXfer *)user_data; 317 xfer = (PurpleXfer *)user_data;
318 type = purple_xfer_get_type(xfer);
275 319
276 if (g_stat(filename, &st) != 0) { 320 if (g_stat(filename, &st) != 0) {
277 /* File not found. */ 321 /* File not found. */
278 if (purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE) { 322 if (type == PURPLE_XFER_RECEIVE) {
279 #ifndef _WIN32 323 #ifndef _WIN32
280 int mode = W_OK; 324 int mode = W_OK;
281 #else 325 #else
282 int mode = F_OK; 326 int mode = F_OK;
283 #endif 327 #endif
295 339
296 g_free(dir); 340 g_free(dir);
297 } 341 }
298 else { 342 else {
299 purple_xfer_show_file_error(xfer, filename); 343 purple_xfer_show_file_error(xfer, filename);
300 purple_xfer_request_denied(xfer); 344 purple_xfer_cancel_local(xfer);
301 } 345 }
302 } 346 }
303 else if ((purple_xfer_get_type(xfer) == PURPLE_XFER_SEND) && 347 else if ((type == PURPLE_XFER_SEND) && (st.st_size == 0)) {
304 (st.st_size == 0)) {
305 348
306 purple_notify_error(NULL, NULL, 349 purple_notify_error(NULL, NULL,
307 _("Cannot send a file of 0 bytes."), NULL); 350 _("Cannot send a file of 0 bytes."), NULL);
308 351
309 purple_xfer_request_denied(xfer); 352 purple_xfer_cancel_local(xfer);
310 } 353 }
311 else if ((purple_xfer_get_type(xfer) == PURPLE_XFER_SEND) && 354 else if ((type == PURPLE_XFER_SEND) && S_ISDIR(st.st_mode)) {
312 S_ISDIR(st.st_mode)) {
313 /* 355 /*
314 * XXX - Sending a directory should be valid for some protocols. 356 * XXX - Sending a directory should be valid for some protocols.
315 */ 357 */
316 purple_notify_error(NULL, NULL, 358 purple_notify_error(NULL, NULL,
317 _("Cannot send a directory."), NULL); 359 _("Cannot send a directory."), NULL);
318 360
319 purple_xfer_request_denied(xfer); 361 purple_xfer_cancel_local(xfer);
320 } 362 }
321 else if ((purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE) && 363 else if ((type == PURPLE_XFER_RECEIVE) && S_ISDIR(st.st_mode)) {
322 S_ISDIR(st.st_mode)) {
323 char *msg, *utf8; 364 char *msg, *utf8;
324 utf8 = g_filename_to_utf8(filename, -1, NULL, NULL, NULL); 365 utf8 = g_filename_to_utf8(filename, -1, NULL, NULL, NULL);
325 msg = g_strdup_printf( 366 msg = g_strdup_printf(
326 _("%s is not a regular file. Cowardly refusing to overwrite it.\n"), utf8); 367 _("%s is not a regular file. Cowardly refusing to overwrite it.\n"), utf8);
327 g_free(utf8); 368 g_free(utf8);
328 purple_notify_error(NULL, NULL, msg, NULL); 369 purple_notify_error(NULL, NULL, msg, NULL);
329 g_free(msg); 370 g_free(msg);
330 purple_xfer_request_denied(xfer); 371 purple_xfer_request_denied(xfer);
331 } 372 }
373 else if (type == PURPLE_XFER_SEND) {
374 #ifndef _WIN32
375 int mode = R_OK;
376 #else
377 int mode = F_OK;
378 #endif
379
380 if (g_access(filename, mode) == 0) {
381 purple_xfer_request_accepted(xfer, filename);
382 } else {
383 purple_xfer_ref(xfer);
384 purple_notify_message(
385 NULL, PURPLE_NOTIFY_MSG_ERROR, NULL,
386 _("File is not readable."), NULL,
387 (PurpleNotifyCloseCallback)purple_xfer_choose_file, xfer);
388 }
389 }
332 else { 390 else {
333 purple_xfer_request_accepted(xfer, filename); 391 purple_xfer_request_accepted(xfer, filename);
334 } 392 }
335 393
336 purple_xfer_unref(xfer); 394 purple_xfer_unref(xfer);
340 purple_xfer_choose_file_cancel_cb(void *user_data, const char *filename) 398 purple_xfer_choose_file_cancel_cb(void *user_data, const char *filename)
341 { 399 {
342 PurpleXfer *xfer = (PurpleXfer *)user_data; 400 PurpleXfer *xfer = (PurpleXfer *)user_data;
343 401
344 purple_xfer_set_status(xfer, PURPLE_XFER_STATUS_CANCEL_LOCAL); 402 purple_xfer_set_status(xfer, PURPLE_XFER_STATUS_CANCEL_LOCAL);
345 purple_xfer_request_denied(xfer); 403 if (purple_xfer_get_type(xfer) == PURPLE_XFER_SEND)
404 purple_xfer_cancel_local(xfer);
405 else
406 purple_xfer_request_denied(xfer);
407 purple_xfer_unref(xfer);
346 } 408 }
347 409
348 static int 410 static int
349 purple_xfer_choose_file(PurpleXfer *xfer) 411 purple_xfer_choose_file(PurpleXfer *xfer)
350 { 412 {
504 return; 566 return;
505 567
506 type = purple_xfer_get_type(xfer); 568 type = purple_xfer_get_type(xfer);
507 account = purple_xfer_get_account(xfer); 569 account = purple_xfer_get_account(xfer);
508 570
571 purple_debug_misc("xfer", "request accepted for %p\n", xfer);
572
509 if (!filename && type == PURPLE_XFER_RECEIVE) { 573 if (!filename && type == PURPLE_XFER_RECEIVE) {
510 xfer->status = PURPLE_XFER_STATUS_ACCEPTED; 574 xfer->status = PURPLE_XFER_STATUS_ACCEPTED;
511 xfer->ops.init(xfer); 575 xfer->ops.init(xfer);
512 return; 576 return;
513 } 577 }
580 644
581 void 645 void
582 purple_xfer_request_denied(PurpleXfer *xfer) 646 purple_xfer_request_denied(PurpleXfer *xfer)
583 { 647 {
584 g_return_if_fail(xfer != NULL); 648 g_return_if_fail(xfer != NULL);
649
650 purple_debug_misc("xfer", "xfer %p denied\n", xfer);
585 651
586 if (xfer->ops.request_denied != NULL) 652 if (xfer->ops.request_denied != NULL)
587 xfer->ops.request_denied(xfer); 653 xfer->ops.request_denied(xfer);
588 654
589 purple_xfer_unref(xfer); 655 purple_xfer_unref(xfer);
1028 * UI isn't ready to send data. It will call 1094 * UI isn't ready to send data. It will call
1029 * purple_xfer_ui_ready when ready, which sets back up this 1095 * purple_xfer_ui_ready when ready, which sets back up this
1030 * watcher. 1096 * watcher.
1031 */ 1097 */
1032 if (xfer->watcher != 0) { 1098 if (xfer->watcher != 0) {
1033 purple_timeout_remove(xfer->watcher); 1099 purple_input_remove(xfer->watcher);
1034 xfer->watcher = 0; 1100 xfer->watcher = 0;
1035 } 1101 }
1036 1102
1037 return; 1103 return;
1038 } else if (tmp < 0) { 1104 } else if (tmp < 0) {
1109 if (0 == (priv->ready & PURPLE_XFER_READY_UI)) { 1175 if (0 == (priv->ready & PURPLE_XFER_READY_UI)) {
1110 priv->ready |= PURPLE_XFER_READY_PRPL; 1176 priv->ready |= PURPLE_XFER_READY_PRPL;
1111 1177
1112 purple_input_remove(xfer->watcher); 1178 purple_input_remove(xfer->watcher);
1113 xfer->watcher = 0; 1179 xfer->watcher = 0;
1180
1181 purple_debug_misc("xfer", "prpl is ready on ft %p, waiting for UI\n", xfer);
1114 return; 1182 return;
1115 } 1183 }
1116 } 1184 }
1117 1185
1118 do_transfer(xfer); 1186 do_transfer(xfer);
1171 g_return_if_fail(xfer != NULL); 1239 g_return_if_fail(xfer != NULL);
1172 1240
1173 priv = g_hash_table_lookup(xfers_data, xfer); 1241 priv = g_hash_table_lookup(xfers_data, xfer);
1174 priv->ready |= PURPLE_XFER_READY_UI; 1242 priv->ready |= PURPLE_XFER_READY_UI;
1175 1243
1176 if (0 == (priv->ready & PURPLE_XFER_READY_PRPL)) 1244 if (0 == (priv->ready & PURPLE_XFER_READY_PRPL)) {
1245 purple_debug_misc("xfer", "UI is ready on ft %p, waiting for prpl\n", xfer);
1177 return; 1246 return;
1247 }
1248
1249 purple_debug_misc("xfer", "UI (and prpl) ready on ft %p, so proceeding\n", xfer);
1178 1250
1179 type = purple_xfer_get_type(xfer); 1251 type = purple_xfer_get_type(xfer);
1180 if (type == PURPLE_XFER_SEND) 1252 if (type == PURPLE_XFER_SEND)
1181 cond = PURPLE_INPUT_WRITE; 1253 cond = PURPLE_INPUT_WRITE;
1182 else /* if (type == PURPLE_XFER_RECEIVE) */ 1254 else /* if (type == PURPLE_XFER_RECEIVE) */
1199 1271
1200 priv = g_hash_table_lookup(xfers_data, xfer); 1272 priv = g_hash_table_lookup(xfers_data, xfer);
1201 priv->ready |= PURPLE_XFER_READY_PRPL; 1273 priv->ready |= PURPLE_XFER_READY_PRPL;
1202 1274
1203 /* I don't think fwrite/fread are ever *not* ready */ 1275 /* I don't think fwrite/fread are ever *not* ready */
1204 if (xfer->dest_fp == NULL && 0 == (priv->ready & PURPLE_XFER_READY_UI)) 1276 if (xfer->dest_fp == NULL && 0 == (priv->ready & PURPLE_XFER_READY_UI)) {
1277 purple_debug_misc("xfer", "prpl is ready on ft %p, waiting for UI\n", xfer);
1205 return; 1278 return;
1279 }
1280
1281 purple_debug_misc("xfer", "Prpl (and UI) ready on ft %p, so proceeding\n", xfer);
1206 1282
1207 priv->ready = PURPLE_XFER_READY_NONE; 1283 priv->ready = PURPLE_XFER_READY_NONE;
1208 1284
1209 do_transfer(xfer); 1285 do_transfer(xfer);
1210 } 1286 }