Beispiel #1
0
        /// <summary>
        /// Returns the next valid date, given the start and the interval
        /// </summary>
        /// <param name="basetime">The base time</param>
        /// <param name="firstdata">The first allowed date</param>
        /// <param name="repetition">The repetition interval</param>
        /// <param name="allowedDays">The days the backup is allowed to run</param>
        /// <returns>The next valid date, or throws an exception if no such date can be found</returns>
        public static DateTime GetNextValidTime(DateTime basetime, DateTime firstdate, string repetition, DayOfWeek[] allowedDays)
        {
            DateTime res = basetime;

            int i = 50000;

            while ((!IsDateAllowed(res, allowedDays) || res < firstdate) && i-- > 0)
            {
                res = Timeparser.ParseTimeInterval(repetition, res);
            }

            if (!IsDateAllowed(res, allowedDays) || res < firstdate)
            {
                StringBuilder sb = new StringBuilder();
                if (allowedDays != null)
                {
                    foreach (DayOfWeek w in allowedDays)
                    {
                        if (sb.Length != 0)
                        {
                            sb.Append(", ");
                        }
                        sb.Append(w.ToString());
                    }
                }

                throw new Exception(Strings.Scheduler.InvalidTimeSetupError(basetime, repetition, sb.ToString()));
            }

            return(res);
        }
        void IncrementalSettings_PageLeave(object sender, PageChangedArgs args)
        {
            if (args.Direction == PageChangedDirection.Back)
            {
                return;
            }

            if (EnableCleanupDuration.Checked)
            {
                try
                {
                    if (Timeparser.ParseTimeSpan(CleanupDuration.Value).TotalDays < 1)
                    {
                        MessageBox.Show(this, Strings.CleanupSettings.TooShortCleanupDurationDay, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
                        args.Cancel = true;
                        return;
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show(this, string.Format(GUI.Strings.Common.InvalidDuration, ex.Message), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
                    args.Cancel = true;
                    return;
                }
            }

            if (!m_wrapper.CleanupSettingsUI.HasWarnedClean && !(EnableCleanupDuration.Checked || EnableFullBackupClean.Checked))
            {
                if (MessageBox.Show(this, Strings.CleanupSettings.DisabledCleanupWarning, Application.ProductName, MessageBoxButtons.YesNoCancel, MessageBoxIcon.Warning) != DialogResult.Yes)
                {
                    args.Cancel = true;
                    return;
                }
                m_wrapper.CleanupSettingsUI.HasWarnedClean = true;
            }

            m_wrapper.MaxFullBackups       = EnableFullBackupClean.Checked ? (int)CleanFullBackupCount.Value : 0;
            m_wrapper.BackupExpireInterval = EnableCleanupDuration.Checked ? CleanupDuration.Value : "";
            m_wrapper.IgnoreFileTimestamps = IgnoreTimestamps.Checked;

            //Don't set args.NextPage, it runs on a list
        }
        public SharePointBackend(string url, Dictionary <string, string> options)
        {
            m_deleteToRecycler    = Utility.Utility.ParseBoolOption(options, "delete-to-recycler");
            m_useBinaryDirectMode = Utility.Utility.ParseBoolOption(options, "binary-direct-mode");

            try
            {
                string strSpan;
                if (options.TryGetValue("web-timeout", out strSpan))
                {
                    TimeSpan ts = Timeparser.ParseTimeSpan(strSpan);
                    if (ts.TotalMilliseconds > 30000 && ts.TotalMilliseconds < int.MaxValue)
                    {
                        this.m_useContextTimeoutMs = (int)ts.TotalMilliseconds;
                    }
                }
            }
            catch { }

            try
            {
                string strChunkSize;
                if (options.TryGetValue("chunk-size", out strChunkSize))
                {
                    long pSize = Utility.Sizeparser.ParseSize(strChunkSize, "MB");
                    if (pSize >= (1 << 14) && pSize <= (1 << 30)) // [16kb .. 1GB]
                    {
                        this.m_fileChunkSize = (int)pSize;
                    }
                }
            }
            catch { }


            var u = new Utility.Uri(url);

            u.RequireHost();

            // Create sanitized plain https-URI (note: still has double slashes for processing web)
            m_orgUrl = new Utility.Uri("https", u.Host, u.Path, null, null, null, u.Port);

            // Actual path to Web will be searched for on first use. Ctor should not throw.
            m_spWebUrl = null;

            m_serverRelPath = u.Path;
            if (!m_serverRelPath.StartsWith("/", StringComparison.Ordinal))
            {
                m_serverRelPath = "/" + m_serverRelPath;
            }
            if (!m_serverRelPath.EndsWith("/", StringComparison.Ordinal))
            {
                m_serverRelPath += "/";
            }
            // remove marker for SP-Web
            m_serverRelPath = m_serverRelPath.Replace("//", "/");

            // Authentication settings processing:
            // Default: try integrated auth (will normally not work for Office365, but maybe with on-prem SharePoint...).
            // Otherwise: Use settings from URL(precedence) or from command line options.
            bool useIntegratedAuthentication = Utility.Utility.ParseBoolOption(options, "integrated-authentication");

            string useUsername = null;
            string usePassword = null;

            if (!useIntegratedAuthentication)
            {
                if (!string.IsNullOrEmpty(u.Username))
                {
                    useUsername = u.Username;
                    if (!string.IsNullOrEmpty(u.Password))
                    {
                        usePassword = u.Password;
                    }
                    else if (options.ContainsKey("auth-password"))
                    {
                        usePassword = options["auth-password"];
                    }
                }
                else
                {
                    if (options.ContainsKey("auth-username"))
                    {
                        useUsername = options["auth-username"];
                        if (options.ContainsKey("auth-password"))
                        {
                            usePassword = options["auth-password"];
                        }
                    }
                }
            }

            if (useIntegratedAuthentication || (useUsername == null || usePassword == null))
            {
                // This might or might not work for on-premises SP. Maybe support if someone complains...
                m_userInfo = System.Net.CredentialCache.DefaultNetworkCredentials;
            }
            else
            {
                System.Security.SecureString securePwd = new System.Security.SecureString();
                usePassword.ToList().ForEach(c => securePwd.AppendChar(c));
                m_userInfo = new Microsoft.SharePoint.Client.SharePointOnlineCredentials(useUsername, securePwd);
                // Other options (also ADAL, see class remarks) might be supported on request.
                // Maybe go in deep then and also look at:
                // - Microsoft.SharePoint.Client.AppPrincipalCredential.CreateFromKeyGroup()
                // - ctx.AuthenticationMode = SP.ClientAuthenticationMode.FormsAuthentication;
                // - ctx.FormsAuthenticationLoginInfo = new SP.FormsAuthenticationLoginInfo(user, pwd);
            }
        }
Beispiel #4
0
        /// <summary>
        /// Returns the next valid date, given the start and the interval
        /// </summary>
        /// <param name="basetime">The base time</param>
        /// <param name="firstdate">The first allowed date</param>
        /// <param name="repetition">The repetition interval</param>
        /// <param name="allowedDays">The days the backup is allowed to run</param>
        /// <returns>The next valid date, or throws an exception if no such date can be found</returns>
        public static DateTime GetNextValidTime(DateTime basetime, DateTime firstdate, string repetition, DayOfWeek[] allowedDays)
        {
            var res = basetime;

            var i = 50000;

            while (res < firstdate && i-- > 0)
            {
                res = Timeparser.ParseTimeInterval(repetition, res);
            }

            // If we arived somewhere after the first allowed date
            if (res >= firstdate)
            {
                var ts = Timeparser.ParseTimeSpan(repetition);

                if (ts.TotalDays >= 1)
                {
                    // We jump in days, so we pick the first valid day after firstdate

                    for (var n = 0; n < 8; n++)
                    {
                        if (IsDateAllowed(res, allowedDays))
                        {
                            break;
                        }
                        else
                        {
                            res = res.AddDays(1);
                        }
                    }
                }
                else
                {
                    // We jump less than a day, so we keep adding the repetition until
                    // we hit a valid day

                    i = 50000;
                    while (!IsDateAllowed(res, allowedDays) && i-- > 0)
                    {
                        res = Timeparser.ParseTimeInterval(repetition, res);
                    }
                }
            }

            if (!IsDateAllowed(res, allowedDays) || res < firstdate)
            {
                StringBuilder sb = new StringBuilder();
                if (allowedDays != null)
                {
                    foreach (DayOfWeek w in allowedDays)
                    {
                        if (sb.Length != 0)
                        {
                            sb.Append(", ");
                        }
                        sb.Append(w.ToString());
                    }
                }

                throw new Exception(Strings.Scheduler.InvalidTimeSetupError(basetime, repetition, sb.ToString()));
            }

            return(res);
        }
Beispiel #5
0
        private void BuildRecent()
        {
            Log[] logs;
            lock (Program.MainLock)
                logs = Program.DataConnection.GetObjects <Log>("EndTime > ? AND SubAction LIKE ? ORDER BY EndTime DESC", Timeparser.ParseTimeInterval(new Datamodel.ApplicationSettings(Program.DataConnection).RecentBackupDuration, DateTime.Now, true), "Primary");

            try
            {
                recentBackups.BeginUpdate();
                recentBackups.Items.Clear();
                foreach (Log l in logs)
                {
                    ListViewItem lvi = new ListViewItem(new string[] { l.EndTime.ToString("g"), l.OwnerTask == null || l.OwnerTask.Schedule == null ? "" : l.OwnerTask.Schedule.Name, l.Transfersize > 0 ? l.TransferSizeString : "" });

                    lvi.Tag        = l;
                    lvi.ImageIndex = imageList.Images.ContainsKey(l.ParsedStatus) ? imageList.Images.IndexOfKey(l.ParsedStatus) : imageList.Images.IndexOfKey("Warning");
                    recentBackups.Items.Add(lvi);

                    if (!string.IsNullOrEmpty(l.ParsedMessage))
                    {
                        lvi.ToolTipText = l.ParsedMessage;
                    }
                    else
                    {
                        switch (l.ParsedStatus)
                        {
                        case DuplicatiOutputParser.OKStatus:
                            lvi.ToolTipText = Strings.ServiceStatus.BackupStatusOK;
                            break;

                        case DuplicatiOutputParser.ErrorStatus:
                            lvi.ToolTipText = Strings.ServiceStatus.BackupStatusError;
                            break;

                        case DuplicatiOutputParser.WarningStatus:
                            lvi.ToolTipText = Strings.ServiceStatus.BackupStatusWarning;
                            break;

                        case DuplicatiOutputParser.PartialStatus:
                            lvi.ToolTipText = Strings.ServiceStatus.BackupStatusPartial;
                            break;
                        }
                    }
                }
            }
            finally
            {
                recentBackups.EndUpdate();
            }
        }
Beispiel #6
0
        /// <summary>
        /// The actual scheduling procedure
        /// </summary>
        private void Runner()
        {
            while (!m_terminate)
            {
                List <Schedule> reps = new List <Schedule>();
                List <Schedule> tmp;
                lock (m_datalock)
                    tmp = new List <Schedule>(m_connection.GetObjects <Schedule>());

                //Determine schedule list
                foreach (Schedule sc in tmp)
                {
                    if (!string.IsNullOrEmpty(sc.Repeat))
                    {
                        DateTime start = sc.NextScheduledTime;

                        try { start = GetNextValidTime(sc.NextScheduledTime, sc.Repeat, sc.AllowedWeekdays); }
                        catch { } //TODO: Report this somehow

                        //If time is exceeded, run it now
                        if (start <= DateTime.Now)
                        {
                            //See if it is already queued
                            List <IDuplicityTask> tmplst   = m_worker.CurrentTasks;
                            IDuplicityTask        tastTemp = m_worker.CurrentTask;
                            if (tastTemp != null)
                            {
                                tmplst.Add(tastTemp);
                            }

                            bool found = false;
                            foreach (IDuplicityTask t in tmplst)
                            {
                                if (t != null && t is IncrementalBackupTask && ((IncrementalBackupTask)t).Schedule.ID == sc.ID)
                                {
                                    found = true;
                                    break;
                                }
                            }

                            //If it is not already in queue, put it there
                            if (!found)
                            {
                                m_worker.AddTask(new IncrementalBackupTask(sc));
                            }

                            //Caluclate next time, by adding the interval to the start until we have
                            // passed the current date and time
                            //TODO: Make this more efficient
                            int i = 50000;
                            while (start <= DateTime.Now && i-- > 0)
                            {
                                try { start = GetNextValidTime(Timeparser.ParseTimeInterval(sc.Repeat, start), sc.Repeat, sc.AllowedWeekdays); }
                                catch
                                {
                                    //TODO: Report this somehow
                                    continue;
                                }
                            }

                            if (start < DateTime.Now)
                            {
                                continue;
                            }
                        }

                        //Add to schedule list at the new time
                        reps.Add(sc);
                        sc.NextScheduledTime = start;
                    }
                }

                System.Data.LightDatamodel.QueryModel.OperationOrParameter op = System.Data.LightDatamodel.QueryModel.Parser.ParseQuery("ORDER BY When ASC");

                //Sort them, lock as we assign the m_schedule variable
                lock (m_lock)
                    m_schedule = op.EvaluateList <Schedule>(reps).ToArray();

                //Raise event if needed
                if (NewSchedule != null)
                {
                    NewSchedule(this, null);
                }

                int waittime = 0;

                //Figure out a sensible amount of time to sleep the thread
                if (m_schedule.Length > 0)
                {
                    //When is the next run scheduled?
                    TimeSpan nextrun = m_schedule[0].NextScheduledTime - DateTime.Now;
                    if (nextrun.TotalMilliseconds < 0)
                    {
                        continue;
                    }

                    //Don't sleep for more than 5 minutes
                    waittime = (int)Math.Min(nextrun.TotalMilliseconds, 60 * 1000 * 5);
                }
                else
                {
                    //No tasks, check back later
                    waittime = 60 * 1000;
                }

                //Waiting on the event, enables a wakeup call from termination
                // never use waittime = 0
                m_event.WaitOne(Math.Max(100, waittime), false);
            }
        }
Beispiel #7
0
        void SelectWhen_PageLeave(object sender, PageChangedArgs args)
        {
            if (args.Direction == PageChangedDirection.Back)
            {
                return;
            }

            if (!m_wrapper.SelectWhenUI.HasWarnedNoSchedule && NoScheduleRadio.Checked)
            {
                if (MessageBox.Show(this, Strings.SelectWhen.NoScheduleWarning, Application.ProductName, MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button3) != DialogResult.Yes)
                {
                    args.Cancel = true;
                    return;
                }
                m_wrapper.SelectWhenUI.HasWarnedNoSchedule = true;
            }

            if (!m_wrapper.SelectWhenUI.HasWarnedNoIncrementals && !IncrementalPeriodRadio.Checked)
            {
                string s = NeverFullRadio.Checked ? Strings.SelectWhen.OnlyIncrementalBackupsWarning : Strings.SelectWhen.OnlyFullBackupsWarning;
                if (MessageBox.Show(this, s, Application.ProductName, MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button3) != DialogResult.Yes)
                {
                    args.Cancel = true;
                    return;
                }
                m_wrapper.SelectWhenUI.HasWarnedNoIncrementals = true;
            }

            DateTime scheduledTime    = OffsetDate.Value.Date.Add(OffsetTime.Value.TimeOfDay);
            TimeSpan scheduleInterval = new TimeSpan(0);

            if (ScheduleRadio.Checked)
            {
                try
                {
                    scheduleInterval = Timeparser.ParseTimeSpan(RepeatInterval.Value);
                    if (scheduleInterval.TotalMinutes < 5)
                    {
                        MessageBox.Show(this, string.Format(Strings.SelectWhen.TooShortScheduleDurationError, 5), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
                        args.Cancel = true;
                        return;
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show(this, string.Format(Duplicati.GUI.Strings.Common.InvalidDuration, ex.Message), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
                    args.Cancel = true;
                    return;
                }
            }

            TimeSpan fullDuration = new TimeSpan(0);

            if (IncrementalPeriodRadio.Checked)
            {
                try
                {
                    fullDuration = Timeparser.ParseTimeSpan(FullDuration.Value);
                    if (fullDuration.TotalMinutes < 10)
                    {
                        MessageBox.Show(this, string.Format(Strings.SelectWhen.TooShortFullDurationError, 10), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
                        args.Cancel = true;
                        return;
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show(this, string.Format(Duplicati.GUI.Strings.Common.InvalidDuration, ex.Message), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
                    args.Cancel = true;
                    return;
                }
            }

            if (ScheduleRadio.Checked && IncrementalPeriodRadio.Checked)
            {
                if (fullDuration < scheduleInterval)
                {
                    MessageBox.Show(this, Strings.SelectWhen.FullDurationShorterThanScheduleDurationError, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
                    args.Cancel = true;
                    return;
                }

                if (!m_wrapper.SelectWhenUI.HasWarnedTooManyIncremental && fullDuration.Ticks / scheduleInterval.Ticks > 100)
                {
                    if (MessageBox.Show(this, string.Format(Strings.SelectWhen.TooManyIncrementalsWarning, fullDuration.Ticks / scheduleInterval.Ticks), Application.ProductName, MessageBoxButtons.YesNoCancel, MessageBoxIcon.Warning) != DialogResult.Yes)
                    {
                        args.Cancel = true;
                        return;
                    }

                    m_wrapper.SelectWhenUI.HasWarnedTooManyIncremental = true;
                }
            }

            m_wrapper.BackupTimeOffset = scheduledTime;
            if (ScheduleRadio.Checked)
            {
                m_wrapper.RepeatInterval = RepeatInterval.Value;
                List <DayOfWeek> w    = new List <DayOfWeek>();
                CheckBox[]       chks = new CheckBox[] { Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday };
                for (int i = 0; i < chks.Length; i++)
                {
                    if (chks[i].Checked)
                    {
                        w.Add((DayOfWeek)i);
                    }
                }

                m_wrapper.AllowedWeekdays = w.ToArray();

                try
                {
                    Scheduler.GetNextValidTime(m_wrapper.BackupTimeOffset, m_wrapper.RepeatInterval, m_wrapper.AllowedWeekdays);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(this, string.Format(Duplicati.GUI.Strings.Common.InvalidDuration, ex.Message), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
                    args.Cancel = true;
                    return;
                }
            }
            else
            {
                m_wrapper.RepeatInterval  = "";
                m_wrapper.AllowedWeekdays = null;
            }

            if (IncrementalPeriodRadio.Checked)
            {
                m_wrapper.FullBackupInterval = FullDuration.Value;
            }
            else if (NeverFullRadio.Checked)
            {
                m_wrapper.FullBackupInterval = "";
            }
            else if (AlwaysFullRadio.Checked)
            {
                m_wrapper.FullBackupInterval = "1s"; //TODO: Is this a good way to specify this?
            }
            //Don't set args.NextPage, it runs on a list
        }