From cf9c47149f391074ccedf2fe76acce8a89309fbc Mon Sep 17 00:00:00 2001 From: Peter Keresztes Schmidt Date: Tue, 29 Jun 2021 11:18:57 +0200 Subject: [PATCH 1/4] db: Add helper for escaping strings and use it --- src/zm_db.cpp | 12 ++++++++++++ src/zm_db.h | 2 ++ src/zm_event.cpp | 7 ++----- src/zm_logger.cpp | 6 +----- src/zm_user.cpp | 10 +--------- 5 files changed, 18 insertions(+), 19 deletions(-) diff --git a/src/zm_db.cpp b/src/zm_db.cpp index 7224241b4..1b811b7ee 100644 --- a/src/zm_db.cpp +++ b/src/zm_db.cpp @@ -267,3 +267,15 @@ void zmDbQueue::push(std::string &&sql) { mQueue.push(std::move(sql)); mCondition.notify_all(); } + +std::string zmDbEscapeString(const std::string& to_escape) { + // According to docs, size of safer_whatever must be 2 * length + 1 + // due to unicode conversions + null terminator. + std::string escaped((to_escape.length() * 2) + 1, '\0'); + + + size_t escaped_len = mysql_real_escape_string(&dbconn, &escaped[0], to_escape.c_str(), to_escape.length()); + escaped.resize(escaped_len); + + return escaped; +} diff --git a/src/zm_db.h b/src/zm_db.h index c243aa6d6..a35b17c13 100644 --- a/src/zm_db.h +++ b/src/zm_db.h @@ -78,4 +78,6 @@ int zmDbDoUpdate(const char *query); MYSQL_RES * zmDbFetch(const char *query); zmDbRow *zmDbFetchOne(const char *query); +std::string zmDbEscapeString(const std::string& to_escape); + #endif // ZM_DB_H diff --git a/src/zm_event.cpp b/src/zm_event.cpp index b0215662a..9b612556a 100644 --- a/src/zm_event.cpp +++ b/src/zm_event.cpp @@ -402,12 +402,9 @@ void Event::updateNotes(const StringSetMap &newNoteSetMap) { Error("Unable to execute sql '%s': %s", sql, mysql_stmt_error(stmt)); } #else - char sql[ZM_SQL_LGE_BUFSIZ]; - static char escapedNotes[ZM_SQL_MED_BUFSIZ]; + std::string escaped_notes = zmDbEscapeString(notes); - mysql_real_escape_string(&dbconn, escapedNotes, notes.c_str(), notes.length()); - - snprintf(sql, sizeof(sql), "UPDATE `Events` SET `Notes` = '%s' WHERE `Id` = %" PRIu64, escapedNotes, id); + std::string sql = stringtf("UPDATE `Events` SET `Notes` = '%s' WHERE `Id` = %" PRIu64, escaped_notes.c_str(), id); dbQueue.push(std::move(sql)); #endif } // end if update diff --git a/src/zm_logger.cpp b/src/zm_logger.cpp index 580043488..841ee51cf 100644 --- a/src/zm_logger.cpp +++ b/src/zm_logger.cpp @@ -518,11 +518,7 @@ void Logger::logPrint(bool hex, const char *filepath, int line, int level, const if (level <= mDatabaseLevel) { if (zmDbConnected) { - int syslogSize = syslogEnd - syslogStart; - std::string escapedString; - escapedString.resize((syslogSize * 2) + 1); - mysql_real_escape_string(&dbconn, &escapedString[0], syslogStart, syslogSize); - escapedString.resize(std::strlen(escapedString.c_str())); + std::string escapedString = zmDbEscapeString({syslogStart, syslogEnd}); std::string sql_string = stringtf( "INSERT INTO `Logs` " diff --git a/src/zm_user.cpp b/src/zm_user.cpp index 85e858545..29bf7d327 100644 --- a/src/zm_user.cpp +++ b/src/zm_user.cpp @@ -85,15 +85,7 @@ bool User::canAccess(int monitor_id) { // Function to load a user from username and password // Please note that in auth relay mode = none, password is NULL User *zmLoadUser(const char *username, const char *password) { - int username_length = strlen(username); - - // According to docs, size of safer_whatever must be 2*length+1 - // due to unicode conversions + null terminator. - std::string escaped_username((username_length * 2) + 1, '\0'); - - - size_t escaped_len = mysql_real_escape_string(&dbconn, &escaped_username[0], username, username_length); - escaped_username.resize(escaped_len); + std::string escaped_username = zmDbEscapeString(username); std::string sql = stringtf("SELECT `Id`, `Username`, `Password`, `Enabled`," " `Stream`+0, `Events`+0, `Control`+0, `Monitors`+0, `System`+0," From fc15afefcf3d050b55138f832dd6e1dd1e1fec46 Mon Sep 17 00:00:00 2001 From: Peter Keresztes Schmidt Date: Wed, 30 Jun 2021 20:47:39 +0200 Subject: [PATCH 2/4] Event: Remove unused and broken prepared statement code --- src/zm_event.cpp | 55 +++--------------------------------------------- 1 file changed, 3 insertions(+), 52 deletions(-) diff --git a/src/zm_event.cpp b/src/zm_event.cpp index 9b612556a..0a3fb5b88 100644 --- a/src/zm_event.cpp +++ b/src/zm_event.cpp @@ -32,8 +32,6 @@ #include #include -//#define USE_PREPARED_SQL 1 - const char * Event::frame_type_names[3] = { "Normal", "Bulk", "Alarm" }; #define MAX_DB_FRAMES 100 @@ -351,62 +349,15 @@ void Event::updateNotes(const StringSetMap &newNoteSetMap) { } // end if have old notes } // end if have new notes - if ( update ) { + if (update) { std::string notes; createNotes(notes); Debug(2, "Updating notes for event %" PRIu64 ", '%s'", id, notes.c_str()); -#if USE_PREPARED_SQL - static MYSQL_STMT *stmt = 0; - char notesStr[ZM_SQL_MED_BUFSIZ] = ""; - unsigned long notesLen = 0; - - if ( !stmt ) { - const char *sql = "UPDATE `Events` SET `Notes` = ? WHERE `Id` = ?"; - - stmt = mysql_stmt_init(&dbconn); - if ( mysql_stmt_prepare(stmt, sql, strlen(sql)) ) { - Fatal("Unable to prepare sql '%s': %s", sql, mysql_stmt_error(stmt)); - } - - /* Get the parameter count from the statement */ - if ( mysql_stmt_param_count(stmt) != 2 ) { - Error("Unexpected parameter count %ld in sql '%s'", mysql_stmt_param_count(stmt), sql); - } - - MYSQL_BIND bind[2]; - memset(bind, 0, sizeof(bind)); - - /* STRING PARAM */ - bind[0].buffer_type = MYSQL_TYPE_STRING; - bind[0].buffer = (char *)notesStr; - bind[0].buffer_length = sizeof(notesStr); - bind[0].is_null = 0; - bind[0].length = ¬esLen; - - bind[1].buffer_type= MYSQL_TYPE_LONG; - bind[1].buffer= (char *)&id; - bind[1].is_null= 0; - bind[1].length= 0; - - /* Bind the buffers */ - if ( mysql_stmt_bind_param(stmt, bind) ) { - Error("Unable to bind sql '%s': %s", sql, mysql_stmt_error(stmt)); - } - } // end if ! stmt - - strncpy(notesStr, notes.c_str(), sizeof(notesStr)); - - if ( mysql_stmt_execute(stmt) ) { - Error("Unable to execute sql '%s': %s", sql, mysql_stmt_error(stmt)); - } -#else - std::string escaped_notes = zmDbEscapeString(notes); - - std::string sql = stringtf("UPDATE `Events` SET `Notes` = '%s' WHERE `Id` = %" PRIu64, escaped_notes.c_str(), id); + std::string sql = stringtf("UPDATE `Events` SET `Notes` = '%s' WHERE `Id` = %" PRIu64, + zmDbEscapeString(notes).c_str(), id); dbQueue.push(std::move(sql)); -#endif } // end if update } // void Event::updateNotes(const StringSetMap &newNoteSetMap) From c60b577aecc953f2bfbd486ffee3bd99c09a94b0 Mon Sep 17 00:00:00 2001 From: Peter Keresztes Schmidt Date: Wed, 30 Jun 2021 20:49:37 +0200 Subject: [PATCH 3/4] Convert more char array buffers to std::string Remove now unused ZM_SQL_*SIZE defines --- src/zm_config.h | 3 -- src/zm_group.cpp | 41 +++++++++++++------------- src/zm_monitor.cpp | 10 +++---- src/zm_rtsp.cpp | 5 ++-- src/zm_storage.cpp | 71 +++++++++++++++++++++++----------------------- src/zm_zone.cpp | 5 ++-- src/zmc.cpp | 16 +++++------ 7 files changed, 71 insertions(+), 80 deletions(-) diff --git a/src/zm_config.h b/src/zm_config.h index a6d0420b4..3d38cf683 100644 --- a/src/zm_config.h +++ b/src/zm_config.h @@ -38,10 +38,7 @@ #define ZM_SCALE_BASE 100 // The factor by which we bump up 'scale' to simulate FP #define ZM_RATE_BASE 100 // The factor by which we bump up 'rate' to simulate FP -#define ZM_SQL_BATCH_SIZE 50 // Limit the size of multi-row SQL statements -#define ZM_SQL_SML_BUFSIZ 256 // Size of SQL buffer #define ZM_SQL_MED_BUFSIZ 1024 // Size of SQL buffer -#define ZM_SQL_LGE_BUFSIZ 8192 // Size of SQL buffer #define ZM_NETWORK_BUFSIZ 32768 // Size of network buffer diff --git a/src/zm_group.cpp b/src/zm_group.cpp index b2fc43e5f..c3cf55069 100644 --- a/src/zm_group.cpp +++ b/src/zm_group.cpp @@ -20,6 +20,7 @@ #include "zm_group.h" #include "zm_logger.h" +#include "zm_utils.h" #include Group::Group() { @@ -39,27 +40,27 @@ Group::Group(const MYSQL_ROW &dbrow) { /* If a zero or invalid p_id is passed, then the old default path will be assumed. */ Group::Group(unsigned int p_id) { - id = 0; + id = 0; - if ( p_id ) { - char sql[ZM_SQL_SML_BUFSIZ]; - snprintf(sql, sizeof(sql), "SELECT `Id`, `ParentId`, `Name` FROM `Group` WHERE `Id`=%u", p_id); - Debug(2,"Loading Group for %u using %s", p_id, sql); - zmDbRow dbrow; - if ( !dbrow.fetch(sql) ) { - Error("Unable to load group for id %u: %s", p_id, mysql_error(&dbconn)); - } else { - unsigned int index = 0; - id = atoi(dbrow[index++]); - parent_id = dbrow[index] ? atoi(dbrow[index]): 0; index++; - strncpy(name, dbrow[index++], sizeof(name)-1); - Debug(1, "Loaded Group area %d '%s'", id, this->Name()); - } - } - if ( ! id ) { - Debug(1,"No id passed to Group constructor."); - strcpy(name, "Default"); - } + if (p_id) { + std::string sql = stringtf("SELECT `Id`, `ParentId`, `Name` FROM `Group` WHERE `Id`=%u", p_id); + Debug(2, "Loading Group for %u using %s", p_id, sql.c_str()); + zmDbRow dbrow; + if (!dbrow.fetch(sql.c_str())) { + Error("Unable to load group for id %u: %s", p_id, mysql_error(&dbconn)); + } else { + unsigned int index = 0; + id = atoi(dbrow[index++]); + parent_id = dbrow[index] ? atoi(dbrow[index]) : 0; + index++; + strncpy(name, dbrow[index++], sizeof(name) - 1); + Debug(1, "Loaded Group area %d '%s'", id, this->Name()); + } + } + if (!id) { + Debug(1, "No id passed to Group constructor."); + strcpy(name, "Default"); + } } Group::~Group() { diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index 4dc7a3128..633dc3cea 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -1287,17 +1287,15 @@ void Monitor::actionReload() { void Monitor::actionEnable() { shared_data->action |= RELOAD; - char sql[ZM_SQL_SML_BUFSIZ]; - snprintf(sql, sizeof(sql), "UPDATE `Monitors` SET `Enabled` = 1 WHERE `Id` = %u", id); - zmDbDo(sql); + std::string sql = stringtf("UPDATE `Monitors` SET `Enabled` = 1 WHERE `Id` = %u", id); + zmDbDo(sql.c_str()); } void Monitor::actionDisable() { shared_data->action |= RELOAD; - char sql[ZM_SQL_SML_BUFSIZ]; - snprintf(sql, sizeof(sql), "UPDATE `Monitors` SET `Enabled` = 0 WHERE `Id` = %u", id); - zmDbDo(sql); + std::string sql = stringtf("UPDATE `Monitors` SET `Enabled` = 0 WHERE `Id` = %u", id); + zmDbDo(sql.c_str()); } void Monitor::actionSuspend() { diff --git a/src/zm_rtsp.cpp b/src/zm_rtsp.cpp index d31df3012..4cd641fac 100644 --- a/src/zm_rtsp.cpp +++ b/src/zm_rtsp.cpp @@ -86,11 +86,10 @@ bool RtspThread::recvResponse(std::string &response) { int RtspThread::requestPorts() { if ( !smMinDataPort ) { - char sql[ZM_SQL_SML_BUFSIZ]; //FIXME Why not load specifically by Id? This will get ineffeicient with a lot of monitors - strncpy(sql, "SELECT `Id` FROM `Monitors` WHERE `Function` != 'None' AND `Type` = 'Remote' AND `Protocol` = 'rtsp' AND `Method` = 'rtpUni' ORDER BY `Id` ASC", sizeof(sql)); + std::string sql = "SELECT `Id` FROM `Monitors` WHERE `Function` != 'None' AND `Type` = 'Remote' AND `Protocol` = 'rtsp' AND `Method` = 'rtpUni' ORDER BY `Id` ASC"; - MYSQL_RES *result = zmDbFetch(sql); + MYSQL_RES *result = zmDbFetch(sql.c_str()); int nMonitors = mysql_num_rows(result); int position = 0; diff --git a/src/zm_storage.cpp b/src/zm_storage.cpp index 5edc36e00..79f3e8c0b 100644 --- a/src/zm_storage.cpp +++ b/src/zm_storage.cpp @@ -21,32 +21,33 @@ #include "zm_db.h" #include "zm_logger.h" +#include "zm_utils.h" #include Storage::Storage() : id(0) { - Warning("Instantiating default Storage Object. Should not happen."); - strcpy(name, "Default"); - if ( staticConfig.DIR_EVENTS[0] != '/' ) { + Warning("Instantiating default Storage Object. Should not happen."); + strcpy(name, "Default"); + if (staticConfig.DIR_EVENTS[0] != '/') { // not using an absolute path. Make it one by appending ZM_PATH_WEB snprintf(path, sizeof(path), "%s/%s", - staticConfig.PATH_WEB.c_str(), staticConfig.DIR_EVENTS.c_str()); + staticConfig.PATH_WEB.c_str(), staticConfig.DIR_EVENTS.c_str()); } else { - strncpy(path, staticConfig.DIR_EVENTS.c_str(), sizeof(path)-1); + strncpy(path, staticConfig.DIR_EVENTS.c_str(), sizeof(path) - 1); } scheme = MEDIUM; scheme_str = "Medium"; } Storage::Storage(MYSQL_ROW &dbrow) { - unsigned int index = 0; - id = atoi(dbrow[index++]); - strncpy(name, dbrow[index++], sizeof(name)-1); - strncpy(path, dbrow[index++], sizeof(path)-1); + unsigned int index = 0; + id = atoi(dbrow[index++]); + strncpy(name, dbrow[index++], sizeof(name) - 1); + strncpy(path, dbrow[index++], sizeof(path) - 1); type_str = std::string(dbrow[index++]); scheme_str = std::string(dbrow[index++]); - if ( scheme_str == "Deep" ) { + if (scheme_str == "Deep") { scheme = DEEP; - } else if ( scheme_str == "Medium" ) { + } else if (scheme_str == "Medium") { scheme = MEDIUM; } else { scheme = SHALLOW; @@ -55,44 +56,42 @@ Storage::Storage(MYSQL_ROW &dbrow) { /* If a zero or invalid p_id is passed, then the old default path will be assumed. */ Storage::Storage(unsigned int p_id) : id(p_id) { - - if ( id ) { - char sql[ZM_SQL_SML_BUFSIZ]; - snprintf(sql, sizeof(sql), "SELECT `Id`, `Name`, `Path`, `Type`, `Scheme` FROM `Storage` WHERE `Id`=%u", id); - Debug(2, "Loading Storage for %u using %s", id, sql); - zmDbRow dbrow; - if ( !dbrow.fetch(sql) ) { - Error("Unable to load storage area for id %d: %s", id, mysql_error(&dbconn)); - } else { - unsigned int index = 0; - id = atoi(dbrow[index++]); - strncpy(name, dbrow[index++], sizeof(name)-1); - strncpy(path, dbrow[index++], sizeof(path)-1); + if (id) { + std::string sql = stringtf("SELECT `Id`, `Name`, `Path`, `Type`, `Scheme` FROM `Storage` WHERE `Id`=%u", id); + Debug(2, "Loading Storage for %u using %s", id, sql.c_str()); + zmDbRow dbrow; + if (!dbrow.fetch(sql.c_str())) { + Error("Unable to load storage area for id %d: %s", id, mysql_error(&dbconn)); + } else { + unsigned int index = 0; + id = atoi(dbrow[index++]); + strncpy(name, dbrow[index++], sizeof(name) - 1); + strncpy(path, dbrow[index++], sizeof(path) - 1); type_str = std::string(dbrow[index++]); scheme_str = std::string(dbrow[index++]); - if ( scheme_str == "Deep" ) { + if (scheme_str == "Deep") { scheme = DEEP; - } else if ( scheme_str == "Medium" ) { + } else if (scheme_str == "Medium") { scheme = MEDIUM; } else { scheme = SHALLOW; } - Debug(1, "Loaded Storage area %d '%s'", id, name); - } - } - if ( !id ) { - if ( staticConfig.DIR_EVENTS[0] != '/' ) { + Debug(1, "Loaded Storage area %d '%s'", id, name); + } + } + if (!id) { + if (staticConfig.DIR_EVENTS[0] != '/') { // not using an absolute path. Make it one by appending ZM_PATH_WEB snprintf(path, sizeof(path), "%s/%s", - staticConfig.PATH_WEB.c_str(), staticConfig.DIR_EVENTS.c_str()); + staticConfig.PATH_WEB.c_str(), staticConfig.DIR_EVENTS.c_str()); } else { - strncpy(path, staticConfig.DIR_EVENTS.c_str(), sizeof(path)-1); + strncpy(path, staticConfig.DIR_EVENTS.c_str(), sizeof(path) - 1); } - Debug(1, "No id passed to Storage constructor. Using default path %s instead", path); - strcpy(name, "Default"); + Debug(1, "No id passed to Storage constructor. Using default path %s instead", path); + strcpy(name, "Default"); scheme = MEDIUM; scheme_str = "Medium"; - } + } } Storage::~Storage() { diff --git a/src/zm_zone.cpp b/src/zm_zone.cpp index 41174857f..dfda5d868 100644 --- a/src/zm_zone.cpp +++ b/src/zm_zone.cpp @@ -116,8 +116,7 @@ Zone::~Zone() { } void Zone::RecordStats(const Event *event) { - static char sql[ZM_SQL_MED_BUFSIZ]; - snprintf(sql, sizeof(sql), + std::string sql = stringtf( "INSERT INTO Stats SET MonitorId=%d, ZoneId=%d, EventId=%" PRIu64 ", FrameId=%d, " "PixelDiff=%d, AlarmPixels=%d, FilterPixels=%d, BlobPixels=%d, " "Blobs=%d, MinBlobSize=%d, MaxBlobSize=%d, " @@ -136,7 +135,7 @@ void Zone::RecordStats(const Event *event) { stats.alarm_box_.Hi().y_, stats.score_ ); - zmDbDo(sql); + zmDbDo(sql.c_str()); } // end void Zone::RecordStats( const Event *event ) bool Zone::CheckOverloadCount() { diff --git a/src/zmc.cpp b/src/zmc.cpp index 9cb23dfba..3f9db1bd5 100644 --- a/src/zmc.cpp +++ b/src/zmc.cpp @@ -232,7 +232,6 @@ int main(int argc, char *argv[]) { while (!zm_terminate) { result = 0; - static char sql[ZM_SQL_SML_BUFSIZ]; for (const std::shared_ptr &monitor : monitors) { monitor->LoadCamera(); @@ -244,11 +243,11 @@ int main(int argc, char *argv[]) { monitor->SetStartupTime(now); monitor->SetHeartbeatTime(now); - snprintf(sql, sizeof(sql), + std::string sql = stringtf( "INSERT INTO Monitor_Status (MonitorId,Status,CaptureFPS,AnalysisFPS)" " VALUES (%u, 'Running',0,0) ON DUPLICATE KEY UPDATE Status='Running',CaptureFPS=0,AnalysisFPS=0", monitor->Id()); - zmDbDo(sql); + zmDbDo(sql.c_str()); Seconds sleep_time = Seconds(0); while (monitor->PrimeCapture() <= 0) { @@ -273,10 +272,10 @@ int main(int argc, char *argv[]) { break; } - snprintf(sql, sizeof(sql), + sql = stringtf( "INSERT INTO Monitor_Status (MonitorId,Status) VALUES (%u, 'Connected') ON DUPLICATE KEY UPDATE Status='Connected'", - monitor->Id()); - zmDbDo(sql); + monitor->Id()); + zmDbDo(sql.c_str()); } // end foreach monitor if (zm_terminate){ @@ -360,11 +359,10 @@ int main(int argc, char *argv[]) { } // end while ! zm_terminate outer connection loop for (std::shared_ptr &monitor : monitors) { - static char sql[ZM_SQL_SML_BUFSIZ]; - snprintf(sql, sizeof(sql), + std::string sql = stringtf( "INSERT INTO Monitor_Status (MonitorId,Status) VALUES (%u, 'NotRunning') ON DUPLICATE KEY UPDATE Status='NotRunning'", monitor->Id()); - zmDbDo(sql); + zmDbDo(sql.c_str()); } Image::Deinitialise(); From 65656de6ce18a73931daf849bc42ad341f6c8fae Mon Sep 17 00:00:00 2001 From: Peter Keresztes Schmidt Date: Thu, 1 Jul 2021 09:16:26 +0200 Subject: [PATCH 4/4] db: Adjust the query methods to accept std::strings --- src/zm_config.cpp | 4 ++-- src/zm_config.h | 2 -- src/zm_db.cpp | 42 +++++++++++++++++++++--------------------- src/zm_db.h | 15 ++++++--------- src/zm_event.cpp | 18 +++++++++--------- src/zm_eventstream.cpp | 8 ++++---- src/zm_group.cpp | 2 +- src/zm_monitor.cpp | 16 ++++++++-------- src/zm_rtsp.cpp | 2 +- src/zm_storage.cpp | 2 +- src/zm_user.cpp | 6 +++--- src/zm_zone.cpp | 4 ++-- src/zmc.cpp | 6 +++--- src/zmu.cpp | 2 +- 14 files changed, 62 insertions(+), 67 deletions(-) diff --git a/src/zm_config.cpp b/src/zm_config.cpp index 97e2f8c2a..c4185e055 100644 --- a/src/zm_config.cpp +++ b/src/zm_config.cpp @@ -75,7 +75,7 @@ void zmLoadDBConfig() { std::string sql = stringtf("SELECT `Id` FROM `Servers` WHERE `Name`='%s'", staticConfig.SERVER_NAME.c_str()); zmDbRow dbrow; - if (dbrow.fetch(sql.c_str())) { + if (dbrow.fetch(sql)) { staticConfig.SERVER_ID = atoi(dbrow[0]); } else { Fatal("Can't get ServerId for Server %s", staticConfig.SERVER_NAME.c_str()); @@ -87,7 +87,7 @@ void zmLoadDBConfig() { std::string sql = stringtf("SELECT `Name` FROM `Servers` WHERE `Id`='%d'", staticConfig.SERVER_ID); zmDbRow dbrow; - if (dbrow.fetch(sql.c_str())) { + if (dbrow.fetch(sql)) { staticConfig.SERVER_NAME = std::string(dbrow[0]); } else { Fatal("Can't get ServerName for Server ID %d", staticConfig.SERVER_ID); diff --git a/src/zm_config.h b/src/zm_config.h index 3d38cf683..881a2e52e 100644 --- a/src/zm_config.h +++ b/src/zm_config.h @@ -38,8 +38,6 @@ #define ZM_SCALE_BASE 100 // The factor by which we bump up 'scale' to simulate FP #define ZM_RATE_BASE 100 // The factor by which we bump up 'rate' to simulate FP -#define ZM_SQL_MED_BUFSIZ 1024 // Size of SQL buffer - #define ZM_NETWORK_BUFSIZ 32768 // Size of network buffer #define ZM_MAX_FPS 30 // The maximum frame rate we expect to handle diff --git a/src/zm_db.cpp b/src/zm_db.cpp index 1b811b7ee..0d499edbd 100644 --- a/src/zm_db.cpp +++ b/src/zm_db.cpp @@ -117,25 +117,25 @@ void zmDbClose() { } } -MYSQL_RES * zmDbFetch(const char * query) { +MYSQL_RES *zmDbFetch(const std::string &query) { std::lock_guard lck(db_mutex); if (!zmDbConnected) { Error("Not connected."); return nullptr; } - if (mysql_query(&dbconn, query)) { + if (mysql_query(&dbconn, query.c_str())) { Error("Can't run query: %s", mysql_error(&dbconn)); return nullptr; } MYSQL_RES *result = mysql_store_result(&dbconn); if (!result) { - Error("Can't use query result: %s for query %s", mysql_error(&dbconn), query); + Error("Can't use query result: %s for query %s", mysql_error(&dbconn), query.c_str()); } return result; -} // end MYSQL_RES * zmDbFetch(const char * query); +} -zmDbRow *zmDbFetchOne(const char *query) { +zmDbRow *zmDbFetchOne(const std::string &query) { zmDbRow *row = new zmDbRow(); if (row->fetch(query)) { return row; @@ -144,13 +144,13 @@ zmDbRow *zmDbFetchOne(const char *query) { return nullptr; } -MYSQL_RES *zmDbRow::fetch(const char *query) { +MYSQL_RES *zmDbRow::fetch(const std::string &query) { result_set = zmDbFetch(query); if (!result_set) return result_set; int n_rows = mysql_num_rows(result_set); if (n_rows != 1) { - Error("Bogus number of lines return from query, %d returned for query %s.", n_rows, query); + Error("Bogus number of lines return from query, %d returned for query %s.", n_rows, query.c_str()); mysql_free_result(result_set); result_set = nullptr; return result_set; @@ -160,23 +160,23 @@ MYSQL_RES *zmDbRow::fetch(const char *query) { if (!row) { mysql_free_result(result_set); result_set = nullptr; - Error("Error getting row from query %s. Error is %s", query, mysql_error(&dbconn)); + Error("Error getting row from query %s. Error is %s", query.c_str(), mysql_error(&dbconn)); } else { Debug(5, "Success"); } return result_set; } -int zmDbDo(const char *query) { +int zmDbDo(const std::string &query) { std::lock_guard lck(db_mutex); if (!zmDbConnected) return 0; int rc; - while ((rc = mysql_query(&dbconn, query)) and !zm_terminate) { + while ((rc = mysql_query(&dbconn, query.c_str())) and !zm_terminate) { Logger *logger = Logger::fetch(); Logger::Level oldLevel = logger->databaseLevel(); logger->databaseLevel(Logger::NOLOG); - Error("Can't run query %s: %s", query, mysql_error(&dbconn)); + Error("Can't run query %s: %s", query.c_str(), mysql_error(&dbconn)); logger->databaseLevel(oldLevel); if ( (mysql_errno(&dbconn) != ER_LOCK_WAIT_TIMEOUT) ) { return rc; @@ -186,36 +186,36 @@ int zmDbDo(const char *query) { Logger::Level oldLevel = logger->databaseLevel(); logger->databaseLevel(Logger::NOLOG); - Debug(1, "Success running sql query %s", query); + Debug(1, "Success running sql query %s", query.c_str()); logger->databaseLevel(oldLevel); return 1; } -int zmDbDoInsert(const char *query) { +int zmDbDoInsert(const std::string &query) { std::lock_guard lck(db_mutex); if (!zmDbConnected) return 0; int rc; - while ( (rc = mysql_query(&dbconn, query)) and !zm_terminate) { - Error("Can't run query %s: %s", query, mysql_error(&dbconn)); + while ( (rc = mysql_query(&dbconn, query.c_str())) and !zm_terminate) { + Error("Can't run query %s: %s", query.c_str(), mysql_error(&dbconn)); if ( (mysql_errno(&dbconn) != ER_LOCK_WAIT_TIMEOUT) ) return 0; } int id = mysql_insert_id(&dbconn); - Debug(2, "Success running sql insert %s. Resulting id is %d", query, id); + Debug(2, "Success running sql insert %s. Resulting id is %d", query.c_str(), id); return id; } -int zmDbDoUpdate(const char *query) { +int zmDbDoUpdate(const std::string &query) { std::lock_guard lck(db_mutex); if (!zmDbConnected) return 0; int rc; - while ( (rc = mysql_query(&dbconn, query)) and !zm_terminate) { - Error("Can't run query %s: %s", query, mysql_error(&dbconn)); + while ( (rc = mysql_query(&dbconn, query.c_str())) and !zm_terminate) { + Error("Can't run query %s: %s", query.c_str(), mysql_error(&dbconn)); if ( (mysql_errno(&dbconn) != ER_LOCK_WAIT_TIMEOUT) ) return -rc; } int affected = mysql_affected_rows(&dbconn); - Debug(2, "Success running sql update %s. Rows modified %d", query, affected); + Debug(2, "Success running sql update %s. Rows modified %d", query.c_str(), affected); return affected; } @@ -255,7 +255,7 @@ void zmDbQueue::process() { // My idea for leaving the locking around each sql statement is to allow // other db writers to get a chance lock.unlock(); - zmDbDo(sql.c_str()); + zmDbDo(sql); lock.lock(); } } diff --git a/src/zm_db.h b/src/zm_db.h index a35b17c13..7343ac75b 100644 --- a/src/zm_db.h +++ b/src/zm_db.h @@ -38,7 +38,6 @@ class zmDbQueue { public: zmDbQueue(); ~zmDbQueue(); - void push(const char *sql) { return push(std::string(sql)); }; void push(std::string &&sql); void process(); void stop(); @@ -50,7 +49,7 @@ class zmDbRow { MYSQL_ROW row; public: zmDbRow() : result_set(nullptr), row(nullptr) { }; - MYSQL_RES *fetch(const char *query); + MYSQL_RES *fetch(const std::string &query); zmDbRow(MYSQL_RES *, MYSQL_ROW *row); ~zmDbRow(); @@ -67,16 +66,14 @@ extern zmDbQueue dbQueue; extern bool zmDbConnected; -extern bool zmDbConnected; - bool zmDbConnect(); void zmDbClose(); -int zmDbDo(const char *query); -int zmDbDoInsert(const char *query); -int zmDbDoUpdate(const char *query); +int zmDbDo(const std::string &query); +int zmDbDoInsert(const std::string &query); +int zmDbDoUpdate(const std::string &query); -MYSQL_RES * zmDbFetch(const char *query); -zmDbRow *zmDbFetchOne(const char *query); +MYSQL_RES * zmDbFetch(const std::string &query); +zmDbRow *zmDbFetchOne(const std::string &query); std::string zmDbEscapeString(const std::string& to_escape); diff --git a/src/zm_event.cpp b/src/zm_event.cpp index 0a3fb5b88..4d8b9471d 100644 --- a/src/zm_event.cpp +++ b/src/zm_event.cpp @@ -125,7 +125,7 @@ Event::Event( storage->SchemeString().c_str() ); - id = zmDbDoInsert(sql.c_str()); + id = zmDbDoInsert(sql); if ( !SetPath(storage) ) { // Try another @@ -138,7 +138,7 @@ Event::Event( Debug(1, "%s", sql.c_str()); storage = nullptr; - MYSQL_RES *result = zmDbFetch(sql.c_str()); + MYSQL_RES *result = zmDbFetch(sql); if ( result ) { for ( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row(result); i++ ) { storage = new Storage(atoi(dbrow[0])); @@ -157,7 +157,7 @@ Event::Event( if ( monitor->ServerId() ) sql += stringtf(" OR ServerId != %u", monitor->ServerId()); - result = zmDbFetch(sql.c_str()); + result = zmDbFetch(sql); if ( result ) { for ( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row(result); i++ ) { storage = new Storage(atoi(dbrow[0])); @@ -175,7 +175,7 @@ Event::Event( Warning("Failed to find a storage area to save events."); } sql = stringtf("UPDATE Events SET StorageId = '%d' WHERE Id=%" PRIu64, storage->Id(), id); - zmDbDo(sql.c_str()); + zmDbDo(sql); } // end if ! setPath(Storage) Debug(1, "Using storage area at %s", path.c_str()); @@ -211,11 +211,11 @@ Event::Event( if ( ! ( save_jpegs & 1 ) ) { save_jpegs |= 1; // Turn on jpeg storage sql = stringtf("UPDATE Events SET SaveJpegs=%d WHERE Id=%" PRIu64, save_jpegs, id); - zmDbDo(sql.c_str()); + zmDbDo(sql); } } else { sql = stringtf("UPDATE Events SET Videoed=1, DefaultVideo = '%s' WHERE Id=%" PRIu64, video_name.c_str(), id); - zmDbDo(sql.c_str()); + zmDbDo(sql); } } // end if GetOptVideoWriter } @@ -253,7 +253,7 @@ Event::~Event() { tot_score, static_cast(alarm_frames ? (tot_score / alarm_frames) : 0), max_score, id); - if (!zmDbDoUpdate(sql.c_str())) { + if (!zmDbDoUpdate(sql)) { // Name might have been changed during recording, so just do the update without changing the name. sql = stringtf( "UPDATE Events SET EndDateTime = from_unixtime(%ld), Length = %.2f, Frames = %d, AlarmFrames = %d, TotScore = %d, AvgScore = %d, MaxScore = %d WHERE Id = %" PRIu64, @@ -262,7 +262,7 @@ Event::~Event() { frames, alarm_frames, tot_score, static_cast(alarm_frames ? (tot_score / alarm_frames) : 0), max_score, id); - zmDbDoUpdate(sql.c_str()); + zmDbDoUpdate(sql); } // end if no changed rows due to Name change during recording } // Event::~Event() @@ -425,7 +425,7 @@ void Event::WriteDbFrames() { } // end while frames // The -1 is for the extra , added for values above frame_insert_sql.erase(frame_insert_sql.size()-1); - //zmDbDo(frame_insert_sql.c_str()); + //zmDbDo(frame_insert_sql); dbQueue.push(std::move(frame_insert_sql)); if (stats_insert_sql.size() > 208) { // The -1 is for the extra , added for values above diff --git a/src/zm_eventstream.cpp b/src/zm_eventstream.cpp index 6c18940d2..487ecfd69 100644 --- a/src/zm_eventstream.cpp +++ b/src/zm_eventstream.cpp @@ -46,7 +46,7 @@ bool EventStream::loadInitialEventData(int monitor_id, SystemTimePoint event_tim "`MonitorId` = %d AND unix_timestamp(`EndDateTime`) > %ld " "ORDER BY `Id` ASC LIMIT 1", monitor_id, event_time); - MYSQL_RES *result = zmDbFetch(sql.c_str()); + MYSQL_RES *result = zmDbFetch(sql); if (!result) exit(-1); @@ -117,7 +117,7 @@ bool EventStream::loadEventData(uint64_t event_id) { "(SELECT max(`Delta`)-min(`Delta`) FROM `Frames` WHERE `EventId`=`Events`.`Id`) AS FramesDuration, " "`DefaultVideo`, `Scheme`, `SaveJPEGs`, `Orientation`+0 FROM `Events` WHERE `Id` = %" PRIu64, event_id); - MYSQL_RES *result = zmDbFetch(sql.c_str()); + MYSQL_RES *result = zmDbFetch(sql); if (!result) { exit(-1); } @@ -229,7 +229,7 @@ bool EventStream::loadEventData(uint64_t event_id) { sql = stringtf("SELECT `FrameId`, unix_timestamp(`TimeStamp`), `Delta` " "FROM `Frames` WHERE `EventId` = %" PRIu64 " ORDER BY `FrameId` ASC", event_id); - result = zmDbFetch(sql.c_str()); + result = zmDbFetch(sql); if (!result) { exit(-1); } @@ -640,7 +640,7 @@ bool EventStream::checkEventLoaded() { if ( forceEventChange || ( (mode != MODE_SINGLE) && (mode != MODE_NONE) ) ) { Debug(1, "Checking for next event %s", sql.c_str()); - MYSQL_RES *result = zmDbFetch(sql.c_str()); + MYSQL_RES *result = zmDbFetch(sql); if (!result) { exit(-1); } diff --git a/src/zm_group.cpp b/src/zm_group.cpp index c3cf55069..9ed7a1093 100644 --- a/src/zm_group.cpp +++ b/src/zm_group.cpp @@ -46,7 +46,7 @@ Group::Group(unsigned int p_id) { std::string sql = stringtf("SELECT `Id`, `ParentId`, `Name` FROM `Group` WHERE `Id`=%u", p_id); Debug(2, "Loading Group for %u using %s", p_id, sql.c_str()); zmDbRow dbrow; - if (!dbrow.fetch(sql.c_str())) { + if (!dbrow.fetch(sql)) { Error("Unable to load group for id %u: %s", p_id, mysql_error(&dbconn)); } else { unsigned int index = 0; diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index 633dc3cea..46efe8bd5 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -880,7 +880,7 @@ std::shared_ptr Monitor::Load(unsigned int p_id, bool load_zones, Purpo std::string sql = load_monitor_sql + stringtf(" WHERE Id=%d", p_id); zmDbRow dbrow; - if ( !dbrow.fetch(sql.c_str()) ) { + if (!dbrow.fetch(sql)) { Error("Can't use query result: %s", mysql_error(&dbconn)); return nullptr; } @@ -1288,14 +1288,14 @@ void Monitor::actionEnable() { shared_data->action |= RELOAD; std::string sql = stringtf("UPDATE `Monitors` SET `Enabled` = 1 WHERE `Id` = %u", id); - zmDbDo(sql.c_str()); + zmDbDo(sql); } void Monitor::actionDisable() { shared_data->action |= RELOAD; std::string sql = stringtf("UPDATE `Monitors` SET `Enabled` = 0 WHERE `Id` = %u", id); - zmDbDo(sql.c_str()); + zmDbDo(sql); } void Monitor::actionSuspend() { @@ -1452,7 +1452,7 @@ void Monitor::DumpZoneImage(const char *zone_string) { // Grab the most revent event image std::string sql = stringtf("SELECT MAX(`Id`) FROM `Events` WHERE `MonitorId`=%d AND `Frames` > 0", id); zmDbRow eventid_row; - if ( eventid_row.fetch(sql.c_str()) ) { + if (eventid_row.fetch(sql)) { uint64_t event_id = atoll(eventid_row[0]); Debug(3, "Got event %" PRIu64, event_id); @@ -2283,7 +2283,7 @@ void Monitor::Reload() { } std::string sql = load_monitor_sql + stringtf(" WHERE Id=%d", id); - zmDbRow *row = zmDbFetchOne(sql.c_str()); + zmDbRow *row = zmDbFetchOne(sql); if (!row) { Error("Can't run query: %s", mysql_error(&dbconn)); } else if (MYSQL_ROW dbrow = row->mysql_row()) { @@ -2369,7 +2369,7 @@ void Monitor::ReloadLinkedMonitors(const char *p_linked_monitors) { " AND `Enabled`=1", link_ids[i]); - MYSQL_RES *result = zmDbFetch(sql.c_str()); + MYSQL_RES *result = zmDbFetch(sql); if (!result) { continue; } @@ -2393,7 +2393,7 @@ std::vector> Monitor::LoadMonitors(const std::string &w std::string sql = load_monitor_sql + " WHERE " + where; Debug(1, "Loading Monitors with %s", sql.c_str()); - MYSQL_RES *result = zmDbFetch(sql.c_str()); + MYSQL_RES *result = zmDbFetch(sql); if (!result) { Error("Can't load local monitors: %s", mysql_error(&dbconn)); return {}; @@ -3139,7 +3139,7 @@ std::vector Monitor::Groups() { std::string sql = stringtf( "SELECT `Id`, `ParentId`, `Name` FROM `Groups` WHERE `Groups.Id` IN " "(SELECT `GroupId` FROM `Groups_Monitors` WHERE `MonitorId`=%d)", id); - MYSQL_RES *result = zmDbFetch(sql.c_str()); + MYSQL_RES *result = zmDbFetch(sql); if (!result) { Error("Can't load groups: %s", mysql_error(&dbconn)); return groups; diff --git a/src/zm_rtsp.cpp b/src/zm_rtsp.cpp index 4cd641fac..1daecf18b 100644 --- a/src/zm_rtsp.cpp +++ b/src/zm_rtsp.cpp @@ -89,7 +89,7 @@ int RtspThread::requestPorts() { //FIXME Why not load specifically by Id? This will get ineffeicient with a lot of monitors std::string sql = "SELECT `Id` FROM `Monitors` WHERE `Function` != 'None' AND `Type` = 'Remote' AND `Protocol` = 'rtsp' AND `Method` = 'rtpUni' ORDER BY `Id` ASC"; - MYSQL_RES *result = zmDbFetch(sql.c_str()); + MYSQL_RES *result = zmDbFetch(sql); int nMonitors = mysql_num_rows(result); int position = 0; diff --git a/src/zm_storage.cpp b/src/zm_storage.cpp index 79f3e8c0b..e53e79335 100644 --- a/src/zm_storage.cpp +++ b/src/zm_storage.cpp @@ -60,7 +60,7 @@ Storage::Storage(unsigned int p_id) : id(p_id) { std::string sql = stringtf("SELECT `Id`, `Name`, `Path`, `Type`, `Scheme` FROM `Storage` WHERE `Id`=%u", id); Debug(2, "Loading Storage for %u using %s", id, sql.c_str()); zmDbRow dbrow; - if (!dbrow.fetch(sql.c_str())) { + if (!dbrow.fetch(sql)) { Error("Unable to load storage area for id %d: %s", id, mysql_error(&dbconn)); } else { unsigned int index = 0; diff --git a/src/zm_user.cpp b/src/zm_user.cpp index 29bf7d327..44a22df38 100644 --- a/src/zm_user.cpp +++ b/src/zm_user.cpp @@ -93,7 +93,7 @@ User *zmLoadUser(const char *username, const char *password) { " FROM `Users` WHERE `Username` = '%s' AND `Enabled` = 1", escaped_username.c_str()); - MYSQL_RES *result = zmDbFetch(sql.c_str()); + MYSQL_RES *result = zmDbFetch(sql); if (!result) return nullptr; @@ -144,7 +144,7 @@ User *zmLoadTokenUser(const std::string &jwt_token_str, bool use_remote_addr) { " `Control`+0, `Monitors`+0, `System`+0, `MonitorIds`, `TokenMinExpiry`" " FROM `Users` WHERE `Username` = '%s' AND `Enabled` = 1", username.c_str()); - MYSQL_RES *result = zmDbFetch(sql.c_str()); + MYSQL_RES *result = zmDbFetch(sql); if (!result) return nullptr; @@ -187,7 +187,7 @@ User *zmLoadAuthUser(const char *auth, bool use_remote_addr) { " `Stream`+0, `Events`+0, `Control`+0, `Monitors`+0, `System`+0," " `MonitorIds` FROM `Users` WHERE `Enabled` = 1"; - MYSQL_RES *result = zmDbFetch(sql.c_str()); + MYSQL_RES *result = zmDbFetch(sql); if (!result) return nullptr; diff --git a/src/zm_zone.cpp b/src/zm_zone.cpp index dfda5d868..0807b7765 100644 --- a/src/zm_zone.cpp +++ b/src/zm_zone.cpp @@ -135,7 +135,7 @@ void Zone::RecordStats(const Event *event) { stats.alarm_box_.Hi().y_, stats.score_ ); - zmDbDo(sql.c_str()); + zmDbDo(sql); } // end void Zone::RecordStats( const Event *event ) bool Zone::CheckOverloadCount() { @@ -829,7 +829,7 @@ std::vector Zone::Load(Monitor *monitor) { "OverloadFrames,ExtendAlarmFrames" " FROM Zones WHERE MonitorId = %d ORDER BY Type, Id", monitor->Id()); - MYSQL_RES *result = zmDbFetch(sql.c_str()); + MYSQL_RES *result = zmDbFetch(sql); if (!result) { return {}; } diff --git a/src/zmc.cpp b/src/zmc.cpp index 3f9db1bd5..246729f6c 100644 --- a/src/zmc.cpp +++ b/src/zmc.cpp @@ -247,7 +247,7 @@ int main(int argc, char *argv[]) { "INSERT INTO Monitor_Status (MonitorId,Status,CaptureFPS,AnalysisFPS)" " VALUES (%u, 'Running',0,0) ON DUPLICATE KEY UPDATE Status='Running',CaptureFPS=0,AnalysisFPS=0", monitor->Id()); - zmDbDo(sql.c_str()); + zmDbDo(sql); Seconds sleep_time = Seconds(0); while (monitor->PrimeCapture() <= 0) { @@ -275,7 +275,7 @@ int main(int argc, char *argv[]) { sql = stringtf( "INSERT INTO Monitor_Status (MonitorId,Status) VALUES (%u, 'Connected') ON DUPLICATE KEY UPDATE Status='Connected'", monitor->Id()); - zmDbDo(sql.c_str()); + zmDbDo(sql); } // end foreach monitor if (zm_terminate){ @@ -362,7 +362,7 @@ int main(int argc, char *argv[]) { std::string sql = stringtf( "INSERT INTO Monitor_Status (MonitorId,Status) VALUES (%u, 'NotRunning') ON DUPLICATE KEY UPDATE Status='NotRunning'", monitor->Id()); - zmDbDo(sql.c_str()); + zmDbDo(sql); } Image::Deinitialise(); diff --git a/src/zmu.cpp b/src/zmu.cpp index e9ec379ac..5a6036891 100644 --- a/src/zmu.cpp +++ b/src/zmu.cpp @@ -736,7 +736,7 @@ int main(int argc, char *argv[]) { } sql += " ORDER BY Id ASC"; - MYSQL_RES *result = zmDbFetch(sql.c_str()); + MYSQL_RES *result = zmDbFetch(sql); if (!result) { exit_zmu(-1); }