fix(mail): escape mail data placed in attributes of a compiled part

the generic attribute writer used for these two spots does not escape what it
writes, so a value taken from the message ends the attribute and starts a new
one. both are inside a part that is compiled, which is where an injected
handler runs.

* the organizer link took inEvent.organizer.email verbatim. a value such as
  mailto:x@y" onpointerover="... produced a live handler on the anchor, and an
  entity encoded scheme such as javascript: reached the href, where the
  browser decodes it. the href is now built as mailto: plus the parsed address
  and escaped as an attribute value.

* the attachment name paragraph of the image and the link viewer took
  filenameForDisplay verbatim. a quote inside an RFC 2231 encoded filename
  ended the title attribute. the writer escapes & < > there but not the quote,
  so the accessor drops the quote instead of escaping it, which keeps a plain
  filename such as A&B.pdf unchanged in the tooltip.

the img title of the image viewer is left alone: attributes of that element are
escaped by the framework already.
This commit is contained in:
Jan Kahmen
2026-08-17 23:48:41 +02:00
parent 8813677ecb
commit 045a0b9c0a
7 changed files with 26 additions and 4 deletions
@@ -46,6 +46,7 @@
- (BOOL) isEndDateOnSameDay;
- (BOOL) hasLocation;
- (NSString *)location;
- (NSString *) organizerHref;
- (NSString *) userComment;
- (NSString *) eventDescription;
@@ -418,6 +418,18 @@
return YES;
}
- (NSString *) organizerHref
{
NSString *address;
address = [[[self inEvent] organizer] rfc822Email];
if (![address length])
return nil;
return [[NSString stringWithFormat: @"mailto:%@", address]
stringByEscapingHTMLAttributeValue];
}
- (NSString *) organizerDisplayName
{
iCalPerson *organizer;
+1
View File
@@ -86,6 +86,7 @@
- (NSString *)preferredPathExtension;
- (NSString *)filename;
- (NSString *)filenameForDisplay;
- (NSString *)filenameForTitle;
- (NSFormatter *)sizeFormatter;
/* caches */
+8
View File
@@ -340,6 +340,14 @@
: (id)@"untitled";
}
- (NSString *) filenameForTitle
{
/* the generic attribute writer escapes & but not the quote, so a quote in the
filename would end the title attribute and start a new one */
return [[self filenameForDisplay] stringByReplacingOccurrencesOfString: @"\""
withString: @""];
}
- (NSFormatter *) sizeFormatter
{
return [UIxMailSizeFormatter sharedMailSizeFormatter];
@@ -137,7 +137,7 @@
<p>
<var:string label:value="Organizer" />
<a ng-non-bindable="" var:href="inEvent.organizer.email"
<a ng-non-bindable="" var:href="organizerHref"
><var:string value="organizerDisplayName" /></a>
<var:string label:value="request_info" />
</p>
@@ -147,7 +147,7 @@
<var:if condition="isLoggedInUserAnAttendee" const:negate="YES">
<p>
<var:string label:value="Organizer" />
<a ng-non-bindable="" var:href="inEvent.organizer.email">
<a ng-non-bindable="" var:href="organizerHref">
<var:string value="organizerDisplayName" />
</a>
<var:string label:value="request_info_no_attendee" />
@@ -10,7 +10,7 @@
<img var:src="pathToAttachment"
var:title="filenameForDisplay"><!-- image --></img>
<md-card-content>
<p class="md-caption" var:title="filenameForDisplay">
<p class="md-caption" var:title="filenameForTitle">
<var:string value="filenameForDisplay" />
</p>
</md-card-content>
@@ -6,7 +6,7 @@
xmlns:label="OGo:label">
<md-card>
<md-card-content>
<p class="md-caption sg-attachment-name" var:title="filenameForDisplay">
<p class="md-caption sg-attachment-name" var:title="filenameForTitle">
<var:if condition="preferredPathExtension.length"><span class="sg-label-outline"><var:string value="preferredPathExtension"/></span></var:if>
<var:string value="filenameForDisplay"/>
</p>