-class Exception
-{
+class Exception {
protected:
typedef enum { INFO, WARNING, ERROR, FATAL } Severity;
@@ -32,33 +31,28 @@ protected:
Severity mSeverity;
public:
- Exception( const std::string &message, Severity severity=ERROR ) : mMessage( message ), mSeverity( severity )
+ explicit Exception(const std::string &message, const Severity severity=ERROR) :
+ mMessage(message),
+ mSeverity(severity)
{
}
-public:
- const std::string &getMessage() const
- {
- return( mMessage );
+ const std::string &getMessage() const {
+ return mMessage;
}
- Severity getSeverity() const
- {
- return( mSeverity );
+ Severity getSeverity() const {
+ return mSeverity;
}
- bool isInfo() const
- {
- return( mSeverity == INFO );
+ bool isInfo() const {
+ return mSeverity == INFO;
}
- bool isWarning() const
- {
+ bool isWarning() const {
return( mSeverity == WARNING );
}
- bool isError() const
- {
+ bool isError() const {
return( mSeverity == ERROR );
}
- bool isFatal() const
- {
+ bool isFatal() const {
return( mSeverity == FATAL );
}
};
diff --git a/src/zm_ffmpeg_input.h b/src/zm_ffmpeg_input.h
index 41dc03008..30af56a32 100644
--- a/src/zm_ffmpeg_input.h
+++ b/src/zm_ffmpeg_input.h
@@ -24,10 +24,10 @@ class FFmpeg_Input {
int Close();
AVFrame *get_frame( int stream_id=-1 );
AVFrame *get_frame( int stream_id, double at );
- int get_video_stream_id() {
+ int get_video_stream_id() const {
return video_stream_id;
}
- int get_audio_stream_id() {
+ int get_audio_stream_id() const {
return audio_stream_id;
}
diff --git a/src/zm_fifo.h b/src/zm_fifo.h
index 065fd569c..abd666891 100644
--- a/src/zm_fifo.h
+++ b/src/zm_fifo.h
@@ -68,19 +68,26 @@ class FifoStream : public StreamBase {
);
protected:
- typedef enum { MJPEG, RAW } StreamType;
+ typedef enum { UNKNOWN, MJPEG, RAW } StreamType;
StreamType stream_type;
bool sendMJEGFrames();
bool sendRAWFrames();
void processCommand(const CmdMsg *msg) {}
public:
- FifoStream() {}
+ FifoStream() :
+ stream_path(nullptr),
+ fd(0),
+ total_read(0),
+ bytes_read(0),
+ frame_count(0),
+ stream_type(UNKNOWN)
+ {}
static void fifo_create_if_missing(
const char * path,
bool delete_fake_fifo = true);
void setStreamStart(const char * path);
void setStreamStart(int monitor_id, const char * format);
- void runStream();
+ void runStream() override;
};
#endif // ZM_FIFO_H
diff --git a/src/zm_local_camera.h b/src/zm_local_camera.h
index c466f72b8..d31fa3e20 100644
--- a/src/zm_local_camera.h
+++ b/src/zm_local_camera.h
@@ -149,16 +149,17 @@ public:
int Palette() const { return( palette ); }
int Extras() const { return( extras ); }
- int Brightness( int p_brightness=-1 );
- int Hue( int p_hue=-1 );
- int Colour( int p_colour=-1 );
- int Contrast( int p_contrast=-1 );
+ int Brightness( int p_brightness=-1 ) override;
+ int Hue( int p_hue=-1 ) override;
+ int Colour( int p_colour=-1 ) override;
+ int Contrast( int p_contrast=-1 ) override;
+
+ int PrimeCapture()override ;
+ int PreCapture()override ;
+ int Capture(ZMPacket &p) override;
+ int PostCapture()override ;
+ int Close() override { return 0; };
- int PrimeCapture();
- int PreCapture();
- int Capture(ZMPacket &p);
- int PostCapture();
- int Close() { return 0; };
static bool GetCurrentSettings( const char *device, char *output, int version, bool verbose );
AVStream* get_VideoStream();
};
diff --git a/src/zm_logger.cpp b/src/zm_logger.cpp
index 619cba115..6fad415a7 100644
--- a/src/zm_logger.cpp
+++ b/src/zm_logger.cpp
@@ -44,18 +44,6 @@ Logger *Logger::smInstance = nullptr;
Logger::StringMap Logger::smCodes;
Logger::IntMap Logger::smSyslogPriorities;
-#if 0
-static void subtractTime( struct timeval * const tp1, struct timeval * const tp2 ) {
- tp1->tv_sec -= tp2->tv_sec;
- if ( tp1->tv_usec <= tp2->tv_usec ) {
- tp1->tv_sec--;
- tp1->tv_usec = 1000000 - (tp2->tv_usec - tp1->tv_usec);
- } else {
- tp1->tv_usec = tp1->tv_usec - tp2->tv_usec;
- }
-}
-#endif
-
void Logger::usrHandler(int sig) {
Logger *logger = fetch();
if ( sig == SIGUSR1 )
diff --git a/src/zm_logger.h b/src/zm_logger.h
index 82144a1c9..ad1ac398b 100644
--- a/src/zm_logger.h
+++ b/src/zm_logger.h
@@ -121,7 +121,7 @@ private:
Logger();
~Logger();
- int limit(int level) {
+ int limit(const int level) const {
if ( level > DEBUG9 )
return DEBUG9;
if ( level < NOLOG )
@@ -163,7 +163,7 @@ public:
}
Level level(Level=NOOPT);
- bool debugOn() {
+ bool debugOn() const {
return mEffectiveLevel >= DEBUG1;
}
diff --git a/src/zm_mem_utils.h b/src/zm_mem_utils.h
index 6ef1bdac5..a9e1ab097 100644
--- a/src/zm_mem_utils.h
+++ b/src/zm_mem_utils.h
@@ -26,7 +26,7 @@
inline void* zm_mallocaligned(unsigned int reqalignment, size_t reqsize) {
uint8_t* retptr;
#if HAVE_POSIX_MEMALIGN
- if ( posix_memalign((void**)&retptr,reqalignment,reqsize) != 0 )
+ if ( posix_memalign((void**)&retptr, reqalignment, reqsize) != 0 )
return nullptr;
return retptr;
@@ -39,7 +39,7 @@ inline void* zm_mallocaligned(unsigned int reqalignment, size_t reqsize) {
alloc = retptr + sizeof(void*);
- if(((long)alloc % reqalignment) != 0)
+ if ( ((long)alloc % reqalignment) != 0 )
alloc = alloc + (reqalignment - ((long)alloc % reqalignment));
/* Store a pointer before to the start of the block, just before returned aligned memory */
diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp
index db23cfa48..25acabdf4 100644
--- a/src/zm_monitor.cpp
+++ b/src/zm_monitor.cpp
@@ -2465,7 +2465,6 @@ int Monitor::Capture() {
} // end if result
} // end if deinterlacing
-
// Icon: I'm not sure these should be here. They have nothing to do with capturing
if ( shared_data->action & GET_SETTINGS ) {
shared_data->brightness = camera->Brightness();
@@ -2527,23 +2526,10 @@ void Monitor::TimestampImage(Image *ts_image, const struct timeval *ts_time) con
bool Monitor::closeEvent() {
if ( !event )
- return true;
-#if 0
- if ( event_delete_thread ) {
- event_delete_thread->join();
- delete event_delete_thread;
- event_delete_thread = NULL;
- }
- event_delete_thread = new std::thread([](Event *event) {
- Event * e = event;
- event = nullptr;
- delete e;
- e = nullptr;
- }, event);
-#else
+ return false;
+
delete event;
event = nullptr;
-#endif
video_store_data->recording = (struct timeval){0};
return true;
} // end bool Monitor::closeEvent()
diff --git a/src/zm_monitor.h b/src/zm_monitor.h
index 792bf7c55..e71ddffe2 100644
--- a/src/zm_monitor.h
+++ b/src/zm_monitor.h
@@ -419,7 +419,7 @@ public:
inline Function GetFunction() const {
return function;
}
- inline bool Enabled() {
+ inline bool Enabled() const {
if ( function <= MONITOR )
return false;
return enabled;
@@ -427,7 +427,7 @@ public:
inline const char *EventPrefix() const {
return event_prefix;
}
- inline bool Ready() {
+ inline bool Ready() const {
if ( function <= MONITOR ) {
Error("Should not be calling Ready if the function doesn't include motion detection");
return false;
@@ -435,15 +435,15 @@ public:
if ( image_count >= ready_count ) {
return true;
}
- Debug(2, "Not ready because image_count(%d) <= ready_count(%d)", image_count, ready_count );
+ Debug(2, "Not ready because image_count(%d) <= ready_count(%d)", image_count, ready_count);
return false;
}
- inline bool Active() {
+ inline bool Active() const {
if ( function <= MONITOR )
return false;
return( enabled && shared_data->active );
}
- inline bool Exif() {
+ inline bool Exif() const {
return embed_exif;
}
inline bool RecordAudio() {
@@ -474,7 +474,7 @@ public:
void SetVideoWriterEventId( uint64_t p_event_id ) { video_store_data->current_event = p_event_id; }
struct timeval GetVideoWriterStartTime() const { return video_store_data->recording; }
- void SetVideoWriterStartTime(struct timeval &t) { video_store_data->recording = t; }
+ void SetVideoWriterStartTime(const struct timeval &t) { video_store_data->recording = t; }
unsigned int GetPreEventCount() const { return pre_event_count; };
struct timeval GetVideoBufferDuration() const { return video_buffer_duration; };
@@ -502,7 +502,7 @@ public:
inline void setStartupTime( time_t p_time ) { shared_data->startup_time = p_time; }
void get_ref_image();
- int LabelSize() { return label_size; }
+ int LabelSize() const { return label_size; }
void actionReload();
void actionEnable();
diff --git a/src/zm_monitorstream.cpp b/src/zm_monitorstream.cpp
index e586a0910..68d3bbc5d 100644
--- a/src/zm_monitorstream.cpp
+++ b/src/zm_monitorstream.cpp
@@ -292,7 +292,7 @@ void MonitorStream::processCommand(const CmdMsg *msg) {
if ( (nbytes = sendto(sd, &status_msg, sizeof(status_msg), MSG_DONTWAIT, (sockaddr *)&rem_addr, sizeof(rem_addr))) < 0 ) {
//if ( errno != EAGAIN )
{
- Error( "Can't sendto on sd %d: %s", sd, strerror(errno) );
+ Error("Can't sendto on sd %d: %s", sd, strerror(errno));
//exit( -1 );
}
}
@@ -507,7 +507,7 @@ void MonitorStream::runStream() {
const int max_swap_len_suffix = 15;
int swap_path_length = staticConfig.PATH_SWAP.length() + 1; // +1 for NULL terminator
- int subfolder1_length = snprintf(nullptr, 0, "/zmswap-m%d", monitor->Id()) + 1;
+ int subfolder1_length = snprintf(nullptr, 0, "/zmswap-m%u", monitor->Id()) + 1;
int subfolder2_length = snprintf(nullptr, 0, "/zmswap-q%06d", connkey) + 1;
int total_swap_path_length = swap_path_length + subfolder1_length + subfolder2_length;
@@ -878,7 +878,7 @@ void MonitorStream::SingleImageRaw(int scale) {
}
fprintf(stdout,
- "Content-Length: %d\r\n"
+ "Content-Length: %u\r\n"
"Content-Type: image/x-rgb\r\n\r\n",
snap_image->Size());
fwrite(snap_image->Buffer(), snap_image->Size(), 1, stdout);
diff --git a/src/zm_monitorstream.h b/src/zm_monitorstream.h
index 24655b636..20842fa55 100644
--- a/src/zm_monitorstream.h
+++ b/src/zm_monitorstream.h
@@ -71,7 +71,7 @@ class MonitorStream : public StreamBase {
bool setStreamStart(int monitor_id) {
return loadMonitor(monitor_id);
}
- void runStream();
+ void runStream() override;
};
#endif // ZM_MONITORSTREAM_H
diff --git a/src/zm_signal.cpp b/src/zm_signal.cpp
index 81012c07e..2756802a3 100644
--- a/src/zm_signal.cpp
+++ b/src/zm_signal.cpp
@@ -29,15 +29,13 @@
bool zm_reload = false;
bool zm_terminate = false;
-RETSIGTYPE zm_hup_handler(int signal)
-{
+RETSIGTYPE zm_hup_handler(int signal) {
// Shouldn't do complex things in signal handlers, logging is complex and can block due to mutexes.
//Info("Got signal %d (%s), reloading", signal, strsignal(signal));
zm_reload = true;
}
-RETSIGTYPE zm_term_handler(int signal)
-{
+RETSIGTYPE zm_term_handler(int signal) {
// Shouldn't do complex things in signal handlers, logging is complex and can block due to mutexes.
//Info("Got signal %d (%s), exiting", signal, strsignal(signal));
zm_terminate = true;
@@ -55,8 +53,7 @@ RETSIGTYPE zm_die_handler(int signal)
#if ( HAVE_SIGINFO_T && HAVE_UCONTEXT_T )
void *ip = nullptr;
void *cr2 = nullptr;
- if (info && context) {
-
+ if ( info && context ) {
Debug(1,
"Signal information: number %d code %d errno %d pid %d uid %d status %d",
signal, info->si_code, info->si_errno, info->si_pid,
@@ -79,7 +76,7 @@ RETSIGTYPE zm_die_handler(int signal)
#endif // defined(__x86_64__)
// Print the signal address and instruction pointer if available
- if (ip) {
+ if ( ip ) {
Error("Signal address is %p, from %p", cr2, ip);
} else {
Error("Signal address is %p, no instruction pointer", cr2);
@@ -115,8 +112,7 @@ RETSIGTYPE zm_die_handler(int signal)
exit(signal);
}
-void zmSetHupHandler(SigHandler * handler)
-{
+void zmSetHupHandler(SigHandler * handler) {
sigset_t block_set;
sigemptyset(&block_set);
struct sigaction action, old_action;
@@ -127,8 +123,7 @@ void zmSetHupHandler(SigHandler * handler)
sigaction(SIGHUP, &action, &old_action);
}
-void zmSetTermHandler(SigHandler * handler)
-{
+void zmSetTermHandler(SigHandler * handler) {
sigset_t block_set;
sigemptyset(&block_set);
struct sigaction action, old_action;
@@ -141,8 +136,7 @@ void zmSetTermHandler(SigHandler * handler)
sigaction(SIGQUIT, &action, &old_action);
}
-void zmSetDieHandler(SigHandler * handler)
-{
+void zmSetDieHandler(SigHandler * handler) {
sigset_t block_set;
sigemptyset(&block_set);
struct sigaction action, old_action;
@@ -163,19 +157,16 @@ void zmSetDieHandler(SigHandler * handler)
sigaction(SIGFPE, &action, &old_action);
}
-void zmSetDefaultHupHandler()
-{
+void zmSetDefaultHupHandler() {
zmSetHupHandler((SigHandler *) zm_hup_handler);
}
-void zmSetDefaultTermHandler()
-{
+void zmSetDefaultTermHandler() {
zmSetTermHandler((SigHandler *) zm_term_handler);
}
-void zmSetDefaultDieHandler()
-{
- if (config.dump_cores) {
+void zmSetDefaultDieHandler() {
+ if ( config.dump_cores ) {
// Do nothing
} else {
zmSetDieHandler((SigHandler *) zm_die_handler);
diff --git a/src/zm_time.h b/src/zm_time.h
index 0f7dbc794..490ca1e2c 100644
--- a/src/zm_time.h
+++ b/src/zm_time.h
@@ -76,7 +76,9 @@ struct DeltaTimeval
#define USEC_PER_SEC 1000000
#define MSEC_PER_SEC 1000
+/*
extern struct timeval tv;
+*/
inline int tvDiffUsec( struct timeval first, struct timeval last )
{
diff --git a/src/zm_user.h b/src/zm_user.h
index 42fe07554..519ea13de 100644
--- a/src/zm_user.h
+++ b/src/zm_user.h
@@ -46,7 +46,7 @@ class User {
User();
explicit User(const MYSQL_ROW &dbrow);
~User();
- User(User &u) { Copy(u); }
+ User(const User &u) { Copy(u); }
void Copy(const User &u);
User& operator=(const User &u) {
Copy(u); return *this;
diff --git a/src/zm_video.cpp b/src/zm_video.cpp
index d97c75167..b24905ece 100644
--- a/src/zm_video.cpp
+++ b/src/zm_video.cpp
@@ -216,7 +216,7 @@ int X264MP4Writer::Open() {
int X264MP4Writer::Close() {
/* Flush all pending frames */
for ( int i = (x264_encoder_delayed_frames(x264enc) + 1); i > 0; i-- ) {
-Debug(1,"Encoding delayed frame");
+ Debug(1, "Encoding delayed frame");
if ( x264encodeloop(true) < 0 )
break;
}
@@ -227,7 +227,7 @@ Debug(1,"Encoding delayed frame");
/* Close MP4 handle */
MP4Close(mp4h);
- Debug(1,"Optimising");
+ Debug(1, "Optimising");
/* Required for proper HTTP streaming */
MP4Optimize((path + ".incomplete").c_str(), path.c_str());
diff --git a/src/zmc.cpp b/src/zmc.cpp
index 509183bb0..921b5433e 100644
--- a/src/zmc.cpp
+++ b/src/zmc.cpp
@@ -248,8 +248,8 @@ int main(int argc, char *argv[]) {
time_t now = (time_t)time(nullptr);
monitors[i]->setStartupTime(now);
- snprintf(sql, sizeof(sql),
- "REPLACE INTO Monitor_Status (MonitorId, Status) VALUES ('%d','Running')",
+ snprintf(sql, sizeof(sql),
+ "INSERT INTO Monitor_Status (MonitorId,Status) VALUES (%d, 'Running') ON DUPLICATE KEY UPDATE Status='Running'",
monitors[i]->Id());
if ( mysql_query(&dbconn, sql) ) {
Error("Can't run query: %s", mysql_error(&dbconn));
@@ -270,7 +270,7 @@ int main(int argc, char *argv[]) {
}
for ( int i = 0; i < n_monitors; i++ ) {
snprintf(sql, sizeof(sql),
- "REPLACE INTO Monitor_Status (MonitorId, Status) VALUES ('%d','Connected')",
+ "INSERT INTO Monitor_Status (MonitorId,Status) VALUES (%d, 'Connected') ON DUPLICATE KEY UPDATE Status='Connected'",
monitors[i]->Id());
if ( mysql_query(&dbconn, sql) ) {
Error("Can't run query: %s", mysql_error(&dbconn));
@@ -391,7 +391,7 @@ int main(int argc, char *argv[]) {
for ( int i = 0; i < n_monitors; i++ ) {
static char sql[ZM_SQL_SML_BUFSIZ];
snprintf(sql, sizeof(sql),
- "REPLACE INTO Monitor_Status (MonitorId, Status) VALUES ('%d','NotRunning')",
+ "INSERT INTO Monitor_Status (MonitorId,Status) VALUES (%d, 'Connected') ON DUPLICATE KEY UPDATE Status='NotRunning'",
monitors[i]->Id());
if ( mysql_query(&dbconn, sql) ) {
Error("Can't run query: %s", mysql_error(&dbconn));
diff --git a/src/zms.cpp b/src/zms.cpp
index 9b661c564..4e77ea4c1 100644
--- a/src/zms.cpp
+++ b/src/zms.cpp
@@ -95,91 +95,92 @@ int main(int argc, const char *argv[], char **envp) {
}
const char *query = getenv("QUERY_STRING");
- if ( query ) {
- Debug(1, "Query: %s", query);
-
- char temp_query[1024];
- strncpy(temp_query, query, sizeof(temp_query)-1);
- char *q_ptr = temp_query;
- char *parms[16]; // Shouldn't be more than this
- int parm_no = 0;
- while ( (parm_no < 16) && (parms[parm_no] = strtok(q_ptr, "&")) ) {
- parm_no++;
- q_ptr = nullptr;
- }
-
- for ( int p = 0; p < parm_no; p++ ) {
- char *name = strtok(parms[p], "=");
- char const *value = strtok(nullptr, "=");
- if ( !value )
- value = "";
- if ( !strcmp(name, "source") ) {
- source = !strcmp(value, "event")?ZMS_EVENT:ZMS_MONITOR;
- if ( !strcmp(value, "fifo") )
- source = ZMS_FIFO;
- } else if ( !strcmp(name, "mode") ) {
- mode = !strcmp(value, "jpeg")?ZMS_JPEG:ZMS_MPEG;
- mode = !strcmp(value, "raw")?ZMS_RAW:mode;
- mode = !strcmp(value, "zip")?ZMS_ZIP:mode;
- mode = !strcmp(value, "single")?ZMS_SINGLE:mode;
- } else if ( !strcmp(name, "format") ) {
- strncpy( format, value, sizeof(format) );
- } else if ( !strcmp(name, "monitor") ) {
- monitor_id = atoi(value);
- if ( source == ZMS_UNKNOWN )
- source = ZMS_MONITOR;
- } else if ( !strcmp(name, "time") ) {
- event_time = atoi(value);
- } else if ( !strcmp(name, "event") ) {
- event_id = strtoull(value, nullptr, 10);
- source = ZMS_EVENT;
- } else if ( !strcmp(name, "frame") ) {
- frame_id = strtoull(value, nullptr, 10);
- source = ZMS_EVENT;
- } else if ( !strcmp(name, "scale") ) {
- scale = atoi(value);
- } else if ( !strcmp(name, "rate") ) {
- rate = atoi(value);
- } else if ( !strcmp(name, "maxfps") ) {
- maxfps = atof(value);
- } else if ( !strcmp(name, "bitrate") ) {
- bitrate = atoi(value);
- } else if ( !strcmp(name, "ttl") ) {
- ttl = atoi(value);
- } else if ( !strcmp(name, "replay") ) {
- if ( !strcmp(value, "gapless") ) {
- replay = EventStream::MODE_ALL_GAPLESS;
- } else if ( !strcmp(value, "all") ) {
- replay = EventStream::MODE_ALL;
- } else if ( !strcmp(value, "none") ) {
- replay = EventStream::MODE_NONE;
- } else if ( !strcmp(value, "single") ) {
- replay = EventStream::MODE_SINGLE;
- } else {
- Error("Unsupported value %s for replay, defaulting to none", value);
- }
- } else if ( !strcmp(name, "connkey") ) {
- connkey = atoi(value);
- } else if ( !strcmp(name, "buffer") ) {
- playback_buffer = atoi(value);
- } else if ( !strcmp(name, "auth") ) {
- strncpy(auth, value, sizeof(auth)-1);
- } else if ( !strcmp(name, "token") ) {
- jwt_token_str = value;
- Debug(1, "ZMS: JWT token found: %s", jwt_token_str.c_str());
- } else if ( !strcmp(name, "user") ) {
- username = UriDecode(value);
- } else if ( !strcmp(name, "pass") ) {
- password = UriDecode(value);
- Debug(1, "Have %s for password", password.c_str());
- } else {
- Debug(1, "Unknown parameter passed to zms %s=%s", name, value);
- } // end if possible parameter names
- } // end foreach parm
- } else {
+ if ( query == nullptr ) {
Fatal("No query string.");
+ return 0;
} // end if query
+ Debug(1, "Query: %s", query);
+
+ char temp_query[1024];
+ strncpy(temp_query, query, sizeof(temp_query)-1);
+ char *q_ptr = temp_query;
+ char *parms[16]; // Shouldn't be more than this
+ int parm_no = 0;
+ while ( (parm_no < 16) && (parms[parm_no] = strtok(q_ptr, "&")) ) {
+ parm_no++;
+ q_ptr = nullptr;
+ }
+
+ for ( int p = 0; p < parm_no; p++ ) {
+ char *name = strtok(parms[p], "=");
+ char const *value = strtok(nullptr, "=");
+ if ( !value )
+ value = "";
+ if ( !strcmp(name, "source") ) {
+ source = !strcmp(value, "event")?ZMS_EVENT:ZMS_MONITOR;
+ if ( !strcmp(value, "fifo") )
+ source = ZMS_FIFO;
+ } else if ( !strcmp(name, "mode") ) {
+ mode = !strcmp(value, "jpeg")?ZMS_JPEG:ZMS_MPEG;
+ mode = !strcmp(value, "raw")?ZMS_RAW:mode;
+ mode = !strcmp(value, "zip")?ZMS_ZIP:mode;
+ mode = !strcmp(value, "single")?ZMS_SINGLE:mode;
+ } else if ( !strcmp(name, "format") ) {
+ strncpy(format, value, sizeof(format)-1);
+ } else if ( !strcmp(name, "monitor") ) {
+ monitor_id = atoi(value);
+ if ( source == ZMS_UNKNOWN )
+ source = ZMS_MONITOR;
+ } else if ( !strcmp(name, "time") ) {
+ event_time = atoi(value);
+ } else if ( !strcmp(name, "event") ) {
+ event_id = strtoull(value, nullptr, 10);
+ source = ZMS_EVENT;
+ } else if ( !strcmp(name, "frame") ) {
+ frame_id = strtoull(value, nullptr, 10);
+ source = ZMS_EVENT;
+ } else if ( !strcmp(name, "scale") ) {
+ scale = atoi(value);
+ } else if ( !strcmp(name, "rate") ) {
+ rate = atoi(value);
+ } else if ( !strcmp(name, "maxfps") ) {
+ maxfps = atof(value);
+ } else if ( !strcmp(name, "bitrate") ) {
+ bitrate = atoi(value);
+ } else if ( !strcmp(name, "ttl") ) {
+ ttl = atoi(value);
+ } else if ( !strcmp(name, "replay") ) {
+ if ( !strcmp(value, "gapless") ) {
+ replay = EventStream::MODE_ALL_GAPLESS;
+ } else if ( !strcmp(value, "all") ) {
+ replay = EventStream::MODE_ALL;
+ } else if ( !strcmp(value, "none") ) {
+ replay = EventStream::MODE_NONE;
+ } else if ( !strcmp(value, "single") ) {
+ replay = EventStream::MODE_SINGLE;
+ } else {
+ Error("Unsupported value %s for replay, defaulting to none", value);
+ }
+ } else if ( !strcmp(name, "connkey") ) {
+ connkey = atoi(value);
+ } else if ( !strcmp(name, "buffer") ) {
+ playback_buffer = atoi(value);
+ } else if ( !strcmp(name, "auth") ) {
+ strncpy(auth, value, sizeof(auth)-1);
+ } else if ( !strcmp(name, "token") ) {
+ jwt_token_str = value;
+ Debug(1, "ZMS: JWT token found: %s", jwt_token_str.c_str());
+ } else if ( !strcmp(name, "user") ) {
+ username = UriDecode(value);
+ } else if ( !strcmp(name, "pass") ) {
+ password = UriDecode(value);
+ Debug(1, "Have %s for password", password.c_str());
+ } else {
+ Debug(1, "Unknown parameter passed to zms %s=%s", name, value);
+ } // end if possible parameter names
+ } // end foreach parm
+
if ( monitor_id ) {
snprintf(log_id_string, sizeof(log_id_string), "zms_m%d", monitor_id);
} else {
diff --git a/src/zmu.cpp b/src/zmu.cpp
index bdc467812..30a2a0ce7 100644
--- a/src/zmu.cpp
+++ b/src/zmu.cpp
@@ -482,7 +482,7 @@ int main(int argc, char *argv[]) {
} // end if ! MONITOR
if ( verbose ) {
- printf("Monitor %d(%s)\n", monitor->Id(), monitor->Name());
+ printf("Monitor %u(%s)\n", monitor->Id(), monitor->Name());
}
if ( !monitor->connect() ) {
Error("Can't connect to capture daemon: %d %s", monitor->Id(), monitor->Name());
@@ -521,19 +521,19 @@ int main(int argc, char *argv[]) {
}
if ( function & ZMU_READ_IDX ) {
if ( verbose )
- printf("Last read index: %d\n", monitor->GetLastReadIndex());
+ printf("Last read index: %u\n", monitor->GetLastReadIndex());
else {
if ( have_output ) fputc(separator, stdout);
- printf("%d", monitor->GetLastReadIndex());
+ printf("%u", monitor->GetLastReadIndex());
have_output = true;
}
}
if ( function & ZMU_WRITE_IDX ) {
if ( verbose ) {
- printf("Last write index: %d\n", monitor->GetLastWriteIndex());
+ printf("Last write index: %u\n", monitor->GetLastWriteIndex());
} else {
if ( have_output ) fputc(separator, stdout);
- printf("%d", monitor->GetLastWriteIndex());
+ printf("%u", monitor->GetLastWriteIndex());
have_output = true;
}
}
@@ -558,9 +558,9 @@ int main(int argc, char *argv[]) {
if ( function & ZMU_IMAGE ) {
if ( verbose ) {
if ( image_idx == -1 )
- printf("Dumping last image captured to Monitor%d.jpg", monitor->Id());
+ printf("Dumping last image captured to Monitor%u.jpg", monitor->Id());
else
- printf("Dumping buffer image %d to Monitor%d.jpg", image_idx, monitor->Id());
+ printf("Dumping buffer image %d to Monitor%u.jpg", image_idx, monitor->Id());
if ( scale != -1 )
printf(", scaling by %d%%", scale);
printf("\n");
@@ -569,7 +569,7 @@ int main(int argc, char *argv[]) {
}
if ( function & ZMU_ZONES ) {
if ( verbose )
- printf("Dumping zone image to Zones%d.jpg\n", monitor->Id());
+ printf("Dumping zone image to Zones%u.jpg\n", monitor->Id());
monitor->DumpZoneImage(zoneString);
}
if ( function & ZMU_ALARM ) {
@@ -735,17 +735,17 @@ int main(int argc, char *argv[]) {
Debug(1, "Got %d monitors", mysql_num_rows(result));
printf("%4s%5s%6s%9s%14s%6s%6s%8s%8s\n", "Id", "Func", "State", "TrgState", "LastImgTim", "RdIdx", "WrIdx", "LastEvt", "FrmRate");
- for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row(result); i++ ) {
- int mon_id = atoi(dbrow[0]);
- int function = atoi(dbrow[1]);
- if ( !user || user->canAccess(mon_id) ) {
- if ( function > 1 ) {
- Monitor *monitor = Monitor::Load(mon_id, false, Monitor::QUERY);
+ for ( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row(result); i++ ) {
+ int monitor_id = atoi(dbrow[0]);
+ int monitor_function = atoi(dbrow[1]);
+ if ( !user || user->canAccess(monitor_id) ) {
+ if ( monitor_function > 1 ) {
+ Monitor *monitor = Monitor::Load(monitor_id, false, Monitor::QUERY);
if ( monitor && monitor->connect() ) {
struct timeval tv = monitor->GetTimestamp();
printf( "%4d%5d%6d%9d%11ld.%02ld%6d%6d%8" PRIu64 "%8.2f\n",
monitor->Id(),
- function,
+ monitor_function,
monitor->GetState(),
monitor->GetTriggerState(),
tv.tv_sec, tv.tv_usec/10000,
diff --git a/utils/packpack/startpackpack.sh b/utils/packpack/startpackpack.sh
index 1b2eafd8f..d464089d3 100755
--- a/utils/packpack/startpackpack.sh
+++ b/utils/packpack/startpackpack.sh
@@ -94,12 +94,12 @@ commonprep () {
# The rpm specfile requires we download each submodule as a tarball then manually move it into place
# Might as well do this for Debian as well, rather than git submodule init
- CRUDVER="3.1.0-zm"
+ CRUDVER="3.2.0"
if [ -e "build/crud-${CRUDVER}.tar.gz" ]; then
echo "Found existing Crud ${CRUDVER} tarball..."
else
echo "Retrieving Crud ${CRUDVER} submodule..."
- curl -L https://github.com/ZoneMinder/crud/archive/v${CRUDVER}.tar.gz > build/crud-${CRUDVER}.tar.gz
+ curl -L https://github.com/FriendsOfCake/crud/archive/v${CRUDVER}.tar.gz > build/crud-${CRUDVER}.tar.gz
if [ $? -ne 0 ]; then
echo "ERROR: Crud tarball retreival failed..."
exit 1
diff --git a/version b/version
index a0b71b46f..31d4ef08d 100644
--- a/version
+++ b/version
@@ -1 +1 @@
-1.35.10
+1.35.14
diff --git a/web/ajax/events.php b/web/ajax/events.php
index f9a4fc14b..5d58a5a41 100644
--- a/web/ajax/events.php
+++ b/web/ajax/events.php
@@ -26,22 +26,22 @@ if ( $message ) {
return;
}
+$filter = isset($_REQUEST['filter']) ? ZM\Filter::parse($_REQUEST['filter']) : new ZM\Filter();
+if ( $user['MonitorIds'] ) {
+ $filter = $filter->addTerm(array('cnj'=>'and', 'attr'=>'MonitorId', 'op'=>'IN', 'val'=>$user['MonitorIds']));
+}
+
// Search contains a user entered string to search on
$search = isset($_REQUEST['search']) ? $_REQUEST['search'] : '';
// Advanced search contains an array of "column name" => "search text" pairs
// Bootstrap table sends json_ecoded array, which we must decode
-$advsearch = isset($_REQUEST['filter']) ? json_decode($_REQUEST['filter'], JSON_OBJECT_AS_ARRAY) : array();
+$advsearch = isset($_REQUEST['advsearch']) ? json_decode($_REQUEST['advsearch'], JSON_OBJECT_AS_ARRAY) : array();
// Sort specifies the name of the column to sort on
-$sort = 'StartTime';
+$sort = 'StartDateTime';
if ( isset($_REQUEST['sort']) ) {
- if ( !in_array($_REQUEST['sort'], array_merge($columns, $col_alt)) ) {
- ZM\Error('Invalid sort field: ' . $_REQUEST['sort']);
- } else {
- $sort = $_REQUEST['sort'];
- //if ( $sort == 'DateTime' ) $sort = 'TimeKey';
- }
+ $sort = $_REQUEST['sort'];
}
// Offset specifies the starting row to return, used for pagination
@@ -80,7 +80,7 @@ switch ( $task ) {
foreach ( $eids as $eid ) $data[] = deleteRequest($eid);
break;
case 'query' :
- $data = queryRequest($search, $advsearch, $sort, $offset, $order, $limit);
+ $data = queryRequest($filter, $search, $advsearch, $sort, $offset, $order, $limit);
break;
default :
ZM\Fatal("Unrecognised task '$task'");
@@ -114,62 +114,79 @@ function deleteRequest($eid) {
return $message;
}
-function queryRequest($search, $advsearch, $sort, $offset, $order, $limit) {
+function queryRequest($filter, $search, $advsearch, $sort, $offset, $order, $limit) {
+ $data = array(
+ 'total' => 0,
+ 'totalNotFiltered' => 0,
+ 'rows' => array(),
+ 'updated' => preg_match('/%/', DATE_FMT_CONSOLE_LONG) ? strftime(DATE_FMT_CONSOLE_LONG) : date(DATE_FMT_CONSOLE_LONG)
+ );
+
+ $failed = !$filter->test_pre_sql_conditions();
+ if ( $failed ) {
+ ZM\Debug('Pre conditions failed, not doing sql');
+ return $data;
+ }
+
// Put server pagination code here
// The table we want our data from
$table = 'Events';
- // The names of the dB columns in the log table we are interested in
- $columns = array('Id', 'MonitorId', 'StorageId', 'Name', 'Cause', 'StartTime', 'EndTime', 'Length', 'Frames', 'AlarmFrames', 'TotScore', 'AvgScore', 'MaxScore', 'Archived', 'Emailed', 'Notes', 'DiskSpace');
+ // The names of the dB columns in the events table we are interested in
+ $columns = array('Id', 'MonitorId', 'StorageId', 'Name', 'Cause', 'StartDateTime', 'EndDateTime', 'Length', 'Frames', 'AlarmFrames', 'TotScore', 'AvgScore', 'MaxScore', 'Archived', 'Emailed', 'Notes', 'DiskSpace');
- // The names of columns shown in the log view that are NOT dB columns in the database
+ // The names of columns shown in the event view that are NOT dB columns in the database
$col_alt = array('Monitor', 'Storage');
- $col_str = implode(', ', $columns);
+ if ( !in_array($sort, array_merge($columns, $col_alt)) ) {
+ ZM\Error('Invalid sort field: ' . $sort);
+ $sort = 'Id';
+ }
+
$data = array();
$query = array();
$query['values'] = array();
$likes = array();
- $where = '';
+ $where = ($filter->sql()?'('.$filter->sql().')' : '');
// There are two search bars in the log view, normal and advanced
// Making an exuctive decision to ignore the normal search, when advanced search is in use
// Alternatively we could try to do both
if ( count($advsearch) ) {
foreach ( $advsearch as $col=>$text ) {
- if ( !in_array($col, array_merge($columns, $col_alt)) ) {
+ if ( in_array($col, $columns) ) {
+ array_push($likes, 'E.'.$col.' LIKE ?');
+ array_push($query['values'], $text);
+ } else if ( in_array($col, $col_alt) ) {
+ array_push($likes, 'M.'.$col.' LIKE ?');
+ array_push($query['values'], $text);
+ } else {
ZM\Error("'$col' is not a sortable column name");
continue;
}
- $text = '%' .$text. '%';
- array_push($likes, $col.' LIKE ?');
- array_push($query['values'], $text);
- }
+ } # end foreach col in advsearch
$wherevalues = $query['values'];
- $where = ' WHERE (' .implode(' OR ', $likes). ')';
+ $where .= ($where != '') ? ' AND (' .implode(' OR ', $likes). ')' : implode(' OR ', $likes);
} else if ( $search != '' ) {
$search = '%' .$search. '%';
foreach ( $columns as $col ) {
- array_push($likes, $col.' LIKE ?');
+ array_push($likes, 'E.'.$col.' LIKE ?');
array_push($query['values'], $search);
}
$wherevalues = $query['values'];
- $where = ' WHERE (' .implode(' OR ', $likes). ')';
- }
+ $where .= ( $where != '') ? ' AND (' .implode(' OR ', $likes). ')' : implode(' OR ', $likes);
+ }
+ if ( $where )
+ $where = ' WHERE '.$where;
- $query['sql'] = 'SELECT ' .$col_str. ' FROM `' .$table. '` ' .$where. ' ORDER BY ' .$sort. ' ' .$order. ' LIMIT ?, ?';
+ $sort = $sort == 'Monitor' ? 'M.Name' : 'E.'.$sort;
+ $col_str = 'E.*, M.Name AS Monitor';
+ $query['sql'] = 'SELECT ' .$col_str. ' FROM `' .$table. '` AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id'.$where.' ORDER BY ' .$sort. ' ' .$order. ' LIMIT ?, ?';
array_push($query['values'], $offset, $limit);
- //ZM\Warning('Calling the following sql query: ' .$query['sql']);
-
- $data['totalNotFiltered'] = dbFetchOne('SELECT count(*) AS Total FROM ' .$table, 'Total');
- if ( $search != '' || count($advsearch) ) {
- $data['total'] = dbFetchOne('SELECT count(*) AS Total FROM ' .$table.$where , 'Total', $wherevalues);
- } else {
- $data['total'] = $data['totalNotFiltered'];
- }
+ //ZM\Debug('Calling the following sql query: ' .$query['sql']);
$storage_areas = ZM\Storage::find();
$StorageById = array();
@@ -177,37 +194,41 @@ function queryRequest($search, $advsearch, $sort, $offset, $order, $limit) {
$StorageById[$S->Id()] = $S;
}
- $monitor_names = ZM\Monitor::find();
- $MonitorById = array();
- foreach ( $monitor_names as $S ) {
- $MonitorById[$S->Id()] = $S;
- }
-
$rows = array();
foreach ( dbFetchAll($query['sql'], NULL, $query['values']) as $row ) {
- $event = new ZM\Event($row['Id']);
+ $event = new ZM\Event($row);
+ if ( !$filter->test_post_sql_conditions($event) ) {
+ $event->remove_from_cache();
+ continue;
+ }
$scale = intval(5*100*ZM_WEB_LIST_THUMB_WIDTH / $event->Width());
$imgSrc = $event->getThumbnailSrc(array(),'&');
$streamSrc = $event->getStreamSrc(array(
- 'mode'=>'jpeg', 'scale'=>$scale, 'maxfps'=>ZM_WEB_VIDEO_MAXFPS, 'replay'=>'single', 'rate'=>'400'), '&');
+ 'mode'=>'jpeg', 'scale'=>$scale, 'maxfps'=>ZM_WEB_VIDEO_MAXFPS, 'replay'=>'single', 'rate'=>'400'), '&');
// Modify the row data as needed
$row['imgHtml'] = ' ';
$row['Name'] = validHtmlStr($row['Name']);
$row['Archived'] = $row['Archived'] ? translate('Yes') : translate('No');
$row['Emailed'] = $row['Emailed'] ? translate('Yes') : translate('No');
- $row['Monitor'] = ( $row['MonitorId'] and isset($MonitorById[$row['MonitorId']]) ) ? $MonitorById[$row['MonitorId']]->Name() : '';
$row['Cause'] = validHtmlStr($row['Cause']);
- $row['StartTime'] = strftime(STRF_FMT_DATETIME_SHORTER, strtotime($row['StartTime']));
- $row['EndTime'] = strftime(STRF_FMT_DATETIME_SHORTER, strtotime($row['StartTime']));
+ $row['StartDateTime'] = strftime(STRF_FMT_DATETIME_SHORTER, strtotime($row['StartDateTime']));
+ $row['EndDateTime'] = $row['EndDateTime'] ? strftime(STRF_FMT_DATETIME_SHORTER, strtotime($row['EndDateTime'])) : null;
$row['Length'] = gmdate('H:i:s', $row['Length'] );
$row['Storage'] = ( $row['StorageId'] and isset($StorageById[$row['StorageId']]) ) ? $StorageById[$row['StorageId']]->Name() : 'Default';
- $row['Notes'] = htmlspecialchars($row['Notes']);
- $row['DiskSpace'] = human_filesize($row['DiskSpace']);
+ $row['Notes'] = nl2br(htmlspecialchars($row['Notes']));
+ $row['DiskSpace'] = human_filesize($event->DiskSpace());
$rows[] = $row;
}
$data['rows'] = $rows;
- $data['updated'] = preg_match('/%/', DATE_FMT_CONSOLE_LONG) ? strftime(DATE_FMT_CONSOLE_LONG) : date(DATE_FMT_CONSOLE_LONG);
+
+ # totalNotFiltered must equal total, except when either search bar has been used
+ $data['totalNotFiltered'] = dbFetchOne('SELECT count(*) AS Total FROM Events AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id'. ($filter->sql() ? ' WHERE '.$filter->sql():''), 'Total');
+ if ( $search != '' || count($advsearch) ) {
+ $data['total'] = dbFetchOne('SELECT count(*) AS Total FROM Events AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id'.$where , 'Total', $wherevalues);
+ } else {
+ $data['total'] = $data['totalNotFiltered'];
+ }
return $data;
}
diff --git a/web/ajax/log.php b/web/ajax/log.php
index 9e6bd9585..60f0c1dc4 100644
--- a/web/ajax/log.php
+++ b/web/ajax/log.php
@@ -1,132 +1,186 @@
"search text" pairs
-// Bootstrap table sends json_ecoded array, which we must decode
-$advsearch = isset($_REQUEST['filter']) ? json_decode($_REQUEST['filter'], JSON_OBJECT_AS_ARRAY) : array();
-
-// Sort specifies the name of the column to sort on
-$sort = 'TimeKey';
-if ( isset($_REQUEST['sort']) ) {
- if ( !in_array($_REQUEST['sort'], array_merge($columns, $col_alt)) ) {
- ZM\Error('Invalid sort field: ' . $_REQUEST['sort']);
- } else {
- $sort = $_REQUEST['sort'];
- if ( $sort == 'DateTime' ) $sort = 'TimeKey';
- }
-}
-
-// Offset specifies the starting row to return, used for pagination
-$offset = 0;
-if ( isset($_REQUEST['offset']) ) {
- if ( ( !is_int($_REQUEST['offset']) and !ctype_digit($_REQUEST['offset']) ) ) {
- ZM\Error('Invalid value for offset: ' . $_REQUEST['offset']);
- } else {
- $offset = $_REQUEST['offset'];
- }
-}
-
-// Order specifies the sort direction, either asc or desc
-$order = (isset($_REQUEST['order']) and (strtolower($_REQUEST['order']) == 'asc')) ? 'ASC' : 'DESC';
-
-// Limit specifies the number of rows to return
-$limit = 100;
-if ( isset($_REQUEST['limit']) ) {
- if ( ( !is_int($_REQUEST['limit']) and !ctype_digit($_REQUEST['limit']) ) ) {
- ZM\Error('Invalid value for limit: ' . $_REQUEST['limit']);
- } else {
- $limit = $_REQUEST['limit'];
- }
-}
-
-$col_str = implode(', ', $columns);
$data = array();
-$query = array();
-$query['values'] = array();
-$likes = array();
-$where = '';
-// There are two search bars in the log view, normal and advanced
-// Making an exuctive decision to ignore the normal search, when advanced search is in use
-// Alternatively we could try to do both
-if ( count($advsearch) ) {
+$message = '';
- foreach ( $advsearch as $col=>$text ) {
- if ( !in_array($col, array_merge($columns, $col_alt)) ) {
- ZM\Error("'$col' is not a sortable column name");
- continue;
- }
- $text = '%' .$text. '%';
- array_push($likes, $col.' LIKE ?');
- array_push($query['values'], $text);
- }
- $wherevalues = $query['values'];
- $where = ' WHERE (' .implode(' OR ', $likes). ')';
+//
+// INITIALIZE AND CHECK SANITY
+//
-} else if ( $search != '' ) {
+if ( !canView('System') )
+ $message = 'Insufficient permissions to view log entries for user '.$user['Username'];
- $search = '%' .$search. '%';
- foreach ( $columns as $col ) {
- array_push($likes, $col.' LIKE ?');
- array_push($query['values'], $search);
- }
- $wherevalues = $query['values'];
- $where = ' WHERE (' .implode(' OR ', $likes). ')';
-}
-
-$query['sql'] = 'SELECT ' .$col_str. ' FROM `' .$table. '` ' .$where. ' ORDER BY ' .$sort. ' ' .$order. ' LIMIT ?, ?';
-array_push($query['values'], $offset, $limit);
-
-//ZM\Warning('Calling the following sql query: ' .$query['sql']);
-
-$data['totalNotFiltered'] = dbFetchOne('SELECT count(*) AS Total FROM ' .$table, 'Total');
-if ( $search != '' || count($advsearch) ) {
- $data['total'] = dbFetchOne('SELECT count(*) AS Total FROM ' .$table.$where , 'Total', $wherevalues);
+// task must be set
+if ( !isset($_REQUEST['task']) ) {
+ $message = 'This request requires a task to be set';
+} else if ( $_REQUEST['task'] != 'query' && $_REQUEST['task'] != 'create' ) {
+ // Only the query and create tasks are supported at the moment
+ $message = 'Unrecognised task '.$_REQUEST['task'];
} else {
- $data['total'] = $data['totalNotFiltered'];
+ $task = $_REQUEST['task'];
}
-if ( !$Servers )
- $Servers = ZM\Server::find();
-$servers_by_Id = array();
-# There is probably a better way to do this.
-foreach ( $Servers as $server ) {
- $servers_by_Id[$server->Id()] = $server;
+if ( $message ) {
+ ajaxError($message);
+ return;
}
-$rows = array();
-foreach ( dbFetchAll($query['sql'], NULL, $query['values']) as $row ) {
- $row['DateTime'] = strftime('%Y-%m-%d %H:%M:%S', intval($row['TimeKey']));
- $row['Server'] = ( $row['ServerId'] and isset($servers_by_Id[$row['ServerId']]) ) ? $servers_by_Id[$row['ServerId']]->Name() : '';
- // First strip out any html tags
- // Second strip out all characters that are not ASCII 32-126 (yes, 126)
- $row['Message'] = preg_replace('/[^\x20-\x7E]/', '', strip_tags($row['Message']));
- $rows[] = $row;
-}
-$data['rows'] = $rows;
-$data['logstate'] = logState();
-$data['updated'] = preg_match('/%/', DATE_FMT_CONSOLE_LONG) ? strftime(DATE_FMT_CONSOLE_LONG) : date(DATE_FMT_CONSOLE_LONG);
+//
+// MAIN LOOP
+//
+
+switch ( $task ) {
+ case 'create' :
+ createRequest();
+ break;
+ case 'query' :
+ $data = queryRequest();
+ break;
+ default :
+ ZM\Fatal('Unrecognised task '.$task);
+} // end switch task
ajaxResponse($data);
+//
+// FUNCTION DEFINITIONS
+//
+
+function createRequest() {
+ if ( !empty($_POST['level']) && !empty($_POST['message']) ) {
+ ZM\logInit(array('id'=>'web_js'));
+
+ $string = $_POST['message'];
+
+ $file = !empty($_POST['file']) ? preg_replace('/\w+:\/\/[\w.:]+\//', '', $_POST['file']) : '';
+ if ( !empty($_POST['line']) ) {
+ $line = validInt($_POST['line']);
+ } else {
+ $line = NULL;
+ }
+
+ $levels = array_flip(ZM\Logger::$codes);
+ if ( !isset($levels[$_POST['level']]) ) {
+ ZM\Panic('Unexpected logger level '.$_POST['level']);
+ }
+ $level = $levels[$_POST['level']];
+ ZM\Logger::fetch()->logPrint($level, $string, $file, $line);
+ } else {
+ ZM\Error('Invalid log create: '.print_r($_POST, true));
+ }
+}
+
+function queryRequest() {
+
+ // Offset specifies the starting row to return, used for pagination
+ $offset = 0;
+ if ( isset($_REQUEST['offset']) ) {
+ if ( ( !is_int($_REQUEST['offset']) and !ctype_digit($_REQUEST['offset']) ) ) {
+ ZM\Error('Invalid value for offset: ' . $_REQUEST['offset']);
+ } else {
+ $offset = $_REQUEST['offset'];
+ }
+ }
+
+ // Limit specifies the number of rows to return
+ $limit = 100;
+ if ( isset($_REQUEST['limit']) ) {
+ if ( ( !is_int($_REQUEST['limit']) and !ctype_digit($_REQUEST['limit']) ) ) {
+ ZM\Error('Invalid value for limit: ' . $_REQUEST['limit']);
+ } else {
+ $limit = $_REQUEST['limit'];
+ }
+ }
+ // The table we want our data from
+ $table = 'Logs';
+
+ // The names of the dB columns in the log table we are interested in
+ $columns = array('TimeKey', 'Component', 'ServerId', 'Pid', 'Code', 'Message', 'File', 'Line');
+
+ // The names of columns shown in the log view that are NOT dB columns in the database
+ $col_alt = array('DateTime', 'Server');
+
+ $sort = 'TimeKey';
+ if ( isset($_REQUEST['sort']) ) {
+ $sort = $_REQUEST['sort'];
+ if ( $sort == 'DateTime' ) $sort = 'TimeKey';
+ }
+ if ( !in_array($sort, array_merge($columns, $col_alt)) ) {
+ ZM\Error('Invalid sort field: ' . $sort);
+ return;
+ }
+
+ // Order specifies the sort direction, either asc or desc
+ $order = (isset($_REQUEST['order']) and (strtolower($_REQUEST['order']) == 'asc')) ? 'ASC' : 'DESC';
+
+ $col_str = implode(', ', $columns);
+ $data = array();
+ $query = array();
+ $query['values'] = array();
+ $likes = array();
+ $where = '';
+ // There are two search bars in the log view, normal and advanced
+ // Making an exuctive decision to ignore the normal search, when advanced search is in use
+ // Alternatively we could try to do both
+ //
+ // Advanced search contains an array of "column name" => "search text" pairs
+ // Bootstrap table sends json_ecoded array, which we must decode
+ $advsearch = isset($_REQUEST['filter']) ? json_decode($_REQUEST['filter'], JSON_OBJECT_AS_ARRAY) : array();
+ // Search contains a user entered string to search on
+ $search = isset($_REQUEST['search']) ? $_REQUEST['search'] : '';
+ if ( count($advsearch) ) {
+
+ foreach ( $advsearch as $col=>$text ) {
+ if ( !in_array($col, array_merge($columns, $col_alt)) ) {
+ ZM\Error("'$col' is not a searchable column name");
+ continue;
+ }
+ // Don't use wildcards on advanced search
+ //$text = '%' .$text. '%';
+ array_push($likes, $col.' LIKE ?');
+ array_push($query['values'], $text);
+ }
+ $wherevalues = $query['values'];
+ $where = ' WHERE (' .implode(' OR ', $likes). ')';
+
+ } else if ( $search != '' ) {
+
+ $search = '%' .$search. '%';
+ foreach ( $columns as $col ) {
+ array_push($likes, $col.' LIKE ?');
+ array_push($query['values'], $search);
+ }
+ $wherevalues = $query['values'];
+ $where = ' WHERE (' .implode(' OR ', $likes). ')';
+ }
+
+ $query['sql'] = 'SELECT ' .$col_str. ' FROM `' .$table. '` ' .$where. ' ORDER BY ' .$sort. ' ' .$order. ' LIMIT ?, ?';
+ array_push($query['values'], $offset, $limit);
+
+ $data['totalNotFiltered'] = dbFetchOne('SELECT count(*) AS Total FROM ' .$table, 'Total');
+ if ( $search != '' || count($advsearch) ) {
+ $data['total'] = dbFetchOne('SELECT count(*) AS Total FROM ' .$table.$where , 'Total', $wherevalues);
+ } else {
+ $data['total'] = $data['totalNotFiltered'];
+ }
+
+ $rows = array();
+ $results = dbFetchAll($query['sql'], NULL, $query['values']);
+ if ( !$results ) {
+ return $data;
+ }
+
+ foreach ( $results as $row ) {
+ $row['DateTime'] = strftime('%Y-%m-%d %H:%M:%S', intval($row['TimeKey']));
+ $Server = new ZM\Server($row['ServerId']);
+ $row['Server'] = $Server->Name();
+ // First strip out any html tags
+ // Second strip out all characters that are not ASCII 32-126 (yes, 126)
+ $row['Message'] = preg_replace('/[^\x20-\x7E]/', '', strip_tags($row['Message']));
+ $rows[] = $row;
+ }
+ $data['rows'] = $rows;
+ $data['logstate'] = logState();
+ $data['updated'] = preg_match('/%/', DATE_FMT_CONSOLE_LONG) ? strftime(DATE_FMT_CONSOLE_LONG) : date(DATE_FMT_CONSOLE_LONG);
+
+ return $data;
+}
diff --git a/web/ajax/status.php b/web/ajax/status.php
index 1fe4fa6a4..41c8a625d 100644
--- a/web/ajax/status.php
+++ b/web/ajax/status.php
@@ -6,6 +6,7 @@ if ( $_REQUEST['entity'] == 'navBar' ) {
$auth_hash = generateAuthHash(ZM_AUTH_HASH_IPS);
if ( isset($_REQUEST['auth']) and ($_REQUEST['auth'] != $auth_hash) ) {
$data['auth'] = $auth_hash;
+ $data['auth_relay'] = get_auth_relay();
}
}
// Each widget on the navbar has its own function
@@ -108,9 +109,9 @@ $statusData = array(
'Name' => true,
'Cause' => true,
'Notes' => true,
- 'StartTime' => true,
- 'StartTimeShort' => array( 'sql' => 'date_format( StartTime, \''.MYSQL_FMT_DATETIME_SHORT.'\' )' ),
- 'EndTime' => true,
+ 'StartDateTime' => true,
+ 'StartTimeShort' => array( 'sql' => 'date_format( StartDateTime, \''.MYSQL_FMT_DATETIME_SHORT.'\' )' ),
+ 'EndDateTime' => true,
'Width' => true,
'Height' => true,
'Length' => true,
@@ -132,9 +133,9 @@ $statusData = array(
'MonitorName' => array('sql' => '(SELECT Monitors.Name FROM Monitors WHERE Monitors.Id = Events.MonitorId)'),
'Name' => true,
'Cause' => true,
- 'StartTime' => true,
- 'StartTimeShort' => array( 'sql' => 'date_format( StartTime, \''.MYSQL_FMT_DATETIME_SHORT.'\' )' ),
- 'EndTime' => true,
+ 'StartDateTime' => true,
+ 'StartTimeShort' => array( 'sql' => 'date_format( StartDateTime, \''.MYSQL_FMT_DATETIME_SHORT.'\' )' ),
+ 'EndDateTime' => true,
'Width' => true,
'Height' => true,
'Length' => true,
@@ -179,7 +180,7 @@ $statusData = array(
'EventId' => true,
'Type' => true,
'TimeStamp' => true,
- 'TimeStampShort' => array( 'sql' => 'date_format( StartTime, \''.MYSQL_FMT_DATETIME_SHORT.'\' )' ),
+ 'TimeStampShort' => array( 'sql' => 'date_format( StartDateTime, \''.MYSQL_FMT_DATETIME_SHORT.'\' )' ),
'Delta' => true,
'Score' => true,
//'Image' => array( 'postFunc' => 'getFrameImage' ),
@@ -416,48 +417,54 @@ function getNearEvents() {
$event = dbFetchOne('SELECT * FROM Events WHERE Id=?', NULL, array($eventId));
if ( !$event ) return $NearEvents;
- if ( isset($_REQUEST['filter']) )
- parseFilter( $_REQUEST['filter'] );
+ $filter = ZM\Filter::parse($_REQUEST['filter']);
parseSort();
-
- if ( $user['MonitorIds'] )
- $midSql = ' AND MonitorId IN ('.join( ',', preg_split( '/["\'\s]*,["\'\s]*/', $user['MonitorIds'] ) ).')';
- else
- $midSql = '';
+ if ( $user['MonitorIds'] ) {
+ $filter = $filter->addTerm(array('cnj'=>'and', 'attr'=>'MonitorId', 'op'=>'IN', 'val'=>$user['MonitorIds']));
+ }
# When listing, it may make sense to list them in descending order. But when viewing Prev should timewise earlier and Next should be after.
- if ( $sortColumn == 'E.Id' or $sortColumn == 'E.StartTime' ) {
+ if ( $sortColumn == 'E.Id' or $sortColumn == 'E.StartDateTime' ) {
$sortOrder = 'ASC';
}
- $sql = 'SELECT E.Id AS Id, E.StartTime AS StartTime FROM Events AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id WHERE '.$sortColumn.' '.($sortOrder=='ASC'?'<=':'>=').' \''.$event[$_REQUEST['sort_field']].'\''.$_REQUEST['filter']['sql'].$midSql.' AND E.Id<'.$event['Id'] . ' ORDER BY '.$sortColumn.' '.($sortOrder=='ASC'?'DESC':'ASC');
+ $sql = 'SELECT E.Id AS Id, E.StartDateTime AS StartDateTime FROM Events AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id WHERE '.$sortColumn.' '.($sortOrder=='ASC'?'<=':'>=').' \''.$event[$_REQUEST['sort_field']].'\' AND ('.$filter->sql().') AND E.Id<'.$event['Id'] . ' ORDER BY '.$sortColumn.' '.($sortOrder=='ASC'?'DESC':'ASC');
if ( $sortColumn != 'E.Id' ) {
# When sorting by starttime, if we have two events with the same starttime (diffreent monitors) then we should sort secondly by Id
$sql .= ', E.Id DESC';
}
$sql .= ' LIMIT 1';
$result = dbQuery($sql);
+ if ( !$result ) {
+ ZM\Error('Failed to load previous event using '.$sql);
+ return $NearEvents;
+ }
+
$prevEvent = dbFetchNext($result);
- $sql = 'SELECT E.Id AS Id, E.StartTime AS StartTime FROM Events AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id WHERE '.$sortColumn .' '.($sortOrder=='ASC'?'>=':'<=').' \''.$event[$_REQUEST['sort_field']]."'".$_REQUEST['filter']['sql'].$midSql.' AND E.Id>'.$event['Id'] . ' ORDER BY '.$sortColumn.' '.($sortOrder=='ASC'?'ASC':'DESC');
+ $sql = 'SELECT E.Id AS Id, E.StartDateTime AS StartDateTime FROM Events AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id WHERE '.$sortColumn .' '.($sortOrder=='ASC'?'>=':'<=').' \''.$event[$_REQUEST['sort_field']]."' AND (".$filter->sql().') AND E.Id>'.$event['Id'] . ' ORDER BY '.$sortColumn.' '.($sortOrder=='ASC'?'ASC':'DESC');
if ( $sortColumn != 'E.Id' ) {
# When sorting by starttime, if we have two events with the same starttime (diffreent monitors) then we should sort secondly by Id
$sql .= ', E.Id ASC';
}
$sql .= ' LIMIT 1';
$result = dbQuery($sql);
+ if ( !$result ) {
+ ZM\Error('Failed to load next event using '.$sql);
+ return $NearEvents;
+ }
$nextEvent = dbFetchNext($result);
if ( $prevEvent ) {
$NearEvents['PrevEventId'] = $prevEvent['Id'];
- $NearEvents['PrevEventStartTime'] = $prevEvent['StartTime'];
+ $NearEvents['PrevEventStartTime'] = $prevEvent['StartDateTime'];
$NearEvents['PrevEventDefVideoPath'] = getEventDefaultVideoPath($prevEvent['Id']);
} else {
- $NearEvents['PrevEventId'] = $result['PrevEventStartTime'] = $result['PrevEventDefVideoPath'] = 0;
+ $NearEvents['PrevEventId'] = $NearEvents['PrevEventStartTime'] = $NearEvents['PrevEventDefVideoPath'] = 0;
}
if ( $nextEvent ) {
$NearEvents['NextEventId'] = $nextEvent['Id'];
- $NearEvents['NextEventStartTime'] = $nextEvent['StartTime'];
+ $NearEvents['NextEventStartTime'] = $nextEvent['StartDateTime'];
$NearEvents['NextEventDefVideoPath'] = getEventDefaultVideoPath($nextEvent['Id']);
} else {
$NearEvents['NextEventId'] = $NearEvents['NextEventStartTime'] = $NearEvents['NextEventDefVideoPath'] = 0;
diff --git a/web/ajax/stream.php b/web/ajax/stream.php
index 2c583ba14..cdb67c0f9 100644
--- a/web/ajax/stream.php
+++ b/web/ajax/stream.php
@@ -128,7 +128,7 @@ if ( sem_acquire($semaphore,1) !== false ) {
$data['auth'] = $auth_hash;
ZM\Debug("including nw auth hash " . $data['auth']);
} else {
- ZM\Debug('Not including nw auth hash becase it hashn\'t changed '.$auth_hash);
+ ZM\Debug('Not including new auth hash becase it hasn\'t changed '.$auth_hash);
}
}
ajaxResponse(array('status'=>$data));
diff --git a/web/api/app/Controller/Component/ImageComponent.php b/web/api/app/Controller/Component/ImageComponent.php
index 2033e0d8c..567333a71 100644
--- a/web/api/app/Controller/Component/ImageComponent.php
+++ b/web/api/app/Controller/Component/ImageComponent.php
@@ -89,11 +89,11 @@ class ImageComponent extends Component {
}
- // Take the StartTime of an Event and return
+ // Take the StartDateTime of an Event and return
// the path to its location on the filesystem
public function getEventPath( $event ) {
if ( $config['ZM_USE_DEEP_STORAGE'] == 1 )
- return $event['Event']['MonitorId'].'/'.strftime( "%y/%m/%d/%H/%M/%S", strtotime($event['Event']['StartTime']) );
+ return $event['Event']['MonitorId'].'/'.strftime( '%y/%m/%d/%H/%M/%S', strtotime($event['Event']['StartDateTime']) );
else
return $event['Event']['MonitorId'].'/'.$event['Event']['Id'];
}
diff --git a/web/api/app/Controller/EventsController.php b/web/api/app/Controller/EventsController.php
index 3b132e932..d18409387 100644
--- a/web/api/app/Controller/EventsController.php
+++ b/web/api/app/Controller/EventsController.php
@@ -48,9 +48,24 @@ class EventsController extends AppController {
$mon_options = '';
}
- if ( $this->request->params['named'] ) {
+ $named_params = $this->request->params['named'];
+ if ( $named_params ) {
+ # In 1.35.13 we renamed StartTime and EndTime to StartDateTime and EndDateTime.
+ # This hack renames the query string params
+ foreach ( $named_params as $k=>$v ) {
+ if ( false !== strpos($k, 'StartTime') ) {
+ $new_k = preg_replace('/StartTime/', 'StartDateTime', $k);
+ $named_params[$new_k] = $named_params[$k];
+ unset($named_params[$k]);
+ }
+ if ( false !== strpos($k, 'EndTime') ) {
+ $new_k = preg_replace('/EndTime/', 'EndDateTime', $k);
+ $named_params[$new_k] = $named_params[$k];
+ unset($named_params[$k]);
+ }
+ }
$this->FilterComponent = $this->Components->load('Filter');
- $conditions = $this->FilterComponent->buildFilter($this->request->params['named']);
+ $conditions = $this->FilterComponent->buildFilter($named_params);
} else {
$conditions = array();
}
@@ -65,7 +80,7 @@ class EventsController extends AppController {
// API
'limit' => '100',
- 'order' => array('StartTime'),
+ 'order' => array('StartDateTime'),
'paramType' => 'querystring',
);
if ( isset($conditions['GroupId']) ) {
@@ -309,7 +324,7 @@ class EventsController extends AppController {
} else {
$conditions = array();
}
- array_push($conditions, array("StartTime >= DATE_SUB(NOW(), INTERVAL $expr $unit)"));
+ array_push($conditions, array("StartDateTime >= DATE_SUB(NOW(), INTERVAL $expr $unit)"));
$query = $this->Event->find('all', array(
'fields' => array(
'MonitorId',
diff --git a/web/api/app/Model/Event.php b/web/api/app/Model/Event.php
index 22a97f62f..e54fd125f 100644
--- a/web/api/app/Model/Event.php
+++ b/web/api/app/Model/Event.php
@@ -31,6 +31,10 @@ class Event extends AppModel {
*/
public $displayField = 'Name';
+ public $virtualFields = array(
+ 'StartTime' => 'StartDateTime',
+ 'EndTime' => 'EndDateTime'
+ );
//The Associations below have been created with all possible keys, those that are not needed can be removed
diff --git a/web/includes/Event.php b/web/includes/Event.php
index 70eb27d8c..4e218edb2 100644
--- a/web/includes/Event.php
+++ b/web/includes/Event.php
@@ -14,8 +14,8 @@ class Event extends ZM_Object {
'StorageId' => null,
'SecondaryStorageId' => null,
'Cause' => '',
- 'StartTime' => null,
- 'EndTime' => null,
+ 'StartDateTime' => null,
+ 'EndDateTime' => null,
'Width' => null,
'Height' => null,
'Length' => null,
@@ -93,7 +93,7 @@ class Event extends ZM_Object {
public function Time() {
if ( ! isset($this->{'Time'}) ) {
- $this->{'Time'} = strtotime($this->{'StartTime'});
+ $this->{'Time'} = strtotime($this->{'StartDateTime'});
}
return $this->{'Time'};
}
@@ -153,9 +153,9 @@ class Event extends ZM_Object {
if ( $this->{'Scheme'} == 'Deep' ) {
# Assumption: All events have a start time
- $start_date = date_parse($this->{'StartTime'});
+ $start_date = date_parse($this->{'StartDateTime'});
if ( ! $start_date ) {
- throw new Exception('Unable to parse start time for event ' . $this->{'Id'} . ' not deleting files.');
+ throw new Exception('Unable to parse start date time for event ' . $this->{'Id'} . ' not deleting files.');
}
$start_date['year'] = $start_date['year'] % 100;
@@ -279,7 +279,7 @@ class Event extends ZM_Object {
}
if ( (!property_exists($this, 'DiskSpace')) or (null === $this->{'DiskSpace'}) ) {
$this->{'DiskSpace'} = folder_size($this->Path());
- if ( $this->{'EndTime'} ) {
+ if ( $this->{'EndDateTime'} ) {
# Finished events shouldn't grow in size much so we can commit it to the db.
dbQuery('UPDATE Events SET DiskSpace=? WHERE Id=?', array($this->{'DiskSpace'}, $this->{'Id'}));
}
@@ -606,7 +606,7 @@ class Event extends ZM_Object {
if ( $this->Archived() ) {
return false;
}
- if ( !$this->EndTime() ) {
+ if ( !$this->EndDateTime() ) {
return false;
}
if ( !canEdit('Events') ) {
@@ -619,7 +619,7 @@ class Event extends ZM_Object {
public function cant_delete_reason() {
if ( $this->Archived() ) {
return 'You cannot delete an archived event. Unarchive it first.';
- } else if ( ! $this->EndTime() ) {
+ } else if ( ! $this->EndDateTime() ) {
return 'You cannot delete an event while it is being recorded. Wait for it to finish.';
} else if ( ! canEdit('Events') ) {
return 'You do not have rights to edit Events.';
diff --git a/web/includes/Filter.php b/web/includes/Filter.php
index 86c72692b..c4610de4d 100644
--- a/web/includes/Filter.php
+++ b/web/includes/Filter.php
@@ -1,6 +1,7 @@
0,
'Concurrent' => 0,
'Query_json' => '',
+ 'LockRows' => 0,
);
protected $_querystring;
@@ -40,6 +42,7 @@ class Filter extends ZM_Object {
public function sql() {
if ( ! isset($this->_sql) ) {
+ $this->_sql = '';
foreach ( $this->FilterTerms() as $term ) {
#if ( ! ($term->is_pre_sql() or $term->is_post_sql()) ) {
$this->_sql .= $term->sql();
@@ -51,13 +54,14 @@ class Filter extends ZM_Object {
return $this->_sql;
}
- public function querystring($separator='&') {
- if ( (! isset($this->_querystring)) or ( $separator != '&' ) ) {
+ public function querystring($objectname='filter', $separator='&') {
+ if ( (! isset($this->_querystring)) or ( $separator != '&' ) or ($objectname != 'filter') ) {
+ $this->_querystring = '';
foreach ( $this->FilterTerms() as $term ) {
- $this->_querystring .= $term->querystring($separator);
+ $this->_querystring .= $term->querystring($objectname, $separator);
} # end foreach term
if ( $this->Id() ) {
- $this->_querystring .= $separator.'filter[Id]='.$this->Id();
+ $this->_querystring .= $separator.$objectname.urlencode('[Id]').'='.$this->Id();
}
}
return $this->_querystring;
@@ -65,6 +69,7 @@ class Filter extends ZM_Object {
public function hidden_fields() {
if ( ! isset($this->_hidden_fields) ) {
+ $this->_hidden_fields = '';
foreach ( $this->FilterTerms() as $term ) {
$this->_hidden_fields .= $term->hidden_fields();
} # end foreach term
@@ -141,6 +146,13 @@ class Filter extends ZM_Object {
if ( func_num_args( ) ) {
$this->{'Query'} = func_get_arg(0);
$this->{'Query_json'} = jsonEncode($this->{'Query'});
+ # We have altered the query so need to reset all the calculated results.
+ unset($this->_querystring);
+ unset($this->_sql);
+ unset($this->_hidden_fields);
+ unset($this->_pre_sql_conditions);
+ unset($this->_post_sql_conditions);
+ unset($this->_Terms);
}
if ( !property_exists($this, 'Query') ) {
if ( property_exists($this, 'Query_json') and $this->{'Query_json'} ) {
@@ -380,35 +392,35 @@ class Filter extends ZM_Object {
break;
case 'DateTime':
case 'StartDateTime':
- $sqlValue = 'E.StartTime';
+ $sqlValue = 'E.StartDateTime';
$dtAttr = true;
break;
case 'Date':
case 'StartDate':
- $sqlValue = 'to_days(E.StartTime)';
+ $sqlValue = 'to_days(E.StartDateTime)';
$dtAttr = true;
break;
case 'Time':
case 'StartTime':
- $sqlValue = 'extract(hour_second from E.StartTime)';
+ $sqlValue = 'extract(hour_second from E.StartDateTime)';
break;
case 'Weekday':
case 'StartWeekday':
- $sqlValue = 'weekday(E.StartTime)';
+ $sqlValue = 'weekday(E.StartDateTime)';
break;
case 'EndDateTime':
- $sqlValue = 'E.EndTime';
+ $sqlValue = 'E.EndDateTime';
$dtAttr = true;
break;
case 'EndDate':
- $sqlValue = 'to_days(E.EndTime)';
+ $sqlValue = 'to_days(E.EndDateTime)';
$dtAttr = true;
break;
case 'EndTime':
- $sqlValue = 'extract(hour_second from E.EndTime)';
+ $sqlValue = 'extract(hour_second from E.EndDateTime)';
break;
case 'EndWeekday':
- $sqlValue = 'weekday(E.EndTime)';
+ $sqlValue = 'weekday(E.EndDateTime)';
break;
case 'Id':
case 'Name':
@@ -619,6 +631,37 @@ class Filter extends ZM_Object {
return array_pop($exprStack);
} # end function tree
-} # end class Filter
+ function addTerm($term=false, $position=null) {
+ if ( !FilterTerm::is_valid_attr($term['attr']) ) {
+ Error('Unsupported filter attribute ' . $term['attr']);
+ return $this;
+ }
+
+ $terms = $this->terms();
+
+ if ( (!isset($position)) or ($position > count($terms)) )
+ $position = count($terms);
+ else if ( $position < 0 )
+ $position = 0;
+
+ if ( $term && ($position == 0) ) {
+ # if only 1 term, don't need AND or OR
+ unset($term['cnj']);
+ }
+
+ array_splice($terms, $position, 0, array($term ? $term : array()));
+ $this->terms($terms);
+
+ return $this;
+ } # end function addTerm
+
+ function addTerms($terms, $options=null) {
+ foreach ( $terms as $term ) {
+ $this->addTerm($term);
+ }
+ return $this;
+ }
+
+} # end class Filter
?>
diff --git a/web/includes/FilterTerm.php b/web/includes/FilterTerm.php
index 1f428fefa..6b41a2e1d 100644
--- a/web/includes/FilterTerm.php
+++ b/web/includes/FilterTerm.php
@@ -13,6 +13,7 @@ function getFilterQueryConjunctionTypes() {
return $validConjunctionTypes;
}
+
class FilterTerm {
public $filter;
public $index;
@@ -35,7 +36,7 @@ class FilterTerm {
$this->val = $term['val'];
if ( isset($term['cnj']) ) {
if ( array_key_exists($term['cnj'], $validConjunctionTypes) ) {
- $this->cnj = $term['cnj'];
+ $this->cnj = $term['cnj'];
} else {
Warning('Invalid cnj ' . $term['cnj'].' in '.print_r($term, true));
}
@@ -65,7 +66,8 @@ class FilterTerm {
return $values;
}
- foreach ( preg_split('/["\'\s]*?,["\'\s]*?/', preg_replace('/^["\']+?(.+)["\']+?$/', '$1', $this->val)) as $value ) {
+ $vals = is_array($this->val) ? $this->val : preg_split('/["\'\s]*?,["\'\s]*?/', preg_replace('/^["\']+?(.+)["\']+?$/', '$1', $this->val));
+ foreach ( $vals as $value ) {
switch ( $this->attr ) {
@@ -75,7 +77,7 @@ class FilterTerm {
case 'ExistsInFileSystem':
$value = '';
break;
- case 'DiskSpace':
+ case 'DiskPercent':
$value = '';
break;
case 'MonitorName':
@@ -83,7 +85,7 @@ class FilterTerm {
case 'Name':
case 'Cause':
case 'Notes':
- if ( $this->op == 'LIKE' || $this->op == 'NOT LIKE' ) {
+ if ( strstr($this->op, 'LIKE') and ! strstr($this->val, '%' ) ) {
$value = '%'.$value.'%';
}
$value = dbEscape($value);
@@ -145,7 +147,7 @@ class FilterTerm {
case 'AlarmZoneId':
return ' EXISTS ';
case 'ExistsInFileSystem':
- case 'DiskSpace':
+ case 'DiskPercent':
return '';
}
@@ -185,7 +187,7 @@ class FilterTerm {
}
return ' IS NOT ';
default:
- ZM\Warning('Invalid operator in filter: ' . print_r($this->op, true));
+ Warning('Invalid operator in filter: ' . print_r($this->op, true));
} // end switch op
} # end public function sql_operator
@@ -202,7 +204,7 @@ class FilterTerm {
switch ( $this->attr ) {
case 'ExistsInFileSystem':
- case 'DiskSpace':
+ case 'DiskPercent':
$sql .= 'TRUE /*'.$this->attr.'*/';
break;
case 'MonitorName':
@@ -220,49 +222,50 @@ class FilterTerm {
break;
# Unspecified start or end, so assume start, this is to support legacy filters
case 'DateTime':
- $sql .= 'E.StartTime';
+ $sql .= 'E.StartDateTime';
break;
case 'Date':
- $sql .= 'to_days(E.StartTime)';
+ $sql .= 'to_days(E.StartDateTime)';
break;
case 'Time':
- $sql .= 'extract(hour_second FROM E.StartTime)';
+ $sql .= 'extract(hour_second FROM E.StartDateTime)';
break;
case 'Weekday':
- $sql .= 'weekday(E.StartTime)';
+ $sql .= 'weekday(E.StartDateTime)';
break;
# Starting Time
case 'StartDateTime':
- $sql .= 'E.StartTime';
+ $sql .= 'E.StartDateTime';
break;
case 'FramesEventId':
$sql .= 'F.EventId';
break;
case 'StartDate':
- $sql .= 'to_days(E.StartTime)';
+ $sql .= 'to_days(E.StartDateTime)';
break;
case 'StartTime':
- $sql .= 'extract(hour_second FROM E.StartTime)';
+ $sql .= 'extract(hour_second FROM E.StartDateTime)';
break;
case 'StartWeekday':
- $sql .= 'weekday(E.StartTime)';
+ $sql .= 'weekday(E.StartDateTime)';
break;
# Ending Time
case 'EndDateTime':
- $sql .= 'E.EndTime';
+ $sql .= 'E.EndDateTime';
break;
case 'EndDate':
- $sql .= 'to_days(E.EndTime)';
+ $sql .= 'to_days(E.EndDateTime)';
break;
case 'EndTime':
- $sql .= 'extract(hour_second FROM E.EndTime)';
+ $sql .= 'extract(hour_second FROM E.EndDateTime)';
break;
case 'EndWeekday':
- $sql .= 'weekday(E.EndTime)';
+ $sql .= 'weekday(E.EndDateTime)';
break;
+ case 'Emailed':
case 'Id':
case 'Name':
- case 'EventDiskSpace':
+ case 'DiskSpace':
case 'MonitorId':
case 'StorageId':
case 'SecondaryStorageId':
@@ -292,19 +295,19 @@ class FilterTerm {
return $sql;
} # end public function sql
- public function querystring($querySep='&') {
+ public function querystring($objectname='filter', $querySep='&') {
# We don't validate the term parameters here
$query = '';
if ( $this->cnj )
- $query .= $querySep.urlencode('filter[Query][terms]['.$this->index.'][cnj]').'='.$this->cnj;
+ $query .= $querySep.urlencode($objectname.'[Query][terms]['.$this->index.'][cnj]').'='.$this->cnj;
if ( $this->obr )
- $query .= $querySep.urlencode('filter[Query][terms]['.$this->index.'][obr]').'='.$this->obr;
+ $query .= $querySep.urlencode($objectname.'[Query][terms]['.$this->index.'][obr]').'='.$this->obr;
- $query .= $querySep.urlencode('filter[Query][terms]['.$this->index.'][attr]').'='.urlencode($this->attr);
- $query .= $querySep.urlencode('filter[Query][terms]['.$this->index.'][op]').'='.urlencode($this->op);
- $query .= $querySep.urlencode('filter[Query][terms]['.$this->index.'][val]').'='.urlencode($this->val);
+ $query .= $querySep.urlencode($objectname.'[Query][terms]['.$this->index.'][attr]').'='.urlencode($this->attr);
+ $query .= $querySep.urlencode($objectname.'[Query][terms]['.$this->index.'][op]').'='.urlencode($this->op);
+ $query .= $querySep.urlencode($objectname.'[Query][terms]['.$this->index.'][val]').'='.urlencode($this->val);
if ( $this->cbr )
- $query .= $querySep.urlencode('filter[Query][terms]['.$this->index.'][cbr]').'='.$this->cbr;
+ $query .= $querySep.urlencode($objectname.'[Query][terms]['.$this->index.'][cbr]').'='.$this->cbr;
return $query;
} # end public function querystring
@@ -400,21 +403,63 @@ class FilterTerm {
}
public function is_pre_sql() {
- if ( $this->attr == 'DiskPercent' ) {
+ if ( $this->attr == 'DiskPercent' )
+ return true;
+ if ( $this->attr == 'DiskBlocks' )
return true;
- }
return false;
}
public function is_post_sql() {
if ( $this->attr == 'ExistsInFileSystem' ) {
return true;
- } else if ( $this->attr == 'DiskPercent' ) {
- return true;
}
return false;
}
+ public static function is_valid_attr($attr) {
+ $attrs = array(
+ 'ExistsInFileSystem',
+ 'Emailed',
+ 'DiskSpace',
+ 'DiskPercent',
+ 'DiskBlocks',
+ 'MonitorName',
+ 'ServerId',
+ 'MonitorServerId',
+ 'StorageServerId',
+ 'FilterServerId',
+ 'DateTime',
+ 'Date',
+ 'Time',
+ 'Weekday',
+ 'StartDateTime',
+ 'FramesEventId',
+ 'StartDate',
+ 'StartTime',
+ 'StartWeekday',
+ 'EndDateTime',
+ 'EndDate',
+ 'EndTime',
+ 'EndWeekday',
+ 'Id',
+ 'Name',
+ 'MonitorId',
+ 'StorageId',
+ 'SecondaryStorageId',
+ 'Length',
+ 'Frames',
+ 'AlarmFrames',
+ 'TotScore',
+ 'AvgScore',
+ 'MaxScore',
+ 'Cause',
+ 'Notes',
+ 'StateId',
+ 'Archived'
+ );
+ return in_array($attr, $attrs);
+ }
} # end class FilterTerm
?>
diff --git a/web/includes/Monitor.php b/web/includes/Monitor.php
index de1a10c2e..f2a0c2b8e 100644
--- a/web/includes/Monitor.php
+++ b/web/includes/Monitor.php
@@ -114,18 +114,6 @@ class Monitor extends ZM_Object {
'WebColour' => '#ff0000',
'Exif' => array('type'=>'boolean','default'=>0),
'Sequence' => null,
- 'TotalEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
- 'TotalEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
- 'HourEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
- 'HourEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
- 'DayEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
- 'DayEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
- 'WeekEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
- 'WeekEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
- 'MonthEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
- 'MonthEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
- 'ArchivedEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
- 'ArchivedEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
'ZoneCount' => 0,
'Refresh' => null,
'DefaultCodec' => 'auto',
@@ -138,6 +126,18 @@ class Monitor extends ZM_Object {
'AnalysisFPS' => null,
'CaptureFPS' => null,
'CaptureBandwidth' => null,
+ 'TotalEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
+ 'TotalEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
+ 'HourEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
+ 'HourEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
+ 'DayEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
+ 'DayEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
+ 'WeekEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
+ 'WeekEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
+ 'MonthEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
+ 'MonthEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
+ 'ArchivedEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
+ 'ArchivedEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1),
);
public function Control() {
diff --git a/web/includes/Object.php b/web/includes/Object.php
index e8fff930b..aa571bb59 100644
--- a/web/includes/Object.php
+++ b/web/includes/Object.php
@@ -11,7 +11,16 @@ class ZM_Object {
$row = NULL;
if ( $IdOrRow ) {
+ global $object_cache;
+ if ( ! isset($object_cache[$class]) ) {
+ $object_cache[$class] = array();
+ }
+ $cache = &$object_cache[$class];
+
if ( is_integer($IdOrRow) or ctype_digit($IdOrRow) ) {
+ if ( isset($cache[$IdOrRow]) ) {
+ return $cache[$IdOrRow];
+ }
$table = $class::$table;
$row = dbFetchOne("SELECT * FROM `$table` WHERE `Id`=?", NULL, array($IdOrRow));
if ( !$row ) {
@@ -22,12 +31,6 @@ class ZM_Object {
}
if ( $row ) {
- global $object_cache;
- if ( ! isset($object_cache[$class]) ) {
- $object_cache[$class] = array();
- }
- $cache = &$object_cache[$class];
-
foreach ($row as $k => $v) {
$this->{$k} = $v;
}
diff --git a/web/includes/actions/filter.php b/web/includes/actions/filter.php
index 63f4af94e..9216ef723 100644
--- a/web/includes/actions/filter.php
+++ b/web/includes/actions/filter.php
@@ -46,7 +46,6 @@ if ( isset($_REQUEST['object']) and ( $_REQUEST['object'] == 'filter' ) ) {
}
} else if ( ( $action == 'Save' ) or ( $action == 'SaveAs' ) or ( $action == 'execute' ) ) {
- $sql = '';
$_REQUEST['filter']['Query']['sort_field'] = validStr($_REQUEST['filter']['Query']['sort_field']);
$_REQUEST['filter']['Query']['sort_asc'] = validStr($_REQUEST['filter']['Query']['sort_asc']);
$_REQUEST['filter']['Query']['limit'] = validInt($_REQUEST['filter']['Query']['limit']);
@@ -95,7 +94,7 @@ if ( isset($_REQUEST['object']) and ( $_REQUEST['object'] == 'filter' ) ) {
} else if ( $filter->Background() ) {
$filter->control('start');
}
- $redirect = '?view=filter&Id='.$filter->Id();
+ $redirect = '?view=filter'.$filter->querystring('filter', '&');
} else if ( $action == 'control' ) {
if ( $_REQUEST['command'] == 'start'
diff --git a/web/includes/actions/monitor.php b/web/includes/actions/monitor.php
index 140957046..be17578cf 100644
--- a/web/includes/actions/monitor.php
+++ b/web/includes/actions/monitor.php
@@ -121,7 +121,8 @@ if ( $action == 'save' ) {
}
$saferNewName = basename($_REQUEST['newMonitor']['Name']);
$link_path = $NewStorage->Path().'/'.$saferNewName;
- if ( !symlink($NewStorage->Path().'/'.$mid, $link_path) ) {
+ // Use a relative path for the target so the link continues to work from backups or directory changes.
+ if ( !symlink($mid, $link_path) ) {
if ( ! ( file_exists($link_path) and is_link($link_path) ) ) {
ZM\Warning('Unable to symlink ' . $NewStorage->Path().'/'.$mid . ' to ' . $NewStorage->Path().'/'.$saferNewName);
}
diff --git a/web/includes/auth.php b/web/includes/auth.php
index f7cf7ec82..a4e1e4268 100644
--- a/web/includes/auth.php
+++ b/web/includes/auth.php
@@ -248,14 +248,12 @@ function userFromSession() {
if ( isset($_SESSION['AuthHash'.$_SESSION['remoteAddr']]) )
$user = getAuthUser($_SESSION['AuthHash'.$_SESSION['remoteAddr']]);
else
- ZM\Debug("No auth hash in session, there should have been");
+ ZM\Debug('No auth hash in session, there should have been');
} else {
# Need to refresh permissions and validate that the user still exists
$sql = 'SELECT * FROM Users WHERE Enabled=1 AND Username=?';
$user = dbFetchOne($sql, NULL, array($_SESSION['username']));
}
- } else {
- ZM\Debug('No username in session');
}
return $user;
}
diff --git a/web/includes/functions.php b/web/includes/functions.php
index 7a562ca38..9ac46cd3c 100644
--- a/web/includes/functions.php
+++ b/web/includes/functions.php
@@ -996,23 +996,19 @@ function parseSort($saveToSession=false, $querySep='&') {
$sortColumn = 'E.Cause';
break;
case 'DateTime' :
- $sortColumn = 'E.StartTime';
- $_REQUEST['sort_field'] = 'StartTime';
+ $sortColumn = 'E.StartDateTime';
+ $_REQUEST['sort_field'] = 'StartDateTime';
break;
case 'DiskSpace' :
$sortColumn = 'E.DiskSpace';
break;
case 'StartTime' :
- $sortColumn = 'E.StartTime';
- break;
case 'StartDateTime' :
- $sortColumn = 'E.StartTime';
+ $sortColumn = 'E.StartDateTime';
break;
case 'EndTime' :
- $sortColumn = 'E.EndTime';
- break;
case 'EndDateTime' :
- $sortColumn = 'E.EndTime';
+ $sortColumn = 'E.EndDateTime';
break;
case 'Length' :
$sortColumn = 'E.Length';
@@ -1048,7 +1044,7 @@ function parseSort($saveToSession=false, $querySep='&') {
$sortColumn = 'F.Score';
break;
default:
- $sortColumn = 'E.StartTime';
+ $sortColumn = 'E.StartDateTime';
break;
}
if ( !isset($_REQUEST['sort_asc']) )
@@ -1077,7 +1073,7 @@ function parseFilter(&$filter, $saveToSession=false, $querySep='&') {
$Filter = ZM\Filter::parse($filter, $querySep);
$filter['sql'] = $Filter->sql();
- $filter['querystring'] = $Filter->querystring($querySep);
+ $filter['querystring'] = $Filter->querystring('filter', $querySep);
$filter['hidden_fields'] = $Filter->hidden_fields();
$filter['pre_sql_conditions'] = $Filter->pre_sql_conditions();
$filter['post_sql_conditions'] = $Filter->post_sql_conditions();
diff --git a/web/includes/logger.php b/web/includes/logger.php
index fb7d58f93..ab59b412b 100644
--- a/web/includes/logger.php
+++ b/web/includes/logger.php
@@ -408,10 +408,10 @@ class Logger {
}
}
- $message = $code.' ['.$string.']';
if ( $level <= $this->syslogLevel )
- syslog( self::$syslogPriorities[$level], $message );
+ syslog(self::$syslogPriorities[$level], $message);
+ $message = $code.' ['.$string.']';
if ( $level <= $this->databaseLevel ) {
try {
global $dbConn;
diff --git a/web/includes/session.php b/web/includes/session.php
index 2358567ba..0190f9897 100644
--- a/web/includes/session.php
+++ b/web/includes/session.php
@@ -144,8 +144,10 @@ class Session {
}
public function _gc($max) {
// Calculate what is to be deemed old
- $old = time() - $max;
- $sth = $this->db->prepare('DELETE * FROM Sessions WHERE access < :old');
+ $now = time();
+ $old = $now - $max;
+ ZM\Debug('doing session gc ' . $now . '-' . $max. '='.$old);
+ $sth = $this->db->prepare('DELETE FROM Sessions WHERE access < :old');
$sth->bindParam(':old', $old, PDO::PARAM_INT);
return $sth->execute() ? true : false;
}
diff --git a/web/lang/en_gb.php b/web/lang/en_gb.php
index b80121bed..0877f7399 100644
--- a/web/lang/en_gb.php
+++ b/web/lang/en_gb.php
@@ -371,6 +371,7 @@ $SLANG = array(
'FilterUpdateDiskSpace' => 'Update used disk space',
'FilterDeleteEvents' => 'Delete all matches',
'FilterCopyEvents' => 'Copy all matches',
+ 'FilterLockRows' => 'Lock Rows',
'FilterMoveEvents' => 'Move all matches',
'FilterEmailEvents' => 'Email details of all matches',
'FilterEmailTo' => 'Email To',
diff --git a/web/skins/classic/css/base/skin.css b/web/skins/classic/css/base/skin.css
index c6723b3a8..ee7a8a471 100644
--- a/web/skins/classic/css/base/skin.css
+++ b/web/skins/classic/css/base/skin.css
@@ -123,7 +123,7 @@ table th:last-child{
a:link {
- color: #3498db;
+ color: #0fbcf9;
text-decoration: none;
}
diff --git a/web/skins/classic/css/base/views/cycle.css b/web/skins/classic/css/base/views/cycle.css
new file mode 100644
index 000000000..9d89bc4b3
--- /dev/null
+++ b/web/skins/classic/css/base/views/cycle.css
@@ -0,0 +1,3 @@
+#imageFeed {
+ margin: 0 auto;
+}
diff --git a/web/skins/classic/js/skin.js b/web/skins/classic/js/skin.js
index b33d1bb7d..85449927c 100644
--- a/web/skins/classic/js/skin.js
+++ b/web/skins/classic/js/skin.js
@@ -351,6 +351,11 @@ if ( currentView != 'none' && currentView != 'login' ) {
.done(setNavBar)
.fail(function(jqxhr, textStatus, error) {
console.log("Request Failed: " + textStatus + ", " + error);
+ if ( ! jqxhr.responseText ) {
+ console.log("No responseText in jqxhr");
+ console.log(jqxhr);
+ return;
+ }
console.log("Response Text: " + jqxhr.responseText.replace(/(<([^>]+)>)/gi, ''));
if ( textStatus != "timeout" ) {
// The idea is that this should only fail due to auth, so reload the page
@@ -367,10 +372,14 @@ if ( currentView != 'none' && currentView != 'login' ) {
}
if ( data.auth ) {
if ( data.auth != auth_hash ) {
+ console.log("Update auth_hash to "+data.auth);
// Update authentication token.
auth_hash = data.auth;
}
}
+ if ( data.auth_relay ) {
+ auth_relay = data.auth_relay;
+ }
// iterate through all the keys then update each element id with the same name
for (var key of Object.keys(data)) {
if ( key == "auth" ) continue;
@@ -752,8 +761,13 @@ function stateStuff(action, runState, newState) {
}
function logAjaxFail(jqxhr, textStatus, error) {
- var responseText = jqxhr.responseText.replace(/(<([^>]+)>)/gi, '').trim(); // strip any html or whitespace from the response
console.log("Request Failed: " + textStatus + ", " + error);
+ if ( ! jqxhr.responseText ) {
+ console.log("Ajax request failed. No responseText. jqxhr follows:");
+ console.log(jqxhr);
+ return;
+ }
+ var responseText = jqxhr.responseText.replace(/(<([^>]+)>)/gi, '').trim(); // strip any html or whitespace from the response
if ( responseText ) console.log("Response Text: " + responseText);
}
diff --git a/web/skins/classic/views/cycle.php b/web/skins/classic/views/cycle.php
index ba97d341c..b9f779c50 100644
--- a/web/skins/classic/views/cycle.php
+++ b/web/skins/classic/views/cycle.php
@@ -182,7 +182,7 @@ xhtmlHeaders(__FILE__, translate('CycleWatch'));
?>
-
diff --git a/web/skins/classic/views/export.php b/web/skins/classic/views/export.php
index 90e269a33..e234402f4 100644
--- a/web/skins/classic/views/export.php
+++ b/web/skins/classic/views/export.php
@@ -152,8 +152,8 @@ while ( $event_row = dbFetchNext($results) ) {
Name()).($event->Archived()?'*':'') ?>
MonitorId(), $event->MonitorName(), canEdit( 'Monitors' ) ) ?>
Cause()), canEdit( 'Events' ), 'title="' .htmlspecialchars($event->Notes()). '" class="eDetailLink" data-eid=' .$event->Id(). '"') ?>
- StartTime())) .
-( $event->EndTime() ? ' until ' . strftime(STRF_FMT_DATETIME_SHORTER, strtotime($event->EndTime()) ) : '' ) ?>
+ StartDateTime())) .
+( $event->EndDateTime() ? ' until ' . strftime(STRF_FMT_DATETIME_SHORTER, strtotime($event->EndDateTime()) ) : '' ) ?>
Length() ) ?>
Id(), $event->Frames() ) ?>
diff --git a/web/skins/classic/views/filter.php b/web/skins/classic/views/filter.php
index c19e06ef7..723414f6e 100644
--- a/web/skins/classic/views/filter.php
+++ b/web/skins/classic/views/filter.php
@@ -35,13 +35,12 @@ $filterNames = array(''=>translate('ChooseFilter'));
$filter = NULL;
$fid = 0;
-if ( isset($_REQUEST['Id']) ) {
+if ( isset($_REQUEST['Id']) and $_REQUEST['Id'] ) {
$fid = validInt($_REQUEST['Id']);
-} else if ( isset($_REQUEST['filter[Id]']) ) {
- $fid = validInt($_REQUEST['filter[Id]']);
- ZM\Warning("got fid by object id $fid");
+} else if ( isset($_REQUEST['filter']) and isset($_REQUEST['filter']['Id']) ) {
+ $fid = validInt($_REQUEST['filter']['Id']);
}
-
+$filter = null;
foreach ( ZM\Filter::find(null,array('order'=>'lower(Name)')) as $Filter ) {
$filterNames[$Filter->Id()] = $Filter->Id() . ' ' . $Filter->Name();
if ( $Filter->Background() )
@@ -53,17 +52,18 @@ foreach ( ZM\Filter::find(null,array('order'=>'lower(Name)')) as $Filter ) {
$filter = $Filter;
}
}
-if ( !$filter ) {
+if ( !$filter ) {
$filter = new ZM\Filter();
-
- if ( isset($_REQUEST['filter']) ) {
- # Update our filter object with whatever changes we have made before saving
- $filter->set($_REQUEST['filter']);
- }
-} else {
- ZM\Debug('filter: ' . print_r($filter,true));
}
+ZM\Debug('filter: ' . print_r($filter,true));
+if ( isset($_REQUEST['filter']) ) {
+ # Update our filter object with whatever changes we have made before saving
+ $filter->set($_REQUEST['filter']);
+ ZM\Debug("Setting filter from " . print_r($_REQUEST['filter'], true));
+}
+ZM\Debug('filter: ' . print_r($filter,true));
+
$conjunctionTypes = ZM\getFilterQueryConjunctionTypes();
$obracketTypes = array();
$cbracketTypes = array();
@@ -89,8 +89,8 @@ $attrTypes = array(
'Cause' => translate('AttrCause'),
'DiskBlocks' => translate('AttrDiskBlocks'),
'DiskPercent' => translate('AttrDiskPercent'),
- 'DiskSpace' => translate('AttrDiskSpace'),
- 'EventDiskSpace' => translate('AttrEventDiskSpace'),
+ #'StorageDiskSpace' => translate('AttrStorageDiskSpace'),
+ 'DiskSpace' => translate('AttrEventDiskSpace'),
'EndDateTime' => translate('AttrEndDateTime'),
'EndDate' => translate('AttrEndDate'),
'EndTime' => translate('AttrEndTime'),
@@ -366,6 +366,7 @@ for ( $i=0; $i < count($terms); $i++ ) {
translate('AttrId'),
'Name' => translate('AttrName'),
@@ -373,7 +374,7 @@ $sort_fields = array(
'DiskSpace' => translate('AttrDiskSpace'),
'Notes' => translate('AttrNotes'),
'MonitorName' => translate('AttrMonitorName'),
- 'StartDateTime' => translate('AttrStartDateTime'),
+ 'StartTime' => translate('AttrStartDateTime'),
'Length' => translate('AttrDuration'),
'Frames' => translate('AttrFrames'),
'AlarmFrames' => translate('AttrAlarmFrames'),
@@ -381,7 +382,7 @@ $sort_fields = array(
'AvgScore' => translate('AttrAvgScore'),
'MaxScore' => translate('AttrMaxScore'),
);
-echo htmlSelect( 'filter[Query][sort_field]', $sort_fields, $filter->sort_field() );
+echo htmlSelect('filter[Query][sort_field]', $sort_fields, $filter->sort_field());
$sort_dirns = array(
'1' => translate('SortAsc'),
'0' => translate('SortDesc')
@@ -484,6 +485,10 @@ if ( ZM_OPT_MESSAGE ) {
Concurrent() ) { ?> checked="checked" data-on-click-this="updateButtons"/>
+
+
+ LockRows() ) { ?> checked="checked" data-on-click-this="updateButtons"/>
+
diff --git a/web/skins/classic/views/frames.php b/web/skins/classic/views/frames.php
index 359703acd..da2f4c2ae 100644
--- a/web/skins/classic/views/frames.php
+++ b/web/skins/classic/views/frames.php
@@ -181,8 +181,9 @@ if ( count($frames) ) {
Id();
+ $ratio_factor = $Monitor->ViewHeight() / $Monitor->ViewWidth();
$thmb_width = ZM_WEB_LIST_THUMB_WIDTH ? 'width='.ZM_WEB_LIST_THUMB_WIDTH : '';
- $thmb_height = ZM_WEB_LIST_THUMB_HEIGHT ? 'height='.ZM_WEB_LIST_THUMB_HEIGHT : '';
+ $thmb_height = 'height="'.( ZM_WEB_LIST_THUMB_HEIGHT ? ZM_WEB_LIST_THUMB_HEIGHT : ZM_WEB_LIST_THUMB_WIDTH*$ratio_factor ) .'"';
$thmb_fn = 'filename=' .$Event->MonitorId(). '_' .$frame['EventId']. '_' .$frame['FrameId']. '.jpg';
$img_src = join('&', array_filter(array($base_img_src, $thmb_width, $thmb_height, $thmb_fn)));
$full_img_src = join('&', array_filter(array($base_img_src, $thmb_fn)));
diff --git a/web/skins/classic/views/js/cycle.js b/web/skins/classic/views/js/cycle.js
index a6fb05482..de958d8d0 100644
--- a/web/skins/classic/views/js/cycle.js
+++ b/web/skins/classic/views/js/cycle.js
@@ -40,6 +40,8 @@ function cyclePrev() {
function initCycle() {
periodical_id = nextCycleView.periodical(cycleRefreshTimeout);
+ var scale = $j('#scale').val();
+ if ( scale == '0' || scale == 'auto' ) changeScale();
}
function changeSize() {
@@ -100,6 +102,8 @@ function changeScale() {
}
if ( scale != '0' && scale != '' && scale != 'auto' ) {
+ var newWidth = ( monitorData[monIdx].width * scale ) / SCALE_BASE;
+ var newHeight = ( monitorData[monIdx].height * scale ) / SCALE_BASE;
if ( newWidth ) {
monitor_frame.css('width', newWidth+'px');
}
@@ -107,8 +111,13 @@ function changeScale() {
monitor_frame.css('height', newHeight+'px');
}
} else {
- monitor_frame.css('width', '100%');
- monitor_frame.css('height', 'auto');
+ //var bottomEl = streamMode == 'stills' ? $j('#eventImageNav') : $j('#replayStatus');
+ var newSize = scaleToFit(monitorData[monIdx].width, monitorData[monIdx].height, monitor_frame, $j('#buttons'));
+ newWidth = newSize.width;
+ newHeight = newSize.height;
+ autoScale = newSize.autoScale;
+ monitor_frame.width(newWidth);
+ monitor_frame.height(newHeight);
}
/*Stream could be an applet so can't use moo tools*/
@@ -124,6 +133,7 @@ function changeScale() {
//src = src.replace(/rand=\d+/i,'rand='+Math.floor((Math.random() * 1000000) ));
src = src.replace(/scale=[\.\d]+/i, 'scale='+scale);
+ // zms doesn't actually use width&height
if ( scale != '0' && scale != '' && scale != 'auto' ) {
src = src.replace(/width=[\.\d]+/i, 'width='+newWidth);
src = src.replace(/height=[\.\d]+/i, 'height='+newHeight);
diff --git a/web/skins/classic/views/js/event.js b/web/skins/classic/views/js/event.js
index 143f51ebc..1ddb111fa 100644
--- a/web/skins/classic/views/js/event.js
+++ b/web/skins/classic/views/js/event.js
@@ -16,7 +16,7 @@ function vjsReplay() {
var overLaid = $j("#videoobj");
overLaid.append('
No more events
');
} else {
- var endTime = (Date.parse(eventData.EndTime)).getTime();
+ var endTime = (Date.parse(eventData.EndDateTime)).getTime();
var nextStartTime = nextEventStartTime.getTime(); //nextEventStartTime.getTime() is a mootools workaround, highjacks Date.parse
if ( nextStartTime <= endTime ) {
streamNext(true);
@@ -176,12 +176,7 @@ function changeScale() {
} else {
alarmCue.html(renderAlarmCues(eventViewer));//just re-render alarmCues. skip ajax call
}
- if ( scale == '0' ) {
- Cookie.write('zmEventScaleAuto', 'auto', {duration: 10*365, samesite: 'strict'});
- } else {
- Cookie.write('zmEventScale'+eventData.MonitorId, scale, {duration: 10*365, samesite: 'strict'});
- Cookie.dispose('zmEventScaleAuto');
- }
+ Cookie.write('zmEventScale'+eventData.MonitorId, scale, {duration: 10*365, samesite: 'strict'});
} // end function changeScale
function changeReplayMode() {
@@ -584,7 +579,7 @@ function getEventResponse(respObj, respText) {
$('dataCause').setProperty( 'title', causeString );
}
$('dataCause').set( 'text', eventData.Cause );
- $('dataTime').set( 'text', eventData.StartTime );
+ $('dataTime').set( 'text', eventData.StartDateTime );
$('dataDuration').set( 'text', eventData.Length );
$('dataFrames').set( 'text', eventData.Frames+"/"+eventData.AlarmFrames );
$('dataScore').set( 'text', eventData.TotScore+"/"+eventData.AvgScore+"/"+eventData.MaxScore );
@@ -606,7 +601,7 @@ function getEventResponse(respObj, respText) {
vid.src({type: 'video/mp4', src: CurEventDefVideoPath}); //Currently mp4 is all we use
console.log('getEventResponse');
initialAlarmCues(eventData.Id);//ajax and render, new event
- addVideoTimingTrack(vid, LabelFormat, eventData.MonitorName, eventData.Length, eventData.StartTime);
+ addVideoTimingTrack(vid, LabelFormat, eventData.MonitorName, eventData.Length, eventData.StartDateTime);
CurEventDefVideoPath = null;
$j('#modeValue').html('Replay');
$j('#zoomValue').html('1');
@@ -1088,7 +1083,7 @@ function initPage() {
//FIXME prevent blocking...not sure what is happening or best way to unblock
if ( $j('#videoobj').length ) {
vid = videojs('videoobj');
- addVideoTimingTrack(vid, LabelFormat, eventData.MonitorName, eventData.Length, eventData.StartTime);
+ addVideoTimingTrack(vid, LabelFormat, eventData.MonitorName, eventData.Length, eventData.StartDateTime);
$j('.vjs-progress-control').append('
');//add a place for videojs only on first load
vid.on('ended', vjsReplay);
vid.on('play', vjsPlay);
diff --git a/web/skins/classic/views/js/event.js.php b/web/skins/classic/views/js/event.js.php
index beee0b668..105f47da1 100644
--- a/web/skins/classic/views/js/event.js.php
+++ b/web/skins/classic/views/js/event.js.php
@@ -44,8 +44,8 @@ var eventData = {
Width: 'Width() ?>',
Height: 'Height() ?>',
Length: 'Length() ?>',
- StartTime: 'StartTime() ?>',
- EndTime: 'EndTime() ?>',
+ StartDateTime: 'StartDateTime() ?>',
+ EndDateTime: 'EndDateTime() ?>',
Frames: 'Frames() ?>',
MonitorName: 'Name()) ?>'
};
diff --git a/web/skins/classic/views/js/events.js b/web/skins/classic/views/js/events.js
index f037795e8..7d4c67369 100644
--- a/web/skins/classic/views/js/events.js
+++ b/web/skins/classic/views/js/events.js
@@ -17,14 +17,14 @@ var params =
"data":
{
"search":"some search text",
- "sort":"StartTime",
+ "sort":"StartDateTime",
"order":"asc",
"offset":0,
"limit":25
"filter":
{
"Name":"some advanced search text"
- "StartTime":"some more advanced search text"
+ "StartDateTime":"some more advanced search text"
}
},
"cache":true,
@@ -35,7 +35,11 @@ var params =
// Called by bootstrap-table to retrieve zm event data
function ajaxRequest(params) {
- $j.getJSON(thisUrl + '?view=request&request=events&task=query', params.data)
+ if ( params.data && params.data.filter ) {
+ params.data.advsearch = params.data.filter;
+ delete params.data.filter;
+ }
+ $j.getJSON(thisUrl + '?view=request&request=events&task=query'+filterQuery, params.data)
.done(function(data) {
var rows = processRows(data.rows);
// rearrange the result into what bootstrap-table expects
@@ -57,14 +61,14 @@ function processRows(rows) {
if ( canEditMonitors ) row.Monitor = '
' + row.Monitor + ' ';
if ( canEditEvents ) row.Cause = '
' + row.Cause + ' ';
if ( row.Notes.indexOf('detected:') >= 0 ) {
- row.Cause = row.Cause + '
' + row.Notes + '
';
+ row.Cause = row.Cause + '
' + row.Notes + '
';
} else if ( row.Notes != 'Forced Web: ' ) {
row.Cause = row.Cause + '
' + row.Notes + '
';
}
row.Frames = '
' + row.Frames + ' ';
row.AlarmFrames = '
' + row.AlarmFrames + ' ';
row.MaxScore = '
' + row.MaxScore + ' ';
- row.Thumbnail = '
' + row.imgHtml + ' ';
+ if ( WEB_LIST_THUMBS ) row.Thumbnail = '
' + row.imgHtml + ' ';
});
return rows;
@@ -131,7 +135,7 @@ function manageDelConfirmModalBtns() {
$j.getJSON(thisUrl + '?request=events&task=delete&eids[]='+selections.join('&eids[]='))
.done( function(data) {
$j('#eventTable').bootstrapTable('refresh');
- window.location.reload(true);
+ $j('#deleteConfirm').modal('hide');
})
.fail(logAjaxFail);
});
@@ -157,6 +161,9 @@ function getEventDetailModal(eid) {
}
function initPage() {
+ // Remove the thumbnail column from the DOM if thumbnails are off globally
+ if ( !WEB_LIST_THUMBS ) $j('th[data-field="Thumbnail"]').remove();
+
// Load the delete confirmation modal into the DOM
getDelConfirmModal();
@@ -234,7 +241,6 @@ function initPage() {
$j.getJSON(thisUrl + '?request=events&task=archive&eids[]='+selections.join('&eids[]='))
.done( function(data) {
$j('#eventTable').bootstrapTable('refresh');
- window.location.reload(true);
})
.fail(logAjaxFail);
});
@@ -247,17 +253,14 @@ function initPage() {
}
var selections = getIdSelections();
- console.log(selections);
+ //console.log(selections);
evt.preventDefault();
$j.getJSON(thisUrl + '?request=events&task=unarchive&eids[]='+selections.join('&eids[]='))
.done( function(data) {
$j('#eventTable').bootstrapTable('refresh');
- window.location.reload(true);
})
.fail(logAjaxFail);
-
- //window.location.reload(true);
});
// Manage the EDIT button
@@ -317,13 +320,6 @@ function initPage() {
$j('#deleteConfirm').modal('show');
});
- // Manage the eventdetail links in the events list
- $j(".eDetailLink").click(function(evt) {
- evt.preventDefault();
- var eid = $j(this).data('eid');
- getEventDetailModal(eid);
- });
-
// Update table links each time after new data is loaded
table.on('post-body.bs.table', function(data) {
// Manage the eventdetail links in the events list
@@ -339,6 +335,7 @@ function initPage() {
table.find("tr td:nth-child(" + (thumb_ndx+1) + ")").addClass('colThumbnail zoom');
});
+ table.bootstrapTable('resetSearch');
// The table is initially given a hidden style, so now that we are done rendering, show it
table.show();
}
diff --git a/web/skins/classic/views/js/events.js.php b/web/skins/classic/views/js/events.js.php
index 48f405dd7..207a6745e 100644
--- a/web/skins/classic/views/js/events.js.php
+++ b/web/skins/classic/views/js/events.js.php
@@ -11,3 +11,4 @@ var archivedString = "";
var emailedString = "";
var yesString = "";
var noString = "";
+var WEB_LIST_THUMBS = ;
diff --git a/web/skins/classic/views/js/filter.js b/web/skins/classic/views/js/filter.js
index fd7ee94ca..707fb06e1 100644
--- a/web/skins/classic/views/js/filter.js
+++ b/web/skins/classic/views/js/filter.js
@@ -74,35 +74,32 @@ function validateForm(form) {
function updateButtons(element) {
var form = element.form;
- if ( element.type == 'checkbox' && element.checked ) {
- form.elements['executeButton'].disabled = false;
- } else {
- var canExecute = false;
- if ( form.elements['filter[AutoArchive]'] && form.elements['filter[AutoArchive]'].checked ) {
- canExecute = true;
- } else if ( form.elements['filter[AutoUnarchive]'] && form.elements['filter[AutoUnarchive]'].checked ) {
- canExecute = true;
- } else if ( form.elements['filter[AutoCopy]'] && form.elements['filter[AutoCopy]'].checked ) {
- canExecute = true;
- } else if ( form.elements['filter[AutoMove]'] && form.elements['filter[AutoMove]'].checked ) {
- canExecute = true;
- } else if ( form.elements['filter[AutoVideo]'] && form.elements['filter[AutoVideo]'].checked ) {
- canExecute = true;
- } else if ( form.elements['filter[AutoUpload]'] && form.elements['filter[AutoUpload]'].checked ) {
- canExecute = true;
- } else if ( form.elements['filter[AutoEmail]'] && form.elements['filter[AutoEmail]'].checked ) {
- canExecute = true;
- } else if ( form.elements['filter[AutoMessage]'] && form.elements['filter[AutoMessage]'].checked ) {
- canExecute = true;
- } else if ( form.elements['filter[AutoExecute]'].checked && form.elements['filter[AutoExecuteCmd]'].value != '' ) {
- canExecute = true;
- } else if ( form.elements['filter[AutoDelete]'].checked ) {
- canExecute = true;
- } else if ( form.elements['filter[UpdateDiskSpace]'].checked ) {
- canExecute = true;
- }
- form.elements['executeButton'].disabled = !canExecute;
+
+ var canExecute = false;
+ if ( form.elements['filter[AutoArchive]'] && form.elements['filter[AutoArchive]'].checked ) {
+ canExecute = true;
+ } else if ( form.elements['filter[AutoUnarchive]'] && form.elements['filter[AutoUnarchive]'].checked ) {
+ canExecute = true;
+ } else if ( form.elements['filter[AutoCopy]'] && form.elements['filter[AutoCopy]'].checked ) {
+ canExecute = true;
+ } else if ( form.elements['filter[AutoMove]'] && form.elements['filter[AutoMove]'].checked ) {
+ canExecute = true;
+ } else if ( form.elements['filter[AutoVideo]'] && form.elements['filter[AutoVideo]'].checked ) {
+ canExecute = true;
+ } else if ( form.elements['filter[AutoUpload]'] && form.elements['filter[AutoUpload]'].checked ) {
+ canExecute = true;
+ } else if ( form.elements['filter[AutoEmail]'] && form.elements['filter[AutoEmail]'].checked ) {
+ canExecute = true;
+ } else if ( form.elements['filter[AutoMessage]'] && form.elements['filter[AutoMessage]'].checked ) {
+ canExecute = true;
+ } else if ( form.elements['filter[AutoExecute]'].checked && form.elements['filter[AutoExecuteCmd]'].value != '' ) {
+ canExecute = true;
+ } else if ( form.elements['filter[AutoDelete]'].checked ) {
+ canExecute = true;
+ } else if ( form.elements['filter[UpdateDiskSpace]'].checked ) {
+ canExecute = true;
}
+ form.elements['executeButton'].disabled = !canExecute;
if ( form.elements['filter[Name]'].value ) {
form.elements['Save'].disabled = false;
form.elements['SaveAs'].disabled = false;
diff --git a/web/skins/classic/views/js/monitor.js b/web/skins/classic/views/js/monitor.js
index d612e806e..75cb89707 100644
--- a/web/skins/classic/views/js/monitor.js
+++ b/web/skins/classic/views/js/monitor.js
@@ -105,7 +105,6 @@ function initPage() {
document.querySelectorAll('input[name="newMonitor[MaxFPS]"]').forEach(function(el) {
el.oninput = el.onclick = function(e) {
if ( e.target.value ) {
- console.log('showing');
$j('#newMonitor\\[MaxFPS\\]').show();
} else {
$j('#newMonitor\\[MaxFPS\\]').hide();
@@ -115,7 +114,6 @@ function initPage() {
document.querySelectorAll('input[name="newMonitor[AlarmMaxFPS]"]').forEach(function(el) {
el.oninput = el.onclick = function(e) {
if ( e.target.value ) {
- console.log('showing');
$j('#newMonitor\\[AlarmMaxFPS\\]').show();
} else {
$j('#newMonitor\\[AlarmMaxFPS\\]').hide();
@@ -209,7 +207,6 @@ function initPage() {
var form = document.getElementById('contentForm');
var latitude = form.elements['newMonitor[Latitude]'].value;
var longitude = form.elements['newMonitor[Longitude]'].value;
- console.log("lat: " + latitude + ', long:'+longitude);
map = L.map('LocationMap', {
center: L.latLng(latitude, longitude),
zoom: 13,
@@ -258,13 +255,9 @@ function random_WebColour() {
function update_estimated_ram_use() {
var buffer_count = document.querySelectorAll('input[name="newMonitor[ImageBufferCount]"]')[0].value;
- console.log(buffer_count);
var width = document.querySelectorAll('input[name="newMonitor[Width]"]')[0].value;
- console.log(width);
var height = document.querySelectorAll('input[name="newMonitor[Height]"]')[0].value;
- console.log(height);
var colours = document.querySelectorAll('select[name="newMonitor[Colours]"]')[0].value;
- console.log(colours);
document.getElementById('estimated_ram_use').innerHTML = human_filesize(buffer_count * width * height * colours, 0);
}
diff --git a/web/skins/classic/views/js/monitor.js.php b/web/skins/classic/views/js/monitor.js.php
index cc61270d0..bdcc17554 100644
--- a/web/skins/classic/views/js/monitor.js.php
+++ b/web/skins/classic/views/js/monitor.js.php
@@ -1,4 +1,4 @@
-var ZM_OPT_USE_GEOLOCATION = '';
+var ZM_OPT_USE_GEOLOCATION = '' == '1' ? true : false;
0
';
-// select E.Id,E.Name,UNIX_TIMESTAMP(E.StartTime) as StartTimeSecs,UNIX_TIMESTAMP(max(DATE_ADD(E.StartTime, Interval Delta+0.5 Second))) as CalcEndTimeSecs, E.Length,max(F.FrameId) as Frames,E.MaxScore,E.Cause,E.Notes,E.Archived,E.MonitorId
+// select E.Id,E.Name,UNIX_TIMESTAMP(E.StartDateTime) as StartTimeSecs,UNIX_TIMESTAMP(max(DATE_ADD(E.StartDateTime, Interval Delta+0.5 Second))) as CalcEndTimeSecs, E.Length,max(F.FrameId) as Frames,E.MaxScore,E.Cause,E.Notes,E.Archived,E.MonitorId
// from Events as E
// inner join Monitors as M on (E.MonitorId = M.Id)
// inner join Frames F on F.EventId=E.Id
-// where not isnull(E.Frames) and not isnull(StartTime) ";
+// where not isnull(E.Frames) and not isnull(StartDateTime) ";
// Note that the delta value seems more accurate than the time stamp for some reason.
$framesSql = '
@@ -219,14 +219,14 @@ $initialDisplayInterval = 1000;
if ( isset($_REQUEST['displayinterval']) )
$initialDisplayInterval = validHtmlStr($_REQUEST['displayinterval']);
-#$eventsSql .= ' GROUP BY E.Id,E.Name,E.StartTime,E.Length,E.Frames,E.MaxScore,E.Cause,E.Notes,E.Archived,E.MonitorId';
+#$eventsSql .= ' GROUP BY E.Id,E.Name,E.StartDateTime,E.Length,E.Frames,E.MaxScore,E.Cause,E.Notes,E.Archived,E.MonitorId';
$minTimeSecs = $maxTimeSecs = 0;
if ( isset($minTime) && isset($maxTime) ) {
$minTimeSecs = strtotime($minTime);
$maxTimeSecs = strtotime($maxTime);
- $eventsSql .= " AND EndTime > '" . $minTime . "' AND StartTime < '" . $maxTime . "'";
- $framesSql .= " AND EndTime > '" . $minTime . "' AND StartTime < '" . $maxTime . "'";
+ $eventsSql .= " AND EndDateTime > '" . $minTime . "' AND StartDateTime < '" . $maxTime . "'";
+ $framesSql .= " AND EndDateTime > '" . $minTime . "' AND StartDateTime < '" . $maxTime . "'";
$framesSql .= ") AND TimeStamp > '" . $minTime . "' AND TimeStamp < '" . $maxTime . "'";
} else {
$framesSql .= ')';
diff --git a/web/skins/classic/views/options.php b/web/skins/classic/views/options.php
index cc8b0b568..2be9e9b52 100644
--- a/web/skins/classic/views/options.php
+++ b/web/skins/classic/views/options.php
@@ -231,6 +231,7 @@ foreach ( array_map('basename', glob('skins/'.$skin.'/css/*', GLOB_ONLYDIR)) as
Url()), $canEdit, $svr_opt ) ?>
PathToIndex()), $canEdit, $svr_opt ) ?>
PathToZMS()), $canEdit, $svr_opt ) ?>
+
PathToAPI()), $canEdit, $svr_opt ) ?>
Status()), $canEdit, $svr_opt) ?>
Id()]), $canEdit, $svr_opt) ?>
@@ -279,17 +280,23 @@ foreach ( array_map('basename', glob('skins/'.$skin.'/css/*', GLOB_ONLYDIR)) as
'lower(Name)') ) as $Storage ) {
+ $filter = new ZM\Filter();
+ $filter->addTerm(array('attr'=>'StorageId','op'=>'=','val'=>$Storage->Id()));
+ if ( $user['MonitorIds'] ) {
+ $filter = $filter->addTerm(array('cnj'=>'and', 'attr'=>'MonitorId', 'op'=>'IN', 'val'=>$user['MonitorIds']));
+ }
+
$str_opt = 'class="storageCol" data-sid="'.$Storage->Id().'"';
?>
- Id()), $canEdit, $str_opt ) ?>
- Name()), $canEdit, $str_opt ) ?>
- Path()), $canEdit, $str_opt ) ?>
- Type()), $canEdit, $str_opt ) ?>
- Scheme()), $canEdit, $str_opt ) ?>
- Server()->Name()), $canEdit, $str_opt ) ?>
+ Id()), $canEdit, $str_opt) ?>
+ Name()), $canEdit, $str_opt) ?>
+ Path()), $canEdit, $str_opt) ?>
+ Type()), $canEdit, $str_opt) ?>
+ Scheme()), $canEdit, $str_opt) ?>
+ Server()->Name()), $canEdit, $str_opt) ?>
disk_used_space()) . ' of ' . human_filesize($Storage->disk_total_space()) ?>
- EventCount().' using '.human_filesize($Storage->event_disk_space()) ?>
+ querystring(), $Storage->EventCount().' using '.human_filesize($Storage->event_disk_space()) ); ?>
EventCount() or !$canEdit ) { ?> disabled="disabled"EventCount() ? ' title="Can\'t delete as long as there are events stored here."' : ''?>/>
@@ -302,13 +309,12 @@ foreach ( array_map('basename', glob('skins/'.$skin.'/css/*', GLOB_ONLYDIR)) as
APIs are disabled. To enable, please turn on OPT_USE_API in Options->System";
- }
- else {
+ $apiEnabled = dbFetchOne('SELECT Value FROM Config WHERE Name=\'ZM_OPT_USE_API\'');
+ if ( $apiEnabled['Value'] != '1' ) {
+ echo 'APIs are disabled. To enable, please turn on OPT_USE_API in Options->System
';
+ } else {
?>