aboutsummaryrefslogtreecommitdiffstats
path: root/main/src/cgeo/geocaching/files
diff options
context:
space:
mode:
Diffstat (limited to 'main/src/cgeo/geocaching/files')
-rw-r--r--main/src/cgeo/geocaching/files/AbstractFileListActivity.java12
-rw-r--r--main/src/cgeo/geocaching/files/FileParser.java5
-rw-r--r--main/src/cgeo/geocaching/files/GPXImporter.java4
-rw-r--r--main/src/cgeo/geocaching/files/GPXParser.java27
-rw-r--r--main/src/cgeo/geocaching/files/LocParser.java4
-rw-r--r--main/src/cgeo/geocaching/files/LocalStorage.java42
-rw-r--r--main/src/cgeo/geocaching/files/ProgressInputStream.java18
-rw-r--r--main/src/cgeo/geocaching/files/SimpleDirChooser.java30
8 files changed, 93 insertions, 49 deletions
diff --git a/main/src/cgeo/geocaching/files/AbstractFileListActivity.java b/main/src/cgeo/geocaching/files/AbstractFileListActivity.java
index b0aba58..35e6265 100644
--- a/main/src/cgeo/geocaching/files/AbstractFileListActivity.java
+++ b/main/src/cgeo/geocaching/files/AbstractFileListActivity.java
@@ -2,12 +2,12 @@ package cgeo.geocaching.files;
import cgeo.geocaching.Intents;
import cgeo.geocaching.R;
-import cgeo.geocaching.StoredList;
import cgeo.geocaching.activity.AbstractListActivity;
+import cgeo.geocaching.list.StoredList;
import cgeo.geocaching.utils.FileUtils;
import cgeo.geocaching.utils.Log;
-import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import android.app.ProgressDialog;
@@ -66,7 +66,7 @@ public abstract class AbstractFileListActivity<T extends ArrayAdapter<File>> ext
if (waitDialog != null) {
waitDialog.dismiss();
}
- if (CollectionUtils.isEmpty(files)) {
+ if (CollectionUtils.isEmpty(files) && requireFiles()) {
showToast(res.getString(R.string.file_list_no_files));
finish();
} else if (adapter != null) {
@@ -104,7 +104,7 @@ public abstract class AbstractFileListActivity<T extends ArrayAdapter<File>> ext
if (searchingThread != null && searchingThread.isAlive()) {
searchingThread.notifyEnd();
}
- if (files.isEmpty()) {
+ if (files.isEmpty() && requireFiles()) {
finish();
}
}
@@ -121,6 +121,10 @@ public abstract class AbstractFileListActivity<T extends ArrayAdapter<File>> ext
}
+ protected boolean requireFiles() {
+ return true;
+ }
+
protected abstract T getAdapter(List<File> files);
private void setAdapter() {
diff --git a/main/src/cgeo/geocaching/files/FileParser.java b/main/src/cgeo/geocaching/files/FileParser.java
index f979d74..396a589 100644
--- a/main/src/cgeo/geocaching/files/FileParser.java
+++ b/main/src/cgeo/geocaching/files/FileParser.java
@@ -2,7 +2,8 @@ package cgeo.geocaching.files;
import cgeo.geocaching.Geocache;
import cgeo.geocaching.utils.CancellableHandler;
-import cgeo.geocaching.utils.IOUtils;
+
+import org.apache.commons.io.IOUtils;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
@@ -51,7 +52,7 @@ public abstract class FileParser {
protected static StringBuilder readStream(InputStream is, CancellableHandler progressHandler) throws IOException {
final StringBuilder buffer = new StringBuilder();
ProgressInputStream progressInputStream = new ProgressInputStream(is);
- final BufferedReader input = new BufferedReader(new InputStreamReader(progressInputStream));
+ final BufferedReader input = new BufferedReader(new InputStreamReader(progressInputStream, "UTF-8"));
try {
String line;
diff --git a/main/src/cgeo/geocaching/files/GPXImporter.java b/main/src/cgeo/geocaching/files/GPXImporter.java
index 3f11c26..bf0aa72 100644
--- a/main/src/cgeo/geocaching/files/GPXImporter.java
+++ b/main/src/cgeo/geocaching/files/GPXImporter.java
@@ -4,7 +4,7 @@ import cgeo.geocaching.Geocache;
import cgeo.geocaching.R;
import cgeo.geocaching.SearchResult;
import cgeo.geocaching.StaticMapsProvider;
-import cgeo.geocaching.cgData;
+import cgeo.geocaching.DataStore;
import cgeo.geocaching.activity.ActivityMixin;
import cgeo.geocaching.activity.Progress;
import cgeo.geocaching.enumerations.LoadFlags;
@@ -175,7 +175,7 @@ public class GPXImporter {
private boolean importStaticMaps(final SearchResult importedCaches) {
int storedCacheMaps = 0;
for (final String geocode : importedCaches.getGeocodes()) {
- final Geocache cache = cgData.loadCache(geocode, LoadFlags.LOAD_WAYPOINTS);
+ final Geocache cache = DataStore.loadCache(geocode, LoadFlags.LOAD_WAYPOINTS);
if (cache != null) {
Log.d("GPXImporter.ImportThread.importStaticMaps start downloadMaps for cache " + geocode);
StaticMapsProvider.downloadMaps(cache);
diff --git a/main/src/cgeo/geocaching/files/GPXParser.java b/main/src/cgeo/geocaching/files/GPXParser.java
index 3358759..e01c191 100644
--- a/main/src/cgeo/geocaching/files/GPXParser.java
+++ b/main/src/cgeo/geocaching/files/GPXParser.java
@@ -1,13 +1,12 @@
package cgeo.geocaching.files;
+import cgeo.geocaching.CgeoApplication;
+import cgeo.geocaching.DataStore;
import cgeo.geocaching.Geocache;
import cgeo.geocaching.LogEntry;
import cgeo.geocaching.R;
-import cgeo.geocaching.StoredList;
import cgeo.geocaching.Trackable;
import cgeo.geocaching.Waypoint;
-import cgeo.geocaching.cgData;
-import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.connector.ConnectorFactory;
import cgeo.geocaching.enumerations.CacheSize;
import cgeo.geocaching.enumerations.CacheType;
@@ -17,9 +16,11 @@ import cgeo.geocaching.enumerations.LoadFlags.SaveFlag;
import cgeo.geocaching.enumerations.LogType;
import cgeo.geocaching.enumerations.WaypointType;
import cgeo.geocaching.geopoint.Geopoint;
+import cgeo.geocaching.list.StoredList;
import cgeo.geocaching.utils.CancellableHandler;
import cgeo.geocaching.utils.Log;
import cgeo.geocaching.utils.MatcherWrapper;
+import cgeo.geocaching.utils.SynchronizedDateFormat;
import org.apache.commons.lang3.StringUtils;
import org.xml.sax.Attributes;
@@ -35,7 +36,6 @@ import android.util.Xml;
import java.io.IOException;
import java.io.InputStream;
import java.text.ParseException;
-import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
@@ -47,9 +47,9 @@ import java.util.regex.Pattern;
public abstract class GPXParser extends FileParser {
- private static final SimpleDateFormat formatSimple = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.US); // 2010-04-20T07:00:00
- private static final SimpleDateFormat formatSimpleZ = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US); // 2010-04-20T07:00:00Z
- private static final SimpleDateFormat formatTimezone = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.US); // 2010-04-20T01:01:03-04:00
+ private static final SynchronizedDateFormat formatSimple = new SynchronizedDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.US); // 2010-04-20T07:00:00
+ private static final SynchronizedDateFormat formatSimpleZ = new SynchronizedDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US); // 2010-04-20T07:00:00Z
+ private static final SynchronizedDateFormat formatTimezone = new SynchronizedDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.US); // 2010-04-20T01:01:03-04:00
/**
* Attention: case sensitive geocode pattern to avoid matching normal words in the name or description of the cache.
@@ -205,7 +205,7 @@ public abstract class GPXParser extends FileParser {
// get text for string
String stringName;
try {
- stringName = cgeoapplication.getInstance().getResources().getResourceName(stringId);
+ stringName = CgeoApplication.getInstance().getResources().getResourceName(stringId);
} catch (final NullPointerException e) {
return null;
}
@@ -312,10 +312,10 @@ public abstract class GPXParser extends FileParser {
// finally store the cache in the database
result.add(geocode);
- cgData.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB));
+ DataStore.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB));
// avoid the cachecache using lots of memory for caches which the user did not actually look at
- cgData.removeAllFromCache();
+ DataStore.removeAllFromCache();
showProgressMessage(progressHandler, progressStream.getProgress());
} else if (StringUtils.isNotBlank(cache.getName())
&& StringUtils.containsIgnoreCase(type, "waypoint")) {
@@ -331,7 +331,7 @@ public abstract class GPXParser extends FileParser {
if (cache.getName().length() > 2) {
final String cacheGeocodeForWaypoint = "GC" + cache.getName().substring(2).toUpperCase(Locale.US);
// lookup cache for waypoint in already parsed caches
- final Geocache cacheForWaypoint = cgData.loadCache(cacheGeocodeForWaypoint, LoadFlags.LOAD_CACHE_OR_DB);
+ final Geocache cacheForWaypoint = DataStore.loadCache(cacheGeocodeForWaypoint, LoadFlags.LOAD_CACHE_OR_DB);
if (cacheForWaypoint != null) {
final Waypoint waypoint = new Waypoint(cache.getShortDescription(), convertWaypointSym2Type(sym), false);
waypoint.setId(-1);
@@ -349,7 +349,7 @@ public abstract class GPXParser extends FileParser {
newPoints.add(waypoint);
Waypoint.mergeWayPoints(newPoints, mergedWayPoints, true);
cacheForWaypoint.setWaypoints(newPoints, false);
- cgData.saveCache(cacheForWaypoint, EnumSet.of(SaveFlag.SAVE_DB));
+ DataStore.saveCache(cacheForWaypoint, EnumSet.of(SaveFlag.SAVE_DB));
showProgressMessage(progressHandler, progressStream.getProgress());
}
}
@@ -785,9 +785,8 @@ public abstract class GPXParser extends FileParser {
try {
progressStream = new ProgressInputStream(stream);
Xml.parse(progressStream, Xml.Encoding.UTF_8, root.getContentHandler());
- return cgData.loadCaches(result, EnumSet.of(LoadFlag.LOAD_DB_MINIMAL));
+ return DataStore.loadCaches(result, EnumSet.of(LoadFlag.LOAD_DB_MINIMAL));
} catch (final SAXException e) {
- Log.w("Cannot parse .gpx file as GPX " + version + ": could not parse XML - ", e);
throw new ParserException("Cannot parse .gpx file as GPX " + version + ": could not parse XML", e);
}
}
diff --git a/main/src/cgeo/geocaching/files/LocParser.java b/main/src/cgeo/geocaching/files/LocParser.java
index 1cfb2a3..3d01c1b 100644
--- a/main/src/cgeo/geocaching/files/LocParser.java
+++ b/main/src/cgeo/geocaching/files/LocParser.java
@@ -1,8 +1,8 @@
package cgeo.geocaching.files;
+import cgeo.geocaching.DataStore;
import cgeo.geocaching.Geocache;
import cgeo.geocaching.SearchResult;
-import cgeo.geocaching.cgData;
import cgeo.geocaching.enumerations.CacheSize;
import cgeo.geocaching.enumerations.CacheType;
import cgeo.geocaching.enumerations.LoadFlags;
@@ -59,7 +59,7 @@ public final class LocParser extends FileParser {
contained.add(geocode);
}
}
- Set<Geocache> caches = cgData.loadCaches(contained, LoadFlags.LOAD_CACHE_OR_DB);
+ Set<Geocache> caches = DataStore.loadCaches(contained, LoadFlags.LOAD_CACHE_OR_DB);
for (Geocache cache : caches) {
Geocache coord = cidCoords.get(cache.getGeocode());
copyCoordToCache(coord, cache);
diff --git a/main/src/cgeo/geocaching/files/LocalStorage.java b/main/src/cgeo/geocaching/files/LocalStorage.java
index fc82409..edbecf6 100644
--- a/main/src/cgeo/geocaching/files/LocalStorage.java
+++ b/main/src/cgeo/geocaching/files/LocalStorage.java
@@ -1,15 +1,16 @@
package cgeo.geocaching.files;
-import cgeo.geocaching.cgeoapplication;
+import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.utils.CryptUtils;
import cgeo.geocaching.utils.FileUtils;
-import cgeo.geocaching.utils.IOUtils;
import cgeo.geocaching.utils.Log;
import ch.boye.httpclientandroidlib.Header;
import ch.boye.httpclientandroidlib.HttpResponse;
+import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
+import org.eclipse.jdt.annotation.Nullable;
import android.os.Environment;
@@ -21,11 +22,13 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
-import java.io.FileReader;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
+import java.io.InputStreamReader;
import java.io.OutputStream;
+import java.io.Reader;
+import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
@@ -35,6 +38,7 @@ import java.util.List;
*/
public final class LocalStorage {
+ private static final String FILE_SYSTEM_TABLE_PATH = "/system/etc/vold.fstab";
public static final String HEADER_LAST_MODIFIED = "last-modified";
public static final String HEADER_ETAG = "etag";
@@ -86,7 +90,7 @@ public final class LocalStorage {
private static File getInternalStorageBase() {
if (internalStorageBase == null) {
// A race condition will do no harm as the operation is idempotent. No need to synchronize.
- internalStorageBase = cgeoapplication.getInstance().getApplicationContext().getFilesDir().getParentFile();
+ internalStorageBase = CgeoApplication.getInstance().getApplicationContext().getFilesDir().getParentFile();
}
return internalStorageBase;
}
@@ -99,7 +103,14 @@ public final class LocalStorage {
* @return the file extension, including the leading dot, or the empty string if none could be determined
*/
static String getExtension(final String url) {
- final String urlExt = StringUtils.substringAfterLast(url, ".");
+ String urlExt;
+ if (url.startsWith("data:")) {
+ // "data:image/png;base64,i53…" -> ".png"
+ urlExt = StringUtils.substringAfter(StringUtils.substringBefore(url, ";"), "/");
+ } else {
+ // "http://example.com/foo/bar.png" -> ".png"
+ urlExt = StringUtils.substringAfterLast(url, ".");
+ }
return urlExt.length() >= 1 && urlExt.length() <= 4 ? "." + urlExt : "";
}
@@ -198,13 +209,19 @@ public final class LocalStorage {
return false;
}
- private static void saveHeader(final String name, final HttpResponse response, final File baseFile) {
+ private static void saveHeader(final String name, @Nullable final HttpResponse response, final File baseFile) {
final Header header = response != null ? response.getFirstHeader(name) : null;
final File file = filenameForHeader(baseFile, name);
if (header == null) {
FileUtils.deleteIgnoringFailure(file);
} else {
- saveToFile(new ByteArrayInputStream(header.getValue().getBytes()), file);
+ try {
+ saveToFile(new ByteArrayInputStream(header.getValue().getBytes("UTF-8")), file);
+ } catch (final UnsupportedEncodingException e) {
+ // Do not try to display the header in the log message, as our default encoding is
+ // likely to be UTF-8 and it will fail as well.
+ Log.e("LocalStorage.saveHeader: unable to decode header", e);
+ }
}
}
@@ -219,12 +236,13 @@ public final class LocalStorage {
* the name of the cached resource
* @param name
* the name of the header ("etag" or "last-modified")
- * @return null if no value has been cached, the value otherwise
+ * @return the cached value, or <tt>null</tt> if none has been cached
*/
+ @Nullable
public static String getSavedHeader(final File baseFile, final String name) {
try {
final File file = filenameForHeader(baseFile, name);
- final FileReader f = new FileReader(file);
+ final Reader f = new InputStreamReader(new FileInputStream(file), "UTF-8");
try {
// No header will be more than 256 bytes
final char[] value = new char[256];
@@ -408,12 +426,12 @@ public final class LocalStorage {
String extStorage = Environment.getExternalStorageDirectory().getAbsolutePath();
List<File> storages = new ArrayList<File>();
storages.add(new File(extStorage));
- File file = new File("/system/etc/vold.fstab");
+ File file = new File(FILE_SYSTEM_TABLE_PATH);
if (file.canRead()) {
- FileReader fr = null;
+ Reader fr = null;
BufferedReader br = null;
try {
- fr = new FileReader(file);
+ fr = new InputStreamReader(new FileInputStream(file), "UTF-8");
br = new BufferedReader(fr);
String s = br.readLine();
while (s != null) {
diff --git a/main/src/cgeo/geocaching/files/ProgressInputStream.java b/main/src/cgeo/geocaching/files/ProgressInputStream.java
index 593949b..552aee0 100644
--- a/main/src/cgeo/geocaching/files/ProgressInputStream.java
+++ b/main/src/cgeo/geocaching/files/ProgressInputStream.java
@@ -4,6 +4,14 @@ import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
+/**
+ * Stream to measure progress of reading automatically.
+ * <p>
+ * The method @link ProgressInputStream#read(byte[]) does not need to be overridden as it delegates to @link
+ * ProgressInputStream#read(byte[], int, int) anyway.
+ * </p>
+ *
+ */
public class ProgressInputStream extends FilterInputStream {
private int progress = 0;
@@ -15,17 +23,13 @@ public class ProgressInputStream extends FilterInputStream {
@Override
public int read() throws IOException {
final int read = super.read();
- progress += read;
+ if (read >= 0) {
+ progress++;
+ }
return read;
}
@Override
- public int read(byte[] buffer) throws IOException {
- return super.read(buffer);
- // don't increment here, this calls another read implementation which we already measure
- }
-
- @Override
public int read(byte[] buffer, int offset, int count) throws IOException {
final int read = super.read(buffer, offset, count);
progress += read;
diff --git a/main/src/cgeo/geocaching/files/SimpleDirChooser.java b/main/src/cgeo/geocaching/files/SimpleDirChooser.java
index 8f69b88..e59287d 100644
--- a/main/src/cgeo/geocaching/files/SimpleDirChooser.java
+++ b/main/src/cgeo/geocaching/files/SimpleDirChooser.java
@@ -32,17 +32,20 @@ import java.util.List;
* Dialog for choosing a file or directory.
*/
public class SimpleDirChooser extends AbstractListActivity {
+ public static final String EXTRA_CHOOSE_FOR_WRITING = "chooseForWriting";
private static final String PARENT_DIR = ".. ";
private File currentDir;
private FileArrayAdapter adapter;
private Button okButton = null;
private int lastPosition = -1;
+ private boolean chooseForWriting = false;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final Bundle extras = getIntent().getExtras();
currentDir = dirContaining(extras.getString(Intents.EXTRA_START_DIR));
+ chooseForWriting = extras.getBoolean(SimpleDirChooser.EXTRA_CHOOSE_FOR_WRITING, false);
ActivityMixin.setTheme(this);
setContentView(R.layout.simple_dir_chooser);
@@ -85,19 +88,20 @@ public class SimpleDirChooser extends AbstractListActivity {
}
private void fill(File dir) {
+ lastPosition = -1;
EditText path = (EditText) findViewById(R.id.simple_dir_chooser_path);
path.setText(this.getResources().getString(R.string.simple_dir_chooser_current_path) + " " + dir.getAbsolutePath());
final File[] dirs = dir.listFiles(new DirOnlyFilenameFilter());
List<Option> listDirs = new ArrayList<Option>();
try {
for (File currentDir : dirs) {
- listDirs.add(new Option(currentDir.getName(), currentDir.getAbsolutePath()));
+ listDirs.add(new Option(currentDir.getName(), currentDir.getAbsolutePath(), currentDir.canWrite()));
}
} catch (RuntimeException e) {
}
Collections.sort(listDirs);
if (dir.getParent() != null) {
- listDirs.add(0, new Option(PARENT_DIR, dir.getParent()));
+ listDirs.add(0, new Option(PARENT_DIR, dir.getParent(), false));
}
this.adapter = new FileArrayAdapter(this, R.layout.simple_dir_item, listDirs);
this.setListAdapter(adapter);
@@ -138,8 +142,13 @@ public class SimpleDirChooser extends AbstractListActivity {
}
CheckBox check = (CheckBox) v.findViewById(R.id.CheckBox);
if (check != null) {
- check.setOnClickListener(new OnCheckBoxClickListener(position));
- check.setChecked(option.isChecked());
+ if (!chooseForWriting || option.isWriteable()) {
+ check.setOnClickListener(new OnCheckBoxClickListener(position));
+ check.setChecked(option.isChecked());
+ check.setEnabled(true);
+ } else {
+ check.setEnabled(false);
+ }
}
}
return v;
@@ -196,14 +205,19 @@ public class SimpleDirChooser extends AbstractListActivity {
}
}
+ /**
+ * Note: this class has a natural ordering that is inconsistent with equals.
+ */
public static class Option implements Comparable<Option> {
private final String name;
private final String path;
private boolean checked = false;
+ private boolean writeable = false;
- public Option(String name, String path) {
+ public Option(String name, String path, boolean writeable) {
this.name = name;
this.path = path;
+ this.writeable = writeable;
}
public String getName() {
@@ -222,6 +236,10 @@ public class SimpleDirChooser extends AbstractListActivity {
this.checked = checked;
}
+ public boolean isWriteable() {
+ return writeable;
+ }
+
@Override
public int compareTo(Option other) {
if (other != null && this.name != null) {
@@ -236,7 +254,7 @@ public class SimpleDirChooser extends AbstractListActivity {
@Override
public boolean accept(File dir, String filename) {
File file = new File(dir, filename);
- return file.isDirectory() && file.canWrite();
+ return file.isDirectory() && file.canRead();
}
}