package org.wikimedia.wikipedia;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.util.Base64;
import android.view.View;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * Contains utility methods that Java doesn't have because we can't make code look too good, can we?
 */
public class Utils {
    /**
     * Compares two strings properly, even when one of them is null - without throwing up
     *
     * @param str1 The first string
     * @param str2 Guess?
     * @return true if they are both equal (even if both are null)
     */
    public static boolean compareStrings(String str1, String str2) {
        return (str1 == null ? str2 == null : str1.equals(str2));
    }

    /**
     * Crossfades two views, one of which is assumed to be currently visible
     * @param curView The view that is currently visible
     * @param newView The new view that should be faded in
     */
    public static void crossFade(final View curView, final View newView) {
        newView.setAlpha(0f);
        newView.setVisibility(View.VISIBLE);
        newView.animate()
                .alpha(1.0f)
                .setDuration(WikipediaApp.MEDIUM_ANIMATION_DURATION)
                .setListener(null);

        curView.animate()
                .alpha(0f)
                .setDuration(WikipediaApp.MEDIUM_ANIMATION_DURATION)
                .setListener(new AnimatorListenerAdapter() {
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        curView.setVisibility(View.GONE);
                        curView.setAlpha(1.0f);
                    }
                });
    }

    /**
     * Creates an MD5 hash of the provided string & returns its base64 representation
     * @param s String to hash
     * @return Base64'd MD5 representation of the string passed in
     */
    public static final String md5(final String s) {
        try {
            // Create MD5 Hash
            MessageDigest digest = java.security.MessageDigest
                    .getInstance("MD5");
            digest.update(s.getBytes("utf-8"));
            byte messageDigest[] = digest.digest();

            return Base64.encodeToString(messageDigest, Base64.URL_SAFE | Base64.NO_WRAP);
        } catch (NoSuchAlgorithmException e) {
            // This will never happen, yes.
            throw new RuntimeException(e);
        } catch (UnsupportedEncodingException e) {
            // This will never happen, yes.
            throw new RuntimeException(e);
        }
    }

    /**
     * Returns the local file name for a remote image.
     *
     * Warning: Should be kept stable between releases.
     * @param url URL of the thumbnail image. Expects them in Mediawiki format
     * @return
     */
    public static final String imageUrlToFileName(String url) {
        String[] urlParts = url.split("/");
        return "saved-image-" + urlParts[urlParts.length - 1];
    }
}
@@ -2867,27 +2867,56 @@
 hem 
-in Mediawiki format
+to be not protocol relative & have an extension.
 %0A   
@@ -3016,18 +3016,23 @@
 tring%5B%5D 
-ur
+protoco
 lParts =
@@ -3043,16 +3043,18 @@
 .split(%22
+:/
 /%22);%0A   
@@ -3083,22 +3083,52 @@
 ge-%22
- + urlParts%5Bur
+%0A                + md5(protocolParts%5Bprotoco
 lPar
@@ -3141,16 +3141,17 @@
 gth - 1%5D
+)
 ;%0A    %7D%0A

Use md5 for generating image save URLs