package org.limewire.core.impl.friend;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.Collections;
import java.util.Set;
import org.apache.http.auth.Credentials;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.limewire.friend.api.FriendPresence;
import org.limewire.friend.api.feature.AuthTokenFeature;
import org.limewire.friend.impl.address.FriendAddress;
import org.limewire.friend.impl.address.FriendAddressResolver;
import org.limewire.io.Address;
import org.limewire.io.GUID;
import org.limewire.net.address.AddressFactory;
import org.limewire.security.SecureMessage.Status;
import org.limewire.util.Objects;
import org.limewire.util.StringUtils;
import com.limegroup.gnutella.RemoteFileDesc;
import com.limegroup.gnutella.URN;
import com.limegroup.gnutella.UrnSet;
import com.limegroup.gnutella.downloader.serial.RemoteHostMemento;
import com.limegroup.gnutella.http.HTTPConstants;
import com.limegroup.gnutella.xml.LimeXMLDocument;
public class FriendRemoteFileDesc implements RemoteFileDesc {
private final FriendAddress address;
static final String TYPE = "XMPPRFD";
private final long index;
private final String filename;
private final long size;
private final byte[] clientGUID;
private final int speed;
private final int quality;
private final LimeXMLDocument xmlDoc;
private final Set<URN> urns;
private final String vendor;
private final long createTime;
private final AddressFactory addressFactory;
private boolean http11;
private final FriendAddressResolver addressResolver;
private int hashCode = -1;
public FriendRemoteFileDesc(FriendAddress address, long index, String filename,
long size, byte[] clientGUID, int speed, int quality, LimeXMLDocument xmlDoc, Set<? extends URN> urns,
String vendor, long createTime, boolean http11,
AddressFactory addressFactory, FriendAddressResolver addressResolver) {
this.address = address;
this.index = index;
this.filename = filename;
this.size = size;
this.clientGUID = Objects.nonNull(clientGUID, "clientGUID");
this.speed = speed;
this.quality = quality;
this.xmlDoc = xmlDoc;
this.urns = Collections.unmodifiableSet(urns);
this.vendor = vendor;
this.createTime = createTime;
this.http11 = http11;
this.addressResolver = addressResolver;
this.addressFactory = addressFactory;
}
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof FriendRemoteFileDesc)) {
return false;
}
FriendRemoteFileDesc other = (FriendRemoteFileDesc)obj;
if (!Arrays.equals(clientGUID, other.clientGUID)) {
return false;
}
if (!address.equals(other.address)) {
return false;
}
if (size != other.size) {
return false;
}
if (!urns.equals(other.urns)) {
return false;
}
return true;
}
@Override
public int hashCode() {
int h = hashCode;
if (h == -1) {
h = address.hashCode();
h = 31 * h + (int)size;
h = 31 * h + new GUID(clientGUID).hashCode();
h = 31 * h + urns.hashCode();
hashCode = h;
}
return h;
}
@Override
public Address getAddress() {
return address;
}
@Override
public Credentials getCredentials() {
FriendPresence presence = addressResolver.getPresence(address);
if (presence == null) {
return null;
}
// TODO change auth token to type string
AuthTokenFeature authTokenFeature = (AuthTokenFeature)presence.getFeature(AuthTokenFeature.ID);
if(authTokenFeature == null) {
return null;
}
return new UsernamePasswordCredentials(presence.getFriend().getNetwork().getCanonicalizedLocalID(), StringUtils.toUTF8String(authTokenFeature.getFeature().getToken()));
}
@Override
public Status getSecureStatus() {
return Status.INSECURE;
}
@Override
public float getSpamRating() {
return 0.0f;
}
@Override
public String getUrlPath() {
URN sha1Urn = getSHA1Urn();
FriendPresence presence = addressResolver.getPresence(address);
if (presence == null) {
// race condition, friend is already offline, just return a possibly invalid path
// download will fail elsewhere
return HTTPConstants.URI_RES_N2R + sha1Urn.httpStringValue();
}
try {
return CoreGlueFriendService.FRIEND_DOWNLOAD_PREFIX + URLEncoder.encode(presence.getFriend().getNetwork().getCanonicalizedLocalID(), "UTF-8") + HTTPConstants.URI_RES_N2R + sha1Urn.httpStringValue();
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
@Override
public boolean isAltLocCapable() {
return false;
}
@Override
public boolean isFromAlternateLocation() {
return false;
}
@Override
public boolean isMe(byte[] myClientGUID) {
return Arrays.equals(clientGUID, myClientGUID);
}
@Override
public boolean isSpam() {
return false;
}
@Override
public void setSecureStatus(Status secureStatus) {
}
@Override
public void setSpamRating(float rating) {
}
@Override
public RemoteHostMemento toMemento() {
return new RemoteHostMemento(address, filename, index, clientGUID, speed, size, quality, isReplyToMulticast(), getXml(), urns, isBrowseHostEnabled(), vendor, http11, TYPE, addressFactory);
}
private String getXml() {
return xmlDoc != null ? xmlDoc.getXMLString() : null;
}
@Override
public long getCreationTime() {
return createTime;
}
@Override
public String getFileName() {
return filename;
}
@Override
public long getIndex() {
return index;
}
@Override
public URN getSHA1Urn() {
URN sha1Urn = UrnSet.getSha1(urns);
if (sha1Urn == null) {
throw new IllegalArgumentException(urns + " should have sha1");
}
return sha1Urn;
}
@Override
public long getSize() {
return size;
}
@Override
public Set<URN> getUrns() {
return urns;
}
@Override
public LimeXMLDocument getXMLDocument() {
return xmlDoc;
}
@Override
public byte[] getClientGUID() {
return clientGUID;
}
@Override
public int getQuality() {
return quality;
}
@Override
public int getSpeed() {
return speed;
}
@Override
public String getVendor() {
return vendor;
}
@Override
public boolean isBrowseHostEnabled() {
return true;
}
@Override
public boolean isHTTP11() {
return http11;
}
@Override
public boolean isReplyToMulticast() {
return false;
}
@Override
public void setHTTP11(boolean http11) {
this.http11 = http11;
}
@Override
public String toString() {
return StringUtils.toString(this, filename, address);
}
}