Significant MMS changes

1) Remove all our PDU code and switch to the PDU code from the
   klinker library

2) Switch to using the system Lollipop MMS library by default,
   and falling back to our own custom library if that fails.

3) Format SMIL differently, using code from klinker instead of
   what we've pieced together.

4) Pull per-carrier MMS media constraints from the XML config
   files in the klinker library, instead of hardcoding it at 280kb.

Hopefully this is an improvement, but given that MMS is involved,
it will probably make things worse instead.
master
Moxie Marlinspike 2017-05-08 15:32:59 -07:00
parent 165fae5734
commit 51d6144591
99 changed files with 530 additions and 11696 deletions

View File

@ -3,7 +3,7 @@
xmlns:tools="http://schemas.android.com/tools"
package="org.thoughtcrime.securesms">
<uses-sdk tools:overrideLibrary="com.amulyakhare.textdrawable,com.astuetz.pagerslidingtabstrip,pl.tajchert.waitingdots,com.h6ah4i.android.multiselectlistpreferencecompat,android.support.v13,com.davemorrissey.labs.subscaleview,com.tomergoldst.tooltips"/>
<uses-sdk tools:overrideLibrary="com.amulyakhare.textdrawable,com.astuetz.pagerslidingtabstrip,pl.tajchert.waitingdots,com.h6ah4i.android.multiselectlistpreferencecompat,android.support.v13,com.davemorrissey.labs.subscaleview,com.tomergoldst.tooltips,com.klinker.android.send_message"/>
<permission android:name="org.thoughtcrime.securesms.ACCESS_SECRETS"
android:label="Access to TextSecure Secrets"

View File

@ -96,6 +96,10 @@ dependencies {
compile ('com.tomergoldst.android:tooltips:1.0.6') {
exclude group: 'com.android.support', module: 'appcompat-v7'
}
compile ('com.klinkerapps:android-smsmms:4.0.1') {
exclude group: 'com.squareup.okhttp', module: 'okhttp'
exclude group: 'com.squareup.okhttp', module: 'okhttp-urlconnection'
}
testCompile 'junit:junit:4.12'
testCompile 'org.assertj:assertj-core:1.7.1'
@ -157,6 +161,7 @@ dependencyVerification {
'com.davemorrissey.labs:subsampling-scale-image-view:550c5baa07e0bb4ff0a18b705e96d34436d22619248bd8c08c08c730b1f55cfe',
'cn.carbswang.android:NumberPickerView:18b3c316d62c7c277978a8d4ed57a5b8f4e943762264960f579a8a549c756729',
'com.tomergoldst.android:tooltips:4c56697dd1ad64b8066535c61f961a6d901e7ae5d97ae27084ba40ad620349b6',
'com.klinkerapps:android-smsmms:e7c3328a0f3a8dd44daa8129de4e99996f3057a4546e47891b036b81e0ebf1d1',
'com.android.support:support-v4:ed4cda7c752f51d33f9bbdfff3422b425b323d356cd1bdc9786aa413c912e594',
'com.android.support:support-vector-drawable:2697503d3e8e709023ae176ba5db7f98ca0aa0b4e6290aedcb3c371904806bf7',
'com.android.support:animated-vector-drawable:6d05cb63d1f68900220f85c56dfe1066a9bb19cb0ec1247cc68fc2ba32f6b4a7',
@ -171,6 +176,7 @@ dependencyVerification {
'com.nineoldandroids:library:68025a14e3e7673d6ad2f95e4b46d78d7d068343aa99256b686fe59de1b3163a',
'javax.inject:javax.inject:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'com.madgag.spongycastle:core:8d6240b974b0aca4d3da9c7dd44d42339d8a374358aca5fc98e50a995764511f',
'com.klinkerapps:logger:177e325259a8b111ad6745ec10db5861723c99f402222b80629f576f49408541',
'com.google.android.gms:play-services-tasks:69ec265168e601d0203d04cd42e34bb019b2f029aa1e16fabd38a5153eea2086',
'org.whispersystems:curve25519-android:bf6c34223d45d2f2813a8efcab9923caf99115115c760c9acea680bcb42d23c0',
'org.whispersystems:signal-protocol-java:a835cd0609cf116a74651bd0aa748db9392bba48c2d2af787757b8a1b50d131c',

View File

@ -157,8 +157,6 @@ import java.security.SecureRandom;
import java.util.List;
import java.util.concurrent.ExecutionException;
import ws.com.google.android.mms.ContentType;
import static org.thoughtcrime.securesms.TransportOption.Type;
import static org.thoughtcrime.securesms.database.GroupDatabase.GroupRecord;
import static org.whispersystems.signalservice.internal.push.SignalServiceProtos.GroupContext;
@ -1407,8 +1405,8 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
private MediaConstraints getCurrentMediaConstraints() {
return sendButton.getSelectedTransport().getType() == Type.TEXTSECURE
? MediaConstraints.PUSH_CONSTRAINTS
: MediaConstraints.MMS_CONSTRAINTS;
? MediaConstraints.getPushMediaConstraints()
: MediaConstraints.getMmsMediaConstraints(sendButton.getSelectedTransport().getSimSubscriptionId().or(-1));
}
private void markThreadAsRead() {
@ -1607,7 +1605,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
@Override
public void onImageCapture(@NonNull final byte[] imageBytes) {
setMedia(PersistentBlobProvider.getInstance(this)
.create(masterSecret, imageBytes, ContentType.IMAGE_JPEG),
.create(masterSecret, imageBytes, MediaUtil.IMAGE_JPEG),
MediaType.IMAGE);
quickAttachmentDrawer.hide(false);
}
@ -1648,7 +1646,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
boolean forceSms = sendButton.isManualSelection() && sendButton.getSelectedTransport().isSms();
int subscriptionId = sendButton.getSelectedTransport().getSimSubscriptionId().or(-1);
long expiresIn = recipients.getExpireMessages() * 1000;
AudioSlide audioSlide = new AudioSlide(ConversationActivity.this, result.first, result.second, ContentType.AUDIO_AAC);
AudioSlide audioSlide = new AudioSlide(ConversationActivity.this, result.first, result.second, MediaUtil.AUDIO_AAC);
SlideDeck slideDeck = new SlideDeck();
slideDeck.addSlide(audioSlide);
@ -1719,11 +1717,11 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
public void onMediaSelected(@NonNull Uri uri, String contentType) {
if (!TextUtils.isEmpty(contentType) && contentType.trim().equals("image/gif")) {
setMedia(uri, MediaType.GIF);
} else if (ContentType.isImageType(contentType)) {
} else if (MediaUtil.isImageType(contentType)) {
setMedia(uri, MediaType.IMAGE);
} else if (ContentType.isVideoType(contentType)) {
} else if (MediaUtil.isVideoType(contentType)) {
setMedia(uri, MediaType.VIDEO);
} else if (ContentType.isAudioType(contentType)) {
} else if (MediaUtil.isAudioType(contentType)) {
setMedia(uri, MediaType.AUDIO);
}
}

View File

@ -20,8 +20,6 @@ import org.thoughtcrime.securesms.util.concurrent.SettableFuture;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import ws.com.google.android.mms.ContentType;
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public class AudioRecorder {
@ -58,7 +56,7 @@ public class AudioRecorder {
captureUri = blobProvider.create(masterSecret,
new ParcelFileDescriptor.AutoCloseInputStream(fds[0]),
ContentType.AUDIO_AAC);
MediaUtil.AUDIO_AAC);
audioCodec = new AudioCodec();
audioCodec.start(new ParcelFileDescriptor.AutoCloseOutputStream(fds[1]));

View File

@ -36,13 +36,13 @@ import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.attachments.Attachment;
import org.thoughtcrime.securesms.attachments.AttachmentId;
import org.thoughtcrime.securesms.attachments.DatabaseAttachment;
import org.thoughtcrime.securesms.crypto.AsymmetricMasterCipher;
import org.thoughtcrime.securesms.crypto.DecryptingPartInputStream;
import org.thoughtcrime.securesms.crypto.EncryptingPartOutputStream;
import org.thoughtcrime.securesms.crypto.MasterCipher;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.crypto.MasterSecretUnion;
import org.thoughtcrime.securesms.mms.MediaStream;
import org.thoughtcrime.securesms.mms.MmsException;
import org.thoughtcrime.securesms.mms.PartAuthority;
import org.thoughtcrime.securesms.util.MediaUtil;
import org.thoughtcrime.securesms.util.MediaUtil.ThumbnailData;
@ -50,8 +50,6 @@ import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.video.EncryptedMediaDataSource;
import org.whispersystems.libsignal.InvalidMessageException;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
@ -63,9 +61,6 @@ import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import ws.com.google.android.mms.ContentType;
import ws.com.google.android.mms.MmsException;
public class AttachmentDatabase extends Database {
private static final String TAG = AttachmentDatabase.class.getSimpleName();
@ -610,7 +605,7 @@ public class AttachmentDatabase extends Database {
ThumbnailData data;
if (ContentType.isVideoType(attachment.getContentType())) {
if (MediaUtil.isVideoType(attachment.getContentType())) {
data = generateVideoThumbnail(masterSecret, attachmentId);
} else{
data = MediaUtil.generateThumbnail(context, masterSecret, attachment.getContentType(), attachment.getDataUri());

View File

@ -17,15 +17,11 @@
package org.thoughtcrime.securesms.database;
import android.content.ContentValues;
import android.util.Log;
import com.google.android.mms.pdu_alt.EncodedStringValue;
import org.thoughtcrime.securesms.util.Util;
import ws.com.google.android.mms.pdu.CharacterSets;
import ws.com.google.android.mms.pdu.EncodedStringValue;
import java.io.UnsupportedEncodingException;
public class ContentValuesBuilder {
private final ContentValues contentValues;

View File

@ -33,6 +33,7 @@ import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.crypto.MasterSecretUtil;
import org.thoughtcrime.securesms.notifications.MessageNotifier;
import org.thoughtcrime.securesms.util.Base64;
import org.thoughtcrime.securesms.util.MediaUtil;
import org.thoughtcrime.securesms.util.Util;
import org.whispersystems.libsignal.IdentityKey;
import org.whispersystems.libsignal.InvalidMessageException;
@ -42,8 +43,6 @@ import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import ws.com.google.android.mms.ContentType;
public class DatabaseFactory {
private static final int INTRODUCED_IDENTITIES_VERSION = 2;
@ -381,7 +380,7 @@ public class DatabaseFactory {
while (partCursor != null && partCursor.moveToNext()) {
String contentType = partCursor.getString(partCursor.getColumnIndexOrThrow("ct"));
if (ContentType.isTextType(contentType)) {
if (MediaUtil.isTextType(contentType)) {
try {
long partId = partCursor.getLong(partCursor.getColumnIndexOrThrow("_id"));
String dataLocation = partCursor.getString(partCursor.getColumnIndexOrThrow("_data"));
@ -401,9 +400,9 @@ public class DatabaseFactory {
} catch (IOException e) {
Log.w("DatabaseFactory", e);
}
} else if (ContentType.isAudioType(contentType) ||
ContentType.isImageType(contentType) ||
ContentType.isVideoType(contentType))
} else if (MediaUtil.isAudioType(contentType) ||
MediaUtil.isImageType(contentType) ||
MediaUtil.isVideoType(contentType))
{
partCount++;
}

View File

@ -23,6 +23,8 @@ import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.support.annotation.NonNull;
import com.google.android.mms.pdu_alt.PduHeaders;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientFactory;
import org.thoughtcrime.securesms.recipients.Recipients;
@ -30,8 +32,6 @@ import org.thoughtcrime.securesms.recipients.Recipients;
import java.util.LinkedList;
import java.util.List;
import ws.com.google.android.mms.pdu.PduHeaders;
public class MmsAddressDatabase extends Database {
private static final String TAG = MmsAddressDatabase.class.getSimpleName();

View File

@ -19,7 +19,6 @@ package org.thoughtcrime.securesms.database;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.net.Uri;
@ -29,6 +28,8 @@ import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;
import com.google.android.mms.pdu_alt.NotificationInd;
import com.google.android.mms.pdu_alt.PduHeaders;
import com.google.i18n.phonenumbers.PhoneNumberUtil;
import org.thoughtcrime.securesms.ApplicationContext;
@ -77,9 +78,7 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import ws.com.google.android.mms.MmsException;
import ws.com.google.android.mms.pdu.NotificationInd;
import ws.com.google.android.mms.pdu.PduHeaders;
import org.thoughtcrime.securesms.mms.MmsException;
import static org.thoughtcrime.securesms.util.Util.canonicalizeNumber;
import static org.thoughtcrime.securesms.util.Util.canonicalizeNumberOrGroup;
@ -593,23 +592,16 @@ public class MmsDatabase extends MessagingDatabase {
return new Pair<>(messageId, threadId);
}
public Optional<Pair<NotificationInd, Integer>> getNotification(long messageId) {
public Optional<MmsNotificationInfo> getNotification(long messageId) {
Cursor cursor = null;
try {
cursor = rawQuery(RAW_ID_WHERE, new String[] {String.valueOf(messageId)});
if (cursor != null && cursor.moveToNext()) {
PduHeaders headers = new PduHeaders();
PduHeadersBuilder builder = new PduHeadersBuilder(headers, cursor);
builder.addText(CONTENT_LOCATION, PduHeaders.CONTENT_LOCATION);
builder.addLong(NORMALIZED_DATE_SENT, PduHeaders.DATE);
builder.addLong(EXPIRY, PduHeaders.EXPIRY);
builder.addLong(MESSAGE_SIZE, PduHeaders.MESSAGE_SIZE);
builder.addText(TRANSACTION_ID, PduHeaders.TRANSACTION_ID);
return Optional.of(new Pair<>(new NotificationInd(headers),
cursor.getInt(cursor.getColumnIndexOrThrow(SUBSCRIPTION_ID))));
return Optional.of(new MmsNotificationInfo(cursor.getString(cursor.getColumnIndexOrThrow(CONTENT_LOCATION)),
cursor.getString(cursor.getColumnIndexOrThrow(TRANSACTION_ID)),
cursor.getInt(cursor.getColumnIndexOrThrow(SUBSCRIPTION_ID))));
} else {
return Optional.absent();
}
@ -820,22 +812,21 @@ public class MmsDatabase extends MessagingDatabase {
SQLiteDatabase db = databaseHelper.getWritableDatabase();
MmsAddressDatabase addressDatabase = DatabaseFactory.getMmsAddressDatabase(context);
long threadId = getThreadIdFor(notification);
PduHeaders headers = notification.getPduHeaders();
ContentValues contentValues = new ContentValues();
ContentValuesBuilder contentBuilder = new ContentValuesBuilder(contentValues);
Log.w(TAG, "Message received type: " + notification.getMessageType());
Log.w(TAG, "Message received type: " + headers.getOctet(PduHeaders.MESSAGE_TYPE));
contentBuilder.add(CONTENT_LOCATION, headers.getTextString(PduHeaders.CONTENT_LOCATION));
contentBuilder.add(DATE_SENT, headers.getLongInteger(PduHeaders.DATE) * 1000L);
contentBuilder.add(EXPIRY, headers.getLongInteger(PduHeaders.EXPIRY));
contentBuilder.add(MESSAGE_SIZE, headers.getLongInteger(PduHeaders.MESSAGE_SIZE));
contentBuilder.add(TRANSACTION_ID, headers.getTextString(PduHeaders.TRANSACTION_ID));
contentBuilder.add(MESSAGE_TYPE, headers.getOctet(PduHeaders.MESSAGE_TYPE));
contentBuilder.add(CONTENT_LOCATION, notification.getContentLocation());
contentBuilder.add(DATE_SENT, System.currentTimeMillis());
contentBuilder.add(EXPIRY, notification.getExpiry());
contentBuilder.add(MESSAGE_SIZE, notification.getMessageSize());
contentBuilder.add(TRANSACTION_ID, notification.getTransactionId());
contentBuilder.add(MESSAGE_TYPE, notification.getMessageType());
if (headers.getEncodedStringValue(PduHeaders.FROM) != null) {
contentBuilder.add(ADDRESS, headers.getEncodedStringValue(PduHeaders.FROM).getTextString());
if (notification.getFrom() != null) {
contentBuilder.add(ADDRESS, notification.getFrom().getTextString());
} else {
contentBuilder.add(ADDRESS, null);
}
@ -852,7 +843,7 @@ public class MmsDatabase extends MessagingDatabase {
long messageId = db.insert(TABLE_NAME, null, contentValues);
if (headers.getEncodedStringValue(PduHeaders.FROM) != null) {
if (notification.getFrom() != null) {
addressDatabase.insertAddressesForId(messageId, MmsAddresses.forFrom(Util.toIsoString(notification.getFrom().getTextString())));
}
@ -1129,6 +1120,30 @@ public class MmsDatabase extends MessagingDatabase {
public static final int DOWNLOAD_APN_UNAVAILABLE = 6;
}
public static class MmsNotificationInfo {
private final String contentLocation;
private final String transactionId;
private final int subscriptionId;
public MmsNotificationInfo(String contentLocation, String transactionId, int subscriptionId) {
this.contentLocation = contentLocation;
this.transactionId = transactionId;
this.subscriptionId = subscriptionId;
}
public String getContentLocation() {
return contentLocation;
}
public String getTransactionId() {
return transactionId;
}
public int getSubscriptionId() {
return subscriptionId;
}
}
public class OutgoingMessageReader {
private final OutgoingMediaMessage message;

View File

@ -1,80 +0,0 @@
/**
* 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 <http://www.gnu.org/licenses/>.
*/
package org.thoughtcrime.securesms.database;
import android.database.Cursor;
import android.util.Log;
import ws.com.google.android.mms.InvalidHeaderValueException;
import ws.com.google.android.mms.pdu.CharacterSets;
import ws.com.google.android.mms.pdu.EncodedStringValue;
import ws.com.google.android.mms.pdu.PduHeaders;
import java.io.UnsupportedEncodingException;
public class PduHeadersBuilder {
private final PduHeaders headers;
private final Cursor cursor;
public PduHeadersBuilder(PduHeaders headers, Cursor cursor) {
this.headers = headers;
this.cursor = cursor;
}
public PduHeaders getHeaders() {
return headers;
}
public void addLong(String key, int headersKey) {
int columnIndex = cursor.getColumnIndexOrThrow(key);
if (!cursor.isNull(columnIndex))
headers.setLongInteger(cursor.getLong(columnIndex), headersKey);
}
public void addOctet(String key, int headersKey) throws InvalidHeaderValueException {
int columnIndex = cursor.getColumnIndexOrThrow(key);
if (!cursor.isNull(columnIndex))
headers.setOctet(cursor.getInt(columnIndex), headersKey);
}
public void addText(String key, int headersKey) {
String value = cursor.getString(cursor.getColumnIndexOrThrow(key));
if (value != null && value.trim().length() > 0)
headers.setTextString(getBytes(value), headersKey);
}
public void add(String key, String charsetKey, int headersKey) {
String value = cursor.getString(cursor.getColumnIndexOrThrow(key));
if (value != null && value.trim().length() > 0) {
int charsetValue = cursor.getInt(cursor.getColumnIndexOrThrow(charsetKey));
EncodedStringValue encodedValue = new EncodedStringValue(charsetValue, getBytes(value));
headers.setEncodedStringValue(encodedValue, headersKey);
}
}
private byte[] getBytes(String data) {
try {
return data.getBytes(CharacterSets.MIMENAME_ISO_8859_1);
} catch (UnsupportedEncodingException e) {
Log.e("PduHeadersBuilder", "ISO_8859_1 must be supported!", e);
return new byte[0];
}
}
}

View File

@ -1,108 +0,0 @@
/*
* Copyright (C) 2007 Esmertec AG.
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thoughtcrime.securesms.dom;
import org.w3c.dom.Attr;
import org.w3c.dom.DOMException;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.TypeInfo;
public class AttrImpl extends NodeImpl implements Attr {
private String mName;
private String mValue;
/*
* Internal methods
*/
protected AttrImpl(DocumentImpl owner, String name) {
super(owner);
mName = name;
}
/*
* Attr Interface Methods
*/
public String getName() {
return mName;
}
public Element getOwnerElement() {
// TODO Auto-generated method stub
return null;
}
public boolean getSpecified() {
return mValue != null;
}
public String getValue() {
return mValue;
}
// Instead of setting a <code>Text></code> with the content of the
// String value as defined in the specs, we directly set here the
// internal mValue member.
public void setValue(String value) throws DOMException {
mValue = value;
}
/*
* Node Interface Methods
*/
@Override
public String getNodeName() {
return mName;
}
@Override
public short getNodeType() {
return Node.ATTRIBUTE_NODE;
}
@Override
public Node getParentNode() {
return null;
}
@Override
public Node getPreviousSibling() {
return null;
}
@Override
public Node getNextSibling() {
return null;
}
@Override
public void setNodeValue(String nodeValue) throws DOMException {
setValue(nodeValue);
}
public TypeInfo getSchemaTypeInfo() {
return null;
}
public boolean isId() {
return false;
}
}

View File

@ -1,194 +0,0 @@
/*
* Copyright (C) 2007 Esmertec AG.
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thoughtcrime.securesms.dom;
import org.w3c.dom.Attr;
import org.w3c.dom.CDATASection;
import org.w3c.dom.Comment;
import org.w3c.dom.DOMConfiguration;
import org.w3c.dom.DOMException;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentFragment;
import org.w3c.dom.DocumentType;
import org.w3c.dom.Element;
import org.w3c.dom.EntityReference;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.ProcessingInstruction;
import org.w3c.dom.Text;
public abstract class DocumentImpl extends NodeImpl implements Document {
/*
* Internal methods
*/
public DocumentImpl() {
super(null);
}
/*
* Document Interface Methods
*/
public Attr createAttribute(String name) throws DOMException {
return new AttrImpl(this, name);
}
public Attr createAttributeNS(String namespaceURI, String qualifiedName)
throws DOMException {
// TODO Auto-generated method stub
return null;
}
public CDATASection createCDATASection(String data) throws DOMException {
// TODO Auto-generated method stub
return null;
}
public Comment createComment(String data) {
// TODO Auto-generated method stub
return null;
}
public DocumentFragment createDocumentFragment() {
// TODO Auto-generated method stub
return null;
}
public abstract Element createElement(String tagName) throws DOMException;
public Element createElementNS(String namespaceURI, String qualifiedName)
throws DOMException {
// TODO Auto-generated method stub
return null;
}
public EntityReference createEntityReference(String name) throws DOMException {
// TODO Auto-generated method stub
return null;
}
public ProcessingInstruction createProcessingInstruction(String target, String data)
throws DOMException {
// TODO Auto-generated method stub
return null;
}
public Text createTextNode(String data) {
// TODO Auto-generated method stub
return null;
}
public DocumentType getDoctype() {
// TODO Auto-generated method stub
return null;
}
public abstract Element getDocumentElement();
public Element getElementById(String elementId) {
// TODO Auto-generated method stub
return null;
}
public NodeList getElementsByTagName(String tagname) {
// TODO Auto-generated method stub
return null;
}
public NodeList getElementsByTagNameNS(String namespaceURI, String localName) {
// TODO Auto-generated method stub
return null;
}
public DOMImplementation getImplementation() {
// TODO Auto-generated method stub
return null;
}
public Node importNode(Node importedNode, boolean deep) throws DOMException {
// TODO Auto-generated method stub
return null;
}
/*
* Node Interface methods
*/
@Override
public short getNodeType() {
return Node.DOCUMENT_NODE;
}
@Override
public String getNodeName() {
// The value of nodeName is "#document" when Node is a Document
return "#document";
}
public String getInputEncoding() {
return null;
}
public String getXmlEncoding() {
return null;
}
public boolean getXmlStandalone() {
return false;
}
public void setXmlStandalone(boolean xmlStandalone) throws DOMException {}
public String getXmlVersion() {
return null;
}
public void setXmlVersion(String xmlVersion) throws DOMException {}
public boolean getStrictErrorChecking() {
return true;
}
public void setStrictErrorChecking(boolean strictErrorChecking) {}
public String getDocumentURI() {
return null;
}
public void setDocumentURI(String documentURI) {}
public Node adoptNode(Node source) throws DOMException {
throw new DOMException(DOMException.NOT_SUPPORTED_ERR, null);
}
public DOMConfiguration getDomConfig() {
throw new DOMException(DOMException.NOT_SUPPORTED_ERR, null);
}
public void normalizeDocument() {
throw new DOMException(DOMException.NOT_SUPPORTED_ERR, null);
}
public Node renameNode(Node n, String namespaceURI, String qualifiedName)
throws DOMException {
throw new DOMException(DOMException.NOT_SUPPORTED_ERR, null);
}
}

View File

@ -1,172 +0,0 @@
/*
* Copyright (C) 2007 Esmertec AG.
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thoughtcrime.securesms.dom;
import org.w3c.dom.Attr;
import org.w3c.dom.DOMException;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.NodeList;
import org.w3c.dom.TypeInfo;
public class ElementImpl extends NodeImpl implements Element {
private String mTagName;
private NamedNodeMap mAttributes = new NamedNodeMapImpl();
/*
* Internal methods
*/
protected ElementImpl(DocumentImpl owner, String tagName) {
super(owner);
mTagName = tagName;
}
/*
* Element Interface methods
*/
public String getAttribute(String name) {
Attr attrNode = getAttributeNode(name);
String attrValue = "";
if (attrNode != null) {
attrValue = attrNode.getValue();
}
return attrValue;
}
public String getAttributeNS(String namespaceURI, String localName) {
// TODO Auto-generated method stub
return null;
}
public Attr getAttributeNode(String name) {
return (Attr)mAttributes.getNamedItem(name);
}
public Attr getAttributeNodeNS(String namespaceURI, String localName) {
// TODO Auto-generated method stub
return null;
}
public NodeList getElementsByTagName(String name) {
return new NodeListImpl(this, name, true);
}
public NodeList getElementsByTagNameNS(String namespaceURI, String localName) {
// TODO Auto-generated method stub
return null;
}
public String getTagName() {
return mTagName;
}
public boolean hasAttribute(String name) {
return (getAttributeNode(name) != null);
}
public boolean hasAttributeNS(String namespaceURI, String localName) {
// TODO Auto-generated method stub
return false;
}
public void removeAttribute(String name) throws DOMException {
// TODO Auto-generated method stub
}
public void removeAttributeNS(String namespaceURI, String localName)
throws DOMException {
// TODO Auto-generated method stub
}
public Attr removeAttributeNode(Attr oldAttr) throws DOMException {
// TODO Auto-generated method stub
return null;
}
public void setAttribute(String name, String value) throws DOMException {
Attr attribute = getAttributeNode(name);
if (attribute == null) {
attribute = mOwnerDocument.createAttribute(name);
}
attribute.setNodeValue(value);
mAttributes.setNamedItem(attribute);
}
public void setAttributeNS(String namespaceURI, String qualifiedName,
String value) throws DOMException {
// TODO Auto-generated method stub
}
public Attr setAttributeNode(Attr newAttr) throws DOMException {
// TODO Auto-generated method stub
return null;
}
public Attr setAttributeNodeNS(Attr newAttr) throws DOMException {
// TODO Auto-generated method stub
return null;
}
/*
* Node Interface methods
*/
@Override
public short getNodeType() {
return ELEMENT_NODE;
}
@Override
public String getNodeName() {
// The value of nodeName is tagName when Node is an Element
return mTagName;
}
@Override
public NamedNodeMap getAttributes() {
return mAttributes;
}
@Override
public boolean hasAttributes() {
return (mAttributes.getLength() > 0);
}
public TypeInfo getSchemaTypeInfo() {
return null;
}
public void setIdAttribute(String name, boolean isId) throws DOMException {
throw new DOMException(DOMException.NOT_SUPPORTED_ERR, null);
}
public void setIdAttributeNS(String namespaceURI, String localName,
boolean isId) throws DOMException {
throw new DOMException(DOMException.NOT_SUPPORTED_ERR, null);
}
public void setIdAttributeNode(Attr idAttr, boolean isId)
throws DOMException {
throw new DOMException(DOMException.NOT_SUPPORTED_ERR, null);
}
}

View File

@ -1,87 +0,0 @@
/*
* Copyright (C) 2007 Esmertec AG.
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thoughtcrime.securesms.dom;
import java.util.Vector;
import org.w3c.dom.DOMException;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
public class NamedNodeMapImpl implements NamedNodeMap {
private Vector<Node> mNodes = new Vector<Node>();
public int getLength() {
return mNodes.size();
}
public Node getNamedItem(String name) {
Node node = null;
for (int i = 0; i < mNodes.size(); i++) {
if (name.equals(mNodes.elementAt(i).getNodeName())) {
node = mNodes.elementAt(i);
break;
}
}
return node;
}
public Node getNamedItemNS(String namespaceURI, String localName) {
// TODO Auto-generated method stub
return null;
}
public Node item(int index) {
if (index < mNodes.size()) {
return mNodes.elementAt(index);
}
return null;
}
public Node removeNamedItem(String name) throws DOMException {
Node node = getNamedItem(name);
if (node == null) {
throw new DOMException(DOMException.NOT_FOUND_ERR, "Not found");
} else {
mNodes.remove(node);
}
return node;
}
public Node removeNamedItemNS(String namespaceURI, String localName)
throws DOMException {
// TODO Auto-generated method stub
return null;
}
public Node setNamedItem(Node arg) throws DOMException {
Node existing = getNamedItem(arg.getNodeName());
if (existing != null) {
mNodes.remove(existing);
}
mNodes.add(arg);
return existing;
}
public Node setNamedItemNS(Node arg) throws DOMException {
// TODO Auto-generated method stub
return null;
}
}

View File

@ -1,273 +0,0 @@
/*
* Copyright (C) 2007 Esmertec AG.
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thoughtcrime.securesms.dom;
import java.util.NoSuchElementException;
import java.util.Vector;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.UserDataHandler;
import org.w3c.dom.events.Event;
import org.w3c.dom.events.EventException;
import org.w3c.dom.events.EventListener;
import org.w3c.dom.events.EventTarget;
import org.thoughtcrime.securesms.dom.events.EventTargetImpl;
public abstract class NodeImpl implements Node, EventTarget {
private Node mParentNode;
private final Vector<Node> mChildNodes = new Vector<Node>();
DocumentImpl mOwnerDocument;
private final EventTarget mEventTarget = new EventTargetImpl(this);
/*
* Internal methods
*/
protected NodeImpl(DocumentImpl owner) {
mOwnerDocument = owner;
}
/*
* Node Interface Methods
*/
public Node appendChild(Node newChild) throws DOMException {
((NodeImpl)newChild).setParentNode(this);
mChildNodes.remove(newChild);
mChildNodes.add(newChild);
return newChild;
}
public Node cloneNode(boolean deep) {
// TODO Auto-generated method stub
return null;
}
public NamedNodeMap getAttributes() {
// Default. Override in Element.
return null;
}
public NodeList getChildNodes() {
return new NodeListImpl(this, null, false);
}
public Node getFirstChild() {
Node firstChild = null;
try {
firstChild = mChildNodes.firstElement();
}
catch (NoSuchElementException e) {
// Ignore and return null
}
return firstChild;
}
public Node getLastChild() {
Node lastChild = null;
try {
lastChild = mChildNodes.lastElement();
}
catch (NoSuchElementException e) {
// Ignore and return null
}
return lastChild;
}
public String getLocalName() {
// TODO Auto-generated method stub
return null;
}
public String getNamespaceURI() {
// TODO Auto-generated method stub
return null;
}
public Node getNextSibling() {
if ((mParentNode != null) && (this != mParentNode.getLastChild())) {
Vector<Node> siblings = ((NodeImpl)mParentNode).mChildNodes;
int indexOfThis = siblings.indexOf(this);
return siblings.elementAt(indexOfThis + 1);
}
return null;
}
public abstract String getNodeName();
public abstract short getNodeType();
public String getNodeValue() throws DOMException {
// Default behaviour. Override if required.
return null;
}
public Document getOwnerDocument() {
return mOwnerDocument;
}
public Node getParentNode() {
return mParentNode;
}
public String getPrefix() {
// TODO Auto-generated method stub
return null;
}
public Node getPreviousSibling() {
if ((mParentNode != null) && (this != mParentNode.getFirstChild())) {
Vector<Node> siblings = ((NodeImpl)mParentNode).mChildNodes;
int indexOfThis = siblings.indexOf(this);
return siblings.elementAt(indexOfThis - 1);
}
return null;
}
public boolean hasAttributes() {
// Default. Override in Element.
return false;
}
public boolean hasChildNodes() {
return !(mChildNodes.isEmpty());
}
public Node insertBefore(Node newChild, Node refChild) throws DOMException {
// TODO Auto-generated method stub
return null;
}
public boolean isSupported(String feature, String version) {
// TODO Auto-generated method stub
return false;
}
public void normalize() {
// TODO Auto-generated method stub
}
public Node removeChild(Node oldChild) throws DOMException {
if (mChildNodes.contains(oldChild)) {
mChildNodes.remove(oldChild);
((NodeImpl)oldChild).setParentNode(null);
} else {
throw new DOMException(DOMException.NOT_FOUND_ERR, "Child does not exist");
}
return null;
}
public Node replaceChild(Node newChild, Node oldChild) throws DOMException {
if (mChildNodes.contains(oldChild)) {
// Try to remove the new child if available
try {
mChildNodes.remove(newChild);
} catch (DOMException e) {
// Ignore exception
}
mChildNodes.setElementAt(newChild, mChildNodes.indexOf(oldChild));
((NodeImpl)newChild).setParentNode(this);
((NodeImpl)oldChild).setParentNode(null);
} else {
throw new DOMException(DOMException.NOT_FOUND_ERR, "Old child does not exist");
}
return oldChild;
}
public void setNodeValue(String nodeValue) throws DOMException {
// Default behaviour. Override if required.
}
public void setPrefix(String prefix) throws DOMException {
// TODO Auto-generated method stub
}
private void setParentNode(Node parentNode) {
mParentNode = parentNode;
}
/*
* EventTarget Interface
*/
public void addEventListener(String type, EventListener listener, boolean useCapture) {
mEventTarget.addEventListener(type, listener, useCapture);
}
public void removeEventListener(String type, EventListener listener, boolean useCapture) {
mEventTarget.removeEventListener(type, listener, useCapture);
}
public boolean dispatchEvent(Event evt) throws EventException {
return mEventTarget.dispatchEvent(evt);
}
public String getBaseURI() {
return null;
}
public short compareDocumentPosition(Node other) throws DOMException {
throw new DOMException(DOMException.NOT_SUPPORTED_ERR, null);
}
public String getTextContent() throws DOMException {
throw new DOMException(DOMException.NOT_SUPPORTED_ERR, null);
}
public void setTextContent(String textContent) throws DOMException {
throw new DOMException(DOMException.NOT_SUPPORTED_ERR, null);
}
public boolean isSameNode(Node other) {
throw new DOMException(DOMException.NOT_SUPPORTED_ERR, null);
}
public String lookupPrefix(String namespaceURI) {
return null;
}
public boolean isDefaultNamespace(String namespaceURI) {
throw new DOMException(DOMException.NOT_SUPPORTED_ERR, null);
}
public String lookupNamespaceURI(String prefix) {
return null;
}
public boolean isEqualNode(Node arg) {
throw new DOMException(DOMException.NOT_SUPPORTED_ERR, null);
}
public Object getFeature(String feature, String version) {
return null;
}
public Object setUserData(String key, Object data,
UserDataHandler handler) {
throw new DOMException(DOMException.NOT_SUPPORTED_ERR, null);
}
public Object getUserData(String key) {
return null;
}
}

View File

@ -1,128 +0,0 @@
/*
* Copyright (C) 2007 Esmertec AG.
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thoughtcrime.securesms.dom;
import java.util.ArrayList;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class NodeListImpl implements NodeList {
private ArrayList<Node> mSearchNodes;
private ArrayList<Node> mStaticNodes;
private Node mRootNode;
private String mTagName;
private boolean mDeepSearch;
/*
* Internal Interface
*/
/**
* Constructs a NodeList by searching for all descendants or the direct
* children of a root node with a given tag name.
* @param rootNode The root <code>Node</code> of the search.
* @param tagName The tag name to be searched for. If null, all descendants
* will be returned.
* @param deep Limit the search to the direct children of rootNode if false,
* to all descendants otherwise.
*/
public NodeListImpl(Node rootNode, String tagName, boolean deepSearch) {
mRootNode = rootNode;
mTagName = tagName;
mDeepSearch = deepSearch;
}
/**
* Constructs a NodeList for a given static node list.
* @param nodes The static node list.
*/
public NodeListImpl(ArrayList<Node> nodes) {
mStaticNodes = nodes;
}
/*
* NodeListImpl Interface
*/
public int getLength() {
if (mStaticNodes == null) {
fillList(mRootNode);
return mSearchNodes.size();
} else {
return mStaticNodes.size();
}
}
public Node item(int index) {
Node node = null;
if (mStaticNodes == null) {
fillList(mRootNode);
try {
node = mSearchNodes.get(index);
} catch (IndexOutOfBoundsException e) {
// Do nothing and return null
}
} else {
try {
node = mStaticNodes.get(index);
} catch (IndexOutOfBoundsException e) {
// Do nothing and return null
}
}
return node;
}
/**
* A preorder traversal is done in the following order:
* <ul>
* <li> Visit root.
* <li> Traverse children from left to right in preorder.
* </ul>
* This method fills the live node list.
* @param The root of preorder traversal
* @return The next match
*/
private void fillList(Node node) {
// (Re)-initialize the container if this is the start of the search.
// Visit the root of this iteration otherwise.
if (node == mRootNode) {
mSearchNodes = new ArrayList<Node>();
} else {
if ((mTagName == null) || node.getNodeName().equals(mTagName)) {
mSearchNodes.add(node);
}
}
// Descend one generation...
node = node.getFirstChild();
// ...and visit in preorder the children if we are in deep search
// or directly add the children to the list otherwise.
while (node != null) {
if (mDeepSearch) {
fillList(node);
} else {
if ((mTagName == null) || node.getNodeName().equals(mTagName)) {
mSearchNodes.add(node);
}
}
node = node.getNextSibling();
}
}
}

View File

@ -1,127 +0,0 @@
/*
* Copyright (C) 2007 Esmertec AG.
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thoughtcrime.securesms.dom.events;
import org.w3c.dom.events.Event;
import org.w3c.dom.events.EventTarget;
public class EventImpl implements Event {
// Event type informations
private String mEventType;
private boolean mCanBubble;
private boolean mCancelable;
// Flags whether the event type information was set
// FIXME: Can we use mEventType for this purpose?
private boolean mInitialized;
// Target of this event
private EventTarget mTarget;
// Event status variables
private short mEventPhase;
private boolean mStopPropagation;
private boolean mPreventDefault;
private EventTarget mCurrentTarget;
private int mSeekTo;
private final long mTimeStamp = System.currentTimeMillis();
public boolean getBubbles() {
return mCanBubble;
}
public boolean getCancelable() {
return mCancelable;
}
public EventTarget getCurrentTarget() {
return mCurrentTarget;
}
public short getEventPhase() {
return mEventPhase;
}
public EventTarget getTarget() {
return mTarget;
}
public long getTimeStamp() {
return mTimeStamp;
}
public String getType() {
return mEventType;
}
public void initEvent(String eventTypeArg, boolean canBubbleArg,
boolean cancelableArg) {
mEventType = eventTypeArg;
mCanBubble = canBubbleArg;
mCancelable = cancelableArg;
mInitialized = true;
}
public void initEvent(String eventTypeArg, boolean canBubbleArg, boolean cancelableArg,
int seekTo) {
mSeekTo = seekTo;
initEvent(eventTypeArg, canBubbleArg, cancelableArg);
}
public void preventDefault() {
mPreventDefault = true;
}
public void stopPropagation() {
mStopPropagation = true;
}
/*
* Internal Interface
*/
boolean isInitialized() {
return mInitialized;
}
boolean isPreventDefault() {
return mPreventDefault;
}
boolean isPropogationStopped() {
return mStopPropagation;
}
void setTarget(EventTarget target) {
mTarget = target;
}
void setEventPhase(short eventPhase) {
mEventPhase = eventPhase;
}
void setCurrentTarget(EventTarget currentTarget) {
mCurrentTarget = currentTarget;
}
public int getSeekTo() {
return mSeekTo;
}
}

View File

@ -1,131 +0,0 @@
/*
* Copyright (C) 2007 Esmertec AG.
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thoughtcrime.securesms.dom.events;
import java.util.ArrayList;
import org.w3c.dom.events.Event;
import org.w3c.dom.events.EventException;
import org.w3c.dom.events.EventListener;
import org.w3c.dom.events.EventTarget;
import android.util.Log;
public class EventTargetImpl implements EventTarget {
private static final String TAG = "EventTargetImpl";
private ArrayList<EventListenerEntry> mListenerEntries;
private EventTarget mNodeTarget;
static class EventListenerEntry
{
final String mType;
final EventListener mListener;
final boolean mUseCapture;
EventListenerEntry(String type, EventListener listener, boolean useCapture)
{
mType = type;
mListener = listener;
mUseCapture = useCapture;
}
}
public EventTargetImpl(EventTarget target) {
mNodeTarget = target;
}
public void addEventListener(String type, EventListener listener, boolean useCapture) {
if ((type == null) || type.equals("") || (listener == null)) {
return;
}
// Make sure we have only one entry
removeEventListener(type, listener, useCapture);
if (mListenerEntries == null) {
mListenerEntries = new ArrayList<EventListenerEntry>();
}
mListenerEntries.add(new EventListenerEntry(type, listener, useCapture));
}
public boolean dispatchEvent(Event evt) throws EventException {
// We need to use the internal APIs to modify and access the event status
EventImpl eventImpl = (EventImpl)evt;
if (!eventImpl.isInitialized()) {
throw new EventException(EventException.UNSPECIFIED_EVENT_TYPE_ERR,
"Event not initialized");
} else if ((eventImpl.getType() == null) || eventImpl.getType().equals("")) {
throw new EventException(EventException.UNSPECIFIED_EVENT_TYPE_ERR,
"Unspecified even type");
}
// Initialize event status
eventImpl.setTarget(mNodeTarget);
// TODO: At this point, to support event capturing and bubbling, we should
// establish the chain of EventTargets from the top of the tree to this
// event's target.
// TODO: CAPTURING_PHASE skipped
// Handle AT_TARGET
// Invoke handleEvent of non-capturing listeners on this EventTarget.
eventImpl.setEventPhase(Event.AT_TARGET);
eventImpl.setCurrentTarget(mNodeTarget);
if (!eventImpl.isPropogationStopped() && (mListenerEntries != null)) {
for (int i = 0; i < mListenerEntries.size(); i++) {
EventListenerEntry listenerEntry = mListenerEntries.get(i);
if (!listenerEntry.mUseCapture
&& listenerEntry.mType.equals(eventImpl.getType())) {
try {
listenerEntry.mListener.handleEvent(eventImpl);
}
catch (Exception e) {
// Any exceptions thrown inside an EventListener will
// not stop propagation of the event
Log.w(TAG, "Catched EventListener exception", e);
}
}
}
}
if (eventImpl.getBubbles()) {
// TODO: BUBBLING_PHASE skipped
}
return eventImpl.isPreventDefault();
}
public void removeEventListener(String type, EventListener listener,
boolean useCapture) {
if (null == mListenerEntries) {
return;
}
for (int i = 0; i < mListenerEntries.size(); i ++) {
EventListenerEntry listenerEntry = mListenerEntries.get(i);
if ((listenerEntry.mUseCapture == useCapture)
&& (listenerEntry.mListener == listener)
&& listenerEntry.mType.equals(type)) {
mListenerEntries.remove(i);
break;
}
}
}
}

View File

@ -1,155 +0,0 @@
/*
* Copyright (C) 2007-2008 Esmertec AG.
* Copyright (C) 2007-2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thoughtcrime.securesms.dom.smil;
import java.util.ArrayList;
import org.w3c.dom.DOMException;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.smil.ElementParallelTimeContainer;
import org.w3c.dom.smil.ElementTime;
import org.w3c.dom.smil.SMILElement;
import org.w3c.dom.smil.Time;
import org.w3c.dom.smil.TimeList;
import org.thoughtcrime.securesms.dom.NodeListImpl;
public abstract class ElementParallelTimeContainerImpl extends ElementTimeContainerImpl
implements ElementParallelTimeContainer {
private final static String ENDSYNC_ATTRIBUTE_NAME = "endsync";
private final static String ENDSYNC_FIRST = "first";
private final static String ENDSYNC_LAST = "last";
private final static String ENDSYNC_ALL = "all";
private final static String ENDSYNC_MEDIA = "media";
/*
* Internal Interface
*/
ElementParallelTimeContainerImpl(SMILElement element) {
super(element);
}
public String getEndSync() {
String endsync = mSmilElement.getAttribute(ENDSYNC_ATTRIBUTE_NAME);
if ((endsync == null) || (endsync.length() == 0)) {
setEndSync(ENDSYNC_LAST);
return ENDSYNC_LAST;
}
if (ENDSYNC_FIRST.equals(endsync) || ENDSYNC_LAST.equals(endsync) ||
ENDSYNC_ALL.equals(endsync) || ENDSYNC_MEDIA.equals(endsync)) {
return endsync;
}
// FIXME add the checking for ID-Value and smil1.0-Id-value.
setEndSync(ENDSYNC_LAST);
return ENDSYNC_LAST;
}
public void setEndSync(String endSync) throws DOMException {
if (ENDSYNC_FIRST.equals(endSync) || ENDSYNC_LAST.equals(endSync) ||
ENDSYNC_ALL.equals(endSync) || ENDSYNC_MEDIA.equals(endSync)) {
mSmilElement.setAttribute(ENDSYNC_ATTRIBUTE_NAME, endSync);
} else { // FIXME add the support for ID-Value and smil1.0-Id-value.
throw new DOMException(DOMException.NOT_SUPPORTED_ERR,
"Unsupported endsync value" + endSync);
}
}
@Override
public float getDur() {
float dur = super.getDur();
if (dur == 0) {
dur = getImplicitDuration();
}
return dur;
}
public float getImplicitDuration() {
float dur = -1.0F;
if (ENDSYNC_LAST.equals(getEndSync())) {
NodeList children = getTimeChildren();
for (int i = 0; i < children.getLength(); ++i) {
ElementTime child = (ElementTime) children.item(i);
TimeList endTimeList = child.getEnd();
for (int j = 0; j < endTimeList.getLength(); ++j) {
Time endTime = endTimeList.item(j);
if (endTime.getTimeType() == Time.SMIL_TIME_INDEFINITE) {
// Return "indefinite" here.
return -1.0F;
}
if (endTime.getResolved()) {
float end = (float)endTime.getResolvedOffset();
dur = (end > dur) ? end : dur;
}
}
}
} // Other endsync types are not supported now.
return dur;
}
public NodeList getActiveChildrenAt(float instant) {
/*
* Find the closest Time of ElementTime before instant.
* Add ElementTime to list of active elements if the Time belongs to the begin-list,
* do not add it otherwise.
*/
ArrayList<Node> activeChildren = new ArrayList<Node>();
NodeList children = getTimeChildren();
int childrenLen = children.getLength();
for (int i = 0; i < childrenLen; ++i) {
double maxOffset = 0.0;
boolean active = false;
ElementTime child = (ElementTime) children.item(i);
TimeList beginList = child.getBegin();
int len = beginList.getLength();
for (int j = 0; j < len; ++j) {
Time begin = beginList.item(j);
if (begin.getResolved()) {
double resolvedOffset = begin.getResolvedOffset() * 1000.0;
if ((resolvedOffset <= instant) && (resolvedOffset >= maxOffset)) {
maxOffset = resolvedOffset;
active = true;
}
}
}
TimeList endList = child.getEnd();
len = endList.getLength();
for (int j = 0; j < len; ++j) {
Time end = endList.item(j);
if (end.getResolved()) {
double resolvedOffset = end.getResolvedOffset() * 1000.0;
if ((resolvedOffset <= instant) && (resolvedOffset >= maxOffset)) {
maxOffset = resolvedOffset;
active = false;
}
}
}
if (active) {
activeChildren.add((Node) child);
}
}
return new NodeListImpl(activeChildren);
}
}

View File

@ -1,73 +0,0 @@
/*
* Copyright (C) 2007 Esmertec AG.
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thoughtcrime.securesms.dom.smil;
import java.util.ArrayList;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.smil.ElementSequentialTimeContainer;
import org.w3c.dom.smil.ElementTime;
import org.w3c.dom.smil.SMILElement;
import org.thoughtcrime.securesms.dom.NodeListImpl;
public abstract class ElementSequentialTimeContainerImpl extends
ElementTimeContainerImpl implements ElementSequentialTimeContainer {
/*
* Internal Interface
*/
ElementSequentialTimeContainerImpl(SMILElement element) {
super(element);
}
/*
* ElementSequentialTimeContainer Interface
*/
public NodeList getActiveChildrenAt(float instant) {
NodeList allChildren = this.getTimeChildren();
ArrayList<Node> nodes = new ArrayList<Node>();
for (int i = 0; i < allChildren.getLength(); i++) {
instant -= ((ElementTime) allChildren.item(i)).getDur();
if (instant < 0) {
nodes.add(allChildren.item(i));
return new NodeListImpl(nodes);
}
}
return new NodeListImpl(nodes);
}
public float getDur() {
float dur = super.getDur();
if (dur == 0) {
NodeList children = getTimeChildren();
for (int i = 0; i < children.getLength(); ++i) {
ElementTime child = (ElementTime) children.item(i);
if (child.getDur() < 0) {
// Return "indefinite" since containing a child whose duration is indefinite.
return -1.0F;
}
dur += child.getDur();
}
}
return dur;
}
}

View File

@ -1,33 +0,0 @@
/*
* Copyright (C) 2007 Esmertec AG.
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thoughtcrime.securesms.dom.smil;
import org.w3c.dom.smil.ElementTimeContainer;
import org.w3c.dom.smil.SMILElement;
public abstract class ElementTimeContainerImpl extends ElementTimeImpl implements
ElementTimeContainer {
/*
* Internal Interface
*/
ElementTimeContainerImpl(SMILElement element) {
super(element);
}
}

View File

@ -1,348 +0,0 @@
/*
* Copyright (C) 2007-2008 Esmertec AG.
* Copyright (C) 2007-2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thoughtcrime.securesms.dom.smil;
import java.util.ArrayList;
import org.w3c.dom.DOMException;
import org.w3c.dom.smil.ElementTime;
import org.w3c.dom.smil.SMILElement;
import org.w3c.dom.smil.Time;
import org.w3c.dom.smil.TimeList;
import android.util.Log;
public abstract class ElementTimeImpl implements ElementTime {
private static final String TAG = "ElementTimeImpl";
private static final String FILL_REMOVE_ATTRIBUTE = "remove";
private static final String FILL_FREEZE_ATTRIBUTE = "freeze";
private static final String FILL_HOLD_ATTRIBUTE = "hold";
private static final String FILL_TRANSITION_ATTRIBUTE = "transition";
private static final String FILL_AUTO_ATTRIBUTE = "auto";
private static final String FILL_ATTRIBUTE_NAME = "fill";
private static final String FILLDEFAULT_ATTRIBUTE_NAME = "fillDefault";
final SMILElement mSmilElement;
/*
* Internal Interface
*/
ElementTimeImpl(SMILElement element) {
mSmilElement = element;
}
// Default implementation. Override if required.
int getBeginConstraints() {
return TimeImpl.ALLOW_ALL;
}
// Default implementation. Override if required
int getEndConstraints() {
return TimeImpl.ALLOW_ALL;
}
/**
* To get the parent node on the ElementTime tree. It is in opposition to getTimeChildren.
* @return the parent ElementTime. Returns <code>null</code> if there is no parent.
*/
abstract ElementTime getParentElementTime();
/*
* ElementTime Interface
*/
public TimeList getBegin() {
String[] beginTimeStringList = mSmilElement.getAttribute("begin").split(";");
// TODO: Check other constraints on parsed values, e.g., "single, non-negative offset values
ArrayList<Time> beginTimeList = new ArrayList<Time>();
// Initialize Time instances and add them to Vector
for (int i = 0; i < beginTimeStringList.length; i++) {
try {
beginTimeList.add(new TimeImpl(beginTimeStringList[i], getBeginConstraints()));
} catch (IllegalArgumentException e) {
// Ignore badly formatted times
}
}
if (beginTimeList.size() == 0) {
/*
* What is the right default value?
*
* In MMS SMIL, this method may be called either on an instance of:
*
* 1 - ElementSequentialTimeContainer (The SMILDocument)
* 2 - ElementParallelTimeContainer (A Time-Child of the SMILDocument, which is a seq)
* 3 - ElementTime (A SMILMediaElement).
*
* 1 - In the first case, the default start time is obviously 0.
* 2 - In the second case, the specifications mentions that
* "For children of a sequence, the only legal value for begin is
* a (single) non-negative offset value. The default begin value is 0."
* 3 - In the third case, the specification mentions that
* "The default value of begin for children of a par is 0."
*
* In short, if no value is specified, the default is always 0.
*/
beginTimeList.add(new TimeImpl("0", TimeImpl.ALLOW_ALL));
}
return new TimeListImpl(beginTimeList);
}
public float getDur() {
float dur = 0;
try {
String durString = mSmilElement.getAttribute("dur");
if (durString != null) {
dur = TimeImpl.parseClockValue(durString) / 1000f;
}
} catch (IllegalArgumentException e) {
// Do nothing and return the minimum value
}
return dur;
}
public TimeList getEnd() {
ArrayList<Time> endTimeList = new ArrayList<Time>();
String[] endTimeStringList = mSmilElement.getAttribute("end").split(";");
int len = endTimeStringList.length;
if (!((len == 1) && (endTimeStringList[0].length() == 0))) { // Ensure the end field is set.
// Initialize Time instances and add them to Vector
for (int i = 0; i < len; i++) {
try {
endTimeList.add(new TimeImpl(endTimeStringList[i],
getEndConstraints()));
} catch (IllegalArgumentException e) {
// Ignore badly formatted times
Log.e(TAG, "Malformed time value.", e);
}
}
}
// "end" time is not specified
if (endTimeList.size() == 0) {
// Get duration
float duration = getDur();
if (duration < 0) {
endTimeList.add(new TimeImpl("indefinite", getEndConstraints()));
} else {
// Get begin
TimeList begin = getBegin();
for (int i = 0; i < begin.getLength(); i++) {
endTimeList.add(new TimeImpl(
// end = begin + dur
begin.item(i).getResolvedOffset() + duration + "s",
getEndConstraints()));
}
}
}
return new TimeListImpl(endTimeList);
}
private boolean beginAndEndAreZero() {
TimeList begin = getBegin();
TimeList end = getEnd();
if (begin.getLength() == 1 && end.getLength() == 1) {
Time beginTime = begin.item(0);
Time endTime = end.item(0);
return beginTime.getOffset() == 0. && endTime.getOffset() == 0.;
}
return false;
}
public short getFill() {
String fill = mSmilElement.getAttribute(FILL_ATTRIBUTE_NAME);
if (fill.equalsIgnoreCase(FILL_FREEZE_ATTRIBUTE)) {
return FILL_FREEZE;
} else if (fill.equalsIgnoreCase(FILL_REMOVE_ATTRIBUTE)) {
return FILL_REMOVE;
} else if (fill.equalsIgnoreCase(FILL_HOLD_ATTRIBUTE)) {
// FIXME handle it as freeze for now
return FILL_FREEZE;
} else if (fill.equalsIgnoreCase(FILL_TRANSITION_ATTRIBUTE)) {
// FIXME handle it as freeze for now
return FILL_FREEZE;
} else if (!fill.equalsIgnoreCase(FILL_AUTO_ATTRIBUTE)) {
/*
* fill = default
* The fill behavior for the element is determined by the value of the fillDefault
* attribute. This is the default value.
*/
short fillDefault = getFillDefault();
if (fillDefault != FILL_AUTO) {
return fillDefault;
}
}
/*
* fill = auto
* The fill behavior for this element depends on whether the element specifies any of
* the attributes that define the simple or active duration:
* - If none of the attributes dur, end, repeatCount or repeatDur are specified on
* the element, then the element will have a fill behavior identical to that if it were
* specified as "freeze".
* - Otherwise, the element will have a fill behavior identical to that if it were
* specified as "remove".
*/
if (((mSmilElement.getAttribute("dur").length() == 0) &&
(mSmilElement.getAttribute("end").length() == 0) &&
(mSmilElement.getAttribute("repeatCount").length() == 0) &&
(mSmilElement.getAttribute("repeatDur").length() == 0)) ||
beginAndEndAreZero()) {
return FILL_FREEZE;
} else {
return FILL_REMOVE;
}
}
public short getFillDefault() {
String fillDefault = mSmilElement.getAttribute(FILLDEFAULT_ATTRIBUTE_NAME);
if (fillDefault.equalsIgnoreCase(FILL_REMOVE_ATTRIBUTE)) {
return FILL_REMOVE;
} else if (fillDefault.equalsIgnoreCase(FILL_FREEZE_ATTRIBUTE)) {
return FILL_FREEZE;
} else if (fillDefault.equalsIgnoreCase(FILL_AUTO_ATTRIBUTE)) {
return FILL_AUTO;
} else if (fillDefault.equalsIgnoreCase(FILL_HOLD_ATTRIBUTE)) {
// FIXME handle it as freeze for now
return FILL_FREEZE;
} else if (fillDefault.equalsIgnoreCase(FILL_TRANSITION_ATTRIBUTE)) {
// FIXME handle it as freeze for now
return FILL_FREEZE;
} else {
/*
* fillDefault = inherit
* Specifies that the value of this attribute (and of the fill behavior) are
* inherited from the fillDefault value of the parent element.
* This is the default value.
*/
ElementTime parent = getParentElementTime();
if (parent == null) {
/*
* fillDefault = auto
* If there is no parent element, the value is "auto".
*/
return FILL_AUTO;
} else {
return ((ElementTimeImpl) parent).getFillDefault();
}
}
}
public float getRepeatCount() {
String repeatCount = mSmilElement.getAttribute("repeatCount");
try {
float value = Float.parseFloat(repeatCount);
if (value > 0) {
return value;
} else {
return 0; // default
}
} catch (NumberFormatException e) {
return 0; // default
}
}
public float getRepeatDur() {
try {
float repeatDur =
TimeImpl.parseClockValue(mSmilElement.getAttribute("repeatDur"));
if (repeatDur > 0) {
return repeatDur;
} else {
return 0; // default
}
} catch (IllegalArgumentException e) {
return 0; // default
}
}
public short getRestart() {
String restart = mSmilElement.getAttribute("restart");
if (restart.equalsIgnoreCase("never")) {
return RESTART_NEVER;
} else if (restart.equalsIgnoreCase("whenNotActive")) {
return RESTART_WHEN_NOT_ACTIVE;
} else {
return RESTART_ALWAYS; // default
}
}
public void setBegin(TimeList begin) throws DOMException {
// TODO Implement this
mSmilElement.setAttribute("begin", "indefinite");
}
public void setDur(float dur) throws DOMException {
// In SMIL 3.0, the dur could be a timecount-value which may contain fractions.
// However, in MMS 1.3, the dur SHALL be expressed in integer milliseconds.
mSmilElement.setAttribute("dur", Integer.toString((int)(dur * 1000)) + "ms");
}
public void setEnd(TimeList end) throws DOMException {
// TODO Implement this
mSmilElement.setAttribute("end", "indefinite");
}
public void setFill(short fill) throws DOMException {
if (fill == FILL_FREEZE) {
mSmilElement.setAttribute(FILL_ATTRIBUTE_NAME, FILL_FREEZE_ATTRIBUTE);
} else {
mSmilElement.setAttribute(FILL_ATTRIBUTE_NAME, FILL_REMOVE_ATTRIBUTE); // default
}
}
public void setFillDefault(short fillDefault) throws DOMException {
if (fillDefault == FILL_FREEZE) {
mSmilElement.setAttribute(FILLDEFAULT_ATTRIBUTE_NAME, FILL_FREEZE_ATTRIBUTE);
} else {
mSmilElement.setAttribute(FILLDEFAULT_ATTRIBUTE_NAME, FILL_REMOVE_ATTRIBUTE);
}
}
public void setRepeatCount(float repeatCount) throws DOMException {
String repeatCountString = "indefinite";
if (repeatCount > 0) {
repeatCountString = Float.toString(repeatCount);
}
mSmilElement.setAttribute("repeatCount", repeatCountString);
}
public void setRepeatDur(float repeatDur) throws DOMException {
String repeatDurString = "indefinite";
if (repeatDur > 0) {
repeatDurString = Float.toString(repeatDur) + "ms";
}
mSmilElement.setAttribute("repeatDur", repeatDurString);
}
public void setRestart(short restart) throws DOMException {
if (restart == RESTART_NEVER) {
mSmilElement.setAttribute("restart", "never");
} else if (restart == RESTART_WHEN_NOT_ACTIVE) {
mSmilElement.setAttribute("restart", "whenNotActive");
} else {
mSmilElement.setAttribute("restart", "always");
}
}
}

View File

@ -1,291 +0,0 @@
/*
* Copyright (C) 2007 Esmertec AG.
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thoughtcrime.securesms.dom.smil;
import org.w3c.dom.DOMException;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.events.DocumentEvent;
import org.w3c.dom.events.Event;
import org.w3c.dom.smil.ElementSequentialTimeContainer;
import org.w3c.dom.smil.ElementTime;
import org.w3c.dom.smil.SMILDocument;
import org.w3c.dom.smil.SMILElement;
import org.w3c.dom.smil.SMILLayoutElement;
import org.w3c.dom.smil.TimeList;
import org.thoughtcrime.securesms.dom.DocumentImpl;
import org.thoughtcrime.securesms.dom.events.EventImpl;
public class SmilDocumentImpl extends DocumentImpl implements SMILDocument, DocumentEvent {
/*
* The sequential time container cannot be initialized here because the real container
* is body, which hasn't been created yet. It will be initialized when the body has
* already been created. Please see getBody().
*/
ElementSequentialTimeContainer mSeqTimeContainer;
public final static String SMIL_DOCUMENT_START_EVENT = "SmilDocumentStart";
public final static String SMIL_DOCUMENT_END_EVENT = "SimlDocumentEnd";
/*
* Internal methods
*/
public SmilDocumentImpl() {
super();
}
/*
* ElementSequentialTimeContainer stuff
*/
public NodeList getActiveChildrenAt(float instant) {
return mSeqTimeContainer.getActiveChildrenAt(instant);
}
public NodeList getTimeChildren() {
return mSeqTimeContainer.getTimeChildren();
}
public boolean beginElement() {
return mSeqTimeContainer.beginElement();
}
public boolean endElement() {
return mSeqTimeContainer.endElement();
}
public TimeList getBegin() {
return mSeqTimeContainer.getBegin();
}
public float getDur() {
return mSeqTimeContainer.getDur();
}
public TimeList getEnd() {
return mSeqTimeContainer.getEnd();
}
public short getFill() {
return mSeqTimeContainer.getFill();
}
public short getFillDefault() {
return mSeqTimeContainer.getFillDefault();
}
public float getRepeatCount() {
return mSeqTimeContainer.getRepeatCount();
}
public float getRepeatDur() {
return mSeqTimeContainer.getRepeatDur();
}
public short getRestart() {
return mSeqTimeContainer.getRestart();
}
public void pauseElement() {
mSeqTimeContainer.pauseElement();
}
public void resumeElement() {
mSeqTimeContainer.resumeElement();
}
public void seekElement(float seekTo) {
mSeqTimeContainer.seekElement(seekTo);
}
public void setBegin(TimeList begin) throws DOMException {
mSeqTimeContainer.setBegin(begin);
}
public void setDur(float dur) throws DOMException {
mSeqTimeContainer.setDur(dur);
}
public void setEnd(TimeList end) throws DOMException {
mSeqTimeContainer.setEnd(end);
}
public void setFill(short fill) throws DOMException {
mSeqTimeContainer.setFill(fill);
}
public void setFillDefault(short fillDefault) throws DOMException {
mSeqTimeContainer.setFillDefault(fillDefault);
}
public void setRepeatCount(float repeatCount) throws DOMException {
mSeqTimeContainer.setRepeatCount(repeatCount);
}
public void setRepeatDur(float repeatDur) throws DOMException {
mSeqTimeContainer.setRepeatDur(repeatDur);
}
public void setRestart(short restart) throws DOMException {
mSeqTimeContainer.setRestart(restart);
}
/*
* Document Interface
*/
@Override
public Element createElement(String tagName) throws DOMException {
// Find the appropriate class for this element
tagName = tagName.toLowerCase();
if (tagName.equals("text") ||
tagName.equals("img") ||
tagName.equals("video")) {
return new SmilRegionMediaElementImpl(this, tagName);
} else if (tagName.equals("audio")) {
return new SmilMediaElementImpl(this, tagName);
} else if (tagName.equals("layout")) {
return new SmilLayoutElementImpl(this, tagName);
} else if (tagName.equals("root-layout")) {
return new SmilRootLayoutElementImpl(this, tagName);
} else if (tagName.equals("region")) {
return new SmilRegionElementImpl(this, tagName);
} else if (tagName.equals("ref")) {
return new SmilRefElementImpl(this, tagName);
} else if (tagName.equals("par")) {
return new SmilParElementImpl(this, tagName);
} else {
// This includes also the structural nodes SMIL,
// HEAD, BODY, for which no specific types are defined.
return new SmilElementImpl(this, tagName);
}
}
@Override
public SMILElement getDocumentElement() {
Node rootElement = getFirstChild();
if (rootElement == null || !(rootElement instanceof SMILElement)) {
// The root doesn't exist. Create a new one.
rootElement = createElement("smil");
appendChild(rootElement);
}
return (SMILElement) rootElement;
}
/*
* SMILElement Interface
*/
public SMILElement getHead() {
Node rootElement = getDocumentElement();
Node headElement = rootElement.getFirstChild();
if (headElement == null || !(headElement instanceof SMILElement)) {
// The head doesn't exist. Create a new one.
headElement = createElement("head");
rootElement.appendChild(headElement);
}
return (SMILElement) headElement;
}
public SMILElement getBody() {
Node rootElement = getDocumentElement();
Node headElement = getHead();
Node bodyElement = headElement.getNextSibling();
if (bodyElement == null || !(bodyElement instanceof SMILElement)) {
// The body doesn't exist. Create a new one.
bodyElement = createElement("body");
rootElement.appendChild(bodyElement);
}
// Initialize the real sequential time container, which is body.
mSeqTimeContainer = new ElementSequentialTimeContainerImpl((SMILElement) bodyElement) {
public NodeList getTimeChildren() {
return getBody().getElementsByTagName("par");
}
public boolean beginElement() {
Event startEvent = createEvent("Event");
startEvent.initEvent(SMIL_DOCUMENT_START_EVENT, false, false);
dispatchEvent(startEvent);
return true;
}
public boolean endElement() {
Event endEvent = createEvent("Event");
endEvent.initEvent(SMIL_DOCUMENT_END_EVENT, false, false);
dispatchEvent(endEvent);
return true;
}
public void pauseElement() {
// TODO Auto-generated method stub
}
public void resumeElement() {
// TODO Auto-generated method stub
}
public void seekElement(float seekTo) {
// TODO Auto-generated method stub
}
ElementTime getParentElementTime() {
return null;
}
};
return (SMILElement) bodyElement;
}
public SMILLayoutElement getLayout() {
Node headElement = getHead();
Node layoutElement = null;
// Find the layout element under <code>HEAD</code>
layoutElement = headElement.getFirstChild();
while ((layoutElement != null) && !(layoutElement instanceof SMILLayoutElement)) {
layoutElement = layoutElement.getNextSibling();
}
if (layoutElement == null) {
// The layout doesn't exist. Create a default one.
layoutElement = new SmilLayoutElementImpl(this, "layout");
headElement.appendChild(layoutElement);
}
return (SMILLayoutElement) layoutElement;
}
/*
* DocumentEvent Interface
*/
public Event createEvent(String eventType) throws DOMException {
if ("Event".equals(eventType)) {
return new EventImpl();
} else {
throw new DOMException(DOMException.NOT_SUPPORTED_ERR,
"Not supported interface");
}
}
}

View File

@ -1,47 +0,0 @@
/*
* Copyright (C) 2007 Esmertec AG.
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thoughtcrime.securesms.dom.smil;
import org.w3c.dom.DOMException;
import org.w3c.dom.smil.SMILElement;
import org.thoughtcrime.securesms.dom.ElementImpl;
public class SmilElementImpl extends ElementImpl implements SMILElement {
/**
* This constructor is used by the factory methods of the SmilDocument.
*
* @param owner The SMIL document to which this element belongs to
* @param tagName The tag name of the element
*/
SmilElementImpl(SmilDocumentImpl owner, String tagName)
{
super(owner, tagName.toLowerCase());
}
public String getId() {
// TODO Auto-generated method stub
return null;
}
public void setId(String id) throws DOMException {
// TODO Auto-generated method stub
}
}

View File

@ -1,63 +0,0 @@
/*
* Copyright (C) 2007 Esmertec AG.
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thoughtcrime.securesms.dom.smil;
import org.thoughtcrime.securesms.util.SmilUtil;
import org.w3c.dom.NodeList;
import org.w3c.dom.smil.SMILLayoutElement;
import org.w3c.dom.smil.SMILRootLayoutElement;
public class SmilLayoutElementImpl extends SmilElementImpl implements
SMILLayoutElement {
SmilLayoutElementImpl(SmilDocumentImpl owner, String tagName) {
super(owner, tagName);
}
public boolean getResolved() {
// TODO Auto-generated method stub
return false;
}
public String getType() {
return this.getAttribute("type");
}
public NodeList getRegions() {
return this.getElementsByTagName("region");
}
public SMILRootLayoutElement getRootLayout() {
NodeList childNodes = this.getChildNodes();
SMILRootLayoutElement rootLayoutNode = null;
int childrenCount = childNodes.getLength();
for (int i = 0; i < childrenCount; i++) {
if (childNodes.item(i).getNodeName().equals("root-layout")) {
rootLayoutNode = (SMILRootLayoutElement)childNodes.item(i);
}
}
if (null == rootLayoutNode) {
// root-layout node is not set. Create a default one.
rootLayoutNode = (SMILRootLayoutElement) getOwnerDocument().createElement("root-layout");
rootLayoutNode.setWidth(SmilUtil.ROOT_WIDTH);
rootLayoutNode.setHeight(SmilUtil.ROOT_HEIGHT);
appendChild(rootLayoutNode);
}
return rootLayoutNode;
}
}

View File

@ -1,343 +0,0 @@
/*
* Copyright (C) 2007-2008 Esmertec AG.
* Copyright (C) 2007-2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thoughtcrime.securesms.dom.smil;
import org.w3c.dom.DOMException;
import org.w3c.dom.events.DocumentEvent;
import org.w3c.dom.events.Event;
import org.w3c.dom.smil.ElementTime;
import org.w3c.dom.smil.SMILMediaElement;
import org.w3c.dom.smil.TimeList;
import android.util.Log;
import org.thoughtcrime.securesms.dom.events.EventImpl;
public class SmilMediaElementImpl extends SmilElementImpl implements
SMILMediaElement {
public final static String SMIL_MEDIA_START_EVENT = "SmilMediaStart";
public final static String SMIL_MEDIA_END_EVENT = "SmilMediaEnd";
public final static String SMIL_MEDIA_PAUSE_EVENT = "SmilMediaPause";
public final static String SMIL_MEDIA_SEEK_EVENT = "SmilMediaSeek";
private final static String TAG = "Mms:smil";
private static final boolean DEBUG = false;
private static final boolean LOCAL_LOGV = false;
ElementTime mElementTime = new ElementTimeImpl(this) {
private Event createEvent(String eventType) {
DocumentEvent doc =
(DocumentEvent)SmilMediaElementImpl.this.getOwnerDocument();
Event event = doc.createEvent("Event");
event.initEvent(eventType, false, false);
if (LOCAL_LOGV) {
Log.v(TAG, "Dispatching 'begin' event to "
+ SmilMediaElementImpl.this.getTagName() + " "
+ SmilMediaElementImpl.this.getSrc() + " at "
+ System.currentTimeMillis());
}
return event;
}
private Event createEvent(String eventType, int seekTo) {
DocumentEvent doc =
(DocumentEvent)SmilMediaElementImpl.this.getOwnerDocument();
EventImpl event = (EventImpl) doc.createEvent("Event");
event.initEvent(eventType, false, false, seekTo);
if (LOCAL_LOGV) {
Log.v(TAG, "Dispatching 'begin' event to "
+ SmilMediaElementImpl.this.getTagName() + " "
+ SmilMediaElementImpl.this.getSrc() + " at "
+ System.currentTimeMillis());
}
return event;
}
public boolean beginElement() {
Event startEvent = createEvent(SMIL_MEDIA_START_EVENT);
dispatchEvent(startEvent);
return true;
}
public boolean endElement() {
Event endEvent = createEvent(SMIL_MEDIA_END_EVENT);
dispatchEvent(endEvent);
return true;
}
public void resumeElement() {
Event resumeEvent = createEvent(SMIL_MEDIA_START_EVENT);
dispatchEvent(resumeEvent);
}
public void pauseElement() {
Event pauseEvent = createEvent(SMIL_MEDIA_PAUSE_EVENT);
dispatchEvent(pauseEvent);
}
public void seekElement(float seekTo) {
Event seekEvent = createEvent(SMIL_MEDIA_SEEK_EVENT, (int) seekTo);
dispatchEvent(seekEvent);
}
@Override
public float getDur() {
float dur = super.getDur();
if (dur == 0) {
// Duration is not specified, So get the implicit duration.
String tag = getTagName();
if (tag.equals("video") || tag.equals("audio")) {
// Continuous media
// FIXME Should get the duration of the media. "indefinite" instead here.
dur = -1.0F;
} else if (tag.equals("text") || tag.equals("img")) {
// Discrete media
dur = 0;
} else {
Log.w(TAG, "Unknown media type");
}
}
return dur;
}
@Override
ElementTime getParentElementTime() {
return ((SmilParElementImpl) mSmilElement.getParentNode()).mParTimeContainer;
}
};
/*
* Internal Interface
*/
SmilMediaElementImpl(SmilDocumentImpl owner, String tagName) {
super(owner, tagName);
}
/*
* SMILMediaElement Interface
*/
public String getAbstractAttr() {
return this.getAttribute("abstract");
}
public String getAlt() {
return this.getAttribute("alt");
}
public String getAuthor() {
return this.getAttribute("author");
}
public String getClipBegin() {
return this.getAttribute("clipBegin");
}
public String getClipEnd() {
return this.getAttribute("clipEnd");
}
public String getCopyright() {
return this.getAttribute("copyright");
}
public String getLongdesc() {
return this.getAttribute("longdesc");
}
public String getPort() {
return this.getAttribute("port");
}
public String getReadIndex() {
return this.getAttribute("readIndex");
}
public String getRtpformat() {
return this.getAttribute("rtpformat");
}
public String getSrc() {
return this.getAttribute("src");
}
public String getStripRepeat() {
return this.getAttribute("stripRepeat");
}
public String getTitle() {
return this.getAttribute("title");
}
public String getTransport() {
return this.getAttribute("transport");
}
public String getType() {
return this.getAttribute("type");
}
public void setAbstractAttr(String abstractAttr) throws DOMException {
this.setAttribute("abstract", abstractAttr);
}
public void setAlt(String alt) throws DOMException {
this.setAttribute("alt", alt);
}
public void setAuthor(String author) throws DOMException {
this.setAttribute("author", author);
}
public void setClipBegin(String clipBegin) throws DOMException {
this.setAttribute("clipBegin", clipBegin);
}
public void setClipEnd(String clipEnd) throws DOMException {
this.setAttribute("clipEnd", clipEnd);
}
public void setCopyright(String copyright) throws DOMException {
this.setAttribute("copyright", copyright);
}
public void setLongdesc(String longdesc) throws DOMException {
this.setAttribute("longdesc", longdesc);
}
public void setPort(String port) throws DOMException {
this.setAttribute("port", port);
}
public void setReadIndex(String readIndex) throws DOMException {
this.setAttribute("readIndex", readIndex);
}
public void setRtpformat(String rtpformat) throws DOMException {
this.setAttribute("rtpformat", rtpformat);
}
public void setSrc(String src) throws DOMException {
this.setAttribute("src", src);
}
public void setStripRepeat(String stripRepeat) throws DOMException {
this.setAttribute("stripRepeat", stripRepeat);
}
public void setTitle(String title) throws DOMException {
this.setAttribute("title", title);
}
public void setTransport(String transport) throws DOMException {
this.setAttribute("transport", transport);
}
public void setType(String type) throws DOMException {
this.setAttribute("type", type);
}
/*
* TimeElement Interface
*/
public boolean beginElement() {
return mElementTime.beginElement();
}
public boolean endElement() {
return mElementTime.endElement();
}
public TimeList getBegin() {
return mElementTime.getBegin();
}
public float getDur() {
return mElementTime.getDur();
}
public TimeList getEnd() {
return mElementTime.getEnd();
}
public short getFill() {
return mElementTime.getFill();
}
public short getFillDefault() {
return mElementTime.getFillDefault();
}
public float getRepeatCount() {
return mElementTime.getRepeatCount();
}
public float getRepeatDur() {
return mElementTime.getRepeatDur();
}
public short getRestart() {
return mElementTime.getRestart();
}
public void pauseElement() {
mElementTime.pauseElement();
}
public void resumeElement() {
mElementTime.resumeElement();
}
public void seekElement(float seekTo) {
mElementTime.seekElement(seekTo);
}
public void setBegin(TimeList begin) throws DOMException {
mElementTime.setBegin(begin);
}
public void setDur(float dur) throws DOMException {
mElementTime.setDur(dur);
}
public void setEnd(TimeList end) throws DOMException {
mElementTime.setEnd(end);
}
public void setFill(short fill) throws DOMException {
mElementTime.setFill(fill);
}
public void setFillDefault(short fillDefault) throws DOMException {
mElementTime.setFillDefault(fillDefault);
}
public void setRepeatCount(float repeatCount) throws DOMException {
mElementTime.setRepeatCount(repeatCount);
}
public void setRepeatDur(float repeatDur) throws DOMException {
mElementTime.setRepeatDur(repeatDur);
}
public void setRestart(short restart) throws DOMException {
mElementTime.setRestart(restart);
}
}

View File

@ -1,217 +0,0 @@
/*
* Copyright (C) 2007 Esmertec AG.
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thoughtcrime.securesms.dom.smil;
import java.util.ArrayList;
import org.w3c.dom.DOMException;
import org.w3c.dom.NodeList;
import org.w3c.dom.events.DocumentEvent;
import org.w3c.dom.events.Event;
import org.w3c.dom.smil.ElementParallelTimeContainer;
import org.w3c.dom.smil.ElementTime;
import org.w3c.dom.smil.SMILParElement;
import org.w3c.dom.smil.Time;
import org.w3c.dom.smil.TimeList;
public class SmilParElementImpl extends SmilElementImpl implements SMILParElement {
public final static String SMIL_SLIDE_START_EVENT = "SmilSlideStart";
public final static String SMIL_SLIDE_END_EVENT = "SmilSlideEnd";
ElementParallelTimeContainer mParTimeContainer =
new ElementParallelTimeContainerImpl(this) {
@Override
public TimeList getBegin() {
/*
* For children of a sequence, the only legal value for begin is
* a (single) non-negative offset value.
*/
TimeList beginTimeList = super.getBegin();
if (beginTimeList.getLength() > 1) {
ArrayList<Time> singleTimeContainer = new ArrayList<Time>();
singleTimeContainer.add(beginTimeList.item(0));
beginTimeList = new TimeListImpl(singleTimeContainer);
}
return beginTimeList;
}
public NodeList getTimeChildren() {
return getChildNodes();
}
public boolean beginElement() {
DocumentEvent doc = (DocumentEvent) SmilParElementImpl.this.getOwnerDocument();
Event startEvent = doc.createEvent("Event");
startEvent.initEvent(SMIL_SLIDE_START_EVENT, false, false);
dispatchEvent(startEvent);
return true;
}
public boolean endElement() {
DocumentEvent doc = (DocumentEvent) SmilParElementImpl.this.getOwnerDocument();
Event endEvent = doc.createEvent("Event");
endEvent.initEvent(SMIL_SLIDE_END_EVENT, false, false);
dispatchEvent(endEvent);
return true;
}
public void pauseElement() {
// TODO Auto-generated method stub
}
public void resumeElement() {
// TODO Auto-generated method stub
}
public void seekElement(float seekTo) {
// TODO Auto-generated method stub
}
ElementTime getParentElementTime() {
return ((SmilDocumentImpl) mSmilElement.getOwnerDocument()).mSeqTimeContainer;
}
};
/*
* Internal Interface
*/
SmilParElementImpl(SmilDocumentImpl owner, String tagName)
{
super(owner, tagName.toUpperCase());
}
int getBeginConstraints() {
/*
* For children of a sequence, the only legal value for begin is
* a (single) non-negative offset value.
*/
return (TimeImpl.ALLOW_OFFSET_VALUE); // Do not set ALLOW_NEGATIVE_VALUE
}
/*
* ElementParallelTimeContainer
*/
public String getEndSync() {
return mParTimeContainer.getEndSync();
}
public float getImplicitDuration() {
return mParTimeContainer.getImplicitDuration();
}
public void setEndSync(String endSync) throws DOMException {
mParTimeContainer.setEndSync(endSync);
}
public NodeList getActiveChildrenAt(float instant) {
return mParTimeContainer.getActiveChildrenAt(instant);
}
public NodeList getTimeChildren() {
return mParTimeContainer.getTimeChildren();
}
public boolean beginElement() {
return mParTimeContainer.beginElement();
}
public boolean endElement() {
return mParTimeContainer.endElement();
}
public TimeList getBegin() {
return mParTimeContainer.getBegin();
}
public float getDur() {
return mParTimeContainer.getDur();
}
public TimeList getEnd() {
return mParTimeContainer.getEnd();
}
public short getFill() {
return mParTimeContainer.getFill();
}
public short getFillDefault() {
return mParTimeContainer.getFillDefault();
}
public float getRepeatCount() {
return mParTimeContainer.getRepeatCount();
}
public float getRepeatDur() {
return mParTimeContainer.getRepeatDur();
}
public short getRestart() {
return mParTimeContainer.getRestart();
}
public void pauseElement() {
mParTimeContainer.pauseElement();
}
public void resumeElement() {
mParTimeContainer.resumeElement();
}
public void seekElement(float seekTo) {
mParTimeContainer.seekElement(seekTo);
}
public void setBegin(TimeList begin) throws DOMException {
mParTimeContainer.setBegin(begin);
}
public void setDur(float dur) throws DOMException {
mParTimeContainer.setDur(dur);
}
public void setEnd(TimeList end) throws DOMException {
mParTimeContainer.setEnd(end);
}
public void setFill(short fill) throws DOMException {
mParTimeContainer.setFill(fill);
}
public void setFillDefault(short fillDefault) throws DOMException {
mParTimeContainer.setFillDefault(fillDefault);
}
public void setRepeatCount(float repeatCount) throws DOMException {
mParTimeContainer.setRepeatCount(repeatCount);
}
public void setRepeatDur(float repeatDur) throws DOMException {
mParTimeContainer.setRepeatDur(repeatDur);
}
public void setRestart(short restart) throws DOMException {
mParTimeContainer.setRestart(restart);
}
}

View File

@ -1,29 +0,0 @@
/*
* Copyright (C) 2007 Esmertec AG.
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thoughtcrime.securesms.dom.smil;
import org.w3c.dom.smil.SMILRefElement;
public class SmilRefElementImpl extends SmilRegionMediaElementImpl implements
SMILRefElement {
SmilRefElementImpl(SmilDocumentImpl owner, String tagName) {
super(owner, tagName);
}
}

View File

@ -1,283 +0,0 @@
/*
* Copyright (C) 2007-2008 Esmertec AG.
* Copyright (C) 2007-2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thoughtcrime.securesms.dom.smil;
import org.w3c.dom.DOMException;
import org.w3c.dom.smil.SMILDocument;
import org.w3c.dom.smil.SMILRegionElement;
import android.util.Log;
public class SmilRegionElementImpl extends SmilElementImpl implements
SMILRegionElement {
/*
* Internal Interface
*/
private static final String HIDDEN_ATTRIBUTE = "hidden";
private static final String SLICE_ATTRIBUTE = "slice";
private static final String SCROLL_ATTRIBUTE = "scroll";
private static final String MEET_ATTRIBUTE = "meet";
private static final String FILL_ATTRIBUTE = "fill";
private static final String ID_ATTRIBUTE_NAME = "id";
private static final String WIDTH_ATTRIBUTE_NAME = "width";
private static final String TITLE_ATTRIBUTE_NAME = "title";
private static final String HEIGHT_ATTRIBUTE_NAME = "height";
private static final String BACKGROUND_COLOR_ATTRIBUTE_NAME = "backgroundColor";
private static final String Z_INDEX_ATTRIBUTE_NAME = "z-index";
private static final String TOP_ATTRIBUTE_NAME = "top";
private static final String LEFT_ATTRIBUTE_NAME = "left";
private static final String RIGHT_ATTRIBUTE_NAME = "right";
private static final String BOTTOM_ATTRIBUTE_NAME = "bottom";
private static final String FIT_ATTRIBUTE_NAME = "fit";
private static final String TAG = "SmilRegionElementImpl";
private static final boolean DEBUG = false;
private static final boolean LOCAL_LOGV = false;
SmilRegionElementImpl(SmilDocumentImpl owner, String tagName) {
super(owner, tagName);
}
/*
* SMILRegionElement Interface
*/
public String getFit() {
String fit = getAttribute(FIT_ATTRIBUTE_NAME);
if (FILL_ATTRIBUTE.equalsIgnoreCase(fit)) {
return FILL_ATTRIBUTE;
} else if (MEET_ATTRIBUTE.equalsIgnoreCase(fit)) {
return MEET_ATTRIBUTE;
} else if (SCROLL_ATTRIBUTE.equalsIgnoreCase(fit)) {
return SCROLL_ATTRIBUTE;
} else if (SLICE_ATTRIBUTE.equalsIgnoreCase(fit)) {
return SLICE_ATTRIBUTE;
} else {
return HIDDEN_ATTRIBUTE;
}
}
public int getLeft() {
try {
return parseRegionLength(getAttribute(LEFT_ATTRIBUTE_NAME), true);
} catch (NumberFormatException _) {
if (LOCAL_LOGV) {
Log.v(TAG, "Left attribute is not set or incorrect.");
}
}
try {
int bbw = ((SMILDocument) getOwnerDocument()).getLayout().getRootLayout().getWidth();
int right = parseRegionLength(getAttribute(RIGHT_ATTRIBUTE_NAME), true);
int width = parseRegionLength(getAttribute(WIDTH_ATTRIBUTE_NAME), true);
return bbw - right - width;
} catch (NumberFormatException _) {
if (LOCAL_LOGV) {
Log.v(TAG, "Right or width attribute is not set or incorrect.");
}
}
return 0;
}
public int getTop() {
try {
return parseRegionLength(getAttribute(TOP_ATTRIBUTE_NAME), false);
} catch (NumberFormatException _) {
if (LOCAL_LOGV) {
Log.v(TAG, "Top attribute is not set or incorrect.");
}
}
try {
int bbh = ((SMILDocument) getOwnerDocument()).getLayout().getRootLayout().getHeight();
int bottom = parseRegionLength(getAttribute(BOTTOM_ATTRIBUTE_NAME), false);
int height = parseRegionLength(getAttribute(HEIGHT_ATTRIBUTE_NAME), false);
return bbh - bottom - height;
} catch (NumberFormatException _) {
if (LOCAL_LOGV) {
Log.v(TAG, "Bottom or height attribute is not set or incorrect.");
}
}
return 0;
}
public int getZIndex() {
try {
return Integer.parseInt(this.getAttribute(Z_INDEX_ATTRIBUTE_NAME));
} catch (NumberFormatException _) {
return 0;
}
}
public void setFit(String fit) throws DOMException {
if (fit.equalsIgnoreCase(FILL_ATTRIBUTE)
|| fit.equalsIgnoreCase(MEET_ATTRIBUTE)
|| fit.equalsIgnoreCase(SCROLL_ATTRIBUTE)
|| fit.equalsIgnoreCase(SLICE_ATTRIBUTE)) {
this.setAttribute(FIT_ATTRIBUTE_NAME, fit.toLowerCase());
} else {
this.setAttribute(FIT_ATTRIBUTE_NAME, HIDDEN_ATTRIBUTE);
}
}
public void setLeft(int left) throws DOMException {
this.setAttribute(LEFT_ATTRIBUTE_NAME, String.valueOf(left));
}
public void setTop(int top) throws DOMException {
this.setAttribute(TOP_ATTRIBUTE_NAME, String.valueOf(top));
}
public void setZIndex(int zIndex) throws DOMException {
if (zIndex > 0) {
this.setAttribute(Z_INDEX_ATTRIBUTE_NAME, Integer.toString(zIndex));
} else {
this.setAttribute(Z_INDEX_ATTRIBUTE_NAME, Integer.toString(0));
}
}
public String getBackgroundColor() {
return this.getAttribute(BACKGROUND_COLOR_ATTRIBUTE_NAME);
}
public int getHeight() {
try {
final int height = parseRegionLength(getAttribute(HEIGHT_ATTRIBUTE_NAME), false);
return height == 0 ?
((SMILDocument) getOwnerDocument()).getLayout().getRootLayout().getHeight() :
height;
} catch (NumberFormatException _) {
if (LOCAL_LOGV) {
Log.v(TAG, "Height attribute is not set or incorrect.");
}
}
int bbh = ((SMILDocument) getOwnerDocument()).getLayout().getRootLayout().getHeight();
try {
bbh -= parseRegionLength(getAttribute(TOP_ATTRIBUTE_NAME), false);
} catch (NumberFormatException _) {
if (LOCAL_LOGV) {
Log.v(TAG, "Top attribute is not set or incorrect.");
}
}
try {
bbh -= parseRegionLength(getAttribute(BOTTOM_ATTRIBUTE_NAME), false);
} catch (NumberFormatException _) {
if (LOCAL_LOGV) {
Log.v(TAG, "Bottom attribute is not set or incorrect.");
}
}
return bbh;
}
public String getTitle() {
return this.getAttribute(TITLE_ATTRIBUTE_NAME);
}
public int getWidth() {
try {
final int width = parseRegionLength(getAttribute(WIDTH_ATTRIBUTE_NAME), true);
return width == 0 ?
((SMILDocument) getOwnerDocument()).getLayout().getRootLayout().getWidth() :
width;
} catch (NumberFormatException _) {
if (LOCAL_LOGV) {
Log.v(TAG, "Width attribute is not set or incorrect.");
}
}
int bbw = ((SMILDocument) getOwnerDocument()).getLayout().getRootLayout().getWidth();
try {
bbw -= parseRegionLength(getAttribute(LEFT_ATTRIBUTE_NAME), true);
} catch (NumberFormatException _) {
if (LOCAL_LOGV) {
Log.v(TAG, "Left attribute is not set or incorrect.");
}
}
try {
bbw -= parseRegionLength(getAttribute(RIGHT_ATTRIBUTE_NAME), true);
} catch (NumberFormatException _) {
if (LOCAL_LOGV) {
Log.v(TAG, "Right attribute is not set or incorrect.");
}
}
return bbw;
}
public void setBackgroundColor(String backgroundColor) throws DOMException {
this.setAttribute(BACKGROUND_COLOR_ATTRIBUTE_NAME, backgroundColor);
}
public void setHeight(int height) throws DOMException {
this.setAttribute(HEIGHT_ATTRIBUTE_NAME, String.valueOf(height) + "px");
}
public void setTitle(String title) throws DOMException {
this.setAttribute(TITLE_ATTRIBUTE_NAME, title);
}
public void setWidth(int width) throws DOMException {
this.setAttribute(WIDTH_ATTRIBUTE_NAME, String.valueOf(width) + "px");
}
/*
* SMILElement Interface
*/
@Override
public String getId() {
return this.getAttribute(ID_ATTRIBUTE_NAME);
}
@Override
public void setId(String id) throws DOMException {
this.setAttribute(ID_ATTRIBUTE_NAME, id);
}
/*
* Internal Interface
*/
private int parseRegionLength(String length, boolean horizontal) {
if (length.endsWith("px")) {
length = length.substring(0, length.indexOf("px"));
return Integer.parseInt(length);
} else if (length.endsWith("%")) {
double value = 0.01*Integer.parseInt(length.substring(0, length.length() - 1));
if (horizontal) {
value *= ((SMILDocument) getOwnerDocument()).getLayout().getRootLayout().getWidth();
} else {
value *= ((SMILDocument) getOwnerDocument()).getLayout().getRootLayout().getHeight();
}
return (int) Math.round(value);
} else {
return Integer.parseInt(length);
}
}
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return super.toString()
+ ": id=" + getId()
+ ", width=" + getWidth()
+ ", height=" + getHeight()
+ ", left=" + getLeft()
+ ", top=" + getTop();
}
}

View File

@ -1,53 +0,0 @@
/*
* Copyright (C) 2007 Esmertec AG.
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thoughtcrime.securesms.dom.smil;
import org.w3c.dom.NodeList;
import org.w3c.dom.smil.SMILDocument;
import org.w3c.dom.smil.SMILRegionElement;
import org.w3c.dom.smil.SMILRegionMediaElement;
public class SmilRegionMediaElementImpl extends SmilMediaElementImpl implements
SMILRegionMediaElement {
private SMILRegionElement mRegion;
SmilRegionMediaElementImpl(SmilDocumentImpl owner, String tagName) {
super(owner, tagName);
}
public SMILRegionElement getRegion() {
if (mRegion == null) {
SMILDocument doc = (SMILDocument)this.getOwnerDocument();
NodeList regions = doc.getLayout().getElementsByTagName("region");
SMILRegionElement region = null;
for (int i = 0; i < regions.getLength(); i++) {
region = (SMILRegionElement)regions.item(i);
if (region.getId().equals(this.getAttribute("region"))) {
mRegion = region;
}
}
}
return mRegion;
}
public void setRegion(SMILRegionElement region) {
this.setAttribute("region", region.getId());
mRegion = region;
}
}

View File

@ -1,84 +0,0 @@
/*
* Copyright (C) 2007 Esmertec AG.
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thoughtcrime.securesms.dom.smil;
import org.w3c.dom.DOMException;
import org.w3c.dom.smil.SMILRootLayoutElement;
public class SmilRootLayoutElementImpl extends SmilElementImpl implements
SMILRootLayoutElement {
private static final String WIDTH_ATTRIBUTE_NAME = "width";
private static final String HEIGHT_ATTRIBUTE_NAME = "height";
private static final String BACKGROUND_COLOR_ATTRIBUTE_NAME = "backgroundColor";
private static final String TITLE_ATTRIBUTE_NAME = "title";
SmilRootLayoutElementImpl(SmilDocumentImpl owner, String tagName) {
super(owner, tagName);
}
public String getBackgroundColor() {
return this.getAttribute(BACKGROUND_COLOR_ATTRIBUTE_NAME);
}
public int getHeight() {
String heightString = this.getAttribute(HEIGHT_ATTRIBUTE_NAME);
return parseAbsoluteLength(heightString);
}
public String getTitle() {
return this.getAttribute(TITLE_ATTRIBUTE_NAME);
}
public int getWidth() {
String widthString = this.getAttribute(WIDTH_ATTRIBUTE_NAME);
return parseAbsoluteLength(widthString);
}
public void setBackgroundColor(String backgroundColor) throws DOMException {
this.setAttribute(BACKGROUND_COLOR_ATTRIBUTE_NAME, backgroundColor);
}
public void setHeight(int height) throws DOMException {
this.setAttribute(HEIGHT_ATTRIBUTE_NAME, String.valueOf(height) + "px");
}
public void setTitle(String title) throws DOMException {
this.setAttribute(TITLE_ATTRIBUTE_NAME, title);
}
public void setWidth(int width) throws DOMException {
this.setAttribute(WIDTH_ATTRIBUTE_NAME, String.valueOf(width) + "px");
}
/*
* Internal Interface
*/
private int parseAbsoluteLength(String length) {
if (length.endsWith("px")) {
length = length.substring(0, length.indexOf("px"));
}
try {
return Integer.parseInt(length);
} catch (NumberFormatException e) {
return 0;
}
}
}

View File

@ -1,295 +0,0 @@
/*
* Copyright (C) 2007-2008 Esmertec AG.
* Copyright (C) 2007-2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thoughtcrime.securesms.dom.smil;
import org.w3c.dom.DOMException;
import org.w3c.dom.Element;
import org.w3c.dom.smil.Time;
public class TimeImpl implements Time {
static final int ALLOW_INDEFINITE_VALUE = (1 << 0);
static final int ALLOW_OFFSET_VALUE = (1 << 1);
static final int ALLOW_SYNCBASE_VALUE = (1 << 2);
static final int ALLOW_SYNCTOPREV_VALUE = (1 << 3);
static final int ALLOW_EVENT_VALUE = (1 << 4);
static final int ALLOW_MARKER_VALUE = (1 << 5);
static final int ALLOW_WALLCLOCK_VALUE = (1 << 6);
static final int ALLOW_NEGATIVE_VALUE = (1 << 7);
static final int ALLOW_ALL = 0xFF;
short mTimeType;
boolean mResolved;
double mResolvedOffset;
/**
* Creates a TimeImpl representation of a time-value represented as a String.
* Time-values have the following syntax:
* <p>
* <pre>
* Time-val ::= ( smil-1.0-syncbase-value
* | "indefinite"
* | offset-value
* | syncbase-value
* | syncToPrev-value
* | event-value
* | media-marker-value
* | wallclock-sync-value )
* Smil-1.0-syncbase-value ::=
* "id(" id-ref ")" ( "(" ( "begin" | "end" | clock-value ) ")" )?
* Offset-value ::= ( "+" | "-" )? clock-value
* Syncbase-value ::= ( id-ref "." ( "begin" | "end" ) ) ( ( "+" | "-" ) clock-value )?
* SyncToPrev-value ::= ( "prev.begin" | "prev.end" ) ( ( "+" | "-" ) clock-value )?
* Event-value ::= ( id-ref "." )? ( event-ref ) ( ( "+" | "-" ) clock-value )?
* Media-marker-value ::= id-ref ".marker(" marker-name ")"
* Wallclock-sync-value ::= "wallclock(" wallclock-value ")"
* </pre>
*
* @param timeValue A String in the representation specified above
* @param constraints Any combination of the #ALLOW_* flags
* @return A TimeImpl instance representing
* @exception java.lang.IllegalArgumentException if the timeValue input
* parameter does not comply with the defined syntax
* @exception java.lang.NullPointerException if the timekValue string is
* <code>null</code>
*/
TimeImpl(String timeValue, int constraints) {
/*
* We do not support yet:
* - smil-1.0-syncbase-value
* - syncbase-value
* - syncToPrev-value
* - event-value
* - Media-marker-value
* - Wallclock-sync-value
*/
// Will throw NullPointerException if timeValue is null
if (timeValue.equals("indefinite")
&& ((constraints & ALLOW_INDEFINITE_VALUE) != 0) ) {
mTimeType = SMIL_TIME_INDEFINITE;
} else if ((constraints & ALLOW_OFFSET_VALUE) != 0) {
int sign = 1;
if (timeValue.startsWith("+")) {
timeValue = timeValue.substring(1);
} else if (timeValue.startsWith("-")) {
timeValue = timeValue.substring(1);
sign = -1;
}
mResolvedOffset = sign*parseClockValue(timeValue)/1000.0;
mResolved = true;
mTimeType = SMIL_TIME_OFFSET;
} else {
throw new IllegalArgumentException("Unsupported time value");
}
}
/**
* Converts a String representation of a clock value into the float
* representation used in this API.
* <p>
* Clock values have the following syntax:
* </p>
* <p>
* <pre>
* Clock-val ::= ( Full-clock-val | Partial-clock-val | Timecount-val )
* Full-clock-val ::= Hours ":" Minutes ":" Seconds ("." Fraction)?
* Partial-clock-val ::= Minutes ":" Seconds ("." Fraction)?
* Timecount-val ::= Timecount ("." Fraction)? (Metric)?
* Metric ::= "h" | "min" | "s" | "ms"
* Hours ::= DIGIT+; any positive number
* Minutes ::= 2DIGIT; range from 00 to 59
* Seconds ::= 2DIGIT; range from 00 to 59
* Fraction ::= DIGIT+
* Timecount ::= DIGIT+
* 2DIGIT ::= DIGIT DIGIT
* DIGIT ::= [0-9]
* </pre>
*
* @param clockValue A String in the representation specified above
* @return A float value in milliseconds that matches the string
* representation given as the parameter
* @exception java.lang.IllegalArgumentException if the clockValue input
* parameter does not comply with the defined syntax
* @exception java.lang.NullPointerException if the clockValue string is
* <code>null</code>
*/
public static float parseClockValue(String clockValue) {
try {
float result = 0;
// Will throw NullPointerException if clockValue is null
clockValue = clockValue.trim();
// Handle first 'Timecount-val' cases with metric
if (clockValue.endsWith("ms")) {
result = parseFloat(clockValue, 2, true);
} else if (clockValue.endsWith("s")) {
result = 1000*parseFloat(clockValue, 1, true);
} else if (clockValue.endsWith("min")) {
result = 60000*parseFloat(clockValue, 3, true);
} else if (clockValue.endsWith("h")) {
result = 3600000*parseFloat(clockValue, 1, true);
} else {
// Handle Timecount-val without metric
try {
return parseFloat(clockValue, 0, true) * 1000;
} catch (NumberFormatException _) {
// Ignore
}
// Split in {[Hours], Minutes, Seconds}
String[] timeValues = clockValue.split(":");
// Read Hours if present and remember location of Minutes
int indexOfMinutes;
if (timeValues.length == 2) {
indexOfMinutes = 0;
} else if (timeValues.length == 3) {
result = 3600000*(int)parseFloat(timeValues[0], 0, false);
indexOfMinutes = 1;
} else {
throw new IllegalArgumentException();
}
// Read Minutes
int minutes = (int)parseFloat(timeValues[indexOfMinutes], 0, false);
if ((minutes >= 00) && (minutes <= 59)) {
result += 60000*minutes;
} else {
throw new IllegalArgumentException();
}
// Read Seconds
float seconds = parseFloat(timeValues[indexOfMinutes + 1], 0, true);
if ((seconds >= 00) && (seconds < 60)) {
result += 60000*seconds;
} else {
throw new IllegalArgumentException();
}
}
return result;
} catch (NumberFormatException e) {
throw new IllegalArgumentException();
}
}
/**
* Parse a value formatted as follows:
* <p>
* <pre>
* Value ::= Number ("." Decimal)? (Text)?
* Number ::= DIGIT+; any positive number
* Decimal ::= DIGIT+; any positive number
* Text ::= CHAR*; any sequence of chars
* DIGIT ::= [0-9]
* </pre>
* @param value The Value to parse
* @param ignoreLast The size of Text to ignore
* @param parseDecimal Whether Decimal is expected
* @return The float value without Text, rounded to 3 digits after '.'
* @throws IllegalArgumentException if Decimal was not expected but encountered
*/
private static float parseFloat(String value, int ignoreLast, boolean parseDecimal) {
// Ignore last characters
value = value.substring(0, value.length() - ignoreLast);
float result;
int indexOfComma = value.indexOf('.');
if (indexOfComma != -1) {
if (!parseDecimal) {
throw new IllegalArgumentException("int value contains decimal");
}
// Ensure that there are at least 3 decimals
value = value + "000";
// Read value up to 3 decimals and cut the rest
result = Float.parseFloat(value.substring(0, indexOfComma));
result += Float.parseFloat(
value.substring(indexOfComma + 1, indexOfComma + 4))/1000;
} else {
result = Integer.parseInt(value);
}
return result;
}
/*
* Time Interface
*/
public boolean getBaseBegin() {
// TODO Auto-generated method stub
return false;
}
public Element getBaseElement() {
// TODO Auto-generated method stub
return null;
}
public String getEvent() {
// TODO Auto-generated method stub
return null;
}
public String getMarker() {
// TODO Auto-generated method stub
return null;
}
public double getOffset() {
// TODO Auto-generated method stub
return 0;
}
public boolean getResolved() {
return mResolved;
}
public double getResolvedOffset() {
return mResolvedOffset;
}
public short getTimeType() {
return mTimeType;
}
public void setBaseBegin(boolean baseBegin) throws DOMException {
// TODO Auto-generated method stub
}
public void setBaseElement(Element baseElement) throws DOMException {
// TODO Auto-generated method stub
}
public void setEvent(String event) throws DOMException {
// TODO Auto-generated method stub
}
public void setMarker(String marker) throws DOMException {
// TODO Auto-generated method stub
}
public void setOffset(double offset) throws DOMException {
// TODO Auto-generated method stub
}
}

View File

@ -1,53 +0,0 @@
/*
* Copyright (C) 2007 Esmertec AG.
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thoughtcrime.securesms.dom.smil;
import java.util.ArrayList;
import org.w3c.dom.smil.Time;
import org.w3c.dom.smil.TimeList;
public class TimeListImpl implements TimeList {
private final ArrayList<Time> mTimes;
/*
* Internal Interface
*/
TimeListImpl(ArrayList<Time> times) {
mTimes = times;
}
/*
* TimeList Interface
*/
public int getLength() {
return mTimes.size();
}
public Time item(int index) {
Time time = null;
try {
time = mTimes.get(index);
} catch (IndexOutOfBoundsException e) {
// Do nothing and return null
}
return time;
}
}

View File

@ -1,80 +0,0 @@
/*
* Copyright (C) 2007 Esmertec AG.
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thoughtcrime.securesms.dom.smil.parser;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import org.w3c.dom.Attr;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.smil.SMILDocument;
import org.w3c.dom.smil.SMILElement;
public class SmilXmlSerializer {
public static void serialize(SMILDocument smilDoc, OutputStream out) {
try {
Writer writer = new BufferedWriter(new OutputStreamWriter(out, "UTF-8"), 2048);
writeElement(writer, smilDoc.getDocumentElement());
writer.flush();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private static void writeElement(Writer writer, Element element)
throws IOException {
writer.write('<');
writer.write(element.getTagName());
if (element.hasAttributes()) {
NamedNodeMap attributes = element.getAttributes();
for (int i = 0; i < attributes.getLength(); i++) {
Attr attribute = (Attr)attributes.item(i);
writer.write(" " + attribute.getName());
writer.write("=\"" + attribute.getValue() + "\"");
}
}
// FIXME: Might throw ClassCastException
SMILElement childElement = (SMILElement) element.getFirstChild();
if (childElement != null) {
writer.write('>');
do {
writeElement(writer, childElement);
childElement = (SMILElement) childElement.getNextSibling();
} while (childElement != null);
writer.write("</");
writer.write(element.getTagName());
writer.write('>');
} else {
writer.write("/>");
}
}
}

View File

@ -22,6 +22,7 @@ import org.thoughtcrime.securesms.recipients.Recipients;
import org.thoughtcrime.securesms.sms.MessageSender;
import org.thoughtcrime.securesms.util.BitmapUtil;
import org.thoughtcrime.securesms.util.GroupUtil;
import org.thoughtcrime.securesms.util.MediaUtil;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.Util;
import org.whispersystems.signalservice.api.util.InvalidNumberException;
@ -32,8 +33,6 @@ import java.util.HashSet;
import java.util.LinkedList;
import java.util.Set;
import ws.com.google.android.mms.ContentType;
public class GroupManager {
public static @NonNull GroupActionResult createGroup(@NonNull Context context,
@NonNull MasterSecret masterSecret,
@ -104,7 +103,7 @@ public class GroupManager {
if (avatar != null) {
Uri avatarUri = SingleUseBlobProvider.getInstance().createUri(avatar);
avatarAttachment = new UriAttachment(avatarUri, ContentType.IMAGE_PNG, AttachmentDatabase.TRANSFER_PROGRESS_DONE, avatar.length, null);
avatarAttachment = new UriAttachment(avatarUri, MediaUtil.IMAGE_PNG, AttachmentDatabase.TRANSFER_PROGRESS_DONE, avatar.length, null);
}
OutgoingGroupMediaMessage outgoingMessage = new OutgoingGroupMediaMessage(groupRecipient, groupContext, avatarAttachment, System.currentTimeMillis(), 0);

View File

@ -37,7 +37,7 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import ws.com.google.android.mms.MmsException;
import org.thoughtcrime.securesms.mms.MmsException;
import static org.thoughtcrime.securesms.database.GroupDatabase.GroupRecord;
import static org.whispersystems.signalservice.internal.push.SignalServiceProtos.AttachmentPointer;

View File

@ -36,7 +36,7 @@ import java.io.InputStream;
import javax.inject.Inject;
import ws.com.google.android.mms.MmsException;
import org.thoughtcrime.securesms.mms.MmsException;
public class AttachmentDownloadJob extends MasterSecretJob implements InjectableType {
private static final long serialVersionUID = 1L;

View File

@ -3,7 +3,12 @@ package org.thoughtcrime.securesms.jobs;
import android.content.Context;
import android.net.Uri;
import android.util.Log;
import android.util.Pair;
import com.google.android.mms.pdu_alt.CharacterSets;
import com.google.android.mms.pdu_alt.EncodedStringValue;
import com.google.android.mms.pdu_alt.PduBody;
import com.google.android.mms.pdu_alt.PduPart;
import com.google.android.mms.pdu_alt.RetrieveConf;
import org.thoughtcrime.securesms.attachments.Attachment;
import org.thoughtcrime.securesms.attachments.UriAttachment;
@ -32,16 +37,12 @@ import org.whispersystems.libsignal.NoSessionException;
import org.whispersystems.libsignal.util.guava.Optional;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import ws.com.google.android.mms.MmsException;
import ws.com.google.android.mms.pdu.EncodedStringValue;
import ws.com.google.android.mms.pdu.NotificationInd;
import ws.com.google.android.mms.pdu.PduBody;
import ws.com.google.android.mms.pdu.PduPart;
import ws.com.google.android.mms.pdu.RetrieveConf;
import org.thoughtcrime.securesms.mms.MmsException;
public class MmsDownloadJob extends MasterSecretJob {
@ -75,8 +76,8 @@ public class MmsDownloadJob extends MasterSecretJob {
@Override
public void onRun(MasterSecret masterSecret) {
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
Optional<Pair<NotificationInd, Integer>> notification = database.getNotification(messageId);
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
Optional<MmsDatabase.MmsNotificationInfo> notification = database.getNotification(messageId);
if (!notification.isPresent()) {
Log.w(TAG, "No notification for ID: " + messageId);
@ -84,24 +85,30 @@ public class MmsDownloadJob extends MasterSecretJob {
}
try {
if (notification.get().first.getContentLocation() == null) {
if (notification.get().getContentLocation() == null) {
throw new MmsException("Notification content location was null.");
}
database.markDownloadState(messageId, MmsDatabase.Status.DOWNLOAD_CONNECTING);
String contentLocation = new String(notification.get().first.getContentLocation());
byte[] transactionId = notification.get().first.getTransactionId();
String contentLocation = notification.get().getContentLocation();
byte[] transactionId = new byte[0];
try {
transactionId = notification.get().getTransactionId().getBytes(CharacterSets.MIMENAME_ISO_8859_1);
} catch (UnsupportedEncodingException e) {
Log.w(TAG, e);
}
Log.w(TAG, "Downloading mms at " + Uri.parse(contentLocation).getHost());
RetrieveConf retrieveConf = new CompatMmsConnection(context).retrieve(contentLocation, transactionId, notification.get().second);
RetrieveConf retrieveConf = new CompatMmsConnection(context).retrieve(contentLocation, transactionId, notification.get().getSubscriptionId());
if (retrieveConf == null) {
throw new MmsException("RetrieveConf was null");
}
storeRetrievedMms(masterSecret, contentLocation, messageId, threadId, retrieveConf, notification.get().second);
storeRetrievedMms(masterSecret, contentLocation, messageId, threadId, retrieveConf, notification.get().getSubscriptionId());
} catch (ApnUnavailableException e) {
Log.w(TAG, e);
handleDownloadError(masterSecret, messageId, threadId, MmsDatabase.Status.DOWNLOAD_APN_UNAVAILABLE,

View File

@ -4,6 +4,11 @@ import android.content.Context;
import android.util.Log;
import android.util.Pair;
import com.google.android.mms.pdu_alt.GenericPdu;
import com.google.android.mms.pdu_alt.NotificationInd;
import com.google.android.mms.pdu_alt.PduHeaders;
import com.google.android.mms.pdu_alt.PduParser;
import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.MmsDatabase;
@ -12,11 +17,6 @@ import org.thoughtcrime.securesms.recipients.Recipients;
import org.thoughtcrime.securesms.util.Util;
import org.whispersystems.jobqueue.JobParameters;
import ws.com.google.android.mms.pdu.GenericPdu;
import ws.com.google.android.mms.pdu.NotificationInd;
import ws.com.google.android.mms.pdu.PduHeaders;
import ws.com.google.android.mms.pdu.PduParser;
public class MmsReceiveJob extends ContextJob {
private static final long serialVersionUID = 1L;

View File

@ -3,13 +3,27 @@ package org.thoughtcrime.securesms.jobs;
import android.content.Context;
import android.text.TextUtils;
import android.util.Log;
import android.webkit.MimeTypeMap;
import com.android.mms.dom.smil.parser.SmilXmlSerializer;
import com.google.android.mms.ContentType;
import com.google.android.mms.InvalidHeaderValueException;
import com.google.android.mms.pdu_alt.CharacterSets;
import com.google.android.mms.pdu_alt.EncodedStringValue;
import com.google.android.mms.pdu_alt.PduBody;
import com.google.android.mms.pdu_alt.PduComposer;
import com.google.android.mms.pdu_alt.PduHeaders;
import com.google.android.mms.pdu_alt.PduPart;
import com.google.android.mms.pdu_alt.SendConf;
import com.google.android.mms.pdu_alt.SendReq;
import com.google.android.mms.smil.SmilHelper;
import com.klinker.android.send_message.Utils;
import org.thoughtcrime.securesms.attachments.Attachment;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.MmsDatabase;
import org.thoughtcrime.securesms.database.NoSuchMessageException;
import org.thoughtcrime.securesms.database.ThreadDatabase.DistributionTypes;
import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement;
import org.thoughtcrime.securesms.mms.CompatMmsConnection;
import org.thoughtcrime.securesms.mms.MediaConstraints;
@ -22,26 +36,16 @@ import org.thoughtcrime.securesms.transport.InsecureFallbackApprovalException;
import org.thoughtcrime.securesms.transport.UndeliverableMessageException;
import org.thoughtcrime.securesms.util.Hex;
import org.thoughtcrime.securesms.util.NumberUtil;
import org.thoughtcrime.securesms.util.SmilUtil;
import org.thoughtcrime.securesms.util.TelephonyUtil;
import org.thoughtcrime.securesms.util.Util;
import org.whispersystems.jobqueue.JobParameters;
import org.whispersystems.jobqueue.requirements.NetworkRequirement;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import ws.com.google.android.mms.ContentType;
import ws.com.google.android.mms.MmsException;
import ws.com.google.android.mms.pdu.CharacterSets;
import ws.com.google.android.mms.pdu.EncodedStringValue;
import ws.com.google.android.mms.pdu.PduBody;
import ws.com.google.android.mms.pdu.PduComposer;
import ws.com.google.android.mms.pdu.PduHeaders;
import ws.com.google.android.mms.pdu.PduPart;
import ws.com.google.android.mms.pdu.SendConf;
import ws.com.google.android.mms.pdu.SendReq;
import org.thoughtcrime.securesms.mms.MmsException;
public class MmsSendJob extends SendJob {
@ -64,8 +68,7 @@ public class MmsSendJob extends SendJob {
@Override
public void onAdded() {
// MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
// database.markAsSending(messageId);
}
@Override
@ -109,14 +112,6 @@ public class MmsSendJob extends SendJob {
private byte[] getPduBytes(SendReq message)
throws IOException, UndeliverableMessageException, InsecureFallbackApprovalException
{
String number = TelephonyUtil.getManager(context).getLine1Number();
message.setBody(SmilUtil.getSmilBody(message.getBody()));
if (!TextUtils.isEmpty(number)) {
message.setFrom(new EncodedStringValue(number));
}
byte[] pduBytes = new PduComposer(context, message).make();
if (pduBytes == null) {
@ -174,51 +169,100 @@ public class MmsSendJob extends SendJob {
private SendReq constructSendPdu(MasterSecret masterSecret, OutgoingMediaMessage message)
throws UndeliverableMessageException
{
SendReq sendReq = new SendReq();
PduBody body = new PduBody();
List<String> numbers = message.getRecipients().toNumberStringList(true);
SendReq req = new SendReq();
String lineNumber = Utils.getMyPhoneNumber(context);
List<String> numbers = message.getRecipients().toNumberStringList(true);
MediaConstraints mediaConstraints = MediaConstraints.getMmsMediaConstraints(message.getSubscriptionId());
List<Attachment> scaledAttachments = scaleAttachments(masterSecret, mediaConstraints, message.getAttachments());
for (String number : numbers) {
if (message.getDistributionType() == DistributionTypes.CONVERSATION) {
sendReq.addTo(new EncodedStringValue(Util.toIsoBytes(number)));
} else {
sendReq.addBcc(new EncodedStringValue(Util.toIsoBytes(number)));
}
if (!TextUtils.isEmpty(lineNumber)) {
req.setFrom(new EncodedStringValue(lineNumber));
}
sendReq.setDate(message.getSentTimeMillis() / 1000L);
for (String recipient : numbers) {
req.addTo(new EncodedStringValue(recipient));
}
req.setDate(System.currentTimeMillis() / 1000);
PduBody body = new PduBody();
int size = 0;
if (!TextUtils.isEmpty(message.getBody())) {
PduPart part = new PduPart();
String name = String.valueOf(System.currentTimeMillis());
part.setData(Util.toUtf8Bytes(message.getBody()));
part.setCharset(CharacterSets.UTF_8);
part.setContentType(ContentType.TEXT_PLAIN.getBytes());
part.setContentId((System.currentTimeMillis()+"").getBytes());
part.setName(("Text"+System.currentTimeMillis()).getBytes());
part.setContentId(name.getBytes());
part.setContentLocation((name + ".txt").getBytes());
part.setName((name + ".txt").getBytes());
body.addPart(part);
size += getPartSize(part);
}
List<Attachment> scaledAttachments = scaleAttachments(masterSecret, MediaConstraints.MMS_CONSTRAINTS, message.getAttachments());
for (Attachment attachment : scaledAttachments) {
try {
if (attachment.getDataUri() == null) throw new IOException("Assertion failed, attachment for outgoing MMS has no data!");
PduPart part = new PduPart();
String fileName = attachment.getFileName();
PduPart part = new PduPart();
if (fileName == null) {
fileName = String.valueOf(Math.abs(Util.getSecureRandom().nextLong()));
String fileExtension = MimeTypeMap.getSingleton().getExtensionFromMimeType(attachment.getContentType());
if (fileExtension != null) fileName = fileName + "." + fileExtension;
}
if (attachment.getContentType().startsWith("text")) {
part.setCharset(CharacterSets.UTF_8);
}
part.setContentType(attachment.getContentType().getBytes());
part.setContentLocation(fileName.getBytes());
part.setName(fileName.getBytes());
int index = fileName.lastIndexOf(".");
String contentId = (index == -1) ? fileName : fileName.substring(0, index);
part.setContentId(contentId.getBytes());
part.setData(Util.readFully(PartAuthority.getAttachmentStream(context, masterSecret, attachment.getDataUri())));
part.setContentType(Util.toIsoBytes(attachment.getContentType()));
part.setContentId((System.currentTimeMillis() + "").getBytes());
part.setName((System.currentTimeMillis() + "").getBytes());
body.addPart(part);
size += getPartSize(part);
} catch (IOException e) {
Log.w(TAG, e);
}
}
sendReq.setBody(body);
return sendReq;
ByteArrayOutputStream out = new ByteArrayOutputStream();
SmilXmlSerializer.serialize(SmilHelper.createSmilDocument(body), out);
PduPart smilPart = new PduPart();
smilPart.setContentId("smil".getBytes());
smilPart.setContentLocation("smil.xml".getBytes());
smilPart.setContentType(ContentType.APP_SMIL.getBytes());
smilPart.setData(out.toByteArray());
body.addPart(0, smilPart);
req.setBody(body);
req.setMessageSize(size);
req.setMessageClass(PduHeaders.MESSAGE_CLASS_PERSONAL_STR.getBytes());
req.setExpiry(7 * 24 * 60 * 60);
try {
req.setPriority(PduHeaders.PRIORITY_NORMAL);
req.setDeliveryReport(PduHeaders.VALUE_NO);
req.setReadReport(PduHeaders.VALUE_NO);
} catch (InvalidHeaderValueException e) {}
return req;
}
private long getPartSize(PduPart part) {
return part.getName().length + part.getContentLocation().length +
part.getContentType().length + part.getData().length +
part.getContentId().length;
}
private void notifyMediaMessageDeliveryFailed(Context context, long messageId) {

View File

@ -7,7 +7,6 @@ import android.util.Log;
import android.util.Pair;
import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.attachments.Attachment;
import org.thoughtcrime.securesms.attachments.DatabaseAttachment;
import org.thoughtcrime.securesms.attachments.PointerAttachment;
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil;
@ -77,11 +76,10 @@ import org.whispersystems.signalservice.api.messages.multidevice.SentTranscriptM
import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage;
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
import ws.com.google.android.mms.MmsException;
import org.thoughtcrime.securesms.mms.MmsException;
public class PushDecryptJob extends ContextJob {

View File

@ -13,6 +13,7 @@ import org.thoughtcrime.securesms.database.documents.NetworkFailure;
import org.thoughtcrime.securesms.dependencies.InjectableType;
import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement;
import org.thoughtcrime.securesms.mms.MediaConstraints;
import org.thoughtcrime.securesms.mms.MmsException;
import org.thoughtcrime.securesms.mms.OutgoingGroupMediaMessage;
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
import org.thoughtcrime.securesms.recipients.Recipient;
@ -40,8 +41,6 @@ import java.util.List;
import javax.inject.Inject;
import ws.com.google.android.mms.MmsException;
import static org.thoughtcrime.securesms.dependencies.SignalCommunicationModule.SignalMessageSenderFactory;
public class PushGroupSendJob extends PushSendJob implements InjectableType {
@ -139,7 +138,8 @@ public class PushGroupSendJob extends PushSendJob implements InjectableType {
SignalServiceMessageSender messageSender = messageSenderFactory.create();
byte[] groupId = GroupUtil.getDecodedId(message.getRecipients().getPrimaryRecipient().getNumber());
Recipients recipients = DatabaseFactory.getGroupDatabase(context).getGroupMembers(groupId, false);
List<Attachment> scaledAttachments = scaleAttachments(masterSecret, MediaConstraints.PUSH_CONSTRAINTS, message.getAttachments());
MediaConstraints mediaConstraints = MediaConstraints.getPushMediaConstraints();
List<Attachment> scaledAttachments = scaleAttachments(masterSecret, mediaConstraints, message.getAttachments());
List<SignalServiceAttachment> attachmentStreams = getAttachmentsFor(masterSecret, scaledAttachments);
List<SignalServiceAddress> addresses;

View File

@ -32,7 +32,7 @@ import java.util.List;
import javax.inject.Inject;
import ws.com.google.android.mms.MmsException;
import org.thoughtcrime.securesms.mms.MmsException;
import static org.thoughtcrime.securesms.dependencies.SignalCommunicationModule.SignalMessageSenderFactory;
@ -119,7 +119,8 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType {
try {
SignalServiceAddress address = getPushAddress(message.getRecipients().getPrimaryRecipient().getNumber());
List<Attachment> scaledAttachments = scaleAttachments(masterSecret, MediaConstraints.PUSH_CONSTRAINTS, message.getAttachments());
MediaConstraints mediaConstraints = MediaConstraints.getPushMediaConstraints();
List<Attachment> scaledAttachments = scaleAttachments(masterSecret, mediaConstraints, message.getAttachments());
List<SignalServiceAttachment> attachmentStreams = getAttachmentsFor(masterSecret, scaledAttachments);
SignalServiceDataMessage mediaMessage = SignalServiceDataMessage.newBuilder()
.withBody(message.getBody())

View File

@ -30,8 +30,6 @@ import java.io.InputStream;
import java.util.LinkedList;
import java.util.List;
import ws.com.google.android.mms.ContentType;
public abstract class PushSendJob extends SendJob {
private static final String TAG = PushSendJob.class.getSimpleName();

View File

@ -7,23 +7,19 @@ import org.thoughtcrime.securesms.BuildConfig;
import org.thoughtcrime.securesms.TextSecureExpiredException;
import org.thoughtcrime.securesms.attachments.Attachment;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.AttachmentDatabase;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.mms.MediaConstraints;
import org.thoughtcrime.securesms.mms.MediaStream;
import org.thoughtcrime.securesms.mms.MmsException;
import org.thoughtcrime.securesms.transport.UndeliverableMessageException;
import org.thoughtcrime.securesms.util.MediaUtil;
import org.thoughtcrime.securesms.util.Util;
import org.whispersystems.jobqueue.JobParameters;
import java.io.IOException;
import java.io.InputStream;
import java.util.LinkedList;
import java.util.List;
import ws.com.google.android.mms.ContentType;
import ws.com.google.android.mms.MmsException;
public abstract class SendJob extends MasterSecretJob {
private final static String TAG = SendJob.class.getSimpleName();

View File

@ -19,8 +19,6 @@ import org.whispersystems.jobqueue.requirements.Requirement;
import java.util.Collections;
import java.util.Set;
import ws.com.google.android.mms.ContentType;
public class MediaNetworkRequirement implements Requirement, ContextDependent {
private static final long serialVersionUID = 0L;
private static final String TAG = MediaNetworkRequirement.class.getSimpleName();
@ -112,8 +110,8 @@ public class MediaNetworkRequirement implements Requirement, ContextDependent {
private boolean isNonDocumentType(String contentType) {
return
ContentType.isImageType(contentType) ||
ContentType.isVideoType(contentType) ||
ContentType.isAudioType(contentType);
MediaUtil.isImageType(contentType) ||
MediaUtil.isVideoType(contentType) ||
MediaUtil.isAudioType(contentType);
}
}

View File

@ -35,7 +35,6 @@ import android.util.Log;
import android.view.View;
import android.widget.Toast;
import com.bumptech.glide.Glide;
import com.google.android.gms.common.GooglePlayServicesNotAvailableException;
import com.google.android.gms.common.GooglePlayServicesRepairableException;
import com.google.android.gms.location.places.ui.PlacePicker;
@ -67,7 +66,6 @@ import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import ws.com.google.android.mms.ContentType;
public class AttachmentManager {
@ -192,7 +190,7 @@ public class AttachmentManager {
public void onSuccess(@NonNull Bitmap result) {
byte[] blob = BitmapUtil.toByteArray(result);
Uri uri = PersistentBlobProvider.getInstance(context)
.create(masterSecret, blob, ContentType.IMAGE_PNG);
.create(masterSecret, blob, MediaUtil.IMAGE_PNG);
LocationSlide locationSlide = new LocationSlide(context, uri, blob.length, place);
setSlide(locationSlide);
@ -204,7 +202,8 @@ 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)
{
inflateStub();
new AsyncTask<Void, Void, Slide>() {
@ -350,7 +349,7 @@ public class AttachmentManager {
if (captureIntent.resolveActivity(activity.getPackageManager()) != null) {
if (captureUri == null) {
captureUri = PersistentBlobProvider.getInstance(context)
.createForExternal(ContentType.IMAGE_JPEG);
.createForExternal(MediaUtil.IMAGE_JPEG);
}
Log.w(TAG, "captureUri path is " + captureUri.getPath());
captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, captureUri);
@ -462,11 +461,11 @@ public class AttachmentManager {
}
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 (MediaUtil.isImageType(mimeType)) return IMAGE;
if (MediaUtil.isAudioType(mimeType)) return AUDIO;
if (MediaUtil.isVideoType(mimeType)) return VIDEO;
return null;
}

View File

@ -27,17 +27,14 @@ import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.attachments.Attachment;
import org.thoughtcrime.securesms.attachments.UriAttachment;
import org.thoughtcrime.securesms.database.AttachmentDatabase;
import org.thoughtcrime.securesms.util.MediaUtil;
import org.thoughtcrime.securesms.util.ResUtil;
import java.io.IOException;
import ws.com.google.android.mms.ContentType;
import ws.com.google.android.mms.pdu.PduPart;
public class AudioSlide extends Slide {
public AudioSlide(Context context, Uri uri, long dataSize) {
super(context, constructAttachmentFromUri(context, uri, ContentType.AUDIO_UNSPECIFIED, dataSize, false, null));
super(context, constructAttachmentFromUri(context, uri, MediaUtil.AUDIO_UNSPECIFIED, dataSize, false, null));
}
public AudioSlide(Context context, Uri uri, long dataSize, String contentType) {

View File

@ -1,22 +1,20 @@
package org.thoughtcrime.securesms.mms;
import android.content.Context;
import android.os.Build;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;
import com.google.android.mms.pdu_alt.PduHeaders;
import com.google.android.mms.pdu_alt.RetrieveConf;
import com.google.android.mms.pdu_alt.SendConf;
import org.thoughtcrime.securesms.transport.UndeliverableMessageException;
import java.io.IOException;
import ws.com.google.android.mms.MmsException;
import ws.com.google.android.mms.pdu.PduHeaders;
import ws.com.google.android.mms.pdu.RetrieveConf;
import ws.com.google.android.mms.pdu.SendConf;
public class CompatMmsConnection implements OutgoingMmsConnection, IncomingMmsConnection {
private static final String TAG = CompatMmsConnection.class.getSimpleName();
@ -31,7 +29,18 @@ public class CompatMmsConnection implements OutgoingMmsConnection, IncomingMmsCo
public SendConf send(@NonNull byte[] pduBytes, int subscriptionId)
throws UndeliverableMessageException
{
if (subscriptionId == -1 || VERSION.SDK_INT < 22) {
if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
try {
Log.w(TAG, "Sending via Lollipop API");
return new OutgoingLollipopMmsConnection(context).send(pduBytes, subscriptionId);
} catch (UndeliverableMessageException e) {
Log.w(TAG, e);
}
}
Log.w(TAG, "Falling back to legacy connection...");
if (subscriptionId == -1) {
Log.w(TAG, "Sending via legacy connection");
try {
SendConf result = new OutgoingLegacyMmsConnection(context).send(pduBytes, subscriptionId);
@ -46,11 +55,7 @@ public class CompatMmsConnection implements OutgoingMmsConnection, IncomingMmsCo
}
}
if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
return new OutgoingLollipopMmsConnection(context).send(pduBytes, subscriptionId);
} else {
throw new UndeliverableMessageException("Lollipop API not available to try...");
}
throw new UndeliverableMessageException("Both lollipop and legacy connections failed...");
}
@Nullable
@ -60,8 +65,13 @@ public class CompatMmsConnection implements OutgoingMmsConnection, IncomingMmsCo
int subscriptionId)
throws MmsException, MmsRadioException, ApnUnavailableException, IOException
{
if (VERSION.SDK_INT < 22 || subscriptionId == -1) {
Log.w(TAG, "Receiving via legacy connection");
if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
Log.w(TAG, "Receiving via Lollipop API");
return new IncomingLollipopMmsConnection(context).retrieve(contentLocation, transactionId, subscriptionId);
}
if (subscriptionId == -1) {
Log.w(TAG, "Falling back to receiving via legacy connection");
try {
return new IncomingLegacyMmsConnection(context).retrieve(contentLocation, transactionId, subscriptionId);
} catch (MmsRadioException | ApnUnavailableException | IOException e) {
@ -69,11 +79,6 @@ public class CompatMmsConnection implements OutgoingMmsConnection, IncomingMmsCo
}
}
if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
Log.w(TAG, "Falling back to try receiving via Lollipop API");
return new IncomingLollipopMmsConnection(context).retrieve(contentLocation, transactionId, subscriptionId);
} else {
throw new IOException("Not able to use Lollipop APIs, giving up...");
}
throw new IOException("Both lollipop and fallback APIs failed...");
}
}

View File

@ -5,13 +5,7 @@ import android.net.Uri;
import android.support.annotation.Nullable;
import org.thoughtcrime.securesms.attachments.Attachment;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import java.io.IOException;
import java.io.InputStream;
import ws.com.google.android.mms.ContentType;
import ws.com.google.android.mms.pdu.PduPart;
import org.thoughtcrime.securesms.util.MediaUtil;
public class GifSlide extends ImageSlide {
@ -20,7 +14,7 @@ public class GifSlide extends ImageSlide {
}
public GifSlide(Context context, Uri uri, long size) {
super(context, constructAttachmentFromUri(context, uri, ContentType.IMAGE_GIF, size, true, null));
super(context, constructAttachmentFromUri(context, uri, MediaUtil.IMAGE_GIF, size, true, null));
}
@Override

View File

@ -24,8 +24,7 @@ import android.support.annotation.NonNull;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.attachments.Attachment;
import ws.com.google.android.mms.ContentType;
import org.thoughtcrime.securesms.util.MediaUtil;
public class ImageSlide extends Slide {
@ -36,7 +35,7 @@ public class ImageSlide extends Slide {
}
public ImageSlide(Context context, Uri uri, long size) {
super(context, constructAttachmentFromUri(context, uri, ContentType.IMAGE_JPEG, size, true, null));
super(context, constructAttachmentFromUri(context, uri, MediaUtil.IMAGE_JPEG, size, true, null));
}
@Override

View File

@ -22,6 +22,13 @@ import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;
import com.google.android.mms.InvalidHeaderValueException;
import com.google.android.mms.pdu_alt.NotifyRespInd;
import com.google.android.mms.pdu_alt.PduComposer;
import com.google.android.mms.pdu_alt.PduHeaders;
import com.google.android.mms.pdu_alt.PduParser;
import com.google.android.mms.pdu_alt.RetrieveConf;
import org.apache.http.Header;
import org.apache.http.HttpHost;
import org.apache.http.client.config.RequestConfig;
@ -31,12 +38,6 @@ import org.apache.http.client.methods.HttpUriRequest;
import java.io.IOException;
import java.util.Arrays;
import ws.com.google.android.mms.InvalidHeaderValueException;
import ws.com.google.android.mms.pdu.NotifyRespInd;
import ws.com.google.android.mms.pdu.PduComposer;
import ws.com.google.android.mms.pdu.PduHeaders;
import ws.com.google.android.mms.pdu.PduParser;
import ws.com.google.android.mms.pdu.RetrieveConf;
@SuppressWarnings("deprecation")
public class IncomingLegacyMmsConnection extends LegacyMmsConnection implements IncomingMmsConnection {

View File

@ -26,18 +26,16 @@ import android.support.annotation.Nullable;
import android.telephony.SmsManager;
import android.util.Log;
import com.google.android.mms.pdu_alt.PduParser;
import com.google.android.mms.pdu_alt.RetrieveConf;
import org.thoughtcrime.securesms.providers.MmsBodyProvider;
import org.thoughtcrime.securesms.util.Hex;
import org.thoughtcrime.securesms.util.Util;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
import ws.com.google.android.mms.MmsException;
import ws.com.google.android.mms.pdu.PduParser;
import ws.com.google.android.mms.pdu.RetrieveConf;
public class IncomingLollipopMmsConnection extends LollipopMmsConnection implements IncomingMmsConnection {
public static final String ACTION = IncomingLollipopMmsConnection.class.getCanonicalName() + "MMS_DOWNLOADED_ACTION";
@ -89,7 +87,7 @@ public class IncomingLollipopMmsConnection extends LollipopMmsConnection impleme
Util.copy(pointer.getInputStream(), baos);
pointer.close();
Log.w(TAG, baos.size() + "-byte response: " + Hex.dump(baos.toByteArray()));
Log.w(TAG, baos.size() + "-byte response: ");// + Hex.dump(baos.toByteArray()));
return (RetrieveConf) new PduParser(baos.toByteArray()).parse();
} catch (IOException | TimeoutException e) {

View File

@ -3,11 +3,11 @@ package org.thoughtcrime.securesms.mms;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.google.android.mms.pdu_alt.RetrieveConf;
import java.io.IOException;
import ws.com.google.android.mms.MmsException;
import ws.com.google.android.mms.pdu.RetrieveConf;
public interface IncomingMmsConnection {
@Nullable RetrieveConf retrieve(@NonNull String contentLocation, byte[] transactionId, int subscriptionId) throws MmsException, MmsRadioException, ApnUnavailableException, IOException;
@Nullable
RetrieveConf retrieve(@NonNull String contentLocation, byte[] transactionId, int subscriptionId) throws MmsException, MmsRadioException, ApnUnavailableException, IOException;
}

View File

@ -18,33 +18,33 @@ import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import ws.com.google.android.mms.ContentType;
public abstract class MediaConstraints {
private static final String TAG = MediaConstraints.class.getSimpleName();
public static MediaConstraints MMS_CONSTRAINTS = new MmsMediaConstraints();
public static MediaConstraints PUSH_CONSTRAINTS = new PushMediaConstraints();
public static MediaConstraints getPushMediaConstraints() {
return new PushMediaConstraints();
}
public static MediaConstraints getMmsMediaConstraints(int subscriptionId) {
return new MmsMediaConstraints(subscriptionId);
}
public abstract int getImageMaxWidth(Context context);
public abstract int getImageMaxHeight(Context context);
public abstract int getImageMaxSize();
public abstract int getImageMaxSize(Context context);
public abstract int getGifMaxSize();
public abstract int getVideoMaxSize();
public abstract int getAudioMaxSize();
public abstract int getDocumentMaxSize();
public abstract int getGifMaxSize(Context context);
public abstract int getVideoMaxSize(Context context);
public abstract int getAudioMaxSize(Context context);
public abstract int getDocumentMaxSize(Context context);
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.isFile(attachment) && attachment.getSize() <= getDocumentMaxSize());
return (MediaUtil.isGif(attachment) && attachment.getSize() <= getGifMaxSize(context) && isWithinBounds(context, masterSecret, attachment.getDataUri())) ||
(MediaUtil.isImage(attachment) && attachment.getSize() <= getImageMaxSize(context) && isWithinBounds(context, masterSecret, attachment.getDataUri())) ||
(MediaUtil.isAudio(attachment) && attachment.getSize() <= getAudioMaxSize(context)) ||
(MediaUtil.isVideo(attachment) && attachment.getSize() <= getVideoMaxSize(context)) ||
(MediaUtil.isFile(attachment) && attachment.getSize() <= getDocumentMaxSize(context));
} catch (IOException ioe) {
Log.w(TAG, "Failed to determine if media's constraints are satisfied.", ioe);
return false;
@ -78,7 +78,7 @@ public abstract class MediaConstraints {
try {
// XXX - This is loading everything into memory! We want the send path to be stream-like.
return new MediaStream(new ByteArrayInputStream(BitmapUtil.createScaledBytes(context, new DecryptableUri(masterSecret, attachment.getDataUri()), this)),
ContentType.IMAGE_JPEG);
MediaUtil.IMAGE_JPEG);
} catch (BitmapDecodingException e) {
throw new IOException(e);
}

View File

@ -0,0 +1,53 @@
package org.thoughtcrime.securesms.mms;
import android.content.Context;
import android.content.res.Configuration;
import android.os.Build;
import android.support.annotation.Nullable;
import android.support.annotation.WorkerThread;
import com.android.mms.service_alt.MmsConfig;
import org.thoughtcrime.securesms.util.dualsim.SubscriptionInfoCompat;
import org.thoughtcrime.securesms.util.dualsim.SubscriptionManagerCompat;
import org.whispersystems.libsignal.util.guava.Optional;
import java.util.HashMap;
import java.util.Map;
public class MmsConfigManager {
private static Map<Integer, MmsConfig> mmsConfigMap = new HashMap<>();
@WorkerThread
public synchronized static @Nullable MmsConfig getMmsConfig(Context context, int subscriptionId) {
if (mmsConfigMap.containsKey(subscriptionId)) {
return mmsConfigMap.get(subscriptionId);
}
MmsConfig loadedConfig = loadMmsConfig(context, subscriptionId);
if (loadedConfig != null) mmsConfigMap.put(subscriptionId, loadedConfig);
return loadedConfig;
}
private static MmsConfig loadMmsConfig(Context context, int subscriptionId) {
if (subscriptionId != -1 && Build.VERSION.SDK_INT >= 24) {
Optional<SubscriptionInfoCompat> subscriptionInfo = new SubscriptionManagerCompat(context).getActiveSubscriptionInfo(subscriptionId);
if (subscriptionInfo.isPresent()) {
Configuration configuration = context.getResources().getConfiguration();
configuration.mcc = subscriptionInfo.get().getMcc();
configuration.mnc = subscriptionInfo.get().getMnc();
Context subcontext = context.createConfigurationContext(configuration);
return new MmsConfig(subcontext, subscriptionId);
}
}
return new MmsConfig(context, subscriptionId);
}
}

View File

@ -0,0 +1,60 @@
/*
* Copyright (C) 2007 Esmertec AG.
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thoughtcrime.securesms.mms;
/**
* A generic exception that is thrown by the Mms client.
*/
public class MmsException extends Exception {
private static final long serialVersionUID = -7323249827281485390L;
/**
* Creates a new MmsException.
*/
public MmsException() {
super();
}
/**
* Creates a new MmsException with the specified detail message.
*
* @param message the detail message.
*/
public MmsException(String message) {
super(message);
}
/**
* Creates a new MmsException with the specified cause.
*
* @param cause the cause.
*/
public MmsException(Throwable cause) {
super(cause);
}
/**
* Creates a new MmsException with the specified detail message and cause.
*
* @param message the detail message.
* @param cause the cause.
*/
public MmsException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@ -1,46 +1,78 @@
package org.thoughtcrime.securesms.mms;
import android.content.Context;
import android.os.Bundle;
import org.thoughtcrime.securesms.util.Util;
import com.android.mms.service_alt.MmsConfig;
public class MmsMediaConstraints extends MediaConstraints {
private static final int MAX_IMAGE_DIMEN_LOWMEM = 768;
private static final int MAX_IMAGE_DIMEN = 1024;
public static final int MAX_MESSAGE_SIZE = 280 * 1024;
class MmsMediaConstraints extends MediaConstraints {
private static final int DEFAULT_MAX_IMAGE_DIMEN = 1024;
private static final int DEFAULT_MAX_MESSAGE_SIZE = 280 * 1024;
private final int subscriptionId;
MmsMediaConstraints(int subscriptionId) {
this.subscriptionId = subscriptionId;
}
@Override
public int getImageMaxWidth(Context context) {
return Util.isLowMemory(context) ? MAX_IMAGE_DIMEN_LOWMEM : MAX_IMAGE_DIMEN;
MmsConfig mmsConfig = MmsConfigManager.getMmsConfig(context, subscriptionId);
if (mmsConfig != null) {
MmsConfig.Overridden overridden = new MmsConfig.Overridden(mmsConfig, new Bundle());
return overridden.getMaxImageWidth();
}
return DEFAULT_MAX_IMAGE_DIMEN;
}
@Override
public int getImageMaxHeight(Context context) {
return getImageMaxWidth(context);
MmsConfig mmsConfig = MmsConfigManager.getMmsConfig(context, subscriptionId);
if (mmsConfig != null) {
MmsConfig.Overridden overridden = new MmsConfig.Overridden(mmsConfig, new Bundle());
return overridden.getMaxImageHeight();
}
return DEFAULT_MAX_IMAGE_DIMEN;
}
@Override
public int getImageMaxSize() {
return MAX_MESSAGE_SIZE;
public int getImageMaxSize(Context context) {
return getMaxMessageSize(context);
}
@Override
public int getGifMaxSize() {
return MAX_MESSAGE_SIZE;
public int getGifMaxSize(Context context) {
return getMaxMessageSize(context);
}
@Override
public int getVideoMaxSize() {
return MAX_MESSAGE_SIZE;
public int getVideoMaxSize(Context context) {
return getMaxMessageSize(context);
}
@Override
public int getAudioMaxSize() {
return MAX_MESSAGE_SIZE;
public int getAudioMaxSize(Context context) {
return getMaxMessageSize(context);
}
@Override
public int getDocumentMaxSize() {
return MAX_MESSAGE_SIZE;
public int getDocumentMaxSize(Context context) {
return getMaxMessageSize(context);
}
private int getMaxMessageSize(Context context) {
MmsConfig mmsConfig = MmsConfigManager.getMmsConfig(context, subscriptionId);
if (mmsConfig != null) {
MmsConfig.Overridden overridden = new MmsConfig.Overridden(mmsConfig, new Bundle());
return overridden.getMaxMessageSize();
}
return DEFAULT_MAX_MESSAGE_SIZE;
}
}

View File

@ -24,6 +24,9 @@ import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;
import com.google.android.mms.pdu_alt.PduParser;
import com.google.android.mms.pdu_alt.SendConf;
import org.apache.http.Header;
import org.apache.http.HttpHost;
import org.apache.http.client.config.RequestConfig;
@ -34,8 +37,6 @@ import org.thoughtcrime.securesms.transport.UndeliverableMessageException;
import java.io.IOException;
import ws.com.google.android.mms.pdu.PduParser;
import ws.com.google.android.mms.pdu.SendConf;
@SuppressWarnings("deprecation")
public class OutgoingLegacyMmsConnection extends LegacyMmsConnection implements OutgoingMmsConnection {

View File

@ -21,11 +21,16 @@ import android.content.Context;
import android.content.Intent;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.telephony.SmsManager;
import android.util.Log;
import com.android.mms.service_alt.MmsConfig;
import com.google.android.mms.pdu_alt.PduParser;
import com.google.android.mms.pdu_alt.SendConf;
import org.thoughtcrime.securesms.providers.MmsBodyProvider;
import org.thoughtcrime.securesms.transport.UndeliverableMessageException;
import org.thoughtcrime.securesms.util.Util;
@ -34,9 +39,6 @@ import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
import ws.com.google.android.mms.pdu.PduParser;
import ws.com.google.android.mms.pdu.SendConf;
public class OutgoingLollipopMmsConnection extends LollipopMmsConnection implements OutgoingMmsConnection {
private static final String TAG = OutgoingLollipopMmsConnection.class.getSimpleName();
private static final String ACTION = OutgoingLollipopMmsConnection.class.getCanonicalName() + "MMS_SENT_ACTION";
@ -75,10 +77,21 @@ public class OutgoingLollipopMmsConnection extends LollipopMmsConnection impleme
smsManager = SmsManager.getDefault();
}
Bundle configOverrides = new Bundle();
configOverrides.putBoolean(SmsManager.MMS_CONFIG_GROUP_MMS_ENABLED, true);
MmsConfig mmsConfig = MmsConfigManager.getMmsConfig(getContext(), subscriptionId);
if (mmsConfig != null) {
MmsConfig.Overridden overridden = new MmsConfig.Overridden(mmsConfig, new Bundle());
configOverrides.putString(SmsManager.MMS_CONFIG_HTTP_PARAMS, overridden.getHttpParams());
configOverrides.putInt(SmsManager.MMS_CONFIG_MAX_MESSAGE_SIZE, overridden.getMaxMessageSize());
}
smsManager.sendMultimediaMessage(getContext(),
pointer.getUri(),
null,
null,
configOverrides,
getPendingIntent());
waitForResult();

View File

@ -3,10 +3,12 @@ package org.thoughtcrime.securesms.mms;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.google.android.mms.pdu_alt.SendConf;
import org.thoughtcrime.securesms.transport.UndeliverableMessageException;
import ws.com.google.android.mms.pdu.SendConf;
public interface OutgoingMmsConnection {
@Nullable SendConf send(@NonNull byte[] pduBytes, int subscriptionId) throws UndeliverableMessageException;
@Nullable
SendConf send(@NonNull byte[] pduBytes, int subscriptionId) throws UndeliverableMessageException;
}

View File

@ -1,14 +1,10 @@
package org.thoughtcrime.securesms.mms;
import android.content.Context;
import org.thoughtcrime.securesms.attachments.Attachment;
import org.thoughtcrime.securesms.recipients.Recipients;
import java.util.List;
import ws.com.google.android.mms.pdu.PduBody;
public class OutgoingSecureMediaMessage extends OutgoingMediaMessage {
public OutgoingSecureMediaMessage(Recipients recipients, String body,

View File

@ -2,14 +2,15 @@ package org.thoughtcrime.securesms.mms;
import android.util.Log;
import com.google.android.mms.ContentType;
import com.google.android.mms.pdu_alt.CharacterSets;
import com.google.android.mms.pdu_alt.PduBody;
import com.google.android.mms.pdu_alt.PduPart;
import org.thoughtcrime.securesms.util.Util;
import java.io.UnsupportedEncodingException;
import ws.com.google.android.mms.ContentType;
import ws.com.google.android.mms.pdu.CharacterSets;
import ws.com.google.android.mms.pdu.PduBody;
import ws.com.google.android.mms.pdu.PduPart;
public class PartParser {
public static String getMessageText(PduBody body) {

View File

@ -5,6 +5,7 @@ import android.content.Context;
import org.thoughtcrime.securesms.util.Util;
public class PushMediaConstraints extends MediaConstraints {
private static final int MAX_IMAGE_DIMEN_LOWMEM = 768;
private static final int MAX_IMAGE_DIMEN = 4096;
private static final int KB = 1024;
@ -21,27 +22,27 @@ public class PushMediaConstraints extends MediaConstraints {
}
@Override
public int getImageMaxSize() {
public int getImageMaxSize(Context context) {
return 6 * MB;
}
@Override
public int getGifMaxSize() {
public int getGifMaxSize(Context context) {
return 25 * MB;
}
@Override
public int getVideoMaxSize() {
public int getVideoMaxSize(Context context) {
return 100 * MB;
}
@Override
public int getAudioMaxSize() {
public int getAudioMaxSize(Context context) {
return 100 * MB;
}
@Override
public int getDocumentMaxSize() {
public int getDocumentMaxSize(Context context) {
return 100 * MB;
}
}

View File

@ -27,12 +27,10 @@ import org.thoughtcrime.securesms.attachments.Attachment;
import org.thoughtcrime.securesms.util.MediaUtil;
import org.thoughtcrime.securesms.util.ResUtil;
import ws.com.google.android.mms.ContentType;
public class VideoSlide extends Slide {
public VideoSlide(Context context, Uri uri, long dataSize) {
super(context, constructAttachmentFromUri(context, uri, ContentType.VIDEO_UNSPECIFIED, dataSize, MediaUtil.hasVideoThumbnail(uri), null));
super(context, constructAttachmentFromUri(context, uri, MediaUtil.VIDEO_UNSPECIFIED, dataSize, MediaUtil.hasVideoThumbnail(uri), null));
}
public VideoSlide(Context context, Attachment attachment) {

View File

@ -28,14 +28,13 @@ import org.thoughtcrime.securesms.scribbles.widget.VerticalSlideColorPicker;
import org.thoughtcrime.securesms.scribbles.widget.entity.ImageEntity;
import org.thoughtcrime.securesms.scribbles.widget.entity.MotionEntity;
import org.thoughtcrime.securesms.scribbles.widget.entity.TextEntity;
import org.thoughtcrime.securesms.util.MediaUtil;
import org.thoughtcrime.securesms.util.concurrent.ListenableFuture;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import ws.com.google.android.mms.ContentType;
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public class ScribbleActivity extends PassphraseRequiredActionBarActivity implements ScribbleToolbar.ScribbleToolbarListener, VerticalSlideColorPicker.OnColorChangeListener {
@ -230,7 +229,7 @@ public class ScribbleActivity extends PassphraseRequiredActionBarActivity implem
baos = null;
result = null;
Uri uri = provider.create(masterSecret, data, ContentType.IMAGE_JPEG);
Uri uri = provider.create(masterSecret, data, MediaUtil.IMAGE_JPEG);
Intent intent = new Intent();
intent.setData(uri);
setResult(RESULT_OK, intent);

View File

@ -52,7 +52,7 @@ import org.whispersystems.signalservice.api.util.InvalidNumberException;
import java.io.IOException;
import ws.com.google.android.mms.MmsException;
import org.thoughtcrime.securesms.mms.MmsException;
public class MessageSender {

View File

@ -72,14 +72,14 @@ public class BitmapUtil {
Log.w(TAG, "iteration with quality " + quality + " size " + (bytes.length / 1024) + "kb");
if (quality == MIN_COMPRESSION_QUALITY) break;
int nextQuality = (int)Math.floor(quality * Math.sqrt((double)constraints.getImageMaxSize() / bytes.length));
int nextQuality = (int)Math.floor(quality * Math.sqrt((double)constraints.getImageMaxSize(context) / bytes.length));
if (quality - nextQuality < MIN_COMPRESSION_QUALITY_DECREASE) {
nextQuality = quality - MIN_COMPRESSION_QUALITY_DECREASE;
}
quality = Math.max(nextQuality, MIN_COMPRESSION_QUALITY);
}
while (bytes.length > constraints.getImageMaxSize() && attempts++ < MAX_COMPRESSION_ATTEMPTS);
if (bytes.length > constraints.getImageMaxSize()) {
while (bytes.length > constraints.getImageMaxSize(context) && attempts++ < MAX_COMPRESSION_ATTEMPTS);
if (bytes.length > constraints.getImageMaxSize(context)) {
throw new BitmapDecodingException("Unable to scale image below: " + bytes.length);
}
Log.w(TAG, "createScaledBytes(" + model.toString() + ") -> quality " + Math.min(quality, MAX_COMPRESSION_QUALITY) + ", " + attempts + " attempt(s)");

View File

@ -31,19 +31,25 @@ import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.ExecutionException;
import ws.com.google.android.mms.ContentType;
public class MediaUtil {
private static final String TAG = MediaUtil.class.getSimpleName();
public static final String IMAGE_PNG = "image/png";
public static final String IMAGE_JPEG = "image/jpeg";
public static final String IMAGE_GIF = "image/gif";
public static final String AUDIO_AAC = "audio/aac";
public static final String AUDIO_UNSPECIFIED = "audio/*";
public static final String VIDEO_UNSPECIFIED = "video/*";
public static @Nullable ThumbnailData generateThumbnail(Context context, MasterSecret masterSecret, String contentType, Uri uri)
throws BitmapDecodingException
{
long startMillis = System.currentTimeMillis();
ThumbnailData data = null;
if (ContentType.isImageType(contentType)) {
if (isImageType(contentType)) {
data = new ThumbnailData(generateImageThumbnail(context, masterSecret, uri));
}
@ -77,11 +83,11 @@ public class MediaUtil {
Slide slide = null;
if (isGif(attachment.getContentType())) {
slide = new GifSlide(context, attachment);
} else if (ContentType.isImageType(attachment.getContentType())) {
} else if (isImageType(attachment.getContentType())) {
slide = new ImageSlide(context, attachment);
} else if (ContentType.isVideoType(attachment.getContentType())) {
} else if (isVideoType(attachment.getContentType())) {
slide = new VideoSlide(context, attachment);
} else if (ContentType.isAudioType(attachment.getContentType())) {
} else if (isAudioType(attachment.getContentType())) {
slide = new AudioSlide(context, attachment);
} else if (isMms(attachment.getContentType())) {
slide = new MmsSlide(context, attachment);
@ -112,8 +118,8 @@ public class MediaUtil {
switch(mimeType) {
case "image/jpg":
return MimeTypeMap.getSingleton().hasMimeType(ContentType.IMAGE_JPEG)
? ContentType.IMAGE_JPEG
return MimeTypeMap.getSingleton().hasMimeType(IMAGE_JPEG)
? IMAGE_JPEG
: mimeType;
default:
return mimeType;
@ -140,34 +146,50 @@ public class MediaUtil {
return !TextUtils.isEmpty(contentType) && contentType.trim().equals("application/mms");
}
public static boolean isGif(String contentType) {
return !TextUtils.isEmpty(contentType) && contentType.trim().equals("image/gif");
}
public static boolean isGif(Attachment attachment) {
return isGif(attachment.getContentType());
}
public static boolean isImage(Attachment attachment) {
return ContentType.isImageType(attachment.getContentType());
return isImageType(attachment.getContentType());
}
public static boolean isAudio(Attachment attachment) {
return ContentType.isAudioType(attachment.getContentType());
return isAudioType(attachment.getContentType());
}
public static boolean isVideo(Attachment attachment) {
return ContentType.isVideoType(attachment.getContentType());
return isVideoType(attachment.getContentType());
}
public static boolean isVideo(String contentType) {
return !TextUtils.isEmpty(contentType) && contentType.trim().startsWith("video/");
}
public static boolean isGif(String contentType) {
return !TextUtils.isEmpty(contentType) && contentType.trim().equals("image/gif");
}
public static boolean isFile(Attachment attachment) {
return !isGif(attachment) && !isImage(attachment) && !isAudio(attachment) && !isVideo(attachment);
}
public static boolean isTextType(String contentType) {
return (null != contentType) && contentType.startsWith("text/");
}
public static boolean isImageType(String contentType) {
return (null != contentType) && contentType.startsWith("image/");
}
public static boolean isAudioType(String contentType) {
return (null != contentType) && contentType.startsWith("audio/");
}
public static boolean isVideoType(String contentType) {
return (null != contentType) && contentType.startsWith("video/");
}
public static boolean hasVideoThumbnail(Uri uri) {
Log.w(TAG, "Checking: " + uri);

View File

@ -1,132 +0,0 @@
package org.thoughtcrime.securesms.util;
import android.util.Log;
import org.thoughtcrime.securesms.dom.smil.SmilDocumentImpl;
import org.thoughtcrime.securesms.dom.smil.parser.SmilXmlSerializer;
import org.thoughtcrime.securesms.mms.PartParser;
import org.w3c.dom.smil.SMILDocument;
import org.w3c.dom.smil.SMILElement;
import org.w3c.dom.smil.SMILLayoutElement;
import org.w3c.dom.smil.SMILMediaElement;
import org.w3c.dom.smil.SMILParElement;
import org.w3c.dom.smil.SMILRegionElement;
import org.w3c.dom.smil.SMILRegionMediaElement;
import org.w3c.dom.smil.SMILRootLayoutElement;
import java.io.ByteArrayOutputStream;
import ws.com.google.android.mms.ContentType;
import ws.com.google.android.mms.pdu.PduBody;
import ws.com.google.android.mms.pdu.PduPart;
public class SmilUtil {
private static final String TAG = SmilUtil.class.getSimpleName();
public static final int ROOT_HEIGHT = 1024;
public static final int ROOT_WIDTH = 1024;
public static PduBody getSmilBody(PduBody body) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
SmilXmlSerializer.serialize(SmilUtil.createSmilDocument(body), out);
PduPart smilPart = new PduPart();
smilPart.setContentId("smil".getBytes());
smilPart.setContentLocation("smil.xml".getBytes());
smilPart.setContentType(ContentType.APP_SMIL.getBytes());
smilPart.setData(out.toByteArray());
body.addPart(0, smilPart);
return body;
}
private static SMILDocument createSmilDocument(PduBody body) {
Log.w(TAG, "Creating SMIL document from PduBody.");
SMILDocument document = new SmilDocumentImpl();
SMILElement smilElement = (SMILElement) document.createElement("smil");
document.appendChild(smilElement);
SMILElement headElement = (SMILElement) document.createElement("head");
smilElement.appendChild(headElement);
SMILLayoutElement layoutElement = (SMILLayoutElement) document.createElement("layout");
headElement.appendChild(layoutElement);
SMILRootLayoutElement rootLayoutElement = (SMILRootLayoutElement) document.createElement("root-layout");
rootLayoutElement.setWidth(ROOT_WIDTH);
rootLayoutElement.setHeight(ROOT_HEIGHT);
layoutElement.appendChild(rootLayoutElement);
SMILElement bodyElement = (SMILElement) document.createElement("body");
smilElement.appendChild(bodyElement);
SMILParElement par = (SMILParElement) document.createElement("par");
bodyElement.appendChild(par);
for (int i=0; i<body.getPartsNum(); i++) {
PduPart part = body.getPart(i);
SMILRegionElement regionElement = getRegion(document, part);
SMILMediaElement mediaElement = getMediaElement(document, part);
if (regionElement != null) {
((SMILRegionMediaElement)mediaElement).setRegion(regionElement);
layoutElement.appendChild(regionElement);
}
par.appendChild(mediaElement);
}
return document;
}
private static SMILRegionElement getRegion(SMILDocument document, PduPart part) {
if (PartParser.isAudio(part)) return null;
SMILRegionElement region = (SMILRegionElement) document.createElement("region");
if (PartParser.isText(part)) {
region.setId("Text");
region.setTop(SmilUtil.ROOT_HEIGHT);
region.setHeight(50);
} else {
region.setId("Image");
region.setTop(0);
region.setHeight(SmilUtil.ROOT_HEIGHT);
}
region.setLeft(0);
region.setWidth(SmilUtil.ROOT_WIDTH);
region.setFit("meet");
return region;
}
private static SMILMediaElement getMediaElement(SMILDocument document, PduPart part) {
final String tag;
if (PartParser.isImage(part)) {
tag = "img";
} else if (PartParser.isAudio(part)) {
tag = "audio";
} else if (PartParser.isVideo(part)) {
tag = "video";
} else if (PartParser.isText(part)) {
tag = "text";
} else {
tag = "ref";
}
return createMediaElement(tag, document, new String(part.getName() == null
? new byte[]{}
: part.getName()));
}
private static SMILMediaElement createMediaElement(String tag, SMILDocument document, String src) {
SMILMediaElement mediaElement = (SMILMediaElement) document.createElement(tag);
mediaElement.setSrc(escapeXML(src));
return mediaElement;
}
private static String escapeXML(String str) {
return str.replaceAll("&","&amp;")
.replaceAll("<", "&lt;")
.replaceAll(">", "&gt;")
.replaceAll("\"", "&quot;")
.replaceAll("'", "&apos;");
}
}

View File

@ -40,6 +40,8 @@ import android.text.style.StyleSpan;
import android.util.Log;
import android.widget.EditText;
import com.google.android.mms.pdu_alt.CharacterSets;
import com.google.android.mms.pdu_alt.EncodedStringValue;
import com.google.i18n.phonenumbers.PhoneNumberUtil;
import org.thoughtcrime.securesms.BuildConfig;
@ -65,9 +67,6 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import ws.com.google.android.mms.pdu.CharacterSets;
import ws.com.google.android.mms.pdu.EncodedStringValue;
public class Util {
private static final String TAG = Util.class.getSimpleName();

View File

@ -6,11 +6,15 @@ import android.support.annotation.Nullable;
public class SubscriptionInfoCompat {
private final int subscriptionId;
private final int mcc;
private final int mnc;
private final @Nullable CharSequence displayName;
public SubscriptionInfoCompat(int subscriptionId, @Nullable CharSequence displayName) {
public SubscriptionInfoCompat(int subscriptionId, @Nullable CharSequence displayName, int mcc, int mnc) {
this.subscriptionId = subscriptionId;
this.displayName = displayName;
this.mcc = mcc;
this.mnc = mnc;
}
public @NonNull CharSequence getDisplayName() {
@ -20,4 +24,12 @@ public class SubscriptionInfoCompat {
public int getSubscriptionId() {
return subscriptionId;
}
public int getMnc() {
return mnc;
}
public int getMcc() {
return mcc;
}
}

View File

@ -35,7 +35,8 @@ public class SubscriptionManagerCompat {
SubscriptionInfo subscriptionInfo = SubscriptionManager.from(context).getActiveSubscriptionInfo(subscriptionId);
if (subscriptionInfo != null) {
return Optional.of(new SubscriptionInfoCompat(subscriptionId, subscriptionInfo.getDisplayName()));
return Optional.of(new SubscriptionInfoCompat(subscriptionId, subscriptionInfo.getDisplayName(),
subscriptionInfo.getMcc(), subscriptionInfo.getMnc()));
} else {
return Optional.absent();
}
@ -56,7 +57,9 @@ public class SubscriptionManagerCompat {
for (SubscriptionInfo subscriptionInfo : subscriptionInfos) {
compatList.add(new SubscriptionInfoCompat(subscriptionInfo.getSubscriptionId(),
subscriptionInfo.getDisplayName()));
subscriptionInfo.getDisplayName(),
subscriptionInfo.getMcc(),
subscriptionInfo.getMnc()));
}
return compatList;

View File

@ -1,229 +0,0 @@
/*
* Copyright (C) 2007-2008 Esmertec AG.
* Copyright (C) 2007-2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ws.com.google.android.mms;
import java.util.ArrayList;
public class ContentType {
public static final String MMS_MESSAGE = "application/vnd.wap.mms-message";
// The phony content type for generic PDUs (e.g. ReadOrig.ind,
// Notification.ind, Delivery.ind).
public static final String MMS_GENERIC = "application/vnd.wap.mms-generic";
public static final String MULTIPART_MIXED = "application/vnd.wap.multipart.mixed";
public static final String MULTIPART_RELATED = "application/vnd.wap.multipart.related";
public static final String MULTIPART_ALTERNATIVE = "application/vnd.wap.multipart.alternative";
public static final String TEXT_PLAIN = "text/plain";
public static final String TEXT_HTML = "text/html";
public static final String TEXT_VCALENDAR = "text/x-vCalendar";
public static final String TEXT_VCARD = "text/x-vCard";
public static final String IMAGE_UNSPECIFIED = "image/*";
public static final String IMAGE_JPEG = "image/jpeg";
public static final String IMAGE_JPG = "image/jpg";
public static final String IMAGE_GIF = "image/gif";
public static final String IMAGE_WBMP = "image/vnd.wap.wbmp";
public static final String IMAGE_PNG = "image/png";
public static final String IMAGE_X_MS_BMP = "image/x-ms-bmp";
public static final String AUDIO_UNSPECIFIED = "audio/*";
public static final String AUDIO_AAC = "audio/aac";
public static final String AUDIO_AMR = "audio/amr";
public static final String AUDIO_IMELODY = "audio/imelody";
public static final String AUDIO_MID = "audio/mid";
public static final String AUDIO_MIDI = "audio/midi";
public static final String AUDIO_MP3 = "audio/mp3";
public static final String AUDIO_MPEG3 = "audio/mpeg3";
public static final String AUDIO_MPEG = "audio/mpeg";
public static final String AUDIO_MPG = "audio/mpg";
public static final String AUDIO_MP4 = "audio/mp4";
public static final String AUDIO_X_MID = "audio/x-mid";
public static final String AUDIO_X_MIDI = "audio/x-midi";
public static final String AUDIO_X_MP3 = "audio/x-mp3";
public static final String AUDIO_X_MPEG3 = "audio/x-mpeg3";
public static final String AUDIO_X_MPEG = "audio/x-mpeg";
public static final String AUDIO_X_MPG = "audio/x-mpg";
public static final String AUDIO_3GPP = "audio/3gpp";
public static final String AUDIO_X_WAV = "audio/x-wav";
public static final String AUDIO_OGG = "application/ogg";
public static final String VIDEO_UNSPECIFIED = "video/*";
public static final String VIDEO_3GPP = "video/3gpp";
public static final String VIDEO_3G2 = "video/3gpp2";
public static final String VIDEO_H263 = "video/h263";
public static final String VIDEO_MP4 = "video/mp4";
public static final String APP_SMIL = "application/smil";
public static final String APP_WAP_XHTML = "application/vnd.wap.xhtml+xml";
public static final String APP_XHTML = "application/xhtml+xml";
public static final String APP_DRM_CONTENT = "application/vnd.oma.drm.content";
public static final String APP_DRM_MESSAGE = "application/vnd.oma.drm.message";
private static final ArrayList<String> sSupportedContentTypes = new ArrayList<String>();
private static final ArrayList<String> sSupportedImageTypes = new ArrayList<String>();
private static final ArrayList<String> sSupportedAudioTypes = new ArrayList<String>();
private static final ArrayList<String> sSupportedVideoTypes = new ArrayList<String>();
static {
sSupportedContentTypes.add(TEXT_PLAIN);
sSupportedContentTypes.add(TEXT_HTML);
sSupportedContentTypes.add(TEXT_VCALENDAR);
sSupportedContentTypes.add(TEXT_VCARD);
sSupportedContentTypes.add(IMAGE_JPEG);
sSupportedContentTypes.add(IMAGE_GIF);
sSupportedContentTypes.add(IMAGE_WBMP);
sSupportedContentTypes.add(IMAGE_PNG);
sSupportedContentTypes.add(IMAGE_JPG);
sSupportedContentTypes.add(IMAGE_X_MS_BMP);
//supportedContentTypes.add(IMAGE_SVG); not yet supported.
sSupportedContentTypes.add(AUDIO_AAC);
sSupportedContentTypes.add(AUDIO_AMR);
sSupportedContentTypes.add(AUDIO_IMELODY);
sSupportedContentTypes.add(AUDIO_MID);
sSupportedContentTypes.add(AUDIO_MIDI);
sSupportedContentTypes.add(AUDIO_MP3);
sSupportedContentTypes.add(AUDIO_MPEG3);
sSupportedContentTypes.add(AUDIO_MPEG);
sSupportedContentTypes.add(AUDIO_MPG);
sSupportedContentTypes.add(AUDIO_X_MID);
sSupportedContentTypes.add(AUDIO_X_MIDI);
sSupportedContentTypes.add(AUDIO_X_MP3);
sSupportedContentTypes.add(AUDIO_X_MPEG3);
sSupportedContentTypes.add(AUDIO_X_MPEG);
sSupportedContentTypes.add(AUDIO_X_MPG);
sSupportedContentTypes.add(AUDIO_X_WAV);
sSupportedContentTypes.add(AUDIO_3GPP);
sSupportedContentTypes.add(AUDIO_OGG);
sSupportedContentTypes.add(VIDEO_3GPP);
sSupportedContentTypes.add(VIDEO_3G2);
sSupportedContentTypes.add(VIDEO_H263);
sSupportedContentTypes.add(VIDEO_MP4);
sSupportedContentTypes.add(APP_SMIL);
sSupportedContentTypes.add(APP_WAP_XHTML);
sSupportedContentTypes.add(APP_XHTML);
sSupportedContentTypes.add(APP_DRM_CONTENT);
sSupportedContentTypes.add(APP_DRM_MESSAGE);
// add supported image types
sSupportedImageTypes.add(IMAGE_JPEG);
sSupportedImageTypes.add(IMAGE_GIF);
sSupportedImageTypes.add(IMAGE_WBMP);
sSupportedImageTypes.add(IMAGE_PNG);
sSupportedImageTypes.add(IMAGE_JPG);
sSupportedImageTypes.add(IMAGE_X_MS_BMP);
// add supported audio types
sSupportedAudioTypes.add(AUDIO_AAC);
sSupportedAudioTypes.add(AUDIO_AMR);
sSupportedAudioTypes.add(AUDIO_IMELODY);
sSupportedAudioTypes.add(AUDIO_MID);
sSupportedAudioTypes.add(AUDIO_MIDI);
sSupportedAudioTypes.add(AUDIO_MP3);
sSupportedAudioTypes.add(AUDIO_MPEG3);
sSupportedAudioTypes.add(AUDIO_MPEG);
sSupportedAudioTypes.add(AUDIO_MPG);
sSupportedAudioTypes.add(AUDIO_MP4);
sSupportedAudioTypes.add(AUDIO_X_MID);
sSupportedAudioTypes.add(AUDIO_X_MIDI);
sSupportedAudioTypes.add(AUDIO_X_MP3);
sSupportedAudioTypes.add(AUDIO_X_MPEG3);
sSupportedAudioTypes.add(AUDIO_X_MPEG);
sSupportedAudioTypes.add(AUDIO_X_MPG);
sSupportedAudioTypes.add(AUDIO_X_WAV);
sSupportedAudioTypes.add(AUDIO_3GPP);
sSupportedAudioTypes.add(AUDIO_OGG);
// add supported video types
sSupportedVideoTypes.add(VIDEO_3GPP);
sSupportedVideoTypes.add(VIDEO_3G2);
sSupportedVideoTypes.add(VIDEO_H263);
sSupportedVideoTypes.add(VIDEO_MP4);
}
// This class should never be instantiated.
private ContentType() {
}
public static boolean isSupportedType(String contentType) {
return (null != contentType) && sSupportedContentTypes.contains(contentType);
}
public static boolean isSupportedImageType(String contentType) {
return isImageType(contentType) && isSupportedType(contentType);
}
public static boolean isSupportedAudioType(String contentType) {
return isAudioType(contentType) && isSupportedType(contentType);
}
public static boolean isSupportedVideoType(String contentType) {
return isVideoType(contentType) && isSupportedType(contentType);
}
public static boolean isTextType(String contentType) {
return (null != contentType) && contentType.startsWith("text/");
}
public static boolean isImageType(String contentType) {
return (null != contentType) && contentType.startsWith("image/");
}
public static boolean isAudioType(String contentType) {
return (null != contentType) && contentType.startsWith("audio/");
}
public static boolean isVideoType(String contentType) {
return (null != contentType) && contentType.startsWith("video/");
}
public static boolean isDrmType(String contentType) {
return (null != contentType)
&& (contentType.equals(APP_DRM_CONTENT)
|| contentType.equals(APP_DRM_MESSAGE));
}
public static boolean isUnspecified(String contentType) {
return (null != contentType) && contentType.endsWith("*");
}
@SuppressWarnings("unchecked")
public static ArrayList<String> getImageTypes() {
return (ArrayList<String>) sSupportedImageTypes.clone();
}
@SuppressWarnings("unchecked")
public static ArrayList<String> getAudioTypes() {
return (ArrayList<String>) sSupportedAudioTypes.clone();
}
@SuppressWarnings("unchecked")
public static ArrayList<String> getVideoTypes() {
return (ArrayList<String>) sSupportedVideoTypes.clone();
}
@SuppressWarnings("unchecked")
public static ArrayList<String> getSupportedTypes() {
return (ArrayList<String>) sSupportedContentTypes.clone();
}
}

View File

@ -1,41 +0,0 @@
/*
* Copyright (C) 2007 Esmertec AG.
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ws.com.google.android.mms;
/**
* Thrown when an invalid header value was set.
*/
public class InvalidHeaderValueException extends MmsException {
private static final long serialVersionUID = -2053384496042052262L;
/**
* Constructs an InvalidHeaderValueException with no detailed message.
*/
public InvalidHeaderValueException() {
super();
}
/**
* Constructs an InvalidHeaderValueException with the specified detailed message.
*
* @param message the detailed message.
*/
public InvalidHeaderValueException(String message) {
super(message);
}
}

View File

@ -1,60 +0,0 @@
/*
* Copyright (C) 2007 Esmertec AG.
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ws.com.google.android.mms;
/**
* A generic exception that is thrown by the Mms client.
*/
public class MmsException extends Exception {
private static final long serialVersionUID = -7323249827281485390L;
/**
* Creates a new MmsException.
*/
public MmsException() {
super();
}
/**
* Creates a new MmsException with the specified detail message.
*
* @param message the detail message.
*/
public MmsException(String message) {
super(message);
}
/**
* Creates a new MmsException with the specified cause.
*
* @param cause the cause.
*/
public MmsException(Throwable cause) {
super(cause);
}
/**
* Creates a new MmsException with the specified detail message and cause.
*
* @param message the detail message.
* @param cause the cause.
*/
public MmsException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@ -1,5 +0,0 @@
<body>
{@hide}
</body>

View File

@ -1,89 +0,0 @@
/*
* Copyright (C) 2007 Esmertec AG.
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ws.com.google.android.mms.pdu;
import ws.com.google.android.mms.InvalidHeaderValueException;
/**
* M-Acknowledge.ind PDU.
*/
public class AcknowledgeInd extends GenericPdu {
/**
* Constructor, used when composing a M-Acknowledge.ind pdu.
*
* @param mmsVersion current viersion of mms
* @param transactionId the transaction-id value
* @throws InvalidHeaderValueException if parameters are invalid.
* NullPointerException if transactionId is null.
*/
public AcknowledgeInd(int mmsVersion, byte[] transactionId)
throws InvalidHeaderValueException {
super();
setMessageType(PduHeaders.MESSAGE_TYPE_ACKNOWLEDGE_IND);
setMmsVersion(mmsVersion);
setTransactionId(transactionId);
}
/**
* Constructor with given headers.
*
* @param headers Headers for this PDU.
*/
AcknowledgeInd(PduHeaders headers) {
super(headers);
}
/**
* Get X-Mms-Report-Allowed field value.
*
* @return the X-Mms-Report-Allowed value
*/
public int getReportAllowed() {
return mPduHeaders.getOctet(PduHeaders.REPORT_ALLOWED);
}
/**
* Set X-Mms-Report-Allowed field value.
*
* @param value the value
* @throws InvalidHeaderValueException if the value is invalid.
*/
public void setReportAllowed(int value) throws InvalidHeaderValueException {
mPduHeaders.setOctet(value, PduHeaders.REPORT_ALLOWED);
}
/**
* Get X-Mms-Transaction-Id field value.
*
* @return the X-Mms-Report-Allowed value
*/
public byte[] getTransactionId() {
return mPduHeaders.getTextString(PduHeaders.TRANSACTION_ID);
}
/**
* Set X-Mms-Transaction-Id field value.
*
* @param value the value
* @throws NullPointerException if the value is null.
*/
public void setTransactionId(byte[] value) {
mPduHeaders.setTextString(value, PduHeaders.TRANSACTION_ID);
}
}

View File

@ -1,167 +0,0 @@
/*
* Copyright (C) 2007 Esmertec AG.
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ws.com.google.android.mms.pdu;
public class Base64 {
/**
* Used to get the number of Quadruples.
*/
static final int FOURBYTE = 4;
/**
* Byte used to pad output.
*/
static final byte PAD = (byte) '=';
/**
* The base length.
*/
static final int BASELENGTH = 255;
// Create arrays to hold the base64 characters
private static byte[] base64Alphabet = new byte[BASELENGTH];
// Populating the character arrays
static {
for (int i = 0; i < BASELENGTH; i++) {
base64Alphabet[i] = (byte) -1;
}
for (int i = 'Z'; i >= 'A'; i--) {
base64Alphabet[i] = (byte) (i - 'A');
}
for (int i = 'z'; i >= 'a'; i--) {
base64Alphabet[i] = (byte) (i - 'a' + 26);
}
for (int i = '9'; i >= '0'; i--) {
base64Alphabet[i] = (byte) (i - '0' + 52);
}
base64Alphabet['+'] = 62;
base64Alphabet['/'] = 63;
}
/**
* Decodes Base64 data into octects
*
* @param base64Data Byte array containing Base64 data
* @return Array containing decoded data.
*/
public static byte[] decodeBase64(byte[] base64Data) {
// RFC 2045 requires that we discard ALL non-Base64 characters
base64Data = discardNonBase64(base64Data);
// handle the edge case, so we don't have to worry about it later
if (base64Data.length == 0) {
return new byte[0];
}
int numberQuadruple = base64Data.length / FOURBYTE;
byte decodedData[] = null;
byte b1 = 0, b2 = 0, b3 = 0, b4 = 0, marker0 = 0, marker1 = 0;
// Throw away anything not in base64Data
int encodedIndex = 0;
int dataIndex = 0;
{
// this sizes the output array properly - rlw
int lastData = base64Data.length;
// ignore the '=' padding
while (base64Data[lastData - 1] == PAD) {
if (--lastData == 0) {
return new byte[0];
}
}
decodedData = new byte[lastData - numberQuadruple];
}
for (int i = 0; i < numberQuadruple; i++) {
dataIndex = i * 4;
marker0 = base64Data[dataIndex + 2];
marker1 = base64Data[dataIndex + 3];
b1 = base64Alphabet[base64Data[dataIndex]];
b2 = base64Alphabet[base64Data[dataIndex + 1]];
if (marker0 != PAD && marker1 != PAD) {
//No PAD e.g 3cQl
b3 = base64Alphabet[marker0];
b4 = base64Alphabet[marker1];
decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
decodedData[encodedIndex + 1] =
(byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
decodedData[encodedIndex + 2] = (byte) (b3 << 6 | b4);
} else if (marker0 == PAD) {
//Two PAD e.g. 3c[Pad][Pad]
decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
} else if (marker1 == PAD) {
//One PAD e.g. 3cQ[Pad]
b3 = base64Alphabet[marker0];
decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
decodedData[encodedIndex + 1] =
(byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
}
encodedIndex += 3;
}
return decodedData;
}
/**
* Check octect wheter it is a base64 encoding.
*
* @param octect to be checked byte
* @return ture if it is base64 encoding, false otherwise.
*/
private static boolean isBase64(byte octect) {
if (octect == PAD) {
return true;
} else if (base64Alphabet[octect] == -1) {
return false;
} else {
return true;
}
}
/**
* Discards any characters outside of the base64 alphabet, per
* the requirements on page 25 of RFC 2045 - "Any characters
* outside of the base64 alphabet are to be ignored in base64
* encoded data."
*
* @param data The base-64 encoded data to groom
* @return The data, less non-base64 characters (see RFC 2045).
*/
static byte[] discardNonBase64(byte[] data) {
byte groomedData[] = new byte[data.length];
int bytesCopied = 0;
for (int i = 0; i < data.length; i++) {
if (isBase64(data[i])) {
groomedData[bytesCopied++] = data[i];
}
}
byte packedData[] = new byte[bytesCopied];
System.arraycopy(groomedData, 0, packedData, 0, bytesCopied);
return packedData;
}
}

View File

@ -1,172 +0,0 @@
/*
* Copyright (C) 2007 Esmertec AG.
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ws.com.google.android.mms.pdu;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
public class CharacterSets {
/**
* IANA assigned MIB enum numbers.
*
* From wap-230-wsp-20010705-a.pdf
* Any-charset = <Octet 128>
* Equivalent to the special RFC2616 charset value "*"
*/
public static final int ANY_CHARSET = 0x00;
public static final int US_ASCII = 0x03;
public static final int ISO_8859_1 = 0x04;
public static final int ISO_8859_2 = 0x05;
public static final int ISO_8859_3 = 0x06;
public static final int ISO_8859_4 = 0x07;
public static final int ISO_8859_5 = 0x08;
public static final int ISO_8859_6 = 0x09;
public static final int ISO_8859_7 = 0x0A;
public static final int ISO_8859_8 = 0x0B;
public static final int ISO_8859_9 = 0x0C;
public static final int SHIFT_JIS = 0x11;
public static final int UTF_8 = 0x6A;
public static final int BIG5 = 0x07EA;
public static final int UCS2 = 0x03E8;
public static final int UTF_16 = 0x03F7;
/**
* If the encoding of given data is unsupported, use UTF_8 to decode it.
*/
public static final int DEFAULT_CHARSET = UTF_8;
/**
* Array of MIB enum numbers.
*/
private static final int[] MIBENUM_NUMBERS = {
ANY_CHARSET,
US_ASCII,
ISO_8859_1,
ISO_8859_2,
ISO_8859_3,
ISO_8859_4,
ISO_8859_5,
ISO_8859_6,
ISO_8859_7,
ISO_8859_8,
ISO_8859_9,
SHIFT_JIS,
UTF_8,
BIG5,
UCS2,
UTF_16,
};
/**
* The Well-known-charset Mime name.
*/
public static final String MIMENAME_ANY_CHARSET = "*";
public static final String MIMENAME_US_ASCII = "us-ascii";
public static final String MIMENAME_ISO_8859_1 = "iso-8859-1";
public static final String MIMENAME_ISO_8859_2 = "iso-8859-2";
public static final String MIMENAME_ISO_8859_3 = "iso-8859-3";
public static final String MIMENAME_ISO_8859_4 = "iso-8859-4";
public static final String MIMENAME_ISO_8859_5 = "iso-8859-5";
public static final String MIMENAME_ISO_8859_6 = "iso-8859-6";
public static final String MIMENAME_ISO_8859_7 = "iso-8859-7";
public static final String MIMENAME_ISO_8859_8 = "iso-8859-8";
public static final String MIMENAME_ISO_8859_9 = "iso-8859-9";
public static final String MIMENAME_SHIFT_JIS = "shift_JIS";
public static final String MIMENAME_UTF_8 = "utf-8";
public static final String MIMENAME_BIG5 = "big5";
public static final String MIMENAME_UCS2 = "iso-10646-ucs-2";
public static final String MIMENAME_UTF_16 = "utf-16";
public static final String DEFAULT_CHARSET_NAME = MIMENAME_UTF_8;
/**
* Array of the names of character sets.
*/
private static final String[] MIME_NAMES = {
MIMENAME_ANY_CHARSET,
MIMENAME_US_ASCII,
MIMENAME_ISO_8859_1,
MIMENAME_ISO_8859_2,
MIMENAME_ISO_8859_3,
MIMENAME_ISO_8859_4,
MIMENAME_ISO_8859_5,
MIMENAME_ISO_8859_6,
MIMENAME_ISO_8859_7,
MIMENAME_ISO_8859_8,
MIMENAME_ISO_8859_9,
MIMENAME_SHIFT_JIS,
MIMENAME_UTF_8,
MIMENAME_BIG5,
MIMENAME_UCS2,
MIMENAME_UTF_16,
};
private static final HashMap<Integer, String> MIBENUM_TO_NAME_MAP;
private static final HashMap<String, Integer> NAME_TO_MIBENUM_MAP;
static {
// Create the HashMaps.
MIBENUM_TO_NAME_MAP = new HashMap<Integer, String>();
NAME_TO_MIBENUM_MAP = new HashMap<String, Integer>();
assert(MIBENUM_NUMBERS.length == MIME_NAMES.length);
int count = MIBENUM_NUMBERS.length - 1;
for(int i = 0; i <= count; i++) {
MIBENUM_TO_NAME_MAP.put(MIBENUM_NUMBERS[i], MIME_NAMES[i]);
NAME_TO_MIBENUM_MAP.put(MIME_NAMES[i], MIBENUM_NUMBERS[i]);
}
}
private CharacterSets() {} // Non-instantiatable
/**
* Map an MIBEnum number to the name of the charset which this number
* is assigned to by IANA.
*
* @param mibEnumValue An IANA assigned MIBEnum number.
* @return The name string of the charset.
* @throws UnsupportedEncodingException
*/
public static String getMimeName(int mibEnumValue)
throws UnsupportedEncodingException {
String name = MIBENUM_TO_NAME_MAP.get(mibEnumValue);
if (name == null) {
throw new UnsupportedEncodingException();
}
return name;
}
/**
* Map a well-known charset name to its assigned MIBEnum number.
*
* @param mimeName The charset name.
* @return The MIBEnum number assigned by IANA for this charset.
* @throws UnsupportedEncodingException
*/
public static int getMibEnumValue(String mimeName)
throws UnsupportedEncodingException {
if(null == mimeName) {
return -1;
}
Integer mibEnumValue = NAME_TO_MIBENUM_MAP.get(mimeName);
if (mibEnumValue == null) {
throw new UnsupportedEncodingException();
}
return mibEnumValue;
}
}

View File

@ -1,138 +0,0 @@
/*
* Copyright (C) 2007 Esmertec AG.
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ws.com.google.android.mms.pdu;
import ws.com.google.android.mms.InvalidHeaderValueException;
/**
* M-Delivery.Ind Pdu.
*/
public class DeliveryInd extends GenericPdu {
/**
* Empty constructor.
* Since the Pdu corresponding to this class is constructed
* by the Proxy-Relay server, this class is only instantiated
* by the Pdu Parser.
*
* @throws InvalidHeaderValueException if error occurs.
*/
public DeliveryInd() throws InvalidHeaderValueException {
super();
setMessageType(PduHeaders.MESSAGE_TYPE_DELIVERY_IND);
}
/**
* Constructor with given headers.
*
* @param headers Headers for this PDU.
*/
DeliveryInd(PduHeaders headers) {
super(headers);
}
/**
* Get Date value.
*
* @return the value
*/
public long getDate() {
return mPduHeaders.getLongInteger(PduHeaders.DATE);
}
/**
* Set Date value.
*
* @param value the value
*/
public void setDate(long value) {
mPduHeaders.setLongInteger(value, PduHeaders.DATE);
}
/**
* Get Message-ID value.
*
* @return the value
*/
public byte[] getMessageId() {
return mPduHeaders.getTextString(PduHeaders.MESSAGE_ID);
}
/**
* Set Message-ID value.
*
* @param value the value, should not be null
* @throws NullPointerException if the value is null.
*/
public void setMessageId(byte[] value) {
mPduHeaders.setTextString(value, PduHeaders.MESSAGE_ID);
}
/**
* Get Status value.
*
* @return the value
*/
public int getStatus() {
return mPduHeaders.getOctet(PduHeaders.STATUS);
}
/**
* Set Status value.
*
* @param value the value
* @throws InvalidHeaderValueException if the value is invalid.
*/
public void setStatus(int value) throws InvalidHeaderValueException {
mPduHeaders.setOctet(value, PduHeaders.STATUS);
}
/**
* Get To value.
*
* @return the value
*/
public EncodedStringValue[] getTo() {
return mPduHeaders.getEncodedStringValues(PduHeaders.TO);
}
/**
* set To value.
*
* @param value the value
* @throws NullPointerException if the value is null.
*/
public void setTo(EncodedStringValue[] value) {
mPduHeaders.setEncodedStringValues(value, PduHeaders.TO);
}
/*
* Optional, not supported header fields:
*
* public byte[] getApplicId() {return null;}
* public void setApplicId(byte[] value) {}
*
* public byte[] getAuxApplicId() {return null;}
* public void getAuxApplicId(byte[] value) {}
*
* public byte[] getReplyApplicId() {return 0x00;}
* public void setReplyApplicId(byte[] value) {}
*
* public EncodedStringValue getStatusText() {return null;}
* public void setStatusText(EncodedStringValue value) {}
*/
}

View File

@ -1,284 +0,0 @@
/*
* Copyright (C) 2007-2008 Esmertec AG.
* Copyright (C) 2007-2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ws.com.google.android.mms.pdu;
import android.util.Config;
import android.util.Log;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
/**
* Encoded-string-value = Text-string | Value-length Char-set Text-string
*/
public class EncodedStringValue implements Cloneable {
private static final String TAG = "EncodedStringValue";
private static final boolean DEBUG = false;
private static final boolean LOCAL_LOGV = DEBUG ? Config.LOGD : Config.LOGV;
/**
* The Char-set value.
*/
private int mCharacterSet;
/**
* The Text-string value.
*/
private byte[] mData;
/**
* Constructor.
*
* @param charset the Char-set value
* @param data the Text-string value
* @throws NullPointerException if Text-string value is null.
*/
public EncodedStringValue(int charset, byte[] data) {
// TODO: CharSet needs to be validated against MIBEnum.
if(null == data) {
throw new NullPointerException("EncodedStringValue: Text-string is null.");
}
mCharacterSet = charset;
mData = new byte[data.length];
System.arraycopy(data, 0, mData, 0, data.length);
}
/**
* Constructor.
*
* @param data the Text-string value
* @throws NullPointerException if Text-string value is null.
*/
public EncodedStringValue(byte[] data) {
this(CharacterSets.DEFAULT_CHARSET, data);
}
public EncodedStringValue(String data) {
try {
mData = data.getBytes(CharacterSets.DEFAULT_CHARSET_NAME);
mCharacterSet = CharacterSets.DEFAULT_CHARSET;
} catch (UnsupportedEncodingException e) {
Log.e(TAG, "Default encoding must be supported.", e);
}
}
/**
* Get Char-set value.
*
* @return the value
*/
public int getCharacterSet() {
return mCharacterSet;
}
/**
* Set Char-set value.
*
* @param charset the Char-set value
*/
public void setCharacterSet(int charset) {
// TODO: CharSet needs to be validated against MIBEnum.
mCharacterSet = charset;
}
/**
* Get Text-string value.
*
* @return the value
*/
public byte[] getTextString() {
byte[] byteArray = new byte[mData.length];
System.arraycopy(mData, 0, byteArray, 0, mData.length);
return byteArray;
}
/**
* Set Text-string value.
*
* @param textString the Text-string value
* @throws NullPointerException if Text-string value is null.
*/
public void setTextString(byte[] textString) {
if(null == textString) {
throw new NullPointerException("EncodedStringValue: Text-string is null.");
}
mData = new byte[textString.length];
System.arraycopy(textString, 0, mData, 0, textString.length);
}
/**
* Convert this object to a {@link java.lang.String}. If the encoding of
* the EncodedStringValue is null or unsupported, it will be
* treated as iso-8859-1 encoding.
*
* @return The decoded String.
*/
public String getString() {
if (CharacterSets.ANY_CHARSET == mCharacterSet) {
return new String(mData); // system default encoding.
} else {
try {
String name = CharacterSets.getMimeName(mCharacterSet);
return new String(mData, name);
} catch (UnsupportedEncodingException e) {
if (LOCAL_LOGV) {
Log.v(TAG, e.getMessage(), e);
}
try {
return new String(mData, CharacterSets.MIMENAME_ISO_8859_1);
} catch (UnsupportedEncodingException _) {
return new String(mData); // system default encoding.
}
}
}
}
/**
* Append to Text-string.
*
* @param textString the textString to append
* @throws NullPointerException if the text String is null
* or an IOException occured.
*/
public void appendTextString(byte[] textString) {
if(null == textString) {
throw new NullPointerException("Text-string is null.");
}
if(null == mData) {
mData = new byte[textString.length];
System.arraycopy(textString, 0, mData, 0, textString.length);
} else {
ByteArrayOutputStream newTextString = new ByteArrayOutputStream();
try {
newTextString.write(mData);
newTextString.write(textString);
} catch (IOException e) {
e.printStackTrace();
throw new NullPointerException(
"appendTextString: failed when write a new Text-string");
}
mData = newTextString.toByteArray();
}
}
/*
* (non-Javadoc)
* @see java.lang.Object#clone()
*/
@Override
public Object clone() throws CloneNotSupportedException {
super.clone();
int len = mData.length;
byte[] dstBytes = new byte[len];
System.arraycopy(mData, 0, dstBytes, 0, len);
try {
return new EncodedStringValue(mCharacterSet, dstBytes);
} catch (Exception e) {
Log.e(TAG, "failed to clone an EncodedStringValue: " + this);
e.printStackTrace();
throw new CloneNotSupportedException(e.getMessage());
}
}
/**
* Split this encoded string around matches of the given pattern.
*
* @param pattern the delimiting pattern
* @return the array of encoded strings computed by splitting this encoded
* string around matches of the given pattern
*/
public EncodedStringValue[] split(String pattern) {
String[] temp = getString().split(pattern);
EncodedStringValue[] ret = new EncodedStringValue[temp.length];
for (int i = 0; i < ret.length; ++i) {
try {
ret[i] = new EncodedStringValue(mCharacterSet,
temp[i].getBytes());
} catch (NullPointerException _) {
// Can't arrive here
return null;
}
}
return ret;
}
/**
* Extract an EncodedStringValue[] from a given String.
*/
public static EncodedStringValue[] extract(String src) {
String[] values = src.split(";");
ArrayList<EncodedStringValue> list = new ArrayList<EncodedStringValue>();
for (int i = 0; i < values.length; i++) {
if (values[i].length() > 0) {
list.add(new EncodedStringValue(values[i]));
}
}
int len = list.size();
if (len > 0) {
return list.toArray(new EncodedStringValue[len]);
} else {
return null;
}
}
/**
* Concatenate an EncodedStringValue[] into a single String.
*/
public static String concat(EncodedStringValue[] addr) {
StringBuilder sb = new StringBuilder();
int maxIndex = addr.length - 1;
for (int i = 0; i <= maxIndex; i++) {
sb.append(addr[i].getString());
if (i < maxIndex) {
sb.append(";");
}
}
return sb.toString();
}
public static EncodedStringValue copy(EncodedStringValue value) {
if (value == null) {
return null;
}
return new EncodedStringValue(value.mCharacterSet, value.mData);
}
public static EncodedStringValue[] encodeStrings(String[] array) {
int count = array.length;
if (count > 0) {
EncodedStringValue[] encodedArray = new EncodedStringValue[count];
for (int i = 0; i < count; i++) {
encodedArray[i] = new EncodedStringValue(array[i]);
}
return encodedArray;
}
return null;
}
}

View File

@ -1,113 +0,0 @@
/*
* Copyright (C) 2007 Esmertec AG.
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ws.com.google.android.mms.pdu;
import ws.com.google.android.mms.InvalidHeaderValueException;
public class GenericPdu {
/**
* The headers of pdu.
*/
PduHeaders mPduHeaders = null;
/**
* Constructor.
*/
public GenericPdu() {
mPduHeaders = new PduHeaders();
}
/**
* Constructor.
*
* @param headers Headers for this PDU.
*/
GenericPdu(PduHeaders headers) {
mPduHeaders = headers;
}
/**
* Get the headers of this PDU.
*
* @return A PduHeaders of this PDU.
*/
public PduHeaders getPduHeaders() {
return mPduHeaders;
}
/**
* Get X-Mms-Message-Type field value.
*
* @return the X-Mms-Report-Allowed value
*/
public int getMessageType() {
return mPduHeaders.getOctet(PduHeaders.MESSAGE_TYPE);
}
/**
* Set X-Mms-Message-Type field value.
*
* @param value the value
* @throws InvalidHeaderValueException if the value is invalid.
* RuntimeException if field's value is not Octet.
*/
public void setMessageType(int value) throws InvalidHeaderValueException {
mPduHeaders.setOctet(value, PduHeaders.MESSAGE_TYPE);
}
/**
* Get X-Mms-MMS-Version field value.
*
* @return the X-Mms-MMS-Version value
*/
public int getMmsVersion() {
return mPduHeaders.getOctet(PduHeaders.MMS_VERSION);
}
/**
* Set X-Mms-MMS-Version field value.
*
* @param value the value
* @throws InvalidHeaderValueException if the value is invalid.
* RuntimeException if field's value is not Octet.
*/
public void setMmsVersion(int value) throws InvalidHeaderValueException {
mPduHeaders.setOctet(value, PduHeaders.MMS_VERSION);
}
/**
* Get From value.
* From-value = Value-length
* (Address-present-token Encoded-string-value | Insert-address-token)
*
* @return the value
*/
public EncodedStringValue getFrom() {
return mPduHeaders.getEncodedStringValue(PduHeaders.FROM);
}
/**
* Set From value.
*
* @param value the value
* @throws NullPointerException if the value is null.
*/
public void setFrom(EncodedStringValue value) {
mPduHeaders.setEncodedStringValue(value, PduHeaders.FROM);
}
}

View File

@ -1,150 +0,0 @@
/*
* Copyright (C) 2007 Esmertec AG.
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ws.com.google.android.mms.pdu;
import ws.com.google.android.mms.InvalidHeaderValueException;
/**
* Multimedia message PDU.
*/
public class MultimediaMessagePdu extends GenericPdu{
/**
* The body.
*/
private PduBody mMessageBody;
/**
* Constructor.
*/
public MultimediaMessagePdu() {
super();
}
/**
* Constructor.
*
* @param header the header of this PDU
* @param body the body of this PDU
*/
public MultimediaMessagePdu(PduHeaders header, PduBody body) {
super(header);
mMessageBody = body;
}
/**
* Constructor with given headers.
*
* @param headers Headers for this PDU.
*/
MultimediaMessagePdu(PduHeaders headers) {
super(headers);
}
/**
* Get body of the PDU.
*
* @return the body
*/
public PduBody getBody() {
return mMessageBody;
}
/**
* Set body of the PDU.
*
* @param body the body
*/
public void setBody(PduBody body) {
mMessageBody = body;
}
/**
* Get subject.
*
* @return the value
*/
public EncodedStringValue getSubject() {
return mPduHeaders.getEncodedStringValue(PduHeaders.SUBJECT);
}
/**
* Set subject.
*
* @param value the value
* @throws NullPointerException if the value is null.
*/
public void setSubject(EncodedStringValue value) {
mPduHeaders.setEncodedStringValue(value, PduHeaders.SUBJECT);
}
/**
* Get To value.
*
* @return the value
*/
public EncodedStringValue[] getTo() {
return mPduHeaders.getEncodedStringValues(PduHeaders.TO);
}
/**
* Add a "To" value.
*
* @param value the value
* @throws NullPointerException if the value is null.
*/
public void addTo(EncodedStringValue value) {
mPduHeaders.appendEncodedStringValue(value, PduHeaders.TO);
}
/**
* Get X-Mms-Priority value.
*
* @return the value
*/
public int getPriority() {
return mPduHeaders.getOctet(PduHeaders.PRIORITY);
}
/**
* Set X-Mms-Priority value.
*
* @param value the value
* @throws InvalidHeaderValueException if the value is invalid.
*/
public void setPriority(int value) throws InvalidHeaderValueException {
mPduHeaders.setOctet(value, PduHeaders.PRIORITY);
}
/**
* Get Date value.
*
* @return the value
*/
public long getDate() {
return mPduHeaders.getLongInteger(PduHeaders.DATE);
}
/**
* Set Date value in seconds.
*
* @param value the value
*/
public void setDate(long value) {
mPduHeaders.setLongInteger(value, PduHeaders.DATE);
}
}

View File

@ -1,289 +0,0 @@
/*
* Copyright (C) 2007 Esmertec AG.
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ws.com.google.android.mms.pdu;
import ws.com.google.android.mms.InvalidHeaderValueException;
/**
* M-Notification.ind PDU.
*/
public class NotificationInd extends GenericPdu {
/**
* Empty constructor.
* Since the Pdu corresponding to this class is constructed
* by the Proxy-Relay server, this class is only instantiated
* by the Pdu Parser.
*
* @throws InvalidHeaderValueException if error occurs.
* RuntimeException if an undeclared error occurs.
*/
public NotificationInd() throws InvalidHeaderValueException {
super();
setMessageType(PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND);
}
/**
* Constructor with given headers.
*
* @param headers Headers for this PDU.
*/
public NotificationInd(PduHeaders headers) {
super(headers);
}
public int getStatus() {
return mPduHeaders.getOctet(PduHeaders.STATUS);
}
/**
* Get X-Mms-Content-Class Value.
*
* @return the value
*/
public int getContentClass() {
return mPduHeaders.getOctet(PduHeaders.CONTENT_CLASS);
}
/**
* Set X-Mms-Content-Class Value.
*
* @param value the value
* @throws InvalidHeaderValueException if the value is invalid.
* RuntimeException if an undeclared error occurs.
*/
public void setContentClass(int value) throws InvalidHeaderValueException {
mPduHeaders.setOctet(value, PduHeaders.CONTENT_CLASS);
}
/**
* Get X-Mms-Content-Location value.
* When used in a PDU other than M-Mbox-Delete.conf and M-Delete.conf:
* Content-location-value = Uri-value
*
* @return the value
*/
public byte[] getContentLocation() {
return mPduHeaders.getTextString(PduHeaders.CONTENT_LOCATION);
}
/**
* Set X-Mms-Content-Location value.
*
* @param value the value
* @throws NullPointerException if the value is null.
* RuntimeException if an undeclared error occurs.
*/
public void setContentLocation(byte[] value) {
mPduHeaders.setTextString(value, PduHeaders.CONTENT_LOCATION);
}
/**
* Get X-Mms-Expiry value.
*
* Expiry-value = Value-length
* (Absolute-token Date-value | Relative-token Delta-seconds-value)
*
* @return the value
*/
public long getExpiry() {
return mPduHeaders.getLongInteger(PduHeaders.EXPIRY);
}
/**
* Set X-Mms-Expiry value.
*
* @param value the value
* @throws RuntimeException if an undeclared error occurs.
*/
public void setExpiry(long value) {
mPduHeaders.setLongInteger(value, PduHeaders.EXPIRY);
}
/**
* Get From value.
* From-value = Value-length
* (Address-present-token Encoded-string-value | Insert-address-token)
*
* @return the value
*/
public EncodedStringValue getFrom() {
return mPduHeaders.getEncodedStringValue(PduHeaders.FROM);
}
/**
* Set From value.
*
* @param value the value
* @throws NullPointerException if the value is null.
* RuntimeException if an undeclared error occurs.
*/
public void setFrom(EncodedStringValue value) {
mPduHeaders.setEncodedStringValue(value, PduHeaders.FROM);
}
/**
* Get X-Mms-Message-Class value.
* Message-class-value = Class-identifier | Token-text
* Class-identifier = Personal | Advertisement | Informational | Auto
*
* @return the value
*/
public byte[] getMessageClass() {
return mPduHeaders.getTextString(PduHeaders.MESSAGE_CLASS);
}
/**
* Set X-Mms-Message-Class value.
*
* @param value the value
* @throws NullPointerException if the value is null.
* RuntimeException if an undeclared error occurs.
*/
public void setMessageClass(byte[] value) {
mPduHeaders.setTextString(value, PduHeaders.MESSAGE_CLASS);
}
/**
* Get X-Mms-Message-Size value.
* Message-size-value = Long-integer
*
* @return the value
*/
public long getMessageSize() {
return mPduHeaders.getLongInteger(PduHeaders.MESSAGE_SIZE);
}
/**
* Set X-Mms-Message-Size value.
*
* @param value the value
* @throws RuntimeException if an undeclared error occurs.
*/
public void setMessageSize(long value) {
mPduHeaders.setLongInteger(value, PduHeaders.MESSAGE_SIZE);
}
/**
* Get subject.
*
* @return the value
*/
public EncodedStringValue getSubject() {
return mPduHeaders.getEncodedStringValue(PduHeaders.SUBJECT);
}
/**
* Set subject.
*
* @param value the value
* @throws NullPointerException if the value is null.
* RuntimeException if an undeclared error occurs.
*/
public void setSubject(EncodedStringValue value) {
mPduHeaders.setEncodedStringValue(value, PduHeaders.SUBJECT);
}
/**
* Get X-Mms-Transaction-Id.
*
* @return the value
*/
public byte[] getTransactionId() {
return mPduHeaders.getTextString(PduHeaders.TRANSACTION_ID);
}
/**
* Set X-Mms-Transaction-Id.
*
* @param value the value
* @throws NullPointerException if the value is null.
* RuntimeException if an undeclared error occurs.
*/
public void setTransactionId(byte[] value) {
mPduHeaders.setTextString(value, PduHeaders.TRANSACTION_ID);
}
/**
* Get X-Mms-Delivery-Report Value.
*
* @return the value
*/
public int getDeliveryReport() {
return mPduHeaders.getOctet(PduHeaders.DELIVERY_REPORT);
}
/**
* Set X-Mms-Delivery-Report Value.
*
* @param value the value
* @throws InvalidHeaderValueException if the value is invalid.
* RuntimeException if an undeclared error occurs.
*/
public void setDeliveryReport(int value) throws InvalidHeaderValueException {
mPduHeaders.setOctet(value, PduHeaders.DELIVERY_REPORT);
}
/*
* Optional, not supported header fields:
*
* public byte[] getApplicId() {return null;}
* public void setApplicId(byte[] value) {}
*
* public byte[] getAuxApplicId() {return null;}
* public void getAuxApplicId(byte[] value) {}
*
* public byte getDrmContent() {return 0x00;}
* public void setDrmContent(byte value) {}
*
* public byte getDistributionIndicator() {return 0x00;}
* public void setDistributionIndicator(byte value) {}
*
* public ElementDescriptorValue getElementDescriptor() {return null;}
* public void getElementDescriptor(ElementDescriptorValue value) {}
*
* public byte getPriority() {return 0x00;}
* public void setPriority(byte value) {}
*
* public byte getRecommendedRetrievalMode() {return 0x00;}
* public void setRecommendedRetrievalMode(byte value) {}
*
* public byte getRecommendedRetrievalModeText() {return 0x00;}
* public void setRecommendedRetrievalModeText(byte value) {}
*
* public byte[] getReplaceId() {return 0x00;}
* public void setReplaceId(byte[] value) {}
*
* public byte[] getReplyApplicId() {return 0x00;}
* public void setReplyApplicId(byte[] value) {}
*
* public byte getReplyCharging() {return 0x00;}
* public void setReplyCharging(byte value) {}
*
* public byte getReplyChargingDeadline() {return 0x00;}
* public void setReplyChargingDeadline(byte value) {}
*
* public byte[] getReplyChargingId() {return 0x00;}
* public void setReplyChargingId(byte[] value) {}
*
* public long getReplyChargingSize() {return 0;}
* public void setReplyChargingSize(long value) {}
*
* public byte getStored() {return 0x00;}
* public void setStored(byte value) {}
*/
}

View File

@ -1,114 +0,0 @@
/*
* Copyright (C) 2007 Esmertec AG.
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ws.com.google.android.mms.pdu;
import ws.com.google.android.mms.InvalidHeaderValueException;
/**
* M-NofifyResp.ind PDU.
*/
public class NotifyRespInd extends GenericPdu {
/**
* Constructor, used when composing a M-NotifyResp.ind pdu.
*
* @param mmsVersion current version of mms
* @param transactionId the transaction-id value
* @param status the status value
* @throws InvalidHeaderValueException if parameters are invalid.
* NullPointerException if transactionId is null.
* RuntimeException if an undeclared error occurs.
*/
public NotifyRespInd(int mmsVersion,
byte[] transactionId,
int status) throws InvalidHeaderValueException {
super();
setMessageType(PduHeaders.MESSAGE_TYPE_NOTIFYRESP_IND);
setMmsVersion(mmsVersion);
setTransactionId(transactionId);
setStatus(status);
}
/**
* Constructor with given headers.
*
* @param headers Headers for this PDU.
*/
NotifyRespInd(PduHeaders headers) {
super(headers);
}
/**
* Get X-Mms-Report-Allowed field value.
*
* @return the X-Mms-Report-Allowed value
*/
public int getReportAllowed() {
return mPduHeaders.getOctet(PduHeaders.REPORT_ALLOWED);
}
/**
* Set X-Mms-Report-Allowed field value.
*
* @param value the value
* @throws InvalidHeaderValueException if the value is invalid.
* RuntimeException if an undeclared error occurs.
*/
public void setReportAllowed(int value) throws InvalidHeaderValueException {
mPduHeaders.setOctet(value, PduHeaders.REPORT_ALLOWED);
}
/**
* Set X-Mms-Status field value.
*
* @param value the value
* @throws InvalidHeaderValueException if the value is invalid.
* RuntimeException if an undeclared error occurs.
*/
public void setStatus(int value) throws InvalidHeaderValueException {
mPduHeaders.setOctet(value, PduHeaders.STATUS);
}
/**
* GetX-Mms-Status field value.
*
* @return the X-Mms-Status value
*/
public int getStatus() {
return mPduHeaders.getOctet(PduHeaders.STATUS);
}
/**
* Get X-Mms-Transaction-Id field value.
*
* @return the X-Mms-Report-Allowed value
*/
public byte[] getTransactionId() {
return mPduHeaders.getTextString(PduHeaders.TRANSACTION_ID);
}
/**
* Set X-Mms-Transaction-Id field value.
*
* @param value the value
* @throws NullPointerException if the value is null.
* RuntimeException if an undeclared error occurs.
*/
public void setTransactionId(byte[] value) {
mPduHeaders.setTextString(value, PduHeaders.TRANSACTION_ID);
}
}

View File

@ -1,191 +0,0 @@
/*
* Copyright (C) 2007 Esmertec AG.
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ws.com.google.android.mms.pdu;
import java.util.HashMap;
import java.util.Map;
import java.util.Vector;
public class PduBody {
private Vector<PduPart> mParts = null;
private Map<String, PduPart> mPartMapByContentId = null;
private Map<String, PduPart> mPartMapByContentLocation = null;
private Map<String, PduPart> mPartMapByName = null;
private Map<String, PduPart> mPartMapByFileName = null;
/**
* Constructor.
*/
public PduBody() {
mParts = new Vector<PduPart>();
mPartMapByContentId = new HashMap<String, PduPart>();
mPartMapByContentLocation = new HashMap<String, PduPart>();
mPartMapByName = new HashMap<String, PduPart>();
mPartMapByFileName = new HashMap<String, PduPart>();
}
private void putPartToMaps(PduPart part) {
// Put part to mPartMapByContentId.
byte[] contentId = part.getContentId();
if(null != contentId) {
mPartMapByContentId.put(new String(contentId), part);
}
// Put part to mPartMapByContentLocation.
byte[] contentLocation = part.getContentLocation();
if(null != contentLocation) {
String clc = new String(contentLocation);
mPartMapByContentLocation.put(clc, part);
}
// Put part to mPartMapByName.
byte[] name = part.getName();
if(null != name) {
String clc = new String(name);
mPartMapByName.put(clc, part);
}
// Put part to mPartMapByFileName.
byte[] fileName = part.getFilename();
if(null != fileName) {
String clc = new String(fileName);
mPartMapByFileName.put(clc, part);
}
}
/**
* Appends the specified part to the end of this body.
*
* @param part part to be appended
* @return true when success, false when fail
* @throws NullPointerException when part is null
*/
public boolean addPart(PduPart part) {
if(null == part) {
throw new NullPointerException();
}
putPartToMaps(part);
return mParts.add(part);
}
/**
* Inserts the specified part at the specified position.
*
* @param index index at which the specified part is to be inserted
* @param part part to be inserted
* @throws NullPointerException when part is null
*/
public void addPart(int index, PduPart part) {
if(null == part) {
throw new NullPointerException();
}
putPartToMaps(part);
mParts.add(index, part);
}
/**
* Removes the part at the specified position.
*
* @param index index of the part to return
* @return part at the specified index
*/
public PduPart removePart(int index) {
return mParts.remove(index);
}
/**
* Remove all of the parts.
*/
public void removeAll() {
mParts.clear();
}
/**
* Get the part at the specified position.
*
* @param index index of the part to return
* @return part at the specified index
*/
public PduPart getPart(int index) {
return mParts.get(index);
}
/**
* Get the index of the specified part.
*
* @param part the part object
* @return index the index of the first occurrence of the part in this body
*/
public int getPartIndex(PduPart part) {
return mParts.indexOf(part);
}
/**
* Get the number of parts.
*
* @return the number of parts
*/
public int getPartsNum() {
return mParts.size();
}
/**
* Get pdu part by content id.
*
* @param cid the value of content id.
* @return the pdu part.
*/
public PduPart getPartByContentId(String cid) {
return mPartMapByContentId.get(cid);
}
/**
* Get pdu part by Content-Location. Content-Location of part is
* the same as filename and name(param of content-type).
*
* @param fileName the value of filename.
* @return the pdu part.
*/
public PduPart getPartByContentLocation(String contentLocation) {
return mPartMapByContentLocation.get(contentLocation);
}
/**
* Get pdu part by name.
*
* @param fileName the value of filename.
* @return the pdu part.
*/
public PduPart getPartByName(String name) {
return mPartMapByName.get(name);
}
/**
* Get pdu part by filename.
*
* @param fileName the value of filename.
* @return the pdu part.
*/
public PduPart getPartByFileName(String filename) {
return mPartMapByFileName.get(filename);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,110 +0,0 @@
/*
* Copyright (C) 2007 Esmertec AG.
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ws.com.google.android.mms.pdu;
public class PduContentTypes {
/**
* All content types. From:
* http://www.openmobilealliance.org/tech/omna/omna-wsp-content-type.htm
*/
static final String[] contentTypes = {
"*/*", /* 0x00 */
"text/*", /* 0x01 */
"text/html", /* 0x02 */
"text/plain", /* 0x03 */
"text/x-hdml", /* 0x04 */
"text/x-ttml", /* 0x05 */
"text/x-vCalendar", /* 0x06 */
"text/x-vCard", /* 0x07 */
"text/vnd.wap.wml", /* 0x08 */
"text/vnd.wap.wmlscript", /* 0x09 */
"text/vnd.wap.wta-event", /* 0x0A */
"multipart/*", /* 0x0B */
"multipart/mixed", /* 0x0C */
"multipart/form-data", /* 0x0D */
"multipart/byterantes", /* 0x0E */
"multipart/alternative", /* 0x0F */
"application/*", /* 0x10 */
"application/java-vm", /* 0x11 */
"application/x-www-form-urlencoded", /* 0x12 */
"application/x-hdmlc", /* 0x13 */
"application/vnd.wap.wmlc", /* 0x14 */
"application/vnd.wap.wmlscriptc", /* 0x15 */
"application/vnd.wap.wta-eventc", /* 0x16 */
"application/vnd.wap.uaprof", /* 0x17 */
"application/vnd.wap.wtls-ca-certificate", /* 0x18 */
"application/vnd.wap.wtls-user-certificate", /* 0x19 */
"application/x-x509-ca-cert", /* 0x1A */
"application/x-x509-user-cert", /* 0x1B */
"image/*", /* 0x1C */
"image/gif", /* 0x1D */
"image/jpeg", /* 0x1E */
"image/tiff", /* 0x1F */
"image/png", /* 0x20 */
"image/vnd.wap.wbmp", /* 0x21 */
"application/vnd.wap.multipart.*", /* 0x22 */
"application/vnd.wap.multipart.mixed", /* 0x23 */
"application/vnd.wap.multipart.form-data", /* 0x24 */
"application/vnd.wap.multipart.byteranges", /* 0x25 */
"application/vnd.wap.multipart.alternative", /* 0x26 */
"application/xml", /* 0x27 */
"text/xml", /* 0x28 */
"application/vnd.wap.wbxml", /* 0x29 */
"application/x-x968-cross-cert", /* 0x2A */
"application/x-x968-ca-cert", /* 0x2B */
"application/x-x968-user-cert", /* 0x2C */
"text/vnd.wap.si", /* 0x2D */
"application/vnd.wap.sic", /* 0x2E */
"text/vnd.wap.sl", /* 0x2F */
"application/vnd.wap.slc", /* 0x30 */
"text/vnd.wap.co", /* 0x31 */
"application/vnd.wap.coc", /* 0x32 */
"application/vnd.wap.multipart.related", /* 0x33 */
"application/vnd.wap.sia", /* 0x34 */
"text/vnd.wap.connectivity-xml", /* 0x35 */
"application/vnd.wap.connectivity-wbxml", /* 0x36 */
"application/pkcs7-mime", /* 0x37 */
"application/vnd.wap.hashed-certificate", /* 0x38 */
"application/vnd.wap.signed-certificate", /* 0x39 */
"application/vnd.wap.cert-response", /* 0x3A */
"application/xhtml+xml", /* 0x3B */
"application/wml+xml", /* 0x3C */
"text/css", /* 0x3D */
"application/vnd.wap.mms-message", /* 0x3E */
"application/vnd.wap.rollover-certificate", /* 0x3F */
"application/vnd.wap.locc+wbxml", /* 0x40 */
"application/vnd.wap.loc+xml", /* 0x41 */
"application/vnd.syncml.dm+wbxml", /* 0x42 */
"application/vnd.syncml.dm+xml", /* 0x43 */
"application/vnd.syncml.notification", /* 0x44 */
"application/vnd.wap.xhtml+xml", /* 0x45 */
"application/vnd.wv.csp.cir", /* 0x46 */
"application/vnd.oma.dd+xml", /* 0x47 */
"application/vnd.oma.drm.message", /* 0x48 */
"application/vnd.oma.drm.content", /* 0x49 */
"application/vnd.oma.drm.rights+xml", /* 0x4A */
"application/vnd.oma.drm.rights+wbxml", /* 0x4B */
"application/vnd.wv.csp+xml", /* 0x4C */
"application/vnd.wv.csp+wbxml", /* 0x4D */
"application/vnd.syncml.ds.notification", /* 0x4E */
"audio/*", /* 0x4F */
"video/*", /* 0x50 */
"application/vnd.oma.dd2+xml", /* 0x51 */
"application/mikey" /* 0x52 */
};
}

View File

@ -1,731 +0,0 @@
/*
* Copyright (C) 2007 Esmertec AG.
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ws.com.google.android.mms.pdu;
import ws.com.google.android.mms.InvalidHeaderValueException;
import java.util.ArrayList;
import java.util.HashMap;
public class PduHeaders {
/**
* All pdu header fields.
*/
public static final int BCC = 0x81;
public static final int CC = 0x82;
public static final int CONTENT_LOCATION = 0x83;
public static final int CONTENT_TYPE = 0x84;
public static final int DATE = 0x85;
public static final int DELIVERY_REPORT = 0x86;
public static final int DELIVERY_TIME = 0x87;
public static final int EXPIRY = 0x88;
public static final int FROM = 0x89;
public static final int MESSAGE_CLASS = 0x8A;
public static final int MESSAGE_ID = 0x8B;
public static final int MESSAGE_TYPE = 0x8C;
public static final int MMS_VERSION = 0x8D;
public static final int MESSAGE_SIZE = 0x8E;
public static final int PRIORITY = 0x8F;
public static final int READ_REPLY = 0x90;
public static final int READ_REPORT = 0x90;
public static final int REPORT_ALLOWED = 0x91;
public static final int RESPONSE_STATUS = 0x92;
public static final int RESPONSE_TEXT = 0x93;
public static final int SENDER_VISIBILITY = 0x94;
public static final int STATUS = 0x95;
public static final int SUBJECT = 0x96;
public static final int TO = 0x97;
public static final int TRANSACTION_ID = 0x98;
public static final int RETRIEVE_STATUS = 0x99;
public static final int RETRIEVE_TEXT = 0x9A;
public static final int READ_STATUS = 0x9B;
public static final int REPLY_CHARGING = 0x9C;
public static final int REPLY_CHARGING_DEADLINE = 0x9D;
public static final int REPLY_CHARGING_ID = 0x9E;
public static final int REPLY_CHARGING_SIZE = 0x9F;
public static final int PREVIOUSLY_SENT_BY = 0xA0;
public static final int PREVIOUSLY_SENT_DATE = 0xA1;
public static final int STORE = 0xA2;
public static final int MM_STATE = 0xA3;
public static final int MM_FLAGS = 0xA4;
public static final int STORE_STATUS = 0xA5;
public static final int STORE_STATUS_TEXT = 0xA6;
public static final int STORED = 0xA7;
public static final int ATTRIBUTES = 0xA8;
public static final int TOTALS = 0xA9;
public static final int MBOX_TOTALS = 0xAA;
public static final int QUOTAS = 0xAB;
public static final int MBOX_QUOTAS = 0xAC;
public static final int MESSAGE_COUNT = 0xAD;
public static final int CONTENT = 0xAE;
public static final int START = 0xAF;
public static final int ADDITIONAL_HEADERS = 0xB0;
public static final int DISTRIBUTION_INDICATOR = 0xB1;
public static final int ELEMENT_DESCRIPTOR = 0xB2;
public static final int LIMIT = 0xB3;
public static final int RECOMMENDED_RETRIEVAL_MODE = 0xB4;
public static final int RECOMMENDED_RETRIEVAL_MODE_TEXT = 0xB5;
public static final int STATUS_TEXT = 0xB6;
public static final int APPLIC_ID = 0xB7;
public static final int REPLY_APPLIC_ID = 0xB8;
public static final int AUX_APPLIC_ID = 0xB9;
public static final int CONTENT_CLASS = 0xBA;
public static final int DRM_CONTENT = 0xBB;
public static final int ADAPTATION_ALLOWED = 0xBC;
public static final int REPLACE_ID = 0xBD;
public static final int CANCEL_ID = 0xBE;
public static final int CANCEL_STATUS = 0xBF;
/**
* X-Mms-Message-Type field types.
*/
public static final int MESSAGE_TYPE_SEND_REQ = 0x80;
public static final int MESSAGE_TYPE_SEND_CONF = 0x81;
public static final int MESSAGE_TYPE_NOTIFICATION_IND = 0x82;
public static final int MESSAGE_TYPE_NOTIFYRESP_IND = 0x83;
public static final int MESSAGE_TYPE_RETRIEVE_CONF = 0x84;
public static final int MESSAGE_TYPE_ACKNOWLEDGE_IND = 0x85;
public static final int MESSAGE_TYPE_DELIVERY_IND = 0x86;
public static final int MESSAGE_TYPE_READ_REC_IND = 0x87;
public static final int MESSAGE_TYPE_READ_ORIG_IND = 0x88;
public static final int MESSAGE_TYPE_FORWARD_REQ = 0x89;
public static final int MESSAGE_TYPE_FORWARD_CONF = 0x8A;
public static final int MESSAGE_TYPE_MBOX_STORE_REQ = 0x8B;
public static final int MESSAGE_TYPE_MBOX_STORE_CONF = 0x8C;
public static final int MESSAGE_TYPE_MBOX_VIEW_REQ = 0x8D;
public static final int MESSAGE_TYPE_MBOX_VIEW_CONF = 0x8E;
public static final int MESSAGE_TYPE_MBOX_UPLOAD_REQ = 0x8F;
public static final int MESSAGE_TYPE_MBOX_UPLOAD_CONF = 0x90;
public static final int MESSAGE_TYPE_MBOX_DELETE_REQ = 0x91;
public static final int MESSAGE_TYPE_MBOX_DELETE_CONF = 0x92;
public static final int MESSAGE_TYPE_MBOX_DESCR = 0x93;
public static final int MESSAGE_TYPE_DELETE_REQ = 0x94;
public static final int MESSAGE_TYPE_DELETE_CONF = 0x95;
public static final int MESSAGE_TYPE_CANCEL_REQ = 0x96;
public static final int MESSAGE_TYPE_CANCEL_CONF = 0x97;
/**
* X-Mms-Delivery-Report |
* X-Mms-Read-Report |
* X-Mms-Report-Allowed |
* X-Mms-Sender-Visibility |
* X-Mms-Store |
* X-Mms-Stored |
* X-Mms-Totals |
* X-Mms-Quotas |
* X-Mms-Distribution-Indicator |
* X-Mms-DRM-Content |
* X-Mms-Adaptation-Allowed |
* field types.
*/
public static final int VALUE_YES = 0x80;
public static final int VALUE_NO = 0x81;
/**
* Delivery-Time |
* Expiry and Reply-Charging-Deadline |
* field type components.
*/
public static final int VALUE_ABSOLUTE_TOKEN = 0x80;
public static final int VALUE_RELATIVE_TOKEN = 0x81;
/**
* X-Mms-MMS-Version field types.
*/
public static final int MMS_VERSION_1_3 = ((1 << 4) | 3);
public static final int MMS_VERSION_1_2 = ((1 << 4) | 2);
public static final int MMS_VERSION_1_1 = ((1 << 4) | 1);
public static final int MMS_VERSION_1_0 = ((1 << 4) | 0);
// Current version is 1.2.
public static final int CURRENT_MMS_VERSION = MMS_VERSION_1_2;
/**
* From field type components.
*/
public static final int FROM_ADDRESS_PRESENT_TOKEN = 0x80;
public static final int FROM_INSERT_ADDRESS_TOKEN = 0x81;
public static final String FROM_ADDRESS_PRESENT_TOKEN_STR = "address-present-token";
public static final String FROM_INSERT_ADDRESS_TOKEN_STR = "insert-address-token";
/**
* X-Mms-Status Field.
*/
public static final int STATUS_EXPIRED = 0x80;
public static final int STATUS_RETRIEVED = 0x81;
public static final int STATUS_REJECTED = 0x82;
public static final int STATUS_DEFERRED = 0x83;
public static final int STATUS_UNRECOGNIZED = 0x84;
public static final int STATUS_INDETERMINATE = 0x85;
public static final int STATUS_FORWARDED = 0x86;
public static final int STATUS_UNREACHABLE = 0x87;
/**
* MM-Flags field type components.
*/
public static final int MM_FLAGS_ADD_TOKEN = 0x80;
public static final int MM_FLAGS_REMOVE_TOKEN = 0x81;
public static final int MM_FLAGS_FILTER_TOKEN = 0x82;
/**
* X-Mms-Message-Class field types.
*/
public static final int MESSAGE_CLASS_PERSONAL = 0x80;
public static final int MESSAGE_CLASS_ADVERTISEMENT = 0x81;
public static final int MESSAGE_CLASS_INFORMATIONAL = 0x82;
public static final int MESSAGE_CLASS_AUTO = 0x83;
public static final String MESSAGE_CLASS_PERSONAL_STR = "personal";
public static final String MESSAGE_CLASS_ADVERTISEMENT_STR = "advertisement";
public static final String MESSAGE_CLASS_INFORMATIONAL_STR = "informational";
public static final String MESSAGE_CLASS_AUTO_STR = "auto";
/**
* X-Mms-Priority field types.
*/
public static final int PRIORITY_LOW = 0x80;
public static final int PRIORITY_NORMAL = 0x81;
public static final int PRIORITY_HIGH = 0x82;
/**
* X-Mms-Response-Status field types.
*/
public static final int RESPONSE_STATUS_OK = 0x80;
public static final int RESPONSE_STATUS_ERROR_UNSPECIFIED = 0x81;
public static final int RESPONSE_STATUS_ERROR_SERVICE_DENIED = 0x82;
public static final int RESPONSE_STATUS_ERROR_MESSAGE_FORMAT_CORRUPT = 0x83;
public static final int RESPONSE_STATUS_ERROR_SENDING_ADDRESS_UNRESOLVED = 0x84;
public static final int RESPONSE_STATUS_ERROR_MESSAGE_NOT_FOUND = 0x85;
public static final int RESPONSE_STATUS_ERROR_NETWORK_PROBLEM = 0x86;
public static final int RESPONSE_STATUS_ERROR_CONTENT_NOT_ACCEPTED = 0x87;
public static final int RESPONSE_STATUS_ERROR_UNSUPPORTED_MESSAGE = 0x88;
public static final int RESPONSE_STATUS_ERROR_TRANSIENT_FAILURE = 0xC0;
public static final int RESPONSE_STATUS_ERROR_TRANSIENT_SENDNG_ADDRESS_UNRESOLVED = 0xC1;
public static final int RESPONSE_STATUS_ERROR_TRANSIENT_MESSAGE_NOT_FOUND = 0xC2;
public static final int RESPONSE_STATUS_ERROR_TRANSIENT_NETWORK_PROBLEM = 0xC3;
public static final int RESPONSE_STATUS_ERROR_TRANSIENT_PARTIAL_SUCCESS = 0xC4;
public static final int RESPONSE_STATUS_ERROR_PERMANENT_FAILURE = 0xE0;
public static final int RESPONSE_STATUS_ERROR_PERMANENT_SERVICE_DENIED = 0xE1;
public static final int RESPONSE_STATUS_ERROR_PERMANENT_MESSAGE_FORMAT_CORRUPT = 0xE2;
public static final int RESPONSE_STATUS_ERROR_PERMANENT_SENDING_ADDRESS_UNRESOLVED = 0xE3;
public static final int RESPONSE_STATUS_ERROR_PERMANENT_MESSAGE_NOT_FOUND = 0xE4;
public static final int RESPONSE_STATUS_ERROR_PERMANENT_CONTENT_NOT_ACCEPTED = 0xE5;
public static final int RESPONSE_STATUS_ERROR_PERMANENT_REPLY_CHARGING_LIMITATIONS_NOT_MET = 0xE6;
public static final int RESPONSE_STATUS_ERROR_PERMANENT_REPLY_CHARGING_REQUEST_NOT_ACCEPTED = 0xE6;
public static final int RESPONSE_STATUS_ERROR_PERMANENT_REPLY_CHARGING_FORWARDING_DENIED = 0xE8;
public static final int RESPONSE_STATUS_ERROR_PERMANENT_REPLY_CHARGING_NOT_SUPPORTED = 0xE9;
public static final int RESPONSE_STATUS_ERROR_PERMANENT_ADDRESS_HIDING_NOT_SUPPORTED = 0xEA;
public static final int RESPONSE_STATUS_ERROR_PERMANENT_LACK_OF_PREPAID = 0xEB;
public static final int RESPONSE_STATUS_ERROR_PERMANENT_END = 0xFF;
/**
* X-Mms-Retrieve-Status field types.
*/
public static final int RETRIEVE_STATUS_OK = 0x80;
public static final int RETRIEVE_STATUS_ERROR_TRANSIENT_FAILURE = 0xC0;
public static final int RETRIEVE_STATUS_ERROR_TRANSIENT_MESSAGE_NOT_FOUND = 0xC1;
public static final int RETRIEVE_STATUS_ERROR_TRANSIENT_NETWORK_PROBLEM = 0xC2;
public static final int RETRIEVE_STATUS_ERROR_PERMANENT_FAILURE = 0xE0;
public static final int RETRIEVE_STATUS_ERROR_PERMANENT_SERVICE_DENIED = 0xE1;
public static final int RETRIEVE_STATUS_ERROR_PERMANENT_MESSAGE_NOT_FOUND = 0xE2;
public static final int RETRIEVE_STATUS_ERROR_PERMANENT_CONTENT_UNSUPPORTED = 0xE3;
public static final int RETRIEVE_STATUS_ERROR_END = 0xFF;
/**
* X-Mms-Sender-Visibility field types.
*/
public static final int SENDER_VISIBILITY_HIDE = 0x80;
public static final int SENDER_VISIBILITY_SHOW = 0x81;
/**
* X-Mms-Read-Status field types.
*/
public static final int READ_STATUS_READ = 0x80;
public static final int READ_STATUS__DELETED_WITHOUT_BEING_READ = 0x81;
/**
* X-Mms-Cancel-Status field types.
*/
public static final int CANCEL_STATUS_REQUEST_SUCCESSFULLY_RECEIVED = 0x80;
public static final int CANCEL_STATUS_REQUEST_CORRUPTED = 0x81;
/**
* X-Mms-Reply-Charging field types.
*/
public static final int REPLY_CHARGING_REQUESTED = 0x80;
public static final int REPLY_CHARGING_REQUESTED_TEXT_ONLY = 0x81;
public static final int REPLY_CHARGING_ACCEPTED = 0x82;
public static final int REPLY_CHARGING_ACCEPTED_TEXT_ONLY = 0x83;
/**
* X-Mms-MM-State field types.
*/
public static final int MM_STATE_DRAFT = 0x80;
public static final int MM_STATE_SENT = 0x81;
public static final int MM_STATE_NEW = 0x82;
public static final int MM_STATE_RETRIEVED = 0x83;
public static final int MM_STATE_FORWARDED = 0x84;
/**
* X-Mms-Recommended-Retrieval-Mode field types.
*/
public static final int RECOMMENDED_RETRIEVAL_MODE_MANUAL = 0x80;
/**
* X-Mms-Content-Class field types.
*/
public static final int CONTENT_CLASS_TEXT = 0x80;
public static final int CONTENT_CLASS_IMAGE_BASIC = 0x81;
public static final int CONTENT_CLASS_IMAGE_RICH = 0x82;
public static final int CONTENT_CLASS_VIDEO_BASIC = 0x83;
public static final int CONTENT_CLASS_VIDEO_RICH = 0x84;
public static final int CONTENT_CLASS_MEGAPIXEL = 0x85;
public static final int CONTENT_CLASS_CONTENT_BASIC = 0x86;
public static final int CONTENT_CLASS_CONTENT_RICH = 0x87;
/**
* X-Mms-Store-Status field types.
*/
public static final int STORE_STATUS_SUCCESS = 0x80;
public static final int STORE_STATUS_ERROR_TRANSIENT_FAILURE = 0xC0;
public static final int STORE_STATUS_ERROR_TRANSIENT_NETWORK_PROBLEM = 0xC1;
public static final int STORE_STATUS_ERROR_PERMANENT_FAILURE = 0xE0;
public static final int STORE_STATUS_ERROR_PERMANENT_SERVICE_DENIED = 0xE1;
public static final int STORE_STATUS_ERROR_PERMANENT_MESSAGE_FORMAT_CORRUPT = 0xE2;
public static final int STORE_STATUS_ERROR_PERMANENT_MESSAGE_NOT_FOUND = 0xE3;
public static final int STORE_STATUS_ERROR_PERMANENT_MMBOX_FULL = 0xE4;
public static final int STORE_STATUS_ERROR_END = 0xFF;
/**
* The map contains the value of all headers.
*/
private HashMap<Integer, Object> mHeaderMap = null;
private long messageBox;
/**
* Constructor of PduHeaders.
*/
public PduHeaders() {
mHeaderMap = new HashMap<Integer, Object>();
}
/**
* Get octet value by header field.
*
* @param field the field
* @return the octet value of the pdu header
* with specified header field. Return 0 if
* the value is not set.
*/
public int getOctet(int field) {
Integer octet = (Integer) mHeaderMap.get(field);
if (null == octet) {
return 0;
}
return octet;
}
public void setMessageBox(long messageBox) {
this.messageBox = messageBox;
}
public long getMessageBox() {
return this.messageBox;
}
/**
* Set octet value to pdu header by header field.
*
* @param value the value
* @param field the field
* @throws InvalidHeaderValueException if the value is invalid.
*/
public void setOctet(int value, int field)
throws InvalidHeaderValueException{
/**
* Check whether this field can be set for specific
* header and check validity of the field.
*/
switch (field) {
case REPORT_ALLOWED:
case ADAPTATION_ALLOWED:
case DELIVERY_REPORT:
case DRM_CONTENT:
case DISTRIBUTION_INDICATOR:
case QUOTAS:
case READ_REPORT:
case STORE:
case STORED:
case TOTALS:
case SENDER_VISIBILITY:
if ((VALUE_YES != value) && (VALUE_NO != value)) {
// Invalid value.
throw new InvalidHeaderValueException("Invalid Octet value!");
}
break;
case READ_STATUS:
if ((READ_STATUS_READ != value) &&
(READ_STATUS__DELETED_WITHOUT_BEING_READ != value)) {
// Invalid value.
throw new InvalidHeaderValueException("Invalid Octet value!");
}
break;
case CANCEL_STATUS:
if ((CANCEL_STATUS_REQUEST_SUCCESSFULLY_RECEIVED != value) &&
(CANCEL_STATUS_REQUEST_CORRUPTED != value)) {
// Invalid value.
throw new InvalidHeaderValueException("Invalid Octet value!");
}
break;
case PRIORITY:
if ((value < PRIORITY_LOW) || (value > PRIORITY_HIGH)) {
// Invalid value.
throw new InvalidHeaderValueException("Invalid Octet value!");
}
break;
case STATUS:
// if ((value < STATUS_EXPIRED) || (value > STATUS_UNREACHABLE)) {
// // Invalid value.
// throw new InvalidHeaderValueException("Invalid Octet value!");
// }
break;
case REPLY_CHARGING:
if ((value < REPLY_CHARGING_REQUESTED)
|| (value > REPLY_CHARGING_ACCEPTED_TEXT_ONLY)) {
// Invalid value.
throw new InvalidHeaderValueException("Invalid Octet value!");
}
break;
case MM_STATE:
if ((value < MM_STATE_DRAFT) || (value > MM_STATE_FORWARDED)) {
// Invalid value.
throw new InvalidHeaderValueException("Invalid Octet value!");
}
break;
case RECOMMENDED_RETRIEVAL_MODE:
if (RECOMMENDED_RETRIEVAL_MODE_MANUAL != value) {
// Invalid value.
throw new InvalidHeaderValueException("Invalid Octet value!");
}
break;
case CONTENT_CLASS:
if ((value < CONTENT_CLASS_TEXT)
|| (value > CONTENT_CLASS_CONTENT_RICH)) {
// Invalid value.
throw new InvalidHeaderValueException("Invalid Octet value!");
}
break;
case RETRIEVE_STATUS:
// According to oma-ts-mms-enc-v1_3, section 7.3.50, we modify the invalid value.
if ((value > RETRIEVE_STATUS_ERROR_TRANSIENT_NETWORK_PROBLEM) &&
(value < RETRIEVE_STATUS_ERROR_PERMANENT_FAILURE)) {
value = RETRIEVE_STATUS_ERROR_TRANSIENT_FAILURE;
} else if ((value > RETRIEVE_STATUS_ERROR_PERMANENT_CONTENT_UNSUPPORTED) &&
(value <= RETRIEVE_STATUS_ERROR_END)) {
value = RETRIEVE_STATUS_ERROR_PERMANENT_FAILURE;
} else if ((value < RETRIEVE_STATUS_OK) ||
((value > RETRIEVE_STATUS_OK) &&
(value < RETRIEVE_STATUS_ERROR_TRANSIENT_FAILURE)) ||
(value > RETRIEVE_STATUS_ERROR_END)) {
value = RETRIEVE_STATUS_ERROR_PERMANENT_FAILURE;
}
break;
case STORE_STATUS:
// According to oma-ts-mms-enc-v1_3, section 7.3.58, we modify the invalid value.
if ((value > STORE_STATUS_ERROR_TRANSIENT_NETWORK_PROBLEM) &&
(value < STORE_STATUS_ERROR_PERMANENT_FAILURE)) {
value = STORE_STATUS_ERROR_TRANSIENT_FAILURE;
} else if ((value > STORE_STATUS_ERROR_PERMANENT_MMBOX_FULL) &&
(value <= STORE_STATUS_ERROR_END)) {
value = STORE_STATUS_ERROR_PERMANENT_FAILURE;
} else if ((value < STORE_STATUS_SUCCESS) ||
((value > STORE_STATUS_SUCCESS) &&
(value < STORE_STATUS_ERROR_TRANSIENT_FAILURE)) ||
(value > STORE_STATUS_ERROR_END)) {
value = STORE_STATUS_ERROR_PERMANENT_FAILURE;
}
break;
case RESPONSE_STATUS:
// According to oma-ts-mms-enc-v1_3, section 7.3.48, we modify the invalid value.
if ((value > RESPONSE_STATUS_ERROR_TRANSIENT_PARTIAL_SUCCESS) &&
(value < RESPONSE_STATUS_ERROR_PERMANENT_FAILURE)) {
value = RESPONSE_STATUS_ERROR_TRANSIENT_FAILURE;
} else if (((value > RESPONSE_STATUS_ERROR_PERMANENT_LACK_OF_PREPAID) &&
(value <= RESPONSE_STATUS_ERROR_PERMANENT_END)) ||
(value < RESPONSE_STATUS_OK) ||
((value > RESPONSE_STATUS_ERROR_UNSUPPORTED_MESSAGE) &&
(value < RESPONSE_STATUS_ERROR_TRANSIENT_FAILURE)) ||
(value > RESPONSE_STATUS_ERROR_PERMANENT_END)) {
value = RESPONSE_STATUS_ERROR_PERMANENT_FAILURE;
}
break;
case MMS_VERSION:
if ((value < MMS_VERSION_1_0)|| (value > MMS_VERSION_1_3)) {
value = CURRENT_MMS_VERSION; // Current version is the default value.
}
break;
case MESSAGE_TYPE:
if ((value < MESSAGE_TYPE_SEND_REQ) || (value > MESSAGE_TYPE_CANCEL_CONF)) {
// Invalid value.
throw new InvalidHeaderValueException("Invalid Octet value!");
}
break;
default:
// This header value should not be Octect.
throw new RuntimeException("Invalid header field!");
}
mHeaderMap.put(field, value);
}
/**
* Get TextString value by header field.
*
* @param field the field
* @return the TextString value of the pdu header
* with specified header field
*/
public byte[] getTextString(int field) {
return (byte[]) mHeaderMap.get(field);
}
/**
* Set TextString value to pdu header by header field.
*
* @param value the value
* @param field the field
* @return the TextString value of the pdu header
* with specified header field
* @throws NullPointerException if the value is null.
*/
public void setTextString(byte[] value, int field) {
/**
* Check whether this field can be set for specific
* header and check validity of the field.
*/
if (null == value) {
throw new NullPointerException();
}
switch (field) {
case TRANSACTION_ID:
case REPLY_CHARGING_ID:
case AUX_APPLIC_ID:
case APPLIC_ID:
case REPLY_APPLIC_ID:
case MESSAGE_ID:
case REPLACE_ID:
case CANCEL_ID:
case CONTENT_LOCATION:
case MESSAGE_CLASS:
case CONTENT_TYPE:
break;
default:
// This header value should not be Text-String.
throw new RuntimeException("Invalid header field!");
}
mHeaderMap.put(field, value);
}
/**
* Get EncodedStringValue value by header field.
*
* @param field the field
* @return the EncodedStringValue value of the pdu header
* with specified header field
*/
public EncodedStringValue getEncodedStringValue(int field) {
return (EncodedStringValue) mHeaderMap.get(field);
}
/**
* Get TO, CC or BCC header value.
*
* @param field the field
* @return the EncodeStringValue array of the pdu header
* with specified header field
*/
public EncodedStringValue[] getEncodedStringValues(int field) {
ArrayList<EncodedStringValue> list =
(ArrayList<EncodedStringValue>) mHeaderMap.get(field);
if (null == list) {
return null;
}
EncodedStringValue[] values = new EncodedStringValue[list.size()];
return list.toArray(values);
}
/**
* Set EncodedStringValue value to pdu header by header field.
*
* @param value the value
* @param field the field
* @return the EncodedStringValue value of the pdu header
* with specified header field
* @throws NullPointerException if the value is null.
*/
public void setEncodedStringValue(EncodedStringValue value, int field) {
/**
* Check whether this field can be set for specific
* header and check validity of the field.
*/
if (null == value) {
throw new NullPointerException();
}
switch (field) {
case SUBJECT:
case RECOMMENDED_RETRIEVAL_MODE_TEXT:
case RETRIEVE_TEXT:
case STATUS_TEXT:
case STORE_STATUS_TEXT:
case RESPONSE_TEXT:
case FROM:
case PREVIOUSLY_SENT_BY:
case MM_FLAGS:
break;
default:
// This header value should not be Encoded-String-Value.
throw new RuntimeException("Invalid header field!");
}
mHeaderMap.put(field, value);
}
/**
* Set TO, CC or BCC header value.
*
* @param value the value
* @param field the field
* @return the EncodedStringValue value array of the pdu header
* with specified header field
* @throws NullPointerException if the value is null.
*/
protected void setEncodedStringValues(EncodedStringValue[] value, int field) {
/**
* Check whether this field can be set for specific
* header and check validity of the field.
*/
if (null == value) {
throw new NullPointerException();
}
switch (field) {
case BCC:
case CC:
case TO:
break;
default:
// This header value should not be Encoded-String-Value.
throw new RuntimeException("Invalid header field!");
}
ArrayList<EncodedStringValue> list = new ArrayList<EncodedStringValue>();
for (int i = 0; i < value.length; i++) {
list.add(value[i]);
}
mHeaderMap.put(field, list);
}
/**
* Append one EncodedStringValue to another.
*
* @param value the EncodedStringValue to append
* @param field the field
* @throws NullPointerException if the value is null.
*/
public void appendEncodedStringValue(EncodedStringValue value,
int field) {
if (null == value) {
throw new NullPointerException();
}
switch (field) {
case BCC:
case CC:
case TO:
break;
default:
throw new RuntimeException("Invalid header field!");
}
ArrayList<EncodedStringValue> list =
(ArrayList<EncodedStringValue>) mHeaderMap.get(field);
if (null == list) {
list = new ArrayList<EncodedStringValue>();
}
list.add(value);
mHeaderMap.put(field, list);
}
/**
* Get LongInteger value by header field.
*
* @param field the field
* @return the LongInteger value of the pdu header
* with specified header field. if return -1, the
* field is not existed in pdu header.
*/
public long getLongInteger(int field) {
Long longInteger = (Long) mHeaderMap.get(field);
if (null == longInteger) {
return -1;
}
return longInteger.longValue();
}
/**
* Set LongInteger value to pdu header by header field.
*
* @param value the value
* @param field the field
*/
public void setLongInteger(long value, int field) {
/**
* Check whether this field can be set for specific
* header and check validity of the field.
*/
switch (field) {
case DATE:
case REPLY_CHARGING_SIZE:
case MESSAGE_SIZE:
case MESSAGE_COUNT:
case START:
case LIMIT:
case DELIVERY_TIME:
case EXPIRY:
case REPLY_CHARGING_DEADLINE:
case PREVIOUSLY_SENT_DATE:
break;
default:
// This header value should not be LongInteger.
throw new RuntimeException("Invalid header field!");
}
mHeaderMap.put(field, value);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,402 +0,0 @@
/*
* Copyright (C) 2007-2008 Esmertec AG.
* Copyright (C) 2007-2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ws.com.google.android.mms.pdu;
import android.net.Uri;
import java.util.HashMap;
import java.util.Map;
/**
* The pdu part.
*/
public class PduPart {
/**
* Well-Known Parameters.
*/
public static final int P_Q = 0x80;
public static final int P_CHARSET = 0x81;
public static final int P_LEVEL = 0x82;
public static final int P_TYPE = 0x83;
public static final int P_DEP_NAME = 0x85;
public static final int P_DEP_FILENAME = 0x86;
public static final int P_DIFFERENCES = 0x87;
public static final int P_PADDING = 0x88;
// This value of "TYPE" s used with Content-Type: multipart/related
public static final int P_CT_MR_TYPE = 0x89;
public static final int P_DEP_START = 0x8A;
public static final int P_DEP_START_INFO = 0x8B;
public static final int P_DEP_COMMENT = 0x8C;
public static final int P_DEP_DOMAIN = 0x8D;
public static final int P_MAX_AGE = 0x8E;
public static final int P_DEP_PATH = 0x8F;
public static final int P_SECURE = 0x90;
public static final int P_SEC = 0x91;
public static final int P_MAC = 0x92;
public static final int P_CREATION_DATE = 0x93;
public static final int P_MODIFICATION_DATE = 0x94;
public static final int P_READ_DATE = 0x95;
public static final int P_SIZE = 0x96;
public static final int P_NAME = 0x97;
public static final int P_FILENAME = 0x98;
public static final int P_START = 0x99;
public static final int P_START_INFO = 0x9A;
public static final int P_COMMENT = 0x9B;
public static final int P_DOMAIN = 0x9C;
public static final int P_PATH = 0x9D;
/**
* Header field names.
*/
public static final int P_CONTENT_TYPE = 0x91;
public static final int P_CONTENT_LOCATION = 0x8E;
public static final int P_CONTENT_ID = 0xC0;
public static final int P_DEP_CONTENT_DISPOSITION = 0xAE;
public static final int P_CONTENT_DISPOSITION = 0xC5;
// The next header is unassigned header, use reserved header(0x48) value.
public static final int P_CONTENT_TRANSFER_ENCODING = 0xC8;
/**
* Content=Transfer-Encoding string.
*/
public static final String CONTENT_TRANSFER_ENCODING =
"Content-Transfer-Encoding";
/**
* Value of Content-Transfer-Encoding.
*/
public static final String P_BINARY = "binary";
public static final String P_7BIT = "7bit";
public static final String P_8BIT = "8bit";
public static final String P_BASE64 = "base64";
public static final String P_QUOTED_PRINTABLE = "quoted-printable";
/**
* Value of disposition can be set to PduPart when the value is octet in
* the PDU.
* "from-data" instead of Form-data<Octet 128>.
* "attachment" instead of Attachment<Octet 129>.
* "inline" instead of Inline<Octet 130>.
*/
static final byte[] DISPOSITION_FROM_DATA = "from-data".getBytes();
static final byte[] DISPOSITION_ATTACHMENT = "attachment".getBytes();
static final byte[] DISPOSITION_INLINE = "inline".getBytes();
/**
* Content-Disposition value.
*/
public static final int P_DISPOSITION_FROM_DATA = 0x80;
public static final int P_DISPOSITION_ATTACHMENT = 0x81;
public static final int P_DISPOSITION_INLINE = 0x82;
/**
* Header of part.
*/
private Map<Integer, Object> mPartHeader = null;
/**
* Data uri.
*/
private Uri mUri = null;
/**
* Part data.
*/
private byte[] mPartData = null;
private static final String TAG = "PduPart";
/**
* Empty Constructor.
*/
public PduPart() {
mPartHeader = new HashMap<Integer, Object>();
}
/**
* Set part data. The data are stored as byte array.
*
* @param data the data
*/
public void setData(byte[] data) {
if(data == null) {
return;
}
mPartData = new byte[data.length];
System.arraycopy(data, 0, mPartData, 0, data.length);
}
/**
* @return A copy of the part data or null if the data wasn't set or
* the data is stored as Uri.
* @see #getDataUri
*/
public byte[] getData() {
if(mPartData == null) {
return null;
}
byte[] byteArray = new byte[mPartData.length];
System.arraycopy(mPartData, 0, byteArray, 0, mPartData.length);
return byteArray;
}
/**
* Set data uri. The data are stored as Uri.
*
* @param uri the uri
*/
public void setDataUri(Uri uri) {
mUri = uri;
}
/**
* @return The Uri of the part data or null if the data wasn't set or
* the data is stored as byte array.
* @see #getData
*/
public Uri getDataUri() {
return mUri;
}
/**
* Set Content-id value
*
* @param contentId the content-id value
* @throws NullPointerException if the value is null.
*/
public void setContentId(byte[] contentId) {
if((contentId == null) || (contentId.length == 0)) {
throw new IllegalArgumentException(
"Content-Id may not be null or empty.");
}
if ((contentId.length > 1)
&& ((char) contentId[0] == '<')
&& ((char) contentId[contentId.length - 1] == '>')) {
mPartHeader.put(P_CONTENT_ID, contentId);
return;
}
// Insert beginning '<' and trailing '>' for Content-Id.
byte[] buffer = new byte[contentId.length + 2];
buffer[0] = (byte) (0xff & '<');
buffer[buffer.length - 1] = (byte) (0xff & '>');
System.arraycopy(contentId, 0, buffer, 1, contentId.length);
mPartHeader.put(P_CONTENT_ID, buffer);
}
/**
* Get Content-id value.
*
* @return the value
*/
public byte[] getContentId() {
return (byte[]) mPartHeader.get(P_CONTENT_ID);
}
/**
* Set Char-set value.
*
* @param charset the value
*/
public void setCharset(int charset) {
mPartHeader.put(P_CHARSET, charset);
}
/**
* Get Char-set value
*
* @return the charset value. Return 0 if charset was not set.
*/
public int getCharset() {
Integer charset = (Integer) mPartHeader.get(P_CHARSET);
if(charset == null) {
return 0;
} else {
return charset.intValue();
}
}
/**
* Set Content-Location value.
*
* @param contentLocation the value
* @throws NullPointerException if the value is null.
*/
public void setContentLocation(byte[] contentLocation) {
if(contentLocation == null) {
throw new NullPointerException("null content-location");
}
mPartHeader.put(P_CONTENT_LOCATION, contentLocation);
}
/**
* Get Content-Location value.
*
* @return the value
* return PduPart.disposition[0] instead of <Octet 128> (Form-data).
* return PduPart.disposition[1] instead of <Octet 129> (Attachment).
* return PduPart.disposition[2] instead of <Octet 130> (Inline).
*/
public byte[] getContentLocation() {
return (byte[]) mPartHeader.get(P_CONTENT_LOCATION);
}
/**
* Set Content-Disposition value.
* Use PduPart.disposition[0] instead of <Octet 128> (Form-data).
* Use PduPart.disposition[1] instead of <Octet 129> (Attachment).
* Use PduPart.disposition[2] instead of <Octet 130> (Inline).
*
* @param contentDisposition the value
* @throws NullPointerException if the value is null.
*/
public void setContentDisposition(byte[] contentDisposition) {
if(contentDisposition == null) {
throw new NullPointerException("null content-disposition");
}
mPartHeader.put(P_CONTENT_DISPOSITION, contentDisposition);
}
/**
* Get Content-Disposition value.
*
* @return the value
*/
public byte[] getContentDisposition() {
return (byte[]) mPartHeader.get(P_CONTENT_DISPOSITION);
}
/**
* Set Content-Type value.
*
* @param contentType the value
* @throws NullPointerException if the value is null.
*/
public void setContentType(byte[] contentType) {
if(contentType == null) {
throw new NullPointerException("null content-type");
}
mPartHeader.put(P_CONTENT_TYPE, contentType);
}
/**
* Get Content-Type value of part.
*
* @return the value
*/
public byte[] getContentType() {
return (byte[]) mPartHeader.get(P_CONTENT_TYPE);
}
/**
* Set Content-Transfer-Encoding value
*
* @param contentTransferEncoding the value
* @throws NullPointerException if the value is null.
*/
public void setContentTransferEncoding(byte[] contentTransferEncoding) {
if(contentTransferEncoding == null) {
throw new NullPointerException("null content-transfer-encoding");
}
mPartHeader.put(P_CONTENT_TRANSFER_ENCODING, contentTransferEncoding);
}
/**
* Get Content-Transfer-Encoding value.
*
* @return the value
*/
public byte[] getContentTransferEncoding() {
return (byte[]) mPartHeader.get(P_CONTENT_TRANSFER_ENCODING);
}
/**
* Set Content-type parameter: name.
*
* @param name the name value
* @throws NullPointerException if the value is null.
*/
public void setName(byte[] name) {
if(null == name) {
throw new NullPointerException("null content-id");
}
mPartHeader.put(P_NAME, name);
}
/**
* Get content-type parameter: name.
*
* @return the name
*/
public byte[] getName() {
return (byte[]) mPartHeader.get(P_NAME);
}
/**
* Get Content-disposition parameter: filename
*
* @param fileName the filename value
* @throws NullPointerException if the value is null.
*/
public void setFilename(byte[] fileName) {
if(null == fileName) {
throw new NullPointerException("null content-id");
}
mPartHeader.put(P_FILENAME, fileName);
}
/**
* Set Content-disposition parameter: filename
*
* @return the filename
*/
public byte[] getFilename() {
return (byte[]) mPartHeader.get(P_FILENAME);
}
public String generateLocation() {
// Assumption: At least one of the content-location / name / filename
// or content-id should be set. This is guaranteed by the PduParser
// for incoming messages and by MM composer for outgoing messages.
byte[] location = (byte[]) mPartHeader.get(P_NAME);
if(null == location) {
location = (byte[]) mPartHeader.get(P_FILENAME);
if (null == location) {
location = (byte[]) mPartHeader.get(P_CONTENT_LOCATION);
}
}
if (null == location) {
byte[] contentId = (byte[]) mPartHeader.get(P_CONTENT_ID);
return "cid:" + new String(contentId);
} else {
return new String(location);
}
}
}

View File

@ -1,68 +0,0 @@
/*
* Copyright (C) 2007 Esmertec AG.
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ws.com.google.android.mms.pdu;
import java.io.ByteArrayOutputStream;
public class QuotedPrintable {
private static byte ESCAPE_CHAR = '=';
/**
* Decodes an array quoted-printable characters into an array of original bytes.
* Escaped characters are converted back to their original representation.
*
* <p>
* This function implements a subset of
* quoted-printable encoding specification (rule #1 and rule #2)
* as defined in RFC 1521.
* </p>
*
* @param bytes array of quoted-printable characters
* @return array of original bytes,
* null if quoted-printable decoding is unsuccessful.
*/
public static final byte[] decodeQuotedPrintable(byte[] bytes) {
if (bytes == null) {
return null;
}
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
for (int i = 0; i < bytes.length; i++) {
int b = bytes[i];
if (b == ESCAPE_CHAR) {
try {
if('\r' == (char)bytes[i + 1] &&
'\n' == (char)bytes[i + 2]) {
i += 2;
continue;
}
int u = Character.digit((char) bytes[++i], 16);
int l = Character.digit((char) bytes[++i], 16);
if (u == -1 || l == -1) {
return null;
}
buffer.write((char) ((u << 4) + l));
} catch (ArrayIndexOutOfBoundsException e) {
return null;
}
} else {
buffer.write(b);
}
}
return buffer.toByteArray();
}
}

View File

@ -1,153 +0,0 @@
/*
* Copyright (C) 2007 Esmertec AG.
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ws.com.google.android.mms.pdu;
import ws.com.google.android.mms.InvalidHeaderValueException;
public class ReadOrigInd extends GenericPdu {
/**
* Empty constructor.
* Since the Pdu corresponding to this class is constructed
* by the Proxy-Relay server, this class is only instantiated
* by the Pdu Parser.
*
* @throws InvalidHeaderValueException if error occurs.
*/
public ReadOrigInd() throws InvalidHeaderValueException {
super();
setMessageType(PduHeaders.MESSAGE_TYPE_READ_ORIG_IND);
}
/**
* Constructor with given headers.
*
* @param headers Headers for this PDU.
*/
ReadOrigInd(PduHeaders headers) {
super(headers);
}
/**
* Get Date value.
*
* @return the value
*/
public long getDate() {
return mPduHeaders.getLongInteger(PduHeaders.DATE);
}
/**
* Set Date value.
*
* @param value the value
*/
public void setDate(long value) {
mPduHeaders.setLongInteger(value, PduHeaders.DATE);
}
/**
* Get From value.
* From-value = Value-length
* (Address-present-token Encoded-string-value | Insert-address-token)
*
* @return the value
*/
public EncodedStringValue getFrom() {
return mPduHeaders.getEncodedStringValue(PduHeaders.FROM);
}
/**
* Set From value.
*
* @param value the value
* @throws NullPointerException if the value is null.
*/
public void setFrom(EncodedStringValue value) {
mPduHeaders.setEncodedStringValue(value, PduHeaders.FROM);
}
/**
* Get Message-ID value.
*
* @return the value
*/
public byte[] getMessageId() {
return mPduHeaders.getTextString(PduHeaders.MESSAGE_ID);
}
/**
* Set Message-ID value.
*
* @param value the value
* @throws NullPointerException if the value is null.
*/
public void setMessageId(byte[] value) {
mPduHeaders.setTextString(value, PduHeaders.MESSAGE_ID);
}
/**
* Get X-MMS-Read-status value.
*
* @return the value
*/
public int getReadStatus() {
return mPduHeaders.getOctet(PduHeaders.READ_STATUS);
}
/**
* Set X-MMS-Read-status value.
*
* @param value the value
* @throws InvalidHeaderValueException if the value is invalid.
*/
public void setReadStatus(int value) throws InvalidHeaderValueException {
mPduHeaders.setOctet(value, PduHeaders.READ_STATUS);
}
/**
* Get To value.
*
* @return the value
*/
public EncodedStringValue[] getTo() {
return mPduHeaders.getEncodedStringValues(PduHeaders.TO);
}
/**
* Set To value.
*
* @param value the value
* @throws NullPointerException if the value is null.
*/
public void setTo(EncodedStringValue[] value) {
mPduHeaders.setEncodedStringValues(value, PduHeaders.TO);
}
/*
* Optional, not supported header fields:
*
* public byte[] getApplicId() {return null;}
* public void setApplicId(byte[] value) {}
*
* public byte[] getAuxApplicId() {return null;}
* public void getAuxApplicId(byte[] value) {}
*
* public byte[] getReplyApplicId() {return 0x00;}
* public void setReplyApplicId(byte[] value) {}
*/
}

View File

@ -1,144 +0,0 @@
/*
* Copyright (C) 2007 Esmertec AG.
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ws.com.google.android.mms.pdu;
import ws.com.google.android.mms.InvalidHeaderValueException;
public class ReadRecInd extends GenericPdu {
/**
* Constructor, used when composing a M-ReadRec.ind pdu.
*
* @param from the from value
* @param messageId the message ID value
* @param mmsVersion current viersion of mms
* @param readStatus the read status value
* @param to the to value
* @throws InvalidHeaderValueException if parameters are invalid.
* NullPointerException if messageId or to is null.
*/
public ReadRecInd(EncodedStringValue from,
byte[] messageId,
int mmsVersion,
int readStatus,
EncodedStringValue[] to) throws InvalidHeaderValueException {
super();
setMessageType(PduHeaders.MESSAGE_TYPE_READ_REC_IND);
setFrom(from);
setMessageId(messageId);
setMmsVersion(mmsVersion);
setTo(to);
setReadStatus(readStatus);
}
/**
* Constructor with given headers.
*
* @param headers Headers for this PDU.
*/
ReadRecInd(PduHeaders headers) {
super(headers);
}
/**
* Get Date value.
*
* @return the value
*/
public long getDate() {
return mPduHeaders.getLongInteger(PduHeaders.DATE);
}
/**
* Set Date value.
*
* @param value the value
*/
public void setDate(long value) {
mPduHeaders.setLongInteger(value, PduHeaders.DATE);
}
/**
* Get Message-ID value.
*
* @return the value
*/
public byte[] getMessageId() {
return mPduHeaders.getTextString(PduHeaders.MESSAGE_ID);
}
/**
* Set Message-ID value.
*
* @param value the value
* @throws NullPointerException if the value is null.
*/
public void setMessageId(byte[] value) {
mPduHeaders.setTextString(value, PduHeaders.MESSAGE_ID);
}
/**
* Get To value.
*
* @return the value
*/
public EncodedStringValue[] getTo() {
return mPduHeaders.getEncodedStringValues(PduHeaders.TO);
}
/**
* Set To value.
*
* @param value the value
* @throws NullPointerException if the value is null.
*/
public void setTo(EncodedStringValue[] value) {
mPduHeaders.setEncodedStringValues(value, PduHeaders.TO);
}
/**
* Get X-MMS-Read-status value.
*
* @return the value
*/
public int getReadStatus() {
return mPduHeaders.getOctet(PduHeaders.READ_STATUS);
}
/**
* Set X-MMS-Read-status value.
*
* @param value the value
* @throws InvalidHeaderValueException if the value is invalid.
*/
public void setReadStatus(int value) throws InvalidHeaderValueException {
mPduHeaders.setOctet(value, PduHeaders.READ_STATUS);
}
/*
* Optional, not supported header fields:
*
* public byte[] getApplicId() {return null;}
* public void setApplicId(byte[] value) {}
*
* public byte[] getAuxApplicId() {return null;}
* public void getAuxApplicId(byte[] value) {}
*
* public byte[] getReplyApplicId() {return 0x00;}
* public void setReplyApplicId(byte[] value) {}
*/
}

View File

@ -1,300 +0,0 @@
/*
* Copyright (C) 2007 Esmertec AG.
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ws.com.google.android.mms.pdu;
import ws.com.google.android.mms.InvalidHeaderValueException;
/**
* M-Retrive.conf Pdu.
*/
public class RetrieveConf extends MultimediaMessagePdu {
/**
* Empty constructor.
* Since the Pdu corresponding to this class is constructed
* by the Proxy-Relay server, this class is only instantiated
* by the Pdu Parser.
*
* @throws InvalidHeaderValueException if error occurs.
*/
public RetrieveConf() throws InvalidHeaderValueException {
super();
setMessageType(PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF);
}
/**
* Constructor with given headers.
*
* @param headers Headers for this PDU.
*/
RetrieveConf(PduHeaders headers) {
super(headers);
}
/**
* Constructor with given headers and body
*
* @param headers Headers for this PDU.
* @param body Body of this PDu.
*/
public RetrieveConf(PduHeaders headers, PduBody body) {
super(headers, body);
}
/**
* Get CC value.
*
* @return the value
*/
public EncodedStringValue[] getCc() {
return mPduHeaders.getEncodedStringValues(PduHeaders.CC);
}
/**
* Add a "CC" value.
*
* @param value the value
* @throws NullPointerException if the value is null.
*/
public void addCc(EncodedStringValue value) {
mPduHeaders.appendEncodedStringValue(value, PduHeaders.CC);
}
/**
* Get Content-type value.
*
* @return the value
*/
public byte[] getContentType() {
return mPduHeaders.getTextString(PduHeaders.CONTENT_TYPE);
}
/**
* Set Content-type value.
*
* @param value the value
* @throws NullPointerException if the value is null.
*/
public void setContentType(byte[] value) {
mPduHeaders.setTextString(value, PduHeaders.CONTENT_TYPE);
}
/**
* Get X-Mms-Delivery-Report value.
*
* @return the value
*/
public int getDeliveryReport() {
return mPduHeaders.getOctet(PduHeaders.DELIVERY_REPORT);
}
/**
* Set X-Mms-Delivery-Report value.
*
* @param value the value
* @throws InvalidHeaderValueException if the value is invalid.
*/
public void setDeliveryReport(int value) throws InvalidHeaderValueException {
mPduHeaders.setOctet(value, PduHeaders.DELIVERY_REPORT);
}
/**
* Get From value.
* From-value = Value-length
* (Address-present-token Encoded-string-value | Insert-address-token)
*
* @return the value
*/
public EncodedStringValue getFrom() {
return mPduHeaders.getEncodedStringValue(PduHeaders.FROM);
}
/**
* Set From value.
*
* @param value the value
* @throws NullPointerException if the value is null.
*/
public void setFrom(EncodedStringValue value) {
mPduHeaders.setEncodedStringValue(value, PduHeaders.FROM);
}
/**
* Get X-Mms-Message-Class value.
* Message-class-value = Class-identifier | Token-text
* Class-identifier = Personal | Advertisement | Informational | Auto
*
* @return the value
*/
public byte[] getMessageClass() {
return mPduHeaders.getTextString(PduHeaders.MESSAGE_CLASS);
}
/**
* Set X-Mms-Message-Class value.
*
* @param value the value
* @throws NullPointerException if the value is null.
*/
public void setMessageClass(byte[] value) {
mPduHeaders.setTextString(value, PduHeaders.MESSAGE_CLASS);
}
/**
* Get Message-ID value.
*
* @return the value
*/
public byte[] getMessageId() {
return mPduHeaders.getTextString(PduHeaders.MESSAGE_ID);
}
/**
* Set Message-ID value.
*
* @param value the value
* @throws NullPointerException if the value is null.
*/
public void setMessageId(byte[] value) {
mPduHeaders.setTextString(value, PduHeaders.MESSAGE_ID);
}
/**
* Get X-Mms-Read-Report value.
*
* @return the value
*/
public int getReadReport() {
return mPduHeaders.getOctet(PduHeaders.READ_REPORT);
}
/**
* Set X-Mms-Read-Report value.
*
* @param value the value
* @throws InvalidHeaderValueException if the value is invalid.
*/
public void setReadReport(int value) throws InvalidHeaderValueException {
mPduHeaders.setOctet(value, PduHeaders.READ_REPORT);
}
/**
* Get X-Mms-Retrieve-Status value.
*
* @return the value
*/
public int getRetrieveStatus() {
return mPduHeaders.getOctet(PduHeaders.RETRIEVE_STATUS);
}
/**
* Set X-Mms-Retrieve-Status value.
*
* @param value the value
* @throws InvalidHeaderValueException if the value is invalid.
*/
public void setRetrieveStatus(int value) throws InvalidHeaderValueException {
mPduHeaders.setOctet(value, PduHeaders.RETRIEVE_STATUS);
}
/**
* Get X-Mms-Retrieve-Text value.
*
* @return the value
*/
public EncodedStringValue getRetrieveText() {
return mPduHeaders.getEncodedStringValue(PduHeaders.RETRIEVE_TEXT);
}
/**
* Set X-Mms-Retrieve-Text value.
*
* @param value the value
* @throws NullPointerException if the value is null.
*/
public void setRetrieveText(EncodedStringValue value) {
mPduHeaders.setEncodedStringValue(value, PduHeaders.RETRIEVE_TEXT);
}
/**
* Get X-Mms-Transaction-Id.
*
* @return the value
*/
public byte[] getTransactionId() {
return mPduHeaders.getTextString(PduHeaders.TRANSACTION_ID);
}
/**
* Set X-Mms-Transaction-Id.
*
* @param value the value
* @throws NullPointerException if the value is null.
*/
public void setTransactionId(byte[] value) {
mPduHeaders.setTextString(value, PduHeaders.TRANSACTION_ID);
}
/*
* Optional, not supported header fields:
*
* public byte[] getApplicId() {return null;}
* public void setApplicId(byte[] value) {}
*
* public byte[] getAuxApplicId() {return null;}
* public void getAuxApplicId(byte[] value) {}
*
* public byte getContentClass() {return 0x00;}
* public void setApplicId(byte value) {}
*
* public byte getDrmContent() {return 0x00;}
* public void setDrmContent(byte value) {}
*
* public byte getDistributionIndicator() {return 0x00;}
* public void setDistributionIndicator(byte value) {}
*
* public PreviouslySentByValue getPreviouslySentBy() {return null;}
* public void setPreviouslySentBy(PreviouslySentByValue value) {}
*
* public PreviouslySentDateValue getPreviouslySentDate() {}
* public void setPreviouslySentDate(PreviouslySentDateValue value) {}
*
* public MmFlagsValue getMmFlags() {return null;}
* public void setMmFlags(MmFlagsValue value) {}
*
* public MmStateValue getMmState() {return null;}
* public void getMmState(MmStateValue value) {}
*
* public byte[] getReplaceId() {return 0x00;}
* public void setReplaceId(byte[] value) {}
*
* public byte[] getReplyApplicId() {return 0x00;}
* public void setReplyApplicId(byte[] value) {}
*
* public byte getReplyCharging() {return 0x00;}
* public void setReplyCharging(byte value) {}
*
* public byte getReplyChargingDeadline() {return 0x00;}
* public void setReplyChargingDeadline(byte value) {}
*
* public byte[] getReplyChargingId() {return 0x00;}
* public void setReplyChargingId(byte[] value) {}
*
* public long getReplyChargingSize() {return 0;}
* public void setReplyChargingSize(long value) {}
*/
}

View File

@ -1,117 +0,0 @@
/*
* Copyright (C) 2007 Esmertec AG.
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ws.com.google.android.mms.pdu;
import ws.com.google.android.mms.InvalidHeaderValueException;
public class SendConf extends GenericPdu {
/**
* Empty constructor.
* Since the Pdu corresponding to this class is constructed
* by the Proxy-Relay server, this class is only instantiated
* by the Pdu Parser.
*
* @throws InvalidHeaderValueException if error occurs.
*/
public SendConf() throws InvalidHeaderValueException {
super();
setMessageType(PduHeaders.MESSAGE_TYPE_SEND_CONF);
}
/**
* Constructor with given headers.
*
* @param headers Headers for this PDU.
*/
SendConf(PduHeaders headers) {
super(headers);
}
/**
* Get Message-ID value.
*
* @return the value
*/
public byte[] getMessageId() {
return mPduHeaders.getTextString(PduHeaders.MESSAGE_ID);
}
/**
* Set Message-ID value.
*
* @param value the value
* @throws NullPointerException if the value is null.
*/
public void setMessageId(byte[] value) {
mPduHeaders.setTextString(value, PduHeaders.MESSAGE_ID);
}
/**
* Get X-Mms-Response-Status.
*
* @return the value
*/
public int getResponseStatus() {
return mPduHeaders.getOctet(PduHeaders.RESPONSE_STATUS);
}
/**
* Set X-Mms-Response-Status.
*
* @param value the values
* @throws InvalidHeaderValueException if the value is invalid.
*/
public void setResponseStatus(int value) throws InvalidHeaderValueException {
mPduHeaders.setOctet(value, PduHeaders.RESPONSE_STATUS);
}
/**
* Get X-Mms-Transaction-Id field value.
*
* @return the X-Mms-Report-Allowed value
*/
public byte[] getTransactionId() {
return mPduHeaders.getTextString(PduHeaders.TRANSACTION_ID);
}
/**
* Set X-Mms-Transaction-Id field value.
*
* @param value the value
* @throws NullPointerException if the value is null.
*/
public void setTransactionId(byte[] value) {
mPduHeaders.setTextString(value, PduHeaders.TRANSACTION_ID);
}
/*
* Optional, not supported header fields:
*
* public byte[] getContentLocation() {return null;}
* public void setContentLocation(byte[] value) {}
*
* public EncodedStringValue getResponseText() {return null;}
* public void setResponseText(EncodedStringValue value) {}
*
* public byte getStoreStatus() {return 0x00;}
* public void setStoreStatus(byte value) {}
*
* public byte[] getStoreStatusText() {return null;}
* public void setStoreStatusText(byte[] value) {}
*/
}

View File

@ -1,345 +0,0 @@
/*
* Copyright (C) 2007-2008 Esmertec AG.
* Copyright (C) 2007-2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ws.com.google.android.mms.pdu;
import android.util.Log;
import ws.com.google.android.mms.InvalidHeaderValueException;
public class SendReq extends MultimediaMessagePdu {
private static final String TAG = "SendReq";
public SendReq() {
super();
try {
setMessageType(PduHeaders.MESSAGE_TYPE_SEND_REQ);
setMmsVersion(PduHeaders.CURRENT_MMS_VERSION);
// FIXME: Content-type must be decided according to whether
// SMIL part present.
setContentType("application/vnd.wap.multipart.related".getBytes());
setFrom(new EncodedStringValue(PduHeaders.FROM_INSERT_ADDRESS_TOKEN_STR.getBytes()));
setTransactionId(generateTransactionId());
} catch (InvalidHeaderValueException e) {
// Impossible to reach here since all headers we set above are valid.
Log.e(TAG, "Unexpected InvalidHeaderValueException.", e);
throw new RuntimeException(e);
}
}
private byte[] generateTransactionId() {
String transactionId = "T" + Long.toHexString(System.currentTimeMillis());
return transactionId.getBytes();
}
/**
* Constructor, used when composing a M-Send.req pdu.
*
* @param contentType the content type value
* @param from the from value
* @param mmsVersion current viersion of mms
* @param transactionId the transaction-id value
* @throws InvalidHeaderValueException if parameters are invalid.
* NullPointerException if contentType, form or transactionId is null.
*/
public SendReq(byte[] contentType,
EncodedStringValue from,
int mmsVersion,
byte[] transactionId) throws InvalidHeaderValueException {
super();
setMessageType(PduHeaders.MESSAGE_TYPE_SEND_REQ);
setContentType(contentType);
setFrom(from);
setMmsVersion(mmsVersion);
setTransactionId(transactionId);
}
/**
* Constructor with given headers.
*
* @param headers Headers for this PDU.
*/
SendReq(PduHeaders headers) {
super(headers);
}
/**
* Constructor with given headers and body
*
* @param headers Headers for this PDU.
* @param body Body of this PDu.
*/
public SendReq(PduHeaders headers, PduBody body) {
super(headers, body);
}
/**
* Get Bcc value.
*
* @return the value
*/
public EncodedStringValue[] getBcc() {
return mPduHeaders.getEncodedStringValues(PduHeaders.BCC);
}
/**
* Add a "BCC" value.
*
* @param value the value
* @throws NullPointerException if the value is null.
*/
public void addBcc(EncodedStringValue value) {
mPduHeaders.appendEncodedStringValue(value, PduHeaders.BCC);
}
/**
* Set "BCC" value.
*
* @param value the value
* @throws NullPointerException if the value is null.
*/
public void setBcc(EncodedStringValue[] value) {
mPduHeaders.setEncodedStringValues(value, PduHeaders.BCC);
}
/**
* Get CC value.
*
* @return the value
*/
public EncodedStringValue[] getCc() {
return mPduHeaders.getEncodedStringValues(PduHeaders.CC);
}
/**
* Add a "CC" value.
*
* @param value the value
* @throws NullPointerException if the value is null.
*/
public void addCc(EncodedStringValue value) {
mPduHeaders.appendEncodedStringValue(value, PduHeaders.CC);
}
/**
* Set "CC" value.
*
* @param value the value
* @throws NullPointerException if the value is null.
*/
public void setCc(EncodedStringValue[] value) {
mPduHeaders.setEncodedStringValues(value, PduHeaders.CC);
}
/**
* Get Content-type value.
*
* @return the value
*/
public byte[] getContentType() {
return mPduHeaders.getTextString(PduHeaders.CONTENT_TYPE);
}
/**
* Set Content-type value.
*
* @param value the value
* @throws NullPointerException if the value is null.
*/
public void setContentType(byte[] value) {
mPduHeaders.setTextString(value, PduHeaders.CONTENT_TYPE);
}
/**
* Get X-Mms-Delivery-Report value.
*
* @return the value
*/
public int getDeliveryReport() {
return mPduHeaders.getOctet(PduHeaders.DELIVERY_REPORT);
}
/**
* Set X-Mms-Delivery-Report value.
*
* @param value the value
* @throws InvalidHeaderValueException if the value is invalid.
*/
public void setDeliveryReport(int value) throws InvalidHeaderValueException {
mPduHeaders.setOctet(value, PduHeaders.DELIVERY_REPORT);
}
/**
* Get X-Mms-Expiry value.
*
* Expiry-value = Value-length
* (Absolute-token Date-value | Relative-token Delta-seconds-value)
*
* @return the value
*/
public long getExpiry() {
return mPduHeaders.getLongInteger(PduHeaders.EXPIRY);
}
/**
* Set X-Mms-Expiry value.
*
* @param value the value
*/
public void setExpiry(long value) {
mPduHeaders.setLongInteger(value, PduHeaders.EXPIRY);
}
/**
* Get X-Mms-MessageSize value.
*
* Expiry-value = size of message
*
* @return the value
*/
public long getMessageSize() {
return mPduHeaders.getLongInteger(PduHeaders.MESSAGE_SIZE);
}
/**
* Set X-Mms-MessageSize value.
*
* @param value the value
*/
public void setMessageSize(long value) {
mPduHeaders.setLongInteger(value, PduHeaders.MESSAGE_SIZE);
}
/**
* Get X-Mms-Message-Class value.
* Message-class-value = Class-identifier | Token-text
* Class-identifier = Personal | Advertisement | Informational | Auto
*
* @return the value
*/
public byte[] getMessageClass() {
return mPduHeaders.getTextString(PduHeaders.MESSAGE_CLASS);
}
/**
* Set X-Mms-Message-Class value.
*
* @param value the value
* @throws NullPointerException if the value is null.
*/
public void setMessageClass(byte[] value) {
mPduHeaders.setTextString(value, PduHeaders.MESSAGE_CLASS);
}
/**
* Get X-Mms-Read-Report value.
*
* @return the value
*/
public int getReadReport() {
return mPduHeaders.getOctet(PduHeaders.READ_REPORT);
}
/**
* Set X-Mms-Read-Report value.
*
* @param value the value
* @throws InvalidHeaderValueException if the value is invalid.
*/
public void setReadReport(int value) throws InvalidHeaderValueException {
mPduHeaders.setOctet(value, PduHeaders.READ_REPORT);
}
/**
* Set "To" value.
*
* @param value the value
* @throws NullPointerException if the value is null.
*/
public void setTo(EncodedStringValue[] value) {
mPduHeaders.setEncodedStringValues(value, PduHeaders.TO);
}
/**
* Get X-Mms-Transaction-Id field value.
*
* @return the X-Mms-Report-Allowed value
*/
public byte[] getTransactionId() {
return mPduHeaders.getTextString(PduHeaders.TRANSACTION_ID);
}
/**
* Set X-Mms-Transaction-Id field value.
*
* @param value the value
* @throws NullPointerException if the value is null.
*/
public void setTransactionId(byte[] value) {
mPduHeaders.setTextString(value, PduHeaders.TRANSACTION_ID);
}
/*
* Optional, not supported header fields:
*
* public byte getAdaptationAllowed() {return 0};
* public void setAdaptationAllowed(btye value) {};
*
* public byte[] getApplicId() {return null;}
* public void setApplicId(byte[] value) {}
*
* public byte[] getAuxApplicId() {return null;}
* public void getAuxApplicId(byte[] value) {}
*
* public byte getContentClass() {return 0x00;}
* public void setApplicId(byte value) {}
*
* public long getDeliveryTime() {return 0};
* public void setDeliveryTime(long value) {};
*
* public byte getDrmContent() {return 0x00;}
* public void setDrmContent(byte value) {}
*
* public MmFlagsValue getMmFlags() {return null;}
* public void setMmFlags(MmFlagsValue value) {}
*
* public MmStateValue getMmState() {return null;}
* public void getMmState(MmStateValue value) {}
*
* public byte[] getReplyApplicId() {return 0x00;}
* public void setReplyApplicId(byte[] value) {}
*
* public byte getReplyCharging() {return 0x00;}
* public void setReplyCharging(byte value) {}
*
* public byte getReplyChargingDeadline() {return 0x00;}
* public void setReplyChargingDeadline(byte value) {}
*
* public byte[] getReplyChargingId() {return 0x00;}
* public void setReplyChargingId(byte[] value) {}
*
* public long getReplyChargingSize() {return 0;}
* public void setReplyChargingSize(long value) {}
*
* public byte[] getReplyApplicId() {return 0x00;}
* public void setReplyApplicId(byte[] value) {}
*
* public byte getStore() {return 0x00;}
* public void setStore(byte value) {}
*/
}

View File

@ -1,5 +0,0 @@
<body>
{@hide}
</body>