From e077c014616f7b4e28dbbfab622ba36c8e922268 Mon Sep 17 00:00:00 2001
From: Jean Chalard <jchalard@google.com>
Date: Tue, 20 May 2014 17:35:51 +0900
Subject: [PATCH] Add the rawChecksum column to the database.

Bug: 13125743
Change-Id: I082aa9df1dd4a10cdb3f97ee0692f2d72f6c8e7e
---
 .../dictionarypack/ActionBatch.java           | 12 +++---
 .../dictionarypack/MetadataDbHelper.java      | 37 ++++++++++++++++---
 .../dictionarypack/MetadataHandler.java       |  3 ++
 .../dictionarypack/MetadataParser.java        |  2 +
 .../dictionarypack/WordListMetadata.java      | 13 +++++--
 5 files changed, 52 insertions(+), 15 deletions(-)

diff --git a/java/src/com/android/inputmethod/dictionarypack/ActionBatch.java b/java/src/com/android/inputmethod/dictionarypack/ActionBatch.java
index 706bdea8ee..3f69cedee1 100644
--- a/java/src/com/android/inputmethod/dictionarypack/ActionBatch.java
+++ b/java/src/com/android/inputmethod/dictionarypack/ActionBatch.java
@@ -325,8 +325,9 @@ public final class ActionBatch {
                     MetadataDbHelper.TYPE_BULK, MetadataDbHelper.STATUS_AVAILABLE,
                     mWordList.mId, mWordList.mLocale, mWordList.mDescription,
                     null == mWordList.mLocalFilename ? "" : mWordList.mLocalFilename,
-                    mWordList.mRemoteFilename, mWordList.mLastUpdate, mWordList.mChecksum,
-                    mWordList.mFileSize, mWordList.mVersion, mWordList.mFormatVersion);
+                    mWordList.mRemoteFilename, mWordList.mLastUpdate, mWordList.mRawChecksum,
+                    mWordList.mChecksum, mWordList.mFileSize, mWordList.mVersion,
+                    mWordList.mFormatVersion);
             PrivateLog.log("Insert 'available' record for " + mWordList.mDescription
                     + " and locale " + mWordList.mLocale);
             db.insert(MetadataDbHelper.METADATA_TABLE_NAME, null, values);
@@ -374,7 +375,7 @@ public final class ActionBatch {
             final ContentValues values = MetadataDbHelper.makeContentValues(0,
                     MetadataDbHelper.TYPE_BULK, MetadataDbHelper.STATUS_INSTALLED,
                     mWordList.mId, mWordList.mLocale, mWordList.mDescription,
-                    "", mWordList.mRemoteFilename, mWordList.mLastUpdate,
+                    "", mWordList.mRemoteFilename, mWordList.mLastUpdate, mWordList.mRawChecksum,
                     mWordList.mChecksum, mWordList.mFileSize, mWordList.mVersion,
                     mWordList.mFormatVersion);
             PrivateLog.log("Insert 'preinstalled' record for " + mWordList.mDescription
@@ -416,8 +417,9 @@ public final class ActionBatch {
                     oldValues.getAsInteger(MetadataDbHelper.STATUS_COLUMN),
                     mWordList.mId, mWordList.mLocale, mWordList.mDescription,
                     oldValues.getAsString(MetadataDbHelper.LOCAL_FILENAME_COLUMN),
-                    mWordList.mRemoteFilename, mWordList.mLastUpdate, mWordList.mChecksum,
-                    mWordList.mFileSize, mWordList.mVersion, mWordList.mFormatVersion);
+                    mWordList.mRemoteFilename, mWordList.mLastUpdate, mWordList.mRawChecksum,
+                    mWordList.mChecksum, mWordList.mFileSize, mWordList.mVersion,
+                    mWordList.mFormatVersion);
             PrivateLog.log("Updating record for " + mWordList.mDescription
                     + " and locale " + mWordList.mLocale);
             db.update(MetadataDbHelper.METADATA_TABLE_NAME, values,
diff --git a/java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java b/java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java
index 4a8fa51ee2..668eb925bf 100644
--- a/java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java
+++ b/java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java
@@ -20,6 +20,7 @@ import android.content.ContentValues;
 import android.content.Context;
 import android.database.Cursor;
 import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteException;
 import android.database.sqlite.SQLiteOpenHelper;
 import android.text.TextUtils;
 import android.util.Log;
@@ -46,7 +47,7 @@ public class MetadataDbHelper extends SQLiteOpenHelper {
     // used to identify the versions for upgrades. This should never change going forward.
     private static final int METADATA_DATABASE_VERSION_WITH_CLIENTID = 6;
     // The current database version.
-    private static final int CURRENT_METADATA_DATABASE_VERSION = 7;
+    private static final int CURRENT_METADATA_DATABASE_VERSION = 8;
 
     private final static long NOT_A_DOWNLOAD_ID = -1;
 
@@ -66,7 +67,8 @@ public class MetadataDbHelper extends SQLiteOpenHelper {
     public static final String VERSION_COLUMN = "version";
     public static final String FORMATVERSION_COLUMN = "formatversion";
     public static final String FLAGS_COLUMN = "flags";
-    public static final int COLUMN_COUNT = 13;
+    public static final String RAW_CHECKSUM_COLUMN = "rawChecksum";
+    public static final int COLUMN_COUNT = 14;
 
     private static final String CLIENT_CLIENT_ID_COLUMN = "clientid";
     private static final String CLIENT_METADATA_URI_COLUMN = "uri";
@@ -119,8 +121,9 @@ public class MetadataDbHelper extends SQLiteOpenHelper {
             + CHECKSUM_COLUMN + " TEXT, "
             + FILESIZE_COLUMN + " INTEGER, "
             + VERSION_COLUMN + " INTEGER,"
-            + FORMATVERSION_COLUMN + " INTEGER,"
-            + FLAGS_COLUMN + " INTEGER,"
+            + FORMATVERSION_COLUMN + " INTEGER, "
+            + FLAGS_COLUMN + " INTEGER, "
+            + RAW_CHECKSUM_COLUMN + " TEXT,"
             + "PRIMARY KEY (" + WORDLISTID_COLUMN + "," + VERSION_COLUMN + "));";
     private static final String METADATA_CREATE_CLIENT_TABLE =
             "CREATE TABLE IF NOT EXISTS " + CLIENT_TABLE_NAME + " ("
@@ -136,7 +139,8 @@ public class MetadataDbHelper extends SQLiteOpenHelper {
     static final String[] METADATA_TABLE_COLUMNS = { PENDINGID_COLUMN, TYPE_COLUMN,
             STATUS_COLUMN, WORDLISTID_COLUMN, LOCALE_COLUMN, DESCRIPTION_COLUMN,
             LOCAL_FILENAME_COLUMN, REMOTE_FILENAME_COLUMN, DATE_COLUMN, CHECKSUM_COLUMN,
-            FILESIZE_COLUMN, VERSION_COLUMN, FORMATVERSION_COLUMN, FLAGS_COLUMN };
+            FILESIZE_COLUMN, VERSION_COLUMN, FORMATVERSION_COLUMN, FLAGS_COLUMN,
+            RAW_CHECKSUM_COLUMN };
     // List of all client table columns.
     static final String[] CLIENT_TABLE_COLUMNS = { CLIENT_CLIENT_ID_COLUMN,
             CLIENT_METADATA_URI_COLUMN, CLIENT_PENDINGID_COLUMN, FLAGS_COLUMN };
@@ -215,6 +219,17 @@ public class MetadataDbHelper extends SQLiteOpenHelper {
         createClientTable(db);
     }
 
+    private void addRawChecksumColumnUnlessPresent(final SQLiteDatabase db, final String clientId) {
+        try {
+            db.execSQL("SELECT " + RAW_CHECKSUM_COLUMN + " FROM "
+                    + METADATA_TABLE_NAME + " LIMIT 0;");
+        } catch (SQLiteException e) {
+            Log.i(TAG, "No " + RAW_CHECKSUM_COLUMN + " column : creating it");
+            db.execSQL("ALTER TABLE " + METADATA_TABLE_NAME + " ADD COLUMN "
+                    + RAW_CHECKSUM_COLUMN + " TEXT;");
+        }
+    }
+
     /**
      * Upgrade the database. Upgrade from version 3 is supported.
      * Version 3 has a DB named METADATA_DATABASE_NAME_STEM containing a table METADATA_TABLE_NAME.
@@ -260,6 +275,12 @@ public class MetadataDbHelper extends SQLiteOpenHelper {
             db.execSQL("DROP TABLE IF EXISTS " + CLIENT_TABLE_NAME);
             onCreate(db);
         }
+        // A rawChecksum column that did not exist in the previous versions was added that
+        // corresponds to the md5 checksum of the file after decompression/decryption. This is to
+        // strengthen the system against corrupted dictionary files.
+        // The most secure way to upgrade a database is to just test for the column presence, and
+        // add it if it's not there.
+        addRawChecksumColumnUnlessPresent(db, mClientId);
     }
 
     /**
@@ -431,7 +452,7 @@ public class MetadataDbHelper extends SQLiteOpenHelper {
     public static ContentValues makeContentValues(final int pendingId, final int type,
             final int status, final String wordlistId, final String locale,
             final String description, final String filename, final String url, final long date,
-            final String checksum, final long filesize, final int version,
+            final String rawChecksum, final String checksum, final long filesize, final int version,
             final int formatVersion) {
         final ContentValues result = new ContentValues(COLUMN_COUNT);
         result.put(PENDINGID_COLUMN, pendingId);
@@ -443,6 +464,7 @@ public class MetadataDbHelper extends SQLiteOpenHelper {
         result.put(LOCAL_FILENAME_COLUMN, filename);
         result.put(REMOTE_FILENAME_COLUMN, url);
         result.put(DATE_COLUMN, date);
+        result.put(RAW_CHECKSUM_COLUMN, rawChecksum);
         result.put(CHECKSUM_COLUMN, checksum);
         result.put(FILESIZE_COLUMN, filesize);
         result.put(VERSION_COLUMN, version);
@@ -478,6 +500,8 @@ public class MetadataDbHelper extends SQLiteOpenHelper {
         if (null == result.get(REMOTE_FILENAME_COLUMN)) result.put(REMOTE_FILENAME_COLUMN, "");
         // 0 for the update date : 1970/1/1. Unless specified.
         if (null == result.get(DATE_COLUMN)) result.put(DATE_COLUMN, 0);
+        // Raw checksum unknown unless specified
+        if (null == result.get(RAW_CHECKSUM_COLUMN)) result.put(RAW_CHECKSUM_COLUMN, "");
         // Checksum unknown unless specified
         if (null == result.get(CHECKSUM_COLUMN)) result.put(CHECKSUM_COLUMN, "");
         // No filesize unless specified
@@ -525,6 +549,7 @@ public class MetadataDbHelper extends SQLiteOpenHelper {
             putStringResult(result, cursor, LOCAL_FILENAME_COLUMN);
             putStringResult(result, cursor, REMOTE_FILENAME_COLUMN);
             putIntResult(result, cursor, DATE_COLUMN);
+            putStringResult(result, cursor, RAW_CHECKSUM_COLUMN);
             putStringResult(result, cursor, CHECKSUM_COLUMN);
             putIntResult(result, cursor, FILESIZE_COLUMN);
             putIntResult(result, cursor, VERSION_COLUMN);
diff --git a/java/src/com/android/inputmethod/dictionarypack/MetadataHandler.java b/java/src/com/android/inputmethod/dictionarypack/MetadataHandler.java
index 5c2289911d..63e419871c 100644
--- a/java/src/com/android/inputmethod/dictionarypack/MetadataHandler.java
+++ b/java/src/com/android/inputmethod/dictionarypack/MetadataHandler.java
@@ -52,6 +52,8 @@ public class MetadataHandler {
             final int idIndex = results.getColumnIndex(MetadataDbHelper.WORDLISTID_COLUMN);
             final int updateIndex = results.getColumnIndex(MetadataDbHelper.DATE_COLUMN);
             final int fileSizeIndex = results.getColumnIndex(MetadataDbHelper.FILESIZE_COLUMN);
+            final int rawChecksumIndex =
+                    results.getColumnIndex(MetadataDbHelper.RAW_CHECKSUM_COLUMN);
             final int checksumIndex = results.getColumnIndex(MetadataDbHelper.CHECKSUM_COLUMN);
             final int localFilenameIndex =
                     results.getColumnIndex(MetadataDbHelper.LOCAL_FILENAME_COLUMN);
@@ -66,6 +68,7 @@ public class MetadataHandler {
                         results.getString(descriptionColumn),
                         results.getLong(updateIndex),
                         results.getLong(fileSizeIndex),
+                        results.getString(rawChecksumIndex),
                         results.getString(checksumIndex),
                         results.getString(localFilenameIndex),
                         results.getString(remoteFilenameIndex),
diff --git a/java/src/com/android/inputmethod/dictionarypack/MetadataParser.java b/java/src/com/android/inputmethod/dictionarypack/MetadataParser.java
index 27670fddf0..a88173e8e5 100644
--- a/java/src/com/android/inputmethod/dictionarypack/MetadataParser.java
+++ b/java/src/com/android/inputmethod/dictionarypack/MetadataParser.java
@@ -37,6 +37,7 @@ public class MetadataParser {
     private static final String DESCRIPTION_FIELD_NAME = MetadataDbHelper.DESCRIPTION_COLUMN;
     private static final String UPDATE_FIELD_NAME = "update";
     private static final String FILESIZE_FIELD_NAME = MetadataDbHelper.FILESIZE_COLUMN;
+    private static final String RAW_CHECKSUM_FIELD_NAME = MetadataDbHelper.RAW_CHECKSUM_COLUMN;
     private static final String CHECKSUM_FIELD_NAME = MetadataDbHelper.CHECKSUM_COLUMN;
     private static final String REMOTE_FILENAME_FIELD_NAME =
             MetadataDbHelper.REMOTE_FILENAME_COLUMN;
@@ -80,6 +81,7 @@ public class MetadataParser {
                 arguments.get(DESCRIPTION_FIELD_NAME),
                 Long.parseLong(arguments.get(UPDATE_FIELD_NAME)),
                 Long.parseLong(arguments.get(FILESIZE_FIELD_NAME)),
+                arguments.get(RAW_CHECKSUM_FIELD_NAME),
                 arguments.get(CHECKSUM_FIELD_NAME),
                 null,
                 arguments.get(REMOTE_FILENAME_FIELD_NAME),
diff --git a/java/src/com/android/inputmethod/dictionarypack/WordListMetadata.java b/java/src/com/android/inputmethod/dictionarypack/WordListMetadata.java
index 69bff9597d..9e510a68bf 100644
--- a/java/src/com/android/inputmethod/dictionarypack/WordListMetadata.java
+++ b/java/src/com/android/inputmethod/dictionarypack/WordListMetadata.java
@@ -30,6 +30,7 @@ public class WordListMetadata {
     public final String mDescription;
     public final long mLastUpdate;
     public final long mFileSize;
+    public final String mRawChecksum;
     public final String mChecksum;
     public final String mLocalFilename;
     public final String mRemoteFilename;
@@ -50,13 +51,15 @@ public class WordListMetadata {
 
     public WordListMetadata(final String id, final int type,
             final String description, final long lastUpdate, final long fileSize,
-            final String checksum, final String localFilename, final String remoteFilename,
-            final int version, final int formatVersion, final int flags, final String locale) {
+            final String rawChecksum, final String checksum, final String localFilename,
+            final String remoteFilename, final int version, final int formatVersion,
+            final int flags, final String locale) {
         mId = id;
         mType = type;
         mDescription = description;
         mLastUpdate = lastUpdate; // In milliseconds
         mFileSize = fileSize;
+        mRawChecksum = rawChecksum;
         mChecksum = checksum;
         mLocalFilename = localFilename;
         mRemoteFilename = remoteFilename;
@@ -77,6 +80,7 @@ public class WordListMetadata {
         final String description = values.getAsString(MetadataDbHelper.DESCRIPTION_COLUMN);
         final Long lastUpdate = values.getAsLong(MetadataDbHelper.DATE_COLUMN);
         final Long fileSize = values.getAsLong(MetadataDbHelper.FILESIZE_COLUMN);
+        final String rawChecksum = values.getAsString(MetadataDbHelper.RAW_CHECKSUM_COLUMN);
         final String checksum = values.getAsString(MetadataDbHelper.CHECKSUM_COLUMN);
         final String localFilename = values.getAsString(MetadataDbHelper.LOCAL_FILENAME_COLUMN);
         final String remoteFilename = values.getAsString(MetadataDbHelper.REMOTE_FILENAME_COLUMN);
@@ -98,8 +102,8 @@ public class WordListMetadata {
                 || null == locale) {
             throw new IllegalArgumentException();
         }
-        return new WordListMetadata(id, type, description, lastUpdate, fileSize, checksum,
-                localFilename, remoteFilename, version, formatVersion, flags, locale);
+        return new WordListMetadata(id, type, description, lastUpdate, fileSize, rawChecksum,
+                checksum, localFilename, remoteFilename, version, formatVersion, flags, locale);
     }
 
     @Override
@@ -110,6 +114,7 @@ public class WordListMetadata {
         sb.append("\nDescription : ").append(mDescription);
         sb.append("\nLastUpdate : ").append(mLastUpdate);
         sb.append("\nFileSize : ").append(mFileSize);
+        sb.append("\nRawChecksum : ").append(mRawChecksum);
         sb.append("\nChecksum : ").append(mChecksum);
         sb.append("\nLocalFilename : ").append(mLocalFilename);
         sb.append("\nRemoteFilename : ").append(mRemoteFilename);
-- 
GitLab