2025-02-28 22:56:32 +08:00

1035 lines
34 KiB
HTML

<%+header%>
<script>
var pduParser = {};
pduParser.parse = function(pdu) {
//Cursor points to the last octet we've read.
var cursor = 0;
var buffer = new Buffer(pdu.slice(0,4), 'hex');
var smscSize = buffer[0];
var smscType = buffer[1].toString(16);
cursor = (smscSize*2+2);
var smscNum = pduParser.deSwapNibbles(pdu.slice(4, cursor));
var buffer = new Buffer(pdu.slice(cursor,cursor+6), 'hex');
cursor += 6;
var smsDeliver = buffer[0];
var smsDeliverBits = ("00000000"+parseInt(smsDeliver).toString(2)).slice(-8);
var udhi = smsDeliverBits.slice(1,2) === "1";
var senderSize = buffer[1];
if(senderSize % 2 === 1)
senderSize++;
var senderType = parseInt(buffer[2]).toString(16)
var encodedSender = pdu.slice(cursor, cursor + senderSize);
var senderNum;
if (senderType === '91') {
senderNum = pduParser.deSwapNibbles(encodedSender);
} else if (senderType === 'd0') {
senderNum = this.decode7Bit(encodedSender).replace(/\0/g, '');
} else {
console.error('unsupported sender type.');
}
cursor += senderSize;
var protocolIdentifier = pdu.slice(cursor, cursor+2);
cursor += 2;
var dataCodingScheme = pdu.slice(cursor, cursor+2);
cursor = cursor+2;
var encoding = pduParser.detectEncoding(dataCodingScheme);
var timestamp = pduParser.deSwapNibbles(pdu.slice(cursor, cursor+14));
var time = new Date;
time.setUTCFullYear('20'+timestamp.slice(0,2));
time.setUTCMonth(timestamp.slice(2,4)-1);
time.setUTCDate(timestamp.slice(4,6));
time.setUTCHours(timestamp.slice(6,8));
time.setUTCMinutes(timestamp.slice(8,10));
time.setUTCSeconds(timestamp.slice(10,12));
var firstTimezoneOctet = parseInt(timestamp.slice(12,13));
var binary = ("0000"+firstTimezoneOctet.toString(2)).slice(-4);
var factor = binary.slice(0,1) === '1' ? 1 : -1;
var binary = '0'+binary.slice(1, 4);
var firstTimezoneOctet = parseInt(binary, 2).toString(10);
var timezoneDiff = parseInt(firstTimezoneOctet + timestamp.slice(13, 14));
var time = new Date(time.getTime() + (timezoneDiff * 15 * 1000 * 60 * factor));
cursor += 14;
var dataLength = parseInt(pdu.slice(cursor, cursor+2), 16).toString(10);
cursor += 2;
if(udhi) { //User-Data-Header-Indicator: means there's some User-Data-Header.
var udhLength = pdu.slice(cursor, cursor+2);
var iei = pdu.slice(cursor+2, cursor+4);
if(iei == "00") { //Concatenated sms.
var headerLength = pdu.slice(cursor+4, cursor+6);
var referenceNumber = pdu.slice(cursor+6, cursor+8);
var parts = pdu.slice(cursor+8, cursor+10);
var currentPart = pdu.slice(cursor+10, cursor+12);
}
if(iei == "08") { //Concatenaded sms with a two-bytes reference number
var headerLength = pdu.slice(cursor+4, cursor+6);
var referenceNumber = pdu.slice(cursor+6, cursor+10);
var parts = pdu.slice(cursor+10, cursor+12);
var currentPart = pdu.slice(cursor+12, cursor+14);
}
if(encoding === '16bit')
if(iei == '00')
cursor += (udhLength-2)*4;
else if(iei == '08')
cursor += ((udhLength-2)*4)+2;
else
cursor += (udhLength-2)*2;
}
if(encoding === '16bit')
var text = pduParser.decode16Bit(pdu.slice(cursor), dataLength);
else if(encoding === '7bit')
var text = pduParser.decode7Bit(pdu.slice(cursor), dataLength);
else if(encoding === '8bit')
var text = ''; //TODO
var data = {
'smsc' : smscNum,
'smsc_type' : smscType,
'sender' : senderNum,
'sender_type' : senderType,
'encoding' : encoding,
'time' : time,
'text' : text
};
if(udhi) {
data['udh'] = {
'length' : udhLength,
'iei' : iei,
};
if(iei == '00' || iei == '08') {
data['udh']['reference_number'] = referenceNumber;
data['udh']['parts'] = parseInt(parts);
data['udh']['current_part'] = parseInt(currentPart);
}
}
return data;
}
pduParser.detectEncoding = function(dataCodingScheme) {
var binary = ('00000000'+(parseInt(dataCodingScheme, 16).toString(2))).slice(-8);
if(binary == '00000000')
return '7bit';
if(binary.slice(0, 2) === '00') {
var compressed = binary.slice(2, 1) === '1';
var bitsHaveMeaning = binary.slice(3, 1) === '1';
if(binary.slice(4,6) === '00')
return '7bit';
if(binary.slice(4,6) === '01')
return '8bit';
if(binary.slice(4,6) === '10')
return '16bit';
}
}
pduParser.decode16Bit = function(data, length) {
//We are getting ucs2 characters.
var ucs2 = '';
for(var i = 0;i<=data.length;i=i+4) {
ucs2 += String.fromCharCode("0x"+data[i]+data[i+1]+data[i+2]+data[i+3]);
}
return ucs2;
}
pduParser.deSwapNibbles = function(nibbles) {
var out = '';
for(var i = 0; i< nibbles.length; i=i+2) {
if(nibbles[i] === 'F') //Dont consider trailing F.
out += parseInt(nibbles[i+1], 16).toString(10);
else
out += parseInt(nibbles[i+1], 16).toString(10)+parseInt(nibbles[i], 16).toString(10);
}
return out;
}
pduParser.decode7Bit = function(code, count) {
//We are getting 'septeps'. We should decode them.
var binary = '';
for(var i = 0; i<code.length;i++)
binary += ('0000'+parseInt(code.slice(i,i+1), 16).toString(2)).slice(-4);
var bin = Array();
var cursor = 0;
var fromPrevious = '';
var i = 0;
while(binary[i]) {
var remaining = 7 - fromPrevious.length;
var toNext = 8 - remaining;
bin[i] = binary.slice(cursor+toNext, cursor+toNext+remaining) + fromPrevious;
var fromPrevious = binary.slice(cursor, cursor+toNext);
if(toNext === 8)
fromPrevious = '';
else
cursor += 8;
i++;
}
var ascii = '';
for(i in bin)
ascii += String.fromCharCode(parseInt(bin[i], 2));
return ascii;
}
pduParser.encode7Bit = function(ascii) {
//We should create septeps now.
var octets = new Array();
for(var i = 0; i<ascii.length; i++)
octets.push(('0000000'+(ascii.charCodeAt(i).toString(2))).slice(-7));
for(var i in octets) {
var i = parseInt(i);
var freeSpace = 8 - octets[i].length;
if(octets[i+1] && freeSpace !== 8) {
octets[i] = octets[i+1].slice(7-freeSpace) + octets[i];
octets[i+1] = octets[i+1].slice(0, 7-freeSpace);
}
}
var hex = '';
for(i in octets)
if(octets[i].length > 0)
hex += ('00'+(parseInt(octets[i], 2).toString(16))).slice(-2);
return hex;
}
//TODO: TP-Validity-Period (Delivery)
pduParser.generate = function(message) {
var pdu = '00';
var parts = 1;
if(message.encoding === '16bit' && message.text.length > 70)
parts = message.text.length / 66;
else if(message.encoding === '7bit' && message.text.length > 160)
parts = message.text.length / 153;
parts = Math.ceil(parts);
TPMTI = 1;
TPRD = 4;
TPVPF = 8;
TPSRR = 32;
TPUDHI = 64;
TPRP = 128;
var submit = TPMTI;
if(parts > 1) //UDHI
submit = submit | TPUDHI;
submit = submit | TPSRR;
pdu += submit.toString(16);
pdu += '00'; //TODO: Reference Number;
var receiverSize = ('00'+(parseInt(message.receiver.length, 10).toString(16))).slice(-2);
var receiver = pduParser.swapNibbles(message.receiver);
var receiverType = 81; //TODO: NOT-Hardcoded PDU generation. Please note that Hamrah1 doesnt work if we set it to 91 (International).
pdu += receiverSize.toString(16) + receiverType + receiver;
pdu += '00'; //TODO TP-PID
if(message.encoding === '16bit')
pdu += '08';
else if(message.encoding === '7bit')
pdu += '00';
var pdus = new Array();
var csms = randomHexa(2); // CSMS allows to give a reference to a concatenated message
for(var i=0; i< parts; i++) {
pdus[i] = pdu;
if(message.encoding === '16bit') {
/* If there are more than one messages to be sent, we are going to have to put some UDH. Then, we would have space only
* for 66 UCS2 characters instead of 70 */
if(parts === 1)
var length = 70;
else
var length = 66;
} else if(message.encoding === '7bit') {
/* If there are more than one messages to be sent, we are going to have to put some UDH. Then, we would have space only
* for 153 ASCII characters instead of 160 */
if(parts === 1)
var length = 160;
else
var length = 153;
}
var text = message.text.slice(i*length, (i*length)+length);
if(message.encoding === '16bit') {
user_data = pduParser.encode16Bit(text);
var size = (user_data.length / 2);
if(parts > 1)
size += 6; //6 is the number of data headers we append.
} else if(message.encoding === '7bit') {
user_data = pduParser.encode7Bit(text);
var size = user_data.length / 2;
}
pdus[i] += ('00'+parseInt(size).toString(16)).slice(-2);
if(parts > 1) {
pdus[i] += '05';
pdus[i] += '00';
pdus[i] += '03';
pdus[i] += csms;
pdus[i] += ('00'+parts.toString(16)).slice(-2);
pdus[i] += ('00'+(i+1).toString(16)).slice(-2);
}
pdus[i] += user_data;
}
return pdus;
}
pduParser.encode16Bit = function(text) {
var out = '';
for(var i = 0; i<text.length;i++) {
out += ('0000'+(parseInt(text.charCodeAt(i), 10).toString(16))).slice(-4);
}
return out;
}
pduParser.swapNibbles = function(nibbles) {
var out = '';
for(var i = 0; i< nibbles.length; i=i+2) {
if(typeof(nibbles[i+1]) === 'undefined') // Add a trailing F.
out += 'F'+parseInt(nibbles[i], 16).toString(10);
else
out += parseInt(nibbles[i+1], 16).toString(10)+parseInt(nibbles[i], 16).toString(10);
}
return out;
}
pduParser.parseStatusReport = function(pdu) {
//Cursor points to the last octet we've read.
var cursor = 0;
var smscSize = parseInt(pdu.slice(0, 2), 16);
cursor += 2;
var smscType = parseInt(pdu.slice(cursor, cursor+2), 16);
cursor += 2;
var smscNum = pduParser.deSwapNibbles(pdu.slice(cursor, (smscSize*2)+2));
cursor = (smscSize*2+2);
var header = parseInt(pdu.slice(cursor,cursor+2));
cursor += 2;
var reference = parseInt(pdu.slice(cursor,cursor+2), 16);
cursor += 2;
var senderSize = parseInt(pdu.slice(cursor,cursor+2), 16);
if(senderSize % 2 === 1)
senderSize++;
cursor += 2;
var senderType = parseInt(pdu.slice(cursor,cursor+2));
cursor += 2;
var sender = pduParser.deSwapNibbles(pdu.slice(cursor, cursor+senderSize));
var status = pdu.slice(-2);
return {
smsc:smscNum,
reference:reference,
sender:sender,
status:status
}
}
function randomHexa(size)
{
var text = "";
var possible = "0123456789ABCDEF";
for( var i=0; i < size; i++ )
text += possible.charAt(Math.floor(Math.random() * possible.length));
return text;
}
class LuciTable{
constructor(){
this.rows = [];
this.tbody;
this.fieldset;
this.init_table();
}
init_table(){
//create a luci fieldset (class cbi-section)
var fieldset = document.createElement('fieldset');
fieldset.className="cbi-section";
//set fieldset Header name
var legend = document.createElement('legend');
var title_span = document.createElement('span');
title_span.className="panel-title"
//init table
var table = document.createElement('table');
var tbody = document.createElement('tbody');
table.className="table"
//save
this.fieldset = fieldset;
this.tbody = tbody
this.title_span = title_span
this.legend = legend
fieldset.appendChild(legend);
fieldset.appendChild(title_span);
table.appendChild(tbody)
fieldset.appendChild(table)
}
new_tr(data,index){
var type = data.type;
var col = data.col;
var left = data.left;
var right = data.right;
//clear the row
this.rows[index].left.innerHTML = "";
this.rows[index].right.innerHTML = "";
//set the row
this.rows[index].left.appendChild(left);
this.rows[index].right.appendChild(right);
if (right == null || right == "") {
this.rows[index].row.style.display = "none";
}
else{
this.rows[index].row.style.display = "";
}
}
set title(value){
this.legend.innerHTML = value;
this.title_span.innerHTML = value;
}
set object_data(value){
var row_length = this.rows.length;
var value_length = Object.keys(value).length;
if (row_length < value_length) {
for ( let i = row_length; i < value_length; i++) {
let row = document.createElement('tr');
row.className = "tr"
let cell_left = document.createElement('td');
cell_left.classList.add("td")
cell_left.setAttribute("width","33%")
let cell_right = document.createElement('td');
cell_right.classList.add("td");
row.appendChild(cell_left);
row.appendChild(cell_right);
this.tbody.appendChild(row);
var row_dict = {
"row":row,
"left":cell_left,
"right":cell_right,
}
this.rows.push(row_dict);
}
}
else if(row_length > value_length){
for (let i = value_length; i < row_length; i++) {
this.tbody.removeChild(this.rows[i].row);
}
this.rows = this.rows.slice(0,value_length);
}
var index = 0;
for (var key in value) {
this.rows[index].left.innerHTML = key;
this.rows[index].right.innerHTML = value[key];
index++;
}
}
set array_data(value){
var row_length = this.rows.length;
var value_length = value.length;
if (row_length < value_length) {
for ( let i = row_length; i < value_length; i++) {
let row = document.createElement('tr');
row.className = "tr"
let cell_left = document.createElement('td');
cell_left.classList.add("td")
cell_left.setAttribute("width","33%")
let cell_right = document.createElement('td');
cell_right.classList.add("sms_recv_content")
cell_right.classList.add("td")
row.appendChild(cell_left);
row.appendChild(cell_right);
this.tbody.appendChild(row);
var row_dict = {
"row":row,
"left":cell_left,
"right":cell_right,
}
this.rows.push(row_dict);
}
}
else if(row_length > value_length){
for (let i = value_length; i < row_length; i++) {
this.tbody.removeChild(this.rows[i].row);
}
this.rows = this.rows.slice(0,value_length);
}
for (let i = 0; i < value.length; i++) {
this.new_tr(value[i],i);
}
}
set data(value){
if (value == null) {
return;
}
if (Array.isArray(value)) {
this.array_data = value;
}
else{
this.object_data = value;
}
}
}
class ModemSMS {
constructor() {
this.data = null;
this.cfg_id = null;
this.modem_cfg_list = [];
this.sms_recvbox_table = new LuciTable();
this.sms_send_table = new LuciTable();
this.sms_storage_table = new LuciTable();
this.sms_send_table.title = "<%:Send SMS%>";
this.cbi_map = document.querySelector('.cbi-map');
this.cbi_map.appendChild(this.sms_storage_table.fieldset);
this.cbi_map.appendChild(this.sms_recvbox_table.fieldset);
this.cbi_map.appendChild(this.sms_send_table.fieldset);
this.modem_selector = document.getElementById('modem_selector');
this.create_modem_cfg_selector();
this.update_modem_cfg_list();
this.init_send_table_view();
this.init_msg_box();
this.init_sms_storage_table();
}
init_sms_storage_table() {
const createOption = (value, text, disabled = false, selected = false) => {
const opt = document.createElement('option');
opt.value = value;
opt.innerHTML = text;
opt.disabled = disabled;
opt.selected = selected;
return opt;
};
const reading_storage = document.createElement('select');
const writing_storage = document.createElement('select');
const etc_storage = document.createElement('select');
const set_storage_btn = document.createElement('input');
set_storage_btn.type = "button";
set_storage_btn.value = "Set";
set_storage_btn.onclick = () => this.set_sms_storage();
const opt_mt = createOption("ME", "<%: Mobile equipment message storage %>");
const opt_sm = createOption("SM", "<%: (U)SIM message storage %>");
const opt_loading = createOption("Loading", "<%: Loading... %>", true, true);
const storages = [reading_storage, writing_storage, etc_storage];
storages.forEach(storage => {
storage.appendChild(opt_mt.cloneNode(true));
storage.appendChild(opt_sm.cloneNode(true));
storage.appendChild(opt_loading.cloneNode(true));
storage.options[2].selected = true;
});
const data = [
{ "col": 2, "left": document.createTextNode("<%: Reading Storage%>"), "right": reading_storage },
{ "col": 2, "left": document.createTextNode("<%: Writing Storage%>"), "right": writing_storage },
{ "col": 2, "left": document.createTextNode("<%: ETC Storage%>"), "right": etc_storage },
{ "col": 2, "left": document.createTextNode("<%: Set Storage%>"), "right": set_storage_btn }
];
this.sms_storage_table.title = "<%:SMS Storage%>";
this.sms_storage_table.data = data;
this.reading_storage = reading_storage;
this.writing_storage = writing_storage;
this.etc_storage = etc_storage;
this.opt_mt1 = storages[0].querySelector('option[value="ME"]');
this.opt_sm1 = storages[0].querySelector('option[value="SM"]');
this.opt_mt2 = storages[1].querySelector('option[value="ME"]');
this.opt_sm2 = storages[1].querySelector('option[value="SM"]');
this.opt_mt3 = storages[2].querySelector('option[value="ME"]');
this.opt_sm3 = storages[2].querySelector('option[value="SM"]');
}
init_msg_box()
{
var warn_msg_box = document.createElement('div');
warn_msg_box.className = "cbi-section";
var warn_msg = document.createElement('div');
warn_msg.className = "alert";
warn_msg_box.appendChild(warn_msg);
this.cbi_map.appendChild(warn_msg_box);
this.warn_msg_box = warn_msg_box;
//hide
this.warn_msg_box.style.display = "none";
}
warn_msg(msg,timeout){
this.warn_msg_box.style.display = "";
this.warn_msg_box.classList.add("alert-warning");
this.warn_msg_box.firstChild.innerHTML = msg;
setTimeout(()=>{
this.warn_msg_box.style.display = "none";
this.warn_msg_box.classList.remove("alert-warning");
},timeout);
}
log_msg(msg,timeout){
this.warn_msg_box.style.display = "";
this.warn_msg_box.classList.add("alert-info");
this.warn_msg_box.firstChild.innerHTML = msg;
setTimeout(()=>{
this.warn_msg_box.style.display = "none";
this.warn_msg_box.classList.remove("alert-info");
},timeout);
}
create_modem_cfg_selector(){
var selector = document.createElement('select');
selector.addEventListener('change', (event) => {
this.update();
this.cfg_id = event.target.value;
console.log(this.cfg_id);
});
this.modem_selector.appendChild(selector);
this.selector = selector;
this.poll_info();
}
send(){
//if content contain non-ascii char, use raw pdu
var content = this.message_content.value;
var is_ascii = /^[\x00-\x7F]*$/.test(content);
if (is_ascii) {
this.send_raw_pdu();
}
else{
this.send_raw_pdu();
}
}
send_gsm(){
var phone_number = this.phone_number.value;
var message_content = this.message_content.value;
XHR.get('<%=luci.dispatcher.build_url("admin", "modem", "qmodem", "send_sms")%>',{
"cfg": this.cfg_id,
"phone_number": phone_number,
"message_content": message_content,
},(x,data)=>{
this.update();
data.result.status == 1 ? this.log_msg("<%:Send SMS Success%>",3000) : this.warn_msg("<%:Send SMS Failed%>",3000);
});
}
send_raw_pdu(){
var pdu = pduParser.generate(
{
text: this.message_content.value,
encoding: "16bit",
receiver: this.phone_number.value,
}
)
//if pdu is array,send first pdu
if (Array.isArray(pdu)) {
pdu = pdu[0];
}
XHR.get('<%=luci.dispatcher.build_url("admin", "modem", "qmodem", "send_sms")%>',{
"cfg": this.cfg_id,
"pdu": pdu,
},(x,data)=>{
this.update();
data.result.status == 1 ? this.log_msg("<%:Send SMS Success%>",3000) : this.warn_msg("<%:Send SMS Failed%>",3000);
});
}
set_sms_storage(){
let payload;
let mem1,mem2,mem3;
mem1 = this.reading_storage.value;
mem2 = this.writing_storage.value;
mem3 = this.etc_storage.value;
payload = {
"mem1": mem1,
"mem2": mem2,
"mem3": mem3,
}
XHR.get('<%=luci.dispatcher.build_url("admin", "modem", "qmodem", "modem_ctrl")%>', {
"cfg": this.cfg_id,
"action":"set_sms_storage",
"params": JSON.stringify(JSON.stringify(payload))
},(x,data)=>{
this.update();
});
}
lock(){
var delete_btns = document.querySelectorAll('input[value="<%:Delete%>"]');
for (let btn of delete_btns) {
console.log(btn);
btn.disabled = true;
}
}
release(){
var delete_btns = document.querySelectorAll('input[value="<%:Delete%>"]');
for (let btn of delete_btns) {
btn.disabled = false;
}
}
init_send_table_view(){
let phone_number,message_content,send_button,send_raw_pdu_button;
phone_number = document.createElement('input');
phone_number.type = "text";
message_content = document.createElement('textarea');
message_content.rows = 5;
message_content.cols = 50;
send_button = document.createElement('input');
send_button.type = "button";
send_button.value = "<%:Send%>";
send_button.addEventListener('click',()=>{
this.send();
});
this.phone_number = phone_number;
this.message_content = message_content;
this.sms_send_table.data = [
{
"col": 2,
"left": document.createTextNode("<%:Phone Number%>"),
"right": phone_number,
},
{
"col": 2,
"left": document.createTextNode("<%:Message Content%>"),
"right": message_content,
},
{
"col": 2,
"left": document.createTextNode("<%:Send%>"),
"right": send_button,
}
];
}
poll_info(){
if (this.cfg_id == null){
return;
}
XHR.poll(10,'<%=luci.dispatcher.build_url("admin", "modem", "qmodem", "get_sms")%>',{
"cfg": this.cfg_id,
}, (x,data) => {
this.combine_messages(data);
});
}
update(){
XHR.get('<%=luci.dispatcher.build_url("admin", "modem", "qmodem", "get_sms")%>',{
"cfg": this.cfg_id,
}, (x,data) => {
this.combine_messages(data);
this.update_sms_capabilities(data);
});
}
update_modem_cfg_list(){
XHR.poll(5,'<%=luci.dispatcher.build_url("admin", "modem", "qmodem", "get_modem_cfg")%>',{},(x,data)=>{
var new_cfg_list = [];
var cfgs = data.cfgs;
for (let i = 0; i < cfgs.length; i++) {
var cfg = cfgs[i];
var name = cfg.name;
var value = cfg.cfg;
new_cfg_list.push({"value":value,"name":name});
}
if (new_cfg_list != this.modem_cfg_list) {
this.cfg_options = new_cfg_list;
}
});
}
combine_messages(data){
var messages,reference_table,msgs;
messages = []
reference_table = {}
msgs = data.msg;
for ( let msg of msgs){
let part,total,index,reference,sender,timestamp,content;
if (msg.reference){
reference = `${msg.reference}.${msg.sender}`;
if (reference in reference_table){
reference_table[reference].push(msg);
}
else{
reference_table[reference] = [msg];
}
}
else{
msg.index = [msg.index]
messages.push(msg);
}
}
//combile the messages in reference_table
for (let key in reference_table){
let reference_msgs = reference_table[key];
let total = reference_msgs[0].total;
let part = [];
let content = "";
let sender = reference_msgs[0].sender;
let timestamp = reference_msgs[0].timestamp;
let index = [];
reference_msgs.sort((a,b)=>{
return a.part - b.part;
});
for (let reference_msg of reference_msgs){
content += reference_msg.content;
part.push(reference_msg.part);
index.push(reference_msg.index);
}
messages.push({
"sender":sender,
"timestamp":timestamp,
"content":content,
"part":part,
"total":total,
"index":index,
});
}
messages.sort((a,b)=>{
//filter timestamp space and / :
let at,bt
at = a.timestamp;
bt = b.timestamp;
if (typeof at == "string") {
at = at.replace(/ /g,"");
bt = bt.replace(/ /g,"");
at = at.replace(/\//g,"");
bt = bt.replace(/\//g,"");
at = at.replace(/:/g,"");
bt = bt.replace(/:/g,"");
}
return bt - at;
});
this.view = messages;
}
update_sms_capabilities(data) {
const sms_capabilities = data.sms_capabilities;
const storages = [
{ mem: sms_capabilities.mem1, storage: this.reading_storage, opts: ['opt_mt1', 'opt_sm1'] },
{ mem: sms_capabilities.mem2, storage: this.writing_storage, opts: ['opt_mt2', 'opt_sm2'] },
{ mem: sms_capabilities.mem3, storage: this.etc_storage, opts: ['opt_mt3', 'opt_sm3'] }
];
const updateStorage = (mem, storage, mtOpt, smOpt) => {
let mt = "", sm = "";
if (mem === "MT" || mem === "ME") {
if (storage.value === "Loading") storage.value = "ME";
mt = "[<%:Using%>]";
} else if (mem === "SM") {
if (storage.value === "Loading") storage.value = "SM";
sm = "[<%:Using%>]";
} else {
storage.value = "Loading";
}
this[mtOpt].innerHTML = mt + me_message_text;
this[smOpt].innerHTML = sm + sm_message_text;
};
const me_message_text = sms_capabilities.ME.used
? `<%: Mobile equipment message storage %> <%: (Used/Total) %>(${sms_capabilities.ME.used}/${sms_capabilities.ME.total})`
: "<%: Mobile equipment message storage %>";
const sm_message_text = sms_capabilities.SM.used
? `<%: (U)SIM message storage %> <%: (Used/Total) %>(${sms_capabilities.SM.used}/${sms_capabilities.SM.total})`
: "<%: (U)SIM message storage %>";
storages.forEach(({ mem, storage, opts }) => updateStorage(mem, storage, opts[0], opts[1]));
}
set cfg_options(value){
var longger = this.modem_cfg_list.length > value.length ? this.modem_cfg_list : value;
if (longger.length == 0) {
return;
}
for (let i = 0; i < longger.length; i++) {
var option = this.selector.options[i];
if (i < value.length) {
if (i >= this.selector.options.length) {
option = document.createElement('option');
this.selector.appendChild(option);
}
option.value = value[i].value;
option.innerHTML = value[i].name;
}
else{
this.selector.removeChild(option);
}
}
this.cfg_id = this.selector.value;
this.modem_cfg_list = value;
this.update();
}
set view(data){
this.data = data;
if (data == null) {
return;
}
var enties = []
var msgs = data;
for (let msg of msgs){
let sender,timestamp,content,part,total,index;
sender = msg.sender;
if (typeof(msg.timestamp) == "number") {
timestamp = new Date(msg.timestamp*1000).toISOString()
}
else{
timestamp = msg.timestamp;
}
content = msg.content;
part = msg.part;
total = msg.total;
index = msg.index;
let sender_strong,timestamp_strong,content_strong,part_strong,total_strong,delete_btn;
let left,right;
left = document.createElement('div');
right = document.createElement('div');
delete_btn = document.createElement('input');
delete_btn.type = "button";
delete_btn.value = "<%:Delete%>";
delete_btn.addEventListener('click',()=>{
this.lock();
XHR.get('<%=luci.dispatcher.build_url("admin", "modem", "qmodem", "delete_sms")%>',{
"cfg": this.cfg_id,
"index": index.sort((a,b)=>{return b-a}).join(" "),
},(x,data)=>{
this.update();
this.release
});
});
sender_strong = document.createElement('strong');
sender_strong.innerHTML = `<%:Sender%>: ${sender}`;
timestamp_strong = document.createElement('strong');
timestamp_strong.innerHTML = `<%:Timestamp%>: ${timestamp}`;
content_strong = document.createElement('strong');
content_strong.innerHTML = `<%:Content%>: ${content}`;
left.appendChild(sender_strong);
left.appendChild(document.createElement('br'));
left.appendChild(timestamp_strong);
left.appendChild(document.createElement('br'));
left.appendChild(delete_btn);
right.appendChild(content_strong);
if (part != null) {
part_strong = document.createElement('strong');
part_strong.innerHTML = `(${part}/${total})`;
right.appendChild(document.createElement('br'));
right.appendChild(part_strong);
}
enties.push({
"col" : 2,
"left" : left,
"right" : right
});
}
this.sms_recvbox_table.data = enties;
this.sms_recvbox_table.title = "SMS";
}
}
window.onload = function(){
const getSMS = new ModemSMS();
}
</script>
<style>
.sms_recv_content {
text-align: left;
word-wrap: break-word;
white-space: normal;
overflow-wrap: break-word;
}
</style>
<div>
<div class="cbi-map">
<fieldset class="cbi-section">
<table class="table">
<tbody>
<tr class="tr">
<td class="td" width="33%"><%:Modem Name%></td>
<td class="td" id="modem_selector">
</td>
</tr>
</tbody>
</table>
</fieldset>
</div>
</div>
<%+footer%>