Skip to content

Commit

Permalink
imp - Improved support for GEO in calendars
Browse files Browse the repository at this point in the history
---

We've improved parsing the GEO values.

---

Type: imp
Breaking: False
Doc Required: False
Backport Required: False
Part: 1/1
  • Loading branch information
AptiviCEO committed Oct 1, 2024
1 parent 96860e8 commit e67a952
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 77 deletions.
2 changes: 1 addition & 1 deletion VisualCard.Calendar/Parsers/VCalendarParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ public Parts.Calendar Parse()
// Handle the part type
Type calendarType = subPart is not null ? subPart.GetType() : calendar.GetType();
string valueType = VcardCommonTools.GetFirstValue(splitArgs, defaultValueType, VCalendarConstants._valueArgumentSpecifier);
string finalValue = VcardParserTools.ProcessStringValue(value, valueType);
string finalValue = VcardParserTools.ProcessStringValue(value, valueType, calendarVersion.Major == 1 ? ';' : ',');
switch (type)
{
case PartType.Strings:
Expand Down
4 changes: 2 additions & 2 deletions VisualCard.Calendar/Parts/Implementations/GeoInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,12 @@ internal static BaseCalendarPartInfo FromStringVcalendarStatic(string value, str
new GeoInfo().FromStringVcalendarInternal(value, finalArgs, elementTypes, valueType, calendarVersion);

internal override string ToStringVcalendarInternal(Version calendarVersion) =>
$"{Latitude}{(calendarVersion.Major == 1 ? ';' : ',')}{Longitude}";
$"{Latitude}{(calendarVersion.Major == 1 ? ',' : ';')}{Longitude}";

internal override BaseCalendarPartInfo FromStringVcalendarInternal(string value, string[] finalArgs, string[] elementTypes, string valueType, Version calendarVersion)
{
// Get the value
string[] _geoSplit = value.Split(calendarVersion.Major == 1 ? ';' : ',');
string[] _geoSplit = value.Split(calendarVersion.Major == 1 ? ',' : ';');
if (_geoSplit.Length != 2)
throw new ArgumentException($"When splitting geography, the split value is {_geoSplit.Length} instead of 2.");
if (!double.TryParse(_geoSplit[0], out double lat))
Expand Down
1 change: 1 addition & 0 deletions VisualCard.ShowCalendars/TestFiles/vevent.vcs
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,6 @@ DESCRIPTION:Networld+Interop Conference
Atlanta\, Georgia
POPULAR:True
X-TRENDING:True
GEO:37.24;-17.87
END:VEVENT
END:VCALENDAR
1 change: 1 addition & 0 deletions VisualCard.ShowCalendars/TestFiles/vevent1.vcs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ DTEND:19960401T083000Z
SUMMARY:Steve's Proposal Review
DESCRIPTION:Steve and John to review newest proposal material
CLASS:PRIVATE
GEO:37.24,-17.87
END:VEVENT
BEGIN:VTODO
SUMMARY:John to pay for lunch
Expand Down
153 changes: 79 additions & 74 deletions VisualCard/Parsers/VcardParserTools.cs
Original file line number Diff line number Diff line change
Expand Up @@ -252,85 +252,90 @@ internal static (PartType type, object enumeration, Type? enumType, Func<string,
_ => (PartType.PartsArray, PartsArrayEnum.IanaNames, typeof(ExtraInfo), ExtraInfo.FromStringVcardStatic, "", "", "", []),
};

internal static string ProcessStringValue(string value, string valueType)
internal static string ProcessStringValue(string value, string valueType, char split = ';')
{
// Now, handle each type individually
string finalValue;
finalValue = Regex.Unescape(value);
switch (valueType.ToUpper())
foreach (string finalValuePart in finalValue.Split(split))
{
case "URI":
case "URL":
// Check the URI
if (!Uri.TryCreate(finalValue, UriKind.Absolute, out Uri uri))
throw new InvalidDataException($"URL {finalValue} is invalid");
finalValue = uri is not null ? uri.ToString() : finalValue;
break;
case "UTC-OFFSET":
// Check the UTC offset
VcardCommonTools.ParseUtcOffset(finalValue);
break;
case "DATE":
// Check the date
if (!VcardCommonTools.TryParsePosixDate(finalValue, out _))
throw new InvalidDataException($"Date {finalValue} is invalid");
break;
case "TIME":
// Check the time
if (!VcardCommonTools.TryParsePosixTime(finalValue, out _))
throw new InvalidDataException($"Time {finalValue} is invalid");
break;
case "DATE-TIME":
// Check the date and time
if (!VcardCommonTools.TryParsePosixDateTime(finalValue, out _))
throw new InvalidDataException($"Date and time {finalValue} is invalid");
break;
case "DATE-AND-OR-TIME":
// Check the date and/or time
if (!VcardCommonTools.TryParsePosixDateTime(finalValue, out _) &&
!VcardCommonTools.TryParsePosixTime(finalValue, out _))
throw new InvalidDataException($"Date and/or time {finalValue} is invalid");
break;
case "TIMESTAMP":
// Check the timestamp
if (!VcardCommonTools.TryParsePosixTimestamp(finalValue, out _))
throw new InvalidDataException($"Timestamp {finalValue} is invalid");
break;
case "BOOLEAN":
// Check the boolean
if (!finalValue.Equals("true", StringComparison.OrdinalIgnoreCase) &&
!finalValue.Equals("false", StringComparison.OrdinalIgnoreCase))
throw new InvalidDataException($"Boolean {finalValue} is invalid");
break;
case "INTEGER":
// Check the integer
if (!int.TryParse(finalValue, out _))
throw new InvalidDataException($"Integer {finalValue} is invalid");
break;
case "FLOAT":
// Check the float
if (!double.TryParse(finalValue, out _))
throw new InvalidDataException($"Float {finalValue} is invalid");
break;
case "DURATION":
// Check the duration
VcardCommonTools.GetDurationSpan(finalValue);
break;
case "PERIOD":
// Check the period
VcardCommonTools.GetTimePeriod(finalValue);
break;
case "RECUR":
// Check the recursion rules
try
{
RecurrenceParser.ParseRuleV1(finalValue);
}
catch
{
RecurrenceParser.ParseRuleV2(finalValue);
}
break;
switch (valueType.ToUpper())
{
case "URI":
case "URL":
// Check the URI
if (!Uri.TryCreate(finalValue, UriKind.Absolute, out Uri uri))
throw new InvalidDataException($"URL {finalValue} is invalid");
finalValue = uri is not null ? uri.ToString() : finalValue;
break;
case "UTC-OFFSET":
// Check the UTC offset
VcardCommonTools.ParseUtcOffset(finalValue);
break;
case "DATE":
// Check the date
if (!VcardCommonTools.TryParsePosixDate(finalValue, out _))
throw new InvalidDataException($"Date {finalValue} is invalid");
break;
case "TIME":
// Check the time
if (!VcardCommonTools.TryParsePosixTime(finalValue, out _))
throw new InvalidDataException($"Time {finalValue} is invalid");
break;
case "DATE-TIME":
// Check the date and time
if (!VcardCommonTools.TryParsePosixDateTime(finalValue, out _))
throw new InvalidDataException($"Date and time {finalValue} is invalid");
break;
case "DATE-AND-OR-TIME":
// Check the date and/or time
if (!VcardCommonTools.TryParsePosixDateTime(finalValue, out _) &&
!VcardCommonTools.TryParsePosixTime(finalValue, out _))
throw new InvalidDataException($"Date and/or time {finalValue} is invalid");
break;
case "TIMESTAMP":
// Check the timestamp
if (!VcardCommonTools.TryParsePosixTimestamp(finalValue, out _))
throw new InvalidDataException($"Timestamp {finalValue} is invalid");
break;
case "BOOLEAN":
// Check the boolean
if (!finalValue.Equals("true", StringComparison.OrdinalIgnoreCase) &&
!finalValue.Equals("false", StringComparison.OrdinalIgnoreCase))
throw new InvalidDataException($"Boolean {finalValue} is invalid");
break;
case "INTEGER":
// Check the integer
if (!int.TryParse(finalValue, out _))
throw new InvalidDataException($"Integer {finalValue} is invalid");
break;
case "FLOAT":
// Check the float
string[] floatParts = finalValuePart.Split(split == ';' ? ',' : ';');
foreach (var floatPart in floatParts)
if (!double.TryParse(floatPart, out _))
throw new InvalidDataException($"Float {floatPart} in {finalValue} is invalid");
break;
case "DURATION":
// Check the duration
VcardCommonTools.GetDurationSpan(finalValue);
break;
case "PERIOD":
// Check the period
VcardCommonTools.GetTimePeriod(finalValue);
break;
case "RECUR":
// Check the recursion rules
try
{
RecurrenceParser.ParseRuleV1(finalValue);
}
catch
{
RecurrenceParser.ParseRuleV2(finalValue);
}
break;
}
}

// Return the result
Expand Down

0 comments on commit e67a952

Please sign in to comment.