/// <summary> /// Create UpdateFile instance /// </summary> /// <param name="parent"> /// <para>throws ArgumentNullException if null</para> /// <para>throws ArgumentException if parent type is UpdateType::Unknown</para> /// </param> /// <param name="crc">expected CRC32 of file</param> /// <param name="size">expected size of file, can be different than final size if file is packed</param> /// <param name="filename">final name of file, including relative directory</param> /// <param name="options"></param> /// /// <exception cref="ArgumentException">A</exception> protected UpdateFile( UpdateInfo parent, uint crc, uint size, string filename, List<string> options ) { if( parent == null ) throw new ArgumentNullException( "parent" ); else if( parent.Type == FOUpdateType.Unknown ) // should never happen throw new ArgumentException( "parent" ); this.CRC = crc; this.Size = size; this.FileName = filename.Replace( '\\', '/' ); this.Options = options; this.ID = ++FileID; // TODO?: this is probably not the best way, but let it stay for now this.Parent = parent; this.Parent.Files.Add( this ); }
/// <summary> /// Core of FOUpdater, /// /// </summary> /// <param name="_message">callback for writing messages</param> /// <param name="_progress">callback for </param> /// <returns></returns> public FOUpdaterResult Update(UpdaterMessage _message, UpdaterProgress _progress, string defaultSource = null) { lock ( locker ) { this.message = _message; this.progress = _progress; this.SendMessage(FOUpdaterMessage.General, Strings.Initializing); } List <string> sources = new List <string>(); if (defaultSource != null) { if (this.GetUpdateType(defaultSource) != FOUpdateType.Unknown) { sources.Add(defaultSource); } if (this.FOnlineCfg == null && !File.Exists(Strings.ConfigFile)) { using (StreamWriter file = File.CreateText(Strings.ConfigFile)) { file.Flush(); file.Close(); } if (File.Exists(Strings.ConfigFile)) { this.FOnlineCfg = new IniFile(Strings.ConfigFile); this.FOnlineCfg.SetValue(Strings.Section, Strings.Source + "0", defaultSource); this.FOnlineCfg.Flush(); this.Sources.Add(defaultSource); } } } else // defaultSource == null { if (this.FOnlineCfg != null) { for (uint s = 0; s < uint.MaxValue; s++) { string source = this.FOnlineCfg.GetValue(Strings.Section, Strings.Source + s, (string)null); if (source == null || source.Length == 0) { break; } else if (this.GetUpdateType(source) != FOUpdateType.Unknown) { sources.Add(source); } } if (sources.Count == 0) { return(FOUpdaterResult.InvalidConfig); } } else { return(FOUpdaterResult.NoConfig); } } if (sources.Count == 0) { return(FOUpdaterResult.InvalidConfig); } if (this.FOnlineCfg.GetValue(FOUpdaterClient.Strings.Section, FOUpdaterClient.Strings.RandomSource, false)) { List <string> randomList = new List <string>(); Random random = new Random((int)DateTime.Now.Ticks); int count = sources.Count; while (randomList.Count != count) { string element = sources[random.Next(0, sources.Count)]; if (randomList.Contains(element)) { continue; } randomList.Add(element); sources.Remove(element); } sources = randomList; } this.Sources = sources; uint updated = 0, deleted = 0; bool foundSource = false; foreach (string source in this.Sources) { bool nextUpdateType = false; FOUpdateType type = this.GetUpdateType(source); UpdateInfo info = null; if (type == FOUpdateType.Stream) { info = new UpdateInfoStream(this); } else if (type == FOUpdateType.HTTP) { info = new UpdateInfoHTTP(this); } /* * else if( type == UpdateType.FTP ) * info = new UpdateInfoFTP( this ); */ else { continue; } if (info.Start(defaultSource)) { foundSource = true; lock (this.locker) { this.SendMessage(FOUpdaterMessage.General, Strings.CheckingFiles); } List <UpdateFile> needUpdate = new List <UpdateFile>(); this.SendProgress(FOUpdaterProgress.FileValue, 0); this.SendProgress(FOUpdaterProgress.FileMaximum, 0); this.SendProgress(FOUpdaterProgress.TotalValue, 0); this.SendProgress(FOUpdaterProgress.TotalMaximum, 0); uint progressMax = 0; foreach (UpdateFile file in info.Files) { lock (this.locker) { if (file.Delete) { if (File.Exists(file.FileName)) { File.Delete(file.FileName); deleted++; } continue; } if (file.NeedUpdate) { progressMax += file.Size; this.SendProgress(FOUpdaterProgress.TotalMaximum, progressMax); needUpdate.Add(file); } } } if (needUpdate.Count == 0) { lock (this.locker) { this.SendMessage(FOUpdaterMessage.General, (deleted > 0 ? Strings.DeletedFiles : Strings.UpdateNotNeeded )); } info.End(); return(FOUpdaterResult.OK); } foreach (UpdateFile file in needUpdate) { lock (this.locker) { if (this.Cancelled) { break; } this.SendProgress(FOUpdaterProgress.FileValue, 0); this.SendProgress(FOUpdaterProgress.FileMaximum, file.Size); this.SendMessage(FOUpdaterMessage.General, Strings.Downloading.Replace("%s", file.FileName)); } file.PrepareDirectory(); if (!file.Download(fileProgress, fileSave, fileComplete)) { if (this.Cancelled) { break; } else { nextUpdateType = true; } } else { updated++; } lock ( locker ) { this.progressTotal += file.Size; this.SendProgress(FOUpdaterProgress.TotalValue, this.progressTotal); } } info.End(); } else { nextUpdateType = true; } if (this.Cancelled || !nextUpdateType) { break; } } FOUpdaterResult result = FOUpdaterResult.OK; lock (this.locker) { this.SendMessage(FOUpdaterMessage.Detailed, null); if (!foundSource) { this.SendMessage(FOUpdaterMessage.General, Strings.NoSources); result = FOUpdaterResult.NoSource; } else if (this.Cancelled) { this.SendMessage(FOUpdaterMessage.General, Strings.Cancelled); result = FOUpdaterResult.Cancel; } else { this.SendProgress(FOUpdaterProgress.FileValue, 0); this.SendProgress(FOUpdaterProgress.FileMaximum, 0); this.SendMessage(FOUpdaterMessage.General, (deleted > 0 ? Strings.UpdatedDeletedFiles.Replace("%u", "" + updated).Replace("%d", "" + deleted) : Strings.UpdatedFiles.Replace("%u", "" + updated))); } } return(result); }