Add a more generic mbox wrapper
[cygwin-setup.git] / geturl.cc
blob321259e8f078f786ef0659f3a18ae258cd4aabe5
1 /*
4 * Copyright (c) 2000, 2001, Red Hat, Inc.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * A copy of the GNU General Public License can be found at
12 * http://www.gnu.org/
14 * Written by DJ Delorie <dj@cygnus.com>
18 /* The purpose of this file is to act as a pretty interface to
19 netio.cc. We add a progress dialog and some convenience functions
20 (like collect to string or file */
22 #include "win32.h"
23 #include "commctrl.h"
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <errno.h>
29 #include "dialog.h"
30 #include "geturl.h"
31 #include "resource.h"
32 #include "netio.h"
33 #include "msg.h"
34 #include "io_stream.h"
35 #include "io_stream_memory.h"
36 #include "state.h"
37 #include "diskfull.h"
38 #include "mount.h"
39 #include "filemanip.h"
41 #include "threebar.h"
43 #include "Exception.h"
45 #include "LogSingleton.h"
47 extern ThreeBarProgressPage Progress;
49 static int max_bytes = 0;
50 static int is_local_install = 0;
52 long long int total_download_bytes = 0;
53 long long int total_download_bytes_sofar = 0;
55 static DWORD start_tics;
57 static void
58 init_dialog (const std::string &url, int length)
60 if (is_local_install)
61 return;
63 std::string::size_type divide = url.find_last_of('/');
64 max_bytes = length;
65 Progress.SetText1(IDS_PROGRESS_DOWNLOADING);
66 Progress.SetText2((url.substr(divide + 1) + " from "
67 + url.substr(0, divide)).c_str());
68 Progress.SetText3(IDS_PROGRESS_CONNECTING);
69 Progress.SetBar1(0);
70 start_tics = GetTickCount ();
74 static void
75 progress (int bytes)
77 if (is_local_install)
78 return;
79 static char buf[100];
80 double kbps;
81 static unsigned int last_tics = 0;
82 DWORD tics = GetTickCount ();
83 if (tics == start_tics) // to prevent division by zero
84 return;
85 if (tics < last_tics + 200) // to prevent flickering updates
86 return;
87 last_tics = tics;
89 kbps = ((double)bytes) / (double)(tics - start_tics);
90 if (max_bytes > 0)
92 int perc = (int)(100.0 * ((double)bytes) / (double)max_bytes);
93 Progress.SetBar1(bytes, max_bytes);
94 sprintf (buf, "%d %% (%dk/%dk) %03.1f kB/s",
95 perc, bytes / 1000, max_bytes / 1000, kbps);
96 if (total_download_bytes > 0)
97 Progress.SetBar2(total_download_bytes_sofar + bytes,
98 total_download_bytes);
100 else
101 sprintf (buf, "%d %2.1f kB/s", bytes, kbps);
103 Progress.SetText3(buf);
106 static void
107 getUrlToStream (const std::string &_url, io_stream *output)
109 is_local_install = (source == IDC_SOURCE_LOCALDIR);
110 init_dialog (_url, 0);
111 NetIO *n = NetIO::open (_url.c_str(), true);
112 if (!n || !n->ok ())
114 delete n;
115 throw new Exception (TOSTRING(__LINE__) " " __FILE__, "Error opening url", APPERR_IO_ERROR);
118 if (n->file_size)
119 max_bytes = n->file_size;
121 int total_bytes = 0;
122 progress (0);
123 while (1)
125 char buf[2048];
126 ssize_t rlen, wlen;
127 rlen = n->read (buf, 2048);
128 if (rlen > 0)
130 wlen = output->write (buf, rlen);
131 if (wlen != rlen)
132 /* FIXME: Show an error message */
133 break;
134 total_bytes += rlen;
135 progress (total_bytes);
137 else
138 break;
140 if (n)
141 delete (n);
142 /* reseeking is up to the recipient if desired */
144 Log (LOG_BABBLE) << "Fetched URL: " << _url << endLog;
147 io_stream *
148 get_url_to_membuf (const std::string &_url, HWND owner)
150 io_stream_memory *membuf = new io_stream_memory ();
151 try
153 getUrlToStream (_url, membuf);
155 if (membuf->seek (0, IO_SEEK_SET))
157 if (membuf)
158 delete membuf;
159 Log (LOG_BABBLE) << "get_url_to_membuf(): seek (0) failed for membuf!" << endLog;
160 return 0;
162 return membuf;
164 catch (Exception *e)
166 if (e->errNo() != APPERR_IO_ERROR)
167 throw e;
168 delete membuf;
169 return 0;
173 // predicate: url has no '\0''s in it.
174 std::string
175 get_url_to_string (const std::string &_url, HWND owner)
177 io_stream *stream = get_url_to_membuf (_url, owner);
178 if (!stream)
179 return std::string();
180 size_t bytes = stream->get_size ();
181 if (!bytes)
183 /* zero length, or error retrieving length */
184 delete stream;
185 Log (LOG_BABBLE) << "get_url_to_string(): couldn't retrieve buffer size, or zero length buffer" << endLog;
186 return std::string();
188 char temp [bytes + 1];
189 /* membufs are quite safe */
190 stream->read (temp, bytes);
191 temp [bytes] = '\0';
192 delete stream;
193 return std::string(temp);
197 get_url_to_file (const std::string &_url,
198 const std::string &_filename,
199 int expected_length,
200 HWND owner)
202 Log (LOG_BABBLE) << "get_url_to_file " << _url << " " << _filename << endLog;
203 if (total_download_bytes > 0)
205 int df = diskfull (get_root_dir ().c_str());
206 Progress.SetBar3(df);
208 init_dialog (_url, expected_length);
210 remove (_filename.c_str()); /* but ignore errors */
212 NetIO *n = NetIO::open (_url.c_str(), false);
213 if (!n || !n->ok ())
215 delete n;
216 return 1;
219 FILE *f = nt_fopen (_filename.c_str(), "wb");
220 if (!f)
222 const char *err = strerror (errno);
223 if (!err)
224 err = "(unknown error)";
225 fatal (owner, IDS_ERR_OPEN_WRITE, _filename.c_str(), err);
228 if (n->file_size)
229 max_bytes = n->file_size;
231 int total_bytes = 0;
232 progress (0);
233 while (1)
235 char buf[8192];
236 int count;
237 count = n->read (buf, sizeof (buf));
238 if (count <= 0)
239 break;
240 fwrite (buf, 1, count, f);
241 total_bytes += count;
242 progress (total_bytes);
245 total_download_bytes_sofar += total_bytes;
247 fclose (f);
248 if (n)
249 delete n;
251 if (total_download_bytes > 0)
253 int df = diskfull (get_root_dir ().c_str());
254 Progress.SetBar3(df);
257 return 0;