mirror of
https://github.com/DanielnetoDotCom/YouPHPTube
synced 2025-10-03 09:49:28 +02:00
Updates
This commit is contained in:
parent
7f1d5e5a98
commit
5ce81cc9be
5 changed files with 146 additions and 85 deletions
|
@ -487,9 +487,14 @@ function execFFMPEGAsyncOrRemote($command, $keyword = null)
|
||||||
$obj = AVideoPlugin::getDataObjectIfEnabled('API');
|
$obj = AVideoPlugin::getDataObjectIfEnabled('API');
|
||||||
if(!empty($obj) && !empty($obj->standAloneFFMPEG)){
|
if(!empty($obj) && !empty($obj->standAloneFFMPEG)){
|
||||||
$url = "{$obj->standAloneFFMPEG}";
|
$url = "{$obj->standAloneFFMPEG}";
|
||||||
|
|
||||||
|
$codeToExec = array('ffmpegCommand'=>$command, 'keyword'=>$keyword, 'time'=>time());
|
||||||
|
|
||||||
|
$codeToExecEncrypted = encryptString(json_encode($codeToExec));
|
||||||
|
|
||||||
$url = addQueryStringParameter($url, 'APISecret', $obj->APISecret);
|
$url = addQueryStringParameter($url, 'APISecret', $obj->APISecret);
|
||||||
$url = addQueryStringParameter($url, 'ffmpegCommand', $command);
|
$url = addQueryStringParameter($url, 'codeToExecEncrypted', $codeToExecEncrypted);
|
||||||
$url = addQueryStringParameter($url, 'keyword', $keyword);
|
//var_dump($url);
|
||||||
_error_log("execFFMPEGAsyncOrRemote: URL $command");
|
_error_log("execFFMPEGAsyncOrRemote: URL $command");
|
||||||
_error_log("execFFMPEGAsyncOrRemote: URL $url");
|
_error_log("execFFMPEGAsyncOrRemote: URL $url");
|
||||||
return url_get_contents($url);
|
return url_get_contents($url);
|
||||||
|
|
|
@ -121,8 +121,11 @@ function getMySQLDate()
|
||||||
|
|
||||||
function _mysql_connect($persistent = false, $try = 0)
|
function _mysql_connect($persistent = false, $try = 0)
|
||||||
{
|
{
|
||||||
global $global, $mysqlHost, $mysqlUser, $mysqlPass, $mysqlDatabase, $mysqlPort, $mysql_connect_was_closed, $mysql_connect_is_persistent;
|
global $global, $mysqlHost, $mysqlUser, $mysqlPass, $mysqlDatabase, $mysqlPort, $mysql_connect_was_closed, $mysql_connect_is_persistent, $isStandAlone;
|
||||||
|
if(!empty($isStandAlone)){
|
||||||
|
_error_log('StandAlone Mode');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
$checkValues = ['mysqlHost', 'mysqlUser', 'mysqlPass', 'mysqlDatabase'];
|
$checkValues = ['mysqlHost', 'mysqlUser', 'mysqlPass', 'mysqlDatabase'];
|
||||||
|
|
||||||
foreach ($checkValues as $value) {
|
foreach ($checkValues as $value) {
|
||||||
|
|
|
@ -2907,12 +2907,12 @@ class API extends PluginAbstract
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param array $parameters return true if the secret is valid and false if it is not
|
* return true if the secret is valid and false if it is not
|
||||||
* 'APISecret' mandatory for security reasons - required
|
* 'APISecret' mandatory for security reasons - required
|
||||||
* @example {webSiteRootURL}plugin/API/{getOrSet}.json.php?APIName={APIName}&APISecret={APISecret}
|
* @example {webSiteRootURL}plugin/API/{getOrSet}.json.php?APIName={APIName}&APISecret={APISecret}
|
||||||
* @return \ApiObject Returns an ApiObject.
|
* @return \ApiObject Returns an ApiObject.
|
||||||
*/
|
*/
|
||||||
public function get_api_isAPISecretValid($parameters)
|
public function get_api_isAPISecretValid()
|
||||||
{
|
{
|
||||||
global $global;
|
global $global;
|
||||||
if (!self::isAPISecretValid()) {
|
if (!self::isAPISecretValid()) {
|
||||||
|
@ -2921,6 +2921,17 @@ class API extends PluginAbstract
|
||||||
return new ApiObject("APISecret is valid", false);
|
return new ApiObject("APISecret is valid", false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* decrypt a string
|
||||||
|
* 'string' mandatory
|
||||||
|
* @example {webSiteRootURL}plugin/API/{getOrSet}.json.php?APIName={APIName}&string=stringEncryptedToDecrypt
|
||||||
|
* @return \ApiObject Returns an ApiObject.
|
||||||
|
*/
|
||||||
|
public function get_api_decryptString()
|
||||||
|
{
|
||||||
|
return new ApiObject(decryptString($_REQUEST['string']), false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ApiObject
|
class ApiObject
|
||||||
|
|
|
@ -87,98 +87,140 @@
|
||||||
* Replace `https://yourSite.com/` with your actual website URL.
|
* Replace `https://yourSite.com/` with your actual website URL.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
$global_timeLimit = 300;
|
$global_timeLimit = 300;
|
||||||
|
|
||||||
ini_set("memory_limit", -1);
|
ini_set("memory_limit", -1);
|
||||||
ini_set('default_socket_timeout', $global_timeLimit);
|
ini_set('default_socket_timeout', $global_timeLimit);
|
||||||
set_time_limit($global_timeLimit);
|
set_time_limit($global_timeLimit);
|
||||||
ini_set('max_execution_time', $global_timeLimit);
|
ini_set('max_execution_time', $global_timeLimit);
|
||||||
ini_set("memory_limit", "-1");
|
ini_set("memory_limit", "-1");
|
||||||
|
|
||||||
header('Content-Type: application/json');
|
header('Content-Type: application/json');
|
||||||
|
|
||||||
require_once __DIR__ . "/../../../objects/functionsStandAlone.php";
|
require_once __DIR__ . "/../../../objects/functionsStandAlone.php";
|
||||||
|
|
||||||
if (empty($streamerURL)) {
|
if (empty($streamerURL)) {
|
||||||
echo json_encode(['error' => true, 'message' => 'streamerURL not defined']);
|
echo json_encode(['error' => true, 'message' => 'streamerURL not defined']);
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function to safely get inputs from either command line or request
|
function _decryptString($string)
|
||||||
function getInput($key, $default = '') {
|
{
|
||||||
|
global $global;
|
||||||
|
$url = "{$global['webSiteRootURL']}plugin/API/get.json.php?APIName=decryptString&string={$string}";
|
||||||
|
|
||||||
|
$content = file_get_contents($url);
|
||||||
|
$json = json_decode($content);
|
||||||
|
|
||||||
|
if (!empty($json) && empty($json->error)) {
|
||||||
|
$json2 = json_decode($json->message);
|
||||||
|
if ($json2->time > strtotime('30 seconds ago')) {
|
||||||
|
return $json2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//return $json2;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to safely get inputs from either command line or request
|
||||||
|
function getInput($key, $default = '') {
|
||||||
global $argv;
|
global $argv;
|
||||||
|
|
||||||
// Check if running from command line or HTTP request
|
// Check if running from command line or HTTP request
|
||||||
if (php_sapi_name() === 'cli') {
|
if (php_sapi_name() === 'cli') {
|
||||||
// Look for the parameter in $argv (command line)
|
|
||||||
foreach ($argv as $arg) {
|
foreach ($argv as $arg) {
|
||||||
if (strpos($arg, "{$key}=") === 0) {
|
if (strpos($arg, "{$key}=") === 0) {
|
||||||
return substr($arg, strlen("{$key}="));
|
return substr($arg, strlen("{$key}="));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Fallback to HTTP request ($_REQUEST)
|
|
||||||
return isset($_REQUEST[$key]) ? $_REQUEST[$key] : $default;
|
return isset($_REQUEST[$key]) ? $_REQUEST[$key] : $default;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $default;
|
return $default;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate and sanitize the ffmpegCommand
|
// Validate and sanitize the ffmpegCommand
|
||||||
function sanitizeFFmpegCommand($command) {
|
function sanitizeFFmpegCommand($command) {
|
||||||
// Allowable ffmpeg prefixes
|
|
||||||
$allowedPrefixes = ['ffmpeg', '/usr/bin/ffmpeg', '/bin/ffmpeg'];
|
$allowedPrefixes = ['ffmpeg', '/usr/bin/ffmpeg', '/bin/ffmpeg'];
|
||||||
|
|
||||||
// Remove dangerous characters
|
// Remove dangerous characters
|
||||||
$command = str_replace('&&', '', $command);
|
$command = str_replace('&&', '', $command);
|
||||||
$command = preg_replace('/[;|`<]/', '', $command);
|
|
||||||
|
|
||||||
// Ensure it starts with ffmpeg
|
// Remove existing log file redirection (e.g., '> /path/to/log 2>&1' or '> /path/to/log')
|
||||||
|
$command = preg_replace('/\s*>.*(?:2>&1)?/', '', $command);
|
||||||
|
$command = preg_replace('/[;|`<>]/', '', $command);
|
||||||
|
|
||||||
|
// Ensure it starts with an allowed prefix
|
||||||
foreach ($allowedPrefixes as $prefix) {
|
foreach ($allowedPrefixes as $prefix) {
|
||||||
if (strpos(trim($command), $prefix) === 0) {
|
if (strpos(trim($command), $prefix) === 0) {
|
||||||
return $command;
|
return $command;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If it doesn't start with an allowed prefix, return an empty string
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch and sanitize inputs
|
|
||||||
$ffmpegCommand = sanitizeFFmpegCommand(getInput('ffmpegCommand', ''));
|
|
||||||
$keyword = getInput('keyword', '');
|
|
||||||
|
|
||||||
// Kill processes associated with the keyword
|
// Fetch and sanitize inputs
|
||||||
if (!empty($keyword)) {
|
$codeToExecEncrypted = getInput('codeToExecEncrypted', '');
|
||||||
|
$codeToExec = _decryptString($codeToExecEncrypted);
|
||||||
|
|
||||||
|
if (empty($codeToExec)) {
|
||||||
|
die('Invalid Request');
|
||||||
|
}
|
||||||
|
|
||||||
|
$ffmpegCommand = sanitizeFFmpegCommand($codeToExec->ffmpegCommand);
|
||||||
|
$keyword = preg_replace('/[^a-zA-Z0-9_-]/', '', $codeToExec->keyword);
|
||||||
|
|
||||||
|
// Kill processes associated with the keyword
|
||||||
|
if (!empty($keyword)) {
|
||||||
killProcessFromKeyword($keyword);
|
killProcessFromKeyword($keyword);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate that ffmpegCommand is not empty after sanitization
|
// Validate that ffmpegCommand is not empty after sanitization
|
||||||
if (empty($ffmpegCommand)) {
|
if (empty($ffmpegCommand)) {
|
||||||
echo json_encode([
|
echo json_encode([
|
||||||
'error' => true,
|
'error' => true,
|
||||||
'msg' => 'Invalid or empty ffmpeg command',
|
'msg' => 'Invalid or empty ffmpeg command',
|
||||||
]);
|
]);
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debug output (optional)
|
// Get the system's temporary directory
|
||||||
error_log("Constructed FFMPEG Command: $ffmpegCommand");
|
$tempDir = sys_get_temp_dir();
|
||||||
|
|
||||||
try {
|
// Ensure the temp directory ends with a directory separator
|
||||||
|
$tempDir = rtrim($tempDir, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
|
||||||
|
|
||||||
|
// Create a unique log file path
|
||||||
|
$timestamp = date('YmdHis');
|
||||||
|
$logFile = "{$tempDir}ffmpeg_{$keyword}_{$timestamp}.log";
|
||||||
|
|
||||||
|
|
||||||
|
// Redirect all output to the log file
|
||||||
|
$ffmpegCommand .= " > {$logFile} 2>&1";
|
||||||
|
|
||||||
|
// Debug output (optional)
|
||||||
|
error_log("Constructed FFMPEG Command: $ffmpegCommand");
|
||||||
|
|
||||||
|
try {
|
||||||
$pid = execAsync($ffmpegCommand, $keyword);
|
$pid = execAsync($ffmpegCommand, $keyword);
|
||||||
echo json_encode([
|
echo json_encode([
|
||||||
'error' => false,
|
'error' => false,
|
||||||
'msg' => 'Command executed',
|
'msg' => 'Command executed',
|
||||||
'command' => $ffmpegCommand,
|
'command' => $ffmpegCommand,
|
||||||
'pid' => $pid,
|
'pid' => $pid,
|
||||||
|
'logFile' => $logFile,
|
||||||
]);
|
]);
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
echo json_encode([
|
echo json_encode([
|
||||||
'error' => true,
|
'error' => true,
|
||||||
'msg' => 'Failed to execute command',
|
'msg' => 'Failed to execute command',
|
||||||
'errorMsg' => $e->getMessage(),
|
'errorMsg' => $e->getMessage(),
|
||||||
|
'logFile' => $logFile,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
exit;
|
exit;
|
||||||
|
|
|
@ -636,7 +636,7 @@ function startRestream($m3u8, $restreamsDestinations, $logFile, $robj, $tries =
|
||||||
file_put_contents($logFile, $command . PHP_EOL);
|
file_put_contents($logFile, $command . PHP_EOL);
|
||||||
if (empty($isATest)) {
|
if (empty($isATest)) {
|
||||||
// use remote ffmpeg here
|
// use remote ffmpeg here
|
||||||
exec('nohup ' . $command . ' 2>> ' . $logFile . ' > /dev/null &');
|
execFFMPEGAsyncOrRemote($command . ' > ' . $logFile);
|
||||||
}
|
}
|
||||||
error_log("Restreamer.json.php startRestream finish");
|
error_log("Restreamer.json.php startRestream finish");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue