Skip to content

Commit

Permalink
add - Added whitespace support as specified
Browse files Browse the repository at this point in the history
---

You can now add whitespaces between properties and values as specified in line 654 of vcard-21.txt and line 793 of vcalendar-10.txt.

---

Type: add
Breaking: False
Doc Required: False
Backport Required: False
Part: 1/1
  • Loading branch information
AptiviCEO committed Oct 3, 2024
1 parent 608a56c commit d16dae3
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 29 deletions.
39 changes: 29 additions & 10 deletions VisualCard.Calendar/CalendarTools.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
using Textify.General;
using VisualCard.Calendar.Parsers;
using VisualCard.Parsers;
using VisualCard.Parsers.Arguments;

namespace VisualCard.Calendar
{
Expand Down Expand Up @@ -89,20 +90,39 @@ public static Parts.Calendar[] GetCalendars(StreamReader stream)

// Skip empty lines
CalendarLine = stream.ReadLine();

// Get the property info
string prefix = "";
string value;
try
{
var prop = new PropertyInfo(CalendarLine, new());
prefix = prop.Prefix;
value = prop.Value;
}
catch
{
value = CalendarLine;
}

// Process the line for begin, version, and end specifiers
if (string.IsNullOrEmpty(CalendarLine))
{
if (!stream.EndOfStream)
continue;
}
else if (!CalendarLine.EqualsNoCase(VCalendarConstants._beginText) &&
!CalendarLine.ToUpper().StartsWith(VcardConstants._versionSpecifier) &&
!CalendarLine.EqualsNoCase(VCalendarConstants._endText))
else if ((!prefix.EqualsNoCase(VcardConstants._beginSpecifier) &&
!prefix.EqualsNoCase(VcardConstants._versionSpecifier) &&
!prefix.EqualsNoCase(VcardConstants._endSpecifier)) ||
((prefix.EqualsNoCase(VcardConstants._beginSpecifier) ||
prefix.EqualsNoCase(VcardConstants._endSpecifier)) &&
!value.EqualsNoCase(VCalendarConstants._objectVCalendarSpecifier)))
append = true;
if (append)
lines.Add((lineNumber, CalendarLine));

// All vCalendars must begin with BEGIN:VCALENDAR
if (!CalendarLine.EqualsNoCase(VCalendarConstants._beginText) && !BeginSpotted)
if (!prefix.EqualsNoCase(VcardConstants._beginSpecifier) && !value.EqualsNoCase(VCalendarConstants._objectVCalendarSpecifier) && !BeginSpotted)
throw new InvalidDataException($"This is not a valid vCalendar file.");
else if (!BeginSpotted)
{
Expand All @@ -114,20 +134,19 @@ public static Parts.Calendar[] GetCalendars(StreamReader stream)

// Now that the beginning of the calendar tag is spotted, parse the version as we need to know how to select the appropriate parser.
// All vCalendars are required to have their own version directly after the BEGIN:VCALENDAR tag
if (CalendarLine.ToUpper().StartsWith(VcardConstants._versionSpecifier) &&
!CalendarLine.EqualsNoCase($"{VcardConstants._versionSpecifier}:1.0") &&
!CalendarLine.EqualsNoCase($"{VcardConstants._versionSpecifier}:2.0") &&
if (prefix.EqualsNoCase(VcardConstants._versionSpecifier) &&
!value.EqualsNoCase("1.0") && !value.EqualsNoCase("2.0") &&
!VersionSpotted)
throw new InvalidDataException($"This has an invalid vCalendar version {CalendarLine}.");
else if (!VersionSpotted && CalendarLine.ToUpper().StartsWith(VcardConstants._versionSpecifier))
else if (!VersionSpotted && prefix.EqualsNoCase(VcardConstants._versionSpecifier))
{
VersionSpotted = true;
CalendarVersion = new(CalendarLine.Substring(8));
CalendarVersion = new(value);
continue;
}

// If the ending tag is spotted, reset everything.
if (CalendarLine.EqualsNoCase(VCalendarConstants._endText) && !EndSpotted)
if (prefix.EqualsNoCase(VcardConstants._endSpecifier) && value.EqualsNoCase(VCalendarConstants._objectVCalendarSpecifier) && !EndSpotted)
{
EndSpotted = true;

Expand Down
48 changes: 31 additions & 17 deletions VisualCard/CardTools.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
using System;
using VisualCard.Parts;
using Textify.General;
using VisualCard.Parsers.Arguments;

namespace VisualCard
{
Expand Down Expand Up @@ -92,31 +93,46 @@ public static Card[] GetCards(StreamReader stream)

// Skip empty lines
CardLine = stream.ReadLine();

// Get the property info
string prefix = "";
string value;
try
{
var prop = new PropertyInfo(CardLine, new());
prefix = prop.Prefix;
value = prop.Value;
}
catch
{
value = CardLine;
}

// Process the line for begin, version, and end specifiers
if (string.IsNullOrEmpty(CardLine))
{
if (!stream.EndOfStream)
continue;
}
else if (!CardLine.EqualsNoCase(VcardConstants._beginText) &&
!CardLine.ToUpper().StartsWith(VcardConstants._versionSpecifier) &&
!CardLine.EqualsNoCase(VcardConstants._endText))
else if (!prefix.EqualsNoCase(VcardConstants._beginSpecifier) &&
!prefix.EqualsNoCase(VcardConstants._versionSpecifier) &&
!prefix.EqualsNoCase(VcardConstants._endSpecifier))
append = true;
else if (CardLine.EqualsNoCase(VcardConstants._beginText) && nested)
else if (prefix.EqualsNoCase(VcardConstants._beginSpecifier) && nested)
{
// We have a nested card!
StringBuilder nestedBuilder = new();
int nestLevel = 1;
nestedBuilder.AppendLine(CardLine);
while (!CardLine.EqualsNoCase(VcardConstants._endText))
while (!stream.EndOfStream && !prefix.EqualsNoCase(VcardConstants._endSpecifier) && !value.EqualsNoCase(VcardConstants._objectVCardSpecifier))
{
CardLine = stream.ReadLine();
nestedBuilder.AppendLine(CardLine);
if (CardLine.EqualsNoCase(VcardConstants._beginText))
if (prefix.EqualsNoCase(VcardConstants._beginSpecifier) && value.EqualsNoCase(VcardConstants._objectVCardSpecifier))
nestLevel++;
else if (CardLine.EqualsNoCase(VcardConstants._endText) && nestLevel > 1)
else if (prefix.EqualsNoCase(VcardConstants._endSpecifier) && value.EqualsNoCase(VcardConstants._objectVCardSpecifier) && nestLevel > 1)
{
nestLevel--;
CardLine = "";
continue;
}
}
Expand All @@ -130,7 +146,7 @@ public static Card[] GetCards(StreamReader stream)
lines.Add((lineNumber, CardLine));

// All VCards must begin with BEGIN:VCARD
if (!CardLine.EqualsNoCase(VcardConstants._beginText) && !BeginSpotted)
if (!prefix.EqualsNoCase(VcardConstants._beginSpecifier) && !value.EqualsNoCase(VcardConstants._objectVCardSpecifier) && !BeginSpotted)
throw new InvalidDataException($"This is not a valid VCard contact file.");
else if (!BeginSpotted)
{
Expand All @@ -145,17 +161,15 @@ public static Card[] GetCards(StreamReader stream)
// Now that the beginning of the card tag is spotted, parse the version as we need to know how to select the appropriate parser.
// vCard 4.0 and 5.0 cards are required to have their own version directly after the BEGIN:VCARD tag, but vCard 3.0 and 2.1 may
// or may not place VERSION directly after the BEGIN:VCARD tag.
if (CardLine.ToUpper().StartsWith(VcardConstants._versionSpecifier) &&
!CardLine.EqualsNoCase($"{VcardConstants._versionSpecifier}:2.1") &&
!CardLine.EqualsNoCase($"{VcardConstants._versionSpecifier}:3.0") &&
!CardLine.EqualsNoCase($"{VcardConstants._versionSpecifier}:4.0") &&
!CardLine.EqualsNoCase($"{VcardConstants._versionSpecifier}:5.0") &&
if (prefix.EqualsNoCase(VcardConstants._versionSpecifier) &&
!value.EqualsNoCase("2.1") && !value.EqualsNoCase("3.0") &&
!value.EqualsNoCase("4.0") && !value.EqualsNoCase("5.0") &&
!VersionSpotted)
throw new InvalidDataException($"This has an invalid VCard version {CardLine}.");
else if (!VersionSpotted && CardLine.ToUpper().StartsWith(VcardConstants._versionSpecifier))
else if (!VersionSpotted && prefix.EqualsNoCase(VcardConstants._versionSpecifier))
{
VersionSpotted = true;
CardVersion = new(CardLine.Substring(8));
CardVersion = new(value);

// Check to see if the vCard has VERSION directly after BEGIN:VCARD for 4.0 and 5.0
if (!versionDirect && (CardVersion.Major == 4 || CardVersion.Major == 5))
Expand All @@ -166,7 +180,7 @@ public static Card[] GetCards(StreamReader stream)
versionDirect = false;

// If the ending tag is spotted, reset everything.
if (CardLine.EqualsNoCase(VcardConstants._endText) && !EndSpotted)
if (prefix.EqualsNoCase(VcardConstants._endSpecifier) && value.EqualsNoCase(VcardConstants._objectVCardSpecifier) && !EndSpotted)
{
EndSpotted = true;
nested = false;
Expand Down
5 changes: 3 additions & 2 deletions VisualCard/Parsers/Arguments/PropertyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,9 @@ internal PropertyInfo(string line, Version version)
// Now, parse this value
if (!line.Contains($"{VcardConstants._argumentDelimiter}"))
throw new ArgumentException("The line must contain an argument delimiter.");
string value = line.Substring(line.IndexOf(VcardConstants._argumentDelimiter) + 1);
string prefixWithArgs = line.Substring(0, line.IndexOf(VcardConstants._argumentDelimiter));
line = line.Trim();
string value = line.Substring(line.IndexOf(VcardConstants._argumentDelimiter) + 1).Trim();
string prefixWithArgs = line.Substring(0, line.IndexOf(VcardConstants._argumentDelimiter)).Trim();
string prefix = (prefixWithArgs.Contains($"{VcardConstants._fieldDelimiter}") ? prefixWithArgs.Substring(0, prefixWithArgs.IndexOf($"{VcardConstants._fieldDelimiter}")) : prefixWithArgs).ToUpper();
string args = prefixWithArgs.Contains($"{VcardConstants._fieldDelimiter}") ? prefixWithArgs.Substring(prefix.Length + 1) : "";
string[] splitArgs = args.Split([VcardConstants._fieldDelimiter], StringSplitOptions.RemoveEmptyEntries);
Expand Down

0 comments on commit d16dae3

Please sign in to comment.