Exemple #1
0
        /// <summary>
        /// Returns a sorted list of all existing application jobs.
        /// </summary>
        public static ApplicationJob[] GetJobs()
        {
            Dictionary <Guid, List <UrlVariable> > allVariables = new Dictionary <Guid, List <UrlVariable> >();

            using (IDbCommand command = Connection.CreateCommand())
            {
                command.CommandText = "SELECT * FROM variables";

                using (IDataReader reader = command.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        UrlVariable variable = new UrlVariable();
                        variable.Hydrate(reader);

                        Guid jobGuid = new Guid(reader["JobGuid"] as string);

                        if (!allVariables.ContainsKey(jobGuid))
                        {
                            allVariables[jobGuid] = new List <UrlVariable>();
                        }

                        allVariables[jobGuid].Add(variable);
                    }
                }
            }

            using (IDbCommand command = Connection.CreateCommand())
            {
                command.CommandText = "SELECT * FROM jobs ORDER BY ApplicationName";

                List <ApplicationJob> result = new List <ApplicationJob>();

                using (IDataReader reader = command.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        ApplicationJob job = new ApplicationJob();
                        job.Hydrate(reader);

                        if (allVariables.ContainsKey(job.Guid))
                        {
                            foreach (UrlVariable var in allVariables[job.Guid])
                            {
                                job.Variables[var.Name] = var;
                            }
                        }

                        result.Add(job);
                    }
                }

                return(result.ToArray());
            }
        }
        /// <summary>
        /// Sets the POST data which is sent
        /// along with the request. Replaces variables.
        /// </summary>
        /// <param name="variable">The variable, which sends the request</param>
        public void SetPostData(UrlVariable variable)
        {
            string[][] pairs = GetKeyValuePairs(variable.PostData);
            if (variable.Parent != null)
            {
                foreach (string[] keyValue in pairs)
                {
                    keyValue[0] = variable.Parent.ReplaceAllInString(keyValue[0]);
                    keyValue[1] = variable.Parent.ReplaceAllInString(keyValue[1]);
                }
            }

            StringBuilder sb = new StringBuilder();

            foreach (string[] keyValue in pairs)
            {
                sb.Append(HttpUtility.UrlEncode(keyValue[0]) + "=" + HttpUtility.UrlEncode(keyValue[1]) + "&");
            }

            m_PostData = sb.ToString().TrimEnd('&');
        }
Exemple #3
0
        /// <summary>
        /// Returns an application from the database which has the specified GUID.
        /// </summary>
        public static ApplicationJob GetJob(Guid appGuid)
        {
            ApplicationJob job = null;

            using (IDbCommand command = Connection.CreateCommand())
            {
                command.CommandText = "SELECT * FROM jobs WHERE JobGuid = @JobGuid";
                command.Parameters.Add(new SQLiteParameter("@JobGuid", FormatGuid(appGuid)));

                using (IDataReader reader = command.ExecuteReader())
                {
                    if (reader.Read())
                    {
                        job = new ApplicationJob();
                        job.Hydrate(reader);
                    }
                }
            }

            if (job != null)
            {
                using (IDbCommand command = Connection.CreateCommand())
                {
                    command.CommandText = @"SELECT * FROM variables WHERE JobGuid = @JobGuid";
                    command.Parameters.Add(new SQLiteParameter("@JobGuid", FormatGuid(appGuid)));
                    using (IDataReader reader = command.ExecuteReader())
                    {
                        while (reader.Read())
                        {
                            UrlVariable variable = new UrlVariable(job.Variables);
                            variable.Hydrate(reader);
                            job.Variables.Add(variable.Name, variable);
                        }
                    }
                }
            }

            return(job);
        }
Exemple #4
0
        /// <summary>
        /// Executes a given command for the given application (also resolves variables).
        /// </summary>
        /// <returns>Exit code of the command, if not run in background</returns>
        private static int ExecuteBatchCommand(ApplicationJob job, string commandText, string targetFileName)
        {
            // Ignore empty commands
            if (string.IsNullOrEmpty(commandText))
            {
                return(0);
            }

            commandText = commandText.Replace("\r\n", "\n");

            // Job specific data
            if (job != null)
            {
                commandText = job.Variables.ReplaceAllInString(commandText, DateTime.MinValue, targetFileName, false);
            }
            else
            {
                commandText = UrlVariable.GlobalVariables.ReplaceAllInString(commandText);
            }

            // Replace variable: root
            try
            {
                commandText = UrlVariable.Replace(commandText, "root", Path.GetPathRoot(Application.StartupPath));
            }
            catch (ArgumentException) { }

            // Feed cmd.exe with our commands
            ProcessStartInfo cmdExe = new ProcessStartInfo("cmd.exe");

            cmdExe.RedirectStandardInput  = true;
            cmdExe.UseShellExecute        = false;
            cmdExe.CreateNoWindow         = true;
            cmdExe.RedirectStandardOutput = true;
            cmdExe.RedirectStandardError  = true;

            bool executeBackground = commandText.EndsWith("&");

            commandText = commandText.TrimEnd('&');

            using (Process proc = Process.Start(cmdExe))
            {
                StringBuilder commandResult = new StringBuilder();

                // Set the event handler to asynchronously read the command output.
                proc.OutputDataReceived += new DataReceivedEventHandler(delegate(object sendingProcess, DataReceivedEventArgs outLine)
                {
                    if (!string.IsNullOrEmpty(outLine.Data))
                    {
                        commandResult.AppendLine(outLine.Data);
                    }
                });
                proc.ErrorDataReceived += new DataReceivedEventHandler(delegate(object sendingProcess, DataReceivedEventArgs outLine)
                {
                    if (!string.IsNullOrEmpty(outLine.Data))
                    {
                        commandResult.AppendLine(outLine.Data);
                    }
                });

                // Start the asynchronous read of the command output stream.
                proc.BeginOutputReadLine();
                proc.BeginErrorReadLine();

                // Input commands
                using (proc.StandardInput)
                {
                    string[] commands = commandText.Split('\n');
                    foreach (string command in commands)
                    {
                        if (!string.IsNullOrEmpty(command))
                        {
                            LogDialog.Log(job, "Executing command: " + command);
                        }
                        proc.StandardInput.WriteLine(command);
                    }
                }

                // Read output
                if (!executeBackground)
                {
                    proc.WaitForExit();
                    string commandResultString = commandResult.ToString();
                    if (!string.IsNullOrEmpty(commandResultString))
                    {
                        LogDialog.Log(job, "Command result: " + commandResultString);
                    }
                    return(proc.ExitCode);
                }
            }

            return(0);
        }
Exemple #5
0
        /// <summary>
        /// Returns a sorted list of all existing application jobs.
        /// </summary>
        public static ApplicationJob[] GetJobs()
        {
            Dictionary<Guid, List<UrlVariable>> allVariables = new Dictionary<Guid, List<UrlVariable>>();
            using (IDbCommand command = Connection.CreateCommand())
            {
                command.CommandText = "SELECT * FROM variables";

                using (IDataReader reader = command.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        UrlVariable variable = new UrlVariable();
                        variable.Hydrate(reader);

                        Guid jobGuid = new Guid(reader["JobGuid"] as string);

                        if (!allVariables.ContainsKey(jobGuid))
                        {
                            allVariables[jobGuid] = new List<UrlVariable>();
                        }

                        allVariables[jobGuid].Add(variable);
                    }
                }
            }

            using (IDbCommand command = Connection.CreateCommand())
            {
                command.CommandText = "SELECT * FROM jobs ORDER BY ApplicationName";

                List<ApplicationJob> result = new List<ApplicationJob>();

                using (IDataReader reader = command.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        ApplicationJob job = new ApplicationJob();
                        job.Hydrate(reader);

                        if (allVariables.ContainsKey(job.Guid))
                        {
                            foreach (UrlVariable var in allVariables[job.Guid])
                            {
                                job.Variables[var.Name] = var;
                            }
                        }

                        result.Add(job);
                    }
                }

                return result.ToArray();
            }
        }
Exemple #6
0
        /// <summary>
        /// Returns an application from the database which has the specified GUID.
        /// </summary>
        public static ApplicationJob GetJob(Guid appGuid)
        {
            ApplicationJob job = null;

            using (IDbCommand command = Connection.CreateCommand())
            {
                command.CommandText = "SELECT * FROM jobs WHERE JobGuid = @JobGuid";
                command.Parameters.Add(new SQLiteParameter("@JobGuid", FormatGuid(appGuid)));

                using (IDataReader reader = command.ExecuteReader())
                {
                    if (reader.Read())
                    {
                        job = new ApplicationJob();
                        job.Hydrate(reader);
                    }
                }
            }

            if (job != null)
            {
                using (IDbCommand command = Connection.CreateCommand())
                {
                    command.CommandText = @"SELECT * FROM variables WHERE JobGuid = @JobGuid";
                    command.Parameters.Add(new SQLiteParameter("@JobGuid", DbManager.FormatGuid(appGuid)));
                    using (IDataReader reader = command.ExecuteReader())
                    {
                        while (reader.Read())
                        {
                            UrlVariable variable = new UrlVariable(job.Variables);
                            variable.Hydrate(reader);
                            job.Variables.Add(variable.Name, variable);
                        }
                    }
                }
            }

            return job;
        }
        public static void ImportFromFile(string filename)
        {
            XmlDocument doc = new XmlDocument();
            doc.Load(filename);

            // Import settings from file as dictionary
            XmlElement settingsElem = doc.SelectSingleNode("//Settings/dictionary") as XmlElement;
            if (settingsElem == null)
            {
                // Backward compatibility
                settingsElem = doc.SelectSingleNode("//dictionary") as XmlElement;
            }

            if (settingsElem != null)
            {
                XmlSerializer serializer = new XmlSerializer(typeof(SerializableDictionary<string, string>));

                using (StringReader textReader = new StringReader(settingsElem.OuterXml))
                {
                    DbManager.SetSettings(serializer.Deserialize(textReader) as Dictionary<string, string>);
                }
            }
            
            // Import global variables
            XmlElement varNodes = doc.SelectSingleNode("//GlobalVariables") as XmlElement;
            if (varNodes != null)
            {
                UrlVariable.GlobalVariables.Clear();

                foreach (XmlElement varElem in doc.SelectNodes("//GlobalVariables/Variable"))
                {
                    UrlVariable newVar = new UrlVariable();
                    newVar.Name = varElem.GetAttribute("Name");
                    newVar.CachedContent = varElem.GetAttribute("Content");
                    UrlVariable.GlobalVariables[newVar.Name] = newVar;
                }

                UrlVariable.GlobalVariables.Save();
            }

            // Import code snippets
            XmlElement snippetNodes = doc.SelectSingleNode("//CodeSnippets") as XmlElement;
            if (snippetNodes != null)
            {
                using (SQLiteCommand comm = DbManager.Connection.CreateCommand())
                {
                    comm.CommandText = "DELETE FROM snippets";
                    comm.ExecuteNonQuery();
                }

                foreach (XmlElement snippetElem in doc.SelectNodes("//CodeSnippets/Snippet"))
                {
                    Snippet snippet = new Snippet();
                    snippet.Guid = new Guid(snippetElem.GetAttribute("Guid"));
                    snippet.Name = snippetElem.GetAttribute("Name");
                    snippet.Type = (ScriptType)Convert.ToInt32(snippetElem.GetAttribute("Type"));
                    snippet.Text = snippetElem.InnerText;
                    snippet.Save();
                }
            }

            XmlElement setupNodes = doc.SelectSingleNode("//SetupLists") as XmlElement;
            if (setupNodes != null)
            {
                ApplicationJob[] apps = DbManager.GetJobs();

                using (IDbCommand command = DbManager.Connection.CreateCommand())
                {
                    command.CommandText = @"DELETE FROM setuplists_applications";
                    command.ExecuteNonQuery();
                }

                using (IDbCommand command = DbManager.Connection.CreateCommand())
                {
                    command.CommandText = @"DELETE FROM setuplists";
                    command.ExecuteNonQuery();
                }

                foreach (XmlElement listElem in doc.SelectNodes("//SetupLists/List"))
                {
                    ApplicationList list = new ApplicationList();
                    list.Name = listElem.GetAttribute("Name");
                    list.Guid = new Guid(listElem.GetAttribute("Guid"));

                    foreach (XmlElement appListElem in listElem.SelectNodes("Applications/Application"))
                    {
                        Guid guid = new Guid(appListElem.GetAttribute("Guid"));

                        ApplicationJob job = DbManager.GetJob(guid);
                        if (job != null)
                        {
                            list.Applications.Add(job);
                        }
                    }

                    list.Save();
                }
            }            
        }
Exemple #8
0
        /// <summary>
        /// Executes the actual download from an URL. Does not handle exceptions,
        /// but takes care of proper cleanup.
        /// </summary>
        /// <exception cref="NonBinaryFileException">This exception is thrown, if the resulting file is not of a binary type</exception>
        /// <exception cref="TargetPathInvalidException">This exception is thrown, if the resulting target path of an application is not valid</exception>
        /// <param name="job">The job to process</param>
        /// <param name="urlToRequest">URL from which should be downloaded</param>
        /// <returns>true, if a new update has been found and downloaded, false otherwise</returns>
        protected Status DoDownload(ApplicationJob job, Uri urlToRequest)
        {
            // Determine number of segments to create
            int segmentCount = Convert.ToInt32(Settings.GetValue("SegmentCount", 1));

            job.Variables.ResetDownloadCount();

            WebRequest req = KetarinProtocolProvider.CreateRequest(urlToRequest, job, this.m_Cookies);

            AddRequestToCancel(req);

            using (WebResponse response = WebClient.GetResponse(req))
            {
                LogDialog.Log(job, "Server source file: " + req.RequestUri.AbsolutePath);

                // Occasionally, websites are not available and an error page is encountered
                // For the case that the content type is just plain wrong, ignore it if the size is higher than 500KB
                HttpWebResponse httpResponse = response as HttpWebResponse;
                if (httpResponse != null && response.ContentLength < 500000)
                {
                    if (response.ContentType.StartsWith("text/xml") || response.ContentType.StartsWith("application/xml"))
                    {
                        // If an XML file is served, maybe we have a PAD file
                        ApplicationJob padJob = ApplicationJob.ImportFromPad(httpResponse);
                        if (padJob != null)
                        {
                            job.CachedPadFileVersion = padJob.CachedPadFileVersion;
                            return(this.DoDownload(job, new Uri(padJob.FixedDownloadUrl)));
                        }
                    }

                    if (response.ContentType.StartsWith("text/html"))
                    {
                        bool avoidNonBinary = (bool)Settings.GetValue("AvoidDownloadingNonBinaryFiles", true);
                        if (httpResponse.StatusCode != HttpStatusCode.OK || avoidNonBinary)
                        {
                            throw NonBinaryFileException.Create(response.ContentType, httpResponse.StatusCode);
                        }
                    }
                }

                long fileSize = GetContentLength(response);
                if (fileSize == 0)
                {
                    throw new IOException("Source file on server is empty (ContentLength = 0).");
                }

                string targetFileName = job.GetTargetFile(response, urlToRequest.AbsoluteUri);

                LogDialog.Log(job, "Determined target file name: " + targetFileName);

                // Only download, if the file size or date has changed
                if (!ForceDownload && !job.RequiresDownload(response, targetFileName))
                {
                    // If file already exists (created by user),
                    // the download is not necessary. We still need to
                    // set the file name.
                    // If the file exists, but not at the target location
                    // (after renaming), do not reset the previous location.
                    if (File.Exists(targetFileName))
                    {
                        job.PreviousLocation = targetFileName;
                    }
                    job.Save();
                    return(Status.NoUpdate);
                }

                // Skip downloading!
                // Installing also requires a forced download
                if (!ForceDownload && !m_InstallUpdated && (m_OnlyCheck || (job.CheckForUpdatesOnly && !IgnoreCheckForUpdatesOnly)))
                {
                    LogDialog.Log(job, "Skipped downloading updates");
                    return(Status.UpdateAvailable);
                }

                // Execute: Default pre-update command
                string defaultPreCommand = Settings.GetValue("PreUpdateCommand", "") as string;
                // For starting external download managers: {preupdate-url}
                defaultPreCommand = UrlVariable.Replace(defaultPreCommand, "preupdate-url", urlToRequest.ToString(), job);
                ScriptType defaultPreCommandType = Command.ConvertToScriptType(Settings.GetValue("PreUpdateCommandType", ScriptType.Batch.ToString()) as string);

                int exitCode = new Command(defaultPreCommand, defaultPreCommandType).Execute(job, targetFileName);
                if (exitCode == 1)
                {
                    LogDialog.Log(job, "Default pre-update command returned '1', download aborted");
                    throw new CommandErrorException();
                }
                else if (exitCode == 2)
                {
                    LogDialog.Log(job, "Default pre-update command returned '2', download skipped");
                    return(Status.UpdateAvailable);
                }

                // Execute: Application pre-update command
                exitCode = new Command(UrlVariable.Replace(job.ExecutePreCommand, "preupdate-url", urlToRequest.ToString(), job), job.ExecutePreCommandType).Execute(job, targetFileName);
                if (exitCode == 1)
                {
                    LogDialog.Log(job, "Pre-update command returned '1', download aborted");
                    throw new CommandErrorException();
                }
                else if (exitCode == 2)
                {
                    LogDialog.Log(job, "Pre-update command returned '2', download skipped");
                    return(Status.UpdateAvailable);
                }
                else if (exitCode == 3)
                {
                    LogDialog.Log(job, "Pre-update command returned '3', external download");
                    job.LastUpdated = DateTime.Now;
                    job.Save();
                    return(Status.UpdateSuccessful);
                }

                // Read all file contents to a temporary location
                string   tmpLocation   = Path.GetTempFileName();
                DateTime lastWriteTime = ApplicationJob.GetLastModified(response);

                // Only use segmented downloader with more than one segment.
                if (segmentCount > 1)
                {
                    // Response can be closed now, new one will be created.
                    response.Dispose();

                    m_Size[job] = fileSize;

                    Downloader d = new Downloader(new ResourceLocation {
                        Url = urlToRequest.AbsoluteUri, ProtocolProvider = new KetarinProtocolProvider(job, m_Cookies)
                    }, null, tmpLocation, segmentCount);
                    d.Start();

                    while (d.State < DownloaderState.Ended)
                    {
                        if (m_CancelUpdates)
                        {
                            d.Pause();
                            break;
                        }

                        this.OnProgressChanged(d.Segments.Sum(x => x.Transfered), fileSize, job);
                        Thread.Sleep(250);
                    }

                    if (d.State == DownloaderState.EndedWithError)
                    {
                        throw d.LastError;
                    }
                }
                else
                {
                    // Read contents from the web and put into file
                    using (Stream sourceFile = response.GetResponseStream())
                    {
                        using (FileStream targetFile = File.Create(tmpLocation))
                        {
                            long byteCount = 0;
                            int  readBytes;
                            m_Size[job] = fileSize;

                            // Only create buffer once and re-use.
                            const int bufferSize = 1024 * 1024;
                            byte[]    buffer     = new byte[bufferSize];

                            do
                            {
                                if (m_CancelUpdates)
                                {
                                    break;
                                }

                                // Some adjustment for SCP download: Read only up to the max known bytes
                                int maxRead = (fileSize > 0) ? (int)Math.Min(fileSize - byteCount, bufferSize) : bufferSize;
                                if (maxRead == 0)
                                {
                                    break;
                                }

                                readBytes = sourceFile.Read(buffer, 0, maxRead);
                                if (readBytes > 0)
                                {
                                    targetFile.Write(buffer, 0, readBytes);
                                }
                                byteCount += readBytes;

                                this.OnProgressChanged(byteCount, fileSize, job);
                            } while (readBytes > 0);
                        }
                    }
                }

                if (m_CancelUpdates)
                {
                    m_Progress[job] = 0;
                    OnStatusChanged(job);
                    return(Status.Failure);
                }

                // If each version has a different file name (version number),
                // we might only want to keep one of them. Also, we might
                // want to free some space on the target location.
                if (job.DeletePreviousFile)
                {
                    PathEx.TryDeleteFiles(job.PreviousLocation);
                }

                try
                {
                    File.SetLastWriteTime(tmpLocation, lastWriteTime);
                }
                catch (ArgumentException)
                {
                    // Invalid file date. Ignore and just use DateTime.Now
                }

                // File downloaded. Now let's check if the hash value is valid or abort otherwise!
                if (!string.IsNullOrEmpty(job.HashVariable) && job.HashType != HashType.None)
                {
                    string varName      = job.HashVariable.Trim('{', '}');
                    string expectedHash = job.Variables.ReplaceAllInString("{" + varName + "}").Trim();

                    // Compare online hash with actual current hash.
                    if (!string.IsNullOrEmpty(expectedHash))
                    {
                        string currentHash = job.GetFileHash(tmpLocation);
                        if (string.Compare(expectedHash, currentHash, StringComparison.OrdinalIgnoreCase) != 0)
                        {
                            LogDialog.Log(job, string.Format("File downloaded, but hash of downloaded file {0} does not match the expected hash {1}.", currentHash, expectedHash));
                            File.Delete(tmpLocation);
                            throw new IOException("Hash verification failed.");
                        }
                    }
                }

                try
                {
                    FileInfo downloadedFileInfo = new FileInfo(tmpLocation);
                    job.LastFileSize = downloadedFileInfo.Length;
                    job.LastFileDate = downloadedFileInfo.LastWriteTime;
                }
                catch (Exception ex)
                {
                    LogDialog.Log(job, ex);
                }

                try
                {
                    // Before copying, we might have to create the directory
                    Directory.CreateDirectory(Path.GetDirectoryName(targetFileName));

                    // Copying might fail if variables have been replaced with bad values.
                    // However, we cannot rely on functions to clean up the path, since they
                    // might actually parse the path incorrectly and return an even worse path.
                    File.Copy(tmpLocation, targetFileName, true);
                }
                catch (ArgumentException)
                {
                    throw new TargetPathInvalidException(targetFileName);
                }
                catch (NotSupportedException)
                {
                    throw new TargetPathInvalidException(targetFileName);
                }

                File.Delete(tmpLocation);

                // At this point, the update is complete
                job.LastUpdated      = DateTime.Now;
                job.PreviousLocation = targetFileName;
            }

            job.Save();

            job.ExecutePostUpdateCommands();

            return(Status.UpdateSuccessful);
        }
        public static void ImportFromFile(string filename)
        {
            XmlDocument doc = new XmlDocument();

            doc.Load(filename);

            // Import settings from file as dictionary
            XmlElement settingsElem = doc.SelectSingleNode("//Settings/dictionary") as XmlElement ??
                                      doc.SelectSingleNode("//dictionary") as XmlElement;

            if (settingsElem != null)
            {
                XmlSerializer serializer = new XmlSerializer(typeof(SerializableDictionary <string, string>));

                using (StringReader textReader = new StringReader(settingsElem.OuterXml))
                {
                    DbManager.SetSettings(serializer.Deserialize(textReader) as Dictionary <string, string>);
                }
            }

            // Import global variables
            XmlElement varNodes = doc.SelectSingleNode("//GlobalVariables") as XmlElement;

            if (varNodes != null)
            {
                UrlVariable.GlobalVariables.Clear();

                foreach (XmlElement varElem in doc.SelectNodes("//GlobalVariables/Variable"))
                {
                    UrlVariable newVar = new UrlVariable
                    {
                        Name          = varElem.GetAttribute("Name"),
                        CachedContent = varElem.GetAttribute("Content")
                    };
                    UrlVariable.GlobalVariables[newVar.Name] = newVar;
                }

                UrlVariable.GlobalVariables.Save();
            }

            // Import code snippets
            XmlElement snippetNodes = doc.SelectSingleNode("//CodeSnippets") as XmlElement;

            if (snippetNodes != null)
            {
                using (SQLiteCommand comm = DbManager.Connection.CreateCommand())
                {
                    comm.CommandText = "DELETE FROM snippets";
                    comm.ExecuteNonQuery();
                }

                foreach (XmlElement snippetElem in doc.SelectNodes("//CodeSnippets/Snippet"))
                {
                    Snippet snippet = new Snippet
                    {
                        Guid = new Guid(snippetElem.GetAttribute("Guid")),
                        Name = snippetElem.GetAttribute("Name"),
                        Type = (ScriptType)Convert.ToInt32(snippetElem.GetAttribute("Type")),
                        Text = snippetElem.InnerText
                    };
                    snippet.Save();
                }
            }

            XmlElement setupNodes = doc.SelectSingleNode("//SetupLists") as XmlElement;

            if (setupNodes != null)
            {
                using (IDbCommand command = DbManager.Connection.CreateCommand())
                {
                    command.CommandText = @"DELETE FROM setuplists_applications";
                    command.ExecuteNonQuery();
                }

                using (IDbCommand command = DbManager.Connection.CreateCommand())
                {
                    command.CommandText = @"DELETE FROM setuplists";
                    command.ExecuteNonQuery();
                }

                foreach (XmlElement listElem in doc.SelectNodes("//SetupLists/List"))
                {
                    ApplicationList list = new ApplicationList
                    {
                        Name = listElem.GetAttribute("Name"),
                        Guid = new Guid(listElem.GetAttribute("Guid"))
                    };

                    foreach (XmlElement appListElem in listElem.SelectNodes("Applications/Application"))
                    {
                        Guid guid = new Guid(appListElem.GetAttribute("Guid"));

                        ApplicationJob job = DbManager.GetJob(guid);
                        if (job != null)
                        {
                            list.Applications.Add(job);
                        }
                    }

                    list.Save();
                }
            }
        }
Exemple #10
0
        /// <summary>
        /// Sets the POST data which is sent
        /// along with the request. Replaces variables.
        /// </summary>
        /// <param name="variable">The variable, which sends the request</param>
        public void SetPostData(UrlVariable variable)
        {
            string[][] pairs = GetKeyValuePairs(variable.PostData);
            if (variable.Parent != null)
            {
                foreach (string[] keyValue in pairs)
                {
                    keyValue[0] = variable.Parent.ReplaceAllInString(keyValue[0]);
                    keyValue[1] = variable.Parent.ReplaceAllInString(keyValue[1]);
                }
            }

            StringBuilder sb = new StringBuilder();
            foreach (string[] keyValue in pairs)
            {
                sb.Append(HttpUtility.UrlEncode(keyValue[0]) + "=" + HttpUtility.UrlEncode(keyValue[1]) + "&");
            }

            m_PostData = sb.ToString().TrimEnd('&');
        }
Exemple #11
0
        /// <summary>
        /// Executes the actual download from an URL. Does not handle exceptions,
        /// but takes care of proper cleanup.
        /// </summary>
        /// <exception cref="NonBinaryFileException">This exception is thrown, if the resulting file is not of a binary type</exception>
        /// <exception cref="TargetPathInvalidException">This exception is thrown, if the resulting target path of an application is not valid</exception>
        /// <param name="job">The job to process</param>
        /// <param name="urlToRequest">URL from which should be downloaded</param>
        /// <returns>true, if a new update has been found and downloaded, false otherwise</returns>
        protected Status DoDownload(ApplicationJob job, Uri urlToRequest)
        {
            // Lower security policies
            try
            {
                ServicePointManager.CheckCertificateRevocationList = false;
            }
            catch (PlatformNotSupportedException)
            {
                // .NET bug under special circumstances
            }

            ServicePointManager.ServerCertificateValidationCallback = delegate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
            {
                return(true);
            };

            // If we want to download multiple files simultaneously
            // from the same server, we need to "remove" the connection limit.
            ServicePointManager.DefaultConnectionLimit = 50;

            job.Variables.ResetDownloadCount();

            WebRequest.RegisterPrefix("sf", new ScpWebRequestCreator());
            WebRequest.RegisterPrefix("httpx", new HttpxRequestCreator());

            WebRequest req = WebRequest.CreateDefault(urlToRequest);

            AddRequestToCancel(req);
            req.Timeout = Convert.ToInt32(Settings.GetValue("ConnectionTimeout", 10)) * 1000; // 10 seconds by default

            HttpWebRequest httpRequest = req as HttpWebRequest;

            if (httpRequest != null)
            {
                // Store cookies for future requests. Some sites
                // check for previously stored cookies before allowing to download.
                if (httpRequest.CookieContainer == null)
                {
                    httpRequest.CookieContainer = m_Cookies;
                }
                else
                {
                    httpRequest.CookieContainer.Add(m_Cookies.GetCookies(httpRequest.RequestUri));
                }

                // If we have an HTTP request, some sites may require a correct referer
                // for the download.
                // If there are variables defined (from which most likely the download link
                // or version is being extracted), we'll just use the first variable's URL as referer.
                // The user still has the option to set a custom referer.
                // Note: Some websites don't "like" certain referers
                if (!m_NoAutoReferer.Contains(GetBaseHost(req.RequestUri)))
                {
                    foreach (UrlVariable urlVar in job.Variables.Values)
                    {
                        httpRequest.Referer = urlVar.Url;
                        break;
                    }
                }

                if (!string.IsNullOrEmpty(job.HttpReferer))
                {
                    httpRequest.Referer = job.Variables.ReplaceAllInString(job.HttpReferer);
                }

                LogDialog.Log(job, "Using referer: " + (string.IsNullOrEmpty(httpRequest.Referer) ? "(none)" : httpRequest.Referer));
                httpRequest.UserAgent = (string.IsNullOrEmpty(job.UserAgent) ? WebClient.UserAgent : job.UserAgent);

                // PAD files may be compressed
                httpRequest.AutomaticDecompression = (DecompressionMethods.GZip | DecompressionMethods.Deflate);
            }

            using (WebResponse response = WebClient.GetResponse(req))
            {
                LogDialog.Log(job, "Server source file: " + req.RequestUri.AbsolutePath);

                // Occasionally, websites are not available and an error page is encountered
                // For the case that the content type is just plain wrong, ignore it if the size is higher than 500KB
                HttpWebResponse httpResponse = response as HttpWebResponse;
                if (httpResponse != null && response.ContentLength < 500000)
                {
                    if (response.ContentType.StartsWith("text/xml") || response.ContentType.StartsWith("application/xml"))
                    {
                        // If an XML file is served, maybe we have a PAD file
                        ApplicationJob padJob = ApplicationJob.ImportFromPad(httpResponse);
                        if (padJob != null)
                        {
                            job.CachedPadFileVersion = padJob.CachedPadFileVersion;
                            return(DoDownload(job, new Uri(padJob.FixedDownloadUrl)));
                        }
                    }
                    if (response.ContentType.StartsWith("text/html"))
                    {
                        throw NonBinaryFileException.Create(response.ContentType, httpResponse.StatusCode);
                    }
                }

                long fileSize = GetContentLength(response);
                if (fileSize == 0)
                {
                    throw new IOException("Source file on server is empty (ContentLength = 0).");
                }

                string targetFileName = job.GetTargetFile(response, urlToRequest.AbsoluteUri);

                LogDialog.Log(job, "Determined target file name: " + targetFileName);

                // Only download, if the file size or date has changed
                if (!ForceDownload && !job.RequiresDownload(response, targetFileName))
                {
                    // If file already exists (created by user),
                    // the download is not necessary. We still need to
                    // set the file name.
                    // If the file exists, but not at the target location
                    // (after renaming), do not reset the previous location.
                    if (File.Exists(targetFileName))
                    {
                        job.PreviousLocation = targetFileName;
                    }
                    job.Save();
                    return(Status.NoUpdate);
                }

                // Skip downloading!
                // Installing also requires a forced download
                if (!ForceDownload && !m_InstallUpdated && (m_OnlyCheck || (job.CheckForUpdatesOnly && !IgnoreCheckForUpdatesOnly)))
                {
                    LogDialog.Log(job, "Skipped downloading updates");
                    return(Status.UpdateAvailable);
                }

                // Execute: Default pre-update command
                string defaultPreCommand = Settings.GetValue("PreUpdateCommand", "") as string;
                // For starting external download managers: {preupdate-url}
                defaultPreCommand = UrlVariable.Replace(defaultPreCommand, "preupdate-url", urlToRequest.ToString());
                ScriptType defaultPreCommandType = Command.ConvertToScriptType(Settings.GetValue("PreUpdateCommandType", ScriptType.Batch.ToString()) as string);

                int exitCode = new Command(defaultPreCommand, defaultPreCommandType).Execute(job, targetFileName);
                if (exitCode == 1)
                {
                    LogDialog.Log(job, "Default pre-update command returned '1', download aborted");
                    throw new CommandErrorException();
                }
                else if (exitCode == 2)
                {
                    LogDialog.Log(job, "Default pre-update command returned '2', download skipped");
                    return(Status.UpdateAvailable);
                }

                // Execute: Application pre-update command
                exitCode = new Command(UrlVariable.Replace(job.ExecutePreCommand, "preupdate-url", urlToRequest.ToString()), job.ExecutePreCommandType).Execute(job, targetFileName);
                if (exitCode == 1)
                {
                    LogDialog.Log(job, "Pre-update command returned '1', download aborted");
                    throw new CommandErrorException();
                }
                else if (exitCode == 2)
                {
                    LogDialog.Log(job, "Pre-update command returned '2', download skipped");
                    return(Status.UpdateAvailable);
                }
                else if (exitCode == 3)
                {
                    LogDialog.Log(job, "Pre-update command returned '3', external download");
                    job.LastUpdated = DateTime.Now;
                    job.Save();
                    return(Status.UpdateSuccessful);
                }

                // Read all file contents to a temporary location
                string tmpLocation = Path.GetTempFileName();

                // Read contents from the web and put into file
                using (Stream sourceFile = response.GetResponseStream())
                {
                    using (FileStream targetFile = File.Create(tmpLocation))
                    {
                        long byteCount = 0;
                        int  readBytes = 0;
                        m_Size[job] = fileSize;

                        do
                        {
                            if (m_CancelUpdates)
                            {
                                break;
                            }

                            // Some adjustment for SCP download: Read only up to the max known bytes
                            int maxRead = (fileSize > 0) ? (int)Math.Min(fileSize - byteCount, 1024) : 1024;
                            if (maxRead == 0)
                            {
                                break;
                            }

                            byte[] buffer = new byte[maxRead];
                            readBytes = sourceFile.Read(buffer, 0, maxRead);
                            if (readBytes > 0)
                            {
                                targetFile.Write(buffer, 0, readBytes);
                            }
                            byteCount += readBytes;
                            OnProgressChanged(byteCount, fileSize, job);
                        } while (readBytes > 0);
                    }
                }

                if (m_CancelUpdates)
                {
                    m_Progress[job] = 0;
                    OnStatusChanged(job);
                    return(Status.Failure);
                }

                // If each version has a different file name (version number),
                // we might only want to keep one of them. Also, we might
                // want to free some space on the target location.
                if (job.DeletePreviousFile)
                {
                    PathEx.TryDeleteFiles(job.PreviousLocation);
                }

                try
                {
                    File.SetLastWriteTime(tmpLocation, ApplicationJob.GetLastModified(response));
                }
                catch (ArgumentException)
                {
                    // Invalid file date. Ignore and just use DateTime.Now
                }

                try
                {
                    FileInfo downloadedFileInfo = new FileInfo(tmpLocation);
                    job.LastFileSize = downloadedFileInfo.Length;
                    job.LastFileDate = downloadedFileInfo.LastWriteTime;
                }
                catch (Exception ex)
                {
                    LogDialog.Log(job, ex);
                }

                try
                {
                    // Before copying, we might have to create the directory
                    Directory.CreateDirectory(Path.GetDirectoryName(targetFileName));

                    // Copying might fail if variables have been replaced with bad values.
                    // However, we cannot rely on functions to clean up the path, since they
                    // might actually parse the path incorrectly and return an even worse path.
                    File.Copy(tmpLocation, targetFileName, true);
                }
                catch (ArgumentException)
                {
                    throw new TargetPathInvalidException(targetFileName);
                }
                catch (NotSupportedException)
                {
                    throw new TargetPathInvalidException(targetFileName);
                }

                File.Delete(tmpLocation);

                // At this point, the update is complete
                job.LastUpdated      = DateTime.Now;
                job.PreviousLocation = targetFileName;
            }

            job.Save();

            job.ExecutePostUpdateCommands();

            return(Status.UpdateSuccessful);
        }