+
+ // Error cases:
+ // - file not present neither in cache nor on server
+ // - remote < previous
+ if ((tsServer == -1 && tsOriginal == -1)
+ || (tsServer != -1 && tsOriginal != -1 && ((tsOriginal - tsServer) > GRACE_TIME))) {
+ throw new IOException(
+ "The timestamps between server and client are invalid");
+ }
+
+ // Check changes
+ boolean serverChanges = (tsServer - tsOriginal) > GRACE_TIME;
+ boolean localChanges = false;
+ Card original = null;
+ if (tsOriginal != -1) {
+ original = new Card(getCache(cacheDirOrig), Format.VCard21);
+ localChanges = !local.isEquals(original, true);
+ }
+
+ Command action = null;
+
+ // Sync to server if:
+ if (localChanges) {
+ action = Command.PUT_CARD;
+ }
+
+ // Sync from server if:
+ if (serverChanges) {
+ action = Command.HASH_CONTACT;
+ }
+
+ // Sync from/to server if
+ if (serverChanges && localChanges) {
+ action = Command.HELP;
+ }
+
+ // POST the whole file if:
+ if (tsServer == -1) {
+ action = Command.POST_CARD;
+ }
+
+ // GET the whole file if:
+ if (tsOriginal == -1) {
+ action = Command.GET_CARD;
+ }
+
+ System.err.println("remote: " + (tsServer / 1000) % 1000 + " ("
+ + tsServer + ")");
+ System.err.println("previous: " + (tsOriginal / 1000) % 1000 + " ("
+ + tsOriginal + ")");
+ System.err.println("local changes: " + localChanges);
+ System.err.println("server changes: " + serverChanges);
+ System.err.println("choosen action: " + action);
+
+ if (action != null) {
+ s.sendCommand(Command.SELECT, name);
+ if (tsServer != StringUtils.toTime(s.receiveLine())) {
+ System.err.println("DEBUG: it changed. retry.");
+ s.sendCommand(Command.SELECT);
+ s.close();
+ return sync(force);
+ }
+
+ switch (action) {
+ case GET_CARD: {
+ s.sendCommand(Command.GET_CARD);
+ List<String> data = s.receiveBlock();
+ setLastModified(data.remove(0));
+ Card server = new Card(Vcard21Parser.parseContact(data));
+ local.replaceListContent(server);
+
+ if (local.isDirty())
+ local.save();
+ local.saveAs(getCache(cacheDirOrig), Format.VCard21);
+ break;
+ }
+ case POST_CARD: {
+ s.sendCommand(Command.POST_CARD);
+ s.sendBlock(Vcard21Parser.toStrings(local));
+ local.saveAs(getCache(cacheDirOrig), Format.VCard21);
+ setLastModified(s.receiveLine());
+ break;
+ }
+ case PUT_CARD: {
+ String serverLastModifTime = updateToServer(s, original,
+ local);
+
+ local.saveAs(getCache(cacheDirOrig), Format.VCard21);
+
+ setLastModified(serverLastModifTime);
+ break;
+ }
+ case HASH_CONTACT: {
+ String serverLastModifTime = updateFromServer(s, local);
+
+ local.save();
+ local.saveAs(getCache(cacheDirOrig), Format.VCard21);
+
+ setLastModified(serverLastModifTime);
+ break;
+ }
+ case HELP: {
+ if (true)
+ throw new IOException("two-way sync not supported yet");
+
+ // note: we are holding the server here, so it could throw
+ // us away if we take too long
+
+ File mergeF = File.createTempFile("contact-merge", ".vcf");
+ File serverF = File
+ .createTempFile("contact-server", ".vcf");
+ original.saveAs(serverF, Format.VCard21);
+
+ Card server = new Card(serverF, Format.VCard21);
+ updateFromServer(s, server);
+
+ // TODO: auto merge into mergeF (from original, local,
+ // server)
+ local.saveAs(mergeF, Format.VCard21);
+ Card merge = new Card(mergeF, Format.VCard21);
+
+ // TODO: ask client if ok or to change it herself
+
+ String serverLastModifTime = updateToServer(s, original,
+ merge);
+
+ merge.saveAs(getCache(cacheDir), Format.VCard21);
+ merge.saveAs(getCache(cacheDirOrig), Format.VCard21);
+
+ setLastModified(serverLastModifTime);
+
+ local = merge;
+
+ break;
+ }
+ }
+
+ s.sendCommand(Command.SELECT);
+ }