mirror of
https://gitlab.com/Shinobi-Systems/ShinobiCE.git
synced 2025-03-09 15:40:15 +00:00
Kicking Kangaroo
This commit is contained in:
parent
bc01b19714
commit
e0f7c135af
37 changed files with 1642 additions and 518 deletions
|
@ -6,6 +6,7 @@ module.exports = function(s,config,lang){
|
|||
// WebDAV
|
||||
var beforeAccountSaveForWebDav = function(d){
|
||||
//d = save event
|
||||
d.form.details.webdav_use_global=d.d.webdav_use_global
|
||||
d.form.details.use_webdav=d.d.use_webdav
|
||||
}
|
||||
var cloudDiskUseStartupForWebDav = function(group,userDetails){
|
||||
|
@ -20,6 +21,15 @@ module.exports = function(s,config,lang){
|
|||
var loadWebDavForUser = function(e){
|
||||
// e = user
|
||||
var ar = JSON.parse(e.details);
|
||||
if(ar.webdav_use_global === '1' && config.cloudUploaders && config.cloudUploaders.WebDAV){
|
||||
// {
|
||||
// webdav_user: "",
|
||||
// webdav_pass: "",
|
||||
// webdav_url: "",
|
||||
// webdav_dir: "",
|
||||
// }
|
||||
ar = Object.assign(ar,config.cloudUploaders.WebDAV)
|
||||
}
|
||||
//owncloud/webdav
|
||||
if(!s.group[e.ke].webdav &&
|
||||
ar.webdav_user&&
|
||||
|
@ -150,6 +160,7 @@ module.exports = function(s,config,lang){
|
|||
//Amazon S3
|
||||
var beforeAccountSaveForAmazonS3 = function(d){
|
||||
//d = save event
|
||||
d.form.details.aws_use_global=d.d.aws_use_global
|
||||
d.form.details.use_aws_s3=d.d.use_aws_s3
|
||||
}
|
||||
var cloudDiskUseStartupForAmazonS3 = function(group,userDetails){
|
||||
|
@ -163,7 +174,17 @@ module.exports = function(s,config,lang){
|
|||
}
|
||||
var loadAmazonS3ForUser = function(e){
|
||||
// e = user
|
||||
var ar = JSON.parse(e.details);
|
||||
var ar = JSON.parse(e.details)
|
||||
if(ar.aws_use_global === '1' && config.cloudUploaders && config.cloudUploaders.AmazonS3){
|
||||
// {
|
||||
// aws_accessKeyId: "",
|
||||
// aws_secretAccessKey: "",
|
||||
// aws_region: "",
|
||||
// aws_s3_bucket: "",
|
||||
// aws_s3_dir: "",
|
||||
// }
|
||||
ar = Object.assign(ar,config.cloudUploaders.AmazonS3)
|
||||
}
|
||||
//Amazon S3
|
||||
if(!s.group[e.ke].aws &&
|
||||
!s.group[e.ke].aws_s3 &&
|
||||
|
@ -262,7 +283,8 @@ module.exports = function(s,config,lang){
|
|||
//Backblaze B2
|
||||
var beforeAccountSaveForBackblazeB2 = function(d){
|
||||
//d = save event
|
||||
d.form.details.use_aws_s3=d.d.use_bb_b2
|
||||
d.form.details.b2_use_global=d.d.b2_use_global
|
||||
d.form.details.use_bb_b2=d.d.use_bb_b2
|
||||
}
|
||||
var cloudDiskUseStartupForBackblazeB2 = function(group,userDetails){
|
||||
group.cloudDiskUse['b2'].name = 'Backblaze B2'
|
||||
|
@ -276,6 +298,15 @@ module.exports = function(s,config,lang){
|
|||
var loadBackblazeB2ForUser = function(e){
|
||||
var ar = JSON.parse(e.details);
|
||||
try{
|
||||
if(ar.b2_use_global === '1' && config.cloudUploaders && config.cloudUploaders.BackblazeB2){
|
||||
// {
|
||||
// bb_b2_accountId: "",
|
||||
// bb_b2_applicationKey: "",
|
||||
// bb_b2_bucket: "",
|
||||
// bb_b2_dir: "",
|
||||
// }
|
||||
ar = Object.assign(ar,config.cloudUploaders.BackblazeB2)
|
||||
}
|
||||
if(!s.group[e.ke].bb_b2 &&
|
||||
ar.bb_b2_accountId &&
|
||||
ar.bb_b2_accountId !=='' &&
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
var P2P = require('pipe2pam');
|
||||
var PamDiff = require('pam-diff');
|
||||
// pamDiff is based on https://www.npmjs.com/package/pam-diff
|
||||
var PamDiff = require('./detectorPamDiff.js');
|
||||
module.exports = function(s,config){
|
||||
s.createPamDiffEngine = function(e){
|
||||
var width,
|
||||
|
@ -64,12 +65,13 @@ module.exports = function(s,config){
|
|||
plug:'built-in',
|
||||
name:trigger.name,
|
||||
reason:'motion',
|
||||
confidence:trigger.percent,
|
||||
confidence:trigger.percent
|
||||
},
|
||||
plates:[],
|
||||
imgHeight:height,
|
||||
imgWidth:width
|
||||
imgHeight:e.details.detector_scale_y,
|
||||
imgWidth:e.details.detector_scale_x
|
||||
}
|
||||
if(trigger.matrix)detectorObject.details.matrices = [trigger.matrix]
|
||||
var region = Object.values(regionJson).find(x => x.name == detectorObject.name)
|
||||
s.checkMaximumSensitivity(e, region, detectorObject, function() {
|
||||
s.checkTriggerThreshold(e, region, detectorObject, function() {
|
||||
|
|
622
libs/detectorPamDiff.js
Normal file
622
libs/detectorPamDiff.js
Normal file
|
@ -0,0 +1,622 @@
|
|||
//
|
||||
// Shinobi - fork of pam-diff
|
||||
// Copyright (C) 2018 Kevin Godell
|
||||
// Author : Kevin Godell, https://github.com/kevinGodell
|
||||
// npmjs : https://www.npmjs.com/package/pam-diff
|
||||
// Github : https://github.com/kevinGodell/pam-diff
|
||||
//
|
||||
'use strict';
|
||||
|
||||
const { Transform } = require('stream');
|
||||
|
||||
const PP = require('polygon-points');
|
||||
/**
|
||||
*
|
||||
* @param chunk
|
||||
* @private
|
||||
*/
|
||||
var _getMatrixFromPoints = function(thisRegion) {
|
||||
var coordinates = [
|
||||
thisRegion.topLeft,
|
||||
{"x" : thisRegion.bottomRight.x, "y" : thisRegion.topLeft.y},
|
||||
thisRegion.bottomRight
|
||||
]
|
||||
var width = Math.sqrt( Math.pow(coordinates[1].x - coordinates[0].x, 2) + Math.pow(coordinates[1].y - coordinates[0].y, 2));
|
||||
var height = Math.sqrt( Math.pow(coordinates[2].x - coordinates[1].x, 2) + Math.pow(coordinates[2].y - coordinates[1].y, 2))
|
||||
return {
|
||||
x: coordinates[0].x,
|
||||
y: coordinates[0].y,
|
||||
width: width,
|
||||
height: height,
|
||||
tag: thisRegion.name
|
||||
}
|
||||
}
|
||||
class PamDiff extends Transform {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param [options] {Object}
|
||||
* @param [callback] {Function}
|
||||
*/
|
||||
constructor(options, callback) {
|
||||
super(options);
|
||||
Transform.call(this, {objectMode: true});
|
||||
this.difference = PamDiff._parseOptions('difference', options);//global option, can be overridden per region
|
||||
this.percent = PamDiff._parseOptions('percent', options);//global option, can be overridden per region
|
||||
this.regions = PamDiff._parseOptions('regions', options);//can be no regions or a single region or multiple regions. if no regions, all pixels will be compared.
|
||||
this.callback = callback;//callback function to be called when pixel difference is detected
|
||||
this._parseChunk = this._parseFirstChunk;//first parsing will be reading settings and configuring internal pixel reading
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param option {String}
|
||||
* @param options {Object}
|
||||
* @return {*}
|
||||
* @private
|
||||
*/
|
||||
static _parseOptions(option, options) {
|
||||
if (options && options.hasOwnProperty(option)) {
|
||||
return options[option];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param number {Number}
|
||||
* @param def {Number}
|
||||
* @param low {Number}
|
||||
* @param high {Number}
|
||||
* @return {Number}
|
||||
* @private
|
||||
*/
|
||||
static _validateNumber(number, def, low, high) {
|
||||
if (isNaN(number)) {
|
||||
return def;
|
||||
} else if (number < low) {
|
||||
return low;
|
||||
} else if (number > high) {
|
||||
return high;
|
||||
} else {
|
||||
return number;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @deprecated
|
||||
* @param string {String}
|
||||
*/
|
||||
setGrayscale(string) {
|
||||
console.warn('grayscale option has been removed, "average" has proven to most accurate and is the default');
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param number {Number}
|
||||
*/
|
||||
set difference(number) {
|
||||
this._difference = PamDiff._validateNumber(parseInt(number), 5, 1, 255);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return {Number}
|
||||
*/
|
||||
get difference() {
|
||||
return this._difference;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param number {Number}
|
||||
* @return {PamDiff}
|
||||
*/
|
||||
setDifference(number) {
|
||||
this.difference = number;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param number {Number}
|
||||
*/
|
||||
set percent(number) {
|
||||
this._percent = PamDiff._validateNumber(parseInt(number), 5, 1, 100);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return {Number}
|
||||
*/
|
||||
get percent() {
|
||||
return this._percent;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param number {Number}
|
||||
* @return {PamDiff}
|
||||
*/
|
||||
setPercent(number) {
|
||||
this.percent = number;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param array {Array}
|
||||
*/
|
||||
set regions(array) {
|
||||
if (!array) {
|
||||
if (this._regions) {
|
||||
delete this._regions;
|
||||
delete this._regionsLength;
|
||||
delete this._minDiff;
|
||||
}
|
||||
this._diffs = 0;
|
||||
} else if (!Array.isArray(array) || array.length < 1) {
|
||||
throw new Error(`Regions must be an array of at least 1 region object {name: 'region1', difference: 10, percent: 10, polygon: [[0, 0], [0, 50], [50, 50], [50, 0]]}`);
|
||||
} else {
|
||||
this._regions = [];
|
||||
this._minDiff = 255;
|
||||
for (const region of array) {
|
||||
if (!region.hasOwnProperty('name') || !region.hasOwnProperty('polygon')) {
|
||||
throw new Error('Region must include a name and a polygon property');
|
||||
}
|
||||
const polygonPoints = new PP(region.polygon);
|
||||
const difference = PamDiff._validateNumber(parseInt(region.difference), this._difference, 1, 255);
|
||||
const percent = PamDiff._validateNumber(parseInt(region.percent), this._percent, 1, 100);
|
||||
this._minDiff = Math.min(this._minDiff, difference);
|
||||
this._regions.push(
|
||||
{
|
||||
name: region.name,
|
||||
polygon: polygonPoints,
|
||||
difference: difference,
|
||||
percent: percent,
|
||||
diffs: 0
|
||||
}
|
||||
);
|
||||
}
|
||||
this._regionsLength = this._regions.length;
|
||||
this._createPointsInPolygons(this._regions, this._width, this._height);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return {Array}
|
||||
*/
|
||||
get regions() {
|
||||
return this._regions;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param array {Array}
|
||||
* @return {PamDiff}
|
||||
*/
|
||||
setRegions(array) {
|
||||
this.regions = array;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param func {Function}
|
||||
*/
|
||||
set callback(func) {
|
||||
if (!func) {
|
||||
delete this._callback;
|
||||
} else if (typeof func === 'function' && func.length === 1) {
|
||||
this._callback = func;
|
||||
} else {
|
||||
throw new Error('Callback must be a function that accepts 1 argument.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return {Function}
|
||||
*/
|
||||
get callback() {
|
||||
return this._callback;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param func {Function}
|
||||
* @return {PamDiff}
|
||||
*/
|
||||
setCallback(func) {
|
||||
this.callback = func;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return {PamDiff}
|
||||
*/
|
||||
resetCache() {
|
||||
//delete this._oldPix;
|
||||
//delete this._newPix;
|
||||
//delete this._width;
|
||||
//delete this._length;
|
||||
this._parseChunk = this._parseFirstChunk;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param regions {Array}
|
||||
* @param width {Number}
|
||||
* @param height {Number}
|
||||
* @private
|
||||
*/
|
||||
_createPointsInPolygons(regions, width, height) {
|
||||
if (regions && width && height) {
|
||||
this._pointsInPolygons = [];
|
||||
for (const region of regions) {
|
||||
const bitset = region.polygon.getBitset(this._width, this._height);
|
||||
region.pointsLength = bitset.count;
|
||||
this._pointsInPolygons.push(bitset.buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param chunk
|
||||
* @private
|
||||
*/
|
||||
_blackAndWhitePixelDiff(chunk) {
|
||||
this._newPix = chunk.pixels;
|
||||
for (let y = 0, i = 0; y < this._height; y++) {
|
||||
for (let x = 0; x < this._width; x++, i++) {
|
||||
const diff = this._oldPix[i] !== this._newPix[i];
|
||||
if (this._regions && diff === true) {
|
||||
for (let j = 0; j < this._regionsLength; j++) {
|
||||
if (this._pointsInPolygons[j][i]) {
|
||||
this._regions[j].diffs++;
|
||||
}
|
||||
}
|
||||
} else if (diff === true) {
|
||||
this._diffs++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this._regions) {
|
||||
const regionDiffArray = [];
|
||||
for (let i = 0; i < this._regionsLength; i++) {
|
||||
const percent = Math.floor(100 * this._regions[i].diffs / this._regions[i].pointsLength);
|
||||
if (percent >= this._regions[i].percent) {
|
||||
regionDiffArray.push({name: this._regions[i].name, percent: percent});
|
||||
}
|
||||
this._regions[i].diffs = 0;
|
||||
}
|
||||
if (regionDiffArray.length > 0) {
|
||||
const data = {trigger: regionDiffArray, pam: chunk.pam};
|
||||
if (this._callback) {
|
||||
this._callback(data);
|
||||
}
|
||||
if (this._readableState.pipesCount > 0) {
|
||||
this.push(data);
|
||||
}
|
||||
if (this.listenerCount('diff') > 0) {
|
||||
this.emit('diff', data);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const percent = Math.floor(100 * this._diffs / this._length);
|
||||
if (percent >= this._percent) {
|
||||
const data = {trigger: [{name: 'percent', percent: percent}], pam: chunk.pam};
|
||||
if (this._callback) {
|
||||
this._callback(data);
|
||||
}
|
||||
if (this._readableState.pipesCount > 0) {
|
||||
this.push(data);
|
||||
}
|
||||
if (this.listenerCount('diff') > 0) {
|
||||
this.emit('diff', data);
|
||||
}
|
||||
}
|
||||
this._diffs = 0;
|
||||
}
|
||||
this._oldPix = this._newPix;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param chunk
|
||||
* @private
|
||||
*/
|
||||
_grayScalePixelDiff(chunk) {
|
||||
this._newPix = chunk.pixels;
|
||||
for (let j = 0; j < this._regionsLength; j++) {
|
||||
this._regions[j].topLeft = {
|
||||
x: this._width,
|
||||
y: this._height
|
||||
}
|
||||
this._regions[j].bottomRight = {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
}
|
||||
this.topLeft = {
|
||||
x: this._width,
|
||||
y: this._height
|
||||
}
|
||||
this.bottomRight = {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
for (let y = 0, i = 0; y < this._height; y++) {
|
||||
for (let x = 0; x < this._width; x++, i++) {
|
||||
if (this._oldPix[i] !== this._newPix[i]) {
|
||||
const diff = Math.abs(this._oldPix[i] - this._newPix[i]);
|
||||
if (this._regions && diff >= this._minDiff) {
|
||||
for (let j = 0; j < this._regionsLength; j++) {
|
||||
if (this._pointsInPolygons[j][i] && diff >= this._regions[j].difference) {
|
||||
var theRegion = this._regions[j]
|
||||
theRegion.diffs++;
|
||||
if(theRegion.topLeft.x > x && theRegion.topLeft.y > y){
|
||||
theRegion.topLeft.x = x
|
||||
theRegion.topLeft.y = y
|
||||
}
|
||||
if(theRegion.bottomRight.x < x && theRegion.bottomRight.y < y){
|
||||
theRegion.bottomRight.x = x
|
||||
theRegion.bottomRight.y = y
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (diff >= this._difference) {
|
||||
this._diffs++;
|
||||
if(this.topLeft.x > x && this.topLeft.y > y){
|
||||
this.topLeft.x = x
|
||||
this.topLeft.y = y
|
||||
}
|
||||
if(this.bottomRight.x < x && this.bottomRight.y < y){
|
||||
this.bottomRight.x = x
|
||||
this.bottomRight.y = y
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this._regions) {
|
||||
const regionDiffArray = [];
|
||||
for (let i = 0; i < this._regionsLength; i++) {
|
||||
var thisRegion = this._regions[i]
|
||||
const percent = Math.floor(100 * thisRegion.diffs / thisRegion.pointsLength);
|
||||
if (percent >= thisRegion.percent) {
|
||||
// create matrix from points >>
|
||||
thisRegion._matrix = _getMatrixFromPoints(thisRegion)
|
||||
// create matrix from points />>
|
||||
regionDiffArray.push({name: thisRegion.name, percent: percent, matrix: thisRegion._matrix});
|
||||
}
|
||||
thisRegion.diffs = 0;
|
||||
}
|
||||
if (regionDiffArray.length > 0) {
|
||||
this._matrix = _getMatrixFromPoints(this)
|
||||
const data = {trigger: regionDiffArray, pam: chunk.pam, matrix: this._matrix};
|
||||
if (this._callback) {
|
||||
this._callback(data);
|
||||
}
|
||||
if (this._readableState.pipesCount > 0) {
|
||||
this.push(data);
|
||||
}
|
||||
if (this.listenerCount('diff') > 0) {
|
||||
this.emit('diff', data);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const percent = Math.floor(100 * this._diffs / this._length);
|
||||
if (percent >= this._percent) {
|
||||
this._matrix = _getMatrixFromPoints(this)
|
||||
const data = {trigger: [{name: 'percent', percent: percent, matrix: this._matrix}], pam: chunk.pam};
|
||||
if (this._callback) {
|
||||
this._callback(data);
|
||||
}
|
||||
if (this._readableState.pipesCount > 0) {
|
||||
this.push(data);
|
||||
}
|
||||
if (this.listenerCount('diff') > 0) {
|
||||
this.emit('diff', data);
|
||||
}
|
||||
}
|
||||
this._diffs = 0;
|
||||
}
|
||||
this._oldPix = this._newPix;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param chunk
|
||||
* @private
|
||||
*/
|
||||
_rgbPixelDiff(chunk) {
|
||||
this._newPix = chunk.pixels;
|
||||
for (let y = 0, i = 0, p = 0; y < this._height; y++) {
|
||||
for (let x = 0; x < this._width; x++, i += 3, p++) {
|
||||
if (this._oldPix[i] !== this._newPix[i] || this._oldPix[i + 1] !== this._newPix[i + 1] || this._oldPix[i + 2] !== this._newPix[i + 2]) {
|
||||
const diff = Math.abs(this._oldPix[i] + this._oldPix[i + 1] + this._oldPix[i + 2] - this._newPix[i] - this._newPix[i + 1] - this._newPix[i + 2])/3;
|
||||
if (this._regions && diff >= this._minDiff) {
|
||||
for (let j = 0; j < this._regionsLength; j++) {
|
||||
if (this._pointsInPolygons[j][p] && diff >= this._regions[j].difference) {
|
||||
this._regions[j].diffs++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (diff >= this._difference) {
|
||||
this._diffs++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this._regions) {
|
||||
const regionDiffArray = [];
|
||||
for (let i = 0; i < this._regionsLength; i++) {
|
||||
const percent = Math.floor(100 * this._regions[i].diffs / this._regions[i].pointsLength);
|
||||
if (percent >= this._regions[i].percent) {
|
||||
regionDiffArray.push({name: this._regions[i].name, percent: percent});
|
||||
}
|
||||
this._regions[i].diffs = 0;
|
||||
}
|
||||
if (regionDiffArray.length > 0) {
|
||||
const data = {trigger: regionDiffArray, pam: chunk.pam};
|
||||
if (this._callback) {
|
||||
this._callback(data);
|
||||
}
|
||||
if (this._readableState.pipesCount > 0) {
|
||||
this.push(data);
|
||||
}
|
||||
if (this.listenerCount('diff') > 0) {
|
||||
this.emit('diff', data);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const percent = Math.floor(100 * this._diffs / this._length);
|
||||
if (percent >= this._percent) {
|
||||
const data = {trigger: [{name: 'percent', percent: percent}], pam: chunk.pam};
|
||||
if (this._callback) {
|
||||
this._callback(data);
|
||||
}
|
||||
if (this._readableState.pipesCount > 0) {
|
||||
this.push(data);
|
||||
}
|
||||
if (this.listenerCount('diff') > 0) {
|
||||
this.emit('diff', data);
|
||||
}
|
||||
}
|
||||
this._diffs = 0;
|
||||
}
|
||||
this._oldPix = this._newPix;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param chunk
|
||||
* @private
|
||||
*/
|
||||
_rgbAlphaPixelDiff(chunk) {
|
||||
this._newPix = chunk.pixels;
|
||||
for (let y = 0, i = 0, p = 0; y < this._height; y++) {
|
||||
for (let x = 0; x < this._width; x++, i += 4, p++) {
|
||||
if (this._oldPix[i] !== this._newPix[i] || this._oldPix[i + 1] !== this._newPix[i + 1] || this._oldPix[i + 2] !== this._newPix[i + 2]) {
|
||||
const diff = Math.abs(this._oldPix[i] + this._oldPix[i + 1] + this._oldPix[i + 2] - this._newPix[i] - this._newPix[i + 1] - this._newPix[i + 2])/3;
|
||||
if (this._regions && diff >= this._minDiff) {
|
||||
for (let j = 0; j < this._regionsLength; j++) {
|
||||
if (this._pointsInPolygons[j][p] && diff >= this._regions[j].difference) {
|
||||
this._regions[j].diffs++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (diff >= this._difference) {
|
||||
this._diffs++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this._regions) {
|
||||
const regionDiffArray = [];
|
||||
for (let i = 0; i < this._regionsLength; i++) {
|
||||
const percent = Math.floor(100 * this._regions[i].diffs / this._regions[i].pointsLength);
|
||||
if (percent >= this._regions[i].percent) {
|
||||
regionDiffArray.push({name: this._regions[i].name, percent: percent});
|
||||
}
|
||||
this._regions[i].diffs = 0;
|
||||
}
|
||||
if (regionDiffArray.length > 0) {
|
||||
const data = {trigger: regionDiffArray, pam: chunk.pam};
|
||||
if (this._callback) {
|
||||
this._callback(data);
|
||||
}
|
||||
if (this._readableState.pipesCount > 0) {
|
||||
this.push(data);
|
||||
}
|
||||
if (this.listenerCount('diff') > 0) {
|
||||
this.emit('diff', data);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const percent = Math.floor(100 * this._diffs / this._length);
|
||||
if (percent >= this._percent) {
|
||||
const data = {trigger: [{name: 'percent', percent: percent}], pam: chunk.pam};
|
||||
if (this._callback) {
|
||||
this._callback(data);
|
||||
}
|
||||
if (this._readableState.pipesCount > 0) {
|
||||
this.push(data);
|
||||
}
|
||||
if (this.listenerCount('diff') > 0) {
|
||||
this.emit('diff', data);
|
||||
}
|
||||
}
|
||||
this._diffs = 0;
|
||||
}
|
||||
this._oldPix = this._newPix;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param chunk
|
||||
* @private
|
||||
*/
|
||||
_parseFirstChunk(chunk) {
|
||||
this._width = parseInt(chunk.width);
|
||||
this._height = parseInt(chunk.height);
|
||||
this._oldPix = chunk.pixels;
|
||||
this._length = this._width * this._height;
|
||||
this._createPointsInPolygons(this._regions, this._width, this._height);
|
||||
switch (chunk.tupltype) {
|
||||
case 'blackandwhite' :
|
||||
this._parseChunk = this._blackAndWhitePixelDiff;
|
||||
break;
|
||||
case 'grayscale' :
|
||||
this._parseChunk = this._grayScalePixelDiff;
|
||||
break;
|
||||
case 'rgb' :
|
||||
this._parseChunk = this._rgbPixelDiff;
|
||||
//this._increment = 3;//future use
|
||||
break;
|
||||
case 'rgb_alpha' :
|
||||
this._parseChunk = this._rgbAlphaPixelDiff;
|
||||
//this._increment = 4;//future use
|
||||
break;
|
||||
default :
|
||||
throw Error(`Unsupported tupltype: ${chunk.tupltype}. Supported tupltypes include grayscale(gray), blackandwhite(monob), rgb(rgb24), and rgb_alpha(rgba).`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param chunk
|
||||
* @param encoding
|
||||
* @param callback
|
||||
* @private
|
||||
*/
|
||||
_transform(chunk, encoding, callback) {
|
||||
this._parseChunk(chunk);
|
||||
callback();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param callback
|
||||
* @private
|
||||
*/
|
||||
_flush(callback) {
|
||||
this.resetCache();
|
||||
callback();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @type {PamDiff}
|
||||
*/
|
||||
module.exports = PamDiff;
|
||||
//todo get bounding box of all regions combined to exclude some pixels before checking if they exist inside specific regions
|
|
@ -12,9 +12,7 @@ module.exports = function(s,config,lang){
|
|||
})
|
||||
break;
|
||||
case'delete':
|
||||
d.videos.forEach(function(v,n){
|
||||
s.deleteVideo(v)
|
||||
})
|
||||
s.deleteListOfVideos(d.videos)
|
||||
break;
|
||||
case'execute':
|
||||
exec(d.execute,{detached: true})
|
||||
|
@ -373,6 +371,7 @@ module.exports = function(s,config,lang){
|
|||
delete(s.api[d.auth])
|
||||
s.userLog(d,{type:"Traditional Recording",msg:'Clear Recorder Process'})
|
||||
delete(s.group[d.ke].mon[d.id].eventBasedRecording.process)
|
||||
clearTimeout(s.group[d.ke].mon[d.id].eventBasedRecording.timeout)
|
||||
delete(s.group[d.ke].mon[d.id].eventBasedRecording.timeout)
|
||||
clearTimeout(s.group[d.ke].mon[d.id].recordingChecker)
|
||||
})
|
||||
|
|
|
@ -526,12 +526,9 @@ module.exports = function(s,config,onFinish){
|
|||
//add input feed map
|
||||
x.pipe += s.createFFmpegMap(e,e.details.input_map_choices.stream)
|
||||
}
|
||||
console.log('x.cust_stream',x.cust_stream)
|
||||
|
||||
if(x.stream_fps && (e.details.stream_vcodec !== 'copy' || e.details.stream_type === 'mjpeg' || e.details.stream_type === 'b64')){
|
||||
x.cust_stream += x.stream_fps
|
||||
}
|
||||
console.log('x.cust_stream',x.cust_stream)
|
||||
switch(e.details.stream_type){
|
||||
case'mp4':
|
||||
x.cust_stream+=' -movflags +frag_keyframe+empty_moov+default_base_moof -metadata title="Poseidon Stream" -reset_timestamps 1'
|
||||
|
|
|
@ -1,31 +1,31 @@
|
|||
var fs = require('fs');
|
||||
module.exports = function(s,config){
|
||||
//directories
|
||||
s.group={};
|
||||
s.group = {}
|
||||
if(!config.windowsTempDir&&s.isWin===true){config.windowsTempDir='C:/Windows/Temp'}
|
||||
if(!config.defaultMjpeg){config.defaultMjpeg=s.mainDirectory+'/web/libs/img/bg.jpg'}
|
||||
//default stream folder check
|
||||
if(!config.streamDir){
|
||||
if(s.isWin===false){
|
||||
config.streamDir='/dev/shm'
|
||||
if(s.isWin === false){
|
||||
config.streamDir = '/dev/shm'
|
||||
}else{
|
||||
config.streamDir=config.windowsTempDir
|
||||
config.streamDir = config.windowsTempDir
|
||||
}
|
||||
if(!fs.existsSync(config.streamDir)){
|
||||
config.streamDir=s.mainDirectory+'/streams/'
|
||||
config.streamDir = s.mainDirectory+'/streams/'
|
||||
}else{
|
||||
config.streamDir+='/streams/'
|
||||
config.streamDir += '/streams/'
|
||||
}
|
||||
}
|
||||
if(!config.videosDir){config.videosDir=s.mainDirectory+'/videos/'}
|
||||
if(!config.binDir){config.binDir=s.mainDirectory+'/fileBin/'}
|
||||
if(!config.addStorage){config.addStorage=[]}
|
||||
s.dir={
|
||||
videos:s.checkCorrectPathEnding(config.videosDir),
|
||||
streams:s.checkCorrectPathEnding(config.streamDir),
|
||||
fileBin:s.checkCorrectPathEnding(config.binDir),
|
||||
addStorage:config.addStorage,
|
||||
languages:s.location.languages+'/'
|
||||
videos: s.checkCorrectPathEnding(config.videosDir),
|
||||
streams: s.checkCorrectPathEnding(config.streamDir),
|
||||
fileBin: s.checkCorrectPathEnding(config.binDir),
|
||||
addStorage: config.addStorage,
|
||||
languages: s.location.languages+'/'
|
||||
};
|
||||
//streams dir
|
||||
if(!fs.existsSync(s.dir.streams)){
|
||||
|
@ -41,7 +41,7 @@ module.exports = function(s,config){
|
|||
}
|
||||
//additional storage areas
|
||||
s.dir.addStorage.forEach(function(v,n){
|
||||
v.path=s.checkCorrectPathEnding(v.path)
|
||||
v.path = s.checkCorrectPathEnding(v.path)
|
||||
if(!fs.existsSync(v.path)){
|
||||
fs.mkdirSync(v.path);
|
||||
}
|
||||
|
|
215
libs/monitor.js
215
libs/monitor.js
|
@ -73,6 +73,16 @@ module.exports = function(s,config,lang){
|
|||
if(noPath !== true)url += e.path
|
||||
return url
|
||||
}
|
||||
s.cleanMonitorObjectForDatabase = function(dirtyMonitor){
|
||||
var cleanMonitor = {}
|
||||
var acceptedFields = ['mid','ke','name','shto','shfr','details','type','ext','protocol','host','path','port','fps','mode','width','height']
|
||||
Object.keys(dirtyMonitor).forEach(function(key){
|
||||
if(acceptedFields.indexOf(key) > -1){
|
||||
cleanMonitor[key] = dirtyMonitor[key]
|
||||
}
|
||||
})
|
||||
return cleanMonitor
|
||||
}
|
||||
s.cleanMonitorObject = function(e){
|
||||
x={keys:Object.keys(e),ar:{}};
|
||||
x.keys.forEach(function(v){
|
||||
|
@ -89,18 +99,28 @@ module.exports = function(s,config,lang){
|
|||
}
|
||||
var url
|
||||
var runExtraction = function(){
|
||||
var snapBuffer = []
|
||||
var snapProcess = spawn(config.ffmpegDir,('-loglevel quiet -re -i '+url+options+' -frames:v 1 -f mjpeg pipe:1').split(' '),{detached: true})
|
||||
snapProcess.stdout.on('data',function(data){
|
||||
snapBuffer.push(data)
|
||||
});
|
||||
snapProcess.stderr.on('data',function(data){
|
||||
console.log(data.toString())
|
||||
});
|
||||
snapProcess.on('close',function(data){
|
||||
snapBuffer = Buffer.concat(snapBuffer)
|
||||
callback(snapBuffer,false)
|
||||
})
|
||||
try{
|
||||
var snapBuffer = []
|
||||
var snapProcess = spawn(config.ffmpegDir,('-loglevel quiet -re -i '+url+options+' -frames:v 1 -f image2pipe pipe:1').split(' '),{detached: true})
|
||||
snapProcess.stdout.on('data',function(data){
|
||||
snapBuffer.push(data)
|
||||
})
|
||||
snapProcess.stderr.on('data',function(data){
|
||||
console.log(data.toString())
|
||||
})
|
||||
snapProcess.on('exit',function(data){
|
||||
clearTimeout(snapProcessTimeout)
|
||||
snapBuffer = Buffer.concat(snapBuffer)
|
||||
callback(snapBuffer,false)
|
||||
})
|
||||
var snapProcessTimeout = setTimeout(function(){
|
||||
snapProcess.stdin.setEncoding('utf8')
|
||||
snapProcess.stdin.write('q')
|
||||
delete(snapProcessTimeout)
|
||||
},5000)
|
||||
}catch(err){
|
||||
callback(fs.readFileSync(config.defaultMjpeg,'binary'),false)
|
||||
}
|
||||
}
|
||||
var checkExists = function(localStream,callback){
|
||||
fs.stat(localStream,function(err){
|
||||
|
@ -230,6 +250,7 @@ module.exports = function(s,config,lang){
|
|||
clearTimeout(s.group[e.ke].mon[e.id].watchdog_stop);
|
||||
delete(s.group[e.ke].mon[e.id].watchdog_stop);
|
||||
delete(s.group[e.ke].mon[e.id].lastJpegDetectorFrame);
|
||||
delete(s.group[e.ke].mon[e.id].detectorFrameSaveBuffer);
|
||||
clearTimeout(s.group[e.ke].mon[e.id].recordingSnapper);
|
||||
clearInterval(s.group[e.ke].mon[e.id].getMonitorCpuUsage);
|
||||
if(s.group[e.ke].mon[e.id].onChildNodeExit){
|
||||
|
@ -377,7 +398,7 @@ module.exports = function(s,config,lang){
|
|||
}
|
||||
}
|
||||
//create onvif connection
|
||||
if(!s.group[e.ke].mon[e.id].onvifConnection){
|
||||
if(!s.group[e.ke].mon[e.id].onvifConnection || !s.group[e.ke].mon[e.id].onvifConnection.current_profile || !s.group[e.ke].mon[e.id].onvifConnection.current_profile.token){
|
||||
s.group[e.ke].mon[e.id].onvifConnection = new onvif.OnvifDevice({
|
||||
xaddr : 'http://' + controlURLOptions.host + ':' + controlURLOptions.port + '/onvif/device_service',
|
||||
user : controlURLOptions.username,
|
||||
|
@ -494,8 +515,8 @@ module.exports = function(s,config,lang){
|
|||
}
|
||||
s.cameraSendSnapshot = function(e){
|
||||
s.checkDetails(e)
|
||||
if(config.doSnapshot===true){
|
||||
if(e.mon.mode!=='stop'){
|
||||
if(config.doSnapshot === true){
|
||||
if(e.mon.mode !== 'stop'){
|
||||
var pathDir = s.dir.streams+e.ke+'/'+e.mid+'/'
|
||||
fs.stat(pathDir+'icon.jpg',function(err){
|
||||
if(!err){
|
||||
|
@ -505,36 +526,22 @@ module.exports = function(s,config,lang){
|
|||
})
|
||||
}else{
|
||||
e.url = s.buildMonitorUrl(e.mon)
|
||||
switch(e.mon.type){
|
||||
case'mjpeg':case'h264':case'local':
|
||||
if(e.mon.type==='local'){e.url=e.mon.path;}
|
||||
s.getRawSnapshotFromMonitor(e.mon,'-s 200x200',function(data,isStaticFile){
|
||||
if((data[data.length-2] === 0xFF && data[data.length-1] === 0xD9)){
|
||||
if(!isStaticFile){
|
||||
fs.writeFile(s.dir.streams+e.ke+'/'+e.mid+'/icon.jpg',data,function(){})
|
||||
}
|
||||
s.tx({
|
||||
f:'monitor_snapshot',
|
||||
snapshot:data.toString('base64'),
|
||||
snapshot_format:'b64',
|
||||
mid:e.mid,
|
||||
ke:e.ke
|
||||
},'GRP_'+e.ke)
|
||||
}else{
|
||||
s.tx({f:'monitor_snapshot',snapshot:e.mon.name,snapshot_format:'plc',mid:e.mid,ke:e.ke},'GRP_'+e.ke)
|
||||
}
|
||||
})
|
||||
break;
|
||||
case'jpeg':
|
||||
request({url:e.url,method:'GET',encoding:null},function(err,data){
|
||||
if(err){s.tx({f:'monitor_snapshot',snapshot:e.mon.name,snapshot_format:'plc',mid:e.mid,ke:e.ke},'GRP_'+e.ke);return};
|
||||
s.tx({f:'monitor_snapshot',snapshot:data.body,snapshot_format:'ab',mid:e.mid,ke:e.ke},'GRP_'+e.ke)
|
||||
})
|
||||
break;
|
||||
default:
|
||||
s.tx({f:'monitor_snapshot',snapshot:'...',snapshot_format:'plc',mid:e.mid,ke:e.ke},'GRP_'+e.ke)
|
||||
break;
|
||||
}
|
||||
s.getRawSnapshotFromMonitor(e.mon,'-s 200x200',function(data,isStaticFile){
|
||||
if((data[data.length-2] === 0xFF && data[data.length-1] === 0xD9)){
|
||||
if(!isStaticFile){
|
||||
fs.writeFile(s.dir.streams+e.ke+'/'+e.mid+'/icon.jpg',data,function(){})
|
||||
}
|
||||
s.tx({
|
||||
f: 'monitor_snapshot',
|
||||
snapshot: data.toString('base64'),
|
||||
snapshot_format: 'b64',
|
||||
mid: e.mid,
|
||||
ke: e.ke
|
||||
},'GRP_'+e.ke)
|
||||
}else{
|
||||
s.tx({f:'monitor_snapshot',snapshot:e.mon.name,snapshot_format:'plc',mid:e.mid,ke:e.ke},'GRP_'+e.ke)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}else{
|
||||
|
@ -777,10 +784,34 @@ module.exports = function(s,config,lang){
|
|||
s.group[e.ke].mon[e.id].lastJpegDetectorFrame = d
|
||||
})
|
||||
}
|
||||
}else{
|
||||
s.group[e.ke].mon[e.id].spawn.stdio[3].on('data',function(d){
|
||||
s.ocvTx({f:'frame',mon:s.group[e.ke].mon_conf[e.id].details,ke:e.ke,id:e.id,time:s.formattedTime(),frame:d});
|
||||
})
|
||||
}else if(s.ocv){
|
||||
if(s.ocv.connectionType !== 'ram'){
|
||||
s.group[e.ke].mon[e.id].spawn.stdio[3].on('data',function(d){
|
||||
s.ocvTx({f:'frame',mon:s.group[e.ke].mon_conf[e.id].details,ke:e.ke,id:e.id,time:s.formattedTime(),frame:d});
|
||||
})
|
||||
}else{
|
||||
s.group[e.ke].mon[e.id].spawn.stdio[3].on('data',function(d){
|
||||
if(!s.group[e.ke].mon[e.id].detectorFrameSaveBuffer){
|
||||
s.group[e.ke].mon[e.id].detectorFrameSaveBuffer=[d]
|
||||
}else{
|
||||
s.group[e.ke].mon[e.id].detectorFrameSaveBuffer.push(d)
|
||||
}
|
||||
if(d[d.length-2] === 0xFF && d[d.length-1] === 0xD9){
|
||||
var buffer = Buffer.concat(s.group[e.ke].mon[e.id].detectorFrameSaveBuffer);
|
||||
var frameLocation = s.dir.streams + e.ke + '/' + e.id + '/' + s.gid(5) + '.jpg'
|
||||
if(s.ocv){
|
||||
fs.writeFile(frameLocation,buffer,function(err){
|
||||
if(err){
|
||||
s.debugLog(err)
|
||||
}else{
|
||||
s.ocvTx({f:'frameFromRam',mon:s.group[e.ke].mon_conf[e.id].details,ke:e.ke,id:e.id,time:s.formattedTime(),frameLocation:frameLocation})
|
||||
}
|
||||
})
|
||||
}
|
||||
s.group[e.ke].mon[e.id].detectorFrameSaveBuffer = null;
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
//frames to stream
|
||||
|
@ -1192,6 +1223,92 @@ module.exports = function(s,config,lang){
|
|||
}catch(err){}
|
||||
return false
|
||||
}
|
||||
s.addOrEditMonitor = function(form,callback,user){
|
||||
var endData = {
|
||||
ok: false
|
||||
}
|
||||
if(!form.mid){
|
||||
endData.msg = lang['No Monitor ID Present in Form']
|
||||
callback(endData)
|
||||
return
|
||||
}
|
||||
form.mid = form.mid.replace(/[^\w\s]/gi,'').replace(/ /g,'')
|
||||
form = s.cleanMonitorObjectForDatabase(form)
|
||||
s.sqlQuery('SELECT * FROM Monitors WHERE ke=? AND mid=?',[form.ke,form.mid],function(er,r){
|
||||
var affectMonitor = false
|
||||
var monitorQuery = []
|
||||
var monitorQueryValues = []
|
||||
var txData = {
|
||||
f: 'monitor_edit',
|
||||
mid: form.mid,
|
||||
ke: form.ke,
|
||||
mon: form
|
||||
}
|
||||
if(r&&r[0]){
|
||||
txData.new = false
|
||||
Object.keys(form).forEach(function(v){
|
||||
if(form[v]&&form[v]!==''){
|
||||
monitorQuery.push(v+'=?')
|
||||
if(form[v] instanceof Object){
|
||||
form[v] = s.s(form[v])
|
||||
}
|
||||
monitorQueryValues.push(form[v])
|
||||
}
|
||||
})
|
||||
monitorQuery = monitorQuery.join(',')
|
||||
monitorQueryValues.push(form.ke)
|
||||
monitorQueryValues.push(form.mid)
|
||||
s.userLog(form,{type:'Monitor Updated',msg:'by user : '+user.uid})
|
||||
endData.msg = user.lang['Monitor Updated by user']+' : '+user.uid
|
||||
s.sqlQuery('UPDATE Monitors SET '+monitorQuery+' WHERE ke=? AND mid=?',monitorQueryValues)
|
||||
affectMonitor = true
|
||||
}else if(
|
||||
!s.group[form.ke].init.max_camera ||
|
||||
s.group[form.ke].init.max_camera === '' ||
|
||||
Object.keys(s.group[form.ke].mon).length <= parseInt(s.group[form.ke].init.max_camera)
|
||||
){
|
||||
txData.new = true
|
||||
monitorQueryInsertValues = []
|
||||
Object.keys(form).forEach(function(v){
|
||||
if(form[v] && form[v] !== ''){
|
||||
monitorQuery.push(v)
|
||||
monitorQueryInsertValues.push('?')
|
||||
if(form[v] instanceof Object){
|
||||
form[v] = s.s(form[v])
|
||||
}
|
||||
monitorQueryValues.push(form[v])
|
||||
}
|
||||
})
|
||||
monitorQuery = monitorQuery.join(',')
|
||||
monitorQueryInsertValues = monitorQueryInsertValues.join(',')
|
||||
s.userLog(form,{type:'Monitor Added',msg:'by user : '+user.uid})
|
||||
endData.msg = user.lang['Monitor Added by user']+' : '+user.uid
|
||||
s.sqlQuery('INSERT INTO Monitors ('+monitorQuery+') VALUES ('+monitorQueryInsertValues+')',monitorQueryValues)
|
||||
affectMonitor = true
|
||||
}else{
|
||||
txData.f = 'monitor_edit_failed'
|
||||
txData.ff = 'max_reached'
|
||||
endData.msg = user.lang.monitorEditFailedMaxReached
|
||||
}
|
||||
if(affectMonitor === true){
|
||||
form.details = JSON.parse(form.details)
|
||||
endData.ok = true
|
||||
s.initiateMonitorObject({mid:form.mid,ke:form.ke})
|
||||
s.group[form.ke].mon_conf[form.mid] = s.cleanMonitorObject(form)
|
||||
if(form.mode === 'stop'){
|
||||
s.camera('stop',form)
|
||||
}else{
|
||||
s.camera('stop',form)
|
||||
setTimeout(function(){
|
||||
s.camera(form.mode,form)
|
||||
},5000)
|
||||
}
|
||||
s.tx(txData,'STR_'+form.ke)
|
||||
}
|
||||
s.tx(txData,'GRP_'+form.ke)
|
||||
callback(!endData.ok,endData)
|
||||
})
|
||||
}
|
||||
s.camera = function(x,e,cn){
|
||||
// x = function or mode
|
||||
// e = monitor object
|
||||
|
|
|
@ -30,8 +30,15 @@ module.exports = function(s,config,lang){
|
|||
s.systemLog('Connected to plugin : Detector - '+d.plug+' - '+d.type)
|
||||
switch(d.type){
|
||||
default:case'detector':
|
||||
s.ocv={started:s.timeObject(),id:cn.id,plug:d.plug,notice:d.notice,isClientPlugin:true};
|
||||
cn.ocv=1;
|
||||
s.ocv = {
|
||||
started: s.timeObject(),
|
||||
id: cn.id,
|
||||
plug: d.plug,
|
||||
notice: d.notice,
|
||||
isClientPlugin: true,
|
||||
connectionType: d.connectionType
|
||||
};
|
||||
cn.ocv = 1;
|
||||
s.tx({f:'detector_plugged',plug:d.plug,notice:d.notice},'CPU')
|
||||
break;
|
||||
}
|
||||
|
@ -39,7 +46,14 @@ module.exports = function(s,config,lang){
|
|||
//is in host mode (camera.js is client)
|
||||
switch(d.type){
|
||||
default:case'detector':
|
||||
s.ocv={started:s.timeObject(),id:"host",plug:d.plug,notice:d.notice,isHostPlugin:true};
|
||||
s.ocv = {
|
||||
started:s.timeObject(),
|
||||
id:"host",
|
||||
plug:d.plug,
|
||||
notice:d.notice,
|
||||
isHostPlugin:true,
|
||||
connectionType: d.connectionType
|
||||
};
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ var spawn = require('child_process').spawn;
|
|||
var jsonfile = require("jsonfile");
|
||||
var onvif = require("node-onvif");
|
||||
module.exports = function(s,config,lang,io){
|
||||
s.clientSocketConnection = {}
|
||||
//send data to detector plugin
|
||||
s.ocvTx=function(data){
|
||||
if(!s.ocv){return}
|
||||
|
@ -426,7 +427,15 @@ module.exports = function(s,config,lang,io){
|
|||
// if(!s.group[d.ke].vid)s.group[d.ke].vid={};
|
||||
if(!s.group[d.ke].users)s.group[d.ke].users={};
|
||||
// s.group[d.ke].vid[cn.id]={uid:d.uid};
|
||||
s.group[d.ke].users[d.auth]={cnid:cn.id,uid:r.uid,mail:r.mail,details:JSON.parse(r.details),logged_in_at:s.timeObject(new Date).format(),login_type:'Dashboard'}
|
||||
s.group[d.ke].users[d.auth] = {
|
||||
cnid: cn.id,
|
||||
uid: r.uid,
|
||||
mail: r.mail,
|
||||
details: JSON.parse(r.details),
|
||||
logged_in_at: s.timeObject(new Date).format(),
|
||||
login_type: 'Dashboard'
|
||||
}
|
||||
s.clientSocketConnection[cn.id] = cn
|
||||
try{s.group[d.ke].users[d.auth].details=JSON.parse(r.details)}catch(er){}
|
||||
if(s.group[d.ke].users[d.auth].details.get_server_log!=='0'){
|
||||
cn.join('GRPLOG_'+d.ke)
|
||||
|
@ -588,75 +597,8 @@ module.exports = function(s,config,lang,io){
|
|||
}
|
||||
break;
|
||||
case'edit':
|
||||
s.sqlQuery('SELECT details FROM Users WHERE ke=? AND uid=?',[d.ke,d.uid],function(err,r){
|
||||
if(r&&r[0]){
|
||||
r=r[0];
|
||||
d.d=JSON.parse(r.details);
|
||||
if(!d.d.sub || d.d.user_change === "1"){
|
||||
if(d.d.get_server_log==='1'){
|
||||
cn.join('GRPLOG_'+d.ke)
|
||||
}else{
|
||||
cn.leave('GRPLOG_'+d.ke)
|
||||
}
|
||||
///unchangeable from client side, so reset them in case they did.
|
||||
d.form.details=JSON.parse(d.form.details)
|
||||
s.beforeAccountSaveExtensions.forEach(function(extender){
|
||||
extender(d)
|
||||
})
|
||||
//admin permissions
|
||||
d.form.details.permissions=d.d.permissions
|
||||
d.form.details.edit_size=d.d.edit_size
|
||||
d.form.details.edit_days=d.d.edit_days
|
||||
d.form.details.use_admin=d.d.use_admin
|
||||
d.form.details.use_ldap=d.d.use_ldap
|
||||
//check
|
||||
if(d.d.edit_days=="0"){
|
||||
d.form.details.days=d.d.days;
|
||||
}
|
||||
if(d.d.edit_size=="0"){
|
||||
d.form.details.size=d.d.size;
|
||||
}
|
||||
if(d.d.sub){
|
||||
d.form.details.sub=d.d.sub;
|
||||
if(d.d.monitors){d.form.details.monitors=d.d.monitors;}
|
||||
if(d.d.allmonitors){d.form.details.allmonitors=d.d.allmonitors;}
|
||||
if(d.d.monitor_create){d.form.details.monitor_create=d.d.monitor_create;}
|
||||
if(d.d.video_delete){d.form.details.video_delete=d.d.video_delete;}
|
||||
if(d.d.video_view){d.form.details.video_view=d.d.video_view;}
|
||||
if(d.d.monitor_edit){d.form.details.monitor_edit=d.d.monitor_edit;}
|
||||
if(d.d.size){d.form.details.size=d.d.size;}
|
||||
if(d.d.days){d.form.details.days=d.d.days;}
|
||||
delete(d.form.details.mon_groups)
|
||||
}
|
||||
var newSize = d.form.details.size || 10000
|
||||
d.form.details=JSON.stringify(d.form.details)
|
||||
///
|
||||
d.set=[],d.ar=[];
|
||||
if(d.form.pass&&d.form.pass!==''){d.form.pass=s.createHash(d.form.pass);}else{delete(d.form.pass)};
|
||||
delete(d.form.password_again);
|
||||
d.for=Object.keys(d.form);
|
||||
d.for.forEach(function(v){
|
||||
d.set.push(v+'=?'),d.ar.push(d.form[v]);
|
||||
});
|
||||
d.ar.push(d.ke),d.ar.push(d.uid);
|
||||
s.sqlQuery('UPDATE Users SET '+d.set.join(',')+' WHERE ke=? AND uid=?',d.ar,function(err,r){
|
||||
if(!d.d.sub){
|
||||
var user = Object.assign(d.form,{ke : d.ke})
|
||||
var userDetails = JSON.parse(d.form.details)
|
||||
s.group[d.ke].sizeLimit = parseFloat(newSize)
|
||||
s.onAccountSaveExtensions.forEach(function(extender){
|
||||
extender(s.group[d.ke],userDetails)
|
||||
})
|
||||
s.unloadGroupAppExtensions.forEach(function(extender){
|
||||
extender(user)
|
||||
})
|
||||
s.loadGroupApps(d)
|
||||
}
|
||||
tx({f:'user_settings_change',uid:d.uid,ke:d.ke,form:d.form});
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
d.cnid = cn.id
|
||||
s.accountSettingsEdit(d)
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
@ -1428,6 +1370,7 @@ module.exports = function(s,config,lang,io){
|
|||
if(cn.superSessionKey){
|
||||
delete(s.superUsersApi[cn.superSessionKey])
|
||||
}
|
||||
delete(s.clientSocketConnection[cn.id])
|
||||
})
|
||||
});
|
||||
}
|
||||
|
|
10
libs/sql.js
10
libs/sql.js
|
@ -50,6 +50,9 @@ module.exports = function(s,config){
|
|||
if(!onMoveOn){onMoveOn=function(){}}
|
||||
var mergedQuery = s.mergeQueryValues(query,values)
|
||||
s.debugLog('s.sqlQuery QUERY',mergedQuery)
|
||||
if(!s.databaseEngine || !s.databaseEngine.raw){
|
||||
s.connectDatabase()
|
||||
}
|
||||
return s.databaseEngine
|
||||
.raw(query,values)
|
||||
.asCallback(function(err,r){
|
||||
|
@ -70,11 +73,18 @@ module.exports = function(s,config){
|
|||
}
|
||||
})
|
||||
}
|
||||
s.connectDatabase = function(){
|
||||
s.databaseEngine = require('knex')(s.databaseOptions)
|
||||
}
|
||||
s.preQueries = function(){
|
||||
//add Cloud Videos table, will remove in future
|
||||
s.sqlQuery('CREATE TABLE IF NOT EXISTS `Cloud Videos` (`mid` varchar(50) NOT NULL,`ke` varchar(50) DEFAULT NULL,`href` text NOT NULL,`size` float DEFAULT NULL,`time` timestamp NULL DEFAULT NULL,`end` timestamp NULL DEFAULT NULL,`status` int(1) DEFAULT \'0\' COMMENT \'0:Complete,1:Read,2:Archive\',`details` text) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;',[],function(err){
|
||||
// if(err)console.log(err)
|
||||
},true)
|
||||
//add monitorStates to Preset ENUM
|
||||
s.sqlQuery('ALTER TABLE `Presets` CHANGE COLUMN `type` `type` VARCHAR(50) NULL DEFAULT NULL AFTER `details`;',[],function(err){
|
||||
// if(err)console.log(err)
|
||||
},true)
|
||||
//create Files table
|
||||
s.sqlQuery('CREATE TABLE IF NOT EXISTS `Files` (`ke` varchar(50) NOT NULL,`mid` varchar(50) NOT NULL,`name` tinytext NOT NULL,`size` float NOT NULL DEFAULT \'0\',`details` text NOT NULL,`status` int(1) NOT NULL DEFAULT \'0\') ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;',[],function(err){
|
||||
// if(err)console.log(err)
|
||||
|
|
|
@ -29,6 +29,7 @@ module.exports = function(s,config,lang,io){
|
|||
orphanedVideosForMonitors[monitor.ke][monitor.mid] += orphanedFilesCount
|
||||
}
|
||||
s.group[monitor.ke].mon_conf[monitor.mid] = monitor
|
||||
s.sendMonitorStatus({id:monitor.mid,ke:monitor.ke,status:'Stopped'});
|
||||
var monObj = Object.assign(monitor,{id : monitor.mid})
|
||||
s.camera(monitor.mode,monObj)
|
||||
++loadCompleted
|
||||
|
|
75
libs/user.js
75
libs/user.js
|
@ -230,6 +230,79 @@ module.exports = function(s,config){
|
|||
s.group[e.ke].init[v]=ar[v]
|
||||
})
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
s.accountSettingsEdit = function(d){
|
||||
s.sqlQuery('SELECT details FROM Users WHERE ke=? AND uid=?',[d.ke,d.uid],function(err,r){
|
||||
if(r&&r[0]){
|
||||
r=r[0];
|
||||
d.d=JSON.parse(r.details);
|
||||
if(!d.d.sub || d.d.user_change !== "0"){
|
||||
if(d.cnid){
|
||||
if(d.d.get_server_log==='1'){
|
||||
s.clientSocketConnection[d.cnid].join('GRPLOG_'+d.ke)
|
||||
}else{
|
||||
s.clientSocketConnection[d.cnid].leave('GRPLOG_'+d.ke)
|
||||
}
|
||||
}
|
||||
///unchangeable from client side, so reset them in case they did.
|
||||
d.form.details=JSON.parse(d.form.details)
|
||||
s.beforeAccountSaveExtensions.forEach(function(extender){
|
||||
extender(d)
|
||||
})
|
||||
//admin permissions
|
||||
d.form.details.permissions=d.d.permissions
|
||||
d.form.details.edit_size=d.d.edit_size
|
||||
d.form.details.edit_days=d.d.edit_days
|
||||
d.form.details.use_admin=d.d.use_admin
|
||||
d.form.details.use_ldap=d.d.use_ldap
|
||||
//check
|
||||
if(d.d.edit_days=="0"){
|
||||
d.form.details.days=d.d.days;
|
||||
}
|
||||
if(d.d.edit_size=="0"){
|
||||
d.form.details.size=d.d.size;
|
||||
}
|
||||
if(d.d.sub){
|
||||
d.form.details.sub=d.d.sub;
|
||||
if(d.d.monitors){d.form.details.monitors=d.d.monitors;}
|
||||
if(d.d.allmonitors){d.form.details.allmonitors=d.d.allmonitors;}
|
||||
if(d.d.monitor_create){d.form.details.monitor_create=d.d.monitor_create;}
|
||||
if(d.d.video_delete){d.form.details.video_delete=d.d.video_delete;}
|
||||
if(d.d.video_view){d.form.details.video_view=d.d.video_view;}
|
||||
if(d.d.monitor_edit){d.form.details.monitor_edit=d.d.monitor_edit;}
|
||||
if(d.d.size){d.form.details.size=d.d.size;}
|
||||
if(d.d.days){d.form.details.days=d.d.days;}
|
||||
delete(d.form.details.mon_groups)
|
||||
}
|
||||
var newSize = d.form.details.size || 10000
|
||||
d.form.details=JSON.stringify(d.form.details)
|
||||
///
|
||||
d.set=[],d.ar=[];
|
||||
if(d.form.pass&&d.form.pass!==''){d.form.pass=s.createHash(d.form.pass);}else{delete(d.form.pass)};
|
||||
delete(d.form.password_again);
|
||||
d.for=Object.keys(d.form);
|
||||
d.for.forEach(function(v){
|
||||
d.set.push(v+'=?'),d.ar.push(d.form[v]);
|
||||
});
|
||||
d.ar.push(d.ke),d.ar.push(d.uid);
|
||||
s.sqlQuery('UPDATE Users SET '+d.set.join(',')+' WHERE ke=? AND uid=?',d.ar,function(err,r){
|
||||
if(!d.d.sub){
|
||||
var user = Object.assign(d.form,{ke : d.ke})
|
||||
var userDetails = JSON.parse(d.form.details)
|
||||
s.group[d.ke].sizeLimit = parseFloat(newSize)
|
||||
s.onAccountSaveExtensions.forEach(function(extender){
|
||||
extender(s.group[d.ke],userDetails)
|
||||
})
|
||||
s.unloadGroupAppExtensions.forEach(function(extender){
|
||||
extender(user)
|
||||
})
|
||||
s.loadGroupApps(d)
|
||||
}
|
||||
if(d.cnid)s.tx({f:'user_settings_change',uid:d.uid,ke:d.ke,form:d.form},d.cnid)
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -230,17 +230,69 @@ module.exports = function(s,config,lang){
|
|||
})
|
||||
})
|
||||
})
|
||||
var videoSnap = s.dir.videoSnaps + e.ke + '/' + e.mid + '/' + filename.split('.')[0] + '.jpg'
|
||||
fs.chmod(videoSnap,0o777,function(err){
|
||||
if(!err){
|
||||
fs.unlink(videoSnap,function(err){})
|
||||
}
|
||||
})
|
||||
}else{
|
||||
console.log(new Error())
|
||||
console.log(lang['Database row does not exist'],queryValues)
|
||||
}
|
||||
})
|
||||
}
|
||||
s.deleteListOfVideos = function(videos){
|
||||
var query = 'DELETE FROM Videos WHERE '
|
||||
var videoQuery = []
|
||||
var queryValues = []
|
||||
videos.forEach(function(video){
|
||||
s.checkDetails(video)
|
||||
//e = video object
|
||||
video.dir = s.getVideoDirectory(video)
|
||||
if(!video.filename && video.time){
|
||||
video.filename = s.formattedTime(video.time)
|
||||
}
|
||||
var filename,
|
||||
time
|
||||
if(video.filename.indexOf('.')>-1){
|
||||
filename = video.filename
|
||||
}else{
|
||||
filename = video.filename+'.'+video.ext
|
||||
}
|
||||
if(video.filename && !video.time){
|
||||
time = s.nameToTime(filename)
|
||||
}else{
|
||||
time = video.time
|
||||
}
|
||||
time = new Date(time)
|
||||
fs.chmod(video.dir+filename,0o777,function(err){
|
||||
s.tx({
|
||||
f: 'video_delete',
|
||||
filename: filename,
|
||||
mid: video.id,
|
||||
ke: video.ke,
|
||||
time: s.nameToTime(filename),
|
||||
end: s.formattedTime(new Date,'YYYY-MM-DD HH:mm:ss')
|
||||
},'GRP_'+video.ke);
|
||||
s.setDiskUsedForGroup(video,-(video.size / 1000000))
|
||||
fs.unlink(video.dir+filename,function(err){
|
||||
fs.stat(video.dir+filename,function(err){
|
||||
if(!err){
|
||||
s.file('delete',video.dir+filename)
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
videoQuery.push('(`mid`=? AND `ke`=? AND `time`=?)')
|
||||
queryValues = queryValues.concat([video.id,video.ke,time])
|
||||
})
|
||||
query += videoQuery.join(' OR ')
|
||||
s.sqlQuery(query,queryValues,function(err){
|
||||
if(err){
|
||||
s.systemLog(lang['List of Videos Delete Error'],err)
|
||||
}
|
||||
})
|
||||
}
|
||||
s.deleteVideoFromCloudExtensions = {}
|
||||
s.deleteVideoFromCloudExtensionsRunner = function(e,storageType,video){
|
||||
// e = user
|
||||
|
|
|
@ -4,7 +4,52 @@ var https = require('https');
|
|||
var express = require('express');
|
||||
var app = express()
|
||||
module.exports = function(s,config,lang,io){
|
||||
var server = http.createServer(app);
|
||||
//get page URL
|
||||
if(!config.baseURL){
|
||||
config.baseURL = ""
|
||||
}else if(config.baseURL !== ''){
|
||||
config.baseURL = s.checkCorrectPathEnding(config.baseURL)
|
||||
}
|
||||
//Render Configurations - Web Paths
|
||||
if(config.webPaths === undefined){config.webPaths={}}
|
||||
//main access URI
|
||||
if(config.webPaths.home === undefined){config.webPaths.home='/'}
|
||||
//Super User URI
|
||||
if(config.webPaths.super === undefined){config.webPaths.super='/super'}
|
||||
//Admin URI
|
||||
if(config.webPaths.admin === undefined){config.webPaths.admin='/admin'}
|
||||
//Libraries URI
|
||||
if(config.webPaths.libs === undefined){config.webPaths.libs='/libs'}
|
||||
//API Prefix
|
||||
if(config.webPaths.apiPrefix === undefined){config.webPaths.apiPrefix = s.checkCorrectPathEnding(config.webPaths.home)}else{config.webPaths.apiPrefix = s.checkCorrectPathEnding(config.webPaths.apiPrefix)}
|
||||
//Admin API Prefix
|
||||
if(config.webPaths.adminApiPrefix === undefined){config.webPaths.adminApiPrefix=s.checkCorrectPathEnding(config.webPaths.admin)}else{config.webPaths.adminApiPrefix = s.checkCorrectPathEnding(config.webPaths.adminApiPrefix)}
|
||||
//Super API Prefix
|
||||
if(config.webPaths.superApiPrefix === undefined){config.webPaths.superApiPrefix=s.checkCorrectPathEnding(config.webPaths.super)}else{config.webPaths.superApiPrefix = s.checkCorrectPathEnding(config.webPaths.superApiPrefix)}
|
||||
//Render Configurations - Page Render Paths
|
||||
if(config.renderPaths === undefined){config.renderPaths={}}
|
||||
//login page
|
||||
if(config.renderPaths.index === undefined){config.renderPaths.index='pages/index'}
|
||||
//dashboard page
|
||||
if(config.renderPaths.home === undefined){config.renderPaths.home='pages/home'}
|
||||
//sub-account administration page
|
||||
if(config.renderPaths.admin === undefined){config.renderPaths.admin='pages/admin'}
|
||||
//superuser page
|
||||
if(config.renderPaths.super === undefined){config.renderPaths.super='pages/super'}
|
||||
//2-Factor Auth page
|
||||
if(config.renderPaths.factorAuth === undefined){config.renderPaths.factorAuth='pages/factor'}
|
||||
//Streamer v1 (Dashcam Prototype) page
|
||||
if(config.renderPaths.streamer === undefined){config.renderPaths.streamer='pages/streamer'}
|
||||
//Streamer v2 (Dashcam) page
|
||||
if(config.renderPaths.dashcam === undefined){config.renderPaths.dashcam='pages/dashcam'}
|
||||
//embeddable widget page
|
||||
if(config.renderPaths.embed === undefined){config.renderPaths.embed='pages/embed'}
|
||||
//mjpeg full screen page
|
||||
if(config.renderPaths.mjpeg === undefined){config.renderPaths.mjpeg='pages/mjpeg'}
|
||||
//gridstack only page
|
||||
if(config.renderPaths.grid === undefined){config.renderPaths.grid='pages/grid'}
|
||||
//slick.js (cycle) page
|
||||
if(config.renderPaths.cycle === undefined){config.renderPaths.cycle='pages/cycle'}
|
||||
//SSL options
|
||||
if(config.ssl&&config.ssl.key&&config.ssl.cert){
|
||||
config.ssl.key=fs.readFileSync(s.checkRelativePath(config.ssl.key),'utf8')
|
||||
|
@ -24,12 +69,47 @@ module.exports = function(s,config,lang,io){
|
|||
serverHTTPS.listen(config.ssl.port,config.bindip,function(){
|
||||
console.log('SSL '+lang.Shinobi+' : SSL Web Server Listening on '+config.ssl.port);
|
||||
});
|
||||
io.attach(serverHTTPS);
|
||||
if(config.webPaths.home !== '/'){
|
||||
io.attach(serverHTTPS,{
|
||||
path:'/socket.io',
|
||||
transports: ['websocket']
|
||||
})
|
||||
}
|
||||
io.attach(serverHTTPS,{
|
||||
path:s.checkCorrectPathEnding(config.webPaths.home)+'socket.io',
|
||||
transports: ['websocket']
|
||||
})
|
||||
io.attach(serverHTTPS,{
|
||||
path:s.checkCorrectPathEnding(config.webPaths.admin)+'socket.io',
|
||||
transports: ['websocket']
|
||||
})
|
||||
io.attach(serverHTTPS,{
|
||||
path:s.checkCorrectPathEnding(config.webPaths.super)+'socket.io',
|
||||
transports: ['websocket']
|
||||
})
|
||||
}
|
||||
//start HTTP
|
||||
var server = http.createServer(app);
|
||||
server.listen(config.port,config.bindip,function(){
|
||||
console.log(lang.Shinobi+' : Web Server Listening on '+config.port);
|
||||
});
|
||||
io.attach(server);
|
||||
if(config.webPaths.home !== '/'){
|
||||
io.attach(server,{
|
||||
path:'/socket.io',
|
||||
transports: ['websocket']
|
||||
})
|
||||
}
|
||||
io.attach(server,{
|
||||
path:s.checkCorrectPathEnding(config.webPaths.home)+'socket.io',
|
||||
transports: ['websocket']
|
||||
})
|
||||
io.attach(server,{
|
||||
path:s.checkCorrectPathEnding(config.webPaths.admin)+'socket.io',
|
||||
transports: ['websocket']
|
||||
})
|
||||
io.attach(server,{
|
||||
path:s.checkCorrectPathEnding(config.webPaths.super)+'socket.io',
|
||||
transports: ['websocket']
|
||||
})
|
||||
return app
|
||||
}
|
||||
|
|
|
@ -7,10 +7,6 @@ var exec = require('child_process').exec;
|
|||
var spawn = require('child_process').spawn;
|
||||
var execSync = require('child_process').execSync;
|
||||
module.exports = function(s,config,lang,app){
|
||||
var closeResponse = function(res,endData){
|
||||
res.setHeader('Content-Type', 'application/json')
|
||||
res.end(s.prettyPrint(endData))
|
||||
}
|
||||
/**
|
||||
* API : Administrator : Edit Sub-Account (Account to share cameras with)
|
||||
*/
|
||||
|
@ -21,7 +17,7 @@ module.exports = function(s,config,lang,app){
|
|||
}
|
||||
if(user.details.sub){
|
||||
endData.msg = user.lang['Not Permitted']
|
||||
closeResponse(res,endData)
|
||||
s.closeJsonResponse(res,endData)
|
||||
return
|
||||
}
|
||||
var form = s.getPostData(req)
|
||||
|
@ -56,7 +52,7 @@ module.exports = function(s,config,lang,app){
|
|||
}else{
|
||||
endData.msg = lang.postDataBroken
|
||||
}
|
||||
closeResponse(res,endData)
|
||||
s.closeJsonResponse(res,endData)
|
||||
},res,req)
|
||||
})
|
||||
/**
|
||||
|
@ -69,7 +65,7 @@ module.exports = function(s,config,lang,app){
|
|||
}
|
||||
if(user.details.sub){
|
||||
endData.msg = user.lang['Not Permitted']
|
||||
closeResponse(res,endData)
|
||||
s.closeJsonResponse(res,endData)
|
||||
return
|
||||
}
|
||||
var uid = s.getPostData(req,'uid',false)
|
||||
|
@ -90,7 +86,7 @@ module.exports = function(s,config,lang,app){
|
|||
mail: mail
|
||||
},'ADM_'+req.params.ke)
|
||||
endData.ok = true
|
||||
closeResponse(res,endData)
|
||||
s.closeJsonResponse(res,endData)
|
||||
},res,req)
|
||||
})
|
||||
/**
|
||||
|
@ -109,7 +105,7 @@ module.exports = function(s,config,lang,app){
|
|||
s.auth(req.params,function(user){
|
||||
if(user.details.sub){
|
||||
endData.msg = user.lang['Not an Administrator Account']
|
||||
closeResponse(res,endData)
|
||||
s.closeJsonResponse(res,endData)
|
||||
return
|
||||
}
|
||||
var form = s.getPostData(req)
|
||||
|
@ -159,7 +155,9 @@ module.exports = function(s,config,lang,app){
|
|||
config.webPaths.adminApiPrefix+':auth/configureMonitor/:ke/:id',
|
||||
config.webPaths.adminApiPrefix+':auth/configureMonitor/:ke/:id/:f'
|
||||
], function (req,res){
|
||||
req.ret={ok:false};
|
||||
var endData = {
|
||||
ok: false
|
||||
}
|
||||
res.setHeader('Content-Type', 'application/json');
|
||||
res.header("Access-Control-Allow-Origin",req.headers.origin);
|
||||
s.auth(req.params,function(user){
|
||||
|
@ -167,88 +165,28 @@ module.exports = function(s,config,lang,app){
|
|||
if(req.params.f !== 'delete'){
|
||||
var form = s.getPostData(req)
|
||||
if(!form){
|
||||
req.ret.msg = user.lang.monitorEditText1;
|
||||
res.end(s.prettyPrint(req.ret))
|
||||
return
|
||||
endData.msg = user.lang.monitorEditText1;
|
||||
res.end(s.prettyPrint(endData))
|
||||
return
|
||||
}
|
||||
form.mid = req.params.id.replace(/[^\w\s]/gi,'').replace(/ /g,'')
|
||||
if(!user.details.sub ||
|
||||
user.details.allmonitors === '1' ||
|
||||
hasRestrictions && user.details.monitor_edit.indexOf(form.mid) >- 1 ||
|
||||
hasRestrictions && user.details.monitor_create === '1'){
|
||||
if(form&&form.mid&&form.name){
|
||||
req.set=[],req.ar=[];
|
||||
form.mid=req.params.id.replace(/[^\w\s]/gi,'').replace(/ /g,'');
|
||||
try{
|
||||
JSON.parse(form.details)
|
||||
}catch(er){
|
||||
if(!form.details||!form.details.stream_type){
|
||||
req.ret.msg=user.lang.monitorEditText2;
|
||||
res.end(s.prettyPrint(req.ret))
|
||||
return
|
||||
}else{
|
||||
form.details=JSON.stringify(form.details)
|
||||
}
|
||||
}
|
||||
form.ke=req.params.ke
|
||||
req.logObject={details:JSON.parse(form.details),ke:req.params.ke,mid:req.params.id}
|
||||
s.sqlQuery('SELECT * FROM Monitors WHERE ke=? AND mid=?',[form.ke,form.mid],function(er,r){
|
||||
req.tx={f:'monitor_edit',mid:form.mid,ke:form.ke,mon:form};
|
||||
if(r&&r[0]){
|
||||
req.tx.new=false;
|
||||
Object.keys(form).forEach(function(v){
|
||||
if(form[v]&&form[v]!==''){
|
||||
req.set.push(v+'=?'),req.ar.push(form[v]);
|
||||
}
|
||||
})
|
||||
req.set=req.set.join(',');
|
||||
req.ar.push(form.ke),req.ar.push(form.mid);
|
||||
s.userLog(form,{type:'Monitor Updated',msg:'by user : '+user.uid});
|
||||
req.ret.msg=user.lang['Monitor Updated by user']+' : '+user.uid;
|
||||
s.sqlQuery('UPDATE Monitors SET '+req.set+' WHERE ke=? AND mid=?',req.ar)
|
||||
req.finish=1;
|
||||
}else{
|
||||
if(!s.group[form.ke].init.max_camera||s.group[form.ke].init.max_camera==''||Object.keys(s.group[form.ke].mon).length <= parseInt(s.group[form.ke].init.max_camera)){
|
||||
req.tx.new=true;
|
||||
req.st=[];
|
||||
Object.keys(form).forEach(function(v){
|
||||
if(form[v]&&form[v]!==''){
|
||||
req.set.push(v),req.st.push('?'),req.ar.push(form[v]);
|
||||
}
|
||||
})
|
||||
// req.set.push('ke'),req.st.push('?'),req.ar.push(form.ke);
|
||||
req.set=req.set.join(','),req.st=req.st.join(',');
|
||||
s.userLog(form,{type:'Monitor Added',msg:'by user : '+user.uid});
|
||||
req.ret.msg=user.lang['Monitor Added by user']+' : '+user.uid;
|
||||
s.sqlQuery('INSERT INTO Monitors ('+req.set+') VALUES ('+req.st+')',req.ar)
|
||||
req.finish=1;
|
||||
}else{
|
||||
req.tx.f='monitor_edit_failed';
|
||||
req.tx.ff='max_reached';
|
||||
req.ret.msg=user.lang.monitorEditFailedMaxReached;
|
||||
}
|
||||
}
|
||||
if(req.finish===1){
|
||||
form.details=JSON.parse(form.details)
|
||||
req.ret.ok=true;
|
||||
s.initiateMonitorObject({mid:form.mid,ke:form.ke});
|
||||
s.group[form.ke].mon_conf[form.mid]=s.cleanMonitorObject(form);
|
||||
if(form.mode==='stop'){
|
||||
s.camera('stop',form);
|
||||
}else{
|
||||
s.camera('stop',form);setTimeout(function(){s.camera(form.mode,form);},5000)
|
||||
};
|
||||
s.tx(req.tx,'STR_'+form.ke);
|
||||
};
|
||||
s.tx(req.tx,'GRP_'+form.ke);
|
||||
res.end(s.prettyPrint(req.ret))
|
||||
})
|
||||
if(form && form.name){
|
||||
s.checkDetails(form)
|
||||
form.ke = req.params.ke
|
||||
s.addOrEditMonitor(form,function(err,endData){
|
||||
res.end(s.prettyPrint(endData))
|
||||
},user)
|
||||
}else{
|
||||
req.ret.msg=user.lang.monitorEditText1;
|
||||
res.end(s.prettyPrint(req.ret))
|
||||
endData.msg = user.lang.monitorEditText1;
|
||||
res.end(s.prettyPrint(endData))
|
||||
}
|
||||
}else{
|
||||
req.ret.msg=user.lang['Not Permitted'];
|
||||
res.end(s.prettyPrint(req.ret))
|
||||
endData.msg = user.lang['Not Permitted']
|
||||
res.end(s.prettyPrint(endData))
|
||||
}
|
||||
}else{
|
||||
if(!user.details.sub || user.details.allmonitors === '1' || user.details.monitor_edit.indexOf(req.params.id) > -1 || hasRestrictions && user.details.monitor_create === '1'){
|
||||
|
@ -281,12 +219,12 @@ module.exports = function(s,config,lang,app){
|
|||
}
|
||||
})
|
||||
}
|
||||
req.ret.ok=true;
|
||||
req.ret.msg='Monitor Deleted by user : '+user.uid
|
||||
res.end(s.prettyPrint(req.ret))
|
||||
endData.ok=true;
|
||||
endData.msg='Monitor Deleted by user : '+user.uid
|
||||
res.end(s.prettyPrint(endData))
|
||||
}else{
|
||||
req.ret.msg=user.lang['Not Permitted'];
|
||||
res.end(s.prettyPrint(req.ret))
|
||||
endData.msg=user.lang['Not Permitted'];
|
||||
res.end(s.prettyPrint(endData))
|
||||
}
|
||||
}
|
||||
},res,req)
|
||||
|
@ -328,11 +266,11 @@ module.exports = function(s,config,lang,app){
|
|||
},'GRP_' + req.params.ke)
|
||||
endData.ok = true
|
||||
}
|
||||
closeResponse(res,endData)
|
||||
s.closeJsonResponse(res,endData)
|
||||
})
|
||||
}else{
|
||||
endData.msg = lang.postDataBroken
|
||||
closeResponse(res,endData)
|
||||
s.closeJsonResponse(res,endData)
|
||||
}
|
||||
},res,req)
|
||||
})
|
||||
|
@ -359,7 +297,7 @@ module.exports = function(s,config,lang,app){
|
|||
form:'APIs'
|
||||
},'GRP_' + req.params.ke)
|
||||
endData.msg = lang.postDataBroken
|
||||
closeResponse(res,endData)
|
||||
s.closeJsonResponse(res,endData)
|
||||
return
|
||||
}
|
||||
var row = {
|
||||
|
@ -381,11 +319,11 @@ module.exports = function(s,config,lang,app){
|
|||
endData.ok = true
|
||||
delete(s.api[row.code])
|
||||
}
|
||||
closeResponse(res,endData)
|
||||
s.closeJsonResponse(res,endData)
|
||||
})
|
||||
}else{
|
||||
endData.msg = lang.postDataBroken
|
||||
closeResponse(res,endData)
|
||||
s.closeJsonResponse(res,endData)
|
||||
}
|
||||
},res,req)
|
||||
})
|
||||
|
@ -421,8 +359,143 @@ module.exports = function(s,config,lang,app){
|
|||
endData.ke = user.ke
|
||||
endData.keys = rows
|
||||
}
|
||||
closeResponse(res,endData)
|
||||
s.closeJsonResponse(res,endData)
|
||||
})
|
||||
},res,req)
|
||||
})
|
||||
/**
|
||||
* API : Administrator : Change Group Preset. Currently affects Monitors only.
|
||||
*/
|
||||
app.all([
|
||||
config.webPaths.apiPrefix+':auth/monitorStates/:ke/:stateName',
|
||||
config.webPaths.apiPrefix+':auth/monitorStates/:ke/:stateName/:action',
|
||||
config.webPaths.adminApiPrefix+':auth/monitorStates/:ke/:stateName',
|
||||
config.webPaths.adminApiPrefix+':auth/monitorStates/:ke/:stateName/:action',
|
||||
],function (req,res){
|
||||
s.auth(req.params,function(user){
|
||||
var endData = {
|
||||
ok : false
|
||||
}
|
||||
if(user.details.sub){
|
||||
endData.msg = user.lang['Not Permitted']
|
||||
s.closeJsonResponse(res,endData)
|
||||
return
|
||||
}
|
||||
var findPreset = function(callback){
|
||||
s.sqlQuery("SELECT * FROM Presets WHERE ke=? AND type=? AND name=? LIMIT 1",[req.params.ke,'monitorStates',req.params.stateName],function(err,presets){
|
||||
var preset
|
||||
var notFound = false
|
||||
if(presets && presets[0]){
|
||||
preset = presets[0]
|
||||
s.checkDetails(preset)
|
||||
}else{
|
||||
notFound = true
|
||||
}
|
||||
callback(notFound,preset)
|
||||
})
|
||||
}
|
||||
switch(req.params.action){
|
||||
case'insert':case'edit':
|
||||
var form = s.getPostData(req)
|
||||
s.checkDetails(form)
|
||||
if(!form || !form.monitors){
|
||||
endData.msg = user.lang['Form Data Not Found']
|
||||
s.closeJsonResponse(res,endData)
|
||||
return
|
||||
}
|
||||
findPreset(function(notFound,preset){
|
||||
if(notFound === true){
|
||||
endData.msg = lang["Inserted State Configuration"]
|
||||
var details = {
|
||||
monitors : form.monitors
|
||||
}
|
||||
var insertData = {
|
||||
ke: req.params.ke,
|
||||
name: req.params.stateName,
|
||||
details: s.s(details),
|
||||
type: 'monitorStates'
|
||||
}
|
||||
s.sqlQuery('INSERT INTO Presets ('+Object.keys(insertData).join(',')+') VALUES (?,?,?,?)',Object.values(insertData))
|
||||
s.tx({
|
||||
f: 'add_group_state',
|
||||
details: details,
|
||||
ke: req.params.ke,
|
||||
name: req.params.stateName
|
||||
},'GRP_'+req.params.ke)
|
||||
}else{
|
||||
endData.msg = lang["Edited State Configuration"]
|
||||
var details = Object.assign(preset.details,{
|
||||
monitors : form.monitors
|
||||
})
|
||||
s.sqlQuery('UPDATE Presets SET details=? WHERE ke=? AND name=?',[s.s(details),req.params.ke,req.params.stateName])
|
||||
s.tx({
|
||||
f: 'edit_group_state',
|
||||
details: details,
|
||||
ke: req.params.ke,
|
||||
name: req.params.stateName
|
||||
},'GRP_'+req.params.ke)
|
||||
}
|
||||
endData.ok = true
|
||||
s.closeJsonResponse(res,endData)
|
||||
})
|
||||
break;
|
||||
case'delete':
|
||||
findPreset(function(notFound,preset){
|
||||
if(notFound === true){
|
||||
endData.msg = user.lang['State Configuration Not Found']
|
||||
s.closeJsonResponse(res,endData)
|
||||
}else{
|
||||
s.sqlQuery('DELETE FROM Presets WHERE ke=? AND name=?',[req.params.ke,req.params.stateName],function(err){
|
||||
if(!err){
|
||||
endData.msg = lang["Deleted State Configuration"]
|
||||
endData.ok = true
|
||||
}
|
||||
s.closeJsonResponse(res,endData)
|
||||
})
|
||||
}
|
||||
})
|
||||
break;
|
||||
default://change monitors according to state
|
||||
findPreset(function(notFound,preset){
|
||||
if(notFound === false){
|
||||
var sqlQuery = 'SELECT * FROM Monitors WHERE ke=? AND '
|
||||
var monitorQuery = []
|
||||
var sqlQueryValues = [req.params.ke]
|
||||
var monitorPresets = {}
|
||||
preset.details.monitors.forEach(function(monitor){
|
||||
monitorQuery.push('mid=?')
|
||||
sqlQueryValues.push(monitor.mid)
|
||||
monitorPresets[monitor.mid] = monitor
|
||||
})
|
||||
sqlQuery += '('+monitorQuery.join(' OR ')+')'
|
||||
s.sqlQuery(sqlQuery,sqlQueryValues,function(err,monitors){
|
||||
if(monitors && monitors[0]){
|
||||
monitors.forEach(function(monitor){
|
||||
s.checkDetails(monitor)
|
||||
s.checkDetails(monitorPresets[monitor.mid])
|
||||
var monitorPreset = monitorPresets[monitor.mid]
|
||||
monitorPreset.details = Object.assign(monitor.details,monitorPreset.details)
|
||||
monitor = s.cleanMonitorObjectForDatabase(Object.assign(monitor,monitorPreset))
|
||||
monitor.details = JSON.stringify(monitor.details)
|
||||
s.addOrEditMonitor(Object.assign(monitor,{}),function(err,endData){
|
||||
|
||||
},user)
|
||||
})
|
||||
endData.ok = true
|
||||
s.tx({f:'change_group_state',ke:req.params.ke,name:req.params.stateName},'GRP_'+req.params.ke)
|
||||
s.closeJsonResponse(res,endData)
|
||||
}else{
|
||||
endData.msg = user.lang['State Configuration has no monitors associated']
|
||||
s.closeJsonResponse(res,endData)
|
||||
}
|
||||
})
|
||||
}else{
|
||||
endData.msg = user.lang['State Configuration Not Found']
|
||||
s.closeJsonResponse(res,endData)
|
||||
}
|
||||
})
|
||||
break;
|
||||
}
|
||||
},res,req)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -11,54 +11,15 @@ var httpProxy = require('http-proxy');
|
|||
var proxy = httpProxy.createProxyServer({})
|
||||
var ejs = require('ejs');
|
||||
var CircularJSON = require('circular-json');
|
||||
module.exports = function(s,config,lang,app){
|
||||
module.exports = function(s,config,lang,app,io){
|
||||
if(config.productType==='Pro'){
|
||||
var LdapAuth = require('ldapauth-fork');
|
||||
}
|
||||
//get page URL
|
||||
if(!config.baseURL){
|
||||
config.baseURL = ""
|
||||
}else if(config.baseURL !== ''){
|
||||
config.baseURL = s.checkCorrectPathEnding(config.baseURL)
|
||||
s.renderPage = function(req,res,paths,passables,callback){
|
||||
passables.window = {}
|
||||
passables.originalURL = s.getOriginalUrl(req)
|
||||
res.render(paths,passables,callback)
|
||||
}
|
||||
//Render Configurations - Web Paths
|
||||
if(config.webPaths === undefined){config.webPaths={}}
|
||||
//main access URI
|
||||
if(config.webPaths.home === undefined){config.webPaths.home='/'}
|
||||
//Super User URI
|
||||
if(config.webPaths.super === undefined){config.webPaths.super='/super'}
|
||||
//Admin URI
|
||||
if(config.webPaths.admin === undefined){config.webPaths.admin='/admin'}
|
||||
//API Prefix
|
||||
if(config.webPaths.apiPrefix === undefined){config.webPaths.apiPrefix='/'}else{config.webPaths.apiPrefix = s.checkCorrectPathEnding(config.webPaths.apiPrefix)}
|
||||
//Admin API Prefix
|
||||
if(config.webPaths.adminApiPrefix === undefined){config.webPaths.adminApiPrefix='/admin/'}else{config.webPaths.adminApiPrefix = s.checkCorrectPathEnding(config.webPaths.adminApiPrefix)}
|
||||
//Super API Prefix
|
||||
if(config.webPaths.superApiPrefix === undefined){config.webPaths.superApiPrefix='/super/'}else{config.webPaths.superApiPrefix = s.checkCorrectPathEnding(config.webPaths.superApiPrefix)}
|
||||
//Render Configurations - Page Render Paths
|
||||
if(config.renderPaths === undefined){config.renderPaths={}}
|
||||
//login page
|
||||
if(config.renderPaths.index === undefined){config.renderPaths.index='pages/index'}
|
||||
//dashboard page
|
||||
if(config.renderPaths.home === undefined){config.renderPaths.home='pages/home'}
|
||||
//sub-account administration page
|
||||
if(config.renderPaths.admin === undefined){config.renderPaths.admin='pages/admin'}
|
||||
//superuser page
|
||||
if(config.renderPaths.super === undefined){config.renderPaths.super='pages/super'}
|
||||
//2-Factor Auth page
|
||||
if(config.renderPaths.factorAuth === undefined){config.renderPaths.factorAuth='pages/factor'}
|
||||
//Streamer v1 (Dashcam Prototype) page
|
||||
if(config.renderPaths.streamer === undefined){config.renderPaths.streamer='pages/streamer'}
|
||||
//Streamer v2 (Dashcam) page
|
||||
if(config.renderPaths.dashcam === undefined){config.renderPaths.dashcam='pages/dashcam'}
|
||||
//embeddable widget page
|
||||
if(config.renderPaths.embed === undefined){config.renderPaths.embed='pages/embed'}
|
||||
//mjpeg full screen page
|
||||
if(config.renderPaths.mjpeg === undefined){config.renderPaths.mjpeg='pages/mjpeg'}
|
||||
//gridstack only page
|
||||
if(config.renderPaths.grid === undefined){config.renderPaths.grid='pages/grid'}
|
||||
//slick.js (cycle) page
|
||||
if(config.renderPaths.cycle === undefined){config.renderPaths.cycle='pages/cycle'}
|
||||
//child node proxy check
|
||||
//params = parameters
|
||||
//cb = callback
|
||||
|
@ -72,6 +33,10 @@ module.exports = function(s,config,lang,app){
|
|||
cb()
|
||||
}
|
||||
}
|
||||
s.closeJsonResponse = function(res,endData){
|
||||
res.setHeader('Content-Type', 'application/json')
|
||||
res.end(s.prettyPrint(endData))
|
||||
}
|
||||
//get post data
|
||||
s.getPostData = function(req,target,parseJSON){
|
||||
if(!target)target = 'data'
|
||||
|
@ -93,13 +58,18 @@ module.exports = function(s,config,lang,app){
|
|||
}
|
||||
////Pages
|
||||
app.enable('trust proxy');
|
||||
app.use('/libs',express.static(s.mainDirectory + '/web/libs'));
|
||||
if(config.webPaths.home !== '/'){
|
||||
app.use('/libs',express.static(s.mainDirectory + '/web/libs'))
|
||||
}
|
||||
app.use(s.checkCorrectPathEnding(config.webPaths.home)+'libs',express.static(s.mainDirectory + '/web/libs'))
|
||||
app.use(s.checkCorrectPathEnding(config.webPaths.admin)+'libs',express.static(s.mainDirectory + '/web/libs'))
|
||||
app.use(s.checkCorrectPathEnding(config.webPaths.super)+'libs',express.static(s.mainDirectory + '/web/libs'))
|
||||
app.use(bodyParser.json());
|
||||
app.use(bodyParser.urlencoded({extended: true}));
|
||||
app.set('views', s.mainDirectory + '/web');
|
||||
app.set('view engine','ejs');
|
||||
//add template handler
|
||||
if(config.renderPaths.handler!==undefined){require(s.mainDirectory+'/web/'+config.renderPaths.handler+'.js').addHandlers(s,app,io)}
|
||||
if(config.renderPaths.handler!==undefined){require(s.mainDirectory+'/web/'+config.renderPaths.handler+'.js').addHandlers(s,app,io,config)}
|
||||
|
||||
/**
|
||||
* API : Logout
|
||||
|
@ -118,7 +88,7 @@ module.exports = function(s,config,lang,app){
|
|||
* Page : Login Screen
|
||||
*/
|
||||
app.get(config.webPaths.home, function (req,res){
|
||||
res.render(config.renderPaths.index,{lang:lang,config:config,screen:'dashboard',originalURL:s.getOriginalUrl(req)},function(err,html){
|
||||
s.renderPage(req,res,config.renderPaths.index,{lang:lang,config:config,screen:'dashboard'},function(err,html){
|
||||
if(err){
|
||||
s.systemLog(err)
|
||||
}
|
||||
|
@ -129,7 +99,7 @@ module.exports = function(s,config,lang,app){
|
|||
* Page : Administrator Login Screen
|
||||
*/
|
||||
app.get(config.webPaths.admin, function (req,res){
|
||||
res.render(config.renderPaths.index,{lang:lang,config:config,screen:'admin',originalURL:s.getOriginalUrl(req)},function(err,html){
|
||||
s.renderPage(req,res,config.renderPaths.index,{lang:lang,config:config,screen:'admin'},function(err,html){
|
||||
if(err){
|
||||
s.systemLog(err)
|
||||
}
|
||||
|
@ -141,7 +111,7 @@ module.exports = function(s,config,lang,app){
|
|||
*/
|
||||
app.get(config.webPaths.super, function (req,res){
|
||||
|
||||
res.render(config.renderPaths.index,{lang:lang,config:config,screen:'super',originalURL:s.getOriginalUrl(req)},function(err,html){
|
||||
s.renderPage(req,res,config.renderPaths.index,{lang:lang,config:config,screen:'super'},function(err,html){
|
||||
if(err){
|
||||
s.systemLog(err)
|
||||
}
|
||||
|
@ -171,23 +141,48 @@ module.exports = function(s,config,lang,app){
|
|||
/**
|
||||
* API : Login handler. Dashboard, Streamer, Dashcam Administrator, Superuser
|
||||
*/
|
||||
app.post([config.webPaths.home,s.checkCorrectPathEnding(config.webPaths.home)+':screen'],function (req,res){
|
||||
app.post([
|
||||
config.webPaths.home,
|
||||
config.webPaths.admin,
|
||||
config.webPaths.super,
|
||||
s.checkCorrectPathEnding(config.webPaths.home)+':screen',
|
||||
s.checkCorrectPathEnding(config.webPaths.admin)+':screen',
|
||||
s.checkCorrectPathEnding(config.webPaths.super)+':screen',
|
||||
],function (req,res){
|
||||
req.ip = s.getClientIp(req)
|
||||
if(req.query.json === 'true'){
|
||||
res.header("Access-Control-Allow-Origin",req.headers.origin);
|
||||
}
|
||||
var screenChooser = function(screen){
|
||||
var search = function(screen){
|
||||
if(req.url.indexOf(screen) > -1){
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
switch(true){
|
||||
case search(config.webPaths.admin):
|
||||
return 'admin'
|
||||
break;
|
||||
case search(config.webPaths.super):
|
||||
return 'super'
|
||||
break;
|
||||
default:
|
||||
return 'dashboard'
|
||||
break;
|
||||
}
|
||||
}
|
||||
// brute check
|
||||
if(s.failedLoginAttempts[req.body.mail] && s.failedLoginAttempts[req.body.mail].failCount >= 5){
|
||||
if(req.query.json=='true'){
|
||||
res.end(s.prettyPrint({ok:false}))
|
||||
}else{
|
||||
res.render(config.renderPaths.index,{
|
||||
failedLogin:true,
|
||||
message:lang.failedLoginText1,
|
||||
lang:lang,
|
||||
config:config,
|
||||
screen:req.params.screen,
|
||||
originalURL:s.getOriginalUrl(req)
|
||||
s.renderPage(req,res,config.renderPaths.index,{
|
||||
failedLogin: true,
|
||||
message: lang.failedLoginText1,
|
||||
lang: lang,
|
||||
config: config,
|
||||
screen: screenChooser(req.params.screen)
|
||||
},function(err,html){
|
||||
if(err){
|
||||
s.systemLog(err)
|
||||
|
@ -209,9 +204,8 @@ module.exports = function(s,config,lang,app){
|
|||
res.setHeader('Content-Type', 'application/json');
|
||||
res.end(s.prettyPrint(data))
|
||||
}else{
|
||||
data.originalURL = s.getOriginalUrl(req)
|
||||
data.screen=req.params.screen
|
||||
res.render(focus,data,function(err,html){
|
||||
s.renderPage(req,res,focus,data,function(err,html){
|
||||
if(err){
|
||||
s.systemLog(err)
|
||||
}
|
||||
|
@ -241,13 +235,12 @@ module.exports = function(s,config,lang,app){
|
|||
res.setHeader('Content-Type', 'application/json')
|
||||
res.end(s.prettyPrint({ok:false}))
|
||||
}else{
|
||||
res.render(config.renderPaths.index,{
|
||||
failedLogin:true,
|
||||
message:lang.failedLoginText2,
|
||||
lang:lang,
|
||||
config:config,
|
||||
screen:req.params.screen,
|
||||
originalURL:s.getOriginalUrl(req)
|
||||
s.renderPage(req,res,config.renderPaths.index,{
|
||||
failedLogin: true,
|
||||
message: lang.failedLoginText2,
|
||||
lang: lang,
|
||||
config: config,
|
||||
screen: screenChooser(req.params.screen)
|
||||
},function(err,html){
|
||||
if(err){
|
||||
s.systemLog(err)
|
||||
|
@ -344,7 +337,7 @@ module.exports = function(s,config,lang,app){
|
|||
r.details=JSON.parse(r.details);
|
||||
r.lang=s.getLanguageFile(r.details.lang)
|
||||
req.factorAuth=function(cb){
|
||||
if(r.details.factorAuth==="1"){
|
||||
if(r.details.factorAuth === "1"){
|
||||
if(!r.details.acceptedMachines||!(r.details.acceptedMachines instanceof Object)){
|
||||
r.details.acceptedMachines={}
|
||||
}
|
||||
|
@ -671,14 +664,13 @@ module.exports = function(s,config,lang,app){
|
|||
if(req.path.indexOf('/cycle/') > -1){
|
||||
page = config.renderPaths.cycle
|
||||
}
|
||||
res.render(page,{
|
||||
s.renderPage(req,res,page,{
|
||||
data:Object.assign(req.params,req.query),
|
||||
baseUrl:req.protocol+'://'+req.hostname,
|
||||
config:config,
|
||||
lang:user.lang,
|
||||
$user:user,
|
||||
monitors:r,
|
||||
originalURL:s.getOriginalUrl(req),
|
||||
query:req.query
|
||||
});
|
||||
})
|
||||
|
@ -1490,17 +1482,22 @@ module.exports = function(s,config,lang,app){
|
|||
req.ext=req.params.file.split('.')[1];
|
||||
var total = fs.statSync(req.dir).size;
|
||||
if (req.headers['range']) {
|
||||
var range = req.headers.range;
|
||||
var parts = range.replace(/bytes=/, "").split("-");
|
||||
var partialstart = parts[0];
|
||||
var partialend = parts[1];
|
||||
|
||||
var start = parseInt(partialstart, 10);
|
||||
var end = partialend ? parseInt(partialend, 10) : total-1;
|
||||
var chunksize = (end-start)+1;
|
||||
var file = fs.createReadStream(req.dir, {start: start, end: end});
|
||||
req.headerWrite={ 'Content-Range': 'bytes ' + start + '-' + end + '/' + total, 'Accept-Ranges': 'bytes', 'Content-Length': chunksize, 'Content-Type': 'video/'+req.ext }
|
||||
req.writeCode=206
|
||||
try{
|
||||
var range = req.headers.range;
|
||||
var parts = range.replace(/bytes=/, "").split("-");
|
||||
var partialstart = parts[0];
|
||||
var partialend = parts[1];
|
||||
var start = parseInt(partialstart, 10);
|
||||
var end = partialend ? parseInt(partialend, 10) : total-1;
|
||||
var chunksize = (end-start)+1;
|
||||
var file = fs.createReadStream(req.dir, {start: start, end: end});
|
||||
req.headerWrite={ 'Content-Range': 'bytes ' + start + '-' + end + '/' + total, 'Accept-Ranges': 'bytes', 'Content-Length': chunksize, 'Content-Type': 'video/'+req.ext }
|
||||
req.writeCode=206
|
||||
}catch(err){
|
||||
req.headerWrite={ 'Content-Length': total, 'Content-Type': 'video/'+req.ext};
|
||||
var file = fs.createReadStream(req.dir)
|
||||
req.writeCode=200
|
||||
}
|
||||
} else {
|
||||
req.headerWrite={ 'Content-Length': total, 'Content-Type': 'video/'+req.ext};
|
||||
var file=fs.createReadStream(req.dir)
|
||||
|
@ -1844,4 +1841,27 @@ module.exports = function(s,config,lang,app){
|
|||
}
|
||||
},res,req);
|
||||
})
|
||||
/**
|
||||
* API : Account Edit from Dashboard
|
||||
*/
|
||||
app.all(config.webPaths.apiPrefix+':auth/accounts/:ke/edit',function (req,res){
|
||||
s.auth(req.params,function(user){
|
||||
var endData = {
|
||||
ok : false
|
||||
}
|
||||
var form = s.getPostData(req)
|
||||
if(form){
|
||||
endData.ok = true
|
||||
s.accountSettingsEdit({
|
||||
ke: req.params.ke,
|
||||
uid: user.uid,
|
||||
form: form,
|
||||
cnid: user.cnid
|
||||
})
|
||||
}else{
|
||||
endData.msg = lang.postDataBroken
|
||||
}
|
||||
s.closeJsonResponse(res,endData)
|
||||
},res,req)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ module.exports = function(s,config,lang,app){
|
|||
if(s.group[req.params.ke]&&s.group[req.params.ke].mon[req.params.id]){
|
||||
if(s.group[req.params.ke].mon[req.params.id].isStarted === true){
|
||||
req.params.uid=user.uid;
|
||||
res.render(config.renderPaths.embed,{data:req.params,baseUrl:req.protocol+'://'+req.hostname,config:config,lang:user.lang,mon:CircularJSON.parse(CircularJSON.stringify(s.group[req.params.ke].mon_conf[req.params.id])),originalURL:s.getOriginalUrl(req)});
|
||||
s.renderPage(req,res,config.renderPaths.embed,{data:req.params,baseUrl:req.protocol+'://'+req.hostname,config:config,lang:user.lang,mon:CircularJSON.parse(CircularJSON.stringify(s.group[req.params.ke].mon_conf[req.params.id])),originalURL:s.getOriginalUrl(req)});
|
||||
res.end()
|
||||
}else{
|
||||
res.end(user.lang['Cannot watch a monitor that isn\'t running.'])
|
||||
|
@ -102,7 +102,7 @@ module.exports = function(s,config,lang,app){
|
|||
app.get([config.webPaths.apiPrefix+':auth/mjpeg/:ke/:id',config.webPaths.apiPrefix+':auth/mjpeg/:ke/:id/:channel'], function(req,res) {
|
||||
res.header("Access-Control-Allow-Origin",req.headers.origin);
|
||||
if(req.query.full=='true'){
|
||||
res.render(config.renderPaths.mjpeg,{url:'/'+req.params.auth+'/mjpeg/'+req.params.ke+'/'+req.params.id,originalURL:s.getOriginalUrl(req)});
|
||||
s.renderPage(req,res,config.renderPaths.mjpeg,{url:config.webPaths.apiPrefix + req.params.auth+'/mjpeg/'+req.params.ke+'/'+req.params.id,originalURL:s.getOriginalUrl(req)});
|
||||
res.end()
|
||||
}else{
|
||||
s.auth(req.params,function(user){
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue