Mercurial > pidgin
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 } |