예제 #1
0
        /// <summary>
        /// Generates a response from a GCalRequest
        /// </summary>
        /// <returns></returns>
        public string GenerateResponse()
        {
            /* Create a string builder to hold the text for the response */
            StringBuilder result = new StringBuilder(4096);

            /* Create an exchange provider */
            ExchangeService gateway = new ExchangeService(
                ConfigCache.ExchangeServerUrl,
                ConfigCache.ExchangeUserLogin,
                ConfigCache.ExchangeUserPassword);

            /* Return the exchangers from the GCal Request that was passed in */
            DateTimeRange    range         = new DateTimeRange(request.UTCStartDate, request.UTCEndDate);
            ExchangeUserDict exchangeUsers = gateway.SearchByEmail(range, request.ExchangeUsers);

            /* Create the header of the request */
            result.AppendFormat("['{0}','{1}',", request.VersionNumber, request.MessageId);

            result.AppendFormat("['_ME_AddData','{0}/{1}','{2}'",
                                DateUtil.FormatDateForGoogle(request.StartDate),
                                DateUtil.FormatDateForGoogle(request.EndDate),
                                DateUtil.FormatDateTimeForGoogle(request.Since));

            /* Flag for inserting commas */
            bool firstUser = true;

            result.Append(",[");

            foreach (ExchangeUser user in exchangeUsers.Values)
            {
                /* Don't add a comma if this is the first user */
                if (!firstUser)
                {
                    result.Append(",");
                }

                /* Add the user's credentials */
                string email = ConfigCache.MapToExternalDomain(user.Email);
                result.AppendFormat("'{0}','{1}','{2}',[",
                                    user.DisplayName,
                                    email,
                                    (int)user.AccessLevel);

                GenerateResponseForTimeBlocks(user,
                                              result);

                result.Append("]");
                firstUser = false;
            }

            result.Append("]");
            result.Append("]");
            result.Append("]");

            log.Info("GCal Free/Busy response successfully generated.");
            log.DebugFormat("Response = {0}", result);

            return(result.ToString());
        }
예제 #2
0
        public void TestParseWithDomainMap()
        {
            string        id        = "test-id";
            List <string> srcEmails = new List <string>();

            srcEmails.Add("*****@*****.**");
            srcEmails.Add("*****@*****.**");
            srcEmails.Add("*****@*****.**");
            srcEmails.Add("*****@*****.**");

            List <string> dstEmails = new List <string>();

            dstEmails.Add("*****@*****.**");
            dstEmails.Add("*****@*****.**");
            dstEmails.Add("*****@*****.**");
            dstEmails.Add("*****@*****.**");

            DateTime start = DateUtil.ParseDateToUtc("2008-01-01T00:00:00.000Z");
            DateTime end   = DateUtil.ParseDateToUtc("2008-01-31T00:00:00.000Z");
            DateTime since = DateUtil.ParseDateToUtc("2008-01-01T00:00:00.000Z");
            string   tz    = "America/Los_Angeles";

            string query = string.Format("[ 1, {0}, [{1}], {2}/{3}, {4}, {5}]",
                                         id,
                                         createEmailList(srcEmails),
                                         createDate(start),
                                         createDate(end),
                                         createDateTime(since),
                                         tz);

            ConfigCache.AddDomainMap("example.org", "woot.org");

            GCalFreeBusyRequest request =
                new GCalFreeBusyRequest(query);

            Assert.AreEqual(start, request.StartDate);
            Assert.AreEqual(end, request.EndDate);
            Assert.AreEqual(since, request.Since);
            Assert.AreEqual(id, request.MessageId);
            Assert.AreEqual("1", request.VersionNumber);
            Assert.AreEqual(dstEmails.Count, request.ExchangeUsers.Length);

            for (int i = 0; i < request.ExchangeUsers.Length; i++)
            {
                Assert.AreEqual(dstEmails[i], request.ExchangeUsers[i]);
            }
        }
예제 #3
0
        /// <summary>
        /// Parses the incoming Exchange request from GCal. The requests are of the form:
        /// [ version #, ID, [list of emails], startdate/enddate, sincedata, timezone]
        /// /// </summary>
        /// <param name="rawInput">The incoming GCal request string</param>
        private void Parse(string rawInput)
        {
            if (rawInput != null)
            {
                rawInput = rawInput.Trim();
            }

            /* Test that the request is not null or empty */
            if (string.IsNullOrEmpty(rawInput))
            {
                throw new GCalExchangeException(GCalExchangeErrorCode.MalformedRequest,
                                                "GCalRequest is null or empty.");
            }

            log.InfoFormat("Request received from GCal. [body={0}]", rawInput);

            /* Test that the request has starting and ending brackets */
            if (!rawInput.StartsWith("[") || !rawInput.EndsWith("]"))
            {
                throw new GCalExchangeException(GCalExchangeErrorCode.MalformedRequest,
                                                String.Format("GCalRequest does start and end in brackets: [rawInput:{0}]", rawInput));
            }

            /* Remove the start and end brackets */
            string requestContent = rawInput.Remove(0, 1);

            requestContent = requestContent.Remove(requestContent.Length - 1, 1);
            /* Request is cleaned to have no ending brackets */

            /* Test that the request has an inner bracket pair which (should) contains the usernames */
            if (!(requestContent.Contains("[") && requestContent.IndexOf("]") > requestContent.IndexOf("[")))
            {
                throw new GCalExchangeException(GCalExchangeErrorCode.MalformedRequest,
                                                string.Format("GCalRequest exchange users section is not properly formatted: [rawInput:{0}]", rawInput));
            }

            /* Get the indexes of the start and end username brackets */
            int usersStartIndex = requestContent.IndexOf("[");
            int usersEndIndex   = requestContent.IndexOf("]");
            int usersLength     = usersEndIndex - usersStartIndex + 1;

            /* Get the usernames string from the request */
            string usersString = requestContent.Substring(usersStartIndex, usersLength);

            /* Remove it from the rest of the request */
            requestContent = requestContent.Remove(usersStartIndex, usersLength);

            /* Remove the brackets from the start and end of the username string */
            usersString = usersString.Remove(0, 1);
            usersString = usersString.Remove(usersString.Length - 1, 1);

            /* Split the usernames by comma, store them in the request object */
            exchangeUsers = usersString.Split(',');

            // Apply any domain mappings to the user names
            for (int i = 0; i < exchangeUsers.Length; i++)
            {
                string user = exchangeUsers[i].Trim();
                exchangeUsers[i] = ConfigCache.MapToLocalDomain(user);
            }

            /* Split up the rest of the request */
            string[] requestItems = requestContent.Split(',');

            /* Test that the proper amount of variables remain in the string */
            if (requestItems.Length != expectedRequestItems)
            {
                throw new GCalExchangeException(GCalExchangeErrorCode.MalformedRequest,
                                                String.Format("GCalRequest does not contain the proper amount of variables; Supplied - {0}, Expected - {1}",
                                                              requestItems.Length,
                                                              expectedRequestItems));
            }

            /* Retrieve the version and message ids */
            versionNumber = requestItems[0].Trim();
            messageId     = requestItems[1].Trim();

            /* Get the start and end date from the request, the two dates are separated by '/' */
            string dateString = requestItems[3].Trim();

            string[] dateArray = dateString.Split('/');
            if (dateArray.Length != 2)
            {
                throw new GCalExchangeException(GCalExchangeErrorCode.MalformedRequest,
                                                "GCalRequest does not contain sufficient date information, both a start and end date must be supplied");
            }

            startDate = DateUtil.ParseGoogleDate(dateArray[0].Trim());
            endDate   = DateUtil.ParseGoogleDate(dateArray[1].Trim());

            string requestItemSince = requestItems[4].Trim();

            /* Get the since field from the request */
            try
            {
                since = DateUtil.ParseGoogleDate(requestItemSince);
            }
            catch (GCalExchangeException ex)
            {
                // We don't really use this param anyway and in some cases
                // we've seen an invalid date
                log.Warn(String.Format("Ignoring incorrect since request parameter {0}",
                                       requestItemSince),
                         ex);
                since = new DateTime();
            }

            /* Get the current time zone name */
            timeZone = OlsonUtil.GetTimeZone(requestItems[5].Trim());

            utcStartDate = OlsonUtil.ConvertToUTC(startDate, timeZone);
            utcEndDate   = OlsonUtil.ConvertToUTC(endDate, timeZone);
        }
예제 #4
0
        /// <summary>
        /// Query Google Calendar for a user and return the event feed
        /// </summary>
        /// <param name="email">Email address of the user to query</param>
        /// <param name="visibility">Feed Visibility (Public/Private) to query for</param>
        /// <param name="projection">Feed projection - type of feed to get</param>
        /// <param name="modifiedSince">Last modified time from last check</param>
        /// <param name="window">DateTime range to query between</param>
        /// <returns>An event feed for the user</returns>
        public EventFeed QueryGCal(
            string email,
            GCalVisibility visibility,
            GCalProjection projection,
            DateTime modifiedSince,
            DateTimeRange window)
        {
            // Perform mapping on the username if necessary
            string user = ConfigCache.MapToExternalDomain(email);

            if (log.IsDebugEnabled)
            {
                log.InfoFormat(
                    "FeedQuery with parameters: {0}, {1}, {2}, {3} [{4}]",
                    user,
                    visibility,
                    projection,
                    modifiedSince,
                    window);
            }

            StringBuilder sb = new StringBuilder(ConfigCache.GCalAddress);

            if (!ConfigCache.GCalAddress.EndsWith("/"))
            {
                sb.Append("/");
            }

            sb.AppendFormat("feeds/{0}/", user);

            switch (visibility)
            {
            case GCalVisibility.Public:
                sb.Append("public/");
                break;

            case GCalVisibility.Private:
            default:
                sb.Append("private/");
                break;
            }

            switch (projection)
            {
            case GCalProjection.Full:
                sb.Append("full");
                break;

            case GCalProjection.FullNoAttendees:
                sb.Append("full-noattendees");
                break;

            case GCalProjection.Composite:
                sb.Append("composite");
                break;

            case GCalProjection.AttendeesOnly:
                sb.Append("attendees-only");
                break;

            case GCalProjection.FreeBusy:
                sb.Append("free-busy");
                break;

            case GCalProjection.Basic:
            default:
                sb.Append("basic");
                break;
            }

            EventQuery query = new EventQuery(sb.ToString());

            if (projection != GCalProjection.FreeBusy)
            {
                query.SingleEvents = true;
            }

            GDataRequestFactory f = (GDataRequestFactory)service.RequestFactory;

            f.UseGZip = ConfigCache.EnableHttpCompression;

            if (window.Start != DateTime.MinValue)
            {
                query.StartTime = window.Start;
            }

            if (window.End != DateTime.MaxValue)
            {
                query.EndTime = window.End;
            }

            query.NumberToRetrieve = int.MaxValue; // Make sure we get everything

            try
            {
                return(QueryGCal(query, user, modifiedSince));
            }
            catch (System.IO.IOException e)
            {
                // Known problem with .NET 2.0 - Sometimes keep-alive connection is
                // closed by a proxy and we need to re-attemp the connection
                //
                // http://code.google.com/p/google-gdata/wiki/KeepAliveAndUnderlyingConnectionIsClosed

                if (e.InnerException.GetType().ToString().Equals("System.Net.Sockets.SocketException"))
                {
                    log.Info(String.Format("Attempt Retry Query after keep-alive termination"));
                    // One shot retry i case the keep-alive was closed
                    return(QueryGCal(query, user, modifiedSince));
                }
                else
                {
                    throw;
                }
            }
        }