summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/internal/transport/http/cookies-simple1.txt4
-rw-r--r--org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/internal/transport/http/cookies-simple2.txt4
-rw-r--r--org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/internal/transport/http/cookies-with-empty-and-comment-lines.txt4
-rw-r--r--org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/internal/transport/http/cookies-with-milliseconds.txt2
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/transport/http/NetscapeCookieFileTest.java109
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/transport/http/NetscapeCookieFile.java54
6 files changed, 90 insertions, 87 deletions
diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/internal/transport/http/cookies-simple1.txt b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/internal/transport/http/cookies-simple1.txt
index e06b38c712..527893acfd 100644
--- a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/internal/transport/http/cookies-simple1.txt
+++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/internal/transport/http/cookies-simple1.txt
@@ -1,2 +1,2 @@
-some-domain1 TRUE /some/path1 FALSE 1893499200000 key1 valueFromSimple1
-some-domain1 TRUE /some/path1 FALSE 1893499200000 key2 valueFromSimple1 \ No newline at end of file
+some-domain1 TRUE /some/path1 FALSE 1893499200 key1 valueFromSimple1
+some-domain1 TRUE /some/path1 FALSE 1893499200 key2 valueFromSimple1 \ No newline at end of file
diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/internal/transport/http/cookies-simple2.txt b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/internal/transport/http/cookies-simple2.txt
index 4bf6723fda..5ec0606271 100644
--- a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/internal/transport/http/cookies-simple2.txt
+++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/internal/transport/http/cookies-simple2.txt
@@ -1,2 +1,2 @@
-some-domain1 TRUE /some/path1 FALSE 1893499200000 key1 valueFromSimple2
-some-domain1 TRUE /some/path1 FALSE 1893499200000 key3 valueFromSimple2 \ No newline at end of file
+some-domain1 TRUE /some/path1 FALSE 1893499200 key1 valueFromSimple2
+some-domain1 TRUE /some/path1 FALSE 1893499200 key3 valueFromSimple2 \ No newline at end of file
diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/internal/transport/http/cookies-with-empty-and-comment-lines.txt b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/internal/transport/http/cookies-with-empty-and-comment-lines.txt
index a9b8a28153..573ee9ee10 100644
--- a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/internal/transport/http/cookies-with-empty-and-comment-lines.txt
+++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/internal/transport/http/cookies-with-empty-and-comment-lines.txt
@@ -3,6 +3,6 @@
some-domain1 TRUE /some/path1 FALSE 0 key1 value1
# expires date is 01/01/2030 @ 12:00am (UTC)
-#HttpOnly_.some-domain2 TRUE /some/path2 TRUE 1893499200000 key2 value2
+#HttpOnly_.some-domain2 TRUE /some/path2 TRUE 1893499200 key2 value2
-some-domain3 TRUE /some/path3 FALSE 1893499200000 key3 value3 \ No newline at end of file
+some-domain3 TRUE /some/path3 FALSE 1893499200 key3 value3 \ No newline at end of file
diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/internal/transport/http/cookies-with-milliseconds.txt b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/internal/transport/http/cookies-with-milliseconds.txt
new file mode 100644
index 0000000000..940e3b1a59
--- /dev/null
+++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/internal/transport/http/cookies-with-milliseconds.txt
@@ -0,0 +1,2 @@
+some-domain1 TRUE /some/path1 FALSE 1893499200000 key1 valueFromSimple1
+some-domain1 TRUE /some/path1 FALSE 1893499200 key2 valueFromSimple1 \ No newline at end of file
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/transport/http/NetscapeCookieFileTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/transport/http/NetscapeCookieFileTest.java
index 6c8c3ba61b..b11dd637f1 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/transport/http/NetscapeCookieFileTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/transport/http/NetscapeCookieFileTest.java
@@ -22,13 +22,13 @@ import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
+import java.time.Duration;
import java.time.Instant;
+import java.time.temporal.ChronoUnit;
import java.util.Arrays;
-import java.util.Date;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
-import java.util.regex.Pattern;
import org.eclipse.jgit.internal.storage.file.LockFile;
import org.eclipse.jgit.util.http.HttpCookiesMatcher;
@@ -48,10 +48,14 @@ public class NetscapeCookieFileTest {
private URL baseUrl;
/**
- * This is the expiration date that is used in the test cookie files
+ * This is the expiration date that is used in the test cookie files.
*/
- private static long JAN_01_2030_NOON = Instant
- .parse("2030-01-01T12:00:00.000Z").toEpochMilli();
+ private static final Instant TEST_EXPIRY_DATE = Instant
+ .parse("2030-01-01T12:00:00.000Z");
+
+ /** Earlier than TEST_EXPIRY_DATE. */
+ private static final Instant TEST_DATE = TEST_EXPIRY_DATE.minus(180,
+ ChronoUnit.DAYS);
@Before
public void setUp() throws IOException {
@@ -102,14 +106,13 @@ public class NetscapeCookieFileTest {
cookie.setPath("/");
cookie.setMaxAge(1000);
cookies.add(cookie);
- Date creationDate = new Date();
try (Writer writer = Files.newBufferedWriter(tmpFile,
StandardCharsets.US_ASCII)) {
- NetscapeCookieFile.write(writer, cookies, baseUrl, creationDate);
+ NetscapeCookieFile.write(writer, cookies, baseUrl, TEST_DATE);
}
String expectedExpiration = String
- .valueOf(creationDate.getTime() + (cookie.getMaxAge() * 1000));
+ .valueOf(TEST_DATE.getEpochSecond() + cookie.getMaxAge());
assertThat(Files.readAllLines(tmpFile, StandardCharsets.US_ASCII),
CoreMatchers
@@ -128,13 +131,12 @@ public class NetscapeCookieFileTest {
HttpCookie cookie = new HttpCookie("key2", "value2");
cookie.setMaxAge(1000);
cookies.add(cookie);
- Date creationDate = new Date();
try (Writer writer = Files.newBufferedWriter(tmpFile,
StandardCharsets.US_ASCII)) {
- NetscapeCookieFile.write(writer, cookies, baseUrl, creationDate);
+ NetscapeCookieFile.write(writer, cookies, baseUrl, TEST_DATE);
}
String expectedExpiration = String
- .valueOf(creationDate.getTime() + (cookie.getMaxAge() * 1000));
+ .valueOf(TEST_DATE.getEpochSecond() + cookie.getMaxAge());
assertThat(Files.readAllLines(tmpFile, StandardCharsets.US_ASCII),
CoreMatchers.equalTo(
@@ -161,13 +163,29 @@ public class NetscapeCookieFileTest {
}
@Test
+ public void testReadCookieFileWithMilliseconds() throws IOException {
+ try (InputStream input = this.getClass()
+ .getResourceAsStream("cookies-with-milliseconds.txt")) {
+ Files.copy(input, tmpFile, StandardCopyOption.REPLACE_EXISTING);
+ }
+ NetscapeCookieFile cookieFile = new NetscapeCookieFile(tmpFile,
+ TEST_DATE);
+ long expectedMaxAge = Duration.between(TEST_DATE, TEST_EXPIRY_DATE)
+ .getSeconds();
+ for (HttpCookie cookie : cookieFile.getCookies(true)) {
+ assertEquals(expectedMaxAge, cookie.getMaxAge());
+ }
+ }
+
+ @Test
public void testWriteAfterAnotherJgitProcessModifiedTheFile()
throws IOException, InterruptedException {
try (InputStream input = this.getClass()
.getResourceAsStream("cookies-simple1.txt")) {
Files.copy(input, tmpFile, StandardCopyOption.REPLACE_EXISTING);
}
- NetscapeCookieFile cookieFile = new NetscapeCookieFile(tmpFile);
+ NetscapeCookieFile cookieFile = new NetscapeCookieFile(tmpFile,
+ TEST_DATE);
cookieFile.getCookies(true);
// now modify file externally
try (InputStream input = this.getClass()
@@ -177,39 +195,19 @@ public class NetscapeCookieFileTest {
// now try to write
cookieFile.write(baseUrl);
- // validate that the external changes are there as well
- // due to rounding errors (conversion from ms to sec to ms)
- // the expiration date might not be exact
List<String> lines = Files.readAllLines(tmpFile,
StandardCharsets.US_ASCII);
assertEquals("Expected 3 lines", 3, lines.size());
- assertStringMatchesPatternWithInexactNumber(lines.get(0),
- "some-domain1\tTRUE\t/some/path1\tFALSE\t(\\d*)\tkey1\tvalueFromSimple2",
- JAN_01_2030_NOON, 1000);
- assertStringMatchesPatternWithInexactNumber(lines.get(1),
- "some-domain1\tTRUE\t/some/path1\tFALSE\t(\\d*)\tkey3\tvalueFromSimple2",
- JAN_01_2030_NOON, 1000);
- assertStringMatchesPatternWithInexactNumber(lines.get(2),
- "some-domain1\tTRUE\t/some/path1\tFALSE\t(\\d*)\tkey2\tvalueFromSimple1",
- JAN_01_2030_NOON, 1000);
- }
-
- @SuppressWarnings("boxing")
- private static final void assertStringMatchesPatternWithInexactNumber(
- String string, String pattern, long expectedNumericValue,
- long delta) {
- java.util.regex.Matcher matcher = Pattern.compile(pattern)
- .matcher(string);
- assertTrue("Given string '" + string + "' does not match '" + pattern
- + "'", matcher.matches());
- // extract numeric value
- Long actualNumericValue = Long.decode(matcher.group(1));
-
- assertTrue(
- "Value is supposed to be close to " + expectedNumericValue
- + " but is " + actualNumericValue + ".",
- Math.abs(expectedNumericValue - actualNumericValue) <= delta);
+ assertEquals(
+ "some-domain1\tTRUE\t/some/path1\tFALSE\t1893499200\tkey1\tvalueFromSimple2",
+ lines.get(0));
+ assertEquals(
+ "some-domain1\tTRUE\t/some/path1\tFALSE\t1893499200\tkey3\tvalueFromSimple2",
+ lines.get(1));
+ assertEquals(
+ "some-domain1\tTRUE\t/some/path1\tFALSE\t1893499200\tkey2\tvalueFromSimple1",
+ lines.get(2));
}
@Test
@@ -229,14 +227,13 @@ public class NetscapeCookieFileTest {
cookie.setHttpOnly(true);
cookies.add(cookie);
- Date creationDate = new Date();
-
try (Writer writer = Files.newBufferedWriter(tmpFile,
StandardCharsets.US_ASCII)) {
- NetscapeCookieFile.write(writer, cookies, baseUrl, creationDate);
+ NetscapeCookieFile.write(writer, cookies, baseUrl, TEST_DATE);
}
Set<HttpCookie> actualCookies = new NetscapeCookieFile(tmpFile,
- creationDate).getCookies(true);
+ TEST_DATE)
+ .getCookies(true);
assertThat(actualCookies, HttpCookiesMatcher.containsInOrder(cookies));
}
@@ -246,15 +243,12 @@ public class NetscapeCookieFileTest {
.getResourceAsStream("cookies-simple1.txt")) {
Files.copy(input, tmpFile, StandardCopyOption.REPLACE_EXISTING);
}
- // round up to the next second (to prevent rounding errors)
- Date creationDate = new Date(
- (System.currentTimeMillis() / 1000) * 1000);
- Set<HttpCookie> cookies = new NetscapeCookieFile(tmpFile, creationDate)
+ Set<HttpCookie> cookies = new NetscapeCookieFile(tmpFile, TEST_DATE)
.getCookies(true);
Path tmpFile2 = folder.newFile().toPath();
try (Writer writer = Files.newBufferedWriter(tmpFile2,
StandardCharsets.US_ASCII)) {
- NetscapeCookieFile.write(writer, cookies, baseUrl, creationDate);
+ NetscapeCookieFile.write(writer, cookies, baseUrl, TEST_DATE);
}
// compare original file with newly written one, they should not differ
assertEquals(Files.readAllLines(tmpFile), Files.readAllLines(tmpFile2));
@@ -267,13 +261,13 @@ public class NetscapeCookieFileTest {
Files.copy(input, tmpFile, StandardCopyOption.REPLACE_EXISTING);
}
- Date creationDate = new Date();
Set<HttpCookie> cookies = new LinkedHashSet<>();
HttpCookie cookie = new HttpCookie("key2", "value2");
cookie.setDomain("some-domain2");
cookie.setPath("/some/path2");
- cookie.setMaxAge((JAN_01_2030_NOON - creationDate.getTime()) / 1000);
+ cookie.setMaxAge(
+ Duration.between(TEST_DATE, TEST_EXPIRY_DATE).getSeconds());
cookie.setSecure(true);
cookie.setHttpOnly(true);
cookies.add(cookie);
@@ -281,11 +275,12 @@ public class NetscapeCookieFileTest {
cookie = new HttpCookie("key3", "value3");
cookie.setDomain("some-domain3");
cookie.setPath("/some/path3");
- cookie.setMaxAge((JAN_01_2030_NOON - creationDate.getTime()) / 1000);
+ cookie.setMaxAge(
+ Duration.between(TEST_DATE, TEST_EXPIRY_DATE).getSeconds());
cookies.add(cookie);
- Set<HttpCookie> actualCookies = new NetscapeCookieFile(tmpFile, creationDate)
- .getCookies(true);
+ Set<HttpCookie> actualCookies = new NetscapeCookieFile(tmpFile,
+ TEST_DATE).getCookies(true);
assertThat(actualCookies, HttpCookiesMatcher.containsInOrder(cookies));
}
@@ -296,7 +291,7 @@ public class NetscapeCookieFileTest {
Files.copy(input, tmpFile, StandardCopyOption.REPLACE_EXISTING);
}
- new NetscapeCookieFile(tmpFile)
- .getCookies(true);
+ assertTrue(new NetscapeCookieFile(tmpFile, TEST_DATE).getCookies(true)
+ .isEmpty());
}
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/transport/http/NetscapeCookieFile.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/transport/http/NetscapeCookieFile.java
index 49f26c7885..dae7173059 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/transport/http/NetscapeCookieFile.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/transport/http/NetscapeCookieFile.java
@@ -22,11 +22,12 @@ import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.text.MessageFormat;
+import java.time.Instant;
import java.util.Arrays;
import java.util.Collection;
-import java.util.Date;
import java.util.LinkedHashSet;
import java.util.Set;
+import java.util.concurrent.TimeUnit;
import org.eclipse.jgit.annotations.NonNull;
import org.eclipse.jgit.annotations.Nullable;
@@ -53,6 +54,7 @@ import org.slf4j.LoggerFactory;
* In general this class is not thread-safe. So any consumer needs to take care
* of synchronization!
*
+ * @see <a href="https://curl.se/docs/http-cookies.html">Cookie file format</a>
* @see <a href="http://www.cookiecentral.com/faq/#3.5">Netscape Cookie File
* Format</a>
* @see <a href=
@@ -92,7 +94,7 @@ public final class NetscapeCookieFile {
private byte[] hash;
- final Date creationDate;
+ private final Instant createdAt;
private Set<HttpCookie> cookies = null;
@@ -104,13 +106,13 @@ public final class NetscapeCookieFile {
* where to find the cookie file
*/
public NetscapeCookieFile(Path path) {
- this(path, new Date());
+ this(path, Instant.now());
}
- NetscapeCookieFile(Path path, Date creationDate) {
+ NetscapeCookieFile(Path path, Instant createdAt) {
this.path = path;
this.snapshot = FileSnapshot.DIRTY;
- this.creationDate = creationDate;
+ this.createdAt = createdAt;
}
/**
@@ -142,7 +144,7 @@ public final class NetscapeCookieFile {
if (cookies == null || refresh) {
try {
byte[] in = getFileContentIfModified();
- Set<HttpCookie> newCookies = parseCookieFile(in, creationDate);
+ Set<HttpCookie> newCookies = parseCookieFile(in, createdAt);
if (cookies != null) {
cookies = mergeCookies(newCookies, cookies);
} else {
@@ -168,9 +170,9 @@ public final class NetscapeCookieFile {
*
* @param input
* the file content to parse
- * @param creationDate
- * the date for the creation of the cookies (used to calculate
- * the maxAge based on the expiration date given within the file)
+ * @param createdAt
+ * cookie creation time; used to calculate the maxAge based on
+ * the expiration date given within the file
* @return the set of parsed cookies from the given file (even expired
* ones). If there is more than one cookie with the same name in
* this file the last one overwrites the first one!
@@ -180,7 +182,7 @@ public final class NetscapeCookieFile {
* if the given file does not have a proper format
*/
private static Set<HttpCookie> parseCookieFile(@NonNull byte[] input,
- @NonNull Date creationDate)
+ @NonNull Instant createdAt)
throws IOException, IllegalArgumentException {
String decoded = RawParseUtils.decode(StandardCharsets.US_ASCII, input);
@@ -190,7 +192,7 @@ public final class NetscapeCookieFile {
new StringReader(decoded))) {
String line;
while ((line = reader.readLine()) != null) {
- HttpCookie cookie = parseLine(line, creationDate);
+ HttpCookie cookie = parseLine(line, createdAt);
if (cookie != null) {
cookies.add(cookie);
}
@@ -200,7 +202,7 @@ public final class NetscapeCookieFile {
}
private static HttpCookie parseLine(@NonNull String line,
- @NonNull Date creationDate) {
+ @NonNull Instant createdAt) {
if (line.isEmpty() || (line.startsWith("#") //$NON-NLS-1$
&& !line.startsWith(HTTP_ONLY_PREAMBLE))) {
return null;
@@ -236,7 +238,12 @@ public final class NetscapeCookieFile {
cookie.setSecure(Boolean.parseBoolean(cookieLineParts[3]));
long expires = Long.parseLong(cookieLineParts[4]);
- long maxAge = (expires - creationDate.getTime()) / 1000;
+ // Older versions stored milliseconds. This heuristic to detect that
+ // will cause trouble in the year 33658. :-)
+ if (cookieLineParts[4].length() == 13) {
+ expires = TimeUnit.MILLISECONDS.toSeconds(expires);
+ }
+ long maxAge = expires - createdAt.getEpochSecond();
if (maxAge <= 0) {
return null; // skip expired cookies
}
@@ -245,7 +252,7 @@ public final class NetscapeCookieFile {
}
/**
- * Read the underying file and return its content but only in case it has
+ * Read the underlying file and return its content but only in case it has
* been modified since the last access.
* <p>
* Internally calculates the hash and maintains {@link FileSnapshot}s to
@@ -333,7 +340,7 @@ public final class NetscapeCookieFile {
path);
// reread new changes if necessary
Set<HttpCookie> cookiesFromFile = NetscapeCookieFile
- .parseCookieFile(cookieFileContent, creationDate);
+ .parseCookieFile(cookieFileContent, createdAt);
this.cookies = mergeCookies(cookiesFromFile, cookies);
}
} catch (FileNotFoundException e) {
@@ -343,7 +350,7 @@ public final class NetscapeCookieFile {
ByteArrayOutputStream output = new ByteArrayOutputStream();
try (Writer writer = new OutputStreamWriter(output,
StandardCharsets.US_ASCII)) {
- write(writer, cookies, url, creationDate);
+ write(writer, cookies, url, createdAt);
}
LockFile lockFile = new LockFile(path.toFile());
for (int retryCount = 0; retryCount < LOCK_ACQUIRE_MAX_RETRY_COUNT; retryCount++) {
@@ -377,24 +384,23 @@ public final class NetscapeCookieFile {
* @param url
* the url for which to write the cookie (to derive the default
* values for certain cookie attributes)
- * @param creationDate
- * the date when the cookie has been created. Important for
- * calculation the cookie expiration time (calculated from
- * cookie's maxAge and this creation time)
+ * @param createdAt
+ * cookie creation time; used to calculate a cookie's expiration
+ * time
* @throws IOException
* if an I/O error occurs
*/
static void write(@NonNull Writer writer,
@NonNull Collection<HttpCookie> cookies, @NonNull URL url,
- @NonNull Date creationDate) throws IOException {
+ @NonNull Instant createdAt) throws IOException {
for (HttpCookie cookie : cookies) {
- writeCookie(writer, cookie, url, creationDate);
+ writeCookie(writer, cookie, url, createdAt);
}
}
private static void writeCookie(@NonNull Writer writer,
@NonNull HttpCookie cookie, @NonNull URL url,
- @NonNull Date creationDate) throws IOException {
+ @NonNull Instant createdAt) throws IOException {
if (cookie.getMaxAge() <= 0) {
return; // skip expired cookies
}
@@ -422,7 +428,7 @@ public final class NetscapeCookieFile {
final String expirationDate;
// whenCreated field is not accessible in HttpCookie
expirationDate = String
- .valueOf(creationDate.getTime() + (cookie.getMaxAge() * 1000));
+ .valueOf(createdAt.getEpochSecond() + cookie.getMaxAge());
writer.write(expirationDate);
writer.write(COLUMN_SEPARATOR);
writer.write(cookie.getName());