Skip to content

Commit

Permalink
Merge pull request #61 from lbr38/devel
Browse files Browse the repository at this point in the history
4.2.0
  • Loading branch information
lbr38 authored Jun 8, 2024
2 parents 8d2d27c + efc6e40 commit f3259d2
Show file tree
Hide file tree
Showing 23 changed files with 826 additions and 167 deletions.
8 changes: 8 additions & 0 deletions www/controllers/App/Config/Settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,14 @@ public static function get()
}
}

if (!defined('TIMELAPSE_RETENTION')) {
if (!empty($settings['Timelapse_retention'])) {
define('TIMELAPSE_RETENTION', $settings['Timelapse_retention']);
} else {
define('TIMELAPSE_RETENTION', '30');
}
}

if (!defined('MOTION_EVENTS_VIDEOS_THUMBNAIL')) {
if (!empty($settings['Motion_events_videos_thumbnail']) and $settings['Motion_events_videos_thumbnail'] == 'true') {
define('MOTION_EVENTS_VIDEOS_THUMBNAIL', true);
Expand Down
17 changes: 13 additions & 4 deletions www/controllers/Camera/Camera.php
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,10 @@ public function add(string $name, string $url, string $streamUrl, string $output
/**
* Only allow certain caracters in URL
*/
if (!\Controllers\Common::isAlphanumDash($url, array('&', '=', ':', '/', '.', '?', '&', '='))) {
if (!\Controllers\Common::isAlphanumDash($url, array('&', '=', ':', '/', '.', '?', '&', '=', '@'))) {
throw new Exception('URL contains invalid caracters');
}
if (!\Controllers\Common::isAlphanumDash($streamUrl, array('&', '=', ':', '/', '.', '?', '&', '='))) {
if (!\Controllers\Common::isAlphanumDash($streamUrl, array('&', '=', ':', '/', '.', '?', '&', '=', '@'))) {
throw new Exception('URL contains invalid caracters');
}

Expand Down Expand Up @@ -208,6 +208,15 @@ public function delete(string $id)
}
}

/**
* Delete camera data directory (timelapse images)
*/
if (is_dir(DATA_DIR . '/cameras/camera-' . $id)) {
if (!\Controllers\Filesystem\Directory::deleteRecursive(DATA_DIR . '/cameras/camera-' . $id)) {
throw new Exception('Could not delete camera data directory: ' . DATA_DIR . '/cameras/camera-' . $id);
}
}

/**
* Restart motion service if running
*/
Expand Down Expand Up @@ -240,10 +249,10 @@ public function editGlobalSettings(string $id, string $name, string $url, string
/**
* Only allow certain caracters in URL
*/
if (!\Controllers\Common::isAlphanumDash($url, array('=', ':', '/', '.', '?', '&', '='))) {
if (!\Controllers\Common::isAlphanumDash($url, array('=', ':', '/', '.', '?', '&', '=', '@'))) {
throw new Exception('URL contains invalid caracters');
}
if (!\Controllers\Common::isAlphanumDash($streamUrl, array('=', ':', '/', '.', '?', '&', '='))) {
if (!\Controllers\Common::isAlphanumDash($streamUrl, array('=', ':', '/', '.', '?', '&', '=', '@'))) {
throw new Exception('URL contains invalid caracters');
}

Expand Down
60 changes: 60 additions & 0 deletions www/controllers/Camera/Timelapse.php
Original file line number Diff line number Diff line change
Expand Up @@ -171,4 +171,64 @@ public function timelapse()
sleep(1);
}
}

/**
* Clean timelapse images older than specified date
*/
public function clean(int $retention = 30)
{
$date = date('Y-m-d', strtotime('-' . $retention . ' days'));

/**
* Get cameras
*/
$this->cameras = $this->cameraController->get();

/**
* For each camera, delete timelapse images older than specified date
*/
foreach ($this->cameras as $camera) {
$timelapseDir = DATA_DIR . '/cameras/camera-' . $camera['Id'] . '/timelapse';

/**
* Skip camera if no timelapse directory
*/
if (!file_exists($timelapseDir)) {
continue;
}

/**
* Get all timelapse directories
*/
$directories = glob($timelapseDir . '/*', GLOB_ONLYDIR);

/**
* For each directory, delete if it is older than specified date
*/
foreach ($directories as $directory) {
$directoryDate = basename($directory);

/**
* Skip directory if it is not a date
*/
if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $directoryDate)) {
continue;
}

/**
* Skip directory if it is not older than specified date
*/
if ($directoryDate >= $date) {
continue;
}

/**
* Delete directory
*/
if (!\Controllers\Filesystem\Directory::deleteRecursive($directory)) {
$this->logController->log('error', 'Camera timelapse cleanup', 'Failed to delete timelapse directory: ' . $directory);
}
}
}
}
}
48 changes: 0 additions & 48 deletions www/controllers/Common.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,54 +6,6 @@

class Common
{
/**
* Write to ini file
*/
public static function writeToIni(array $configuration, string $iniFile)
{
$res = array();

foreach ($configuration as $key => $val) {
if (is_array($val)) {
$res[] = "[$key]";
foreach ($val as $skey => $sval) {
$res[] = "$skey = ".(is_numeric($sval) ? $sval : '"'.$sval.'"');
}
} else {
$res[] = "$key = ".(is_numeric($val) ? $val : '"'.$val.'"');
}
}

Common::safeFileRewrite($iniFile, implode("\r\n", $res));
}

public static function safeFileRewrite($fileName, $dataToSave)
{
if ($fp = fopen($fileName, 'w')) {
$startTime = microtime(true);
do {
$canWrite = flock($fp, LOCK_EX);

/**
* If lock not obtained sleep for 0 - 100 milliseconds, to avoid collision and CPU load
*/
if (!$canWrite) {
usleep(round(rand(0, 100)*1000));
}
} while ((!$canWrite)and((microtime(true)-$startTime) < 5));

/**
* File was locked so now we can store information
*/
if ($canWrite) {
fwrite($fp, $dataToSave);
flock($fp, LOCK_UN);
}

fclose($fp);
}
}

/**
* Validate form data
*/
Expand Down
99 changes: 99 additions & 0 deletions www/controllers/Filesystem/Directory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
<?php

namespace Controllers\Filesystem;

use Exception;
use Datetime;

class Directory
{
/**
* Copy directory recursively to another location
*/
public static function copy(string $sourceDir, string $targetDir)
{
if (!is_dir($sourceDir)) {
throw new Exception('Recursive copy error: source directory does not exist: ' . $sourceDir);
}

if (!is_dir($targetDir)) {
if (!mkdir($targetDir, 0755, true)) {
throw new Exception('Recursive copy error: could not create destination directory: ' . $targetDir);
}
}

foreach ($iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($sourceDir, \RecursiveDirectoryIterator::SKIP_DOTS), \RecursiveIteratorIterator::SELF_FIRST) as $item) {
if ($item->isDir()) {
if (!mkdir($targetDir . DIRECTORY_SEPARATOR . $iterator->getSubPathname())) {
throw new Exception('Recursive copy error: could not create directory: ' . $targetDir . DIRECTORY_SEPARATOR . $iterator->getSubPathname());
}
} else {
if (!copy($item, $targetDir . DIRECTORY_SEPARATOR . $iterator->getSubPathname())) {
throw new Exception('Recursive copy error: could not copy file: ' . $targetDir . DIRECTORY_SEPARATOR . $iterator->getSubPathname());
}
}
}

unset($iterator);
}

/**
* Delete specified directory recursively
*/
public static function deleteRecursive(string $directoryPath)
{
/**
* Return true if there is nothing to delete
*/
if (!is_dir($directoryPath)) {
return true;
}

$myprocess = new \Controllers\Process('/usr/bin/rm -rf "' . $directoryPath . '"');
$myprocess->execute();
$myprocess->close();

if ($myprocess->getExitCode() != 0) {
return false;
}

return true;
}

/**
* Get directory size in bytes
*/
public static function getSize(string $path)
{
$bytestotal = 0;
$path = realpath($path);

if (!empty($path) and file_exists($path)) {
foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($path, \FilesystemIterator::SKIP_DOTS)) as $object) {
$bytestotal += $object->getSize();
}
}

return $bytestotal;
}

/**
* Return true if directory is empty
*/
public static function isEmpty($dir)
{
$handle = opendir($dir);

while (false !== ($entry = readdir($handle))) {
if ($entry != "." && $entry != "..") {
closedir($handle);

return false;
}
}

closedir($handle);

return true;
}
}
Loading

0 comments on commit f3259d2

Please sign in to comment.