1/**
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15import commonEvent from '@ohos.commonEventManager';
16import telSim from '@ohos.telephony.sms';
17import http from '@ohos.net.http';
18
19import common from '../data/commonData';
20import telephoneUtils from '../utils/TelephoneUtil';
21import HiLog from '../utils/HiLog';
22import commonService from '../service/CommonService';
23import ConversationService from '../service/ConversationService';
24import NotificationService from '../service/NotificationService';
25import LooseObject from '../data/LooseObject'
26import ConversationListService from '../service/ConversationListService';
27import ContactService from '../service/ContactsService';
28
29const TAG: string = 'MmsStaticSubscriber'
30
31var StaticSubscriberExtensionAbility = globalThis.requireNapi('application.StaticSubscriberExtensionAbility');
32
33export default class MmsStaticSubscriber extends StaticSubscriberExtensionAbility {
34
35    public onReceiveEvent(data): void {
36        HiLog.i(TAG, 'onReceiveEvent, event:' );
37        if (data.event === common.string.SUBSCRIBER_EVENT) {
38            this.dealSmsReceiveData(data, this.context);
39        } else {
40            this.dealMmsReceiveData(data, this.context);
41        }
42    }
43
44    public async dealSmsReceiveData(data, context): Promise<void> {
45        let netType: string = data.parameters.isCdma ? '3gpp2' : '3gpp';
46        // Synchronize wait operation
47        let promisesAll = [];
48        data.parameters.pdus.forEach(pdu => {
49            let promise = telSim.createMessage(this.convertStrArray(pdu), netType);
50            promisesAll.push(promise);
51        });
52        let result: LooseObject = {};
53        let createMessagePromise = Promise.all(promisesAll);
54        createMessagePromise.then(shortMsgList => {
55            result.code = common.int.SUCCESS;
56            result.telephone = telephoneUtils.formatTelephone(shortMsgList[0].visibleRawAddress);
57            result.content = common.string.EMPTY_STR;
58            shortMsgList.forEach(shortMessage => {
59                result.content += shortMessage.visibleMessageBody;
60            });
61        }).catch(error => {
62            HiLog.e(TAG, 'dealSmsReceiveData, error: ' + JSON.stringify(error));
63            result.code = common.int.FAILURE;
64        });
65        await createMessagePromise;
66        let actionData: LooseObject = {};
67        actionData.slotId = data.parameters.slotId;
68        actionData.telephone = result.telephone;
69        actionData.content = result.content;
70        actionData.isMms = false;
71        actionData.mmsSource = [];
72        this.insertMessageDetailBy(actionData, res => {
73            this.sendNotification(result.telephone, res.initDatas[0].id, result.content, context);
74            this.publishData(result.telephone, result.content);
75        }, context);
76    }
77
78    public dealMmsReceiveData(data, context): void {
79        let result = JSON.parse(data.data);
80        this.saveAttachment(result.mmsSource);
81        let content: string = commonService.getMmsContent(result.mmsSource);
82        let actionData: LooseObject = {};
83        actionData.telephone = result.telephone;
84        actionData.content = content;
85        actionData.isMms = true;
86        actionData.mmsSource = result.mmsSource;
87        actionData.slotId = data.parameters.slotId;
88        this.insertMessageDetailBy(actionData, res => {
89            let notificationContent = this.getNotificationContent(result.mmsSource, content);
90            this.sendNotification(result.telephone, res.initDatas[0].id, notificationContent, context);
91            this.publishData(result.telephone, result.content);
92        }, context);
93    }
94
95    public saveAttachment(mmsSource): void {
96        for (let item of mmsSource) {
97            let baseUrl = item.msgUriPath;
98            let httpRequest = http.createHttp();
99            httpRequest.request(common.string.MMS_URL,
100                {
101                    method: http.RequestMethod.GET,
102                    header: {
103                        'Content-Type': 'application/json',
104                    },
105                    extraData: baseUrl,
106                    readTimeout: 50000,
107                    connectTimeout: 50000
108                }, (err, data) => {
109                    HiLog.i(TAG, 'saveAttachment, err: ' + JSON.stringify(err.message));
110                }
111            );
112        }
113    }
114
115    public getNotificationContent(mmsSource, themeContent): string {
116        let content: string = common.string.EMPTY_STR;
117        if (mmsSource.length === 1) {
118            let item = mmsSource[0];
119            switch (item.msgType) {
120                // Subject
121                case 0:
122                    content = themeContent;
123                    break;
124                // Pictures
125                case 1:
126                    content = '(picture)' + themeContent;
127                    break;
128                // Video
129                case 2:
130                    content = '(video)' + themeContent;
131                    break;
132                // Audio
133                case 3:
134                    content = '(audio)' + themeContent;
135                    break;
136            }
137        } else {
138            content = '(slide)' + mmsSource[0].content;
139        }
140        return content;
141    }
142
143    public insertMessageDetailBy(param, callback, context): void {
144        let sendResults: Array<LooseObject> = [];
145        let sendResult: LooseObject = {};
146        sendResult.slotId = param.slotId;
147        sendResult.telephone = param.telephone;
148        sendResult.content = param.content;
149        sendResult.sendStatus = common.int.SEND_MESSAGE_SUCCESS;
150        sendResults.push(sendResult);
151
152        let hasAttachment: boolean = commonService.judgeIsAttachment(param.mmsSource);
153        let actionData: LooseObject = {};
154        actionData.slotId = param.slotId;
155        actionData.sendResults = sendResults;
156        actionData.isReceive = true;
157        actionData.ownNumber = common.string.EMPTY_STR;
158        actionData.isSender = true;
159        actionData.isMms = param.isMms;
160        actionData.mmsSource = param.mmsSource;
161        actionData.hasAttachment = hasAttachment;
162        ConversationService.getInstance().insertSessionAndDetail(actionData, callback, context);
163    }
164
165    public convertStrArray(sourceStr): Array<number> {
166        let wby: string = sourceStr;
167        let length: number = wby.length;
168        let isDouble: boolean = (length % 2) == 0;
169        let halfSize: number = parseInt('' + length / 2);
170        HiLog.i(TAG, 'convertStrArray, length=' + length + ', isDouble=' + isDouble);
171        if (isDouble) {
172            let number0xArray = new Array(halfSize);
173            for (let i = 0;i < halfSize; i++) {
174                number0xArray[i] = '0x' + wby.substr(i * 2, 2);
175            }
176            let numberArray = new Array(halfSize);
177            for (let i = 0;i < halfSize; i++) {
178                numberArray[i] = parseInt(number0xArray[i], 16);
179            }
180            return numberArray;
181        } else {
182            let number0xArray = new Array(halfSize + 1);
183            for (let i = 0;i < halfSize; i++) {
184                number0xArray[i] = '0x' + wby.substr(i * 2, 2);
185            }
186            number0xArray[halfSize] = '0x' + wby.substr((halfSize * 2) + 1, 1);
187            let numberArray = new Array(halfSize + 1);
188            for (let i = 0;i < halfSize; i++) {
189                numberArray[i] = parseInt(number0xArray[i], 16);
190            }
191            let last0x = '0x' + wby.substr(wby.length - 1, 1);
192            numberArray[halfSize] = parseInt(last0x);
193            return numberArray;
194        }
195    }
196
197    public publishData(telephone, content): void {
198        HiLog.i(TAG, 'publishData, start');
199        let actionData = {
200            telephone: telephone,
201            content: content
202        };
203        commonEvent.publish(common.string.RECEIVE_TRANSMIT_EVENT, {
204            bundleName: common.string.BUNDLE_NAME,
205            subscriberPermissions: ['ohos.permission.RECEIVE_SMS'],
206            isOrdered: false,
207            data: JSON.stringify(actionData)
208        }, (res) => {
209        });
210    }
211
212    public sendNotification(telephone, msgId, content, context): void {
213        let condition: LooseObject = {};
214        condition.telephones = [telephone];
215        ContactService.getInstance().queryContactDataByCondition(condition, res => {
216            HiLog.i(TAG, 'sendNotification, callback');
217            if (res.code == common.int.FAILURE) {
218                return;
219            }
220            let contacts: Array<LooseObject> = res.abilityResult;
221            let actionData: LooseObject = this.dealContactParams(contacts, telephone);
222            if (content.length > 15) {
223                content = content.substring(0, 15) + '...';
224            }
225            let title: string = telephone;
226            if(contacts.length > 0) {
227                title = contacts[0].displayName
228            }
229            let message: LooseObject = {
230                'title': title,
231                'text': content,
232            };
233            actionData.message = message;
234            actionData.msgId = msgId;
235            actionData.unreadTotal = 0;
236            NotificationService.getInstance().sendNotify(actionData);
237            ConversationListService.getInstance().statisticalData(res => {
238                if (res.code == common.int.SUCCESS) {
239                    NotificationService.getInstance().setBadgeNumber(Number(res.response.totalListCount));
240                }
241            }, context);
242        }, context);
243    }
244
245    public dealContactParams(contacts, telephone): LooseObject {
246        let actionData: LooseObject = {};
247        let params: Array<LooseObject> = [];
248        if (contacts.length == 0) {
249            params.push({
250                telephone: telephone,
251            });
252        } else {
253            let contact: LooseObject = contacts[0];
254            params.push({
255                contactsName: contact.displayName,
256                telephone: telephone,
257                telephoneFormat: contact.detailInfo,
258            });
259        }
260        actionData.contactObjects = JSON.stringify(params);
261        return actionData;
262    }
263}
264