/// <summary> /// Fetches the signatures for the account. /// </summary> /// <param name="account">The account.</param> /// <returns>The signature hash</returns> private string FetchSignatures(ZPushAccount account) { Logger.Instance.Debug(this, "Fetching signatures for account {0}", account); using (ZPushConnection connection = account.Connect()) using (ZPushWebServiceInfo infoService = connection.InfoService) { GetSignatures result = infoService.Execute(new GetSignaturesRequest()); // Store the signatures Dictionary <object, string> fullNames = new Dictionary <object, string>(); using (ISignatures signatures = ThisAddIn.Instance.GetSignatures()) { foreach (Signature signature in result.all.Values) { string name = StoreSignature(signatures, account, signature); fullNames.Add(signature.id, name); } } // Set default signatures if available and none are set if (!string.IsNullOrEmpty(result.new_message) && ShouldSetSignature(account.Account.SignatureNewMessage)) { account.Account.SignatureNewMessage = fullNames[result.new_message]; } if (!string.IsNullOrEmpty(result.replyforward_message) && ShouldSetSignature(account.Account.SignatureReplyForwardMessage)) { account.Account.SignatureReplyForwardMessage = fullNames[result.replyforward_message]; } return(result.hash); } }
public void SetDeviceOptions(ZPushAccount account, SyncTimeFrame timeFrame) { try { Logger.Instance.Debug(this, "Setting sync time frame for {0} to {1}", account, timeFrame); // First set the server value. using (ZPushConnection connection = account.Connect()) using (ZPushWebServiceDevice deviceService = connection.DeviceService) { deviceService.Execute(new SetDeviceOptionsRequest(timeFrame)); } // And the local value account.SyncTimeFrame = timeFrame; Logger.Instance.Debug(this, "Set sync time frame for {0} to {1}", account, timeFrame); // Sync ThisAddIn.Instance.SendReceive(account.Account); } catch (Exception x) { Logger.Instance.Warning(this, "Exception setting sync time frame for {0} to {1}: {2}", account, timeFrame, x); } }
private void LoadSettings() { BusyText = Properties.Resources.OOFGet_Label; KUITask .New((ctx) => { using (ZPushConnection con = new ZPushConnection(_account, ctx.CancellationToken)) { _settings = con.Execute(new ActiveSync.SettingsOOFGet()); } }) .OnSuccess(InitSettings, true) .OnError((e) => { Logger.Instance.Warning(this, "Exception getting OOF state: {0}", e); if (MessageBox.Show( Properties.Resources.OOFGet_Failed, Properties.Resources.OOFGet_Title, MessageBoxButtons.OKCancel, MessageBoxIcon.Error ) != DialogResult.OK) { DialogResult = DialogResult.Cancel; } else { // Initialise default settings _settings = new ActiveSync.SettingsOOF(true); InitSettings(); } }) .Start(this) ; }
protected override void ProcessRequest() { string username = Url; // Request the data from the ZPush server ZPushConnection connection = new ZPushConnection(_freeBusy.FindZPushAccount(username), new System.Threading.CancellationToken(false)); // Include yesterday in the request, outlook shows it by default var request = new ActiveSync.ResolveRecipientsRequest(username, DateTime.Today.AddDays(-1), DateTime.Today.AddMonths(6)); var response = connection.Execute(request); // If there is no FreeBusy data, return 404 if (response?.FreeBusy == null) { throw new InvalidOperationException(); } Logger.Instance.Trace(this, "Writing response"); // Encode the response in vcard format Out.WriteLine("HTTP/1.0 200 OK"); Out.WriteLine("Content-Type: text/vcard"); Out.WriteLine("Connection: close"); Out.WriteLine(""); Out.WriteLine("BEGIN:VCALENDAR"); Out.WriteLine("PRODID:-//ZPush//EN"); Out.WriteLine("VERSION:2.0"); Out.WriteLine("BEGIN:VFREEBUSY"); Out.WriteLine("ORGANIZER:" + username); Out.WriteLine(string.Format("URL:http://127.0.0.1:{0}/{1}/{2}", _freeBusy.Port, FeatureFreeBusy.URL_IDENTIFIER, username)); Out.WriteLine(string.Format("DTSTAMP:{0:" + Constants.DATE_ISO_8601 + "}", DateTime.Now)); Out.WriteLine(string.Format("DTSTART:{0:" + Constants.DATE_ISO_8601 + "}", response.FreeBusy.StartTime)); Out.WriteLine(string.Format("DTEND:{0:" + Constants.DATE_ISO_8601 + "}", response.FreeBusy.EndTime)); foreach (ActiveSync.FreeBusyData data in response.FreeBusy) { if (data.Type != ActiveSync.FreeBusyType.Free) { string freeBusy = string.Format("FREEBUSY;FBTYPE={2}:{0:" + Constants.DATE_ISO_8601 + "}/{1:" + Constants.DATE_ISO_8601 + "}", data.Start, data.End, MapType(data.Type)); Out.WriteLine(freeBusy); } } Out.WriteLine("END:VFREEBUSY"); Out.WriteLine("END:VCALENDAR"); }
private void Periodic_Sync(ZPushConnection connection) { try { // TODO: merge this into ZPushAccount, allow periodic rechecking of Z-Push confirmation. That was other // features can be updated too, e.g. OOF status. That's pretty easy to do, only need to check if // no other features will break if the ConfirmedChanged event is raised multiple times ActiveSync.SettingsOOF oof = connection.Execute(new ActiveSync.SettingsOOFGet()); SyncSignatures(connection.Account, oof.RawResponse.SignaturesHash); } catch (System.Exception e) { Logger.Instance.Error(this, "Error fetching signature hash: {0}", e); } }
private void CheckSyncState(ZPushAccount account) { // TODO: we probably want one invocation for all accounts using (ZPushConnection connection = account.Connect()) { // Check total size CheckTotalSize(connection); // Update sync state using (ZPushWebServiceDevice deviceService = connection.DeviceService) { // Fetch DeviceDetails details = deviceService.Execute(new GetDeviceDetailsRequest()); if (details != null) { bool wasSyncing = false; // Create or update session SyncSession session = account.GetFeatureData <SyncSession>(this, null); if (session == null) { session = new SyncSession(this, account); } else { wasSyncing = session.IsSyncing; } session.Add(details); // Store with the account account.SetFeatureData(this, null, session); if (wasSyncing != session.IsSyncing) { // Sync state has changed, update the schedule Watcher.Sync.SetTaskSchedule(_task, account, session.IsSyncing ? CheckPeriodSync : (TimeSpan?)null); } } } } // Update the total for all accounts UpdateTotalSyncState(); // Check for stalls CheckSyncStalled(account); }
private void AdditionalFolders_Sync(ZPushConnection connection) { using (SharedFoldersManager manager = Manage(connection.Account)) { Logger.Instance.Debug(this, "Starting sync for account {0}", connection.Account); // Fetch the current shares ICollection <SharedFolder> shares = manager.GetCurrentShares(null); Logger.Instance.Trace(this, "AdditionalFolders_Sync: {0}", shares.Count); // Convert to dictionary Dictionary <SyncId, SharedFolder> dict = shares.ToDictionary(x => x.SyncId); Logger.Instance.Trace(this, "AdditionalFolders_Sync2: {0}", shares.Count); // Store with the account connection.Account.SetFeatureData(this, KEY_SHARES, dict); } }
/// <summary> /// Handles a new account. /// </summary> /// <param name="account">The account.</param> internal void OnAccountDiscovered(ZPushAccount account) { // Notify any account listeners AccountDiscovered?.Invoke(account); // Register any events HandleFolderWatchers(account); if (account.Account.HasPassword) { // Send an OOF request to get the OOF state and capabilities Tasks.Task(null, null, "ZPushCheck: " + account.DisplayName, () => { // TODO: if this fails, retry? ActiveSync.SettingsOOF oof; using (ZPushConnection connection = new ZPushConnection(account, new System.Threading.CancellationToken(false))) { oof = connection.Execute(new ActiveSync.SettingsOOFGet()); } account.OnConfirmationResponse(oof.RawResponse); // [ZO-109] Always update the current selection, it might have changed. Explorer_SelectionChange(); // Notify the OOF feature. // TODO: this coupling is pretty hideous ThisAddIn.Instance.GetFeature <FeatureOutOfOffice>()?.OnOOFSettings(account, oof); }); } else { ThisAddIn.Instance.InvokeUI(() => { Logger.Instance.Warning(this, "Password not available for account: {0}", account); System.Windows.Forms.MessageBox.Show(ThisAddIn.Instance.Window, string.Format(Properties.Resources.AccountNoPassword_Body, account.DisplayName), Properties.Resources.AccountNoPassword_Title, System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Information ); }); } }
/// <summary> /// Returns the task for execution. /// </summary> /// <param name="schedule">The schedule that triggered the task execution, or null if this is a sync.</param> /// <param name="account">The account for which the tasks are requested.</param> /// <returns>The task instance, or null if there is no task to execute in this schedule.</returns> public AcaciaTask GetInstance(Schedule schedule, ZPushAccount account) { if (!IsTaskScheduleApplicable(schedule, account)) { return(null); } if (_actionConnection != null) { return(new AcaciaTask(null, _owner, _name, () => { // TODO: reuse connections using (ZPushConnection con = account.Connect()) { _actionConnection(con); } })); } else { return(new AcaciaTask(null, _owner, _name, () => _action(account))); } }
private void AdditionalFolders_Sync(ZPushConnection connection) { SyncShares(connection.Account); }
private void _buttons_Apply(object sender, EventArgs e) { BusyText = Properties.Resources.OOFSet_Label; ActiveSync.SettingsOOF currentSettings = GetSettings(); KUITask .New((ctx) => { using (ZPushConnection connection = new ZPushConnection(_account, ctx.CancellationToken)) { // Set the OOF state. This always seems to return ok, so we fetch the settings // again, to see what happend connection.Execute(new ActiveSync.SettingsOOFSet(currentSettings)); // Fetch the OOF state return(connection.Execute(new ActiveSync.SettingsOOFGet())); } }) .OnSuccess((appliedSettings) => { // Store them for later use _feature.StoreOOFSettings(_account, appliedSettings); // Check what happened string message; MessageBoxIcon messageIcon; if (currentSettings.State == ActiveSync.OOFState.Disabled) { // Tried to disable. if (appliedSettings.State != ActiveSync.OOFState.Disabled) { // It's an error if its not actually disabled message = Properties.Resources.OOFSet_DisableFailed; messageIcon = MessageBoxIcon.Error; } else { // All good message = Properties.Resources.OOFSet_Disabled; messageIcon = MessageBoxIcon.Information; } } else if (appliedSettings.State == ActiveSync.OOFState.Disabled) { // It's an error if the state is set to disabled when we tried to enable message = Properties.Resources.OOFSet_EnableFailed; messageIcon = MessageBoxIcon.Error; } else { // All good if (appliedSettings.State == ActiveSync.OOFState.EnabledTimeBased) { message = string.Format(Properties.Resources.OOFSet_EnabledTimeBased, appliedSettings.From, appliedSettings.Till); } else { message = Properties.Resources.OOFSet_Enabled; } messageIcon = MessageBoxIcon.Information; // It's okay if the state is not the same, but it deserves a message if (appliedSettings.State != currentSettings.State) { message = Properties.Resources.OOFSet_DifferentState + message; messageIcon = MessageBoxIcon.Warning; } } Logger.Instance.Debug(this, "OOF state updated: {0}, {1}", message, messageIcon); MessageBox.Show(message, Properties.Resources.OOFSet_Title, MessageBoxButtons.OK, messageIcon ); if (messageIcon == MessageBoxIcon.Information) { // All good, close the dialog _buttons.IsDirty = false; DialogResult = DialogResult.OK; } else { // There was a problem, initialise the dialog to what's set. _settings = appliedSettings; InitSettings(); CheckDirty(); } }, true) .OnError((x) => { ErrorUtil.HandleErrorNew(this, "Exception in OOFSet", x, Properties.Resources.OOFSet_Title, Properties.Resources.OOFSet_Failed); }) .Start(this) ; }
/// <summary> /// Creates an instance on an explicit connection. /// </summary> /// <param name="connection">The connection.</param> /// <param name="dispose">Controls whether the connection will be disposed when the API is disposed.</param> public SharedFoldersAPI(ZPushConnection connection, bool dispose = false) { this._connection = connection; this._dispose = dispose; }
private void CheckTotalSize(ZPushConnection connection) { if (!CheckStoreSize || _checkedStoreSize) { return; } // Only works on 2.5 // If we don't have the version yet, try again later if (connection.Account.ZPushVersion == null) { return; } // Only check once _checkedStoreSize = true; // If it's not 2.5, don't check again if (!connection.Account.ZPushVersion.IsAtLeast(2, 5)) { return; } try { Logger.Instance.Debug(this, "Fetching size information for account {0}", connection.Account); using (ZPushWebServiceInfo infoService = connection.InfoService) { UserStoreInfo info = infoService.Execute(new GetUserStoreInfoRequest()); Logger.Instance.Debug(this, "Size information: {0}", info); SyncTimeFrame suggested = SuggestSyncTimeFrame(info); if (suggested.IsShorterThan(connection.Account.SyncTimeFrame)) { // Suggest shorter time frame, if not already done string lastCheckedSize = connection.Account.Account[KEY_CHECKED_SIZE]; if (!string.IsNullOrWhiteSpace(lastCheckedSize)) { try { SyncTimeFrame old = (SyncTimeFrame)int.Parse(lastCheckedSize); if (old >= suggested) { Logger.Instance.Trace(this, "Not suggesting reduced sync time frame again: {0}: {2} -> {1}", info, suggested, old); return; } } catch (Exception e) { Logger.Instance.Warning(this, "Invalid lastCheckedSize: {0}: {1}", lastCheckedSize, e); } } Logger.Instance.Debug(this, "Suggesting reduced sync time frame: {0}: {2} -> {1}", info, suggested, connection.Account.SyncTimeFrame); // Suggest a shorter timeframe DialogResult result = MessageBox.Show(ThisAddIn.Instance.Window, string.Format(Properties.Resources.SyncState_StoreSize_Body, info.storesize.ToSizeString(SizeUtil.Size.MB), suggested.ToDisplayString()), Properties.Resources.SyncState_StoreSize_Caption, MessageBoxButtons.OKCancel, MessageBoxIcon.Information); if (result == DialogResult.OK) { // Set the sync time frame Logger.Instance.Debug(this, "Applying reduced sync time frame: {0}: {2} -> {1}", info, suggested, connection.Account.SyncTimeFrame); connection.Account.SyncTimeFrame = suggested; } } connection.Account.Account[KEY_CHECKED_SIZE] = ((int)suggested).ToString(); } } catch (Exception e) { Logger.Instance.Warning(this, "Error suggesting size: {0}", e); } }