diff --git a/distros/redhat/zoneminder.spec b/distros/redhat/zoneminder.spec index f7eeeb016..2a08edc70 100644 --- a/distros/redhat/zoneminder.spec +++ b/distros/redhat/zoneminder.spec @@ -28,7 +28,7 @@ %global _hardened_build 1 Name: zoneminder -Version: 1.34.10 +Version: 1.34.11 Release: 1%{?dist} Summary: A camera monitoring and analysis tool Group: System Environment/Daemons diff --git a/src/zm_box.h b/src/zm_box.h index fa377e593..efc12cb18 100644 --- a/src/zm_box.h +++ b/src/zm_box.h @@ -33,37 +33,33 @@ // Class used for storing a box, which is defined as a region // defined by two coordinates // -class Box -{ +class Box { private: Coord lo, hi; Coord size; public: - inline Box() - { - } + inline Box() { } explicit inline Box( int p_size ) : lo( 0, 0 ), hi ( p_size-1, p_size-1 ), size( Coord::Range( hi, lo ) ) { } inline Box( int p_x_size, int p_y_size ) : lo( 0, 0 ), hi ( p_x_size-1, p_y_size-1 ), size( Coord::Range( hi, lo ) ) { } inline Box( int lo_x, int lo_y, int hi_x, int hi_y ) : lo( lo_x, lo_y ), hi( hi_x, hi_y ), size( Coord::Range( hi, lo ) ) { } inline Box( const Coord &p_lo, const Coord &p_hi ) : lo( p_lo ), hi( p_hi ), size( Coord::Range( hi, lo ) ) { } - inline const Coord &Lo() const { return( lo ); } - inline int LoX() const { return( lo.X() ); } - inline int LoY() const { return( lo.Y() ); } - inline const Coord &Hi() const { return( hi ); } - inline int HiX() const { return( hi.X() ); } - inline int HiY() const { return( hi.Y() ); } - inline const Coord &Size() const { return( size ); } - inline int Width() const { return( size.X() ); } - inline int Height() const { return( size.Y() ); } - inline int Area() const { return( size.X()*size.Y() ); } + inline const Coord &Lo() const { return lo; } + inline int LoX() const { return lo.X(); } + inline int LoY() const { return lo.Y(); } + inline const Coord &Hi() const { return hi; } + inline int HiX() const { return hi.X(); } + inline int HiY() const { return hi.Y(); } + inline const Coord &Size() const { return size; } + inline int Width() const { return size.X(); } + inline int Height() const { return size.Y(); } + inline int Area() const { return size.X()*size.Y(); } - inline const Coord Centre() const - { + inline const Coord Centre() const { int mid_x = int(round(lo.X()+(size.X()/2.0))); int mid_y = int(round(lo.Y()+(size.Y()/2.0))); - return( Coord( mid_x, mid_y ) ); + return Coord( mid_x, mid_y ); } inline bool Inside( const Coord &coord ) const { diff --git a/src/zm_config.cpp b/src/zm_config.cpp index 7d75042ba..9c99172e9 100644 --- a/src/zm_config.cpp +++ b/src/zm_config.cpp @@ -63,7 +63,9 @@ void zmLoadConfig() { closedir(configSubFolder); } - zmDbConnect(); + if ( !zmDbConnect() ) { + Fatal("Can't connect to db. Can't continue."); + } config.Load(); config.Assign(); diff --git a/src/zm_coord.h b/src/zm_coord.h index 9bf31144c..c6234fb1c 100644 --- a/src/zm_coord.h +++ b/src/zm_coord.h @@ -25,8 +25,7 @@ // // Class used for storing an x,y pair, i.e. a coordinate // -class Coord -{ +class Coord { private: int x, y; @@ -44,8 +43,7 @@ public: inline int &Y() { return( y ); } inline const int &Y() const { return( y ); } - inline static Coord Range( const Coord &coord1, const Coord &coord2 ) - { + inline static Coord Range( const Coord &coord1, const Coord &coord2 ) { Coord result( (coord1.x-coord2.x)+1, (coord1.y-coord2.y)+1 ); return( result ); } diff --git a/src/zm_eventstream.cpp b/src/zm_eventstream.cpp index fbd236cc2..d081f4e76 100644 --- a/src/zm_eventstream.cpp +++ b/src/zm_eventstream.cpp @@ -164,7 +164,22 @@ bool EventStream::loadEventData(uint64_t event_id) { event_data->Orientation = (Monitor::Orientation)(dbrow[8] == NULL ? 0 : atoi(dbrow[8])); mysql_free_result(result); - Storage * storage = new Storage(event_data->storage_id); + if ( !monitor ) { + monitor = Monitor::Load(event_data->monitor_id, false, Monitor::QUERY); + } else if ( monitor->Id() != event_data->monitor_id ) { + delete monitor; + monitor = Monitor::Load(event_data->monitor_id, false, Monitor::QUERY); + } + if ( !monitor ) { + Fatal("Unable to load monitor id %d for streaming", event_data->monitor_id); + } + + if ( !storage ) { + storage = new Storage(event_data->storage_id); + } else if ( storage->Id() != event_data->storage_id ) { + delete storage; + storage = new Storage(event_data->storage_id); + } const char *storage_path = storage->Path(); if ( event_data->scheme == Storage::DEEP ) { @@ -206,7 +221,6 @@ bool EventStream::loadEventData(uint64_t event_id) { staticConfig.PATH_WEB.c_str(), storage_path, event_data->monitor_id, event_data->event_id); } - delete storage; storage = NULL; updateFrameRate((double)event_data->frame_count/event_data->duration); Debug(3, "fps set by frame_count(%d)/duration(%f)", @@ -246,7 +260,7 @@ bool EventStream::loadEventData(uint64_t event_id) { event_data->frames[i-1].timestamp = last_timestamp + ((i-last_id)*frame_delta); event_data->frames[i-1].offset = event_data->frames[i-1].timestamp - event_data->start_time; event_data->frames[i-1].in_db = false; - Debug(3,"Frame %d timestamp:(%f), offset(%f) delta(%f), in_db(%d)", + Debug(3, "Frame %d timestamp:(%f), offset(%f) delta(%f), in_db(%d)", i, event_data->frames[i-1].timestamp, event_data->frames[i-1].offset, @@ -277,7 +291,10 @@ bool EventStream::loadEventData(uint64_t event_id) { mysql_free_result(result); - if ( event_data->video_file[0] ) { + if ( event_data->video_file[0] || (monitor->GetOptVideoWriter() > 0) ) { + if ( !event_data->video_file[0] ) { + snprintf(event_data->video_file, sizeof(event_data->video_file), "%" PRIu64 "-%s", event_data->event_id, "video.mp4"); + } std::string filepath = std::string(event_data->path) + "/" + std::string(event_data->video_file); //char filepath[PATH_MAX]; //snprintf(filepath, sizeof(filepath), "%s/%s", event_data->path, event_data->video_file); @@ -305,7 +322,7 @@ bool EventStream::loadEventData(uint64_t event_id) { void EventStream::processCommand(const CmdMsg *msg) { Debug(2, "Got message, type %d, msg %d", msg->msg_type, msg->msg_data[0]); // Check for incoming command - switch( (MsgCommand)msg->msg_data[0] ) { + switch ( (MsgCommand)msg->msg_data[0] ) { case CMD_PAUSE : Debug(1, "Got PAUSE command"); @@ -657,7 +674,8 @@ bool EventStream::sendFrame(int delta_us) { Image *send_image = prepareImage(&image); if ( !vid_stream ) { - vid_stream = new VideoStream("pipe:", format, bitrate, effective_fps, send_image->Colours(), send_image->SubpixelOrder(), send_image->Width(), send_image->Height()); + vid_stream = new VideoStream("pipe:", format, bitrate, effective_fps, + send_image->Colours(), send_image->SubpixelOrder(), send_image->Width(), send_image->Height()); fprintf(stdout, "Content-type: %s\r\n\r\n", vid_stream->MimeType()); vid_stream->OpenStream(); } @@ -700,9 +718,10 @@ Debug(1, "Loading image"); } else if ( ffmpeg_input ) { // Get the frame from the mp4 input Debug(1,"Getting frame from ffmpeg"); - AVFrame *frame; FrameData *frame_data = &event_data->frames[curr_frame_id-1]; - frame = ffmpeg_input->get_frame( ffmpeg_input->get_video_stream_id(), frame_data->offset ); + AVFrame *frame = ffmpeg_input->get_frame( + ffmpeg_input->get_video_stream_id(), + frame_data->offset); if ( frame ) { image = new Image(frame); //av_frame_free(&frame); @@ -982,8 +1001,8 @@ void EventStream::runStream() { // you can calculate the relationship between now and the start // or calc the relationship from the last frame. I think from the start is better as it self-corrects - if ( send_frame && type != STREAM_MPEG ) { - if ( delta_us > 0) { + if ( send_frame && (type != STREAM_MPEG) ) { + if ( delta_us > 0 ) { if ( delta_us > MAX_SLEEP_USEC ) { Debug(1, "Limiting sleep to %d because calculated sleep is too long %d", MAX_SLEEP_USEC, delta_us); delta_us = MAX_SLEEP_USEC; @@ -1026,18 +1045,12 @@ void EventStream::runStream() { closeComms(); } // void EventStream::runStream() -void EventStream::setStreamStart( uint64_t init_event_id, unsigned int init_frame_id=0 ) { +void EventStream::setStreamStart( + uint64_t init_event_id, + unsigned int init_frame_id=0) { loadInitialEventData(init_event_id, init_frame_id); - if ( !(monitor = Monitor::Load(event_data->monitor_id, false, Monitor::QUERY)) ) { - Fatal("Unable to load monitor id %d for streaming", event_data->monitor_id); - return; - } -} +} // end void EventStream::setStreamStart(init_event_id,init_frame_id=0) void EventStream::setStreamStart(int monitor_id, time_t event_time) { loadInitialEventData(monitor_id, event_time); - if ( !(monitor = Monitor::Load(event_data->monitor_id, false, Monitor::QUERY)) ) { - Fatal("Unable to load monitor id %d for streaming", monitor_id); - return; - } } diff --git a/src/zm_eventstream.h b/src/zm_eventstream.h index 6850a3d11..a482483b4 100644 --- a/src/zm_eventstream.h +++ b/src/zm_eventstream.h @@ -20,9 +20,6 @@ #ifndef ZM_EVENTSTREAM_H #define ZM_EVENTSTREAM_H -#include -#include - #include "zm_image.h" #include "zm_stream.h" #include "zm_video.h" @@ -83,7 +80,6 @@ class EventStream : public StreamBase { struct timeval start; // clock time when started the event EventData *event_data; - FFmpeg_Input *ffmpeg_input; protected: bool loadEventData( uint64_t event_id ); @@ -95,23 +91,40 @@ class EventStream : public StreamBase { bool sendFrame( int delta_us ); public: - EventStream() { - mode = DEFAULT_MODE; - replay_rate = DEFAULT_RATE; - - forceEventChange = false; - - curr_frame_id = 0; - curr_stream_time = 0.0; - send_frame = false; - - event_data = 0; - + EventStream() : + mode(DEFAULT_MODE), + forceEventChange(false), + curr_frame_id(0), + curr_stream_time(0.0), + send_frame(false), + event_data(0), + storage(NULL), + ffmpeg_input(NULL), // Used when loading frames from an mp4 - input_codec_context = 0; - input_codec = 0; - - ffmpeg_input = NULL; + input_codec_context(0), + input_codec(0) + {} + ~EventStream() { + if ( event_data ) { + if ( event_data->frames ) { + delete[] event_data->frames; + event_data->frames = NULL; + } + delete event_data; + event_data = NULL; + } + if ( monitor ) { + delete monitor; + monitor = NULL; + } + if ( storage ) { + delete storage; + storage = NULL; + } + if ( ffmpeg_input ) { + delete ffmpeg_input; + ffmpeg_input = NULL; + } } void setStreamStart( uint64_t init_event_id, unsigned int init_frame_id ); void setStreamStart( int monitor_id, time_t event_time ); @@ -121,8 +134,10 @@ class EventStream : public StreamBase { void runStream(); Image *getImage(); private: - AVCodecContext *input_codec_context; - AVCodec *input_codec; + Storage *storage; + FFmpeg_Input *ffmpeg_input; + AVCodecContext *input_codec_context; + AVCodec *input_codec; }; #endif // ZM_EVENTSTREAM_H diff --git a/src/zm_ffmpeg.h b/src/zm_ffmpeg.h index c65bb38a0..73afff3e3 100644 --- a/src/zm_ffmpeg.h +++ b/src/zm_ffmpeg.h @@ -321,6 +321,7 @@ void zm_dump_codecpar(const AVCodecParameters *par); frame->pts \ ); +#if LIBAVUTIL_VERSION_CHECK(54, 4, 0, 74, 100) #define zm_dump_video_frame(frame,text) Debug(1, "%s: format %d %s %dx%d linesize:%dx%d pts: %" PRId64, \ text, \ frame->format, \ @@ -331,6 +332,18 @@ void zm_dump_codecpar(const AVCodecParameters *par); frame->pts \ ); +#else +#define zm_dump_video_frame(frame,text) Debug(1, "%s: format %d %s %dx%d linesize:%dx%d pts: %" PRId64, \ + text, \ + frame->format, \ + "unsupported", \ + frame->width, \ + frame->height, \ + frame->linesize[0], frame->linesize[1], \ + frame->pts \ + ); +#endif + #if LIBAVCODEC_VERSION_CHECK(56, 8, 0, 60, 100) #define zm_av_packet_unref( packet ) av_packet_unref( packet ) #define zm_av_packet_ref( dst, src ) av_packet_ref( dst, src ) diff --git a/src/zm_ffmpeg_input.cpp b/src/zm_ffmpeg_input.cpp index 45128645c..28ecd4ac7 100644 --- a/src/zm_ffmpeg_input.cpp +++ b/src/zm_ffmpeg_input.cpp @@ -15,10 +15,26 @@ FFmpeg_Input::FFmpeg_Input() { FFmpeg_Input::~FFmpeg_Input() { if ( streams ) { + for ( unsigned int i = 0; i < input_format_context->nb_streams; i += 1 ) { + avcodec_close(streams[i].context); + streams[i].context = NULL; + } delete streams; streams = NULL; } -} + if ( frame ) { + av_frame_free(&frame); + frame = NULL; + } + if ( input_format_context ) { +#if !LIBAVFORMAT_VERSION_CHECK(53, 17, 0, 25, 0) + av_close_input_file(input_format_context); +#else + avformat_close_input(&input_format_context); +#endif + input_format_context = NULL; + } +} // end ~FFmpeg_Input() int FFmpeg_Input::Open(const char *filepath) { @@ -90,6 +106,7 @@ int FFmpeg_Input::Open(const char *filepath) { avcodec_free_context(&streams[i].context); #endif avformat_close_input(&input_format_context); + input_format_context = NULL; return error; } } // end foreach stream @@ -103,7 +120,6 @@ int FFmpeg_Input::Open(const char *filepath) { } // end int FFmpeg_Input::Open( const char * filepath ) AVFrame *FFmpeg_Input::get_frame(int stream_id) { - int frameComplete = false; AVPacket packet; av_init_packet(&packet); @@ -139,8 +155,8 @@ AVFrame *FFmpeg_Input::get_frame(int stream_id) { } ret = zm_send_packet_receive_frame(context, frame, packet); if ( ret < 0 ) { - Error("Unable to decode frame at frame %d: %s, continuing", - streams[packet.stream_index].frame_count, av_make_error_string(ret).c_str()); + Error("Unable to decode frame at frame %d: %d %s, continuing", + streams[packet.stream_index].frame_count, ret, av_make_error_string(ret).c_str()); zm_av_packet_unref(&packet); av_frame_free(&frame); continue; @@ -211,15 +227,17 @@ AVFrame *FFmpeg_Input::get_frame(int stream_id, double at) { last_seek_request = seek_target; // Seeking seems to typically seek to a keyframe, so then we have to decode until we get the frame we want. - if ( frame->pts <= seek_target ) { + if ( frame->pts <= seek_target ) { zm_dump_frame(frame, "pts <= seek_target"); while ( frame && (frame->pts < seek_target) ) { - if ( !get_frame(stream_id) ) + if ( !get_frame(stream_id) ) { + Warning("Got no frame. returning nothing"); return frame; + } } + zm_dump_frame(frame, "frame->pts <= seek_target, got"); return frame; } return get_frame(stream_id); - -} // end AVFrame *FFmpeg_Input::get_frame( int stream_id, struct timeval at) +} // end AVFrame *FFmpeg_Input::get_frame( int stream_id, struct timeval at) diff --git a/src/zm_image.cpp b/src/zm_image.cpp index 97c2132c6..31c71037f 100644 --- a/src/zm_image.cpp +++ b/src/zm_image.cpp @@ -48,6 +48,8 @@ static short *g_v_table; static short *g_u_table; static short *b_u_table; +struct SwsContext *sws_convert_context = NULL; + jpeg_compress_struct *Image::writejpg_ccinfo[101] = { 0 }; jpeg_compress_struct *Image::encodejpg_ccinfo[101] = { 0 }; jpeg_decompress_struct *Image::readjpg_dcinfo = 0; @@ -160,15 +162,17 @@ Image::Image( int p_width, int p_height, int p_colours, int p_subpixelorder, uin update_function_pointers(); } -Image::Image( const AVFrame *frame ) { +Image::Image(const AVFrame *frame) { AVFrame *dest_frame = zm_av_frame_alloc(); text[0] = '\0'; width = frame->width; height = frame->height; pixels = width*height; + colours = ZM_COLOUR_RGB32; subpixelorder = ZM_SUBPIX_ORDER_RGBA; + size = pixels*colours; buffer = 0; holdbuffer = 0; @@ -183,26 +187,28 @@ Image::Image( const AVFrame *frame ) { #endif #if HAVE_LIBSWSCALE - struct SwsContext *mConvertContext = sws_getContext( + sws_convert_context = sws_getCachedContext( + sws_convert_context, width, height, (AVPixelFormat)frame->format, width, height, AV_PIX_FMT_RGBA, SWS_BICUBIC, NULL, NULL, NULL); - if ( mConvertContext == NULL ) - Fatal( "Unable to create conversion context" ); + if ( sws_convert_context == NULL ) + Fatal("Unable to create conversion context"); - if ( sws_scale(mConvertContext, frame->data, frame->linesize, 0, frame->height, dest_frame->data, dest_frame->linesize) < 0 ) + if ( sws_scale(sws_convert_context, frame->data, frame->linesize, 0, frame->height, + dest_frame->data, dest_frame->linesize) < 0 ) Fatal("Unable to convert raw format %u to target format %u", frame->format, AV_PIX_FMT_RGBA); #else // HAVE_LIBSWSCALE Fatal("You must compile ffmpeg with the --enable-swscale option to use ffmpeg cameras"); #endif // HAVE_LIBSWSCALE - av_frame_free( &dest_frame ); + av_frame_free(&dest_frame); update_function_pointers(); -} +} // end Image::Image(const AVFrame *frame) -Image::Image( const Image &p_image ) { +Image::Image(const Image &p_image) { if ( !initialised ) Initialise(); width = p_image.width; @@ -215,7 +221,7 @@ Image::Image( const Image &p_image ) { holdbuffer = 0; AllocImgBuffer(size); (*fptr_imgbufcpy)(buffer, p_image.buffer, size); - strncpy( text, p_image.text, sizeof(text) ); + strncpy(text, p_image.text, sizeof(text)); update_function_pointers(); } @@ -225,35 +231,39 @@ Image::~Image() { /* Should be called as part of program shutdown to free everything */ void Image::Deinitialise() { - if ( initialised ) { - /* - delete[] y_table; - delete[] uv_table; - delete[] r_v_table; - delete[] g_v_table; - delete[] g_u_table; - delete[] b_u_table; + if ( !initialised ) return; + /* + delete[] y_table; + delete[] uv_table; + delete[] r_v_table; + delete[] g_v_table; + delete[] g_u_table; + delete[] b_u_table; */ - initialised = false; - if ( readjpg_dcinfo ) { - jpeg_destroy_decompress( readjpg_dcinfo ); - delete readjpg_dcinfo; - readjpg_dcinfo = 0; - } - if ( decodejpg_dcinfo ) { - jpeg_destroy_decompress( decodejpg_dcinfo ); - delete decodejpg_dcinfo; - decodejpg_dcinfo = 0; - } - for ( unsigned int quality=0; quality <= 100; quality += 1 ) { - if ( writejpg_ccinfo[quality] ) { - jpeg_destroy_compress( writejpg_ccinfo[quality] ); - delete writejpg_ccinfo[quality]; - writejpg_ccinfo[quality] = NULL; - } - } // end foreach quality + initialised = false; + if ( readjpg_dcinfo ) { + jpeg_destroy_decompress( readjpg_dcinfo ); + delete readjpg_dcinfo; + readjpg_dcinfo = 0; } -} + if ( decodejpg_dcinfo ) { + jpeg_destroy_decompress( decodejpg_dcinfo ); + delete decodejpg_dcinfo; + decodejpg_dcinfo = 0; + } + for ( unsigned int quality=0; quality <= 100; quality += 1 ) { + if ( writejpg_ccinfo[quality] ) { + jpeg_destroy_compress( writejpg_ccinfo[quality] ); + delete writejpg_ccinfo[quality]; + writejpg_ccinfo[quality] = NULL; + } + } // end foreach quality + + if ( sws_convert_context ) { + sws_freeContext(sws_convert_context); + sws_convert_context = NULL; + } +} // end void Image::Deinitialise() void Image::Initialise() { /* Assign the blend pointer to function */ @@ -655,15 +665,16 @@ void Image::Assign( const Image &image ) { return; } - if ( !buffer || image.width != width || image.height != height || image.colours != colours || image.subpixelorder != subpixelorder) { + if ( !buffer || image.width != width || image.height != height + || image.colours != colours || image.subpixelorder != subpixelorder) { - if (holdbuffer && buffer) { - if (new_size > allocation) { + if ( holdbuffer && buffer ) { + if ( new_size > allocation ) { Error("Held buffer is undersized for assigned buffer"); return; } } else { - if(new_size > allocation || !buffer) { + if ( new_size > allocation || !buffer) { // DumpImgBuffer(); This is also done in AllocImgBuffer AllocImgBuffer(new_size); } diff --git a/src/zm_image.h b/src/zm_image.h index 6b2448c67..6be574dfb 100644 --- a/src/zm_image.h +++ b/src/zm_image.h @@ -121,7 +121,7 @@ protected: }; inline void DumpImgBuffer() { - DumpBuffer(buffer,buffertype); + DumpBuffer(buffer, buffertype); buffer = NULL; allocation = 0; } diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index 2a4c46724..b2a3b56c5 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -1655,7 +1655,7 @@ bool Monitor::Analyse() { Info("%s: %03d - Left alarm state (%" PRIu64 ") - %d(%d) images", name, image_count, event->Id(), event->Frames(), event->AlarmFrames()); //if ( function != MOCORD || event_close_mode == CLOSE_ALARM || event->Cause() == SIGNAL_CAUSE ) - if ( function != MOCORD || event_close_mode == CLOSE_ALARM ) { + if ( ( function != MOCORD && function != RECORD ) || event_close_mode == CLOSE_ALARM ) { shared_data->state = state = IDLE; Info("%s: %03d - Closing event %" PRIu64 ", alarm end%s", name, image_count, event->Id(), (function==MOCORD)?", section truncated":""); diff --git a/src/zm_poly.cpp b/src/zm_poly.cpp index 13a21e7e0..35319d6af 100644 --- a/src/zm_poly.cpp +++ b/src/zm_poly.cpp @@ -26,11 +26,9 @@ #include #endif -void Polygon::calcArea() -{ +void Polygon::calcArea() { double float_area = 0.0L; - for ( int i = 0, j = n_coords-1; i < n_coords; j = i++ ) - { + for ( int i = 0, j = n_coords-1; i < n_coords; j = i++ ) { double trap_area = ((coords[i].X()-coords[j].X())*((coords[i].Y()+coords[j].Y())))/2.0L; float_area += trap_area; //printf( "%.2f (%.2f)\n", float_area, trap_area ); @@ -38,13 +36,11 @@ void Polygon::calcArea() area = (int)round(fabs(float_area)); } -void Polygon::calcCentre() -{ +void Polygon::calcCentre() { if ( !area && n_coords ) calcArea(); double float_x = 0.0L, float_y = 0.0L; - for ( int i = 0, j = n_coords-1; i < n_coords; j = i++ ) - { + for ( int i = 0, j = n_coords-1; i < n_coords; j = i++ ) { float_x += ((coords[i].Y()-coords[j].Y())*((coords[i].X()*2)+(coords[i].X()*coords[j].X())+(coords[j].X()*2))); float_y += ((coords[j].X()-coords[i].X())*((coords[i].Y()*2)+(coords[i].Y()*coords[j].Y())+(coords[j].Y()*2))); } @@ -54,16 +50,14 @@ void Polygon::calcCentre() centre = Coord( (int)round(float_x), (int)round(float_y) ); } -Polygon::Polygon( int p_n_coords, const Coord *p_coords ) : n_coords( p_n_coords ) -{ +Polygon::Polygon(int p_n_coords, const Coord *p_coords) : n_coords( p_n_coords ) { coords = new Coord[n_coords]; int min_x = -1; int max_x = -1; int min_y = -1; int max_y = -1; - for( int i = 0; i < n_coords; i++ ) - { + for ( int i = 0; i < n_coords; i++ ) { coords[i] = p_coords[i]; if ( min_x == -1 || coords[i].X() < min_x ) min_x = coords[i].X(); @@ -79,38 +73,36 @@ Polygon::Polygon( int p_n_coords, const Coord *p_coords ) : n_coords( p_n_coords calcCentre(); } -Polygon::Polygon( const Polygon &p_polygon ) : n_coords( p_polygon.n_coords ), extent( p_polygon.extent ), area( p_polygon.area ), centre( p_polygon.centre ) +Polygon::Polygon( const Polygon &p_polygon ) : + n_coords(p_polygon.n_coords), + extent(p_polygon.extent), + area(p_polygon.area), + centre(p_polygon.centre) { coords = new Coord[n_coords]; - for( int i = 0; i < n_coords; i++ ) - { + for( int i = 0; i < n_coords; i++ ) { coords[i] = p_polygon.coords[i]; } } -Polygon &Polygon::operator=( const Polygon &p_polygon ) -{ - if ( n_coords < p_polygon.n_coords ) - { +Polygon &Polygon::operator=( const Polygon &p_polygon ) { + if ( n_coords < p_polygon.n_coords ) { delete[] coords; coords = new Coord[p_polygon.n_coords]; } n_coords = p_polygon.n_coords; - for( int i = 0; i < n_coords; i++ ) - { + for ( int i = 0; i < n_coords; i++ ) { coords[i] = p_polygon.coords[i]; } extent = p_polygon.extent; area = p_polygon.area; centre = p_polygon.centre; - return( *this ); + return *this ; } -bool Polygon::isInside( const Coord &coord ) const -{ +bool Polygon::isInside( const Coord &coord ) const { bool inside = false; - for ( int i = 0, j = n_coords-1; i < n_coords; j = i++ ) - { + for ( int i = 0, j = n_coords-1; i < n_coords; j = i++ ) { if ( (((coords[i].Y() <= coord.Y()) && (coord.Y() < coords[j].Y()) ) || ((coords[j].Y() <= coord.Y()) && (coord.Y() < coords[i].Y()))) && (coord.X() < (coords[j].X() - coords[i].X()) * (coord.Y() - coords[i].Y()) / (coords[j].Y() - coords[i].Y()) + coords[i].X())) @@ -118,5 +110,5 @@ bool Polygon::isInside( const Coord &coord ) const inside = !inside; } } - return( inside ); + return inside; } diff --git a/src/zm_poly.h b/src/zm_poly.h index 0fcf34a6e..be039ef3e 100644 --- a/src/zm_poly.h +++ b/src/zm_poly.h @@ -41,13 +41,13 @@ protected: static int CompareYX( const void *p1, const void *p2 ) { const Edge *e1 = reinterpret_cast(p1), *e2 = reinterpret_cast(p2); if ( e1->min_y == e2->min_y ) - return( int(e1->min_x - e2->min_x) ); + return int(e1->min_x - e2->min_x); else - return( int(e1->min_y - e2->min_y) ); + return int(e1->min_y - e2->min_y); } static int CompareX( const void *p1, const void *p2 ) { const Edge *e1 = reinterpret_cast(p1), *e2 = reinterpret_cast(p2); - return( int(e1->min_x - e2->min_x) ); + return int(e1->min_x - e2->min_x); } }; @@ -83,32 +83,32 @@ protected: void calcCentre(); public: - inline Polygon() : n_coords( 0 ), coords( 0 ), area( 0 ), edges(0), slices(0) { + inline Polygon() : n_coords(0), coords(0), area(0), edges(0), slices(0) { } - Polygon( int p_n_coords, const Coord *p_coords ); - Polygon( const Polygon &p_polygon ); + Polygon(int p_n_coords, const Coord *p_coords); + Polygon(const Polygon &p_polygon); ~Polygon() { delete[] coords; } Polygon &operator=( const Polygon &p_polygon ); - inline int getNumCoords() const { return( n_coords ); } + inline int getNumCoords() const { return n_coords; } inline const Coord &getCoord( int index ) const { - return( coords[index] ); + return coords[index]; } - inline const Box &Extent() const { return( extent ); } - inline int LoX() const { return( extent.LoX() ); } - inline int HiX() const { return( extent.HiX() ); } - inline int LoY() const { return( extent.LoY() ); } - inline int HiY() const { return( extent.HiY() ); } - inline int Width() const { return( extent.Width() ); } - inline int Height() const { return( extent.Height() ); } + inline const Box &Extent() const { return extent; } + inline int LoX() const { return extent.LoX(); } + inline int HiX() const { return extent.HiX(); } + inline int LoY() const { return extent.LoY(); } + inline int HiY() const { return extent.HiY(); } + inline int Width() const { return extent.Width(); } + inline int Height() const { return extent.Height(); } - inline int Area() const { return( area ); } + inline int Area() const { return area; } inline const Coord &Centre() const { - return( centre ); + return centre; } bool isInside( const Coord &coord ) const; }; diff --git a/src/zm_stream.cpp b/src/zm_stream.cpp index d355ef4c2..258e04d52 100644 --- a/src/zm_stream.cpp +++ b/src/zm_stream.cpp @@ -114,7 +114,7 @@ bool StreamBase::checkCommandQueue() { return false; } -Image *StreamBase::prepareImage( Image *image ) { +Image *StreamBase::prepareImage(Image *image) { // Do not bother to scale zoomed in images, just crop them and let the browser scale // Works in FF2 but breaks FF3 which doesn't like image sizes changing in mid stream. @@ -124,50 +124,51 @@ Image *StreamBase::prepareImage( Image *image ) { int mag = (scale * zoom) / ZM_SCALE_BASE; int act_mag = optimisedScaling?(mag > ZM_SCALE_BASE?ZM_SCALE_BASE:mag):mag; - Debug( 3, "Scaling by %d, zooming by %d = magnifying by %d(%d)", scale, zoom, mag, act_mag ); int last_mag = (last_scale * last_zoom) / ZM_SCALE_BASE; int last_act_mag = last_mag > ZM_SCALE_BASE?ZM_SCALE_BASE:last_mag; - Debug( 3, "Last scaling by %d, zooming by %d = magnifying by %d(%d)", last_scale, last_zoom, last_mag, last_act_mag ); - int base_image_width = image->Width(), base_image_height = image->Height(); - Debug( 3, "Base image width = %d, height = %d", base_image_width, base_image_height ); - int virt_image_width = (base_image_width * mag) / ZM_SCALE_BASE, virt_image_height = (base_image_height * mag) / ZM_SCALE_BASE; - Debug( 3, "Virtual image width = %d, height = %d", virt_image_width, virt_image_height ); - int last_virt_image_width = (base_image_width * last_mag) / ZM_SCALE_BASE, last_virt_image_height = (base_image_height * last_mag) / ZM_SCALE_BASE; - Debug( 3, "Last virtual image width = %d, height = %d", last_virt_image_width, last_virt_image_height ); - int act_image_width = (base_image_width * act_mag ) / ZM_SCALE_BASE, act_image_height = (base_image_height * act_mag ) / ZM_SCALE_BASE; - Debug( 3, "Actual image width = %d, height = %d", act_image_width, act_image_height ); - int last_act_image_width = (base_image_width * last_act_mag ) / ZM_SCALE_BASE, last_act_image_height = (base_image_height * last_act_mag ) / ZM_SCALE_BASE; - Debug( 3, "Last actual image width = %d, height = %d", last_act_image_width, last_act_image_height ); - int disp_image_width = (image->Width() * scale) / ZM_SCALE_BASE, disp_image_height = (image->Height() * scale) / ZM_SCALE_BASE; - Debug( 3, "Display image width = %d, height = %d", disp_image_width, disp_image_height ); - int last_disp_image_width = (image->Width() * last_scale) / ZM_SCALE_BASE, last_disp_image_height = (image->Height() * last_scale) / ZM_SCALE_BASE; - Debug( 3, "Last display image width = %d, height = %d", last_disp_image_width, last_disp_image_height ); - int send_image_width = (disp_image_width * act_mag ) / mag, send_image_height = (disp_image_height * act_mag ) / mag; - Debug( 3, "Send image width = %d, height = %d", send_image_width, send_image_height ); - int last_send_image_width = (last_disp_image_width * last_act_mag ) / last_mag, last_send_image_height = (last_disp_image_height * last_act_mag ) / last_mag; - Debug( 3, "Last send image width = %d, height = %d", last_send_image_width, last_send_image_height ); - if ( mag != ZM_SCALE_BASE ) { - if ( act_mag != ZM_SCALE_BASE ) { - Debug(3, "Magnifying by %d", mag); - if ( !image_copied ) { - static Image copy_image; - copy_image.Assign(*image); - image = ©_image; - image_copied = true; - } - image->Scale(mag); - } + Debug(3, + "Scaling by %d, zooming by %d = magnifying by %d(%d)\n" + "Last scaling by %d, zooming by %d = magnifying by %d(%d)\n" + "Base image width = %d, height = %d\n" + "Virtual image width = %d, height = %d\n" + "Last virtual image width = %d, height = %d\n" + "Actual image width = %d, height = %d\n" + "Last actual image width = %d, height = %d\n" + "Display image width = %d, height = %d\n" + "Last display image width = %d, height = %d\n" + "Send image width = %d, height = %d\n" + "Last send image width = %d, height = %d\n", + scale, zoom, mag, act_mag, + last_scale, last_zoom, last_mag, last_act_mag, + base_image_width, base_image_height, + virt_image_width, virt_image_height, + last_virt_image_width, last_virt_image_height, + act_image_width, act_image_height, + last_act_image_width, last_act_image_height, + disp_image_width, disp_image_height, + last_disp_image_width, last_disp_image_height, + send_image_width, send_image_height, + last_send_image_width, last_send_image_height + ); + + if ( ( mag != ZM_SCALE_BASE ) && (act_mag != ZM_SCALE_BASE) ) { + Debug(3, "Magnifying by %d", mag); + static Image copy_image; + copy_image.Assign(*image); + image = ©_image; + image_copied = true; + image->Scale(mag); } Debug(3, "Real image width = %d, height = %d", image->Width(), image->Height()); @@ -176,26 +177,22 @@ Image *StreamBase::prepareImage( Image *image ) { static Box last_crop; if ( mag != last_mag || x != last_x || y != last_y ) { - Debug( 3, "Got click at %d,%d x %d", x, y, mag ); - - //if ( !last_mag ) - //last_mag = mag; + Debug(3, "Got click at %d,%d x %d", x, y, mag); if ( !(last_disp_image_width < last_virt_image_width || last_disp_image_height < last_virt_image_height) ) last_crop = Box(); - Debug( 3, "Recalculating crop" ); // Recalculate crop parameters, as %ges int click_x = (last_crop.LoX() * 100 ) / last_act_image_width; // Initial crop offset from last image click_x += ( x * 100 ) / last_virt_image_width; int click_y = (last_crop.LoY() * 100 ) / last_act_image_height; // Initial crop offset from last image click_y += ( y * 100 ) / last_virt_image_height; - Debug( 3, "Got adjusted click at %d%%,%d%%", click_x, click_y ); + Debug(3, "Got adjusted click at %d%%,%d%%", click_x, click_y); // Convert the click locations to the current image pixels click_x = ( click_x * act_image_width ) / 100; click_y = ( click_y * act_image_height ) / 100; - Debug( 3, "Got readjusted click at %d,%d", click_x, click_y ); + Debug(3, "Got readjusted click at %d,%d", click_x, click_y); int lo_x = click_x - (send_image_width/2); if ( lo_x < 0 ) @@ -214,23 +211,25 @@ Image *StreamBase::prepareImage( Image *image ) { lo_y = hi_y - (send_image_height - 1); } last_crop = Box( lo_x, lo_y, hi_x, hi_y ); - } - Debug( 3, "Cropping to %d,%d -> %d,%d", last_crop.LoX(), last_crop.LoY(), last_crop.HiX(), last_crop.HiY() ); + } // end if ( mag != last_mag || x != last_x || y != last_y ) + + Debug(3, "Cropping to %d,%d -> %d,%d", last_crop.LoX(), last_crop.LoY(), last_crop.HiX(), last_crop.HiY()); if ( !image_copied ) { static Image copy_image; - copy_image.Assign( *image ); + copy_image.Assign(*image); image = ©_image; image_copied = true; } - image->Crop( last_crop ); - } + image->Crop(last_crop); + } // end if difference in image vs displayed dimensions + last_scale = scale; last_zoom = zoom; last_x = x; last_y = y; return image; -} +} // end Image *StreamBase::prepareImage(Image *image) bool StreamBase::sendTextFrame(const char *frame_text) { Debug(2, "Sending %dx%d * %d text frame '%s'", @@ -349,7 +348,7 @@ void StreamBase::openComms() { } snprintf(rem_sock_path, sizeof(rem_sock_path), "%s/zms-%06dw.sock", staticConfig.PATH_SOCKS.c_str(), connkey); - strncpy(rem_addr.sun_path, rem_sock_path, sizeof(rem_addr.sun_path)-1); + strncpy(rem_addr.sun_path, rem_sock_path, sizeof(rem_addr.sun_path)); rem_addr.sun_family = AF_UNIX; gettimeofday(&last_comm_update, NULL); diff --git a/src/zm_stream.h b/src/zm_stream.h index eb99b74c1..15ba13423 100644 --- a/src/zm_stream.h +++ b/src/zm_stream.h @@ -77,11 +77,11 @@ protected: protected: int connkey; int sd; - char loc_sock_path[PATH_MAX]; + char loc_sock_path[108]; struct sockaddr_un loc_addr; - char rem_sock_path[PATH_MAX]; + char rem_sock_path[108]; struct sockaddr_un rem_addr; - char sock_path_lock[PATH_MAX]; + char sock_path_lock[108]; int lock_fd; protected: diff --git a/src/zm_user.cpp b/src/zm_user.cpp index 0ad9f0672..8457fd5b7 100644 --- a/src/zm_user.cpp +++ b/src/zm_user.cpp @@ -1,21 +1,21 @@ /* * ZoneMinder regular expression class implementation, $Date$, $Revision$ * Copyright (C) 2001-2008 Philip Coombes - * + * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ +*/ #include "zm.h" #include "zm_db.h" @@ -26,6 +26,7 @@ #include #include #include +#include #if HAVE_GNUTLS_GNUTLS_H #include @@ -35,7 +36,7 @@ #include #elif HAVE_LIBCRYPTO #include -#endif // HAVE_L || HAVE_LIBCRYPTO +#endif // HAVE_GCRYPT_H || HAVE_LIBCRYPTO #include "zm_utils.h" #include "zm_crypt.h" @@ -52,7 +53,7 @@ User::User(const MYSQL_ROW &dbrow) { id = atoi(dbrow[index++]); strncpy(username, dbrow[index++], sizeof(username)-1); strncpy(password, dbrow[index++], sizeof(password)-1); - enabled = (bool)atoi(dbrow[index++]); + enabled = static_cast(atoi(dbrow[index++])); stream = (Permission)atoi(dbrow[index++]); events = (Permission)atoi(dbrow[index++]); control = (Permission)atoi(dbrow[index++]); @@ -61,7 +62,7 @@ User::User(const MYSQL_ROW &dbrow) { char *monitor_ids_str = dbrow[index++]; if ( monitor_ids_str && *monitor_ids_str ) { StringVector ids = split(monitor_ids_str, ","); - for( StringVector::iterator i = ids.begin(); i < ids.end(); ++i ) { + for ( StringVector::iterator i = ids.begin(); i < ids.end(); ++i ) { monitor_ids.push_back(atoi((*i).c_str())); } } @@ -72,9 +73,9 @@ User::~User() { } void User::Copy(const User &u) { - id=u.id; - strncpy(username, u.username, sizeof(username)-1); - strncpy(password, u.password, sizeof(password)-1); + id = u.id; + strncpy(username, u.username, sizeof(username)); + strncpy(password, u.password, sizeof(password)); enabled = u.enabled; stream = u.stream; events = u.events; @@ -87,8 +88,9 @@ void User::Copy(const User &u) { bool User::canAccess(int monitor_id) { if ( monitor_ids.empty() ) return true; - - for ( std::vector::iterator i = monitor_ids.begin(); i != monitor_ids.end(); ++i ) { + + for ( std::vector::iterator i = monitor_ids.begin(); + i != monitor_ids.end(); ++i ) { if ( *i == monitor_id ) { return true; } @@ -103,18 +105,23 @@ User *zmLoadUser(const char *username, const char *password) { int username_length = strlen(username); char *safer_username = new char[(username_length * 2) + 1]; - // According to docs, size of safer_whatever must be 2*length+1 due to unicode conversions + null terminator. + // According to docs, size of safer_whatever must be 2*length+1 + // due to unicode conversions + null terminator. mysql_real_escape_string(&dbconn, safer_username, username, username_length); snprintf(sql, sizeof(sql), - "SELECT `Id`, `Username`, `Password`, `Enabled`, `Stream`+0, `Events`+0, `Control`+0, `Monitors`+0, `System`+0, `MonitorIds`" - " FROM `Users` WHERE `Username` = '%s' AND `Enabled` = 1", safer_username); + "SELECT `Id`, `Username`, `Password`, `Enabled`," + " `Stream`+0, `Events`+0, `Control`+0, `Monitors`+0, `System`+0," + " `MonitorIds`" + " FROM `Users` WHERE `Username` = '%s' AND `Enabled` = 1", + safer_username); + delete[] safer_username; + safer_username = NULL; if ( mysql_query(&dbconn, sql) ) { Error("Can't run query: %s", mysql_error(&dbconn)); - exit(mysql_errno(&dbconn)); + exit(mysql_errno(&dbconn)); } - delete safer_username; MYSQL_RES *result = mysql_store_result(&dbconn); if ( !result ) { @@ -122,162 +129,157 @@ User *zmLoadUser(const char *username, const char *password) { exit(mysql_errno(&dbconn)); } - if ( mysql_num_rows(result) != 1 ) { + if ( mysql_num_rows(result) == 1 ) { + MYSQL_ROW dbrow = mysql_fetch_row(result); + User *user = new User(dbrow); mysql_free_result(result); - Warning("Unable to authenticate user %s", username); - return NULL; - } - MYSQL_ROW dbrow = mysql_fetch_row(result); - User *user = new User(dbrow); + if ( + (! password ) // relay type must be none + || + verifyPassword(username, password, user->getPassword()) ) { + Info("Authenticated user '%s'", user->getUsername()); + return user; + } + } // end if 1 result from db mysql_free_result(result); - if ( !password ) { - // relay type must be none - return user; - } - - if ( verifyPassword(username, password, user->getPassword()) ) { - Info("Authenticated user '%s'", user->getUsername()); - return user; - } - Warning("Unable to authenticate user %s", username); return NULL; -} +} // end User *zmLoadUser(const char *username, const char *password) -User *zmLoadTokenUser (std::string jwt_token_str, bool use_remote_addr ) { +User *zmLoadTokenUser(std::string jwt_token_str, bool use_remote_addr) { std::string key = config.auth_hash_secret; std::string remote_addr = ""; - - if (use_remote_addr) { - remote_addr = std::string(getenv( "REMOTE_ADDR" )); + + if ( use_remote_addr ) { + remote_addr = std::string(getenv("REMOTE_ADDR")); if ( remote_addr == "" ) { - Warning( "Can't determine remote address, using null" ); + Warning("Can't determine remote address, using null"); remote_addr = ""; } key += remote_addr; } - Debug (1,"Inside zmLoadTokenUser, formed key=%s", key.c_str()); + Debug(1, "Inside zmLoadTokenUser, formed key=%s", key.c_str()); std::pair ans = verifyToken(jwt_token_str, key); std::string username = ans.first; unsigned int iat = ans.second; - Debug (1,"retrieved user '%s' from token", username.c_str()); + Debug(1, "retrieved user '%s' from token", username.c_str()); - if (username != "") { - char sql[ZM_SQL_MED_BUFSIZ] = ""; - snprintf(sql, sizeof(sql), - "SELECT `Id`, `Username`, `Password`, `Enabled`, `Stream`+0, `Events`+0, `Control`+0, `Monitors`+0, `System`+0, `MonitorIds`, `TokenMinExpiry`" - " FROM `Users` WHERE `Username` = '%s' AND `Enabled` = 1", username.c_str() ); - - if ( mysql_query(&dbconn, sql) ) { - Error("Can't run query: %s", mysql_error(&dbconn)); - exit(mysql_errno(&dbconn)); - } - - MYSQL_RES *result = mysql_store_result(&dbconn); - if ( !result ) { - Error("Can't use query result: %s", mysql_error(&dbconn)); - exit(mysql_errno(&dbconn)); - } - int n_users = mysql_num_rows(result); - - if ( n_users != 1 ) { - mysql_free_result(result); - Error("Unable to authenticate user '%s'", username.c_str()); - return NULL; - } - - MYSQL_ROW dbrow = mysql_fetch_row(result); - User *user = new User(dbrow); - unsigned int stored_iat = strtoul(dbrow[10], NULL,0 ); - - if (stored_iat > iat ) { // admin revoked tokens - mysql_free_result(result); - Error("Token was revoked for '%s'", username.c_str()); - return NULL; - } - - Debug (1,"Got last token revoke time of: %u",stored_iat); - Debug (1,"Authenticated user '%s' via token", username.c_str()); - mysql_free_result(result); - return user; - - } - else { + if ( username == "" ) { return NULL; } -} + char sql[ZM_SQL_MED_BUFSIZ] = ""; + snprintf(sql, sizeof(sql), + "SELECT `Id`, `Username`, `Password`, `Enabled`, `Stream`+0, `Events`+0," + " `Control`+0, `Monitors`+0, `System`+0, `MonitorIds`, `TokenMinExpiry`" + " FROM `Users` WHERE `Username` = '%s' AND `Enabled` = 1", username.c_str()); + + if ( mysql_query(&dbconn, sql) ) { + Error("Can't run query: %s", mysql_error(&dbconn)); + return NULL; + } + + MYSQL_RES *result = mysql_store_result(&dbconn); + if ( !result ) { + Error("Can't use query result: %s", mysql_error(&dbconn)); + return NULL; + } + + int n_users = mysql_num_rows(result); + if ( n_users != 1 ) { + mysql_free_result(result); + Error("Unable to authenticate user '%s'", username.c_str()); + return NULL; + } + + MYSQL_ROW dbrow = mysql_fetch_row(result); + User *user = new User(dbrow); + unsigned int stored_iat = strtoul(dbrow[10], NULL, 0); + + if ( stored_iat > iat ) { // admin revoked tokens + mysql_free_result(result); + Error("Token was revoked for '%s'", username.c_str()); + return NULL; + } + + Debug(1, "Authenticated user '%s' via token with last revoke time: %u", + username.c_str(), stored_iat); + mysql_free_result(result); + return user; +} // User *zmLoadTokenUser(std::string jwt_token_str, bool use_remote_addr) // Function to validate an authentication string -User *zmLoadAuthUser( const char *auth, bool use_remote_addr ) { +User *zmLoadAuthUser(const char *auth, bool use_remote_addr) { #if HAVE_DECL_MD5 || HAVE_DECL_GNUTLS_FINGERPRINT #ifdef HAVE_GCRYPT_H // Special initialisation for libgcrypt - if ( !gcry_check_version( GCRYPT_VERSION ) ) { - Fatal( "Unable to initialise libgcrypt" ); + if ( !gcry_check_version(GCRYPT_VERSION) ) { + Fatal("Unable to initialise libgcrypt"); } - gcry_control( GCRYCTL_DISABLE_SECMEM, 0 ); - gcry_control( GCRYCTL_INITIALIZATION_FINISHED, 0 ); -#endif // HAVE_GCRYPT_H + gcry_control(GCRYCTL_DISABLE_SECMEM, 0); + gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0); +#endif // HAVE_GCRYPT_H const char *remote_addr = ""; if ( use_remote_addr ) { - remote_addr = getenv( "REMOTE_ADDR" ); + remote_addr = getenv("REMOTE_ADDR"); if ( !remote_addr ) { - Warning( "Can't determine remote address, using null" ); + Warning("Can't determine remote address, using null"); remote_addr = ""; } } - Debug( 1, "Attempting to authenticate user from auth string '%s'", auth ); + Debug(1, "Attempting to authenticate user from auth string '%s'", auth); char sql[ZM_SQL_SML_BUFSIZ] = ""; - snprintf( sql, sizeof(sql), "SELECT `Id`, `Username`, `Password`, `Enabled`, `Stream`+0, `Events`+0, `Control`+0, `Monitors`+0, `System`+0, `MonitorIds` FROM `Users` WHERE `Enabled` = 1" ); + snprintf(sql, sizeof(sql), + "SELECT `Id`, `Username`, `Password`, `Enabled`," + " `Stream`+0, `Events`+0, `Control`+0, `Monitors`+0, `System`+0," + " `MonitorIds` FROM `Users` WHERE `Enabled` = 1"); - if ( mysql_query( &dbconn, sql ) ) { - Error( "Can't run query: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); + if ( mysql_query(&dbconn, sql) ) { + Error("Can't run query: %s", mysql_error(&dbconn)); + exit(mysql_errno(&dbconn)); } - MYSQL_RES *result = mysql_store_result( &dbconn ); + MYSQL_RES *result = mysql_store_result(&dbconn); if ( !result ) { - Error( "Can't use query result: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); + Error("Can't use query result: %s", mysql_error(&dbconn)); + return NULL; } - int n_users = mysql_num_rows( result ); - + int n_users = mysql_num_rows(result); if ( n_users < 1 ) { - mysql_free_result( result ); - Warning( "Unable to authenticate user" ); - return( 0 ); + mysql_free_result(result); + Warning("Unable to authenticate user"); + return NULL; } - while( MYSQL_ROW dbrow = mysql_fetch_row( result ) ) { + time_t now = time(0); + unsigned int hours = config.auth_hash_ttl; + if ( ! hours ) { + Warning("No value set for ZM_AUTH_HASH_TTL. Defaulting to 2."); + hours = 2; + } else { + Debug(1, "AUTH_HASH_TTL is %d", hours); + } + char auth_key[512] = ""; + char auth_md5[32+1] = ""; + size_t md5len = 16; + unsigned char md5sum[md5len]; + + const char * hex = "0123456789abcdef"; + while ( MYSQL_ROW dbrow = mysql_fetch_row(result) ) { const char *user = dbrow[1]; const char *pass = dbrow[2]; - char auth_key[512] = ""; - char auth_md5[32+1] = ""; - size_t md5len = 16; - unsigned char md5sum[md5len]; + time_t our_now = now; + for ( unsigned int i = 0; i < hours; i++, our_now -= 3600 ) { + struct tm *now_tm = localtime(&our_now); - time_t now = time( 0 ); - unsigned int hours = config.auth_hash_ttl; - - if ( ! hours ) { - Warning("No value set for ZM_AUTH_HASH_TTL. Defaulting to 2."); - hours = 2; - } else { - Debug( 1, "AUTH_HASH_TTL is %d", hours ); - } - - for ( unsigned int i = 0; i < hours; i++, now -= 3600 ) { - struct tm *now_tm = localtime( &now ); - - snprintf( auth_key, sizeof(auth_key), "%s%s%s%s%d%d%d%d", + snprintf(auth_key, sizeof(auth_key)-1, "%s%s%s%s%d%d%d%d", config.auth_hash_secret, user, pass, @@ -285,51 +287,57 @@ User *zmLoadAuthUser( const char *auth, bool use_remote_addr ) { now_tm->tm_hour, now_tm->tm_mday, now_tm->tm_mon, - now_tm->tm_year - ); + now_tm->tm_year); #if HAVE_DECL_MD5 - MD5( (unsigned char *)auth_key, strlen(auth_key), md5sum ); + MD5((unsigned char *)auth_key, strlen(auth_key), md5sum); #elif HAVE_DECL_GNUTLS_FINGERPRINT - gnutls_datum_t md5data = { (unsigned char *)auth_key, strlen(auth_key) }; - gnutls_fingerprint( GNUTLS_DIG_MD5, &md5data, md5sum, &md5len ); + gnutls_datum_t md5data = { (unsigned char *)auth_key, (unsigned int)strlen(auth_key) }; + gnutls_fingerprint(GNUTLS_DIG_MD5, &md5data, md5sum, &md5len); #endif - auth_md5[0] = '\0'; + unsigned char *md5sum_ptr = md5sum; + char *auth_md5_ptr = auth_md5; + for ( unsigned int j = 0; j < md5len; j++ ) { - sprintf( &auth_md5[2*j], "%02x", md5sum[j] ); + *auth_md5_ptr++ = hex[(*md5sum_ptr>>4)&0xf]; + *auth_md5_ptr++ = hex[(*md5sum_ptr++)&0xf]; } - Debug( 1, "Checking auth_key '%s' -> auth_md5 '%s' == '%s'", auth_key, auth_md5, auth ); + *auth_md5_ptr = 0; - if ( !strcmp( auth, auth_md5 ) ) { + Debug(1, "Checking auth_key '%s' -> auth_md5 '%s' == '%s'", + auth_key, auth_md5, auth); + + if ( !strcmp(auth, auth_md5) ) { // We have a match - User *user = new User( dbrow ); - Debug(1, "Authenticated user '%s'", user->getUsername() ); - mysql_free_result( result ); - return( user ); + User *user = new User(dbrow); + Debug(1, "Authenticated user '%s'", user->getUsername()); + mysql_free_result(result); + return user; } else { - Debug(1, "No match for %s", auth ); + Debug(1, "No match for %s", auth); } - } - } - mysql_free_result( result ); -#else // HAVE_DECL_MD5 - Error( "You need to build with gnutls or openssl installed to use hash based authentication" ); -#endif // HAVE_DECL_MD5 - Debug(1, "No user found for auth_key %s", auth ); - return 0; -} + } // end foreach hour + } // end foreach user + mysql_free_result(result); +#else // HAVE_DECL_MD5 || HAVE_DECL_GNUTLS_FINGERPRINT + Error("You need to build with gnutls or openssl to use hash based auth"); +#endif // HAVE_DECL_MD5 || HAVE_DECL_GNUTLS_FINGERPRINT + Debug(1, "No user found for auth_key %s", auth); + return NULL; +} // end User *zmLoadAuthUser( const char *auth, bool use_remote_addr ) -//Function to check Username length -bool checkUser ( const char *username) { - if ( ! username ) +// Function to check Username length +bool checkUser(const char *username) { + if ( !username ) return false; if ( strlen(username) > 32 ) return false; return true; } -//Function to check password length -bool checkPass (const char *password) { + +// Function to check password length +bool checkPass(const char *password) { if ( !password ) return false; if ( strlen(password) > 64 ) diff --git a/src/zms.cpp b/src/zms.cpp index 6511afdc8..ad7076e7a 100644 --- a/src/zms.cpp +++ b/src/zms.cpp @@ -184,7 +184,7 @@ int main(int argc, const char *argv[]) { logInit(log_id_string); if ( config.opt_use_auth ) { - User *user = 0; + User *user = NULL; if ( jwt_token_str != "" ) { // user = zmLoadTokenUser(jwt_token_str, config.auth_hash_ips); @@ -195,19 +195,11 @@ int main(int argc, const char *argv[]) { } else { Error("Bad username"); } - } else { - // if ( strcmp( config.auth_relay, "hashed" ) == 0 ) - { - if ( *auth ) { - user = zmLoadAuthUser(auth, config.auth_hash_ips); - } - } - // else if ( strcmp( config.auth_relay, "plain" ) == 0 ) - { - if ( username.length() && password.length() ) { - user = zmLoadUser(username.c_str(), password.c_str()); - } + if ( *auth ) { + user = zmLoadAuthUser(auth, config.auth_hash_ips); + } else if ( username.length() && password.length() ) { + user = zmLoadUser(username.c_str(), password.c_str()); } } if ( !user ) { @@ -218,11 +210,15 @@ int main(int argc, const char *argv[]) { return 0; } if ( !ValidateAccess(user, monitor_id) ) { + delete user; + user = NULL; fputs("HTTP/1.0 403 Forbidden\r\n\r\n", stdout); logTerm(); zmDbClose(); return 0; } + delete user; + user = NULL; } // end if config.opt_use_auth hwcaps_detect(); @@ -336,5 +332,5 @@ int main(int argc, const char *argv[]) { logTerm(); zmDbClose(); - return(0); + return 0; } diff --git a/version b/version index 0ceb7f6f3..6fdc61072 100644 --- a/version +++ b/version @@ -1 +1 @@ -1.34.10 +1.34.11 diff --git a/web/includes/Monitor.php b/web/includes/Monitor.php index c788b5fb8..066625c20 100644 --- a/web/includes/Monitor.php +++ b/web/includes/Monitor.php @@ -39,7 +39,7 @@ class Monitor extends ZM_Object { 'Height' => null, 'Colours' => 4, 'Palette' => '0', - 'Orientation' => null, + 'Orientation' => 'ROTATE_0', 'Deinterlacing' => 0, 'DecoderHWAccelName' => null, 'DecoderHWAccelDevice' => null, @@ -495,12 +495,16 @@ class Monitor extends ZM_Object { } } if ( !count($options) ) { - if ( $command == 'quit' ) { - $options['command'] = 'quit'; - } else if ( $command == 'start' ) { - $options['command'] = 'start'; - } else if ( $command == 'stop' ) { - $options['command'] = 'stop'; + + if ( $command == 'quit' or $command == 'start' or $command == 'stop' ) { + # These are special as we now run zmcontrol as a daemon through zmdc. + $status = daemonStatus('zmcontrol.pl', array('--id', $this->{'Id'})); + Logger::Debug("Current status $status"); + if ( $status or ( (!defined('ZM_SERVER_ID')) or ( property_exists($this, 'ServerId') and (ZM_SERVER_ID==$this->{'ServerId'}) ) ) ) { + daemonControl($command, 'zmcontrol.pl', '--id '.$this->{'Id'}); + return; + } + $options['command'] = $command; } else { Warning("No commands to send to zmcontrol from $command"); return false; @@ -538,12 +542,12 @@ class Monitor extends ZM_Object { $url = ZM_BASE_PROTOCOL . '://'.$Server->Hostname().'/zm/api/monitors/daemonControl/'.$this->{'Id'}.'/'.$command.'/zmcontrol.pl.json'; if ( ZM_OPT_USE_AUTH ) { if ( ZM_AUTH_RELAY == 'hashed' ) { - $url .= '?auth='.generateAuthHash( ZM_AUTH_HASH_IPS ); + $url .= '?auth='.generateAuthHash(ZM_AUTH_HASH_IPS); } else if ( ZM_AUTH_RELAY == 'plain' ) { - $url = '?user='.$_SESSION['username']; - $url = '?pass='.$_SESSION['password']; + $url .= '?user='.$_SESSION['username']; + $url .= '?pass='.$_SESSION['password']; } else if ( ZM_AUTH_RELAY == 'none' ) { - $url = '?user='.$_SESSION['username']; + $url .= '?user='.$_SESSION['username']; } } Logger::Debug("sending command to $url"); diff --git a/web/includes/Object.php b/web/includes/Object.php index 1668a7767..09be86a9e 100644 --- a/web/includes/Object.php +++ b/web/includes/Object.php @@ -249,7 +249,7 @@ class ZM_Object { } } } else if ( array_key_exists($field, $this->defaults) ) { - if ( is_array($this->defaults[$field]) ) { + if ( is_array($this->defaults[$field]) and isset($this->defaults[$field]['default']) ) { $default = $this->defaults[$field]['default']; } else { $default = $this->defaults[$field]; diff --git a/web/includes/Zone.php b/web/includes/Zone.php new file mode 100644 index 000000000..7a19df9d2 --- /dev/null +++ b/web/includes/Zone.php @@ -0,0 +1,41 @@ + null, + 'Name' => '', + 'Type' => 'Active', + 'Units' => 'Pixels', + 'CheckMethod' => 'Blobs', + 'MinPixelThreshold' => null, + 'MaxPixelThreshold' => null, + 'MinAlarmPixels' => null, + 'MaxAlarmPixels' => null, + 'FilterX' => null, + 'FilterY' => null, + 'MinFilterPixels' => null, + 'MaxFilterPixels' => null, + 'MinBlobPixels' => null, + 'MaxBlobPixels' => null, + 'MinBlobs' => null, + 'MaxBlobs' => null, + 'OverloadFrames' => 0, + 'ExtendAlarmFrames' => 0, + ); + + public static function find( $parameters = array(), $options = array() ) { + return ZM_Object::_find(get_class(), $parameters, $options); + } + + public static function find_one( $parameters = array(), $options = array() ) { + return ZM_Object::_find_one(get_class(), $parameters, $options); + } + +} # end class Zone +?> diff --git a/web/index.php b/web/index.php index 18da56e63..b29a4e7e7 100644 --- a/web/index.php +++ b/web/index.php @@ -52,6 +52,9 @@ require_once('includes/Event.php'); require_once('includes/Group.php'); require_once('includes/Monitor.php'); +global $Servers; +$Servers = ZM\Server::find(); + if ( (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') or @@ -71,7 +74,7 @@ define('ZM_BASE_URL', ''); require_once('includes/functions.php'); if ( $_SERVER['REQUEST_METHOD'] == 'OPTIONS' ) { - ZM\Logger::Debug("OPTIONS Method, only doing CORS"); + ZM\Logger::Debug('OPTIONS Method, only doing CORS'); # Add Cross domain access headers CORSHeaders(); return; @@ -152,8 +155,6 @@ if ( setcookie('zmCSS', $css, time()+3600*24*30*12*10); } - - # Running is global but only do the daemonCheck if it is actually needed $running = null; @@ -174,7 +175,6 @@ $user = null; if ( isset($_REQUEST['view']) ) $view = detaintPath($_REQUEST['view']); - # Add CSP Headers $cspNonce = bin2hex(zm_random_bytes(16)); diff --git a/web/skins/classic/includes/control_functions.php b/web/skins/classic/includes/control_functions.php index 6f1399786..61138612f 100644 --- a/web/skins/classic/includes/control_functions.php +++ b/web/skins/classic/includes/control_functions.php @@ -25,15 +25,15 @@ function controlFocus($monitor, $cmds) { ?>
- - - + + +
CanAutoFocus() ) { ?> - - + + @@ -48,15 +48,15 @@ function controlZoom($monitor, $cmds) { ?>
- - - + + +
CanAutoZoom() ) { ?> - - + + @@ -70,15 +70,15 @@ function controlIris($monitor, $cmds) { ?>
- - - + + +
CanAutoIris() ) { ?> - - + + @@ -93,15 +93,15 @@ function controlWhite($monitor, $cmds) { ?>
- - - + + +
CanAutoWhite() ) { ?> - - + + @@ -122,19 +122,19 @@ function controlPanTilt($monitor, $cmds) { $hasTilt = $control->CanTilt(); $hasDiag = $hasPan && $hasTilt && $control->CanMoveDiag(); ?> - - - - + + + + - + - - - - + + + +
NumPresets(); $i++ ) { ?> - + @@ -171,7 +171,7 @@ function controlPresets($monitor, $cmds) { HasHomePreset() ) { ?> - + CanSetPresets() ) { @@ -196,22 +196,22 @@ function controlPower($monitor, $cmds) { CanWake() ) { ?> - + CanSleep() ) { ?> - + CanReset() ) { ?> - + CanReboot() ) { ?> - + @@ -223,9 +223,7 @@ function controlPower($monitor, $cmds) { function ptzControls($monitor) { $control = $monitor->Control(); - //ZM\Error("Control: " . print_r($control,true)); $cmds = $control->commands(); - //ZM\Error("Cmds: " . print_r($cmds, true)); ob_start(); ?>
diff --git a/web/skins/classic/js/skin.js b/web/skins/classic/js/skin.js index dd965a39f..2012837e8 100644 --- a/web/skins/classic/js/skin.js +++ b/web/skins/classic/js/skin.js @@ -182,8 +182,8 @@ window.addEventListener("DOMContentLoaded", function onSkinDCL() { return; } - el.onclick = function() { - window[fnName](); + el.onclick = function(ev) { + window[fnName](ev); }; }); diff --git a/web/skins/classic/js/skin.js.php b/web/skins/classic/js/skin.js.php index a9f6b85af..5250e654f 100644 --- a/web/skins/classic/js/skin.js.php +++ b/web/skins/classic/js/skin.js.php @@ -71,6 +71,22 @@ var focusWindow = ; var imagePrefix = ""; var auth_hash; - -auth_hash = ''; - +var auth_relay; + diff --git a/web/skins/classic/views/events.php b/web/skins/classic/views/events.php index cfbe90383..034e908ef 100644 --- a/web/skins/classic/views/events.php +++ b/web/skins/classic/views/events.php @@ -258,7 +258,7 @@ while ( $event_row = dbFetchNext($results) ) { echo ''; $imgSrc = $event->getThumbnailSrc(array(),'&'); $streamSrc = $event->getStreamSrc(array( - 'mode'=>'jpeg', 'scale'=>$scale, 'maxfps'=>ZM_WEB_VIDEO_MAXFPS, 'replay'=>'single'), '&'); + 'mode'=>'jpeg', 'scale'=>$scale, 'maxfps'=>ZM_WEB_VIDEO_MAXFPS, 'replay'=>'single', 'rate'=>'400'), '&'); $imgHtml = ''. validHtmlStr('Event '.$event->Id()) .''; echo ''.$imgHtml.''; diff --git a/web/skins/classic/views/js/montage.js b/web/skins/classic/views/js/montage.js index b88833db0..d0e0c348c 100644 --- a/web/skins/classic/views/js/montage.js +++ b/web/skins/classic/views/js/montage.js @@ -13,6 +13,8 @@ function Monitor(monitorData) { this.streamCmdParms = 'view=request&request=stream&connkey='+this.connKey; if ( auth_hash ) { this.streamCmdParms += '&auth='+auth_hash; + } else if ( auth_relay ) { + this.streamCmdParms += '&'+auth_relay; } this.streamCmdTimer = null; this.type = monitorData.type; diff --git a/web/skins/classic/views/js/postlogin.js.php b/web/skins/classic/views/js/postlogin.js.php index 75c241a91..a062b4c52 100644 --- a/web/skins/classic/views/js/postlogin.js.php +++ b/web/skins/classic/views/js/postlogin.js.php @@ -21,13 +21,13 @@ } ?>'; - if ( querySuffix == '?view=login' ) { + if ( querySuffix == '?view=login' || querySuffix == '' ) { // If we didn't redirect elsewhere, then don't show login page, go to console querySuffix = '?view=console'; } var newUrl = querySuffix; - -console.log("Redirecting to" + newUrl + ' ' + thisUrl); +console.log("Current location: " + window.location); +console.log("Redirecting to (" + newUrl + ') from :' + thisUrl); window.location.replace(newUrl); } ).delay( 500 ); diff --git a/web/skins/classic/views/js/watch.js b/web/skins/classic/views/js/watch.js index e8977ddd6..633d507a5 100644 --- a/web/skins/classic/views/js/watch.js +++ b/web/skins/classic/views/js/watch.js @@ -546,42 +546,62 @@ function getEventCmdResponse( respObj, respText ) { } ); for ( var i = 0; i < dbEvents.length; i++ ) { - var event = dbEvents[i]; - var row = $('event'+event.Id); + var zm_event = dbEvents[i]; + var row = $('event'+zm_event.Id); var newEvent = (row == null ? true : false); if ( newEvent ) { - row = new Element( 'tr', {'id': 'event'+event.Id} ); - new Element( 'td', {'class': 'colId'} ).inject( row ); - new Element( 'td', {'class': 'colName'} ).inject( row ); - new Element( 'td', {'class': 'colTime'} ).inject( row ); - new Element( 'td', {'class': 'colSecs'} ).inject( row ); - new Element( 'td', {'class': 'colFrames'} ).inject( row ); - new Element( 'td', {'class': 'colScore'} ).inject( row ); - new Element( 'td', {'class': 'colDelete'} ).inject( row ); + row = new Element('tr', {'id': 'event'+zm_event.Id}); + new Element('td', {'class': 'colId'}).inject(row); + new Element('td', {'class': 'colName'}).inject(row); + new Element('td', {'class': 'colTime'}).inject(row); + new Element('td', {'class': 'colSecs'}).inject(row); + new Element('td', {'class': 'colFrames'}).inject(row); + new Element('td', {'class': 'colScore'}).inject(row); + new Element('td', {'class': 'colDelete'}).inject(row); - var link = new Element( 'a', {'href': '#', 'events': {'click': createEventPopup.pass( [event.Id, '&filter[Query][terms][0][attr]=MonitorId&filter[Query][terms][0][op]=%3d&filter[Query][terms][0][val]='+monitorId+'&page=1&popup=1', event.Width, event.Height] )}}); - link.set( 'text', event.Id ); - link.inject( row.getElement( 'td.colId' ) ); + var link = new Element('a', { + 'href': '#', + 'events': { + 'click': createEventPopup.pass( [ + zm_event.Id, + '&filter[Query][terms][0][attr]=MonitorId&filter[Query][terms][0][op]=%3d&filter[Query][terms][0][val]='+monitorId+'&page=1&popup=1', + zm_event.Width, + zm_event.Height + ] ) + } + }); + link.set('text', zm_event.Id); + link.inject(row.getElement('td.colId')); - link = new Element( 'a', {'href': '#', 'events': {'click': createEventPopup.pass( [event.Id, '&filter[Query][terms][0][attr]=MonitorId&filter[Query][terms][0][op]=%3d&filter[Query][terms][0][val]='+monitorId+'&page=1&popup=1', event.Width, event.Height] )}}); - link.set( 'text', event.Name ); - link.inject( row.getElement( 'td.colName' ) ); + link = new Element('a', { + 'href': '#', + 'events': { + 'click': createEventPopup.pass( [ + zm_event.Id, + '&filter[Query][terms][0][attr]=MonitorId&filter[Query][terms][0][op]=%3d&filter[Query][terms][0][val]='+monitorId+'&page=1&popup=1', + zm_event.Width, + zm_event.Height + ] ) + } + }); + link.set('text', zm_event.Name); + link.inject(row.getElement('td.colName')); - row.getElement( 'td.colTime' ).set( 'text', event.StartTime ); - row.getElement( 'td.colSecs' ).set( 'text', event.Length ); + row.getElement('td.colTime').set('text', zm_event.StartTime); + row.getElement('td.colSecs').set('text', zm_event.Length); - link = new Element( 'a', {'href': '#', 'events': {'click': createFramesPopup.pass( [event.Id, event.Width, event.Height] )}}); - link.set( 'text', event.Frames+'/'+event.AlarmFrames ); - link.inject( row.getElement( 'td.colFrames' ) ); + link = new Element('a', {'href': '#', 'events': {'click': createFramesPopup.pass( [zm_event.Id, zm_event.Width, zm_event.Height] )}}); + link.set('text', zm_event.Frames+'/'+zm_event.AlarmFrames); + link.inject(row.getElement('td.colFrames')); - link = new Element( 'a', {'href': '#', 'events': {'click': createFramePopup.pass( [event.Id, '0', event.Width, event.Height] )}}); - link.set( 'text', event.AvgScore+'/'+event.MaxScore ); - link.inject( row.getElement( 'td.colScore' ) ); + link = new Element('a', {'href': '#', 'events': {'click': createFramePopup.pass( [zm_event.Id, '0', zm_event.Width, zm_event.Height] )}}); + link.set('text', zm_event.AvgScore+'/'+zm_event.MaxScore); + link.inject(row.getElement('td.colScore')); - link = new Element( 'button', { + link = new Element('button', { 'type': 'button', 'title': deleteString, - 'data-event-id': event.Id, + 'data-event-id': zm_event.Id, 'events': { 'click': function(e) { var event_id = e.target.getAttribute('data-event-id'); @@ -608,14 +628,14 @@ function getEventCmdResponse( respObj, respText ) { } } } else { - row.getElement('td.colName a').set('text', event.Name); - row.getElement('td.colSecs').set('text', event.Length); - row.getElement('td.colFrames a').set('text', event.Frames+'/'+event.AlarmFrames); - row.getElement('td.colScore a').set('text', event.AvgScore+'/'+event.MaxScore); + row.getElement('td.colName a').set('text', zm_event.Name); + row.getElement('td.colSecs').set('text', zm_event.Length); + row.getElement('td.colFrames a').set('text', zm_event.Frames+'/'+zm_event.AlarmFrames); + row.getElement('td.colScore a').set('text', zm_event.AvgScore+'/'+zm_event.MaxScore); row.removeClass('recent'); } row.addClass('updated'); - } + } // end foreach event var rows = $(eventListBody).getElements('tr'); for ( var i = 0; i < rows.length; i++ ) { @@ -631,7 +651,7 @@ function getEventCmdResponse( respObj, respText ) { } } else { checkStreamForErrors('getEventCmdResponse', respObj); - } + } // end if objresult == ok var eventCmdTimeout = eventsRefreshTimeout; if ( alarmState == STATE_ALARM || alarmState == STATE_ALERT ) { @@ -672,7 +692,8 @@ function getControlResponse(respObj, respText) { } } -function controlCmd(button) { +function controlCmd(event) { + button = event.target; control = button.getAttribute('value'); xtell = button.getAttribute('xtell'); ytell = button.getAttribute('ytell'); @@ -687,7 +708,7 @@ function controlCmd(button) { var y = event.pageY - coords.top; if ( xtell ) { - var xge = parseInt( (x*100)/coords.width ); + var xge = parseInt((x*100)/coords.width); if ( xtell == -1 ) { xge = 100 - xge; } else if ( xtell == 2 ) { @@ -696,7 +717,7 @@ function controlCmd(button) { locParms += '&xge='+xge; } if ( ytell ) { - var yge = parseInt( (y*100)/coords.height ); + var yge = parseInt((y*100)/coords.height); if ( ytell == -1 ) { yge = 100 - yge; } else if ( ytell == 2 ) { diff --git a/web/skins/classic/views/monitor.php b/web/skins/classic/views/monitor.php index 303e335ee..5ac52494e 100644 --- a/web/skins/classic/views/monitor.php +++ b/web/skins/classic/views/monitor.php @@ -783,19 +783,22 @@ include('_monitor_source_nvsocket.php'); ?> Protocol(), "updateMethods( this );if(this.value=='rtsp'){\$('RTSPDescribe').setStyle('display','table-row');}else{\$('RTSPDescribe').hide();}" ); ?> + + + +Protocol() || $monitor->Protocol() == 'http' ) { -?> - Method() ); ?> -Method() ); } else { -?> - Method() ); ?> -Method() ); } ?> - + + + - + Type() == 'File' ) { ?> @@ -803,23 +806,44 @@ include('_monitor_source_nvsocket.php'); Type() == 'cURL' ) { ?> - - - + + + Type() == 'WebSite' ) { ?> - - () - () - + + + + + + () + + + + () + + + + + + Type() == 'Ffmpeg' || $monitor->Type() == 'Libvlc' ) { + } else if ( $monitor->Type() == 'Ffmpeg' || $monitor->Type() == 'Libvlc' ) { ?> - -  ()Method() ); ?> + + + + + + ) + Method()) ?> + -  (Type()), 'zmOptionHelp', 'optionhelp', '?' ) ?>) +  (Type()), 'zmOptionHelp', 'optionhelp', '?' ) ?>) Type() != 'NVSocket' && $monitor->Type() != 'WebSite' ) { + if ( $monitor->Type() != 'NVSocket' && $monitor->Type() != 'WebSite' ) { ?> - Colours() ); ?> - + + + Colours()) ?> + () @@ -884,18 +910,22 @@ if ( $monitor->Type() != 'NVSocket' && $monitor->Type() != 'WebSite' ) { Orientation());?> Type() == 'Local' ) { + } + if ( $monitor->Type() == 'Local' ) { ?> - - + + Deinterlacing())?> + +Type() != 'WebSite' ) { ?> - + + + Deinterlacing())?> + - Type() == 'Remote' ) { ?> Protocol()!= 'rtsp' ) { echo ' style="display:none;"'; } ?>> () RTSPDescribe() ) { ?> checked="checked"/> @@ -939,15 +969,17 @@ if ( $monitor->Type() == 'Local' ) { $videowriteropts[1] = 'X264 Encode'; - if ($monitor->Type() == 'Ffmpeg' ) + if ( $monitor->Type() == 'Ffmpeg' ) $videowriteropts[2] = 'H264 Camera Passthrough'; else $videowriteropts[2] = array('text'=>'H264 Camera Passthrough - only for FFMPEG','disabled'=>1); - echo htmlselect( 'newMonitor[VideoWriter]', $videowriteropts, $monitor->VideoWriter() ); + echo htmlselect('newMonitor[VideoWriter]', $videowriteropts, $monitor->VideoWriter()); ?> - + + + Type() == 'Ffmpeg' ) { ?> RecordAudio() ) { ?> checked="checked"/> @@ -962,22 +994,52 @@ if ( $monitor->Type() == 'Local' ) { case 'timestamp' : { ?> - - - - + + + + + + + + + + + + + + + LabelSize()) ?> + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + Type() == 'Local' ) { ?> - Controllable() ) { ?> checked="checked"/> + Controllable() ) { ?> checked="checked"/> + ControlId()); @@ -1011,20 +1074,19 @@ if ( canEdit('Control') ) { TrackMotion() ) { ?> checked="checked"/> - translate('None'), - '0' => translate('Home'), - '1' => translate('Preset').' 1', - ); -?> - ReturnLocation()); ?> + translate('None'), + '0' => translate('Home'), + '1' => translate('Preset').' 1', + ); +echo htmlSelect('newMonitor[ReturnLocation]', $return_options, $monitor->ReturnLocation()); ?> diff --git a/web/skins/classic/views/watch.php b/web/skins/classic/views/watch.php index fa540557e..e1f54e29d 100644 --- a/web/skins/classic/views/watch.php +++ b/web/skins/classic/views/watch.php @@ -1,6 +1,6 @@ DefaultScale(), ZM_WEB_DEFAULT_SCALE); + $scale = $monitor->DefaultScale(); } $connkey = generateConnKey(); $streamMode = getStreamMode(); -noCacheHeaders(); - $popup = ((isset($_REQUEST['popup'])) && ($_REQUEST['popup'] == 1)); +noCacheHeaders(); xhtmlHeaders(__FILE__, $monitor->Name().' - '.translate('Feed')); ?> @@ -77,7 +76,7 @@ if ( canView('Control') && $monitor->Type() == 'Local' ) {
Status() != 'Connected' ) { +if ( $monitor->Status() != 'Connected' and $monitor->Type() != 'WebSite' ) { echo '
Monitor is not capturing. We will be unable to provide an image
'; } ?>