/// <summary> /// This is implemented to handle properties related to VEvent items /// </summary> /// <param name="propertyName">The name of the property</param> /// <param name="parameters">A string collection containing the parameters and their values. If empty, /// there are no parameters.</param> /// <param name="propertyValue">The value of the property.</param> protected virtual void VEventParser(string propertyName, StringCollection parameters, string propertyValue) { StringCollection sc; string[] parts, parms; int idx; // The last entry is always CustomProperty so scan for length minus one for(idx = 0; idx < ntvEvent.Length - 1; idx++) if(ntvEvent[idx].IsMatch(propertyName)) break; // An opening BEGIN:VEVENT property must have been seen if(vEvent == null) throw new PDIParserException(this.LineNumber, LR.GetString("ExParseNoBeginProp", "BEGIN:VEVENT", propertyName)); // Handle or create the property switch(ntvEvent[idx].EnumValue) { case PropertyType.Begin: // Handle nested objects priorState.Push(currentState); // Is it an alarm? if(String.Compare(propertyValue.Trim(), "VALARM", StringComparison.OrdinalIgnoreCase) == 0) { vAlarm = new VAlarm(); vEvent.Alarms.Add(vAlarm); currentState = VCalendarParserState.VAlarm; } else { // Unknown/custom object currentState = VCalendarParserState.Custom; CustomObjectParser(propertyName, parameters, propertyValue); } break; case PropertyType.End: // For this, the value must be VEVENT if(String.Compare(propertyValue.Trim(), "VEVENT", StringComparison.OrdinalIgnoreCase) != 0) throw new PDIParserException(this.LineNumber, LR.GetString("ExParseUnrecognizedTagValue", ntvEvent[idx].Name, propertyValue)); // The event is added to the collection when created so we don't have to rely on an END tag // to add it. vEvent = null; currentState = priorState.Pop(); break; case PropertyType.Class: vEvent.Classification.EncodedValue = propertyValue; break; case PropertyType.Categories: // If this is seen more than once, just add the new stuff to the existing property CategoriesProperty cp = new CategoriesProperty(); cp.DeserializeParameters(parameters); cp.EncodedValue = propertyValue; foreach(string s in cp.Categories) vEvent.Categories.Categories.Add(s); break; case PropertyType.Resources: // If this is seen more than once, just add the new stuff to the existing property ResourcesProperty rp = new ResourcesProperty(); rp.DeserializeParameters(parameters); rp.EncodedValue = propertyValue; foreach(string s in rp.Resources) vEvent.Resources.Resources.Add(s); break; case PropertyType.Url: vEvent.Url.DeserializeParameters(parameters); vEvent.Url.EncodedValue = propertyValue; break; case PropertyType.UniqueId: vEvent.UniqueId.EncodedValue = propertyValue; break; case PropertyType.LastModified: vEvent.LastModified.DeserializeParameters(parameters); vEvent.LastModified.EncodedValue = propertyValue; break; case PropertyType.GeographicPosition: vEvent.GeographicPosition.EncodedValue = propertyValue; break; case PropertyType.DateCreated: vEvent.DateCreated.DeserializeParameters(parameters); vEvent.DateCreated.EncodedValue = propertyValue; break; case PropertyType.StartDateTime: vEvent.StartDateTime.DeserializeParameters(parameters); vEvent.StartDateTime.EncodedValue = propertyValue; break; case PropertyType.EndDateTime: vEvent.EndDateTime.DeserializeParameters(parameters); vEvent.EndDateTime.EncodedValue = propertyValue; break; case PropertyType.TimeStamp: vEvent.TimeStamp.DeserializeParameters(parameters); vEvent.TimeStamp.EncodedValue = propertyValue; break; case PropertyType.Summary: vEvent.Summary.DeserializeParameters(parameters); vEvent.Summary.EncodedValue = propertyValue; break; case PropertyType.Description: vEvent.Description.DeserializeParameters(parameters); vEvent.Description.EncodedValue = propertyValue; break; case PropertyType.Location: vEvent.Location.DeserializeParameters(parameters); vEvent.Location.EncodedValue = propertyValue; break; case PropertyType.Priority: vEvent.Priority.DeserializeParameters(parameters); vEvent.Priority.EncodedValue = propertyValue; break; case PropertyType.Sequence: vEvent.Sequence.DeserializeParameters(parameters); vEvent.Sequence.EncodedValue = propertyValue; break; case PropertyType.Transparency: vEvent.Transparency.DeserializeParameters(parameters); vEvent.Transparency.EncodedValue = propertyValue; break; case PropertyType.RecurrenceCount: vEvent.RecurrenceCount.DeserializeParameters(parameters); vEvent.RecurrenceCount.EncodedValue = propertyValue; break; case PropertyType.Comment: // If this is seen more than once, just add the new stuff to the existing property if(vEvent.Comment.Value != null) { vEvent.Comment.EncodedValue += "\r\n"; vEvent.Comment.EncodedValue += propertyValue; } else { vEvent.Comment.DeserializeParameters(parameters); vEvent.Comment.EncodedValue = propertyValue; } break; case PropertyType.Contact: ContactProperty c = new ContactProperty(); c.DeserializeParameters(parameters); c.EncodedValue = propertyValue; vEvent.Contacts.Add(c); break; case PropertyType.Organizer: vEvent.Organizer.DeserializeParameters(parameters); vEvent.Organizer.EncodedValue = propertyValue; break; case PropertyType.Attendee: AttendeeProperty ap = new AttendeeProperty(); ap.DeserializeParameters(parameters); ap.EncodedValue = propertyValue; vEvent.Attendees.Add(ap); break; case PropertyType.RelatedTo: RelatedToProperty rt = new RelatedToProperty(); rt.DeserializeParameters(parameters); rt.EncodedValue = propertyValue; vEvent.RelatedTo.Add(rt); break; case PropertyType.Attachment: AttachProperty att = new AttachProperty(); att.DeserializeParameters(parameters); att.EncodedValue = propertyValue; vEvent.Attachments.Add(att); break; case PropertyType.RecurrenceId: vEvent.RecurrenceId.DeserializeParameters(parameters); vEvent.RecurrenceId.EncodedValue = propertyValue; break; case PropertyType.Status: vEvent.Status.DeserializeParameters(parameters); vEvent.Status.EncodedValue = propertyValue; break; case PropertyType.RequestStatus: RequestStatusProperty rs = new RequestStatusProperty(); rs.DeserializeParameters(parameters); rs.EncodedValue = propertyValue; vEvent.RequestStatuses.Add(rs); break; case PropertyType.Duration: vEvent.Duration.DeserializeParameters(parameters); vEvent.Duration.EncodedValue = propertyValue; break; case PropertyType.AudioAlarm: case PropertyType.DisplayAlarm: case PropertyType.EMailAlarm: case PropertyType.ProcedureAlarm: // These are converted to a VAlarm object vAlarm = new VAlarm(); ParseVCalendarAlarm(ntvEvent[idx].EnumValue, parameters, propertyValue); vEvent.Alarms.Add(vAlarm); vAlarm = null; break; case PropertyType.RecurrenceRule: RRuleProperty rr = new RRuleProperty(); rr.DeserializeParameters(parameters); rr.EncodedValue = propertyValue; vEvent.RecurrenceRules.Add(rr); break; case PropertyType.RecurDate: // There may be more than one date in the value. If so, split them into separate ones. This // makes it easier to manage. They'll get written back out as individual properties but // that's okay. parts = propertyValue.Split(',', ';'); // It's important that we retain the same parameters for each one parms = new string[parameters.Count]; parameters.CopyTo(parms, 0); foreach(string s in parts) { sc = new StringCollection(); sc.AddRange(parms); RDateProperty rd = new RDateProperty(); rd.DeserializeParameters(sc); rd.EncodedValue = s; vEvent.RecurDates.Add(rd); } break; case PropertyType.ExceptionRule: ExRuleProperty er = new ExRuleProperty(); er.DeserializeParameters(parameters); er.EncodedValue = propertyValue; vEvent.ExceptionRules.Add(er); break; case PropertyType.ExceptionDate: // There may be more than one date in the value. If so, split them into separate ones. This // makes it easier to manage. They'll get written back out as individual properties but // that's okay. parts = propertyValue.Split(',', ';'); // It's important that we retain the same parameters for each one parms = new string[parameters.Count]; parameters.CopyTo(parms, 0); foreach(string s in parts) { sc = new StringCollection(); sc.AddRange(parms); ExDateProperty ed = new ExDateProperty(); ed.DeserializeParameters(sc); ed.EncodedValue = s; vEvent.ExceptionDates.Add(ed); } break; case PropertyType.ExcludeStartDateTime: // This is a custom property not defined by the spec vEvent.ExcludeStartDateTime = (propertyValue[0] == '1'); break; default: // Anything else is a custom property CustomProperty cust = new CustomProperty(propertyName); cust.DeserializeParameters(parameters); cust.EncodedValue = propertyValue; vEvent.CustomProperties.Add(cust); break; } }
//===================================================================== /// <summary> /// This is overridden to handle the additional state maintained by the calendar parser /// </summary> /// <param name="fullReset">If true, a full reset is done (i.e. this is the start of a brand new session. /// If false only the line state is reset (it's done parsing a property name or value).</param> protected override void ResetState(bool fullReset) { if(fullReset) { currentState = VCalendarParserState.VCalendar; vEvent = null; vToDo = null; vJournal = null; vAlarm = null; vFreeBusy = null; vTimeZone = null; obsRule = null; priorState.Clear(); beginValue.Clear(); } base.ResetState(fullReset); }
/// <summary> /// This is implemented to handle properties as they are parsed from the data stream /// </summary> /// <param name="propertyName">The name of the property.</param> /// <param name="parameters">A string collection containing the parameters and their values. If empty, /// there are no parameters.</param> /// <param name="propertyValue">The value of the property.</param> /// <remarks><para>There may be a mixture of name/value pairs or values alone in the parameters string /// collection. It is up to the derived class to process the parameter list based on the specification /// to which it conforms. For entries that are parameter names, the entry immediately following it in /// the collection is its associated parameter value. The property name, parameter names, and their /// values may be in upper, lower, or mixed case.</para> /// /// <para>The value may be an encoded string. The properties are responsible for any decoding that may /// need to occur (i.e. base 64 encoded image data).</para></remarks> /// <exception cref="PDIParserException">This is thrown if an error is encountered while parsing the data /// stream. Refer to the and inner exceptions for information on the cause of the problem.</exception> protected override void PropertyParser(string propertyName, StringCollection parameters, string propertyValue) { SpecificationVersions version = SpecificationVersions.None; string temp; int idx; // Is it parsing a sub-object? if(currentState != VCalendarParserState.VCalendar) { switch(currentState) { case VCalendarParserState.VEvent: VEventParser(propertyName, parameters, propertyValue); break; case VCalendarParserState.VToDo: VToDoParser(propertyName, parameters, propertyValue); break; case VCalendarParserState.VJournal: VJournalParser(propertyName, parameters, propertyValue); break; case VCalendarParserState.VAlarm: VAlarmParser(propertyName, parameters, propertyValue); break; case VCalendarParserState.VFreeBusy: VFreeBusyParser(propertyName, parameters, propertyValue); break; case VCalendarParserState.VTimeZone: VTimeZoneParser(propertyName, parameters, propertyValue); break; case VCalendarParserState.ObservanceRule: ObservanceRuleParser(propertyName, parameters, propertyValue); break; case VCalendarParserState.Custom: CustomObjectParser(propertyName, parameters, propertyValue); break; } return; } // The last entry is always CustomProperty so scan for length minus one for(idx = 0; idx < ntvCal.Length - 1; idx++) if(ntvCal[idx].IsMatch(propertyName)) break; // An opening BEGIN:VCALENDAR property must have been seen if(vCal == null && ntvCal[idx].EnumValue != PropertyType.Begin) throw new PDIParserException(this.LineNumber, LR.GetString("ExParseNoBeginProp", "BEGIN:VCALENDAR", propertyName)); // Handle or create the property switch(ntvCal[idx].EnumValue) { case PropertyType.Begin: // Start a new object temp = propertyValue.Trim(); // The last entry is always Custom so scan for length - 1 for(idx = 0; idx < ntvObjs.Length - 1; idx++) if(ntvObjs[idx].IsMatch(temp)) break; priorState.Push(currentState); currentState = ntvObjs[idx].EnumValue; switch(currentState) { case VCalendarParserState.VCalendar: // NOTE: If serializing into an existing instance, this may not be null. If so, it // is ignored. It may also exist if two calendars appear in the same file. In that // case, they will be merged into one calendar. if(vCal == null) vCal = new VCalendar(); break; case VCalendarParserState.VEvent: vEvent = new VEvent(); vCal.Events.Add(vEvent); break; case VCalendarParserState.VToDo: vToDo = new VToDo(); vCal.ToDos.Add(vToDo); break; case VCalendarParserState.VJournal: vJournal = new VJournal(); vCal.Journals.Add(vJournal); break; case VCalendarParserState.VFreeBusy: vFreeBusy = new VFreeBusy(); vCal.FreeBusys.Add(vFreeBusy); break; case VCalendarParserState.VTimeZone: // NOTE: Unlike the other objects, time zone are not added to the collection until // the END Tag is encountered as they are shared amongst all calendar instances. vTimeZone = new VTimeZone(); break; case VCalendarParserState.Custom: CustomObjectParser(propertyName, parameters, propertyValue); break; } break; case PropertyType.End: // The value must be VCALENDAR if(String.Compare(propertyValue.Trim(), "VCALENDAR", StringComparison.OrdinalIgnoreCase) != 0) throw new PDIParserException(this.LineNumber, LR.GetString("ExParseUnrecognizedTagValue", ntvCal[idx].Name, propertyValue)); // When done, we'll propagate the version number to all objects to make it consistent vCal.PropagateVersion(); break; case PropertyType.Version: // Version must be 1.0 or 2.0 temp = propertyValue.Trim(); if(temp == "1.0") version = SpecificationVersions.vCalendar10; else if(temp == "2.0") version = SpecificationVersions.iCalendar20; else throw new PDIParserException(this.LineNumber, LR.GetString("ExParseUnrecognizedVersion", "vCalendar/iCalendar", temp)); vCal.Version = version; break; case PropertyType.ProductId: vCal.ProductId.EncodedValue = propertyValue; break; case PropertyType.CalendarScale: vCal.CalendarScale.DeserializeParameters(parameters); vCal.CalendarScale.EncodedValue = propertyValue; break; case PropertyType.Method: vCal.Method.DeserializeParameters(parameters); vCal.Method.EncodedValue = propertyValue; break; case PropertyType.GeographicPosition: vCal.VCalendarGeographicPosition.EncodedValue = propertyValue; break; case PropertyType.TimeZone: vCal.VCalendarTimeZone.DeserializeParameters(parameters); vCal.VCalendarTimeZone.EncodedValue = propertyValue; break; case PropertyType.Daylight: vCal.VCalendarDaylightRule.DeserializeParameters(parameters); vCal.VCalendarDaylightRule.EncodedValue = propertyValue; break; default: // Anything else is a custom property CustomProperty c = new CustomProperty(propertyName); c.DeserializeParameters(parameters); c.EncodedValue = propertyValue; vCal.CustomProperties.Add(c); break; } }
/// <summary> /// This is implemented to handle properties related to custom entries that are wrapped in a BEGIN/END /// sequence. /// </summary> /// <param name="propertyName">The name of the property.</param> /// <param name="parameters">A string collection containing the parameters and their values. If empty, /// there are no parameters.</param> /// <param name="propertyValue">The value of the property.</param> /// <remarks>All unknown objects are stuck in the custom properties collection of the item being /// processed.</remarks> protected virtual void CustomObjectParser(string propertyName, StringCollection parameters, string propertyValue) { CustomProperty cust = new CustomProperty(propertyName); cust.DeserializeParameters(parameters); cust.EncodedValue = propertyValue; switch(priorState.Peek()) { case VCalendarParserState.VCalendar: vCal.CustomProperties.Add(cust); break; case VCalendarParserState.VEvent: vEvent.CustomProperties.Add(cust); break; case VCalendarParserState.VToDo: vToDo.CustomProperties.Add(cust); break; case VCalendarParserState.VJournal: vJournal.CustomProperties.Add(cust); break; case VCalendarParserState.VAlarm: vAlarm.CustomProperties.Add(cust); break; case VCalendarParserState.VFreeBusy: vFreeBusy.CustomProperties.Add(cust); break; case VCalendarParserState.VTimeZone: vTimeZone.CustomProperties.Add(cust); break; default: throw new NotImplementedException(LR.GetString("ExCOPNotImplemented")); } // Is it another nested object if(String.Compare(propertyName, "BEGIN", StringComparison.OrdinalIgnoreCase) == 0) beginValue.Push(propertyValue.Trim()); else // Is it the end of the object? if(String.Compare(propertyName, "END", StringComparison.OrdinalIgnoreCase) == 0) if(String.Compare(propertyValue.Trim(), beginValue.Peek(), StringComparison.OrdinalIgnoreCase) == 0) { beginValue.Pop(); if(beginValue.Count == 0) currentState = priorState.Pop(); } else throw new PDIParserException(this.LineNumber, LR.GetString("ExCOPUnexpectedEnd", beginValue.Pop(), propertyValue)); }
/// <summary> /// This is implemented to handle properties related to observance rule items in VTimeZone objects /// </summary> /// <param name="propertyName">The name of the property.</param> /// <param name="parameters">A string collection containing the parameters and their values. If empty, /// there are no parameters.</param> /// <param name="propertyValue">The value of the property.</param> protected virtual void ObservanceRuleParser(string propertyName, StringCollection parameters, string propertyValue) { StringCollection sc; string[] parts, parms; int idx; // The last entry is always CustomProperty so scan for length minus one for(idx = 0; idx < ntvORule.Length - 1; idx++) if(ntvORule[idx].IsMatch(propertyName)) break; // An opening BEGIN:STANDARD or BEGIN:DAYLIGHT property must have been seen. if(obsRule == null) throw new PDIParserException(this.LineNumber, LR.GetString("ExParseNoBeginProp", "BEGIN:STANDARD/BEGIN:DAYLIGHT", propertyName)); // Handle or create the property switch(ntvORule[idx].EnumValue) { case PropertyType.Begin: // Handle unknown nested objects priorState.Push(currentState); currentState = VCalendarParserState.Custom; CustomObjectParser(propertyName, parameters, propertyValue); break; case PropertyType.End: // For this, the value must be STANDARD or DAYLIGHT depending on the rule type if((obsRule.RuleType == ObservanceRuleType.Standard && String.Compare(propertyValue.Trim(), "STANDARD", StringComparison.OrdinalIgnoreCase) != 0) || (obsRule.RuleType == ObservanceRuleType.Daylight && String.Compare(propertyValue.Trim(), "DAYLIGHT", StringComparison.OrdinalIgnoreCase) != 0)) { throw new PDIParserException(this.LineNumber, LR.GetString("ExParseUnrecognizedTagValue", ntvORule[idx].Name, propertyValue)); } // The rule is added to the collection when created so we don't have to rely on an END tag to // add it. obsRule = null; currentState = priorState.Pop(); break; case PropertyType.StartDateTime: obsRule.StartDateTime.DeserializeParameters(parameters); obsRule.StartDateTime.EncodedValue = propertyValue; break; case PropertyType.TimeZoneOffsetFrom: obsRule.OffsetFrom.DeserializeParameters(parameters); obsRule.OffsetFrom.EncodedValue = propertyValue; break; case PropertyType.TimeZoneOffsetTo: obsRule.OffsetTo.DeserializeParameters(parameters); obsRule.OffsetTo.EncodedValue = propertyValue; break; case PropertyType.Comment: // If this is seen more than once, just add the new stuff to the existing property if(obsRule.Comment.Value != null) { obsRule.Comment.EncodedValue += "\r\n"; obsRule.Comment.EncodedValue += propertyValue; } else { obsRule.Comment.DeserializeParameters(parameters); obsRule.Comment.EncodedValue = propertyValue; } break; case PropertyType.RecurrenceRule: RRuleProperty rr = new RRuleProperty(); rr.DeserializeParameters(parameters); rr.EncodedValue = propertyValue; obsRule.RecurrenceRules.Add(rr); break; case PropertyType.RecurDate: // There may be more than one date in the value. If so, split them into separate ones. This // makes it easier to manage. They'll get written back out as individual properties but // that's okay. parts = propertyValue.Split(',', ';'); // It's important that we retain the same parameters for each one parms = new string[parameters.Count]; parameters.CopyTo(parms, 0); foreach(string s in parts) { sc = new StringCollection(); sc.AddRange(parms); RDateProperty rd = new RDateProperty(); rd.DeserializeParameters(sc); rd.EncodedValue = s; obsRule.RecurDates.Add(rd); } break; case PropertyType.TimeZoneName: TimeZoneNameProperty tzn = new TimeZoneNameProperty(); tzn.DeserializeParameters(parameters); tzn.EncodedValue = propertyValue; obsRule.TimeZoneNames.Add(tzn); break; default: // Anything else is a custom property CustomProperty cust = new CustomProperty(propertyName); cust.DeserializeParameters(parameters); cust.EncodedValue = propertyValue; obsRule.CustomProperties.Add(cust); break; } }
/// <summary> /// This is implemented to handle properties related to VFreeBusy items /// </summary> /// <param name="propertyName">The name of the property.</param> /// <param name="parameters">A string collection containing the parameters and their values. If empty, /// there are no parameters.</param> /// <param name="propertyValue">The value of the property.</param> protected virtual void VFreeBusyParser(string propertyName, StringCollection parameters, string propertyValue) { StringCollection sc; string[] parts, parms; int idx; // The last entry is always CustomProperty so scan for length minus one for(idx = 0; idx < ntvFreeBusy.Length - 1; idx++) if(ntvFreeBusy[idx].IsMatch(propertyName)) break; // An opening BEGIN:VFREEBUSY property must have been seen if(vFreeBusy == null) throw new PDIParserException(this.LineNumber, LR.GetString("ExParseNoBeginProp", "BEGIN:VFREEBUSY", propertyName)); // Handle or create the property switch(ntvFreeBusy[idx].EnumValue) { case PropertyType.Begin: // Handle unknown nested objects priorState.Push(currentState); currentState = VCalendarParserState.Custom; CustomObjectParser(propertyName, parameters, propertyValue); break; case PropertyType.End: // For this, the value must be VFREEBUSY if(String.Compare(propertyValue.Trim(), "VFREEBUSY", StringComparison.OrdinalIgnoreCase) != 0) throw new PDIParserException(this.LineNumber, LR.GetString("ExParseUnrecognizedTagValue", ntvFreeBusy[idx].Name, propertyValue)); // The free/busy item is added to the collection when created so we don't have to rely on an // END tag to add it. vFreeBusy = null; currentState = priorState.Pop(); break; case PropertyType.Url: vFreeBusy.Url.DeserializeParameters(parameters); vFreeBusy.Url.EncodedValue = propertyValue; break; case PropertyType.UniqueId: vFreeBusy.UniqueId.EncodedValue = propertyValue; break; case PropertyType.StartDateTime: vFreeBusy.StartDateTime.DeserializeParameters(parameters); vFreeBusy.StartDateTime.EncodedValue = propertyValue; break; case PropertyType.EndDateTime: vFreeBusy.EndDateTime.DeserializeParameters(parameters); vFreeBusy.EndDateTime.EncodedValue = propertyValue; break; case PropertyType.Duration: vFreeBusy.Duration.DeserializeParameters(parameters); vFreeBusy.Duration.EncodedValue = propertyValue; break; case PropertyType.TimeStamp: vFreeBusy.TimeStamp.DeserializeParameters(parameters); vFreeBusy.TimeStamp.EncodedValue = propertyValue; break; case PropertyType.Comment: // If this is seen more than once, just add the new stuff to the existing property if(vFreeBusy.Comment.Value != null) { vFreeBusy.Comment.EncodedValue += "\r\n"; vFreeBusy.Comment.EncodedValue += propertyValue; } else { vFreeBusy.Comment.DeserializeParameters(parameters); vFreeBusy.Comment.EncodedValue = propertyValue; } break; case PropertyType.Contact: vFreeBusy.Contact.DeserializeParameters(parameters); vFreeBusy.Contact.EncodedValue = propertyValue; break; case PropertyType.Organizer: vFreeBusy.Organizer.DeserializeParameters(parameters); vFreeBusy.Organizer.EncodedValue = propertyValue; break; case PropertyType.Attendee: AttendeeProperty ap = new AttendeeProperty(); ap.DeserializeParameters(parameters); ap.EncodedValue = propertyValue; vFreeBusy.Attendees.Add(ap); break; case PropertyType.RequestStatus: RequestStatusProperty rs = new RequestStatusProperty(); rs.DeserializeParameters(parameters); rs.EncodedValue = propertyValue; vFreeBusy.RequestStatuses.Add(rs); break; case PropertyType.FreeBusy: // There may be more than one period in the value. If so, split them into separate ones. // This makes it easier to manage. They'll get written back out as individual properties but // that's okay. parts = propertyValue.Split(',', ';'); // It's important that we retain the same parameters for each one parms = new string[parameters.Count]; parameters.CopyTo(parms, 0); foreach(string s in parts) { sc = new StringCollection(); sc.AddRange(parms); FreeBusyProperty fb = new FreeBusyProperty(); fb.DeserializeParameters(sc); fb.EncodedValue = s; vFreeBusy.FreeBusy.Add(fb); } break; default: // Anything else is a custom property CustomProperty cust = new CustomProperty(propertyName); cust.DeserializeParameters(parameters); cust.EncodedValue = propertyValue; vFreeBusy.CustomProperties.Add(cust); break; } }
/// <summary> /// This is implemented to handle properties related to VAlarm items /// </summary> /// <param name="propertyName">The name of the property.</param> /// <param name="parameters">A string collection containing the parameters and their values. If empty, /// there are no parameters.</param> /// <param name="propertyValue">The value of the property.</param> protected virtual void VAlarmParser(string propertyName, StringCollection parameters, string propertyValue) { int idx; // The last entry is always CustomProperty so scan for length minus one for(idx = 0; idx < ntvAlarm.Length - 1; idx++) if(ntvAlarm[idx].IsMatch(propertyName)) break; // An opening BEGIN:VALARM property must have been seen if(vAlarm == null) throw new PDIParserException(this.LineNumber, LR.GetString("ExParseNoBeginProp", "BEGIN:VALARM", propertyName)); // Handle or create the property switch(ntvAlarm[idx].EnumValue) { case PropertyType.Begin: // Handle unknown nested objects priorState.Push(currentState); currentState = VCalendarParserState.Custom; CustomObjectParser(propertyName, parameters, propertyValue); break; case PropertyType.End: // For this, the value must be VALARM if(String.Compare(propertyValue.Trim(), "VALARM", StringComparison.OrdinalIgnoreCase) != 0) throw new PDIParserException(this.LineNumber, LR.GetString("ExParseUnrecognizedTagValue", ntvAlarm[idx].Name, propertyValue)); // The alarm is added to the collection when created so we don't have to rely on an END tag // to add it. vAlarm = null; currentState = priorState.Pop(); break; case PropertyType.Action: vAlarm.Action.DeserializeParameters(parameters); vAlarm.Action.EncodedValue = propertyValue; break; case PropertyType.Trigger: vAlarm.Trigger.DeserializeParameters(parameters); vAlarm.Trigger.EncodedValue = propertyValue; break; case PropertyType.Repeat: vAlarm.Repeat.DeserializeParameters(parameters); vAlarm.Repeat.EncodedValue = propertyValue; break; case PropertyType.Duration: vAlarm.Duration.DeserializeParameters(parameters); vAlarm.Duration.EncodedValue = propertyValue; break; case PropertyType.Summary: vAlarm.Summary.DeserializeParameters(parameters); vAlarm.Summary.EncodedValue = propertyValue; break; case PropertyType.Description: vAlarm.Description.DeserializeParameters(parameters); vAlarm.Description.EncodedValue = propertyValue; break; case PropertyType.Attendee: AttendeeProperty ap = new AttendeeProperty(); ap.DeserializeParameters(parameters); ap.EncodedValue = propertyValue; vAlarm.Attendees.Add(ap); break; case PropertyType.Attachment: AttachProperty att = new AttachProperty(); att.DeserializeParameters(parameters); att.EncodedValue = propertyValue; vAlarm.Attachments.Add(att); break; default: // Anything else is a custom property CustomProperty cust = new CustomProperty(propertyName); cust.DeserializeParameters(parameters); cust.EncodedValue = propertyValue; vAlarm.CustomProperties.Add(cust); break; } }
/// <summary> /// This is implemented to handle properties related to VTimeZone items /// </summary> /// <param name="propertyName">The name of the property.</param> /// <param name="parameters">A string collection containing the parameters and their values. If empty, /// there are no parameters.</param> /// <param name="propertyValue">The value of the property.</param> protected virtual void VTimeZoneParser(string propertyName, StringCollection parameters, string propertyValue) { int idx; // The last entry is always CustomProperty so scan for length minus one for(idx = 0; idx < ntvTimeZone.Length - 1; idx++) if(ntvTimeZone[idx].IsMatch(propertyName)) break; // An opening BEGIN:VTIMEZONE property must have been seen if(vTimeZone == null) throw new PDIParserException(this.LineNumber, LR.GetString("ExParseNoBeginProp", "BEGIN:VTIMEZONE", propertyName)); // Handle or create the property switch(ntvTimeZone[idx].EnumValue) { case PropertyType.Begin: // Handle nested objects priorState.Push(currentState); // Is it a STANDARD or DAYLIGHT property? if(String.Compare(propertyValue.Trim(), "STANDARD", StringComparison.OrdinalIgnoreCase) == 0) { obsRule = new ObservanceRule(ObservanceRuleType.Standard); vTimeZone.ObservanceRules.Add(obsRule); currentState = VCalendarParserState.ObservanceRule; } else if(String.Compare(propertyValue.Trim(), "DAYLIGHT", StringComparison.OrdinalIgnoreCase) == 0) { obsRule = new ObservanceRule(ObservanceRuleType.Daylight); vTimeZone.ObservanceRules.Add(obsRule); currentState = VCalendarParserState.ObservanceRule; } else { // Unknown/custom object currentState = VCalendarParserState.Custom; CustomObjectParser(propertyName, parameters, propertyValue); } break; case PropertyType.End: // For this, the value must be VTIMEZONE if(String.Compare(propertyValue.Trim(), "VTIMEZONE", StringComparison.OrdinalIgnoreCase) != 0) throw new PDIParserException(this.LineNumber, LR.GetString("ExParseUnrecognizedTagValue", ntvTimeZone[idx].Name, propertyValue)); // Unlike other objects, we do rely on the end tag to add the time zone object to the // collection as they are shared amongst all instances. VCalendar.TimeZones.Merge(vTimeZone); vTimeZone = null; currentState = priorState.Pop(); break; case PropertyType.TimeZoneId: vTimeZone.TimeZoneId.EncodedValue = propertyValue; break; case PropertyType.TimeZoneUrl: vTimeZone.TimeZoneUrl.EncodedValue = propertyValue; break; case PropertyType.LastModified: vTimeZone.LastModified.DeserializeParameters(parameters); vTimeZone.LastModified.EncodedValue = propertyValue; break; default: // Anything else is a custom property CustomProperty cust = new CustomProperty(propertyName); cust.DeserializeParameters(parameters); cust.EncodedValue = propertyValue; vTimeZone.CustomProperties.Add(cust); break; } }