@seydx/tr064
Advanced tools
Comparing version 0.4.1-2 to 0.4.1-3
{ | ||
"name": "@seydx/tr064", | ||
"version": "0.4.1-2", | ||
"version": "0.4.1-3", | ||
"author": "Nicolai Schmid <hey@schmid.uno>", | ||
@@ -5,0 +5,0 @@ "description": "TR-064 - UPnP/IGD for node.js", |
@@ -1,180 +0,180 @@ | ||
const async = require("async"); | ||
const crypto = require("crypto"); | ||
const s = require("./Service"); | ||
const async = require('async'); | ||
const crypto = require('crypto'); | ||
const s = require('./Service'); | ||
class Device { | ||
constructor(deviceInfo, config){ | ||
this.config = config; | ||
this.meta = deviceInfo; | ||
this.meta.servicesInfo = []; | ||
this.services = {}; | ||
this._isTransaction = false; | ||
this._parseServices(); | ||
this._sslPort = null; | ||
this._auth = { | ||
uid: null, | ||
realm: "F!Box SOAP-Auth", | ||
chCount: 0, | ||
}; | ||
} | ||
constructor(deviceInfo, config){ | ||
this.config = config; | ||
this.meta = deviceInfo; | ||
this.meta.servicesInfo = []; | ||
this.services = {}; | ||
this._isTransaction = false; | ||
this._parseServices(); | ||
this._sslPort = null; | ||
this._auth = { | ||
uid: null, | ||
realm: 'F!Box SOAP-Auth', | ||
chCount: 0, | ||
}; | ||
} | ||
login(user, password){ | ||
if (password === undefined) { | ||
this._auth.uid = "DefaultUser"; | ||
this._auth.pwd = user; | ||
} else { | ||
this._auth.uid = user; | ||
this._auth.pwd = password; | ||
} | ||
} | ||
login(user, password){ | ||
if (password === undefined) { | ||
this._auth.uid = 'DefaultUser'; | ||
this._auth.pwd = user; | ||
} else { | ||
this._auth.uid = user; | ||
this._auth.pwd = password; | ||
} | ||
} | ||
logout(){ | ||
this._auth.uid = null; | ||
this._auth.pwd = null; | ||
this._auth.chCount = 0; | ||
} | ||
logout(){ | ||
this._auth.uid = null; | ||
this._auth.pwd = null; | ||
this._auth.chCount = 0; | ||
} | ||
startTransaction(cb){ | ||
var that = this; | ||
var sessionID = this.uuid(); | ||
this._startTransaction(sessionID, function(err) { | ||
if (!err) { | ||
that._isTransaction = true; | ||
cb(null, that); | ||
} else { | ||
cb(err, null); | ||
} | ||
}); | ||
} | ||
startTransaction(cb){ | ||
var that = this; | ||
var sessionID = this.uuid(); | ||
this._startTransaction(sessionID, function(err) { | ||
if (!err) { | ||
that._isTransaction = true; | ||
cb(null, that); | ||
} else { | ||
cb(err, null); | ||
} | ||
}); | ||
} | ||
stopTransaction(cb){ | ||
var that = this; | ||
this._stopTransaction(function(err) { | ||
if (!err) { | ||
that._isTransaction = false; | ||
cb(null, that); | ||
} else { | ||
cb(err, null); | ||
} | ||
}); | ||
} | ||
stopTransaction(cb){ | ||
var that = this; | ||
this._stopTransaction(function(err) { | ||
if (!err) { | ||
that._isTransaction = false; | ||
cb(null, that); | ||
} else { | ||
cb(err, null); | ||
} | ||
}); | ||
} | ||
startEncryptedCommunication(){ | ||
const self=this; | ||
startEncryptedCommunication(){ | ||
const self=this; | ||
return new Promise(function(resolve, reject){ | ||
return new Promise(function(resolve, reject){ | ||
self._getSSLPort(function(err, port) { | ||
if (!err) { | ||
self._sslPort = port; | ||
resolve(self); | ||
} else { | ||
reject(err); | ||
} | ||
}); | ||
self._getSSLPort(function(err, port) { | ||
if (!err) { | ||
self._sslPort = port; | ||
resolve(self); | ||
} else { | ||
reject(err); | ||
} | ||
}); | ||
}); | ||
} | ||
}); | ||
} | ||
stopEncryptedCommunication(){ | ||
this._sslPort = null; | ||
} | ||
stopEncryptedCommunication(){ | ||
this._sslPort = null; | ||
} | ||
getServicesFromDevice(serviceArray, device){ | ||
const self = this; | ||
serviceArray = serviceArray.concat(device.serviceList.service); | ||
if (device.deviceList && Array.isArray(device.deviceList.device)) { | ||
device.deviceList.device.forEach(function(dev) { | ||
serviceArray = self.getServicesFromDevice(serviceArray, dev); | ||
}); | ||
} else if (device.deviceList && device.deviceList.device) { | ||
serviceArray = self.getServicesFromDevice(serviceArray, device.deviceList.device); | ||
} | ||
return serviceArray; | ||
} | ||
getServicesFromDevice(serviceArray, device){ | ||
const self = this; | ||
serviceArray = serviceArray.concat(device.serviceList.service); | ||
if (device.deviceList && Array.isArray(device.deviceList.device)) { | ||
device.deviceList.device.forEach(function(dev) { | ||
serviceArray = self.getServicesFromDevice(serviceArray, dev); | ||
}); | ||
} else if (device.deviceList && device.deviceList.device) { | ||
serviceArray = self.getServicesFromDevice(serviceArray, device.deviceList.device); | ||
} | ||
return serviceArray; | ||
} | ||
_parseServices(){ | ||
const self = this; | ||
var serviceArray = self.getServicesFromDevice([], this.meta); | ||
var asyncAddService = self._addService.bind(this); | ||
_parseServices(){ | ||
const self = this; | ||
var serviceArray = self.getServicesFromDevice([], this.meta); | ||
var asyncAddService = self._addService.bind(this); | ||
return new Promise(function(resolve, reject){ | ||
return new Promise(function(resolve, reject){ | ||
async.concat(serviceArray, asyncAddService, function(err, results){ | ||
if(!err){ | ||
for (var i in results) { | ||
var service = results[i]; | ||
self.services[service.meta.serviceType] = service; | ||
self.meta.servicesInfo.push(service.meta.serviceType); | ||
} | ||
delete self.meta.deviceList; | ||
delete self.meta.serviceList; | ||
resolve(self); | ||
} else { | ||
reject(err); | ||
} | ||
}); | ||
async.concat(serviceArray, asyncAddService, function(err, results){ | ||
if(!err){ | ||
for (var i in results) { | ||
var service = results[i]; | ||
self.services[service.meta.serviceType] = service; | ||
self.meta.servicesInfo.push(service.meta.serviceType); | ||
} | ||
delete self.meta.deviceList; | ||
delete self.meta.serviceList; | ||
resolve(self); | ||
} else { | ||
reject(err); | ||
} | ||
}); | ||
}); | ||
}); | ||
} | ||
} | ||
_addService(serviceData, callback){ | ||
const self = this; | ||
new s.Service(this, serviceData, self.config, callback); | ||
} | ||
_addService(serviceData, callback){ | ||
const self = this; | ||
new s.Service(this, serviceData, self.config, callback); | ||
} | ||
_getSSLPort(cb){ | ||
var devInfo = this.services["urn:dslforum-org:service:DeviceInfo:1"]; | ||
devInfo.actions.GetSecurityPort(function(err, result) { | ||
if (!err) { | ||
var sslPort = parseInt(result.NewSecurityPort); | ||
if (typeof sslPort === "number" && isFinite(sslPort)) { | ||
cb(null, sslPort); | ||
} else { | ||
cb(new Error("Got bad port from Device. Port:" + result.NewSecurityPort)); | ||
} | ||
} else { | ||
cb(new Error("Encription is not supported for this device.")); | ||
} | ||
}); | ||
} | ||
_getSSLPort(cb){ | ||
var devInfo = this.services['urn:dslforum-org:service:DeviceInfo:1']; | ||
devInfo.actions.GetSecurityPort(function(err, result) { | ||
if (!err) { | ||
var sslPort = parseInt(result.NewSecurityPort); | ||
if (typeof sslPort === 'number' && isFinite(sslPort)) { | ||
cb(null, sslPort); | ||
} else { | ||
cb(new Error('Got bad port from Device. Port:' + result.NewSecurityPort)); | ||
} | ||
} else { | ||
cb(new Error('Encription is not supported for this device.')); | ||
} | ||
}); | ||
} | ||
_calcAuthDigest(uid, pwd, realm, sn){ | ||
var MD5 = crypto.createHash("md5"); | ||
MD5.update(uid + ":" + realm + ":" + pwd); | ||
var secret = MD5.digest("hex"); | ||
MD5 = crypto.createHash("md5"); | ||
MD5.update(secret + ":" + sn); | ||
return MD5.digest("hex"); | ||
} | ||
_calcAuthDigest(uid, pwd, realm, sn){ | ||
var MD5 = crypto.createHash('md5'); | ||
MD5.update(uid + ':' + realm + ':' + pwd); | ||
var secret = MD5.digest('hex'); | ||
MD5 = crypto.createHash('md5'); | ||
MD5.update(secret + ':' + sn); | ||
return MD5.digest('hex'); | ||
} | ||
_startTransaction(sessionID, cb){ | ||
var devConfig = this.services["urn:dslforum-org:service:DeviceConfig:1"]; | ||
devConfig.actions.ConfigurationStarted({ NewSessionID: sessionID }, function(err) { | ||
if (!err) { | ||
cb(null); | ||
} else { | ||
cb(new Error("Transactions are not supported for this device.")); | ||
} | ||
}); | ||
} | ||
_startTransaction(sessionID, cb){ | ||
var devConfig = this.services['urn:dslforum-org:service:DeviceConfig:1']; | ||
devConfig.actions.ConfigurationStarted({ NewSessionID: sessionID }, function(err) { | ||
if (!err) { | ||
cb(null); | ||
} else { | ||
cb(new Error('Transactions are not supported for this device.')); | ||
} | ||
}); | ||
} | ||
_stopTransaction(cb){ | ||
var devConfig = this.services["urn:dslforum-org:service:DeviceConfig:1"]; | ||
devConfig.actions.ConfigurationFinished(function(err) { | ||
if (!err) { | ||
cb(null); | ||
} else { | ||
cb(new Error("Transactions are not supported for this device.")); | ||
} | ||
}); | ||
} | ||
_stopTransaction(cb){ | ||
var devConfig = this.services['urn:dslforum-org:service:DeviceConfig:1']; | ||
devConfig.actions.ConfigurationFinished(function(err) { | ||
if (!err) { | ||
cb(null); | ||
} else { | ||
cb(new Error('Transactions are not supported for this device.')); | ||
} | ||
}); | ||
} | ||
uuid(a){ | ||
const self = this; | ||
return a ? ( a ^ ((Math.random() * 16) >> (a / 4))).toString(16):([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g,self.uuid); | ||
} | ||
uuid(a){ | ||
const self = this; | ||
return a ? ( a ^ ((Math.random() * 16) >> (a / 4))).toString(16):([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g,self.uuid); | ||
} | ||
} | ||
exports.Device = Device; |
121
src/index.js
@@ -1,70 +0,67 @@ | ||
const parseString = require("xml2js").parseString; | ||
const request = require("request"); | ||
const URL = require("url"); | ||
const parseString = require('xml2js').parseString; | ||
const request = require('request'); | ||
const URL = require('url'); | ||
const TR064_DESC_URL = '/tr64desc.xml'; | ||
const IGD_DESC_URL = '/igddesc.xml'; | ||
const PMR_DESC_URL = '/pmr/PersonalMessageReceiver.xml'; | ||
const d = require('./Device'); | ||
const TR064_DESC_URL = "/tr64desc.xml"; | ||
const IGD_DESC_URL = "/igddesc.xml"; | ||
const PMR_DESC_URL = "/pmr/PersonalMessageReceiver.xml"; | ||
class TR064 { | ||
constructor(config){ | ||
this.host = config.host; | ||
this.port = config.port; | ||
this.username = config.username; | ||
this.password = config.password; | ||
this.config = config; | ||
} | ||
const d = require("./Device"); | ||
initDevice(type){ | ||
const self = this; | ||
let url; | ||
class TR064 { | ||
constructor(config){ | ||
this.host = config.host; | ||
this.port = config.port; | ||
this.username = config.username; | ||
this.password = config.password; | ||
this.config = config; | ||
} | ||
initDevice(type){ | ||
const self = this; | ||
let url; | ||
switch(type){ | ||
case "TR064": | ||
url = TR064_DESC_URL; | ||
break; | ||
case "IGD": | ||
url = IGD_DESC_URL; | ||
break; | ||
case "PMR": | ||
url = PMR_DESC_URL; | ||
break; | ||
} | ||
const nurl = "http://" + self.host + ":" + self.port + url; | ||
return new Promise(function(resolve, reject){ | ||
request(nurl, function(error, response, body) { | ||
if (!error && response.statusCode == 200) { | ||
parseString(body, { explicitArray: false }, function(err, result) { | ||
if (!err) { | ||
var devInfo = result.root.device; | ||
devInfo.host = self.host; | ||
devInfo.port = self.port; | ||
var path = URL.parse(nurl).pathname; | ||
devInfo.urlPart = path.substring(0, path.lastIndexOf("/")); | ||
const newDevice = new d.Device(devInfo, self.config); | ||
newDevice._parseServices() | ||
.then(result => { | ||
resolve(result); | ||
}) | ||
.catch(err => { | ||
reject(err); | ||
}); | ||
} else { | ||
reject(error); | ||
} | ||
}); | ||
} else { | ||
reject(error); | ||
} | ||
}); | ||
}); | ||
switch(type){ | ||
case 'TR064': | ||
url = TR064_DESC_URL; | ||
break; | ||
case 'IGD': | ||
url = IGD_DESC_URL; | ||
break; | ||
case 'PMR': | ||
url = PMR_DESC_URL; | ||
break; | ||
} | ||
} | ||
const nurl = 'http://' + self.host + ':' + self.port + url; | ||
return new Promise(function(resolve, reject){ | ||
request(nurl, function(error, response, body) { | ||
if (!error && response.statusCode == 200) { | ||
parseString(body, { explicitArray: false }, function(err, result) { | ||
if (!err) { | ||
var devInfo = result.root.device; | ||
devInfo.host = self.host; | ||
devInfo.port = self.port; | ||
var path = URL.parse(nurl).pathname; | ||
devInfo.urlPart = path.substring(0, path.lastIndexOf('/')); | ||
const newDevice = new d.Device(devInfo, self.config); | ||
newDevice._parseServices() | ||
.then(result => { | ||
resolve(result); | ||
}) | ||
.catch(err => { | ||
reject(err); | ||
}); | ||
} else { | ||
reject(error); | ||
} | ||
}); | ||
} else { | ||
reject(error); | ||
} | ||
}); | ||
}); | ||
} | ||
} | ||
exports.TR064 = TR064; |
@@ -1,343 +0,380 @@ | ||
var parseString = require("xml2js").parseString; | ||
var request = require("request"); | ||
var parseString = require('xml2js').parseString; | ||
var request = require('request'); | ||
class Service{ | ||
constructor(device, serviceInfo, config, callback){ | ||
this.host = device.meta.host; | ||
this.port = device.meta.port; | ||
this.device = device; | ||
this.meta = serviceInfo; | ||
this.meta.actionsInfo = []; | ||
this.readyCallback = callback; | ||
this.actions = {}; | ||
this.stateVariables = {}; | ||
this.logAttempts = []; | ||
this.config = config; | ||
this._parseSCPD(this); | ||
} | ||
constructor(device, serviceInfo, config, callback){ | ||
this.host = device.meta.host; | ||
this.port = device.meta.port; | ||
this.device = device; | ||
this.meta = serviceInfo; | ||
this.meta.actionsInfo = []; | ||
this.readyCallback = callback; | ||
this.actions = {}; | ||
this.stateVariables = {}; | ||
this.logAttempts = []; | ||
this.config = config; | ||
this._parseSCPD(this); | ||
} | ||
_pushArg(argument, inArgs, outArgs){ | ||
if (argument.direction == "in") { | ||
inArgs.push(argument.name); | ||
} else if (argument.direction == "out") { | ||
outArgs.push(argument.name); | ||
} | ||
} | ||
_pushArg(argument, inArgs, outArgs){ | ||
if (argument.direction == 'in') { | ||
inArgs.push(argument.name); | ||
} else if (argument.direction == 'out') { | ||
outArgs.push(argument.name); | ||
} | ||
} | ||
_parseActions(actionData){ | ||
const self = this; | ||
if (!Array.isArray(actionData)) { | ||
return; | ||
} | ||
var insA = self._insertAction.bind(this); | ||
actionData.forEach(insA); | ||
} | ||
_parseActions(actionData){ | ||
const self = this; | ||
if (!Array.isArray(actionData)) { | ||
return; | ||
} | ||
var insA = self._insertAction.bind(this); | ||
actionData.forEach(insA); | ||
} | ||
_parseSCPD(obj){ | ||
const self = this; | ||
if (obj.device.meta.urlPart && obj.device.meta.urlPart.length > 0) { | ||
obj.meta.SCPDURL = obj.device.meta.urlPart + "/" + obj.meta.SCPDURL; | ||
} | ||
var url = "http://" + obj.host + ":" + obj.port + obj.meta.SCPDURL; | ||
//console.log(url); | ||
request(url, function(error, response, body) { | ||
if (!error && response.statusCode == 200) { | ||
// console.log(body); | ||
parseString( | ||
body, | ||
{ | ||
explicitArray: false, | ||
}, | ||
function(err, result) { | ||
var pA = self._parseActions.bind(obj); | ||
var pV = self._parseStateVariables.bind(obj); | ||
pA(result.scpd.actionList.action); | ||
pV(result.scpd.serviceStateTable.stateVariable); | ||
//inspect(obj.stateVariables); | ||
obj.readyCallback(null, obj); | ||
} | ||
); | ||
} else { | ||
obj.readyCallback(error, null); | ||
} | ||
}); | ||
} | ||
_parseSCPD(obj){ | ||
const self = this; | ||
if (obj.device.meta.urlPart && obj.device.meta.urlPart.length > 0) { | ||
obj.meta.SCPDURL = obj.device.meta.urlPart + '/' + obj.meta.SCPDURL; | ||
} | ||
var url = 'http://' + obj.host + ':' + obj.port + obj.meta.SCPDURL; | ||
//console.log(url); | ||
request(url, function(error, response, body) { | ||
if (!error && response.statusCode == 200) { | ||
// console.log(body); | ||
parseString( | ||
body, | ||
{ | ||
explicitArray: false, | ||
}, | ||
function(err, result) { | ||
var pA = self._parseActions.bind(obj); | ||
var pV = self._parseStateVariables.bind(obj); | ||
pA(result.scpd.actionList.action); | ||
pV(result.scpd.serviceStateTable.stateVariable); | ||
//inspect(obj.stateVariables); | ||
obj.readyCallback(null, obj); | ||
} | ||
); | ||
} else { | ||
obj.readyCallback(error, null); | ||
} | ||
}); | ||
} | ||
_insertAction(el){ | ||
const self = this; | ||
var outArgs = []; | ||
var inArgs = []; | ||
if (el.argumentList && Array.isArray(el.argumentList.argument)) { | ||
el.argumentList.argument.forEach(function(argument) { | ||
self._pushArg(argument, inArgs, outArgs); | ||
}); | ||
} else if (el.argumentList) { | ||
self._pushArg(el.argumentList.argument, inArgs, outArgs); | ||
} | ||
_insertAction(el){ | ||
const self = this; | ||
var outArgs = []; | ||
var inArgs = []; | ||
if (el.argumentList && Array.isArray(el.argumentList.argument)) { | ||
el.argumentList.argument.forEach(function(argument) { | ||
self._pushArg(argument, inArgs, outArgs); | ||
}); | ||
} else if (el.argumentList) { | ||
self._pushArg(el.argumentList.argument, inArgs, outArgs); | ||
} | ||
this.meta.actionsInfo.push({ | ||
name: el.name, | ||
inArgs: inArgs, | ||
outArgs: outArgs, | ||
}); | ||
this.meta.actionsInfo.push({ | ||
name: el.name, | ||
inArgs: inArgs, | ||
outArgs: outArgs, | ||
}); | ||
this.actions[el.name] = self.bind(this, function(vars, callback) { | ||
this._callAction(el.name, inArgs, outArgs, vars, callback); | ||
}); | ||
this.actions[el.name] = self.bind(this, function(vars, callback) { | ||
this._callAction(el.name, inArgs, outArgs, vars, callback); | ||
}); | ||
} | ||
} | ||
bind(scope, fn) { | ||
return function() { | ||
return fn.apply(scope, arguments); | ||
}; | ||
} | ||
bind(scope, fn) { | ||
return function() { | ||
return fn.apply(scope, arguments); | ||
}; | ||
} | ||
_callAction(name, inArguments, outArguments, vars, callback){ | ||
if (typeof vars === "function") { | ||
callback = vars; | ||
vars = []; | ||
} | ||
_callAction(name, inArguments, outArguments, vars, callback){ | ||
if (typeof vars === 'function') { | ||
callback = vars; | ||
vars = []; | ||
} | ||
this.bind( | ||
this, | ||
this._sendSOAPActionRequest( | ||
this.device, | ||
this.meta.controlURL, | ||
this.meta.serviceType, | ||
name, | ||
inArguments, | ||
outArguments, | ||
vars, | ||
callback | ||
) | ||
); | ||
} | ||
this.bind( | ||
this, | ||
this._sendSOAPActionRequest( | ||
this.device, | ||
this.meta.controlURL, | ||
this.meta.serviceType, | ||
name, | ||
inArguments, | ||
outArguments, | ||
vars, | ||
callback | ||
) | ||
); | ||
} | ||
_insertStateVariables(sv){ | ||
if (sv.$.sendEvents == "yes") { | ||
this.stateVariables[sv.name] = this.bind(this, function(callback) { | ||
this._subscribeStateVariableChangeEvent(sv, callback); | ||
}); | ||
} | ||
} | ||
_insertStateVariables(sv){ | ||
if (sv.$.sendEvents == 'yes') { | ||
this.stateVariables[sv.name] = this.bind(this, function(callback) { | ||
this._subscribeStateVariableChangeEvent(sv, callback); | ||
}); | ||
} | ||
} | ||
_parseStateVariables(stateVariableData){ | ||
var insSV = this.bind(this, this._insertStateVariables); | ||
if (Array.isArray(stateVariableData)) { | ||
stateVariableData.forEach(insSV); | ||
} else if (typeof stateVariableData === "object") { | ||
insSV(stateVariableData); | ||
} | ||
} | ||
_parseStateVariables(stateVariableData){ | ||
var insSV = this.bind(this, this._insertStateVariables); | ||
if (Array.isArray(stateVariableData)) { | ||
stateVariableData.forEach(insSV); | ||
} else if (typeof stateVariableData === 'object') { | ||
insSV(stateVariableData); | ||
} | ||
} | ||
_sendSOAPActionRequest(device,url,serviceType,action,inArguments,outArguments,vars,callback){ | ||
const self = this; | ||
var head = ""; | ||
if (device._auth.uid) { | ||
// Content Level Authentication | ||
if (device._auth.auth) { | ||
head = "<s:Header>" + | ||
"<h:ClientAuth xmlns:h=\"http://soap-authentication.org/digest/2001/10/\"" + | ||
"s:mustUnderstand=\"1\">" + | ||
"<Nonce>" + | ||
device._auth.sn + | ||
"</Nonce>" + | ||
"<Auth>" + | ||
device._auth.auth + | ||
"</Auth>" + | ||
"<UserID>" + | ||
device._auth.uid + | ||
"</UserID>" + | ||
"<Realm>" + | ||
device._auth.realm + | ||
"</Realm>" + | ||
"</h:ClientAuth>" + | ||
"</s:Header>"; | ||
} else { | ||
// First Auth | ||
head = " <s:Header>" + | ||
"<h:InitChallenge xmlns:h=\"http://soap-authentication.org/digest/2001/10/\"" + | ||
"s:mustUnderstand=\"1\">" + | ||
"<UserID>" + | ||
device._auth.uid + | ||
"</UserID>" + | ||
"<Realm>" + | ||
device._auth.realm + | ||
"</Realm>" + | ||
"</h:InitChallenge>" + | ||
"</s:Header>"; | ||
} | ||
} | ||
_sendSOAPActionRequest(device,url,serviceType,action,inArguments,outArguments,vars,callback){ | ||
const self = this; | ||
var head = ''; | ||
if (device._auth.uid) { | ||
// Content Level Authentication | ||
if (device._auth.auth) { | ||
head = '<s:Header>' + | ||
'<h:ClientAuth xmlns:h="http://soap-authentication.org/digest/2001/10/"' + | ||
's:mustUnderstand="1">' + | ||
'<Nonce>' + | ||
device._auth.sn + | ||
'</Nonce>' + | ||
'<Auth>' + | ||
device._auth.auth + | ||
'</Auth>' + | ||
'<UserID>' + | ||
device._auth.uid + | ||
'</UserID>' + | ||
'<Realm>' + | ||
device._auth.realm + | ||
'</Realm>' + | ||
'</h:ClientAuth>' + | ||
'</s:Header>'; | ||
} else { | ||
// First Auth | ||
head = ' <s:Header>' + | ||
'<h:InitChallenge xmlns:h="http://soap-authentication.org/digest/2001/10/"' + | ||
's:mustUnderstand="1">' + | ||
'<UserID>' + | ||
device._auth.uid + | ||
'</UserID>' + | ||
'<Realm>' + | ||
device._auth.realm + | ||
'</Realm>' + | ||
'</h:InitChallenge>' + | ||
'</s:Header>'; | ||
} | ||
} | ||
var body = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" + | ||
"<s:Envelope s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\" xmlns:s=\" http://schemas.xmlsoap.org/soap/envelope/\">" + | ||
head + | ||
"<s:Body>" + | ||
"<u:" + | ||
action + | ||
" xmlns:u=\"" + | ||
serviceType + | ||
"\">"; | ||
var body = '<?xml version="1.0" encoding="utf-8"?>' + | ||
'<s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s=" http://schemas.xmlsoap.org/soap/envelope/">' + | ||
head + | ||
'<s:Body>' + | ||
'<u:' + | ||
action + | ||
' xmlns:u="' + | ||
serviceType + | ||
'">'; | ||
for (var i in vars) { | ||
body += "<" + vars[i].name + ">"; | ||
body += vars[i].value; | ||
body += "</" + vars[i].name + ">"; | ||
} | ||
for (var i in vars) { | ||
body += '<' + vars[i].name + '>'; | ||
body += vars[i].value; | ||
body += '</' + vars[i].name + '>'; | ||
} | ||
body = body + "</u:" + action + ">" + "</s:Body>" + "</s:Envelope>"; | ||
body = body + '</u:' + action + '>' + '</s:Body>' + '</s:Envelope>'; | ||
var port = 0, | ||
proto = "", | ||
agentOptions = null; | ||
if (device._sslPort) { | ||
port = device._sslPort; | ||
proto = "https://"; | ||
if (device._ca) { | ||
agentOptions = { | ||
ca: device._ca, | ||
}; | ||
} else { | ||
agentOptions = { | ||
rejectUnauthorized: false, | ||
}; // Allow selfsignd Certs | ||
} | ||
} else { | ||
proto = "http://"; | ||
port = device.meta.port; | ||
} | ||
var uri = proto + device.meta.host + ":" + port + url; | ||
var that = this; | ||
var port = 0, | ||
proto = '', | ||
agentOptions = null; | ||
if (device._sslPort) { | ||
port = device._sslPort; | ||
proto = 'https://'; | ||
if (device._ca) { | ||
agentOptions = { | ||
ca: device._ca, | ||
}; | ||
} else { | ||
agentOptions = { | ||
rejectUnauthorized: false, | ||
}; // Allow selfsignd Certs | ||
} | ||
} else { | ||
proto = 'http://'; | ||
port = device.meta.port; | ||
} | ||
var uri = proto + device.meta.host + ':' + port + url; | ||
var that = this; | ||
request( | ||
{ | ||
method: "POST", | ||
uri: uri, | ||
agentOptions: agentOptions, | ||
headers: { | ||
SoapAction: serviceType + "#" + action, | ||
"Content-Type": "text/xml; charset=\"utf-8\"", | ||
}, | ||
body: body, | ||
timeout: self.config.timeout, | ||
}, | ||
function(error, response, body) { | ||
if (!error && response.statusCode == 200) { | ||
parseString( | ||
body, | ||
{ | ||
explicitArray: false, | ||
}, | ||
function(err, result) { | ||
var challange = false; | ||
var res = {}; | ||
var env = result["s:Envelope"]; | ||
if (env["s:Header"]) { | ||
var header = env["s:Header"]; | ||
if (header["h:Challenge"]) { | ||
var ch = header["h:Challenge"]; | ||
challange = true; | ||
if (self.logAttempts.length) { | ||
for (const i in self.logAttempts) { | ||
if ((self.logAttempts[i].service == serviceType && self.logAttempts[i].action == action)) { | ||
if (self.logAttempts[i].attempts >= 1) { | ||
error = new Error("Credentials incorrect"); | ||
} else { | ||
self.logAttempts[i].attempts += 1; | ||
device._auth.des = serviceType; | ||
device._auth.sn = ch.Nonce; | ||
device._auth.realm = ch.Realm; | ||
device._auth.auth = device._calcAuthDigest( | ||
device._auth.uid, | ||
device._auth.pwd, | ||
device._auth.realm, | ||
device._auth.sn | ||
); | ||
device._auth.chCount++; | ||
that._sendSOAPActionRequest( | ||
device, | ||
url, | ||
serviceType, | ||
action, | ||
inArguments, | ||
outArguments, | ||
vars, | ||
callback | ||
); | ||
return; | ||
} | ||
} | ||
} | ||
} else { | ||
self.logAttempts.push({ service: serviceType, action: action, attempts: 1 }); | ||
device._auth.sn = ch.Nonce; | ||
device._auth.realm = ch.Realm; | ||
device._auth.auth = device._calcAuthDigest( | ||
device._auth.uid, | ||
device._auth.pwd, | ||
device._auth.realm, | ||
device._auth.sn | ||
); | ||
device._auth.chCount++; | ||
// Repeat request. | ||
that._sendSOAPActionRequest( | ||
device, | ||
url, | ||
serviceType, | ||
action, | ||
inArguments, | ||
outArguments, | ||
vars, | ||
callback | ||
); | ||
return; | ||
} | ||
} else if (header["h:NextChallenge"]) { | ||
var nx = header["h:NextChallenge"]; | ||
for (const i in self.logAttempts) { | ||
if ((self.logAttempts[i].service == serviceType && self.logAttempts[i].action == action)) { | ||
self.logAttempts[i].attempts = 0; | ||
} | ||
} | ||
device._auth.chCount = 0; | ||
device._auth.sn = nx.Nonce; | ||
device._auth.realm = nx.Realm; | ||
device._auth.auth = device._calcAuthDigest( | ||
device._auth.uid, | ||
device._auth.pwd, | ||
device._auth.realm, | ||
device._auth.sn | ||
); | ||
} | ||
} | ||
request( | ||
{ | ||
method: 'POST', | ||
uri: uri, | ||
agentOptions: agentOptions, | ||
headers: { | ||
SoapAction: serviceType + '#' + action, | ||
'Content-Type': 'text/xml; charset="utf-8"', | ||
}, | ||
body: body, | ||
timeout: self.config.timeout, | ||
}, | ||
function(error, response, body) { | ||
if (!error && response.statusCode == 200) { | ||
parseString( | ||
body, | ||
{ | ||
explicitArray: false, | ||
}, | ||
function(err, result) { | ||
var challange = false; | ||
var res = {}; | ||
var env = result['s:Envelope']; | ||
if (env['s:Header']) { | ||
var header = env['s:Header']; | ||
if (header['h:Challenge']) { | ||
var ch = header['h:Challenge']; | ||
challange = true; | ||
if (self.logAttempts.length) { | ||
for (const i in self.logAttempts) { | ||
if ((self.logAttempts[i].service == serviceType && self.logAttempts[i].action == action)) { | ||
if (self.logAttempts[i].attempts >= 1) { | ||
error = new Error('Credentials incorrect'); | ||
} else { | ||
self.logAttempts[i].attempts += 1; | ||
device._auth.des = serviceType; | ||
device._auth.sn = ch.Nonce; | ||
device._auth.realm = ch.Realm; | ||
device._auth.auth = device._calcAuthDigest( | ||
device._auth.uid, | ||
device._auth.pwd, | ||
device._auth.realm, | ||
device._auth.sn | ||
); | ||
device._auth.chCount++; | ||
that._sendSOAPActionRequest( | ||
device, | ||
url, | ||
serviceType, | ||
action, | ||
inArguments, | ||
outArguments, | ||
vars, | ||
callback | ||
); | ||
return; | ||
} | ||
} | ||
} | ||
} else { | ||
self.logAttempts.push({ service: serviceType, action: action, attempts: 1 }); | ||
device._auth.sn = ch.Nonce; | ||
device._auth.realm = ch.Realm; | ||
device._auth.auth = device._calcAuthDigest( | ||
device._auth.uid, | ||
device._auth.pwd, | ||
device._auth.realm, | ||
device._auth.sn | ||
); | ||
device._auth.chCount++; | ||
// Repeat request. | ||
that._sendSOAPActionRequest( | ||
device, | ||
url, | ||
serviceType, | ||
action, | ||
inArguments, | ||
outArguments, | ||
vars, | ||
callback | ||
); | ||
return; | ||
} | ||
} else if (header['h:NextChallenge']) { | ||
var nx = header['h:NextChallenge']; | ||
for (const i in self.logAttempts) { | ||
if ((self.logAttempts[i].service == serviceType && self.logAttempts[i].action == action)) { | ||
self.logAttempts[i].attempts = 0; | ||
} | ||
} | ||
device._auth.chCount = 0; | ||
device._auth.sn = nx.Nonce; | ||
device._auth.realm = nx.Realm; | ||
device._auth.auth = device._calcAuthDigest( | ||
device._auth.uid, | ||
device._auth.pwd, | ||
device._auth.realm, | ||
device._auth.sn | ||
); | ||
} | ||
} | ||
if (env["s:Body"]) { | ||
var body = env["s:Body"]; | ||
if (body["u:" + action + "Response"]) { | ||
var responseVars = body["u:" + action + "Response"]; | ||
if (outArguments) { | ||
outArguments.forEach(function(arg) { | ||
res[arg] = responseVars[arg]; | ||
}); | ||
} | ||
} else if (body["s:Fault"]) { | ||
var fault = body["s:Fault"]; | ||
let errorStatus = body['s:Fault'].detail.UPnPError.errorDescription; | ||
error = new Error("Device responded with fault: " + errorStatus); | ||
res = fault; | ||
} | ||
} | ||
callback(error, res); | ||
} | ||
); | ||
} else { | ||
let newError = new Error("sendSOAPActionRequest Error! [" + action + "] [" + serviceType + "]" + (response ? " [" + response.statusCode + "]" : "") + (error ? " [" + error.code + "]" : "")); | ||
callback(newError, null); | ||
} | ||
} | ||
); | ||
} | ||
if (env['s:Body']) { | ||
var body = env['s:Body']; | ||
if (body['u:' + action + 'Response']) { | ||
var responseVars = body['u:' + action + 'Response']; | ||
if (outArguments) { | ||
outArguments.forEach(function(arg) { | ||
res[arg] = responseVars[arg]; | ||
}); | ||
} | ||
} else if (body['s:Fault']) { | ||
var fault = body['s:Fault']; | ||
//let errorStatus = body['s:Fault'].detail.UPnPError.errorDescription; | ||
let newFault = body['s:Fault']; | ||
error = { | ||
response: response.statusMessage, | ||
responseCode: response.statusCode, | ||
tr064: newFault.detail.UPnPError.errorDescription, | ||
tr064code: newFault.detail.UPnPError.errorCode, | ||
fault: newFault.faultstring, | ||
faultcode: newFault.faultcode, | ||
serviceType: serviceType, | ||
action: action | ||
}; | ||
res = fault; | ||
} | ||
} | ||
callback(error, res); | ||
} | ||
); | ||
} else { | ||
parseString(body,{explicitArray: false,}, function (err, result) { | ||
if(!err){ | ||
let env = result['s:Envelope']; | ||
if(env['s:Body']){ | ||
let newBody = env['s:Body']; | ||
if(newBody['s:Fault']){ | ||
let fault = newBody['s:Fault']; | ||
error = { | ||
response: response.statusMessage, | ||
responseCode: response.statusCode, | ||
tr064: fault.detail.UPnPError.errorDescription, | ||
tr064code: fault.detail.UPnPError.errorCode, | ||
fault: fault.faultstring, | ||
faultcode: fault.faultcode, | ||
serviceType: serviceType, | ||
action: action | ||
}; | ||
} | ||
} | ||
} else { | ||
error = { | ||
response: response.statusMessage, | ||
responseCode: response.statusCode, | ||
serviceType: serviceType, | ||
action: action | ||
}; | ||
} | ||
}); | ||
callback(error, null); | ||
} | ||
} | ||
); | ||
} | ||
} | ||
exports.Service = Service; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
222080
711