Exemplo n.º 1
0
        /// <summary>
        /// Get the Outlook category colour from the name given to the category
        /// </summary>
        /// <param name="categoryName">The user named Outlook category</param>
        /// <returns>The Outlook category type</returns>
        public Outlook.OlCategoryColor?OutlookColour(String categoryName)
        {
            if (string.IsNullOrEmpty(categoryName))
            {
                log.Warn("Category name is empty.");
            }

            try {
                if (this.categories != null && this.categories.Count > 0)
                {
                }
            } catch (System.Exception ex) {
                OGCSexception.Analyse("Categories are not accessible!", OGCSexception.LogAsFail(ex));
                this.categories = null;
            }

            if (this.categories == null || OutlookOgcs.Calendar.Categories == null)
            {
                OutlookOgcs.Calendar.Instance.IOutlook.RefreshCategories();
                this.categories = Calendar.Categories.categories;
            }

            foreach (Outlook.Category category in this.categories)
            {
                if (category.Name == categoryName.Trim())
                {
                    return(category.Color);
                }
            }

            log.Warn("Could not convert category name '" + categoryName + "' into Outlook category type.");
            return(null);
        }
Exemplo n.º 2
0
        private void ogcsPushTimer_Tick(object sender, EventArgs e)
        {
            if (Forms.ErrorReporting.Instance.Visible)
            {
                return;
            }
            log.Fine("Push sync triggered.");

            try {
                System.Collections.Generic.List <Microsoft.Office.Interop.Outlook.AppointmentItem> items = OutlookOgcs.Calendar.Instance.GetCalendarEntriesInRange(true);

                if (items.Count < this.lastRunItemCount || items.FindAll(x => x.LastModificationTime > this.lastRunTime).Count > 0)
                {
                    log.Debug("Changes found for Push sync.");
                    Forms.Main.Instance.NotificationTray.ShowBubbleInfo("Autosyncing calendars: " + Settings.Instance.SyncDirection.Name + "...");
                    if (!Sync.Engine.Instance.SyncingNow)
                    {
                        Forms.Main.Instance.Sync_Click(sender, null);
                    }
                    else
                    {
                        log.Debug("Busy syncing already. No need to push.");
                    }
                }
                else
                {
                    log.Fine("No changes found.");
                }
                failures = 0;
            } catch (System.Exception ex) {
                failures++;
                log.Warn("Push Sync failed " + failures + " times to check for changed items.");

                String hResult = OGCSexception.GetErrorCode(ex);
                if ((ex is System.InvalidCastException && hResult == "0x80004002" && ex.Message.Contains("0x800706BA")) || //The RPC server is unavailable
                    (ex is System.Runtime.InteropServices.COMException && (
                         ex.Message.Contains("0x80010108(RPC_E_DISCONNECTED)") ||                                          //The object invoked has disconnected from its clients
                         hResult == "0x800706BE" ||                                                                        //The remote procedure call failed
                         hResult == "0x800706BA"))                                                                         //The RPC server is unavailable
                    )
                {
                    OGCSexception.Analyse(OGCSexception.LogAsFail(ex));
                    try {
                        OutlookOgcs.Calendar.Instance.Reset();
                    } catch (System.Exception ex2) {
                        OGCSexception.Analyse("Failed resetting Outlook connection.", ex2);
                    }
                }
                else
                {
                    OGCSexception.Analyse(ex);
                }
                if (failures == 10)
                {
                    Forms.Main.Instance.Console.UpdateWithError("Push Sync is failing.", ex, notifyBubble: true);
                }
            }
        }
        public Boolean UserSubscriptionCheck()
        {
            List <Event> result    = new List <Event>();
            Events       request   = null;
            String       pageToken = null;
            Int16        pageNum   = 1;

            log.Debug("Retrieving all subscribers from past year.");
            try {
                do
                {
                    EventsResource.ListRequest lr = GoogleOgcs.Calendar.Instance.Service.Events.List("*****@*****.**");

                    lr.PageToken    = pageToken;
                    lr.SingleEvents = true;
                    lr.OrderBy      = EventsResource.ListRequest.OrderByEnum.StartTime;
                    lr.Q            = (Settings.Instance.GaccountEmail == null) ? "" : HashedGmailAccount;
                    request         = lr.Execute();
                    log.Debug("Page " + pageNum + " received.");

                    if (request != null)
                    {
                        pageToken = request.NextPageToken;
                        pageNum++;
                        if (request.Items != null)
                        {
                            result.AddRange(request.Items);
                        }
                    }
                } while (pageToken != null);

                if (String.IsNullOrEmpty(Settings.Instance.GaccountEmail))   //This gets retrieved via the above lr.Execute()
                {
                    log.Warn("User's Google account username is not present - cannot check if they have subscribed.");
                    return(false);
                }
            } catch (Google.Apis.Auth.OAuth2.Responses.TokenResponseException ex) {
                OGCSexception.AnalyseTokenResponse(ex);
            } catch (Google.GoogleApiException ex) {
                switch (GoogleOgcs.Calendar.HandleAPIlimits(ref ex, null))
                {
                case Calendar.ApiException.throwException: throw;

                case Calendar.ApiException.freeAPIexhausted:
                    OGCSexception.LogAsFail(ref ex);
                    OGCSexception.Analyse(ex);
                    System.ApplicationException aex = new System.ApplicationException(GoogleOgcs.Calendar.Instance.SubscriptionInvite);
                    OGCSexception.LogAsFail(ref aex);
                    GoogleOgcs.Calendar.Instance.Service = null;
                    throw aex;
                }
            } catch (System.Exception ex) {
                log.Error(ex.Message);
                throw new ApplicationException("Failed to retrieve subscribers - cannot check if they have subscribed.");
            }

            log.Debug("Searching for subscription for: " + Settings.Instance.GaccountEmail_masked());
            List <Event> subscriptions = result.Where(x => x.Summary == HashedGmailAccount).ToList();

            if (subscriptions.Count == 0)
            {
                log.Fine("This user has never subscribed.");
                Settings.Instance.Subscribed = DateTime.Parse("01-Jan-2000");
                return(false);
            }
            else
            {
                Boolean  subscribed;
                Event    subscription      = subscriptions.Last();
                DateTime subscriptionStart = (subscription.Start.DateTime ?? DateTime.Parse(subscription.Start.Date)).Date;
                log.Debug("Last subscription date: " + subscriptionStart.ToString());
                Double subscriptionRemaining = (subscriptionStart.AddYears(1) - DateTime.Now.Date).TotalDays;
                if (subscriptionRemaining >= 0)
                {
                    if (subscriptionRemaining > 360)
                    {
                        Forms.Main.Instance.SyncNote(Forms.Main.SyncNotes.RecentSubscription, null);
                    }
                    if (subscriptionRemaining < 28)
                    {
                        Forms.Main.Instance.SyncNote(Forms.Main.SyncNotes.SubscriptionPendingExpire, subscriptionStart.AddYears(1));
                    }
                    subscribed = true;
                }
                else
                {
                    if (subscriptionRemaining > -14)
                    {
                        Forms.Main.Instance.SyncNote(Forms.Main.SyncNotes.SubscriptionExpired, subscriptionStart.AddYears(1));
                    }
                    subscribed = false;
                }

                DateTime prevSubscriptionStart = Settings.Instance.Subscribed;
                if (subscribed)
                {
                    log.Info("User has an active subscription.");
                    Settings.Instance.Subscribed = subscriptionStart;
                }
                else
                {
                    log.Info("User has no active subscription.");
                    Settings.Instance.Subscribed = DateTime.Parse("01-Jan-2000");
                }

                //Check for any unmigrated entries
                if (subscriptions.Where(s => s.ExtendedProperties != null && s.ExtendedProperties.Shared != null &&
                                        s.ExtendedProperties.Shared.ContainsKey("migrated") && s.ExtendedProperties.Shared["migrated"] == "true").Count() < subscriptions.Count())
                {
                    Forms.Main.Instance.Console.CallGappScript("subscriber");
                }

                if (prevSubscriptionStart != Settings.Instance.Subscribed)
                {
                    if (prevSubscriptionStart == DateTime.Parse("01-Jan-2000") ||         //No longer a subscriber
                        Settings.Instance.Subscribed == DateTime.Parse("01-Jan-2000"))    //New subscriber
                    {
                        ApiKeyring.ChangeKeys();
                    }
                }
                return(subscribed);
            }
        }
        private async Task <bool> getAuthenticated(ClientSecrets cs)
        {
            log.Debug("Authenticating with Google calendar service...");

            FileDataStore tokenStore = new FileDataStore(Program.UserFilePath);

            tokenFullPath = Path.Combine(tokenStore.FolderPath, TokenFile);

            log.Debug("Google credential file location: " + tokenFullPath);
            if (!tokenFileExists)
            {
                log.Info("No Google credentials file available - need user authorisation for OGCS to manage their calendar.");
            }

            string[] scopes = new[] { "https://www.googleapis.com/auth/calendar", "email" };

            UserCredential credential = null;

            try {
                //This will open the authorisation process in a browser, if required
                credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(cs, scopes, "user", CancelTokenSource.Token, tokenStore);

                if (tokenFileExists)
                {
                    log.Debug("User has provided authorisation and credential file saved.");
                }
            } catch (Google.Apis.Auth.OAuth2.Responses.TokenResponseException ex) {
                //OGCSexception.AnalyseTokenResponse(ex);
                if (ex.Error.Error == "access_denied")
                {
                    String noAuthGiven = "Sorry, but this application will not work if you don't allow it access to your Google Calendar :(";
                    log.Warn("User did not provide authorisation code. Sync will not be able to work.");
                    OgcsMessageBox.Show(noAuthGiven, "Authorisation not given", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                    throw new ApplicationException(noAuthGiven);
                }
                else
                {
                    Forms.Main.Instance.Console.UpdateWithError("Unable to authenticate with Google. The following error occurred:", ex);
                }
            } catch (OperationCanceledException) {
                Forms.Main.Instance.Console.Update("Unable to authenticate with Google. The operation was cancelled.", Console.Markup.warning);
            } catch (System.Exception ex) {
                OGCSexception.Analyse(ex);
                Forms.Main.Instance.Console.UpdateWithError("Unable to authenticate with Google. The following error occurred:", ex);
            }

            if (credential.Token.AccessToken != "" && credential.Token.RefreshToken != "")
            {
                log.Info("Refresh and Access token successfully retrieved.");
                log.Debug("Access token expires " + credential.Token.IssuedUtc.AddSeconds(credential.Token.ExpiresInSeconds.Value).ToLocalTime().ToString());
            }

            GoogleOgcs.Calendar.Instance.Service = new CalendarService(new Google.Apis.Services.BaseClientService.Initializer()
            {
                HttpClientInitializer = credential
            });
            if (Settings.Instance.Proxy.Type == "Custom")
            {
                GoogleOgcs.Calendar.Instance.Service.HttpClient.DefaultRequestHeaders.Add("user-agent", Settings.Instance.Proxy.BrowserUserAgent);
            }

            if (credential.Token.IssuedUtc.AddSeconds(credential.Token.ExpiresInSeconds.Value) < DateTime.UtcNow.AddMinutes(-1))
            {
                log.Debug("Access token needs refreshing.");
                //This will happen automatically when using the calendar service
                //But we need a valid token before we call getGaccountEmail() which doesn't use the service
                int backoff = 0;
                while (backoff < Calendar.BackoffLimit)
                {
                    try {
                        GoogleOgcs.Calendar.Instance.Service.Settings.Get("useKeyboardShortcuts").Execute();
                        break;
                    } catch (Google.GoogleApiException ex) {
                        switch (Calendar.HandleAPIlimits(ref ex, null))
                        {
                        case Calendar.ApiException.throwException: throw;

                        case Calendar.ApiException.freeAPIexhausted:
                            OGCSexception.LogAsFail(ref ex);
                            OGCSexception.Analyse(ex);
                            System.ApplicationException aex = new System.ApplicationException(Calendar.Instance.SubscriptionInvite);
                            OGCSexception.LogAsFail(ref aex);
                            authenticated = false;
                            return(authenticated);

                        case Calendar.ApiException.backoffThenRetry:
                            backoff++;
                            if (backoff == Calendar.BackoffLimit)
                            {
                                log.Fail("API limit backoff was not successful. Retrieving useKeyboardShortcuts setting failed.");
                                authenticated = false;
                                return(authenticated);
                            }
                            else
                            {
                                log.Warn("API rate limit reached. Backing off " + backoff + "sec before retry.");
                                System.Threading.Thread.Sleep(backoff * 1000);
                            }
                            break;
                        }
                    } catch (System.Exception ex) {
                        if (ex is Google.Apis.Auth.OAuth2.Responses.TokenResponseException)
                        {
                            OGCSexception.AnalyseTokenResponse(ex as Google.Apis.Auth.OAuth2.Responses.TokenResponseException, false);
                        }
                        else
                        {
                            OGCSexception.Analyse(ex);
                            Forms.Main.Instance.Console.Update("Unable to communicate with Google services. " + (ex.InnerException != null ? ex.InnerException.Message : ex.Message), Console.Markup.warning);
                        }
                        authenticated = false;
                        return(authenticated);
                    }
                }
                log.Debug("Access token refreshed.");
            }

            getGaccountEmail(credential.Token.AccessToken);
            authenticated = true;
            Forms.Main.Instance.Console.Update("Handshake successful.", verbose: true);
            return(authenticated);
        }