PersonIdent: Strip some special chars from external strings

The special characters <> and '\n' interfere with parsing of
identities. C git strips these special characters, so we should too.

Rather than allocating extra strings by calling String#trim(), add a
few lines to our sanitization method to perform the same trimming as
described in String's Javadoc.

Change-Id: I96edcb93a2fc194ee354d60566d352299742a52f
This commit is contained in:
Dave Borowitz 2016-04-29 11:10:36 -04:00
parent 773f9661d0
commit 125a8959d2
2 changed files with 76 additions and 6 deletions

View File

@ -89,14 +89,47 @@ public void nullForEmailShouldThrowIllegalArgumentException() {
@Test
public void testToExternalStringTrimsNameAndEmail() throws Exception {
PersonIdent personIdent = new PersonIdent(" A U Thor ",
" author@example.com ");
PersonIdent personIdent = new PersonIdent(" \u0010A U Thor ",
" author@example.com \u0009");
assertEquals(" A U Thor ", personIdent.getName());
assertEquals(" author@example.com ", personIdent.getEmailAddress());
assertEquals(" \u0010A U Thor ", personIdent.getName());
assertEquals(" author@example.com \u0009", personIdent.getEmailAddress());
String externalString = personIdent.toExternalString();
assertTrue(externalString.startsWith("A U Thor <author@example.com>"));
}
@Test
public void testToExternalStringTrimsAllWhitespace() {
String ws = " \u0001 \n ";
PersonIdent personIdent = new PersonIdent(ws, ws);
assertEquals(ws, personIdent.getName());
assertEquals(ws, personIdent.getEmailAddress());
String externalString = personIdent.toExternalString();
assertTrue(externalString.startsWith(" <>"));
}
@Test
public void testToExternalStringTrimsOtherBadCharacters() {
String name = " Foo\r\n<Bar> ";
String email = " Baz>\n\u1234<Quux ";
PersonIdent personIdent = new PersonIdent(name, email);
assertEquals(name, personIdent.getName());
assertEquals(email, personIdent.getEmailAddress());
String externalString = personIdent.toExternalString();
assertTrue(externalString.startsWith("Foo\rBar <Baz\u1234Quux>"));
}
@Test
public void testEmptyNameAndEmail() {
PersonIdent personIdent = new PersonIdent("", "");
assertEquals("", personIdent.getName());
assertEquals("", personIdent.getEmailAddress());
String externalString = personIdent.toExternalString();
assertTrue(externalString.startsWith(" <>"));
}
}

View File

@ -111,6 +111,43 @@ public static void appendTimezone(StringBuilder r, int offset) {
r.append(offsetMins);
}
/**
* Sanitize the given string for use in an identity and append to output.
* <p>
* Trims whitespace from both ends and special characters {@code \n < >} that
* interfere with parsing; appends all other characters to the output.
* Analogous to the C git function {@code strbuf_addstr_without_crud}.
*
* @param r
* string builder to append to.
* @param str
* input string.
*/
private static void appendSanitized(StringBuilder r, String str) {
// Trim any whitespace less than \u0020 as in String#trim().
int i = 0;
while (i < str.length() && str.charAt(i) <= ' ') {
i++;
}
int end = str.length();
while (end > i && str.charAt(end - 1) <= ' ') {
end--;
}
for (; i < end; i++) {
char c = str.charAt(i);
switch (c) {
case '\n':
case '<':
case '>':
continue;
default:
r.append(c);
break;
}
}
}
private final String name;
private final String emailAddress;
@ -305,9 +342,9 @@ && getEmailAddress().equals(p.getEmailAddress())
*/
public String toExternalString() {
final StringBuilder r = new StringBuilder();
r.append(getName().trim());
appendSanitized(r, getName());
r.append(" <"); //$NON-NLS-1$
r.append(getEmailAddress().trim());
appendSanitized(r, getEmailAddress());
r.append("> "); //$NON-NLS-1$
r.append(when / 1000);
r.append(' ');