package org.gcube.keycloak.oidc.avatar.importer.libravatar; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.util.Map; import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.io.IOUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.base.Preconditions; public class Libravatar { protected static final Logger logger = LoggerFactory.getLogger(Libravatar.class); private String email; private LibravatarOptions options = new LibravatarOptions().withoutHttps(); private Libravatar(final String email) { Preconditions.checkNotNull(email).toLowerCase(); this.email = email; } /** * Construct new libravatar downloader for the provided email * @param email the email address * @return the new libravatar downloader instance */ public static Libravatar from(String email) { return new Libravatar(email); } /** * Adds he options to be used for download * @param options the libravatar options * @return */ public Libravatar withOptions(LibravatarOptions options) { this.options = options; return this; } /*** * Performs the avatar download by searching for a domain specific server and then on the libravatar public service * @return the avatar's byte array * @throws LibravatarException if no default has been set in options ({@link LibravatarOptions#defaultingTo(LibravatarDefaultImage)}) and the image hasn't found on remote server */ public byte[] downloadArray() throws LibravatarException { try (InputStream is = download()) { return IOUtils.toByteArray(is); } catch (IOException e) { throw new LibravatarException("Cannot download image byte's array for email: " + email, e); } } /*** * Performs the avatar download by searching for a domain specific server and then on the libravatar public service * @return the avatar byte array * @throws LibravatarException if no default has been set in options ({@link LibravatarOptions#defaultingTo(LibravatarDefaultImage)}) and the image hasn't found on remote server * */ public InputStream download() throws LibravatarException { try { return getURL().openStream(); } catch (IOException e) { throw new LibravatarException("Cannot open image stream for email: " + email, e); } } /** * Construct the URL to be used for the download * @return the URL to use * @throws MalformedURLException */ private URL getURL() throws MalformedURLException { logger.debug("Constructing download URL for email: {}", email); logger.debug("Getting the DNS queries domain first"); String baseTarget = options.isUseHttps() ? DNSUtil.resolveSecureSRVRecordFromEmail(email) : DNSUtil.resolveSRVRecordFromEmail(email); if (baseTarget != null) { logger.debug("Building URL with the DNS queried domain"); return buildURL(baseTarget); } else { logger.debug("Defaulting to the liravatar URL"); return buildURL(options.isUseHttps() ? LibravatarOptions.getSecureBaseUri() : LibravatarOptions.getBaseUri()); } } /** * Builds the URL with query string to be used starting from the provided base URL * @param baseURL the base url to be used * @return the complete URL ready to be called * @throws MalformedURLException */ private URL buildURL(String baseURL) throws MalformedURLException { StringBuilder sb = new StringBuilder(baseURL); String hash = options.isUseSHA256() ? DigestUtils.sha256Hex(email.getBytes()) : DigestUtils.md5Hex(email.getBytes()); logger.trace("Computed hash is: {}", hash); sb.append(hash); Map parametersMap = options.toParametersMap(); String queryString = parametersMap.entrySet().stream().map(p -> p.getKey() + "=" + p.getValue()) .reduce((p1, p2) -> p1 + "&" + p2).orElse(""); if (queryString != null && !"".equals(queryString)) { sb.append("?"); sb.append(queryString); } String url = sb.toString(); logger.trace("Resulting URL string is: {}", url); return new URL(url); } }