Loading java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java +46 −3 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.inputmethod.latin; import com.android.inputmethod.latin.makedict.BinaryDictInputOutput; import android.content.Context; import android.content.SharedPreferences; import android.content.pm.PackageManager.NameNotFoundException; Loading @@ -23,6 +25,7 @@ import android.content.res.AssetFileDescriptor; import android.util.Log; import java.io.File; import java.io.RandomAccessFile; import java.util.ArrayList; import java.util.HashMap; import java.util.Locale; Loading Loading @@ -51,6 +54,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() {} Loading Loading @@ -336,6 +342,42 @@ 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; try { // Read the version of the file final RandomAccessFile raf = new RandomAccessFile(f, "r"); final int magic = raf.readInt(); if (magic != BinaryDictInputOutput.VERSION_2_MAGIC_NUMBER) { return false; } final int formatVersion = raf.readInt(); final int headerSize = raf.readInt(); final HashMap<String, String> options = new HashMap<String, String>(); BinaryDictInputOutput.populateOptionsFromFile(raf, 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; } } /** * Returns a list of file addresses for a given locale, trying relevant methods in order. * Loading Loading @@ -366,14 +408,15 @@ class BinaryDictionaryGetter { // 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"); } } Loading java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java +17 −6 Original line number Diff line number Diff line Loading @@ -124,7 +124,7 @@ public class BinaryDictInputOutput { */ private static final int VERSION_1_MAGIC_NUMBER = 0x78B1; private static final int VERSION_2_MAGIC_NUMBER = 0x9BC13AFE; public static final int VERSION_2_MAGIC_NUMBER = 0x9BC13AFE; private static final int MINIMUM_SUPPORTED_VERSION = 1; private static final int MAXIMUM_SUPPORTED_VERSION = 2; private static final int NOT_A_VERSION_NUMBER = -1; Loading Loading @@ -1327,6 +1327,21 @@ public class BinaryDictInputOutput { return NOT_A_VERSION_NUMBER; } /** * Reads options from a file and populate a map with their contents. * * The file is read at the current file pointer, so the caller must take care the pointer * is in the right place before calling this. */ public static void populateOptionsFromFile(final RandomAccessFile source, final long headerSize, final HashMap<String, String> options) throws IOException { while (source.getFilePointer() < headerSize) { final String key = CharEncoding.readString(source); final String value = CharEncoding.readString(source); options.put(key, value); } } /** * Reads a random access file and returns the memory representation of the dictionary. * Loading Loading @@ -1358,11 +1373,7 @@ public class BinaryDictInputOutput { } else { headerSize = (source.readUnsignedByte() << 24) + (source.readUnsignedByte() << 16) + (source.readUnsignedByte() << 8) + source.readUnsignedByte(); while (source.getFilePointer() < headerSize) { final String key = CharEncoding.readString(source); final String value = CharEncoding.readString(source); options.put(key, value); } populateOptionsFromFile(source, headerSize, options); source.seek(headerSize); } Loading Loading
java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java +46 −3 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.inputmethod.latin; import com.android.inputmethod.latin.makedict.BinaryDictInputOutput; import android.content.Context; import android.content.SharedPreferences; import android.content.pm.PackageManager.NameNotFoundException; Loading @@ -23,6 +25,7 @@ import android.content.res.AssetFileDescriptor; import android.util.Log; import java.io.File; import java.io.RandomAccessFile; import java.util.ArrayList; import java.util.HashMap; import java.util.Locale; Loading Loading @@ -51,6 +54,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() {} Loading Loading @@ -336,6 +342,42 @@ 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; try { // Read the version of the file final RandomAccessFile raf = new RandomAccessFile(f, "r"); final int magic = raf.readInt(); if (magic != BinaryDictInputOutput.VERSION_2_MAGIC_NUMBER) { return false; } final int formatVersion = raf.readInt(); final int headerSize = raf.readInt(); final HashMap<String, String> options = new HashMap<String, String>(); BinaryDictInputOutput.populateOptionsFromFile(raf, 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; } } /** * Returns a list of file addresses for a given locale, trying relevant methods in order. * Loading Loading @@ -366,14 +408,15 @@ class BinaryDictionaryGetter { // 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"); } } Loading
java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java +17 −6 Original line number Diff line number Diff line Loading @@ -124,7 +124,7 @@ public class BinaryDictInputOutput { */ private static final int VERSION_1_MAGIC_NUMBER = 0x78B1; private static final int VERSION_2_MAGIC_NUMBER = 0x9BC13AFE; public static final int VERSION_2_MAGIC_NUMBER = 0x9BC13AFE; private static final int MINIMUM_SUPPORTED_VERSION = 1; private static final int MAXIMUM_SUPPORTED_VERSION = 2; private static final int NOT_A_VERSION_NUMBER = -1; Loading Loading @@ -1327,6 +1327,21 @@ public class BinaryDictInputOutput { return NOT_A_VERSION_NUMBER; } /** * Reads options from a file and populate a map with their contents. * * The file is read at the current file pointer, so the caller must take care the pointer * is in the right place before calling this. */ public static void populateOptionsFromFile(final RandomAccessFile source, final long headerSize, final HashMap<String, String> options) throws IOException { while (source.getFilePointer() < headerSize) { final String key = CharEncoding.readString(source); final String value = CharEncoding.readString(source); options.put(key, value); } } /** * Reads a random access file and returns the memory representation of the dictionary. * Loading Loading @@ -1358,11 +1373,7 @@ public class BinaryDictInputOutput { } else { headerSize = (source.readUnsignedByte() << 24) + (source.readUnsignedByte() << 16) + (source.readUnsignedByte() << 8) + source.readUnsignedByte(); while (source.getFilePointer() < headerSize) { final String key = CharEncoding.readString(source); final String value = CharEncoding.readString(source); options.put(key, value); } populateOptionsFromFile(source, headerSize, options); source.seek(headerSize); } Loading