"\n%%% $Id$\n";
#endif
+#include "download.h"
+
#include "win32.h"
#include <stdio.h>
#include "resource.h"
#include "msg.h"
-#include "ini.h"
#include "dialog.h"
#include "String++.h"
#include "geturl.h"
#include "state.h"
-#include "mkdir.h"
-#include "log.h"
+#include "LogSingleton.h"
#include "filemanip.h"
-#include "port.h"
#include "io_stream.h"
#include "rfc1738.h"
#include "threebar.h"
+
+#include "md5.h"
+
+#include "Exception.h"
+
extern ThreeBarProgressPage Progress;
+
+bool
+validateCachedPackage (String const &fullname, packagesource & pkgsource)
+{
+ if (pkgsource.md5.isSet())
+ {
+ // check the MD5 sum of the cached file here
+ io_stream *thefile = io_stream::open (fullname, "rb");
+ if (!thefile)
+ return 0;
+ md5_state_t pns;
+ md5_init (&pns);
+
+ log (LOG_BABBLE) << "Checking MD5 for " << fullname << endLog;
+
+ Progress.SetText1 ((String ("Checking MD5 for ") + pkgsource.Base()).cstr_oneuse());
+ Progress.SetText4 ("Progress:");
+ Progress.SetBar1 (0);
+
+ unsigned char buffer[16384];
+ ssize_t count;
+ while ((count = thefile->read (buffer, 16384)) > 0)
+ {
+ md5_append (&pns, buffer, count);
+ Progress.SetBar1 (thefile->tell(), thefile->get_size());
+ }
+ delete thefile;
+ if (count < 0)
+ throw new Exception ("__LINE__ __FILE__", (String ("IO Error reading ") + pkgsource.Cached()).cstr_oneuse(), APPERR_IO_ERROR);
+
+ md5_byte_t tempdigest[16];
+ md5_finish(&pns, tempdigest);
+ md5 tempMD5;
+ tempMD5.set (tempdigest);
+
+ log (LOG_BABBLE) << "For file '" << fullname <<
+ " ini digest is " << pkgsource.md5.print() <<
+ " file digest is " << tempMD5.print() << endLog;
+
+ if (pkgsource.md5 != tempMD5)
+ return false;
+ }
+ return true;
+}
+
/* 0 on failure
*/
-static int
+int
check_for_cached (packagesource & pkgsource)
{
/* search algo:
file://local_dir
*/
+ // Already found one.
+ if (pkgsource.Cached())
+ return 1;
+
+ String prefix = String ("file://") + local_dir + "/";
DWORD size;
- if ((size =
- get_file_size (local_dir + "/" + pkgsource.Canonical ())) >
- 0)
+ if ((size = get_file_size (prefix + pkgsource.Canonical ())) > 0)
if (size == pkgsource.size)
{
- pkgsource.
- set_cached (String ("file://") + local_dir + "/" + pkgsource.Canonical ());
+ if (validateCachedPackage (prefix + pkgsource.Canonical (), pkgsource))
+ pkgsource.set_cached (prefix + pkgsource.Canonical ());
+ else
+ throw new Exception ("__LINE__ __FILE__", (String ("Package validation failure for ") + prefix + pkgsource.Canonical ()).cstr_oneuse(), APPERR_CORRUPT_PACKAGE);
return 1;
}
/*
2) is there a version from one of the selected mirror sites available ?
*/
- for (size_t n = 1; n <= pkgsource.sites.number (); n++)
- if ((size =
- get_file_size (local_dir + "/" +
- rfc1738_escape_part (pkgsource.sites[n]->key) + "/" +
- pkgsource.Canonical ())) > 0)
+ for (packagesource::sitestype::const_iterator n = pkgsource.sites.begin();
+ n != pkgsource.sites.end(); ++n)
+ {
+ String fullname = prefix + rfc1738_escape_part (n->key) + "/" +
+ pkgsource.Canonical ();
+ if ((size = get_file_size (fullname)) > 0)
if (size == pkgsource.size)
{
- pkgsource.
- set_cached (String ("file://") + local_dir + "/" +
- rfc1738_escape_part (pkgsource.sites[n]->
- key) + "/" +
- pkgsource.Canonical ());
+ if (validateCachedPackage (fullname, pkgsource))
+ pkgsource.set_cached (fullname );
+ else
+ throw new Exception ("__LINE__ __FILE__", (String ("Package validation failure for ") + fullname).cstr_oneuse(), APPERR_CORRUPT_PACKAGE);
return 1;
}
-
+ }
return 0;
}
static int
download_one (packagesource & pkgsource, HWND owner)
{
- if (check_for_cached (pkgsource) && source != IDC_SOURCE_DOWNLOAD)
- return 0;
-
+ try
+ {
+ if (check_for_cached (pkgsource))
+ return 0;
+ }
+ catch (Exception * e)
+ {
+ // We know what to do with these..
+ if (e->errNo() == APPERR_CORRUPT_PACKAGE)
+ {
+ fatal (owner, IDS_CORRUPT_PACKAGE, pkgsource.Canonical());
+ return 1;
+ }
+ // Unexpected exception.
+ throw e;
+ }
/* try the download sites one after another */
int success = 0;
- for (size_t n = 1; n <= pkgsource.sites.number () && !success; n++)
+ for (packagesource::sitestype::const_iterator n = pkgsource.sites.begin();
+ n != pkgsource.sites.end() && !success; ++n)
{
String const local = local_dir + "/" +
- rfc1738_escape_part (pkgsource.sites[n]->
- key) + "/" +
+ rfc1738_escape_part (n->key) + "/" +
pkgsource.Canonical ();
io_stream::mkpath_p (PATH_TO_FILE, String ("file://") + local);
- if (get_url_to_file(pkgsource.sites[n]->key + "/" +
- pkgsource.Canonical (),
+ if (get_url_to_file(n->key + "/" + pkgsource.Canonical (),
local + ".tmp", pkgsource.size, owner))
{
/* FIXME: note new source ? */
}
else
{
- size_t size = get_file_size (local + ".tmp");
+ size_t size = get_file_size (String("file://") + local + ".tmp");
if (size == pkgsource.size)
{
- log (LOG_PLAIN, String ("Downloaded ") + local);
+ log (LOG_PLAIN) << "Downloaded " << local << endLog;
if (_access (local.cstr_oneuse(), 0) == 0)
remove (local.cstr_oneuse());
rename ((local + ".tmp").cstr_oneuse(), local.cstr_oneuse());
}
else
{
- log (LOG_PLAIN,
- "Download %s wrong size (%u actual vs %d expected)",
- local.cstr_oneuse(), size, pkgsource.size);
+ log (LOG_PLAIN) << "Download " << local << " wrong size (" <<
+ size << " actual vs " << pkgsource.size << " expected)" <<
+ endLog;
remove ((local + ".tmp").cstr_oneuse());
continue;
}
packagedb db;
/* calculate the amount needed */
- for (size_t n = 1; n <= db.packages.number (); n++)
+ for (vector <packagemeta *>::iterator i = db.packages.begin ();
+ i != db.packages.end (); ++i)
{
- packagemeta & pkg = *db.packages[n];
- if (pkg.desired && (pkg.desired->srcpicked || pkg.desired->binpicked))
+ packagemeta & pkg = **i;
+ if (pkg.desired.changeRequested())
{
- packageversion *version = pkg.desired;
- if (!
- (check_for_cached (version->bin)
- && source != IDC_SOURCE_DOWNLOAD) && pkg.desired->binpicked)
- total_download_bytes += version->bin.size;
- if (!
- (check_for_cached (version->src)
- && source != IDC_SOURCE_DOWNLOAD) && pkg.desired->srcpicked)
- total_download_bytes += version->src.size;
+ packageversion version = pkg.desired;
+ packageversion sourceversion = version.sourcePackage();
+ try
+ {
+ if (version.picked())
+ {
+ for (vector<packagesource>::iterator i =
+ version.sources ()->begin();
+ i != version.sources ()->end(); ++i)
+ if (!check_for_cached (*i))
+ total_download_bytes += i->size;
+ }
+ if (sourceversion.picked ())
+ {
+ for (vector<packagesource>::iterator i =
+ sourceversion.sources ()->begin();
+ i != sourceversion.sources ()->end(); ++i)
+ if (!check_for_cached (*i))
+ total_download_bytes += i->size;
+ }
+ }
+ catch (Exception * e)
+ {
+ // We know what to do with these..
+ if (e->errNo() == APPERR_CORRUPT_PACKAGE)
+ fatal (owner, IDS_CORRUPT_PACKAGE, pkg.name.cstr_oneuse());
+ // Unexpected exception.
+ throw e;
+ }
}
}
/* and do the download. FIXME: This here we assign a new name for the cached version
* and check that above.
*/
- for (size_t n = 1; n <= db.packages.number (); n++)
+ for (vector <packagemeta *>::iterator i = db.packages.begin ();
+ i != db.packages.end (); ++i)
{
- packagemeta & pkg = *db.packages[n];
- if (pkg.desired && (pkg.desired->srcpicked || pkg.desired->binpicked))
+ packagemeta & pkg = **i;
+ if (pkg.desired.changeRequested())
{
int e = 0;
- packageversion *version = pkg.desired;
- if (version->binpicked)
- e += download_one (version->bin, owner);
- if (version->srcpicked)
- e += download_one (version->src, owner);
+ packageversion version = pkg.desired;
+ packageversion sourceversion = version.sourcePackage();
+ if (version.picked())
+ {
+ for (vector<packagesource>::iterator i =
+ version.sources ()->begin();
+ i != version.sources ()->end(); ++i)
+ e += download_one (*i, owner);
+ }
+ if (sourceversion && sourceversion.picked())
+ {
+ for (vector<packagesource>::iterator i =
+ sourceversion.sources ()->begin();
+ i != sourceversion.sources ()->end(); ++i)
+ e += download_one (*i, owner);
+ }
errors += e;
#if 0
if (e)
next_dialog = IDD_S_INSTALL;
}
-static void
+static DWORD WINAPI
do_download_reflector (void *p)
{
HANDLE *context;
// Tell the progress page that we're done downloading
Progress.PostMessage (WM_APP_DOWNLOAD_THREAD_COMPLETE, 0, next_dialog);
- _endthread ();
+ ExitThread(0);
}
static HANDLE context[2];
context[0] = h;
context[1] = owner;
- _beginthread (do_download_reflector, 0, context);
+ DWORD threadID;
+ CreateThread (NULL, 0, do_download_reflector, context, 0, &threadID);
}