diff options
Diffstat (limited to 'java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java')
-rw-r--r-- | java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java | 73 |
1 files changed, 67 insertions, 6 deletions
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java index 063243e1b..9764df072 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java @@ -16,6 +16,9 @@ package com.android.inputmethod.latin; +import com.android.inputmethod.latin.makedict.BinaryDictInputOutput; +import com.android.inputmethod.latin.makedict.FormatSpec; + import android.content.Context; import android.content.SharedPreferences; import android.content.pm.PackageManager.NameNotFoundException; @@ -23,6 +26,10 @@ import android.content.res.AssetFileDescriptor; import android.util.Log; import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.nio.BufferUnderflowException; +import java.nio.channels.FileChannel; import java.util.ArrayList; import java.util.HashMap; import java.util.Locale; @@ -51,6 +58,9 @@ class BinaryDictionaryGetter { private static final String MAIN_DICTIONARY_CATEGORY = "main"; public static final String ID_CATEGORY_SEPARATOR = ":"; + // The key considered to read the version attribute in a dictionary file. + private static String VERSION_KEY = "version"; + // Prevents this from being instantiated private BinaryDictionaryGetter() {} @@ -254,8 +264,7 @@ class BinaryDictionaryGetter { final Context context) { final File[] directoryList = getCachedDirectoryList(context); if (null == directoryList) return EMPTY_FILE_ARRAY; - final HashMap<String, FileAndMatchLevel> cacheFiles = - new HashMap<String, FileAndMatchLevel>(); + final HashMap<String, FileAndMatchLevel> cacheFiles = CollectionUtils.newHashMap(); for (File directory : directoryList) { if (!directory.isDirectory()) continue; final String dirLocale = getWordListIdFromFileName(directory.getName()); @@ -336,6 +345,57 @@ class BinaryDictionaryGetter { return MAIN_DICTIONARY_CATEGORY.equals(idArray[0]); } + // ## HACK ## we prevent usage of a dictionary before version 18 for English only. The reason + // for this is, since those do not include whitelist entries, the new code with an old version + // of the dictionary would lose whitelist functionality. + private static boolean hackCanUseDictionaryFile(final Locale locale, final File f) { + // Only for English - other languages didn't have a whitelist, hence this + // ad-hock ## HACK ## + if (!Locale.ENGLISH.getLanguage().equals(locale.getLanguage())) return true; + + FileInputStream inStream = null; + try { + // Read the version of the file + inStream = new FileInputStream(f); + final BinaryDictInputOutput.ByteBufferWrapper buffer = + new BinaryDictInputOutput.ByteBufferWrapper(inStream.getChannel().map( + FileChannel.MapMode.READ_ONLY, 0, f.length())); + final int magic = buffer.readInt(); + if (magic != FormatSpec.VERSION_2_MAGIC_NUMBER) { + return false; + } + final int formatVersion = buffer.readInt(); + final int headerSize = buffer.readInt(); + final HashMap<String, String> options = CollectionUtils.newHashMap(); + BinaryDictInputOutput.populateOptions(buffer, headerSize, options); + + final String version = options.get(VERSION_KEY); + if (null == version) { + // No version in the options : the format is unexpected + return false; + } + // Version 18 is the first one to include the whitelist + // Obviously this is a big ## HACK ## + return Integer.parseInt(version) >= 18; + } catch (java.io.FileNotFoundException e) { + return false; + } catch (java.io.IOException e) { + return false; + } catch (NumberFormatException e) { + return false; + } catch (BufferUnderflowException e) { + return false; + } finally { + if (inStream != null) { + try { + inStream.close(); + } catch (IOException e) { + // do nothing + } + } + } + } + /** * Returns a list of file addresses for a given locale, trying relevant methods in order. * @@ -362,18 +422,19 @@ class BinaryDictionaryGetter { final DictPackSettings dictPackSettings = new DictPackSettings(context); boolean foundMainDict = false; - final ArrayList<AssetFileAddress> fileList = new ArrayList<AssetFileAddress>(); + final ArrayList<AssetFileAddress> fileList = CollectionUtils.newArrayList(); // cachedWordLists may not be null, see doc for getCachedDictionaryList for (final File f : cachedWordLists) { final String wordListId = getWordListIdFromFileName(f.getName()); - if (isMainWordListId(wordListId)) { + final boolean canUse = f.canRead() && hackCanUseDictionaryFile(locale, f); + if (canUse && isMainWordListId(wordListId)) { foundMainDict = true; } if (!dictPackSettings.isWordListActive(wordListId)) continue; - if (f.canRead()) { + if (canUse) { fileList.add(AssetFileAddress.makeFromFileName(f.getPath())); } else { - Log.e(TAG, "Found a cached dictionary file but cannot read it"); + Log.e(TAG, "Found a cached dictionary file but cannot read or use it"); } } |