2009-05-26 23:40:34 +00:00
|
|
|
/*
|
2009-06-15 21:40:06 +00:00
|
|
|
* Copyright (C) 2009 The Android Open Source Project
|
2009-05-26 23:40:34 +00:00
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
package com.android.email.provider;
|
|
|
|
|
2010-09-02 02:06:15 +00:00
|
|
|
import com.android.email.Snippet;
|
2010-07-27 19:52:46 +00:00
|
|
|
import com.android.email.Utility;
|
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
import android.content.ContentProviderOperation;
|
|
|
|
import android.content.ContentProviderResult;
|
2009-08-12 10:51:26 +00:00
|
|
|
import android.content.ContentResolver;
|
2009-05-26 23:40:34 +00:00
|
|
|
import android.content.ContentUris;
|
|
|
|
import android.content.ContentValues;
|
|
|
|
import android.content.Context;
|
2009-06-15 21:40:06 +00:00
|
|
|
import android.content.OperationApplicationException;
|
2009-05-26 23:40:34 +00:00
|
|
|
import android.database.Cursor;
|
|
|
|
import android.net.Uri;
|
2009-07-15 22:08:53 +00:00
|
|
|
import android.os.Environment;
|
2009-06-15 21:40:06 +00:00
|
|
|
import android.os.Parcel;
|
|
|
|
import android.os.Parcelable;
|
|
|
|
import android.os.RemoteException;
|
|
|
|
|
2009-07-15 22:08:53 +00:00
|
|
|
import java.io.File;
|
2009-06-15 21:40:06 +00:00
|
|
|
import java.net.URI;
|
|
|
|
import java.net.URISyntaxException;
|
2010-09-02 21:49:36 +00:00
|
|
|
import java.security.InvalidParameterException;
|
2009-06-15 21:40:06 +00:00
|
|
|
import java.util.ArrayList;
|
2010-03-02 21:03:27 +00:00
|
|
|
import java.util.List;
|
2009-06-15 21:40:06 +00:00
|
|
|
import java.util.UUID;
|
2009-05-26 23:40:34 +00:00
|
|
|
|
2009-07-17 23:29:35 +00:00
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
/**
|
|
|
|
* EmailContent is the superclass of the various classes of content stored by EmailProvider.
|
2009-07-30 18:41:31 +00:00
|
|
|
*
|
2009-06-15 21:40:06 +00:00
|
|
|
* It is intended to include 1) column definitions for use with the Provider, and 2) convenience
|
|
|
|
* methods for saving and retrieving content from the Provider.
|
2009-07-30 18:41:31 +00:00
|
|
|
*
|
2009-06-15 21:40:06 +00:00
|
|
|
* This class will be used by 1) the Email process (which includes the application and
|
|
|
|
* EmaiLProvider) as well as 2) the Exchange process (which runs independently). It will
|
|
|
|
* necessarily be cloned for use in these two cases.
|
2009-07-30 18:41:31 +00:00
|
|
|
*
|
2009-06-15 21:40:06 +00:00
|
|
|
* Conventions used in naming columns:
|
|
|
|
* RECORD_ID is the primary key for all Email records
|
2009-07-30 18:41:31 +00:00
|
|
|
* The SyncColumns interface is used by all classes that are synced to the server directly
|
2009-06-15 21:40:06 +00:00
|
|
|
* (Mailbox and Email)
|
2009-07-30 18:41:31 +00:00
|
|
|
*
|
2009-06-15 21:40:06 +00:00
|
|
|
* <name>_KEY always refers to a foreign key
|
|
|
|
* <name>_ID always refers to a unique identifier (whether on client, server, etc.)
|
|
|
|
*
|
|
|
|
*/
|
2009-05-26 23:40:34 +00:00
|
|
|
public abstract class EmailContent {
|
2009-06-15 21:40:06 +00:00
|
|
|
public static final String AUTHORITY = EmailProvider.EMAIL_AUTHORITY;
|
|
|
|
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY);
|
2010-09-29 15:43:31 +00:00
|
|
|
public static final String PARAMETER_LIMIT = "limit";
|
2010-09-28 01:29:50 +00:00
|
|
|
|
2009-08-12 10:51:26 +00:00
|
|
|
// All classes share this
|
|
|
|
public static final String RECORD_ID = "_id";
|
2009-06-15 21:40:06 +00:00
|
|
|
|
|
|
|
private static final String[] COUNT_COLUMNS = new String[]{"count(*)"};
|
2009-08-20 18:09:39 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* This projection can be used with any of the EmailContent classes, when all you need
|
|
|
|
* is a list of id's. Use ID_PROJECTION_COLUMN to access the row data.
|
|
|
|
*/
|
2009-08-12 10:51:26 +00:00
|
|
|
public static final String[] ID_PROJECTION = new String[] {
|
|
|
|
RECORD_ID
|
|
|
|
};
|
2009-08-20 18:09:39 +00:00
|
|
|
public static final int ID_PROJECTION_COLUMN = 0;
|
2009-06-15 21:40:06 +00:00
|
|
|
|
2010-07-30 20:53:59 +00:00
|
|
|
public static final String ID_SELECTION = RECORD_ID + " =?";
|
2010-03-05 23:04:11 +00:00
|
|
|
|
2009-08-20 02:07:29 +00:00
|
|
|
public static final String FIELD_COLUMN_NAME = "field";
|
|
|
|
public static final String ADD_COLUMN_NAME = "add";
|
|
|
|
|
2009-05-26 23:40:34 +00:00
|
|
|
// Newly created objects get this id
|
2010-08-10 00:48:53 +00:00
|
|
|
public static final int NOT_SAVED = -1;
|
2009-05-26 23:40:34 +00:00
|
|
|
// The base Uri that this piece of content came from
|
2009-05-28 18:46:09 +00:00
|
|
|
public Uri mBaseUri;
|
2009-05-26 23:40:34 +00:00
|
|
|
// Lazily initialized uri for this Content
|
2009-05-28 18:46:09 +00:00
|
|
|
private Uri mUri = null;
|
2009-05-26 23:40:34 +00:00
|
|
|
// The id of the Content
|
2009-05-28 18:46:09 +00:00
|
|
|
public long mId = NOT_SAVED;
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2009-05-26 23:40:34 +00:00
|
|
|
// Write the Content into a ContentValues container
|
|
|
|
public abstract ContentValues toContentValues();
|
|
|
|
// Read the Content from a ContentCursor
|
|
|
|
public abstract <T extends EmailContent> T restore (Cursor cursor);
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2009-05-26 23:40:34 +00:00
|
|
|
// The Uri is lazily initialized
|
|
|
|
public Uri getUri() {
|
2009-06-15 21:40:06 +00:00
|
|
|
if (mUri == null) {
|
2009-05-28 18:46:09 +00:00
|
|
|
mUri = ContentUris.withAppendedId(mBaseUri, mId);
|
2009-06-15 21:40:06 +00:00
|
|
|
}
|
2009-05-28 18:46:09 +00:00
|
|
|
return mUri;
|
2009-05-26 23:40:34 +00:00
|
|
|
}
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2009-05-26 23:40:34 +00:00
|
|
|
public boolean isSaved() {
|
2009-05-28 18:46:09 +00:00
|
|
|
return mId != NOT_SAVED;
|
2009-05-26 23:40:34 +00:00
|
|
|
}
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2009-05-26 23:40:34 +00:00
|
|
|
@SuppressWarnings("unchecked")
|
|
|
|
// The Content sub class must have a no-arg constructor
|
|
|
|
static public <T extends EmailContent> T getContent(Cursor cursor, Class<T> klass) {
|
|
|
|
try {
|
|
|
|
T content = klass.newInstance();
|
2009-05-28 18:46:09 +00:00
|
|
|
content.mId = cursor.getLong(0);
|
2009-05-26 23:40:34 +00:00
|
|
|
return (T)content.restore(cursor);
|
|
|
|
} catch (IllegalAccessException e) {
|
|
|
|
e.printStackTrace();
|
|
|
|
} catch (InstantiationException e) {
|
|
|
|
e.printStackTrace();
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2009-05-26 23:40:34 +00:00
|
|
|
public Uri save(Context context) {
|
2009-07-22 22:13:30 +00:00
|
|
|
if (isSaved()) {
|
|
|
|
throw new UnsupportedOperationException();
|
|
|
|
}
|
2009-05-28 18:46:09 +00:00
|
|
|
Uri res = context.getContentResolver().insert(mBaseUri, toContentValues());
|
|
|
|
mId = Long.parseLong(res.getPathSegments().get(1));
|
2009-05-26 23:40:34 +00:00
|
|
|
return res;
|
|
|
|
}
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2009-05-26 23:40:34 +00:00
|
|
|
public int update(Context context, ContentValues contentValues) {
|
2009-07-22 22:13:30 +00:00
|
|
|
if (!isSaved()) {
|
|
|
|
throw new UnsupportedOperationException();
|
|
|
|
}
|
2009-05-26 23:40:34 +00:00
|
|
|
return context.getContentResolver().update(getUri(), contentValues, null, null);
|
|
|
|
}
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
static public int update(Context context, Uri baseUri, long id, ContentValues contentValues) {
|
|
|
|
return context.getContentResolver()
|
|
|
|
.update(ContentUris.withAppendedId(baseUri, id), contentValues, null, null);
|
|
|
|
}
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2010-08-10 00:48:53 +00:00
|
|
|
static public int delete(Context context, Uri baseUri, long id) {
|
|
|
|
return context.getContentResolver()
|
|
|
|
.delete(ContentUris.withAppendedId(baseUri, id), null, null);
|
|
|
|
}
|
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
/**
|
|
|
|
* Generic count method that can be used for any ContentProvider
|
2010-08-04 22:38:25 +00:00
|
|
|
*
|
2009-06-15 21:40:06 +00:00
|
|
|
* @param context the calling Context
|
|
|
|
* @param uri the Uri for the provider query
|
|
|
|
* @param selection as with a query call
|
|
|
|
* @param selectionArgs as with a query call
|
|
|
|
* @return the number of items matching the query (or zero)
|
|
|
|
*/
|
2009-06-22 23:13:03 +00:00
|
|
|
static public int count(Context context, Uri uri, String selection, String[] selectionArgs) {
|
2010-07-27 19:52:46 +00:00
|
|
|
return Utility.getFirstRowLong(context,
|
|
|
|
uri, COUNT_COLUMNS, selection, selectionArgs, null, 0, Long.valueOf(0)).intValue();
|
2009-06-15 21:40:06 +00:00
|
|
|
}
|
|
|
|
|
2010-08-04 22:38:25 +00:00
|
|
|
/**
|
|
|
|
* Same as {@link #count(Context, Uri, String, String[])} without selection.
|
|
|
|
*/
|
|
|
|
static public int count(Context context, Uri uri) {
|
|
|
|
return count(context, uri, null, null);
|
|
|
|
}
|
|
|
|
|
2010-09-28 01:29:50 +00:00
|
|
|
static public Uri uriWithLimit(Uri uri, int limit) {
|
2010-09-29 15:43:31 +00:00
|
|
|
return uri.buildUpon().appendQueryParameter(EmailContent.PARAMETER_LIMIT,
|
2010-09-28 01:29:50 +00:00
|
|
|
Integer.toString(limit)).build();
|
|
|
|
}
|
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
/**
|
|
|
|
* no public constructor since this is a utility class
|
|
|
|
*/
|
|
|
|
private EmailContent() {
|
|
|
|
}
|
|
|
|
|
|
|
|
public interface SyncColumns {
|
2009-08-12 10:51:26 +00:00
|
|
|
public static final String ID = "_id";
|
2009-06-15 21:40:06 +00:00
|
|
|
// source id (string) : the source's name of this item
|
|
|
|
public static final String SERVER_ID = "syncServerId";
|
2009-09-23 01:31:10 +00:00
|
|
|
// source's timestamp (long) for this item
|
|
|
|
public static final String SERVER_TIMESTAMP = "syncServerTimeStamp";
|
2009-06-15 21:40:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public interface BodyColumns {
|
2009-08-12 10:51:26 +00:00
|
|
|
public static final String ID = "_id";
|
2009-06-15 21:40:06 +00:00
|
|
|
// Foreign key to the message corresponding to this body
|
2009-07-30 18:41:31 +00:00
|
|
|
public static final String MESSAGE_KEY = "messageKey";
|
2009-06-15 21:40:06 +00:00
|
|
|
// The html content itself
|
2009-07-30 18:41:31 +00:00
|
|
|
public static final String HTML_CONTENT = "htmlContent";
|
2009-06-15 21:40:06 +00:00
|
|
|
// The plain text content itself
|
2009-07-30 18:41:31 +00:00
|
|
|
public static final String TEXT_CONTENT = "textContent";
|
2009-09-02 06:19:12 +00:00
|
|
|
// Replied-to or forwarded body (in html form)
|
|
|
|
public static final String HTML_REPLY = "htmlReply";
|
|
|
|
// Replied-to or forwarded body (in text form)
|
|
|
|
public static final String TEXT_REPLY = "textReply";
|
2009-12-04 20:49:28 +00:00
|
|
|
// A reference to a message's unique id used in reply/forward.
|
|
|
|
// Protocol code can be expected to use this column in determining whether a message can be
|
|
|
|
// deleted safely (i.e. isn't referenced by other messages)
|
2009-09-07 23:03:02 +00:00
|
|
|
public static final String SOURCE_MESSAGE_KEY = "sourceMessageKey";
|
2009-09-23 01:38:28 +00:00
|
|
|
// The text to be placed between a reply/forward response and the original message
|
|
|
|
public static final String INTRO_TEXT = "introText";
|
2009-06-15 21:40:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public static final class Body extends EmailContent implements BodyColumns {
|
2009-06-16 19:03:45 +00:00
|
|
|
public static final String TABLE_NAME = "Body";
|
2010-09-10 22:19:57 +00:00
|
|
|
|
|
|
|
@SuppressWarnings("hiding")
|
2009-06-16 19:03:45 +00:00
|
|
|
public static final Uri CONTENT_URI = Uri.parse(EmailContent.CONTENT_URI + "/body");
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
public static final int CONTENT_ID_COLUMN = 0;
|
|
|
|
public static final int CONTENT_MESSAGE_KEY_COLUMN = 1;
|
|
|
|
public static final int CONTENT_HTML_CONTENT_COLUMN = 2;
|
|
|
|
public static final int CONTENT_TEXT_CONTENT_COLUMN = 3;
|
2009-09-02 06:19:12 +00:00
|
|
|
public static final int CONTENT_HTML_REPLY_COLUMN = 4;
|
|
|
|
public static final int CONTENT_TEXT_REPLY_COLUMN = 5;
|
2009-09-07 23:03:02 +00:00
|
|
|
public static final int CONTENT_SOURCE_KEY_COLUMN = 6;
|
2009-09-23 01:38:28 +00:00
|
|
|
public static final int CONTENT_INTRO_TEXT_COLUMN = 7;
|
2009-07-30 18:41:31 +00:00
|
|
|
public static final String[] CONTENT_PROJECTION = new String[] {
|
2009-09-02 06:19:12 +00:00
|
|
|
RECORD_ID, BodyColumns.MESSAGE_KEY, BodyColumns.HTML_CONTENT, BodyColumns.TEXT_CONTENT,
|
2009-09-23 01:38:28 +00:00
|
|
|
BodyColumns.HTML_REPLY, BodyColumns.TEXT_REPLY, BodyColumns.SOURCE_MESSAGE_KEY,
|
|
|
|
BodyColumns.INTRO_TEXT
|
2009-06-15 21:40:06 +00:00
|
|
|
};
|
|
|
|
|
2009-09-25 21:54:32 +00:00
|
|
|
public static final String[] COMMON_PROJECTION_TEXT = new String[] {
|
2009-06-15 21:40:06 +00:00
|
|
|
RECORD_ID, BodyColumns.TEXT_CONTENT
|
|
|
|
};
|
2009-09-25 21:54:32 +00:00
|
|
|
public static final String[] COMMON_PROJECTION_HTML = new String[] {
|
2009-06-15 21:40:06 +00:00
|
|
|
RECORD_ID, BodyColumns.HTML_CONTENT
|
|
|
|
};
|
2009-09-25 21:54:32 +00:00
|
|
|
public static final String[] COMMON_PROJECTION_REPLY_TEXT = new String[] {
|
|
|
|
RECORD_ID, BodyColumns.TEXT_REPLY
|
|
|
|
};
|
|
|
|
public static final String[] COMMON_PROJECTION_REPLY_HTML = new String[] {
|
2009-09-23 14:50:31 +00:00
|
|
|
RECORD_ID, BodyColumns.HTML_REPLY
|
|
|
|
};
|
2009-09-25 21:54:32 +00:00
|
|
|
public static final String[] COMMON_PROJECTION_INTRO = new String[] {
|
|
|
|
RECORD_ID, BodyColumns.INTRO_TEXT
|
2009-09-23 14:50:31 +00:00
|
|
|
};
|
2010-08-10 00:48:53 +00:00
|
|
|
public static final String[] COMMON_PROJECTION_SOURCE = new String[] {
|
|
|
|
RECORD_ID, BodyColumns.SOURCE_MESSAGE_KEY
|
|
|
|
};
|
|
|
|
public static final int COMMON_PROJECTION_COLUMN_TEXT = 1;
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2010-02-15 13:56:40 +00:00
|
|
|
private static final String[] PROJECTION_SOURCE_KEY =
|
|
|
|
new String[] { BodyColumns.SOURCE_MESSAGE_KEY };
|
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
public long mMessageKey;
|
|
|
|
public String mHtmlContent;
|
|
|
|
public String mTextContent;
|
2009-09-02 06:19:12 +00:00
|
|
|
public String mHtmlReply;
|
|
|
|
public String mTextReply;
|
2009-09-07 23:03:02 +00:00
|
|
|
public long mSourceKey;
|
2009-09-23 01:38:28 +00:00
|
|
|
public String mIntroText;
|
2009-06-15 21:40:06 +00:00
|
|
|
|
2009-06-24 19:48:57 +00:00
|
|
|
public Body() {
|
2009-06-15 21:40:06 +00:00
|
|
|
mBaseUri = CONTENT_URI;
|
|
|
|
}
|
|
|
|
|
2009-09-25 21:54:32 +00:00
|
|
|
@Override
|
2009-06-15 21:40:06 +00:00
|
|
|
public ContentValues toContentValues() {
|
|
|
|
ContentValues values = new ContentValues();
|
|
|
|
|
|
|
|
// Assign values for each row.
|
|
|
|
values.put(BodyColumns.MESSAGE_KEY, mMessageKey);
|
|
|
|
values.put(BodyColumns.HTML_CONTENT, mHtmlContent);
|
|
|
|
values.put(BodyColumns.TEXT_CONTENT, mTextContent);
|
2009-09-02 06:19:12 +00:00
|
|
|
values.put(BodyColumns.HTML_REPLY, mHtmlReply);
|
|
|
|
values.put(BodyColumns.TEXT_REPLY, mTextReply);
|
2009-09-07 23:03:02 +00:00
|
|
|
values.put(BodyColumns.SOURCE_MESSAGE_KEY, mSourceKey);
|
2009-09-23 01:38:28 +00:00
|
|
|
values.put(BodyColumns.INTRO_TEXT, mIntroText);
|
2009-06-15 21:40:06 +00:00
|
|
|
return values;
|
|
|
|
}
|
|
|
|
|
2009-09-25 21:54:32 +00:00
|
|
|
private static Body restoreBodyWithCursor(Cursor cursor) {
|
|
|
|
try {
|
|
|
|
if (cursor.moveToFirst()) {
|
|
|
|
return getContent(cursor, Body.class);
|
|
|
|
} else {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
} finally {
|
|
|
|
cursor.close();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public static Body restoreBodyWithId(Context context, long id) {
|
|
|
|
Uri u = ContentUris.withAppendedId(Body.CONTENT_URI, id);
|
|
|
|
Cursor c = context.getContentResolver().query(u, Body.CONTENT_PROJECTION,
|
|
|
|
null, null, null);
|
|
|
|
return restoreBodyWithCursor(c);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static Body restoreBodyWithMessageId(Context context, long messageId) {
|
|
|
|
Cursor c = context.getContentResolver().query(Body.CONTENT_URI,
|
|
|
|
Body.CONTENT_PROJECTION, Body.MESSAGE_KEY + "=?",
|
|
|
|
new String[] {Long.toString(messageId)}, null);
|
|
|
|
return restoreBodyWithCursor(c);
|
|
|
|
}
|
2009-07-17 23:29:35 +00:00
|
|
|
|
2009-08-12 10:51:26 +00:00
|
|
|
/**
|
|
|
|
* Returns the bodyId for the given messageId, or -1 if no body is found.
|
|
|
|
*/
|
2010-07-27 19:52:46 +00:00
|
|
|
public static long lookupBodyIdWithMessageId(Context context, long messageId) {
|
|
|
|
return Utility.getFirstRowLong(context, Body.CONTENT_URI,
|
|
|
|
ID_PROJECTION, Body.MESSAGE_KEY + "=?",
|
|
|
|
new String[] {Long.toString(messageId)}, null, ID_PROJECTION_COLUMN,
|
|
|
|
Long.valueOf(-1));
|
2009-08-12 10:51:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Updates the Body for a messageId with the given ContentValues.
|
|
|
|
* If the message has no body, a new body is inserted for the message.
|
|
|
|
* Warning: the argument "values" is modified by this method, setting MESSAGE_KEY.
|
|
|
|
*/
|
2009-08-20 02:07:29 +00:00
|
|
|
public static void updateBodyWithMessageId(Context context, long messageId,
|
2009-08-12 10:51:26 +00:00
|
|
|
ContentValues values) {
|
|
|
|
ContentResolver resolver = context.getContentResolver();
|
2010-07-27 19:52:46 +00:00
|
|
|
long bodyId = lookupBodyIdWithMessageId(context, messageId);
|
2009-08-12 10:51:26 +00:00
|
|
|
values.put(BodyColumns.MESSAGE_KEY, messageId);
|
|
|
|
if (bodyId == -1) {
|
|
|
|
resolver.insert(CONTENT_URI, values);
|
|
|
|
} else {
|
|
|
|
final Uri uri = ContentUris.withAppendedId(CONTENT_URI, bodyId);
|
|
|
|
resolver.update(uri, values, null, null);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-02-15 13:56:40 +00:00
|
|
|
public static long restoreBodySourceKey(Context context, long messageId) {
|
2010-07-27 19:52:46 +00:00
|
|
|
return Utility.getFirstRowLong(context, Body.CONTENT_URI,
|
2010-02-15 13:56:40 +00:00
|
|
|
Body.PROJECTION_SOURCE_KEY,
|
2010-07-27 19:52:46 +00:00
|
|
|
Body.MESSAGE_KEY + "=?", new String[] {Long.toString(messageId)}, null, 0,
|
|
|
|
Long.valueOf(0));
|
2010-02-15 13:56:40 +00:00
|
|
|
}
|
|
|
|
|
2009-09-25 21:54:32 +00:00
|
|
|
private static String restoreTextWithMessageId(Context context, long messageId,
|
|
|
|
String[] projection) {
|
2009-07-17 23:29:35 +00:00
|
|
|
Cursor c = context.getContentResolver().query(Body.CONTENT_URI, projection,
|
|
|
|
Body.MESSAGE_KEY + "=?", new String[] {Long.toString(messageId)}, null);
|
2009-06-15 21:40:06 +00:00
|
|
|
try {
|
|
|
|
if (c.moveToFirst()) {
|
2009-09-25 21:54:32 +00:00
|
|
|
return c.getString(COMMON_PROJECTION_COLUMN_TEXT);
|
2009-06-15 21:40:06 +00:00
|
|
|
} else {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
} finally {
|
|
|
|
c.close();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-07-17 23:29:35 +00:00
|
|
|
public static String restoreBodyTextWithMessageId(Context context, long messageId) {
|
2009-09-25 21:54:32 +00:00
|
|
|
return restoreTextWithMessageId(context, messageId, Body.COMMON_PROJECTION_TEXT);
|
2009-06-15 21:40:06 +00:00
|
|
|
}
|
|
|
|
|
2009-07-17 23:29:35 +00:00
|
|
|
public static String restoreBodyHtmlWithMessageId(Context context, long messageId) {
|
2009-09-25 21:54:32 +00:00
|
|
|
return restoreTextWithMessageId(context, messageId, Body.COMMON_PROJECTION_HTML);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static String restoreReplyTextWithMessageId(Context context, long messageId) {
|
|
|
|
return restoreTextWithMessageId(context, messageId, Body.COMMON_PROJECTION_REPLY_TEXT);
|
2009-06-15 21:40:06 +00:00
|
|
|
}
|
|
|
|
|
2009-09-25 21:54:32 +00:00
|
|
|
public static String restoreReplyHtmlWithMessageId(Context context, long messageId) {
|
|
|
|
return restoreTextWithMessageId(context, messageId, Body.COMMON_PROJECTION_REPLY_HTML);
|
2009-09-23 14:50:31 +00:00
|
|
|
}
|
|
|
|
|
2009-09-25 21:54:32 +00:00
|
|
|
public static String restoreIntroTextWithMessageId(Context context, long messageId) {
|
|
|
|
return restoreTextWithMessageId(context, messageId, Body.COMMON_PROJECTION_INTRO);
|
2009-09-23 14:50:31 +00:00
|
|
|
}
|
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
@Override
|
|
|
|
@SuppressWarnings("unchecked")
|
|
|
|
public EmailContent.Body restore(Cursor c) {
|
2009-06-24 19:48:57 +00:00
|
|
|
mBaseUri = EmailContent.Body.CONTENT_URI;
|
2009-06-15 21:40:06 +00:00
|
|
|
mMessageKey = c.getLong(CONTENT_MESSAGE_KEY_COLUMN);
|
|
|
|
mHtmlContent = c.getString(CONTENT_HTML_CONTENT_COLUMN);
|
|
|
|
mTextContent = c.getString(CONTENT_TEXT_CONTENT_COLUMN);
|
2009-09-02 06:19:12 +00:00
|
|
|
mHtmlReply = c.getString(CONTENT_HTML_REPLY_COLUMN);
|
|
|
|
mTextReply = c.getString(CONTENT_TEXT_REPLY_COLUMN);
|
2009-09-07 23:03:02 +00:00
|
|
|
mSourceKey = c.getLong(CONTENT_SOURCE_KEY_COLUMN);
|
2009-09-23 01:38:28 +00:00
|
|
|
mIntroText = c.getString(CONTENT_INTRO_TEXT_COLUMN);
|
2009-06-15 21:40:06 +00:00
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean update() {
|
|
|
|
// TODO Auto-generated method stub
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public interface MessageColumns {
|
2009-08-12 10:51:26 +00:00
|
|
|
public static final String ID = "_id";
|
2009-06-15 21:40:06 +00:00
|
|
|
// Basic columns used in message list presentation
|
|
|
|
// The name as shown to the user in a message list
|
2009-07-30 18:41:31 +00:00
|
|
|
public static final String DISPLAY_NAME = "displayName";
|
2009-06-15 21:40:06 +00:00
|
|
|
// The time (millis) as shown to the user in a message list [INDEX]
|
2009-07-30 18:41:31 +00:00
|
|
|
public static final String TIMESTAMP = "timeStamp";
|
2009-06-15 21:40:06 +00:00
|
|
|
// Message subject
|
2009-07-30 18:41:31 +00:00
|
|
|
public static final String SUBJECT = "subject";
|
2009-06-15 21:40:06 +00:00
|
|
|
// Boolean, unread = 0, read = 1 [INDEX]
|
2009-07-30 18:41:31 +00:00
|
|
|
public static final String FLAG_READ = "flagRead";
|
2009-09-10 18:52:36 +00:00
|
|
|
// Load state, see constants below (unloaded, partial, complete, deleted)
|
2009-07-30 18:41:31 +00:00
|
|
|
public static final String FLAG_LOADED = "flagLoaded";
|
2009-06-15 21:40:06 +00:00
|
|
|
// Boolean, unflagged = 0, flagged (favorite) = 1
|
2009-07-30 18:41:31 +00:00
|
|
|
public static final String FLAG_FAVORITE = "flagFavorite";
|
2009-06-15 21:40:06 +00:00
|
|
|
// Boolean, no attachment = 0, attachment = 1
|
2009-07-30 18:41:31 +00:00
|
|
|
public static final String FLAG_ATTACHMENT = "flagAttachment";
|
2009-09-02 06:19:12 +00:00
|
|
|
// Bit field for flags which we'll not be selecting on
|
2009-07-30 18:41:31 +00:00
|
|
|
public static final String FLAGS = "flags";
|
2009-06-15 21:40:06 +00:00
|
|
|
|
|
|
|
// Sync related identifiers
|
|
|
|
// Any client-required identifier
|
2009-07-30 18:41:31 +00:00
|
|
|
public static final String CLIENT_ID = "clientId";
|
2009-06-15 21:40:06 +00:00
|
|
|
// The message-id in the message's header
|
2009-07-30 18:41:31 +00:00
|
|
|
public static final String MESSAGE_ID = "messageId";
|
2009-06-15 21:40:06 +00:00
|
|
|
|
|
|
|
// References to other Email objects in the database
|
|
|
|
// Foreign key to the Mailbox holding this message [INDEX]
|
2009-07-30 18:41:31 +00:00
|
|
|
public static final String MAILBOX_KEY = "mailboxKey";
|
2009-06-15 21:40:06 +00:00
|
|
|
// Foreign key to the Account holding this message
|
2009-07-30 18:41:31 +00:00
|
|
|
public static final String ACCOUNT_KEY = "accountKey";
|
2009-06-15 21:40:06 +00:00
|
|
|
|
2009-07-09 21:46:03 +00:00
|
|
|
// Address lists, packed with Address.pack()
|
2009-06-15 21:40:06 +00:00
|
|
|
public static final String FROM_LIST = "fromList";
|
|
|
|
public static final String TO_LIST = "toList";
|
|
|
|
public static final String CC_LIST = "ccList";
|
|
|
|
public static final String BCC_LIST = "bccList";
|
|
|
|
public static final String REPLY_TO_LIST = "replyToList";
|
2010-02-16 00:01:38 +00:00
|
|
|
// Meeting invitation related information (for now, start time in ms)
|
|
|
|
public static final String MEETING_INFO = "meetingInfo";
|
2010-09-02 02:06:15 +00:00
|
|
|
// A text "snippet" derived from the body of the message
|
|
|
|
public static final String SNIPPET = "snippet";
|
2009-06-15 21:40:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public static final class Message extends EmailContent implements SyncColumns, MessageColumns {
|
2009-06-16 19:03:45 +00:00
|
|
|
public static final String TABLE_NAME = "Message";
|
2009-06-27 19:14:14 +00:00
|
|
|
public static final String UPDATED_TABLE_NAME = "Message_Updates";
|
|
|
|
public static final String DELETED_TABLE_NAME = "Message_Deletes";
|
|
|
|
|
|
|
|
// To refer to a specific message, use ContentUris.withAppendedId(CONTENT_URI, id)
|
2010-09-10 22:19:57 +00:00
|
|
|
@SuppressWarnings("hiding")
|
2009-06-16 19:03:45 +00:00
|
|
|
public static final Uri CONTENT_URI = Uri.parse(EmailContent.CONTENT_URI + "/message");
|
2009-06-27 19:14:14 +00:00
|
|
|
public static final Uri SYNCED_CONTENT_URI =
|
|
|
|
Uri.parse(EmailContent.CONTENT_URI + "/syncedMessage");
|
|
|
|
public static final Uri DELETED_CONTENT_URI =
|
|
|
|
Uri.parse(EmailContent.CONTENT_URI + "/deletedMessage");
|
|
|
|
public static final Uri UPDATED_CONTENT_URI =
|
|
|
|
Uri.parse(EmailContent.CONTENT_URI + "/updatedMessage");
|
2009-06-15 21:40:06 +00:00
|
|
|
|
|
|
|
public static final String KEY_TIMESTAMP_DESC = MessageColumns.TIMESTAMP + " desc";
|
|
|
|
|
|
|
|
public static final int CONTENT_ID_COLUMN = 0;
|
|
|
|
public static final int CONTENT_DISPLAY_NAME_COLUMN = 1;
|
|
|
|
public static final int CONTENT_TIMESTAMP_COLUMN = 2;
|
|
|
|
public static final int CONTENT_SUBJECT_COLUMN = 3;
|
2009-09-02 06:19:12 +00:00
|
|
|
public static final int CONTENT_FLAG_READ_COLUMN = 4;
|
|
|
|
public static final int CONTENT_FLAG_LOADED_COLUMN = 5;
|
|
|
|
public static final int CONTENT_FLAG_FAVORITE_COLUMN = 6;
|
|
|
|
public static final int CONTENT_FLAG_ATTACHMENT_COLUMN = 7;
|
|
|
|
public static final int CONTENT_FLAGS_COLUMN = 8;
|
|
|
|
public static final int CONTENT_SERVER_ID_COLUMN = 9;
|
|
|
|
public static final int CONTENT_CLIENT_ID_COLUMN = 10;
|
|
|
|
public static final int CONTENT_MESSAGE_ID_COLUMN = 11;
|
|
|
|
public static final int CONTENT_MAILBOX_KEY_COLUMN = 12;
|
|
|
|
public static final int CONTENT_ACCOUNT_KEY_COLUMN = 13;
|
|
|
|
public static final int CONTENT_FROM_LIST_COLUMN = 14;
|
|
|
|
public static final int CONTENT_TO_LIST_COLUMN = 15;
|
|
|
|
public static final int CONTENT_CC_LIST_COLUMN = 16;
|
|
|
|
public static final int CONTENT_BCC_LIST_COLUMN = 17;
|
|
|
|
public static final int CONTENT_REPLY_TO_COLUMN = 18;
|
2009-09-23 01:31:10 +00:00
|
|
|
public static final int CONTENT_SERVER_TIMESTAMP_COLUMN = 19;
|
2010-02-16 00:01:38 +00:00
|
|
|
public static final int CONTENT_MEETING_INFO_COLUMN = 20;
|
2010-09-02 02:06:15 +00:00
|
|
|
public static final int CONTENT_SNIPPET_COLUMN = 21;
|
2009-09-02 06:19:12 +00:00
|
|
|
|
2009-07-30 18:41:31 +00:00
|
|
|
public static final String[] CONTENT_PROJECTION = new String[] {
|
2009-09-02 06:19:12 +00:00
|
|
|
RECORD_ID,
|
|
|
|
MessageColumns.DISPLAY_NAME, MessageColumns.TIMESTAMP,
|
|
|
|
MessageColumns.SUBJECT, MessageColumns.FLAG_READ,
|
2009-06-15 21:40:06 +00:00
|
|
|
MessageColumns.FLAG_LOADED, MessageColumns.FLAG_FAVORITE,
|
2009-09-02 06:19:12 +00:00
|
|
|
MessageColumns.FLAG_ATTACHMENT, MessageColumns.FLAGS,
|
|
|
|
SyncColumns.SERVER_ID, MessageColumns.CLIENT_ID,
|
|
|
|
MessageColumns.MESSAGE_ID, MessageColumns.MAILBOX_KEY,
|
|
|
|
MessageColumns.ACCOUNT_KEY, MessageColumns.FROM_LIST,
|
|
|
|
MessageColumns.TO_LIST, MessageColumns.CC_LIST,
|
|
|
|
MessageColumns.BCC_LIST, MessageColumns.REPLY_TO_LIST,
|
2010-09-02 02:06:15 +00:00
|
|
|
SyncColumns.SERVER_TIMESTAMP, MessageColumns.MEETING_INFO,
|
|
|
|
MessageColumns.SNIPPET
|
2009-06-15 21:40:06 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
public static final int LIST_ID_COLUMN = 0;
|
|
|
|
public static final int LIST_DISPLAY_NAME_COLUMN = 1;
|
|
|
|
public static final int LIST_TIMESTAMP_COLUMN = 2;
|
|
|
|
public static final int LIST_SUBJECT_COLUMN = 3;
|
2009-09-02 06:19:12 +00:00
|
|
|
public static final int LIST_READ_COLUMN = 4;
|
|
|
|
public static final int LIST_LOADED_COLUMN = 5;
|
|
|
|
public static final int LIST_FAVORITE_COLUMN = 6;
|
|
|
|
public static final int LIST_ATTACHMENT_COLUMN = 7;
|
|
|
|
public static final int LIST_FLAGS_COLUMN = 8;
|
|
|
|
public static final int LIST_MAILBOX_KEY_COLUMN = 9;
|
|
|
|
public static final int LIST_ACCOUNT_KEY_COLUMN = 10;
|
|
|
|
public static final int LIST_SERVER_ID_COLUMN = 11;
|
2010-09-02 02:06:15 +00:00
|
|
|
public static final int LIST_SNIPPET_COLUMN = 12;
|
2009-06-15 21:40:06 +00:00
|
|
|
|
|
|
|
// Public projection for common list columns
|
2009-07-30 18:41:31 +00:00
|
|
|
public static final String[] LIST_PROJECTION = new String[] {
|
2009-09-02 06:19:12 +00:00
|
|
|
RECORD_ID,
|
|
|
|
MessageColumns.DISPLAY_NAME, MessageColumns.TIMESTAMP,
|
|
|
|
MessageColumns.SUBJECT, MessageColumns.FLAG_READ,
|
2009-06-15 21:40:06 +00:00
|
|
|
MessageColumns.FLAG_LOADED, MessageColumns.FLAG_FAVORITE,
|
2009-09-02 06:19:12 +00:00
|
|
|
MessageColumns.FLAG_ATTACHMENT, MessageColumns.FLAGS,
|
|
|
|
MessageColumns.MAILBOX_KEY, MessageColumns.ACCOUNT_KEY,
|
2010-09-02 02:06:15 +00:00
|
|
|
SyncColumns.SERVER_ID, MessageColumns.SNIPPET
|
2009-06-15 21:40:06 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
public static final int ID_COLUMNS_ID_COLUMN = 0;
|
|
|
|
public static final int ID_COLUMNS_SYNC_SERVER_ID = 1;
|
|
|
|
public static final String[] ID_COLUMNS_PROJECTION = new String[] {
|
|
|
|
RECORD_ID, SyncColumns.SERVER_ID
|
|
|
|
};
|
|
|
|
|
2009-09-25 21:54:32 +00:00
|
|
|
public static final int ID_MAILBOX_COLUMN_ID = 0;
|
|
|
|
public static final int ID_MAILBOX_COLUMN_MAILBOX_KEY = 1;
|
|
|
|
public static final String[] ID_MAILBOX_PROJECTION = new String[] {
|
|
|
|
RECORD_ID, MessageColumns.MAILBOX_KEY
|
|
|
|
};
|
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
public static final String[] ID_COLUMN_PROJECTION = new String[] { RECORD_ID };
|
|
|
|
|
2010-08-03 01:16:13 +00:00
|
|
|
private static final String FAVORITE_COUNT_SELECTION =
|
|
|
|
MessageColumns.FLAG_FAVORITE + "= 1";
|
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
// _id field is in AbstractContent
|
|
|
|
public String mDisplayName;
|
|
|
|
public long mTimeStamp;
|
|
|
|
public String mSubject;
|
|
|
|
public boolean mFlagRead = false;
|
2009-09-10 18:52:36 +00:00
|
|
|
public int mFlagLoaded = FLAG_LOADED_UNLOADED;
|
2009-06-15 21:40:06 +00:00
|
|
|
public boolean mFlagFavorite = false;
|
|
|
|
public boolean mFlagAttachment = false;
|
|
|
|
public int mFlags = 0;
|
|
|
|
|
|
|
|
public String mServerId;
|
2009-09-23 01:31:10 +00:00
|
|
|
public long mServerTimeStamp;
|
2009-06-15 21:40:06 +00:00
|
|
|
public String mClientId;
|
|
|
|
public String mMessageId;
|
|
|
|
|
|
|
|
public long mMailboxKey;
|
|
|
|
public long mAccountKey;
|
|
|
|
|
|
|
|
public String mFrom;
|
|
|
|
public String mTo;
|
|
|
|
public String mCc;
|
|
|
|
public String mBcc;
|
|
|
|
public String mReplyTo;
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2010-02-16 00:01:38 +00:00
|
|
|
// For now, just the start time of a meeting invite, in ms
|
|
|
|
public String mMeetingInfo;
|
|
|
|
|
2010-09-02 02:06:15 +00:00
|
|
|
public String mSnippet;
|
|
|
|
|
2009-12-04 20:49:28 +00:00
|
|
|
// The following transient members may be used while building and manipulating messages,
|
2009-09-07 23:03:02 +00:00
|
|
|
// but they are NOT persisted directly by EmailProvider
|
2009-06-15 21:40:06 +00:00
|
|
|
transient public String mText;
|
|
|
|
transient public String mHtml;
|
2009-09-02 06:19:12 +00:00
|
|
|
transient public String mTextReply;
|
|
|
|
transient public String mHtmlReply;
|
2009-09-07 23:03:02 +00:00
|
|
|
transient public long mSourceKey;
|
2009-06-15 21:40:06 +00:00
|
|
|
transient public ArrayList<Attachment> mAttachments = null;
|
2009-09-23 01:38:28 +00:00
|
|
|
transient public String mIntroText;
|
2009-06-15 21:40:06 +00:00
|
|
|
|
2009-09-07 23:03:02 +00:00
|
|
|
// Values used in mFlagRead
|
2009-06-15 21:40:06 +00:00
|
|
|
public static final int UNREAD = 0;
|
|
|
|
public static final int READ = 1;
|
|
|
|
|
2009-09-07 23:03:02 +00:00
|
|
|
// Values used in mFlagLoaded
|
2009-09-10 18:52:36 +00:00
|
|
|
public static final int FLAG_LOADED_UNLOADED = 0;
|
|
|
|
public static final int FLAG_LOADED_COMPLETE = 1;
|
|
|
|
public static final int FLAG_LOADED_PARTIAL = 2;
|
|
|
|
public static final int FLAG_LOADED_DELETED = 3;
|
2009-06-15 21:40:06 +00:00
|
|
|
|
2009-09-07 23:03:02 +00:00
|
|
|
// Bits used in mFlags
|
2010-01-25 20:38:32 +00:00
|
|
|
// The following three states are mutually exclusive, and indicate whether the message is an
|
2009-09-07 23:03:02 +00:00
|
|
|
// original, a reply, or a forward
|
|
|
|
public static final int FLAG_TYPE_ORIGINAL = 0;
|
|
|
|
public static final int FLAG_TYPE_REPLY = 1<<0;
|
|
|
|
public static final int FLAG_TYPE_FORWARD = 1<<1;
|
|
|
|
public static final int FLAG_TYPE_MASK = FLAG_TYPE_REPLY | FLAG_TYPE_FORWARD;
|
2010-02-22 20:57:33 +00:00
|
|
|
// The following flags indicate messages that are determined to be incoming meeting related
|
|
|
|
// (e.g. invites from others)
|
|
|
|
public static final int FLAG_INCOMING_MEETING_INVITE = 1<<2;
|
|
|
|
public static final int FLAG_INCOMING_MEETING_CANCEL = 1<<3;
|
|
|
|
public static final int FLAG_INCOMING_MEETING_MASK =
|
|
|
|
FLAG_INCOMING_MEETING_INVITE | FLAG_INCOMING_MEETING_CANCEL;
|
|
|
|
// The following flags indicate messages that are outgoing and meeting related
|
|
|
|
// (e.g. invites TO others)
|
|
|
|
public static final int FLAG_OUTGOING_MEETING_INVITE = 1<<4;
|
|
|
|
public static final int FLAG_OUTGOING_MEETING_CANCEL = 1<<5;
|
|
|
|
public static final int FLAG_OUTGOING_MEETING_ACCEPT = 1<<6;
|
|
|
|
public static final int FLAG_OUTGOING_MEETING_DECLINE = 1<<7;
|
|
|
|
public static final int FLAG_OUTGOING_MEETING_TENTATIVE = 1<<8;
|
|
|
|
public static final int FLAG_OUTGOING_MEETING_MASK =
|
|
|
|
FLAG_OUTGOING_MEETING_INVITE | FLAG_OUTGOING_MEETING_CANCEL |
|
|
|
|
FLAG_OUTGOING_MEETING_ACCEPT | FLAG_OUTGOING_MEETING_DECLINE |
|
|
|
|
FLAG_OUTGOING_MEETING_TENTATIVE;
|
2010-02-26 21:13:34 +00:00
|
|
|
public static final int FLAG_OUTGOING_MEETING_REQUEST_MASK =
|
|
|
|
FLAG_OUTGOING_MEETING_INVITE | FLAG_OUTGOING_MEETING_CANCEL;
|
2009-09-07 23:03:02 +00:00
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
public Message() {
|
|
|
|
mBaseUri = CONTENT_URI;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public ContentValues toContentValues() {
|
|
|
|
ContentValues values = new ContentValues();
|
|
|
|
|
|
|
|
// Assign values for each row.
|
|
|
|
values.put(MessageColumns.DISPLAY_NAME, mDisplayName);
|
|
|
|
values.put(MessageColumns.TIMESTAMP, mTimeStamp);
|
|
|
|
values.put(MessageColumns.SUBJECT, mSubject);
|
2009-07-30 18:41:31 +00:00
|
|
|
values.put(MessageColumns.FLAG_READ, mFlagRead);
|
|
|
|
values.put(MessageColumns.FLAG_LOADED, mFlagLoaded);
|
|
|
|
values.put(MessageColumns.FLAG_FAVORITE, mFlagFavorite);
|
|
|
|
values.put(MessageColumns.FLAG_ATTACHMENT, mFlagAttachment);
|
2009-06-15 21:40:06 +00:00
|
|
|
values.put(MessageColumns.FLAGS, mFlags);
|
|
|
|
|
2009-09-23 01:31:10 +00:00
|
|
|
values.put(SyncColumns.SERVER_ID, mServerId);
|
|
|
|
values.put(SyncColumns.SERVER_TIMESTAMP, mServerTimeStamp);
|
2009-06-15 21:40:06 +00:00
|
|
|
values.put(MessageColumns.CLIENT_ID, mClientId);
|
|
|
|
values.put(MessageColumns.MESSAGE_ID, mMessageId);
|
|
|
|
|
|
|
|
values.put(MessageColumns.MAILBOX_KEY, mMailboxKey);
|
|
|
|
values.put(MessageColumns.ACCOUNT_KEY, mAccountKey);
|
|
|
|
|
|
|
|
values.put(MessageColumns.FROM_LIST, mFrom);
|
|
|
|
values.put(MessageColumns.TO_LIST, mTo);
|
|
|
|
values.put(MessageColumns.CC_LIST, mCc);
|
|
|
|
values.put(MessageColumns.BCC_LIST, mBcc);
|
|
|
|
values.put(MessageColumns.REPLY_TO_LIST, mReplyTo);
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2010-02-16 00:01:38 +00:00
|
|
|
values.put(MessageColumns.MEETING_INFO, mMeetingInfo);
|
|
|
|
|
2010-09-02 02:06:15 +00:00
|
|
|
values.put(MessageColumns.SNIPPET, mSnippet);
|
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
return values;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static Message restoreMessageWithId(Context context, long id) {
|
|
|
|
Uri u = ContentUris.withAppendedId(Message.CONTENT_URI, id);
|
|
|
|
Cursor c = context.getContentResolver().query(u, Message.CONTENT_PROJECTION,
|
|
|
|
null, null, null);
|
|
|
|
|
|
|
|
try {
|
|
|
|
if (c.moveToFirst()) {
|
|
|
|
return getContent(c, Message.class);
|
|
|
|
} else {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
} finally {
|
|
|
|
c.close();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
@SuppressWarnings("unchecked")
|
|
|
|
public EmailContent.Message restore(Cursor c) {
|
2009-07-17 23:29:35 +00:00
|
|
|
mBaseUri = CONTENT_URI;
|
|
|
|
mId = c.getLong(CONTENT_ID_COLUMN);
|
2009-06-15 21:40:06 +00:00
|
|
|
mDisplayName = c.getString(CONTENT_DISPLAY_NAME_COLUMN);
|
|
|
|
mTimeStamp = c.getLong(CONTENT_TIMESTAMP_COLUMN);
|
|
|
|
mSubject = c.getString(CONTENT_SUBJECT_COLUMN);
|
|
|
|
mFlagRead = c.getInt(CONTENT_FLAG_READ_COLUMN) == 1;
|
|
|
|
mFlagLoaded = c.getInt(CONTENT_FLAG_LOADED_COLUMN);
|
|
|
|
mFlagFavorite = c.getInt(CONTENT_FLAG_FAVORITE_COLUMN) == 1;
|
|
|
|
mFlagAttachment = c.getInt(CONTENT_FLAG_ATTACHMENT_COLUMN) == 1;
|
|
|
|
mFlags = c.getInt(CONTENT_FLAGS_COLUMN);
|
|
|
|
mServerId = c.getString(CONTENT_SERVER_ID_COLUMN);
|
2009-09-23 01:31:10 +00:00
|
|
|
mServerTimeStamp = c.getLong(CONTENT_SERVER_TIMESTAMP_COLUMN);
|
2009-06-15 21:40:06 +00:00
|
|
|
mClientId = c.getString(CONTENT_CLIENT_ID_COLUMN);
|
|
|
|
mMessageId = c.getString(CONTENT_MESSAGE_ID_COLUMN);
|
|
|
|
mMailboxKey = c.getLong(CONTENT_MAILBOX_KEY_COLUMN);
|
|
|
|
mAccountKey = c.getLong(CONTENT_ACCOUNT_KEY_COLUMN);
|
|
|
|
mFrom = c.getString(CONTENT_FROM_LIST_COLUMN);
|
|
|
|
mTo = c.getString(CONTENT_TO_LIST_COLUMN);
|
|
|
|
mCc = c.getString(CONTENT_CC_LIST_COLUMN);
|
|
|
|
mBcc = c.getString(CONTENT_BCC_LIST_COLUMN);
|
|
|
|
mReplyTo = c.getString(CONTENT_REPLY_TO_COLUMN);
|
2010-02-16 00:01:38 +00:00
|
|
|
mMeetingInfo = c.getString(CONTENT_MEETING_INFO_COLUMN);
|
2010-09-02 02:06:15 +00:00
|
|
|
mSnippet = c.getString(CONTENT_SNIPPET_COLUMN);
|
2009-06-15 21:40:06 +00:00
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean update() {
|
|
|
|
// TODO Auto-generated method stub
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2009-07-30 18:41:31 +00:00
|
|
|
/*
|
2009-06-15 21:40:06 +00:00
|
|
|
* Override this so that we can store the Body first and link it to the Message
|
|
|
|
* Also, attachments when we get there...
|
|
|
|
* (non-Javadoc)
|
|
|
|
* @see com.android.email.provider.EmailContent#save(android.content.Context)
|
|
|
|
*/
|
2009-07-30 18:41:31 +00:00
|
|
|
@Override
|
2009-06-15 21:40:06 +00:00
|
|
|
public Uri save(Context context) {
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
boolean doSave = !isSaved();
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
// This logic is in place so I can (a) short circuit the expensive stuff when
|
|
|
|
// possible, and (b) override (and throw) if anyone tries to call save() or update()
|
|
|
|
// directly for Message, which are unsupported.
|
2009-09-02 06:19:12 +00:00
|
|
|
if (mText == null && mHtml == null && mTextReply == null && mHtmlReply == null &&
|
2009-07-16 23:03:40 +00:00
|
|
|
(mAttachments == null || mAttachments.isEmpty())) {
|
2009-06-15 21:40:06 +00:00
|
|
|
if (doSave) {
|
|
|
|
return super.save(context);
|
|
|
|
} else {
|
|
|
|
// Call update, rather than super.update in case we ever override it
|
|
|
|
if (update(context, toContentValues()) == 1) {
|
|
|
|
return getUri();
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
|
2009-06-16 18:26:40 +00:00
|
|
|
addSaveOps(ops);
|
2009-06-15 21:40:06 +00:00
|
|
|
try {
|
2009-07-30 18:41:31 +00:00
|
|
|
ContentProviderResult[] results =
|
2009-06-15 21:40:06 +00:00
|
|
|
context.getContentResolver().applyBatch(EmailProvider.EMAIL_AUTHORITY, ops);
|
|
|
|
// If saving, set the mId's of the various saved objects
|
|
|
|
if (doSave) {
|
|
|
|
Uri u = results[0].uri;
|
|
|
|
mId = Long.parseLong(u.getPathSegments().get(1));
|
2009-07-16 23:03:40 +00:00
|
|
|
if (mAttachments != null) {
|
2009-07-17 23:29:35 +00:00
|
|
|
int resultOffset = 2;
|
2009-07-16 23:03:40 +00:00
|
|
|
for (Attachment a : mAttachments) {
|
2009-07-17 23:29:35 +00:00
|
|
|
// Save the id of the attachment record
|
|
|
|
u = results[resultOffset++].uri;
|
|
|
|
if (u != null) {
|
|
|
|
a.mId = Long.parseLong(u.getPathSegments().get(1));
|
|
|
|
}
|
2009-07-16 23:03:40 +00:00
|
|
|
a.mMessageKey = mId;
|
|
|
|
}
|
|
|
|
}
|
2009-06-15 21:40:06 +00:00
|
|
|
return u;
|
|
|
|
} else {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
} catch (RemoteException e) {
|
|
|
|
// There is nothing to be done here; fail by returning null
|
|
|
|
} catch (OperationApplicationException e) {
|
|
|
|
// There is nothing to be done here; fail by returning null
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void addSaveOps(ArrayList<ContentProviderOperation> ops) {
|
2009-07-17 23:29:35 +00:00
|
|
|
// First, save the message
|
2009-07-22 22:13:30 +00:00
|
|
|
ContentProviderOperation.Builder b = ContentProviderOperation.newInsert(mBaseUri);
|
2010-09-02 02:06:15 +00:00
|
|
|
// Generate the snippet here, before we create the CPO for Message
|
|
|
|
if (mText != null) {
|
|
|
|
mSnippet = Snippet.fromPlainText(mText);
|
|
|
|
} else if (mHtml != null) {
|
|
|
|
mSnippet = Snippet.fromHtmlText(mHtml);
|
|
|
|
}
|
2009-06-15 21:40:06 +00:00
|
|
|
ops.add(b.withValues(toContentValues()).build());
|
2009-07-17 23:29:35 +00:00
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
// Create and save the body
|
|
|
|
ContentValues cv = new ContentValues();
|
|
|
|
if (mText != null) {
|
|
|
|
cv.put(Body.TEXT_CONTENT, mText);
|
|
|
|
}
|
|
|
|
if (mHtml != null) {
|
|
|
|
cv.put(Body.HTML_CONTENT, mHtml);
|
|
|
|
}
|
2009-09-02 06:19:12 +00:00
|
|
|
if (mTextReply != null) {
|
|
|
|
cv.put(Body.TEXT_REPLY, mTextReply);
|
|
|
|
}
|
|
|
|
if (mHtmlReply != null) {
|
|
|
|
cv.put(Body.HTML_REPLY, mHtmlReply);
|
|
|
|
}
|
2009-09-07 23:03:02 +00:00
|
|
|
if (mSourceKey != 0) {
|
|
|
|
cv.put(Body.SOURCE_MESSAGE_KEY, mSourceKey);
|
|
|
|
}
|
2009-09-23 01:38:28 +00:00
|
|
|
if (mIntroText != null) {
|
|
|
|
cv.put(Body.INTRO_TEXT, mIntroText);
|
|
|
|
}
|
2009-07-22 22:13:30 +00:00
|
|
|
b = ContentProviderOperation.newInsert(Body.CONTENT_URI);
|
2009-06-15 21:40:06 +00:00
|
|
|
b.withValues(cv);
|
|
|
|
ContentValues backValues = new ContentValues();
|
2009-07-15 22:08:53 +00:00
|
|
|
int messageBackValue = ops.size() - 1;
|
|
|
|
backValues.put(Body.MESSAGE_KEY, messageBackValue);
|
2009-06-15 21:40:06 +00:00
|
|
|
ops.add(b.withValueBackReferences(backValues).build());
|
2009-07-15 22:08:53 +00:00
|
|
|
|
|
|
|
// Create the attaachments, if any
|
|
|
|
if (mAttachments != null) {
|
|
|
|
for (Attachment att: mAttachments) {
|
2009-07-22 22:13:30 +00:00
|
|
|
ops.add(ContentProviderOperation.newInsert(Attachment.CONTENT_URI)
|
2009-07-15 22:08:53 +00:00
|
|
|
.withValues(att.toContentValues())
|
|
|
|
.withValueBackReference(Attachment.MESSAGE_KEY, messageBackValue)
|
|
|
|
.build());
|
|
|
|
}
|
|
|
|
}
|
2009-06-15 21:40:06 +00:00
|
|
|
}
|
2010-08-03 01:16:13 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @return number of favorite (starred) messages throughout all accounts.
|
|
|
|
*
|
|
|
|
* TODO Add trigger to keep track. (index isn't efficient in this case.)
|
|
|
|
*/
|
|
|
|
public static int getFavoriteMessageCount(Context context) {
|
|
|
|
return count(context, Message.CONTENT_URI, FAVORITE_COUNT_SELECTION, null);
|
|
|
|
}
|
2010-08-24 04:39:35 +00:00
|
|
|
|
|
|
|
public static long getKeyColumnLong(Context context, long messageId, String column) {
|
|
|
|
String[] columns =
|
|
|
|
Utility.getRowColumns(context, Message.CONTENT_URI, messageId, column);
|
|
|
|
if (columns != null && columns[0] != null) {
|
|
|
|
return Long.parseLong(columns[0]);
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
2009-06-15 21:40:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public interface AccountColumns {
|
2009-08-12 10:51:26 +00:00
|
|
|
public static final String ID = "_id";
|
2009-06-15 21:40:06 +00:00
|
|
|
// The display name of the account (user-settable)
|
|
|
|
public static final String DISPLAY_NAME = "displayName";
|
|
|
|
// The email address corresponding to this account
|
|
|
|
public static final String EMAIL_ADDRESS = "emailAddress";
|
|
|
|
// A server-based sync key on an account-wide basis (EAS needs this)
|
|
|
|
public static final String SYNC_KEY = "syncKey";
|
|
|
|
// The default sync lookback period for this account
|
|
|
|
public static final String SYNC_LOOKBACK = "syncLookback";
|
2009-08-05 15:41:16 +00:00
|
|
|
// The default sync frequency for this account, in minutes
|
2009-07-22 22:13:30 +00:00
|
|
|
public static final String SYNC_INTERVAL = "syncInterval";
|
2009-06-15 21:40:06 +00:00
|
|
|
// A foreign key into the account manager, having host, login, password, port, and ssl flags
|
|
|
|
public static final String HOST_AUTH_KEY_RECV = "hostAuthKeyRecv";
|
|
|
|
// (optional) A foreign key into the account manager, having host, login, password, port,
|
|
|
|
// and ssl flags
|
|
|
|
public static final String HOST_AUTH_KEY_SEND = "hostAuthKeySend";
|
|
|
|
// Flags
|
|
|
|
public static final String FLAGS = "flags";
|
|
|
|
// Default account
|
|
|
|
public static final String IS_DEFAULT = "isDefault";
|
|
|
|
// Old-Style UUID for compatibility with previous versions
|
|
|
|
public static final String COMPATIBILITY_UUID = "compatibilityUuid";
|
|
|
|
// User name (for outgoing messages)
|
|
|
|
public static final String SENDER_NAME = "senderName";
|
|
|
|
// Ringtone
|
|
|
|
public static final String RINGTONE_URI = "ringtoneUri";
|
2009-07-17 23:29:35 +00:00
|
|
|
// Protocol version (arbitrary string, used by EAS currently)
|
|
|
|
public static final String PROTOCOL_VERSION = "protocolVersion";
|
2009-08-18 19:14:15 +00:00
|
|
|
// The number of new messages (reported by the sync/download engines
|
|
|
|
public static final String NEW_MESSAGE_COUNT = "newMessageCount";
|
2010-01-21 19:48:02 +00:00
|
|
|
// Flags defining security (provisioning) requirements of this account
|
|
|
|
public static final String SECURITY_FLAGS = "securityFlags";
|
2010-01-27 01:24:15 +00:00
|
|
|
// Server-based sync key for the security policies currently enforced
|
|
|
|
public static final String SECURITY_SYNC_KEY = "securitySyncKey";
|
|
|
|
// Signature to use with this account
|
|
|
|
public static final String SIGNATURE = "signature";
|
2009-06-15 21:40:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public static final class Account extends EmailContent implements AccountColumns, Parcelable {
|
2009-06-16 19:03:45 +00:00
|
|
|
public static final String TABLE_NAME = "Account";
|
2010-09-10 22:19:57 +00:00
|
|
|
@SuppressWarnings("hiding")
|
2009-06-16 19:03:45 +00:00
|
|
|
public static final Uri CONTENT_URI = Uri.parse(EmailContent.CONTENT_URI + "/account");
|
2009-08-20 02:07:29 +00:00
|
|
|
public static final Uri ADD_TO_FIELD_URI =
|
|
|
|
Uri.parse(EmailContent.CONTENT_URI + "/accountIdAddToField");
|
2010-09-14 23:28:50 +00:00
|
|
|
public static final Uri RESET_NEW_MESSAGE_COUNT_URI =
|
|
|
|
Uri.parse(EmailContent.CONTENT_URI + "/resetNewMessageCount");
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
public final static int FLAGS_NOTIFY_NEW_MAIL = 1;
|
2010-03-17 01:08:52 +00:00
|
|
|
public final static int FLAGS_VIBRATE_ALWAYS = 2;
|
2009-06-15 21:40:06 +00:00
|
|
|
public static final int FLAGS_DELETE_POLICY_MASK = 4+8;
|
|
|
|
public static final int FLAGS_DELETE_POLICY_SHIFT = 2;
|
2010-01-17 04:13:29 +00:00
|
|
|
public static final int FLAGS_INCOMPLETE = 16;
|
2010-02-09 01:42:42 +00:00
|
|
|
public static final int FLAGS_SECURITY_HOLD = 32;
|
2010-03-17 01:08:52 +00:00
|
|
|
public static final int FLAGS_VIBRATE_WHEN_SILENT = 64;
|
2010-08-10 00:48:53 +00:00
|
|
|
public static final int FLAGS_SUPPORTS_SMART_FORWARD = 128;
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
public static final int DELETE_POLICY_NEVER = 0;
|
2009-10-01 08:45:10 +00:00
|
|
|
public static final int DELETE_POLICY_7DAYS = 1; // not supported
|
2009-06-15 21:40:06 +00:00
|
|
|
public static final int DELETE_POLICY_ON_DELETE = 2;
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2009-08-12 05:25:39 +00:00
|
|
|
// Sentinel values for the mSyncInterval field of both Account records
|
2009-06-15 21:40:06 +00:00
|
|
|
public static final int CHECK_INTERVAL_NEVER = -1;
|
|
|
|
public static final int CHECK_INTERVAL_PUSH = -2;
|
2009-08-08 05:23:10 +00:00
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
public String mDisplayName;
|
|
|
|
public String mEmailAddress;
|
|
|
|
public String mSyncKey;
|
|
|
|
public int mSyncLookback;
|
2009-07-22 22:13:30 +00:00
|
|
|
public int mSyncInterval;
|
2009-07-30 18:41:31 +00:00
|
|
|
public long mHostAuthKeyRecv;
|
2009-06-15 21:40:06 +00:00
|
|
|
public long mHostAuthKeySend;
|
|
|
|
public int mFlags;
|
2009-07-21 23:44:16 +00:00
|
|
|
public boolean mIsDefault; // note: callers should use getDefaultAccountId()
|
2009-06-15 21:40:06 +00:00
|
|
|
public String mCompatibilityUuid;
|
|
|
|
public String mSenderName;
|
|
|
|
public String mRingtoneUri;
|
2009-07-17 23:29:35 +00:00
|
|
|
public String mProtocolVersion;
|
2009-08-18 19:14:15 +00:00
|
|
|
public int mNewMessageCount;
|
2010-06-09 23:18:57 +00:00
|
|
|
public long mSecurityFlags;
|
2010-01-27 01:24:15 +00:00
|
|
|
public String mSecuritySyncKey;
|
|
|
|
public String mSignature;
|
2009-06-15 21:40:06 +00:00
|
|
|
|
|
|
|
// Convenience for creating an account
|
|
|
|
public transient HostAuth mHostAuthRecv;
|
|
|
|
public transient HostAuth mHostAuthSend;
|
|
|
|
|
|
|
|
public static final int CONTENT_ID_COLUMN = 0;
|
|
|
|
public static final int CONTENT_DISPLAY_NAME_COLUMN = 1;
|
|
|
|
public static final int CONTENT_EMAIL_ADDRESS_COLUMN = 2;
|
|
|
|
public static final int CONTENT_SYNC_KEY_COLUMN = 3;
|
|
|
|
public static final int CONTENT_SYNC_LOOKBACK_COLUMN = 4;
|
2009-07-22 22:13:30 +00:00
|
|
|
public static final int CONTENT_SYNC_INTERVAL_COLUMN = 5;
|
2009-06-15 21:40:06 +00:00
|
|
|
public static final int CONTENT_HOST_AUTH_KEY_RECV_COLUMN = 6;
|
|
|
|
public static final int CONTENT_HOST_AUTH_KEY_SEND_COLUMN = 7;
|
|
|
|
public static final int CONTENT_FLAGS_COLUMN = 8;
|
|
|
|
public static final int CONTENT_IS_DEFAULT_COLUMN = 9;
|
|
|
|
public static final int CONTENT_COMPATIBILITY_UUID_COLUMN = 10;
|
|
|
|
public static final int CONTENT_SENDER_NAME_COLUMN = 11;
|
|
|
|
public static final int CONTENT_RINGTONE_URI_COLUMN = 12;
|
2009-07-17 23:29:35 +00:00
|
|
|
public static final int CONTENT_PROTOCOL_VERSION_COLUMN = 13;
|
2009-08-18 19:14:15 +00:00
|
|
|
public static final int CONTENT_NEW_MESSAGE_COUNT_COLUMN = 14;
|
2010-01-21 19:48:02 +00:00
|
|
|
public static final int CONTENT_SECURITY_FLAGS_COLUMN = 15;
|
2010-01-27 01:24:15 +00:00
|
|
|
public static final int CONTENT_SECURITY_SYNC_KEY_COLUMN = 16;
|
|
|
|
public static final int CONTENT_SIGNATURE_COLUMN = 17;
|
2009-06-15 21:40:06 +00:00
|
|
|
|
|
|
|
public static final String[] CONTENT_PROJECTION = new String[] {
|
|
|
|
RECORD_ID, AccountColumns.DISPLAY_NAME,
|
|
|
|
AccountColumns.EMAIL_ADDRESS, AccountColumns.SYNC_KEY, AccountColumns.SYNC_LOOKBACK,
|
2009-07-22 22:13:30 +00:00
|
|
|
AccountColumns.SYNC_INTERVAL, AccountColumns.HOST_AUTH_KEY_RECV,
|
2009-06-15 21:40:06 +00:00
|
|
|
AccountColumns.HOST_AUTH_KEY_SEND, AccountColumns.FLAGS, AccountColumns.IS_DEFAULT,
|
|
|
|
AccountColumns.COMPATIBILITY_UUID, AccountColumns.SENDER_NAME,
|
2009-08-18 19:14:15 +00:00
|
|
|
AccountColumns.RINGTONE_URI, AccountColumns.PROTOCOL_VERSION,
|
2010-01-27 01:24:15 +00:00
|
|
|
AccountColumns.NEW_MESSAGE_COUNT, AccountColumns.SECURITY_FLAGS,
|
|
|
|
AccountColumns.SECURITY_SYNC_KEY, AccountColumns.SIGNATURE
|
2009-06-15 21:40:06 +00:00
|
|
|
};
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2009-07-22 00:58:08 +00:00
|
|
|
public static final int CONTENT_MAILBOX_TYPE_COLUMN = 1;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This projection is for listing account id's only
|
|
|
|
*/
|
|
|
|
public static final String[] ID_TYPE_PROJECTION = new String[] {
|
|
|
|
RECORD_ID, MailboxColumns.TYPE
|
|
|
|
};
|
|
|
|
|
2010-07-27 19:52:46 +00:00
|
|
|
public static final int ACCOUNT_FLAGS_COLUMN_ID = 0;
|
|
|
|
public static final int ACCOUNT_FLAGS_COLUMN_FLAGS = 1;
|
|
|
|
public static final String[] ACCOUNT_FLAGS_PROJECTION = new String[] {
|
|
|
|
AccountColumns.ID, AccountColumns.FLAGS};
|
|
|
|
|
2009-07-22 00:58:08 +00:00
|
|
|
public static final String MAILBOX_SELECTION =
|
|
|
|
MessageColumns.MAILBOX_KEY + " =?";
|
|
|
|
|
|
|
|
public static final String UNREAD_COUNT_SELECTION =
|
|
|
|
MessageColumns.MAILBOX_KEY + " =? and " + MessageColumns.FLAG_READ + "= 0";
|
|
|
|
|
2010-03-02 21:03:27 +00:00
|
|
|
public static final String UUID_SELECTION = AccountColumns.COMPATIBILITY_UUID + " =?";
|
|
|
|
|
2010-07-27 19:52:46 +00:00
|
|
|
public static final String SECURITY_NONZERO_SELECTION =
|
|
|
|
Account.SECURITY_FLAGS + " IS NOT NULL AND " + Account.SECURITY_FLAGS + "!=0";
|
|
|
|
|
2010-08-27 17:25:03 +00:00
|
|
|
private static final String FIND_INBOX_SELECTION =
|
|
|
|
MailboxColumns.TYPE + " = " + Mailbox.TYPE_INBOX +
|
|
|
|
" AND " + MailboxColumns.ACCOUNT_KEY + " =?";
|
2010-07-27 19:52:46 +00:00
|
|
|
|
2009-07-21 23:44:16 +00:00
|
|
|
/**
|
|
|
|
* This projection is for searching for the default account
|
|
|
|
*/
|
|
|
|
private static final String[] DEFAULT_ID_PROJECTION = new String[] {
|
|
|
|
RECORD_ID, IS_DEFAULT
|
|
|
|
};
|
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
/**
|
|
|
|
* no public constructor since this is a utility class
|
|
|
|
*/
|
|
|
|
public Account() {
|
|
|
|
mBaseUri = CONTENT_URI;
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
// other defaults (policy)
|
|
|
|
mRingtoneUri = "content://settings/system/notification_sound";
|
2009-07-22 22:13:30 +00:00
|
|
|
mSyncInterval = -1;
|
2009-06-15 21:40:06 +00:00
|
|
|
mSyncLookback = -1;
|
|
|
|
mFlags = FLAGS_NOTIFY_NEW_MAIL;
|
|
|
|
mCompatibilityUuid = UUID.randomUUID().toString();
|
|
|
|
}
|
|
|
|
|
|
|
|
public static Account restoreAccountWithId(Context context, long id) {
|
|
|
|
Uri u = ContentUris.withAppendedId(Account.CONTENT_URI, id);
|
|
|
|
Cursor c = context.getContentResolver().query(u, Account.CONTENT_PROJECTION,
|
|
|
|
null, null, null);
|
|
|
|
|
|
|
|
try {
|
|
|
|
if (c.moveToFirst()) {
|
|
|
|
return getContent(c, Account.class);
|
|
|
|
} else {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
} finally {
|
|
|
|
c.close();
|
|
|
|
}
|
|
|
|
}
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
/**
|
|
|
|
* Refresh an account that has already been loaded. This is slightly less expensive
|
|
|
|
* that generating a brand-new account object.
|
|
|
|
*/
|
|
|
|
public void refresh(Context context) {
|
|
|
|
Cursor c = context.getContentResolver().query(this.getUri(), Account.CONTENT_PROJECTION,
|
|
|
|
null, null, null);
|
|
|
|
try {
|
|
|
|
c.moveToFirst();
|
|
|
|
restore(c);
|
|
|
|
} finally {
|
|
|
|
if (c != null) {
|
|
|
|
c.close();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
@SuppressWarnings("unchecked")
|
|
|
|
public EmailContent.Account restore(Cursor cursor) {
|
2009-07-17 23:29:35 +00:00
|
|
|
mId = cursor.getLong(CONTENT_ID_COLUMN);
|
|
|
|
mBaseUri = CONTENT_URI;
|
2009-06-15 21:40:06 +00:00
|
|
|
mDisplayName = cursor.getString(CONTENT_DISPLAY_NAME_COLUMN);
|
|
|
|
mEmailAddress = cursor.getString(CONTENT_EMAIL_ADDRESS_COLUMN);
|
|
|
|
mSyncKey = cursor.getString(CONTENT_SYNC_KEY_COLUMN);
|
|
|
|
mSyncLookback = cursor.getInt(CONTENT_SYNC_LOOKBACK_COLUMN);
|
2009-07-22 22:13:30 +00:00
|
|
|
mSyncInterval = cursor.getInt(CONTENT_SYNC_INTERVAL_COLUMN);
|
2009-06-15 21:40:06 +00:00
|
|
|
mHostAuthKeyRecv = cursor.getLong(CONTENT_HOST_AUTH_KEY_RECV_COLUMN);
|
|
|
|
mHostAuthKeySend = cursor.getLong(CONTENT_HOST_AUTH_KEY_SEND_COLUMN);
|
|
|
|
mFlags = cursor.getInt(CONTENT_FLAGS_COLUMN);
|
|
|
|
mIsDefault = cursor.getInt(CONTENT_IS_DEFAULT_COLUMN) == 1;
|
|
|
|
mCompatibilityUuid = cursor.getString(CONTENT_COMPATIBILITY_UUID_COLUMN);
|
|
|
|
mSenderName = cursor.getString(CONTENT_SENDER_NAME_COLUMN);
|
|
|
|
mRingtoneUri = cursor.getString(CONTENT_RINGTONE_URI_COLUMN);
|
2009-07-17 23:29:35 +00:00
|
|
|
mProtocolVersion = cursor.getString(CONTENT_PROTOCOL_VERSION_COLUMN);
|
2009-08-18 19:14:15 +00:00
|
|
|
mNewMessageCount = cursor.getInt(CONTENT_NEW_MESSAGE_COUNT_COLUMN);
|
2010-06-09 23:18:57 +00:00
|
|
|
mSecurityFlags = cursor.getLong(CONTENT_SECURITY_FLAGS_COLUMN);
|
2010-01-27 01:24:15 +00:00
|
|
|
mSecuritySyncKey = cursor.getString(CONTENT_SECURITY_SYNC_KEY_COLUMN);
|
|
|
|
mSignature = cursor.getString(CONTENT_SIGNATURE_COLUMN);
|
2009-06-15 21:40:06 +00:00
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
private long getId(Uri u) {
|
|
|
|
return Long.parseLong(u.getPathSegments().get(1));
|
|
|
|
}
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
/**
|
|
|
|
* @return the user-visible name for the account
|
|
|
|
*/
|
2009-07-22 22:13:30 +00:00
|
|
|
public String getDisplayName() {
|
2009-06-15 21:40:06 +00:00
|
|
|
return mDisplayName;
|
|
|
|
}
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
/**
|
|
|
|
* Set the description. Be sure to call save() to commit to database.
|
|
|
|
* @param description the new description
|
|
|
|
*/
|
2009-07-22 22:13:30 +00:00
|
|
|
public void setDisplayName(String description) {
|
2009-06-15 21:40:06 +00:00
|
|
|
mDisplayName = description;
|
|
|
|
}
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
/**
|
|
|
|
* @return the email address for this account
|
|
|
|
*/
|
2009-07-22 22:13:30 +00:00
|
|
|
public String getEmailAddress() {
|
2009-06-15 21:40:06 +00:00
|
|
|
return mEmailAddress;
|
|
|
|
}
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
/**
|
|
|
|
* Set the Email address for this account. Be sure to call save() to commit to database.
|
|
|
|
* @param emailAddress the new email address for this account
|
|
|
|
*/
|
2009-07-22 22:13:30 +00:00
|
|
|
public void setEmailAddress(String emailAddress) {
|
2009-06-15 21:40:06 +00:00
|
|
|
mEmailAddress = emailAddress;
|
|
|
|
}
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
/**
|
|
|
|
* @return the sender's name for this account
|
|
|
|
*/
|
2009-07-22 22:13:30 +00:00
|
|
|
public String getSenderName() {
|
2009-06-15 21:40:06 +00:00
|
|
|
return mSenderName;
|
|
|
|
}
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
/**
|
|
|
|
* Set the sender's name. Be sure to call save() to commit to database.
|
|
|
|
* @param name the new sender name
|
|
|
|
*/
|
2009-07-22 22:13:30 +00:00
|
|
|
public void setSenderName(String name) {
|
2009-06-15 21:40:06 +00:00
|
|
|
mSenderName = name;
|
|
|
|
}
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2010-02-02 22:37:54 +00:00
|
|
|
public String getSignature() {
|
|
|
|
return mSignature;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setSignature(String signature) {
|
|
|
|
mSignature = signature;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
/**
|
|
|
|
* @return the minutes per check (for polling)
|
|
|
|
* TODO define sentinel values for "never", "push", etc. See Account.java
|
|
|
|
*/
|
2009-07-22 22:13:30 +00:00
|
|
|
public int getSyncInterval()
|
2009-06-15 21:40:06 +00:00
|
|
|
{
|
2009-07-22 22:13:30 +00:00
|
|
|
return mSyncInterval;
|
2009-06-15 21:40:06 +00:00
|
|
|
}
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
/**
|
|
|
|
* Set the minutes per check (for polling). Be sure to call save() to commit to database.
|
|
|
|
* TODO define sentinel values for "never", "push", etc. See Account.java
|
|
|
|
* @param minutes the number of minutes between polling checks
|
|
|
|
*/
|
2009-07-22 22:13:30 +00:00
|
|
|
public void setSyncInterval(int minutes)
|
2009-06-15 21:40:06 +00:00
|
|
|
{
|
2009-07-22 22:13:30 +00:00
|
|
|
mSyncInterval = minutes;
|
2009-06-15 21:40:06 +00:00
|
|
|
}
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
/**
|
2010-02-23 17:54:56 +00:00
|
|
|
* @return One of the {@code Account.SYNC_WINDOW_*} constants that represents the sync
|
|
|
|
* lookback window.
|
2009-06-15 21:40:06 +00:00
|
|
|
* TODO define sentinel values for "all", "1 month", etc. See Account.java
|
|
|
|
*/
|
2009-07-22 22:13:30 +00:00
|
|
|
public int getSyncLookback() {
|
2009-06-15 21:40:06 +00:00
|
|
|
return mSyncLookback;
|
|
|
|
}
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
/**
|
2010-02-23 17:54:56 +00:00
|
|
|
* Set the sync lookback window. Be sure to call save() to commit to database.
|
2009-06-15 21:40:06 +00:00
|
|
|
* TODO define sentinel values for "all", "1 month", etc. See Account.java
|
2010-02-23 17:54:56 +00:00
|
|
|
* @param value One of the {@code Account.SYNC_WINDOW_*} constants
|
2009-06-15 21:40:06 +00:00
|
|
|
*/
|
2010-02-23 17:54:56 +00:00
|
|
|
public void setSyncLookback(int value) {
|
|
|
|
mSyncLookback = value;
|
2009-06-15 21:40:06 +00:00
|
|
|
}
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
/**
|
|
|
|
* @return the flags for this account
|
|
|
|
* @see #FLAGS_NOTIFY_NEW_MAIL
|
2010-03-17 01:08:52 +00:00
|
|
|
* @see #FLAGS_VIBRATE_ALWAYS
|
|
|
|
* @see #FLAGS_VIBRATE_WHEN_SILENT
|
2009-06-15 21:40:06 +00:00
|
|
|
*/
|
|
|
|
public int getFlags() {
|
|
|
|
return mFlags;
|
|
|
|
}
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
/**
|
|
|
|
* Set the flags for this account
|
|
|
|
* @see #FLAGS_NOTIFY_NEW_MAIL
|
2010-03-17 01:08:52 +00:00
|
|
|
* @see #FLAGS_VIBRATE_ALWAYS
|
|
|
|
* @see #FLAGS_VIBRATE_WHEN_SILENT
|
2009-06-15 21:40:06 +00:00
|
|
|
* @param newFlags the new value for the flags
|
|
|
|
*/
|
|
|
|
public void setFlags(int newFlags) {
|
|
|
|
mFlags = newFlags;
|
|
|
|
}
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
/**
|
|
|
|
* @return the ringtone Uri for this account
|
|
|
|
*/
|
|
|
|
public String getRingtone() {
|
|
|
|
return mRingtoneUri;
|
|
|
|
}
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
/**
|
|
|
|
* Set the ringtone Uri for this account
|
|
|
|
* @param newUri the new URI string for the ringtone for this account
|
|
|
|
*/
|
|
|
|
public void setRingtone(String newUri) {
|
|
|
|
mRingtoneUri = newUri;
|
|
|
|
}
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
/**
|
|
|
|
* Set the "delete policy" as a simple 0,1,2 value set.
|
|
|
|
* @param newPolicy the new delete policy
|
|
|
|
*/
|
|
|
|
public void setDeletePolicy(int newPolicy) {
|
|
|
|
mFlags &= ~FLAGS_DELETE_POLICY_MASK;
|
|
|
|
mFlags |= (newPolicy << FLAGS_DELETE_POLICY_SHIFT) & FLAGS_DELETE_POLICY_MASK;
|
|
|
|
}
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
/**
|
|
|
|
* Return the "delete policy" as a simple 0,1,2 value set.
|
|
|
|
* @return the current delete policy
|
|
|
|
*/
|
|
|
|
public int getDeletePolicy() {
|
|
|
|
return (mFlags & FLAGS_DELETE_POLICY_MASK) >> FLAGS_DELETE_POLICY_SHIFT;
|
|
|
|
}
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
/**
|
|
|
|
* Return the Uuid associated with this account. This is primarily for compatibility
|
|
|
|
* with accounts set up by previous versions, because there are externals references
|
|
|
|
* to the Uuid (e.g. desktop shortcuts).
|
|
|
|
*/
|
2010-01-20 09:36:01 +00:00
|
|
|
public String getUuid() {
|
2009-06-15 21:40:06 +00:00
|
|
|
return mCompatibilityUuid;
|
|
|
|
}
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
/**
|
|
|
|
* For compatibility while converting to provider model, generate a "store URI"
|
2009-07-30 18:41:31 +00:00
|
|
|
*
|
2009-06-15 21:40:06 +00:00
|
|
|
* @return a string in the form of a Uri, as used by the other parts of the email app
|
|
|
|
*/
|
|
|
|
public String getStoreUri(Context context) {
|
|
|
|
// reconstitute if necessary
|
|
|
|
if (mHostAuthRecv == null) {
|
|
|
|
mHostAuthRecv = HostAuth.restoreHostAuthWithId(context, mHostAuthKeyRecv);
|
|
|
|
}
|
|
|
|
// convert if available
|
|
|
|
if (mHostAuthRecv != null) {
|
|
|
|
String storeUri = mHostAuthRecv.getStoreUri();
|
|
|
|
if (storeUri != null) {
|
|
|
|
return storeUri;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return "";
|
|
|
|
}
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
/**
|
|
|
|
* For compatibility while converting to provider model, generate a "sender URI"
|
2009-07-30 18:41:31 +00:00
|
|
|
*
|
2009-06-15 21:40:06 +00:00
|
|
|
* @return a string in the form of a Uri, as used by the other parts of the email app
|
|
|
|
*/
|
|
|
|
public String getSenderUri(Context context) {
|
|
|
|
// reconstitute if necessary
|
|
|
|
if (mHostAuthSend == null) {
|
|
|
|
mHostAuthSend = HostAuth.restoreHostAuthWithId(context, mHostAuthKeySend);
|
|
|
|
}
|
|
|
|
// convert if available
|
|
|
|
if (mHostAuthSend != null) {
|
|
|
|
String senderUri = mHostAuthSend.getStoreUri();
|
|
|
|
if (senderUri != null) {
|
|
|
|
return senderUri;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return "";
|
|
|
|
}
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
/**
|
|
|
|
* For compatibility while converting to provider model, set the store URI
|
2009-07-30 18:41:31 +00:00
|
|
|
*
|
2009-09-02 06:19:12 +00:00
|
|
|
* @param context
|
|
|
|
* @param storeUri the new value
|
2009-06-15 21:40:06 +00:00
|
|
|
*/
|
|
|
|
@Deprecated
|
2009-09-02 06:19:12 +00:00
|
|
|
public void setStoreUri(Context context, String storeUri) {
|
2009-06-15 21:40:06 +00:00
|
|
|
// reconstitute or create if necessary
|
|
|
|
if (mHostAuthRecv == null) {
|
|
|
|
if (mHostAuthKeyRecv != 0) {
|
|
|
|
mHostAuthRecv = HostAuth.restoreHostAuthWithId(context, mHostAuthKeyRecv);
|
|
|
|
} else {
|
|
|
|
mHostAuthRecv = new EmailContent.HostAuth();
|
|
|
|
}
|
|
|
|
}
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
if (mHostAuthRecv != null) {
|
2009-09-02 06:19:12 +00:00
|
|
|
mHostAuthRecv.setStoreUri(storeUri);
|
2009-06-15 21:40:06 +00:00
|
|
|
}
|
|
|
|
}
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
/**
|
|
|
|
* For compatibility while converting to provider model, set the sender URI
|
2009-07-30 18:41:31 +00:00
|
|
|
*
|
2009-09-02 06:19:12 +00:00
|
|
|
* @param context
|
|
|
|
* @param senderUri the new value
|
2009-06-15 21:40:06 +00:00
|
|
|
*/
|
|
|
|
@Deprecated
|
|
|
|
public void setSenderUri(Context context, String senderUri) {
|
|
|
|
// reconstitute or create if necessary
|
|
|
|
if (mHostAuthSend == null) {
|
|
|
|
if (mHostAuthKeySend != 0) {
|
|
|
|
mHostAuthSend = HostAuth.restoreHostAuthWithId(context, mHostAuthKeySend);
|
|
|
|
} else {
|
|
|
|
mHostAuthSend = new EmailContent.HostAuth();
|
|
|
|
}
|
|
|
|
}
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
if (mHostAuthSend != null) {
|
|
|
|
mHostAuthSend.setStoreUri(senderUri);
|
|
|
|
}
|
|
|
|
}
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
/**
|
|
|
|
* For compatibility while converting to provider model, generate a "local store URI"
|
2009-07-30 18:41:31 +00:00
|
|
|
*
|
2009-06-15 21:40:06 +00:00
|
|
|
* @return a string in the form of a Uri, as used by the other parts of the email app
|
|
|
|
*/
|
|
|
|
public String getLocalStoreUri(Context context) {
|
|
|
|
return "local://localhost/" + context.getDatabasePath(getUuid() + ".db");
|
|
|
|
}
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2010-08-09 23:51:40 +00:00
|
|
|
/**
|
|
|
|
* @return true if the instance is of an EAS account.
|
2010-08-24 00:21:53 +00:00
|
|
|
*
|
|
|
|
* NOTE This method accesses the DB if {@link #mHostAuthRecv} hasn't been restored yet.
|
|
|
|
* Use caution when you use this on the main thread.
|
2010-08-09 23:51:40 +00:00
|
|
|
*/
|
2010-08-24 00:21:53 +00:00
|
|
|
public boolean isEasAccount(Context context) {
|
|
|
|
return "eas".equals(getProtocol(context));
|
2010-08-09 23:51:40 +00:00
|
|
|
}
|
|
|
|
|
2010-09-02 21:49:36 +00:00
|
|
|
/**
|
|
|
|
* @return true if the account supports "move messages".
|
|
|
|
*/
|
|
|
|
public static boolean supportsMoveMessages(Context context, long accountId) {
|
|
|
|
String protocol = getProtocol(context, accountId);
|
|
|
|
return "eas".equals(protocol) || "imap".equals(protocol);
|
|
|
|
}
|
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
/**
|
|
|
|
* Set the account to be the default account. If this is set to "true", when the account
|
|
|
|
* is saved, all other accounts will have the same value set to "false".
|
|
|
|
* @param newDefaultState the new default state - if true, others will be cleared.
|
|
|
|
*/
|
|
|
|
public void setDefaultAccount(boolean newDefaultState) {
|
|
|
|
mIsDefault = newDefaultState;
|
|
|
|
}
|
|
|
|
|
2009-07-21 23:44:16 +00:00
|
|
|
/**
|
|
|
|
* Helper method for finding the default account.
|
|
|
|
*/
|
|
|
|
static private long getDefaultAccountWhere(Context context, String where) {
|
2010-07-27 19:52:46 +00:00
|
|
|
return Utility.getFirstRowLong(context, CONTENT_URI,
|
2009-07-21 23:44:16 +00:00
|
|
|
DEFAULT_ID_PROJECTION,
|
2010-07-27 19:52:46 +00:00
|
|
|
where, null, null, 0, Long.valueOf(-1));
|
2009-06-15 21:40:06 +00:00
|
|
|
}
|
|
|
|
|
2010-03-02 21:03:27 +00:00
|
|
|
/**
|
|
|
|
* @return {@link Uri} to this {@link Account} in the
|
|
|
|
* {@code content://com.android.email.provider/account/UUID} format, which is safe to use
|
|
|
|
* for desktop shortcuts.
|
|
|
|
*
|
|
|
|
* <p>We don't want to store _id in shortcuts, because
|
|
|
|
* {@link com.android.email.AccountBackupRestore} won't preserve it.
|
|
|
|
*/
|
|
|
|
public Uri getShortcutSafeUri() {
|
2010-03-26 18:01:12 +00:00
|
|
|
return getShortcutSafeUriFromUuid(mCompatibilityUuid);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return {@link Uri} to an {@link Account} with a {@code uuid}.
|
|
|
|
*/
|
|
|
|
public static Uri getShortcutSafeUriFromUuid(String uuid) {
|
|
|
|
return CONTENT_URI.buildUpon().appendEncodedPath(uuid).build();
|
2010-03-02 21:03:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Parse {@link Uri} in the {@code content://com.android.email.provider/account/ID} format
|
|
|
|
* where ID = account id (used on Eclair, Android 2.0-2.1) or UUID, and return _id of
|
|
|
|
* the {@link Account} associated with it.
|
|
|
|
*
|
|
|
|
* @param context context to access DB
|
|
|
|
* @param uri URI of interest
|
|
|
|
* @return _id of the {@link Account} associated with ID, or -1 if none found.
|
|
|
|
*/
|
|
|
|
public static long getAccountIdFromShortcutSafeUri(Context context, Uri uri) {
|
|
|
|
// Make sure the URI is in the correct format.
|
|
|
|
if (!"content".equals(uri.getScheme())
|
|
|
|
|| !EmailContent.AUTHORITY.equals(uri.getAuthority())) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
final List<String> ps = uri.getPathSegments();
|
|
|
|
if (ps.size() != 2 || !"account".equals(ps.get(0))) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now get the ID part.
|
|
|
|
final String id = ps.get(1);
|
|
|
|
|
|
|
|
// First, see if ID can be parsed as long. (Eclair-style)
|
|
|
|
// (UUIDs have '-' in them, so they are always non-parsable.)
|
|
|
|
try {
|
|
|
|
return Long.parseLong(id);
|
|
|
|
} catch (NumberFormatException ok) {
|
|
|
|
// OK, it's not a long. Continue...
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now id is a UUId.
|
2010-07-27 19:52:46 +00:00
|
|
|
return Utility.getFirstRowLong(context,
|
|
|
|
CONTENT_URI, ID_PROJECTION,
|
|
|
|
UUID_SELECTION, new String[] {id}, null, 0, Long.valueOf(-1));
|
2010-03-02 21:03:27 +00:00
|
|
|
}
|
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
/**
|
2009-07-21 23:44:16 +00:00
|
|
|
* Return the id of the default account. If one hasn't been explicitly specified, return
|
|
|
|
* the first one in the database. For any account saved in the DB, this must be used
|
|
|
|
* to check for the default account - the mIsDefault field is set lazily and may be
|
|
|
|
* incorrect.
|
|
|
|
* @param context the caller's context
|
|
|
|
* @return the id of the default account, or -1 if there are no accounts
|
2009-06-15 21:40:06 +00:00
|
|
|
*/
|
2009-07-21 23:44:16 +00:00
|
|
|
static public long getDefaultAccountId(Context context) {
|
|
|
|
long id = getDefaultAccountWhere(context, AccountColumns.IS_DEFAULT + "=1");
|
|
|
|
if (id == -1) {
|
|
|
|
id = getDefaultAccountWhere(context, null);
|
2009-06-15 21:40:06 +00:00
|
|
|
}
|
2009-07-21 23:44:16 +00:00
|
|
|
return id;
|
2009-06-15 21:40:06 +00:00
|
|
|
}
|
2009-07-22 00:58:08 +00:00
|
|
|
|
2010-03-03 01:49:47 +00:00
|
|
|
/**
|
2010-06-25 18:28:07 +00:00
|
|
|
* Given an account id, return the account's protocol
|
|
|
|
* @param context the caller's context
|
|
|
|
* @param accountId the id of the account to be examined
|
|
|
|
* @return the account's protocol (or null if the Account or HostAuth do not exist)
|
|
|
|
*/
|
|
|
|
public static String getProtocol(Context context, long accountId) {
|
|
|
|
Account account = Account.restoreAccountWithId(context, accountId);
|
|
|
|
if (account != null) {
|
|
|
|
return account.getProtocol(context);
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return the account's protocol
|
|
|
|
* @param context the caller's context
|
|
|
|
* @return the account's protocol (or null if the HostAuth doesn't not exist)
|
|
|
|
*/
|
|
|
|
public String getProtocol(Context context) {
|
|
|
|
HostAuth hostAuth = HostAuth.restoreHostAuthWithId(context, mHostAuthKeyRecv);
|
|
|
|
if (hostAuth != null) {
|
|
|
|
return hostAuth.mProtocol;
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2010-08-24 04:39:35 +00:00
|
|
|
/**
|
|
|
|
* Return the account for a message with a given id
|
|
|
|
* @param context the caller's context
|
|
|
|
* @param messageId the id of the message
|
|
|
|
* @return the account, or null if the account doesn't exist
|
|
|
|
*/
|
|
|
|
public static Account getAccountForMessageId(Context context, long messageId) {
|
|
|
|
long accountId = Message.getKeyColumnLong(context, messageId,
|
|
|
|
MessageColumns.ACCOUNT_KEY);
|
|
|
|
if (accountId != -1) {
|
|
|
|
return Account.restoreAccountWithId(context, accountId);
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2010-06-25 18:28:07 +00:00
|
|
|
/**
|
2010-03-03 01:49:47 +00:00
|
|
|
* @return true if an {@code accountId} is assigned to any existing account.
|
|
|
|
*/
|
|
|
|
public static boolean isValidId(Context context, long accountId) {
|
2010-07-27 19:52:46 +00:00
|
|
|
return null != Utility.getFirstRowLong(context, CONTENT_URI, ID_PROJECTION,
|
2010-09-24 21:50:20 +00:00
|
|
|
ID_SELECTION, new String[] {Long.toString(accountId)}, null,
|
|
|
|
ID_PROJECTION_COLUMN);
|
2010-07-27 19:52:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Check a single account for security hold status.
|
|
|
|
*/
|
|
|
|
public static boolean isSecurityHold(Context context, long accountId) {
|
2010-09-24 21:50:20 +00:00
|
|
|
return (Utility.getFirstRowLong(context,
|
2010-07-27 19:52:46 +00:00
|
|
|
ContentUris.withAppendedId(Account.CONTENT_URI, accountId),
|
2010-09-24 21:50:20 +00:00
|
|
|
ACCOUNT_FLAGS_PROJECTION, null, null, null, ACCOUNT_FLAGS_COLUMN_FLAGS, 0L)
|
|
|
|
& Account.FLAGS_SECURITY_HOLD) != 0;
|
2010-07-27 19:52:46 +00:00
|
|
|
}
|
|
|
|
|
2010-08-27 17:25:03 +00:00
|
|
|
/**
|
|
|
|
* @return id of the "inbox" mailbox, or -1 if not found.
|
|
|
|
*/
|
|
|
|
public static long getInboxId(Context context, long accountId) {
|
|
|
|
return Utility.getFirstRowLong(context, Mailbox.CONTENT_URI, ID_PROJECTION,
|
|
|
|
FIND_INBOX_SELECTION, new String[] {Long.toString(accountId)}, null,
|
2010-09-24 21:50:20 +00:00
|
|
|
ID_PROJECTION_COLUMN, -1L);
|
2010-08-27 17:25:03 +00:00
|
|
|
}
|
|
|
|
|
2010-07-27 19:52:46 +00:00
|
|
|
/**
|
|
|
|
* Clear all account hold flags that are set.
|
|
|
|
*
|
|
|
|
* (This will trigger watchers, and in particular will cause EAS to try and resync the
|
|
|
|
* account(s).)
|
|
|
|
*/
|
|
|
|
public static void clearSecurityHoldOnAllAccounts(Context context) {
|
|
|
|
ContentResolver resolver = context.getContentResolver();
|
|
|
|
Cursor c = resolver.query(Account.CONTENT_URI, ACCOUNT_FLAGS_PROJECTION,
|
|
|
|
SECURITY_NONZERO_SELECTION, null, null);
|
2010-03-03 01:49:47 +00:00
|
|
|
try {
|
2010-07-27 19:52:46 +00:00
|
|
|
while (c.moveToNext()) {
|
|
|
|
int flags = c.getInt(ACCOUNT_FLAGS_COLUMN_FLAGS);
|
|
|
|
|
|
|
|
if (0 != (flags & FLAGS_SECURITY_HOLD)) {
|
|
|
|
ContentValues cv = new ContentValues();
|
|
|
|
cv.put(AccountColumns.FLAGS, flags & ~FLAGS_SECURITY_HOLD);
|
|
|
|
long accountId = c.getLong(ACCOUNT_FLAGS_COLUMN_ID);
|
|
|
|
Uri uri = ContentUris.withAppendedId(Account.CONTENT_URI, accountId);
|
|
|
|
resolver.update(uri, cv, null, null);
|
|
|
|
}
|
2010-03-03 01:49:47 +00:00
|
|
|
}
|
|
|
|
} finally {
|
2010-07-27 19:52:46 +00:00
|
|
|
c.close();
|
2010-03-03 01:49:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-07-22 22:55:45 +00:00
|
|
|
/**
|
|
|
|
* Override update to enforce a single default account, and do it atomically
|
|
|
|
*/
|
2009-07-30 18:41:31 +00:00
|
|
|
@Override
|
2009-07-22 22:55:45 +00:00
|
|
|
public int update(Context context, ContentValues cv) {
|
2009-07-30 18:41:31 +00:00
|
|
|
if (cv.containsKey(AccountColumns.IS_DEFAULT) &&
|
2009-08-27 22:26:06 +00:00
|
|
|
cv.getAsBoolean(AccountColumns.IS_DEFAULT)) {
|
2009-07-22 22:55:45 +00:00
|
|
|
ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
|
|
|
|
ContentValues cv1 = new ContentValues();
|
2009-08-27 22:26:06 +00:00
|
|
|
cv1.put(AccountColumns.IS_DEFAULT, false);
|
2009-07-22 22:55:45 +00:00
|
|
|
// Clear the default flag in all accounts
|
|
|
|
ops.add(ContentProviderOperation.newUpdate(CONTENT_URI).withValues(cv1).build());
|
|
|
|
// Update this account
|
|
|
|
ops.add(ContentProviderOperation
|
|
|
|
.newUpdate(ContentUris.withAppendedId(CONTENT_URI, mId))
|
|
|
|
.withValues(cv).build());
|
|
|
|
try {
|
|
|
|
context.getContentResolver().applyBatch(EmailProvider.EMAIL_AUTHORITY, ops);
|
|
|
|
return 1;
|
|
|
|
} catch (RemoteException e) {
|
|
|
|
// There is nothing to be done here; fail by returning 0
|
|
|
|
} catch (OperationApplicationException e) {
|
|
|
|
// There is nothing to be done here; fail by returning 0
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return super.update(context, cv);
|
|
|
|
}
|
|
|
|
|
2009-07-30 18:41:31 +00:00
|
|
|
/*
|
2009-06-15 21:40:06 +00:00
|
|
|
* Override this so that we can store the HostAuth's first and link them to the Account
|
|
|
|
* (non-Javadoc)
|
|
|
|
* @see com.android.email.provider.EmailContent#save(android.content.Context)
|
|
|
|
*/
|
2009-07-30 18:41:31 +00:00
|
|
|
@Override
|
2009-07-22 22:13:30 +00:00
|
|
|
public Uri save(Context context) {
|
|
|
|
if (isSaved()) {
|
|
|
|
throw new UnsupportedOperationException();
|
|
|
|
}
|
2009-06-15 21:40:06 +00:00
|
|
|
// This logic is in place so I can (a) short circuit the expensive stuff when
|
|
|
|
// possible, and (b) override (and throw) if anyone tries to call save() or update()
|
|
|
|
// directly for Account, which are unsupported.
|
|
|
|
if (mHostAuthRecv == null && mHostAuthSend == null && mIsDefault == false) {
|
|
|
|
return super.save(context);
|
|
|
|
}
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
int index = 0;
|
|
|
|
int recvIndex = -1;
|
|
|
|
int sendIndex = -1;
|
|
|
|
|
|
|
|
// Create operations for saving the send and recv hostAuths
|
|
|
|
// Also, remember which operation in the array they represent
|
|
|
|
ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
|
|
|
|
if (mHostAuthRecv != null) {
|
|
|
|
recvIndex = index++;
|
2009-07-22 22:13:30 +00:00
|
|
|
ops.add(ContentProviderOperation.newInsert(mHostAuthRecv.mBaseUri)
|
2009-06-15 21:40:06 +00:00
|
|
|
.withValues(mHostAuthRecv.toContentValues())
|
|
|
|
.build());
|
|
|
|
}
|
|
|
|
if (mHostAuthSend != null) {
|
|
|
|
sendIndex = index++;
|
2009-07-22 22:13:30 +00:00
|
|
|
ops.add(ContentProviderOperation.newInsert(mHostAuthRecv.mBaseUri)
|
2009-06-15 21:40:06 +00:00
|
|
|
.withValues(mHostAuthSend.toContentValues())
|
|
|
|
.build());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create operations for making this the only default account
|
|
|
|
// Note, these are always updates because they change existing accounts
|
|
|
|
if (mIsDefault) {
|
|
|
|
index++;
|
|
|
|
ContentValues cv1 = new ContentValues();
|
|
|
|
cv1.put(AccountColumns.IS_DEFAULT, 0);
|
|
|
|
ops.add(ContentProviderOperation.newUpdate(CONTENT_URI).withValues(cv1).build());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now do the Account
|
|
|
|
ContentValues cv = null;
|
2009-07-22 22:13:30 +00:00
|
|
|
if (recvIndex >= 0 || sendIndex >= 0) {
|
2009-06-15 21:40:06 +00:00
|
|
|
cv = new ContentValues();
|
|
|
|
if (recvIndex >= 0) {
|
|
|
|
cv.put(Account.HOST_AUTH_KEY_RECV, recvIndex);
|
|
|
|
}
|
|
|
|
if (sendIndex >= 0) {
|
|
|
|
cv.put(Account.HOST_AUTH_KEY_SEND, sendIndex);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-07-22 22:13:30 +00:00
|
|
|
ContentProviderOperation.Builder b = ContentProviderOperation.newInsert(mBaseUri);
|
2009-06-15 21:40:06 +00:00
|
|
|
b.withValues(toContentValues());
|
|
|
|
if (cv != null) {
|
|
|
|
b.withValueBackReferences(cv);
|
|
|
|
}
|
|
|
|
ops.add(b.build());
|
2009-07-22 22:13:30 +00:00
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
try {
|
2009-07-30 18:41:31 +00:00
|
|
|
ContentProviderResult[] results =
|
2009-06-15 21:40:06 +00:00
|
|
|
context.getContentResolver().applyBatch(EmailProvider.EMAIL_AUTHORITY, ops);
|
|
|
|
// If saving, set the mId's of the various saved objects
|
2009-07-22 22:13:30 +00:00
|
|
|
if (recvIndex >= 0) {
|
|
|
|
long newId = getId(results[recvIndex].uri);
|
|
|
|
mHostAuthKeyRecv = newId;
|
|
|
|
mHostAuthRecv.mId = newId;
|
|
|
|
}
|
|
|
|
if (sendIndex >= 0) {
|
|
|
|
long newId = getId(results[sendIndex].uri);
|
|
|
|
mHostAuthKeySend = newId;
|
|
|
|
mHostAuthSend.mId = newId;
|
2009-06-15 21:40:06 +00:00
|
|
|
}
|
2009-07-22 22:13:30 +00:00
|
|
|
Uri u = results[index].uri;
|
|
|
|
mId = getId(u);
|
|
|
|
return u;
|
2009-06-15 21:40:06 +00:00
|
|
|
} catch (RemoteException e) {
|
|
|
|
// There is nothing to be done here; fail by returning null
|
|
|
|
} catch (OperationApplicationException e) {
|
|
|
|
// There is nothing to be done here; fail by returning null
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public ContentValues toContentValues() {
|
|
|
|
ContentValues values = new ContentValues();
|
|
|
|
values.put(AccountColumns.DISPLAY_NAME, mDisplayName);
|
|
|
|
values.put(AccountColumns.EMAIL_ADDRESS, mEmailAddress);
|
|
|
|
values.put(AccountColumns.SYNC_KEY, mSyncKey);
|
|
|
|
values.put(AccountColumns.SYNC_LOOKBACK, mSyncLookback);
|
2009-07-22 22:13:30 +00:00
|
|
|
values.put(AccountColumns.SYNC_INTERVAL, mSyncInterval);
|
2009-06-15 21:40:06 +00:00
|
|
|
values.put(AccountColumns.HOST_AUTH_KEY_RECV, mHostAuthKeyRecv);
|
|
|
|
values.put(AccountColumns.HOST_AUTH_KEY_SEND, mHostAuthKeySend);
|
|
|
|
values.put(AccountColumns.FLAGS, mFlags);
|
2009-08-27 22:26:06 +00:00
|
|
|
values.put(AccountColumns.IS_DEFAULT, mIsDefault);
|
2009-06-15 21:40:06 +00:00
|
|
|
values.put(AccountColumns.COMPATIBILITY_UUID, mCompatibilityUuid);
|
|
|
|
values.put(AccountColumns.SENDER_NAME, mSenderName);
|
|
|
|
values.put(AccountColumns.RINGTONE_URI, mRingtoneUri);
|
2009-07-17 23:29:35 +00:00
|
|
|
values.put(AccountColumns.PROTOCOL_VERSION, mProtocolVersion);
|
2009-08-18 19:14:15 +00:00
|
|
|
values.put(AccountColumns.NEW_MESSAGE_COUNT, mNewMessageCount);
|
2010-01-21 19:48:02 +00:00
|
|
|
values.put(AccountColumns.SECURITY_FLAGS, mSecurityFlags);
|
2010-01-27 01:24:15 +00:00
|
|
|
values.put(AccountColumns.SECURITY_SYNC_KEY, mSecuritySyncKey);
|
|
|
|
values.put(AccountColumns.SIGNATURE, mSignature);
|
2009-06-15 21:40:06 +00:00
|
|
|
return values;
|
|
|
|
}
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
/**
|
|
|
|
* Supports Parcelable
|
|
|
|
*/
|
|
|
|
public int describeContents() {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Supports Parcelable
|
|
|
|
*/
|
|
|
|
public static final Parcelable.Creator<EmailContent.Account> CREATOR
|
|
|
|
= new Parcelable.Creator<EmailContent.Account>() {
|
|
|
|
public EmailContent.Account createFromParcel(Parcel in) {
|
|
|
|
return new EmailContent.Account(in);
|
|
|
|
}
|
|
|
|
|
|
|
|
public EmailContent.Account[] newArray(int size) {
|
|
|
|
return new EmailContent.Account[size];
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Supports Parcelable
|
|
|
|
*/
|
|
|
|
public void writeToParcel(Parcel dest, int flags) {
|
|
|
|
// mBaseUri is not parceled
|
|
|
|
dest.writeLong(mId);
|
|
|
|
dest.writeString(mDisplayName);
|
|
|
|
dest.writeString(mEmailAddress);
|
|
|
|
dest.writeString(mSyncKey);
|
|
|
|
dest.writeInt(mSyncLookback);
|
2009-07-22 22:13:30 +00:00
|
|
|
dest.writeInt(mSyncInterval);
|
2009-07-30 18:41:31 +00:00
|
|
|
dest.writeLong(mHostAuthKeyRecv);
|
2009-06-15 21:40:06 +00:00
|
|
|
dest.writeLong(mHostAuthKeySend);
|
|
|
|
dest.writeInt(mFlags);
|
|
|
|
dest.writeByte(mIsDefault ? (byte)1 : (byte)0);
|
|
|
|
dest.writeString(mCompatibilityUuid);
|
|
|
|
dest.writeString(mSenderName);
|
|
|
|
dest.writeString(mRingtoneUri);
|
2009-08-18 19:14:15 +00:00
|
|
|
dest.writeString(mProtocolVersion);
|
|
|
|
dest.writeInt(mNewMessageCount);
|
2010-06-09 23:18:57 +00:00
|
|
|
dest.writeLong(mSecurityFlags);
|
2010-01-27 01:24:15 +00:00
|
|
|
dest.writeString(mSecuritySyncKey);
|
|
|
|
dest.writeString(mSignature);
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
if (mHostAuthRecv != null) {
|
|
|
|
dest.writeByte((byte)1);
|
|
|
|
mHostAuthRecv.writeToParcel(dest, flags);
|
|
|
|
} else {
|
|
|
|
dest.writeByte((byte)0);
|
|
|
|
}
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
if (mHostAuthSend != null) {
|
|
|
|
dest.writeByte((byte)1);
|
|
|
|
mHostAuthSend.writeToParcel(dest, flags);
|
|
|
|
} else {
|
|
|
|
dest.writeByte((byte)0);
|
|
|
|
}
|
|
|
|
}
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
/**
|
|
|
|
* Supports Parcelable
|
|
|
|
*/
|
|
|
|
public Account(Parcel in) {
|
|
|
|
mBaseUri = EmailContent.Account.CONTENT_URI;
|
|
|
|
mId = in.readLong();
|
|
|
|
mDisplayName = in.readString();
|
|
|
|
mEmailAddress = in.readString();
|
|
|
|
mSyncKey = in.readString();
|
|
|
|
mSyncLookback = in.readInt();
|
2009-07-22 22:13:30 +00:00
|
|
|
mSyncInterval = in.readInt();
|
2009-07-30 18:41:31 +00:00
|
|
|
mHostAuthKeyRecv = in.readLong();
|
2009-06-15 21:40:06 +00:00
|
|
|
mHostAuthKeySend = in.readLong();
|
|
|
|
mFlags = in.readInt();
|
|
|
|
mIsDefault = in.readByte() == 1;
|
|
|
|
mCompatibilityUuid = in.readString();
|
|
|
|
mSenderName = in.readString();
|
|
|
|
mRingtoneUri = in.readString();
|
2009-08-18 19:14:15 +00:00
|
|
|
mProtocolVersion = in.readString();
|
|
|
|
mNewMessageCount = in.readInt();
|
2010-06-09 23:18:57 +00:00
|
|
|
mSecurityFlags = in.readLong();
|
2010-01-27 01:24:15 +00:00
|
|
|
mSecuritySyncKey = in.readString();
|
|
|
|
mSignature = in.readString();
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
mHostAuthRecv = null;
|
|
|
|
if (in.readByte() == 1) {
|
|
|
|
mHostAuthRecv = new EmailContent.HostAuth(in);
|
|
|
|
}
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
mHostAuthSend = null;
|
|
|
|
if (in.readByte() == 1) {
|
|
|
|
mHostAuthSend = new EmailContent.HostAuth(in);
|
|
|
|
}
|
|
|
|
}
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
/**
|
|
|
|
* For debugger support only - DO NOT use for code.
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public String toString() {
|
|
|
|
StringBuilder sb = new StringBuilder('[');
|
|
|
|
if (mHostAuthRecv != null && mHostAuthRecv.mProtocol != null) {
|
|
|
|
sb.append(mHostAuthRecv.mProtocol);
|
|
|
|
sb.append(':');
|
|
|
|
}
|
|
|
|
if (mDisplayName != null) sb.append(mDisplayName);
|
|
|
|
sb.append(':');
|
|
|
|
if (mEmailAddress != null) sb.append(mEmailAddress);
|
|
|
|
sb.append(':');
|
|
|
|
if (mSenderName != null) sb.append(mSenderName);
|
|
|
|
sb.append(']');
|
|
|
|
return sb.toString();
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
public interface AttachmentColumns {
|
2009-08-12 10:51:26 +00:00
|
|
|
public static final String ID = "_id";
|
2009-07-30 18:41:31 +00:00
|
|
|
// The display name of the attachment
|
2009-06-15 21:40:06 +00:00
|
|
|
public static final String FILENAME = "fileName";
|
|
|
|
// The mime type of the attachment
|
|
|
|
public static final String MIME_TYPE = "mimeType";
|
|
|
|
// The size of the attachment in bytes
|
|
|
|
public static final String SIZE = "size";
|
|
|
|
// The (internal) contentId of the attachment (inline attachments will have these)
|
|
|
|
public static final String CONTENT_ID = "contentId";
|
|
|
|
// The location of the loaded attachment (probably a file)
|
2010-09-10 22:19:57 +00:00
|
|
|
@SuppressWarnings("hiding")
|
2009-06-15 21:40:06 +00:00
|
|
|
public static final String CONTENT_URI = "contentUri";
|
|
|
|
// A foreign key into the Message table (the message owning this attachment)
|
|
|
|
public static final String MESSAGE_KEY = "messageKey";
|
|
|
|
// The location of the attachment on the server side
|
|
|
|
// For IMAP, this is a part number (e.g. 2.1); for EAS, it's the internal file name
|
|
|
|
public static final String LOCATION = "location";
|
|
|
|
// The transfer encoding of the attachment
|
|
|
|
public static final String ENCODING = "encoding";
|
2010-03-12 21:30:26 +00:00
|
|
|
// Not currently used
|
2010-02-22 20:57:33 +00:00
|
|
|
public static final String CONTENT = "content";
|
|
|
|
// Flags
|
|
|
|
public static final String FLAGS = "flags";
|
2010-03-12 21:30:26 +00:00
|
|
|
// Content that is actually contained in the Attachment row
|
|
|
|
public static final String CONTENT_BYTES = "content_bytes";
|
2009-06-15 21:40:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public static final class Attachment extends EmailContent implements AttachmentColumns {
|
2009-06-16 19:03:45 +00:00
|
|
|
public static final String TABLE_NAME = "Attachment";
|
2010-09-10 22:19:57 +00:00
|
|
|
@SuppressWarnings("hiding")
|
2009-06-16 19:03:45 +00:00
|
|
|
public static final Uri CONTENT_URI = Uri.parse(EmailContent.CONTENT_URI + "/attachment");
|
2009-07-16 23:03:40 +00:00
|
|
|
// This must be used with an appended id: ContentUris.withAppendedId(MESSAGE_ID_URI, id)
|
|
|
|
public static final Uri MESSAGE_ID_URI = Uri.parse(
|
|
|
|
EmailContent.CONTENT_URI + "/attachment/message");
|
2009-06-15 21:40:06 +00:00
|
|
|
|
|
|
|
public String mFileName;
|
|
|
|
public String mMimeType;
|
|
|
|
public long mSize;
|
|
|
|
public String mContentId;
|
|
|
|
public String mContentUri;
|
|
|
|
public long mMessageKey;
|
|
|
|
public String mLocation;
|
|
|
|
public String mEncoding;
|
2010-03-12 21:30:26 +00:00
|
|
|
public String mContent; // Not currently used
|
2010-02-22 20:57:33 +00:00
|
|
|
public int mFlags;
|
2010-03-12 21:30:26 +00:00
|
|
|
public byte[] mContentBytes;
|
2009-06-15 21:40:06 +00:00
|
|
|
|
|
|
|
public static final int CONTENT_ID_COLUMN = 0;
|
|
|
|
public static final int CONTENT_FILENAME_COLUMN = 1;
|
|
|
|
public static final int CONTENT_MIME_TYPE_COLUMN = 2;
|
|
|
|
public static final int CONTENT_SIZE_COLUMN = 3;
|
|
|
|
public static final int CONTENT_CONTENT_ID_COLUMN = 4;
|
|
|
|
public static final int CONTENT_CONTENT_URI_COLUMN = 5;
|
|
|
|
public static final int CONTENT_MESSAGE_ID_COLUMN = 6;
|
|
|
|
public static final int CONTENT_LOCATION_COLUMN = 7;
|
|
|
|
public static final int CONTENT_ENCODING_COLUMN = 8;
|
2010-03-12 21:30:26 +00:00
|
|
|
public static final int CONTENT_CONTENT_COLUMN = 9; // Not currently used
|
2010-02-22 20:57:33 +00:00
|
|
|
public static final int CONTENT_FLAGS_COLUMN = 10;
|
2010-03-12 21:30:26 +00:00
|
|
|
public static final int CONTENT_CONTENT_BYTES_COLUMN = 11;
|
2009-06-15 21:40:06 +00:00
|
|
|
public static final String[] CONTENT_PROJECTION = new String[] {
|
|
|
|
RECORD_ID, AttachmentColumns.FILENAME, AttachmentColumns.MIME_TYPE,
|
|
|
|
AttachmentColumns.SIZE, AttachmentColumns.CONTENT_ID, AttachmentColumns.CONTENT_URI,
|
2010-02-22 20:57:33 +00:00
|
|
|
AttachmentColumns.MESSAGE_KEY, AttachmentColumns.LOCATION, AttachmentColumns.ENCODING,
|
2010-03-12 21:30:26 +00:00
|
|
|
AttachmentColumns.CONTENT, AttachmentColumns.FLAGS, AttachmentColumns.CONTENT_BYTES
|
2009-06-15 21:40:06 +00:00
|
|
|
};
|
|
|
|
|
2010-02-22 20:57:33 +00:00
|
|
|
// Bits used in mFlags
|
2010-03-16 20:38:47 +00:00
|
|
|
// Instruct Rfc822Output to 1) not use Content-Disposition and 2) use multipart/alternative
|
|
|
|
// with this attachment. This is only valid if there is one and only one attachment and
|
|
|
|
// that attachment has this flag set
|
|
|
|
public static final int FLAG_ICS_ALTERNATIVE_PART = 1<<0;
|
2010-08-10 00:48:53 +00:00
|
|
|
// Indicate that this attachment has been requested for downloading by the user; this is
|
|
|
|
// the highest priority for attachment downloading
|
|
|
|
public static final int FLAG_DOWNLOAD_USER_REQUEST = 1<<1;
|
|
|
|
// Indicate that this attachment needs to be downloaded as part of an outgoing forwarded
|
|
|
|
// message
|
|
|
|
public static final int FLAG_DOWNLOAD_FORWARD = 1<<2;
|
|
|
|
// Indicates that the attachment download failed in a non-recoverable manner
|
|
|
|
public static final int FLAG_DOWNLOAD_FAILED = 1<<3;
|
2010-02-22 20:57:33 +00:00
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
/**
|
|
|
|
* no public constructor since this is a utility class
|
|
|
|
*/
|
|
|
|
public Attachment() {
|
|
|
|
mBaseUri = CONTENT_URI;
|
|
|
|
}
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
/**
|
|
|
|
* Restore an Attachment from the database, given its unique id
|
|
|
|
* @param context
|
|
|
|
* @param id
|
|
|
|
* @return the instantiated Attachment
|
|
|
|
*/
|
|
|
|
public static Attachment restoreAttachmentWithId (Context context, long id) {
|
|
|
|
Uri u = ContentUris.withAppendedId(Attachment.CONTENT_URI, id);
|
|
|
|
Cursor c = context.getContentResolver().query(u, Attachment.CONTENT_PROJECTION,
|
|
|
|
null, null, null);
|
|
|
|
|
|
|
|
try {
|
|
|
|
if (c.moveToFirst()) {
|
|
|
|
return getContent(c, Attachment.class);
|
|
|
|
} else {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
} finally {
|
|
|
|
c.close();
|
|
|
|
}
|
|
|
|
}
|
2009-08-18 16:55:59 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Restore all the Attachments of a message given its messageId
|
|
|
|
*/
|
|
|
|
public static Attachment[] restoreAttachmentsWithMessageId(Context context,
|
|
|
|
long messageId) {
|
|
|
|
Uri uri = ContentUris.withAppendedId(MESSAGE_ID_URI, messageId);
|
|
|
|
Cursor c = context.getContentResolver().query(uri, CONTENT_PROJECTION,
|
|
|
|
null, null, null);
|
|
|
|
try {
|
|
|
|
int count = c.getCount();
|
|
|
|
Attachment[] attachments = new Attachment[count];
|
|
|
|
for (int i = 0; i < count; ++i) {
|
|
|
|
c.moveToNext();
|
|
|
|
attachments[i] = new Attachment().restore(c);
|
|
|
|
}
|
|
|
|
return attachments;
|
|
|
|
} finally {
|
|
|
|
c.close();
|
|
|
|
}
|
|
|
|
}
|
2009-06-15 21:40:06 +00:00
|
|
|
|
2009-07-15 22:08:53 +00:00
|
|
|
/**
|
|
|
|
* Creates a unique file in the external store by appending a hyphen
|
|
|
|
* and a number to the given filename.
|
|
|
|
* @param filename
|
|
|
|
* @return a new File object, or null if one could not be created
|
|
|
|
*/
|
|
|
|
public static File createUniqueFile(String filename) {
|
|
|
|
// TODO Handle internal storage, as required
|
|
|
|
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
|
|
|
|
File directory = Environment.getExternalStorageDirectory();
|
|
|
|
File file = new File(directory, filename);
|
|
|
|
if (!file.exists()) {
|
|
|
|
return file;
|
|
|
|
}
|
|
|
|
// Get the extension of the file, if any.
|
|
|
|
int index = filename.lastIndexOf('.');
|
|
|
|
String name = filename;
|
|
|
|
String extension = "";
|
|
|
|
if (index != -1) {
|
|
|
|
name = filename.substring(0, index);
|
|
|
|
extension = filename.substring(index);
|
|
|
|
}
|
|
|
|
for (int i = 2; i < Integer.MAX_VALUE; i++) {
|
|
|
|
file = new File(directory, name + '-' + i + extension);
|
|
|
|
if (!file.exists()) {
|
|
|
|
return file;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
@Override
|
|
|
|
@SuppressWarnings("unchecked")
|
|
|
|
public EmailContent.Attachment restore(Cursor cursor) {
|
2009-07-17 23:29:35 +00:00
|
|
|
mBaseUri = CONTENT_URI;
|
|
|
|
mId = cursor.getLong(CONTENT_ID_COLUMN);
|
2009-06-15 21:40:06 +00:00
|
|
|
mFileName= cursor.getString(CONTENT_FILENAME_COLUMN);
|
|
|
|
mMimeType = cursor.getString(CONTENT_MIME_TYPE_COLUMN);
|
|
|
|
mSize = cursor.getLong(CONTENT_SIZE_COLUMN);
|
|
|
|
mContentId = cursor.getString(CONTENT_CONTENT_ID_COLUMN);
|
|
|
|
mContentUri = cursor.getString(CONTENT_CONTENT_URI_COLUMN);
|
|
|
|
mMessageKey = cursor.getLong(CONTENT_MESSAGE_ID_COLUMN);
|
|
|
|
mLocation = cursor.getString(CONTENT_LOCATION_COLUMN);
|
|
|
|
mEncoding = cursor.getString(CONTENT_ENCODING_COLUMN);
|
2010-02-22 20:57:33 +00:00
|
|
|
mContent = cursor.getString(CONTENT_CONTENT_COLUMN);
|
|
|
|
mFlags = cursor.getInt(CONTENT_FLAGS_COLUMN);
|
2010-03-12 21:30:26 +00:00
|
|
|
mContentBytes = cursor.getBlob(CONTENT_CONTENT_BYTES_COLUMN);
|
2009-06-15 21:40:06 +00:00
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public ContentValues toContentValues() {
|
|
|
|
ContentValues values = new ContentValues();
|
|
|
|
values.put(AttachmentColumns.FILENAME, mFileName);
|
2009-07-30 18:41:31 +00:00
|
|
|
values.put(AttachmentColumns.MIME_TYPE, mMimeType);
|
|
|
|
values.put(AttachmentColumns.SIZE, mSize);
|
|
|
|
values.put(AttachmentColumns.CONTENT_ID, mContentId);
|
|
|
|
values.put(AttachmentColumns.CONTENT_URI, mContentUri);
|
|
|
|
values.put(AttachmentColumns.MESSAGE_KEY, mMessageKey);
|
|
|
|
values.put(AttachmentColumns.LOCATION, mLocation);
|
|
|
|
values.put(AttachmentColumns.ENCODING, mEncoding);
|
2010-02-22 20:57:33 +00:00
|
|
|
values.put(AttachmentColumns.CONTENT, mContent);
|
|
|
|
values.put(AttachmentColumns.FLAGS, mFlags);
|
2010-03-12 21:30:26 +00:00
|
|
|
values.put(AttachmentColumns.CONTENT_BYTES, mContentBytes);
|
2009-06-15 21:40:06 +00:00
|
|
|
return values;
|
|
|
|
}
|
2009-06-16 19:03:45 +00:00
|
|
|
|
|
|
|
public int describeContents() {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void writeToParcel(Parcel dest, int flags) {
|
|
|
|
// mBaseUri is not parceled
|
|
|
|
dest.writeLong(mId);
|
|
|
|
dest.writeString(mFileName);
|
|
|
|
dest.writeString(mMimeType);
|
|
|
|
dest.writeLong(mSize);
|
|
|
|
dest.writeString(mContentId);
|
|
|
|
dest.writeString(mContentUri);
|
|
|
|
dest.writeLong(mMessageKey);
|
|
|
|
dest.writeString(mLocation);
|
|
|
|
dest.writeString(mEncoding);
|
2010-02-22 20:57:33 +00:00
|
|
|
dest.writeString(mContent);
|
|
|
|
dest.writeInt(mFlags);
|
2010-03-12 21:30:26 +00:00
|
|
|
if (mContentBytes == null) {
|
|
|
|
dest.writeInt(-1);
|
|
|
|
} else {
|
|
|
|
dest.writeInt(mContentBytes.length);
|
|
|
|
dest.writeByteArray(mContentBytes);
|
|
|
|
}
|
2009-06-16 19:03:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public Attachment(Parcel in) {
|
|
|
|
mBaseUri = EmailContent.Attachment.CONTENT_URI;
|
|
|
|
mId = in.readLong();
|
|
|
|
mFileName = in.readString();
|
|
|
|
mMimeType = in.readString();
|
|
|
|
mSize = in.readLong();
|
|
|
|
mContentId = in.readString();
|
|
|
|
mContentUri = in.readString();
|
|
|
|
mMessageKey = in.readLong();
|
|
|
|
mLocation = in.readString();
|
|
|
|
mEncoding = in.readString();
|
2010-02-22 20:57:33 +00:00
|
|
|
mContent = in.readString();
|
|
|
|
mFlags = in.readInt();
|
2010-03-12 21:30:26 +00:00
|
|
|
final int contentBytesLen = in.readInt();
|
|
|
|
if (contentBytesLen == -1) {
|
|
|
|
mContentBytes = null;
|
|
|
|
} else {
|
|
|
|
mContentBytes = new byte[contentBytesLen];
|
|
|
|
in.readByteArray(mContentBytes);
|
|
|
|
}
|
2009-06-16 19:03:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public static final Parcelable.Creator<EmailContent.Attachment> CREATOR
|
|
|
|
= new Parcelable.Creator<EmailContent.Attachment>() {
|
|
|
|
public EmailContent.Attachment createFromParcel(Parcel in) {
|
|
|
|
return new EmailContent.Attachment(in);
|
|
|
|
}
|
|
|
|
|
|
|
|
public EmailContent.Attachment[] newArray(int size) {
|
|
|
|
return new EmailContent.Attachment[size];
|
|
|
|
}
|
|
|
|
};
|
2009-10-14 15:20:59 +00:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public String toString() {
|
|
|
|
return "[" + mFileName + ", " + mMimeType + ", " + mSize + ", " + mContentId + ", "
|
2010-02-22 20:57:33 +00:00
|
|
|
+ mContentUri + ", " + mMessageKey + ", " + mLocation + ", " + mEncoding + ", "
|
2010-03-12 21:30:26 +00:00
|
|
|
+ mFlags + ", " + mContentBytes + "]";
|
2009-10-14 15:20:59 +00:00
|
|
|
}
|
2009-06-15 21:40:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public interface MailboxColumns {
|
|
|
|
public static final String ID = "_id";
|
|
|
|
// The display name of this mailbox [INDEX]
|
2009-07-30 18:41:31 +00:00
|
|
|
static final String DISPLAY_NAME = "displayName";
|
2009-06-15 21:40:06 +00:00
|
|
|
// The server's identifier for this mailbox
|
|
|
|
public static final String SERVER_ID = "serverId";
|
|
|
|
// The server's identifier for the parent of this mailbox (null = top-level)
|
|
|
|
public static final String PARENT_SERVER_ID = "parentServerId";
|
|
|
|
// A foreign key to the Account that owns this mailbox
|
|
|
|
public static final String ACCOUNT_KEY = "accountKey";
|
|
|
|
// The type (role) of this mailbox
|
|
|
|
public static final String TYPE = "type";
|
|
|
|
// The hierarchy separator character
|
|
|
|
public static final String DELIMITER = "delimiter";
|
|
|
|
// Server-based sync key or validity marker (e.g. "SyncKey" for EAS, "uidvalidity" for IMAP)
|
|
|
|
public static final String SYNC_KEY = "syncKey";
|
|
|
|
// The sync lookback period for this mailbox (or null if using the account default)
|
|
|
|
public static final String SYNC_LOOKBACK = "syncLookback";
|
|
|
|
// The sync frequency for this mailbox (or null if using the account default)
|
2009-07-22 22:13:30 +00:00
|
|
|
public static final String SYNC_INTERVAL = "syncInterval";
|
2009-06-15 21:40:06 +00:00
|
|
|
// The time of last successful sync completion (millis)
|
|
|
|
public static final String SYNC_TIME = "syncTime";
|
|
|
|
// Cached unread count
|
|
|
|
public static final String UNREAD_COUNT = "unreadCount";
|
|
|
|
// Visibility of this folder in a list of folders [INDEX]
|
|
|
|
public static final String FLAG_VISIBLE = "flagVisible";
|
|
|
|
// Other states, as a bit field, e.g. CHILDREN_VISIBLE, HAS_CHILDREN
|
|
|
|
public static final String FLAGS = "flags";
|
|
|
|
// Backward compatible
|
|
|
|
public static final String VISIBLE_LIMIT = "visibleLimit";
|
2009-08-05 15:41:16 +00:00
|
|
|
// Sync status (can be used as desired by sync services)
|
|
|
|
public static final String SYNC_STATUS = "syncStatus";
|
2010-07-30 20:53:59 +00:00
|
|
|
// Number of messages in the mailbox.
|
|
|
|
public static final String MESSAGE_COUNT = "messageCount";
|
2009-06-15 21:40:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public static final class Mailbox extends EmailContent implements SyncColumns, MailboxColumns {
|
2009-06-16 19:03:45 +00:00
|
|
|
public static final String TABLE_NAME = "Mailbox";
|
2010-09-10 22:19:57 +00:00
|
|
|
@SuppressWarnings("hiding")
|
2009-06-16 19:03:45 +00:00
|
|
|
public static final Uri CONTENT_URI = Uri.parse(EmailContent.CONTENT_URI + "/mailbox");
|
2009-08-20 02:07:29 +00:00
|
|
|
public static final Uri ADD_TO_FIELD_URI =
|
|
|
|
Uri.parse(EmailContent.CONTENT_URI + "/mailboxIdAddToField");
|
2009-06-16 19:03:45 +00:00
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
public String mDisplayName;
|
|
|
|
public String mServerId;
|
|
|
|
public String mParentServerId;
|
|
|
|
public long mAccountKey;
|
|
|
|
public int mType;
|
|
|
|
public int mDelimiter;
|
|
|
|
public String mSyncKey;
|
|
|
|
public int mSyncLookback;
|
2009-07-22 22:13:30 +00:00
|
|
|
public int mSyncInterval;
|
2009-06-15 21:40:06 +00:00
|
|
|
public long mSyncTime;
|
|
|
|
public int mUnreadCount;
|
|
|
|
public boolean mFlagVisible = true;
|
|
|
|
public int mFlags;
|
|
|
|
public int mVisibleLimit;
|
2009-08-05 15:41:16 +00:00
|
|
|
public String mSyncStatus;
|
2010-07-30 20:53:59 +00:00
|
|
|
public int mMessageCount;
|
2009-06-15 21:40:06 +00:00
|
|
|
|
|
|
|
public static final int CONTENT_ID_COLUMN = 0;
|
|
|
|
public static final int CONTENT_DISPLAY_NAME_COLUMN = 1;
|
|
|
|
public static final int CONTENT_SERVER_ID_COLUMN = 2;
|
|
|
|
public static final int CONTENT_PARENT_SERVER_ID_COLUMN = 3;
|
|
|
|
public static final int CONTENT_ACCOUNT_KEY_COLUMN = 4;
|
|
|
|
public static final int CONTENT_TYPE_COLUMN = 5;
|
|
|
|
public static final int CONTENT_DELIMITER_COLUMN = 6;
|
|
|
|
public static final int CONTENT_SYNC_KEY_COLUMN = 7;
|
|
|
|
public static final int CONTENT_SYNC_LOOKBACK_COLUMN = 8;
|
2009-07-22 22:13:30 +00:00
|
|
|
public static final int CONTENT_SYNC_INTERVAL_COLUMN = 9;
|
2009-06-15 21:40:06 +00:00
|
|
|
public static final int CONTENT_SYNC_TIME_COLUMN = 10;
|
|
|
|
public static final int CONTENT_UNREAD_COUNT_COLUMN = 11;
|
|
|
|
public static final int CONTENT_FLAG_VISIBLE_COLUMN = 12;
|
|
|
|
public static final int CONTENT_FLAGS_COLUMN = 13;
|
|
|
|
public static final int CONTENT_VISIBLE_LIMIT_COLUMN = 14;
|
2009-08-05 15:41:16 +00:00
|
|
|
public static final int CONTENT_SYNC_STATUS_COLUMN = 15;
|
2010-07-30 20:53:59 +00:00
|
|
|
public static final int CONTENT_MESSAGE_COUNT_COLUMN = 16;
|
2009-06-15 21:40:06 +00:00
|
|
|
public static final String[] CONTENT_PROJECTION = new String[] {
|
|
|
|
RECORD_ID, MailboxColumns.DISPLAY_NAME, MailboxColumns.SERVER_ID,
|
|
|
|
MailboxColumns.PARENT_SERVER_ID, MailboxColumns.ACCOUNT_KEY, MailboxColumns.TYPE,
|
|
|
|
MailboxColumns.DELIMITER, MailboxColumns.SYNC_KEY, MailboxColumns.SYNC_LOOKBACK,
|
2009-07-22 22:13:30 +00:00
|
|
|
MailboxColumns.SYNC_INTERVAL, MailboxColumns.SYNC_TIME,MailboxColumns.UNREAD_COUNT,
|
2009-08-05 15:41:16 +00:00
|
|
|
MailboxColumns.FLAG_VISIBLE, MailboxColumns.FLAGS, MailboxColumns.VISIBLE_LIMIT,
|
2010-07-30 20:53:59 +00:00
|
|
|
MailboxColumns.SYNC_STATUS, MailboxColumns.MESSAGE_COUNT
|
2009-06-15 21:40:06 +00:00
|
|
|
};
|
2010-08-03 01:16:13 +00:00
|
|
|
|
|
|
|
private static final String MAILBOX_TYPE_SELECTION =
|
|
|
|
MailboxColumns.TYPE + " =?";
|
|
|
|
private static final String[] MAILBOX_SUM_OF_UNREAD_COUNT_PROJECTION = new String [] {
|
|
|
|
"sum(" + MailboxColumns.UNREAD_COUNT + ")"
|
|
|
|
};
|
|
|
|
private static final int UNREAD_COUNT_COUNT_COLUMN = 0;
|
|
|
|
private static final String[] MAILBOX_SUM_OF_MESSAGE_COUNT_PROJECTION = new String [] {
|
|
|
|
"sum(" + MailboxColumns.MESSAGE_COUNT + ")"
|
|
|
|
};
|
|
|
|
private static final int MESSAGE_COUNT_COUNT_COLUMN = 0;
|
|
|
|
|
2010-08-27 17:25:03 +00:00
|
|
|
private static final String[] MAILBOX_TYPE_PROJECTION = new String [] {
|
|
|
|
MailboxColumns.TYPE
|
|
|
|
};
|
|
|
|
private static final int MAILBOX_TYPE_TYPE_COLUMN = 0;
|
|
|
|
|
2009-07-09 21:46:03 +00:00
|
|
|
public static final long NO_MAILBOX = -1;
|
2009-06-15 21:40:06 +00:00
|
|
|
|
2009-08-12 05:25:39 +00:00
|
|
|
// Sentinel values for the mSyncInterval field of both Mailbox records
|
|
|
|
public static final int CHECK_INTERVAL_NEVER = -1;
|
|
|
|
public static final int CHECK_INTERVAL_PUSH = -2;
|
|
|
|
// The following two sentinel values are used by EAS
|
|
|
|
// Ping indicates that the EAS mailbox is synced based on a "ping" from the server
|
|
|
|
public static final int CHECK_INTERVAL_PING = -3;
|
|
|
|
// Push-Hold indicates an EAS push or ping Mailbox shouldn't sync just yet
|
|
|
|
public static final int CHECK_INTERVAL_PUSH_HOLD = -4;
|
|
|
|
|
2009-07-14 20:08:19 +00:00
|
|
|
private static final String WHERE_TYPE_AND_ACCOUNT_KEY =
|
|
|
|
MailboxColumns.TYPE + "=? and " + MailboxColumns.ACCOUNT_KEY + "=?";
|
|
|
|
|
2010-08-25 16:53:19 +00:00
|
|
|
public static final String MOVE_TO_TARGET_MAILBOX_SELECTION =
|
|
|
|
MailboxColumns.TYPE + " NOT IN (" + Mailbox.TYPE_DRAFTS + "," +
|
|
|
|
Mailbox.TYPE_OUTBOX + "," + Mailbox.TYPE_SENT + "," + Mailbox.TYPE_TRASH + ")";
|
|
|
|
|
2009-06-17 23:15:37 +00:00
|
|
|
// Types of mailboxes. The list is ordered to match a typical UI presentation, e.g.
|
|
|
|
// placing the inbox at the top.
|
|
|
|
// The "main" mailbox for the account, almost always referred to as "Inbox"
|
2009-09-02 19:41:16 +00:00
|
|
|
// Arrays of "special_mailbox_display_names" and "special_mailbox_icons" are depends on
|
|
|
|
// types Id of mailboxes.
|
2009-06-17 23:15:37 +00:00
|
|
|
public static final int TYPE_INBOX = 0;
|
2009-06-16 19:03:45 +00:00
|
|
|
// Types of mailboxes
|
2009-06-15 21:40:06 +00:00
|
|
|
// Holds mail (generic)
|
2009-06-17 23:15:37 +00:00
|
|
|
public static final int TYPE_MAIL = 1;
|
|
|
|
// Parent-only mailbox; holds no mail
|
|
|
|
public static final int TYPE_PARENT = 2;
|
2009-06-15 21:40:06 +00:00
|
|
|
// Holds drafts
|
|
|
|
public static final int TYPE_DRAFTS = 3;
|
|
|
|
// The local outbox associated with the Account
|
2009-06-17 23:15:37 +00:00
|
|
|
public static final int TYPE_OUTBOX = 4;
|
|
|
|
// Holds sent mail
|
|
|
|
public static final int TYPE_SENT = 5;
|
|
|
|
// Holds deleted mail
|
|
|
|
public static final int TYPE_TRASH = 6;
|
2009-06-15 21:40:06 +00:00
|
|
|
// Holds junk mail
|
2009-06-17 23:15:37 +00:00
|
|
|
public static final int TYPE_JUNK = 7;
|
2009-06-15 21:40:06 +00:00
|
|
|
|
2009-06-28 00:21:44 +00:00
|
|
|
// Types after this are used for non-mail mailboxes (as in EAS)
|
2009-07-05 19:54:49 +00:00
|
|
|
public static final int TYPE_NOT_EMAIL = 0x40;
|
2009-06-28 00:21:44 +00:00
|
|
|
public static final int TYPE_CALENDAR = 0x41;
|
|
|
|
public static final int TYPE_CONTACTS = 0x42;
|
|
|
|
public static final int TYPE_TASKS = 0x43;
|
2009-07-31 01:17:52 +00:00
|
|
|
public static final int TYPE_EAS_ACCOUNT_MAILBOX = 0x44;
|
2010-09-16 20:52:41 +00:00
|
|
|
public static final int TYPE_UNKNOWN = 0x45;
|
2009-06-28 00:21:44 +00:00
|
|
|
|
2010-05-04 22:33:08 +00:00
|
|
|
public static final int TYPE_NOT_SYNCABLE = 0x100;
|
|
|
|
// A mailbox that holds Messages that are attachments
|
|
|
|
public static final int TYPE_ATTACHMENT = 0x101;
|
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
// Bit field flags
|
|
|
|
public static final int FLAG_HAS_CHILDREN = 1<<0;
|
|
|
|
public static final int FLAG_CHILDREN_VISIBLE = 1<<1;
|
|
|
|
public static final int FLAG_CANT_PUSH = 1<<2;
|
|
|
|
|
2009-08-24 22:00:45 +00:00
|
|
|
// Magic mailbox ID's
|
|
|
|
// NOTE: This is a quick solution for merged mailboxes. I would rather implement this
|
|
|
|
// with a more generic way of packaging and sharing queries between activities
|
|
|
|
public static final long QUERY_ALL_INBOXES = -2;
|
|
|
|
public static final long QUERY_ALL_UNREAD = -3;
|
|
|
|
public static final long QUERY_ALL_FAVORITES = -4;
|
|
|
|
public static final long QUERY_ALL_DRAFTS = -5;
|
|
|
|
public static final long QUERY_ALL_OUTBOX = -6;
|
|
|
|
|
|
|
|
public Mailbox() {
|
|
|
|
mBaseUri = CONTENT_URI;
|
|
|
|
}
|
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
/**
|
|
|
|
* Restore a Mailbox from the database, given its unique id
|
|
|
|
* @param context
|
|
|
|
* @param id
|
|
|
|
* @return the instantiated Mailbox
|
|
|
|
*/
|
|
|
|
public static Mailbox restoreMailboxWithId(Context context, long id) {
|
|
|
|
Uri u = ContentUris.withAppendedId(Mailbox.CONTENT_URI, id);
|
|
|
|
Cursor c = context.getContentResolver().query(u, Mailbox.CONTENT_PROJECTION,
|
|
|
|
null, null, null);
|
|
|
|
|
|
|
|
try {
|
|
|
|
if (c.moveToFirst()) {
|
|
|
|
return EmailContent.getContent(c, Mailbox.class);
|
|
|
|
} else {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
} finally {
|
|
|
|
c.close();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
@SuppressWarnings("unchecked")
|
|
|
|
public EmailContent.Mailbox restore(Cursor cursor) {
|
2009-07-17 23:29:35 +00:00
|
|
|
mBaseUri = CONTENT_URI;
|
|
|
|
mId = cursor.getLong(CONTENT_ID_COLUMN);
|
2009-06-15 21:40:06 +00:00
|
|
|
mDisplayName = cursor.getString(CONTENT_DISPLAY_NAME_COLUMN);
|
|
|
|
mServerId = cursor.getString(CONTENT_SERVER_ID_COLUMN);
|
|
|
|
mParentServerId = cursor.getString(CONTENT_PARENT_SERVER_ID_COLUMN);
|
|
|
|
mAccountKey = cursor.getLong(CONTENT_ACCOUNT_KEY_COLUMN);
|
|
|
|
mType = cursor.getInt(CONTENT_TYPE_COLUMN);
|
|
|
|
mDelimiter = cursor.getInt(CONTENT_DELIMITER_COLUMN);
|
|
|
|
mSyncKey = cursor.getString(CONTENT_SYNC_KEY_COLUMN);
|
|
|
|
mSyncLookback = cursor.getInt(CONTENT_SYNC_LOOKBACK_COLUMN);
|
2009-07-22 22:13:30 +00:00
|
|
|
mSyncInterval = cursor.getInt(CONTENT_SYNC_INTERVAL_COLUMN);
|
2009-06-15 21:40:06 +00:00
|
|
|
mSyncTime = cursor.getLong(CONTENT_SYNC_TIME_COLUMN);
|
|
|
|
mUnreadCount = cursor.getInt(CONTENT_UNREAD_COUNT_COLUMN);
|
|
|
|
mFlagVisible = cursor.getInt(CONTENT_FLAG_VISIBLE_COLUMN) == 1;
|
|
|
|
mFlags = cursor.getInt(CONTENT_FLAGS_COLUMN);
|
|
|
|
mVisibleLimit = cursor.getInt(CONTENT_VISIBLE_LIMIT_COLUMN);
|
2009-08-05 15:41:16 +00:00
|
|
|
mSyncStatus = cursor.getString(CONTENT_SYNC_STATUS_COLUMN);
|
2010-07-30 20:53:59 +00:00
|
|
|
mMessageCount = cursor.getInt(CONTENT_MESSAGE_COUNT_COLUMN);
|
2009-06-15 21:40:06 +00:00
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public ContentValues toContentValues() {
|
|
|
|
ContentValues values = new ContentValues();
|
2009-07-30 18:41:31 +00:00
|
|
|
values.put(MailboxColumns.DISPLAY_NAME, mDisplayName);
|
|
|
|
values.put(MailboxColumns.SERVER_ID, mServerId);
|
|
|
|
values.put(MailboxColumns.PARENT_SERVER_ID, mParentServerId);
|
|
|
|
values.put(MailboxColumns.ACCOUNT_KEY, mAccountKey);
|
|
|
|
values.put(MailboxColumns.TYPE, mType);
|
|
|
|
values.put(MailboxColumns.DELIMITER, mDelimiter);
|
|
|
|
values.put(MailboxColumns.SYNC_KEY, mSyncKey);
|
|
|
|
values.put(MailboxColumns.SYNC_LOOKBACK, mSyncLookback);
|
|
|
|
values.put(MailboxColumns.SYNC_INTERVAL, mSyncInterval);
|
|
|
|
values.put(MailboxColumns.SYNC_TIME, mSyncTime);
|
|
|
|
values.put(MailboxColumns.UNREAD_COUNT, mUnreadCount);
|
|
|
|
values.put(MailboxColumns.FLAG_VISIBLE, mFlagVisible);
|
|
|
|
values.put(MailboxColumns.FLAGS, mFlags);
|
|
|
|
values.put(MailboxColumns.VISIBLE_LIMIT, mVisibleLimit);
|
2009-08-05 15:41:16 +00:00
|
|
|
values.put(MailboxColumns.SYNC_STATUS, mSyncStatus);
|
2010-07-30 20:53:59 +00:00
|
|
|
values.put(MailboxColumns.MESSAGE_COUNT, mMessageCount);
|
2009-06-15 21:40:06 +00:00
|
|
|
return values;
|
|
|
|
}
|
2009-07-14 20:08:19 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Convenience method to return the id of a given type of Mailbox for a given Account
|
|
|
|
* @param context the caller's context, used to get a ContentResolver
|
|
|
|
* @param accountId the id of the account to be queried
|
|
|
|
* @param type the mailbox type, as defined above
|
|
|
|
* @return the id of the mailbox, or -1 if not found
|
|
|
|
*/
|
|
|
|
public static long findMailboxOfType(Context context, long accountId, int type) {
|
|
|
|
String[] bindArguments = new String[] {Long.toString(type), Long.toString(accountId)};
|
2010-07-27 19:52:46 +00:00
|
|
|
return Utility.getFirstRowLong(context, Mailbox.CONTENT_URI,
|
|
|
|
ID_PROJECTION, WHERE_TYPE_AND_ACCOUNT_KEY, bindArguments, null,
|
|
|
|
ID_PROJECTION_COLUMN, NO_MAILBOX);
|
2009-07-14 20:08:19 +00:00
|
|
|
}
|
2010-02-12 02:14:01 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Convenience method that returns the mailbox found using the method above
|
|
|
|
*/
|
|
|
|
public static Mailbox restoreMailboxOfType(Context context, long accountId, int type) {
|
|
|
|
long mailboxId = findMailboxOfType(context, accountId, type);
|
|
|
|
if (mailboxId != Mailbox.NO_MAILBOX) {
|
|
|
|
return Mailbox.restoreMailboxWithId(context, mailboxId);
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
2010-08-03 01:16:13 +00:00
|
|
|
|
|
|
|
public static int getUnreadCountByMailboxType(Context context, int type) {
|
2010-09-24 21:50:20 +00:00
|
|
|
return Utility.getFirstRowInt(context, Mailbox.CONTENT_URI,
|
2010-08-03 01:16:13 +00:00
|
|
|
MAILBOX_SUM_OF_UNREAD_COUNT_PROJECTION,
|
|
|
|
MAILBOX_TYPE_SELECTION,
|
2010-09-24 21:50:20 +00:00
|
|
|
new String[] { String.valueOf(type) }, null, UNREAD_COUNT_COUNT_COLUMN, 0);
|
2010-08-03 01:16:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public static int getMessageCountByMailboxType(Context context, int type) {
|
2010-09-24 21:50:20 +00:00
|
|
|
return Utility.getFirstRowInt(context, Mailbox.CONTENT_URI,
|
2010-08-03 01:16:13 +00:00
|
|
|
MAILBOX_SUM_OF_MESSAGE_COUNT_PROJECTION,
|
|
|
|
MAILBOX_TYPE_SELECTION,
|
2010-09-24 21:50:20 +00:00
|
|
|
new String[] { String.valueOf(type) }, null, MESSAGE_COUNT_COUNT_COLUMN, 0);
|
2010-08-03 01:16:13 +00:00
|
|
|
}
|
2010-08-24 04:39:35 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Return the mailbox for a message with a given id
|
|
|
|
* @param context the caller's context
|
|
|
|
* @param messageId the id of the message
|
|
|
|
* @return the mailbox, or null if the mailbox doesn't exist
|
|
|
|
*/
|
|
|
|
public static Mailbox getMailboxForMessageId(Context context, long messageId) {
|
|
|
|
long mailboxId = Message.getKeyColumnLong(context, messageId,
|
|
|
|
MessageColumns.MAILBOX_KEY);
|
|
|
|
if (mailboxId != -1) {
|
|
|
|
return Mailbox.restoreMailboxWithId(context, mailboxId);
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
2010-08-27 17:25:03 +00:00
|
|
|
|
2010-09-01 21:34:55 +00:00
|
|
|
/**
|
|
|
|
* @return mailbox type, or -1 if mailbox not found.
|
|
|
|
*/
|
|
|
|
public static int getMailboxType(Context context, long mailboxId) {
|
|
|
|
Uri url = ContentUris.withAppendedId(Mailbox.CONTENT_URI, mailboxId);
|
|
|
|
return Utility.getFirstRowInt(context, url, MAILBOX_TYPE_PROJECTION,
|
|
|
|
null, null, null, MAILBOX_TYPE_TYPE_COLUMN, -1);
|
|
|
|
}
|
|
|
|
|
2010-08-27 17:25:03 +00:00
|
|
|
/**
|
2010-09-02 21:49:36 +00:00
|
|
|
* @param mailboxId ID of a mailbox. This method accepts magic mailbox IDs, such as
|
|
|
|
* {@link #QUERY_ALL_INBOXES}. (They're all non-refreshable.)
|
2010-08-27 17:25:03 +00:00
|
|
|
* @return true if a mailbox is refreshable.
|
|
|
|
*/
|
|
|
|
public static boolean isRefreshable(Context context, long mailboxId) {
|
|
|
|
if (mailboxId < 0) {
|
|
|
|
return false; // magic mailboxes
|
|
|
|
}
|
2010-09-01 21:34:55 +00:00
|
|
|
switch (getMailboxType(context, mailboxId)) {
|
|
|
|
case -1: // not found
|
2010-08-27 17:25:03 +00:00
|
|
|
case TYPE_DRAFTS:
|
|
|
|
case TYPE_OUTBOX:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
2010-09-02 21:49:36 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @param mailboxId ID of a mailbox. This method DOES NOT accept magic mailbox IDs, such as
|
|
|
|
* {@link #QUERY_ALL_INBOXES} (because only the actual mailbox ID matters here. e.g.
|
|
|
|
* {@link #QUERY_ALL_FAVORITES} can contain ANY kind of messages), so don't pass a negative
|
|
|
|
* value.
|
|
|
|
* @return true if messages in a mailbox can be moved to another mailbox.
|
|
|
|
* This method only checks the mailbox information. It doesn't check its account/protocol,
|
|
|
|
* so it may return true even for POP3 mailbox.
|
|
|
|
*/
|
|
|
|
public static boolean canMoveFrom(Context context, long mailboxId) {
|
|
|
|
if (mailboxId < 0) {
|
|
|
|
throw new InvalidParameterException();
|
|
|
|
}
|
|
|
|
Uri url = ContentUris.withAppendedId(Mailbox.CONTENT_URI, mailboxId);
|
|
|
|
int type = Utility.getFirstRowInt(context, url, MAILBOX_TYPE_PROJECTION,
|
|
|
|
null, null, null, MAILBOX_TYPE_TYPE_COLUMN);
|
|
|
|
switch (type) {
|
|
|
|
case TYPE_INBOX:
|
|
|
|
case TYPE_MAIL:
|
|
|
|
case TYPE_TRASH:
|
|
|
|
case TYPE_JUNK:
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false; // TYPE_DRAFTS, TYPE_OUTBOX, TYPE_SENT, etc
|
|
|
|
}
|
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public interface HostAuthColumns {
|
|
|
|
public static final String ID = "_id";
|
|
|
|
// The protocol (e.g. "imap", "pop3", "eas", "smtp"
|
|
|
|
static final String PROTOCOL = "protocol";
|
|
|
|
// The host address
|
2009-07-30 18:41:31 +00:00
|
|
|
static final String ADDRESS = "address";
|
2009-06-15 21:40:06 +00:00
|
|
|
// The port to use for the connection
|
2009-07-30 18:41:31 +00:00
|
|
|
static final String PORT = "port";
|
2009-06-15 21:40:06 +00:00
|
|
|
// General purpose flags
|
2009-07-30 18:41:31 +00:00
|
|
|
static final String FLAGS = "flags";
|
2009-06-15 21:40:06 +00:00
|
|
|
// The login (user name)
|
2009-07-30 18:41:31 +00:00
|
|
|
static final String LOGIN = "login";
|
2009-06-15 21:40:06 +00:00
|
|
|
// Password
|
2009-07-30 18:41:31 +00:00
|
|
|
static final String PASSWORD = "password";
|
2009-06-15 21:40:06 +00:00
|
|
|
// A domain or path, if required (used in IMAP and EAS)
|
2009-07-30 18:41:31 +00:00
|
|
|
static final String DOMAIN = "domain";
|
2009-09-15 21:10:12 +00:00
|
|
|
// DEPRECATED - Will not be set or stored
|
2009-06-15 21:40:06 +00:00
|
|
|
static final String ACCOUNT_KEY = "accountKey";
|
|
|
|
}
|
|
|
|
|
|
|
|
public static final class HostAuth extends EmailContent implements HostAuthColumns, Parcelable {
|
2009-06-16 19:03:45 +00:00
|
|
|
public static final String TABLE_NAME = "HostAuth";
|
2010-09-10 22:19:57 +00:00
|
|
|
@SuppressWarnings("hiding")
|
2009-06-16 19:03:45 +00:00
|
|
|
public static final Uri CONTENT_URI = Uri.parse(EmailContent.CONTENT_URI + "/hostauth");
|
|
|
|
|
2009-07-05 19:54:49 +00:00
|
|
|
public static final int FLAG_SSL = 1;
|
|
|
|
public static final int FLAG_TLS = 2;
|
|
|
|
public static final int FLAG_AUTHENTICATE = 4;
|
2009-09-05 22:14:46 +00:00
|
|
|
public static final int FLAG_TRUST_ALL_CERTIFICATES = 8;
|
2009-06-15 21:40:06 +00:00
|
|
|
|
|
|
|
public String mProtocol;
|
|
|
|
public String mAddress;
|
|
|
|
public int mPort;
|
|
|
|
public int mFlags;
|
|
|
|
public String mLogin;
|
|
|
|
public String mPassword;
|
|
|
|
public String mDomain;
|
2009-09-15 21:10:12 +00:00
|
|
|
public long mAccountKey; // DEPRECATED - Will not be set or stored
|
2009-06-15 21:40:06 +00:00
|
|
|
|
|
|
|
public static final int CONTENT_ID_COLUMN = 0;
|
|
|
|
public static final int CONTENT_PROTOCOL_COLUMN = 1;
|
|
|
|
public static final int CONTENT_ADDRESS_COLUMN = 2;
|
|
|
|
public static final int CONTENT_PORT_COLUMN = 3;
|
|
|
|
public static final int CONTENT_FLAGS_COLUMN = 4;
|
|
|
|
public static final int CONTENT_LOGIN_COLUMN = 5;
|
|
|
|
public static final int CONTENT_PASSWORD_COLUMN = 6;
|
|
|
|
public static final int CONTENT_DOMAIN_COLUMN = 7;
|
|
|
|
public static final int CONTENT_ACCOUNT_KEY_COLUMN = 8;
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
public static final String[] CONTENT_PROJECTION = new String[] {
|
|
|
|
RECORD_ID, HostAuthColumns.PROTOCOL, HostAuthColumns.ADDRESS, HostAuthColumns.PORT,
|
|
|
|
HostAuthColumns.FLAGS, HostAuthColumns.LOGIN,
|
|
|
|
HostAuthColumns.PASSWORD, HostAuthColumns.DOMAIN,
|
|
|
|
HostAuthColumns.ACCOUNT_KEY
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* no public constructor since this is a utility class
|
|
|
|
*/
|
|
|
|
public HostAuth() {
|
|
|
|
mBaseUri = CONTENT_URI;
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
// other defaults policy)
|
|
|
|
mPort = -1;
|
|
|
|
}
|
|
|
|
|
2009-06-16 19:03:45 +00:00
|
|
|
/**
|
2009-06-15 21:40:06 +00:00
|
|
|
* Restore a HostAuth from the database, given its unique id
|
|
|
|
* @param context
|
|
|
|
* @param id
|
|
|
|
* @return the instantiated HostAuth
|
|
|
|
*/
|
|
|
|
public static HostAuth restoreHostAuthWithId(Context context, long id) {
|
|
|
|
Uri u = ContentUris.withAppendedId(EmailContent.HostAuth.CONTENT_URI, id);
|
|
|
|
Cursor c = context.getContentResolver().query(u, HostAuth.CONTENT_PROJECTION,
|
|
|
|
null, null, null);
|
|
|
|
|
|
|
|
try {
|
|
|
|
if (c.moveToFirst()) {
|
|
|
|
return getContent(c, HostAuth.class);
|
|
|
|
} else {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
} finally {
|
|
|
|
c.close();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
@SuppressWarnings("unchecked")
|
|
|
|
public EmailContent.HostAuth restore(Cursor cursor) {
|
2009-07-17 23:29:35 +00:00
|
|
|
mBaseUri = CONTENT_URI;
|
|
|
|
mId = cursor.getLong(CONTENT_ID_COLUMN);
|
2009-06-15 21:40:06 +00:00
|
|
|
mProtocol = cursor.getString(CONTENT_PROTOCOL_COLUMN);
|
|
|
|
mAddress = cursor.getString(CONTENT_ADDRESS_COLUMN);
|
|
|
|
mPort = cursor.getInt(CONTENT_PORT_COLUMN);
|
|
|
|
mFlags = cursor.getInt(CONTENT_FLAGS_COLUMN);
|
|
|
|
mLogin = cursor.getString(CONTENT_LOGIN_COLUMN);
|
|
|
|
mPassword = cursor.getString(CONTENT_PASSWORD_COLUMN);
|
|
|
|
mDomain = cursor.getString(CONTENT_DOMAIN_COLUMN);
|
|
|
|
mAccountKey = cursor.getLong(CONTENT_ACCOUNT_KEY_COLUMN);
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public ContentValues toContentValues() {
|
|
|
|
ContentValues values = new ContentValues();
|
|
|
|
values.put(HostAuthColumns.PROTOCOL, mProtocol);
|
|
|
|
values.put(HostAuthColumns.ADDRESS, mAddress);
|
|
|
|
values.put(HostAuthColumns.PORT, mPort);
|
|
|
|
values.put(HostAuthColumns.FLAGS, mFlags);
|
|
|
|
values.put(HostAuthColumns.LOGIN, mLogin);
|
|
|
|
values.put(HostAuthColumns.PASSWORD, mPassword);
|
|
|
|
values.put(HostAuthColumns.DOMAIN, mDomain);
|
|
|
|
values.put(HostAuthColumns.ACCOUNT_KEY, mAccountKey);
|
|
|
|
return values;
|
|
|
|
}
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
/**
|
|
|
|
* For compatibility while converting to provider model, generate a "store URI"
|
|
|
|
* TODO cache this so we don't rebuild every time
|
2009-07-30 18:41:31 +00:00
|
|
|
*
|
2009-06-15 21:40:06 +00:00
|
|
|
* @return a string in the form of a Uri, as used by the other parts of the email app
|
|
|
|
*/
|
|
|
|
public String getStoreUri() {
|
2009-09-29 22:28:43 +00:00
|
|
|
String security;
|
|
|
|
switch (mFlags & (FLAG_SSL | FLAG_TLS | FLAG_TRUST_ALL_CERTIFICATES)) {
|
|
|
|
case FLAG_SSL:
|
|
|
|
security = "+ssl+";
|
|
|
|
break;
|
|
|
|
case FLAG_SSL | FLAG_TRUST_ALL_CERTIFICATES:
|
|
|
|
security = "+ssl+trustallcerts";
|
|
|
|
break;
|
|
|
|
case FLAG_TLS:
|
|
|
|
security = "+tls+";
|
|
|
|
break;
|
|
|
|
case FLAG_TLS | FLAG_TRUST_ALL_CERTIFICATES:
|
|
|
|
security = "+tls+trustallcerts";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
security = "";
|
|
|
|
break;
|
2009-06-15 21:40:06 +00:00
|
|
|
}
|
|
|
|
String userInfo = null;
|
|
|
|
if ((mFlags & FLAG_AUTHENTICATE) != 0) {
|
|
|
|
String trimUser = (mLogin != null) ? mLogin.trim() : "";
|
|
|
|
String trimPassword = (mPassword != null) ? mPassword.trim() : "";
|
|
|
|
userInfo = trimUser + ":" + trimPassword;
|
|
|
|
}
|
|
|
|
String address = (mAddress != null) ? mAddress.trim() : null;
|
|
|
|
String path = (mDomain != null) ? "/" + mDomain : null;
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
URI uri;
|
|
|
|
try {
|
|
|
|
uri = new URI(
|
|
|
|
mProtocol + security,
|
|
|
|
userInfo,
|
|
|
|
address,
|
|
|
|
mPort,
|
|
|
|
path,
|
|
|
|
null,
|
|
|
|
null);
|
|
|
|
return uri.toString();
|
|
|
|
} catch (URISyntaxException e) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
/**
|
|
|
|
* For compatibility while converting to provider model, set fields from a "store URI"
|
2009-07-30 18:41:31 +00:00
|
|
|
*
|
2009-06-15 21:40:06 +00:00
|
|
|
* @param uriString a String containing a Uri
|
|
|
|
*/
|
|
|
|
@Deprecated
|
|
|
|
public void setStoreUri(String uriString) {
|
|
|
|
try {
|
|
|
|
URI uri = new URI(uriString);
|
|
|
|
mLogin = null;
|
|
|
|
mPassword = null;
|
|
|
|
mFlags &= ~FLAG_AUTHENTICATE;
|
|
|
|
if (uri.getUserInfo() != null) {
|
|
|
|
String[] userInfoParts = uri.getUserInfo().split(":", 2);
|
|
|
|
mLogin = userInfoParts[0];
|
|
|
|
mFlags |= FLAG_AUTHENTICATE;
|
|
|
|
if (userInfoParts.length > 1) {
|
|
|
|
mPassword = userInfoParts[1];
|
|
|
|
}
|
|
|
|
}
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2009-09-29 22:28:43 +00:00
|
|
|
// Set protocol, security, and additional flags based on uri scheme
|
2009-06-15 21:40:06 +00:00
|
|
|
String[] schemeParts = uri.getScheme().split("\\+");
|
|
|
|
mProtocol = (schemeParts.length >= 1) ? schemeParts[0] : null;
|
2009-09-29 22:28:43 +00:00
|
|
|
mFlags &= ~(FLAG_SSL | FLAG_TLS | FLAG_TRUST_ALL_CERTIFICATES);
|
2009-06-15 21:40:06 +00:00
|
|
|
boolean ssl = false;
|
|
|
|
if (schemeParts.length >= 2) {
|
2009-09-05 22:14:46 +00:00
|
|
|
String part1 = schemeParts[1];
|
2009-09-29 22:28:43 +00:00
|
|
|
if ("ssl".equals(part1)) {
|
2009-09-05 22:14:46 +00:00
|
|
|
ssl = true;
|
2009-09-29 22:28:43 +00:00
|
|
|
mFlags |= FLAG_SSL;
|
2009-09-05 22:14:46 +00:00
|
|
|
} else if ("tls".equals(part1)) {
|
2009-09-29 22:28:43 +00:00
|
|
|
mFlags |= FLAG_TLS;
|
|
|
|
}
|
|
|
|
if (schemeParts.length >= 3) {
|
|
|
|
String part2 = schemeParts[2];
|
|
|
|
if ("trustallcerts".equals(part2)) {
|
|
|
|
mFlags |= FLAG_TRUST_ALL_CERTIFICATES;
|
|
|
|
}
|
2009-06-15 21:40:06 +00:00
|
|
|
}
|
2009-09-05 22:14:46 +00:00
|
|
|
}
|
2009-06-15 21:40:06 +00:00
|
|
|
|
|
|
|
mAddress = uri.getHost();
|
|
|
|
mPort = uri.getPort();
|
|
|
|
if (mPort == -1) {
|
|
|
|
// infer port# from protocol + security
|
|
|
|
// SSL implies a different port - TLS runs in the "regular" port
|
2009-09-29 22:28:43 +00:00
|
|
|
// TODO: This really shouldn't be here - it should have been set up
|
|
|
|
// in the account setup screens.
|
2009-06-15 21:40:06 +00:00
|
|
|
if ("pop3".equals(mProtocol)) {
|
|
|
|
mPort = ssl ? 995 : 110;
|
|
|
|
} else if ("imap".equals(mProtocol)) {
|
2009-09-29 22:28:43 +00:00
|
|
|
mPort = ssl ? 993 : 143;
|
2009-06-15 21:40:06 +00:00
|
|
|
} else if ("eas".equals(mProtocol)) {
|
2009-09-29 22:28:43 +00:00
|
|
|
mPort = ssl ? 443 : 80;
|
2009-06-15 21:40:06 +00:00
|
|
|
} else if ("smtp".equals(mProtocol)) {
|
2009-09-29 22:28:43 +00:00
|
|
|
mPort = ssl ? 465 : 587;
|
2009-06-15 21:40:06 +00:00
|
|
|
}
|
|
|
|
}
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
if (uri.getPath() != null && uri.getPath().length() > 0) {
|
|
|
|
mDomain = uri.getPath().substring(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
} catch (URISyntaxException use) {
|
|
|
|
/*
|
|
|
|
* We should always be able to parse our own settings.
|
|
|
|
*/
|
|
|
|
throw new Error(use);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
/**
|
|
|
|
* Supports Parcelable
|
|
|
|
*/
|
|
|
|
public int describeContents() {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Supports Parcelable
|
|
|
|
*/
|
|
|
|
public static final Parcelable.Creator<EmailContent.HostAuth> CREATOR
|
|
|
|
= new Parcelable.Creator<EmailContent.HostAuth>() {
|
|
|
|
public EmailContent.HostAuth createFromParcel(Parcel in) {
|
|
|
|
return new EmailContent.HostAuth(in);
|
|
|
|
}
|
|
|
|
|
|
|
|
public EmailContent.HostAuth[] newArray(int size) {
|
|
|
|
return new EmailContent.HostAuth[size];
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Supports Parcelable
|
|
|
|
*/
|
|
|
|
public void writeToParcel(Parcel dest, int flags) {
|
|
|
|
// mBaseUri is not parceled
|
|
|
|
dest.writeLong(mId);
|
|
|
|
dest.writeString(mProtocol);
|
|
|
|
dest.writeString(mAddress);
|
|
|
|
dest.writeInt(mPort);
|
|
|
|
dest.writeInt(mFlags);
|
|
|
|
dest.writeString(mLogin);
|
|
|
|
dest.writeString(mPassword);
|
|
|
|
dest.writeString(mDomain);
|
|
|
|
dest.writeLong(mAccountKey);
|
|
|
|
}
|
2009-07-30 18:41:31 +00:00
|
|
|
|
2009-06-15 21:40:06 +00:00
|
|
|
/**
|
|
|
|
* Supports Parcelable
|
|
|
|
*/
|
|
|
|
public HostAuth(Parcel in) {
|
|
|
|
mBaseUri = CONTENT_URI;
|
|
|
|
mId = in.readLong();
|
|
|
|
mProtocol = in.readString();
|
|
|
|
mAddress = in.readString();
|
|
|
|
mPort = in.readInt();
|
|
|
|
mFlags = in.readInt();
|
|
|
|
mLogin = in.readString();
|
|
|
|
mPassword = in.readString();
|
|
|
|
mDomain = in.readString();
|
|
|
|
mAccountKey = in.readLong();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* For debugger support only - DO NOT use for code.
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public String toString() {
|
|
|
|
return getStoreUri();
|
|
|
|
}
|
|
|
|
}
|
2009-08-12 10:51:26 +00:00
|
|
|
}
|