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