diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 493fd573a67510cc6b2d50ddf4d10878025a0eb9..31ae95df3d77e965290c99a72a951d9d18240548 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -74,6 +74,7 @@
+
diff --git a/res/drawable-hdpi/ic_attach_grey600_24dp.png b/res/drawable-hdpi/ic_attach_grey600_24dp.png
deleted file mode 100644
index 13c7f0c28dd4ccd70cecb059b1fc70ed11a86fea..0000000000000000000000000000000000000000
Binary files a/res/drawable-hdpi/ic_attach_grey600_24dp.png and /dev/null differ
diff --git a/res/drawable-hdpi/ic_file_attachment_dark.png b/res/drawable-hdpi/ic_file_attachment_dark.png
new file mode 100644
index 0000000000000000000000000000000000000000..d3139364996a65f8004a165148e882e42dda2766
Binary files /dev/null and b/res/drawable-hdpi/ic_file_attachment_dark.png differ
diff --git a/res/drawable-hdpi/ic_file_attachment_light.png b/res/drawable-hdpi/ic_file_attachment_light.png
new file mode 100644
index 0000000000000000000000000000000000000000..5261267fb1102225ce46913346a893e80faecbd7
Binary files /dev/null and b/res/drawable-hdpi/ic_file_attachment_light.png differ
diff --git a/res/drawable-hdpi/ic_file_dark.png b/res/drawable-hdpi/ic_file_dark.png
new file mode 100644
index 0000000000000000000000000000000000000000..d1000674624ddd8f41737856a210bd5d4b4d5a47
Binary files /dev/null and b/res/drawable-hdpi/ic_file_dark.png differ
diff --git a/res/drawable-hdpi/ic_file_light.png b/res/drawable-hdpi/ic_file_light.png
new file mode 100644
index 0000000000000000000000000000000000000000..a00baf46eb188af480c7dd0242c6caa76bf7e846
Binary files /dev/null and b/res/drawable-hdpi/ic_file_light.png differ
diff --git a/res/drawable-mdpi/ic_attach_grey600_24dp.png b/res/drawable-mdpi/ic_attach_grey600_24dp.png
deleted file mode 100644
index 0ea546b1f94beb88a43af1267c2ec87c84b11792..0000000000000000000000000000000000000000
Binary files a/res/drawable-mdpi/ic_attach_grey600_24dp.png and /dev/null differ
diff --git a/res/drawable-mdpi/ic_file_attachment_dark.png b/res/drawable-mdpi/ic_file_attachment_dark.png
new file mode 100644
index 0000000000000000000000000000000000000000..23d012adc4b98b6b17962a0093ce0dac8cf7c906
Binary files /dev/null and b/res/drawable-mdpi/ic_file_attachment_dark.png differ
diff --git a/res/drawable-mdpi/ic_file_attachment_light.png b/res/drawable-mdpi/ic_file_attachment_light.png
new file mode 100644
index 0000000000000000000000000000000000000000..cd12b0e1789765cf57af99da9f86401fda6b4ad5
Binary files /dev/null and b/res/drawable-mdpi/ic_file_attachment_light.png differ
diff --git a/res/drawable-mdpi/ic_file_dark.png b/res/drawable-mdpi/ic_file_dark.png
new file mode 100644
index 0000000000000000000000000000000000000000..657e7a960c21713fccd07de70683b8fedfac8785
Binary files /dev/null and b/res/drawable-mdpi/ic_file_dark.png differ
diff --git a/res/drawable-mdpi/ic_file_light.png b/res/drawable-mdpi/ic_file_light.png
new file mode 100644
index 0000000000000000000000000000000000000000..9eb60e9eba41b0228b819f1a66d3b12590e06e57
Binary files /dev/null and b/res/drawable-mdpi/ic_file_light.png differ
diff --git a/res/drawable-xhdpi/ic_attach_grey600_24dp.png b/res/drawable-xhdpi/ic_attach_grey600_24dp.png
deleted file mode 100644
index 28aef9e9b1c20bf3dbd0046e1fa59dea46b5bc55..0000000000000000000000000000000000000000
Binary files a/res/drawable-xhdpi/ic_attach_grey600_24dp.png and /dev/null differ
diff --git a/res/drawable-xhdpi/ic_file_attachment_dark.png b/res/drawable-xhdpi/ic_file_attachment_dark.png
new file mode 100644
index 0000000000000000000000000000000000000000..a9341832112d5a3809a1391050e53ad0da6a4a1c
Binary files /dev/null and b/res/drawable-xhdpi/ic_file_attachment_dark.png differ
diff --git a/res/drawable-xhdpi/ic_file_attachment_light.png b/res/drawable-xhdpi/ic_file_attachment_light.png
new file mode 100644
index 0000000000000000000000000000000000000000..6237f46349d68b34589112f9a32b0b9d44256903
Binary files /dev/null and b/res/drawable-xhdpi/ic_file_attachment_light.png differ
diff --git a/res/drawable-xhdpi/ic_file_dark.png b/res/drawable-xhdpi/ic_file_dark.png
new file mode 100644
index 0000000000000000000000000000000000000000..b1d32899b65bb03371b23f21709382f72970979c
Binary files /dev/null and b/res/drawable-xhdpi/ic_file_dark.png differ
diff --git a/res/drawable-xhdpi/ic_file_light.png b/res/drawable-xhdpi/ic_file_light.png
new file mode 100644
index 0000000000000000000000000000000000000000..15a87c4a7afaf74f639b3fd26afd6db121e5c11f
Binary files /dev/null and b/res/drawable-xhdpi/ic_file_light.png differ
diff --git a/res/drawable-xxhdpi/ic_attach_grey600_24dp.png b/res/drawable-xxhdpi/ic_attach_grey600_24dp.png
deleted file mode 100644
index 7b0785e116d1b744600ae5b74aad60d36c0d9035..0000000000000000000000000000000000000000
Binary files a/res/drawable-xxhdpi/ic_attach_grey600_24dp.png and /dev/null differ
diff --git a/res/drawable-xxhdpi/ic_file_attachment_dark.png b/res/drawable-xxhdpi/ic_file_attachment_dark.png
new file mode 100644
index 0000000000000000000000000000000000000000..1efba0a65f1c5bf90d0feb3b579652fd74abfeb0
Binary files /dev/null and b/res/drawable-xxhdpi/ic_file_attachment_dark.png differ
diff --git a/res/drawable-xxhdpi/ic_file_attachment_light.png b/res/drawable-xxhdpi/ic_file_attachment_light.png
new file mode 100644
index 0000000000000000000000000000000000000000..36b2d14f50e7abf55669df434824473f88615e2c
Binary files /dev/null and b/res/drawable-xxhdpi/ic_file_attachment_light.png differ
diff --git a/res/drawable-xxhdpi/ic_file_dark.png b/res/drawable-xxhdpi/ic_file_dark.png
new file mode 100644
index 0000000000000000000000000000000000000000..9a982fee52c011185d599192b920d00867dfd7a5
Binary files /dev/null and b/res/drawable-xxhdpi/ic_file_dark.png differ
diff --git a/res/drawable-xxhdpi/ic_file_light.png b/res/drawable-xxhdpi/ic_file_light.png
new file mode 100644
index 0000000000000000000000000000000000000000..9d4172b40fb3dabfa6a137fc31b7dd47e10f3f0d
Binary files /dev/null and b/res/drawable-xxhdpi/ic_file_light.png differ
diff --git a/res/drawable-xxxhdpi/ic_file_dark.png b/res/drawable-xxxhdpi/ic_file_dark.png
new file mode 100644
index 0000000000000000000000000000000000000000..5858d5a764c30973ae2ec9a2986c93e712f041fe
Binary files /dev/null and b/res/drawable-xxxhdpi/ic_file_dark.png differ
diff --git a/res/drawable-xxxhdpi/ic_file_light.png b/res/drawable-xxxhdpi/ic_file_light.png
new file mode 100644
index 0000000000000000000000000000000000000000..9622ae38118be94cbaa008be1d51b73eaeb61914
Binary files /dev/null and b/res/drawable-xxxhdpi/ic_file_light.png differ
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index 341d02395b90f269bd328c59bcd8f65d22d12c38..71337ecdf10a208e34d468ad4ce9955d5d2c262b 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -40,7 +40,7 @@
-
+
@@ -71,6 +71,7 @@
+
diff --git a/res/values/strings.xml b/res/values/strings.xml
index c0ae806213fbcac58a5af17b59deff3ba4098a48..219bc6bd008e20912a20a7e0ba0a0d6c7beadf67 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -49,6 +49,7 @@
(image)
(audio)
(video)
+ (file)
Can\'t find an app to select media.
@@ -58,6 +59,7 @@
Picture
Video
Audio
+ File
Contact info
@@ -118,6 +120,7 @@
MMS not supported
This message cannot be sent since your carrier doesn\'t support MMS.
Please choose a contact
+ Sorry, files cannot be attached to insecure conversations.
Attachment exceeds size limits.
diff --git a/res/values/themes.xml b/res/values/themes.xml
index 5747d433fd76bad672614f554565a45f59605b92..e2f6090a33701cc1889bd62099e097e8fbddf6dd 100644
--- a/res/values/themes.xml
+++ b/res/values/themes.xml
@@ -116,7 +116,7 @@
- @drawable/ic_movie_creation_light
- @drawable/ic_volume_up_light
- @drawable/ic_account_box_light
- - @drawable/ic_attach_grey600_24dp
+ - @drawable/ic_file_attachment_light
- @color/gray12
- #66555555
@@ -172,6 +172,7 @@
- @drawable/ic_audio_light
- @drawable/ic_video_light
+ - @drawable/ic_file_light
- #ff1d85d7
@@ -248,7 +249,7 @@
- @drawable/ic_movie_creation_dark
- @drawable/ic_volume_up_dark
- @drawable/ic_account_box_dark
- - @drawable/ic_attach_white_24dp
+ - @drawable/ic_file_attachment_dark
- @color/gray95
- @color/gray65
@@ -285,6 +286,7 @@
- @drawable/ic_audio_dark
- @drawable/ic_video_dark
+ - @drawable/ic_file_dark
- @color/smssecure_primary_dark
diff --git a/src/org/smssecure/smssecure/ConversationActivity.java b/src/org/smssecure/smssecure/ConversationActivity.java
index cc64dc0d240a878f2e481e6fed5a9b977f94837b..b7747cb898063fed5fb29408b8337b23633167ab 100644
--- a/src/org/smssecure/smssecure/ConversationActivity.java
+++ b/src/org/smssecure/smssecure/ConversationActivity.java
@@ -147,6 +147,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
public static final String THREAD_ID_EXTRA = "thread_id";
public static final String IS_ARCHIVED_EXTRA = "is_archived";
public static final String TEXT_EXTRA = "draft_text";
+ public static final String FILENAME_EXTRA = "filename";
public static final String DISTRIBUTION_TYPE_EXTRA = "distribution_type";
private static final int PICK_IMAGE = 1;
@@ -156,6 +157,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
private static final int GROUP_EDIT = 5;
private static final int TAKE_PHOTO = 6;
private static final int ADD_CONTACT = 7;
+ private static final int PICK_FILE = 8;
private MasterSecret masterSecret;
protected ComposeText composeText;
@@ -314,6 +316,9 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
recipients.addListener(this);
fragment.reloadList();
break;
+ case PICK_FILE:
+ setMedia(data.getData(), MediaType.FILE);
+ break;
}
}
@@ -678,10 +683,21 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
private void initializeDraft() {
final String draftText = getIntent().getStringExtra(TEXT_EXTRA);
final Uri draftMedia = getIntent().getData();
+ final String draftFilename = getIntent().getStringExtra(FILENAME_EXTRA);
final MediaType draftMediaType = MediaType.from(getIntent().getType());
if (draftText != null) composeText.setText(draftText);
- if (draftMedia != null && draftMediaType != null) setMedia(draftMedia, draftMediaType);
+ if (draftMedia != null && draftMediaType != null){
+ Recipient primaryRecipient = getRecipients() == null ? null : getRecipients().getPrimaryRecipient();
+ boolean isSecureSmsDestination = isSingleConversation() && SessionUtil.hasSession(this, masterSecret, primaryRecipient);
+ if (draftMediaType.equals(MediaType.FILE) && !isSecureSmsDestination) {
+ Toast.makeText(this, R.string.ConversationActivity_sorry_no_files_attaching_on_insecure_chat, Toast.LENGTH_LONG).show();
+ } else if (draftFilename != null) {
+ setMedia(draftMedia, draftMediaType, draftFilename);
+ } else {
+ setMedia(draftMedia, draftMediaType);
+ }
+ }
if (draftText == null && draftMedia == null && draftMediaType == null) {
initializeDraftFromDatabase();
@@ -720,6 +736,8 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
setMedia(Uri.parse(draft.getValue()), MediaType.AUDIO);
} else if (draft.getType().equals(Draft.VIDEO)) {
setMedia(Uri.parse(draft.getValue()), MediaType.VIDEO);
+ } else if (draft.getType().equals(Draft.FILE)) {
+ setMedia(Uri.parse(draft.getValue()) , MediaType.FILE);
}
}
@@ -739,7 +757,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
} else {
this.isEncryptedConversation = false;
}
-
+ attachmentAdapter.setSecureDestination(isSecureSmsDestination);
sendButton.resetAvailableTransports(isMediaMessage);
if (!isSecureSmsDestination ) sendButton.disableTransport(Type.SECURE_SMS);
if (recipients.isGroupRecipient()) sendButton.disableTransport(Type.INSECURE_SMS);
@@ -806,7 +824,10 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
composeBubble.getBackground().setColorFilter(defaultColor, PorterDuff.Mode.MULTIPLY);
colors.recycle();
- attachmentAdapter = new AttachmentTypeSelectorAdapter(this);
+ Recipient primaryRecipient = getRecipients() == null ? null : getRecipients().getPrimaryRecipient();
+ boolean isSecureSmsDestination = isSingleConversation() && SessionUtil.hasSession(this, masterSecret, primaryRecipient);
+
+ attachmentAdapter = new AttachmentTypeSelectorAdapter(this, isSecureSmsDestination);
attachmentManager = new AttachmentManager(this, this);
SendButtonListener sendButtonListener = new SendButtonListener();
@@ -952,6 +973,8 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
AttachmentManager.selectContactInfo(this, PICK_CONTACT_INFO); break;
case AttachmentTypeSelectorAdapter.TAKE_PHOTO:
attachmentManager.capturePhoto(this, TAKE_PHOTO); break;
+ case AttachmentTypeSelectorAdapter.ADD_FILE:
+ attachmentManager.selectFile(masterSecret, this, PICK_FILE); break;
}
}
@@ -959,6 +982,10 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
attachmentManager.setMedia(masterSecret, uri, mediaType, getCurrentMediaConstraints());
}
+ private void setMedia(Uri uri, MediaType mediaType, String fileName) {
+ attachmentManager.setMedia(masterSecret, uri, mediaType, getCurrentMediaConstraints(), fileName);
+ }
+
private void addAttachmentContactInfo(Uri contactUri) {
ContactAccessor contactDataList = ContactAccessor.getInstance();
ContactData contactData = contactDataList.getContactData(this, contactUri);
@@ -999,6 +1026,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
for (Slide slide : attachmentManager.buildSlideDeck().getSlides()) {
if (slide.hasAudio()) drafts.add(new Draft(Draft.AUDIO, slide.getUri().toString()));
else if (slide.hasVideo()) drafts.add(new Draft(Draft.VIDEO, slide.getUri().toString()));
+ else if (slide.hasFile() ) drafts.add(new Draft(Draft.FILE, slide.getUri().toString()));
else if (slide.hasImage()) drafts.add(new Draft(Draft.IMAGE, slide.getUri().toString()));
}
diff --git a/src/org/smssecure/smssecure/ConversationFragment.java b/src/org/smssecure/smssecure/ConversationFragment.java
index 04a1a15e39898c91b20361eea89af6d2cc3b5bb0..955bcbcceefe0989044591b44ff07c6fefa0741f 100644
--- a/src/org/smssecure/smssecure/ConversationFragment.java
+++ b/src/org/smssecure/smssecure/ConversationFragment.java
@@ -340,9 +340,9 @@ public class ConversationFragment extends Fragment
SaveAttachmentTask.showWarningDialog(getActivity(), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
for (Slide slide : message.getSlideDeck().getSlides()) {
- if (slide.hasImage() || slide.hasVideo() || slide.hasAudio()) {
+ if (slide.hasImage() || slide.hasVideo() || slide.hasAudio() || slide.hasFile()) {
SaveAttachmentTask saveTask = new SaveAttachmentTask(getActivity(), masterSecret);
- saveTask.execute(new Attachment(slide.getUri(), slide.getContentType(), message.getDateReceived()));
+ saveTask.execute(new Attachment(slide.getUri(), slide.getContentType(), message.getDateReceived(), slide.getFileName()));
return;
}
}
diff --git a/src/org/smssecure/smssecure/ConversationItem.java b/src/org/smssecure/smssecure/ConversationItem.java
index 76034bee723791e8e9f9e9eef8739826ceda2a30..a6adc33a86fbc9d504448f4f3c6e1a2dafb19159 100644
--- a/src/org/smssecure/smssecure/ConversationItem.java
+++ b/src/org/smssecure/smssecure/ConversationItem.java
@@ -63,16 +63,20 @@ import org.smssecure.smssecure.protocol.AutoInitiate;
import org.smssecure.smssecure.recipients.Recipient;
import org.smssecure.smssecure.recipients.Recipients;
import org.smssecure.smssecure.util.DateUtils;
+import org.smssecure.smssecure.util.SaveAttachmentTask;
import org.smssecure.smssecure.util.TelephonyUtil;
import org.smssecure.smssecure.util.Util;
import org.smssecure.smssecure.util.dualsim.SubscriptionInfoCompat;
import org.smssecure.smssecure.util.dualsim.SubscriptionManagerCompat;
import org.whispersystems.libaxolotl.util.guava.Optional;
+import java.util.Date;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;
+import ws.com.google.android.mms.ContentType;
+
/**
* A view that displays an individual conversation item within a conversation
* thread. Used by ComposeMessageActivity's ListActivity via a ConversationAdapter.
@@ -525,6 +529,15 @@ public class ConversationItem extends LinearLayout
intent.putExtra(MediaPreviewActivity.DATE_EXTRA, messageRecord.getTimestamp());
context.startActivity(intent);
+ } else if (slide.hasFile()) {
+ SaveAttachmentTask.showWarningDialog(context, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ SaveAttachmentTask saveTask = new SaveAttachmentTask(context, masterSecret);
+ saveTask.execute(new SaveAttachmentTask.Attachment(slide.getUri(), slide.getContentType(), new Date().getTime(), slide.getFileName()));
+ return;
+ }
+ });
+
} else {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(R.string.ConversationItem_view_secure_media_question);
diff --git a/src/org/smssecure/smssecure/MediaOverviewActivity.java b/src/org/smssecure/smssecure/MediaOverviewActivity.java
index 152098702db19b57ff522018f795ab2d37f51ce2..27dbe5a2beab03c5702ef78037c78ace2a50cb09 100644
--- a/src/org/smssecure/smssecure/MediaOverviewActivity.java
+++ b/src/org/smssecure/smssecure/MediaOverviewActivity.java
@@ -164,7 +164,7 @@ public class MediaOverviewActivity extends PassphraseRequiredActionBarActivity i
ImageRecord record = ImageRecord.from(cursor);
attachments.add(new SaveAttachmentTask.Attachment(record.getAttachment().getDataUri(),
record.getContentType(),
- record.getDate()));
+ record.getDate(), null));
}
return attachments;
diff --git a/src/org/smssecure/smssecure/MediaPreviewActivity.java b/src/org/smssecure/smssecure/MediaPreviewActivity.java
index 61be05d4624f86afe6f589e54083b4401fddc303..b79102a3087be49bb6902ca38772e06e509bbade 100644
--- a/src/org/smssecure/smssecure/MediaPreviewActivity.java
+++ b/src/org/smssecure/smssecure/MediaPreviewActivity.java
@@ -171,7 +171,7 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity im
@Override
public void onClick(DialogInterface dialogInterface, int i) {
SaveAttachmentTask saveTask = new SaveAttachmentTask(MediaPreviewActivity.this, masterSecret);
- saveTask.execute(new Attachment(mediaUri, mediaType, date));
+ saveTask.execute(new Attachment(mediaUri, mediaType, date, null));
}
});
}
diff --git a/src/org/smssecure/smssecure/ShareActivity.java b/src/org/smssecure/smssecure/ShareActivity.java
index 8d983952367263afa42fb246db650aa68c212074..52b963164fa9570916c0fa9b8303f1122d42b39a 100644
--- a/src/org/smssecure/smssecure/ShareActivity.java
+++ b/src/org/smssecure/smssecure/ShareActivity.java
@@ -31,6 +31,7 @@ import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
+import org.smssecure.smssecure.attachments.UriAttachment;
import org.smssecure.smssecure.crypto.MasterSecret;
import org.smssecure.smssecure.mms.PartAuthority;
import org.smssecure.smssecure.providers.PersistentBlobProvider;
@@ -43,6 +44,8 @@ import org.smssecure.smssecure.util.ViewUtil;
import java.io.IOException;
import java.io.InputStream;
+import ws.com.google.android.mms.ContentType;
+
/**
* An activity to quickly share content with contacts
*
@@ -62,6 +65,7 @@ public class ShareActivity extends PassphraseRequiredActionBarActivity
private Uri resolvedExtra;
private String mimeType;
private boolean isPassingAlongMedia;
+ private String resolvedFilename;
@Override
protected void onPreCreate() {
@@ -112,7 +116,9 @@ public class ShareActivity extends PassphraseRequiredActionBarActivity
isPassingAlongMedia = false;
Uri streamExtra = getIntent().getParcelableExtra(Intent.EXTRA_STREAM);
- mimeType = getMimeType(streamExtra);
+ mimeType = streamExtra != null && !ContentType.isTextType(getMimeType(streamExtra)) ? getMimeType(streamExtra)
+ : ContentType.SMS_SECURE_FILE;
+ resolvedFilename = UriAttachment.getFilenameFromUri(streamExtra, context);
if (streamExtra != null && PartAuthority.isLocalUri(streamExtra)) {
isPassingAlongMedia = true;
resolvedExtra = streamExtra;
@@ -171,6 +177,7 @@ public class ShareActivity extends PassphraseRequiredActionBarActivity
final String textExtra = getIntent().getStringExtra(Intent.EXTRA_TEXT);
intent.putExtra(ConversationActivity.TEXT_EXTRA, textExtra);
if (resolvedExtra != null) intent.setDataAndType(resolvedExtra, mimeType);
+ if (resolvedFilename != null) intent.putExtra(ConversationActivity.FILENAME_EXTRA, resolvedFilename);
return intent;
}
diff --git a/src/org/smssecure/smssecure/attachments/Attachment.java b/src/org/smssecure/smssecure/attachments/Attachment.java
index 73c901a6c7e0d04babf3c6a7178162b46b6adf7f..30941faa2651b5f4ef82d810f472f611c492734a 100644
--- a/src/org/smssecure/smssecure/attachments/Attachment.java
+++ b/src/org/smssecure/smssecure/attachments/Attachment.java
@@ -13,6 +13,7 @@ public abstract class Attachment {
private final String contentType;
private final int transferState;
private final long size;
+ private final String fileName;
@Nullable
private final String location;
@@ -28,7 +29,7 @@ public abstract class Attachment {
private Bitmap thumbnail;
public Attachment(@NonNull String contentType, int transferState, long size,
- @Nullable String location, @Nullable String key, @Nullable String relay)
+ @Nullable String location, @Nullable String key, @Nullable String relay, @Nullable String fileName)
{
this.contentType = contentType;
this.transferState = transferState;
@@ -36,6 +37,7 @@ public abstract class Attachment {
this.location = location;
this.key = key;
this.relay = relay;
+ this.fileName = fileName;
}
@Nullable
@@ -85,4 +87,9 @@ public abstract class Attachment {
public Bitmap getThumbnail() {
return thumbnail;
}
+
+ @Nullable
+ public String getFileName(){
+ return fileName;
+ }
}
diff --git a/src/org/smssecure/smssecure/attachments/DatabaseAttachment.java b/src/org/smssecure/smssecure/attachments/DatabaseAttachment.java
index 388c6a76020b46fab189297d59d59bc12e74f035..c9987de597fbfd60a91912a8863741b9612f0d8c 100644
--- a/src/org/smssecure/smssecure/attachments/DatabaseAttachment.java
+++ b/src/org/smssecure/smssecure/attachments/DatabaseAttachment.java
@@ -13,14 +13,21 @@ public class DatabaseAttachment extends Attachment {
public DatabaseAttachment(AttachmentId attachmentId, long mmsId, boolean hasData,
String contentType, int transferProgress, long size,
- String location, String key, String relay)
+ String location, String key, String relay, String fileName)
{
- super(contentType, transferProgress, size, location, key, relay);
+ super(contentType, transferProgress, size, location, key, relay, fileName);
this.attachmentId = attachmentId;
this.hasData = hasData;
this.mmsId = mmsId;
}
+ public DatabaseAttachment(AttachmentId attachmentId, long mmsId, boolean hasData,
+ String contentType, int transferProgress, long size,
+ String location, String key, String relay)
+ {
+ this(attachmentId, mmsId, hasData, contentType, transferProgress, size, location, key, relay, null);
+ }
+
@Override
@NonNull
public Uri getDataUri() {
diff --git a/src/org/smssecure/smssecure/attachments/UriAttachment.java b/src/org/smssecure/smssecure/attachments/UriAttachment.java
index a366a6d19732a8513ee8402d5726b59b1ab3d62c..167ae75732ae309fc6b8517720ea74230f355ef2 100644
--- a/src/org/smssecure/smssecure/attachments/UriAttachment.java
+++ b/src/org/smssecure/smssecure/attachments/UriAttachment.java
@@ -1,31 +1,40 @@
package org.smssecure.smssecure.attachments;
import android.content.Context;
+import android.database.Cursor;
import android.net.Uri;
+import android.provider.OpenableColumns;
import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.util.Log;
-import org.smssecure.smssecure.crypto.MasterSecret;
-import org.smssecure.smssecure.util.MediaUtil;
-import org.whispersystems.libaxolotl.util.guava.Optional;
-
-import java.io.IOException;
-import java.io.InputStream;
+import ws.com.google.android.mms.ContentType;
public class UriAttachment extends Attachment {
+ private static final String TAG = UriAttachment.class.getSimpleName();
+
private final @NonNull Uri dataUri;
private final @NonNull Uri thumbnailUri;
- public UriAttachment(@NonNull Uri uri, @NonNull String contentType, int transferState, long size) {
- this(uri, uri, contentType, transferState, size);
+ public UriAttachment(@NonNull Uri uri, @NonNull String contentType, int transferState, long size, Context context) {
+ this(uri, uri, contentType, transferState, size, UriAttachment.getFilenameFromUri(uri, context));
+ }
+
+ public UriAttachment(@NonNull Uri uri, @NonNull String contentType, int transferState, long size, String inputFilename) {
+ this(uri, uri, contentType, transferState, size, inputFilename);
}
public UriAttachment(@NonNull Uri dataUri, @NonNull Uri thumbnailUri,
- @NonNull String contentType, int transferState, long size)
+ @NonNull String contentType, int transferState, long size, @Nullable String fileName)
{
- super(contentType, transferState, size, null, null, null);
+ super(contentType, transferState, size, null, null, null, fileName);
this.dataUri = dataUri;
- this.thumbnailUri = thumbnailUri;
+ if(!ContentType.isVendorFileType(contentType)) {
+ this.thumbnailUri = thumbnailUri;
+ } else {
+ this.thumbnailUri = null;
+ }
}
@Override
@@ -49,4 +58,27 @@ public class UriAttachment extends Attachment {
public int hashCode() {
return dataUri.hashCode();
}
+
+ public static String getFilenameFromUri(Uri uri, Context context) {
+ String fileName = null;
+ if (uri != null && uri.getScheme() != null && uri.getScheme().equals("content")) {
+ Log.w(TAG, "contenturi: "+uri.toString());
+ Cursor cursor = context.getContentResolver().query(uri, null, null, null, null);
+ try {
+ if (cursor != null && cursor.moveToFirst()) {
+ fileName = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
+ }
+ } finally {
+ if (cursor != null) cursor.close();
+ }
+ }
+ if (fileName == null) {
+ fileName = uri.getPath();
+ int cut = fileName != null ? fileName.lastIndexOf('/') : -1;
+ if (cut != -1) {
+ fileName = fileName.substring(cut + 1);
+ }
+ }
+ return fileName;
+ }
}
diff --git a/src/org/smssecure/smssecure/components/ThumbnailView.java b/src/org/smssecure/smssecure/components/ThumbnailView.java
index 4096912a71d469fb807a74515e1479a5a5369493..a85ab91b2163cb679b02de7df0fc65dcca916f57 100644
--- a/src/org/smssecure/smssecure/components/ThumbnailView.java
+++ b/src/org/smssecure/smssecure/components/ThumbnailView.java
@@ -118,9 +118,9 @@ public class ThumbnailView extends FrameLayout {
this.slide = slide;
- if (slide.getThumbnailUri() != null) buildThumbnailGlideRequest(slide, masterSecret).into(image);
- else if (slide.hasPlaceholder()) buildPlaceholderGlideRequest(slide).into(image);
- else Glide.clear(image);
+ if (slide.getThumbnailUri() != null && !slide.hasFile()) buildThumbnailGlideRequest(slide, masterSecret).into(image);
+ else if (slide.hasPlaceholder()) buildPlaceholderGlideRequest(slide).into(image);
+ else Glide.clear(image);
}
public void setImageResource(@NonNull MasterSecret masterSecret, @NonNull Uri uri) {
diff --git a/src/org/smssecure/smssecure/database/AttachmentDatabase.java b/src/org/smssecure/smssecure/database/AttachmentDatabase.java
index cce5ecf3325b5bab3dcc491534d2dfbcef39f2d7..f7baa6c0bcfe52c495dc2e9d8393307e6d9d6c77 100644
--- a/src/org/smssecure/smssecure/database/AttachmentDatabase.java
+++ b/src/org/smssecure/smssecure/database/AttachmentDatabase.java
@@ -65,6 +65,7 @@ public class AttachmentDatabase extends Database {
static final String MMS_ID = "mid";
static final String CONTENT_TYPE = "ct";
static final String NAME = "name";
+ static final String FILENAME = "filename";
static final String CONTENT_DISPOSITION = "cd";
static final String CONTENT_LOCATION = "cl";
static final String DATA = "_data";
@@ -85,11 +86,11 @@ public class AttachmentDatabase extends Database {
MMS_ID, CONTENT_TYPE, NAME, CONTENT_DISPOSITION,
CONTENT_LOCATION, DATA, TRANSFER_STATE,
SIZE, THUMBNAIL, THUMBNAIL_ASPECT_RATIO,
- UNIQUE_ID};
+ UNIQUE_ID, FILENAME};
public static final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + " (" + ROW_ID + " INTEGER PRIMARY KEY, " +
MMS_ID + " INTEGER, " + "seq" + " INTEGER DEFAULT 0, " +
- CONTENT_TYPE + " TEXT, " + NAME + " TEXT, " + "chset" + " INTEGER, " +
+ CONTENT_TYPE + " TEXT, " + NAME + " TEXT, " + FILENAME + " TEXT, " + "chset" + " INTEGER, " +
CONTENT_DISPOSITION + " TEXT, " + "fn" + " TEXT, " + "cid" + " TEXT, " +
CONTENT_LOCATION + " TEXT, " + "ctt_s" + " INTEGER, " +
"ctt_t" + " TEXT, " + "encrypted" + " INTEGER, " +
@@ -260,6 +261,7 @@ public class AttachmentDatabase extends Database {
values.put(CONTENT_LOCATION, (String)null);
values.put(CONTENT_DISPOSITION, (String)null);
values.put(NAME, (String) null);
+ values.put(FILENAME, (String) null);
if (database.update(TABLE_NAME, values, PART_ID_WHERE, attachmentId.toStrings()) == 0) {
//noinspection ResultOfMethodCallIgnored
@@ -305,6 +307,9 @@ public class AttachmentDatabase extends Database {
ContentValues contentValues = new ContentValues();
contentValues.put(SIZE, dataSize);
contentValues.put(CONTENT_TYPE, mediaStream.getMimeType());
+ if (attachment.getFileName() != null) {
+ contentValues.put(FILENAME, databaseAttachment.getFileName());
+ }
database.update(TABLE_NAME, contentValues, PART_ID_WHERE, databaseAttachment.getAttachmentId().toStrings());
@@ -316,7 +321,8 @@ public class AttachmentDatabase extends Database {
dataSize,
databaseAttachment.getLocation(),
databaseAttachment.getKey(),
- databaseAttachment.getRelay());
+ databaseAttachment.getRelay(),
+ databaseAttachment.getFileName());
}
@@ -437,7 +443,8 @@ public class AttachmentDatabase extends Database {
cursor.getLong(cursor.getColumnIndexOrThrow(SIZE)),
cursor.getString(cursor.getColumnIndexOrThrow(CONTENT_LOCATION)),
cursor.getString(cursor.getColumnIndexOrThrow(CONTENT_DISPOSITION)),
- cursor.getString(cursor.getColumnIndexOrThrow(NAME)));
+ cursor.getString(cursor.getColumnIndexOrThrow(NAME)),
+ cursor.getString(cursor.getColumnIndexOrThrow(FILENAME)));
}
@@ -463,7 +470,9 @@ public class AttachmentDatabase extends Database {
contentValues.put(CONTENT_LOCATION, attachment.getLocation());
contentValues.put(CONTENT_DISPOSITION, attachment.getKey());
contentValues.put(NAME, attachment.getRelay());
-
+ if (attachment.getFileName() != null) {
+ contentValues.put(FILENAME, attachment.getFileName());
+ }
if (partData != null) {
contentValues.put(DATA, partData.first.getAbsolutePath());
contentValues.put(SIZE, partData.second);
diff --git a/src/org/smssecure/smssecure/database/DatabaseFactory.java b/src/org/smssecure/smssecure/database/DatabaseFactory.java
index 750b9bc836adefb3ad21e9c7bc38c601a5456a5f..7d8c126e0fedeca5990c23d5e2a8975d3db6fd4f 100644
--- a/src/org/smssecure/smssecure/database/DatabaseFactory.java
+++ b/src/org/smssecure/smssecure/database/DatabaseFactory.java
@@ -73,7 +73,8 @@ public class DatabaseFactory {
private static final int INTRODUCED_CONVERSATION_LIST_STATUS_VERSION = 25;
private static final int MIGRATED_CONVERSATION_LIST_STATUS_VERSION = 26;
private static final int INTRODUCED_SUBSCRIPTION_ID_VERSION = 28;
- private static final int DATABASE_VERSION = 28;
+ private static final int INTRODUCED_ATTACHMENT_FILENAME = 29;
+ private static final int DATABASE_VERSION = 29;
private static final String DATABASE_NAME = "messages.db";
private static final Object lock = new Object();
@@ -392,7 +393,8 @@ public class DatabaseFactory {
}
} else if (ContentType.isAudioType(contentType) ||
ContentType.isImageType(contentType) ||
- ContentType.isVideoType(contentType))
+ ContentType.isVideoType(contentType) ||
+ ContentType.isVendorFileType(contentType))
{
partCount++;
}
@@ -817,6 +819,11 @@ public class DatabaseFactory {
db.execSQL("ALTER TABLE mms ADD COLUMN subscription_id INTEGER DEFAULT -1");
}
+ if (oldVersion < INTRODUCED_ATTACHMENT_FILENAME) {
+ db.execSQL("ALTER TABLE part ADD COLUMN filename TEXT DEFAULT NULL;");
+ db.execSQL("UPDATE part SET filename = ?;", new String[]{""});
+ }
+
db.setTransactionSuccessful();
db.endTransaction();
}
diff --git a/src/org/smssecure/smssecure/database/DraftDatabase.java b/src/org/smssecure/smssecure/database/DraftDatabase.java
index bf9afafc7464a20c7ce124817530ec0c8ca1eca4..9670545e2c0fbc494312a68766f7a99f74cb3aee 100644
--- a/src/org/smssecure/smssecure/database/DraftDatabase.java
+++ b/src/org/smssecure/smssecure/database/DraftDatabase.java
@@ -107,6 +107,7 @@ public class DraftDatabase extends Database {
public static final String IMAGE = "image";
public static final String VIDEO = "video";
public static final String AUDIO = "audio";
+ public static final String FILE = "file";
private final String type;
private final String value;
@@ -130,6 +131,7 @@ public class DraftDatabase extends Database {
case IMAGE: return context.getString(R.string.DraftDatabase_Draft_image_snippet);
case VIDEO: return context.getString(R.string.DraftDatabase_Draft_video_snippet);
case AUDIO: return context.getString(R.string.DraftDatabase_Draft_audio_snippet);
+ case FILE: return context.getString(R.string.DraftDatabase_Draft_file_snippet);
default: return null;
}
}
diff --git a/src/org/smssecure/smssecure/database/MmsDatabase.java b/src/org/smssecure/smssecure/database/MmsDatabase.java
index 9204bdbd29c83e5972380abdb356e4d0efb49ec6..8e97c36187f0252718cc61e485e63e0478858426 100644
--- a/src/org/smssecure/smssecure/database/MmsDatabase.java
+++ b/src/org/smssecure/smssecure/database/MmsDatabase.java
@@ -138,6 +138,7 @@ public class MmsDatabase extends MessagingDatabase {
AttachmentDatabase.CONTENT_LOCATION,
AttachmentDatabase.CONTENT_DISPOSITION,
AttachmentDatabase.NAME,
+ AttachmentDatabase.FILENAME,
AttachmentDatabase.TRANSFER_STATE
};
@@ -503,7 +504,8 @@ public class MmsDatabase extends MessagingDatabase {
databaseAttachment.getSize(),
databaseAttachment.getLocation(),
databaseAttachment.getKey(),
- databaseAttachment.getRelay()));
+ databaseAttachment.getRelay(),
+ databaseAttachment.getFileName()));
}
return insertMediaMessage(masterSecret,
diff --git a/src/org/smssecure/smssecure/database/MmsSmsDatabase.java b/src/org/smssecure/smssecure/database/MmsSmsDatabase.java
index 05d837d0921db19940e7a6a77a3d86d5a15d62b4..fe3e4b50efca0a71b5600fcb01670c334992e94c 100644
--- a/src/org/smssecure/smssecure/database/MmsSmsDatabase.java
+++ b/src/org/smssecure/smssecure/database/MmsSmsDatabase.java
@@ -25,6 +25,7 @@ import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;
+import org.smssecure.smssecure.attachments.Attachment;
import org.smssecure.smssecure.crypto.MasterSecret;
import org.smssecure.smssecure.database.model.MessageRecord;
import org.whispersystems.libaxolotl.util.guava.Optional;
@@ -63,6 +64,7 @@ public class MmsSmsDatabase extends Database {
AttachmentDatabase.CONTENT_LOCATION,
AttachmentDatabase.CONTENT_DISPOSITION,
AttachmentDatabase.NAME,
+ AttachmentDatabase.FILENAME,
AttachmentDatabase.TRANSFER_STATE};
public MmsSmsDatabase(Context context, SQLiteOpenHelper databaseHelper) {
@@ -137,6 +139,7 @@ public class MmsSmsDatabase extends Database {
AttachmentDatabase.CONTENT_LOCATION,
AttachmentDatabase.CONTENT_DISPOSITION,
AttachmentDatabase.NAME,
+ AttachmentDatabase.FILENAME,
AttachmentDatabase.TRANSFER_STATE};
String[] smsProjection = {SmsDatabase.DATE_SENT + " AS " + MmsSmsColumns.NORMALIZED_DATE_SENT,
@@ -162,6 +165,7 @@ public class MmsSmsDatabase extends Database {
AttachmentDatabase.CONTENT_LOCATION,
AttachmentDatabase.CONTENT_DISPOSITION,
AttachmentDatabase.NAME,
+ AttachmentDatabase.FILENAME,
AttachmentDatabase.TRANSFER_STATE};
SQLiteQueryBuilder mmsQueryBuilder = new SQLiteQueryBuilder();
@@ -209,6 +213,7 @@ public class MmsSmsDatabase extends Database {
mmsColumnsPresent.add(AttachmentDatabase.CONTENT_LOCATION);
mmsColumnsPresent.add(AttachmentDatabase.CONTENT_DISPOSITION);
mmsColumnsPresent.add(AttachmentDatabase.NAME);
+ mmsColumnsPresent.add(AttachmentDatabase.FILENAME);
mmsColumnsPresent.add(AttachmentDatabase.TRANSFER_STATE);
Set smsColumnsPresent = new HashSet<>();
diff --git a/src/org/smssecure/smssecure/jobs/MmsDownloadJob.java b/src/org/smssecure/smssecure/jobs/MmsDownloadJob.java
index bdd5591dea4eda59f90fdd3e4dacae1c802a33c8..80d5c6ab8d256e88ef9a52c526541d9c80b45d34 100644
--- a/src/org/smssecure/smssecure/jobs/MmsDownloadJob.java
+++ b/src/org/smssecure/smssecure/jobs/MmsDownloadJob.java
@@ -7,6 +7,8 @@ import android.os.Build.VERSION_CODES;
import android.util.Log;
import android.util.Pair;
+import com.fasterxml.jackson.databind.util.ISO8601Utils;
+
import org.smssecure.smssecure.attachments.Attachment;
import org.smssecure.smssecure.attachments.UriAttachment;
import org.smssecure.smssecure.crypto.MasterSecret;
@@ -209,9 +211,10 @@ public class MmsDownloadJob extends MasterSecretJob {
if (part.getData() != null) {
Uri uri = provider.createUri(part.getData());
+ String potentialFilename = part.getFilename() != null ? Util.toIsoString(part.getFilename()) : null;
attachments.add(new UriAttachment(uri, Util.toIsoString(part.getContentType()),
AttachmentDatabase.TRANSFER_PROGRESS_DONE,
- part.getData().length));
+ part.getData().length, potentialFilename));
}
}
}
diff --git a/src/org/smssecure/smssecure/jobs/MmsSendJob.java b/src/org/smssecure/smssecure/jobs/MmsSendJob.java
index 1f16800f97aed4dd5d907272dc2aa7d040781d8a..666abdc53911bcdd340320749b8520b577bd8006 100644
--- a/src/org/smssecure/smssecure/jobs/MmsSendJob.java
+++ b/src/org/smssecure/smssecure/jobs/MmsSendJob.java
@@ -25,6 +25,7 @@ import org.smssecure.smssecure.recipients.RecipientFormattingException;
import org.smssecure.smssecure.transport.InsecureFallbackApprovalException;
import org.smssecure.smssecure.transport.UndeliverableMessageException;
import org.smssecure.smssecure.util.Hex;
+import org.smssecure.smssecure.util.MediaUtil;
import org.smssecure.smssecure.util.NumberUtil;
import org.smssecure.smssecure.util.SmilUtil;
import org.smssecure.smssecure.util.TelephonyUtil;
@@ -234,6 +235,9 @@ public class MmsSendJob extends SendJob {
PduPart part = new PduPart();
part.setData(Util.readFully(PartAuthority.getAttachmentStream(context, masterSecret, attachment.getDataUri())));
part.setContentType(Util.toIsoBytes(attachment.getContentType()));
+ if (MediaUtil.isFile(attachment) && attachment.getFileName() != null) {
+ part.setFilename(Util.toIsoBytes(attachment.getFileName()));
+ }
part.setContentId((System.currentTimeMillis() + "").getBytes());
part.setName((System.currentTimeMillis() + "").getBytes());
diff --git a/src/org/smssecure/smssecure/mms/AttachmentManager.java b/src/org/smssecure/smssecure/mms/AttachmentManager.java
index 7f00091251398dc05ab09f717f0adfad3a562518..3f86bd69dcc10062967212ed347c6c8cba1e6011 100644
--- a/src/org/smssecure/smssecure/mms/AttachmentManager.java
+++ b/src/org/smssecure/smssecure/mms/AttachmentManager.java
@@ -32,8 +32,6 @@ import android.util.Log;
import android.view.View;
import android.widget.Toast;
-import junit.framework.Assert;
-
import org.smssecure.smssecure.MediaPreviewActivity;
import org.smssecure.smssecure.R;
import org.smssecure.smssecure.components.AudioView;
@@ -41,12 +39,12 @@ import org.smssecure.smssecure.components.RemovableMediaView;
import org.smssecure.smssecure.components.ThumbnailView;
import org.smssecure.smssecure.crypto.MasterSecret;
import org.smssecure.smssecure.providers.PersistentBlobProvider;
-import org.smssecure.smssecure.recipients.Recipients;
import org.smssecure.smssecure.util.MediaUtil;
import org.smssecure.smssecure.util.ViewUtil;
import org.smssecure.smssecure.util.concurrent.ListenableFuture.Listener;
import org.whispersystems.libaxolotl.util.guava.Optional;
+import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.LinkedList;
@@ -82,6 +80,15 @@ public class AttachmentManager {
thumbnail.setOnClickListener(new ThumbnailClickListener());
}
+ public void selectFile(final MasterSecret secret, final Activity activity, int requestCode) {
+ new FileChooser(activity).setFileListener(new FileChooser.FileSelectedListener() {
+ @Override
+ public void fileSelected(final File file) {
+ setMedia(secret, Uri.fromFile(file), MediaType.FILE, new MmsMediaConstraints());
+ }
+ }).showDialog();
+ }
+
public void clear() {
ViewUtil.fadeOut(attachmentView, 200).addListener(new Listener() {
@Override
@@ -140,7 +147,15 @@ public class AttachmentManager {
public void setMedia(@NonNull final MasterSecret masterSecret,
@NonNull final Uri uri,
@NonNull final MediaType mediaType,
- @NonNull final MediaConstraints constraints)
+ @NonNull final MediaConstraints constraints){
+ setMedia(masterSecret, uri, mediaType, constraints, null);
+ }
+
+ public void setMedia(@NonNull final MasterSecret masterSecret,
+ @NonNull final Uri uri,
+ @NonNull final MediaType mediaType,
+ @NonNull final MediaConstraints constraints,
+ final String fileName)
{
new AsyncTask() {
@Override protected void onPreExecute() {
@@ -153,7 +168,7 @@ public class AttachmentManager {
long start = System.currentTimeMillis();
try {
final long mediaSize = MediaUtil.getMediaSize(context, masterSecret, uri);
- final Slide slide = mediaType.createSlide(context, uri, mediaSize);
+ final Slide slide = mediaType.createSlide(context, uri, mediaSize, fileName);
Log.w(TAG, "slide with size " + mediaSize + " took " + (System.currentTimeMillis() - start) + "ms");
return slide;
} catch (IOException ioe) {
@@ -306,28 +321,30 @@ public class AttachmentManager {
}
public enum MediaType {
- IMAGE, GIF, AUDIO, VIDEO;
+ IMAGE, GIF, AUDIO, VIDEO, FILE;
public @NonNull Slide createSlide(@NonNull Context context,
@NonNull Uri uri,
- long dataSize)
- throws IOException
- {
+ long dataSize,
+ String fileName)
+ throws IOException {
switch (this) {
case IMAGE: return new ImageSlide(context, uri, dataSize);
case GIF: return new GifSlide(context, uri, dataSize);
case AUDIO: return new AudioSlide(context, uri, dataSize);
case VIDEO: return new VideoSlide(context, uri, dataSize);
+ case FILE: return new FileSlide(context, uri, dataSize, fileName);
default: throw new AssertionError("unrecognized enum");
}
}
public static @Nullable MediaType from(final @Nullable String mimeType) {
- if (TextUtils.isEmpty(mimeType)) return null;
- if (MediaUtil.isGif(mimeType)) return GIF;
- if (ContentType.isImageType(mimeType)) return IMAGE;
- if (ContentType.isAudioType(mimeType)) return AUDIO;
- if (ContentType.isVideoType(mimeType)) return VIDEO;
+ if (TextUtils.isEmpty(mimeType)) return null;
+ if (MediaUtil.isGif(mimeType)) return GIF;
+ if (ContentType.isImageType(mimeType)) return IMAGE;
+ if (ContentType.isAudioType(mimeType)) return AUDIO;
+ if (ContentType.isVideoType(mimeType)) return VIDEO;
+ if (ContentType.isVendorFileType(mimeType)) return FILE;
return null;
}
}
diff --git a/src/org/smssecure/smssecure/mms/AttachmentTypeSelectorAdapter.java b/src/org/smssecure/smssecure/mms/AttachmentTypeSelectorAdapter.java
index e0afe63df03e556eefc85989b87d105ea99bc1cd..8febd2a7148fe8efec3d297fa2a0c25210ebb47b 100644
--- a/src/org/smssecure/smssecure/mms/AttachmentTypeSelectorAdapter.java
+++ b/src/org/smssecure/smssecure/mms/AttachmentTypeSelectorAdapter.java
@@ -28,6 +28,7 @@ import android.widget.TextView;
import org.smssecure.smssecure.R;
import org.smssecure.smssecure.util.ResUtil;
+import org.smssecure.smssecure.util.SMSSecurePreferences;
import java.util.ArrayList;
import java.util.List;
@@ -39,11 +40,14 @@ public class AttachmentTypeSelectorAdapter extends ArrayAdapter getItemList(Context context) {
+ private static List getItemList(Context context, boolean isEncryptedConversation) {
List data = new ArrayList<>(4);
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){
addItem(data, context.getString(R.string.AttachmentTypeSelectorAdapter_camera), ResUtil.getDrawableRes(context, R.attr.conversation_attach_camera), TAKE_PHOTO);
@@ -80,7 +84,12 @@ public class AttachmentTypeSelectorAdapter extends ArrayAdapter= 0) {
+ remove(fileIdentifier);
+ }
+ }
+
public static class IconListItem {
private final String title;
private final int resource;
diff --git a/src/org/smssecure/smssecure/mms/FileChooser.java b/src/org/smssecure/smssecure/mms/FileChooser.java
new file mode 100644
index 0000000000000000000000000000000000000000..94932eb190e878fc9807b41bff5e26d0627606d8
--- /dev/null
+++ b/src/org/smssecure/smssecure/mms/FileChooser.java
@@ -0,0 +1,127 @@
+package org.smssecure.smssecure.mms;
+
+import android.app.Activity;
+import android.app.Dialog;
+import android.os.Environment;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager.LayoutParams;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+import android.widget.TextView;
+import java.io.File;
+import java.io.FileFilter;
+import java.util.Arrays;
+
+public class FileChooser {
+ private static final String PARENT_DIR = "..";
+
+ private final Activity activity;
+ private ListView list;
+ private Dialog dialog;
+ private File currentPath;
+
+ private String extension = null;
+
+ public void setExtension(String extension) {
+ this.extension = (extension == null) ? null : extension.toLowerCase();
+ }
+
+ public interface FileSelectedListener {
+ void fileSelected(File file);
+ }
+
+ public FileChooser setFileListener(FileSelectedListener fileListener) {
+ this.fileListener = fileListener;
+ return this;
+ }
+
+ private FileSelectedListener fileListener;
+
+ public FileChooser(Activity activity) {
+ this.activity = activity;
+ dialog = new Dialog(activity);
+ list = new ListView(activity);
+ list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ @Override public void onItemClick(AdapterView> parent, View view, int which, long id) {
+ String fileChosen = (String) list.getItemAtPosition(which);
+ File chosenFile = getChosenFile(fileChosen);
+ if (chosenFile.isDirectory()) {
+ refresh(chosenFile);
+ } else {
+ if (fileListener != null) {
+ fileListener.fileSelected(chosenFile);
+ }
+ dialog.dismiss();
+ }
+ }
+ });
+ dialog.setContentView(list);
+ dialog.getWindow().setLayout(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
+ refresh(Environment.getExternalStorageDirectory());
+ }
+
+ public void showDialog() {
+ dialog.show();
+ }
+
+ private void refresh(File path) {
+ this.currentPath = path;
+ if (path.exists()) {
+ File[] dirs = path.listFiles(new FileFilter() {
+ @Override public boolean accept(File file) {
+ return (file.isDirectory() && file.canRead());
+ }
+ });
+ File[] files = path.listFiles(new FileFilter() {
+ @Override public boolean accept(File file) {
+ if (!file.isDirectory()) {
+ if (!file.canRead()) {
+ return false;
+ } else if (extension == null) {
+ return true;
+ } else {
+ return file.getName().toLowerCase().endsWith(extension);
+ }
+ } else {
+ return false;
+ }
+ }
+ });
+
+ int i = 0;
+ String[] fileList;
+ if (path.getParentFile() == null) {
+ fileList = new String[dirs.length + files.length];
+ } else {
+ fileList = new String[dirs.length + files.length + 1];
+ fileList[i++] = PARENT_DIR;
+ }
+ Arrays.sort(dirs);
+ Arrays.sort(files);
+ for (File dir : dirs) { fileList[i++] = dir.getName(); }
+ for (File file : files ) { fileList[i++] = file.getName(); }
+
+ dialog.setTitle(currentPath.getPath());
+ list.setAdapter(new ArrayAdapter(activity,
+ android.R.layout.simple_list_item_1, fileList) {
+ @Override
+ public View getView(int pos, View view, ViewGroup parent) {
+ view = super.getView(pos, view, parent);
+ ((TextView) view).setSingleLine(true);
+ return view;
+ }
+ });
+ }
+ }
+
+ private File getChosenFile(String fileChosen) {
+ if (fileChosen.equals(PARENT_DIR)) {
+ return currentPath.getParentFile();
+ } else {
+ return new File(currentPath, fileChosen);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/org/smssecure/smssecure/mms/FileSlide.java b/src/org/smssecure/smssecure/mms/FileSlide.java
new file mode 100644
index 0000000000000000000000000000000000000000..63ae01219dabae30e936ea7531923737535ece41
--- /dev/null
+++ b/src/org/smssecure/smssecure/mms/FileSlide.java
@@ -0,0 +1,77 @@
+/**
+ * Copyright (C) 2011 Whisper Systems
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.smssecure.smssecure.mms;
+
+import android.content.Context;
+import android.content.res.Resources.Theme;
+import android.net.Uri;
+import android.support.annotation.DrawableRes;
+import android.support.annotation.Nullable;
+
+import org.smssecure.smssecure.R;
+import org.smssecure.smssecure.attachments.Attachment;
+import org.smssecure.smssecure.crypto.MasterSecret;
+import org.smssecure.smssecure.util.ResUtil;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+
+import ws.com.google.android.mms.ContentType;
+import ws.com.google.android.mms.pdu.PduPart;
+
+public class FileSlide extends Slide {
+
+ public FileSlide(Context context, Uri uri, long dataSize, String fileName) throws IOException {
+ super(context, constructAttachmentFromUri(context, uri, ContentType.SMS_SECURE_FILE, dataSize, fileName));
+ }
+
+ public FileSlide(Context context, Attachment attachment) {
+ super(context, attachment);
+ }
+
+ @Override
+ @Nullable
+ public Uri getThumbnailUri() {
+ return null;
+ }
+
+ @Override
+ public boolean hasPlaceholder() {
+ return true;
+ }
+
+ @Override
+ public boolean hasFile(){
+ return true;
+ }
+
+ @Override
+ public boolean hasImage() {
+ return true;
+ }
+
+ @Override
+ public String getFileName(){
+ return attachment.getFileName();
+ }
+
+ @Override
+ public @DrawableRes int getPlaceholderRes(Theme theme) {
+ return ResUtil.getDrawableRes(theme, R.attr.conversation_icon_attach_file);
+ }
+}
diff --git a/src/org/smssecure/smssecure/mms/MediaConstraints.java b/src/org/smssecure/smssecure/mms/MediaConstraints.java
index fd451f9c3208a3980170ba50985ef1362d6d868c..d6fe50aebaa41e49bdd43933d1de3cb9bb7476f4 100644
--- a/src/org/smssecure/smssecure/mms/MediaConstraints.java
+++ b/src/org/smssecure/smssecure/mms/MediaConstraints.java
@@ -35,13 +35,16 @@ public abstract class MediaConstraints {
public abstract int getAudioMaxSize();
+ public abstract int getFileMaxSize();
+
public boolean isSatisfied(@NonNull Context context, @NonNull MasterSecret masterSecret, @NonNull Attachment attachment) {
try {
return (MediaUtil.isGif(attachment) && attachment.getSize() <= getGifMaxSize() && isWithinBounds(context, masterSecret, attachment.getDataUri())) ||
(MediaUtil.isImage(attachment) && attachment.getSize() <= getImageMaxSize() && isWithinBounds(context, masterSecret, attachment.getDataUri())) ||
(MediaUtil.isAudio(attachment) && attachment.getSize() <= getAudioMaxSize()) ||
(MediaUtil.isVideo(attachment) && attachment.getSize() <= getVideoMaxSize()) ||
- (!MediaUtil.isImage(attachment) && !MediaUtil.isAudio(attachment) && !MediaUtil.isVideo(attachment));
+ (MediaUtil.isFile(attachment) && attachment.getSize() <= getFileMaxSize()) ||
+ (!MediaUtil.isImage(attachment) && !MediaUtil.isAudio(attachment) && !MediaUtil.isVideo(attachment) && !MediaUtil.isFile(attachment));
} catch (IOException ioe) {
Log.w(TAG, "Failed to determine if media's constraints are satisfied.", ioe);
return false;
@@ -60,7 +63,7 @@ public abstract class MediaConstraints {
}
public boolean canResize(@Nullable Attachment attachment) {
- return attachment != null && MediaUtil.isImage(attachment) && !MediaUtil.isGif(attachment);
+ return attachment != null && MediaUtil.isImage(attachment) && !MediaUtil.isGif(attachment) && !MediaUtil.isFile(attachment);
}
public MediaStream getResizedMedia(@NonNull Context context,
diff --git a/src/org/smssecure/smssecure/mms/MmsMediaConstraints.java b/src/org/smssecure/smssecure/mms/MmsMediaConstraints.java
index 65e9776cc90757e501d939655cfddf8b898c4a68..4bd79c769cda093c54668fb420f260e019065d28 100644
--- a/src/org/smssecure/smssecure/mms/MmsMediaConstraints.java
+++ b/src/org/smssecure/smssecure/mms/MmsMediaConstraints.java
@@ -38,4 +38,10 @@ public class MmsMediaConstraints extends MediaConstraints {
public int getAudioMaxSize() {
return MAX_MESSAGE_SIZE;
}
+
+ @Override
+ public int getFileMaxSize() {
+ return MAX_MESSAGE_SIZE;
+ }
+
}
diff --git a/src/org/smssecure/smssecure/mms/OutgoingMediaMessage.java b/src/org/smssecure/smssecure/mms/OutgoingMediaMessage.java
index 5a5f3cada64c9aa16a306d6d0b9a2359f4b0e8cf..81c0140fa0f9541f436136c377bf26d9368413f3 100644
--- a/src/org/smssecure/smssecure/mms/OutgoingMediaMessage.java
+++ b/src/org/smssecure/smssecure/mms/OutgoingMediaMessage.java
@@ -32,6 +32,7 @@ public class OutgoingMediaMessage {
public OutgoingMediaMessage(Recipients recipients, SlideDeck slideDeck, String message, long sentTimeMillis, int subscriptionId, int distributionType)
{
+
this(recipients,
buildMessage(slideDeck, message),
slideDeck.asAttachments(),
diff --git a/src/org/smssecure/smssecure/mms/PartParser.java b/src/org/smssecure/smssecure/mms/PartParser.java
index 920a76cd8ecf09804eb6172f96c7f16e56ff9e44..538a40d5a48d262d55b4c00b12aed09d65d3344f 100644
--- a/src/org/smssecure/smssecure/mms/PartParser.java
+++ b/src/org/smssecure/smssecure/mms/PartParser.java
@@ -83,6 +83,11 @@ public class PartParser {
}
public static boolean isDisplayableMedia(PduPart part) {
- return isImage(part) || isAudio(part) || isVideo(part);
+ return isFile(part) || isImage(part) || isAudio(part) || isVideo(part);
}
+
+ public static boolean isFile(PduPart part) {
+ return ContentType.isVendorFileType(Util.toIsoString(part.getContentType()));
+ }
+
}
diff --git a/src/org/smssecure/smssecure/mms/Slide.java b/src/org/smssecure/smssecure/mms/Slide.java
index dc8cec451de893c62c340ec5ae0e976d783d656b..c570be095d4f716295f671984a7149bb22049c14 100644
--- a/src/org/smssecure/smssecure/mms/Slide.java
+++ b/src/org/smssecure/smssecure/mms/Slide.java
@@ -72,6 +72,14 @@ public abstract class Slide {
return false;
}
+ public boolean hasFile() {
+ return false;
+ }
+
+ public String getFileName() {
+ return null;
+ }
+
public @NonNull String getContentDescription() { return ""; }
public Attachment asAttachment() {
@@ -102,10 +110,22 @@ public abstract class Slide {
protected static Attachment constructAttachmentFromUri(@NonNull Context context,
@NonNull Uri uri,
@NonNull String defaultMime,
- long size)
+ long size)
+ {
+ Optional resolvedType = Optional.fromNullable(MediaUtil.getMimeType(context, uri));
+ return new UriAttachment(uri, resolvedType.or(defaultMime), AttachmentDatabase.TRANSFER_PROGRESS_STARTED, size, context);
+ }
+ protected static Attachment constructAttachmentFromUri(@NonNull Context context,
+ @NonNull Uri uri,
+ @NonNull String defaultMime,
+ long size,
+ String fileName)
{
Optional resolvedType = Optional.fromNullable(MediaUtil.getMimeType(context, uri));
- return new UriAttachment(uri, resolvedType.or(defaultMime), AttachmentDatabase.TRANSFER_PROGRESS_STARTED, size);
+ if (fileName != null) {
+ return new UriAttachment(uri, resolvedType.or(defaultMime), AttachmentDatabase.TRANSFER_PROGRESS_STARTED, size, fileName);
+ }
+ return new UriAttachment(uri, resolvedType.or(defaultMime), AttachmentDatabase.TRANSFER_PROGRESS_STARTED, size, context);
}
@Override
@@ -118,6 +138,7 @@ public abstract class Slide {
this.hasAudio() == that.hasAudio() &&
this.hasImage() == that.hasImage() &&
this.hasVideo() == that.hasVideo() &&
+ this.hasFile() == that.hasFile() &&
this.getTransferState() == that.getTransferState() &&
Util.equals(this.getUri(), that.getUri()) &&
Util.equals(this.getThumbnailUri(), that.getThumbnailUri());
diff --git a/src/org/smssecure/smssecure/mms/SlideDeck.java b/src/org/smssecure/smssecure/mms/SlideDeck.java
index 9bc512b68e614d6addbb8e9ff22862fd24734fd0..054646906fb35c65df150b9b146203300d035e60 100644
--- a/src/org/smssecure/smssecure/mms/SlideDeck.java
+++ b/src/org/smssecure/smssecure/mms/SlideDeck.java
@@ -86,7 +86,30 @@ public class SlideDeck {
public boolean containsMediaSlide() {
for (Slide slide : slides) {
- if (slide.hasImage() || slide.hasVideo() || slide.hasAudio()) {
+ if (slide.hasImage() || slide.hasVideo() || slide.hasAudio() || slide.hasFile()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public boolean removeFileSlides() {
+ boolean returnObject = false;
+ if (slides.isEmpty()) {
+ return returnObject;
+ }
+ for (Slide slide : slides) {
+ if (slide.hasFile()) {
+ returnObject = true;
+ slides.remove(slide);
+ }
+ }
+ return returnObject;
+ }
+
+ public boolean hasFileSlide() {
+ for (Slide slide : slides) {
+ if (slide.hasFile()) {
return true;
}
}
diff --git a/src/org/smssecure/smssecure/util/MediaUtil.java b/src/org/smssecure/smssecure/util/MediaUtil.java
index ec74669362004731d27122da0c820b8509232288..3961c45a2964f91327fc39fee26a9e245074dd76 100644
--- a/src/org/smssecure/smssecure/util/MediaUtil.java
+++ b/src/org/smssecure/smssecure/util/MediaUtil.java
@@ -14,6 +14,7 @@ import org.smssecure.smssecure.attachments.Attachment;
import org.smssecure.smssecure.crypto.MasterSecret;
import org.smssecure.smssecure.mms.AudioSlide;
import org.smssecure.smssecure.mms.DecryptableStreamUriLoader.DecryptableUri;
+import org.smssecure.smssecure.mms.FileSlide;
import org.smssecure.smssecure.mms.GifSlide;
import org.smssecure.smssecure.mms.ImageSlide;
import org.smssecure.smssecure.mms.PartAuthority;
@@ -23,7 +24,6 @@ import org.smssecure.smssecure.providers.PersistentBlobProvider;
import java.io.IOException;
import java.io.InputStream;
-import java.util.concurrent.ExecutionException;
import ws.com.google.android.mms.ContentType;
@@ -66,6 +66,8 @@ public class MediaUtil {
slide = new VideoSlide(context, attachment);
} else if (ContentType.isAudioType(attachment.getContentType())) {
slide = new AudioSlide(context, attachment);
+ } else if (ContentType.isVendorFileType(attachment.getContentType())) {
+ slide = new FileSlide(context, attachment);
}
return slide;
@@ -93,6 +95,9 @@ public class MediaUtil {
? ContentType.IMAGE_JPEG
: mimeType;
default:
+ if (ContentType.isNonTextVideoImageAudioType(mimeType)) {
+ return ContentType.SMS_SECURE_FILE;
+ }
return mimeType;
}
}
@@ -129,6 +134,10 @@ public class MediaUtil {
return ContentType.isAudioType(attachment.getContentType());
}
+ public static boolean isFile(Attachment attachment) {
+ return ContentType.isVendorFileType(attachment.getContentType());
+ }
+
public static boolean isVideo(Attachment attachment) {
return ContentType.isVideoType(attachment.getContentType());
}
diff --git a/src/org/smssecure/smssecure/util/SaveAttachmentTask.java b/src/org/smssecure/smssecure/util/SaveAttachmentTask.java
index fd81f170934b78a19684e32cb0ca41246dc87eb9..39993b0929d9f71d49320f88aa221804390cbd4b 100644
--- a/src/org/smssecure/smssecure/util/SaveAttachmentTask.java
+++ b/src/org/smssecure/smssecure/util/SaveAttachmentTask.java
@@ -7,6 +7,7 @@ import android.net.Uri;
import android.os.Environment;
import android.support.v7.app.AlertDialog;
import android.util.Log;
+import android.util.Pair;
import android.webkit.MimeTypeMap;
import android.widget.Toast;
@@ -23,7 +24,9 @@ import java.io.OutputStream;
import java.lang.ref.WeakReference;
import java.text.SimpleDateFormat;
-public class SaveAttachmentTask extends ProgressDialogAsyncTask {
+import ws.com.google.android.mms.ContentType;
+
+public class SaveAttachmentTask extends ProgressDialogAsyncTask> {
private static final String TAG = SaveAttachmentTask.class.getSimpleName();
private static final int SUCCESS = 0;
@@ -49,7 +52,7 @@ public class SaveAttachmentTask extends ProgressDialogAsyncTask doInBackground(SaveAttachmentTask.Attachment... attachments) {
if (attachments == null || attachments.length == 0) {
throw new AssertionError("must pass in at least one attachment");
}
@@ -59,33 +62,41 @@ public class SaveAttachmentTask extends ProgressDialogAsyncTask(WRITE_ACCESS_FAILURE, null);
}
if (context == null) {
- return FAILURE;
+ return new Pair(FAILURE, null);
}
+ StringBuilder builder = new StringBuilder();
for (Attachment attachment : attachments) {
- if (attachment != null && !saveAttachment(context, masterSecret, attachment)) {
- return FAILURE;
+ if(attachment == null)
+ return new Pair(FAILURE, null);
+ Pair saveResult = saveAttachment(context, masterSecret, attachment);
+ if (saveResult.first.equals(FAILURE)) {
+ return new Pair(FAILURE, null);
+ }
+ else if (saveResult.second != null){
+ if(builder.length() != 0)
+ builder.append(",");
+ builder.append(saveResult.second);
}
}
-
- return SUCCESS;
+ return new Pair(SUCCESS, builder.toString());
} catch (IOException ioe) {
Log.w(TAG, ioe);
- return FAILURE;
+ return new Pair(FAILURE, null);
}
}
- private boolean saveAttachment(Context context, MasterSecret masterSecret, Attachment attachment) throws IOException {
+ private Pair saveAttachment(Context context, MasterSecret masterSecret, Attachment attachment) throws IOException {
String contentType = MediaUtil.getCorrectedMimeType(attachment.contentType);
- File mediaFile = constructOutputFile(contentType, attachment.date);
+ File mediaFile = constructOutputFile(attachment, attachment.date);
InputStream inputStream = PartAuthority.getAttachmentStream(context, masterSecret, attachment.uri);
if (inputStream == null) {
- return false;
+ return new Pair(FAILURE, null);
}
OutputStream outputStream = new FileOutputStream(mediaFile);
@@ -94,16 +105,16 @@ public class SaveAttachmentTask extends ProgressDialogAsyncTask(SUCCESS, mediaFile.getAbsolutePath());
}
@Override
- protected void onPostExecute(Integer result) {
+ protected void onPostExecute(Pair result) {
super.onPostExecute(result);
Context context = contextReference.get();
if (context == null) return;
- switch (result) {
+ switch (result.first) {
case FAILURE:
Toast.makeText(context,
context.getResources().getQuantityText(R.plurals.ConversationFragment_error_while_saving_attachments_to_sd_card,
@@ -111,7 +122,7 @@ public class SaveAttachmentTask extends ProgressDialogAsyncTask sSupportedContentTypes = new ArrayList();
private static final ArrayList sSupportedImageTypes = new ArrayList();
private static final ArrayList sSupportedAudioTypes = new ArrayList();
@@ -124,6 +126,7 @@ public class ContentType {
sSupportedContentTypes.add(APP_DRM_CONTENT);
sSupportedContentTypes.add(APP_DRM_MESSAGE);
+ sSupportedContentTypes.add(SMS_SECURE_FILE);
// add supported image types
sSupportedImageTypes.add(IMAGE_JPEG);
@@ -197,10 +200,13 @@ public class ContentType {
return (null != contentType) && contentType.startsWith("video/");
}
- public static boolean isDrmType(String contentType) {
+ public static boolean isNonTextVideoImageAudioType(String contentType){
+ return !isVideoType(contentType) && !isTextType(contentType) && !isAudioType(contentType) && !isImageType(contentType);
+ }
+
+ public static boolean isVendorFileType(String contentType) {
return (null != contentType)
- && (contentType.equals(APP_DRM_CONTENT)
- || contentType.equals(APP_DRM_MESSAGE));
+ && (contentType.equals(SMS_SECURE_FILE));
}
public static boolean isUnspecified(String contentType) {
diff --git a/src/ws/com/google/android/mms/pdu/PduComposer.java b/src/ws/com/google/android/mms/pdu/PduComposer.java
index d2808cc7c50f06f54a0f8422878272c7a627baee..ecbca36846499f6ac7fa886344a8fb4de7bf2a73 100644
--- a/src/ws/com/google/android/mms/pdu/PduComposer.java
+++ b/src/ws/com/google/android/mms/pdu/PduComposer.java
@@ -961,6 +961,13 @@ public class PduComposer {
appendValueLength(contentTypeLength);
mStack.copy();
+ // file-name for fileslides
+ if(part.getFilename() != null) {
+ Log.w("PduComposer", "Filenameheader added to part: " + new String(part.getFilename()));
+ appendOctet(PduPart.P_FILENAME);
+ appendTextString(part.getFilename());
+ }
+
// content id
byte[] contentId = part.getContentId();
diff --git a/src/ws/com/google/android/mms/pdu/PduParser.java b/src/ws/com/google/android/mms/pdu/PduParser.java
index f95e4a0ad1f46d56b3a9540534a7afe5501edd8c..fefbe3956e1a4ea39b54be0dbe9e5163d5270839 100644
--- a/src/ws/com/google/android/mms/pdu/PduParser.java
+++ b/src/ws/com/google/android/mms/pdu/PduParser.java
@@ -778,7 +778,7 @@ public class PduParser {
int partHeaderLen = headerLength - (startPos - endPos);
if (partHeaderLen > 0) {
if (false == parsePartHeaders(pduDataStream, part, partHeaderLen)) {
- // Parse part header faild.
+ // Parse part header failed.
return null;
}
} else if (partHeaderLen < 0) {
@@ -1618,6 +1618,13 @@ public class PduParser {
lastLen = length - (startPos - tempPos);
}
break;
+ case PduPart.P_FILENAME:
+ // filename
+ byte[] filename = parseWapString(pduDataStream, TYPE_TEXT_STRING);
+ if (null != filename) {
+ part.setFilename(filename);
+ }
+ break;
default:
if (LOCAL_LOGV) {
Log.v(LOG_TAG, "Not supported Part headers: " + header);