This commit is contained in:
ed 2021-12-22 10:44:27 +01:00
parent 4ccdb9a673
commit 8dac813b54

View File

@ -138,7 +138,7 @@ let charsets = {
090F 091E 0928 ? 093D 094D o 097F 090F 091E 0928 ? 093D 094D o 097F
`, `,
//A.3.7 Kannada National Language Locking Shift Table // A.3.7 Kannada National Language Locking Shift Table
Kannada: ` Kannada: `
0000 0C90 SP 0 0CAC 0CBE 0CD5 p 0000 0C90 SP 0 0CAC 0CBE 0CD5 p
0C82 0000 ! 1 0CAD 0CBF a q 0C82 0000 ! 1 0CAD 0CBF a q
@ -277,7 +277,7 @@ let charsets = {
067A 0689 . 0634 0645 064F n 0656 067A 0689 . 0634 0645 064F n 0656
067C 068A 0698 ? 0646 0657 o 0670 067C 068A 0698 ? 0646 0657 o 0670
` `
} };
let extensions = { let extensions = {
// 6.2.1.1 GSM 7 bit default alphabet extension table // 6.2.1.1 GSM 7 bit default alphabet extension table
@ -321,7 +321,7 @@ let extensions = {
`, `,
// A.2.2 Spanish National Language Single Shift Table // A.2.2 Spanish National Language Single Shift Table
Spanish: ` Spanish: `
0000 0000 0000 0000 | 0000 0000 0000 0000 0000 0000 0000 | 0000 0000 0000
0000 0000 0000 0000 Á 0000 á 0000 0000 0000 0000 0000 Á 0000 á 0000
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
@ -561,44 +561,44 @@ let extensions = {
- 06F2 0612 ] N 0000 0000 0000 - 06F2 0612 ] N 0000 0000 0000
/ 06F3 \\ 06D4 O 0000 0000 0000 / 06F3 \\ 06D4 O 0000 0000 0000
` `
} };
// Special characters in previous tables // Special characters in previous tables
let specials = { let specials = {
'1)': '\x1b', "1)": "\x1b",
'3)': '\x0c', "3)": "\x0c",
'4)': '\r', "4)": "\r",
'SP': ' ', "SP": " ",
'CR': '\r', "CR": "\r",
'LF': '\n' "LF": "\n"
} };
/** /**
* Converting 3GPP tables in charsets and extensions OPTION arrays * Converting 3GPP tables in charsets and extensions OPTION arrays
*/ */
function convertCharTable(chars) { function convertCharTable(chars) {
console.assert(chars.length==128) console.assert(chars.length===128);
let conv = new Array(128); const conv = new Array(128);
for (let i=0; i<128; i++) { for (let i=0; i<128; i++) {
let char = chars[~~(i/16) + (i%16)*8]; let char = chars[~~(i/16) + (i%16)*8];
if (char in specials) { if (char in specials) {
char = specials[char]; char = specials[char];
} }
if (char.length == 4) { if (char.length === 4) {
char = String.fromCodePoint(Number("0x" + char)); char = String.fromCodePoint(Number("0x" + char));
} }
conv[i] = char; conv[i] = char;
} }
return conv; return conv;
} }
export var CHARSET_OPTIONS = []; export const CHARSET_OPTIONS = [];
for (const lang in charsets) { for (const lang in charsets) {
let charset = convertCharTable(charsets[lang].trim().split(/\s+/)); const charset = convertCharTable(charsets[lang].trim().split(/\s+/));
CHARSET_OPTIONS.push({name: lang, value: charset}); CHARSET_OPTIONS.push({name: lang, value: charset});
} }
export var EXTENSION_OPTIONS = []; export const EXTENSION_OPTIONS = [];
for (const lang in extensions) { for (const lang in extensions) {
let extension = convertCharTable(extensions[lang].trim().split(/\s+/)); const extension = convertCharTable(extensions[lang].trim().split(/\s+/));
EXTENSION_OPTIONS.push({name: lang, value: extension}); EXTENSION_OPTIONS.push({name: lang, value: extension});
} }
charsets = undefined; charsets = undefined;
@ -617,51 +617,52 @@ specials = undefined;
*/ */
export function toGsm7(text, charset, extension, CRpad) { export function toGsm7(text, charset, extension, CRpad) {
if (!text) return []; if (!text) return [];
if (charset == 'Default') { if (charset === "Default") {
charset = CHARSET_OPTIONS[0].value; charset = CHARSET_OPTIONS[0].value;
} }
if (extension == 'Default') { if (extension === "Default") {
extension = EXTENSION_OPTIONS[0].value; extension = EXTENSION_OPTIONS[0].value;
} }
// step #1 : encoding with given charset and extension // step #1 : encoding with given charset and extension
let codePoints = []; const codePoints = [];
for (let char of text) { for (const char of text) {
let c = charset.indexOf(char); let c = charset.indexOf(char);
if (c==-1) { if (c===-1) {
c = extension.indexOf(char); c = extension.indexOf(char);
if (c==-1) { if (c===-1) {
throw new OperationError("character '" + char + "' is not present in current charset+extension.<br>" + throw new OperationError("character '" + char + "' is not present in current charset+extension.<br>" +
"A real device would encode this SMS using UCS-2 (UTF-16)"); "A real device would encode this SMS using UCS-2 (UTF-16)");
} }
codePoints.push(0x1b); codePoints.push(0x1b);
} }
codePoints.push(c); codePoints.push(c);
} }
// optional step #2: final CR to cope with unexpected encoding of 0x00 or to affirm a wanted final CR // optional step #2: final CR to cope with unexpected encoding of 0x00 or to affirm a wanted final CR
if (CRpad) { if (CRpad) {
if ((codePoints.length % 8 == 7) || ((codePoints.length % 8 == 0) && codePoints[codePoints.length-1] == 13)) { if ((codePoints.length % 8 === 7) || ((codePoints.length % 8 === 0) && codePoints[codePoints.length-1] === 13)) {
codePoints.push(13); codePoints.push(13);
} }
} }
// step #3: 7bit packing // step #3: 7bit packing
let sms = []; const sms = [];
let mod;
let previous;
for (let i = 0; i < codePoints.length; i++) { for (let i = 0; i < codePoints.length; i++) {
var previous; const c = codePoints[i];
let c = codePoints[i]; mod = i % 8;
var mod = i % 8; if (mod === 0) {
if (mod == 0) { previous = c;
previous = c; } else {
} else { const b = ((c << (8 - mod)) & 0xff) + previous;
let b = ((c << (8 - mod)) & 0xff) + previous; previous = c >> mod;
previous = c >> mod; sms.push(b);
sms.push(b) }
}
} }
if (mod != 7) { if (mod !== 7) {
sms.push(previous); sms.push(previous);
} }
return sms; return sms;
} }
@ -677,55 +678,55 @@ export function toGsm7(text, charset, extension, CRpad) {
* @returns {string} * @returns {string}
*/ */
export function fromGsm7(sms, charset, extension, CRpad) { export function fromGsm7(sms, charset, extension, CRpad) {
if (sms.length == 0) return ""; if (sms.length === 0) return "";
if (charset == 'Default') { if (charset === "Default") {
charset = CHARSET_OPTIONS[0].value; charset = CHARSET_OPTIONS[0].value;
} }
if (extension == 'Default') { if (extension === "Default") {
extension = EXTENSION_OPTIONS[0].value; extension = EXTENSION_OPTIONS[0].value;
} }
// step #1: 7bit unpacking // step #1: 7bit unpacking
let codePoints = []; const codePoints = [];
let previousBits = 0; let previousBits = 0;
for (let i = 0; i < sms.length; i++) { for (let i = 0; i < sms.length; i++) {
let b = sms[i]; const b = sms[i];
let mod = i % 7; const mod = i % 7;
let c = previousBits + ((b << mod) & 0x7f); let c = previousBits + ((b << mod) & 0x7f);
previousBits = b >> (7-mod); previousBits = b >> (7-mod);
codePoints.push(c); codePoints.push(c);
if (mod==6) { if (mod===6) {
c = previousBits; c = previousBits;
previousBits = 0; previousBits = 0;
codePoints.push(c); codePoints.push(c);
} }
} }
// optional step #2: remove final CR when on octet boundary // optional step #2: remove final CR when on octet boundary
if (CRpad) { if (CRpad) {
if ((codePoints.length % 8 == 0) && codePoints[codePoints.length-1] == 13) { if ((codePoints.length % 8 === 0) && codePoints[codePoints.length-1] === 13) {
codePoints.pop(); codePoints.pop();
} }
} }
// step #3: decoding with given charset and extension // step #3: decoding with given charset and extension
let text = []; const text = [];
let esc = false; let esc = false;
for (let c of codePoints) { for (const c of codePoints) {
if (esc) { if (esc) {
let char = extension[c]; let char = extension[c];
if (char=='\x00') { if (char === "\x00") {
char = charset[c]; char = charset[c];
} else if (char=='\x1b') { } else if (char === "\x1b") {
char = ' '; char = " ";
} }
text.push(char); text.push(char);
esc = false; esc = false;
} else if (c==0x1b) { } else if (c === 0x1b) {
esc = true; esc = true;
} else { } else {
text.push(charset[c]); text.push(charset[c]);
} }
} }
return text.join(""); return text.join("");
} }