/// <summary> /// Try to download a single ModDirectory, and update the stored file if necessary. /// </summary> /// <param name="name">The name of the ModDirectory, used for debug output and the storage file.</param> /// <param name="location">The location from which the ModDirectory can theoretically be downloaded.</param> /// <returns></returns> private ModDirectory TryDownloadModDirectory(string name, Uri location) { string directoryname = dotapath + "/moddota/dirs/" + name + ".dir"; string downloadcontents; ModDirectory md; try { using (WebClient client = new WebClient()) { downloadcontents = client.DownloadString(location); } } catch (Exception e) { Console.WriteLine("Error downloading the mod directory for " + name + " to be downloaded from " + location.ToString() + ". Exception was: " + e.ToString()); return(null); } try { md = new ModDirectory(KV.KVParser.ParseKeyValue(downloadcontents), location.Host); // at this point we've already jumped down to one of the two exception handlers below if there's something wrong with the data, so it won't write bad stuff. try { File.WriteAllText(directoryname, downloadcontents); } catch (Exception e) { // This is actually one from which we can nicely recover. Console.WriteLine("Error writing the moddirectory for " + name + " to disk; using in-memory version. Encountered this exception: " + e.ToString()); } return(md); } catch (CryptoChainValidator.SignatureException) { // Can't do much about it here Console.WriteLine("Mod Directory for " + name + " failed signature check, skipping..."); } catch (KV.KVParser.KeyValueParsingException) { // Well, can't do anything about it here. Console.WriteLine("Error parsing the new download version ModDirectory for " + name + "..."); } return(null); }
/// <summary> /// Get the mod list from the local cache. /// </summary> /// <param name="nodownload">If true, don't download new versions for missing/incorrect/outdated directories.</param> /// <param name="forcereacquire">If true, force a new download of all directories.</param> public ModDirectory GetModDirectories(bool nodownload = false, bool forcereacquire = false) { // First get the list of directories we need to look at if (!File.Exists(dotapath + "/moddota/directories.kv")) { return(null); } string contents = null; try { contents = File.ReadAllText(dotapath + "/moddota/directories.kv"); } catch (Exception) { Console.WriteLine("Couldn't access directories file!"); } KV.KeyValue kv = null; try { kv = KV.KVParser.ParseKeyValue(contents); } catch (KV.KVParser.KeyValueParsingException) { Console.WriteLine("poorly formatted kv file for directories, using default"); kv = new KV.KeyValue("directories"); KV.KeyValue defaultentry = new KV.KeyValue("moddota"); KV.KeyValue defaultdirectory = new KV.KeyValue("directory"); defaultdirectory.Set("https://moddota.com/mdc/directory.kv"); defaultentry.AddChild(defaultdirectory); KV.KeyValue defaultversion = new KV.KeyValue("version"); defaultversion.Set("https://moddota.com/mdc/directory.version"); defaultentry.AddChild(defaultversion); kv.AddChild(defaultentry); } ModDirectoryList mdl = new ModDirectoryList(kv); ModDirectory basemd = new ModDirectory(); foreach (Tuple <string, Uri, Uri> tpl in mdl.directories) { try { string directoryname = dotapath + "/moddota/dirs/" + tpl.Item1 + ".dir"; bool trieddownload = false; // If we don't have that particular directory, force a re-acquire if (!File.Exists(directoryname) || forcereacquire) { if (nodownload) { // don't have it and can't get it, just go to the next one. continue; } else { TryDownloadModDirectory(tpl.Item1, tpl.Item2); trieddownload = true; } } ModDirectory md = null; // Try to parse the file, since we have one try { md = new ModDirectory(KV.KVParser.ParseKeyValueFile(directoryname), tpl.Item2.Host); } catch (CryptoChainValidator.SignatureException) { // The signature was wrong. if (nodownload) { // Since we can't download a new version, we might as well just give up on this one continue; } else { md = TryDownloadModDirectory(tpl.Item1, tpl.Item2); trieddownload = true; } } catch (KV.KVParser.KeyValueParsingException) { // The format was wrong. if (nodownload) { // Since we can't download a new version, we might as well just give up on this one continue; } else { md = TryDownloadModDirectory(tpl.Item1, tpl.Item2); trieddownload = true; } } // Version check - don't check the version if we aren't going to download a new one anyway, and don't check it if we already just downloaded it. if (!nodownload && !trieddownload) { Version remoteversion; try { using (WebClient client = new WebClient()) { remoteversion = new Version(client.DownloadString(tpl.Item3)); } if (remoteversion > md.version) { if (nodownload) { // don't actually skip this time - we just let people play offline with the old version. } else { ModDirectory newmd = TryDownloadModDirectory(tpl.Item1, tpl.Item2); if (newmd != null) { md = newmd; } trieddownload = true; } } } catch (Exception) { Console.WriteLine("Encountered exception while parsing files for " + tpl.Item1 + "'s directory version information"); } } basemd.add(md); } catch (Exception) { Console.WriteLine("Failed to acquire or parse the ModDirectory from " + tpl.Item2.ToString()); } } return(basemd); }
/// <summary> /// Add all of the entries from the other ModDirectory to this one. /// </summary> /// <param name="other">The other ModDirectory.</param> public void add(ModDirectory other) { entries.AddRange(other.entries); }