1
0
Fork 0
mirror of https://github.com/DanielnetoDotCom/YouPHPTube synced 2025-10-03 09:49:28 +02:00
This commit is contained in:
Daniel Neto 2024-12-03 11:30:16 -03:00
parent 7f1d5e5a98
commit 5ce81cc9be
5 changed files with 146 additions and 85 deletions

View file

@ -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);

View file

@ -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) {

View file

@ -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

View file

@ -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;

View file

@ -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");
} }