private void btSave_Click(object sender, EventArgs e)
 {
     try {
         Settings.Instance.TimezoneMaps.Clear();
         foreach (DataGridViewRow row in tzGridView.Rows)
         {
             if (row.Cells[0].Value == null || row.Cells[0].Value.ToString().Trim() == "")
             {
                 continue;
             }
             try {
                 Settings.Instance.TimezoneMaps.Add(row.Cells[0].Value.ToString(), row.Cells[1].Value.ToString());
             } catch (System.ArgumentException ex) {
                 if (OGCSexception.GetErrorCode(ex) == "0x80070057")
                 {
                     //An item with the same key has already been added
                 }
                 else
                 {
                     throw;
                 }
             }
         }
     } catch (System.Exception ex) {
         OGCSexception.Analyse("Could not save timezone mappings to Settings.", ex);
     } finally {
         this.Close();
     }
 }
예제 #2
0
        private void btOK_Click(object sender, EventArgs e)
        {
            log.Fine("Checking no duplicate mappings exist.");
            SettingsStore.Calendar profile = Forms.Main.Instance.ActiveCalendarProfile;
            try {
                List <String> oColValues = new List <String>();
                List <String> gColValues = new List <String>();
                foreach (DataGridViewRow row in colourGridView.Rows)
                {
                    oColValues.Add(row.Cells["OutlookColour"].Value.ToString());
                    gColValues.Add(row.Cells["GoogleColour"].Value.ToString());
                }
                String oDuplicates = string.Join("\r\n", oColValues.GroupBy(v => v).Where(g => g.Count() > 1).Select(s => "- " + s.Key).ToList());
                String gDuplicates = string.Join("\r\n", gColValues.GroupBy(v => v).Where(g => g.Count() > 1).Select(s => "- " + s.Key).ToList());

                if (!string.IsNullOrEmpty(oDuplicates) && (profile.SyncDirection.Id == Sync.Direction.OutlookToGoogle.Id || profile.SyncDirection.Id == Sync.Direction.Bidirectional.Id))
                {
                    OgcsMessageBox.Show("The following Outlook categories cannot be mapped more than once:-\r\n\r\n" + oDuplicates, "Duplicate Outlook Mappings", MessageBoxButtons.OK, MessageBoxIcon.Stop);
                    return;
                }
                else if (!string.IsNullOrEmpty(gDuplicates) && (profile.SyncDirection.Id == Sync.Direction.GoogleToOutlook.Id || profile.SyncDirection.Id == Sync.Direction.Bidirectional.Id))
                {
                    OgcsMessageBox.Show("The following Google colours cannot be mapped more than once:-\r\n\r\n" + gDuplicates, "Duplicate Google Mappings", MessageBoxButtons.OK, MessageBoxIcon.Stop);
                    return;
                }
            } catch (System.Exception ex) {
                OGCSexception.Analyse("Failed looking for duplicating mappings before storing in Settings.", ex);
                OgcsMessageBox.Show("An error was encountered storing your custom mappings.", "Cannot save mappings", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            try {
                log.Fine("Storing colour mappings in Settings.");
                profile.ColourMaps.Clear();
                foreach (DataGridViewRow row in colourGridView.Rows)
                {
                    if (row.Cells["OutlookColour"].Value == null || row.Cells["OutlookColour"].Value.ToString().Trim() == "")
                    {
                        continue;
                    }
                    try {
                        profile.ColourMaps.Add(row.Cells["OutlookColour"].Value.ToString(), GoogleOgcs.EventColour.Palette.GetColourId(row.Cells["GoogleColour"].Value.ToString()));
                    } catch (System.ArgumentException ex) {
                        if (OGCSexception.GetErrorCode(ex) == "0x80070057")
                        {
                            //An item with the same key has already been added
                        }
                        else
                        {
                            throw;
                        }
                    }
                }
            } catch (System.Exception ex) {
                OGCSexception.Analyse("Could not save colour/category mappings to Settings.", ex);
            } finally {
                this.Close();
            }
        }
예제 #3
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);
                }
            }
        }
예제 #4
0
        private void findCalendars(Folders folders, Dictionary <string, MAPIFolder> calendarFolders, String excludeDeletedFolder, MAPIFolder defaultCalendar = null)
        {
            //Initiate progress bar (red line underneath "Getting calendars" text)
            System.Drawing.Graphics g          = Forms.Main.Instance.tabOutlook.CreateGraphics();
            System.Drawing.Pen      p          = new System.Drawing.Pen(System.Drawing.Color.Red, 3);
            System.Drawing.Point    startPoint = new System.Drawing.Point(Forms.Main.Instance.lOutlookCalendar.Location.X,
                                                                          Forms.Main.Instance.lOutlookCalendar.Location.Y + Forms.Main.Instance.lOutlookCalendar.Size.Height + 3);
            double stepSize = Forms.Main.Instance.lOutlookCalendar.Size.Width / folders.Count;

            int fldCnt = 0;

            foreach (MAPIFolder folder in folders)
            {
                fldCnt++;
                System.Drawing.Point endPoint = new System.Drawing.Point(Forms.Main.Instance.lOutlookCalendar.Location.X + Convert.ToInt16(fldCnt * stepSize),
                                                                         Forms.Main.Instance.lOutlookCalendar.Location.Y + Forms.Main.Instance.lOutlookCalendar.Size.Height + 3);
                try { g.DrawLine(p, startPoint, endPoint); } catch { /*May get GDI+ error if g has been repainted*/ }
                System.Windows.Forms.Application.DoEvents();
                try {
                    OlItemType defaultItemType = folder.DefaultItemType;
                    if (defaultItemType == OlItemType.olAppointmentItem)
                    {
                        if (defaultCalendar == null || (folder.EntryID != defaultCalendar.EntryID))
                        {
                            calendarFolderAdd(folder.Name, folder);
                        }
                    }
                    if (folder.EntryID != excludeDeletedFolder && folder.Folders.Count > 0)
                    {
                        findCalendars(folder.Folders, calendarFolders, excludeDeletedFolder, defaultCalendar);
                    }
                } catch (System.Exception ex) {
                    OGCSexception.Analyse(ex);
                    if (oApp.Session.ExchangeConnectionMode.ToString().Contains("Disconnected") ||
                        ex.Message.StartsWith("Network problems are preventing connection to Microsoft Exchange.") ||
                        OGCSexception.GetErrorCode(ex, 0x000FFFFF) == "0x00040115")
                    {
                        log.Info("Currently disconnected from Exchange - unable to retrieve MAPI folders.");
                        Forms.Main.Instance.ToolTips.SetToolTip(Forms.Main.Instance.cbOutlookCalendars,
                                                                "The Outlook calendar to synchonize with.\nSome may not be listed as you are currently disconnected.");
                    }
                    else
                    {
                        log.Error("Failed to recurse MAPI folders.");
                        log.Error(ex.Message);
                        MessageBox.Show("A problem was encountered when searching for Outlook calendar folders.",
                                        "Calendar Folders", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    }
                }
            }
            p.Dispose();
            try { g.Clear(System.Drawing.Color.White); } catch { }
            g.Dispose();
            System.Windows.Forms.Application.DoEvents();
        }
예제 #5
0
 /// <summary>
 /// Handles non-unique calendar names by recursively adding parent folders to the name
 /// </summary>
 /// <param name="name">Name/path of calendar (dictionary key)</param>
 /// <param name="folder">The target folder (dictionary value)</param>
 /// <param name="parentFolder">Recursive parent folder - leave null on initial call</param>
 private void calendarFolderAdd(String name, MAPIFolder folder, MAPIFolder parentFolder = null)
 {
     try {
         calendarFolders.Add(name, folder);
     } catch (System.ArgumentException ex) {
         if (OGCSexception.GetErrorCode(ex) == "0x80070057")
         {
             //An item with the same key has already been added.
             //Let's recurse up to the parent folder, looking to make it unique
             object parentObj = (parentFolder != null ? parentFolder.Parent : folder.Parent);
             if (parentObj is NameSpace)
             {
                 //We've traversed all the way up the folder path to the root and still not unique
                 log.Warn("MAPIFolder " + name + " does not have a unique name - so cannot use!");
             }
             else if (parentObj is MAPIFolder)
             {
                 String parentFolderName = (parentObj as MAPIFolder).FolderPath.Split('\\').Last();
                 calendarFolderAdd(System.IO.Path.Combine(parentFolderName, name), folder, parentObj as MAPIFolder);
             }
         }
     }
 }
예제 #6
0
        private static void backupSettingsFile()
        {
            if (string.IsNullOrEmpty(settingsVersion))
            {
                log.Debug("The settings file is a vanilla template. No need to back it up.");
                return;
            }

            String backupFile = "";

            try {
                log.Info("Backing up '" + Settings.ConfigFile + "' for v" + settingsVersion);
                backupFile = System.Text.RegularExpressions.Regex.Replace(Settings.ConfigFile, @"(\.\w+)$", "-v" + settingsVersion + "$1");
                File.Copy(Settings.ConfigFile, backupFile, false);
                log.Info(backupFile + " created.");
            } catch (System.IO.IOException ex) {
                if (OGCSexception.GetErrorCode(ex) == "0x80070050")   //File already exists
                {
                    log.Warn("The backfile already exists, not overwriting " + backupFile);
                }
            } catch (System.Exception ex) {
                OGCSexception.Analyse("Failed to create backup settings file", ex);
            }
        }
        private void getGaccountEmail(String accessToken)
        {
            String jsonString = "";

            log.Debug("Retrieving email address associated with Google account.");
            try {
                System.Net.WebClient wc = new System.Net.WebClient();
                wc.Headers.Add("user-agent", Settings.Instance.Proxy.BrowserUserAgent);
                jsonString = wc.DownloadString("https://www.googleapis.com/plus/v1/people/me?fields=emails&access_token=" + accessToken);
                JObject jo      = Newtonsoft.Json.Linq.JObject.Parse(jsonString);
                JToken  jtEmail = jo["emails"].Where(e => e.Value <String>("type") == "account").First();
                String  email   = jtEmail.Value <String>("value");

                if (Settings.Instance.GaccountEmail != email)
                {
                    if (!String.IsNullOrEmpty(Settings.Instance.GaccountEmail))
                    {
                        log.Debug("Looks like the Google account username value has been tampering with? :-O");
                    }
                    Settings.Instance.GaccountEmail = email;
                    log.Debug("Updating Google account username: "******"Inner exception: " + ex.InnerException.Message);
                }
                if (ex.Response != null)
                {
                    log.Debug("Reading response.");
                    System.IO.Stream       stream = ex.Response.GetResponseStream();
                    System.IO.StreamReader sr     = new System.IO.StreamReader(stream);
                    log.Error(sr.ReadToEnd());
                }
                if (OGCSexception.GetErrorCode(ex) == "0x80131509")
                {
                    log.Warn(ex.Message);
                    System.Text.RegularExpressions.Regex rgx = new System.Text.RegularExpressions.Regex(@"\b(403|Forbidden|Prohibited|Insufficient Permission)\b",
                                                                                                        System.Text.RegularExpressions.RegexOptions.IgnoreCase);

                    if (rgx.IsMatch(ex.Message))
                    {
                        if (Settings.Instance.UsingPersonalAPIkeys())
                        {
                            String msg = "If you are using your own API keys, you must also enable the Google+ API.";
                            MessageBox.Show(msg, "Missing API Service", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Exclamation);
                            throw new System.ApplicationException(msg);
                        }
                        else
                        {
                            if (getEmailAttempts > 1)
                            {
                                log.Error("Failed to retrieve Google account username.");
                                log.Debug("Using previously retrieved username: "******"access denied"))
                {
                    MainForm.Instance.Console.Update("Failed to obtain Calendar access from Google - it's possible your access has been revoked."
                                                     + "<br/>Try disconnecting your Google account and reauthorising OGCS.", Console.Markup.error);
                }
                throw ex;
            } catch (System.Exception ex) {
                log.Debug("JSON: " + jsonString);
                log.Error("Failed to retrieve Google account username.");
                OGCSexception.Analyse(ex);
                log.Debug("Using previously retrieved username: " + Settings.Instance.GaccountEmail_masked());
            }
        }
예제 #8
0
        private SyncResult synchronize()
        {
            Console console = Forms.Main.Instance.Console;

            console.Update("Finding Calendar Entries", Console.Markup.mag_right, newLine: false);

            List <AppointmentItem> outlookEntries = null;
            List <Event>           googleEntries  = null;

            try {
                #region Read Outlook items
                console.Update("Scanning Outlook calendar...");
                outlookEntries = OutlookOgcs.Calendar.Instance.GetCalendarEntriesInRange(false);
                console.Update(outlookEntries.Count + " Outlook calendar entries found.", Console.Markup.sectionEnd, newLine: false);

                if (CancellationPending)
                {
                    return(SyncResult.UserCancelled);
                }
                #endregion

                #region Read Google items
                console.Update("Scanning Google calendar...");
                try {
                    googleEntries = GoogleOgcs.Calendar.Instance.GetCalendarEntriesInRange();
                } catch (AggregateException agex) {
                    OGCSexception.AnalyseAggregate(agex);
                } catch (Google.Apis.Auth.OAuth2.Responses.TokenResponseException ex) {
                    OGCSexception.AnalyseTokenResponse(ex, false);
                    return(SyncResult.Fail);
                } catch (System.Net.Http.HttpRequestException ex) {
                    OGCSexception.Analyse(ex);
                    ex.Data.Add("OGCS", "ERROR: Unable to connect to the Google calendar. Please try again.");
                    throw ex;
                } catch (System.Exception ex) {
                    OGCSexception.Analyse(ex);
                    ex.Data.Add("OGCS", "ERROR: Unable to connect to the Google calendar.");
                    if (OGCSexception.GetErrorCode(ex) == "0x8013153B") //ex.Message == "A task was canceled." - likely timed out.
                    {
                        ex.Data["OGCS"] += " Please try again.";
                    }
                    throw ex;
                }
                Recurrence.Instance.SeparateGoogleExceptions(googleEntries);
                if (Recurrence.Instance.GoogleExceptions != null && Recurrence.Instance.GoogleExceptions.Count > 0)
                {
                    console.Update(googleEntries.Count + " Google calendar entries found.");
                    console.Update(Recurrence.Instance.GoogleExceptions.Count + " are exceptions to recurring events.", Console.Markup.sectionEnd, newLine: false);
                }
                else
                {
                    console.Update(googleEntries.Count + " Google calendar entries found.", Console.Markup.sectionEnd, newLine: false);
                }

                if (CancellationPending)
                {
                    return(SyncResult.UserCancelled);
                }
                #endregion

                #region Normalise recurring items in sync window
                console.Update("Total inc. recurring items spanning sync date range...");
                //Outlook returns recurring items that span the sync date range, Google doesn't
                //So check for master Outlook items occurring before sync date range, and retrieve Google equivalent
                for (int o = outlookEntries.Count - 1; o >= 0; o--)
                {
                    log.Fine("Processing " + (o + 1) + "/" + outlookEntries.Count);
                    AppointmentItem ai = null;
                    try {
                        if (outlookEntries[o] is AppointmentItem)
                        {
                            ai = outlookEntries[o];
                        }
                        else if (outlookEntries[o] is MeetingItem)
                        {
                            log.Info("Calendar object appears to be a MeetingItem, so retrieving associated AppointmentItem.");
                            MeetingItem mi = outlookEntries[o] as MeetingItem;
                            outlookEntries[o] = mi.GetAssociatedAppointment(false);
                            ai = outlookEntries[o];
                        }
                        else
                        {
                            log.Warn("Unknown calendar object type - cannot sync it.");
                            skipCorruptedItem(ref outlookEntries, outlookEntries[o], "Unknown object type.");
                            outlookEntries[o] = (AppointmentItem)OutlookOgcs.Calendar.ReleaseObject(outlookEntries[o]);
                            continue;
                        }
                    } catch (System.Exception ex) {
                        log.Warn("Encountered error casting calendar object to AppointmentItem - cannot sync it.");
                        log.Debug(ex.Message);
                        skipCorruptedItem(ref outlookEntries, outlookEntries[o], ex.Message);
                        outlookEntries[o] = (AppointmentItem)OutlookOgcs.Calendar.ReleaseObject(outlookEntries[o]);
                        ai = (AppointmentItem)OutlookOgcs.Calendar.ReleaseObject(ai);
                        continue;
                    }

                    //Now let's check there's a start/end date - sometimes it can be missing, even though this shouldn't be possible!!
                    String entryID;
                    try {
                        entryID = outlookEntries[o].EntryID;
                        DateTime checkDates = ai.Start;
                        checkDates = ai.End;
                    } catch (System.Exception ex) {
                        log.Warn("Calendar item does not have a proper date range - cannot sync it.");
                        log.Debug(ex.Message);
                        skipCorruptedItem(ref outlookEntries, outlookEntries[o], ex.Message);
                        outlookEntries[o] = (AppointmentItem)OutlookOgcs.Calendar.ReleaseObject(outlookEntries[o]);
                        ai = (AppointmentItem)OutlookOgcs.Calendar.ReleaseObject(ai);
                        continue;
                    }

                    if (ai.IsRecurring && ai.Start.Date < Settings.Instance.SyncStart && ai.End.Date < Settings.Instance.SyncStart)
                    {
                        //We won't bother getting Google master event if appointment is yearly reoccurring in a month outside of sync range
                        //Otherwise, every sync, the master event will have to be retrieved, compared, concluded nothing's changed (probably) = waste of API calls
                        RecurrencePattern oPattern = ai.GetRecurrencePattern();
                        try {
                            if (oPattern.RecurrenceType.ToString().Contains("Year"))
                            {
                                log.Fine("It's an annual event.");
                                Boolean  monthInSyncRange = false;
                                DateTime monthMarker      = Settings.Instance.SyncStart;
                                while (Convert.ToInt32(monthMarker.ToString("yyyyMM")) <= Convert.ToInt32(Settings.Instance.SyncEnd.ToString("yyyyMM")) &&
                                       !monthInSyncRange)
                                {
                                    if (monthMarker.Month == ai.Start.Month)
                                    {
                                        monthInSyncRange = true;
                                    }
                                    monthMarker = monthMarker.AddMonths(1);
                                }
                                log.Fine("Found it to be " + (monthInSyncRange ? "inside" : "outside") + " sync range.");
                                if (!monthInSyncRange)
                                {
                                    outlookEntries.Remove(ai); log.Fine("Removed."); continue;
                                }
                            }
                            Event masterEv = Recurrence.Instance.GetGoogleMasterEvent(ai);
                            if (masterEv != null && masterEv.Status != "cancelled")
                            {
                                Event cachedEv = googleEntries.Find(x => x.Id == masterEv.Id);
                                if (cachedEv == null)
                                {
                                    googleEntries.Add(masterEv);
                                }
                                else
                                {
                                    if (masterEv.Updated > cachedEv.Updated)
                                    {
                                        log.Debug("Refreshing cache for this Event.");
                                        googleEntries.Remove(cachedEv);
                                        googleEntries.Add(masterEv);
                                    }
                                }
                            }
                        } catch (System.Exception ex) {
                            console.Update("Failed to retrieve master for Google recurring event outside of sync range.", Console.Markup.error);
                            throw ex;
                        } finally {
                            oPattern = (RecurrencePattern)OutlookOgcs.Calendar.ReleaseObject(oPattern);
                        }
                    }
                    //Completely dereference object and retrieve afresh (due to GetRecurrencePattern earlier)
                    ai = (AppointmentItem)OutlookOgcs.Calendar.ReleaseObject(ai);
                    OutlookOgcs.Calendar.Instance.IOutlook.GetAppointmentByID(entryID, out ai);
                    outlookEntries[o] = ai;
                }
                console.Update("Outlook " + outlookEntries.Count + ", Google " + googleEntries.Count);

                GoogleOgcs.Calendar.ExportToCSV("Outputting all Events.", "google_events.csv", googleEntries);
                OutlookOgcs.Calendar.ExportToCSV("Outputting all Appointments.", "outlook_appointments.csv", outlookEntries);
                if (CancellationPending)
                {
                    return(SyncResult.UserCancelled);
                }
                #endregion

                Boolean success    = true;
                String  bubbleText = "";
                if (Settings.Instance.SyncDirection != Direction.GoogleToOutlook)
                {
                    success = outlookToGoogle(outlookEntries, googleEntries, ref bubbleText);
                    if (CancellationPending)
                    {
                        return(SyncResult.UserCancelled);
                    }
                }
                if (!success)
                {
                    return(SyncResult.Fail);
                }
                if (Settings.Instance.SyncDirection != Direction.OutlookToGoogle)
                {
                    if (bubbleText != "")
                    {
                        bubbleText += "\r\n";
                    }
                    success = googleToOutlook(googleEntries, outlookEntries, ref bubbleText);
                    if (CancellationPending)
                    {
                        return(SyncResult.UserCancelled);
                    }
                }
                if (bubbleText != "")
                {
                    Forms.Main.Instance.NotificationTray.ShowBubbleInfo(bubbleText);
                }

                return(SyncResult.OK);
            } finally {
                for (int o = outlookEntries.Count() - 1; o >= 0; o--)
                {
                    outlookEntries[o] = (AppointmentItem)OutlookOgcs.Calendar.ReleaseObject(outlookEntries[o]);
                    outlookEntries.RemoveAt(o);
                }
            }
        }
        /// <summary>
        /// Get the Outlook category name for a given category colour.
        /// If category not yet used, new one added of the form "OGCS [colour]"
        /// </summary>
        /// <param name="olCategory">The Outlook category to search by</param>
        /// <param name="categoryName">Optional: The Outlook category name to also search by</param>
        /// <param name="createMissingCategory">Optional: Create unused category colour?</param>
        /// <returns>The matching category name</returns>
        public String FindName(Outlook.OlCategoryColor?olCategory, String categoryName = null, Boolean createMissingCategory = true)
        {
            if (olCategory == null || olCategory == Outlook.OlCategoryColor.olCategoryColorNone)
            {
                return("");
            }

            Outlook.Category failSafeCategory = null;
            foreach (Outlook.Category category in this.categories)
            {
                try {
                    if (category.Color == olCategory)
                    {
                        if (categoryName == null)
                        {
                            if (category.Name.StartsWith("OGCS "))
                            {
                                return(category.Name);
                            }
                            else if (!createMissingCategory)
                            {
                                return(category.Name);
                            }
                        }
                        else
                        {
                            if (category.Name == categoryName)
                            {
                                return(category.Name);
                            }
                            if (category.Name.StartsWith("OGCS "))
                            {
                                failSafeCategory = category;
                            }
                        }
                    }
                } catch (System.Runtime.InteropServices.COMException ex) {
                    if (OGCSexception.GetErrorCode(ex, 0x0000FFFF) == "0x00004005")   //The operation failed.
                    {
                        log.Warn("It seems a category has been manually removed in Outlook.");
                        OutlookOgcs.Calendar.Instance.IOutlook.RefreshCategories();
                    }
                    else
                    {
                        throw;
                    }
                }
            }

            if (failSafeCategory != null)
            {
                log.Warn("Failed to find Outlook category " + olCategory.ToString() + " with name '" + categoryName + "'");
                log.Debug("Using category with name \"" + failSafeCategory.Name + "\" instead.");
                return(failSafeCategory.Name);
            }

            log.Debug("Did not find Outlook category " + olCategory.ToString() + (categoryName == null ? "" : " \"" + categoryName + "\""));
            String newCategoryName = "OGCS " + FriendlyCategoryName(olCategory);

            if (!createMissingCategory)
            {
                createMissingCategory = System.Windows.Forms.OgcsMessageBox.Show("There is no matching Outlook category.\r\nWould you like to create one of the form '" + newCategoryName + "'?",
                                                                                 "Create new Outlook category?", System.Windows.Forms.MessageBoxButtons.YesNo, System.Windows.Forms.MessageBoxIcon.Question) == System.Windows.Forms.DialogResult.Yes;
            }
            if (createMissingCategory)
            {
                Outlook.Category newCategory = categories.Add(newCategoryName, olCategory);
                log.Info("Added new Outlook category \"" + newCategory.Name + "\" for " + newCategory.Color.ToString());
                return(newCategory.Name);
            }
            return("");
        }
예제 #10
0
        public NameSpace GetCurrentUser(NameSpace oNS)
        {
            //We only need the current user details when syncing meeting attendees.
            //If GAL had previously been detected as blocked, let's always try one attempt to see if it's been opened up
            if (!Settings.Instance.OutlookGalBlocked && !Settings.Instance.AddAttendees)
            {
                return(oNS);
            }

            Boolean releaseNamespace = (oNS == null);

            if (releaseNamespace)
            {
                oNS = oApp.GetNamespace("mapi");
            }

            Recipient currentUser = null;

            try {
                DateTime triggerOOMsecurity = DateTime.Now;
                try {
                    currentUser = oNS.CurrentUser;
                    if (!Forms.Main.Instance.IsHandleCreated && (DateTime.Now - triggerOOMsecurity).TotalSeconds > 1)
                    {
                        log.Warn(">1s delay possibly due to Outlook security popup.");
                        OutlookOgcs.Calendar.OOMsecurityInfo = true;
                    }
                } catch (System.Exception ex) {
                    OGCSexception.Analyse(ex);
                    if (Settings.Instance.OutlookGalBlocked)   //Fail fast
                    {
                        log.Debug("Corporate policy is still blocking access to GAL.");
                        return(oNS);
                    }
                    log.Warn("We seem to have a faux connection to Outlook! Forcing starting it with a system call :-/");
                    oNS = (NameSpace)OutlookOgcs.Calendar.ReleaseObject(oNS);
                    Disconnect();
                    OutlookOgcs.Calendar.AttachToOutlook(ref oApp, openOutlookOnFail: true, withSystemCall: true);
                    oNS = oApp.GetNamespace("mapi");

                    int maxDelay = 5;
                    int delay    = 1;
                    while (delay <= maxDelay)
                    {
                        log.Debug("Sleeping..." + delay + "/" + maxDelay);
                        System.Threading.Thread.Sleep(10000);
                        try {
                            currentUser = oNS.CurrentUser;
                            delay       = maxDelay;
                        } catch (System.Exception ex2) {
                            if (delay == maxDelay)
                            {
                                if (OGCSexception.GetErrorCode(ex2) == "0x80004004")   //E_ABORT
                                {
                                    log.Warn("Corporate policy or possibly anti-virus is blocking access to GAL.");
                                }
                                else
                                {
                                    OGCSexception.Analyse(ex2);
                                }
                                log.Warn("OGCS is unable to obtain CurrentUser from Outlook.");
                                Settings.Instance.OutlookGalBlocked = true;
                                return(oNS);
                            }
                            OGCSexception.Analyse(ex2);
                        }
                        delay++;
                    }
                }
                if (Settings.Instance.OutlookGalBlocked)
                {
                    log.Debug("GAL is no longer blocked!");
                }
                Settings.Instance.OutlookGalBlocked = false;
                currentUserSMTP = GetRecipientEmail(currentUser);
                currentUserName = currentUser.Name;
            } finally {
                currentUser = (Recipient)OutlookOgcs.Calendar.ReleaseObject(currentUser);
                if (releaseNamespace)
                {
                    oNS = (NameSpace)OutlookOgcs.Calendar.ReleaseObject(oNS);
                }
            }
            return(oNS);
        }
예제 #11
0
        public static void Initialise()
        {
            if (Program.StartedWithSquirrelArgs && !(Environment.GetCommandLineArgs()[1].ToLower().Equals("--squirrel-firstrun")))
            {
                return;
            }
            if (Program.InDeveloperMode)
            {
                return;
            }

            //Note, logging isn't actually initialised yet, so log4net won't log any lines within this function

            String cloudCredsURL = "https://raw.githubusercontent.com/phw198/OutlookGoogleCalendarSync/master/docs/keyring.md";
            String html          = null;
            String line          = null;
            String placeHolder   = "###";
            String cloudID       = null;
            String cloudKey      = null;

            log.Debug("Getting credential attributes");
            try {
                try {
                    html = new Extensions.OgcsWebClient().DownloadString(cloudCredsURL);
                    html = html.Replace("\n", "");
                } catch (System.Exception ex) {
                    log.Error("Failed to retrieve data: " + ex.Message);
                }

                if (string.IsNullOrEmpty(html))
                {
                    throw new ApplicationException("Not able to retrieve error reporting credentials.");
                }

                Regex           rgx        = new Regex(@"### Error Reporting.*\|ID\|(.*)\|\|Key\|(.*?)\|", RegexOptions.IgnoreCase);
                MatchCollection keyRecords = rgx.Matches(html);
                if (keyRecords.Count == 1)
                {
                    cloudID  = keyRecords[0].Groups[1].ToString();
                    cloudKey = keyRecords[0].Groups[2].ToString();
                }
                else
                {
                    throw new ApplicationException("Unexpected parse of error reporting credentials.");
                }

                List <String> newLines = new List <string>();
                StreamReader  sr       = new StreamReader(templateCredFile);
                while ((line = sr.ReadLine()) != null)
                {
                    if (line.IndexOf(placeHolder) > 0)
                    {
                        if (line.IndexOf("private_key_id") > 0)
                        {
                            line = line.Replace(placeHolder, cloudID);
                        }
                        else if (line.IndexOf("private_key") > 0)
                        {
                            line = line.Replace(placeHolder, cloudKey);
                        }
                    }
                    newLines.Add(line);
                }
                try {
                    File.WriteAllLines(credFile, newLines.ToArray());
                } catch (System.IO.IOException ex) {
                    if (OGCSexception.GetErrorCode(ex) == "0x80070020")
                    {
                        log.Warn("ErrorReporting.json is being used by another process (perhaps multiple instances of OGCS are being started on system startup?)");
                    }
                    else
                    {
                        throw;
                    }
                }
                Environment.SetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS", credFile);
            } catch (ApplicationException ex) {
                log.Warn(ex.Message);
                Initialised = false;

                //} catch (System.Exception ex) {
                //Logging isn't initialised yet, so don't catch this error - let it crash out so user is aware and hopefully reports it!
                //System.Windows.Forms.OgcsMessageBox.Show(ex.Message);
                //log.Debug("Failed to initialise error reporting.");
                //OGCSexception.Analyse(ex);
            }
        }
        public void Connect()
        {
            if (!OutlookOgcs.Calendar.InstanceConnect)
            {
                return;
            }

            OutlookOgcs.Calendar.AttachToOutlook(ref oApp, openOutlookOnFail: true, withSystemCall: false);
            log.Debug("Setting up Outlook connection.");

            // Get the NameSpace and Logon information.
            NameSpace oNS = null;

            try {
                oNS = oApp.GetNamespace("mapi");

                //Log on by using a dialog box to choose the profile.
                //oNS.Logon("", Type.Missing, true, true);

                //Implicit logon to default profile, with no dialog box
                //If 1< profile, a dialogue is forced unless implicit login used
                exchangeConnectionMode = oNS.ExchangeConnectionMode;
                if (exchangeConnectionMode != OlExchangeConnectionMode.olNoExchange)
                {
                    log.Info("Exchange server version: " + oNS.ExchangeMailboxServerVersion.ToString());
                }

                //Logon using a specific profile. Can't see a use case for this when using OGsync
                //If using this logon method, change the profile name to an appropriate value:
                //HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\Windows Messaging Subsystem\Profiles
                //oNS.Logon("YourValidProfile", Type.Missing, false, true);

                log.Info("Exchange connection mode: " + exchangeConnectionMode.ToString());

                oNS = GetCurrentUser(oNS);

                if (!Settings.Instance.OutlookGalBlocked && currentUserName == "Unknown")
                {
                    log.Info("Current username is \"Unknown\"");
                    if (Settings.Instance.AddAttendees)
                    {
                        System.Windows.Forms.MessageBox.Show("It appears you do not have an Email Account configured in Outlook.\r\n" +
                                                             "You should set one up now (Tools > Email Accounts) to avoid problems syncing meeting attendees.",
                                                             "No Email Account Found", System.Windows.Forms.MessageBoxButtons.OK,
                                                             System.Windows.Forms.MessageBoxIcon.Warning);
                    }
                }

                log.Debug("Get the folders configured in Outlook");
                folders = oNS.Folders;

                // Get the Calendar folders
                useOutlookCalendar = getCalendarStore(oNS);
                if (Forms.Main.Instance.IsHandleCreated)
                {
                    log.Fine("Resetting connection, so re-selecting calendar from GUI dropdown");

                    Forms.Main.Instance.cbOutlookCalendars.SelectedIndexChanged -= Forms.Main.Instance.cbOutlookCalendar_SelectedIndexChanged;
                    Forms.Main.Instance.cbOutlookCalendars.DataSource            = new BindingSource(calendarFolders, null);

                    //Select the right calendar
                    int c = 0;
                    foreach (KeyValuePair <String, MAPIFolder> calendarFolder in calendarFolders)
                    {
                        if (calendarFolder.Value.EntryID == Settings.Instance.UseOutlookCalendar.Id)
                        {
                            Forms.Main.Instance.SetControlPropertyThreadSafe(Forms.Main.Instance.cbOutlookCalendars, "SelectedIndex", c);
                        }
                        c++;
                    }
                    if ((int)Forms.Main.Instance.GetControlPropertyThreadSafe(Forms.Main.Instance.cbOutlookCalendars, "SelectedIndex") == -1)
                    {
                        Forms.Main.Instance.SetControlPropertyThreadSafe(Forms.Main.Instance.cbOutlookCalendars, "SelectedIndex", 0);
                    }

                    KeyValuePair <String, MAPIFolder> calendar = (KeyValuePair <String, MAPIFolder>)Forms.Main.Instance.GetControlPropertyThreadSafe(Forms.Main.Instance.cbOutlookCalendars, "SelectedItem");
                    useOutlookCalendar = calendar.Value;

                    Forms.Main.Instance.cbOutlookCalendars.SelectedIndexChanged += Forms.Main.Instance.cbOutlookCalendar_SelectedIndexChanged;
                }

                OutlookOgcs.Calendar.Categories = new OutlookOgcs.Categories();
                Calendar.Categories.Get(oApp, useOutlookCalendar);

                //Set up event handlers
                explorerWatcher = new ExplorerWatcher(oApp);
            } catch (System.Runtime.InteropServices.COMException ex) {
                if (OGCSexception.GetErrorCode(ex) == "0x84120009")   //Cannot complete the operation. You are not connected. [Issue #514, occurs on GetNamespace("mapi")]
                {
                    log.Warn(ex.Message);
                    throw new ApplicationException("A problem was encountered with your Office install.\r\n" +
                                                   "Please perform an Office Repair or reinstall Outlook and then try running OGCS again.");
                }
                else
                {
                    throw ex;
                }
            } finally {
                // Done. Log off.
                if (oNS != null)
                {
                    oNS.Logoff();
                }
                oNS = (NameSpace)OutlookOgcs.Calendar.ReleaseObject(oNS);
            }
        }