Skip to content

Commit

Permalink
* Fixed #108
Browse files Browse the repository at this point in the history
  • Loading branch information
rgrashel committed Dec 4, 2023
1 parent 4c0ea76 commit f9f8231
Show file tree
Hide file tree
Showing 7 changed files with 140 additions and 60 deletions.
5 changes: 0 additions & 5 deletions examples/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,6 @@
<artifactId>jakarta.servlet.jsp.jstl</artifactId>
<version>3.0.1</version>
</dependency>
<dependency>
<groupId>jakarta.mail</groupId>
<artifactId>jakarta.mail-api</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
Expand Down
14 changes: 0 additions & 14 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -78,20 +78,6 @@
<version>1.1.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>jakarta.mail</groupId>
<artifactId>jakarta.mail-api</artifactId>
<version>2.1.2</version>
<scope>provided</scope>
<optional>true</optional>
<exclusions>
<exclusion>
<groupId>jakarta.activation</groupId>
<artifactId>jakarta.activation-api</artifactId>
</exclusion>
</exclusions>
</dependency>

<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
Expand Down
4 changes: 0 additions & 4 deletions stripes/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,6 @@
<version>5.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>jakarta.mail</groupId>
<artifactId>jakarta.mail-api</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,9 @@
*/
package net.sourceforge.stripes.validation;

import jakarta.mail.internet.AddressException;
import jakarta.mail.internet.InternetAddress;
import java.util.Collection;
import java.util.Locale;
import java.util.regex.Pattern;

/**
* A faux TypeConverter that validates that the String supplied is a valid email address. Relies on
Expand All @@ -42,6 +41,14 @@
* @since Stripes 1.2
*/
public class EmailTypeConverter implements TypeConverter<String> {

/**
* This RegEx is taken from the HTML5 <a
* href="https://html.spec.whatwg.org/multipage/input.html#valid-e-mail-address">spec</a>.
*/
private static final Pattern EMAIL_VALIDATION_REGEX =
Pattern.compile(
"[ \\a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[[\\[]a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[]a-zA-Z0-9])?)*");
/** Accepts the Locale provided, but does nothing with it since emails are Locale-less. */
public void setLocale(Locale locale) {
/** Doesn't matter for email. */
Expand All @@ -59,19 +66,31 @@ public void setLocale(Locale locale) {
public String convert(
String input, Class<? extends String> targetType, Collection<ValidationError> errors) {

String result = null;
// Used to test for more than one @ symbol
int atSymbolOccurrences = (input.length() - input.replace("@", "").length());

// Used to test for no dots after the last @ sign
boolean noDotsAfterLastAtSign =
input.contains("@") && !input.substring(input.lastIndexOf("@")).contains(".");

// Used to test for starts with a dot
boolean startsWithDot = input.split("@")[0].startsWith(".");

// Used to test for ends with a dot
boolean endsWithDot = input.split("@")[0].endsWith(".");

// Used to test for two consecutive dots
boolean twoConsecutiveDots = input.split("@")[0].contains("..");

try {
InternetAddress address = new InternetAddress(input, true);
result = address.getAddress();
if (!result.contains("@")) {
result = null;
throw new AddressException();
}
} catch (AddressException ae) {
if (atSymbolOccurrences > 1
|| noDotsAfterLastAtSign
|| startsWithDot
|| endsWithDot
|| twoConsecutiveDots
|| !EMAIL_VALIDATION_REGEX.matcher(input).matches()) {
errors.add(new ScopedLocalizableError("converter.email", "invalidEmail"));
}

return result;
return input;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@
*/
package net.sourceforge.stripes.action;

import jakarta.mail.internet.ContentDisposition;
import jakarta.mail.internet.ParseException;
import java.io.ByteArrayInputStream;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import net.sourceforge.stripes.mock.MockHttpServletResponse;
import org.apache.commons.fileupload2.core.ParameterParser;
import org.junit.Assert;
import org.junit.Test;

Expand All @@ -34,7 +34,7 @@ public void testContentDisposition() throws Exception {
}

private void doTestContentDisposition(boolean attachment, String filename) throws Exception {
byte[] data = UUID.randomUUID().toString().getBytes(Charset.forName("UTF-8"));
byte[] data = UUID.randomUUID().toString().getBytes(StandardCharsets.UTF_8);
ByteArrayInputStream is = new ByteArrayInputStream(data);

StreamingResolution resolution = new StreamingResolution("application/octet-stream", is);
Expand All @@ -48,32 +48,35 @@ private void doTestContentDisposition(boolean attachment, String filename) throw
resolution.stream(response);
Assert.assertArrayEquals(data, response.getOutputBytes());

ContentDisposition disposition = getContentDisposition(response);
// Use commons-fileupload to parse the Content-Disposition header
String disposition = null;
String cdAttachment = null;
String cdFilename = null;
final List<Object> list = response.getHeaderMap().get("Content-Disposition");
if (list != null && !list.isEmpty()) {
disposition = list.get(0).toString();
final ParameterParser parser = new ParameterParser();
parser.setLowerCaseNames(true);
final Map<String, String> params = parser.parse(disposition, ';');
cdAttachment = params.containsKey("attachment") ? "attachment" : null;
cdFilename = params.getOrDefault("filename", null);
}
if (attachment) {
Assert.assertNotNull(disposition);
Assert.assertEquals("attachment", cdAttachment);
if (filename == null) {
Assert.assertNotNull(disposition);
Assert.assertEquals("attachment", disposition.getDisposition());
Assert.assertNull(disposition.getParameter("filename"));
Assert.assertNull(cdFilename);
} else {
Assert.assertNotNull(disposition);
Assert.assertEquals("attachment", disposition.getDisposition());
Assert.assertNotNull(disposition.getParameter("filename"));
Assert.assertNotNull(cdFilename);
}
} else {
if (filename == null) {
Assert.assertNull(disposition);
} else {
Assert.assertNotNull(disposition);
Assert.assertEquals("attachment", disposition.getDisposition());
Assert.assertNotNull(disposition.getParameter("filename"));
Assert.assertEquals("attachment", cdAttachment);
Assert.assertNotNull(cdFilename);
}
}
}

private ContentDisposition getContentDisposition(MockHttpServletResponse response)
throws ParseException {
final List<Object> list = response.getHeaderMap().get("Content-Disposition");
if (list == null || list.isEmpty()) return null;
else return new ContentDisposition(list.get(0).toString());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package net.sourceforge.stripes.validation;

import java.util.ArrayList;
import java.util.List;
import org.junit.Assert;
import org.junit.Test;

/**
* Unit tests for the EmailTypeConverter class. Test email address cases taken from <a
* href="https://codefool.tumblr.com/post/15288874550/list-of-valid-and-invalid-email-addresses">here</a>.
*/
public class EmailTypeConverterTest {
@Test
public void validEmailTests() {
List<String> validEmailAddresses =
List.of(
"email@example.com",
"firstname.lastname@example.com",
"email@subdomain.example.com",
"firstname+lastname@example.com",
"email@123.123.123.123",
"email@[123.123.123.123]",
"\"email\"@example.com",
"johno'reilly@example.com",
"1234567890@example.com",
"email@example-one.com",
"_______@example.com",
"email@example.name",
"email@example.museum",
"email@example.co.jp",
"firstname-lastname@example.com",
"much.\"more\\ unusual\"@example.com"
// "very.unusual.\"@\".unusual.com@example.com", - Does not pass, and it should
// "very.\"(),:;<>[]\".VERY.\"very@\\\\\\ \"very\".unusual@strange.example.com" -- Does
// not pass and it should
);

for (String email : validEmailAddresses) {
TypeConverter<String> converter = new EmailTypeConverter();
List<ValidationError> errors = new ArrayList<>();
String result = converter.convert(email, String.class, errors);
Assert.assertEquals(result, email);
Assert.assertEquals(
"Valid email address check failed. Valid Email address was: " + email, 0, errors.size());
}
}

@Test
public void invalidEmailTests() {
List<String> invalidEmailAddresses =
List.of(
"plainaddress",
"#@%^%#$@#$@#.com",
"@example.com",
"Joe Smith <email@example.com>",
"email.example.com",
"email@example@example.com",
".email@example.com",
"email.@example.com",
"email..email@example.com",
"あいうえお@example.com",
"email@example.com (Joe Smith)",
"email@example",
"email@-example.com",
// "email@example.web", Should fail even though this is not strict to the old RFC which
// had limited TLDs.
// "email@111.222.333.44444", Should fail but ignoring because this is going overboard
"email@example..com",
"Abc..123@example.com"
// "\"(),:;<>[\\]@example.com", Should fail but ignoring because this is going overboard
// "just\"not\"right@example.com", Should fail but ignoring because this is going
// overboard
// "this\\ is\"really\"not\\\\allowed@example.com" Should fail but ignoring because this
// is going overboard
);

for (String email : invalidEmailAddresses) {
TypeConverter<String> converter = new EmailTypeConverter();
List<ValidationError> errors = new ArrayList<>();
String result = converter.convert(email, String.class, errors);
Assert.assertEquals(result, email);
Assert.assertEquals(
"Invalid email address check failed. Email address was: " + email, 1, errors.size());
}
}
}
5 changes: 0 additions & 5 deletions webtests/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,6 @@
<version>6.0.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>jakarta.mail</groupId>
<artifactId>jakarta.mail-api</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
Expand Down

0 comments on commit f9f8231

Please sign in to comment.