Statistics
| Revision:

root / src / recv.c @ 1

History | View | Annotate | Download (4.78 KB)

1
/*
2
 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3
 * Copyright (C) 1999-2001 Hiroyuki Yamamoto
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation; either version 2 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
 */
19

    
20
#ifdef HAVE_CONFIG_H
21
#  include "config.h"
22
#endif
23

    
24
#include "defs.h"
25

    
26
#include <glib.h>
27
#include <stdio.h>
28
#include <string.h>
29
#include <unistd.h>
30
#include <sys/time.h>
31

    
32
#include "intl.h"
33
#include "recv.h"
34
#include "socket.h"
35
#include "utils.h"
36

    
37
static RecvUIFunc        recv_ui_func;
38
static gpointer                recv_ui_func_data;
39

    
40
gint recv_write_to_file(SockInfo *sock, const gchar *filename)
41
{
42
        FILE *fp;
43
        gint ret;
44

    
45
        g_return_val_if_fail(filename != NULL, -1);
46

    
47
        if ((fp = fopen(filename, "wb")) == NULL) {
48
                FILE_OP_ERROR(filename, "fopen");
49
                recv_write(sock, NULL);
50
                return -1;
51
        }
52

    
53
        if (change_file_mode_rw(fp, filename) < 0)
54
                FILE_OP_ERROR(filename, "chmod");
55

    
56
        if ((ret = recv_write(sock, fp)) < 0) {
57
                fclose(fp);
58
                unlink(filename);
59
                return ret;
60
        }
61

    
62
        if (fclose(fp) == EOF) {
63
                FILE_OP_ERROR(filename, "fclose");
64
                unlink(filename);
65
                return -1;
66
        }
67

    
68
        return 0;
69
}
70

    
71
gint recv_bytes_write_to_file(SockInfo *sock, glong size, const gchar *filename)
72
{
73
        FILE *fp;
74
        gint ret;
75

    
76
        g_return_val_if_fail(filename != NULL, -1);
77

    
78
        if ((fp = fopen(filename, "wb")) == NULL) {
79
                FILE_OP_ERROR(filename, "fopen");
80
                recv_write(sock, NULL);
81
                return -1;
82
        }
83

    
84
        if (change_file_mode_rw(fp, filename) < 0)
85
                FILE_OP_ERROR(filename, "chmod");
86

    
87
        if ((ret = recv_bytes_write(sock, size, fp)) < 0) {
88
                fclose(fp);
89
                unlink(filename);
90
                return ret;
91
        }
92

    
93
        if (fclose(fp) == EOF) {
94
                FILE_OP_ERROR(filename, "fclose");
95
                unlink(filename);
96
                return -1;
97
        }
98

    
99
        return 0;
100
}
101

    
102
gint recv_write(SockInfo *sock, FILE *fp)
103
{
104
        gchar buf[BUFFSIZE];
105
        gint len;
106
        gint count = 0;
107
        gint bytes = 0;
108
        struct timeval tv_prev, tv_cur;
109

    
110
        gettimeofday(&tv_prev, NULL);
111

    
112
        for (;;) {
113
                if (sock_gets(sock, buf, sizeof(buf)) < 0) {
114
                        g_warning(_("error occurred while retrieving data.\n"));
115
                        return -2;
116
                }
117

    
118
                len = strlen(buf);
119
                if (len > 1 && buf[0] == '.' && buf[1] == '\r') {
120
                        if (recv_ui_func)
121
                                recv_ui_func(sock, count, bytes,
122
                                             recv_ui_func_data);
123
                        break;
124
                }
125
                count++;
126
                bytes += len;
127

    
128
                if (recv_ui_func) {
129
                        gettimeofday(&tv_cur, NULL);
130
                        /* if elapsed time from previous update is greater
131
                           than 50msec, update UI */
132
                        if (tv_cur.tv_sec - tv_prev.tv_sec > 0 ||
133
                            tv_cur.tv_usec - tv_prev.tv_usec > UI_REFRESH_INTERVAL) {
134
                                gboolean ret;
135
                                ret = recv_ui_func(sock, count, bytes,
136
                                                   recv_ui_func_data);
137
                                if (ret == FALSE) return -1;
138
                                gettimeofday(&tv_prev, NULL);
139
                        }
140
                }
141

    
142
                if (len > 1 && buf[len - 1] == '\n' && buf[len - 2] == '\r') {
143
                        buf[len - 2] = '\n';
144
                        buf[len - 1] = '\0';
145
                        len--;
146
                }
147

    
148
                if (buf[0] == '.' && buf[1] == '.')
149
                        memmove(buf, buf + 1, len--);
150

    
151
                if (!strncmp(buf, ">From ", 6))
152
                        memmove(buf, buf + 1, len--);
153

    
154
                if (fp && fputs(buf, fp) == EOF) {
155
                        perror("fputs");
156
                        g_warning(_("Can't write to file.\n"));
157
                        fp = NULL;
158
                }
159
        }
160

    
161
        if (!fp) return -1;
162

    
163
        return 0;
164
}
165

    
166
gint recv_bytes_write(SockInfo *sock, glong size, FILE *fp)
167
{
168
        gchar *buf;
169
        glong count = 0;
170
        gchar *prev, *cur;
171

    
172
        if (size == 0)
173
                return 0;
174

    
175
        buf = g_malloc(size);
176

    
177
        do {
178
                gint read_count;
179

    
180
                read_count = sock_read(sock, buf + count, size - count);
181
                if (read_count < 0) {
182
                        g_free(buf);
183
                        return -2;
184
                }
185
                count += read_count;
186
        } while (count < size);
187

    
188
        /* +------------------+----------------+--------------------------+ *
189
         * ^buf               ^prev            ^cur             buf+size-1^ */
190

    
191
        prev = buf;
192
        while ((cur = memchr(prev, '\r', size - (prev - buf))) != NULL) {
193
                if (cur == buf + size - 1) break;
194

    
195
                if (fwrite(prev, sizeof(gchar), cur - prev, fp) == EOF ||
196
                    fwrite("\n", sizeof(gchar), 1, fp) == EOF) {
197
                        perror("fwrite");
198
                        g_warning(_("Can't write to file.\n"));
199
                        g_free(buf);
200
                        return -1;
201
                }
202

    
203
                if (*(cur + 1) == '\n')
204
                        prev = cur + 2;
205
                else
206
                        prev = cur + 1;
207

    
208
                if (prev - buf >= size) break;
209
        }
210

    
211
        if (prev - buf < size && fwrite(buf, sizeof(gchar),
212
                                        size - (prev - buf), fp) == EOF) {
213
                perror("fwrite");
214
                g_warning(_("Can't write to file.\n"));
215
                g_free(buf);
216
                return -1;
217
        }
218

    
219
        g_free(buf);
220
        return 0;
221
}
222

    
223
void recv_set_ui_func(RecvUIFunc func, gpointer data)
224
{
225
        recv_ui_func = func;
226
        recv_ui_func_data = data;
227
}