2011-02-10 19:29:46 -05:00
|
|
|
package com.fsck.k9.view;
|
|
|
|
|
2011-02-11 10:09:15 -05:00
|
|
|
import android.app.Activity;
|
2011-02-14 11:54:01 -05:00
|
|
|
import android.content.ContentResolver;
|
2011-02-10 19:29:46 -05:00
|
|
|
import android.content.Context;
|
2011-02-14 11:54:01 -05:00
|
|
|
import android.content.Intent;
|
|
|
|
import android.content.pm.ResolveInfo;
|
|
|
|
import android.database.Cursor;
|
|
|
|
import android.net.Uri;
|
2012-04-01 16:46:36 -04:00
|
|
|
import android.os.AsyncTask;
|
2012-02-23 21:43:42 -05:00
|
|
|
import android.os.Parcel;
|
|
|
|
import android.os.Parcelable;
|
2011-02-10 19:29:46 -05:00
|
|
|
import android.util.AttributeSet;
|
2011-02-11 10:09:15 -05:00
|
|
|
import android.util.Log;
|
2012-04-01 16:46:36 -04:00
|
|
|
import android.view.ContextMenu;
|
|
|
|
import android.view.ContextMenu.ContextMenuInfo;
|
2011-02-11 10:09:15 -05:00
|
|
|
import android.view.KeyEvent;
|
|
|
|
import android.view.LayoutInflater;
|
2012-04-01 16:46:36 -04:00
|
|
|
import android.view.Menu;
|
|
|
|
import android.view.MenuItem;
|
|
|
|
import android.view.MenuItem.OnMenuItemClickListener;
|
2011-02-11 10:09:15 -05:00
|
|
|
import android.view.View;
|
2012-04-01 16:46:36 -04:00
|
|
|
import android.view.View.*;
|
|
|
|
import android.webkit.WebView;
|
|
|
|
import android.webkit.WebView.HitTestResult;
|
2011-02-11 10:09:15 -05:00
|
|
|
import android.widget.Button;
|
2011-02-10 19:29:46 -05:00
|
|
|
import android.widget.LinearLayout;
|
2012-04-01 16:46:36 -04:00
|
|
|
import android.widget.Toast;
|
|
|
|
|
2011-02-11 10:09:15 -05:00
|
|
|
import com.fsck.k9.Account;
|
|
|
|
import com.fsck.k9.K9;
|
|
|
|
import com.fsck.k9.R;
|
2012-02-20 22:56:05 -05:00
|
|
|
import com.fsck.k9.activity.K9Activity;
|
2011-02-11 10:09:15 -05:00
|
|
|
import com.fsck.k9.controller.MessagingController;
|
|
|
|
import com.fsck.k9.controller.MessagingListener;
|
|
|
|
import com.fsck.k9.crypto.CryptoProvider;
|
|
|
|
import com.fsck.k9.crypto.PgpData;
|
2012-04-01 16:46:36 -04:00
|
|
|
import com.fsck.k9.helper.ClipboardManager;
|
2011-02-14 12:27:40 -05:00
|
|
|
import com.fsck.k9.helper.Contacts;
|
|
|
|
import com.fsck.k9.helper.Utility;
|
2011-02-11 10:09:15 -05:00
|
|
|
import com.fsck.k9.mail.*;
|
2012-04-01 16:46:36 -04:00
|
|
|
import com.fsck.k9.mail.internet.MimeUtility;
|
2011-02-11 10:09:15 -05:00
|
|
|
import com.fsck.k9.mail.store.LocalStore;
|
2012-02-23 21:43:42 -05:00
|
|
|
import com.fsck.k9.mail.store.LocalStore.LocalMessage;
|
2012-04-01 16:46:36 -04:00
|
|
|
import com.fsck.k9.provider.AttachmentProvider.AttachmentProviderColumns;
|
|
|
|
|
|
|
|
import org.apache.commons.io.IOUtils;
|
|
|
|
|
|
|
|
import java.io.File;
|
|
|
|
import java.io.FileOutputStream;
|
|
|
|
import java.io.InputStream;
|
|
|
|
import java.net.URL;
|
|
|
|
import java.net.URLConnection;
|
|
|
|
import java.net.URLDecoder;
|
2011-02-14 11:54:01 -05:00
|
|
|
import java.util.List;
|
|
|
|
|
2011-02-10 19:29:46 -05:00
|
|
|
|
2012-03-01 23:16:58 -05:00
|
|
|
public class SingleMessageView extends LinearLayout implements OnClickListener,
|
2012-04-01 16:46:36 -04:00
|
|
|
MessageHeader.OnLayoutChangedListener, OnCreateContextMenuListener {
|
|
|
|
private static final int MENU_ITEM_LINK_VIEW = Menu.FIRST;
|
|
|
|
private static final int MENU_ITEM_LINK_SHARE = Menu.FIRST + 1;
|
|
|
|
private static final int MENU_ITEM_LINK_COPY = Menu.FIRST + 2;
|
|
|
|
|
|
|
|
private static final int MENU_ITEM_IMAGE_VIEW = Menu.FIRST;
|
|
|
|
private static final int MENU_ITEM_IMAGE_SAVE = Menu.FIRST + 1;
|
|
|
|
private static final int MENU_ITEM_IMAGE_COPY = Menu.FIRST + 2;
|
|
|
|
|
|
|
|
private static final int MENU_ITEM_PHONE_CALL = Menu.FIRST;
|
|
|
|
private static final int MENU_ITEM_PHONE_SAVE = Menu.FIRST + 1;
|
|
|
|
private static final int MENU_ITEM_PHONE_COPY = Menu.FIRST + 2;
|
|
|
|
|
|
|
|
private static final int MENU_ITEM_EMAIL_SEND = Menu.FIRST;
|
|
|
|
private static final int MENU_ITEM_EMAIL_SAVE = Menu.FIRST + 1;
|
|
|
|
private static final int MENU_ITEM_EMAIL_COPY = Menu.FIRST + 2;
|
|
|
|
|
|
|
|
private static final String[] ATTACHMENT_PROJECTION = new String[] {
|
|
|
|
AttachmentProviderColumns._ID,
|
|
|
|
AttachmentProviderColumns.DISPLAY_NAME
|
|
|
|
};
|
|
|
|
private static final int DISPLAY_NAME_INDEX = 1;
|
|
|
|
|
|
|
|
|
2011-02-11 10:09:15 -05:00
|
|
|
private boolean mScreenReaderEnabled;
|
|
|
|
private MessageCryptoView mCryptoView;
|
|
|
|
private MessageWebView mMessageContentView;
|
|
|
|
private AccessibleWebView mAccessibleMessageContentView;
|
|
|
|
private MessageHeader mHeaderContainer;
|
2011-11-02 11:34:06 -04:00
|
|
|
private LinearLayout mAttachments;
|
2012-02-20 22:56:05 -05:00
|
|
|
private Button mShowHiddenAttachments;
|
|
|
|
private LinearLayout mHiddenAttachments;
|
|
|
|
private View mShowPicturesAction;
|
|
|
|
private View mShowMessageAction;
|
|
|
|
private View mShowAttachmentsAction;
|
2011-02-11 10:09:15 -05:00
|
|
|
private boolean mShowPictures;
|
2012-02-22 16:56:05 -05:00
|
|
|
private boolean mHasAttachments;
|
2011-02-11 10:09:15 -05:00
|
|
|
private Button mDownloadRemainder;
|
2011-02-11 12:13:18 -05:00
|
|
|
private LayoutInflater mInflater;
|
2011-02-14 12:27:40 -05:00
|
|
|
private Contacts mContacts;
|
2011-04-24 00:00:10 -04:00
|
|
|
private AttachmentView.AttachmentFileDownloadCallback attachmentCallback;
|
2012-02-20 22:56:05 -05:00
|
|
|
private LinearLayout mHeaderPlaceHolder;
|
|
|
|
private LinearLayout mTitleBarHeaderContainer;
|
|
|
|
private View mAttachmentsContainer;
|
2012-02-24 18:43:09 -05:00
|
|
|
private LinearLayout mInsideAttachmentsContainer;
|
2012-02-23 21:43:42 -05:00
|
|
|
private SavedState mSavedState;
|
2012-04-01 16:46:36 -04:00
|
|
|
private ClipboardManager mClipboardManager;
|
|
|
|
|
2011-02-11 10:09:15 -05:00
|
|
|
|
2011-02-14 11:54:01 -05:00
|
|
|
public void initialize(Activity activity) {
|
2011-02-11 10:09:15 -05:00
|
|
|
mMessageContentView = (MessageWebView) findViewById(R.id.message_content);
|
|
|
|
mAccessibleMessageContentView = (AccessibleWebView) findViewById(R.id.accessible_message_content);
|
2012-02-20 22:56:05 -05:00
|
|
|
mMessageContentView.configure();
|
2012-04-01 16:46:36 -04:00
|
|
|
activity.registerForContextMenu(mMessageContentView);
|
|
|
|
mMessageContentView.setOnCreateContextMenuListener(this);
|
2012-02-20 22:56:05 -05:00
|
|
|
|
|
|
|
mHeaderPlaceHolder = (LinearLayout) findViewById(R.id.message_view_header_container);
|
|
|
|
|
2011-02-11 10:09:15 -05:00
|
|
|
mHeaderContainer = (MessageHeader) findViewById(R.id.header_container);
|
2012-03-01 23:16:58 -05:00
|
|
|
mHeaderContainer.setOnLayoutChangedListener(this);
|
2012-02-20 22:56:05 -05:00
|
|
|
|
|
|
|
mAttachmentsContainer = findViewById(R.id.attachments_container);
|
2012-02-24 18:43:09 -05:00
|
|
|
mInsideAttachmentsContainer = (LinearLayout) findViewById(R.id.inside_attachments_container);
|
2012-02-20 22:56:05 -05:00
|
|
|
mAttachments = (LinearLayout) findViewById(R.id.attachments);
|
|
|
|
mHiddenAttachments = (LinearLayout) findViewById(R.id.hidden_attachments);
|
|
|
|
mHiddenAttachments.setVisibility(View.GONE);
|
|
|
|
mShowHiddenAttachments = (Button) findViewById(R.id.show_hidden_attachments);
|
|
|
|
mShowHiddenAttachments.setVisibility(View.GONE);
|
2011-02-11 10:09:15 -05:00
|
|
|
mCryptoView = (MessageCryptoView) findViewById(R.id.layout_decrypt);
|
|
|
|
mCryptoView.setActivity(activity);
|
|
|
|
mCryptoView.setupChildViews();
|
2012-02-20 22:56:05 -05:00
|
|
|
mShowPicturesAction = findViewById(R.id.show_pictures);
|
|
|
|
mShowMessageAction = findViewById(R.id.show_message);
|
|
|
|
|
|
|
|
mShowAttachmentsAction = findViewById(R.id.show_attachments);
|
|
|
|
|
2011-02-11 10:09:15 -05:00
|
|
|
mShowPictures = false;
|
|
|
|
|
2011-02-14 12:27:40 -05:00
|
|
|
mContacts = Contacts.getInstance(activity);
|
|
|
|
|
2011-02-11 12:13:18 -05:00
|
|
|
mInflater = activity.getLayoutInflater();
|
2011-02-11 10:09:15 -05:00
|
|
|
mDownloadRemainder = (Button) findViewById(R.id.download_remainder);
|
2012-02-20 22:56:05 -05:00
|
|
|
mDownloadRemainder.setVisibility(View.GONE);
|
|
|
|
mAttachmentsContainer.setVisibility(View.GONE);
|
2011-02-14 11:54:01 -05:00
|
|
|
if (isScreenReaderActive(activity)) {
|
2011-02-11 10:09:15 -05:00
|
|
|
mAccessibleMessageContentView.setVisibility(View.VISIBLE);
|
|
|
|
mMessageContentView.setVisibility(View.GONE);
|
2011-02-14 11:54:01 -05:00
|
|
|
mScreenReaderEnabled = true;
|
2011-02-11 10:09:15 -05:00
|
|
|
} else {
|
|
|
|
mAccessibleMessageContentView.setVisibility(View.GONE);
|
|
|
|
mMessageContentView.setVisibility(View.VISIBLE);
|
2011-02-14 11:54:01 -05:00
|
|
|
mScreenReaderEnabled = false;
|
2012-02-20 22:56:05 -05:00
|
|
|
|
|
|
|
mHeaderPlaceHolder.removeView(mHeaderContainer);
|
|
|
|
// the HTC version of WebView tries to force the background of the
|
|
|
|
// titlebar, which is really unfair.
|
|
|
|
mHeaderContainer.setBackgroundColor(((K9Activity)activity).getThemeBackgroundColor());
|
|
|
|
|
|
|
|
mTitleBarHeaderContainer = new LinearLayout(activity);
|
|
|
|
mTitleBarHeaderContainer.addView(mHeaderContainer);
|
|
|
|
mMessageContentView.wrapSetTitleBar(mTitleBarHeaderContainer);
|
2011-02-11 10:09:15 -05:00
|
|
|
}
|
|
|
|
|
2012-02-21 10:21:47 -05:00
|
|
|
mShowHiddenAttachments.setOnClickListener(this);
|
|
|
|
mShowMessageAction.setOnClickListener(this);
|
|
|
|
mShowAttachmentsAction.setOnClickListener(this);
|
2012-02-22 16:44:31 -05:00
|
|
|
mShowPicturesAction.setOnClickListener(this);
|
2012-04-01 16:46:36 -04:00
|
|
|
|
|
|
|
mClipboardManager = ClipboardManager.getInstance(activity);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
|
|
|
|
super.onCreateContextMenu(menu);
|
|
|
|
|
|
|
|
WebView webview = (WebView) v;
|
|
|
|
WebView.HitTestResult result = webview.getHitTestResult();
|
|
|
|
int type = result.getType();
|
|
|
|
Context context = getContext();
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
case HitTestResult.SRC_ANCHOR_TYPE: {
|
|
|
|
final String url = result.getExtra();
|
|
|
|
OnMenuItemClickListener listener = new OnMenuItemClickListener() {
|
|
|
|
@Override
|
|
|
|
public boolean onMenuItemClick(MenuItem item) {
|
|
|
|
switch (item.getItemId()) {
|
|
|
|
case MENU_ITEM_LINK_VIEW: {
|
|
|
|
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
|
|
|
|
getContext().startActivity(intent);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case MENU_ITEM_LINK_SHARE: {
|
|
|
|
Intent intent = new Intent(Intent.ACTION_SEND);
|
|
|
|
intent.setType("text/plain");
|
|
|
|
intent.putExtra(Intent.EXTRA_TEXT, url);
|
|
|
|
getContext().startActivity(intent);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case MENU_ITEM_LINK_COPY: {
|
|
|
|
String label = getContext().getString(
|
|
|
|
R.string.webview_contextmenu_link_clipboard_label);
|
|
|
|
mClipboardManager.setText(label, url);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
menu.setHeaderTitle(url);
|
|
|
|
|
|
|
|
menu.add(Menu.NONE, MENU_ITEM_LINK_VIEW, 0,
|
|
|
|
context.getString(R.string.webview_contextmenu_link_view_action))
|
|
|
|
.setOnMenuItemClickListener(listener);
|
|
|
|
|
|
|
|
menu.add(Menu.NONE, MENU_ITEM_LINK_SHARE, 1,
|
|
|
|
context.getString(R.string.webview_contextmenu_link_share_action))
|
|
|
|
.setOnMenuItemClickListener(listener);
|
|
|
|
|
|
|
|
menu.add(Menu.NONE, MENU_ITEM_LINK_COPY, 2,
|
|
|
|
context.getString(R.string.webview_contextmenu_link_copy_action))
|
|
|
|
.setOnMenuItemClickListener(listener);
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case HitTestResult.IMAGE_TYPE:
|
|
|
|
case HitTestResult.SRC_IMAGE_ANCHOR_TYPE: {
|
|
|
|
final String url = result.getExtra();
|
|
|
|
final boolean externalImage = url.startsWith("http");
|
|
|
|
OnMenuItemClickListener listener = new OnMenuItemClickListener() {
|
|
|
|
@Override
|
|
|
|
public boolean onMenuItemClick(MenuItem item) {
|
|
|
|
switch (item.getItemId()) {
|
|
|
|
case MENU_ITEM_IMAGE_VIEW: {
|
|
|
|
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
|
|
|
|
if (!externalImage) {
|
|
|
|
// Grant read permission if this points to our
|
|
|
|
// AttachmentProvider
|
|
|
|
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
|
|
|
}
|
|
|
|
getContext().startActivity(intent);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case MENU_ITEM_IMAGE_SAVE: {
|
|
|
|
new DownloadImageTask().execute(url);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case MENU_ITEM_IMAGE_COPY: {
|
|
|
|
String label = getContext().getString(
|
|
|
|
R.string.webview_contextmenu_image_clipboard_label);
|
|
|
|
mClipboardManager.setText(label, url);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
menu.setHeaderTitle((externalImage) ?
|
|
|
|
url : context.getString(R.string.webview_contextmenu_image_title));
|
|
|
|
|
|
|
|
menu.add(Menu.NONE, MENU_ITEM_IMAGE_VIEW, 0,
|
|
|
|
context.getString(R.string.webview_contextmenu_image_view_action))
|
|
|
|
.setOnMenuItemClickListener(listener);
|
|
|
|
|
|
|
|
menu.add(Menu.NONE, MENU_ITEM_IMAGE_SAVE, 1,
|
|
|
|
(externalImage) ?
|
|
|
|
context.getString(R.string.webview_contextmenu_image_download_action) :
|
|
|
|
context.getString(R.string.webview_contextmenu_image_save_action))
|
|
|
|
.setOnMenuItemClickListener(listener);
|
|
|
|
|
|
|
|
if (externalImage) {
|
|
|
|
menu.add(Menu.NONE, MENU_ITEM_IMAGE_COPY, 2,
|
|
|
|
context.getString(R.string.webview_contextmenu_image_copy_action))
|
|
|
|
.setOnMenuItemClickListener(listener);
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case HitTestResult.PHONE_TYPE: {
|
|
|
|
final String phoneNumber = result.getExtra();
|
|
|
|
OnMenuItemClickListener listener = new OnMenuItemClickListener() {
|
|
|
|
@Override
|
|
|
|
public boolean onMenuItemClick(MenuItem item) {
|
|
|
|
switch (item.getItemId()) {
|
|
|
|
case MENU_ITEM_PHONE_CALL: {
|
|
|
|
Uri uri = Uri.parse(WebView.SCHEME_TEL + phoneNumber);
|
|
|
|
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
|
|
|
|
getContext().startActivity(intent);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case MENU_ITEM_PHONE_SAVE: {
|
|
|
|
Contacts contacts = Contacts.getInstance(getContext());
|
|
|
|
contacts.addPhoneContact(phoneNumber);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case MENU_ITEM_PHONE_COPY: {
|
|
|
|
String label = getContext().getString(
|
|
|
|
R.string.webview_contextmenu_phone_clipboard_label);
|
|
|
|
mClipboardManager.setText(label, phoneNumber);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
menu.setHeaderTitle(phoneNumber);
|
|
|
|
|
|
|
|
menu.add(Menu.NONE, MENU_ITEM_PHONE_CALL, 0,
|
|
|
|
context.getString(R.string.webview_contextmenu_phone_call_action))
|
|
|
|
.setOnMenuItemClickListener(listener);
|
|
|
|
|
|
|
|
menu.add(Menu.NONE, MENU_ITEM_PHONE_SAVE, 1,
|
|
|
|
context.getString(R.string.webview_contextmenu_phone_save_action))
|
|
|
|
.setOnMenuItemClickListener(listener);
|
|
|
|
|
|
|
|
menu.add(Menu.NONE, MENU_ITEM_PHONE_COPY, 2,
|
|
|
|
context.getString(R.string.webview_contextmenu_phone_copy_action))
|
|
|
|
.setOnMenuItemClickListener(listener);
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case WebView.HitTestResult.EMAIL_TYPE: {
|
|
|
|
final String email = result.getExtra();
|
|
|
|
OnMenuItemClickListener listener = new OnMenuItemClickListener() {
|
|
|
|
@Override
|
|
|
|
public boolean onMenuItemClick(MenuItem item) {
|
|
|
|
switch (item.getItemId()) {
|
|
|
|
case MENU_ITEM_EMAIL_SEND: {
|
|
|
|
Uri uri = Uri.parse(WebView.SCHEME_MAILTO + email);
|
|
|
|
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
|
|
|
|
getContext().startActivity(intent);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case MENU_ITEM_EMAIL_SAVE: {
|
|
|
|
Contacts contacts = Contacts.getInstance(getContext());
|
|
|
|
contacts.createContact(new Address(email));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case MENU_ITEM_EMAIL_COPY: {
|
|
|
|
String label = getContext().getString(
|
|
|
|
R.string.webview_contextmenu_email_clipboard_label);
|
|
|
|
mClipboardManager.setText(label, email);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
menu.setHeaderTitle(email);
|
|
|
|
|
|
|
|
menu.add(Menu.NONE, MENU_ITEM_EMAIL_SEND, 0,
|
|
|
|
context.getString(R.string.webview_contextmenu_email_send_action))
|
|
|
|
.setOnMenuItemClickListener(listener);
|
|
|
|
|
|
|
|
menu.add(Menu.NONE, MENU_ITEM_EMAIL_SAVE, 1,
|
|
|
|
context.getString(R.string.webview_contextmenu_email_save_action))
|
|
|
|
.setOnMenuItemClickListener(listener);
|
|
|
|
|
|
|
|
menu.add(Menu.NONE, MENU_ITEM_EMAIL_COPY, 2,
|
|
|
|
context.getString(R.string.webview_contextmenu_email_copy_action))
|
|
|
|
.setOnMenuItemClickListener(listener);
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2012-02-21 10:21:47 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onClick(View view) {
|
|
|
|
switch (view.getId()) {
|
|
|
|
case R.id.show_hidden_attachments: {
|
|
|
|
onShowHiddenAttachments();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case R.id.show_message: {
|
|
|
|
onShowMessage();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case R.id.show_attachments: {
|
|
|
|
onShowAttachments();
|
|
|
|
break;
|
|
|
|
}
|
2012-02-22 16:44:31 -05:00
|
|
|
case R.id.show_pictures: {
|
|
|
|
setLoadPictures(true);
|
|
|
|
break;
|
|
|
|
}
|
2012-02-21 10:21:47 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void onShowHiddenAttachments() {
|
|
|
|
mShowHiddenAttachments.setVisibility(View.GONE);
|
|
|
|
mHiddenAttachments.setVisibility(View.VISIBLE);
|
|
|
|
}
|
|
|
|
|
2012-02-22 16:56:05 -05:00
|
|
|
public void onShowMessage() {
|
2012-02-21 10:21:47 -05:00
|
|
|
showShowMessageAction(false);
|
|
|
|
showAttachments(false);
|
2012-02-22 16:56:05 -05:00
|
|
|
showShowAttachmentsAction(mHasAttachments);
|
2012-02-21 10:21:47 -05:00
|
|
|
showMessageWebView(true);
|
|
|
|
}
|
|
|
|
|
2012-02-22 16:56:05 -05:00
|
|
|
public void onShowAttachments() {
|
2012-02-21 10:21:47 -05:00
|
|
|
showMessageWebView(false);
|
|
|
|
showShowAttachmentsAction(false);
|
|
|
|
showShowMessageAction(true);
|
|
|
|
showAttachments(true);
|
2011-02-11 10:09:15 -05:00
|
|
|
}
|
|
|
|
|
2011-02-10 19:29:46 -05:00
|
|
|
public SingleMessageView(Context context, AttributeSet attrs) {
|
|
|
|
super(context, attrs);
|
|
|
|
}
|
2011-02-11 10:09:15 -05:00
|
|
|
|
2011-02-14 11:54:01 -05:00
|
|
|
|
2011-02-14 12:27:40 -05:00
|
|
|
private boolean isScreenReaderActive(Activity activity) {
|
2011-02-14 11:54:01 -05:00
|
|
|
final String SCREENREADER_INTENT_ACTION = "android.accessibilityservice.AccessibilityService";
|
|
|
|
final String SCREENREADER_INTENT_CATEGORY = "android.accessibilityservice.category.FEEDBACK_SPOKEN";
|
|
|
|
// Restrict the set of intents to only accessibility services that have
|
|
|
|
// the category FEEDBACK_SPOKEN (aka, screen readers).
|
|
|
|
Intent screenReaderIntent = new Intent(SCREENREADER_INTENT_ACTION);
|
|
|
|
screenReaderIntent.addCategory(SCREENREADER_INTENT_CATEGORY);
|
|
|
|
List<ResolveInfo> screenReaders = activity.getPackageManager().queryIntentServices(
|
2011-02-14 12:27:40 -05:00
|
|
|
screenReaderIntent, 0);
|
2011-02-14 11:54:01 -05:00
|
|
|
ContentResolver cr = activity.getContentResolver();
|
|
|
|
Cursor cursor = null;
|
|
|
|
int status = 0;
|
|
|
|
for (ResolveInfo screenReader : screenReaders) {
|
|
|
|
// All screen readers are expected to implement a content provider
|
|
|
|
// that responds to
|
|
|
|
// content://<nameofpackage>.providers.StatusProvider
|
|
|
|
cursor = cr.query(Uri.parse("content://" + screenReader.serviceInfo.packageName
|
2011-02-14 12:27:40 -05:00
|
|
|
+ ".providers.StatusProvider"), null, null, null, null);
|
2012-02-16 08:52:56 -05:00
|
|
|
try {
|
|
|
|
if (cursor != null && cursor.moveToFirst()) {
|
|
|
|
// These content providers use a special cursor that only has
|
|
|
|
// one element,
|
|
|
|
// an integer that is 1 if the screen reader is running.
|
|
|
|
status = cursor.getInt(0);
|
|
|
|
if (status == 1) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} finally {
|
|
|
|
if (cursor != null) {
|
|
|
|
cursor.close();
|
2011-02-14 11:54:01 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-02-11 10:09:15 -05:00
|
|
|
public boolean showPictures() {
|
|
|
|
return mShowPictures;
|
|
|
|
}
|
2011-11-02 19:39:23 -04:00
|
|
|
|
2011-02-11 10:09:15 -05:00
|
|
|
public void setShowPictures(Boolean show) {
|
|
|
|
mShowPictures = show;
|
|
|
|
}
|
|
|
|
|
2011-02-14 11:40:52 -05:00
|
|
|
/**
|
|
|
|
* Enable/disable image loading of the WebView. But always hide the
|
|
|
|
* "Show pictures" button!
|
|
|
|
*
|
|
|
|
* @param enable true, if (network) images should be loaded.
|
|
|
|
* false, otherwise.
|
|
|
|
*/
|
2011-02-14 12:27:40 -05:00
|
|
|
public void setLoadPictures(boolean enable) {
|
2011-02-14 11:40:52 -05:00
|
|
|
mMessageContentView.blockNetworkData(!enable);
|
|
|
|
setShowPictures(enable);
|
2012-02-20 22:56:05 -05:00
|
|
|
showShowPicturesAction(false);
|
2011-02-11 10:09:15 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
public Button downloadRemainderButton() {
|
|
|
|
return mDownloadRemainder;
|
|
|
|
}
|
|
|
|
|
2012-02-20 22:56:05 -05:00
|
|
|
public void showShowPicturesAction(boolean show) {
|
|
|
|
mShowPicturesAction.setVisibility(show ? View.VISIBLE : View.GONE);
|
|
|
|
}
|
|
|
|
public void showShowMessageAction(boolean show) {
|
|
|
|
mShowMessageAction.setVisibility(show ? View.VISIBLE : View.GONE);
|
|
|
|
}
|
|
|
|
public void showShowAttachmentsAction(boolean show) {
|
|
|
|
mShowAttachmentsAction.setVisibility(show ? View.VISIBLE : View.GONE);
|
2011-02-11 10:09:15 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
public void setHeaders(final Message message, Account account) {
|
|
|
|
try {
|
|
|
|
mHeaderContainer.populate(message, account);
|
2012-02-20 22:56:05 -05:00
|
|
|
mHeaderContainer.setVisibility(View.VISIBLE);
|
2011-02-11 12:10:45 -05:00
|
|
|
|
|
|
|
|
2011-02-11 10:09:15 -05:00
|
|
|
} catch (Exception me) {
|
|
|
|
Log.e(K9.LOG_TAG, "setHeaders - error", me);
|
|
|
|
}
|
2011-02-11 12:11:21 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
public void setShowDownloadButton(Message message) {
|
2011-02-11 10:09:15 -05:00
|
|
|
if (message.isSet(Flag.X_DOWNLOADED_FULL)) {
|
|
|
|
mDownloadRemainder.setVisibility(View.GONE);
|
|
|
|
} else {
|
|
|
|
mDownloadRemainder.setEnabled(true);
|
|
|
|
mDownloadRemainder.setVisibility(View.VISIBLE);
|
|
|
|
}
|
|
|
|
}
|
2011-02-11 12:10:45 -05:00
|
|
|
|
|
|
|
public void setOnFlagListener(OnClickListener listener) {
|
|
|
|
mHeaderContainer.setOnFlagListener(listener);
|
|
|
|
}
|
|
|
|
|
2011-02-11 10:09:15 -05:00
|
|
|
public void showAllHeaders() {
|
|
|
|
mHeaderContainer.onShowAdditionalHeaders();
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean additionalHeadersVisible() {
|
|
|
|
return mHeaderContainer.additionalHeadersVisible();
|
|
|
|
}
|
|
|
|
|
2012-02-23 21:43:42 -05:00
|
|
|
public void setMessage(Account account, LocalMessage message, PgpData pgpData,
|
|
|
|
MessagingController controller, MessagingListener listener) throws MessagingException {
|
2012-02-20 22:56:05 -05:00
|
|
|
resetView();
|
2011-02-14 12:27:40 -05:00
|
|
|
|
|
|
|
String type;
|
|
|
|
String text = pgpData.getDecryptedData();
|
|
|
|
if (text != null) {
|
|
|
|
type = "text/plain";
|
|
|
|
} else {
|
|
|
|
// getTextForDisplay() always returns HTML-ified content.
|
2012-02-23 21:43:42 -05:00
|
|
|
text = message.getTextForDisplay();
|
2011-02-14 12:27:40 -05:00
|
|
|
type = "text/html";
|
|
|
|
}
|
|
|
|
if (text != null) {
|
|
|
|
final String emailText = text;
|
|
|
|
final String contentType = type;
|
2012-02-23 21:43:42 -05:00
|
|
|
loadBodyFromText(emailText, contentType);
|
2012-02-20 22:56:05 -05:00
|
|
|
updateCryptoLayout(account.getCryptoProvider(), pgpData, message);
|
2012-02-23 21:43:42 -05:00
|
|
|
} else {
|
|
|
|
loadBodyFromUrl("file:///android_asset/empty.html");
|
|
|
|
}
|
|
|
|
|
|
|
|
mHasAttachments = message.hasAttachments();
|
|
|
|
|
|
|
|
if (mHasAttachments) {
|
|
|
|
renderAttachments(message, 0, message, account, controller, listener);
|
|
|
|
}
|
|
|
|
|
|
|
|
mHiddenAttachments.setVisibility(View.GONE);
|
|
|
|
|
|
|
|
boolean lookForImages = true;
|
|
|
|
if (mSavedState != null) {
|
|
|
|
if (mSavedState.showPictures) {
|
|
|
|
setLoadPictures(true);
|
|
|
|
lookForImages = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mSavedState.attachmentViewVisible) {
|
|
|
|
onShowAttachments();
|
|
|
|
} else {
|
|
|
|
onShowMessage();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mSavedState.hiddenAttachmentsVisible) {
|
|
|
|
onShowHiddenAttachments();
|
|
|
|
}
|
|
|
|
|
|
|
|
mSavedState = null;
|
|
|
|
} else {
|
|
|
|
onShowMessage();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (text != null && lookForImages) {
|
2011-02-14 12:27:40 -05:00
|
|
|
// If the message contains external pictures and the "Show pictures"
|
|
|
|
// button wasn't already pressed, see if the user's preferences has us
|
|
|
|
// showing them anyway.
|
|
|
|
if (Utility.hasExternalImages(text) && !showPictures()) {
|
2011-10-01 14:30:22 -04:00
|
|
|
Address[] from = message.getFrom();
|
2011-02-14 12:27:40 -05:00
|
|
|
if ((account.getShowPictures() == Account.ShowPictures.ALWAYS) ||
|
|
|
|
((account.getShowPictures() == Account.ShowPictures.ONLY_FROM_CONTACTS) &&
|
2011-10-01 14:30:22 -04:00
|
|
|
// Make sure we have at least one from address
|
|
|
|
(from != null && from.length > 0) &&
|
|
|
|
mContacts.isInContacts(from[0].getAddress()))) {
|
2011-02-14 12:27:40 -05:00
|
|
|
setLoadPictures(true);
|
|
|
|
} else {
|
2012-02-20 22:56:05 -05:00
|
|
|
showShowPicturesAction(true);
|
2011-02-14 12:27:40 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-02-11 10:09:15 -05:00
|
|
|
|
2011-02-11 12:09:47 -05:00
|
|
|
public void loadBodyFromUrl(String url) {
|
2011-02-11 10:09:15 -05:00
|
|
|
mMessageContentView.loadUrl(url);
|
2011-02-11 12:12:09 -05:00
|
|
|
mCryptoView.hide();
|
2011-02-11 10:09:15 -05:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2012-02-23 21:43:42 -05:00
|
|
|
private void loadBodyFromText(String emailText, String contentType) {
|
2011-02-11 10:09:15 -05:00
|
|
|
if (mScreenReaderEnabled) {
|
|
|
|
mAccessibleMessageContentView.loadDataWithBaseURL("http://", emailText, contentType, "utf-8", null);
|
|
|
|
} else {
|
|
|
|
mMessageContentView.loadDataWithBaseURL("http://", emailText, contentType, "utf-8", null);
|
|
|
|
mMessageContentView.scrollTo(0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
public void updateCryptoLayout(CryptoProvider cp, PgpData pgpData, Message message) {
|
|
|
|
mCryptoView.updateLayout(cp, pgpData, message);
|
|
|
|
}
|
|
|
|
|
2012-02-20 22:56:05 -05:00
|
|
|
public void showAttachments(boolean show) {
|
|
|
|
mAttachmentsContainer.setVisibility(show ? View.VISIBLE : View.GONE);
|
2012-02-23 21:43:42 -05:00
|
|
|
boolean showHidden = (show && mHiddenAttachments.getVisibility() == View.GONE &&
|
|
|
|
mHiddenAttachments.getChildCount() > 0);
|
2012-02-20 22:56:05 -05:00
|
|
|
mShowHiddenAttachments.setVisibility(showHidden ? View.VISIBLE : View.GONE);
|
|
|
|
|
|
|
|
if (show) {
|
|
|
|
moveHeaderToLayout();
|
|
|
|
} else {
|
|
|
|
moveHeaderToWebViewTitleBar();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void showMessageWebView(boolean show) {
|
|
|
|
mMessageContentView.setVisibility(show ? View.VISIBLE : View.GONE);
|
|
|
|
}
|
|
|
|
|
2011-02-11 10:09:15 -05:00
|
|
|
public void setAttachmentsEnabled(boolean enabled) {
|
|
|
|
for (int i = 0, count = mAttachments.getChildCount(); i < count; i++) {
|
|
|
|
AttachmentView attachment = (AttachmentView) mAttachments.getChildAt(i);
|
|
|
|
attachment.viewButton.setEnabled(enabled);
|
|
|
|
attachment.downloadButton.setEnabled(enabled);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void removeAllAttachments() {
|
|
|
|
for (int i = 0, count = mAttachments.getChildCount(); i < count; i++) {
|
|
|
|
mAttachments.removeView(mAttachments.getChildAt(i));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-11-02 11:34:06 -04:00
|
|
|
public void renderAttachments(Part part, int depth, Message message, Account account,
|
|
|
|
MessagingController controller, MessagingListener listener) throws MessagingException {
|
2011-02-11 10:09:15 -05:00
|
|
|
|
|
|
|
if (part.getBody() instanceof Multipart) {
|
|
|
|
Multipart mp = (Multipart) part.getBody();
|
|
|
|
for (int i = 0; i < mp.getCount(); i++) {
|
|
|
|
renderAttachments(mp.getBodyPart(i), depth + 1, message, account, controller, listener);
|
|
|
|
}
|
|
|
|
} else if (part instanceof LocalStore.LocalAttachmentBodyPart) {
|
2011-02-11 12:13:18 -05:00
|
|
|
AttachmentView view = (AttachmentView)mInflater.inflate(R.layout.message_view_attachment, null);
|
2011-04-24 00:00:10 -04:00
|
|
|
view.setCallback(attachmentCallback);
|
2012-02-20 22:56:05 -05:00
|
|
|
|
2012-02-27 15:00:44 -05:00
|
|
|
try {
|
|
|
|
if (view.populateFromPart(part, message, account, controller, listener)) {
|
|
|
|
addAttachment(view);
|
|
|
|
} else {
|
|
|
|
addHiddenAttachment(view);
|
|
|
|
}
|
|
|
|
} catch (Exception e) {
|
|
|
|
Log.e(K9.LOG_TAG, "Error adding attachment view", e);
|
2011-02-11 10:09:15 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void addAttachment(View attachmentView) {
|
|
|
|
mAttachments.addView(attachmentView);
|
2012-02-20 22:56:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
public void addHiddenAttachment(View attachmentView) {
|
|
|
|
mHiddenAttachments.addView(attachmentView);
|
2011-02-11 10:09:15 -05:00
|
|
|
}
|
2011-11-02 11:34:06 -04:00
|
|
|
|
2011-02-11 10:09:15 -05:00
|
|
|
public void zoom(KeyEvent event) {
|
|
|
|
if (mScreenReaderEnabled) {
|
|
|
|
mAccessibleMessageContentView.zoomIn();
|
|
|
|
} else {
|
|
|
|
if (event.isShiftPressed()) {
|
|
|
|
mMessageContentView.zoomIn();
|
|
|
|
} else {
|
|
|
|
mMessageContentView.zoomOut();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-11-02 11:34:06 -04:00
|
|
|
|
2011-02-11 10:09:15 -05:00
|
|
|
public void beginSelectingText() {
|
|
|
|
mMessageContentView.emulateShiftHeld();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void resetView() {
|
2012-02-23 21:43:42 -05:00
|
|
|
mDownloadRemainder.setVisibility(View.GONE);
|
|
|
|
setLoadPictures(false);
|
|
|
|
showShowAttachmentsAction(false);
|
|
|
|
showShowMessageAction(false);
|
|
|
|
showShowPicturesAction(false);
|
2011-02-11 10:09:15 -05:00
|
|
|
mAttachments.removeAllViews();
|
2012-02-20 22:56:05 -05:00
|
|
|
mHiddenAttachments.removeAllViews();
|
2012-02-23 21:43:42 -05:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Clear the WebView content
|
|
|
|
*
|
|
|
|
* For some reason WebView.clearView() doesn't clear the contents when the WebView changes
|
|
|
|
* its size because the button to download the complete message was previously shown and
|
|
|
|
* is now hidden.
|
|
|
|
*/
|
|
|
|
loadBodyFromText("", "text/plain");
|
2012-02-20 22:56:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
public void resetHeaderView() {
|
|
|
|
mHeaderContainer.setVisibility(View.GONE);
|
2011-02-11 10:09:15 -05:00
|
|
|
}
|
2011-04-24 00:00:10 -04:00
|
|
|
|
|
|
|
public AttachmentView.AttachmentFileDownloadCallback getAttachmentCallback() {
|
|
|
|
return attachmentCallback;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setAttachmentCallback(
|
|
|
|
AttachmentView.AttachmentFileDownloadCallback attachmentCallback) {
|
|
|
|
this.attachmentCallback = attachmentCallback;
|
|
|
|
}
|
2011-11-02 19:39:23 -04:00
|
|
|
|
2012-02-20 22:56:05 -05:00
|
|
|
private void moveHeaderToLayout() {
|
|
|
|
if (mTitleBarHeaderContainer != null && mTitleBarHeaderContainer.getChildCount() != 0) {
|
|
|
|
mTitleBarHeaderContainer.removeView(mHeaderContainer);
|
2012-02-24 18:43:09 -05:00
|
|
|
mInsideAttachmentsContainer.addView(mHeaderContainer, 0);
|
2012-02-20 22:56:05 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void moveHeaderToWebViewTitleBar() {
|
|
|
|
if (mTitleBarHeaderContainer != null && mTitleBarHeaderContainer.getChildCount() == 0) {
|
2012-02-24 18:43:09 -05:00
|
|
|
mInsideAttachmentsContainer.removeView(mHeaderContainer);
|
2012-02-20 22:56:05 -05:00
|
|
|
mTitleBarHeaderContainer.addView(mHeaderContainer);
|
2011-11-02 19:39:23 -04:00
|
|
|
}
|
|
|
|
}
|
2012-02-23 21:43:42 -05:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public Parcelable onSaveInstanceState() {
|
|
|
|
Parcelable superState = super.onSaveInstanceState();
|
|
|
|
|
|
|
|
SavedState savedState = new SavedState(superState);
|
|
|
|
|
|
|
|
savedState.attachmentViewVisible = (mAttachmentsContainer != null &&
|
|
|
|
mAttachmentsContainer.getVisibility() == View.VISIBLE);
|
|
|
|
savedState.hiddenAttachmentsVisible = (mHiddenAttachments != null &&
|
|
|
|
mHiddenAttachments.getVisibility() == View.VISIBLE);
|
|
|
|
savedState.showPictures = mShowPictures;
|
|
|
|
|
|
|
|
return savedState;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onRestoreInstanceState(Parcelable state) {
|
|
|
|
if(!(state instanceof SavedState)) {
|
|
|
|
super.onRestoreInstanceState(state);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
SavedState savedState = (SavedState)state;
|
|
|
|
super.onRestoreInstanceState(savedState.getSuperState());
|
|
|
|
|
|
|
|
mSavedState = savedState;
|
|
|
|
}
|
|
|
|
|
2012-03-01 23:16:58 -05:00
|
|
|
public void onLayoutChanged() {
|
|
|
|
if (mMessageContentView != null) {
|
|
|
|
mMessageContentView.invalidate();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-02-23 21:43:42 -05:00
|
|
|
static class SavedState extends BaseSavedState {
|
|
|
|
boolean attachmentViewVisible;
|
|
|
|
boolean hiddenAttachmentsVisible;
|
|
|
|
boolean showPictures;
|
|
|
|
|
|
|
|
@SuppressWarnings("hiding")
|
|
|
|
public static final Parcelable.Creator<SavedState> CREATOR =
|
|
|
|
new Parcelable.Creator<SavedState>() {
|
|
|
|
@Override
|
|
|
|
public SavedState createFromParcel(Parcel in) {
|
|
|
|
return new SavedState(in);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public SavedState[] newArray(int size) {
|
|
|
|
return new SavedState[size];
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
SavedState(Parcelable superState) {
|
|
|
|
super(superState);
|
|
|
|
}
|
|
|
|
|
|
|
|
private SavedState(Parcel in) {
|
|
|
|
super(in);
|
|
|
|
this.attachmentViewVisible = (in.readInt() != 0);
|
|
|
|
this.hiddenAttachmentsVisible = (in.readInt() != 0);
|
|
|
|
this.showPictures = (in.readInt() != 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void writeToParcel(Parcel out, int flags) {
|
|
|
|
super.writeToParcel(out, flags);
|
|
|
|
out.writeInt((this.attachmentViewVisible) ? 1 : 0);
|
|
|
|
out.writeInt((this.hiddenAttachmentsVisible) ? 1 : 0);
|
|
|
|
out.writeInt((this.showPictures) ? 1 : 0);
|
|
|
|
}
|
|
|
|
}
|
2012-04-01 16:46:36 -04:00
|
|
|
|
|
|
|
class DownloadImageTask extends AsyncTask<String, Void, String> {
|
|
|
|
@Override
|
|
|
|
protected String doInBackground(String... params) {
|
|
|
|
String urlString = params[0];
|
|
|
|
try {
|
|
|
|
boolean externalImage = urlString.startsWith("http");
|
|
|
|
|
|
|
|
String filename = null;
|
|
|
|
String mimeType = null;
|
|
|
|
InputStream in = null;
|
|
|
|
|
|
|
|
try {
|
|
|
|
if (externalImage) {
|
|
|
|
URL url = new URL(urlString);
|
|
|
|
URLConnection conn = url.openConnection();
|
|
|
|
in = conn.getInputStream();
|
|
|
|
|
|
|
|
String path = url.getPath();
|
|
|
|
|
|
|
|
// Try to get the filename from the URL
|
|
|
|
int start = path.lastIndexOf("/");
|
|
|
|
if (start != -1 && start + 1 < path.length()) {
|
|
|
|
filename = URLDecoder.decode(path.substring(start + 1), "UTF-8");
|
|
|
|
} else {
|
|
|
|
// Use a dummy filename if necessary
|
|
|
|
filename = "saved_image";
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the MIME type if we couldn't find a file extension
|
|
|
|
if (filename.indexOf('.') == -1) {
|
|
|
|
mimeType = conn.getContentType();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ContentResolver contentResolver = getContext().getContentResolver();
|
|
|
|
Uri uri = Uri.parse(urlString);
|
|
|
|
|
|
|
|
// Get the filename from AttachmentProvider
|
|
|
|
Cursor cursor = contentResolver.query(uri, ATTACHMENT_PROJECTION, null, null, null);
|
|
|
|
if (cursor != null) {
|
|
|
|
try {
|
|
|
|
if (cursor.moveToNext()) {
|
|
|
|
filename = cursor.getString(DISPLAY_NAME_INDEX);
|
|
|
|
}
|
|
|
|
} finally {
|
|
|
|
cursor.close();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Use a dummy filename if necessary
|
|
|
|
if (filename == null) {
|
|
|
|
filename = "saved_image";
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the MIME type if we couldn't find a file extension
|
|
|
|
if (filename.indexOf('.') == -1) {
|
|
|
|
mimeType = contentResolver.getType(uri);
|
|
|
|
}
|
|
|
|
|
|
|
|
in = contentResolver.openInputStream(uri);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Do we still need an extension?
|
|
|
|
if (filename.indexOf('.') == -1) {
|
|
|
|
// Use JPEG as fallback
|
|
|
|
String extension = "jpeg";
|
|
|
|
if (mimeType != null) {
|
|
|
|
// Try to find an extension for the given MIME type
|
|
|
|
String ext = MimeUtility.getExtensionByMimeType(mimeType);
|
|
|
|
if (ext != null) {
|
|
|
|
extension = ext;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
filename += "." + extension;
|
|
|
|
}
|
|
|
|
|
|
|
|
String sanitized = Utility.sanitizeFilename(filename);
|
|
|
|
|
|
|
|
File directory = new File(K9.getAttachmentDefaultPath());
|
|
|
|
File file = Utility.createUniqueFile(directory, sanitized);
|
|
|
|
FileOutputStream out = new FileOutputStream(file);
|
|
|
|
try {
|
|
|
|
IOUtils.copy(in, out);
|
|
|
|
out.flush();
|
|
|
|
} finally {
|
|
|
|
out.close();
|
|
|
|
}
|
|
|
|
|
|
|
|
return file.getName();
|
|
|
|
|
|
|
|
} finally {
|
|
|
|
if (in != null) {
|
|
|
|
in.close();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} catch (Exception e) {
|
|
|
|
e.printStackTrace();
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected void onPostExecute(String filename) {
|
|
|
|
String text;
|
|
|
|
if (filename == null) {
|
|
|
|
text = getContext().getString(R.string.image_saving_failed);
|
|
|
|
} else {
|
|
|
|
text = getContext().getString(R.string.image_saved_as, filename);
|
|
|
|
}
|
|
|
|
|
|
|
|
Toast.makeText(getContext(), text, Toast.LENGTH_LONG).show();
|
|
|
|
}
|
|
|
|
}
|
2011-02-10 19:29:46 -05:00
|
|
|
}
|