mirror of
https://github.com/moparisthebest/k-9
synced 2024-12-24 08:38:51 -05:00
Extract file related helper functions into separate class
This commit is contained in:
parent
e64ca84f1b
commit
34cfd8e5b4
165
src/com/fsck/k9/helper/FileHelper.java
Normal file
165
src/com/fsck/k9/helper/FileHelper.java
Normal file
@ -0,0 +1,165 @@
|
||||
package com.fsck.k9.helper;
|
||||
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.util.Locale;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.fsck.k9.K9;
|
||||
|
||||
|
||||
public class FileHelper {
|
||||
/**
|
||||
* Regular expression that represents characters we won't allow in file names.
|
||||
*
|
||||
* <p>
|
||||
* Allowed are:
|
||||
* <ul>
|
||||
* <li>word characters (letters, digits, and underscores): {@code \w}</li>
|
||||
* <li>spaces: {@code " "}</li>
|
||||
* <li>special characters: {@code !}, {@code #}, {@code $}, {@code %}, {@code &}, {@code '},
|
||||
* {@code (}, {@code )}, {@code -}, {@code @}, {@code ^}, {@code `}, <code>{</code>,
|
||||
* <code>}</code>, {@code ~}, {@code .}, {@code ,}</li>
|
||||
* </ul></p>
|
||||
*
|
||||
* @see #sanitizeFilename(String)
|
||||
*/
|
||||
private static final String INVALID_CHARACTERS = "[^\\w !#$%&'()\\-@\\^`{}~.,]+";
|
||||
|
||||
/**
|
||||
* Invalid characters in a file name are replaced by this character.
|
||||
*
|
||||
* @see #sanitizeFilename(String)
|
||||
*/
|
||||
private static final String REPLACEMENT_CHARACTER = "_";
|
||||
|
||||
|
||||
/**
|
||||
* Creates a unique file in the given directory by appending a hyphen
|
||||
* and a number to the given filename.
|
||||
*/
|
||||
public static File createUniqueFile(File directory, String filename) {
|
||||
File file = new File(directory, filename);
|
||||
if (!file.exists()) {
|
||||
return file;
|
||||
}
|
||||
// Get the extension of the file, if any.
|
||||
int index = filename.lastIndexOf('.');
|
||||
String format;
|
||||
if (index != -1) {
|
||||
String name = filename.substring(0, index);
|
||||
String extension = filename.substring(index);
|
||||
format = name + "-%d" + extension;
|
||||
} else {
|
||||
format = filename + "-%d";
|
||||
}
|
||||
for (int i = 2; i < Integer.MAX_VALUE; i++) {
|
||||
file = new File(directory, String.format(Locale.US, format, i));
|
||||
if (!file.exists()) {
|
||||
return file;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void touchFile(final File parentDir, final String name) {
|
||||
final File file = new File(parentDir, name);
|
||||
try {
|
||||
if (!file.exists()) {
|
||||
file.createNewFile();
|
||||
} else {
|
||||
file.setLastModified(System.currentTimeMillis());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.d(K9.LOG_TAG, "Unable to touch file: " + file.getAbsolutePath(), e);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean move(final File from, final File to) {
|
||||
if (to.exists()) {
|
||||
to.delete();
|
||||
}
|
||||
to.getParentFile().mkdirs();
|
||||
|
||||
try {
|
||||
FileInputStream in = new FileInputStream(from);
|
||||
try {
|
||||
FileOutputStream out = new FileOutputStream(to);
|
||||
try {
|
||||
byte[] buffer = new byte[1024];
|
||||
int count = -1;
|
||||
while ((count = in.read(buffer)) > 0) {
|
||||
out.write(buffer, 0, count);
|
||||
}
|
||||
} finally {
|
||||
out.close();
|
||||
}
|
||||
} finally {
|
||||
try { in.close(); } catch (Throwable ignore) {}
|
||||
}
|
||||
from.delete();
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
Log.w(K9.LOG_TAG, "cannot move " + from.getAbsolutePath() + " to " + to.getAbsolutePath(), e);
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void moveRecursive(final File fromDir, final File toDir) {
|
||||
if (!fromDir.exists()) {
|
||||
return;
|
||||
}
|
||||
if (!fromDir.isDirectory()) {
|
||||
if (toDir.exists()) {
|
||||
if (!toDir.delete()) {
|
||||
Log.w(K9.LOG_TAG, "cannot delete already existing file/directory " + toDir.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
if (!fromDir.renameTo(toDir)) {
|
||||
Log.w(K9.LOG_TAG, "cannot rename " + fromDir.getAbsolutePath() + " to " + toDir.getAbsolutePath() + " - moving instead");
|
||||
move(fromDir, toDir);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!toDir.exists() || !toDir.isDirectory()) {
|
||||
if (toDir.exists()) {
|
||||
toDir.delete();
|
||||
}
|
||||
if (!toDir.mkdirs()) {
|
||||
Log.w(K9.LOG_TAG, "cannot create directory " + toDir.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
File[] files = fromDir.listFiles();
|
||||
for (File file : files) {
|
||||
if (file.isDirectory()) {
|
||||
moveRecursive(file, new File(toDir, file.getName()));
|
||||
file.delete();
|
||||
} else {
|
||||
File target = new File(toDir, file.getName());
|
||||
if (!file.renameTo(target)) {
|
||||
Log.w(K9.LOG_TAG, "cannot rename " + file.getAbsolutePath() + " to " + target.getAbsolutePath() + " - moving instead");
|
||||
move(file, target);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!fromDir.delete()) {
|
||||
Log.w(K9.LOG_TAG, "cannot delete " + fromDir.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace characters we don't allow in file names with a replacement character.
|
||||
*
|
||||
* @param filename
|
||||
* The original file name.
|
||||
*
|
||||
* @return The sanitized file name containing only allowed characters.
|
||||
*/
|
||||
public static String sanitizeFilename(String filename) {
|
||||
return filename.replaceAll(INVALID_CHARACTERS, REPLACEMENT_CHARACTER);
|
||||
}
|
||||
}
|
@ -17,40 +17,13 @@ import android.widget.TextView;
|
||||
import com.fsck.k9.K9;
|
||||
import com.fsck.k9.mail.filter.Base64;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class Utility {
|
||||
/**
|
||||
* Regular expression that represents characters we won't allow in file names.
|
||||
*
|
||||
* <p>
|
||||
* Allowed are:
|
||||
* <ul>
|
||||
* <li>word characters (letters, digits, and underscores): {@code \w}</li>
|
||||
* <li>spaces: {@code " "}</li>
|
||||
* <li>special characters: {@code !}, {@code #}, {@code $}, {@code %}, {@code &}, {@code '},
|
||||
* {@code (}, {@code )}, {@code -}, {@code @}, {@code ^}, {@code `}, <code>{</code>,
|
||||
* <code>}</code>, {@code ~}, {@code .}, {@code ,}</li>
|
||||
* </ul></p>
|
||||
*
|
||||
* @see #sanitizeFilename(String)
|
||||
*/
|
||||
private static final String INVALID_CHARACTERS = "[^\\w !#$%&'()\\-@\\^`{}~.,]+";
|
||||
|
||||
/**
|
||||
* Invalid characters in a file name are replaced by this character.
|
||||
*
|
||||
* @see #sanitizeFilename(String)
|
||||
*/
|
||||
private static final String REPLACEMENT_CHARACTER = "_";
|
||||
|
||||
// \u00A0 (non-breaking space) happens to be used by French MUA
|
||||
|
||||
@ -454,139 +427,6 @@ public class Utility {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param parentDir
|
||||
* @param name
|
||||
* Never <code>null</code>.
|
||||
*/
|
||||
public static void touchFile(final File parentDir, final String name) {
|
||||
final File file = new File(parentDir, name);
|
||||
try {
|
||||
if (!file.exists()) {
|
||||
file.createNewFile();
|
||||
} else {
|
||||
file.setLastModified(System.currentTimeMillis());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.d(K9.LOG_TAG, "Unable to touch file: " + file.getAbsolutePath(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a unique file in the given directory by appending a hyphen
|
||||
* and a number to the given filename.
|
||||
*
|
||||
* @param directory
|
||||
* @param filename
|
||||
* @return
|
||||
*/
|
||||
public static File createUniqueFile(File directory, String filename) {
|
||||
File file = new File(directory, filename);
|
||||
if (!file.exists()) {
|
||||
return file;
|
||||
}
|
||||
// Get the extension of the file, if any.
|
||||
int index = filename.lastIndexOf('.');
|
||||
String format;
|
||||
if (index != -1) {
|
||||
String name = filename.substring(0, index);
|
||||
String extension = filename.substring(index);
|
||||
format = name + "-%d" + extension;
|
||||
} else {
|
||||
format = filename + "-%d";
|
||||
}
|
||||
for (int i = 2; i < Integer.MAX_VALUE; i++) {
|
||||
file = new File(directory, String.format(Locale.US, format, i));
|
||||
if (!file.exists()) {
|
||||
return file;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param from
|
||||
* @param to
|
||||
* @return
|
||||
*/
|
||||
public static boolean move(final File from, final File to) {
|
||||
if (to.exists()) {
|
||||
to.delete();
|
||||
}
|
||||
to.getParentFile().mkdirs();
|
||||
|
||||
try {
|
||||
FileInputStream in = new FileInputStream(from);
|
||||
try {
|
||||
FileOutputStream out = new FileOutputStream(to);
|
||||
try {
|
||||
byte[] buffer = new byte[1024];
|
||||
int count = -1;
|
||||
while ((count = in.read(buffer)) > 0) {
|
||||
out.write(buffer, 0, count);
|
||||
}
|
||||
} finally {
|
||||
out.close();
|
||||
}
|
||||
} finally {
|
||||
try { in.close(); } catch (Throwable ignore) {}
|
||||
}
|
||||
from.delete();
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
Log.w(K9.LOG_TAG, "cannot move " + from.getAbsolutePath() + " to " + to.getAbsolutePath(), e);
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param fromDir
|
||||
* @param toDir
|
||||
*/
|
||||
public static void moveRecursive(final File fromDir, final File toDir) {
|
||||
if (!fromDir.exists()) {
|
||||
return;
|
||||
}
|
||||
if (!fromDir.isDirectory()) {
|
||||
if (toDir.exists()) {
|
||||
if (!toDir.delete()) {
|
||||
Log.w(K9.LOG_TAG, "cannot delete already existing file/directory " + toDir.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
if (!fromDir.renameTo(toDir)) {
|
||||
Log.w(K9.LOG_TAG, "cannot rename " + fromDir.getAbsolutePath() + " to " + toDir.getAbsolutePath() + " - moving instead");
|
||||
move(fromDir, toDir);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!toDir.exists() || !toDir.isDirectory()) {
|
||||
if (toDir.exists()) {
|
||||
toDir.delete();
|
||||
}
|
||||
if (!toDir.mkdirs()) {
|
||||
Log.w(K9.LOG_TAG, "cannot create directory " + toDir.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
File[] files = fromDir.listFiles();
|
||||
for (File file : files) {
|
||||
if (file.isDirectory()) {
|
||||
moveRecursive(file, new File(toDir, file.getName()));
|
||||
file.delete();
|
||||
} else {
|
||||
File target = new File(toDir, file.getName());
|
||||
if (!file.renameTo(target)) {
|
||||
Log.w(K9.LOG_TAG, "cannot rename " + file.getAbsolutePath() + " to " + target.getAbsolutePath() + " - moving instead");
|
||||
move(file, target);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!fromDir.delete()) {
|
||||
Log.w(K9.LOG_TAG, "cannot delete " + fromDir.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
private static final String IMG_SRC_REGEX = "(?is:<img[^>]+src\\s*=\\s*['\"]?([a-z]+)\\:)";
|
||||
private static final Pattern IMG_PATTERN = Pattern.compile(IMG_SRC_REGEX);
|
||||
@ -624,18 +464,6 @@ public class Utility {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace characters we don't allow in file names with a replacement character.
|
||||
*
|
||||
* @param filename
|
||||
* The original file name.
|
||||
*
|
||||
* @return The sanitized file name containing only allowed characters.
|
||||
*/
|
||||
public static String sanitizeFilename(String filename) {
|
||||
return filename.replaceAll(INVALID_CHARACTERS, REPLACEMENT_CHARACTER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if we have network connectivity.
|
||||
* @param app Current application (Hint: see if your base class has a getApplication() method.)
|
||||
|
@ -14,7 +14,7 @@ import android.os.Build;
|
||||
import android.util.Log;
|
||||
|
||||
import com.fsck.k9.K9;
|
||||
import com.fsck.k9.helper.Utility;
|
||||
import com.fsck.k9.helper.FileHelper;
|
||||
import com.fsck.k9.mail.MessagingException;
|
||||
|
||||
public class LockableDatabase {
|
||||
@ -337,9 +337,10 @@ public class LockableDatabase {
|
||||
prepareStorage(newProviderId);
|
||||
|
||||
// move all database files
|
||||
Utility.moveRecursive(oldDatabase, storageManager.getDatabase(uUid, newProviderId));
|
||||
FileHelper.moveRecursive(oldDatabase, storageManager.getDatabase(uUid, newProviderId));
|
||||
// move all attachment files
|
||||
Utility.moveRecursive(storageManager.getAttachmentDirectory(uUid, oldProviderId), storageManager.getAttachmentDirectory(uUid, newProviderId));
|
||||
FileHelper.moveRecursive(storageManager.getAttachmentDirectory(uUid, oldProviderId),
|
||||
storageManager.getAttachmentDirectory(uUid, newProviderId));
|
||||
// remove any remaining old journal files
|
||||
deleteDatabase(oldDatabase);
|
||||
|
||||
@ -425,7 +426,7 @@ public class LockableDatabase {
|
||||
// Android seems to be unmounting the storage...
|
||||
throw new UnavailableStorageException("Unable to access: " + databaseParentDir);
|
||||
}
|
||||
Utility.touchFile(databaseParentDir, ".nomedia");
|
||||
FileHelper.touchFile(databaseParentDir, ".nomedia");
|
||||
}
|
||||
|
||||
final File attachmentDir;
|
||||
@ -435,7 +436,7 @@ public class LockableDatabase {
|
||||
attachmentParentDir = attachmentDir.getParentFile();
|
||||
if (!attachmentParentDir.exists()) {
|
||||
attachmentParentDir.mkdirs();
|
||||
Utility.touchFile(attachmentParentDir, ".nomedia");
|
||||
FileHelper.touchFile(attachmentParentDir, ".nomedia");
|
||||
}
|
||||
if (!attachmentDir.exists()) {
|
||||
attachmentDir.mkdirs();
|
||||
|
@ -12,6 +12,8 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import com.fsck.k9.helper.FileHelper;
|
||||
import org.xmlpull.v1.XmlSerializer;
|
||||
|
||||
import android.content.Context;
|
||||
@ -23,7 +25,6 @@ import android.util.Xml;
|
||||
import com.fsck.k9.Account;
|
||||
import com.fsck.k9.K9;
|
||||
import com.fsck.k9.Preferences;
|
||||
import com.fsck.k9.helper.Utility;
|
||||
import com.fsck.k9.mail.Store;
|
||||
import com.fsck.k9.mail.ServerSettings;
|
||||
import com.fsck.k9.mail.Transport;
|
||||
@ -87,7 +88,7 @@ public class SettingsExporter {
|
||||
File dir = new File(Environment.getExternalStorageDirectory() + File.separator
|
||||
+ context.getPackageName());
|
||||
dir.mkdirs();
|
||||
File file = Utility.createUniqueFile(dir, EXPORT_FILENAME);
|
||||
File file = FileHelper.createUniqueFile(dir, EXPORT_FILENAME);
|
||||
filename = file.getAbsolutePath();
|
||||
os = new FileOutputStream(filename);
|
||||
|
||||
|
@ -34,9 +34,9 @@ import com.fsck.k9.K9;
|
||||
import com.fsck.k9.R;
|
||||
import com.fsck.k9.controller.MessagingController;
|
||||
import com.fsck.k9.controller.MessagingListener;
|
||||
import com.fsck.k9.helper.FileHelper;
|
||||
import com.fsck.k9.helper.MediaScannerNotifier;
|
||||
import com.fsck.k9.helper.SizeFormatter;
|
||||
import com.fsck.k9.helper.Utility;
|
||||
import com.fsck.k9.mail.Message;
|
||||
import com.fsck.k9.mail.MessagingException;
|
||||
import com.fsck.k9.mail.Part;
|
||||
@ -237,8 +237,8 @@ public class AttachmentView extends FrameLayout implements OnClickListener, OnLo
|
||||
}
|
||||
|
||||
private File writeAttachmentToStorage(File directory) throws IOException {
|
||||
String filename = Utility.sanitizeFilename(name);
|
||||
File file = Utility.createUniqueFile(directory, filename);
|
||||
String filename = FileHelper.sanitizeFilename(name);
|
||||
File file = FileHelper.createUniqueFile(directory, filename);
|
||||
|
||||
Uri uri = AttachmentProvider.getAttachmentUri(account, part.getAttachmentId());
|
||||
InputStream in = context.getContentResolver().openInputStream(uri);
|
||||
@ -317,7 +317,7 @@ public class AttachmentView extends FrameLayout implements OnClickListener, OnLo
|
||||
Intent intent;
|
||||
int activitiesCount;
|
||||
|
||||
File dummyFile = new File(Utility.sanitizeFilename(name));
|
||||
File dummyFile = new File(FileHelper.sanitizeFilename(name));
|
||||
Uri fileUri = Uri.fromFile(dummyFile);
|
||||
|
||||
Intent originalMimeTypeIntent = createViewIntentForFileUri(contentType, fileUri);
|
||||
|
@ -46,6 +46,7 @@ import com.fsck.k9.crypto.PgpData;
|
||||
import com.fsck.k9.fragment.MessageViewFragment;
|
||||
import com.fsck.k9.helper.ClipboardManager;
|
||||
import com.fsck.k9.helper.Contacts;
|
||||
import com.fsck.k9.helper.FileHelper;
|
||||
import com.fsck.k9.helper.HtmlConverter;
|
||||
import com.fsck.k9.helper.Utility;
|
||||
import com.fsck.k9.mail.Address;
|
||||
@ -842,10 +843,10 @@ public class SingleMessageView extends LinearLayout implements OnClickListener,
|
||||
filename += "." + extension;
|
||||
}
|
||||
|
||||
String sanitized = Utility.sanitizeFilename(filename);
|
||||
String sanitized = FileHelper.sanitizeFilename(filename);
|
||||
|
||||
File directory = new File(K9.getAttachmentDefaultPath());
|
||||
File file = Utility.createUniqueFile(directory, sanitized);
|
||||
File file = FileHelper.createUniqueFile(directory, sanitized);
|
||||
FileOutputStream out = new FileOutputStream(file);
|
||||
try {
|
||||
IOUtils.copy(in, out);
|
||||
|
Loading…
Reference in New Issue
Block a user