import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
+import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
-import android.preference.PreferenceManager;
+import android.support.v7.preference.PreferenceManager;
import android.provider.Settings;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
final String action = intent.getAction();
if (DownloadManager.ACTION_NOTIFICATION_CLICKED.equals(action)) {
- startActivity(DictionaryManagerActivity.getLaunchIntent(getApplicationContext()).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP));
+ startActivity(getLaunchIntent(getApplicationContext()).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP));
}
if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(action)) {
final long downloadId = intent.getLongExtra(
}
}
zipFile = new ZipInputStream(new BufferedInputStream(zipFileStream));
- final ZipEntry zipEntry = zipFile.getNextEntry();
- Log.d(LOG, "Unzipping entry: " + zipEntry.getName());
- File targetFile = new File(application.getDictDir(), zipEntry.getName());
- if (targetFile.exists()) {
- targetFile.renameTo(new File(targetFile.getAbsolutePath().replace(".quickdic", ".bak.quickdic")));
- targetFile = new File(application.getDictDir(), zipEntry.getName());
+ ZipEntry zipEntry;
+ while ((zipEntry = zipFile.getNextEntry()) != null) {
+ // Note: this check prevents security issues like accidental path
+ // traversal, which unfortunately ZipInputStream has no protection against.
+ // So take extra care when changing it.
+ if (!Pattern.matches("[-A-Za-z]+\\.quickdic", zipEntry.getName())) {
+ Log.w(LOG, "Invalid zip entry: " + zipEntry.getName());
+ continue;
+ }
+ Log.d(LOG, "Unzipping entry: " + zipEntry.getName());
+ File targetFile = new File(application.getDictDir(), zipEntry.getName());
+ if (targetFile.exists()) {
+ targetFile.renameTo(new File(targetFile.getAbsolutePath().replace(".quickdic", ".bak.quickdic")));
+ targetFile = new File(application.getDictDir(), zipEntry.getName());
+ }
+ zipOut = new FileOutputStream(targetFile);
+ copyStream(zipFile, zipOut);
}
- zipOut = new FileOutputStream(targetFile);
- copyStream(zipFile, zipOut);
application.backgroundUpdateDictionaries(dictionaryUpdater);
if (!isFinishing())
Toast.makeText(context, getString(R.string.installationFinished, dest),
} finally {
try {
if (zipOut != null) zipOut.close();
- } catch (IOException e) {}
+ } catch (IOException ignored) {}
try {
if (zipFile != null) zipFile.close();
- } catch (IOException e) {}
+ } catch (IOException ignored) {}
try {
if (zipFileStream != null) zipFileStream.close();
- } catch (IOException e) {}
- if (localZipFile != null && delete) localZipFile.delete();
+ } catch (IOException ignored) {}
+ if (localZipFile != null && delete) //noinspection ResultOfMethodCallIgnored
+ localZipFile.delete();
}
return result;
}
}
@Override
- public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) {
+ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
readableCheckAndError(false);
application.backgroundUpdateDictionaries(dictionaryUpdater);
}
});
+ /*
+ Disable version update notification, I don't maintain the text really
+ and I don't think it is very useful.
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
final String thanksForUpdatingLatestVersion = getString(R.string.thanksForUpdatingVersion);
if (!prefs.getString(C.THANKS_FOR_UPDATING_VERSION, "").equals(
prefs.edit().putString(C.THANKS_FOR_UPDATING_VERSION, thanksForUpdatingLatestVersion)
.commit();
}
+ */
IntentFilter downloadManagerIntents = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
downloadManagerIntents.addAction(DownloadManager.ACTION_NOTIFICATION_CLICKED);
registerReceiver(broadcastReceiver, downloadManagerIntents);
public boolean onMenuItemClick(final MenuItem menuItem) {
final Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri
- .parse("https://github.com/rdoeffinger/Dictionary/releases/v0.2-dictionaries"));
+ .parse("https://github.com/rdoeffinger/Dictionary/releases/v0.3-dictionaries"));
startActivity(intent);
return false;
}
if (cursor == null) {
if (cancel) {
String msg = getString(R.string.downloadManagerQueryFailed);
- new AlertDialog.Builder(DictionaryManagerActivity.this).setTitle(getString(R.string.error))
+ new AlertDialog.Builder(this).setTitle(getString(R.string.error))
.setMessage(getString(R.string.downloadFailed, msg))
.setNeutralButton("Close", null).show();
}
bytes / 1024.0 / 1024.0));
return;
}
- Request request = new Request(
- Uri.parse(downloadUrl));
+ // API 19 and earlier have issues with github URLs, both http and https.
+ // Really old (~API 10) DownloadManager cannot handle https at all.
+ // Work around both with in one.
+ String altUrl = downloadUrl.replace("https://github.com/rdoeffinger/Dictionary/releases/download/v0.2-dictionaries/", "http://ffmpeg.org/~reimar/dict/");
+ altUrl = altUrl.replace("https://github.com/rdoeffinger/Dictionary/releases/download/v0.3-dictionaries/", "http://ffmpeg.org/~reimar/dict/");
+ Request request = new Request(Uri.parse(Build.VERSION.SDK_INT < 21 ? altUrl : downloadUrl));
String destFile;
try {
DownloadManager downloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
+ if (downloadManager == null) {
+ String msg = getString(R.string.downloadManagerQueryFailed);
+ new AlertDialog.Builder(this).setTitle(getString(R.string.error))
+ .setMessage(getString(R.string.downloadFailed, msg))
+ .setNeutralButton("Close", null).show();
+ return;
+ }
+
try {
downloadManager.enqueue(request);
} catch (SecurityException e) {