comparison src/ft.c @ 7805:5f0bb52c0609

[gaim-migrate @ 8452] File transfer changes from marv. This fixes various ft related bugs, including: * Sometimes clicking cancel on a send would crash. * We seemed to leak the GaimXfer most of the time. * Choosing to not overwrite the file would cancel the receive altogether. This should fix all these issues. It would be nice if someone (SimGuy?) could test this for me, especially on windows, to make sure i didn't break anything. Jabber ft is untested, althoughi didn't make any changes in the jabber source. So, it should still work, i just can't comfirm it. Yahoo and OSCAR do still work. Amoung other things, this patch impliments some reference counting on the GaimXfer, so the ui can keep it around a while if it wants, without leaking it because we're afraid to destroy it. committer: Tailor Script <tailor@pidgin.im>
author Mark Doliner <mark@kingant.net>
date Mon, 08 Dec 2003 04:58:07 +0000
parents b14442b31a9b
children 8e60ddc28a22
comparison
equal deleted inserted replaced
7804:622c9149609c 7805:5f0bb52c0609
38 g_return_val_if_fail(account != NULL, NULL); 38 g_return_val_if_fail(account != NULL, NULL);
39 g_return_val_if_fail(who != NULL, NULL); 39 g_return_val_if_fail(who != NULL, NULL);
40 40
41 xfer = g_new0(GaimXfer, 1); 41 xfer = g_new0(GaimXfer, 1);
42 42
43 xfer->ref = 1;
43 xfer->type = type; 44 xfer->type = type;
44 xfer->account = account; 45 xfer->account = account;
45 xfer->who = g_strdup(who); 46 xfer->who = g_strdup(who);
46 xfer->ui_ops = gaim_xfers_get_ui_ops(); 47 xfer->ui_ops = gaim_xfers_get_ui_ops();
47 48
53 ui_ops->new_xfer(xfer); 54 ui_ops->new_xfer(xfer);
54 55
55 return xfer; 56 return xfer;
56 } 57 }
57 58
58 void 59 static void
59 gaim_xfer_destroy(GaimXfer *xfer) 60 gaim_xfer_destroy(GaimXfer *xfer)
60 { 61 {
61 GaimXferUiOps *ui_ops; 62 GaimXferUiOps *ui_ops;
62 63
63 g_return_if_fail(xfer != NULL); 64 g_return_if_fail(xfer != NULL);
64 65
65 if (!xfer->completed) 66 if (gaim_xfer_get_status(xfer) == GAIM_XFER_STATUS_STARTED)
66 gaim_xfer_cancel_local(xfer); 67 gaim_xfer_cancel_local(xfer);
67 68
68 ui_ops = gaim_xfer_get_ui_ops(xfer); 69 ui_ops = gaim_xfer_get_ui_ops(xfer);
69 70
70 if (ui_ops != NULL && ui_ops->destroy != NULL) 71 if (ui_ops != NULL && ui_ops->destroy != NULL)
81 82
82 g_free(xfer); 83 g_free(xfer);
83 } 84 }
84 85
85 void 86 void
87 gaim_xfer_ref(GaimXfer *xfer)
88 {
89 g_return_if_fail(xfer != NULL);
90
91 xfer->ref++;
92 }
93
94 void
95 gaim_xfer_unref(GaimXfer *xfer)
96 {
97 g_return_if_fail(xfer != NULL);
98
99 xfer->ref--;
100
101 if (xfer->ref == 0)
102 gaim_xfer_destroy(xfer);
103 }
104
105 void
86 gaim_xfer_request(GaimXfer *xfer) 106 gaim_xfer_request(GaimXfer *xfer)
87 { 107 {
88 GaimXferUiOps *ui_ops; 108 GaimXferUiOps *ui_ops;
89 109
90 g_return_if_fail(xfer != NULL); 110 g_return_if_fail(xfer != NULL);
97 117
98 ui_ops->request_file(xfer); 118 ui_ops->request_file(xfer);
99 } 119 }
100 120
101 void 121 void
102 gaim_xfer_request_accepted(GaimXfer *xfer, char *filename) 122 gaim_xfer_request_accepted(GaimXfer *xfer, const char *filename)
103 { 123 {
104 GaimXferType type; 124 GaimXferType type;
105 125
106 if (xfer == NULL || filename == NULL) { 126 if (xfer == NULL || filename == NULL) {
107
108 if (filename != NULL)
109 g_free(filename);
110
111 return; 127 return;
112 } 128 }
113 129
114 type = gaim_xfer_get_type(xfer); 130 type = gaim_xfer_get_type(xfer);
115 131
124 filename); 140 filename);
125 141
126 gaim_xfer_error(type, xfer->who, msg); 142 gaim_xfer_error(type, xfer->who, msg);
127 143
128 g_free(msg); 144 g_free(msg);
129 g_free(filename); 145 gaim_xfer_unref(xfer);
130
131 return; 146 return;
132 } 147 }
133 148
134 if (stat(filename, &sb) == -1) { 149 if (stat(filename, &sb) == -1) {
135 char *msg; 150 char *msg;
137 msg = g_strdup_printf(_("%s was not found.\n"), filename); 152 msg = g_strdup_printf(_("%s was not found.\n"), filename);
138 153
139 gaim_xfer_error(type, xfer->who, msg); 154 gaim_xfer_error(type, xfer->who, msg);
140 155
141 g_free(msg); 156 g_free(msg);
142 g_free(filename); 157 gaim_xfer_unref(xfer);
143
144 return; 158 return;
145 } 159 }
146 160
147 gaim_xfer_set_local_filename(xfer, filename); 161 gaim_xfer_set_local_filename(xfer, filename);
148 gaim_xfer_set_size(xfer, sb.st_size); 162 gaim_xfer_set_size(xfer, sb.st_size);
151 /* TODO: Sanity checks and file overwrite checks. */ 165 /* TODO: Sanity checks and file overwrite checks. */
152 166
153 gaim_xfer_set_local_filename(xfer, filename); 167 gaim_xfer_set_local_filename(xfer, filename);
154 } 168 }
155 169
156 g_free(filename);
157 170
158 xfer->ops.init(xfer); 171 xfer->ops.init(xfer);
159 } 172 }
160 173
161 void 174 void
162 gaim_xfer_request_denied(GaimXfer *xfer) 175 gaim_xfer_request_denied(GaimXfer *xfer)
163 { 176 {
164 g_return_if_fail(xfer != NULL); 177 g_return_if_fail(xfer != NULL);
165 178
166 gaim_xfer_destroy(xfer); 179 if (xfer->ops.request_denied != NULL)
167 180 xfer->ops.request_denied(xfer);
168 /* TODO */ 181
182 gaim_xfer_unref(xfer);
169 } 183 }
170 184
171 GaimXferType 185 GaimXferType
172 gaim_xfer_get_type(const GaimXfer *xfer) 186 gaim_xfer_get_type(const GaimXfer *xfer)
173 { 187 {
182 g_return_val_if_fail(xfer != NULL, NULL); 196 g_return_val_if_fail(xfer != NULL, NULL);
183 197
184 return xfer->account; 198 return xfer->account;
185 } 199 }
186 200
187 GaimXferCancelType 201 GaimXferStatusType
202 gaim_xfer_get_status(const GaimXfer *xfer)
203 {
204 g_return_val_if_fail(xfer != NULL, GAIM_XFER_STATUS_UNKNOWN);
205
206 return xfer->status;
207 }
208
209 gboolean
188 gaim_xfer_is_canceled(const GaimXfer *xfer) 210 gaim_xfer_is_canceled(const GaimXfer *xfer)
189 { 211 {
190 g_return_val_if_fail(xfer != NULL, TRUE); 212 g_return_val_if_fail(xfer != NULL, TRUE);
191 213
192 return xfer->canceled; 214 if ((gaim_xfer_get_status(xfer) == GAIM_XFER_STATUS_CANCEL_LOCAL) ||
215 (gaim_xfer_get_status(xfer) == GAIM_XFER_STATUS_CANCEL_REMOTE))
216 return TRUE;
217 else
218 return FALSE;
193 } 219 }
194 220
195 gboolean 221 gboolean
196 gaim_xfer_is_completed(const GaimXfer *xfer) 222 gaim_xfer_is_completed(const GaimXfer *xfer)
197 { 223 {
198 g_return_val_if_fail(xfer != NULL, TRUE); 224 g_return_val_if_fail(xfer != NULL, TRUE);
199 225
200 return xfer->completed; 226 return (gaim_xfer_get_status(xfer) == GAIM_XFER_STATUS_DONE);
201 } 227 }
202 228
203 const char * 229 const char *
204 gaim_xfer_get_filename(const GaimXfer *xfer) 230 gaim_xfer_get_filename(const GaimXfer *xfer)
205 { 231 {
283 309
284 return xfer->remote_port; 310 return xfer->remote_port;
285 } 311 }
286 312
287 static void 313 static void
288 gaim_xfer_set_canceled(GaimXfer *xfer, GaimXferCancelType canceled) 314 gaim_xfer_set_status(GaimXfer *xfer, GaimXferStatusType status)
289 { 315 {
290 g_return_if_fail(xfer != NULL); 316 g_return_if_fail(xfer != NULL);
291 317
292 xfer->canceled = canceled; 318 xfer->status = status;
293 } 319 }
294 320
295 void 321 void
296 gaim_xfer_set_completed(GaimXfer *xfer, gboolean completed) 322 gaim_xfer_set_completed(GaimXfer *xfer, gboolean completed)
297 { 323 {
298 GaimXferUiOps *ui_ops; 324 GaimXferUiOps *ui_ops;
299 325
300 g_return_if_fail(xfer != NULL); 326 g_return_if_fail(xfer != NULL);
301 327
302 xfer->completed = completed; 328 if (completed == TRUE)
329 gaim_xfer_set_status(xfer, GAIM_XFER_STATUS_DONE);
303 330
304 ui_ops = gaim_xfer_get_ui_ops(xfer); 331 ui_ops = gaim_xfer_get_ui_ops(xfer);
305 332
306 if (ui_ops != NULL && ui_ops->update_progress != NULL) 333 if (ui_ops != NULL && ui_ops->update_progress != NULL)
307 ui_ops->update_progress(xfer, gaim_xfer_get_progress(xfer)); 334 ui_ops->update_progress(xfer, gaim_xfer_get_progress(xfer));
355 g_return_if_fail(xfer != NULL); 382 g_return_if_fail(xfer != NULL);
356 383
357 xfer->ops.init = fnc; 384 xfer->ops.init = fnc;
358 } 385 }
359 386
387 void gaim_xfer_set_request_denied_fnc(GaimXfer *xfer, void (*fnc)(GaimXfer *))
388 {
389 g_return_if_fail(xfer != NULL);
390
391 xfer->ops.request_denied = fnc;
392 }
360 393
361 void 394 void
362 gaim_xfer_set_read_fnc(GaimXfer *xfer, size_t (*fnc)(char **, GaimXfer *)) 395 gaim_xfer_set_read_fnc(GaimXfer *xfer, size_t (*fnc)(char **, GaimXfer *))
363 { 396 {
364 g_return_if_fail(xfer != NULL); 397 g_return_if_fail(xfer != NULL);
563 type = gaim_xfer_get_type(xfer); 596 type = gaim_xfer_get_type(xfer);
564 597
565 xfer->bytes_remaining = gaim_xfer_get_size(xfer); 598 xfer->bytes_remaining = gaim_xfer_get_size(xfer);
566 xfer->bytes_sent = 0; 599 xfer->bytes_sent = 0;
567 600
601 gaim_xfer_set_status(xfer, GAIM_XFER_STATUS_STARTED);
602
568 if (type == GAIM_XFER_RECEIVE) { 603 if (type == GAIM_XFER_RECEIVE) {
569 cond = GAIM_INPUT_READ; 604 cond = GAIM_INPUT_READ;
570 605
571 if (ip != NULL) { 606 if (ip != NULL) {
572 xfer->remote_ip = g_strdup(ip); 607 xfer->remote_ip = g_strdup(ip);
595 gaim_xfer_end(GaimXfer *xfer) 630 gaim_xfer_end(GaimXfer *xfer)
596 { 631 {
597 g_return_if_fail(xfer != NULL); 632 g_return_if_fail(xfer != NULL);
598 633
599 /* See if we are actually trying to cancel this. */ 634 /* See if we are actually trying to cancel this. */
600 if (!xfer->completed) { 635 if (gaim_xfer_get_status(xfer) != GAIM_XFER_STATUS_DONE) {
601 gaim_xfer_cancel_local(xfer); 636 gaim_xfer_cancel_local(xfer);
602 return; 637 return;
603 } 638 }
604 639
605 if (xfer->ops.end != NULL) 640 if (xfer->ops.end != NULL)
615 650
616 if (xfer->dest_fp != NULL) { 651 if (xfer->dest_fp != NULL) {
617 fclose(xfer->dest_fp); 652 fclose(xfer->dest_fp);
618 xfer->dest_fp = NULL; 653 xfer->dest_fp = NULL;
619 } 654 }
655
656 gaim_xfer_unref(xfer);
620 } 657 }
621 658
622 void 659 void
623 gaim_xfer_cancel_local(GaimXfer *xfer) 660 gaim_xfer_cancel_local(GaimXfer *xfer)
624 { 661 {
625 GaimXferUiOps *ui_ops; 662 GaimXferUiOps *ui_ops;
626 663
627 g_return_if_fail(xfer != NULL); 664 g_return_if_fail(xfer != NULL);
628 665
629 gaim_xfer_set_canceled(xfer, GAIM_XFER_CANCEL_LOCAL); 666 gaim_xfer_set_status(xfer, GAIM_XFER_STATUS_CANCEL_LOCAL);
630 667
631 if (gaim_xfer_get_type(xfer) == GAIM_XFER_SEND) 668 if (gaim_xfer_get_type(xfer) == GAIM_XFER_SEND)
632 { 669 {
633 if (xfer->ops.cancel_send != NULL) 670 if (xfer->ops.cancel_send != NULL)
634 xfer->ops.cancel_send(xfer); 671 xfer->ops.cancel_send(xfer);
656 693
657 if (ui_ops != NULL && ui_ops->cancel_local != NULL) 694 if (ui_ops != NULL && ui_ops->cancel_local != NULL)
658 ui_ops->cancel_local(xfer); 695 ui_ops->cancel_local(xfer);
659 696
660 xfer->bytes_remaining = 0; 697 xfer->bytes_remaining = 0;
698
699 gaim_xfer_unref(xfer);
661 } 700 }
662 701
663 void 702 void
664 gaim_xfer_cancel_remote(GaimXfer *xfer) 703 gaim_xfer_cancel_remote(GaimXfer *xfer)
665 { 704 {
666 GaimXferUiOps *ui_ops; 705 GaimXferUiOps *ui_ops;
667 706
668 g_return_if_fail(xfer != NULL); 707 g_return_if_fail(xfer != NULL);
669 708
670 gaim_xfer_set_canceled(xfer, GAIM_XFER_CANCEL_REMOTE); 709 gaim_xfer_set_status(xfer, GAIM_XFER_STATUS_CANCEL_REMOTE);
671 710
672 if (gaim_xfer_get_type(xfer) == GAIM_XFER_SEND) 711 if (gaim_xfer_get_type(xfer) == GAIM_XFER_SEND)
673 { 712 {
674 if (xfer->ops.cancel_send != NULL) 713 if (xfer->ops.cancel_send != NULL)
675 xfer->ops.cancel_send(xfer); 714 xfer->ops.cancel_send(xfer);
697 736
698 if (ui_ops != NULL && ui_ops->cancel_remote != NULL) 737 if (ui_ops != NULL && ui_ops->cancel_remote != NULL)
699 ui_ops->cancel_remote(xfer); 738 ui_ops->cancel_remote(xfer);
700 739
701 xfer->bytes_remaining = 0; 740 xfer->bytes_remaining = 0;
741
742 gaim_xfer_unref(xfer);
702 } 743 }
703 744
704 void 745 void
705 gaim_xfer_error(GaimXferType type, const char *who, const char *msg) 746 gaim_xfer_error(GaimXferType type, const char *who, const char *msg)
706 { 747 {