/* * Copyright 2016 Brian Pellin. * * This file is part of KeePassDroid. * * KeePassDroid 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 2 of the License, or * (at your option) any later version. * * KeePassDroid 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 KeePassDroid. If not, see <http://www.gnu.org/licenses/>. * */ package com.keepassdroid.utils; import android.content.Context; import android.database.Cursor; import android.net.Uri; import com.keepassdroid.compat.StorageAF; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.InputStream; /** * Created by bpellin on 3/5/16. */ public class UriUtil { public static Uri parseDefaultFile(String text) { if (EmptyUtils.isNullOrEmpty(text)) { return null; } Uri uri = Uri.parse(text); if (EmptyUtils.isNullOrEmpty(uri.getScheme())) { uri = uri.buildUpon().scheme("file").authority("").build(); } return uri; } public static Uri parseDefaultFile(Uri uri) { if (EmptyUtils.isNullOrEmpty(uri.getScheme())) { uri = uri.buildUpon().scheme("file").authority("").build(); } return uri; } public static boolean equalsDefaultfile(Uri left, String right) { left = parseDefaultFile(left); Uri uriRight = parseDefaultFile(right); return left.equals(uriRight); } public static InputStream getUriInputStream(Context ctx, Uri uri) throws FileNotFoundException { if (uri == null) return null; String scheme = uri.getScheme(); if (EmptyUtils.isNullOrEmpty(scheme) || scheme.equals("file")) { return new FileInputStream(uri.getPath()); } else if (scheme.equals("content")) { return ctx.getContentResolver().openInputStream(uri); } else { return null; } } /** * Many android apps respond with non-writeable content URIs that correspond to files. * This will attempt to translate the content URIs to file URIs when possible/appropriate * @param uri * @return */ public static Uri translate(Context ctx, Uri uri) { // StorageAF provides nice URIs if (StorageAF.useStorageFramework(ctx) || hasWritableContentUri(uri)) { return uri; } String scheme = uri.getScheme(); if (EmptyUtils.isNullOrEmpty(scheme)) { return uri; } String filepath = null; try { // Use content resolver to try and find the file if (scheme.equalsIgnoreCase("content")) { Cursor cursor = ctx.getContentResolver().query(uri, new String[]{android.provider.MediaStore.Images.ImageColumns.DATA}, null, null, null); cursor.moveToFirst(); if (cursor != null) { filepath = cursor.getString(0); cursor.close(); if (!isValidFilePath(filepath)) { filepath = null; } } } // Try using the URI path as a straight file if (EmptyUtils.isNullOrEmpty(filepath)) { filepath = uri.getEncodedPath(); if (!isValidFilePath(filepath)) { filepath = null; } } } // Fall back to URI if this fails. catch (Exception e) { filepath = null; } // Update the file to a file URI if (!EmptyUtils.isNullOrEmpty(filepath)) { Uri.Builder b = new Uri.Builder(); uri = b.scheme("file").authority("").path(filepath).build(); } return uri; } private static boolean isValidFilePath(String filepath) { if (EmptyUtils.isNullOrEmpty(filepath)) { return false; } File file = new File(filepath); return file.exists() && file.canRead(); } /** * Whitelist for known content providers that support writing * @param uri * @return */ private static boolean hasWritableContentUri(Uri uri) { String scheme = uri.getScheme(); if (EmptyUtils.isNullOrEmpty(scheme)) { return false; } if (!scheme.equalsIgnoreCase("content")) { return false; } switch (uri.getAuthority()) { case "com.google.android.apps.docs.storage": return true; } return false; } }