1/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.internal.telephony;
18
19import com.android.internal.telephony.SmsConstants;
20import com.android.internal.telephony.SmsHeader;
21import java.util.Arrays;
22
23import android.provider.Telephony;
24
25/**
26 * Base class declaring the specific methods and members for SmsMessage.
27 * {@hide}
28 */
29public abstract class SmsMessageBase {
30    /** {@hide} The address of the SMSC. May be null */
31    protected String mScAddress;
32
33    /** {@hide} The address of the sender */
34    protected SmsAddress mOriginatingAddress;
35
36    /** {@hide} The message body as a string. May be null if the message isn't text */
37    protected String mMessageBody;
38
39    /** {@hide} */
40    protected String mPseudoSubject;
41
42    /** {@hide} Non-null if this is an email gateway message */
43    protected String mEmailFrom;
44
45    /** {@hide} Non-null if this is an email gateway message */
46    protected String mEmailBody;
47
48    /** {@hide} */
49    protected boolean mIsEmail;
50
51    /** {@hide} */
52    protected long mScTimeMillis;
53
54    /** {@hide} The raw PDU of the message */
55    protected byte[] mPdu;
56
57    /** {@hide} The raw bytes for the user data section of the message */
58    protected byte[] mUserData;
59
60    /** {@hide} */
61    protected SmsHeader mUserDataHeader;
62
63    // "Message Waiting Indication Group"
64    // 23.038 Section 4
65    /** {@hide} */
66    protected boolean mIsMwi;
67
68    /** {@hide} */
69    protected boolean mMwiSense;
70
71    /** {@hide} */
72    protected boolean mMwiDontStore;
73
74    /**
75     * Indicates status for messages stored on the ICC.
76     */
77    protected int mStatusOnIcc = -1;
78
79    /**
80     * Record index of message in the EF.
81     */
82    protected int mIndexOnIcc = -1;
83
84    /** TP-Message-Reference - Message Reference of sent message. @hide */
85    public int mMessageRef;
86
87    // TODO(): This class is duplicated in SmsMessage.java. Refactor accordingly.
88    public static abstract class SubmitPduBase  {
89        public byte[] encodedScAddress; // Null if not applicable.
90        public byte[] encodedMessage;
91
92        @Override
93        public String toString() {
94            return "SubmitPdu: encodedScAddress = "
95                    + Arrays.toString(encodedScAddress)
96                    + ", encodedMessage = "
97                    + Arrays.toString(encodedMessage);
98        }
99    }
100
101    /**
102     * Returns the address of the SMS service center that relayed this message
103     * or null if there is none.
104     */
105    public String getServiceCenterAddress() {
106        return mScAddress;
107    }
108
109    /**
110     * Returns the originating address (sender) of this SMS message in String
111     * form or null if unavailable
112     */
113    public String getOriginatingAddress() {
114        if (mOriginatingAddress == null) {
115            return null;
116        }
117
118        return mOriginatingAddress.getAddressString();
119    }
120
121    /**
122     * Returns the originating address, or email from address if this message
123     * was from an email gateway. Returns null if originating address
124     * unavailable.
125     */
126    public String getDisplayOriginatingAddress() {
127        if (mIsEmail) {
128            return mEmailFrom;
129        } else {
130            return getOriginatingAddress();
131        }
132    }
133
134    /**
135     * Returns the message body as a String, if it exists and is text based.
136     * @return message body is there is one, otherwise null
137     */
138    public String getMessageBody() {
139        return mMessageBody;
140    }
141
142    /**
143     * Returns the class of this message.
144     */
145    public abstract SmsConstants.MessageClass getMessageClass();
146
147    /**
148     * Returns the message body, or email message body if this message was from
149     * an email gateway. Returns null if message body unavailable.
150     */
151    public String getDisplayMessageBody() {
152        if (mIsEmail) {
153            return mEmailBody;
154        } else {
155            return getMessageBody();
156        }
157    }
158
159    /**
160     * Unofficial convention of a subject line enclosed in parens empty string
161     * if not present
162     */
163    public String getPseudoSubject() {
164        return mPseudoSubject == null ? "" : mPseudoSubject;
165    }
166
167    /**
168     * Returns the service centre timestamp in currentTimeMillis() format
169     */
170    public long getTimestampMillis() {
171        return mScTimeMillis;
172    }
173
174    /**
175     * Returns true if message is an email.
176     *
177     * @return true if this message came through an email gateway and email
178     *         sender / subject / parsed body are available
179     */
180    public boolean isEmail() {
181        return mIsEmail;
182    }
183
184    /**
185     * @return if isEmail() is true, body of the email sent through the gateway.
186     *         null otherwise
187     */
188    public String getEmailBody() {
189        return mEmailBody;
190    }
191
192    /**
193     * @return if isEmail() is true, email from address of email sent through
194     *         the gateway. null otherwise
195     */
196    public String getEmailFrom() {
197        return mEmailFrom;
198    }
199
200    /**
201     * Get protocol identifier.
202     */
203    public abstract int getProtocolIdentifier();
204
205    /**
206     * See TS 23.040 9.2.3.9 returns true if this is a "replace short message"
207     * SMS
208     */
209    public abstract boolean isReplace();
210
211    /**
212     * Returns true for CPHS MWI toggle message.
213     *
214     * @return true if this is a CPHS MWI toggle message See CPHS 4.2 section
215     *         B.4.2
216     */
217    public abstract boolean isCphsMwiMessage();
218
219    /**
220     * returns true if this message is a CPHS voicemail / message waiting
221     * indicator (MWI) clear message
222     */
223    public abstract boolean isMWIClearMessage();
224
225    /**
226     * returns true if this message is a CPHS voicemail / message waiting
227     * indicator (MWI) set message
228     */
229    public abstract boolean isMWISetMessage();
230
231    /**
232     * returns true if this message is a "Message Waiting Indication Group:
233     * Discard Message" notification and should not be stored.
234     */
235    public abstract boolean isMwiDontStore();
236
237    /**
238     * returns the user data section minus the user data header if one was
239     * present.
240     */
241    public byte[] getUserData() {
242        return mUserData;
243    }
244
245    /**
246     * Returns an object representing the user data header
247     *
248     * {@hide}
249     */
250    public SmsHeader getUserDataHeader() {
251        return mUserDataHeader;
252    }
253
254    /**
255     * TODO(cleanup): The term PDU is used in a seemingly non-unique
256     * manner -- for example, what is the difference between this byte
257     * array and the contents of SubmitPdu objects.  Maybe a more
258     * illustrative term would be appropriate.
259     */
260
261    /**
262     * Returns the raw PDU for the message.
263     */
264    public byte[] getPdu() {
265        return mPdu;
266    }
267
268    /**
269     * For an SMS-STATUS-REPORT message, this returns the status field from
270     * the status report.  This field indicates the status of a previously
271     * submitted SMS, if requested.  See TS 23.040, 9.2.3.15 TP-Status for a
272     * description of values.
273     *
274     * @return 0 indicates the previously sent message was received.
275     *         See TS 23.040, 9.9.2.3.15 for a description of other possible
276     *         values.
277     */
278    public abstract int getStatus();
279
280    /**
281     * Return true iff the message is a SMS-STATUS-REPORT message.
282     */
283    public abstract boolean isStatusReportMessage();
284
285    /**
286     * Returns true iff the <code>TP-Reply-Path</code> bit is set in
287     * this message.
288     */
289    public abstract boolean isReplyPathPresent();
290
291    /**
292     * Returns the status of the message on the ICC (read, unread, sent, unsent).
293     *
294     * @return the status of the message on the ICC.  These are:
295     *         SmsManager.STATUS_ON_ICC_FREE
296     *         SmsManager.STATUS_ON_ICC_READ
297     *         SmsManager.STATUS_ON_ICC_UNREAD
298     *         SmsManager.STATUS_ON_ICC_SEND
299     *         SmsManager.STATUS_ON_ICC_UNSENT
300     */
301    public int getStatusOnIcc() {
302        return mStatusOnIcc;
303    }
304
305    /**
306     * Returns the record index of the message on the ICC (1-based index).
307     * @return the record index of the message on the ICC, or -1 if this
308     *         SmsMessage was not created from a ICC SMS EF record.
309     */
310    public int getIndexOnIcc() {
311        return mIndexOnIcc;
312    }
313
314    protected void parseMessageBody() {
315        // originatingAddress could be null if this message is from a status
316        // report.
317        if (mOriginatingAddress != null && mOriginatingAddress.couldBeEmailGateway()) {
318            extractEmailAddressFromMessageBody();
319        }
320    }
321
322    /**
323     * Try to parse this message as an email gateway message
324     * There are two ways specified in TS 23.040 Section 3.8 :
325     *  - SMS message "may have its TP-PID set for Internet electronic mail - MT
326     * SMS format: [<from-address><space>]<message> - "Depending on the
327     * nature of the gateway, the destination/origination address is either
328     * derived from the content of the SMS TP-OA or TP-DA field, or the
329     * TP-OA/TP-DA field contains a generic gateway address and the to/from
330     * address is added at the beginning as shown above." (which is supported here)
331     * - Multiple addresses separated by commas, no spaces, Subject field delimited
332     * by '()' or '##' and '#' Section 9.2.3.24.11 (which are NOT supported here)
333     */
334    protected void extractEmailAddressFromMessageBody() {
335
336        /* Some carriers may use " /" delimiter as below
337         *
338         * 1. [x@y][ ]/[subject][ ]/[body]
339         * -or-
340         * 2. [x@y][ ]/[body]
341         */
342         String[] parts = mMessageBody.split("( /)|( )", 2);
343         if (parts.length < 2) return;
344         mEmailFrom = parts[0];
345         mEmailBody = parts[1];
346         mIsEmail = Telephony.Mms.isEmailAddress(mEmailFrom);
347    }
348
349}
350