TFS_ANTIGUO/SIGPC/hfda/HermesMsg.js
kledezma 290b81b54d SIGPC
git-tfs-id: [http://192.168.1.10:8080/tfs/AyA]$/SINORT;C518
2021-01-22 14:59:35 +00:00

1283 lines
No EOL
30 KiB
JavaScript

function HermesMsg(baseUrl)
{
// Estados del servicio
this.NoRegistrado = 0;
this.Registrando = 1;
this.Registrado = 2;
this.Respondiendo = 3;
// Estados del cliente
this.Desocupado = 0;
this.EnviandoMensaje = 1;
this.EsperandoRespuesta = 2;
// Tipos de mensajes
this.MensajeCliente = 0;
this.MensajeInicioSesion = 1;
this.MensajeEstablecerSesion = 2;
// Dirección base para los URLs que utiliza esta clase
this.baseUrl = baseUrl;
// Indica si hay un llamado ajax en curso
this.esperandoRespuesta = false;
// Identificador asignado a este servicio
this.servicioId = null;
// Estado del servicio
this.Estado = this.NoRegistrado;
// Estado del cliente
this.EstadoMensaje = this.Desocupado;
// Id del ultimo mensaje enviado
this.MensajeId = null;
// lista de mensajes
this.Mensajes = new Array();
// callback que se llama cuando hay un mensaje listo
this.MensajeListo = function () { };
// Este evento se llama cuando se detecta que el servicio se detuvo
this.ServicioDetenido = function () { };
// Este campo tiene la información de la sesión o null si no hay una sesion segura
this.sesion = null;
// Objeto que contiene la funcionalidad de encripción
this.subtle = null;
if (window.msrCrypto)
{
this.subtle = window.msrCrypto.subtle;
}
// Especifica el tipo de mensaje que se va a enviar
this.TipoMensaje = this.MensajeCliente;
// Contiene las llaves RSA del servicio
this.privateKey = null;
this.publicKeyJwk = null;
// Contiene las llaves de encripción de las sesiones
this.sesiones = new Array();
// Controla si se aceptan o no mensajes sin encripción
this.encryptionRequired = false;
}
HermesMsg.prototype.RegistrarServicio =
function (callback, callbackError)
{
if (this.Estado != this.NoRegistrado)
{
safeCallback(callbackError, "No está registrado");
return false;
}
this.Estado = this.Registrando;
var obj = this;
this.HacerSolicitud(
this.CreateUrl("servicio/CrearServicio"),
function (respuesta)
{
if (respuesta.Resultado)
{
obj.servicioId = respuesta.Datos;
obj.Estado = obj.Registrado;
safeCallback(callback);
// Iniciar timer para revisar mensajes para el servicio
obj.PonerTimeoutRevisionMensajesPendientes();
// Crear las llaves RSA y exportar la llave publica
var crypto = window.crypto || window.msCrypto;
var subtle = crypto.subtle || crypto.webkitSubtle;
var keySetupFailedCallback =
function()
{
obj.privateKey = null;
obj.publicKeyJwk = null;
}
if (crypto != null) {
var result = subtle.generateKey(
{
name: "RSA-OAEP",
modulusLength: 2048, //can be 1024, 2048, or 4096
publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
hash: { name: "SHA-256" }
},
true, //whether the key is extractable (i.e. can be used in exportKey)
["encrypt", "decrypt"] //must contain both "encrypt" and "decrypt"
);
CryptoCall(
result,
function (rsaKeys) {
// Exportar la llave publica
result = subtle.exportKey(
"jwk",
rsaKeys.publicKey
);
CryptoCall(
result,
function (publicKeyJwk) {
// Convertir publicKeyJwk a string y guardarlo en el campo del mismo nombre. Si es necesario convertirlo a JSON (IE)
if (GetType(publicKeyJwk) != "ArrayBuffer") {
obj.publicKeyJwk = JSON.stringify(publicKeyJwk);
}
else {
// IE retorna un ArrayBuffer
var s = "";
var bytes = new Int8Array(publicKeyJwk);
for (var i = 0; i < bytes.length; i++) {
if (bytes[i] == 0) //IE agrega un 0 al final
{
continue;
}
s += String.fromCharCode(bytes[i]);
}
obj.publicKeyJwk = s;
}
// Exportar la llave privada
result = subtle.exportKey(
"jwk",
rsaKeys.privateKey
);
CryptoCall(
result,
function (privateKeyJwk) {
// IE retorna un ArrayBuffer
if (GetType(privateKeyJwk) != "ArrayBuffer") {
privateKeyJwk = JSON.stringify(privateKeyJwk);
}
result = obj.subtle.importKey(
"jwk",
toSupportedArray(privateKeyJwk),
{ name: "RSAES-PKCS1-v1_5" },
true,
["decrypt"]
);
CryptoCall(
result,
function (privateKey) {
obj.privateKey = privateKey;
},
keySetupFailedCallback
);
},
keySetupFailedCallback
);
},
keySetupFailedCallback
);
},
keySetupFailedCallback
);
}
}
else
{
obj.servicioId = null;
obj.Estado = obj.NoRegistrado;
safeCallback(callbackError, respuesta.Error);
}
},
function (error)
{
obj.Estado = obj.NoRegistrado;
safeCallback(callbackError,error);
}
);
return true;
}
HermesMsg.prototype.HacerSolicitud =
function (url, callback, errorCallback, mensaje)
{
this.esperandoRespuesta = true;
var obj = this;
// Convertir el objeto mensaje en una hilera en formato form-data
var postData = "";
if (mensaje != null)
{
for(var key in mensaje)
{
postData += key + "=" + encodeURIComponent(mensaje[key]) + "&";
}
if (postData.length>0 && postData[postData.length-1] == "&")
{
postData = postData.substr(0, postData.length - 1);
}
}
var result =
$.ajax(
{
type: "POST",
url: url,
data: postData,
dataType: "json",
async: true,
cache: false,
error:
function (error)
{
obj.esperandoRespuesta = false;
safeCallback(errorCallback,error);
},
success:
function (respuesta)
{
obj.esperandoRespuesta = false;
safeCallback(callback,respuesta);
}
}
);
return true;
}
HermesMsg.prototype.ServicioId =
function ()
{
return this.servicioId;
}
HermesMsg.prototype.CreateUrl =
function (urlPart) {
var url = this.baseUrl;
if (url.length == 0 || url[url.length - 1] != '/') {
url += "/";
}
url += urlPart;
return url;
}
HermesMsg.prototype.EnviarMensaje =
function(servicioId, contenido, callback, callbackError)
{
if (this.EstadoMensaje != this.Desocupado)
{
return false;
}
this.EstadoMensaje = this.EnviandoMensaje;
var obj = this;
var mensaje = { contenido: contenido, tipo: this.TipoMensaje };
// Si se establecio una sesión hay que encriptar el mensaje
if (this.sesion != null && this.sesion.idSesion != null)
{
// Encriptar el mensaje
var result = obj.subtle.encrypt(
{ name: "AES-CBC", iv: this.sesion.iv },
this.sesion.aesKey,
toSupportedArray(JSON.stringify(contenido))
);
CryptoCall(
result,
function (cipherText) {
mensaje = { contenido: _arrayBufferToBase64(cipherText), tipo: obj.TipoMensaje, sesion: obj.sesion.idSesion };
obj.EnviarMensajeInterno(servicioId, mensaje, callback, callbackError);
},
function (error)
{
obj.Estado = obj.Desocupado;
safeCallback(callbackError, error);
}
);
}
else
{
this.EnviarMensajeInterno(servicioId, mensaje, callback, callbackError);
}
}
HermesMsg.prototype.EnviarMensajeInterno =
function (servicioId, mensaje, callback, callbackError)
{
var obj = this;
var result = this.HacerSolicitud(
this.CreateUrl("servicio/EnviarMensaje"),
function (respuesta) {
if (respuesta.Resultado) {
obj.EstadoMensaje = obj.EsperandoRespuesta;
var mensajeId = respuesta.Datos.Id;
// Monitorear constantemente para ver si ya está lista la respuesta
window.setTimeout(
function () {
obj.RevisarRespuesta(servicioId, mensajeId, callback, callbackError);
},
1000
);
}
else {
deleteFromCache("Sesion");
obj.EstadoMensaje = obj.Desocupado;
safeCallback(callbackError, respuesta.Error);
}
},
function (error) {
deleteFromCache("Sesion");
obj.Estado = obj.Desocupado;
safeCallback(callbackError, error);
},
{ servicioId: servicioId, contenido: JSON.stringify(mensaje) }
);
}
HermesMsg.prototype.RevisarRespuesta =
function (servicioId, mensajeId, callback, callbackError)
{
var obj = this;
var result = this.HacerSolicitud(
this.CreateUrl("servicio/RecibirRespuesta"),
function (respuesta) {
if (respuesta.Resultado) {
if(respuesta.Datos != null)
{
// Esto significa que la respuesta del mensaje esta lista
window.clearInterval(obj.intervalId);
obj.EstadoMensaje = obj.Desocupado;
// Si han una sesión entonces se debe desencriptar el mensaje
if (obj.sesion != null && obj.sesion.idSesion != null) {
// Desencriptar el mensaje
var result = obj.subtle.decrypt(
{ name: "AES-CBC", iv: toSupportedArray(obj.sesion.iv) },
obj.sesion.aesKey,
toSupportedArray(_base64ToArrayBuffer(respuesta.Datos))
);
CryptoCall(
result,
function (plainText)
{
var s = "";
var bytes = new Int8Array(plainText);
for (var i = 0; i < bytes.length; i++) {
if (bytes[i] == 0) //IE agrega un 0 al final
{
continue;
}
s += String.fromCharCode(bytes[i]);
}
var mensaje = JSON.parse(s);
safeCallback(callback, mensaje.contenido);
},
function ()
{
safeCallback(callbackError);
}
);
}
else {
var mensaje = JSON.parse(respuesta.Datos);
safeCallback(callback, mensaje.contenido);
}
}
else
{
// La respuesta no está lista, volver a ejecutar timeout
window.setTimeout(
function () {
obj.RevisarRespuesta(servicioId, mensajeId, callback, callbackError);
},
1000
);
}
}
else {
// Esto significa que el mensaje no existe
deleteFromCache("Sesion");
obj.EstadoMensaje = obj.Desocupado;
safeCallback(callbackError);
}
},
function (error) {
// Esto es un error técnico, por lo que no se cancela el timer
window.setTimeout(
function () {
obj.RevisarRespuesta(servicioId, mensajeId, callback, callbackError);
},
1000
);
},
{servicioId : servicioId, mensajeId : mensajeId}
);
}
HermesMsg.prototype.ProcesarMensajesPendientes =
function ()
{
var obj = this;
var result = this.HacerSolicitud(
this.CreateUrl("servicio/MensajesPendientes"),
function (respuesta) {
obj.PonerTimeoutRevisionMensajesPendientes();
if (respuesta.Resultado) {
// Procesar los mensajes recibidos
var mensajesCliente = new Array();
for (var i = 0; i < respuesta.Datos.length; i++)
{
respuesta.Datos[i]._Respuesta = null; // Significa que el mensaje todavia no tiene una respuesta
var mensaje = JSON.parse(respuesta.Datos[i].Mensaje);
if (mensaje.tipo == obj.MensajeInicioSesion) {
var mensajeActual = respuesta.Datos[i];
// Se debe responder con la llave publica del servicio
var mensaje2 = { contenido: obj.publicKeyJwk };
// Enviar la respuesta del mensaje
obj.HacerSolicitud(
obj.CreateUrl("servicio/EnviarRespuesta"),
function (respuesta) {
// No hay nada que hacer, el mensaje sale de la lista de pendientes
},
function (error) {
// En este caso no se responde y el cliente debe reintentar
},
{ servicioId: obj.servicioId, mensajeId: mensajeActual.Id, contenido: JSON.stringify(mensaje2) }
);
}
else if (mensaje.tipo == obj.MensajeEstablecerSesion)
{
var mensajeActual = respuesta.Datos[i];
// Desencriptar la llave AES y el vector iv y guardarla en Sesiones
var encryptedKey = _base64ToArrayBuffer(mensaje.contenido);
// Si se produce un error se retorna -1 al cliente
var errorCallback =
function ()
{
obj.HacerSolicitud(
obj.CreateUrl("servicio/EnviarRespuesta"),
function (respuesta) {},
function (error) {},
{ servicioId: obj.servicioId, mensajeId: mensajeActual.Id, contenido: JSON.stringify({contenido:-1}) }
);
};
try
{
var result = obj.subtle.decrypt(
{ name: "RSAES-PKCS1-v1_5" },
obj.privateKey,
toSupportedArray(encryptedKey)
);
CryptoCall(
result,
function (aesKeyIvBytes) {
// Separar la llave AES y el vector IV
var aesKeyIvBytes8 = new Uint8Array(aesKeyIvBytes);
var aesKeyBytes = new Uint8Array(aesKeyIvBytes8.length - 16);
var iv = new Uint8Array(16);
for (var i = 0; i < aesKeyBytes.length; i++)
{
aesKeyBytes[i] = aesKeyIvBytes8[i];
}
for (var i = 0; i < iv.length; i++)
{
iv[i] = aesKeyIvBytes8[i + aesKeyBytes.length];
}
// Importar la llave AES
var result = obj.subtle.importKey(
"raw",
toSupportedArray(aesKeyBytes),
{
name: "AES-CBC",
length: 256, //can be 128, 192, or 256
},
true,
["encrypt", "decrypt"]
);
CryptoCall(
result,
function (aesKey) {
// Incluir la llave AES y el vector IV en la lista de sesiones y retornar
// el numero de sesion al cliente
obj.sesiones.push({ aesKey: aesKey, iv: iv });
obj.HacerSolicitud(
obj.CreateUrl("servicio/EnviarRespuesta"),
function (respuesta) {},
function (error) { },
{ servicioId: obj.servicioId, mensajeId: mensajeActual.Id, contenido: JSON.stringify({ contenido: obj.sesiones.length }) }
);
},
errorCallback
);
},
errorCallback
);
}
catch(e)
{
errorCallback();
}
}
else if (mensaje.tipo == obj.MensajeCliente) {
var mensajeActual = respuesta.Datos[i];
// Si el mensaje está encriptado es necesario desencriptarlo
if (mensaje.sesion != null) {
// esto permite identificar que la respuesta del mensaje debe encriptarse
mensajeActual.sesion = mensaje.sesion;
// Desencriptar el mensaje
var iv = obj.sesiones[mensaje.sesion-1].iv;
var aesKey = obj.sesiones[mensaje.sesion-1].aesKey;
var result = obj.subtle.decrypt(
{ name: "AES-CBC", iv: toSupportedArray(iv) },
aesKey,
toSupportedArray(_base64ToArrayBuffer(mensaje.contenido))
);
CryptoCall(
result,
function (plainText)
{
// Convertir los bytes a una hilera
var s = "";
var bytes = new Int8Array(plainText);
for (var i = 0; i < bytes.length; i++) {
if (bytes[i] == 0) //IE agrega un 0 al final
{
continue;
}
s += String.fromCharCode(bytes[i]);
}
mensajeActual.Mensaje = JSON.parse(s);
obj.Mensajes.push(mensajeActual);
try {
obj.MensajeListo(mensajeActual);
}
catch (e) {
}
},
function () {}
);
}
else {
// Si se requiere encripción entonces se debe rechazar el mensaje sin encriptar
if (obj.encryptionRequired)
{
mensajeActual._Respuesta = "Mensaje rechazado porque no está encriptado";
obj.Mensajes.push(mensajeActual);
}
else
{
mensajeActual.Mensaje = mensaje.contenido;
obj.Mensajes.push(mensajeActual);
mensajesCliente.push(mensajeActual);
}
}
}
}
// Notificar que se recibieron nuevos mensajes
if (obj.MensajeListo != null && mensajesCliente.length > 0)
{
try
{
obj.MensajeListo(mensajesCliente[0]);
}
catch(e)
{
}
}
// Enviar las respuestas pendientes de enviar
if (obj.Mensajes.length > 0)
{
obj.EnviarRespuestasPendientes();
}
}
else {
// Esto significa que el servicio esta inactivo o no existe
obj.Estado = obj.NoRegistrado;
safeCallback(obj.ServicioDetenido);
}
},
function (error) {
// Esto es un error técnico, por lo que no se cancela el timer
obj.PonerTimeoutRevisionMensajesPendientes();
},
{ servicioId: this.servicioId }
);
}
HermesMsg.prototype.ResponderMensaje =
function(mensaje, respuesta)
{
// Asegurarse que el servicio esté registrado
if (this.Estado != this.Registrado) {
safeCallback(callbackError, "Estado invalido");
return false;
}
mensaje._Respuesta = respuesta;
this.EnviarRespuestasPendientes();
}
HermesMsg.prototype.EnviarRespuestasPendientes =
function()
{
// Si estamos en medio de una solicitud Ajax entonces esperar
if (this.esperandoRespuesta)
{
return;
}
// Buscar el primer mensaje pendiente
var pendientes = new Array(); // al final del ciclo contendrá los mensajes pendientes
var mensaje = null; // al final del ciclo tendrá el mensaje que se va a responder
var obj = this;
for (var i = 0; i < this.Mensajes.length; i++ )
{
// Si el mensaje actual no tiene una respuesta entonces
// introducirlo en la lista de pendientes
if (this.Mensajes[i]._Respuesta == null || mensaje != null)
{
pendientes.push(this.Mensajes[i]);
continue;
}
mensaje = this.Mensajes[i];
}
// Enviar el mensaje pendiente que se encontro
if (mensaje != null)
{
this.Mensajes = pendientes;
var mensaje2 = { contenido: mensaje._Respuesta };
// Si hay una sesión es necesaro encriptar la respuesta
if (mensaje.sesion != null) {
var iv = obj.sesiones[mensaje.sesion - 1].iv;
var aesKey = obj.sesiones[mensaje.sesion - 1].aesKey;
var result = obj.subtle.encrypt(
{ name: "AES-CBC", iv: toSupportedArray(iv) },
aesKey,
toSupportedArray(JSON.stringify(mensaje2))
);
CryptoCall(
result,
function (encrypted)
{
// Enviar la respuesta del mensaje
obj.HacerSolicitud(
obj.CreateUrl("servicio/EnviarRespuesta"),
function (respuesta) {
// No hay nada que hacer, el mensaje sale de la lista de pendientes
},
function (error) {
// Si hay un error tecnico el mensaje vuelve a la lista de pendientes
obj.Mensajes.push(mensaje);
},
{ servicioId: obj.servicioId, mensajeId: mensaje.Id, contenido: _arrayBufferToBase64(encrypted) }
);
},
function (error) {
// Si hay un error tecnico el mensaje vuelve a la lista de pendientes
obj.Mensajes.push(mensaje);
}
);
}
else {
// Enviar la respuesta del mensaje
this.HacerSolicitud(
this.CreateUrl("servicio/EnviarRespuesta"),
function (respuesta) {
// No hay nada que hacer, el mensaje sale de la lista de pendientes
},
function (error) {
// Si hay un error tecnico el mensaje vuelve a la lista de pendientes
obj.Mensajes.push(mensaje);
},
{ servicioId: this.servicioId, mensajeId: mensaje.Id, contenido: JSON.stringify(mensaje2) }
);
}
}
}
HermesMsg.prototype.DetenerServicio =
function (callback, callbackError) {
// No se puede detener si no está registrado
if (this.Estado != this.Registrado) {
safeCallback(callbackError,"Estado invalido");
return false;
}
var obj = this;
this.HacerSolicitud(
this.CreateUrl("servicio/DetenerServicio"),
function (respuesta) {
obj.servicioId = null;
obj.Estado = obj.NoRegistrado;
safeCallback(callback);
},
function (error) {
safeCallback(callbackError,error);
},
{ servicioId: this.servicioId }
);
return true;
}
HermesMsg.prototype.IniciarSesion =
function (servicioId, callback, callbackError) {
// Verificar que se haya incluido la libreria msrCrypto
if (!this.subtle)
{
return false;
}
if (this.sesion != null)
{
return false;
}
var obj = this;
// Tratar de recuperar la sesion del cache
var sesion = getFromCache("Sesion");
if (sesion != null)
{
var keyData8 = new Uint8Array(_base64ToArrayBuffer(sesion.keyData));
var result = obj.subtle.importKey(
"raw",
toSupportedArray(keyData8),
{
name: "AES-CBC",
length: 256, //can be 128, 192, or 256
},
true,
["encrypt", "decrypt"]
);
CryptoCall(
result,
function (aesKey) {
obj.sesion = sesion.sesion;
obj.sesion.aesKey = aesKey;
obj.sesion.iv = new Uint8Array(_base64ToArrayBuffer(sesion.iv));
safeCallback(callback);
},
callbackError
);
return;
}
// Solicitar al servicio que inicie una sesión segura
this.TipoMensaje = this.MensajeInicioSesion;
// Si se produce un error este callback pone el campo sesion en null
// para establecer que no hay una sesión
var callbackError2 =
function (error)
{
obj.TipoMensaje = obj.MensajeCliente;
obj.sesion = null;
safeCallback(callbackError, error);
}
this.EnviarMensaje(
servicioId,
"",
function(respuesta)
{
obj.TipoMensaje = obj.MensajeCliente;
// Si respuesta es vacio significa que hubo un error del
// lado del servidor
if (respuesta == null || respuesta == "")
{
callbackError2();
return;
}
obj.sesion = { publicKeyJwk: respuesta, idSesion:null };
// Importar la llave RSA recibida del servicio
var result = obj.subtle.importKey(
"jwk",
toSupportedArray(obj.sesion.publicKeyJwk),
{ name: "RSAES-PKCS1-v1_5" },
true,
["encrypt"]
);
CryptoCall(
result,
function (publicKey) {
// Generar la llave AES
var result = obj.subtle.generateKey(
{
name: "AES-CBC",
length: 256, //can be 128, 192, or 256
},
true, //whether the key is extractable (i.e. can be used in exportKey)
["encrypt", "decrypt"] //can be any combination of "encrypt" and "decrypt"
);
CryptoCall(
result,
function (aeskey) {
// Es necesario guardar la llave de encripción para encryptar los mensajes
// posteriores
obj.sesion.aesKey = aeskey;
// Exportar la llave AES para poder encriptarla luego con la llave publica del servicio
result = obj.subtle.exportKey(
"raw",
aeskey
);
CryptoCall(
result,
function (keyData) {
// Generar el vector IV para randomizar los paquetes encriptados
obj.sesion.iv = window.msrCrypto.getRandomValues(new Uint8Array(16));
// Crear un solo vector (textoPlano) que incluya la clave AES y el vector IV
// para su posterior encripción. El objetivo es hace una solo operación de encripción
// en lugar de dos, para disminuir el tiempo de ejecución
var keyData8 = new Uint8Array(keyData);
var textoPlano = new Uint8Array(keyData8.length + obj.sesion.iv.length);
for (i = 0; i < keyData8.length; i++)
{
textoPlano[i] = keyData8[i];
}
for (i = 0; i < obj.sesion.iv.length; i++)
{
textoPlano[keyData8.length+i] = obj.sesion.iv[i];
}
// Encriptar la llave AES + el vector IV
result = obj.subtle.encrypt(
{ name: "RSAES-PKCS1-v1_5" },
publicKey,
toSupportedArray(textoPlano)
);
CryptoCall(
result,
function (encryptedKeyData) {
// Enviar la llave AES y el IV encriptada al servicio
obj.TipoMensaje = obj.MensajeEstablecerSesion;
var ivAndAes =_arrayBufferToBase64(encryptedKeyData);
obj.EnviarMensaje(
servicioId,
ivAndAes,
function (respuesta) {
// Si respuesta es < 0 significa que se produjo un error
if (respuesta == null || respuesta < 0) {
callbackError2();
return;
}
obj.TipoMensaje = obj.MensajeCliente;
obj.sesion.idSesion = respuesta
addToCache(
"Sesion",
{ sesion: obj.sesion, keyData: _arrayBufferToBase64(keyData), iv: _arrayBufferToBase64(obj.sesion.iv.buffer) }
);
safeCallback(callback);
},
callbackError2
);
},
callbackError2
);
}
);
},
callbackError2
);
},
callbackError2
);
},
function()
{
obj.TipoMensaje = obj.MensajeCliente;
callbackError2();
}
);
return true;
}
HermesMsg.prototype.PonerTimeoutRevisionMensajesPendientes =
function () {
var obj = this;
window.setTimeout(
function () {
obj.ProcesarMensajesPendientes();
},
1000
);
}
function safeCallback(callback, param) {
if (callback == null) {
return;
}
try {
callback(param);
}
catch (e) {
}
}
function toSupportedArray(data) {
// does this browser support Typed Arrays?
var typedArraySupport = (typeof Uint8Array !== "undefined");
// get the data type of the parameter
var dataType = Object.prototype.toString.call(data);
dataType = dataType.substring(8, dataType.length - 1);
// determine the type
switch (dataType) {
// Regular JavaScript Array. Convert to Uint8Array if supported
// else do nothing and return the array
case "Array":
return typedArraySupport ? new Uint8Array(data) : data;
// ArrayBuffer. IE11 Web Crypto API returns ArrayBuffers that you have to convert
// to Typed Arrays. Convert to a Uint8Arrays and return;
case "ArrayBuffer":
return new Uint8Array(data);
// Already Uint8Array. Obviously there is support.
case "Uint8Array":
return data;
case "Uint16Array":
case "Uint32Array":
return new Uint8Array(data);
// String. Convert the string to a byte array using Typed Arrays if
// supported.
case "String":
var newArray = typedArraySupport ? new Uint8Array(data.length) : new Array(data.length);
for (var i = 0; i < data.length; i += 1) {
newArray[i] = data.charCodeAt(i);
}
return newArray;
// Some other type. Just return the data unchanged.
default:
throw new Error("toSupportedArray : unsupported data type " + dataType);
}
}
function CryptoCall(result, successCallback, errorCallback) {
if (result.then == null) {
result.oncomplete =
function () {
successCallback(result.result);
};
result.onerror =
function (err) {
errorCallback(err);
}
}
else {
result.then(successCallback).catch(errorCallback);
}
}
function _arrayBufferToBase64(buffer) {
var binary = '';
var bytes = new Uint8Array(buffer);
var len = bytes.byteLength;
for (var i = 0; i < len; i++) {
binary += String.fromCharCode(bytes[i]);
}
return window.btoa(binary);
}
function _base64ToArrayBuffer(base64) {
var binary_string = window.atob(base64);
var len = binary_string.length;
var bytes = new Uint8Array(len);
for (var i = 0; i < len; i++) {
bytes[i] = binary_string.charCodeAt(i);
}
return bytes.buffer;
}
function GetType(data) {
// get the data type of the parameter
var dataType = Object.prototype.toString.call(data);
dataType = dataType.substring(8, dataType.length - 1);
return dataType;
}
function addToCache(name,value)
{
if (typeof(window.localStorage)=="undefined")
{
return;
}
// Los items del cache expiran cada 2 horas
window.localStorage.setItem(name, JSON.stringify({ value: value, expiration: (new Date()).getTime() + 7200000 }));
}
function getFromCache(name)
{
if (typeof (window.localStorage) == "undefined") {
return null;
}
var result = window.localStorage.getItem(name);
if (result == null)
{
return null;
}
result = JSON.parse(result);
// Si ya expiró la entrada del cache entonces borrarla
if (result.expiration < (new Date()).getTime())
{
window.localStorage.removeItem(name);
return null;
}
return result.value;
}
function deleteFromCache(name)
{
if (typeof (window.localStorage) == "undefined") {
return;
}
window.localStorage.removeItem(name);
}