Files
calendar-lite/test/org/gingercal/BridgeTest.java
T
2026-10-15 16:35:05 +02:00

100 lines
4.4 KiB
Java

package org.gingercal;
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.List;
import java.util.UUID;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLParameters;
import javax.net.ssl.TrustManager;
import org.gingercal.Model.Cal;
/** Talks to the legacy bridge the way Android 2.3 does: TLS 1.0, AES128-SHA, pinned cert. */
public class BridgeTest {
static int fails;
static void check(boolean ok, String what) {
System.out.println((ok ? " ok " : " FAIL ") + what);
if (!ok) fails++;
}
static class GingerbreadHttp implements Http {
final Tls.PinTrust trust;
final HttpClient c;
GingerbreadHttp(String pin) throws Exception {
trust = new Tls.PinTrust(pin);
SSLContext ctx = SSLContext.getInstance("TLSv1");
ctx.init(null, new TrustManager[] {trust}, null);
SSLParameters p = new SSLParameters(new String[] {"TLS_RSA_WITH_AES_128_CBC_SHA"}, new String[] {"TLSv1"});
c = HttpClient.newBuilder().sslContext(ctx).sslParameters(p).build();
}
public Resp exec(String method, String url, String[] h, String body, String ct) throws IOException {
HttpRequest.Builder b = HttpRequest.newBuilder(URI.create(url)).method(method,
body == null ? HttpRequest.BodyPublishers.noBody() : HttpRequest.BodyPublishers.ofString(body));
for (int i = 0; i + 1 < h.length; i += 2) b.header(h[i], h[i + 1]);
if (ct != null) b.header("Content-Type", ct);
trust.reset();
try {
HttpResponse<String> r = c.send(b.build(), HttpResponse.BodyHandlers.ofString());
Resp o = new Resp();
o.code = r.statusCode();
o.body = r.body();
o.etag = r.headers().firstValue("ETag").orElse(null);
o.location = r.headers().firstValue("Location").orElse(null);
return o;
} catch (IOException e) {
throw trust.translate(e);
} catch (InterruptedException e) {
throw new IOException(e);
}
}
public void close() {}
}
public static void main(String[] a) throws Exception {
String url = "https://127.0.0.1:8443";
String expected = a[0];
// 1. first contact: not trusted -> app shows fingerprint
try {
new Dav(new GingerbreadHttp(""), url, "xose", "secret").calendarHome();
check(false, "untrusted cert reported");
} catch (DavException.UntrustedCert u) {
check(u.fingerprint.equals(expected) && !u.pinMismatch, "untrusted cert reported with fingerprint " + u.fingerprint.substring(0, 11) + "...");
}
// 2. wrong pin -> mismatch warning
try {
new Dav(new GingerbreadHttp(expected.replace('1', '2')), url, "xose", "secret").calendarHome();
check(false, "pin mismatch reported");
} catch (DavException.UntrustedCert u) {
check(u.pinMismatch, "pin mismatch reported");
}
// 3. pinned: full flow through the bridge
Dav dav = new Dav(new GingerbreadHttp(expected), url, "xose", "secret");
String home = dav.calendarHome();
check(home.equals(url + "/remote.php/dav/xose/"), "discovered home via bridge: " + home);
List<Cal> cals = dav.calendars(home);
check(cals.size() == 2, "calendars via bridge: " + cals.size());
CoreTest.MemStore st = new CoreTest.MemStore();
Syncer.Result r = Syncer.sync(dav, st, System.currentTimeMillis(), 1, 60, false);
check(r.events > 0, "sync via bridge: " + r.summary());
String uid = UUID.randomUUID().toString();
long s = ICal.startOfDay(System.currentTimeMillis()) + 2 * ICal.DAY + 9 * ICal.HOUR;
Cal w = cals.get(0);
dav.create(w.href, uid, ICal.newEvent(uid, "Via bridge", "", "", s, s + ICal.HOUR, false, 10));
String[] got = dav.get(w.href + uid + ".ics");
check(ICal.parse(got[0]).get(0).summary.equals("Via bridge"), "create+get via bridge");
dav.delete(w.href + uid + ".ics", got[1]);
check(true, "delete via bridge");
System.out.println(fails == 0 ? "ALL PASSED" : fails + " FAILED");
System.exit(fails == 0 ? 0 : 1);
}
}