Merge branch 'release-1.34'
This commit is contained in:
commit
d716d1d686
|
@ -299,7 +299,7 @@ void Image::Deinitialise() {
|
|||
void Image::Initialise() {
|
||||
/* Assign the blend pointer to function */
|
||||
if ( config.fast_image_blends ) {
|
||||
if ( config.cpu_extensions && sseversion >= 20 ) {
|
||||
if ( config.cpu_extensions && sse_version >= 20 ) {
|
||||
fptr_blend = &sse2_fastblend; /* SSE2 fast blend */
|
||||
Debug(4, "Blend: Using SSE2 fast blend function");
|
||||
} else if ( config.cpu_extensions && neonversion >= 1 ) {
|
||||
|
@ -356,7 +356,7 @@ void Image::Initialise() {
|
|||
|
||||
/* Assign the delta functions */
|
||||
if ( config.cpu_extensions ) {
|
||||
if ( sseversion >= 35 ) {
|
||||
if ( sse_version >= 35 ) {
|
||||
/* SSSE3 available */
|
||||
fptr_delta8_rgba = &ssse3_delta8_rgba;
|
||||
fptr_delta8_bgra = &ssse3_delta8_bgra;
|
||||
|
@ -364,7 +364,7 @@ void Image::Initialise() {
|
|||
fptr_delta8_abgr = &ssse3_delta8_abgr;
|
||||
fptr_delta8_gray8 = &sse2_delta8_gray8;
|
||||
Debug(4, "Delta: Using SSSE3 delta functions");
|
||||
} else if ( sseversion >= 20 ) {
|
||||
} else if ( sse_version >= 20 ) {
|
||||
/* SSE2 available */
|
||||
fptr_delta8_rgba = &sse2_delta8_rgba;
|
||||
fptr_delta8_bgra = &sse2_delta8_bgra;
|
||||
|
@ -468,7 +468,7 @@ void Image::Initialise() {
|
|||
|
||||
#if defined(__i386__) && !defined(__x86_64__)
|
||||
/* Use SSE2 aligned memory copy? */
|
||||
if ( config.cpu_extensions && sseversion >= 20 ) {
|
||||
if ( config.cpu_extensions && sse_version >= 20 ) {
|
||||
fptr_imgbufcpy = &sse2_aligned_memcpy;
|
||||
Debug(4, "Image buffer copy: Using SSE2 aligned memcpy");
|
||||
} else {
|
||||
|
@ -480,52 +480,12 @@ void Image::Initialise() {
|
|||
Debug(4, "Image buffer copy: Using standard memcpy");
|
||||
#endif
|
||||
|
||||
/* Code below relocated from zm_local_camera */
|
||||
Debug(3, "Setting up static colour tables");
|
||||
|
||||
y_table = y_table_global;
|
||||
uv_table = uv_table_global;
|
||||
r_v_table = r_v_table_global;
|
||||
g_v_table = g_v_table_global;
|
||||
g_u_table = g_u_table_global;
|
||||
b_u_table = b_u_table_global;
|
||||
/*
|
||||
y_table = new unsigned char[256];
|
||||
for ( int i = 0; i <= 255; i++ )
|
||||
{
|
||||
unsigned char c = i;
|
||||
if ( c <= 16 )
|
||||
y_table[c] = 0;
|
||||
else if ( c >= 235 )
|
||||
y_table[c] = 255;
|
||||
else
|
||||
y_table[c] = (255*(c-16))/219;
|
||||
}
|
||||
|
||||
uv_table = new signed char[256];
|
||||
for ( int i = 0; i <= 255; i++ )
|
||||
{
|
||||
unsigned char c = i;
|
||||
if ( c <= 16 )
|
||||
uv_table[c] = -127;
|
||||
else if ( c >= 240 )
|
||||
uv_table[c] = 127;
|
||||
else
|
||||
uv_table[c] = (127*(c-128))/112;
|
||||
}
|
||||
|
||||
r_v_table = new short[255];
|
||||
g_v_table = new short[255];
|
||||
g_u_table = new short[255];
|
||||
b_u_table = new short[255];
|
||||
for ( int i = 0; i < 255; i++ )
|
||||
{
|
||||
r_v_table[i] = (1402*(i-128))/1000;
|
||||
g_u_table[i] = (344*(i-128))/1000;
|
||||
g_v_table[i] = (714*(i-128))/1000;
|
||||
b_u_table[i] = (1772*(i-128))/1000;
|
||||
}
|
||||
*/
|
||||
|
||||
initialised = true;
|
||||
}
|
||||
|
@ -2179,7 +2139,7 @@ void Image::DeColourise() {
|
|||
subpixelorder = ZM_SUBPIX_ORDER_NONE;
|
||||
size = width * height;
|
||||
|
||||
if ( colours == ZM_COLOUR_RGB32 && config.cpu_extensions && sseversion >= 35 ) {
|
||||
if ( colours == ZM_COLOUR_RGB32 && config.cpu_extensions && sse_version >= 35 ) {
|
||||
/* Use SSSE3 functions */
|
||||
switch (subpixelorder) {
|
||||
case ZM_SUBPIX_ORDER_BGRA:
|
||||
|
|
|
@ -504,7 +504,7 @@ LocalCamera::LocalCamera(
|
|||
subpixelorder = ZM_SUBPIX_ORDER_NONE;
|
||||
} else if ( palette == V4L2_PIX_FMT_YUYV && colours == ZM_COLOUR_GRAY8 ) {
|
||||
/* Fast YUYV->Grayscale conversion by extracting the Y channel */
|
||||
if ( config.cpu_extensions && sseversion >= 35 ) {
|
||||
if ( config.cpu_extensions && sse_version >= 35 ) {
|
||||
conversion_fptr = &ssse3_convert_yuyv_gray8;
|
||||
Debug(2,"Using SSSE3 YUYV->grayscale fast conversion");
|
||||
} else {
|
||||
|
@ -616,7 +616,7 @@ LocalCamera::LocalCamera(
|
|||
}
|
||||
} else if ( (palette == VIDEO_PALETTE_YUYV || palette == VIDEO_PALETTE_YUV422) && colours == ZM_COLOUR_GRAY8 ) {
|
||||
/* Fast YUYV->Grayscale conversion by extracting the Y channel */
|
||||
if ( config.cpu_extensions && sseversion >= 35 ) {
|
||||
if ( config.cpu_extensions && sse_version >= 35 ) {
|
||||
conversion_fptr = &ssse3_convert_yuyv_gray8;
|
||||
Debug(2,"Using SSSE3 YUYV->grayscale fast conversion");
|
||||
} else {
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
#include <curl/curl.h>
|
||||
#endif
|
||||
|
||||
unsigned int sseversion = 0;
|
||||
unsigned int sse_version = 0;
|
||||
unsigned int neonversion = 0;
|
||||
|
||||
std::string trimSet(std::string str, std::string trimset) {
|
||||
|
@ -227,7 +227,7 @@ int pairsplit(const char* string, const char delim, std::string& name, std::stri
|
|||
/* Detect special hardware features, such as SIMD instruction sets */
|
||||
void hwcaps_detect() {
|
||||
neonversion = 0;
|
||||
sseversion = 0;
|
||||
sse_version = 0;
|
||||
#if (defined(__i386__) || defined(__x86_64__))
|
||||
/* x86 or x86-64 processor */
|
||||
uint32_t r_edx, r_ecx, r_ebx;
|
||||
|
@ -265,31 +265,31 @@ void hwcaps_detect() {
|
|||
#endif
|
||||
|
||||
if ( r_ebx & 0x00000020 ) {
|
||||
sseversion = 52; /* AVX2 */
|
||||
sse_version = 52; /* AVX2 */
|
||||
Debug(1, "Detected a x86\\x86-64 processor with AVX2");
|
||||
} else if ( r_ecx & 0x10000000 ) {
|
||||
sseversion = 51; /* AVX */
|
||||
sse_version = 51; /* AVX */
|
||||
Debug(1, "Detected a x86\\x86-64 processor with AVX");
|
||||
} else if ( r_ecx & 0x00100000 ) {
|
||||
sseversion = 42; /* SSE4.2 */
|
||||
sse_version = 42; /* SSE4.2 */
|
||||
Debug(1, "Detected a x86\\x86-64 processor with SSE4.2");
|
||||
} else if ( r_ecx & 0x00080000 ) {
|
||||
sseversion = 41; /* SSE4.1 */
|
||||
sse_version = 41; /* SSE4.1 */
|
||||
Debug(1, "Detected a x86\\x86-64 processor with SSE4.1");
|
||||
} else if ( r_ecx & 0x00000200 ) {
|
||||
sseversion = 35; /* SSSE3 */
|
||||
sse_version = 35; /* SSSE3 */
|
||||
Debug(1,"Detected a x86\\x86-64 processor with SSSE3");
|
||||
} else if ( r_ecx & 0x00000001 ) {
|
||||
sseversion = 30; /* SSE3 */
|
||||
sse_version = 30; /* SSE3 */
|
||||
Debug(1, "Detected a x86\\x86-64 processor with SSE3");
|
||||
} else if ( r_edx & 0x04000000 ) {
|
||||
sseversion = 20; /* SSE2 */
|
||||
sse_version = 20; /* SSE2 */
|
||||
Debug(1, "Detected a x86\\x86-64 processor with SSE2");
|
||||
} else if ( r_edx & 0x02000000 ) {
|
||||
sseversion = 10; /* SSE */
|
||||
sse_version = 10; /* SSE */
|
||||
Debug(1, "Detected a x86\\x86-64 processor with SSE");
|
||||
} else {
|
||||
sseversion = 0;
|
||||
sse_version = 0;
|
||||
Debug(1, "Detected a x86\\x86-64 processor");
|
||||
}
|
||||
#elif defined(__arm__)
|
||||
|
|
|
@ -59,7 +59,7 @@ void* sse2_aligned_memcpy(void* dest, const void* src, size_t bytes);
|
|||
void timespec_diff(struct timespec *start, struct timespec *end, struct timespec *diff);
|
||||
|
||||
void hwcaps_detect();
|
||||
extern unsigned int sseversion;
|
||||
extern unsigned int sse_version;
|
||||
extern unsigned int neonversion;
|
||||
|
||||
char *timeval_to_string( struct timeval tv );
|
||||
|
|
|
@ -229,7 +229,7 @@ bool Zone::CheckAlarms(const Image *delta_image) {
|
|||
|
||||
Debug(4, "Checking alarms for zone %d/%s in lines %d -> %d", id, label, lo_y, hi_y);
|
||||
|
||||
/* if(config.cpu_extensions && sseversion >= 20) {
|
||||
/* if(config.cpu_extensions && sse_version >= 20) {
|
||||
sse2_alarmedpixels(diff_image, pg_image, &alarm_pixels, &pixel_diff_count);
|
||||
} else {
|
||||
std_alarmedpixels(diff_image, pg_image, &alarm_pixels, &pixel_diff_count);
|
||||
|
|
|
@ -128,27 +128,3 @@ global $configvals;
|
|||
foreach( $configvals as $key => $value) {
|
||||
Configure::write($key, $value);
|
||||
}
|
||||
if ( 0 ) {
|
||||
// No longer needed, but I want to keep the code for reference
|
||||
//
|
||||
// For Human-readability, use ZM_SERVER_HOST or ZM_SERVER_NAME in zm.conf, and convert it here to a ZM_SERVER_ID
|
||||
if ( ! defined('ZM_SERVER_ID') ) {
|
||||
App::uses('ClassRegistry', 'Utility');
|
||||
$ServerModel = ClassRegistry::init('Server');
|
||||
if ( defined('ZM_SERVER_NAME') and ZM_SERVER_NAME ) {
|
||||
$Server = $ServerModel->find( 'first', array( 'conditions'=>array('Name'=>ZM_SERVER_NAME) ) );
|
||||
if ( ! $Server ) {
|
||||
Error('Invalid Multi-Server configration detected. ZM_SERVER_NAME set to ' . ZM_SERVER_NAME . ' in zm.conf, but no corresponding entry found in Servers table.');
|
||||
} else {
|
||||
define( 'ZM_SERVER_ID', $Server['Server']['Id'] );
|
||||
}
|
||||
} else if ( defined('ZM_SERVER_HOST') and ZM_SERVER_HOST ) {
|
||||
$Server = $ServerModel->find( 'first', array( 'conditions'=>array('Name'=>ZM_SERVER_HOST) ) );
|
||||
if ( ! $Server ) {
|
||||
Error('Invalid Multi-Server configration detected. ZM_SERVER_HOST set to ' . ZM_SERVER_HOST . ' in zm.conf, but no corresponding entry found in Servers table.');
|
||||
} else {
|
||||
define( 'ZM_SERVER_ID', $Server['Server']['Id'] );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,12 +36,6 @@ class UsersController extends AppController {
|
|||
* @return void
|
||||
*/
|
||||
public function view($id = null) {
|
||||
$this->loadModel('Config');
|
||||
$configs = $this->Config->find('list', array(
|
||||
'fields' => array('Name', 'Value'),
|
||||
'conditions' => array('Name' => array('ZM_DIR_EVENTS'))
|
||||
));
|
||||
|
||||
$this->User->recursive = 1;
|
||||
if (!$this->User->exists($id)) {
|
||||
throw new NotFoundException(__('Invalid user'));
|
||||
|
@ -130,12 +124,7 @@ class UsersController extends AppController {
|
|||
public function beforeFilter() {
|
||||
parent::beforeFilter();
|
||||
|
||||
$this->loadModel('Config');
|
||||
$configs = $this->Config->find('list', array(
|
||||
'fields' => array('Name', 'Value'),
|
||||
'conditions' => array('Name' => array('ZM_OPT_USE_AUTH'))
|
||||
));
|
||||
if ( $configs['ZM_OPT_USE_AUTH'] ) {
|
||||
if ( ZM_OPT_USE_AUTH ) {
|
||||
$this->Auth->allow('add', 'logout');
|
||||
} else {
|
||||
$this->Auth->allow();
|
||||
|
@ -143,13 +132,7 @@ class UsersController extends AppController {
|
|||
}
|
||||
|
||||
public function login() {
|
||||
$this->loadModel('Config');
|
||||
$configs = $this->Config->find('list', array(
|
||||
'fields' => array('Name', 'Value'),
|
||||
'conditions' => array('Name' => array('ZM_OPT_USE_AUTH'))
|
||||
));
|
||||
|
||||
if ( ! $configs['ZM_OPT_USE_AUTH'] ) {
|
||||
if ( !ZM_OPT_USE_AUTH ) {
|
||||
$this->set(array(
|
||||
'message' => 'Login is not required.',
|
||||
'_serialize' => array('message')
|
||||
|
@ -168,5 +151,4 @@ class UsersController extends AppController {
|
|||
public function logout() {
|
||||
return $this->redirect($this->Auth->logout());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@ class ZonesController extends AppController {
|
|||
'_serialize' => array('zones')
|
||||
));
|
||||
}
|
||||
|
||||
public function index() {
|
||||
$this->Zone->recursive = -1;
|
||||
|
||||
|
@ -63,7 +64,11 @@ class ZonesController extends AppController {
|
|||
* @return void
|
||||
*/
|
||||
public function add() {
|
||||
if ( $this->request->is('post') ) {
|
||||
|
||||
if ( !$this->request->is('post') ) {
|
||||
throw new BadRequestException(__('Invalid method. Should be post'));
|
||||
return;
|
||||
}
|
||||
|
||||
global $user;
|
||||
$canEdit = (!$user) || $user['Monitors'] == 'Edit';
|
||||
|
@ -72,14 +77,30 @@ class ZonesController extends AppController {
|
|||
return;
|
||||
}
|
||||
|
||||
$zone = null;
|
||||
|
||||
$this->Zone->create();
|
||||
if ( $this->Zone->save($this->request->data) ) {
|
||||
return $this->flash(__('The zone has been saved.'), array('action' => 'index'));
|
||||
$zone = $this->Zone->save($this->request->data);
|
||||
if ( $zone ) {
|
||||
require_once __DIR__ .'/../../../includes/Monitor.php';
|
||||
$monitor = new ZM\Monitor($zone['Zone']['MonitorId']);
|
||||
$monitor->zmaControl('restart');
|
||||
$message = 'Saved';
|
||||
//$zone = $this->Zone->find('first', array('conditions' => array( array('Zone.' . $this->Zone->primaryKey => $this->Zone),
|
||||
} else {
|
||||
$message = 'Error: ';
|
||||
// if there is a validation message, use it
|
||||
if ( !$this->Zone->validates() ) {
|
||||
$message = $this->Zone->validationErrors;
|
||||
}
|
||||
}
|
||||
$monitors = $this->Zone->Monitor->find('list');
|
||||
$this->set(compact('monitors'));
|
||||
}
|
||||
|
||||
$this->set(array(
|
||||
'message' => $message,
|
||||
'zone' => $zone,
|
||||
'_serialize' => array('message','zone')
|
||||
));
|
||||
} // end function add()
|
||||
|
||||
/**
|
||||
* edit method
|
||||
|
|
|
@ -3,8 +3,6 @@ App::uses('AppModel', 'Model');
|
|||
/**
|
||||
* User Model
|
||||
*
|
||||
* @property Monitor $Monitor
|
||||
* @property Frame $Frame
|
||||
*/
|
||||
class User extends AppModel {
|
||||
|
||||
|
@ -53,14 +51,6 @@ class User extends AppModel {
|
|||
* @var array
|
||||
*/
|
||||
public $belongsTo = array(
|
||||
/*'Monitor' => array(
|
||||
'className' => 'Monitor',
|
||||
'foreignKey' => 'MonitorId',
|
||||
'conditions' => '',
|
||||
'fields' => '',
|
||||
'order' => ''
|
||||
)
|
||||
*/
|
||||
);
|
||||
|
||||
/**
|
||||
|
@ -69,21 +59,6 @@ class User extends AppModel {
|
|||
* @var array
|
||||
*/
|
||||
public $hasMany = array(
|
||||
/*
|
||||
'Frame' => array(
|
||||
'className' => 'Frame',
|
||||
'foreignKey' => 'UserId',
|
||||
'dependent' => true,
|
||||
'conditions' => '',
|
||||
'fields' => '',
|
||||
'order' => '',
|
||||
'limit' => '',
|
||||
'offset' => '',
|
||||
'exclusive' => '',
|
||||
'finderQuery' => '',
|
||||
'counterQuery' => ''
|
||||
)
|
||||
*/
|
||||
);
|
||||
|
||||
}
|
||||
|
|
|
@ -30,6 +30,32 @@ class Zone extends AppModel {
|
|||
|
||||
public $recursive = -1;
|
||||
|
||||
/**
|
||||
* Validation rules
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $validate = array(
|
||||
'MonitorId' => array(
|
||||
'rule' => 'checkMonitorId',
|
||||
//array('naturalNumber'),
|
||||
'message' => 'Zones must have a valid MonitorId',
|
||||
'allowEmpty' => false,
|
||||
'required' => true,
|
||||
//'last' => false, // Stop validation after this rule
|
||||
//'on' => 'create', // Limit validation to 'create' or 'update' operations
|
||||
),
|
||||
'Name' => array(
|
||||
'required' => array(
|
||||
//'on' => 'create',
|
||||
'rule' => 'notBlank',
|
||||
'message' => 'Zone Name must be specified for creation',
|
||||
'required' => true,
|
||||
),
|
||||
)
|
||||
|
||||
);
|
||||
|
||||
//The Associations below have been created with all possible keys, those that are not needed can be removed
|
||||
|
||||
/**
|
||||
|
@ -41,9 +67,17 @@ class Zone extends AppModel {
|
|||
'Monitor' => array(
|
||||
'className' => 'Monitor',
|
||||
'foreignKey' => 'MonitorId',
|
||||
'conditions' => '',
|
||||
'fields' => '',
|
||||
'order' => ''
|
||||
//'conditions' => '',
|
||||
//'fields' => '',
|
||||
//'order' => ''
|
||||
)
|
||||
);
|
||||
|
||||
public function checkMonitorId($data) {
|
||||
if ( !$this->Monitor->find('first', array('conditions'=>array('Id'=>$data['MonitorId']))) ) {
|
||||
//$this->invalidate('MonitorId', 'Invalid Monitor Id');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -205,6 +205,11 @@ class Monitor extends ZM_Object {
|
|||
if ( ZM_RAND_STREAM ) {
|
||||
$args['rand'] = time();
|
||||
}
|
||||
foreach ( array('scale','height','width') as $int_arg ) {
|
||||
if ( isset($args[$int_arg]) and (!is_int($args[$int_arg]) or !$args[$int_arg] ) ) {
|
||||
unset($args[$int_arg]);
|
||||
}
|
||||
}
|
||||
|
||||
$streamSrc .= '?'.http_build_query($args, '', $querySep);
|
||||
|
||||
|
@ -297,7 +302,7 @@ class Monitor extends ZM_Object {
|
|||
return;
|
||||
}
|
||||
}
|
||||
Logger::Debug("sending command to $url");
|
||||
Logger::Debug('sending command to '.$url);
|
||||
|
||||
$context = stream_context_create();
|
||||
try {
|
||||
|
@ -321,7 +326,8 @@ class Monitor extends ZM_Object {
|
|||
|
||||
if ( (!defined('ZM_SERVER_ID')) or ( property_exists($this, 'ServerId') and (ZM_SERVER_ID==$this->{'ServerId'}) ) ) {
|
||||
if ( $this->{'Function'} == 'None' || $this->{'Function'} == 'Monitor' || $mode == 'stop' ) {
|
||||
if ( ZM_OPT_CONTROL ) {
|
||||
if ( ZM_OPT_CONTROL && $this->Controllable() && $this->TrackMotion() &&
|
||||
( $this->{'Function'} == 'Modect' || $this->{'Function'} == 'Mocord' ) ) {
|
||||
daemonControl('stop', 'zmtrack.pl', '-m '.$this->{'Id'});
|
||||
}
|
||||
daemonControl('stop', 'zma', '-m '.$this->{'Id'});
|
||||
|
@ -344,7 +350,7 @@ class Monitor extends ZM_Object {
|
|||
} else if ( $this->ServerId() ) {
|
||||
$Server = $this->Server();
|
||||
|
||||
$url = ZM_BASE_PROTOCOL . '://'.$Server->Hostname().'/zm/api/monitors/daemonControl/'.$this->{'Id'}.'/'.$mode.'/zma.json';
|
||||
$url = $Server->UrlToApi().'/monitors/daemonControl/'.$this->{'Id'}.'/'.$mode.'/zma.json';
|
||||
if ( ZM_OPT_USE_AUTH ) {
|
||||
if ( ZM_AUTH_RELAY == 'hashed' ) {
|
||||
$url .= '?auth='.generateAuthHash(ZM_AUTH_HASH_IPS);
|
||||
|
@ -497,12 +503,11 @@ class Monitor extends ZM_Object {
|
|||
foreach ( explode(' ', $command) as $option ) {
|
||||
if ( preg_match('/--([^=]+)(?:=(.+))?/', $option, $matches) ) {
|
||||
$options[$matches[1]] = $matches[2]?$matches[2]:1;
|
||||
} else if ( $option != '' and $option != 'quit' ) {
|
||||
} else if ( $option != '' and $option != 'quit' and $option != 'start' and $option != 'stop' ) {
|
||||
Warning("Ignored command for zmcontrol $option in $command");
|
||||
}
|
||||
}
|
||||
if ( !count($options) ) {
|
||||
|
||||
if ( $command == 'quit' or $command == 'start' or $command == 'stop' ) {
|
||||
# These are special as we now run zmcontrol as a daemon through zmdc.
|
||||
$status = daemonStatus('zmcontrol.pl', array('--id', $this->{'Id'}));
|
||||
|
@ -546,7 +551,7 @@ class Monitor extends ZM_Object {
|
|||
} else if ( $this->ServerId() ) {
|
||||
$Server = $this->Server();
|
||||
|
||||
$url = ZM_BASE_PROTOCOL . '://'.$Server->Hostname().'/zm/api/monitors/daemonControl/'.$this->{'Id'}.'/'.$command.'/zmcontrol.pl.json';
|
||||
$url = $Server->UrlToApi().'/monitors/daemonControl/'.$this->{'Id'}.'/'.$command.'/zmcontrol.pl.json';
|
||||
if ( ZM_OPT_USE_AUTH ) {
|
||||
if ( ZM_AUTH_RELAY == 'hashed' ) {
|
||||
$url .= '?auth='.generateAuthHash(ZM_AUTH_HASH_IPS);
|
||||
|
|
Loading…
Reference in New Issue