Search in sources :

Example 6 with MimeStructureState

use of com.fsck.k9.mailstore.migrations.MigrationTo51.MimeStructureState in project k-9 by k9mail.

the class MigrationMimeStructureStateTest method init_apply_nextmulti_nextchild_shouldCrash.

@Test(expected = IllegalStateException.class)
public void init_apply_nextmulti_nextchild_shouldCrash() throws Exception {
    MimeStructureState state = MimeStructureState.getNewRootState();
    ContentValues cv = new ContentValues();
    state.applyValues(cv);
    state.nextMultipartChild(1);
    state.nextChild(1);
}
Also used : ContentValues(android.content.ContentValues) MimeStructureState(com.fsck.k9.mailstore.migrations.MigrationTo51.MimeStructureState) Test(org.junit.Test)

Example 7 with MimeStructureState

use of com.fsck.k9.mailstore.migrations.MigrationTo51.MimeStructureState in project k-9 by k9mail.

the class MigrationTo51 method db51MigrateMessageFormat.

/**
     * This method converts from the old message table structure to the new one.
     *
     * This is a complex migration, and ultimately we do not have enough
     * information to recreate the mime structure of the original mails.
     * What we have:
     *  - general mail info
     *  - html_content and text_content data, which is the squashed readable content of the mail
     *  - a table with message headers
     *  - attachments
     *
     * What we need to do:
     *  - migrate general mail info as-is
     *  - flag mails as migrated for re-download
     *  - for each message, recreate a mime structure from its message content and attachments:
     *    + insert one or both of textContent and htmlContent, depending on mimeType
     *    + if mimeType is text/plain, text/html or multipart/alternative and no
     *      attachments are present, just insert that.
     *    + otherwise, use multipart/mixed, adding attachments after textual content
     *    + revert content:// URIs in htmlContent to original cid: URIs.
     */
public static void db51MigrateMessageFormat(SQLiteDatabase db, MigrationsHelper migrationsHelper) {
    renameOldMessagesTableAndCreateNew(db);
    copyMessageMetadataToNewTable(db);
    File attachmentDirNew, attachmentDirOld;
    Account account = migrationsHelper.getAccount();
    attachmentDirNew = StorageManager.getInstance(K9.app).getAttachmentDirectory(account.getUuid(), account.getLocalStorageProviderId());
    attachmentDirOld = renameOldAttachmentDirAndCreateNew(account, attachmentDirNew);
    Cursor msgCursor = db.query("messages_old", new String[] { "id", "flags", "html_content", "text_content", "mime_type", "attachment_count" }, null, null, null, null, null);
    try {
        Timber.d("migrating %d messages", msgCursor.getCount());
        ContentValues cv = new ContentValues();
        while (msgCursor.moveToNext()) {
            long messageId = msgCursor.getLong(0);
            String messageFlags = msgCursor.getString(1);
            String htmlContent = msgCursor.getString(2);
            String textContent = msgCursor.getString(3);
            String mimeType = msgCursor.getString(4);
            int attachmentCount = msgCursor.getInt(5);
            try {
                updateFlagsForMessage(db, messageId, messageFlags, migrationsHelper);
                MimeHeader mimeHeader = loadHeaderFromHeadersTable(db, messageId);
                MimeStructureState structureState = MimeStructureState.getNewRootState();
                boolean messageHadSpecialFormat = false;
                // we do not rely on the protocol parameter here but guess by the multipart structure
                boolean isMaybePgpMimeEncrypted = attachmentCount == 2 && MimeUtil.isSameMimeType(mimeType, "multipart/encrypted");
                if (isMaybePgpMimeEncrypted) {
                    MimeStructureState maybeStructureState = migratePgpMimeEncryptedContent(db, messageId, attachmentDirOld, attachmentDirNew, mimeHeader, structureState);
                    if (maybeStructureState != null) {
                        structureState = maybeStructureState;
                        messageHadSpecialFormat = true;
                    }
                }
                if (!messageHadSpecialFormat) {
                    boolean isSimpleStructured = attachmentCount == 0 && Utility.isAnyMimeType(mimeType, "text/plain", "text/html", "multipart/alternative");
                    if (isSimpleStructured) {
                        structureState = migrateSimpleMailContent(db, htmlContent, textContent, mimeType, mimeHeader, structureState);
                    } else {
                        mimeType = "multipart/mixed";
                        structureState = migrateComplexMailContent(db, attachmentDirOld, attachmentDirNew, messageId, htmlContent, textContent, mimeHeader, structureState);
                    }
                }
                cv.clear();
                cv.put("mime_type", mimeType);
                cv.put("message_part_id", structureState.rootPartId);
                cv.put("attachment_count", attachmentCount);
                db.update("messages", cv, "id = ?", new String[] { Long.toString(messageId) });
            } catch (IOException e) {
                Timber.e(e, "error inserting into database");
            }
        }
    } finally {
        msgCursor.close();
    }
    cleanUpOldAttachmentDirectory(attachmentDirOld);
    dropOldMessagesTable(db);
}
Also used : ContentValues(android.content.ContentValues) Account(com.fsck.k9.Account) MimeHeader(com.fsck.k9.mail.internet.MimeHeader) IOException(java.io.IOException) Cursor(android.database.Cursor) File(java.io.File)

Example 8 with MimeStructureState

use of com.fsck.k9.mailstore.migrations.MigrationTo51.MimeStructureState in project k-9 by k9mail.

the class MigrationTo51 method insertTextualPartIntoDatabase.

private static MimeStructureState insertTextualPartIntoDatabase(SQLiteDatabase db, MimeStructureState structureState, MimeHeader mimeHeader, String content, boolean isHtml) throws IOException {
    if (mimeHeader == null) {
        mimeHeader = new MimeHeader();
    }
    mimeHeader.setHeader(MimeHeader.HEADER_CONTENT_TYPE, isHtml ? "text/html; charset=\"utf-8\"" : "text/plain; charset=\"utf-8\"");
    mimeHeader.setHeader(MimeHeader.HEADER_CONTENT_TRANSFER_ENCODING, MimeUtil.ENC_QUOTED_PRINTABLE);
    byte[] contentBytes;
    int decodedBodySize;
    int dataLocation;
    if (content != null) {
        ByteArrayOutputStream contentOutputStream = new ByteArrayOutputStream();
        QuotedPrintableOutputStream quotedPrintableOutputStream = new QuotedPrintableOutputStream(contentOutputStream, false);
        quotedPrintableOutputStream.write(content.getBytes());
        quotedPrintableOutputStream.flush();
        dataLocation = DATA_LOCATION__IN_DATABASE;
        contentBytes = contentOutputStream.toByteArray();
        decodedBodySize = content.length();
    } else {
        dataLocation = DATA_LOCATION__MISSING;
        contentBytes = null;
        decodedBodySize = 0;
    }
    ContentValues cv = new ContentValues();
    cv.put("type", MESSAGE_PART_TYPE__UNKNOWN);
    cv.put("data_location", dataLocation);
    cv.put("mime_type", isHtml ? "text/html" : "text/plain");
    cv.put("header", mimeHeader.toString());
    cv.put("data", contentBytes);
    cv.put("decoded_body_size", decodedBodySize);
    cv.put("encoding", MimeUtil.ENC_QUOTED_PRINTABLE);
    cv.put("charset", "utf-8");
    structureState.applyValues(cv);
    long partId = db.insertOrThrow("message_parts", null, cv);
    return structureState.nextChild(partId);
}
Also used : ContentValues(android.content.ContentValues) QuotedPrintableOutputStream(org.apache.james.mime4j.codec.QuotedPrintableOutputStream) MimeHeader(com.fsck.k9.mail.internet.MimeHeader) ByteArrayOutputStream(java.io.ByteArrayOutputStream)

Example 9 with MimeStructureState

use of com.fsck.k9.mailstore.migrations.MigrationTo51.MimeStructureState in project k-9 by k9mail.

the class MigrationMimeStructureStateTest method init_apply_nextchild_apply_shouldCrash.

@Test(expected = IllegalStateException.class)
public void init_apply_nextchild_apply_shouldCrash() throws Exception {
    MimeStructureState state = MimeStructureState.getNewRootState();
    ContentValues cv = new ContentValues();
    state.applyValues(cv);
    state = state.nextChild(123);
    cv.clear();
    state.applyValues(cv);
}
Also used : ContentValues(android.content.ContentValues) MimeStructureState(com.fsck.k9.mailstore.migrations.MigrationTo51.MimeStructureState) Test(org.junit.Test)

Example 10 with MimeStructureState

use of com.fsck.k9.mailstore.migrations.MigrationTo51.MimeStructureState in project k-9 by k9mail.

the class MigrationMimeStructureStateTest method init_apply_nextchild_nextmulti_shouldCrash.

@Test(expected = IllegalStateException.class)
public void init_apply_nextchild_nextmulti_shouldCrash() throws Exception {
    MimeStructureState state = MimeStructureState.getNewRootState();
    ContentValues cv = new ContentValues();
    state.applyValues(cv);
    state.nextChild(1);
    state.nextMultipartChild(1);
}
Also used : ContentValues(android.content.ContentValues) MimeStructureState(com.fsck.k9.mailstore.migrations.MigrationTo51.MimeStructureState) Test(org.junit.Test)

Aggregations

ContentValues (android.content.ContentValues)12 MimeStructureState (com.fsck.k9.mailstore.migrations.MigrationTo51.MimeStructureState)11 Test (org.junit.Test)11 MimeHeader (com.fsck.k9.mail.internet.MimeHeader)4 File (java.io.File)2 IOException (java.io.IOException)2 Cursor (android.database.Cursor)1 Uri (android.net.Uri)1 Account (com.fsck.k9.Account)1 ByteArrayOutputStream (java.io.ByteArrayOutputStream)1 QuotedPrintableOutputStream (org.apache.james.mime4j.codec.QuotedPrintableOutputStream)1