Ejemplo n.º 1
0
        /// <summary>
        /// Returns <paramref name="propertyDefinition"/> property value from Exchange storage <paramref name="item"/>.
        /// If property value not reachable, returns default <paramref name="propertyDefinition"/> value.
        /// </summary>
        /// <typeparam name="T">Return value type.</typeparam>
        /// <param name="item"><see cref="Exchange.Item"/> instance.</param>
        /// <param name="propertyDefinition"><see cref="Exchange.PropertyDefinition"/> instance.</param>
        /// <returns><paramref name="propertyDefinition"/> value from <paramref name="item"/> if value reachable,
        /// dafault <paramref name="propertyDefinition"/> value otherwise.</returns>
        public static T SafeGetValue <T>(this Exchange.Item item, Exchange.PropertyDefinition propertyDefinition)
        {
            T value;

            item.TryGetProperty(propertyDefinition, out value);
            return(value);
        }
Ejemplo n.º 2
0
        static bool SetProperty(EmailMessage message, PropertyDefinition propertyDefinition, object value)
        {
            if (message == null)
                return false;

            // get value of PropertyBag property — that is wrapper
            // over dictionary of inner message’s properties
            var members = message.GetType().FindMembers(MemberTypes.Property, BindingFlags.NonPublic | BindingFlags.Instance,PartialName,"PropertyBag");
            if (members.Length < 1)
                return false;

            var propertyInfo = members[0] as PropertyInfo;
            if (propertyInfo == null)
                return false;

            var bag = propertyInfo.GetValue(message, null);
            members = bag.GetType().FindMembers(MemberTypes.Property,BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,PartialName,"Properties");
            if (members.Length < 1)
                return false;

            // get dictionary of properties values
            var properties = ((PropertyInfo)members[0]).GetMethod.Invoke(bag, null);
            var dictionary = properties as Dictionary<PropertyDefinition, object>;
            if (dictionary == null)
                return false;

            dictionary[propertyDefinition] = value;
            return true;
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Validates this property set instance for request to ensure that:
        /// 1. Properties are valid for the request server version.
        /// 2. If only summary properties are legal for this request (e.g. FindItem) then only summary properties were specified.
        /// </summary>
        /// <param name="request">The request.</param>
        /// <param name="summaryPropertiesOnly">if set to <c>true</c> then only summary properties are allowed.</param>
        internal void ValidateForRequest(ServiceRequestBase request, bool summaryPropertiesOnly)
        {
            foreach (PropertyDefinitionBase propDefBase in this.additionalProperties)
            {
                PropertyDefinition propertyDefinition = propDefBase as PropertyDefinition;
                if (propertyDefinition != null)
                {
                    if (propertyDefinition.Version > request.Service.RequestedServerVersion)
                    {
                        throw new ServiceVersionException(
                                  string.Format(
                                      Strings.PropertyIncompatibleWithRequestVersion,
                                      propertyDefinition.Name,
                                      propertyDefinition.Version));
                    }

                    if (summaryPropertiesOnly && !propertyDefinition.HasFlag(PropertyDefinitionFlags.CanFind, request.Service.RequestedServerVersion))
                    {
                        throw new ServiceValidationException(
                                  string.Format(
                                      Strings.NonSummaryPropertyCannotBeUsed,
                                      propertyDefinition.Name,
                                      request.GetXmlElementName()));
                    }
                }
            }

            if (this.FilterHtmlContent.HasValue)
            {
                if (request.Service.RequestedServerVersion < ExchangeVersion.Exchange2010)
                {
                    throw new ServiceVersionException(
                              string.Format(
                                  Strings.PropertyIncompatibleWithRequestVersion,
                                  "FilterHtmlContent",
                                  ExchangeVersion.Exchange2010));
                }
            }

            if (this.ConvertHtmlCodePageToUTF8.HasValue)
            {
                if (request.Service.RequestedServerVersion < ExchangeVersion.Exchange2010_SP1)
                {
                    throw new ServiceVersionException(
                              string.Format(
                                  Strings.PropertyIncompatibleWithRequestVersion,
                                  "ConvertHtmlCodePageToUTF8",
                                  ExchangeVersion.Exchange2010_SP1));
                }
            }

            if (!string.IsNullOrEmpty(this.InlineImageUrlTemplate))
            {
                if (request.Service.RequestedServerVersion < ExchangeVersion.Exchange2013)
                {
                    throw new ServiceVersionException(
                              string.Format(
                                  Strings.PropertyIncompatibleWithRequestVersion,
                                  "InlineImageUrlTemplate",
                                  ExchangeVersion.Exchange2013));
                }
            }

            if (this.BlockExternalImages.HasValue)
            {
                if (request.Service.RequestedServerVersion < ExchangeVersion.Exchange2013)
                {
                    throw new ServiceVersionException(
                              string.Format(
                                  Strings.PropertyIncompatibleWithRequestVersion,
                                  "BlockExternalImages",
                                  ExchangeVersion.Exchange2013));
                }
            }

            if (this.AddBlankTargetToLinks.HasValue)
            {
                if (request.Service.RequestedServerVersion < ExchangeVersion.Exchange2013)
                {
                    throw new ServiceVersionException(
                              string.Format(
                                  Strings.PropertyIncompatibleWithRequestVersion,
                                  "AddTargetToLinks",
                                  ExchangeVersion.Exchange2013));
                }
            }

            if (this.MaximumBodySize.HasValue)
            {
                if (request.Service.RequestedServerVersion < ExchangeVersion.Exchange2013)
                {
                    throw new ServiceVersionException(
                              string.Format(
                                  Strings.PropertyIncompatibleWithRequestVersion,
                                  "MaximumBodySize",
                                  ExchangeVersion.Exchange2013));
                }
            }
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Scopes the date time property to the appropriate time zone, if necessary.
        /// </summary>
        /// <param name="service">The service emitting the request.</param>
        /// <param name="dateTime">The date time.</param>
        /// <param name="propertyBag">The property bag.</param>
        /// <param name="isUpdateOperation">Indicates whether the scoping is to be performed in the context of an update operation.</param>
        /// <returns>The converted DateTime.</returns>
        internal override DateTime ScopeToTimeZone(
            ExchangeServiceBase service,
            DateTime dateTime,
            PropertyBag propertyBag,
            bool isUpdateOperation)
        {
            if (!propertyBag.Owner.GetIsCustomDateTimeScopingRequired())
            {
                // Most item types do not require a custom scoping mechanism. For those item types,
                // use the default scoping mechanism.
                return(base.ScopeToTimeZone(
                           service,
                           dateTime,
                           propertyBag,
                           isUpdateOperation));
            }
            else
            {
                // Appointment, however, requires a custom scoping mechanism which is based on an
                // associated time zone property.
                PropertyDefinition timeZoneProperty      = this.GetTimeZoneProperty(service.RequestedServerVersion);
                object             timeZonePropertyValue = null;

                bool timeZonePropertyIsSet = propertyBag.TryGetProperty(timeZoneProperty, out timeZonePropertyValue);

                if (timeZonePropertyValue != null && propertyBag.IsPropertyUpdated(timeZoneProperty))
                {
                    // If we have the associated time zone property handy and if it has been updated locally,
                    // then we scope the date time to that time zone.
                    try
                    {
                        DateTime convertedDateTime = EwsUtilities.ConvertTime(
                            dateTime,
                            (TimeZoneInfo)timeZonePropertyValue,
                            TimeZoneInfo.Utc);

                        // This is necessary to stamp the date/time with the Local kind.
                        return(new DateTime(convertedDateTime.Ticks, DateTimeKind.Utc));
                    }
                    catch (TimeZoneConversionException e)
                    {
                        throw new PropertyException(
                                  string.Format(Strings.InvalidDateTime, dateTime),
                                  this.Name,
                                  e);
                    }
                }
                else
                {
                    if (isUpdateOperation)
                    {
                        // In an update operation, what we do depends on what version of EWS
                        // we are targeting.
                        if (service.RequestedServerVersion == ExchangeVersion.Exchange2007_SP1)
                        {
                            // For Exchange 2007 SP1, we still need to scope to the service's time zone.
                            return(base.ScopeToTimeZone(
                                       service,
                                       dateTime,
                                       propertyBag,
                                       isUpdateOperation));
                        }
                        else
                        {
                            // Otherwise, we let the server scope to the appropriate time zone.
                            return(dateTime);
                        }
                    }
                    else
                    {
                        // In a Create operation, always scope to the service's time zone.
                        return(base.ScopeToTimeZone(
                                   service,
                                   dateTime,
                                   propertyBag,
                                   isUpdateOperation));
                    }
                }
            }
        }
        /// <summary>
        /// Writes the update to Json.
        /// </summary>
        /// <param name="service">The service.</param>
        /// <param name="ewsObject">The ews object.</param>
        /// <param name="propertyDefinition">Property definition.</param>
        /// <param name="updates">The updates.</param>
        /// <returns>
        /// True if property generated serialization.
        /// </returns>
        bool ICustomUpdateSerializer.WriteSetUpdateToJson(ExchangeService service, ServiceObject ewsObject, PropertyDefinition propertyDefinition, List <JsonObject> updates)
        {
            // If the collection is empty, delete the property.
            if (this.Count == 0)
            {
                JsonObject jsonUpdate = new JsonObject();

                jsonUpdate.AddTypeParameter(ewsObject.GetDeleteFieldXmlElementName());
                jsonUpdate.Add(JsonNames.Path, (propertyDefinition as IJsonSerializable).ToJson(service));
                return(true);
            }

            // Otherwise, use the default Json serializer.
            else
            {
                return(false);
            }
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Writes the set update to json.
        /// </summary>
        /// <param name="service">The service.</param>
        /// <param name="ewsObject">The ews object.</param>
        /// <param name="propertyDefinition">The property definition.</param>
        /// <param name="updates">The updates.</param>
        /// <returns></returns>
        bool ICustomUpdateSerializer.WriteSetUpdateToJson(
            ExchangeService service,
            ServiceObject ewsObject,
            PropertyDefinition propertyDefinition,
            List <JsonObject> updates)
        {
            List <TEntry> tempEntries = new List <TEntry>();

            foreach (TKey key in this.addedEntries)
            {
                tempEntries.Add(this.entries[key]);
            }
            foreach (TKey key in this.modifiedEntries)
            {
                tempEntries.Add(this.entries[key]);
            }

            foreach (TEntry entry in tempEntries)
            {
                if (!entry.WriteSetUpdateToJson(
                        service,
                        ewsObject,
                        propertyDefinition,
                        updates))
                {
                    JsonObject jsonUpdate = new JsonObject();

                    jsonUpdate.AddTypeParameter(ewsObject.GetSetFieldXmlElementName());

                    JsonObject jsonUri = new JsonObject();

                    jsonUri.AddTypeParameter(JsonNames.PathToIndexedFieldType);
                    jsonUri.Add(XmlAttributeNames.FieldURI, this.GetFieldURI());
                    jsonUri.Add(XmlAttributeNames.FieldIndex, entry.Key.ToString());

                    jsonUpdate.Add(JsonNames.Path, jsonUri);

                    object jsonProperty = entry.InternalToJson(service);

                    JsonObject jsonServiceObject = new JsonObject();
                    jsonServiceObject.AddTypeParameter(ewsObject.GetXmlElementName());
                    jsonServiceObject.Add(propertyDefinition.XmlElementName, new object[] { jsonProperty });

                    jsonUpdate.Add(PropertyBag.GetPropertyUpdateItemName(ewsObject), jsonServiceObject);

                    updates.Add(jsonUpdate);
                }
            }

            foreach (TEntry entry in this.removedEntries.Values)
            {
                if (!entry.WriteDeleteUpdateToJson(service, ewsObject, updates))
                {
                    JsonObject jsonUpdate = new JsonObject();

                    jsonUpdate.AddTypeParameter(ewsObject.GetDeleteFieldXmlElementName());

                    JsonObject jsonUri = new JsonObject();

                    jsonUri.AddTypeParameter(JsonNames.PathToIndexedFieldType);
                    jsonUri.Add(XmlAttributeNames.FieldURI, this.GetFieldURI());
                    jsonUri.Add(XmlAttributeNames.FieldIndex, entry.Key.ToString());

                    jsonUpdate.Add(JsonNames.Path, jsonUri);

                    updates.Add(jsonUpdate);
                }
            }

            return(true);
        }
Ejemplo n.º 7
0
 /// <summary>
 /// Tries to retrieve the value of the specified property.
 /// </summary>
 /// <param name="propertyDefinition">The property for which to retrieve a value.</param>
 /// <param name="propertyValue">If the method succeeds, contains the value of the property.</param>
 /// <returns>True if the value could be retrieved, false otherwise.</returns>
 internal bool TryGetValue(PropertyDefinition propertyDefinition, out object propertyValue)
 {
     return(this.properties.TryGetValue(propertyDefinition, out propertyValue));
 }
Ejemplo n.º 8
0
 /// <summary>
 /// Determines whether the property bag contains a specific property.
 /// </summary>
 /// <param name="propertyDefinition">The property to check against.</param>
 /// <returns>True if the specified property is in the bag, false otherwise.</returns>
 internal bool Contains(PropertyDefinition propertyDefinition)
 {
     return(this.properties.ContainsKey(propertyDefinition));
 }
Ejemplo n.º 9
0
        /// <summary>
        /// Gets or sets the value of a property.
        /// </summary>
        /// <param name="propertyDefinition">The property to get or set.</param>
        /// <returns>An object representing the value of the property.</returns>
        /// <exception cref="ServiceVersionException">Raised if this property requires a later version of Exchange.</exception>
        /// <exception cref="ServiceObjectPropertyException">Raised for get if property hasn't been assigned or loaded. Raised for set if property cannot be updated or deleted.</exception>
        internal object this[PropertyDefinition propertyDefinition]
        {
            get
            {
                ServiceLocalException serviceException;
                object propertyValue = this.GetPropertyValueOrException(propertyDefinition, out serviceException);
                if (serviceException == null)
                {
                    return(propertyValue);
                }
                else
                {
                    throw serviceException;
                }
            }

            set
            {
                if (propertyDefinition.Version > this.Owner.Service.RequestedServerVersion)
                {
                    throw new ServiceVersionException(
                              string.Format(
                                  Strings.PropertyIncompatibleWithRequestVersion,
                                  propertyDefinition.Name,
                                  propertyDefinition.Version));
                }

                // If the property bag is not in the loading state, we need to verify whether
                // the property can actually be set or updated.
                if (!this.loading)
                {
                    // If the owner is new and if the property cannot be set, throw.
                    if (this.Owner.IsNew && !propertyDefinition.HasFlag(PropertyDefinitionFlags.CanSet, this.Owner.Service.RequestedServerVersion))
                    {
                        throw new ServiceObjectPropertyException(Strings.PropertyIsReadOnly, propertyDefinition);
                    }

                    if (!this.Owner.IsNew)
                    {
                        // If owner is an item attachment, properties cannot be updated (EWS doesn't support updating item attachments)
                        Item ownerItem = this.Owner as Item;
                        if ((ownerItem != null) && ownerItem.IsAttachment)
                        {
                            throw new ServiceObjectPropertyException(Strings.ItemAttachmentCannotBeUpdated, propertyDefinition);
                        }

                        // If the property cannot be deleted, throw.
                        if (value == null && !propertyDefinition.HasFlag(PropertyDefinitionFlags.CanDelete))
                        {
                            throw new ServiceObjectPropertyException(Strings.PropertyCannotBeDeleted, propertyDefinition);
                        }

                        // If the property cannot be updated, throw.
                        if (!propertyDefinition.HasFlag(PropertyDefinitionFlags.CanUpdate))
                        {
                            throw new ServiceObjectPropertyException(Strings.PropertyCannotBeUpdated, propertyDefinition);
                        }
                    }
                }

                // If the value is set to null, delete the property.
                if (value == null)
                {
                    this.DeleteProperty(propertyDefinition);
                }
                else
                {
                    ComplexProperty complexProperty;
                    object          currentValue;

                    if (this.properties.TryGetValue(propertyDefinition, out currentValue))
                    {
                        complexProperty = currentValue as ComplexProperty;

                        if (complexProperty != null)
                        {
                            complexProperty.OnChange -= this.PropertyChanged;
                        }
                    }

                    // If the property was to be deleted, the deletion becomes an update.
                    if (this.deletedProperties.Remove(propertyDefinition))
                    {
                        AddToChangeList(propertyDefinition, this.modifiedProperties);
                    }
                    else
                    {
                        // If the property value was not set, we have a newly set property.
                        if (!this.properties.ContainsKey(propertyDefinition))
                        {
                            AddToChangeList(propertyDefinition, this.addedProperties);
                        }
                        else
                        {
                            // The last case is that we have a modified property.
                            if (!this.modifiedProperties.Contains(propertyDefinition))
                            {
                                AddToChangeList(propertyDefinition, this.modifiedProperties);
                            }
                        }
                    }

                    this.InitComplexProperty(value as ComplexProperty);
                    this.properties[propertyDefinition] = value;

                    this.Changed();
                }
            }
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Gets the property value.
        /// </summary>
        /// <param name="propertyDefinition">The property definition.</param>
        /// <param name="exception">Exception that would be raised if there's an error retrieving the property.</param>
        /// <returns>Propert value. May be null.</returns>
        private object GetPropertyValueOrException(PropertyDefinition propertyDefinition, out ServiceLocalException exception)
        {
            object propertyValue = null;

            exception = null;

            if (propertyDefinition.Version > this.Owner.Service.RequestedServerVersion)
            {
                exception = new ServiceVersionException(
                    string.Format(
                        Strings.PropertyIncompatibleWithRequestVersion,
                        propertyDefinition.Name,
                        propertyDefinition.Version));
                return(null);
            }

            if (this.TryGetValue(propertyDefinition, out propertyValue))
            {
                // If the requested property is in the bag, return it.
                return(propertyValue);
            }
            else
            {
                if (propertyDefinition.HasFlag(PropertyDefinitionFlags.AutoInstantiateOnRead))
                {
                    // The requested property is an auto-instantiate-on-read property
                    ComplexPropertyDefinitionBase complexPropertyDefinition = propertyDefinition as ComplexPropertyDefinitionBase;

                    EwsUtilities.Assert(
                        complexPropertyDefinition != null,
                        "PropertyBag.get_this[]",
                        "propertyDefinition is marked with AutoInstantiateOnRead but is not a descendant of ComplexPropertyDefinitionBase");

                    propertyValue = complexPropertyDefinition.CreatePropertyInstance(this.Owner);

                    if (propertyValue != null)
                    {
                        this.InitComplexProperty(propertyValue as ComplexProperty);
                        this.properties[propertyDefinition] = propertyValue;
                    }
                }
                else
                {
                    // If the property is not the Id (we need to let developers read the Id when it's null) and if has
                    // not been loaded, we throw.
                    if (propertyDefinition != this.Owner.GetIdPropertyDefinition())
                    {
                        if (!this.IsPropertyLoaded(propertyDefinition))
                        {
                            exception = new ServiceObjectPropertyException(Strings.MustLoadOrAssignPropertyBeforeAccess, propertyDefinition);
                            return(null);
                        }

                        // Non-nullable properties (int, bool, etc.) must be assigned or loaded; cannot return null value.
                        if (!propertyDefinition.IsNullable)
                        {
                            string errorMessage = this.IsRequestedProperty(propertyDefinition)
                                                        ? Strings.ValuePropertyNotLoaded
                                                        : Strings.ValuePropertyNotAssigned;
                            exception = new ServiceObjectPropertyException(errorMessage, propertyDefinition);
                        }
                    }
                }

                return(propertyValue);
            }
        }
Ejemplo n.º 11
0
 /// <summary>
 /// Determines whether the specified property has been updated.
 /// </summary>
 /// <param name="propertyDefinition">The property definition.</param>
 /// <returns>
 ///     <c>true</c> if the specified property has been updated; otherwise, <c>false</c>.
 /// </returns>
 internal bool IsPropertyUpdated(PropertyDefinition propertyDefinition)
 {
     return(this.modifiedProperties.Contains(propertyDefinition) || this.addedProperties.Contains(propertyDefinition));
 }