Skip to content

Commit b1eaf67

Browse files
committed
[bugfix] Only parameter values that contain special tokens need to be quoted
1 parent e1b25be commit b1eaf67

File tree

1 file changed

+37
-2
lines changed

1 file changed

+37
-2
lines changed

extensions/modules/mail/src/main/java/org/exist/xquery/modules/mail/SendEmailFunction.java

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
import java.net.InetAddress;
4949
import java.net.Socket;
5050
import java.util.*;
51+
import java.util.regex.Pattern;
5152

5253
/**
5354
* eXist Mail Module Extension SendEmailFunction
@@ -70,6 +71,11 @@ public class SendEmailFunction extends BasicFunction {
7071

7172
private final static int MIME_BASE64_MAX_LINE_LENGTH = 76; //RFC 2045, page 24
7273

74+
/**
75+
* Regular expression for checking for an RFC 2045 non-token.
76+
*/
77+
private static final Pattern NON_TOKEN_PATTERN = Pattern.compile("^.*[\\s\\p{Cntrl}()<>@,;:\\\"/\\[\\]?=].*$");
78+
7379
private String charset;
7480

7581
public final static FunctionSignature deprecated = new FunctionSignature(
@@ -568,10 +574,10 @@ private void writeMessage(final PrintWriter out, final Mail aMail, final boolean
568574
for (final Iterator<MailAttachment> itAttachment = aMail.attachmentIterator(); itAttachment.hasNext(); ) {
569575
final MailAttachment ma = itAttachment.next();
570576

571-
out.print("Content-Type: " + ma.getMimeType() + "; name=\"" + ma.getFilename() + "\"" + eol);
577+
out.print("Content-Type: " + ma.getMimeType() + "; name=" + parameterValue(ma.getFilename()) + eol);
572578
out.print("Content-Transfer-Encoding: base64" + eol);
573579
out.print("Content-Description: " + ma.getFilename() + eol);
574-
out.print("Content-Disposition: attachment; filename=\"" + ma.getFilename() + "\"" + eol);
580+
out.print("Content-Disposition: attachment; filename=" + parameterValue(ma.getFilename()) + eol);
575581
out.print(eol);
576582

577583

@@ -1330,4 +1336,33 @@ public Iterator<MailAttachment> attachmentIterator() {
13301336
private static boolean nonEmpty(@Nullable final String str) {
13311337
return str != null && !str.isEmpty();
13321338
}
1339+
1340+
/**
1341+
* Creates a "quoted-string" of the parameter value
1342+
* if it contains a non-token value (See {@link #isNonToken(String)}),
1343+
* otherwise it returns the parameter value as is.
1344+
*
1345+
* @param value parameter value.
1346+
*
1347+
* @return the quoted string parameter value, or the parameter value as is.
1348+
*/
1349+
private static String parameterValue(final String value) {
1350+
if (isNonToken(value)) {
1351+
return "\"" + value + "\"";
1352+
} else {
1353+
return value;
1354+
}
1355+
}
1356+
1357+
/**
1358+
* Determines if the string contains SPACE, CTLs, or `tspecial` (special token)
1359+
* according to <a href="https://www.rfc-editor.org/rfc/rfc2045#section-5">RFC 2045 - Section 5</a>.
1360+
*
1361+
* @param str the string to test
1362+
*
1363+
* @return true if the string contains a non-token, false otherwise.
1364+
*/
1365+
private static boolean isNonToken(final String str) {
1366+
return NON_TOKEN_PATTERN.matcher(str).matches();
1367+
}
13331368
}

0 commit comments

Comments
 (0)