summaryrefslogtreecommitdiff
path: root/libsylph/recv.c
diff options
context:
space:
mode:
authorSimeon Simeonov2018-02-26 11:23:00 +0100
committerSimeon Simeonov2018-02-26 11:23:00 +0100
commit0b3cbf57875fd692e4ba0b336fefa4bee1ed00dc (patch)
treeaf916a30553c78ce9d4f2d8658656a175c5b6921 /libsylph/recv.c
Initial commit for sylpheed 3.7.0
Diffstat (limited to 'libsylph/recv.c')
-rw-r--r--libsylph/recv.c245
1 files changed, 245 insertions, 0 deletions
diff --git a/libsylph/recv.c b/libsylph/recv.c
new file mode 100644
index 0000000..6ed4db2
--- /dev/null
+++ b/libsylph/recv.c
@@ -0,0 +1,245 @@
1/*
2 * LibSylph -- E-Mail client library
3 * Copyright (C) 1999-2014 Hiroyuki Yamamoto
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library 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 GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 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 <glib/gi18n.h>
28#include <stdio.h>
29#include <string.h>
30#include <unistd.h>
31
32#include "recv.h"
33#include "socket.h"
34#include "utils.h"
35
36static RecvUIFunc recv_ui_func;
37static gpointer recv_ui_func_data;
38
39
40gchar *recv_bytes(SockInfo *sock, glong size)
41{
42 gchar *buf;
43 glong count = 0;
44
45 if (size == 0)
46 return NULL;
47
48 buf = g_malloc(size + 1);
49
50 do {
51 gint read_count;
52
53 read_count = sock_read(sock, buf + count,
54 MIN(BUFFSIZE, size - count));
55 if (read_count <= 0) {
56 g_free(buf);
57 return NULL;
58 }
59 count += read_count;
60 } while (count < size);
61
62 buf[size] = '\0';
63
64 return buf;
65}
66
67gint recv_write_to_file(SockInfo *sock, const gchar *filename)
68{
69 FILE *fp;
70 gint ret;
71
72 g_return_val_if_fail(filename != NULL, -1);
73
74 if ((fp = g_fopen(filename, "wb")) == NULL) {
75 FILE_OP_ERROR(filename, "fopen");
76 recv_write(sock, NULL);
77 return -1;
78 }
79
80 if (change_file_mode_rw(fp, filename) < 0)
81 FILE_OP_ERROR(filename, "chmod");
82
83 if ((ret = recv_write(sock, fp)) < 0) {
84 fclose(fp);
85 g_unlink(filename);
86 return ret;
87 }
88
89 if (fclose(fp) == EOF) {
90 FILE_OP_ERROR(filename, "fclose");
91 g_unlink(filename);
92 return -1;
93 }
94
95 return 0;
96}
97
98gint recv_bytes_write_to_file(SockInfo *sock, glong size, const gchar *filename)
99{
100 FILE *fp;
101 gint ret;
102
103 g_return_val_if_fail(filename != NULL, -1);
104
105 if ((fp = g_fopen(filename, "wb")) == NULL) {
106 FILE_OP_ERROR(filename, "fopen");
107 return recv_bytes_write(sock, size, NULL);
108 }
109
110 if (change_file_mode_rw(fp, filename) < 0)
111 FILE_OP_ERROR(filename, "chmod");
112
113 if ((ret = recv_bytes_write(sock, size, fp)) < 0) {
114 fclose(fp);
115 g_unlink(filename);
116 return ret;
117 }
118
119 if (fclose(fp) == EOF) {
120 FILE_OP_ERROR(filename, "fclose");
121 g_unlink(filename);
122 return -1;
123 }
124
125 return 0;
126}
127
128gint recv_write(SockInfo *sock, FILE *fp)
129{
130 gchar buf[BUFFSIZE];
131 gint len;
132 gint count = 0;
133 gint bytes = 0;
134 gchar *p;
135 GTimeVal tv_prev, tv_cur;
136
137 g_get_current_time(&tv_prev);
138
139 for (;;) {
140 if (sock_gets(sock, buf, sizeof(buf)) < 0) {
141 g_warning(_("error occurred while retrieving data.\n"));
142 return -2;
143 }
144
145 len = strlen(buf);
146 if (len > 1 && buf[0] == '.' && buf[1] == '\r') {
147 if (recv_ui_func)
148 recv_ui_func(sock, count, bytes,
149 recv_ui_func_data);
150 break;
151 }
152 count++;
153 bytes += len;
154
155 if (recv_ui_func) {
156 g_get_current_time(&tv_cur);
157 /* if elapsed time from previous update is greater
158 than 50msec, update UI */
159 if (tv_cur.tv_sec - tv_prev.tv_sec > 0 ||
160 tv_cur.tv_usec - tv_prev.tv_usec > UI_REFRESH_INTERVAL) {
161 gboolean ret;
162 ret = recv_ui_func(sock, count, bytes,
163 recv_ui_func_data);
164 if (ret == FALSE) return -1;
165 g_get_current_time(&tv_prev);
166 }
167 }
168
169 p = buf;
170
171 if (len > 1 && buf[len - 1] == '\n' && buf[len - 2] == '\r') {
172 buf[len - 2] = '\n';
173 buf[len - 1] = '\0';
174 }
175
176 if (buf[0] == '.' && buf[1] == '.')
177 p++;
178 else if (!strncmp(buf, ">From ", 6))
179 p++;
180
181 if (fp && fputs(p, fp) == EOF) {
182 perror("fputs");
183 g_warning(_("Can't write to file.\n"));
184 fp = NULL;
185 }
186 }
187
188 if (!fp) return -1;
189
190 return 0;
191}
192
193gint recv_bytes_write(SockInfo *sock, glong size, FILE *fp)
194{
195 gchar *buf;
196 gchar *prev, *cur;
197
198 if (size == 0)
199 return 0;
200
201 buf = recv_bytes(sock, size);
202 if (!buf)
203 return -2;
204
205 /* +------------------+----------------+--------------------------+ *
206 * ^buf ^prev ^cur buf+size-1^ */
207
208 prev = buf;
209 while ((cur = memchr(prev, '\r', size - (prev - buf))) != NULL) {
210 if (cur == buf + size - 1) break;
211
212 if (fp && (fwrite(prev, sizeof(gchar), cur - prev, fp) == EOF ||
213 fwrite("\n", sizeof(gchar), 1, fp) == EOF)) {
214 perror("fwrite");
215 g_warning(_("Can't write to file.\n"));
216 fp = NULL;
217 }
218
219 if (*(cur + 1) == '\n')
220 prev = cur + 2;
221 else
222 prev = cur + 1;
223
224 if (prev - buf >= size) break;
225 }
226
227 if (prev - buf < size && fp &&
228 fwrite(prev, sizeof(gchar), size - (prev - buf), fp) == EOF) {
229 perror("fwrite");
230 g_warning(_("Can't write to file.\n"));
231 fp = NULL;
232 }
233
234 g_free(buf);
235
236 if (!fp) return -1;
237
238 return 0;
239}
240
241void recv_set_ui_func(RecvUIFunc func, gpointer data)
242{
243 recv_ui_func = func;
244 recv_ui_func_data = data;
245}