Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -388,9 +388,6 @@ message(STATUS "Excluding main.c from CORE_SOURCES (library build)")
file(GLOB DATABASE_SOURCES "src/database/*.c")
file(GLOB STORAGE_SOURCES "src/storage/*.c")
file(GLOB UTILS_SOURCES "src/utils/*.c")
# Exclude rebuild_recordings.c from UTILS_SOURCES to avoid multiple main functions
list(FILTER UTILS_SOURCES EXCLUDE REGEX ".*rebuild_recordings\\.c$")
message(STATUS "Excluding rebuild_recordings.c from main executable")
file(GLOB_RECURSE WEB_SOURCES "src/web/*.c")

# Filter web sources - exclude libuv sources (they're added separately via LIBUV_SERVER_SOURCES)
Expand All @@ -410,10 +407,10 @@ list(APPEND ROOT_SOURCES
# errors when linking test executables against lightnvr_lib.
list(FILTER ROOT_SOURCES EXCLUDE REGEX ".*sod/sod\\.c$")
list(FILTER ROOT_SOURCES EXCLUDE REGEX ".*core/main\\.c$")
list(FILTER ROOT_SOURCES EXCLUDE REGEX ".*utils/rebuild_recordings\\.c$")
list(FILTER ROOT_SOURCES EXCLUDE REGEX ".*tools/.*\\.c$")
# Also exclude libuv sources from ROOT_SOURCES (they're added separately)
list(FILTER ROOT_SOURCES EXCLUDE REGEX ".*libuv_.*\\.c$")
message(STATUS "Excluding main.c and rebuild_recordings.c from ROOT_SOURCES")
message(STATUS "Excluding main.c and tools from ROOT_SOURCES")

# Collect video sources from src/video, then exclude motion_detection_optimized.c,
# detection_thread_pool.c, and the original hls_writer_thread.c (since we're using our split version).
Expand Down Expand Up @@ -504,9 +501,10 @@ add_executable(lightnvr src/core/main.c)

# Define source files for rebuild_recordings utility (excluding inih)
set(REBUILD_RECORDINGS_SOURCES
src/utils/rebuild_recordings.c
src/tools/rebuild_recordings.c
src/core/config.c
src/core/logger.c
src/utils/strings.c
src/database/db_core.c
src/database/db_streams.c
src/database/db_recordings.c
Expand Down
14 changes: 7 additions & 7 deletions examples/onvif_motion_recording_example.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ void example_enable_motion_recording(void) {
};

// Set codec and quality
strncpy(config.codec, "h264", sizeof(config.codec) - 1);
strncpy(config.quality, "high", sizeof(config.quality) - 1);
safe_strcpy(config.codec, "h264", sizeof(config.codec), 0);
safe_strcpy(config.quality, "high", sizeof(config.quality), 0);

// Enable for a stream
const char *stream_name = "front_door";
Expand Down Expand Up @@ -115,7 +115,7 @@ void example_check_status(void) {
}

// Get current recording path
char path[512];
char path[MAX_PATH_LENGTH];
if (get_current_motion_recording_path(stream_name, path, sizeof(path)) == 0) {
printf("Current recording: %s\n", path);
} else {
Expand All @@ -140,8 +140,8 @@ void example_update_configuration(void) {
.retention_days = 60 // Increased to 60 days
};

strncpy(new_config.codec, "h265", sizeof(new_config.codec) - 1);
strncpy(new_config.quality, "medium", sizeof(new_config.quality) - 1);
safe_strcpy(new_config.codec, "h265", sizeof(new_config.codec), 0);
safe_strcpy(new_config.quality, "medium", sizeof(new_config.quality), 0);

int result = update_motion_recording_config(stream_name, &new_config);

Expand Down Expand Up @@ -199,8 +199,8 @@ void example_multiple_cameras(void) {
.retention_days = 30
};

strncpy(config.codec, "h264", sizeof(config.codec) - 1);
strncpy(config.quality, "high", sizeof(config.quality) - 1);
safe_strcpy(config.codec, "h264", sizeof(config.codec), 0);
safe_strcpy(config.quality, "high", sizeof(config.quality), 0);

int result = enable_motion_recording(cameras[i], &config);

Expand Down
2 changes: 1 addition & 1 deletion include/core/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ typedef struct {

// New recording format options
bool record_mp4_directly; // Record directly to MP4 alongside HLS
char mp4_storage_path[256]; // Path for MP4 recordings storage
char mp4_storage_path[MAX_PATH_LENGTH]; // Path for MP4 recordings storage
int mp4_segment_duration; // Duration of each MP4 segment in seconds
int mp4_retention_days; // Number of days to keep MP4 recordings

Expand Down
4 changes: 3 additions & 1 deletion include/database/db_recordings.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@
#include <stdbool.h>
#include <time.h>

#include "core/config.h"

// Recording metadata structure
typedef struct {
uint64_t id;
char stream_name[64];
char file_path[256];
char file_path[MAX_PATH_LENGTH];
time_t start_time;
time_t end_time;
uint64_t size_bytes;
Expand Down
4 changes: 3 additions & 1 deletion include/storage/storage_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@
#include <stdbool.h>
#include <time.h>

#include "core/config.h"

// Recording file information structure
typedef struct {
char path[256];
char path[MAX_PATH_LENGTH];
char stream_name[64];
time_t start_time;
time_t end_time;
Expand Down
28 changes: 0 additions & 28 deletions include/utils/memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,34 +40,6 @@ void *safe_calloc(size_t nmemb, size_t size);
*/
void safe_free(void *ptr);

/**
* Safe string duplication
*
* @param str String to duplicate
* @return Pointer to duplicated string or NULL on failure
*/
char *safe_strdup(const char *str);

/**
* Safe string copy with size checking
*
* @param dest Destination buffer
* @param src Source string
* @param size Size of destination buffer
* @return 0 on success, -1 on failure
*/
int safe_strcpy(char *dest, const char *src, size_t size);

/**
* Safe string concatenation with size checking
*
* @param dest Destination buffer
* @param src Source string
* @param size Size of destination buffer
* @return 0 on success, -1 on failure
*/
int safe_strcat(char *dest, const char *src, size_t size);

/**
* Secure memory clearing function that won't be optimized away
*
Expand Down
99 changes: 99 additions & 0 deletions include/utils/strings.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,40 @@
#ifndef STRINGS_H
#define STRINGS_H

#include <ctype.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>

/**
* Safe string duplication
*
* @param str String to duplicate
* @return Pointer to duplicated string or NULL on failure
*/
char *safe_strdup(const char *str);

/**
* Safe string copy with size checking. It is safe to pass an unterminated
* string in `src`: the string will not be checked beyond `src_size` bytes.
*
* @param dest Destination buffer
* @param src Source string
* @param dst_size Size of destination buffer
* @param src_size Size of source buffer if not null-terminated
* @return 0 on success (including if the string is truncated), -1 on failure
*/
int safe_strcpy(char *dest, const char *src, size_t dst_size, size_t src_size);

/**
* Safe string concatenation with size checking
*
* @param dest Destination buffer
* @param src Source string
* @param size Size of destination buffer
* @return 0 on success, -1 on failure
*/
int safe_strcat(char *dest, const char *src, size_t size);

/**
* Check if a string ends with a given suffix
Expand All @@ -14,4 +47,70 @@
*/
bool ends_with(const char *str, const char *suffix);

/**
* Returns a pointer to the first printable non-space character in the input string
* and terminates the string after the last printable non-space character.
*
* @param value The input string
* @return A pointer into the original string
*/
char *trim_ascii_whitespace(char *value);

/**
* Copies up to `output_size` bytes of the input string excluding any leading
* and trailing whitespace or non-printing characters into the output buffer.
* Guaranteed to null-terminate the output buffer.
*
* @param output The output buffer
* @param output_size The size of the output buffer
* @param input The input string
* @param input_size The maximum size of the input string to check, or zero to
* not limit the input string size
* @return The number of bytes copied, not counting the terminator
*/
size_t copy_trimmed_value(char *output, size_t output_size, const char *input, size_t input_size);

/**
* Returns a pointer to the first printable character in the input string.
*/
static inline const char *ltrim_pos(const char *input) {
if (!input) {
return NULL;
}

unsigned char *start = (unsigned char *)input;
while (*start && !isgraph(*start)) {
start++;
}
return (const char *)start;
}

/**
* Returns a pointer to the byte _after_ the last printable character
* in the input string. Set the returned pointer to '\0' to terminate
* the string after the last printable character.
*/
static inline const char *rtrim_pos(const char *input, size_t input_size) {
if (!input) {
return NULL;
}

const char *end;
if (input_size > 0) {
end = (input + strnlen(input, input_size) - 1);
} else {
// If input_size is zero, use the unbounded strlen
end = (input + strlen(input) - 1);
}
// `end` will now point to the last non-null character. If the input is
// empty, `end` will be (input-1), the character *before* the terminating
// null.
while (end > input && !isgraph((unsigned char)*end)) {
end--;
}
// Point to the character after the last printable character. If input was
// empty, this will now point to the terminating null.
return end + 1;
}

#endif //STRINGS_H
5 changes: 2 additions & 3 deletions include/video/onvif_soap.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,13 @@ char *onvif_create_security_header(const char *username, const char *password);
* can be parsed at the error level. If the XML cannot be parsed at all,
* logs the raw response (truncated) as a fallback.
*
* @param response The raw XML response body (will be modified by the
* XML parser — pass a copy if the original is needed).
* @param response The raw XML response body.
* @param response_len Length of the response in bytes.
* @param context A short description of the request that failed
* (e.g. "PullMessages", "CreatePullPointSubscription"),
* used to prefix the log message. May be NULL.
*/
void onvif_log_soap_fault(char *response, size_t response_len, const char *context);
void onvif_log_soap_fault(const char *response, size_t response_len, const char *context);

#endif /* ONVIF_SOAP_H */

2 changes: 1 addition & 1 deletion include/web/api_handlers_timeline.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
typedef struct {
uint64_t id;
char stream_name[64];
char file_path[256];
char file_path[MAX_PATH_LENGTH];
time_t start_time;
time_t end_time;
uint64_t size_bytes;
Expand Down
6 changes: 3 additions & 3 deletions include/web/http_server.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@ typedef struct {
char allowed_methods[256]; // CORS allowed methods
char allowed_headers[256]; // CORS allowed headers
bool ssl_enabled; // SSL/TLS enabled
char cert_path[256]; // SSL/TLS certificate path
char key_path[256]; // SSL/TLS key path
char cert_path[MAX_PATH_LENGTH]; // SSL/TLS certificate path
char key_path[MAX_PATH_LENGTH]; // SSL/TLS key path
int max_connections; // Maximum number of connections
int connection_timeout; // Connection timeout in seconds
bool daemon_mode; // Daemon mode
char pid_file[256]; // PID file path
char pid_file[MAX_PATH_LENGTH]; // PID file path
} http_server_config_t;

/**
Expand Down
2 changes: 1 addition & 1 deletion include/web/libuv_server.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ typedef struct libuv_connection {
// Thread pool offloading (uv_queue_work)
bool handler_on_worker; // Handler is running on a thread pool worker
bool deferred_file_serve; // File serving deferred until back on loop thread
char deferred_file_path[1024]; // Deferred file path to serve
char deferred_file_path[MAX_PATH_LENGTH]; // Deferred file path to serve
char deferred_content_type[128]; // Deferred content type (empty = auto-detect)
char deferred_extra_headers[512]; // Deferred extra headers (empty = none)
write_complete_action_t deferred_action; // Action to take after async response completes
Expand Down
2 changes: 1 addition & 1 deletion rtsp_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ void handle_signal(int sig) {
// Function to log FFmpeg errors
void log_error(int err, const char *message) {
char error_buf[AV_ERROR_MAX_STRING_SIZE] = {0};
av_strerror(ret, error_buf, AV_ERROR_MAX_STRING_SIZE);
av_strerror(err, error_buf, AV_ERROR_MAX_STRING_SIZE);
fprintf(stderr, "%s: %s\n", message, error_buf);
}

Expand Down
Loading
Loading