/* * * * Copyright (C) 2014 Open Whisper Systems * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * / */ package org.anhonesteffort.flock.sync.addressbook; import org.anhonesteffort.flock.util.guava.Optional; import org.anhonesteffort.flock.sync.HidingDavCollectionMixin; import org.anhonesteffort.flock.webdav.WebDavConstants; import org.anhonesteffort.flock.webdav.carddav.CardDavConstants; import org.anhonesteffort.flock.crypto.MasterCipher; import org.anhonesteffort.flock.sync.HidingDavStore; import org.anhonesteffort.flock.crypto.HidingUtil; import org.anhonesteffort.flock.webdav.DavClient; import org.anhonesteffort.flock.webdav.PropertyParseException; import org.anhonesteffort.flock.webdav.carddav.CardDavCollection; import org.anhonesteffort.flock.webdav.carddav.CardDavStore; import org.apache.jackrabbit.webdav.DavException; import org.apache.jackrabbit.webdav.MultiStatus; import org.apache.jackrabbit.webdav.MultiStatusResponse; import org.apache.jackrabbit.webdav.client.methods.PropFindMethod; import org.apache.jackrabbit.webdav.property.DavPropertyName; import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; import org.apache.jackrabbit.webdav.property.DavPropertySet; import org.apache.jackrabbit.webdav.property.DefaultDavProperty; import java.io.IOException; import java.security.GeneralSecurityException; import java.util.LinkedList; import java.util.List; /** * Programmer: rhodey */ public class HidingCardDavStore implements HidingDavStore<HidingCardDavCollection> { private MasterCipher masterCipher; private CardDavStore cardDavStore; public HidingCardDavStore(MasterCipher masterCipher, String hostHREF, String username, String password, Optional<String> currentUserPrincipal, Optional<String> addressBookHomeSet) throws DavException, IOException { this.masterCipher = masterCipher; this.cardDavStore = new CardDavStore(hostHREF, username, password, currentUserPrincipal, addressBookHomeSet); } public HidingCardDavStore(MasterCipher masterCipher, DavClient client, Optional<String> currentUserPrincipal, Optional<String> addressBookHomeSet) { this.masterCipher = masterCipher; this.cardDavStore = new CardDavStore(client, currentUserPrincipal, addressBookHomeSet); } @Override public String getHostHREF() { return cardDavStore.getHostHREF(); } public Optional<String> getAddressbookHomeSet() throws PropertyParseException, DavException, IOException { return cardDavStore.getAddressbookHomeSet(); } @Override public Optional<HidingCardDavCollection> getCollection(String path) throws DavException, IOException { HidingCardDavCollection targetCollection = new HidingCardDavCollection(cardDavStore, path, masterCipher); DavPropertyNameSet collectionProps = targetCollection.getPropertyNamesForFetch(); PropFindMethod propFindMethod = new PropFindMethod(path, collectionProps, PropFindMethod.DEPTH_0); try { cardDavStore.getClient().execute(propFindMethod); MultiStatus multiStatus = propFindMethod.getResponseBodyAsMultiStatus(); MultiStatusResponse[] responses = multiStatus.getResponses(); List<CardDavCollection> returnedCollections = CardDavStore.getCollectionsFromMultiStatusResponses(cardDavStore, responses); if (returnedCollections.size() == 0) Optional.absent(); return Optional.of(new HidingCardDavCollection(returnedCollections.get(0), masterCipher)); } catch (DavException e) { if (e.getErrorCode() == WebDavConstants.SC_NOT_FOUND) return Optional.absent(); throw e; } finally { propFindMethod.releaseConnection(); } } @Override public List<HidingCardDavCollection> getCollections() throws PropertyParseException, DavException, IOException { Optional<String> addressbookHomeSetUri = getAddressbookHomeSet(); if (!addressbookHomeSetUri.isPresent()) throw new PropertyParseException("No addressbook-home-set property found for user.", getHostHREF(), CardDavConstants.PROPERTY_NAME_ADDRESSBOOK_HOME_SET); HidingCardDavCollection hack = new HidingCardDavCollection(cardDavStore, "hack", masterCipher); DavPropertyNameSet addressbookProps = hack.getPropertyNamesForFetch(); PropFindMethod method = new PropFindMethod(getHostHREF().concat(addressbookHomeSetUri.get()), addressbookProps, PropFindMethod.DEPTH_1); try { cardDavStore.getClient().execute(method); MultiStatus multiStatus = method.getResponseBodyAsMultiStatus(); MultiStatusResponse[] responses = multiStatus.getResponses(); List<HidingCardDavCollection> hidingCollections = new LinkedList<HidingCardDavCollection>(); List<CardDavCollection> collections = CardDavStore.getCollectionsFromMultiStatusResponses(cardDavStore, responses); for (CardDavCollection collection : collections) hidingCollections.add(new HidingCardDavCollection(collection, masterCipher)); return hidingCollections; } finally { method.releaseConnection(); } } @Override public void addCollection(String path) throws DavException, IOException, GeneralSecurityException { DavPropertySet properties = new DavPropertySet(); properties.add(new DefaultDavProperty<Object>(HidingDavCollectionMixin.PROPERTY_FLOCK_COLLECTION, "true")); cardDavStore.addCollection(path, properties); } public void addCollection(String path, String displayName) throws DavException, IOException, GeneralSecurityException { DavPropertySet properties = new DavPropertySet(); String hiddenDisplayName = HidingUtil.encryptEncodeAndPrefix(masterCipher, displayName); properties.add(new DefaultDavProperty<Object>(HidingDavCollectionMixin.PROPERTY_FLOCK_COLLECTION, "true")); properties.add(new DefaultDavProperty<String>(DavPropertyName.DISPLAYNAME, hiddenDisplayName)); cardDavStore.addCollection(path, properties); } @Override public void removeCollection(String path) throws DavException, IOException { cardDavStore.removeCollection(path); } @Override public void releaseConnections() { cardDavStore.closeHttpConnection(); } }