diff --git a/install/markAllLivesAsFinished.php b/install/markAllLivesAsFinished.php new file mode 100644 index 000000000..b6cabd80f --- /dev/null +++ b/install/markAllLivesAsFinished.php @@ -0,0 +1,14 @@ + 0 && $upload_max < $max_size) { $max_size = $upload_max; } } return $max_size; } function parse_size($size) { $unit = preg_replace('/[^bkmgtpezy]/i', '', $size); // Remove the non-unit characters from the size. $size = preg_replace('/[^0-9\.]/', '', $size); // Remove the non-numeric characters from the size. if ($unit) { // Find the position of the unit in the ordered string which is the power of magnitude to multiply a kilobyte by. return round($size * pow(1024, stripos('bkmgtpezy', $unit[0]))); } else { return round($size); } } function humanFileSize($size, $unit = "") { if ((!$unit && $size >= 1 << 30) || $unit == "GB") { return number_format($size / (1 << 30), 2) . "GB"; } if ((!$unit && $size >= 1 << 20) || $unit == "MB") { return number_format($size / (1 << 20), 2) . "MB"; } if ((!$unit && $size >= 1 << 10) || $unit == "KB") { return number_format($size / (1 << 10), 2) . "KB"; } return number_format($size) . " bytes"; } function get_max_file_size() { return humanFileSize(file_upload_max_size()); } function humanTiming($time, $precision = 0, $useDatabaseTime = true) { $time = secondsIntervalFromNow($time, $useDatabaseTime); return secondsToHumanTiming($time, $precision); } /** * * @param type $time * @param type $precision * @param type $useDatabaseTime good if you are checking the created time * @return type */ function humanTimingAgo($time, $precision = 0, $useDatabaseTime = true) { $time = secondsIntervalFromNow($time, $useDatabaseTime); if (empty($time)) { return __("Now"); } return secondsToHumanTiming($time, $precision) . " " . __("ago"); } function humanTimingAfterwards($time, $precision = 0, $useDatabaseTime = true) { if (!is_numeric($time)) { $time = strtotime($time); } $time = secondsIntervalFromNow($time, $useDatabaseTime); if (empty($time)) { return __("Now"); } else if ($time > 0) { return secondsToHumanTiming($time, $precision) . ' ' . __('Ago'); } return __('Coming in') . ' ' . secondsToHumanTiming($time, $precision); } function secondsToHumanTiming($time, $precision = 0) { if (empty($time)) { return __("Now"); } $time = ($time < 0) ? $time * -1 : $time; $time = ($time < 1) ? 1 : $time; $tokens = array( 31536000 => 'year', 2592000 => 'month', 604800 => 'week', 86400 => 'day', 3600 => 'hour', 60 => 'minute', 1 => 'second', ); /** * For detection propouse only */ __('year'); __('month'); __('week'); __('day'); __('hour'); __('minute'); __('second'); __('years'); __('months'); __('weeks'); __('days'); __('hours'); __('minutes'); __('seconds'); foreach ($tokens as $unit => $text) { if ($time < $unit) { continue; } $numberOfUnits = floor($time / $unit); if ($numberOfUnits > 1) { $text = __($text . "s"); } else { $text = __($text); } if ($precision) { $rest = $time % $unit; if ($rest) { $text .= ' ' . secondsToHumanTiming($rest, $precision - 1); } } return $numberOfUnits . ' ' . $text; } } function checkVideosDir() { $dir = "../videos"; if (file_exists($dir)) { return is_writable($dir); } return mkdir($dir); } function isApache() { return (strpos($_SERVER['SERVER_SOFTWARE'], 'Apache') !== false); } function isPHP($version = "'7.0.0'") { return (version_compare(PHP_VERSION, $version) >= 0); } function modEnabled($mod_name) { if (!function_exists('apache_get_modules')) { ob_start(); phpinfo(INFO_MODULES); $contents = ob_get_contents(); ob_end_clean(); return (strpos($contents, 'mod_' . $mod_name) !== false); } return in_array('mod_' . $mod_name, apache_get_modules()); } function modRewriteEnabled() { return modEnabled("rewrite"); } function modAliasEnabled() { return modEnabled("alias"); } function isFFMPEG() { return trim(shell_exec('which ffmpeg')); } function isUnzip() { return trim(shell_exec('which unzip')); } function isExifToo() { return trim(shell_exec('which exiftool')); } function getPathToApplication() { return str_replace("install/index.php", "", $_SERVER["SCRIPT_FILENAME"]); } function getURLToApplication() { $url = (isset($_SERVER['HTTPS']) ? "https" : "http") . "://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]"; $url = explode("install/index.php", $url); return $url[0]; } //max_execution_time = 7200 function check_max_execution_time() { $max_size = ini_get('max_execution_time'); $recomended_size = 7200; return ($recomended_size <= $max_size); } //post_max_size = 100M function check_post_max_size() { $max_size = parse_size(ini_get('post_max_size')); $recomended_size = parse_size('100M'); return ($recomended_size <= $max_size); } //upload_max_filesize = 100M function check_upload_max_filesize() { $max_size = parse_size(ini_get('upload_max_filesize')); $recomended_size = parse_size('100M'); return ($recomended_size <= $max_size); } //memory_limit = 100M function check_memory_limit() { $max_size = parse_size(ini_get('memory_limit')); $recomended_size = parse_size('512M'); return ($recomended_size <= $max_size); } function check_mysqlnd() { return function_exists('mysqli_fetch_all'); } function base64DataToImage($imgBase64) { $img = $imgBase64; $img = str_replace('data:image/png;base64,', '', $img); $img = str_replace(' ', '+', $img); return base64_decode($img); } function getRealIpAddr() { if (!empty($_SERVER['HTTP_CLIENT_IP'])) { //check ip from share internet $ip = $_SERVER['HTTP_CLIENT_IP']; } elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) { //to check ip is pass from proxy $ip = $_SERVER['HTTP_X_FORWARDED_FOR']; } elseif (!empty($_SERVER['REMOTE_ADDR'])) { $ip = $_SERVER['REMOTE_ADDR']; } else { $ip = "127.0.0.1"; } return $ip; } function cleanString($text) { $utf8 = array( '/[áàâãªä]/u' => 'a', '/[ÁÀÂÃÄ]/u' => 'A', '/[ÍÌÎÏ]/u' => 'I', '/[íìîï]/u' => 'i', '/[éèêë]/u' => 'e', '/[ÉÈÊË]/u' => 'E', '/[óòôõºö]/u' => 'o', '/[ÓÒÔÕÖ]/u' => 'O', '/[úùûü]/u' => 'u', '/[ÚÙÛÜ]/u' => 'U', '/ç/' => 'c', '/Ç/' => 'C', '/ñ/' => 'n', '/Ñ/' => 'N', '/–/' => '-', // UTF-8 hyphen to 'normal' hyphen '/[’‘‹›‚]/u' => ' ', // Literally a single quote '/[“”«»„]/u' => ' ', // Double quote '/ /' => ' ', // nonbreaking space (equiv. to 0x160) '/Є/' => 'YE', '/І/' => 'I', '/Ѓ/' => 'G', '/і/' => 'i', '/№/' => '#', '/є/' => 'ye', '/ѓ/' => 'g', '/А/' => 'A', '/Б/' => 'B', '/В/' => 'V', '/Г/' => 'G', '/Д/' => 'D', '/Е/' => 'E', '/Ё/' => 'YO', '/Ж/' => 'ZH', '/З/' => 'Z', '/И/' => 'I', '/Й/' => 'J', '/К/' => 'K', '/Л/' => 'L', '/М/' => 'M', '/Н/' => 'N', '/О/' => 'O', '/П/' => 'P', '/Р/' => 'R', '/С/' => 'S', '/Т/' => 'T', '/У/' => 'U', '/Ф/' => 'F', '/Х/' => 'H', '/Ц/' => 'C', '/Ч/' => 'CH', '/Ш/' => 'SH', '/Щ/' => 'SHH', '/Ъ/' => '', '/Ы/' => 'Y', '/Ь/' => '', '/Э/' => 'E', '/Ю/' => 'YU', '/Я/' => 'YA', '/а/' => 'a', '/б/' => 'b', '/в/' => 'v', '/г/' => 'g', '/д/' => 'd', '/е/' => 'e', '/ё/' => 'yo', '/ж/' => 'zh', '/з/' => 'z', '/и/' => 'i', '/й/' => 'j', '/к/' => 'k', '/л/' => 'l', '/м/' => 'm', '/н/' => 'n', '/о/' => 'o', '/п/' => 'p', '/р/' => 'r', '/с/' => 's', '/т/' => 't', '/у/' => 'u', '/ф/' => 'f', '/х/' => 'h', '/ц/' => 'c', '/ч/' => 'ch', '/ш/' => 'sh', '/щ/' => 'shh', '/ъ/' => '', '/ы/' => 'y', '/ь/' => '', '/э/' => 'e', '/ю/' => 'yu', '/я/' => 'ya', '/—/' => '-', '/«/' => '', '/»/' => '', '/…/' => '' ); return preg_replace(array_keys($utf8), array_values($utf8), $text); } function cleanURLName($name) { $name = preg_replace('/[!#$&\'()*+,\\/:;=?@[\\]%" ]+/', '-', trim(strtolower(cleanString($name)))); return trim(preg_replace('/[\x00-\x1F\x7F]/u', '', $name), "-"); } /** * @brief return true if running in CLI, false otherwise * if is set $_GET['ignoreCommandLineInterface'] will return false * @return boolean */ function isCommandLineInterface() { return (empty($_GET['ignoreCommandLineInterface']) && php_sapi_name() === 'cli'); } /** * @brief show status message as text (CLI) or JSON-encoded array (web) * * @param array $statusarray associative array with type/message pairs * @return string */ function status($statusarray) { if (isCommandLineInterface()) { foreach ($statusarray as $status => $message) { echo $status . ":" . $message . "\n"; } } else { echo json_encode(array_map(function ($text) { return nl2br($text); }, $statusarray)); } } /** * @brief show status message and die * * @param array $statusarray associative array with type/message pairs */ function croak($statusarray) { status($statusarray); die; } function getSecondsTotalVideosLength() { $configFile = dirname(__FILE__) . '/../videos/configuration.php'; require_once $configFile; global $global; if (!User::isLogged()) { return 0; } $sql = "SELECT * FROM videos v "; $formats = ""; $values = array(); if (!User::isAdmin()) { $id = User::getId(); $sql .= " WHERE users_id = ? "; $formats = "i"; $values = array($id); } $res = sqlDAL::readSql($sql, $formats, $values); $fullData = sqlDAL::fetchAllAssoc($res); sqlDAL::close($res); $seconds = 0; foreach ($fullData as $row) { $seconds += parseDurationToSeconds($row['duration']); } return $seconds; } function getMinutesTotalVideosLength() { $seconds = getSecondsTotalVideosLength(); return floor($seconds / 60); } function secondsToVideoTime($seconds) { if (!is_numeric($seconds)) { return $seconds; } $seconds = round($seconds); $hours = floor($seconds / 3600); $mins = floor($seconds / 60 % 60); $secs = floor($seconds % 60); return sprintf('%02d:%02d:%02d', $hours, $mins, $secs); } function parseSecondsToDuration($seconds) { return secondsToVideoTime($seconds); } function parseDurationToSeconds($str) { if (is_numeric($str)) { return intval($str); } $durationParts = explode(":", $str); if (empty($durationParts[1]) || $durationParts[0] == "EE") { return 0; } if (empty($durationParts[2])) { $durationParts[2] = 0; } $minutes = intval(($durationParts[0]) * 60) + intval($durationParts[1]); return intval($durationParts[2]) + ($minutes * 60); } function durationToSeconds($str) { return parseDurationToSeconds($str); } function secondsToDuration($seconds) { return parseSecondsToDuration($seconds); } /** * * @global type $global * @param type $mail * call it before send mail to let AVideo decide the method */ function setSiteSendMessage(&$mail) { global $global; if (empty($_POST["comment"])) { $_POST["comment"] = ""; } require_once $global['systemRootPath'] . 'objects/configuration.php'; $config = new Configuration(); $mail->CharSet = 'UTF-8'; if ($config->getSmtp()) { _error_log("Sending SMTP Email"); $mail->CharSet = 'UTF-8'; $mail->IsSMTP(); // enable SMTP if (!empty($_POST) && $_POST["comment"] == "Teste of comment" && User::isAdmin()) { $mail->SMTPDebug = 3; $mail->Debugoutput = function ($str, $level) { _error_log("SMTP ERROR $level; message: $str", AVideoLog::$ERROR); }; } $mail->SMTPOptions = array( 'ssl' => array( 'verify_peer' => false, 'verify_peer_name' => false, 'allow_self_signed' => true ) ); $mail->SMTPAuth = $config->getSmtpAuth(); // authentication enabled $mail->SMTPSecure = $config->getSmtpSecure(); // secure transfer enabled REQUIRED for Gmail $mail->Host = $config->getSmtpHost(); $mail->Port = $config->getSmtpPort(); $mail->Username = $config->getSmtpUsername(); $mail->Password = $config->getSmtpPassword(); //_error_log(print_r($config, true)); } else { _error_log("Sending SendMail Email"); $mail->isSendmail(); } } function array_iunique($array) { return array_intersect_key($array, array_unique(array_map("strtolower", $array))); } function partition(array $list, $totalItens) { $listlen = count($list); _error_log("partition: listlen={$listlen} totalItens={$totalItens}"); $p = ceil($listlen / $totalItens); $partlen = floor($listlen / $p); $partition = array(); $mark = 0; for ($index = 0; $index < $p; $index++) { $partition[$index] = array_slice($list, $mark, $totalItens); $mark += $totalItens; } return $partition; } function sendSiteEmail($to, $subject, $message) { global $advancedCustom; if (empty($to)) { return false; } if (!is_array($to)) { $to = array($to); } if (empty($advancedCustom)) { $advancedCustom = AVideoPlugin::loadPlugin("CustomizeAdvanced"); } $subject = UTF8encode($subject); $message = UTF8encode($message); $message = createEmailMessageFromTemplate($message); _error_log("sendSiteEmail [" . count($to) . "] {$subject}"); global $config, $global; //require_once $global['systemRootPath'] . 'objects/include_phpmailer.php'; $contactEmail = $config->getContactEmail(); $webSiteTitle = $config->getWebSiteTitle(); try { if (!is_array($to)) { $mail = new \PHPMailer\PHPMailer\PHPMailer; setSiteSendMessage($mail); $mail->setFrom($contactEmail, $webSiteTitle); $mail->Subject = $subject . " - " . $webSiteTitle; $mail->msgHTML($message); $mail->addAddress($to); $resp = $mail->send(); if (!$resp) { _error_log("sendSiteEmail Error Info: {$mail->ErrorInfo}"); } else { _error_log("sendSiteEmail Success Info: $subject " . json_encode($to)); } } else { $size = intval(@$advancedCustom->splitBulkEmailSend); if (empty($size)) { $size = 90; } $to = array_iunique($to); $pieces = partition($to, $size); foreach ($pieces as $piece) { $mail = new \PHPMailer\PHPMailer\PHPMailer; setSiteSendMessage($mail); $mail->setFrom($contactEmail, $webSiteTitle); $mail->Subject = $subject . " - " . $webSiteTitle; $mail->msgHTML($message); $count = 0; foreach ($piece as $value) { $count++; _error_log("sendSiteEmail::addBCC [{$count}] {$value}"); $mail->addBCC($value); } $resp = $mail->send(); if (!$resp) { _error_log("sendSiteEmail Error Info: {$mail->ErrorInfo}"); } else { _error_log("sendSiteEmail Success Info: $subject " . json_encode($to)); } } } //Set the subject line return $resp; } catch (phpmailerException $e) { _error_log($e->errorMessage()); //Pretty error messages from PHPMailer } catch (Exception $e) { _error_log($e->getMessage()); //Boring error messages from anything else! } } function sendSiteEmailAsync($to, $subject, $message) { global $global; $content = array('to' => $to, 'subject' => $subject, 'message' => $message); $tmpFile = getTmpFile(); file_put_contents($tmpFile, _json_encode($content)); //outputAndContinueInBackground(); $command = "php {$global['systemRootPath']}objects/sendSiteEmailAsync.php '$tmpFile'"; _error_log("sendSiteEmailAsync start ($command)"); $pid = execAsync($command); _error_log("sendSiteEmailAsync end {$pid}"); return $pid; } function createEmailMessageFromTemplate($message) { //check if the message already have a HTML body if (preg_match("/html>/i", $message)) { return $message; } global $global, $config; $text = file_get_contents("{$global['systemRootPath']}view/include/emailTemplate.html"); $siteTitle = $config->getWebSiteTitle(); $logo = "getLogo(true) . "\" alt=\"{$siteTitle}\">"; $words = array($logo, $message, $siteTitle); $replace = array('{logo}', '{message}', '{siteTitle}'); return str_replace($replace, $words, $text); } function sendEmailToSiteOwner($subject, $message) { global $advancedCustom; $subject = UTF8encode($subject); $message = UTF8encode($message); _error_log("sendEmailToSiteOwner {$subject}"); global $config, $global; require_once $global['systemRootPath'] . 'objects/include_phpmailer.php'; $contactEmail = $config->getContactEmail(); $webSiteTitle = $config->getWebSiteTitle(); try { $mail = new \PHPMailer\PHPMailer\PHPMailer; setSiteSendMessage($mail); $mail->setFrom($contactEmail, $webSiteTitle); $mail->Subject = $subject . " - " . $webSiteTitle; $mail->msgHTML($message); $mail->addAddress($contactEmail); $resp = $mail->send(); if (!$resp) { _error_log("sendEmailToSiteOwner Error Info: {$mail->ErrorInfo}"); } else { _error_log("sendEmailToSiteOwner Success Info: $subject " . json_encode($to)); } return $resp; } catch (phpmailerException $e) { _error_log($e->errorMessage()); //Pretty error messages from PHPMailer } catch (Exception $e) { _error_log($e->getMessage()); //Boring error messages from anything else! } } function parseVideos($videoString = null, $autoplay = 0, $loop = 0, $mute = 0, $showinfo = 0, $controls = 1, $time = 0, $objectFit = "") { global $global; //_error_log("parseVideos: $videoString"); if (strpos($videoString, 'youtube.com/embed') !== false) { return $videoString . (parse_url($videoString, PHP_URL_QUERY) ? '&' : '?') . 'modestbranding=1&showinfo=' . $showinfo . "&autoplay={$autoplay}&controls=$controls&loop=$loop&mute=$mute&t=$time&objectFit=$objectFit"; } if (strpos($videoString, 'iframe') !== false) { // retrieve the video url $anchorRegex = '/src="(.*)?"/isU'; $results = array(); if (preg_match($anchorRegex, $video, $results)) { $link = trim($results[1]); } } else { // we already have a url $link = $videoString; } if (stripos($link, 'embed') !== false) { return $link . (parse_url($link, PHP_URL_QUERY) ? '&' : '?') . 'modestbranding=1&showinfo=' . $showinfo . "&autoplay={$autoplay}&controls=$controls&loop=$loop&mute=$mute&t=$time&objectFit=$objectFit"; } elseif (strpos($link, 'youtube.com') !== false) { preg_match( '/[\\?\\&]v=([^\\?\\&]+)/', $link, $matches ); //the ID of the YouTube URL: x6qe_kVaBpg if (empty($matches[1])) { return $link; } $id = $matches[1]; return '//www.youtube.com/embed/' . $id . '?modestbranding=1&showinfo=' . $showinfo . "&autoplay={$autoplay}&controls=$controls&loop=$loop&mute=$mute&te=$time&objectFit=$objectFit"; } elseif (strpos($link, 'youtu.be') !== false) { //https://youtu.be/9XXOBSsPoMU preg_match( '/youtu.be\/([a-zA-Z0-9_]+)($|\/)/', $link, $matches ); //the ID of the YouTube URL: x6qe_kVaBpg $id = $matches[1]; return '//www.youtube.com/embed/' . $id . '?modestbranding=1&showinfo=' . $showinfo . "&autoplay={$autoplay}&controls=$controls&loop=$loop&mute=$mute&te=$time&objectFit=$objectFit"; } elseif (strpos($link, 'player.vimeo.com') !== false) { // works on: // http://player.vimeo.com/video/37985580?title=0&byline=0&portrait=0 $videoIdRegex = '/player.vimeo.com\/video\/([0-9]+)\??/i'; preg_match($videoIdRegex, $link, $matches); $id = $matches[1]; return '//player.vimeo.com/video/' . $id; } elseif (strpos($link, 'vimeo.com/channels') !== false) { //extract the ID preg_match( '/\/\/(www\.)?vimeo.com\/channels\/[a-z0-9-]+\/(\d+)($|\/)/i', $link, $matches ); //the ID of the Vimeo URL: 71673549 $id = $matches[2]; return '//player.vimeo.com/video/' . $id; } elseif (strpos($link, 'vimeo.com') !== false) { //extract the ID preg_match( '/\/\/(www\.)?vimeo.com\/(\d+)($|\/)/', $link, $matches ); //the ID of the Vimeo URL: 71673549 $id = $matches[2]; return '//player.vimeo.com/video/' . $id; } elseif (strpos($link, 'dailymotion.com') !== false) { //extract the ID preg_match( '/\/\/(www\.)?dailymotion.com\/video\/([a-zA-Z0-9_]+)($|\/)/', $link, $matches ); //the ID of the Vimeo URL: 71673549 $id = $matches[2]; return '//www.dailymotion.com/embed/video/' . $id; } elseif (strpos($link, 'metacafe.com') !== false) { //extract the ID preg_match( '/\/\/(www\.)?metacafe.com\/watch\/([a-zA-Z0-9_\/-]+)$/', $link, $matches ); $id = $matches[2]; return '//www.metacafe.com/embed/' . $id; } elseif (strpos($link, 'vid.me') !== false) { //extract the ID preg_match( '/\/\/(www\.)?vid.me\/([a-zA-Z0-9_-]+)$/', $link, $matches ); $id = $matches[2]; return '//vid.me/e/' . $id; } elseif (strpos($link, 'rutube.ru') !== false) { //extract the ID preg_match('/\/\/(www\.)?rutube.ru\/video\/([a-zA-Z0-9_-]+)\/.*/', $link, $matches); $id = $matches[2]; return '//rutube.ru/play/embed/' . $id; } elseif (strpos($link, 'ok.ru') !== false) { //extract the ID preg_match('/\/\/(www\.)?ok.ru\/video\/([a-zA-Z0-9_-]+)$/', $link, $matches); $id = $matches[2]; return '//ok.ru/videoembed/' . $id; } elseif (strpos($link, 'streamable.com') !== false) { //extract the ID preg_match('/\/\/(www\.)?streamable.com\/([a-zA-Z0-9_-]+)$/', $link, $matches); $id = $matches[2]; return '//streamable.com/s/' . $id; } elseif (strpos($link, 'twitch.tv/videos') !== false) { //extract the ID preg_match('/\/\/(www\.)?twitch.tv\/videos\/([a-zA-Z0-9_-]+)$/', $link, $matches); if (!empty($matches[2])) { $id = $matches[2]; return '//player.twitch.tv/?video=' . $id . '&parent=' . parse_url($global['webSiteRootURL'], PHP_URL_HOST); } //extract the ID preg_match('/\/\/(www\.)?twitch.tv\/[a-zA-Z0-9_-]+\/v\/([a-zA-Z0-9_-]+)$/', $link, $matches); $id = $matches[2]; return '//player.twitch.tv/?video=' . $id . '&parent=' . parse_url($global['webSiteRootURL'], PHP_URL_HOST); } elseif (strpos($link, 'twitch.tv') !== false) { //extract the ID preg_match('/\/\/(www\.)?twitch.tv\/([a-zA-Z0-9_-]+)$/', $link, $matches); $id = $matches[2]; return '//player.twitch.tv/?channel=' . $id . '&parent=' . parse_url($global['webSiteRootURL'], PHP_URL_HOST); } elseif (strpos($link, 'bitchute.com/video') !== false) { //extract the ID preg_match('/\/\/(www\.)?bitchute.com\/video\/([^\/]+)/', $link, $matches); $id = $matches[2]; return 'https://www.bitchute.com/embed/' . $id . '/?parent=' . parse_url($global['webSiteRootURL'], PHP_URL_HOST); } elseif (strpos($link, '/evideo/') !== false) { //extract the ID preg_match('/(http.+)\/evideo\/([a-zA-Z0-9_-]+)($|\/)/i', $link, $matches); //the AVideo site $site = $matches[1]; $id = $matches[2]; return $site . '/evideoEmbed/' . $id . "?autoplay={$autoplay}&controls=$controls&loop=$loop&mute=$mute&t=$time"; } elseif (strpos($link, '/video/') !== false) { //extract the ID preg_match('/(http.+)\/video\/([a-zA-Z0-9_-]+)($|\/)/i', $link, $matches); //the AVideo site if (!empty($matches[1])) { $site = $matches[1]; $id = $matches[2]; return $site . '/videoEmbeded/' . $id . "?autoplay={$autoplay}&controls=$controls&loop=$loop&mute=$mute&t=$time"; } else { return $link; } } $url = $videoString; $url_parsed = parse_url($url); if (empty($url_parsed['query'])) { return ""; } $new_qs_parsed = array(); // Grab our first query string parse_str($url_parsed['query'], $new_qs_parsed); // Here's the other query string $other_query_string = 'modestbranding=1&showinfo=' . $showinfo . "&autoplay={$autoplay}&controls=$controls&loop=$loop&mute=$mute&t=$time"; $other_qs_parsed = array(); parse_str($other_query_string, $other_qs_parsed); // Stitch the two query strings together $final_query_string_array = array_merge($new_qs_parsed, $other_qs_parsed); $final_query_string = http_build_query($final_query_string_array); // Now, our final URL: if (empty($url_parsed['scheme'])) { $scheme = ''; } else { $scheme = "{$url_parsed['scheme']}:"; } $new_url = $scheme . '//' . $url_parsed['host'] . $url_parsed['path'] . '?' . $final_query_string; return $new_url; // return data } $canUseCDN = array(); function canUseCDN($videos_id) { if (empty($videos_id)) { return false; } global $global, $canUseCDN; if (!isset($canUseCDN[$videos_id])) { require_once $global['systemRootPath'] . 'plugin/VR360/Objects/VideosVR360.php'; $pvr360 = AVideoPlugin::isEnabledByName('VR360'); // if the VR360 is enabled you can not use the CDN, it fail to load the GL $isVR360Enabled = VideosVR360::isVR360Enabled($videos_id); if ($pvr360 && $isVR360Enabled) { $ret = false; } else { $ret = true; } //_error_log(json_encode(array('canUseCDN'=>$ret, '$pvr360'=>$pvr360, '$isVR360Enabled'=>$isVR360Enabled, '$videos_id'=>$videos_id))); $canUseCDN[$videos_id] = $ret; } return $canUseCDN[$videos_id]; } function clearVideosURL($fileName = "") { global $global; $path = getCacheDir() . "getVideosURL/"; if (empty($path)) { rrmdir($path); } else { $cacheFilename = "{$path}{$fileName}.cache"; @unlink($cacheFilename); } } function maxLifetime() { global $maxLifetime; if (!isset($maxLifetime)) { $aws_s3 = AVideoPlugin::getObjectDataIfEnabled('AWS_S3'); $bb_b2 = AVideoPlugin::getObjectDataIfEnabled('Blackblaze_B2'); $secure = AVideoPlugin::getObjectDataIfEnabled('SecureVideosDirectory'); $maxLifetime = 0; if (!empty($aws_s3) && empty($aws_s3->makeMyFilesPublicRead) && !empty($aws_s3->presignedRequestSecondsTimeout) && (empty($maxLifetime) || $aws_s3->presignedRequestSecondsTimeout < $maxLifetime)) { $maxLifetime = $aws_s3->presignedRequestSecondsTimeout; //_error_log("maxLifetime: AWS_S3 = {$maxLifetime}"); } if (!empty($bb_b2) && empty($bb_b2->usePublicBucket) && !empty($bb_b2->presignedRequestSecondsTimeout) && (empty($maxLifetime) || $bb_b2->presignedRequestSecondsTimeout < $maxLifetime)) { $maxLifetime = $bb_b2->presignedRequestSecondsTimeout; //_error_log("maxLifetime: B2 = {$maxLifetime}"); } if (!empty($secure) && !empty($secure->tokenTimeOut) && (empty($maxLifetime) || $secure->tokenTimeOut < $maxLifetime)) { $maxLifetime = $secure->tokenTimeOut; //_error_log("maxLifetime: Secure = {$maxLifetime}"); } } return $maxLifetime; } $cacheExpirationTime = false; function cacheExpirationTime() { if (isBot()) { return 604800; // 1 week } global $cacheExpirationTime; if (empty($cacheExpirationTime)) { $obj = AVideoPlugin::getObjectDataIfEnabled('Cache'); $cacheExpirationTime = @$obj->cacheTimeInSeconds; } return intval($cacheExpirationTime); } /** * tell if a file should recreate a cache, based on its time and the plugins toke expirations * @param type $filename * @return boolean */ function recreateCache($filename) { return (!file_exists($filename) || time() - filemtime($filename) > minimumExpirationTime()); } function _getImagesURL($fileName, $type) { global $global; $files = array(); $source = Video::getSourceFile($fileName, ".jpg"); $file1 = $source['path']; if (file_exists($file1)) { $files["jpg"] = array( 'filename' => "{$fileName}.jpg", 'path' => $file1, 'url' => $source['url'], 'type' => 'image', ); } else { unset($file1); $files["jpg"] = array( 'filename' => "{$type}.png", 'path' => getCDN() . "view/img/{$type}.png", 'url' => getCDN() . "view/img/{$type}.png", 'type' => 'image', ); } $source = Video::getSourceFile($fileName, "_portrait.jpg"); $file2 = $source['path']; if (file_exists($file2)) { $files["pjpg"] = array( 'filename' => "{$fileName}_portrait.jpg", 'path' => $file2, 'url' => $source['url'], 'type' => 'image', ); } elseif ($type != 'image') { if (!empty($file1)) { $files["pjpg"] = $files["jpg"]; } else { $files["pjpg"] = array( 'filename' => "{$type}_portrait.png", 'path' => getCDN() . "view/img/{$type}_portrait.png", 'url' => getCDN() . "view/img/{$type}_portrait.png", 'type' => 'image', ); } } return $files; } function getVideosURLPDF($fileName) { global $global; if (empty($fileName)) { return array(); } $time = microtime(); $time = explode(' ', $time); $time = $time[1] + $time[0]; $start = $time; $source = Video::getSourceFile($fileName, ".pdf"); $file = $source['path']; $files["pdf"] = array( 'filename' => "{$fileName}.pdf", 'path' => $file, 'url' => $source['url'], 'type' => 'pdf', ); $files = array_merge($files, _getImagesURL($fileName, 'pdf')); $time = microtime(); $time = explode(' ', $time); $time = $time[1] + $time[0]; $finish = $time; $total_time = round(($finish - $start), 4); //_error_log("getVideosURLPDF generated in {$total_time} seconds. fileName: $fileName "); return $files; } function getVideosURLIMAGE($fileName) { global $global; if (empty($fileName)) { return array(); } $time = microtime(); $time = explode(' ', $time); $time = $time[1] + $time[0]; $start = $time; $types = array('png', 'gif', 'webp', 'jpg'); foreach ($types as $value) { $source = Video::getSourceFile($fileName, ".{$value}"); $file = $source['path']; $files["image"] = array( 'filename' => "{$fileName}.{$value}", 'path' => $file, 'url' => $source['url'], 'type' => 'image', ); if (file_exists($file)) { break; } } $files = array_merge($files, _getImagesURL($fileName, 'image')); $time = microtime(); $time = explode(' ', $time); $time = $time[1] + $time[0]; $finish = $time; $total_time = round(($finish - $start), 4); //_error_log("getVideosURLPDF generated in {$total_time} seconds. fileName: $fileName "); return $files; } function getVideosURLZIP($fileName) { global $global; if (empty($fileName)) { return array(); } $time = microtime(); $time = explode(' ', $time); $time = $time[1] + $time[0]; $start = $time; $types = array('zip'); foreach ($types as $value) { $source = Video::getSourceFile($fileName, ".{$value}"); $file = $source['path']; $files["zip"] = array( 'filename' => "{$fileName}.zip", 'path' => $file, 'url' => $source['url'], 'type' => 'zip', ); if (file_exists($file)) { break; } } $files = array_merge($files, _getImagesURL($fileName, 'zip')); $time = microtime(); $time = explode(' ', $time); $time = $time[1] + $time[0]; $finish = $time; $total_time = round(($finish - $start), 4); //_error_log("getVideosURLPDF generated in {$total_time} seconds. fileName: $fileName "); return $files; } function getVideosURLArticle($fileName) { global $global; if (empty($fileName)) { return array(); } $time = microtime(); $time = explode(' ', $time); $time = $time[1] + $time[0]; $start = $time; //$files = array_merge($files, _getImagesURL($fileName, 'article')); $files = _getImagesURL($fileName, 'article'); $time = microtime(); $time = explode(' ', $time); $time = $time[1] + $time[0]; $finish = $time; $total_time = round(($finish - $start), 4); //_error_log("getVideosURLPDF generated in {$total_time} seconds. fileName: $fileName "); return $files; } function getVideosURLAudio($fileName, $fileNameisThePath = false) { global $global; if (empty($fileName)) { return array(); } $time = microtime(); $time = explode(' ', $time); $time = $time[1] + $time[0]; $start = $time; if ($fileNameisThePath) { $filename = basename($fileName); $files["mp3"] = array( 'filename' => $filename, 'path' => Video::getPathToFile($filename), 'url' => Video::getURLToFile($filename), 'type' => 'audio', ); } else { $source = Video::getSourceFile($fileName, ".mp3"); $file = $source['path']; $files["mp3"] = array( 'filename' => "{$fileName}.mp3", 'path' => $file, 'url' => $source['url'], 'type' => 'audio', ); } $files = array_merge($files, _getImagesURL($fileName, 'audio_wave')); $time = microtime(); $time = explode(' ', $time); $time = $time[1] + $time[0]; $finish = $time; $total_time = round(($finish - $start), 4); //_error_log("getVideosURLAudio generated in {$total_time} seconds. fileName: $fileName "); return $files; } function getVideosURL($fileName, $cache = true) { return getVideosURL_V2($fileName); // disable this function soon } function getVideosURLMP4Only($fileName) { $allFiles = getVideosURL_V2($fileName); if (is_array($allFiles)) { foreach ($allFiles as $key => $value) { if ($value['format'] !== 'mp4') { unset($allFiles[$key]); } } return $allFiles; } _error_log("getVideosURLMP4Only does not return an ARRAY from getVideosURL_V2($fileName) " . json_encode($allFiles)); return array(); } function getVideosURLWEBMOnly($fileName) { $allFiles = getVideosURL_V2($fileName); // disable this function soon if (is_array($allFiles)) { foreach ($allFiles as $key => $value) { if ($value['format'] !== 'webm') { unset($allFiles[$key]); } } return $allFiles; } _error_log("getVideosURLMP4Only does not return an ARRAY from getVideosURL_V2($fileName) " . json_encode($allFiles)); return array(); } function getVideosURLMP4WEBMOnly($fileName) { return array_merge(getVideosURLMP4Only($fileName), getVideosURLWEBMOnly($fileName)); } function getVideosURLOnly($fileName) { $allFiles = getVideosURL_V2($fileName); // disable this function soon foreach ($allFiles as $key => $value) { if ($value['type'] !== 'video') { unset($allFiles[$key]); } } return $allFiles; } function getAudioURLOnly($fileName) { $allFiles = getVideosURL_V2($fileName); // disable this function soon foreach ($allFiles as $key => $value) { if ($value['type'] !== 'audio') { unset($allFiles[$key]); } } return $allFiles; } function getAudioOrVideoURLOnly($fileName) { $allFiles = getVideosURL_V2($fileName); // disable this function soon foreach ($allFiles as $key => $value) { if ($value['type'] !== 'video' && $value['type'] !== 'audio') { unset($allFiles[$key]); } } return $allFiles; } function getVideosDir() { return Video::getStoragePath(); } $getVideosURL_V2Array = array(); function getVideosURL_V2($fileName, $recreateCache = false) { global $global, $getVideosURL_V2Array; if (empty($fileName)) { return array(); } //$recreateCache = true; $cleanfilename = Video::getCleanFilenameFromFile($fileName); if (!empty($getVideosURL_V2Array[$cleanfilename])) { return $getVideosURL_V2Array[$cleanfilename]; } $paths = Video::getPaths($cleanfilename); $pdf = $paths['path'] . "{$cleanfilename}.pdf"; $mp3 = $paths['path'] . "{$cleanfilename}.mp3"; if (file_exists($pdf)) { return getVideosURLPDF($fileName); } elseif (file_exists($mp3)) { return getVideosURLAudio($mp3, true); } $cacheName = "getVideosURL_V2$fileName"; if (empty($recreateCache)) { $lifetime = maxLifetime(); $TimeLog1 = "getVideosURL_V2($fileName) empty recreateCache"; TimeLogStart($TimeLog1); $files = object_to_array(ObjectYPT::getCache($cacheName, $lifetime, true)); if (is_array($files)) { //_error_log("getVideosURL_V2: do NOT recreate lifetime = {$lifetime}"); $preg_match_url = addcslashes(getCDN(), "/") . "videos"; foreach ($files as $value) { // check if is a dummy file and the URL still wrong $pathFilesize = filesize($value['path']); if ( $value['type'] === 'video' && // is a video preg_match("/^{$preg_match_url}/", $value['url']) && // the URL is the same as the main domain $pathFilesize < 20) { // file size is small _error_log("getVideosURL_V2:: dummy file found, fix cache " . json_encode(array("/^{$preg_match_url}/", $value['url'], preg_match("/^{$preg_match_url}video/", $value['url']), $pathFilesize, $value))); unset($files); $video = Video::getVideoFromFileName($fileName, true, true); Video::clearCache($video['id']); break; } else { //_error_log("getVideosURL_V2:: NOT dummy file ". json_encode(array("/^{$preg_match_url}video/", $value['url'], preg_match("/^{$preg_match_url}video/", $value['url']),filesize($value['path']),$value))); } } //_error_log("getVideosURL_V2:: cachestill good ". json_encode($files)); } else { //_error_log("getVideosURL_V2:: cache not found ". json_encode($files)); } TimeLogEnd($TimeLog1, __LINE__); } else { _error_log("getVideosURL_V2($fileName) Recreate cache requested " . json_encode(debug_backtrace())); } if (empty($files)) { $files = array(); $plugin = AVideoPlugin::loadPlugin("VideoHLS"); if (!empty($plugin)) { $timeName = "getVideosURL_V2::VideoHLS::getSourceFile($fileName)"; TimeLogStart($timeName); $files = VideoHLS::getSourceFile($fileName, true); TimeLogEnd($timeName, __LINE__); } $video = array('webm', 'mp4'); $audio = array('mp3', 'ogg'); $image = array('jpg', 'gif', 'webp'); $formats = array_merge($video, $audio, $image); //$globQuery = getVideosDir()."{$cleanfilename}*.{" . implode(",", $formats) . "}"; //$filesInDir = glob($globQuery, GLOB_BRACE); $timeName = "getVideosURL_V2::globVideosDir($cleanfilename)"; TimeLogStart($timeName); $filesInDir = globVideosDir($cleanfilename, true); TimeLogEnd($timeName, __LINE__); $timeName = "getVideosURL_V2::foreach"; TimeLogStart($timeName); foreach ($filesInDir as $file) { $parts = pathinfo($file); if ($parts['filename'] == 'index') { $parts['filename'] = str_replace(Video::getPathToFile($parts['dirname']), '', $parts['dirname']); } //$timeName2 = "getVideosURL_V2::Video::getSourceFile({$parts['filename']}, .{$parts['extension']})"; //TimeLogStart($timeName2); $source = Video::getSourceFile($parts['filename'], ".{$parts['extension']}"); //TimeLogEnd($timeName2, __LINE__); if (empty($source)) { continue; } if (in_array($parts['extension'], $image) && filesize($file) < 1000 && !preg_match("/Dummy File/i", file_get_contents($file))) { continue; } if (preg_match("/{$cleanfilename}(_.+)[.]{$parts['extension']}$/", $file, $matches)) { $resolution = $matches[1]; } else { preg_match('/_([^_]{0,4}).' . $parts['extension'] . '$/', $file, $matches); $resolution = @$matches[1]; } $type = 'video'; if (in_array($parts['extension'], $video)) { $type = 'video'; } elseif (in_array($parts['extension'], $audio)) { $type = 'audio'; } elseif (in_array($parts['extension'], $image) || preg_match('/^(gif|jpg|webp|png|jpeg)/i', $parts['extension'])) { $type = 'image'; if (!preg_match('/(thumb|roku)/', $resolution)) { $resolution = ''; } } $files["{$parts['extension']}{$resolution}"] = array( 'filename' => "{$parts['filename']}.{$parts['extension']}", 'path' => $file, 'url' => $source['url'], 'url_noCDN' => @$source['url_noCDN'], 'type' => $type, 'format' => strtolower($parts['extension']), ); } TimeLogEnd($timeName, __LINE__); ObjectYPT::setCache($cacheName, $files); } if (is_array($files)) { // sort by resolution uasort($files, "sortVideosURL"); } //var_dump($files);exit; $getVideosURL_V2Array[$cleanfilename] = $files; return $getVideosURL_V2Array[$cleanfilename]; } //Returns < 0 if str1 is less than str2; > 0 if str1 is greater than str2, and 0 if they are equal. function sortVideosURL($a, $b) { if ($a['type'] == 'video') { $aRes = getResolutionFromFilename($a['filename']); $bRes = getResolutionFromFilename($b['filename']); return $aRes - $bRes; } return 0; } function getResolutionFromFilename($filename) { global $getResolutionFromFilenameArray; if (!isset($getResolutionFromFilenameArray)) { $getResolutionFromFilenameArray = array(); } if (!empty($getResolutionFromFilenameArray[$filename])) { return $getResolutionFromFilenameArray[$filename]; } $res = Video::getResolutionFromFilename($filename); if (empty($res)) { if (preg_match('/[_\/]hd[.\/]/i', $filename)) { $res = 720; } else if (preg_match('/[_\/]sd[.\/]/i', $filename)) { $res = 480; } else if (preg_match('/[_\/]low[.\/]/i', $filename)) { $res = 240; } else { $res = 0; } } $getResolutionFromFilenameArray[$filename] = $res; return $res; } function getSources($fileName, $returnArray = false, $try = 0) { if ($returnArray) { $videoSources = $audioTracks = $subtitleTracks = array(); } else { $videoSources = $audioTracks = $subtitleTracks = ""; } $video = Video::getVideoFromFileNameLight($fileName); if ($video['type'] !== 'audio' && function_exists('getVRSSources')) { $videoSources = getVRSSources($fileName, $returnArray); } else { //$files = getVideosURL($fileName); $files = getVideosURL_V2($fileName, !empty($try)); $sources = ""; $sourcesArray = array(); foreach ($files as $key => $value) { $path_parts = pathinfo($value['path']); if ($path_parts['extension'] == "webm" || $path_parts['extension'] == "mp4" || $path_parts['extension'] == "m3u8" || $path_parts['extension'] == "mp3" || $path_parts['extension'] == "ogg") { $obj = new stdClass(); $obj->type = mime_content_type_per_filename($value['path']); $sources .= "type}\">"; $obj->src = $value['url']; $sourcesArray[] = $obj; } } $videoSources = $returnArray ? $sourcesArray : $sources; } if (function_exists('getVTTTracks')) { $subtitleTracks = getVTTTracks($fileName, $returnArray); } if ($returnArray) { $return = array_merge($videoSources, $audioTracks, $subtitleTracks); } else { $return = $videoSources . $audioTracks . $subtitleTracks; } $obj = new stdClass(); $obj->result = $return; if (empty($videoSources) && empty($audioTracks) && !empty($video['id']) && $video['type'] == 'video') { if (empty($try)) { //sleep(1); $sources = getSources($fileName, $returnArray, $try + 1); if (!empty($sources)) { Video::updateFilesize($video['id']); } Video::clearCache($video['id']); return $sources; } else { _error_log("getSources($fileName) File not found " . json_encode($video)); $obj = new stdClass(); $obj->type = "video/mp4"; $obj->src = "Video not found"; $obj->label = "Video not found"; $obj->res = 0; $sourcesArray["mp4"] = $obj; $sources["mp4"] = "type}\" label=\"{$obj->label}\" res=\"{$obj->res}\">"; $return = $returnArray ? $sourcesArray : implode(PHP_EOL, $sources); } } return $return; } /** * * @param type $file_src * @return typeget image size with cache */ function getimgsize($file_src) { global $_getimagesize; if (empty($_getimagesize)) { $_getimagesize = array(); } $name = "getimgsize_" . md5($file_src); if (!empty($_getimagesize[$name])) { $size = $_getimagesize[$name]; } else { $cached = ObjectYPT::getCache($name, 86400); //one day if (!empty($cached)) { $c = (Array) $cached; $size = array(); foreach ($c as $key => $value) { if (preg_match("/^[0-9]+$/", $key)) { $key = intval($key); } $size[$key] = $value; } $_getimagesize[$name] = $size; return $size; } $size = @getimagesize($file_src); if (empty($size)) { $size = array(1024, 768); } ObjectYPT::setCache($name, $size); $_getimagesize[$name] = $size; } return $size; } function im_resize($file_src, $file_dest, $wd, $hd, $q = 80) { if (empty($file_dest)) { return false; } if (!file_exists($file_src)) { _error_log("im_resize: Source not found: {$file_src}"); return false; } $size = getimgsize($file_src); if ($size === false) { _error_log("im_resize: Could not get image size: {$file_src}"); return false; } if (empty($size['mime']) || $size['mime'] == 'image/pjpeg') { $size['mime'] = 'image/jpeg'; } $format = strtolower(substr($size['mime'], strpos($size['mime'], '/') + 1)); if (empty($format)) { $format = 'jpeg'; } $destformat = strtolower(substr($file_dest, -4)); if (empty($destformat)) { _error_log("destformat not found {$file_dest}"); $destformat = ".jpg"; } $icfunc = "imagecreatefrom" . $format; if (!function_exists($icfunc)) { _error_log("im_resize: Function does not exists: {$icfunc}"); return false; } $imgSize = getimagesize($file_src); if (empty($imgSize)) { _error_log("im_resize: getimagesize($file_src) return false " . json_encode($imgSize)); return false; } try { $src = $icfunc($file_src); } catch (Exception $exc) { _error_log("im_resize: " . $exc->getMessage()); _error_log("im_resize: Try {$icfunc} from string"); $src = imagecreatefromstring(file_get_contents($file_src)); if (!$src) { _error_log("im_resize: fail {$icfunc} from string"); return false; } } $ws = imagesx($src); $hs = imagesy($src); if ($ws <= $hs) { $hd = ceil(($wd * $hs) / $ws); } else { $wd = ceil(($hd * $ws) / $hs); } if ($ws <= $wd) { $wd = $ws; $hd = $hs; } $wc = ($wd * $hs) / $hd; if ($wc <= $ws) { $hc = ($wc * $hd) / $wd; } else { $hc = ($ws * $hd) / $wd; $wc = ($wd * $hc) / $hd; } $dest = imagecreatetruecolor($wd, $hd); switch ($format) { case "png": imagealphablending($dest, false); imagesavealpha($dest, true); $transparent = imagecolorallocatealpha($dest, 255, 255, 255, 127); imagefilledrectangle($dest, 0, 0, $wd, $hd, $transparent); break; case "gif": // integer representation of the color black (rgb: 0,0,0) $background = imagecolorallocate($src, 0, 0, 0); // removing the black from the placeholder imagecolortransparent($src, $background); break; } imagecopyresampled($dest, $src, 0, 0, ($ws - $wc) / 2, ($hs - $hc) / 2, $wd, $hd, $wc, $hc); $saved = false; if ($destformat == '.png') { $saved = imagepng($dest, $file_dest); } if ($destformat == '.jpg') { $saved = imagejpeg($dest, $file_dest, $q); } if (!$saved) { _error_log('saving failed'); } imagedestroy($dest); imagedestroy($src); @chmod($file_dest, 0666); return true; } function im_resizeV2($file_src, $file_dest, $wd, $hd, $q = 80) { _error_log("im_resizeV2: $file_src, $file_dest, $wd, $hd, $q"); $newImage = im_resize($file_src, $file_dest, $wd, $hd, 100); if (!$newImage) { return false; } $src = imagecreatefromjpeg($file_dest); $ws = imagesx($src); $hs = imagesy($src); if ($ws < $wd) { $dst_x = ($wd - $ws) / 2; } else { $dst_x = 0; } if ($hs < $hd) { $dst_y = ($hd - $hs) / 2; } else { $dst_y = 0; } $mapImage = imagecreatetruecolor($wd, $hd); $bgColor = imagecolorallocate($mapImage, 0, 0, 0); imagefill($mapImage, 0, 0, $bgColor); $tileImg = imagecreatefromjpeg($file_dest); imagecopy($mapImage, $tileImg, $dst_x, $dst_y, 0, 0, $ws, $hs); $saved = imagejpeg($mapImage, $file_dest, $q); return $saved; } function im_resizePNG($file_src, $file_dest, $wd, $hd) { $srcImage = imagecreatefrompng($file_src); $ws = imagesx($srcImage); $hs = imagesy($srcImage); $targetImage = imagecreatetruecolor($wd, $hd); imagealphablending($targetImage, false); imagesavealpha($targetImage, true); imagecopyresampled($targetImage, $srcImage, 0, 0, 0, 0, $wd, $hd, $ws, $hs); $saved = imagepng($targetImage, $file_dest); return $saved; } function im_resizeV3($file_src, $file_dest, $wd, $hd) { _error_log("im_resizeV3: $file_src, $file_dest, $wd, $hd"); // This tries to preserve the aspect ratio of the thumb while letterboxing it in // The same way that the encoder now does. eval('$ffmpeg ="ffmpeg -i {$file_src} -filter_complex \"scale=(iw*sar)*min({$wd}/(iw*sar)\,{$hd}/ih):ih*min({$wd}/(iw*sar)\,{$hd}/ih), pad={$wd}:{$hd}:({$wd}-iw*min({$wd}/iw\,{$hd}/ih))/2:({$hd}-ih*min({$wd}/iw\,{$hd}/ih))/2\" -sws_flags lanczos -qscale:v 2 {$file_dest}";'); exec($ffmpeg . " < /dev/null 2>&1", $output, $return_val); } function im_resize_gif($file_src, $file_dest, $max_width, $max_height) { if (class_exists('Imagick')) { $imagick = new Imagick($file_src); $format = $imagick->getImageFormat(); if ($format == 'GIF') { $imagick = $imagick->coalesceImages(); do { $imagick->resizeImage($max_width, $max_height, Imagick::FILTER_BOX, 1); } while ($imagick->nextImage()); $imagick = $imagick->deconstructImages(); $imagick->writeImages($file_dest, true); } $imagick->clear(); $imagick->destroy(); } else { copy($file_src, $file_dest); } } function im_resize_max_size($file_src, $file_dest, $max_width, $max_height) { $fn = $file_src; $extension = strtolower(pathinfo($file_dest, PATHINFO_EXTENSION)); if ($extension == 'gif') { im_resize_gif($file_src, $file_dest, $max_width, $max_height); @unlink($file_src); return true; } $tmpFile = getTmpFile() . ".{$extension}"; if (empty($fn)) { _error_log("im_resize_max_size: file name is empty, Destination: {$file_dest}", AVideoLog::$ERROR); return false; } if (function_exists("exif_read_data")) { error_log($fn); convertImage($fn, $tmpFile, 100); $exif = exif_read_data($tmpFile); if ($exif && isset($exif['Orientation'])) { $orientation = $exif['Orientation']; if ($orientation != 1) { $img = imagecreatefromjpeg($tmpFile); $deg = 0; switch ($orientation) { case 3: $deg = 180; break; case 6: $deg = 270; break; case 8: $deg = 90; break; } if ($deg) { $img = imagerotate($img, $deg, 0); } imagejpeg($img, $fn, 100); } } } else { _error_log("Make sure you install the php_mbstring and php_exif to be able to rotate images"); } $size = getimagesize($fn); $ratio = $size[0] / $size[1]; // width/height if ($size[0] <= $max_width && $size[1] <= $max_height) { $width = $size[0]; $height = $size[1]; } elseif ($ratio > 1) { $width = $max_width; $height = $max_height / $ratio; } else { $width = $max_width * $ratio; $height = $max_height; } $src = imagecreatefromstring(file_get_contents($fn)); $dst = imagecreatetruecolor($width, $height); imagecopyresampled($dst, $src, 0, 0, 0, 0, $width, $height, $size[0], $size[1]); imagedestroy($src); imagejpeg($dst, $file_dest); // adjust format as needed imagedestroy($dst); @unlink($file_src); @unlink($tmpFile); } function convertImage($originalImage, $outputImage, $quality) { $imagetype = 0; if (function_exists('exif_imagetype')) { $imagetype = exif_imagetype($originalImage); } $ext = strtolower(pathinfo($originalImage, PATHINFO_EXTENSION)); $extOutput = strtolower(pathinfo($outputImage, PATHINFO_EXTENSION)); if ($ext == $extOutput) { return copy($originalImage, $outputImage); } try { if ($imagetype == IMAGETYPE_JPEG || preg_match('/jpg|jpeg/i', $ext)) { $imageTmp = @imagecreatefromjpeg($originalImage); } elseif ($imagetype == IMAGETYPE_PNG || preg_match('/png/i', $ext)) { $imageTmp = imagecreatefrompng($originalImage); } elseif ($imagetype == IMAGETYPE_GIF || preg_match('/gif/i', $ext)) { $imageTmp = imagecreatefromgif($originalImage); } elseif ($imagetype == IMAGETYPE_BMP || preg_match('/bmp/i', $ext)) { $imageTmp = imagecreatefrombmp($originalImage); } elseif ($imagetype == IMAGETYPE_WEBP || preg_match('/webp/i', $ext)) { $imageTmp = imagecreatefromwebp($originalImage); } else { _error_log("convertImage: File Extension not found ($originalImage, $outputImage, $quality) " . exif_imagetype($originalImage)); return 0; } } catch (Exception $exc) { _error_log("convertImage: " . $exc->getMessage()); return 0; } if (!is_resource($imageTmp)) { _error_log("convertImage: could not create a resource $originalImage, $outputImage, $quality"); return 0; } // quality is a value from 0 (worst) to 100 (best) $response = 0; if ($extOutput === 'jpg') { if (function_exists('imagejpeg')) { $response = imagejpeg($imageTmp, $outputImage, $quality); } else { _error_log("convertImage ERROR: function imagejpeg does not exists"); } } else if ($extOutput === 'png') { if (function_exists('imagepng')) { $response = imagepng($imageTmp, $outputImage, $quality / 10); } else { _error_log("convertImage ERROR: function imagepng does not exists"); } } else if ($extOutput === 'webp') { if (function_exists('imagewebp')) { $response = imagewebp($imageTmp, $outputImage, $quality); } else { _error_log("convertImage ERROR: function imagewebp does not exists"); } } else if ($extOutput === 'gif') { if (function_exists('imagegif')) { $response = imagegif($imageTmp, $outputImage); } else { _error_log("convertImage ERROR: function imagegif does not exists"); } } imagedestroy($imageTmp); return $response; } function decideMoveUploadedToVideos($tmp_name, $filename, $type = "video") { if ($filename == '.zip') { return false; } global $global; $obj = new stdClass(); $aws_s3 = AVideoPlugin::loadPluginIfEnabled('AWS_S3'); $bb_b2 = AVideoPlugin::loadPluginIfEnabled('Blackblaze_B2'); $ftp = AVideoPlugin::loadPluginIfEnabled('FTP_Storage'); $paths = Video::getPaths($filename, true); $destinationFile = "{$paths['path']}{$filename}"; //$destinationFile = getVideosDir() . "{$filename}"; _error_log("decideMoveUploadedToVideos: {$filename}"); $path_info = pathinfo($filename); if ($type !== "zip" && $path_info['extension'] === 'zip') { _error_log("decideMoveUploadedToVideos: ZIp file {$filename}"); $paths = Video::getPaths($path_info['filename']); $dir = $paths['path']; unzipDirectory($tmp_name, $dir); // unzip it cleanDirectory($dir); if (!empty($aws_s3)) { //$aws_s3->move_uploaded_file($tmp_name, $filename); } elseif (!empty($bb_b2)) { $bb_b2->move_uploaded_directory($dir); } elseif (!empty($ftp)) { //$ftp->move_uploaded_file($tmp_name, $filename); } } else { _error_log("decideMoveUploadedToVideos: NOT ZIp file {$filename}"); if (!empty($aws_s3)) { _error_log("decideMoveUploadedToVideos: S3 {$filename}"); $aws_s3->move_uploaded_file($tmp_name, $filename); } elseif (!empty($bb_b2)) { _error_log("decideMoveUploadedToVideos: B2 {$filename}"); $bb_b2->move_uploaded_file($tmp_name, $filename); } elseif (!empty($ftp)) { _error_log("decideMoveUploadedToVideos: FTP {$filename}"); $ftp->move_uploaded_file($tmp_name, $filename); } else { _error_log("decideMoveUploadedToVideos: Local {$filename}"); if (!move_uploaded_file($tmp_name, $destinationFile)) { if (!rename($tmp_name, $destinationFile)) { if (!copy($tmp_name, $destinationFile)) { $obj->msg = "Error on decideMoveUploadedToVideos({$tmp_name}, $destinationFile)"; die(json_encode($obj)); } } } chmod($destinationFile, 0644); } } sleep(1); $fsize = @filesize($destinationFile); _error_log("decideMoveUploadedToVideos: destinationFile {$destinationFile} filesize=" . ($fsize) . " (" . humanFileSize($fsize) . ")"); Video::clearCacheFromFilename($filename); } function unzipDirectory($filename, $destination) { global $global; // Wait a couple of seconds to make sure the file has completed transfer sleep(2); ini_set('memory_limit', '-1'); ini_set('max_execution_time', 7200); // 2 hours $cmd = "unzip {$filename} -d {$destination}" . " 2>&1"; _error_log("unzipDirectory: {$cmd}"); exec($cmd, $output, $return_val); if ($return_val !== 0 && function_exists("zip_open")) { // try to unzip using PHP _error_log("unzipDirectory: TRY to use PHP {$filename}"); $zip = zip_open($filename); if ($zip) { while ($zip_entry = zip_read($zip)) { $path = "{$destination}/" . zip_entry_name($zip_entry); //_error_log("unzipDirectory: fopen $path"); if (substr(zip_entry_name($zip_entry), -1) == '/') { make_path($path); } else { make_path($path); $fp = fopen($path, "w"); if (zip_entry_open($zip, $zip_entry, "r")) { $buf = zip_entry_read($zip_entry, zip_entry_filesize($zip_entry)); fwrite($fp, "$buf"); zip_entry_close($zip_entry); fclose($fp); } } } zip_close($zip); } else { _error_log("unzipDirectory: ERROR php zip does not work"); } } else { _error_log("unzipDirectory: Success {$destination}"); } @unlink($filename); } function make_path($path) { $created = false; if (substr($path, -1) !== DIRECTORY_SEPARATOR) { $path = pathinfo($path, PATHINFO_DIRNAME); } if (!is_dir($path)) { $created = mkdir($path, 0755, true); if (!$created) { _error_log('make_path: could not create the dir ' . json_encode($path)); } } else { $created = true; } return $created; } /** * for security clean all non secure files from directory * @param type $dir * @param type $allowedExtensions * @return type */ function cleanDirectory($dir, $allowedExtensions = array('key', 'm3u8', 'ts', 'vtt', 'jpg', 'gif', 'mp3', 'webm', 'webp')) { $ffs = scandir($dir); unset($ffs[array_search('.', $ffs, true)]); unset($ffs[array_search('..', $ffs, true)]); // prevent empty ordered elements if (count($ffs) < 1) { return; } foreach ($ffs as $ff) { $current = $dir . '/' . $ff; if (is_dir($current)) { cleanDirectory($current, $allowedExtensions); } $path_parts = pathinfo($current); if (!empty($path_parts['extension']) && !in_array($path_parts['extension'], $allowedExtensions)) { unlink($current); } } } function decideFile_put_contentsToVideos($tmp_name, $filename) { global $global; $aws_s3 = AVideoPlugin::loadPluginIfEnabled('AWS_S3'); $bb_b2 = AVideoPlugin::loadPluginIfEnabled('Blackblaze_B2'); $ftp = AVideoPlugin::loadPluginIfEnabled('FTP_Storage'); if (!empty($bb_b2)) { $bb_b2->move_uploaded_file($tmp_name, $filename); } elseif (!empty($aws_s3)) { $aws_s3->move_uploaded_file($tmp_name, $filename); } elseif (!empty($ftp)) { $ftp->move_uploaded_file($tmp_name, $filename); } else { $path = Video::getPathToFile($filename); if (!move_uploaded_file($tmp_name, $path)) { $obj->msg = "Error on move_uploaded_file({$tmp_name}, {$filename})"; die(json_encode($obj)); } } } function isAnyStorageEnabled() { if ($yptStorage = AVideoPlugin::loadPluginIfEnabled("YPTStorage")) { return true; } else if ($aws_s3 = AVideoPlugin::loadPluginIfEnabled("AWS_S3")) { return true; } else if ($bb_b2 = AVideoPlugin::loadPluginIfEnabled("Blackblaze_B2")) { return true; } else if ($ftp = AVideoPlugin::loadPluginIfEnabled("FTP_Storage")) { return true; } return false; } if (!function_exists('mime_content_type')) { function mime_content_type($filename) { return mime_content_type_per_filename($filename); } } function fontAwesomeClassName($filename) { $mime_type = mime_content_type_per_filename($filename); // List of official MIME Types: http://www.iana.org/assignments/media-types/media-types.xhtml $icon_classes = array( // Media 'image' => 'fas fa-file-image', 'audio' => 'fas fa-file-audio', 'video' => 'fas fa-file-video', // Documents 'application/pdf' => 'fas fa-file-pdf', 'application/msword' => 'fas fa-file-word', 'application/vnd.ms-word' => 'fas fa-file-word', 'application/vnd.oasis.opendocument.text' => 'fas fa-file-word', 'application/vnd.openxmlformats-officedocument.wordprocessingml' => 'fas fa-file-word', 'application/vnd.ms-excel' => 'fas fa-file-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml' => 'fas fa-file-excel', 'application/vnd.oasis.opendocument.spreadsheet' => 'fas fa-file-excel', 'application/vnd.ms-powerpoint' => 'fas fa-file-powerpoint', 'application/vnd.openxmlformats-officedocument.presentationml' => 'fas fa-file-powerpoint', 'application/vnd.oasis.opendocument.presentation' => 'fas fa-file-powerpoint', 'text/plain' => 'far fa-file-alt', 'text/html' => 'fas fa-code', 'application/json' => 'fas fa-code', // Archives 'application/gzip' => 'far fa-file-archive', 'application/zip' => 'far fa-file-archive', ); foreach ($icon_classes as $text => $icon) { if (strpos($mime_type, $text) === 0) { return $icon; } } return 'fas fa-file'; } function mime_content_type_per_filename($filename) { $mime_types = array( 'txt' => 'text/plain', 'htm' => 'text/html', 'html' => 'text/html', 'php' => 'text/html', 'css' => 'text/css', 'js' => 'application/javascript', 'json' => 'application/json', 'xml' => 'application/xml', 'swf' => 'application/x-shockwave-flash', 'flv' => 'video/x-flv', // images 'png' => 'image/png', 'jpe' => 'image/jpeg', 'jpeg' => 'image/jpeg', 'jpg' => 'image/jpeg', 'gif' => 'image/gif', 'bmp' => 'image/bmp', 'ico' => 'image/vnd.microsoft.icon', 'tiff' => 'image/tiff', 'tif' => 'image/tiff', 'svg' => 'image/svg+xml', 'svgz' => 'image/svg+xml', // archives 'zip' => 'application/zip', 'rar' => 'application/x-rar-compressed', 'exe' => 'application/x-msdownload', 'msi' => 'application/x-msdownload', 'cab' => 'application/vnd.ms-cab-compressed', // audio/video 'mp3' => 'audio/mpeg', 'qt' => 'video/quicktime', 'mov' => 'video/quicktime', 'mp4' => 'video/mp4', 'avi' => 'video/avi', 'mkv' => 'video/mkv', 'wav' => 'audio/wav', 'm4v' => 'video/mpeg', 'webm' => 'video/webm', 'wmv' => 'video/wmv', 'mpg' => 'video/mpeg', 'mpeg' => 'video/mpeg', 'f4v' => 'video/x-flv', 'm4v' => 'video/m4v', 'm4a' => 'video/quicktime', 'm2p' => 'video/quicktime', 'rm' => 'video/quicktime', 'vob' => 'video/quicktime', 'mkv' => 'video/quicktime', '3gp' => 'video/quicktime', 'm3u8' => 'application/x-mpegURL', // adobe 'pdf' => 'application/pdf', 'psd' => 'image/vnd.adobe.photoshop', 'ai' => 'application/postscript', 'eps' => 'application/postscript', 'ps' => 'application/postscript', // ms office 'doc' => 'application/msword', 'rtf' => 'application/rtf', 'xls' => 'application/vnd.ms-excel', 'ppt' => 'application/vnd.ms-powerpoint', // open office 'odt' => 'application/vnd.oasis.opendocument.text', 'ods' => 'application/vnd.oasis.opendocument.spreadsheet' ); if (filter_var($filename, FILTER_VALIDATE_URL) === false) { $ext = pathinfo($filename, PATHINFO_EXTENSION); } else { $ext = pathinfo(parse_url($filename, PHP_URL_PATH), PATHINFO_EXTENSION); } if ($ext === 'mp4' || $ext === 'webm') { $securePlugin = AVideoPlugin::loadPluginIfEnabled('SecureVideosDirectory'); if (!empty($securePlugin)) { if (method_exists($securePlugin, "useEncoderWatrermarkFromFileName") && $securePlugin->useEncoderWatrermarkFromFileName($filename)) { return "application/x-mpegURL"; } } } if (array_key_exists($ext, $mime_types)) { return $mime_types[$ext]; } elseif (function_exists('finfo_open')) { $finfo = finfo_open(FILEINFO_MIME); $mimetype = finfo_file($finfo, $filename); finfo_close($finfo); return $mimetype; } else { return 'application/octet-stream'; } } function combineFiles($filesArray, $extension = "js") { global $global, $advancedCustom; if ($extension == 'js' && isBot()) { return getCDN() . 'view/js/empty.js'; } $cacheDir = $global['systemRootPath'] . 'videos/cache/' . $extension . "/"; if (!is_dir($cacheDir)) { mkdir($cacheDir, 0777, true); } $str = ""; $fileName = ""; foreach ($filesArray as $value) { $fileName .= $value . filectime($global['systemRootPath'] . $value) . filemtime($global['systemRootPath'] . $value); } if ($advancedCustom != false) { $minifyEnabled = $advancedCustom->EnableMinifyJS; } else { $minifyEnabled = false; } // temporary disable minify $minifyEnabled = false; $md5FileName = md5($fileName) . ".{$extension}"; if (!file_exists($cacheDir . $md5FileName)) { foreach ($filesArray as $value) { if (file_exists($global['systemRootPath'] . $value)) { $str .= "\n/*{$value} created local with systemRootPath */\n" . local_get_contents($global['systemRootPath'] . $value); } elseif (file_exists($value)) { $str .= "\n/*{$value} created local with full-path given */\n" . local_get_contents($value); } else { $allowed = ""; if (ini_get('allow_url_fopen')) { $allowed .= "allow_url_fopen is on and "; } if (function_exists('curl_init')) { $allowed .= "curl is on"; } else { $allowed .= "curl is off"; } $content = url_get_contents($value); if (empty($content)) { $allowed .= " - web-fallback 1 (add webSiteRootURL)"; $content = url_get_contents($global['webSiteRootURL'] . $value); } $str .= "\n/*{$value} created via web with own url ({$allowed}) */\n" . $content; } } //if ((($extension == "js" || $extension == "css") && ($minifyEnabled))) { if ($extension == "css" && ($minifyEnabled)) { require_once $global['systemRootPath'] . 'objects/jshrink.php'; $str = \JShrink\Minifier::minify($str, array('flaggedComments' => false)); } file_put_contents($cacheDir . $md5FileName, $str); } return getCDN() . 'videos/cache/' . $extension . "/" . $md5FileName . "?cache=" . filectime($cacheDir . $md5FileName) . filemtime($cacheDir . $md5FileName); } function local_get_contents($path) { if (function_exists('fopen')) { $myfile = fopen($path, "r") or die("Unable to open file! [{$path}]"); $text = fread($myfile, filesize($path)); fclose($myfile); return $text; } } function getSelfUserAgent() { global $global, $AVideoStreamer_UA; $agent = $AVideoStreamer_UA . "_"; $agent .= md5($global['salt']); return $agent; } -function isValidM3U8Link($url, $timeout = 5){ - $content = url_get_contents($url, '', 5); +function isValidM3U8Link($url, $timeout = 3){ + if(!isValidURL($url)){ + return false; + } + $content = url_get_contents($url, '', $timeout); if(!empty($content)){ if(preg_match('/EXTM3U/', $content)){ return true; } } return false; } function url_get_contents($url, $ctx = "", $timeout = 0, $debug = false) { global $global, $mysqlHost, $mysqlUser, $mysqlPass, $mysqlDatabase, $mysqlPort; if ($debug) { _error_log("url_get_contents: Start $url, $ctx, $timeout " . getSelfURI() . " " . getRealIpAddr() . " " . json_encode(debug_backtrace())); } $agent = getSelfUserAgent(); if (empty($ctx)) { $opts = array( 'http' => array('header' => "User-Agent: {$agent}\r\n"), "ssl" => array( "verify_peer" => false, "verify_peer_name" => false, "allow_self_signed" => true, ), ); if (!empty($timeout)) { ini_set('default_socket_timeout', $timeout); $opts['http'] = array('timeout' => $timeout); } $context = stream_context_create($opts); } else { $context = $ctx; } if (ini_get('allow_url_fopen')) { if ($debug) { _error_log("url_get_contents: allow_url_fopen {$url}"); } try { $tmp = @file_get_contents($url, false, $context); if ($tmp != false) { $response = remove_utf8_bom($tmp); if ($debug) { //_error_log("url_get_contents: SUCCESS file_get_contents($url) {$response}"); _error_log("url_get_contents: SUCCESS file_get_contents($url)"); } return $response; } if ($debug) { _error_log("url_get_contents: ERROR file_get_contents($url) "); } } catch (ErrorException $e) { if ($debug) { _error_log("url_get_contents: allow_url_fopen ERROR " . $e->getMessage() . " {$url}"); } return "url_get_contents: " . $e->getMessage(); } } elseif (function_exists('curl_init')) { if ($debug) { _error_log("url_get_contents: CURL {$url} "); } $ch = curl_init(); curl_setopt($ch, CURLOPT_USERAGENT, $agent); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); if (!empty($timeout)) { curl_setopt($ch, CURLOPT_TIMEOUT, $timeout); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout + 10); } $output = curl_exec($ch); curl_close($ch); if ($debug) { _error_log("url_get_contents: CURL SUCCESS {$url}"); } return remove_utf8_bom($output); } if ($debug) { _error_log("url_get_contents: Nothing yet {$url}"); } // try wget $filename = getTmpDir("YPTurl_get_contents") . md5($url); if ($debug) { _error_log("url_get_contents: try wget $filename {$url}"); } if (wget($url, $filename, $debug)) { if ($debug) { _error_log("url_get_contents: wget success {$url} "); } $result = file_get_contents($filename); unlink($filename); if (!empty($result)) { return remove_utf8_bom($result); } } elseif ($debug) { _error_log("url_get_contents: try wget fail {$url}"); } return false; } function getUpdatesFilesArray() { global $config, $global; if (!class_exists('User') || !User::isAdmin()) { return array(); } $files1 = scandir($global['systemRootPath'] . "updatedb"); $updateFiles = array(); foreach ($files1 as $value) { preg_match("/updateDb.v([0-9.]*).sql/", $value, $match); if (!empty($match)) { if ($config->currentVersionLowerThen($match[1])) { $updateFiles[] = array('filename' => $match[0], 'version' => $match[1]); } } } return $updateFiles; } function thereIsAnyUpdate() { if (!User::isAdmin()) { return false; } $name = 'thereIsAnyUpdate'; if (!isset($_SESSION['sessionCache'][$name])) { $files = getUpdatesFilesArray(); if (!empty($files)) { _session_start(); $_SESSION['sessionCache'][$name] = $files; } } return @$_SESSION['sessionCache'][$name]; } function thereIsAnyRemoteUpdate() { if (!User::isAdmin()) { return false; } global $config; $cacheName = '_thereIsAnyRemoteUpdate'; $cache = ObjectYPT::getCache($cacheName, 86400); // 24 hours if (!empty($cache)) { return $cache; } //$version = _json_decode(url_get_contents("https://tutorials.avideo.com/version")); $version = _json_decode(url_get_contents("https://tutorialsavideo.b-cdn.net/version", "", 4)); if (empty($version)) { return false; } $name = 'thereIsAnyRemoteUpdate'; if (!isset($_SESSION['sessionCache'][$name])) { if (!empty($version)) { _session_start(); if (version_compare($config->getVersion(), $version->version) === -1) { $_SESSION['sessionCache'][$name] = $version; } else { $_SESSION['sessionCache'][$name] = false; } } } ObjectYPT::setCache($cacheName, $_SESSION['sessionCache'][$name]); return $_SESSION['sessionCache'][$name]; } function UTF8encode($data) { global $advancedCustom, $global; if (!empty($advancedCustom->utf8Encode)) { return utf8_encode($data); } if (!empty($advancedCustom->utf8Decode)) { return utf8_decode($data); } return $data; } //detect search engine bots function isBot() { global $_isBot; if (empty($_SERVER['HTTP_USER_AGENT'])) { return true; } if (isAVideoEncoder()) { return false; } if (isset($_isBot)) { return $_isBot; } $_isBot = false; // User lowercase string for comparison. $user_agent = strtolower($_SERVER['HTTP_USER_AGENT']); // A list of some common words used only for bots and crawlers. $bot_identifiers = array( 'bot', 'slurp', 'crawler', 'spider', 'curl', 'facebook', 'fetch', 'loader', 'lighthouse', 'pingdom', 'gtmetrix', 'ptst', 'dmbrowser', 'dareboost' ); // See if one of the identifiers is in the UA string. foreach ($bot_identifiers as $identifier) { if (stripos($user_agent, $identifier) !== false) { $_isBot = true; break; } } return $_isBot; } /** * A function that could get me the last N lines of a log file. * @param type $filepath * @param type $lines * @param type $adaptive * @return boolean */ function tail($filepath, $lines = 1, $adaptive = true, $returnArray = false) { if (!function_exists('mb_strlen')) { $msg = "AVideoLog::ERROR you need to install the mb_strlen function to make it work, please the command 'sudo apt install php-mbstring'"; if ($returnArray) { return array(array($msg)); } else { return $msg; } } // Open file $f = @fopen($filepath, "rb"); if ($f === false) { return false; } // Sets buffer size, according to the number of lines to retrieve. // This gives a performance boost when reading a few lines from the file. if (!$adaptive) { $buffer = 4096; } else { $buffer = ($lines < 2 ? 64 : ($lines < 10 ? 512 : 4096)); } // Jump to last character fseek($f, -1, SEEK_END); // Read it and adjust line number if necessary // (Otherwise the result would be wrong if file doesn't end with a blank line) if (fread($f, 1) != "\n") { $lines -= 1; } // Start reading $output = ''; $chunk = ''; // While we would like more while (ftell($f) > 0 && $lines >= 0) { // Figure out how far back we should jump $seek = min(ftell($f), $buffer); // Do the jump (backwards, relative to where we are) fseek($f, -$seek, SEEK_CUR); // Read a chunk and prepend it to our output $output = ($chunk = fread($f, $seek)) . $output; // Jump back to where we started reading fseek($f, -mb_strlen($chunk, '8bit'), SEEK_CUR); // Decrease our line counter $lines -= substr_count($chunk, "\n"); } // While we have too many lines // (Because of buffer size we might have read too many) while ($lines++ < 0) { // Find first newline and remove all text before that $output = substr($output, strpos($output, "\n") + 1); } // Close file and return fclose($f); $output = trim($output); if ($returnArray) { $array = explode("\n", $output); $newArray = array(); foreach ($array as $value) { $newArray[] = array($value); } return $newArray; } else { return $output; } } function encryptPassword($password, $noSalt = false) { global $advancedCustom, $global, $advancedCustomUser; if (!empty($advancedCustomUser->encryptPasswordsWithSalt) && !empty($global['salt']) && empty($noSalt)) { $password .= $global['salt']; } return md5(hash("whirlpool", sha1($password))); } function encryptPasswordVerify($password, $hash, $encodedPass = false) { global $advancedCustom, $global; if (!$encodedPass || $encodedPass === 'false') { //_error_log("encryptPasswordVerify: encrypt"); $passwordSalted = encryptPassword($password); // in case you enable the salt later $passwordUnSalted = encryptPassword($password, true); } else { //_error_log("encryptPasswordVerify: do not encrypt"); $passwordSalted = $password; // in case you enable the salt later $passwordUnSalted = $password; } //_error_log("passwordSalted = $passwordSalted, hash=$hash, passwordUnSalted=$passwordUnSalted"); return $passwordSalted === $hash || $passwordUnSalted === $hash || $password === $hash; } function isMobile($userAgent = null, $httpHeaders = null) { if (empty($userAgent) && empty($_SERVER["HTTP_USER_AGENT"])) { return false; } global $global; require_once $global['systemRootPath'] . 'objects/Mobile_Detect.php'; $detect = new Mobile_Detect; return $detect->isMobile($userAgent, $httpHeaders); } function isChannelPage() { return strpos($_SERVER["SCRIPT_NAME"], 'view/channel.php') !== false; } function isAVideoMobileApp($user_agent = "") { if (empty($user_agent)) { $user_agent = @$_SERVER['HTTP_USER_AGENT']; } if (empty($user_agent)) { return false; } global $AVideoMobileAPP_UA; if (preg_match("/{$AVideoMobileAPP_UA}(.*)/", $_SERVER["HTTP_USER_AGENT"], $match)) { $url = trim($match[1]); if (!empty($url)) { return $url; } return true; } return false; } function isAVideoEncoder($user_agent = "") { if (empty($user_agent)) { $user_agent = @$_SERVER['HTTP_USER_AGENT']; } if (empty($user_agent)) { return false; } global $AVideoEncoder_UA; if (preg_match("/{$AVideoEncoder_UA}(.*)/", $_SERVER["HTTP_USER_AGENT"], $match)) { $url = trim($match[1]); if (!empty($url)) { return $url; } return true; } return false; } function isCDN() { if (empty($_SERVER['HTTP_CDN_HOST'])) { return false; } return isFromCDN($_SERVER['HTTP_CDN_HOST']); } function isFromCDN($url) { if (preg_match('/cdn.ypt.me/i', $url)) { return true; } return false; } function isAVideo($user_agent = "") { if (empty($user_agent)) { $user_agent = @$_SERVER['HTTP_USER_AGENT']; } if (empty($user_agent)) { return false; } global $AVideoEncoder_UA; if (preg_match("/AVideo(.*)/", $_SERVER["HTTP_USER_AGENT"], $match)) { $url = trim($match[1]); if (!empty($url)) { return $url; } return true; } return false; } function isAVideoEncoderOnSameDomain() { $url = isAVideoEncoder(); if (empty($url)) { return false; } $url = "http://{$url}"; return isSameDomainAsMyAVideo($url); } function isSameDomainAsMyAVideo($url) { global $global; if (empty($url)) { return false; } return isSameDomain($url, $global['webSiteRootURL']) || isSameDomain($url, getCDN()); } function requestComesFromSameDomainAsMyAVideo() { global $global; $url = ""; if (!empty($_SERVER['HTTP_REFERER'])) { $url = $_SERVER['HTTP_REFERER']; } elseif (!empty($_SERVER['HTTP_ORIGIN'])) { $url = $_SERVER['HTTP_ORIGIN']; } //_error_log("requestComesFromSameDomainAsMyAVideo: ({$url}) == ({$global['webSiteRootURL']})"); return isSameDomain($url, $global['webSiteRootURL']) || isSameDomain($url, getCDN()) || isFromCDN($url); } function requestComesFromSafePlace() { return (requestComesFromSameDomainAsMyAVideo() || isAVideo()); } function addGlobalTokenIfSameDomain($url) { if (!filter_var($url, FILTER_VALIDATE_URL) || (empty($_GET['livelink']) || !preg_match("/^http.*/i", $_GET['livelink']))) { return $url; } if (!isSameDomainAsMyAVideo($url)) { return $url; } return addQueryStringParameter($url, 'globalToken', getToken(60)); } /** * Remove a query string parameter from an URL. * * @param string $url * @param string $varname * * @return string */ function removeQueryStringParameter($url, $varname) { $parsedUrl = parse_url($url); $query = array(); if (isset($parsedUrl['query'])) { parse_str($parsedUrl['query'], $query); unset($query[$varname]); } $path = isset($parsedUrl['path']) ? $parsedUrl['path'] : ''; $query = !empty($query) ? '?' . http_build_query($query) : ''; if (empty($parsedUrl['scheme'])) { $scheme = ''; } else { $scheme = "{$parsedUrl['scheme']}:"; } return $scheme . '//' . $parsedUrl['host'] . $path . $query; } /** * Add a query string parameter from an URL. * * @param string $url * @param string $varname * * @return string */ function addQueryStringParameter($url, $varname, $value) { $parsedUrl = parse_url($url); if (empty($parsedUrl['host'])) { return ""; } $query = array(); if (isset($parsedUrl['query'])) { parse_str($parsedUrl['query'], $query); } $query[$varname] = $value; $path = isset($parsedUrl['path']) ? $parsedUrl['path'] : ''; $query = !empty($query) ? '?' . http_build_query($query) : ''; $port = ""; if (!empty($parsedUrl['port']) && $parsedUrl['port'] != '80') { $port = ":{$parsedUrl['port']}"; } if (empty($parsedUrl['scheme'])) { $scheme = ''; } else { $scheme = "{$parsedUrl['scheme']}:"; } return $scheme . '//' . $parsedUrl['host'] . $port . $path . $query; } function isSameDomain($url1, $url2) { if (empty($url1) || empty($url2)) { return false; } return (get_domain($url1) === get_domain($url2)); } function isAVideoStreamer($user_agent = "") { if (empty($user_agent)) { $user_agent = @$_SERVER['HTTP_USER_AGENT']; } if (empty($user_agent)) { return false; } global $AVideoStreamer_UA, $global; $md5 = md5($global['salt']); if (preg_match("/{$AVideoStreamer_UA}_{$md5}/", $_SERVER["HTTP_USER_AGENT"])) { return true; } return false; } function isAVideoUserAgent($user_agent = "") { if (empty($user_agent)) { $user_agent = @$_SERVER['HTTP_USER_AGENT']; } if (empty($user_agent)) { return false; } global $AVideoMobileAPP_UA, $AVideoEncoder_UA, $AVideoStreamer_UA, $AVideoStorage_UA, $global; // Lavf = ffmpeg $agents = array($AVideoMobileAPP_UA, $AVideoEncoder_UA, $AVideoStreamer_UA, $AVideoStorage_UA, 'Lavf'); foreach ($agents as $value) { if (preg_match("/{$value}/", $_SERVER["HTTP_USER_AGENT"])) { return true; } } return false; } function isAVideoStorage($user_agent = "") { if (empty($user_agent)) { $user_agent = @$_SERVER['HTTP_USER_AGENT']; } if (empty($user_agent)) { return false; } global $AVideoStorage_UA; if (preg_match("/{$AVideoStorage_UA}(.*)/", $_SERVER["HTTP_USER_AGENT"], $match)) { $url = trim($match[1]); if (!empty($url)) { return $url; } return true; } return false; } function get_domain($url, $ifEmptyReturnSameString = false) { $pieces = parse_url($url); $domain = isset($pieces['host']) ? $pieces['host'] : ''; if (empty($domain)) { return $ifEmptyReturnSameString ? $url : false; } if (preg_match('/(?P[a-z0-9][a-z0-9\-]{1,63}\.[a-z\.]{2,6})$/i', $domain, $regs)) { return $regs['domain']; } else { $isIp = (bool) ip2long($pieces['host']); if ($isIp) { return $pieces['host']; } } return false; } function verify($url) { ini_set('default_socket_timeout', 5); $cacheFile = sys_get_temp_dir() . "/" . md5($url) . "_verify.log"; $lifetime = 86400; //24 hours error_log("Verification Start {$url}"); $verifyURL = "https://search.avideo.com/verify.php?url=" . urlencode($url); if (!file_exists($cacheFile) || (time() > (filemtime($cacheFile) + $lifetime))) { error_log("Verification Creating the Cache {$url}"); $result = url_get_contents($verifyURL, '', 5); file_put_contents($cacheFile, $result); } else { error_log("Verification GetFrom Cache {$url}"); $result = file_get_contents($cacheFile); } error_log("Verification Response ($verifyURL): {$result}"); return json_decode($result); } function isVerified($url) { $resultV = verify($url); if (!empty($resultV) && !$resultV->verified) { error_log("Error on Login not verified"); return false; } return true; } function siteMap() { _error_log("siteMap: start"); ini_set('memory_limit', '-1'); ini_set('max_execution_time', 0); global $global, $advancedCustom; $date = date('Y-m-d\TH:i:s') . "+00:00"; $xml = ' ' . $global['webSiteRootURL'] . ' ' . $date . ' always 1.00 ' . $global['webSiteRootURL'] . 'help ' . $date . ' monthly 0.50 ' . $global['webSiteRootURL'] . 'about ' . $date . ' monthly 0.50 ' . $global['webSiteRootURL'] . 'contact ' . $date . ' monthly 0.50 ' . $global['webSiteRootURL'] . 'channels ' . $date . ' daily 0.80 '; $_REQUEST['rowCount'] = $advancedCustom->siteMapRowsLimit; _error_log("siteMap: rowCount {$_REQUEST['rowCount']} "); $_POST['sort']['modified'] = "DESC"; $users = User::getAllUsersThatHasVideos(true); _error_log("siteMap: getAllUsers " . count($users)); foreach ($users as $value) { $xml .= ' ' . User::getChannelLink($value['id']) . ' ' . $date . ' daily 0.90 '; } $xml .= ' '; $_REQUEST['rowCount'] = $advancedCustom->siteMapRowsLimit; $_POST['sort']['modified'] = "DESC"; $rows = Category::getAllCategories(); _error_log("siteMap: getAllCategories " . count($rows)); foreach ($rows as $value) { $xml .= ' ' . $global['webSiteRootURL'] . 'cat/' . $value['clean_name'] . ' ' . $date . ' weekly 0.80 '; } $xml .= ''; $_REQUEST['rowCount'] = $advancedCustom->siteMapRowsLimit * 10; $_POST['sort']['created'] = "DESC"; $rows = Video::getAllVideos(!empty($advancedCustom->showPrivateVideosOnSitemap) ? "viewableNotUnlisted" : "publicOnly"); _error_log("siteMap: getAllVideos " . count($rows)); foreach ($rows as $video) { $videos_id = $video['id']; //_error_log("siteMap: getAllVideos videos_id {$videos_id} start"); $source = Video::getSourceFile($video['filename']); if (($video['type'] !== "audio") && ($video['type'] !== "linkAudio") && !empty($source['url'])) { $img = $source['url']; $data = getimgsize($source['path']); $imgw = $data[0]; $imgh = $data[1]; } elseif ($video['type'] == "audio") { $img = getCDN() . "view/img/audio_wave.jpg"; } $type = 'video'; if ($video['type'] === 'pdf') { $type = 'pdf'; } if ($video['type'] === 'article') { $type = 'article'; } $images = Video::getImageFromFilename($video['filename'], $type); if (!empty($images->posterPortrait) && basename($images->posterPortrait) !== 'notfound_portrait.jpg' && basename($images->posterPortrait) !== 'pdf_portrait.png' && basename($images->posterPortrait) !== 'article_portrait.png') { $img = $images->posterPortrait; $data = getimgsize($images->posterPortraitPath); $imgw = $data[0]; $imgh = $data[1]; } else { $img = $images->poster; } $description = str_replace(array('"', "\n", "\r"), array('', ' ', ' '), empty(trim($video['description'])) ? $video['title'] : $video['description']); $duration = parseDurationToSeconds($video['duration']); if ($duration > 28800) { // this is because this issue https://github.com/WWBN/AVideo/issues/3338 remove in the future if is not necessary anymore $duration = 28800; } $xml .= ' ' . Video::getLink($video['id'], $video['clean_title']) . ' ' . $img . ' ' . $duration . ' ' . $video['views_count'] . ' ' . date("Y-m-d\TH:i:s", strtotime($video['created'])) . '+00:00 yes ' . (Video::isPublic($video['id']) ? "no" : "yes") . ' ' . User::getNameIdentificationById($video['users_id']) . ' no '; } $xml .= ' '; _error_log("siteMap: done "); $newXML1 = preg_replace('/[^\x{0009}\x{000a}\x{000d}\x{0020}-\x{D7FF}\x{E000}-\x{FFFD}]+/u', '', $xml); if (empty($newXML1)) { _error_log("siteMap: pregreplace1 fail "); $newXML1 = $xml; } if (!empty($advancedCustom->siteMapUTF8Fix)) { $newXML2 = preg_replace('/&(?!#?[a-z0-9]+;)/', '&', $newXML1); if (empty($newXML2)) { _error_log("siteMap: pregreplace2 fail "); $newXML2 = $newXML1; } $newXML3 = preg_replace('/[\x00-\x1F\x7F-\xFF]/', '', $newXML2); if (empty($newXML3)) { _error_log("siteMap: pregreplace3 fail "); $newXML3 = $newXML2; } $newXML4 = preg_replace('/[\x00-\x1F\x7F]/', '', $newXML3); if (empty($newXML4)) { _error_log("siteMap: pregreplace4 fail "); $newXML4 = $newXML3; } $newXML5 = preg_replace('/[\x00-\x1F\x7F\xA0]/u', '', $newXML4); if (empty($newXML5)) { _error_log("siteMap: pregreplace5 fail "); $newXML5 = $newXML4; } } else { $newXML5 = $newXML1; } return $newXML5; } function object_to_array($obj) { //only process if it's an object or array being passed to the function if (is_object($obj) || is_array($obj)) { $ret = (array) $obj; foreach ($ret as &$item) { //recursively process EACH element regardless of type $item = object_to_array($item); } return $ret; } //otherwise (i.e. for scalar values) return without modification else { return $obj; } } function allowOrigin() { global $global; if (!headers_sent()) { header_remove('Access-Control-Allow-Origin'); } if (empty($_SERVER['HTTP_ORIGIN'])) { $server = parse_url($global['webSiteRootURL']); header('Access-Control-Allow-Origin: ' . $server["scheme"] . '://imasdk.googleapis.com'); } else { header("Access-Control-Allow-Origin: " . $_SERVER['HTTP_ORIGIN']); } header("Access-Control-Allow-Credentials: true"); header("Access-Control-Allow-Methods: GET,HEAD,OPTIONS,POST,PUT"); header("Access-Control-Allow-Headers: Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers"); } function rrmdir($dir) { if (empty($dir)) { _error_log('rrmdir: the dir was empty'); return false; } global $global; $dir = fixPath($dir, true); $pattern = '/' . addcslashes($dir, DIRECTORY_SEPARATOR) . 'videos[\/\\\]?$/i'; if ($dir == getVideosDir() || $dir == "{$global['systemRootPath']}videos" . DIRECTORY_SEPARATOR || preg_match($pattern, $dir)) { _error_log('rrmdir: A script ties to delete the videos Directory [' . $dir . '] ' . json_encode(array($dir == getVideosDir(), $dir == "{$global['systemRootPath']}videos" . DIRECTORY_SEPARATOR, preg_match($pattern, $dir)))); return false; } if (is_dir($dir)) { $objects = scandir($dir); foreach ($objects as $object) { if ($object != "." && $object != "..") { if (is_dir($dir . "/" . $object)) { rrmdir($dir . "/" . $object); } else { @unlink($dir . "/" . $object); } } } if (preg_match('/(\/|^)videos(\/cache)?\/?$/i', $dir)) { // do not delete videos or cache folder return false; } @rmdir($dir); if (is_dir($dir)) { _error_log('rrmdir: The Directory was not deleted, trying again ' . $dir); exec('rm -R ' . $dir); } } else { //_error_log('rrmdir: The Directory does not exists '.$dir); } } /** * You can now configure it on the configuration.php * @return boolean */ function ddosProtection() { global $global; $maxCon = empty($global['ddosMaxConnections']) ? 40 : $global['ddosMaxConnections']; $secondTimeout = empty($global['ddosSecondTimeout']) ? 5 : $global['ddosSecondTimeout']; $whitelistedFiles = array( 'playlists.json.php', 'playlistsFromUserVideos.json.php', 'image404.php' ); if (in_array(basename($_SERVER["SCRIPT_FILENAME"]), $whitelistedFiles)) { return true; } $time = time(); if (!isset($_SESSION['bruteForceBlock']) || empty($_SESSION['bruteForceBlock'])) { $_SESSION['bruteForceBlock'] = array(); $_SESSION['bruteForceBlock'][] = $time; return true; } $_SESSION['bruteForceBlock'][] = $time; //remove requests that are older than secondTimeout foreach ($_SESSION['bruteForceBlock'] as $key => $request_time) { if ($request_time < $time - $secondTimeout) { unset($_SESSION['bruteForceBlock'][$key]); } } //progressive timeout-> more requests, longer timeout $active_connections = count($_SESSION['bruteForceBlock']); $timeoutReal = ($active_connections / $maxCon) < 1 ? 0 : ($active_connections / $maxCon) * $secondTimeout; if ($timeoutReal) { _error_log("ddosProtection:: progressive timeout timeoutReal = ($timeoutReal) active_connections = ($active_connections) maxCon = ($maxCon) ", AVideoLog::$SECURITY); } sleep($timeoutReal); //with strict mode, penalize "attacker" with sleep() above, log and then die if ($global['strictDDOSprotection'] && $timeoutReal > 0) { $str = "bruteForceBlock: maxCon: $maxCon => secondTimeout: $secondTimeout | IP: " . getRealIpAddr() . " | count:" . count($_SESSION['bruteForceBlock']); _error_log($str); die($str); } return true; } function getAdsLeaderBoardBigVideo() { $ad = AVideoPlugin::getObjectDataIfEnabled('ADs'); if (!empty($ad)) { if (isMobile()) { return ADs::giveGoogleATimeout($ad->leaderBoardBigVideoMobile->value); } else { return ADs::giveGoogleATimeout($ad->leaderBoardBigVideo->value); } } } function getAdsLeaderBoardTop() { $ad = AVideoPlugin::getObjectDataIfEnabled('ADs'); if (!empty($ad)) { if (isMobile()) { return ADs::giveGoogleATimeout($ad->leaderBoardTopMobile->value); } else { return ADs::giveGoogleATimeout($ad->leaderBoardTop->value); } } } function getAdsChannelLeaderBoardTop() { $ad = AVideoPlugin::getObjectDataIfEnabled('ADs'); if (!empty($ad)) { if (isMobile()) { return ADs::giveGoogleATimeout($ad->channelLeaderBoardTopMobile->value); } else { return ADs::giveGoogleATimeout($ad->channelLeaderBoardTop->value); } } } function getAdsLeaderBoardTop2() { $ad = AVideoPlugin::getObjectDataIfEnabled('ADs'); if (!empty($ad)) { if (isMobile()) { return ADs::giveGoogleATimeout($ad->leaderBoardTopMobile2->value); } else { return ADs::giveGoogleATimeout($ad->leaderBoardTop2->value); } } } function getAdsLeaderBoardMiddle() { $ad = AVideoPlugin::getObjectDataIfEnabled('ADs'); if (!empty($ad)) { if (isMobile()) { return ADs::giveGoogleATimeout($ad->leaderBoardMiddleMobile->value); } else { return ADs::giveGoogleATimeout($ad->leaderBoardMiddle->value); } } } function getAdsLeaderBoardFooter() { $ad = AVideoPlugin::getObjectDataIfEnabled('ADs'); if (!empty($ad)) { if (isMobile()) { return ADs::giveGoogleATimeout($ad->leaderBoardFooterMobile->value); } else { return ADs::giveGoogleATimeout($ad->leaderBoardFooter->value); } } } function getAdsSideRectangle() { $ad = AVideoPlugin::getObjectDataIfEnabled('ADs'); if (!empty($ad)) { if (isMobile()) { return ADs::giveGoogleATimeout($ad->sideRectangle->value); } else { return ADs::giveGoogleATimeout($ad->sideRectangle->value); } } } function isToHidePrivateVideos() { $obj = AVideoPlugin::getObjectDataIfEnabled("Gallery"); if (!empty($obj)) { return $obj->hidePrivateVideos; } $obj = AVideoPlugin::getObjectDataIfEnabled("YouPHPFlix2"); if (!empty($obj)) { return $obj->hidePrivateVideos; } $obj = AVideoPlugin::getObjectDataIfEnabled("YouTube"); if (!empty($obj)) { return $obj->hidePrivateVideos; } return false; } function convertImageToOG($source, $destination) { if (!file_exists($destination)) { $w = 200; $h = 200; $sizes = getimagesize($source); if ($sizes[0] < $w || $sizes[1] < $h) { $tmpDir = getTmpDir(); $fileConverted = $tmpDir . "_jpg_" . uniqid() . ".jpg"; convertImage($source, $fileConverted, 100); im_resizeV2($fileConverted, $destination, $w, $h, 100); unlink($fileConverted); } } return $destination; } function convertImageToRoku($source, $destination) { if (empty($source)) { _error_log("convertImageToRoku: source image is empty"); return false; } $w = 1280; $h = 720; if (file_exists($destination)) { $sizes = getimagesize($destination); if ($sizes[0] < $w || $sizes[1] < $h) { _error_log("convertImageToRoku: file is smaller " . json_encode($sizes)); unlink($destination); } } if (!file_exists($destination)) { try { $tmpDir = getTmpDir(); $fileConverted = $tmpDir . "_jpg_" . uniqid() . ".jpg"; convertImage($source, $fileConverted, 100); im_resizeV2($fileConverted, $destination, $w, $h, 100); @unlink($fileConverted); } catch (Exception $exc) { _error_log("convertImageToRoku: " . $exc->getMessage()); return false; } } return $destination; } function ogSite() { global $global, $config; include $global['systemRootPath'] . 'objects/functionogSite.php'; } function getOpenGraph($videos_id) { global $global, $config, $advancedCustom; include $global['systemRootPath'] . 'objects/functiongetOpenGraph.php'; } function getLdJson($videos_id) { $cache = ObjectYPT::getCache("getLdJson{$videos_id}", 0); if (empty($cache)) { echo $cache; } global $global, $config; echo ""; if (empty($videos_id)) { echo ""; if (!empty($_GET['videoName'])) { echo ""; $video = Video::getVideoFromCleanTitle($_GET['videoName']); } } else { echo ""; $video = Video::getVideoLight($videos_id); } if (empty($video)) { echo ""; return false; } $videos_id = $video['id']; $source = Video::getSourceFile($video['filename']); if (($video['type'] !== "audio") && ($video['type'] !== "linkAudio") && !empty($source['url'])) { $img = $source['url']; $data = getimgsize($source['path']); $imgw = $data[0]; $imgh = $data[1]; } elseif ($video['type'] == "audio") { $img = getCDN() . "view/img/audio_wave.jpg"; } $type = 'video'; if ($video['type'] === 'pdf') { $type = 'pdf'; } if ($video['type'] === 'article') { $type = 'article'; } $images = Video::getImageFromFilename($video['filename'], $type); if (!empty($images->posterPortrait) && basename($images->posterPortrait) !== 'notfound_portrait.jpg' && basename($images->posterPortrait) !== 'pdf_portrait.png' && basename($images->posterPortrait) !== 'article_portrait.png') { $img = $images->posterPortrait; $data = getimgsize($images->posterPortraitPath); $imgw = $data[0]; $imgh = $data[1]; } else { $img = $images->poster; } $description = html2plainText(empty(trim($video['description'])) ? $video['title'] : $video['description']); $duration = Video::getItemPropDuration($video['duration']); if ($duration == "PT0H0M0S") { $duration = "PT0H0M1S"; } $output = ' '; ObjectYPT::setCache("getLdJson{$videos_id}", $output); echo $output; } function getItemprop($videos_id) { $cache = ObjectYPT::getCache("getItemprop{$videos_id}", 0); if (empty($cache)) { echo $cache; } global $global, $config; echo ""; if (empty($videos_id)) { echo ""; if (!empty($_GET['videoName'])) { echo ""; $video = Video::getVideoFromCleanTitle($_GET['videoName']); } } else { echo ""; $video = Video::getVideoLight($videos_id); } if (empty($video)) { echo ""; return false; } $videos_id = $video['id']; $source = Video::getSourceFile($video['filename']); if (($video['type'] !== "audio") && ($video['type'] !== "linkAudio") && !empty($source['url'])) { $img = $source['url']; $data = getimgsize($source['path']); $imgw = $data[0]; $imgh = $data[1]; } elseif ($video['type'] == "audio") { $img = getCDN() . "view/img/audio_wave.jpg"; } $type = 'video'; if ($video['type'] === 'pdf') { $type = 'pdf'; } if ($video['type'] === 'image') { $type = 'image'; } if ($video['type'] === 'zip') { $type = 'zip'; } if ($video['type'] === 'article') { $type = 'article'; } $images = Video::getImageFromFilename($video['filename'], $type); if (!empty($images->posterPortrait) && basename($images->posterPortrait) !== 'notfound_portrait.jpg' && basename($images->posterPortrait) !== 'pdf_portrait.png' && basename($images->posterPortrait) !== 'article_portrait.png') { $img = $images->posterPortrait; $data = getimgsize($images->posterPortraitPath); $imgw = $data[0]; $imgh = $data[1]; } else { $img = $images->poster; } $description = html2plainText(empty(trim($video['description'])) ? $video['title'] : $video['description']); $duration = Video::getItemPropDuration($video['duration']); if ($duration == "PT0H0M0S") { $duration = "PT0H0M1S"; } $output = ' '; ObjectYPT::setCache("getItemprop{$videos_id}", $output); echo $output; } function getOS($user_agent = "") { if (empty($user_agent)) { $user_agent = @$_SERVER['HTTP_USER_AGENT']; } $os_platform = "Unknown OS Platform"; $os_array = array( '/windows nt 10/i' => 'Windows 10', '/windows nt 6.3/i' => 'Windows 8.1', '/windows nt 6.2/i' => 'Windows 8', '/windows nt 6.1/i' => 'Windows 7', '/windows nt 6.0/i' => 'Windows Vista', '/windows nt 5.2/i' => 'Windows Server 2003/XP x64', '/windows nt 5.1/i' => 'Windows XP', '/windows xp/i' => 'Windows XP', '/windows nt 5.0/i' => 'Windows 2000', '/windows me/i' => 'Windows ME', '/win98/i' => 'Windows 98', '/win95/i' => 'Windows 95', '/win16/i' => 'Windows 3.11', '/macintosh|mac os x/i' => 'Mac OS X', '/mac_powerpc/i' => 'Mac OS 9', '/linux/i' => 'Linux', '/ubuntu/i' => 'Ubuntu', '/iphone/i' => 'iPhone', '/ipod/i' => 'iPod', '/ipad/i' => 'iPad', '/android/i' => 'Android', '/blackberry/i' => 'BlackBerry', '/webos/i' => 'Mobile' ); foreach ($os_array as $regex => $value) { if (preg_match($regex, $user_agent)) { $os_platform = $value; } } return $os_platform; } function get_browser_name($user_agent = "") { if (empty($user_agent)) { $user_agent = @$_SERVER['HTTP_USER_AGENT']; } if (empty($user_agent)) { return 'Unknow'; } // Make case insensitive. $t = strtolower($user_agent); // If the string *starts* with the string, strpos returns 0 (i.e., FALSE). Do a ghetto hack and start with a space. // "[strpos()] may return Boolean FALSE, but may also return a non-Boolean value which evaluates to FALSE." // http://php.net/manual/en/function.strpos.php $t = " " . $t; // Humans / Regular Users if (isAVideoStreamer($t)) { return 'AVideo Mobile App'; } elseif ($url = isAVideoEncoder($t)) { return 'AVideo Encoder ' . $url; } elseif ($url = isAVideoStreamer($t)) { return 'AVideo Streamer ' . $url; } elseif (strpos($t, 'crkey')) { return 'Chromecast'; } elseif (strpos($t, 'opera') || strpos($t, 'opr/')) { return 'Opera'; } elseif (strpos($t, 'edge')) { return 'Edge'; } elseif (strpos($t, 'chrome')) { return 'Chrome'; } elseif (strpos($t, 'safari')) { return 'Safari'; } elseif (strpos($t, 'firefox')) { return 'Firefox'; } elseif (strpos($t, 'msie') || strpos($t, 'trident/7')) { return 'Internet Explorer'; } elseif (strpos($t, 'applecoremedia')) { return 'Native Apple Player'; } // Search Engines elseif (strpos($t, 'google')) { return '[Bot] Googlebot'; } elseif (strpos($t, 'bing')) { return '[Bot] Bingbot'; } elseif (strpos($t, 'slurp')) { return '[Bot] Yahoo! Slurp'; } elseif (strpos($t, 'duckduckgo')) { return '[Bot] DuckDuckBot'; } elseif (strpos($t, 'baidu')) { return '[Bot] Baidu'; } elseif (strpos($t, 'yandex')) { return '[Bot] Yandex'; } elseif (strpos($t, 'sogou')) { return '[Bot] Sogou'; } elseif (strpos($t, 'exabot')) { return '[Bot] Exabot'; } elseif (strpos($t, 'msn')) { return '[Bot] MSN'; } // Common Tools and Bots elseif (strpos($t, 'mj12bot')) { return '[Bot] Majestic'; } elseif (strpos($t, 'ahrefs')) { return '[Bot] Ahrefs'; } elseif (strpos($t, 'semrush')) { return '[Bot] SEMRush'; } elseif (strpos($t, 'rogerbot') || strpos($t, 'dotbot')) { return '[Bot] Moz or OpenSiteExplorer'; } elseif (strpos($t, 'frog') || strpos($t, 'screaming')) { return '[Bot] Screaming Frog'; } // Miscellaneous elseif (strpos($t, 'facebook')) { return '[Bot] Facebook'; } elseif (strpos($t, 'pinterest')) { return '[Bot] Pinterest'; } // Check for strings commonly used in bot user agents elseif (strpos($t, 'crawler') || strpos($t, 'api') || strpos($t, 'spider') || strpos($t, 'http') || strpos($t, 'bot') || strpos($t, 'archive') || strpos($t, 'info') || strpos($t, 'data')) { return '[Bot] Other'; } //_error_log("Unknow user agent ($t) IP=" . getRealIpAddr() . " URI=" . getRequestURI()); return 'Other (Unknown)'; } /** * Due some error on old chrome browsers (version < 70) on decrypt HLS keys with the videojs versions greater then 7.9.7 * we need to detect the chrome browser and load an older version * */ function isOldChromeVersion() { $global; if (empty($_SERVER['HTTP_USER_AGENT'])) { return false; } if (!empty($global['forceOldChrome'])) { return true; } if (preg_match('/Chrome\/([0-9.]+)/i', $_SERVER['HTTP_USER_AGENT'], $matches)) { return version_compare($matches[1], '80', '<='); } return false; } function TimeLogStart($name) { global $global; if (!empty($global['noDebug'])) { return false; } $time = microtime(); $time = explode(' ', $time); $time = $time[1] + $time[0]; if (empty($global['start']) || !is_array($global['start'])) { $global['start'] = array(); } $global['start'][$name] = $time; } function TimeLogEnd($name, $line, $TimeLogLimit = 0.7) { global $global; if (!empty($global['noDebug']) || empty($global['start'][$name])) { return false; } if (!empty($global['TimeLogLimit'])) { $TimeLogLimit = $global['TimeLogLimit']; } $time = microtime(); $time = explode(' ', $time); $time = $time[1] + $time[0]; $finish = $time; $total_time = round(($finish - $global['start'][$name]), 4); if (empty($global['noDebugSlowProcess']) && $total_time > $TimeLogLimit) { _error_log("Warning: Slow process detected [{$name}] On Line {$line} takes {$total_time} seconds to complete, Limit ({$TimeLogLimit}). {$_SERVER["SCRIPT_FILENAME"]}"); } TimeLogStart($name); } class AVideoLog { public static $DEBUG = 0; public static $WARNING = 1; public static $ERROR = 2; public static $SECURITY = 3; public static $SOCKET = 4; } function _error_log_debug($message, $show_args = false) { $array = debug_backtrace(); $message .= PHP_EOL; foreach ($array as $value) { $message .= "function: {$value['function']} Line: {{$value['line']}} File: {{$value['file']}}" . PHP_EOL; if ($show_args) { $message .= print_r($value['args'], true) . PHP_EOL; } } _error_log(PHP_EOL . '***' . PHP_EOL . $message . '***'); } function _error_log($message, $type = 0, $doNotRepeat = false) { if (empty($doNotRepeat)) { // do not log it too many times when you are using HLS format, other wise it will fill the log file with the same error $doNotRepeat = preg_match("/hls.php$/", $_SERVER['SCRIPT_NAME']); } if ($doNotRepeat) { return false; } global $global; if (!empty($global['noDebug']) && $type == 0) { return false; } if (!is_string($message)) { $message = json_encode($message); } $prefix = "AVideoLog::"; switch ($type) { case AVideoLog::$DEBUG: $prefix .= "DEBUG: "; break; case AVideoLog::$WARNING: $prefix .= "WARNING: "; break; case AVideoLog::$ERROR: $prefix .= "ERROR: "; break; case AVideoLog::$SECURITY: $prefix .= "SECURITY: "; break; case AVideoLog::$SOCKET: $prefix .= "SOCKET: "; break; } error_log($prefix . $message . " SCRIPT_NAME: {$_SERVER['SCRIPT_NAME']}"); } function postVariables($url, $array, $httpcodeOnly = true, $timeout = 10) { if (!$url || !is_string($url) || !preg_match('/^http(s)?:\/\/[a-z0-9-]+(.[a-z0-9-]+)*(:[0-9]+)?(\/.*)?$/i', $url)) { return false; } $array = object_to_array($array); $ch = curl_init($url); if ($httpcodeOnly) { @curl_setopt($ch, CURLOPT_HEADER, true); // we want headers @curl_setopt($ch, CURLOPT_NOBODY, true); // we don't need body } else { curl_setopt($curl, CURLOPT_USERAGENT, getSelfUserAgent()); } curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout); //The number of seconds to wait while trying to connect. Use 0 to wait indefinitely. curl_setopt($ch, CURLOPT_TIMEOUT, $timeout + 1); //The maximum number of seconds to allow cURL functions to execute. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $array); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); // execute! $response = curl_exec($ch); if ($httpcodeOnly) { $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE); // close the connection, release resources used curl_close($ch); if ($httpcode == 200) { return true; } return $httpcode; } else { curl_close($ch); return $response; } } function _session_start(array $options = array()) { try { if (!empty($_GET['PHPSESSID'])) { if ($_GET['PHPSESSID'] !== session_id()) { if (session_status() != PHP_SESSION_NONE) { @session_write_close(); } session_id($_GET['PHPSESSID']); _error_log("captcha: session_id changed to " . $_GET['PHPSESSID']); } unset($_GET['PHPSESSID']); return @session_start($options); } else if (session_status() == PHP_SESSION_NONE) { return @session_start($options); } } catch (Exception $exc) { _error_log("_session_start: " . $exc->getTraceAsString()); return false; } } function _mysql_connect() { global $global, $mysqlHost, $mysqlUser, $mysqlPass, $mysqlDatabase, $mysqlPort, $mysql_connect_was_closed; try { if (!_mysql_is_open()) { //_error_log('MySQL Connect '. json_encode(debug_backtrace())); $mysql_connect_was_closed = 0; $global['mysqli'] = new mysqli($mysqlHost, $mysqlUser, $mysqlPass, $mysqlDatabase, @$mysqlPort); if (!empty($global['mysqli_charset'])) { $global['mysqli']->set_charset($global['mysqli_charset']); } } } catch (Exception $exc) { _error_log($exc->getTraceAsString()); return false; } } function _mysql_close() { global $global, $mysql_connect_was_closed; if (_mysql_is_open()) { //_error_log('MySQL Closed '. json_encode(debug_backtrace())); $mysql_connect_was_closed = 1; @$global['mysqli']->close(); $global['mysqli'] = false; } } function _mysql_is_open() { global $global, $mysql_connect_was_closed; try { //if (is_object($global['mysqli']) && (empty($mysql_connect_was_closed) || !empty(@$global['mysqli']->ping()))) { if (!empty($global['mysqli']) && is_object($global['mysqli']) && empty($mysql_connect_was_closed)) { return true; } } catch (Exception $exc) { return false; } return false; } function remove_utf8_bom($text) { if (strlen($text) > 1000000) { return $text; } $bom = pack('H*', 'EFBBBF'); $text = preg_replace("/^$bom/", '', $text); return $text; } function getCacheDir() { $p = AVideoPlugin::loadPlugin("Cache"); return $p->getCacheDir(); } function clearCache($firstPageOnly = false) { global $global; $dir = getVideosDir() . "cache" . DIRECTORY_SEPARATOR; if ($firstPageOnly || !empty($_GET['FirstPage'])) { $dir .= "firstPage" . DIRECTORY_SEPARATOR; } //_error_log('clearCache 1: '.$dir); rrmdir($dir); $dir = getCacheDir(); if ($firstPageOnly || !empty($_GET['FirstPage'])) { $dir .= "firstPage" . DIRECTORY_SEPARATOR; } //_error_log('clearCache 2: '.$dir); rrmdir($dir); $dir = getTmpDir() . 'YPTObjectCache' . DIRECTORY_SEPARATOR; if ($firstPageOnly || !empty($_GET['FirstPage'])) { $dir .= "firstPage" . DIRECTORY_SEPARATOR; } //_error_log('clearCache 3: '.$dir); rrmdir($dir); ObjectYPT::deleteCache("getEncoderURL"); } function getUsageFromFilename($filename, $dir = "") { global $global; if (!empty($global['getUsageFromFilename'])) { // manually add this variable in your configuration.php file to not scan your video usage return 0; } if (empty($dir)) { $paths = Video::getPaths($filename); $dir = $paths['path']; } $dir = addLastSlash($dir); $totalSize = 0; _error_log("getUsageFromFilename: start {$dir}{$filename}"); //$files = glob("{$dir}{$filename}*"); $paths = Video::getPaths($filename); if (is_dir($paths['path'])) { $files = array($paths['path']); } else { $files = globVideosDir($filename); } //var_dump($paths, $files, $filename);exit; session_write_close(); $filesProcessed = array(); if (empty($files)) { _error_log("getUsageFromFilename: we did not find any file for {$dir}{$filename}, we will create a fake one " . json_encode(debug_backtrace())); make_path($dir); file_put_contents("{$dir}{$filename}.notfound", time()); $totalSize = 10; } else { foreach ($files as $f) { if (strpos($f, '.size.lock') !== false) { continue; } if (is_dir($f)) { _error_log("getUsageFromFilename: {$f} is Dir"); $dirSize = getDirSize($f); $totalSize += $dirSize; $minDirSize = 4000000; $isEnabled = AVideoPlugin::isEnabledByName('YPTStorage'); if ($dirSize < $minDirSize && $isEnabled) { // probably the HLS file is hosted on the YPTStorage $info = YPTStorage::getFileInfo($filename); if (!empty($info->size)) { _error_log("getUsageFromFilename: found info on the YPTStorage " . print_r($info, true)); $totalSize += $info->size; } else { _error_log("getUsageFromFilename: there is no info on the YPTStorage " . print_r($info, true)); } } else { if (!($dirSize < $minDirSize)) { _error_log("getUsageFromFilename: does not have the size to process $dirSize < $minDirSize"); } if (!$isEnabled) { _error_log("getUsageFromFilename: YPTStorage is disabled"); } } } elseif (is_file($f)) { $filesize = filesize($f); if ($filesize < 20) { // that means it is a dummy file $lockFile = $f . ".size.lock"; if (!file_exists($lockFile) || (time() - 600) > filemtime($lockFile)) { file_put_contents($lockFile, time()); _error_log("getUsageFromFilename: {$f} is Dummy file ({$filesize})"); $aws_s3 = AVideoPlugin::loadPluginIfEnabled('AWS_S3'); //$bb_b2 = AVideoPlugin::loadPluginIfEnabled('Blackblaze_B2'); if (!empty($aws_s3)) { _error_log("getUsageFromFilename: Get from S3"); $filesize += $aws_s3->getFilesize($filename); } elseif (!empty($bb_b2)) { // TODO } else { $urls = Video::getVideosPaths($filename, true); _error_log("getUsageFromFilename: Paths " . json_encode($urls)); if (!empty($urls["m3u8"]['url'])) { $filesize += getUsageFromURL($urls["m3u8"]['url']); } if (!empty($urls['mp4'])) { foreach ($urls['mp4'] as $mp4) { if (in_array($mp4, $filesProcessed)) { continue; } $filesProcessed[] = $mp4; $filesize += getUsageFromURL($mp4); } } if (!empty($urls['webm'])) { foreach ($urls['webm'] as $mp4) { if (in_array($mp4, $filesProcessed)) { continue; } $filesProcessed[] = $mp4; $filesize += getUsageFromURL($mp4); } } if (!empty($urls["pdf"]['url'])) { $filesize += getUsageFromURL($urls["pdf"]['url']); } if (!empty($urls["image"]['url'])) { $filesize += getUsageFromURL($urls["image"]['url']); } if (!empty($urls["zip"]['url'])) { $filesize += getUsageFromURL($urls["zip"]['url']); } if (!empty($urls["mp3"]['url'])) { $filesize += getUsageFromURL($urls["mp3"]['url']); } } unlink($lockFile); } } else { _error_log("getUsageFromFilename: {$f} is File ({$filesize})"); } $totalSize += $filesize; } } } return $totalSize; } /** * Returns the size of a file without downloading it, or -1 if the file * size could not be determined. * * @param $url - The location of the remote file to download. Cannot * be null or empty. * * @return The size of the file referenced by $url, or false if the size * could not be determined. */ function getUsageFromURL($url) { global $global; if (!empty($global['doNotGetUsageFromURL'])) { // manually add this variable in your configuration.php file to not scan your video usage return 0; } _error_log("getUsageFromURL: start ({$url})"); // Assume failure. $result = false; $curl = curl_init($url); _error_log("getUsageFromURL: curl_init "); try { // Issue a HEAD request and follow any redirects. curl_setopt($curl, CURLOPT_NOBODY, true); curl_setopt($curl, CURLOPT_HEADER, true); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true); //curl_setopt($curl, CURLOPT_USERAGENT, get_user_agent_string()); $data = curl_exec($curl); } catch (Exception $exc) { echo $exc->getTraceAsString(); _error_log("getUsageFromURL: ERROR " . $exc->getMessage()); _error_log("getUsageFromURL: ERROR " . curl_errno($curl)); _error_log("getUsageFromURL: ERROR " . curl_error($curl)); } if ($data) { _error_log("getUsageFromURL: response header " . $data); $content_length = "unknown"; $status = "unknown"; if (preg_match("/^HTTP\/1\.[01] (\d\d\d)/", $data, $matches)) { $status = (int) $matches[1]; } if (preg_match("/Content-Length: (\d+)/", $data, $matches)) { $content_length = (int) $matches[1]; } // http://en.wikipedia.org/wiki/List_of_HTTP_status_codes if ($status == 200 || ($status > 300 && $status <= 308)) { $result = $content_length; } } else { _error_log("getUsageFromURL: ERROR no response data " . curl_error($curl)); } curl_close($curl); return (int) $result; } function getDirSize($dir) { _error_log("getDirSize: start {$dir}"); if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') { return foldersize($dir); } else { $command = "du -sb {$dir}"; exec($command . " < /dev/null 2>&1", $output, $return_val); if ($return_val !== 0) { _error_log("getDirSize: ERROR ON Command {$command}"); return 0; } else { if (!empty($output[0])) { preg_match("/^([0-9]+).*/", $output[0], $matches); } if (!empty($matches[1])) { _error_log("getDirSize: found {$matches[1]} from - {$output[0]}"); return intval($matches[1]); } _error_log("getDirSize: ERROR on pregmatch {$output[0]}"); return 0; } } } function foldersize($path) { $total_size = 0; $files = scandir($path); $cleanPath = rtrim($path, '/') . '/'; foreach ($files as $t) { if ($t <> "." && $t <> "..") { $currentFile = $cleanPath . $t; if (is_dir($currentFile)) { $size = foldersize($currentFile); $total_size += $size; } else { $size = filesize($currentFile); $total_size += $size; } } } return $total_size; } function getDiskUsage() { global $global; $dir = getVideosDir() . ""; $obj = new stdClass(); $obj->disk_free_space = disk_free_space($dir); $obj->disk_total_space = disk_total_space($dir); $obj->videos_dir = getDirSize($dir); $obj->disk_used = $obj->disk_total_space - $obj->disk_free_space; $obj->disk_used_by_other = $obj->disk_used - $obj->videos_dir; $obj->disk_free_space_human = humanFileSize($obj->disk_free_space); $obj->disk_total_space_human = humanFileSize($obj->disk_total_space); $obj->videos_dir_human = humanFileSize($obj->videos_dir); $obj->disk_used_human = humanFileSize($obj->disk_used); $obj->disk_used_by_other_human = humanFileSize($obj->disk_used_by_other); // percentage of disk used $obj->disk_used_percentage = sprintf('%.2f', ($obj->disk_used / $obj->disk_total_space) * 100); $obj->videos_dir_used_percentage = sprintf('%.2f', ($obj->videos_dir / $obj->disk_total_space) * 100); $obj->disk_free_space_percentage = sprintf('%.2f', ($obj->disk_free_space / $obj->disk_total_space) * 100); return $obj; } function unsetSearch() { unset($_GET['searchPhrase'], $_POST['searchPhrase'], $_GET['search'], $_GET['q']); } function encrypt_decrypt($string, $action) { global $global; $output = false; $encrypt_method = "AES-256-CBC"; $secret_key = 'This is my secret key'; $secret_iv = $global['systemRootPath']; while (strlen($secret_iv) < 16) { $secret_iv .= $global['systemRootPath']; } if (empty($secret_iv)) { $secret_iv = '1234567890abcdef'; } // hash $key = hash('sha256', $global['salt']); // iv - encrypt method AES-256-CBC expects 16 bytes - else you will get a warning $iv = substr(hash('sha256', $secret_iv), 0, 16); if ($action == 'encrypt') { $output = openssl_encrypt($string, $encrypt_method, $key, 0, $iv); $output = base64_encode($output); } elseif ($action == 'decrypt') { $output = openssl_decrypt(base64_decode($string), $encrypt_method, $key, 0, $iv); } return $output; } function compressString($string) { if (function_exists("gzdeflate")) { $string = gzdeflate($string, 9); } return $string; } function decompressString($string) { if (function_exists("gzinflate")) { $string = gzinflate($string); } return $string; } function encryptString($string) { if (is_object($string)) { $string = json_encode($string); } return encrypt_decrypt($string, 'encrypt'); } function decryptString($string) { return encrypt_decrypt($string, 'decrypt'); } function getToken($timeout = 0, $salt = "") { global $global; $obj = new stdClass(); $obj->salt = $global['salt'] . $salt; if (!empty($timeout)) { $obj->time = time(); $obj->timeout = $obj->time + $timeout; } else { $obj->time = strtotime("Today 00:00:00"); $obj->timeout = strtotime("Today 23:59:59"); $obj->timeout += cacheExpirationTime(); } $strObj = json_encode($obj); //_error_log("Token created: {$strObj}"); return encryptString($strObj); } function isTokenValid($token, $salt = "") { return verifyToken($token, $salt); } function verifyToken($token, $salt = "") { global $global; $obj = _json_decode(decryptString($token)); if (empty($obj)) { _error_log("verifyToken invalid token"); return false; } if ($obj->salt !== $global['salt'] . $salt) { _error_log("verifyToken salt fail"); return false; } $time = time(); if (!($time >= $obj->time && $time <= $obj->timeout)) { _error_log("verifyToken token timout time = $time; obj->time = $obj->time; obj->timeout = $obj->timeout"); return false; } return true; } class YPTvideoObject { public $id; public $title; public $description; public $thumbnails; public $channelTitle; public $videoLink; public function __construct($id, $title, $description, $thumbnails, $channelTitle, $videoLink) { $this->id = $id; $this->title = $title; $this->description = $description; $this->thumbnails = $thumbnails; $this->channelTitle = $channelTitle; $this->videoLink = $videoLink; } } function isToShowDuration($type) { $notShowTo = array('pdf', 'article', 'serie', 'zip', 'image', 'live', 'livelinks'); if (in_array($type, $notShowTo)) { return false; } else { return true; } } function _dieAndLogObject($obj, $prefix = "") { $objString = json_encode($obj); _error_log($prefix . $objString); die($objString); } function isAVideoPlayer() { if (isVideo() || isSerie()) { return true; } return false; } function isFirstPage() { global $isFirstPage, $global; return !empty($isFirstPage) || getSelfURI() === "{$global['webSiteRootURL']}view/"; } function isVideo() { global $isModeYouTube, $global; if (!empty($global['doNotLoadPlayer'])) { return false; } return !empty($isModeYouTube) || isPlayList() || isEmbed() || isLive(); } function isVideoTypeEmbed() { global $isVideoTypeEmbed; if (isVideo() && !empty($isVideoTypeEmbed) && $videos_id = getVideos_id()) { return $videos_id; } return false; } function isAudio() { global $isAudio; return !empty($isAudio); } function isSerie() { return isPlayList(); } function isPlayList() { global $isPlayList, $isSerie; return !empty($isSerie) || !empty($isPlayList); } function isChannel() { global $isChannel; if (!empty($isChannel) && !isVideo()) { $user_id = 0; if (empty($_GET['channelName'])) { if (User::isLogged()) { $user_id = User::getId(); } else { return false; } } else { $_GET['channelName'] = xss_esc($_GET['channelName']); $user = User::getChannelOwner($_GET['channelName']); if (!empty($user)) { $user_id = $user['id']; } else { $user_id = $_GET['channelName']; } } return $user_id; } return false; } function isEmbed() { global $isEmbed, $global; if (!empty($global['doNotLoadPlayer'])) { return false; } return !empty($isEmbed); } function isWebRTC() { global $isWebRTC, $global; if (!empty($global['doNotLoadPlayer'])) { return false; } return !empty($isWebRTC); } function isLive() { global $isLive, $global; if (!empty($global['doNotLoadPlayer'])) { return false; } if (!empty($isLive)) { $live = getLiveKey(); if (empty($live)) { $live = array('key' => false, 'live_servers_id' => false, 'live_index' => false); } $live['liveLink'] = isLiveLink(); return $live; } else { return false; } } function isLiveLink() { global $isLiveLink; if (!empty($isLiveLink)) { return $isLiveLink; } else { return false; } } function getLiveKey() { global $getLiveKey; if (empty($getLiveKey)) { return false; } return $getLiveKey; } function setLiveKey($key, $live_servers_id, $live_index = '') { global $getLiveKey; $parameters = Live::getLiveParametersFromKey($key); $key = $parameters['key']; $cleanKey = $parameters['cleanKey']; if (empty($live_index)) { $live_index = $parameters['live_index']; } $key = Live::getLiveKeyFromRequest($key, $live_index, $parameters['playlists_id_live']); $getLiveKey = array('key' => $key, 'live_servers_id' => intval($live_servers_id), 'live_index' => $live_index, 'cleanKey' => $cleanKey); return $getLiveKey; } function isVideoPlayerHasProgressBar() { if (isWebRTC()) { return false; } if (isLive()) { $obj = AVideoPlugin::getObjectData('Live'); if (empty($obj->disableDVR)) { return true; } } elseif (isAVideoPlayer()) { return true; } return false; } function isHLS() { global $video, $global; if (isLive()) { return true; } elseif (!empty($video) && $video['type'] == 'video' && file_exists(Video::getPathToFile("{$video['filename']}/index.m3u8"))) { return true; } return false; } function getRedirectUri() { if (!empty($_GET['redirectUri'])) { return $_GET['redirectUri']; } if (!empty($_SERVER["HTTP_REFERER"])) { return $_SERVER["HTTP_REFERER"]; } return getRequestURI(); } function getRedirectToVideo($videos_id) { $redirectUri = getRedirectUri(); $isEmbed = 0; if (stripos($redirectUri, "embed") !== false) { $isEmbed = 1; } $video = Video::getVideoLight($videos_id); if (empty($video)) { return false; } return Video::getLink($videos_id, $video['clean_title'], $isEmbed); } function getRequestURI() { if (empty($_SERVER['REQUEST_URI'])) { return ""; } return (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http") . "://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]"; } function getSelfURI() { if (empty($_SERVER['PHP_SELF']) || empty($_SERVER['HTTP_HOST'])) { return ""; } $queryStringWithoutError = preg_replace("/error=[^&]*/", "", @$_SERVER['QUERY_STRING']); $phpselfWithoutIndex = preg_replace("/index.php/", "", @$_SERVER['PHP_SELF']); $url = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http") . "://$_SERVER[HTTP_HOST]$phpselfWithoutIndex?$queryStringWithoutError"; $url = rtrim($url, '?'); return $url; } function isSameVideoAsSelfURI($url) { return URLsAreSameVideo($url, getSelfURI()); } function URLsAreSameVideo($url1, $url2) { $videos_id1 = getVideoIDFromURL($url1); $videos_id2 = getVideoIDFromURL($url2); if (empty($videos_id1) || empty($videos_id2)) { return false; } return $videos_id1 === $videos_id2; } function getVideos_id() { global $_getVideos_id; $videos_id = false; if (isset($_getVideos_id) && is_int($_getVideos_id)) { return $_getVideos_id; } if (isVideo()) { $videos_id = getVideoIDFromURL(getSelfURI()); if (empty($videos_id) && !empty($_REQUEST['videoName'])) { $video = Video::getVideoFromCleanTitle($_REQUEST['videoName']); if (!empty($video)) { $videos_id = $video['id']; } } setVideos_id($videos_id); } if (empty($videos_id) && !empty($_REQUEST['playlists_id'])) { AVideoPlugin::loadPlugin('PlayLists'); $video = PlayLists::isPlayListASerie($_REQUEST['playlists_id']); if (!empty($video)) { $videos_id = $video['id']; } } if (empty($videos_id) && !empty($_REQUEST['v'])) { $videos_id = $_REQUEST['v']; } $videos_id = videosHashToID($videos_id); return $videos_id; } function setVideos_id($videos_id) { global $_getVideos_id; $_getVideos_id = $videos_id; } function getPlaylists_id() { global $_isPlayList; if (!isset($_isPlayList)) { $_isPlayList = false; if (isPlayList()) { $_isPlayList = intval(@$_GET['playlists_id']); if (empty($_isPlayList)) { $videos_id = getVideos_id(); if (empty($videos_id)) { $_isPlayList = false; } else { $v = Video::getVideoLight($videos_id); if (empty($v) || empty($v['serie_playlists_id'])) { $_isPlayList = false; } else { $_isPlayList = $v['serie_playlists_id']; } } } } } return $_isPlayList; } function isVideoOrAudioNotEmbed() { if (!isVideo()) { return false; } $videos_id = getVideos_id(); if (empty($videos_id)) { return false; } $v = Video::getVideoLight($videos_id); if (empty($v)) { return false; } $types = array('audio', 'video'); if (in_array($v['type'], $types)) { return true; } return false; } function getVideoIDFromURL($url) { if (preg_match("/v=([0-9]+)/", $url, $matches)) { return intval($matches[1]); } if (preg_match('/\/(video|videoEmbed|v|vEmbed|article|articleEmbed)\/([0-9]+)/', $url, $matches)) { return intval($matches[1]); } if (AVideoPlugin::isEnabledByName('PlayLists')) { if (preg_match('/player.php\?playlists_id=([0-9]+)/', $url, $matches)) { $serie_playlists_id = intval($matches[1]); $video = PlayLists::isPlayListASerie($serie_playlists_id); if ($video) { return $video['id']; } } } if (preg_match("/v=(\.[0-9a-zA-Z_-]+)/", $url, $matches)) { return hashToID($matches[1]); } if (preg_match('/\/(video|videoEmbed|v|vEmbed|article|articleEmbed)\/(\.[0-9a-zA-Z_-]+)/', $url, $matches)) { return hashToID($matches[2]); } return false; } function getBackURL() { global $global; $backURL = getRedirectUri(); if (empty($backURL)) { $backURL = getRequestURI(); } if (isSameVideoAsSelfURI($backURL)) { $backURL = getHomeURL(); } return $backURL; } function getHomeURL() { global $global, $advancedCustomUser, $advancedCustom; if (isValidURL($advancedCustomUser->afterLoginGoToURL)) { return $advancedCustomUser->afterLoginGoToURL; } elseif (isValidURL($advancedCustom->logoMenuBarURL) && isSameDomainAsMyAVideo($advancedCustom->logoMenuBarURL)) { return $advancedCustom->logoMenuBarURL; } return $global['webSiteRootURL']; } function isValidURL($url) { //var_dump(empty($url), !is_string($url), preg_match("/^http.*/", $url), filter_var($url, FILTER_VALIDATE_URL)); if (empty($url) || !is_string($url)) { return false; } if (preg_match("/^http.*/", $url) && filter_var($url, FILTER_VALIDATE_URL)) { return true; } return false; } function hasLastSlash($word) { return substr($word, -1) === '/'; } function addLastSlash($word) { return $word . (hasLastSlash($word) ? "" : "/"); } function URLHasLastSlash() { return hasLastSlash($_SERVER["REQUEST_URI"]); } function ucname($str) { $str = ucwords(strtolower($str)); foreach (array('\'', '-') as $delim) { if (strpos($str, $delim) !== false) { $str = implode($delim, array_map('ucfirst', explode($delim, $str))); } } return $str; } function sanitize_input($input) { return htmlentities(strip_tags($input)); } function sanitize_array_item(&$item, $key) { $item = sanitize_input($item); } function getSEOComplement($parameters = array()) { global $config; $allowedTypes = isset($parameters["allowedTypes"]) ? $parameters["allowedTypes"] : null; $addAutoPrefix = isset($parameters["addAutoPrefix"]) ? $parameters["addAutoPrefix"] : true; $addCategory = isset($parameters["addCategory"]) ? $parameters["addCategory"] : true; $parts = array(); if (!empty($_GET['error'])) { array_push($parts, __("Error")); } if ($addCategory && !empty($_GET['catName'])) { array_push($parts, $_GET['catName']); } if (!empty($_GET['channelName'])) { array_push($parts, $_GET['channelName']); } if (!empty($_GET['type'])) { $type = $_GET['type']; if (empty($allowedTypes) || in_array(strtolower($type), $allowedTypes)) { array_push($parts, __(ucname($type))); } } if (!empty($_GET['showOnly'])) { array_push($parts, $_GET['showOnly']); } if (!empty($_GET['page'])) { $page = intval($_GET['page']); if ($page > 1) { array_push($parts, sprintf(__("Page %d"), $page)); } } // Cleaning all entries in the $parts array array_walk($parts, 'sanitize_array_item'); $txt = implode($config->getPageTitleSeparator(), $parts); $txt = (!empty($txt) && $addAutoPrefix ? $config->getPageTitleSeparator() : "") . $txt; return $txt; } function getCurrentPage() { if (!empty($_REQUEST['current'])) { return intval($_REQUEST['current']); } elseif (!empty($_POST['current'])) { return intval($_POST['current']); } elseif (!empty($_GET['current'])) { return intval($_GET['current']); } elseif (isset($_GET['start']) && isset($_GET['length'])) { // for the bootgrid $start = intval($_GET['start']); $length = intval($_GET['length']); if (!empty($start) && !empty($length)) { return floor($start / $length) + 1; } } return 1; } function getRowCount($default = 1000) { global $global; if (!empty($_REQUEST['rowCount'])) { $defaultN = intval($_REQUEST['rowCount']); } elseif (!empty($_POST['rowCount'])) { $defaultN = intval($_POST['rowCount']); } elseif (!empty($_GET['rowCount'])) { $defaultN = intval($_GET['rowCount']); } elseif (!empty($_REQUEST['length'])) { $defaultN = intval($_REQUEST['length']); } elseif (!empty($_POST['length'])) { $defaultN = intval($_POST['length']); } elseif (!empty($_GET['length'])) { $defaultN = intval($_GET['length']); } elseif (!empty($global['rowCount'])) { $defaultN = intval($global['rowCount']); } return (!empty($defaultN) && $defaultN > 0) ? $defaultN : $default; } function getSearchVar() { if (!empty($_REQUEST['search'])) { return $_REQUEST['search']; } elseif (!empty($_REQUEST['q'])) { return $_REQUEST['q']; } if (!empty($_REQUEST['searchPhrase'])) { return $_REQUEST['searchPhrase']; } elseif (!empty($_REQUEST['search']['value'])) { return $_REQUEST['search']['value']; } return ""; } $cleanSearchHistory = ""; function cleanSearchVar() { global $cleanSearchHistory; $search = getSearchVar(); if (!empty($search)) { $cleanSearchHistory = $search; } $searchIdex = array('q', 'searchPhrase', 'search'); foreach ($searchIdex as $value) { unset($_REQUEST[$value], $_POST[$value], $_GET[$value]); } } function reloadSearchVar() { global $cleanSearchHistory; $_REQUEST['search'] = $cleanSearchHistory; if (empty($_GET['search'])) { $_GET['search'] = $cleanSearchHistory; } if (empty($_POST['search'])) { $_POST['search'] = $cleanSearchHistory; } } function wget($url, $filename, $debug = false) { if (empty($url) || $url == "php://input" || !preg_match("/^http/", $url)) { return false; } if (wgetIsLocked($url)) { if ($debug) { _error_log("wget: ERROR the url is already downloading $url, $filename"); } return false; } wgetLock($url); if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') { $content = @file_get_contents($url); if (!empty($content) && file_put_contents($filename, $content) > 100) { wgetRemoveLock($url); return true; } wgetRemoveLock($url); return false; } $cmd = "wget --tries=1 {$url} -O {$filename} --no-check-certificate"; if ($debug) { _error_log("wget Start ({$cmd}) "); } //echo $cmd; exec($cmd); wgetRemoveLock($url); if (!file_exists($filename)) { _error_log("wget: ERROR the url does not download $url, $filename"); return false; } if ($_SERVER['SCRIPT_NAME'] !== '/plugin/Live/m3u8.php' && empty(filesize($filename))) { _error_log("wget: ERROR the url download but is empty $url, $filename"); return true; } return false; } /** * Copy remote file over HTTP one small chunk at a time. * * @param $infile The full URL to the remote file * @param $outfile The path where to save the file */ function copyfile_chunked($infile, $outfile) { $chunksize = 10 * (1024 * 1024); // 10 Megs /** * parse_url breaks a part a URL into it's parts, i.e. host, path, * query string, etc. */ $parts = parse_url($infile); $i_handle = fsockopen($parts['host'], 80, $errstr, $errcode, 5); $o_handle = fopen($outfile, 'wb'); if ($i_handle == false || $o_handle == false) { return false; } if (!empty($parts['query'])) { $parts['path'] .= '?' . $parts['query']; } /** * Send the request to the server for the file */ $request = "GET {$parts['path']} HTTP/1.1\r\n"; $request .= "Host: {$parts['host']}\r\n"; $request .= "User-Agent: Mozilla/5.0\r\n"; $request .= "Keep-Alive: 115\r\n"; $request .= "Connection: keep-alive\r\n\r\n"; fwrite($i_handle, $request); /** * Now read the headers from the remote server. We'll need * to get the content length. */ $headers = array(); while (!feof($i_handle)) { $line = fgets($i_handle); if ($line == "\r\n") break; $headers[] = $line; } /** * Look for the Content-Length header, and get the size * of the remote file. */ $length = 0; foreach ($headers as $header) { if (stripos($header, 'Content-Length:') === 0) { $length = (int) str_replace('Content-Length: ', '', $header); break; } } /** * Start reading in the remote file, and writing it to the * local file one chunk at a time. */ $cnt = 0; while (!feof($i_handle)) { $buf = ''; $buf = fread($i_handle, $chunksize); $bytes = fwrite($o_handle, $buf); if ($bytes == false) { return false; } $cnt += $bytes; /** * We're done reading when we've reached the conent length */ if ($cnt >= $length) break; } fclose($i_handle); fclose($o_handle); return $cnt; } function wgetLockFile($url) { return getTmpDir("YPTWget") . md5($url) . ".lock"; } function wgetLock($url) { $file = wgetLockFile($url); return file_put_contents($file, time() . PHP_EOL, FILE_APPEND | LOCK_EX); } function wgetRemoveLock($url) { $filename = wgetLockFile($url); if (!file_exists($filename)) { return false; } return unlink($filename); } function getLockFile($name) { return getTmpDir("YPTLockFile") . md5($name) . ".lock"; } function setLock($name) { $file = getLockFile($name); return file_put_contents($file, time()); } function isLock($name, $timeout = 60) { $file = getLockFile($name); if (file_exists($file)) { $time = intval(file_get_contents($file)); if ($time + $timeout < time()) { return false; } } } function removeLock($name) { $filename = getLockFile($name); if (!file_exists($filename)) { return false; } return unlink($filename); } function wgetIsLocked($url) { $filename = wgetLockFile($url); if (!file_exists($filename)) { return false; } $time = intval(file_get_contents($filename)); if (time() - $time > 36000) { // more then 10 hours unlink($filename); return false; } return true; } // due the some OS gives a fake is_writable response function isWritable($dir) { $dir = rtrim($dir, '/') . '/'; $file = $dir . uniqid(); $result = false; $time = time(); if (@file_put_contents($file, $time)) { if ($fileTime = @file_get_contents($file)) { if ($fileTime == $time) { $result = true; } } } @unlink($file); return $result; } function _isWritable($dir) { if (!isWritable($dir)) { return false; } $tmpFile = "{$dir}" . uniqid(); $bytes = @file_put_contents($tmpFile, time()); @unlink($tmpFile); return !empty($bytes); } function getTmpDir($subdir = "") { global $global; if (empty($_SESSION['getTmpDir'])) { $_SESSION['getTmpDir'] = array(); } if (empty($_SESSION['getTmpDir'][$subdir . "_"])) { if (empty($global['tmpDir'])) { $tmpDir = sys_get_temp_dir(); if (empty($tmpDir) || !_isWritable($tmpDir)) { $tmpDir = getVideosDir() . "cache" . DIRECTORY_SEPARATOR; } $tmpDir = rtrim($tmpDir, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR; $tmpDir = "{$tmpDir}{$subdir}"; } else { $tmpDir = $global['tmpDir']; } $tmpDir = addLastSlash($tmpDir); if (!is_dir($tmpDir)) { mkdir($tmpDir, 0755, true); } _session_start(); $_SESSION['getTmpDir'][$subdir . "_"] = $tmpDir; } else { $tmpDir = $_SESSION['getTmpDir'][$subdir . "_"]; } return $tmpDir; } function getTmpFile() { return getTmpDir("tmpFiles") . uniqid(); } function getMySQLDate() { global $global; $sql = "SELECT now() as time FROM configurations LIMIT 1"; // I had to add this because the about from customize plugin was not loading on the about page http://127.0.0.1/AVideo/about $res = sqlDAL::readSql($sql); $data = sqlDAL::fetchAssoc($res); sqlDAL::close($res); if ($res) { $row = $data['time']; } else { $row = false; } return $row; } function _file_put_contents($filename, $data, $flags = 0, $context = null) { make_path($filename); return file_put_contents($filename, $data, $flags, $context); } function html2plainText($html) { $text = strip_tags($html); $text = str_replace(array('\\', "\n", "\r", '"'), array('', ' ', ' ', ''), trim($text)); return $text; } function getInputPassword($id, $attributes = 'class="form-control"', $paceholder = '') { if (empty($paceholder)) { $paceholder = __("Password"); } ?>
>
>
" . PHP_EOL; } else { return __LINE__; } $object = object_to_array($object); $json = json_encode($object); if (json_last_error()) { echo "Error 1 Found after array conversion: " . json_last_error_msg() . "
" . PHP_EOL; } else { return __LINE__; } $json = json_encode($object, JSON_UNESCAPED_UNICODE); if (json_last_error()) { echo "Error 1 Found with JSON_UNESCAPED_UNICODE: " . json_last_error_msg() . "
" . PHP_EOL; } else { return __LINE__; } $objectEncoded = $object; array_walk_recursive($objectEncoded, function (&$item) { if (is_string($item)) { $item = utf8_encode($item); } }); $json = json_encode($objectEncoded); if (json_last_error()) { echo "Error 2 Found after array conversion: " . json_last_error_msg() . "
" . PHP_EOL; } else { return __LINE__; } $json = json_encode($objectEncoded, JSON_UNESCAPED_UNICODE); if (json_last_error()) { echo "Error 2 Found with JSON_UNESCAPED_UNICODE: " . json_last_error_msg() . "
" . PHP_EOL; } else { return __LINE__; } $objectDecoded = $object; array_walk_recursive($objectDecoded, function (&$item) { if (is_string($item)) { $item = utf8_decode($item); } }); $json = json_encode($objectDecoded); if (json_last_error()) { echo "Error 2 Found after array conversion: " . json_last_error_msg() . "
" . PHP_EOL; } else { return __LINE__; } $json = json_encode($objectDecoded, JSON_UNESCAPED_UNICODE); if (json_last_error()) { echo "Error 2 Found with JSON_UNESCAPED_UNICODE: " . json_last_error_msg() . "
" . PHP_EOL; } else { return __LINE__; } return false; } function _json_encode($object) { if (empty($object)) { return false; } if (is_string($object)) { return $object; } $json = json_encode($object); if (json_last_error()) { _error_log("_json_encode: Error 1 Found: " . json_last_error_msg()); $object = object_to_array($object); $json = json_encode($object); if (json_last_error()) { _error_log("_json_encode: Error 2 Found: " . json_last_error_msg()); $json = json_encode($object, JSON_UNESCAPED_UNICODE); if (json_last_error()) { _error_log("_json_encode: Error 3 Found: " . json_last_error_msg()); $objectEncoded = $object; array_walk_recursive($objectEncoded, function (&$item) { if (is_string($item)) { $item = utf8_encode($item); } }); $json = json_encode($objectEncoded); if (json_last_error()) { _error_log("_json_encode: Error 4 Found: " . json_last_error_msg()); $json = json_encode($objectEncoded, JSON_UNESCAPED_UNICODE); if (json_last_error()) { _error_log("_json_encode: Error 5 Found: " . json_last_error_msg()); $objectDecoded = $object; array_walk_recursive($objectDecoded, function (&$item) { if (is_string($item)) { $item = utf8_decode($item); } }); $json = json_encode($objectDecoded); if (json_last_error()) { _error_log("_json_encode: Error 6 Found: " . json_last_error_msg()); $json = json_encode($objectDecoded, JSON_UNESCAPED_UNICODE); if (json_last_error()) { _error_log("_json_encode: Error 7 Found: " . json_last_error_msg()); } } } } } } } return $json; } function _json_decode($object) { if (empty($object)) { return false; } if (!is_string($object)) { return $object; } $json = json_decode($object); if ($json === NULL) { $object = str_replace(array("\r", "\n"), array('\r', '\n'), $object); return json_decode($object); } else { return $json; } } // this will make sure the strring will fits in the database field function _substr($string, $start, $length = null) { // make sure the name is not chunked in case of multibyte string if (function_exists("mb_strcut")) { return mb_strcut($string, $start, $length, "UTF-8"); } else { return substr($string, $start, $length); } } function getPagination($total, $page = 0, $link = "", $maxVisible = 10, $infinityScrollGetFromSelector = "", $infinityScrollAppendIntoSelector = "") { global $global, $advancedCustom; if ($total < 2) { return ''; } if (empty($page)) { $page = getCurrentPage(); } $isInfiniteScroll = !empty($infinityScrollGetFromSelector) && !empty($infinityScrollAppendIntoSelector); $uid = md5($link); if ($total < $maxVisible) { $maxVisible = $total; } if (empty($link)) { $link = getSelfURI(); if (preg_match("/(current=[0-9]+)/i", $link, $match)) { $link = str_replace($match[1], "current={page}", $link); } else { //$link = addQueryStringParameter($link, 'current', '{page}'); $link .= (parse_url($link, PHP_URL_QUERY) ? '&' : '?') . 'current={page}'; } } $class = ""; if (!empty($infinityScrollGetFromSelector) && !empty($infinityScrollAppendIntoSelector)) { $class = "infiniteScrollPagination{$uid} hidden"; } if ($isInfiniteScroll && $page > 1) { if (preg_match("/\{page\}/", $link, $match)) { $pageForwardLink = str_replace("{page}", $page + 1, $link); } else { $pageForwardLink = addQueryStringParameter($link, 'current', $page + 1); } return ""; } $pag = ' '; if ($isInfiniteScroll) { $content = file_get_contents($global['systemRootPath'] . 'objects/functiongetPagination.php'); $pag .= str_replace( array('$uid', '$webSiteRootURL', '$infinityScrollGetFromSelector', '$infinityScrollAppendIntoSelector'), array($uid, $global['webSiteRootURL'], $infinityScrollGetFromSelector, $infinityScrollAppendIntoSelector), $content ); } return $pag; } function getShareMenu($title, $permaLink, $URLFriendly, $embedURL, $img, $class = "row bgWhite list-group-item menusDiv", $videoLengthInSeconds = 0) { global $global, $advancedCustom; include $global['systemRootPath'] . 'objects/functiongetShareMenu.php'; } function getSharePopupButton($videos_id, $url = "", $title = "") { global $global, $advancedCustom; if ($advancedCustom->disableShareOnly || $advancedCustom->disableShareAndPlaylist) { return false; } $video['id'] = $videos_id; include $global['systemRootPath'] . 'view/include/socialModal.php'; } function forbiddenPage($message, $logMessage = false) { global $global; $_REQUEST['403ErrorMsg'] = $message; if ($logMessage) { _error_log($message); } include $global['systemRootPath'] . 'view/forbiddenPage.php'; exit; } define('E_FATAL', E_ERROR | E_USER_ERROR | E_PARSE | E_CORE_ERROR | E_COMPILE_ERROR | E_RECOVERABLE_ERROR); if (!isCommandLineInterface() && !isAVideoEncoder()) { register_shutdown_function('avidoeShutdown'); } function avidoeShutdown() { global $global; $error = error_get_last(); if ($error && ($error['type'] & E_FATAL)) { _error_log($error, AVideoLog::$ERROR); header($_SERVER['SERVER_PROTOCOL'] . ' 500 Internal Server Error', true, 500); if (!User::isAdmin()) { if (!preg_match('/json\.php$/i', $_SERVER['PHP_SELF'])) { echo '' . PHP_EOL; include $global['systemRootPath'] . 'view/maintanance.html'; } else { $o = new stdClass(); $o->error = true; $o->msg = __('Under Maintanance'); echo json_encode($o); } } else { var_dump($error); } exit; } } function videoNotFound($message, $logMessage = false) { global $global; $_REQUEST['404ErrorMsg'] = $message; if ($logMessage) { _error_log($message); } include $global['systemRootPath'] . 'view/videoNotFound.php'; exit; } function isForbidden() { global $global; if (!empty($global['isForbidden'])) { return true; } return false; } function diskUsageBars() { global $global; ob_start(); include $global['systemRootPath'] . 'objects/functiondiskUsageBars.php'; $contents = ob_get_contents(); ob_end_clean(); return $contents; } function getDomain() { global $global, $_getDomain; if (isset($_getDomain)) { return $_getDomain; } if (empty($_SERVER['HTTP_HOST'])) { $parse = parse_url($global['webSiteRootURL']); $domain = $parse['host']; } else { $domain = $_SERVER['HTTP_HOST']; } $domain = str_replace("www.", "", $domain); $domain = preg_match("/^\..+/", $domain) ? ltrim($domain, '.') : $domain; $domain = preg_replace('/:[0-9]+$/', '', $domain); $_getDomain = $domain; return $domain; } function getHostOnlyFromURL($url) { $parse = parse_url($url); $domain = $parse['host']; $domain = str_replace("www.", "", $domain); $domain = preg_match("/^\..+/", $domain) ? ltrim($domain, '.') : $domain; $domain = preg_replace('/:[0-9]+$/', '', $domain); return $domain; } /** * It's separated by time, version, clock_seq_hi, clock_seq_lo, node, as indicated in the followoing rfc. * * From the IETF RFC4122: * 8-4-4-4-12 * @return string */ function getDeviceID($useRandomString = true) { $ip = md5(getRealIpAddr()); if (empty($_SERVER['HTTP_USER_AGENT'])) { $device = "unknowDevice-{$ip}"; $device .= '-' . intval(User::getId()); return $device; } if (empty($useRandomString)) { $device = 'ypt-' . get_browser_name() . '-' . getOS() . '-' . $ip . '-' . md5($_SERVER['HTTP_USER_AGENT']); $device = str_replace( array('[', ']', ' '), array('', '', '_'), $device); $device .= '-' . intval(User::getId()); return $device; } $cookieName = "yptDeviceID"; if (empty($_COOKIE[$cookieName])) { if (empty($_GET[$cookieName])) { $id = uniqidV4(); $_GET[$cookieName] = $id; } if (empty($_SESSION[$cookieName])) { _session_start(); $_SESSION[$cookieName] = $_GET[$cookieName]; } else { $_GET[$cookieName] = $_SESSION[$cookieName]; } if (!_setcookie($cookieName, $_GET[$cookieName], strtotime("+ 1 year"))) { return "getDeviceIDError"; } $_COOKIE[$cookieName] = $_GET[$cookieName]; return $_GET[$cookieName]; } return $_COOKIE[$cookieName]; } function deviceIdToObject($deviceID) { $parts = explode('-', $deviceID); $obj = new stdClass(); $obj->browser = ''; $obj->os = ''; $obj->ip = ''; $obj->user_agent = ''; $obj->users_id = 0; foreach ($parts as $key => $value) { $parts[$key] = str_replace('_', ' ', $value); } switch ($parts[0]) { case 'ypt': $obj->browser = $parts[1]; $obj->os = $parts[2]; $obj->ip = $parts[3]; $obj->user_agent = $parts[4]; $obj->users_id = $parts[5]; break; case 'unknowDevice': $obj->browser = $parts[0]; $obj->os = 'unknow OS'; $obj->ip = $parts[1]; $obj->user_agent = 'unknow UA'; $obj->users_id = $parts[2]; break; default: break; } return $obj; } function uniqidV4() { $randomString = openssl_random_pseudo_bytes(16); $time_low = bin2hex(substr($randomString, 0, 4)); $time_mid = bin2hex(substr($randomString, 4, 2)); $time_hi_and_version = bin2hex(substr($randomString, 6, 2)); $clock_seq_hi_and_reserved = bin2hex(substr($randomString, 8, 2)); $node = bin2hex(substr($randomString, 10, 6)); /** * Set the four most significant bits (bits 12 through 15) of the * time_hi_and_version field to the 4-bit version number from * Section 4.1.3. * @see http://tools.ietf.org/html/rfc4122#section-4.1.3 */ $time_hi_and_version = hexdec($time_hi_and_version); $time_hi_and_version = $time_hi_and_version >> 4; $time_hi_and_version = $time_hi_and_version | 0x4000; /** * Set the two most significant bits (bits 6 and 7) of the * clock_seq_hi_and_reserved to zero and one, respectively. */ $clock_seq_hi_and_reserved = hexdec($clock_seq_hi_and_reserved); $clock_seq_hi_and_reserved = $clock_seq_hi_and_reserved >> 2; $clock_seq_hi_and_reserved = $clock_seq_hi_and_reserved | 0x8000; return sprintf('%08s-%04s-%04x-%04x-%012s', $time_low, $time_mid, $time_hi_and_version, $clock_seq_hi_and_reserved, $node); } // guid function _setcookie($cookieName, $value, $expires = 0) { if (empty($expires)) { if (empty($config) || !is_object($config)) { $config = new Configuration(); } $expires = time() + $config->getSession_timeout(); } if (version_compare(phpversion(), '7.3', '>=')) { $cookie_options = array( 'expires' => $expires, 'path' => '/', 'domain' => getDomain(), 'secure' => true, 'httponly' => false, 'samesite' => 'None'); return setcookie($cookieName, $value, $cookie_options); } else { return setcookie($cookieName, $value, (int) $expires, "/", getDomain()); } } function _unsetcookie($cookieName) { $domain = getDomain(); $expires = strtotime("-10 years"); $value = ""; _setcookie($cookieName, $value, $expires); setcookie($cookieName, $value, (int) $expires, "/") && setcookie($cookieName, $value, (int) $expires); setcookie($cookieName, $value, (int) $expires, "/", str_replace("www", "", $domain)); setcookie($cookieName, $value, (int) $expires, "/", "www." . $domain); setcookie($cookieName, $value, (int) $expires, "/", "." . $domain); setcookie($cookieName, $value, (int) $expires, "/", $domain); setcookie($cookieName, $value, (int) $expires, "/"); setcookie($cookieName, $value, (int) $expires); unset($_COOKIE[$cookieName]); } /** * This function is not 100% but try to tell if the site is in an iFrame * @global type $global * @return boolean */ function isIframeInDifferentDomain() { global $global; if (!isIframe()) { return false; } return isSameDomainAsMyAVideo($_SERVER['HTTP_REFERER']); } function isIframe() { global $global; if (isset($_SERVER['HTTP_SEC_FETCH_DEST']) && $_SERVER['HTTP_SEC_FETCH_DEST'] === 'iframe') { return true; } if (empty($_SERVER['HTTP_REFERER']) || $_SERVER['HTTP_REFERER'] == $global['webSiteRootURL'] || str_replace('view/', '', getSelfURI()) == $global['webSiteRootURL']) { return false; } return true; } function getCredentialsURL() { global $global; return "webSiteRootURL=" . urlencode($global['webSiteRootURL']) . "&user=" . urlencode(User::getUserName()) . "&pass=" . urlencode(User::getUserPass()) . "&encodedPass=1"; } function gotToLoginAndComeBackHere($msg) { global $global; if (User::isLogged()) { forbiddenPage($msg); exit; } if (!empty($_GET['comebackhere'])) { return false; } header("Location: {$global['webSiteRootURL']}user?redirectUri=" . urlencode(getSelfURI()) . "&msg=" . urlencode($msg) . "&comebackhere=1"); exit; } function setAlertMessage($msg, $type = "msg") { _session_start(); $_SESSION['YPTalertMessage'][] = array($msg, $type); } function setToastMessage($msg) { setAlertMessage($msg, "toast"); } function showAlertMessage() { if (!empty($_SESSION['YPTalertMessage'])) { foreach ($_SESSION['YPTalertMessage'] as $value) { if (!empty($value[0])) { if (empty($_GET[$value[1]])) { $_GET[$value[1]] = array(); } $_GET[$value[1]][] = $value[0]; } } _session_start(); unset($_SESSION['YPTalertMessage']); } $joinString = array('error', 'msg', 'success'); foreach ($joinString as $value) { if (!empty($_GET[$value]) && is_array($_GET[$value])) { $_GET[$value] = array_unique($_GET[$value]); $newStr = array(); foreach ($_GET[$value] as $value2) { if (!empty($value2)) { $newStr[] = $value2; } } $_GET[$value] = implode("
", $newStr); } } $check = array('error', 'msg', 'success', 'toast'); foreach ($check as $value) { if (!empty($_GET[$value])) { if (is_array($_GET[$value])) { $newStr = array(); foreach ($_GET[$value] as $key => $value2) { $value2 = str_replace('"', "''", $value2); if (!empty($value2)) { $newStr[] = $value2; } } $_GET[$value] = $newStr; } else { $_GET[$value] = str_replace('"', "''", $_GET[$value]); } } } echo "/** showAlertMessage **/", PHP_EOL; if (!empty($_GET['error'])) { echo 'avideoAlertError("' . $_GET['error'] . '");'; echo 'window.history.pushState({}, document.title, "' . getSelfURI() . '");'; } if (!empty($_GET['msg'])) { echo 'avideoAlertInfo("' . $_GET['msg'] . '");'; echo 'window.history.pushState({}, document.title, "' . getSelfURI() . '");'; } if (!empty($_GET['success'])) { echo 'avideoAlertSuccess("' . $_GET['success'] . '");'; echo 'window.history.pushState({}, document.title, "' . getSelfURI() . '");'; } if (!empty($_GET['toast'])) { if (!is_array($_GET['toast'])) { $_GET['toast'] = array($_GET['toast']); } else { $_GET['toast'] = array_unique($_GET['toast']); } foreach ($_GET['toast'] as $key => $value) { $hideAfter = strlen(strip_tags($value)) * 150; if ($hideAfter < 3000) { $hideAfter = 3000; } if ($hideAfter > 15000) { $hideAfter = 15000; } echo '$.toast({ text: "' . $value . '", hideAfter: ' . $hideAfter . ' // in milli seconds });console.log("Toast Hide after ' . $hideAfter . '");'; } echo 'window.history.pushState({}, document.title, "' . getSelfURI() . '");'; } echo PHP_EOL, "/** showAlertMessage END **/"; } function getResolutionLabel($res) { if ($res == 720) { return "" . getResolutionText($res) . ""; } elseif ($res == 1080) { return "" . getResolutionText($res) . ""; } elseif ($res == 1440) { return "" . getResolutionText($res) . ""; } elseif ($res == 2160) { return "" . getResolutionText($res) . ""; } elseif ($res == 4320) { return "" . getResolutionText($res) . ""; } else { return ''; } } function getResolutionText($res) { if ($res == 720) { return "HD"; } elseif ($res == 1080) { return "FHD"; } elseif ($res == 1440) { return "FHD+"; } elseif ($res == 2160) { return "4K"; } elseif ($res == 4320) { return "8K"; } else { return ''; } } // just realize the readdir is a lot faster then glob function _glob($dir, $pattern) { global $_glob; if (empty($dir)) { return array(); } if (empty($_glob)) { $_glob = array(); } $name = md5($dir . $pattern); if (isset($_glob[$name])) { return $_glob[$name]; } $dir = rtrim($dir, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR; $array = array(); if (is_dir($dir) && $handle = opendir($dir)) { $count = 0; while (false !== ($file_name = readdir($handle))) { if ($file_name == '.' || $file_name == '..') { continue; } //_error_log("_glob: {$dir}{$file_name} [$pattern]"); //var_dump($pattern, $file_name, preg_match($pattern, $file_name)); if (preg_match($pattern, $file_name)) { $array[] = "{$dir}{$file_name}"; } } closedir($handle); } $_glob[$name] = $array; return $array; } function globVideosDir($filename, $filesOnly = false) { global $global; if (empty($filename)) { return array(); } $cleanfilename = Video::getCleanFilenameFromFile($filename); $paths = Video::getPaths($filename); $dir = $paths['path']; if (is_dir($dir . $filename)) { $dir = $dir . $filename; $cleanfilename = ''; } $pattern = "/{$cleanfilename}.*"; if (!empty($filesOnly)) { $formats = getValidFormats(); $pattern .= ".(" . implode("|", $formats) . ")"; } $pattern .= "/"; //var_dump($dir, $pattern); return _glob($dir, $pattern); } function getValidFormats() { $video = array('webm', 'mp4', 'm3u8'); $audio = array('mp3', 'ogg'); $image = array('jpg', 'gif', 'webp'); return array_merge($video, $audio, $image); } function isValidFormats($format) { $format = str_replace(".", "", $format); return in_array($format, getValidFormats()); } function getTimerFromDates($startTime, $endTime = 0) { if (!is_int($startTime)) { $startTime = strtotime($startTime); } if (!is_int($endTime)) { $endTime = strtotime($endTime); } if (empty($endTime)) { $endTime = time(); } $timer = abs($endTime - $startTime); $uid = uniqid(); return ""; } function getServerClock() { $id = uniqid(); $today = getdate(); $html = '00:00:00'; $html .= ""; return $html; } /** * Xsendfile and FFMPEG are required for this feature * @global type $global * @param type $filepath * @return boolean */ function downloadHLS($filepath) { global $global; if (!CustomizeUser::canDownloadVideos()) { _error_log("downloadHLS: CustomizeUser::canDownloadVideos said NO"); return false; } if (!file_exists($filepath)) { _error_log("downloadHLS: file NOT found: {$filepath}"); return false; } $output = m3u8ToMP4($filepath); if (empty($output)) { _error_log("downloadHLS: m3u8ToMP4($filepath) return empty"); die("downloadHLS was not possible"); } $outputpath = $output['path']; $outputfilename = $output['filename']; if (!empty($_REQUEST['title'])) { $quoted = sprintf('"%s"', addcslashes(basename($_REQUEST['title']), '"\\')); } elseif (!empty($_REQUEST['file'])) { $quoted = sprintf('"%s"', addcslashes(basename($_REQUEST['file']), '"\\')) . ".mp4"; } else { $quoted = $outputfilename; } header('Content-Description: File Transfer'); header('Content-Disposition: attachment; filename=' . $quoted); header('Content-Transfer-Encoding: binary'); header('Connection: Keep-Alive'); header('Expires: 0'); header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); header('Pragma: public'); header("X-Sendfile: {$outputpath}"); exit; } function playHLSasMP4($filepath) { global $global; if (!CustomizeUser::canDownloadVideos()) { _error_log("playHLSasMP4: CustomizeUser::canDownloadVideos said NO"); return false; } if (!file_exists($filepath)) { _error_log("playHLSasMP4: file NOT found: {$filepath}"); return false; } $output = m3u8ToMP4($filepath); if (empty($output)) { die("playHLSasMP4 was not possible"); } $outputpath = $output['path']; header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0'); header('Cache-Control: post-check=0, pre-check=0', false); header('Pragma: no-cache'); header('Content-type: video/mp4'); header('Content-Length: ' . filesize($outputpath)); header("X-Sendfile: {$outputpath}"); exit; } function m3u8ToMP4($input) { $videosDir = getVideosDir(); $outputfilename = str_replace($videosDir, "", $input); $parts = explode("/", $outputfilename); $resolution = Video::getResolutionFromFilename($input); $outputfilename = $parts[0] . "_{$resolution}_.mp4"; $outputpath = "{$videosDir}cache/downloads/{$outputfilename}"; make_path($outputpath); if (empty($outputfilename)) { _error_log("downloadHLS: empty outputfilename {$outputfilename}"); return false; } _error_log("downloadHLS: m3u8ToMP4($input)"); //var_dump(!preg_match('/^http/i', $input), filesize($input), preg_match('/.m3u8$/i', $input)); if (!preg_match('/^http/i', $input) && (filesize($input) <= 10 || preg_match('/.m3u8$/i', $input))) { // dummy file $filepath = escapeshellcmd(pathToRemoteURL($input, true, true)); } else { $filepath = escapeshellcmd($input); } if (is_dir($filepath)) { $filepath = addLastSlash($filepath) . 'index.m3u8'; } $outputpath = escapeshellcmd($outputpath); if (!file_exists($outputpath)) { $command = get_ffmpeg() . " -allowed_extensions ALL -y -i {$filepath} -c:v copy -c:a copy -bsf:a aac_adtstoasc -strict -2 {$outputpath}"; _error_log("downloadHLS: Exec Command ({$command})"); //var_dump($outputfilename, $command, $_GET, $filepath);exit; exec($command . " 2>&1", $output, $return); if (!empty($return)) { _error_log("downloadHLS: ERROR 1 " . implode(PHP_EOL, $output)); $command = get_ffmpeg() . " -y -i {$filepath} -c:v copy -c:a copy -bsf:a aac_adtstoasc -strict -2 {$outputpath}"; //var_dump($outputfilename, $command, $_GET, $filepath);exit; exec($command . " 2>&1", $output, $return); if (!empty($return)) { _error_log("downloadHLS: ERROR 2 " . implode(PHP_EOL, $output)); return false; } } } else { _error_log("downloadHLS: outputpath not found ({$outputpath})"); } return array('path' => $outputpath, 'filename' => $outputfilename); } function getSocialModal($videos_id, $url = "", $title = "") { global $global; $video['id'] = $videos_id; $sharingUid = uniqid(); ob_start(); ?> $contents, 'id' => $sharingUid); } function getCroppie( $buttonTitle, $callBackJSFunction, $resultWidth, $resultHeight, $viewportWidth = 0, $boundary = 25, $viewportHeight = 0 ) { global $global; if (empty($viewportWidth)) { $viewportWidth = $resultWidth; } $zoom = 0; if (empty($viewportHeight)) { $zoom = ($viewportWidth / $resultWidth); $viewportHeight = $zoom * $resultHeight; } $boundaryWidth = $viewportWidth + $boundary; $boundaryHeight = $viewportHeight + $boundary; $uid = uniqid(); ob_start(); include $global['systemRootPath'] . 'objects/functionCroppie.php'; $contents = ob_get_contents(); ob_end_clean(); $callBackJSFunction = addcslashes($callBackJSFunction, "'"); return array( "html" => $contents, "id" => "croppie{$uid}", "uploadCropObject" => "uploadCrop{$uid}", "getCroppieFunction" => "getCroppie(uploadCrop{$uid}, '{$callBackJSFunction}', {$resultWidth}, {$resultHeight});", "createCroppie" => "createCroppie{$uid}", "restartCroppie" => "restartCroppie{$uid}" ); } function saveCroppieImage($destination, $postIndex = "imgBase64") { if (empty($_POST[$postIndex])) { return false; } $fileData = base64DataToImage($_POST[$postIndex]); return file_put_contents($destination, $fileData); } function get_ffmpeg($ignoreGPU = false) { global $global; $complement = ''; //$complement = ' -user_agent "'.getSelfUserAgent("FFMPEG").'" '; //return 'ffmpeg -headers "User-Agent: '.getSelfUserAgent("FFMPEG").'" '; $ffmpeg = 'ffmpeg '; if (empty($ignoreGPU) && !empty($global['ffmpegGPU'])) { $ffmpeg .= ' --enable-nvenc '; } if (!empty($global['ffmpeg'])) { $ffmpeg = "{$global['ffmpeg']}{$ffmpeg}"; } return $ffmpeg.$complement; } function isHTMLPage($url) { if (preg_match('/https?:\/\/(www\.)?(youtu.be|youtube.com|vimeo.com|bitchute.com)\//i', $url)) { return true; } else if ($type = getHeaderContentTypeFromURL($url)) { if (preg_match('/text\/html/i', $type)) { return true; } } return false; } function getHeaderContentTypeFromURL($url) { if (isValidURL($url) && $type = get_headers($url, 1)["Content-Type"]) { return $type; } return false; } function canFullScreen() { global $doNotFullScreen; if (!empty($doNotFullScreen) || isSerie() || !isVideo()) { return false; } return true; } function getTinyMCE($id) { global $global; ob_start(); include $global['systemRootPath'] . 'objects/functionsGetTinyMCE.php'; $contents = ob_get_contents(); ob_end_clean(); return $contents; } function pathToRemoteURL($filename, $forceHTTP = false, $ignoreCDN = false) { global $pathToRemoteURL, $global; if (!isset($pathToRemoteURL)) { $pathToRemoteURL = array(); } if (isset($pathToRemoteURL[$filename])) { return $pathToRemoteURL[$filename]; } if (!file_exists($filename) || filesize($filename) < 1000) { $fileName = getFilenameFromPath($filename); if ($yptStorage = AVideoPlugin::loadPluginIfEnabled("YPTStorage")) { $source = $yptStorage->getAddress("{$fileName}"); $url = $source['url']; } else if (!preg_match('/index.m3u8$/', $filename)) { if ($aws_s3 = AVideoPlugin::loadPluginIfEnabled("AWS_S3")) { $source = $aws_s3->getAddress("{$fileName}"); $url = $source['url']; if (empty($ignoreCDN)) { $url = replaceCDNIfNeed($url, 'CDN_S3'); } else if (!empty($source['url_noCDN'])) { $url = $source['url_noCDN']; } } else if ($bb_b2 = AVideoPlugin::loadPluginIfEnabled("Blackblaze_B2")) { $source = $bb_b2->getAddress("{$fileName}"); $url = $source['url']; if (empty($ignoreCDN)) { $url = replaceCDNIfNeed($url, 'CDN_B2'); } else if (!empty($source['url_noCDN'])) { $url = $source['url_noCDN']; } } else if ($ftp = AVideoPlugin::loadPluginIfEnabled("FTP_Storage")) { $source = $ftp->getAddress("{$fileName}"); $url = $source['url']; if (empty($ignoreCDN)) { $url = replaceCDNIfNeed($url, 'CDN_FTP'); } else if (!empty($source['url_noCDN'])) { $url = $source['url_noCDN']; } } } } if (empty($url)) { if ($forceHTTP) { $paths = Video::getPaths($filename); //$url = str_replace(getVideosDir(), getCDN() . "videos/", $filename); if (empty($ignoreCDN)) { $url = getCDN() . "{$paths['relative']}"; } else { $url = "{$global['webSiteRootURL']}{$paths['relative']}"; } if (preg_match('/index.m3u8$/', $filename) && !preg_match('/index.m3u8$/', $url)) { $url .= 'index.m3u8'; } } else { $url = $filename; } } //$url = str_replace(array($global['systemRootPath'], '/videos/videos/'), array("", '/videos/'), $url); $pathToRemoteURL[$filename] = $url; return $url; } function getFilenameFromPath($path) { global $global; $fileName = Video::getCleanFilenameFromFile($path); return $fileName; } function showCloseButton() { global $global, $showCloseButtonIncluded; if (!empty($showCloseButtonIncluded)) { return ''; } if (isSerie()) { return ''; } if (!isLive() && $obj = AVideoPlugin::getDataObjectIfEnabled("Gallery")) { if (!empty($obj->playVideoOnFullscreen)) { $_REQUEST['showCloseButton'] = 1; } } if (isLive() && $obj = AVideoPlugin::getDataObjectIfEnabled("Live")) { if (!empty($obj->playLiveInFullScreen)) { $_REQUEST['showCloseButton'] = 1; } } if (!empty($_REQUEST['showCloseButton'])) { $showCloseButtonIncluded = 1; include $global['systemRootPath'] . 'view/include/youtubeModeOnFullscreenCloseButton.php'; } return ''; } function getThemes() { global $_getThemes, $global; if (isset($_getThemes)) { return $_getThemes; } $_getThemes = array(); foreach (glob("{$global['systemRootPath']}view/css/custom/*.css") as $filename) { $fileEx = basename($filename, ".css"); $_getThemes[] = $fileEx; } return $_getThemes; } function getCurrentTheme() { global $config; if (!empty($_REQUEST['customCSS'])) { _setcookie('customCSS', $_REQUEST['customCSS']); return $_REQUEST['customCSS']; } if (!empty($_COOKIE['customCSS'])) { return $_COOKIE['customCSS']; } return $config->getTheme(); } /* * $users_id="" or 0 means send messages to all users * $users_id="-1" means send to no one */ function sendSocketMessage($msg, $callbackJSFunction = "", $users_id = "-1", $send_to_uri_pattern = "") { if (AVideoPlugin::isEnabledByName('YPTSocket')) { if (!is_string($msg)) { $msg = json_encode($msg); } $obj = YPTSocket::send($msg, $callbackJSFunction, $users_id, $send_to_uri_pattern); if ($obj->error && !empty($obj->msg)) { _error_log("sendSocketMessage " . $obj->msg); } return $obj; } return false; } function sendSocketMessageToUsers_id($msg, $users_id, $callbackJSFunction = "") { if (!is_array($users_id)) { $users_id = array($users_id); } $resp = array(); foreach ($users_id as $value) { $resp[] = sendSocketMessage($msg, $callbackJSFunction, $value); } return $resp; } function sendSocketMessageToAll($msg, $callbackJSFunction = "", $send_to_uri_pattern = "") { return sendSocketMessage($msg, $callbackJSFunction, "", $send_to_uri_pattern); } function sendSocketMessageToNone($msg, $callbackJSFunction = "") { return sendSocketMessage($msg, $callbackJSFunction, -1); } function execAsync($command) { //$command = escapeshellarg($command); // If windows, else if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') { //echo $command; //$pid = system("start /min ".$command. " > NUL"); //$commandString = "start /B " . $command; //pclose($pid = popen($commandString, "r")); _error_log($command); $pid = exec($command, $output, $retval); _error_log('execAsync: ' . json_encode($output) . ' ' . $retval); } else { $newCommand = $command . " > /dev/null 2>&1 & echo $!; "; _error_log($newCommand); $pid = exec($newCommand); } return $pid; } function killProcess($pid) { $pid = intval($pid); if (empty($pid)) { return false; } if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') { exec("taskkill /F /PID $pid"); } else { exec("kill -9 $pid"); } return true; } function getPIDUsingPort($port) { $port = intval($port); if (empty($port)) { return false; } if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') { $command = 'netstat -ano | findstr ' . $port; exec($command, $output, $retval); $pid = 0; foreach ($output as $value) { if (preg_match('/LISTENING[^0-9]+([0-9]+)/i', $value, $matches)) { if (!empty($matches[1])) { $pid = intval($matches[1]); return $pid; } } } } else { $command = 'lsof -n -i :' . $port . ' | grep LISTEN'; exec($command, $output, $retval); $pid = 0; foreach ($output as $value) { if (preg_match('/[^ ] +([0-9]+).*/i', $value, $matches)) { if (!empty($matches[1])) { $pid = intval($matches[1]); return $pid; } } } } return false; } function isURL200($url, $forceRecheck = false) { global $_isURL200; $name = "isURL200" . DIRECTORY_SEPARATOR . md5($url); if (empty($forceRecheck)) { $result = ObjectYPT::getCache($name, 30); if (!empty($result)) { $object = _json_decode($result); return $object->result; } } $object = new stdClass(); $object->url = $url; $object->forceRecheck = $forceRecheck; //error_log("isURL200 checking URL {$url}"); $headers = @get_headers($url); if (!is_array($headers)) { $headers = array($headers); } $object->result = false; foreach ($headers as $value) { if ( strpos($value, '200') || strpos($value, '302') || strpos($value, '304') ) { $object->result = true; break; } else { //_error_log('isURL200: '.$value); } } ObjectYPT::setCache($name, json_encode($object)); return $object->result; } function isURL200Clear() { $tmpDir = ObjectYPT::getCacheDir(); $cacheDir = $tmpDir . "isURL200" . DIRECTORY_SEPARATOR; //_error_log("Live::isURL200Clear [{$cacheDir}]"); rrmdir($cacheDir); exec('rm -R ' . $cacheDir); } function getStatsNotifications($force_recreate = false) { $cacheName = "getStats" . DIRECTORY_SEPARATOR . "getStatsNotifications"; if ($force_recreate) { Live::deleteStatsCache(); } else { $json = ObjectYPT::getCache($cacheName, 0, true); } if (empty($json)) { //_error_log('getStatsNotifications: 1 ' . json_encode(debug_backtrace())); $json = Live::getStats(); $json = object_to_array($json); if (empty($json['applications']) && is_array($json)) { $json['applications'] = array(); foreach ($json as $key => $value) { if (empty($value['applications'])) { continue; } $json['applications'] = array_merge($json['applications'], $value['applications']); unset($json[$key]); } } $appArray = AVideoPlugin::getLiveApplicationArray(); if (!empty($appArray)) { if (empty($json)) { $json = array(); } $json['error'] = false; if (empty($json['msg'])) { $json['msg'] = "OFFLINE"; } $json['nclients'] = count($appArray); if (empty($json['applications'])) { $json['applications'] = array(); } $json['applications'] = array_merge($json['applications'], $appArray); } $count = 0; if (!isset($json['total'])) { $json['total'] = 0; } if (!empty($json['applications'])) { $json['total'] += count($json['applications']); } while (!empty($json[$count])) { $json['total'] += count($json[$count]['applications']); $count++; } if (empty($json['countLiveStream']) || $json['countLiveStream'] < $json['total']) { $json['countLiveStream'] = $json['total']; } if (!empty($json['applications'])) { foreach ($json['applications'] as $key => $value) { if (empty($value['users_id']) && !empty($value['user'])) { $u = User::getFromUsername($value['user']); $json['applications'][$key]['users_id'] = $u['id']; } } } $cache = ObjectYPT::setCache($cacheName, $json); _error_log('Live::createStatsCache ' . json_encode($cache)); } else { //_error_log('getStatsNotifications: 2 cached result'); $json = object_to_array($json); } return $json; } function getSocketConnectionLabel() { $html = ' ' . __('Disconnected') . ' ' . __('Connected') . ' '; return $html; } function getSocketVideoClassName($videos_id) { return 'total_on_videos_id_' . $videos_id; } function getSocketLiveClassName($key, $live_servers_id) { return 'total_on_live_' . $key . '_' . intval($live_servers_id); } function getSocketLiveLinksClassName($live_links_id) { return 'total_on_live_links_id_' . $live_links_id; } function getLiveUsersLabelVideo($videos_id, $totalViews = null, $viewsClass = "label label-default", $counterClass = "label label-primary") { if (AVideoPlugin::isEnabledByName('LiveUsers') && method_exists("LiveUsers", "getLabels")) { return LiveUsers::getLabels(getSocketVideoClassName($videos_id), $totalViews, $viewsClass, $counterClass, 'video'); } } function getLiveUsersLabelLive($key, $live_servers_id, $viewsClass = "label label-default", $counterClass = "label label-primary") { if (AVideoPlugin::isEnabledByName('LiveUsers') && method_exists("LiveUsers", "getLabels")) { $totalViews = 0; if (User::isLogged()) { $totalViews = LiveUsers::getTotalUsers($key, $live_servers_id); } return LiveUsers::getLabels(getSocketLiveClassName($key, $live_servers_id), $totalViews, $viewsClass, $counterClass, 'live'); } } function getLiveUsersLabelLiveLinks($liveLinks_id, $totalViews = null, $viewsClass = "label label-default", $counterClass = "label label-primary") { if (AVideoPlugin::isEnabledByName('LiveUsers') && method_exists("LiveUsers", "getWatchingNowLabel")) { return LiveUsers::getWatchingNowLabel(getSocketLiveLinksClassName($liveLinks_id), "label label-primary", '', $viewsClass, 'livelinks'); } } function getLiveUsersLabel($viewsClass = "label label-default", $counterClass = "label label-primary") { if (AVideoPlugin::isEnabledByName('LiveUsers')) { $live = isLive(); if (!empty($live)) { if (!empty($live['key'])) { return getLiveUsersLabelLive($live['key'], $live['live_servers_id'], $viewsClass, $counterClass); } else if (!empty($live['liveLinks_id'])) { return getLiveUsersLabelLiveLinks($live['liveLinks_id'], null, $viewsClass, $counterClass); } } else { $videos_id = getVideos_id(); if (!empty($videos_id)) { $v = new Video("", "", $videos_id); $totalViews = $v->getViews_count(); return getLiveUsersLabelVideo($videos_id, $totalViews, $viewsClass, $counterClass); } } } return ""; } function getLiveUsersLabelHTML($viewsClass = "label label-default", $counterClass = "label label-primary") { global $global; ob_start(); include $global['systemRootPath'] . 'plugin/Live/view/onlineLabel.php'; $htmlMediaTag = '
'; $htmlMediaTag .= ob_get_contents(); ob_end_clean(); $htmlMediaTag .= getLiveUsersLabel($viewsClass, $counterClass); $htmlMediaTag .= '
'; return $htmlMediaTag; } function getHTMLTitle($titleArray) { global $config, $global; if (!is_array($titleArray)) { $titleArray = array(); } $titleArray[] = $config->getWebSiteTitle(); $title = implode($config->getPageTitleSeparator(), $titleArray); $global['pageTitle'] = $title; return "{$title}"; } function getButtonSignInAndUp() { $signIn = getButtonSignIn(); $signUp = getButtonSignUp(); $html = $signIn . $signUp; if (!empty($signIn) && !empty($signIn)) { return '
' . $html . '
'; } else { return $html; } } function getButtonSignUp() { global $global; $obj = AVideoPlugin::getDataObject('CustomizeUser'); if (!empty($obj->disableNativeSignUp)) { return ''; } $url = $global['webSiteRootURL'] . 'signUp'; $url = addQueryStringParameter($url, 'redirectUri', getRedirectUri()); $html = ' ' . __("Sign Up") . ' '; return $html; } function getButtonSignIn() { global $global; $obj = AVideoPlugin::getDataObject('CustomizeUser'); if (!empty($obj->disableNativeSignIn)) { return ''; } $url = $global['webSiteRootURL'] . 'user'; $url = addQueryStringParameter($url, 'redirectUri', getRedirectUri()); $html = ' ' . __("Sign In") . ' '; return $html; } function getTitle() { global $global; if (empty($global['pageTitle'])) { $url = getSelfURI(); $global['pageTitle'] = str_replace($global['webSiteRootURL'], '', $url); if (preg_match('/\/plugin\/([^\/])/i', $url, $matches)) { $global['pageTitle'] = __('Plugin') . ' ' . __($matches[1]); } $title = $global['pageTitle']; } return $global['pageTitle']; } function outputAndContinueInBackground() { global $outputAndContinueInBackground; if (!empty($outputAndContinueInBackground)) { return false; } $outputAndContinueInBackground = 1; @session_write_close(); //_mysql_close(); // Instruct PHP to continue execution ignore_user_abort(true); if (function_exists('fastcgi_finish_request')) { fastcgi_finish_request(); } ob_start(); @header("Connection: close"); @header("Content-Length: " . ob_get_length()); @header("HTTP/1.1 200 OK"); ob_end_flush(); flush(); } function cleanUpRowFromDatabase($row) { if (is_array($row)) { foreach ($row as $key => $value) { if (preg_match('/pass/i', $key)) { unset($row[$key]); } } } return $row; } function getImageTransparent1pxURL() { global $global; return getCDN() . "view/img/transparent1px.png"; } function getDatabaseTime() { global $global, $_getDatabaseTime; if (isset($_getDatabaseTime)) { return $_getDatabaseTime; } $sql = "SELECT CURRENT_TIMESTAMP"; $res = sqlDAL::readSql($sql); $data = sqlDAL::fetchAssoc($res); sqlDAL::close($res); if ($res) { $row = $data; } else { $row = false; } $_getDatabaseTime = strtotime($row['CURRENT_TIMESTAMP']); return $_getDatabaseTime; } function get_js_availableLangs() { global $global; if (empty($global['js_availableLangs'])) { include_once $global['systemRootPath'] . 'objects/bcp47.php'; } return $global['js_availableLangs']; } function listAllWordsToTranslate() { global $global; $cacheName = 'listAllWordsToTranslate'; $cache = ObjectYPT::getCache($cacheName, 0); if (!empty($cache)) { return object_to_array($cache); } ini_set('max_execution_time', 300); function listAll($dir) { $vars = array(); if ($handle = opendir($dir)) { while (false !== ($entry = readdir($handle))) { if ($entry != "." && $entry != "..") { $filename = $dir . "/" . $entry; if (is_dir($filename)) { $vars = listAll($filename); } elseif (preg_match("/\.php$/", $entry)) { $data = file_get_contents($filename); $regex = '/__\(["\']{1}(.*)["\']{1}\)/U'; preg_match_all( $regex, $data, $matches ); foreach ($matches[0] as $key => $value) { $vars[$matches[1][$key]] = $matches[1][$key]; } } } } closedir($handle); } return $vars; } $vars = listAll($global['systemRootPath']); sort($vars); ObjectYPT::setCache($cacheName, $vars); return $vars; } function secondsInterval($time1, $time2) { if (!is_int($time1)) { $time1 = strtotime($time1); } if (!is_int($time2)) { $time2 = strtotime($time2); } return $time1 - $time2; } function secondsIntervalHuman($time, $useDatabaseTime = true) { $dif = secondsIntervalFromNow($time, $useDatabaseTime); if ($dif < 0) { return humanTimingAfterwards($time); } else { return humanTimingAgo($time); } } function isTimeForFuture($time, $useDatabaseTime = true) { $dif = secondsIntervalFromNow($time, $useDatabaseTime); if ($dif < 0) { return true; } else { return false; } } function secondsIntervalFromNow($time, $useDatabaseTimeOrTimezoneString = true) { $timeNow = time(); if (!empty($useDatabaseTimeOrTimezoneString)) { if (is_numeric($useDatabaseTimeOrTimezoneString) || is_bool($useDatabaseTimeOrTimezoneString)) { $timeNow = getDatabaseTime(); } else if (is_string($useDatabaseTimeOrTimezoneString)) { $timeNow = getTimeInTimezone($timeNow, $useDatabaseTimeOrTimezoneString); } } return secondsInterval($timeNow, $time); } function getScriptRunMicrotimeInSeconds() { global $global; $time_now = microtime(true); return ($time_now - $global['avideoStartMicrotime']); } function fixSystemPath() { global $global; $global['systemRootPath'] = fixPath($global['systemRootPath']); } function fixPath($path, $addLastSlash = false) { if (empty($path)) { return false; } if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') { $path = str_replace('/', DIRECTORY_SEPARATOR, $path); $path = str_replace('\\\\\\', DIRECTORY_SEPARATOR, $path); } else { $path = str_replace('\\', DIRECTORY_SEPARATOR, $path); } if ($addLastSlash) { $path = rtrim($path, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR; } return $path; } function idToHash($id) { global $global, $_idToHash; if (!isset($_idToHash)) { $_idToHash = array(); } if (!empty($_idToHash[$id])) { return $_idToHash[$id]; } if (!empty($global['useLongHash'])) { $base = 2; $cipher_algo = 'des'; } else { $base = 32; $cipher_algo = 'rc4'; } if (empty($global['salt'])) { $global['salt'] = '11234567890abcdef'; } $idConverted = base_convert($id, 10, $base); $hash = (@openssl_encrypt($idConverted, $cipher_algo, $global['salt'])); //$hash = preg_replace('/^([+]+)/', '', $hash); $hash = preg_replace('/(=+)$/', '', $hash); $hash = str_replace(array('/', '+', '='), array('_', '-', '.'), $hash); //return base64_encode($hash); $_idToHash[$id] = $hash; return $hash; } function hashToID($hash) { global $global; if (!empty($global['useLongHash'])) { $base = 2; $cipher_algo = 'des'; } else { $base = 32; $cipher_algo = 'rc4'; } //$hash = str_pad($hash, 4, "="); $hash = str_replace(array('_', '-', '.'), array('/', '+', '='), $hash); //$hash = base64_decode($hash); $decrypt = openssl_decrypt(($hash), $cipher_algo, $global['salt']); $decrypt = base_convert($decrypt, $base, 10); return intval($decrypt); } function videosHashToID($hash_of_videos_id) { if (is_int($hash_of_videos_id)) { return $hash_of_videos_id; } if (!is_string($hash_of_videos_id) && !is_numeric($hash_of_videos_id)) { return 0; } if (preg_match('/^\.([0-9a-z._-]+)/i', $hash_of_videos_id, $matches)) { $hash_of_videos_id = hashToID($matches[1]); } return $hash_of_videos_id; } /** * * @global type $advancedCustom * @global type $global * @global type $_getCDNURL * @param type $type enum(CDN, CDN_S3,CDN_B2,CDN_FTP,CDN_YPTStorage,CDN_Live,CDN_LiveServers) * @param type $id the ID of the URL in case the CDN is an array * @return \type */ function getCDN($type = 'CDN', $id = 0) { global $advancedCustom, $global, $_getCDNURL; $index = $type . $id; if (!isset($_getCDNURL)) { $_getCDNURL = array(); } if (empty($_getCDNURL[$index])) { if (!empty($type) && AVideoPlugin::isEnabledByName('CDN')) { $_getCDNURL[$index] = CDN::getURL($type, $id); } } if ($type == 'CDN') { if (!empty($global['ignoreCDN'])) { return $global['webSiteRootURL']; } else if (!empty ($advancedCustom) && isValidURL($advancedCustom->videosCDN)) { $_getCDNURL[$index] = addLastSlash($advancedCustom->videosCDN); } else if (empty($_getCDNURL[$index])) { $_getCDNURL[$index] = $global['webSiteRootURL']; } } //var_dump($type, $id, $_getCDNURL[$index]); return empty($_getCDNURL[$index]) ? false : $_getCDNURL[$index]; } function getURL($relativePath) { global $global; return getCDN() . $relativePath . '?cache=' . (@filemtime("{$global['systemRootPath']}{$relativePath}") . (@filectime("{$global['systemRootPath']}{$relativePath}"))); } function getCDNOrURL($url, $type = 'CDN', $id = 0) { if (!preg_match('/^http/i', $url)) { return $url; } $cdn = getCDN($type, $id); if (!empty($cdn)) { return $cdn; } return addLastSlash($url); } function replaceCDNIfNeed($url, $type = 'CDN', $id = 0) { $cdn = getCDN($type, $id); if (empty($cdn)) { return $url; } return str_replace(parse_url($url, PHP_URL_HOST), parse_url($cdn, PHP_URL_HOST), $url); } function isIPPrivate($ip) { if ($ip == '192.168.1.4') { return false; } if (!filter_var($ip, FILTER_VALIDATE_IP)) { return false; } $result = filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE); if (empty($result)) { return true; } return false; } function countDownPage($toTime, $message, $image, $bgImage) { global $global; include $global['systemRootPath'] . 'objects/functionCountDownPage.php'; exit; } function inputToRequest() { $content = file_get_contents("php://input"); if (!empty($content)) { $json = json_decode($content); if (empty($json)) { return false; } foreach ($json as $key => $value) { if (!isset($_REQUEST[$key])) { $_REQUEST[$key] = $value; } } } } function useVideoHashOrLogin() { if (!empty($_REQUEST['video_id_hash'])) { $videos_id = Video::getVideoIdFromHash($_REQUEST['video_id_hash']); if (!empty($videos_id)) { $users_id = Video::getOwner($videos_id); $user = new User($users_id); _error_log("useVideoHashOrLogin: $users_id, $videos_id"); return $user->login(true); } } return User::loginFromRequest(); } function strip_specific_tags($string, $tags_to_strip = array("script")) { foreach ($tags_to_strip as $tag) { $string = preg_replace('/<' . $tag . '[^>]*>(.*?)<\/' . $tag . '>/s', '', $string); } return $string; } function strip_render_blocking_resources($string) { $tags_to_strip = array('link', 'style'); $head = preg_match('/(.*)<\/head>/s', $string, $matches); $string = str_replace($matches[0], '{_head_}', $string); foreach ($tags_to_strip as $tag) { $string = preg_replace('/<' . $tag . '[^>]*>(.*?)<\/' . $tag . '>/s', '', $string); $string = preg_replace('/<' . $tag . '[^>]*\/>/s', '', $string); } $string = str_replace('{_head_}', $matches[0], $string); return $string; } function optimizeHTMLTags($html) { return $html; //$html = optimizeCSS($html); //$html = optimizeJS($html); return $html . '<--! optimized -->'; } function optimizeCSS($html) { global $global; $css = ''; $cacheDir = getVideosDir() . 'cache/'; $cacheName = md5(getSelfURI() . User::getId()) . '.css'; $filename = "{$cacheDir}{$cacheName}"; $urlname = "{$global['webSiteRootURL']}videos/cache/{$cacheName}"; $HTMLTag = ""; $fileExists = file_exists($filename); //$fileExists = false; // get link tags $pattern = '/((<(link)[^>]*(stylesheet|css)[^>]*\/>)|(<(style)[^>]*>([^<]+)<\/style>))/i'; preg_match_all($pattern, $html, $matches); foreach ($matches[3] as $key => $type) { if (strtolower($type) == 'link') { $linkTag = $matches[0][$key]; $pattern = '/href=.(http[^"\']+)/i'; preg_match($pattern, $linkTag, $href); if (empty($href)) { continue; } if (!$fileExists) { $content = url_get_contents($href[1]); if (empty($content)) { continue; } $css .= PHP_EOL . " /* link {$href[1]} */ " . $content; } $html = str_replace($linkTag, '', $html); } else { if (!$fileExists) { $css .= PHP_EOL . ' /* style */ ' . $matches[7][$key]; } $html = str_replace($matches[1][$key], '', $html); } } if (!$fileExists) { _file_put_contents($filename, $css); } return str_replace('', '' . PHP_EOL . $HTMLTag . PHP_EOL . '', $html); } function optimizeJS($html) { global $global; $js = ''; $cacheDir = getVideosDir() . 'cache/'; $cacheName = md5(getSelfURI() . User::getId()) . '.js'; $filename = "{$cacheDir}{$cacheName}"; $urlname = "{$global['webSiteRootURL']}videos/cache/{$cacheName}"; $HTMLTag = ""; $fileExists = file_exists($filename); $fileExists = false; // get link tags $pattern = '/((]+(src=[^ ]+)[^>]*>( *)<\/script>)|(]*>([^<]+)<\/script>))/si'; preg_match_all($pattern, $html, $matches); foreach ($matches[2] as $key => $type) { if (empty($type)) { if (preg_match('/application_ld_json/i', $matches[1][$key])) { continue; } $js .= PHP_EOL . " /* js */ " . $matches[6][$key]; $html = str_replace($matches[1][$key], '', $html); } else { $pattern = '/src=.(http[^"\']+)/i'; preg_match($pattern, $type, $href); if (empty($href)) { continue; } if (preg_match('/(jquery|video-js|videojs)/i', $href[1])) { continue; } if (!$fileExists) { $content = url_get_contents($href[1]); if (empty($content)) { continue; } $js .= PHP_EOL . " /* js link {$href[1]} */ " . $content; } $html = str_replace($type, '', $html); } } if (!$fileExists) { _file_put_contents($filename, $js); } return str_replace('', '' . PHP_EOL . $HTMLTag . PHP_EOL . '', $html); } function mysqlBeginTransaction() { global $global; _error_log('Begin transaction ' . getSelfURI()); $global['mysqli']->autocommit(false); } function mysqlRollback() { global $global; _error_log('Rollback transaction ' . getSelfURI(), AVideoLog::$ERROR); $global['mysqli']->rollback(); $global['mysqli']->autocommit(true); } function mysqlCommit() { global $global; _error_log('Commit transaction ' . getSelfURI()); $global['mysqli']->commit(); $global['mysqli']->autocommit(true); } function number_format_short($n, $precision = 1) { $n = floatval($n); if ($n < 900) { // 0 - 900 $n_format = number_format($n, $precision); $suffix = ''; } else if ($n < 900000) { // 0.9k-850k $n_format = number_format($n / 1000, $precision); $suffix = 'K'; } else if ($n < 900000000) { // 0.9m-850m $n_format = number_format($n / 1000000, $precision); $suffix = 'M'; } else if ($n < 900000000000) { // 0.9b-850b $n_format = number_format($n / 1000000000, $precision); $suffix = 'B'; } else { // 0.9t+ $n_format = number_format($n / 1000000000000, $precision); $suffix = 'T'; } // Remove unecessary zeroes after decimal. "1.0" -> "1"; "1.00" -> "1" // Intentionally does not affect partials, eg "1.50" -> "1.50" if ($precision > 0) { $dotzero = '.' . str_repeat('0', $precision); $n_format = str_replace($dotzero, '', $n_format); } return $n_format . $suffix; } function seconds2human($ss) { $s = $ss % 60; $m = floor(($ss % 3600) / 60); $h = floor(($ss % 86400) / 3600); $d = floor(($ss % 2592000) / 86400); $M = floor($ss / 2592000); $times = array(); if (!empty($M)) { $times[] = "$M " . __('m'); } if (!empty($d)) { $times[] = "$d " . __('d'); } if (!empty($h)) { $times[] = "$h " . __('h'); } if (!empty($m)) { $times[] = "$m " . __('min'); } if (!empty($s)) { $times[] = "$s " . __('sec'); } return implode(', ', $times); } function getTimeInTimezone($time, $timezone) { if (!is_numeric($time)) { $time = strtotime($time); } if (empty($timezone) || empty(date_default_timezone_get()) || $timezone == date_default_timezone_get()) { return $time; } $date = new DateTime(date('Y-m-d H:i:s', $time)); $date->setTimezone(new DateTimeZone($timezone)); //$date->setTimezone(date_default_timezone_get()); $dateString = $date->format('Y-m-d H:i:s'); return strtotime($dateString); } diff --git a/plugin/Live/Live.php b/plugin/Live/Live.php index 4af03d34c..822a9c28f 100644 --- a/plugin/Live/Live.php +++ b/plugin/Live/Live.php @@ -1,2775 +1,2777 @@ and receive HLS streaming from servers"; $lu = AVideoPlugin::loadPlugin("LiveUsers"); if (!empty($lu)) { if (version_compare($lu->getPluginVersion(), "2.0") < 0) { $desc .= "
You MUST update your LiveUsers plugin to version 2.0 or greater
"; } } $desc .= "
Start Self hosted WebRTC server: php {$global['systemRootPath']}plugin/Live/standAloneFiles/WebRTCServer/server.php "; $desc .= "
Help"; return $desc; } public function getName() { return "Live"; } public function getHTMLMenuRight() { global $global; $buttonTitle = $this->getButtonTitle(); $obj = $this->getDataObject(); if (!empty($obj->hideTopButton)) { return ''; } include $global['systemRootPath'] . 'plugin/Live/view/menuRight.php'; } public function getUUID() { return "e06b161c-cbd0-4c1d-a484-71018efa2f35"; } public function getPluginVersion() { return "10.0"; } public function updateScript() { global $global; //update version 2.0 $sql = "SELECT 1 FROM live_transmitions_history LIMIT 1"; $res = sqlDAL::readSql($sql); $fetch = sqlDAL::fetchAssoc($res); if (!$fetch) { sqlDal::writeSql(file_get_contents($global['systemRootPath'] . 'plugin/Live/install/updateV2.0.sql')); } //update version 3.0 $sql = "SELECT 1 FROM live_transmition_history_log LIMIT 1"; $res = sqlDAL::readSql($sql); $fetch = sqlDAL::fetchAssoc($res); if (!$fetch) { sqlDal::writeSql(file_get_contents($global['systemRootPath'] . 'plugin/Live/install/updateV3.0.sql')); } //update version 4.0 $sql = "SELECT 1 FROM live_servers LIMIT 1"; $res = sqlDAL::readSql($sql); $fetch = sqlDAL::fetchAssoc($res); if (!$fetch) { $sqls = file_get_contents($global['systemRootPath'] . 'plugin/Live/install/updateV4.0.sql'); $sqlParts = explode(";", $sqls); foreach ($sqlParts as $value) { sqlDal::writeSql(trim($value)); } } //update version 5.0 $sql = "SELECT 1 FROM live_restreams LIMIT 1"; $res = sqlDAL::readSql($sql); $fetch = sqlDAL::fetchAssoc($res); if (!$fetch) { $sqls = file_get_contents($global['systemRootPath'] . 'plugin/Live/install/updateV5.0.sql'); $sqlParts = explode(";", $sqls); foreach ($sqlParts as $value) { sqlDal::writeSql(trim($value)); } } //update version 5.1 if (AVideoPlugin::compareVersion($this->getName(), "5.1") < 0) { $sqls = file_get_contents($global['systemRootPath'] . 'plugin/Live/install/updateV5.1.sql'); $sqlParts = explode(";", $sqls); foreach ($sqlParts as $value) { sqlDal::writeSql(trim($value)); } } //update version 5.2 if (AVideoPlugin::compareVersion($this->getName(), "5.2") < 0) { $sqls = file_get_contents($global['systemRootPath'] . 'plugin/Live/install/updateV5.2.sql'); $sqlParts = explode(";", $sqls); foreach ($sqlParts as $value) { sqlDal::writeSql(trim($value)); } } if (AVideoPlugin::compareVersion($this->getName(), "6.0") < 0) { $sqls = file_get_contents($global['systemRootPath'] . 'plugin/Live/install/updateV6.0.sql'); $sqlParts = explode(";", $sqls); foreach ($sqlParts as $value) { sqlDal::writeSql(trim($value)); } } if (AVideoPlugin::compareVersion($this->getName(), "7.0") < 0) { $sqls = file_get_contents($global['systemRootPath'] . 'plugin/Live/install/updateV7.0.sql'); $sqlParts = explode(";", $sqls); foreach ($sqlParts as $value) { sqlDal::writeSql(trim($value)); } } if (AVideoPlugin::compareVersion($this->getName(), "7.2") < 0) { $sqls = file_get_contents($global['systemRootPath'] . 'plugin/Live/install/updateV7.2.sql'); $sqlParts = explode(";", $sqls); foreach ($sqlParts as $value) { sqlDal::writeSql(trim($value)); } } if (AVideoPlugin::compareVersion($this->getName(), "8.0") < 0) { $sqls = file_get_contents($global['systemRootPath'] . 'plugin/Live/install/updateV8.0.sql'); $sqlParts = explode(";", $sqls); foreach ($sqlParts as $value) { sqlDal::writeSql(trim($value)); } } if (AVideoPlugin::compareVersion($this->getName(), "9.0") < 0) { $sqls = file_get_contents($global['systemRootPath'] . 'plugin/Live/install/updateV9.0.sql'); $sqlParts = explode(";", $sqls); foreach ($sqlParts as $value) { sqlDal::writeSql(trim($value)); } } if (AVideoPlugin::compareVersion($this->getName(), "10.0") < 0) { $sqls = file_get_contents($global['systemRootPath'] . 'plugin/Live/install/updateV10.0.sql'); $sqlParts = explode(";", $sqls); foreach ($sqlParts as $value) { sqlDal::writeSql(trim($value)); } + LiveTransmitionHistory::finishALL(); } return true; } public function getLivePanel() { global $global; $filename = $global['systemRootPath'] . 'plugin/Live/view/panel.php'; include $filename; } public function getLiveApplicationArray() { global $global; $obj = $this->getDataObject(); $rows = Live_schedule::getAllActiveLimit(); $array = array(); $liveUsersEnabled = AVideoPlugin::isEnabledByName("LiveUsers"); foreach ($rows as $value) { $isLive = LiveTransmitionHistory::getActiveLiveFromUser($value['users_id'],$value['live_servers_id'], $value['key']); if($isLive){ continue; } $callback = ''; $link = Live::getLinkToLiveFromUsers_idAndLiveServer($value['users_id'],$value['live_servers_id']); $link = addQueryStringParameter($link, 'live_schedule', $value['id']); $LiveUsersLabelLive = ($liveUsersEnabled ? getLiveUsersLabelLive($value['key'], $value['live_servers_id']) : ''); $array[] = self::getLiveApplicationModelArray($value['users_id'], $value['title'], $link, Live_schedule::getPosterURL($value['id']), '' , 'scheduleLive', $LiveUsersLabelLive, 'LiveSchedule_'.$value['id'], $callback, $value['scheduled_time'], 'live_'.$value['key']); } return $array; } static function getLiveApplicationModelArray($users_id, $title, $link, $imgJPG, $imgGIF, $type, $LiveUsersLabelLive='', $uid ='', $callback='', $startsOnDate='', $class='') { global $global; $search = array( '_unique_id_', '_user_photo_', '_title_', '_user_identification_', '_link_', '_imgJPG_', '_imgGIF_', '_total_on_live_links_id_', '_class_', ); if(empty($global['getLiveApplicationModelArray']['content'])){ $filenameExtra = $global['systemRootPath'] . 'plugin/Live/view/extraitems_templates/extraItem.html'; $filenameExtraVideoPage = $global['systemRootPath'] . 'plugin/Live/view/extraitems_templates/extraItemVideoPage.html'; $filename = $filenameListItem = $global['systemRootPath'] . 'plugin/Live/view/extraitems_templates/videoListItem.html'; $global['getLiveApplicationModelArray']['content'] = file_get_contents($filename); $global['getLiveApplicationModelArray']['contentExtra'] = file_get_contents($filenameExtra); $global['getLiveApplicationModelArray']['contentExtraVideoPage'] = file_get_contents($filenameExtraVideoPage); $global['getLiveApplicationModelArray']['contentListem'] = file_get_contents($filenameListItem); } $u = new User($users_id); $lt = LiveTransmition::getFromDbByUser($users_id); $UserPhoto = User::getPhoto($users_id); $name = User::getNameIdentificationById($users_id); $comingsoon = false; if(!empty($startsOnDate)){ if(strtotime($startsOnDate) > time()){ $callback .= ';'. '$(\'.'.$uid . ' .liveNow\').attr(\'class\', \'liveNow label label-primary\');' . '$(\'.'.$uid . ' .liveNow\').text(\'' . $startsOnDate . '\');' . 'startTimerToDate(\'' . $startsOnDate . '\', \'.'.$uid . ' .liveNow\', true);'; $comingsoon = true; } } if(empty($imgJPG)){ $imgJPG = getURL(Live::getPosterThumbsImage($users_id, 0, $comingsoon)); } $replace = array( $uid, $UserPhoto, $title, $u->getUser(), $link, (!empty($imgJPG) ? '':''), (!empty($imgGIF) ? ('') : ''), $LiveUsersLabelLive, $class ); $newContent = str_replace($search, $replace, $global['getLiveApplicationModelArray']['content']); $newContentExtra = str_replace($search, $replace, $global['getLiveApplicationModelArray']['contentExtra']); $newContentExtraVideoPage = str_replace($search, $replace, $global['getLiveApplicationModelArray']['contentExtraVideoPage']); $newContentVideoListItem = str_replace($search, $replace, $global['getLiveApplicationModelArray']['contentListem']); $array = array( "html" => $newContent, "htmlExtra" => $newContentExtra, "htmlExtraVideoPage" => $newContentExtraVideoPage, "htmlExtraVideoListItem" => $newContentVideoListItem, "type" => $type, "photo" => $UserPhoto, "title" => $title, "users_id" => $users_id, "name" => $name, "href" => $link, "link" => $link, "callback" => $callback, 'poster' => $imgJPG, 'imgGif' => $imgGIF, 'categories_id' => intval($lt['categories_id']), 'className' => $uid ); return $array; } public function getEmptyDataObject() { global $global; $server = parse_url($global['webSiteRootURL']); $scheme = "http"; $port = "8080"; if (strtolower($server["scheme"]) == "https") { $scheme = "https"; $port = "8443"; } $obj = new stdClass(); $obj->button_title = "LIVE"; self::addDataObjectHelper('button_title', 'Button Title', 'This is the title that will appear in your button to enter in the Live panel'); $o = new stdClass(); $o->type = array(0=>__('Public').' UNDER DEVELOPMENT', 1=>__('Self Hosted')); $o->value = 1; $obj->server_type = $o; self::addDataObjectHelper('server_type', 'Server type', "If is set to public you do not need to configure anything"); $obj->server = "rtmp://{$server['host']}/live"; self::addDataObjectHelper('server', 'RTMP Server URL', 'Usually it is ' . "rtmp://{$server['host']}/live"); $obj->playerServer = "{$scheme}://{$server['host']}:{$port}/live"; self::addDataObjectHelper('playerServer', 'Player URL', 'This is a URL to your NGINX server, this URL will be used by the HTML5 player, If your site is HTTPS your player URL MUST be HTTPS as well, usually it is ' . "{$scheme}://{$server['host']}:{$port}/live"); $obj->stats = "{$scheme}://{$server['host']}:{$port}/stat"; self::addDataObjectHelper('stats', 'Stats Page URL', 'When you installed the NGINX you also install the stat.xsl, we will use it to grab the information when you have livestreams running, usually it is ' . "{$scheme}://{$server['host']}:{$port}/stat"); $obj->restreamerURL = "{$global['webSiteRootURL']}plugin/Live/standAloneFiles/restreamer.json.php"; self::addDataObjectHelper('restreamerURL', 'Restreamer URL', 'https://github.com/WWBN/AVideo/wiki/Restream'); $obj->controlURL = "{$global['webSiteRootURL']}plugin/Live/standAloneFiles/control.json.php"; self::addDataObjectHelper('controlURL', 'Control URL'); $obj->controlServer = "http://localhost:8080/"; self::addDataObjectHelper('controlServer', 'Control Server'); $obj->disableRestream = false; self::addDataObjectHelper('disableRestream', 'Disable Restream', 'If you check this, we will not send requests to your Restreamer URL'); $obj->disableDVR = false; self::addDataObjectHelper('disableDVR', 'Disable DVR', 'Enable or disable the DVR Feature, you can control the DVR length in your nginx.conf on the parameter hls_playlist_length'); $obj->disableGifThumbs = false; self::addDataObjectHelper('disableGifThumbs', 'Disable Gif Thumbs', 'This option will disable the Animated Gif render, it will save some hardware capacity from your encoder and may speedup your page'); $obj->disableLiveThumbs = false; self::addDataObjectHelper('disableLiveThumbs', 'Disable Live thumbnails', 'This option will disable the çive image extraction and will use the user static image, it will save some hardware capacity from your encoder and may speedup your page'); $obj->hideTopButton = false; self::addDataObjectHelper('hideTopButton', 'Hide Top Button', 'This will hide the "Go Live" button on the top menu bar'); $obj->useAadaptiveMode = false; self::addDataObjectHelper('useAadaptiveMode', 'Adaptive mode', 'https://github.com/WWBN/AVideo/wiki/Adaptive-Bitrates-on-Livestream'); $obj->protectLive = false; self::addDataObjectHelper('protectLive', 'Live Protection', 'With this your encryption key will be protected, and only your site player will be able to play your videos, download tools will not be able to download your video. if you want to share your live externally you can use the embed and you will still be protected. but if you want to use the m3u8 file you must disable this'); $obj->experimentalWebcam = false; self::addDataObjectHelper('experimentalWebcam', 'Experimental Webcam', 'Requires flash and it is deprecated, will be removed. not recommend to enable it.'); $obj->doNotShowLiveOnVideosList = false; self::addDataObjectHelper('doNotShowLiveOnVideosList', 'Do not show live on videos list', 'We will not show the live thumbs on the main Gallery page'); $obj->doNotShowOnlineOfflineLabel = false; self::addDataObjectHelper('doNotShowOnlineOfflineLabel', 'Hide the Online/Offline Badge on live streams'); $obj->doNotShowLiveOnCategoryList = false; self::addDataObjectHelper('doNotShowLiveOnCategoryList', 'Do not show live on site category list', 'We will not show the live thumbs on the main Gallery page'); $obj->doNotShowOfflineLiveOnCategoryList = false; self::addDataObjectHelper('doNotShowOfflineLiveOnCategoryList', 'Do not show offline lives on site category list', 'We will not show the live thumbs on the main Gallery page if it is offline'); $obj->limitLiveOnVideosList = 12; self::addDataObjectHelper('limitLiveOnVideosList', 'Videos List Limit', 'This will limit the maximum of videos that you will see in the Videos page'); $obj->doNotShowGoLiveButton = false; self::addDataObjectHelper('doNotShowGoLiveButton', 'Hide Top Go live Button', 'This will hide the "Go Live" button on the top menu bar'); $obj->doNotProcessNotifications = false; self::addDataObjectHelper('doNotProcessNotifications', 'Do not show notifications', 'Do not show the notification on the top bar'); $obj->useLiveServers = false; self::addDataObjectHelper('useLiveServers', 'Use Live Servers', 'Check this if you will use External Live Servers https://github.com/WWBN/AVideo/wiki/Live-Plugin#livestream-server-balance '); $obj->disableMeetCamera = false; self::addDataObjectHelper('disableMeetCamera', 'Disable Meet camera', 'This requires out Meet Server, with the Meet camera you can use your PC webcam directly in the webpage or mobile to make livestreams'); $obj->playLiveInFullScreen = false; self::addDataObjectHelper('playLiveInFullScreen', 'Play Livestream in Full Screen'); $obj->playLiveInFullScreenOnIframe = false; self::addDataObjectHelper('playLiveInFullScreenOnIframe', 'Play Livestream in Full Screen on IFrame'); $obj->hls_path = "/HLS/live"; self::addDataObjectHelper('hls_path', 'HLS Path URL', 'Used only when we stop a Live, we use this path to delete the files'); $obj->requestStatsTimout = 4; // if the server does not respond we stop wait self::addDataObjectHelper('requestStatsTimout', 'Stats Timout', 'If a remote server (stats page) does not respond we stop waiting after this timeout'); $obj->cacheStatsTimout = 15; // we will cache the result self::addDataObjectHelper('cacheStatsTimout', 'Stats Cache Timeout', 'we will cache the result, this will save some resources'); $obj->requestStatsInterval = 15; // how many seconds untill request the stats again self::addDataObjectHelper('requestStatsInterval', 'Stats Request Interval', 'how many seconds until request the stats again'); $obj->streamDeniedMsg = "You can not stream live videos"; self::addDataObjectHelper('streamDeniedMsg', 'Denied Message', 'We will show this message when a user is not allowed so watch a livestream'); $obj->allowMultipleLivesPerUser = true; self::addDataObjectHelper('allowMultipleLivesPerUser', 'Allow Multiple Lives Per User', 'Your users will be able to make unlimited livestreams'); $obj->controllButtonsShowOnlyToAdmin_record_start = false; self::addDataObjectHelper('controllButtonsShowOnlyToAdmin_record_start', 'Show Record Start Button Only to Admin', 'Regular users will not able to see this button'); $obj->controllButtonsShowOnlyToAdmin_record_stop = false; self::addDataObjectHelper('controllButtonsShowOnlyToAdmin_record_stop', 'Show Record Stop Button Only to Admin', 'Regular users will not able to see this button'); $obj->controllButtonsShowOnlyToAdmin_drop_publisher = false; self::addDataObjectHelper('controllButtonsShowOnlyToAdmin_drop_publisher', 'Show Drop Publisher Button Only to Admin', 'Regular users will not able to see this button'); $obj->controllButtonsShowOnlyToAdmin_drop_publisher_reset_key = false; self::addDataObjectHelper('controllButtonsShowOnlyToAdmin_drop_publisher_reset_key', 'Show Drop Publisher and Reset Key Button Only to Admin', 'Regular users will not able to see this button'); $obj->controllButtonsShowOnlyToAdmin_save_dvr = false; self::addDataObjectHelper('controllButtonsShowOnlyToAdmin_save_dvr', 'Show Save DVR Button Only to Admin', 'Regular users will not able to see this button'); $obj->disable_live_schedule = false; self::addDataObjectHelper('disable_live_schedule', 'Disable Live Schedule'); $obj->webRTC_isDisabled = false; self::addDataObjectHelper('webRTC_isDisabled', 'Disable WebRTC camera', 'https://github.com/WWBN/AVideo/wiki/WebRTC-Server'); $o = new stdClass(); $o->type = array(0=>__('Public'), 1=>__('Self Hosted')); $o->value = 0; $obj->webRTC_server = $o; self::addDataObjectHelper('webRTC_server', 'WebRTC Server', 'https://github.com/WWBN/AVideo/wiki/WebRTC-Server'); $ServerHost = getHostOnlyFromURL($global['webSiteRootURL']); $obj->webRTC_SelfHostedURL = $ServerHost; self::addDataObjectHelper('webRTC_SelfHostedURL', 'Self Hosted URL', 'Self Hosted only'); $obj->webRTC_CertPath = '/etc/letsencrypt/live/' . $ServerHost . '/cert.pem'; self::addDataObjectHelper('webRTC_CertPath', 'SSL Certificate path', 'Self Hosted only'); $obj->webRTC_KeyPath = '/etc/letsencrypt/live/' . $ServerHost . '/privkey.pem'; self::addDataObjectHelper('webRTC_KeyPath', 'SSL Key path', 'Self Hosted only'); $obj->webRTC_ChainCertPath = '/etc/letsencrypt/live/' . $ServerHost . '/chain.pem'; self::addDataObjectHelper('webRTC_ChainCertPath', 'SSL Certificate Chain path', 'Self Hosted only'); $obj->webRTC_PushRTMP = false; self::addDataObjectHelper('webRTC_PushRTMP', 'PushRTMP', 'Self Hosted only If it is unchecked we will restream the Webcam instead of pushing it'); return $obj; } public function getHeadCode() { global $global; $obj = $this->getDataObject(); // preload image $js = ""; $css = ''; if (!empty($obj->playLiveInFullScreen)) { if ((isLive() || isEmbed()) && canFullScreen()) { $css .= ''; $css .= ''; } $js .= ''; $css .= ''; } return $js . $css; } public static function getWebRTCPlayer($live_servers_id = -1) { $player = self::getWebRTCServerURL($live_servers_id); return "{$player}player/"; } public static function getWebRTCServerURL($live_servers_id = -1) { global $global; $obj = AVideoPlugin::getObjectData("Live"); if(empty($obj->webRTC_server->value)){ return 'https://webrtc.ypt.me/'; } if (!empty($obj->useLiveServers)) { if ($live_servers_id < 0) { $live_servers_id = self::getCurrentLiveServersId(); } $ls = new Live_servers($live_servers_id); if (!empty($ls->getwebRTC_server())) { return $ls->getwebRTC_server(); } } return "{$global['webSiteRootURL']}plugin/Live/standAloneFiles/WebRTCServer/"; } public function getFooterCode() { $obj = $this->getDataObject(); global $global; $js = ''; if (!empty($obj->playLiveInFullScreen)) { $js = ''; $js .= ''; } else if (!empty($obj->playLiveInFullScreenOnIframe)) { $js = ''; $js .= ''; } include $global['systemRootPath'] . 'plugin/Live/view/footer.php'; return $js; } public function getButtonTitle() { $o = $this->getDataObject(); return $o->button_title; } public function getKey() { $o = $this->getDataObject(); return $o->key; } static function getDestinationApplicationName() { $server = self::getPlayerServer(); $server = rtrim($server, "/"); $parts = explode("/", $server); $app = array_pop($parts); $domain = self::getControl(); //return "{$domain}/control/drop/publisher?app={$app}&name={$key}"; return "{$app}?p=" . User::getUserPass(); } static function getDestinationHost() { $server = self::getServer(); $host = parse_url($server, PHP_URL_HOST); return $host; } static function getDestinationPort() { $server = self::getServer(); $port = parse_url($server, PHP_URL_PORT); if (empty($port)) { $port = 1935; } return $port; } static function getServer($live_servers_id = -1) { $obj = AVideoPlugin::getObjectData("Live"); if(empty($obj->server_type->value)){ return 'rtmp://'.self::$public_server_domain.'/live'; } if (!empty($obj->useLiveServers)) { if ($live_servers_id < 0) { $live_servers_id = self::getCurrentLiveServersId(); } $ls = new Live_servers($live_servers_id); if (!empty($ls->getRtmp_server())) { return $ls->getRtmp_server(); } } return trim($obj->server); } static function getDropURL($key, $live_servers_id = 0) { $obj = AVideoPlugin::getObjectData("Live"); if(empty($obj->server_type->value)){ $app = 'live'; }else{ $server = $obj->server; $server = rtrim($server, "/"); $parts = explode("/", $server); $app = array_pop($parts); } $domain = self::getControl($live_servers_id); //return "{$domain}/control/drop/publisher?app={$app}&name={$key}"; return "{$domain}?command=drop_publisher&app={$app}&name={$key}&token=" . getToken(60); } static function getIsRecording($key, $live_servers_id = 0) { $obj = AVideoPlugin::getObjectData("Live"); $server = $obj->server; $server = rtrim($server, "/"); $parts = explode("/", $server); $app = array_pop($parts); $domain = self::getControl($live_servers_id); //return "{$domain}/control/drop/publisher?app={$app}&name={$key}"; return "{$domain}?command=is_recording&app={$app}&name={$key}&token=" . getToken(60); } static function getStartRecordURL($key, $live_servers_id = 0) { $obj = AVideoPlugin::getObjectData("Live"); $server = $obj->server; $server = rtrim($server, "/"); $parts = explode("/", $server); $app = array_pop($parts); $domain = self::getControl($live_servers_id); //return "{$domain}/control/drop/publisher?app={$app}&name={$key}"; return "{$domain}?command=record_start&app={$app}&name={$key}&token=" . getToken(60); } static function getStopRecordURL($key, $live_servers_id = 0) { $obj = AVideoPlugin::getObjectData("Live"); $server = $obj->server; $server = rtrim($server, "/"); $parts = explode("/", $server); $app = array_pop($parts); $domain = self::getControl($live_servers_id); return "{$domain}?command=record_stop&app={$app}&name={$key}&token=" . getToken(60); } static function controlRecording($key, $live_servers_id, $start = true, $try = 0) { if ($start) { $url = self::getStartRecordURL($key, $live_servers_id); } else { $url = self::getStopRecordURL($key, $live_servers_id); } $response = url_get_contents($url, '', 5); _error_log("Live:controlRecording {$url} {$live_servers_id} - [{$response}]"); $obj = new stdClass(); $obj->error = true; $obj->msg = ""; $obj->remoteResponse = false; if (!empty($response)) { $json = json_decode($response); if (!empty($json)) { if ($start && empty($json->error) && empty($json->response) && $try < 4) { _error_log("Live:controlRecording start record is not ready trying again in 5 seconds " . (isCommandLineInterface() ? 'From Command Line' : 'Not Command Line')); _error_log("Live:controlRecording " . json_encode(debug_backtrace())); sleep(5); return self::controlRecording($key, $live_servers_id, $start, $try + 1); } _error_log("Live:controlRecording start record is ready {$json->response}"); $obj->error = $json->error; $obj->msg = $json->msg; $obj->remoteResponse = true; } else { $obj->msg = "JSON response fail"; } } else { $obj->msg = "Control response fail"; } if ($obj->error) { _error_log("Live::controlRecording: [$key], [$live_servers_id], [$start] " . json_encode($obj)); } return $obj; } static function controlRecordingAsync($key, $live_servers_id, $start = true) { global $global; outputAndContinueInBackground(); $command = "php {$global['systemRootPath']}plugin/Live/controlRecording.php '$key' '$live_servers_id' '$start'"; _error_log("NGINX Live::controlRecordingAsync start ($command)"); $pid = execAsync($command); _error_log("NGINX Live::controlRecordingAsync end {$pid}"); return $pid; } static function userCanRecordLive($users_id) { if (!AVideoPlugin::isEnabledByName('SendRecordedToEncoder')) { return false; } return SendRecordedToEncoder::canRecord($users_id); } static function getButton($command, $key, $live_servers_id = 0, $iconsOnly = false, $label = "", $class = "", $tooltip = "") { if (!User::canStream()) { return ''; } global $global; $id = "getButton" . uniqid(); $afterLabel = ""; $obj = AVideoPlugin::getDataObject('Live'); switch ($command) { case "record_start": if ($obj->controllButtonsShowOnlyToAdmin_record_start && !User::isAdmin()) { return ''; } if (!self::userCanRecordLive(User::getId())) { return ''; } $buttonClass = "btn btn-success"; $iconClass = "fas fa-video"; if (empty($label)) { $label = __("Start Record"); } if (empty($tooltip)) { $tooltip = __("Start Record"); } $afterLabel = ''; break; case "record_stop": if (!self::userCanRecordLive(User::getId())) { return ''; } if ($obj->controllButtonsShowOnlyToAdmin_record_stop && !User::isAdmin()) { return ''; } $buttonClass = "btn btn-danger"; $iconClass = "fas fa-video-slash"; if (empty($label)) { $label = __("Stop Record"); } if (empty($tooltip)) { $tooltip = __("Stop Record"); } break; case "drop_publisher": if ($obj->controllButtonsShowOnlyToAdmin_drop_publisher && !User::isAdmin()) { return ''; } $buttonClass = "btn btn-default"; $iconClass = "fas fa-wifi"; if (empty($label)) { $label = __("Disconnect Livestream"); } if (empty($tooltip)) { $tooltip = __("Disconnect Livestream"); } break; case "drop_publisher_reset_key": if ($obj->controllButtonsShowOnlyToAdmin_drop_publisher_reset_key && !User::isAdmin()) { return ''; } $buttonClass = "btn btn-default"; $iconClass = "fas fa-key"; if (empty($label)) { $label = __("Disconnect Livestream"); } if (empty($tooltip)) { $tooltip = __("Disconnect Livestream") . __(" and also reset the stream name/key"); } break; case "save_dvr": $obj2 = AVideoPlugin::getDataObjectIfEnabled('SendRecordedToEncoder'); if (empty($obj2) || empty($obj2->saveDVREnable)) { return ''; } if ($obj->controllButtonsShowOnlyToAdmin_save_dvr && !User::isAdmin()) { return ''; } if (!self::userCanRecordLive(User::getId())) { return ''; } return '' . SendRecordedToEncoder::getSaveDVRButton($key, $live_servers_id, $class); break; default: return ''; } if ($iconsOnly) { $label = ""; } $html = ""; return $html; } static function getRecordControlls($key, $live_servers_id = 0, $iconsOnly = false) { if (!User::canStream()) { return ""; } $btn = "
"; $btn .= self::getButton("record_start", $key, $live_servers_id, $iconsOnly); $btn .= self::getButton("record_stop", $key, $live_servers_id, $iconsOnly); $btn .= "
"; return $btn; } static function getAllControlls($key, $live_servers_id = 0, $iconsOnly = false, $btnClass = '') { if (!Live::canManageLiveFromLiveKey($key, User::getId())) { return ''; } $btn = "
"; //$btn .= self::getButton("drop_publisher", $live_transmition_id, $live_servers_id); $btn .= self::getButton("save_dvr", $key, $live_servers_id, $iconsOnly, '', $btnClass); $btn .= self::getButton("drop_publisher_reset_key", $key, $live_servers_id, $iconsOnly, '', $btnClass); $btn .= self::getButton("record_start", $key, $live_servers_id, $iconsOnly, '', $btnClass); $btn .= self::getButton("record_stop", $key, $live_servers_id, $iconsOnly, '', $btnClass); $btn .= "
"; $btn .= ""; return $btn; } static function getRestreamer($live_servers_id = -1) { $obj = AVideoPlugin::getObjectData("Live"); if (!empty($obj->useLiveServers)) { if ($live_servers_id < 0) { $live_servers_id = self::getCurrentLiveServersId(); } $ls = new Live_servers($live_servers_id); if (!empty($ls->getRestreamerURL())) { return $ls->getRestreamerURL(); } } return $obj->restreamerURL; } static function getControl($live_servers_id = -1) { $obj = AVideoPlugin::getObjectData("Live"); if (!empty($obj->useLiveServers) && !empty($live_servers_id)) { if ($live_servers_id < 0) { $live_servers_id = self::getCurrentLiveServersId(); } $ls = new Live_servers($live_servers_id); if (!empty($ls->getControlURL())) { return $ls->getControlURL(); } } return $obj->controlURL; } static function getRTMPLink($users_id, $forceIndex = false) { $key = self::getKeyFromUser($users_id); return self::getRTMPLinkFromKey($key, $forceIndex); } static function getRTMPLinkFromKey($key, $forceIndex = false) { $lso = new LiveStreamObject($key); return $lso->getRTMPLink($forceIndex); } static function getRTMPLinkWithOutKey($users_id) { $lso = new LiveStreamObject(self::getKeyFromUser($users_id)); return $lso->getRTMPLinkWithOutKey(); } static function getRTMPLinkWithOutKeyFromKey($key) { $lso = new LiveStreamObject($key); return $lso->getRTMPLinkWithOutKey(); } static function getKeyFromUser($users_id) { if (!User::isLogged() || ($users_id !== User::getId() && !User::isAdmin())) { return false; } $user = new User($users_id); $trasnmition = LiveTransmition::createTransmitionIfNeed($users_id); return $trasnmition['key']; } static function getDynamicKey($key) { $objLive = AVideoPlugin::getDataObject("Live"); if ($objLive->allowMultipleLivesPerUser) { $key .= '-' . date('His'); } return $key; } static function getPlayerServer() { $obj = AVideoPlugin::getObjectData("Live"); $url = $obj->playerServer; $url = getCDNOrURL($url, 'CDN_Live'); if (!empty($obj->useLiveServers)) { $ls = new Live_servers(self::getLiveServersIdRequest()); if (!empty($ls->getPlayerServer())) { $url = $ls->getPlayerServer(); $url = getCDNOrURL($url, 'CDN_LiveServers', $ls->getId()); } } //$url = str_replace("encoder.gdrive.local", "192.168.1.18", $url); return $url; } static function getUseAadaptiveMode() { $obj = AVideoPlugin::getObjectData("Live"); if(empty($obj->server_type->value)){ return true; } if (!empty($obj->useLiveServers)) { $ls = new Live_servers(self::getCurrentLiveServersId()); return $ls->getUseAadaptiveMode(); } return $obj->useAadaptiveMode; } static function getRemoteFile() { return self::getRemoteFileFromLiveServersID(self::getCurrentLiveServersId()); } static function getRemoteFileFromLiveServersID($live_servers_id) { global $global; $obj = AVideoPlugin::getObjectData("Live"); if (empty($live_servers_id) || !empty($obj->useLiveServers)) { $ls = new Live_servers($live_servers_id); $url = $ls->getGetRemoteFile(); if (IsValidURL($url)) { return $url; } } return "{$global['webSiteRootURL']}plugin/Live/standAloneFiles/getRecordedFile.php"; } static function getRemoteFileFromRTMPHost($rtmpHostURI) { $live_servers_id = Live_servers::getServerIdFromRTMPHost($rtmpHostURI); return self::getRemoteFileFromLiveServersID($live_servers_id); } static function getLiveServersIdRequest() { if (empty($_REQUEST['live_servers_id'])) { return 0; } return intval($_REQUEST['live_servers_id']); } static function getM3U8File($uuid, $doNotProtect = false) { $live_servers_id = self::getLiveServersIdRequest(); $lso = new LiveStreamObject($uuid, $live_servers_id, false, false); return $lso->getM3U8($doNotProtect); } public function getDisableGifThumbs() { $o = $this->getDataObject(); return $o->disableGifThumbs; } public function getStatsURL($live_servers_id = 0) { global $global; $o = $this->getDataObject(); if (!empty($live_servers_id)) { $liveServer = new Live_servers($live_servers_id); if ($liveServer->getStats_url()) { return $liveServer->getStats_url(); } } return $o->stats; } public function getChat($uuid) { global $global; //check if LiveChat Plugin is available $filename = $global['systemRootPath'] . 'plugin/LiveChat/LiveChat.php'; if (file_exists($filename)) { require_once $filename; LiveChat::includeChatPanel($uuid); } } function getStatsObject($live_servers_id = 0, $force_recreate = false, $tries = 0) { if (!function_exists('simplexml_load_file')) { _error_log("Live::getStatsObject: You need to install the simplexml_load_file function to be able to see the Live stats", AVideoLog::$ERROR); return false; } $name = "getStats" . DIRECTORY_SEPARATOR . "live_servers_id_{$live_servers_id}" . DIRECTORY_SEPARATOR . "getStatsObject"; global $getStatsObject; if (!isset($getStatsObject)) { $getStatsObject = array(); } if (empty($force_recreate)) { //_error_log("Live::getStatsObject[$live_servers_id] 1: searching for cache"); if (isset($getStatsObject[$live_servers_id])) { _error_log("Live::getStatsObject[$live_servers_id] 2: return cached result"); return $getStatsObject[$live_servers_id]; } $result = ObjectYPT::getCache($name, maxLifetime() + 60, true); if (!empty($result)) { _error_log("Live::getStatsObject[$live_servers_id] 3: return cached result $name [lifetime=" . (maxLifetime() + 60) . "]"); return _json_decode($result); } _error_log("Live::getStatsObject[$live_servers_id] 4: cache not found"); } else { _error_log("Live::getStatsObject[$live_servers_id] 5: forced to be recreated"); } $o = $this->getDataObject(); if ($o->doNotProcessNotifications) { _error_log("Live::getStatsObject[$live_servers_id]: will not show notifications because you select the option doNotProcessNotifications on the live plugin "); $xml = new stdClass(); $xml->server = new stdClass(); $xml->server->application = array(); $getStatsObject[$live_servers_id] = $xml; ObjectYPT::setCache($name, json_encode($xml)); return $xml; } if (empty($o->requestStatsTimout)) { $o->requestStatsTimout = 2; } ini_set('allow_url_fopen ', 'ON'); $url = $this->getStatsURL($live_servers_id); if (!empty($_SESSION['getStatsObjectRequestStatsTimout'][$url])) { _error_log("Live::getStatsObject[$live_servers_id] RTMP Server ($url) is NOT responding we will wait less from now on => live_servers_id = ($live_servers_id) "); // if the server already fail, do not wait mutch for it next time, just wait 0.5 seconds $o->requestStatsTimout = $_SESSION['getStatsObjectRequestStatsTimout'][$url]; } //_error_log_debug("Live::getStatsObject ($url) ({$o->requestStatsTimout}) "); $waitFile = getTmpDir() . md5($name); if (file_exists($waitFile) && filemtime($waitFile) > time() - 10 && $tries < 10) { _error_log("Live::getStatsObject[$live_servers_id]: there is a request in progeress, please wait {$waitFile}"); sleep(1); return self::getStatsObject($live_servers_id, $force_recreate, $tries + 1); } _error_log("Live::getStatsObject[$live_servers_id]: Creating a waitfile {$waitFile}"); file_put_contents($waitFile, time()); $data = $this->get_data($url, $o->requestStatsTimout); unlink($waitFile); if (empty($data)) { _session_start(); if (empty($_SESSION['getStatsObjectRequestStatsTimout'])) { $_SESSION['getStatsObjectRequestStatsTimout'] = array(); } $_SESSION['getStatsObjectRequestStatsTimout'][$url] = $o->requestStatsTimout - 1; if ($_SESSION['getStatsObjectRequestStatsTimout'][$url] < 1) { $_SESSION['getStatsObjectRequestStatsTimout'][$url] = 2; } _error_log("Live::getStatsObject RTMP Server ($url) is OFFLINE, timeout=({$o->requestStatsTimout}) we could not connect on it => live_servers_id = ($live_servers_id) ", AVideoLog::$ERROR); $data = 'The RTMP Server is Unavailable0'; } else { if (!empty($_SESSION['getStatsObjectRequestStatsTimout'][$url])) { _error_log("Live::getStatsObject RTMP Server ($url) is respond again => live_servers_id = ($live_servers_id) "); // the server respont again, wait the default time _session_start(); $_SESSION['getStatsObjectRequestStatsTimout'][$url] = 0; unset($_SESSION['getStatsObjectRequestStatsTimout'][$url]); } } $xml = simplexml_load_string($data); $getStatsObject[$live_servers_id] = $xml; ObjectYPT::setCache($name, json_encode($xml)); return $xml; } function get_data($url, $timeout) { global $global; if (!IsValidURL($url)) { return false; } _error_log_debug("Live::get_data($url, $timeout)"); return url_get_contents($url, '', $timeout); } public function getChartTabs() { return '
  • ' . __('Live videos') . '
  • '; } public function getChartContent() { global $global; include $global['systemRootPath'] . 'plugin/Live/report.php'; } static public function saveHistoryLog($key) { // get the latest history for this key $latest = LiveTransmitionHistory::getLatest($key); if (!empty($latest)) { LiveTransmitionHistoryLog::addLog($latest['id']); } } public function dataSetup() { $obj = $this->getDataObject(); if (!isLive() || $obj->disableDVR) { return ""; } return "liveui: true"; } static function stopLive($users_id) { if (!User::isAdmin() && User::getId() != $users_id) { return false; } $obj = AVideoPlugin::getObjectData("Live"); if (!empty($obj)) { $server = str_replace("stats", "", $obj->stats); $lt = new LiveTransmition(0); $lt->loadByUser($users_id); $key = $lt->getKey(); $appName = self::getApplicationName(); $url = "{$server}control/drop/publisher?app={$appName}&name=$key"; url_get_contents($url); $dir = $obj->hls_path . "/$key"; if (is_dir($dir)) { exec("rm -fR $dir"); rrmdir($dir); } } } // not implemented yet static function startRecording($users_id) { if (!User::isAdmin() && User::getId() != $users_id) { return false; } $obj = AVideoPlugin::getObjectData("Live"); if (!empty($obj)) { $server = str_replace("stats", "", $obj->stats); $lt = new LiveTransmition(0); $lt->loadByUser($users_id); $key = $lt->getKey(); $appName = self::getApplicationName(); $url = "{$server}control/record/start?app={$appName}&name=$key"; url_get_contents($url); } } static function getApplicationName() { $rtmpServer = self::getServer(); $parts = explode('/', $rtmpServer); $live = end($parts); if (!preg_match('/^live/i', $live)) { $live = 'live'; } return trim($live); } // not implemented yet static function stopRecording($users_id) { if (!User::isAdmin() && User::getId() != $users_id) { return false; } $obj = AVideoPlugin::getObjectData("Live"); if (!empty($obj)) { $server = str_replace("stats", "", $obj->stats); $lt = new LiveTransmition(0); $lt->loadByUser($users_id); $key = $lt->getKey(); $appName = self::getApplicationName(); $url = "{$server}control/record/stop?app={$appName}&name=$key"; url_get_contents($url); } } static function getLinkToLiveFromUsers_id($users_id) { $live_servers_id = self::getCurrentLiveServersId(); return self::getLinkToLiveFromUsers_idAndLiveServer($users_id, $live_servers_id); } static function getLinkToLiveFromUsers_idAndLiveServer($users_id, $live_servers_id, $live_index = null) { if (empty($users_id)) { return false; } global $global; $user = new User($users_id); if (empty($user->getChannelName())) { return false; } return self::getLinkToLiveFromChannelNameAndLiveServer($user->getChannelName(), $live_servers_id, $live_index); } static function getLinkToLiveFromChannelNameAndLiveServer($channelName, $live_servers_id, $live_index = null) { global $global; $live_servers_id = intval($live_servers_id); $channelName = trim($channelName); if (empty($channelName)) { return false; } $url = "{$global['webSiteRootURL']}live/{$live_servers_id}/" . urlencode($channelName); if (!empty($live_index)) { $url .= '/' . urlencode($live_index); } else if (!isset($live_index) && !empty($_REQUEST['live_index'])) { $url .= '/' . urlencode($_REQUEST['live_index']); } if (!empty($_REQUEST['playlists_id_live'])) { $url = addQueryStringParameter($url, 'playlists_id_live', $_REQUEST['playlists_id_live']); } //return "{$global['webSiteRootURL']}plugin/Live/?live_servers_id={$live_servers_id}&c=" . urlencode($channelName); return $url; } static function getAvailableLiveServersId() { $ls = self::getAvailableLiveServer(); if (empty($ls)) { return 0; } else { return intval($ls->live_servers_id); } } static function getLastServersIdFromUser($users_id) { $last = LiveTransmitionHistory::getLatestFromUser($users_id); if (empty($last)) { return 0; } else { return intval($last['live_servers_id']); } } static function getLastsLiveHistoriesFromUser($users_id, $count = 10) { return LiveTransmitionHistory::getLastsLiveHistoriesFromUser($users_id, $count); } static function getLinkToLiveFromUsers_idWithLastServersId($users_id) { $live_servers_id = self::getLastServersIdFromUser($users_id); return self::getLinkToLiveFromUsers_idAndLiveServer($users_id, $live_servers_id); } static function getCurrentLiveServersId() { $live_servers_id = self::getLiveServersIdRequest(); if ($live_servers_id) { return $live_servers_id; } else { return self::getAvailableLiveServersId(); } } public function getVideosManagerListButtonTitle() { global $global; if (!User::isAdmin()) { return ""; } $btn = '
    '; return $btn; } public function getPluginMenu() { global $global; $obj = $this->getDataObject(); $btn = ''; - - if ($obj->useLiveServers) { - $servers = Live_servers::getAll(); - foreach ($servers as $value) { - $btn .= ''; + $btn = ''; + if($obj->server_type->value){ + if ($obj->useLiveServers) { + $servers = Live_servers::getAll(); + foreach ($servers as $value) { + $btn .= ''; + } + } else { + $btn .= ''; } - } else { - $btn .= ''; } - return $btn; } static function getStats($force_recreate = false) { global $getStatsLive, $_getStats, $getStatsObject; if (empty($force_recreate)) { if (isset($getStatsLive)) { _error_log('Live::getStats: return cached result'); return $getStatsLive; } } $obj = AVideoPlugin::getObjectData("Live"); if(empty($obj->server_type->value)){ $rows = LiveTransmitionHistory::getActiveLiveFromUser(0, '', '', 50); $servers = array(); $servers['applications'] = array(); foreach ($rows as $value) { if(!is_array($value)){ continue; } $servers['applications'][] = LiveTransmitionHistory::getApplicationObject($value['id']); } return $servers; }else if (empty($obj->useLiveServers)) { //_error_log('getStats getStats 1: ' . ($force_recreate?'force_recreate':'DO NOT force_recreate')); $getStatsLive = self::_getStats(0, $force_recreate); //_error_log('Live::getStats(0) 1'); return $getStatsLive; } else { $rows = Live_servers::getAllActive(); foreach ($rows as $key => $value) { $ls = new Live_servers(Live::getLiveServersIdRequest()); if (!empty($row['playerServer'])) { //_error_log('getStats getStats 2: ' . ($force_recreate?'force_recreate':'DO NOT force_recreate')); $server = self::_getStats($row['id'], $force_recreate); $server->live_servers_id = $row['id']; $server->playerServer = $row['playerServer']; $getStatsLive = $server; return $server; } } } $ls = Live_servers::getAllActive(); $liveServers = array(); $getLiveServersIdRequest = self::getLiveServersIdRequest(); foreach ($ls as $value) { $server = Live_servers::getStatsFromId($value['id'], $force_recreate); if (!empty($server) && is_object($server)) { $server->live_servers_id = $value['id']; $server->playerServer = $value['playerServer']; $server->applications = object_to_array($server->applications); foreach ($server->applications as $key => $app) { if (self::isAdaptive($app['key'])) { continue; } $_REQUEST['live_servers_id'] = $value['id']; if (empty($app['key'])) { $app['key'] = ""; } $server->applications[$key]['m3u8'] = self::getM3U8File($app['key']); $server->applications[$key]['isURL200'] = isURL200($server->applications[$key]['m3u8']); } $liveServers[] = $server; } else { _error_log("Live::getStats Live Server NOT found {$value['id']} " . json_encode($server) . " " . json_encode($value)); } } _error_log("Live::getStats return " . json_encode($liveServers)); $_REQUEST['live_servers_id'] = $getLiveServersIdRequest; $getStatsLive = $liveServers; return $liveServers; } static function isAdaptive($key) { if (preg_match('/_(hi|low|mid)$/i', $key)) { return true; } return false; } static function getAllServers() { $obj = AVideoPlugin::getObjectData("Live"); if (empty($obj->useLiveServers)) { return array("id" => 0, "name" => __("Default"), "status" => "a", "rtmp_server" => $obj->server, 'playerServer' => $obj->playerServer, "stats_url" => $obj->stats, "disableDVR" => $obj->disableDVR, "disableGifThumbs" => $obj->disableGifThumbs, "useAadaptiveMode" => $obj->useAadaptiveMode, "protectLive" => $obj->protectLive, "getRemoteFile" => ""); } else { return Live_servers::getAllActive(); } } static function getAvailableLiveServer() { global $_getAvailableLiveServer; if (isset($_getAvailableLiveServer)) { return $_getAvailableLiveServer; } // create 1 min cache $name = "Live::getAvailableLiveServer"; $return = ObjectYPT::getCache($name, 60, true); if (empty($return)) { $obj = AVideoPlugin::getObjectData("Live"); if (empty($obj->useLiveServers)) { $return = false; } else { $stats = getStatsNotifications(); $liveServers = array(); $servers = Live_servers::getAllActive(); foreach ($servers as $value) { $obj = new stdClass(); $obj->live_servers_id = $value['id']; $obj->countLiveStream = 0; $liveServers[$value['id']] = $obj; } foreach ($stats['applications'] as $value) { if (!empty($value['live_servers_id'])) { $liveServers[$value['live_servers_id']]->countLiveStream++; } } usort($liveServers, function($a, $b) { if ($a->countLiveStream == $b->countLiveStream) { $_getAvailableLiveServer = 0; return 0; } $_getAvailableLiveServer = ($a->countLiveStream < $b->countLiveStream) ? -1 : 1; return $_getAvailableLiveServer; }); if (empty($liveServers[0])) { _error_log("Live::getAvailableLiveServer we could not get server status, try to uncheck useLiveServers parameter from the Live plugin"); $_getAvailableLiveServer = array(); return array(); } $return = $liveServers[0]; ObjectYPT::setCache($name, $return); } } $_getAvailableLiveServer = $return; return $return; } static function canSeeLiveFromLiveKey($key) { $lt = self::getLiveTransmitionObjectFromKey($key); if (empty($lt)) { return false; } return $lt->userCanSeeTransmition(); } static function canManageLiveFromLiveKey($key, $users_id) { if (empty($users_id)) { return false; } $lt = self::getLiveTransmitionObjectFromKey($key); if (empty($lt)) { return false; } $user = new User($users_id); if ($user->getIsAdmin()) { return true; } $u_id = $lt->getUsers_id(); return $u_id == $users_id; } static function isAPrivateLiveFromLiveKey($key) { $lt = self::getLiveTransmitionObjectFromKey($key); if (empty($lt)) { return false; } return $lt->isAPrivateLive(); } static function getTitleFromUsers_Id($users_id) { $lt = self::getLiveTransmitionObjectFromUsers_id($users_id); return $lt->getTitle(); } static function getLiveTransmitionObjectFromUsers_id($users_id) { $latest = LiveTransmitionHistory::getLatestFromUser($users_id); if (!empty($latest)) { $key = $latest['key']; } else { $key = self::getLiveKey($users_id); } return self::getLiveTransmitionObjectFromKey($key); } static function getLiveTransmitionObjectFromKey($key) { global $getLiveTransmitionObjectFromKey; if (empty($getLiveTransmitionObjectFromKey)) { $getLiveTransmitionObjectFromKey = array(); } $parts = explode("_", $key); if (empty($parts[0])) { return false; } if (!isset($getLiveTransmitionObjectFromKey[$parts[0]])) { $livet = LiveTransmition::keyExists($parts[0]); if (empty($livet)) { $getLiveTransmitionObjectFromKey[$parts[0]] = false; } else { $lt = new LiveTransmition($livet['id']); $getLiveTransmitionObjectFromKey[$parts[0]] = $lt; } } return $getLiveTransmitionObjectFromKey[$parts[0]]; } static function _getStats($live_servers_id = 0, $force_recreate = false) { global $global, $_getStats; if (empty($_REQUEST['name'])) { //_error_log("Live::_getStats {$live_servers_id} GET " . json_encode($_GET)); //_error_log("Live::_getStats {$live_servers_id} POST " . json_encode($_POST)); //_error_log("Live::_getStats {$live_servers_id} REQUEST " . json_encode($_REQUEST)); $_REQUEST['name'] = "undefined"; } //_error_log('_getStats: ' . ($force_recreate?'force_recreate':'DO NOT force_recreate')); $cacheName = "getStats" . DIRECTORY_SEPARATOR . "live_servers_id_{$live_servers_id}" . DIRECTORY_SEPARATOR . "{$_REQUEST['name']}_" . User::getId(); //$force_recreate = true; if (empty($force_recreate)) { if (!empty($_getStats[$live_servers_id][$_REQUEST['name']]) && is_object($_getStats[$live_servers_id][$_REQUEST['name']])) { _error_log("Live::_getStats cached result 1 {$_REQUEST['name']} "); return $_getStats[$live_servers_id][$_REQUEST['name']]; } $result = ObjectYPT::getCache($cacheName, maxLifetime() + 60, true); if (!empty($result)) { _error_log("Live::_getStats cached result 2 {$_REQUEST['name']} {$cacheName}"); return _json_decode($result); } } session_write_close(); $obj = new stdClass(); $obj->error = true; $obj->msg = "OFFLINE"; $obj->nclients = 0; $obj->applications = array(); $obj->hidden_applications = array(); $obj->name = $_REQUEST['name']; $_getStats[$live_servers_id][$_REQUEST['name']] = $obj; $liveUsersEnabled = AVideoPlugin::isEnabledByName("LiveUsers"); $p = AVideoPlugin::loadPlugin("Live"); $xml = $p->getStatsObject($live_servers_id, $force_recreate); $xml = json_encode($xml); $xml = _json_decode($xml); $stream = false; $lifeStream = array(); $applicationName = self::getApplicationName(); if (empty($xml) || !is_object($xml)) { _error_log("_getStats XML is not an object live_servers_id=$live_servers_id"); } else { //$obj->server = $xml->server; if (!empty($xml->server->application) && !is_array($xml->server->application)) { $application = $xml->server->application; $xml->server->application = array(); $xml->server->application[] = $application; } foreach ($xml->server->application as $key => $application) { if ($application->name !== $applicationName && $application->name !== 'adaptive') { continue; } if (!empty($application->live->stream)) { if (empty($lifeStream)) { $lifeStream = array(); } $stream = $application->live->stream; if (empty($application->live->stream->name) && !empty($application->live->stream[0]->name)) { foreach ($application->live->stream as $stream) { if (Live::isAdaptive($stream->name)) { continue; } $lifeStream[] = $stream; } } else { if (Live::isAdaptive($stream->name)) { continue; } $lifeStream[] = $application->live->stream; } } } } $obj->disableGif = $p->getDisableGifThumbs(); foreach ($lifeStream as $value) { if (!empty($value->name)) { $row = LiveTransmition::keyExists($value->name); //var_dump($row);exit; if (empty($row['users_id'])) { continue; } if (!empty($row) && $value->name === $obj->name) { $obj->msg = "ONLINE"; } $title = $row['title']; $u = new User($row['users_id']); $hiddenName = preg_replace('/^(.{5})/', '*****', $value->name); //_error_log('Live::isLiveFromKey:_getStats '. json_encode($_SERVER)); if (!self::canSeeLiveFromLiveKey($value->name)) { $obj->hidden_applications[] = array( "key" => $value->name, "name" => $row['channelName'], "user" => $row['channelName'], "title" => "{$row['channelName']} ($hiddenName} is a private live", ); if (!User::isAdmin()) { continue; } else { $title .= " (private live)"; } } else if (empty($row) || empty($row['public'])) { $obj->hidden_applications[] = array( "key" => $value->name, "name" => $row['channelName'], "user" => $row['channelName'], "title" => "{$row['channelName']} ($hiddenName} " . __("is set to not be listed") ); if (!User::isAdmin()) { continue; } else { $title .= __(" (set to not be listed)"); } } else if ($u->getStatus() !== 'a') { $obj->hidden_applications[] = array( "key" => $value->name, "name" => $row['channelName'], "user" => $row['channelName'], "title" => "{$row['channelName']} {$hiddenName} " . __("the user is inactive"), ); if (!User::isAdmin()) { continue; } else { $title .= __(" (user is inactive)"); } } $users = false; if ($liveUsersEnabled) { $filename = $global['systemRootPath'] . 'plugin/LiveUsers/Objects/LiveOnlineUsers.php'; if (file_exists($filename)) { require_once $filename; $liveUsers = new LiveOnlineUsers(0); $users = $liveUsers->getUsersFromTransmitionKey($value->name, $live_servers_id); } } $userName = $u->getNameIdentificationBd(); $user = $u->getUser(); $channelName = $u->getChannelName(); $photo = $u->getPhotoDB(); //return array('key'=>$key, 'cleanKey'=>$cleanKey, 'live_index'=>$live_index, 'playlists_id_live'=>$playlists_id_live); $parameters = self::getLiveParametersFromKey($value->name); $playlists_id_live = $parameters['playlists_id_live']; $live_index = $parameters['live_index']; if (!empty($playlists_id_live)) { $_REQUEST['playlists_id_live'] = $playlists_id_live; $playlists_id_live = $_REQUEST['playlists_id_live']; $photo = PlayLists::getImage($_REQUEST['playlists_id_live']); $title = PlayLists::getNameOrSerieTitle($_REQUEST['playlists_id_live']); } if (!empty($live_index)) { $_REQUEST['live_index'] = $live_index; } if (!empty($live_index) || $live_index === 'false') { $title .= " ({$live_index})"; } $LiveUsersLabelLive = ($liveUsersEnabled ? getLiveUsersLabelLive($value->name, $live_servers_id) : ''); $imgJPG = $p->getLivePosterImage($row['users_id'], $live_servers_id, $playlists_id_live, $live_index); if($obj->disableGif){ $imgGIF = ''; }else{ $imgGIF = $p->getLivePosterImage($row['users_id'], $live_servers_id, $playlists_id_live, $live_index, 'webp'); } $uid = "live_{$live_servers_id}_{$value->name}"; $link = Live::getLinkToLiveFromChannelNameAndLiveServer($u->getChannelName(), $live_servers_id, $live_index); if(!empty($row['scheduled'])){ $link = addQueryStringParameter($link, 'live_schedule', $row['id']); $imgJPG = addQueryStringParameter($imgJPG, 'live_schedule', $row['id']); if(!empty($imgGIF)){ $imgGIF = addQueryStringParameter($imgGIF, 'live_schedule', $row['id']); } } $app = self::getLiveApplicationModelArray($row['users_id'], $title, $link, $imgJPG, $imgGIF, 'live', $LiveUsersLabelLive, $uid, '', $uid, 'live_'.$value->name); $app['live_servers_id'] = $live_servers_id; $app['key'] = $value->name; $obj->applications[] = $app; if ($value->name === $obj->name) { $obj->error = property_exists($value, 'publishing') ? false : true; $obj->msg = (!$obj->error) ? "ONLINE" : "Waiting for Streamer"; $obj->stream = $value; $obj->nclients = intval($value->nclients); break; } } } $obj->countLiveStream = count($obj->applications); $obj->error = false; $_getStats[$live_servers_id][$_REQUEST['name']] = $obj; //_error_log("Live::_getStats NON cached result {$_REQUEST['name']} " . json_encode($obj)); ObjectYPT::setCache($cacheName, json_encode($obj)); return $obj; } static function byPass() { if (preg_match('/socket_notification/', $_SERVER['SCRIPT_FILENAME'])) { return true; } return false; } static function getLiveParametersFromKey($key) { $key = preg_replace('/[^a-z0-9_-]/i', '', $key); $obj = AVideoPlugin::getObjectData('Live'); $playlists_id_live = false; if (preg_match("/.*_([0-9]+)/", $key, $matches)) { if (!empty($matches[1])) { $playlists_id_live = intval($matches[1]); } } $live_index = ''; if (preg_match("/.*-([0-9a-zA-Z]+)/", $key, $matches)) { if (!empty($matches[1])) { $live_index = strip_tags($matches[1]); if ($live_index === 'false') { $live_index = ''; } } } $cleanKey = self::cleanUpKey($key); return array('key' => $key, 'cleanKey' => $cleanKey, 'live_index' => $live_index, 'playlists_id_live' => $playlists_id_live); } static function getLiveIndexFromKey($key) { $parameters = self::getLiveParametersFromKey($key); return $parameters['live_index']; } static function cleanUpKey($key) { if ($adapKey = self::isAdaptiveTransmition($key)) { $key = $adapKey; } if ($plKey = self::isPlayListTransmition($key)) { $key = $plKey; } if ($subKey = self::isSubTransmition($key)) { $key = $subKey; } return $key; } static function isAdaptiveTransmition($key) { // check if is a subtransmition $parts = explode("_", $key); if (!empty($parts[1])) { $adaptive = array('hi', 'low', 'mid'); if (in_array($parts[1], $adaptive)) { return $parts[0]; ; } } return false; } static function isPlayListTransmition($key) { // check if is a subtransmition $parts = explode("_", $key); if (!empty($parts[1])) { return $parts[0]; } else { return false; } } static function isSubTransmition($key) { // check if is a subtransmition $parts = explode("-", $key); if (!empty($parts[1])) { return $parts[0]; } else { return false; } } static function getImage($users_id, $live_servers_id, $playlists_id_live = 0, $live_index = '') { $p = AVideoPlugin::loadPlugin("Live"); if (self::isLive($users_id, $live_servers_id, $live_index)) { $url = $p->getLivePosterImage($users_id, $live_servers_id, $playlists_id_live, $live_index); $url = addQueryStringParameter($url, "playlists_id_live", $playlists_id_live); } else { $url = self::getOfflineImage(false); } return $url; } static function getLatestKeyFromUser($users_id) { if (empty($users_id)) { return false; } $latest = LiveTransmitionHistory::getLatestFromUser($users_id); if (empty($latest)) { return false; } return $latest['key']; } static function isLive($users_id, $live_servers_id = 0, $live_index = '', $force_recreate = false) { global $_live_is_live; if (empty($users_id)) { return false; } if (!isset($_live_is_live)) { $_live_is_live = array(); } $name = "{$users_id}_{$live_servers_id}"; if (!empty($_live_is_live[$name])) { return $_live_is_live[$name]; } $lh = LiveTransmitionHistory::getActiveLiveFromUser($users_id, $live_servers_id, ''); if (empty($lh)) { _error_log("Live::isLive we could not found any active livestream for user $users_id, $live_servers_id"); return false; } $key = $lh['key']; $_live_is_live[$name] = self::isLiveAndIsReadyFromKey($key, $live_servers_id, $live_index, $force_recreate); return $_live_is_live[$name]; } static function isKeyLiveInStats($key, $live_servers_id = 0, $live_index = '', $force_recreate = false) { global $_isLiveFromKey; if (empty($key) || $key == '-1') { _error_log('Live::isKeyLiveInStats key is empty'); return false; } $index = "$key, $live_servers_id,$live_index"; if (!isset($_isLiveFromKey)) { $_isLiveFromKey = array(); } if (empty($force_recreate) && isset($_isLiveFromKey[$index])) { _error_log('Live::isKeyLiveInStats key is already set'); return $_isLiveFromKey[$index]; } $o = AVideoPlugin::getObjectData("Live"); if(empty($o->server_type->value)){ return LiveTransmitionHistory::isLive($key); } //_error_log('getStats execute getStats: ' . __LINE__ . ' ' . __FILE__); //$json = getStatsNotifications($force_recreate); //_error_log('getStats execute getStats: ' . ($force_recreate?'force_recreate':'DO NOT force_recreate')); $json = self::getStats($force_recreate); //_error_log('Live::isKeyLiveInStats:self::getStats ' . json_encode($json)); $_isLiveFromKey[$index] = false; if (!empty($json)) { //_error_log("Live::isLiveFromKey {$key} JSON was not empty"); if (!is_array($json)) { $json = array($json); } $namesFound = array(); foreach ($json as $ki => $item) { //_error_log("Live::isLiveFromKey json [$ki] " . json_encode($item)); $applications = array(); if (empty($item->applications) && is_array($item)) { $applications = $item; } else if (is_object($item) && !empty($item->applications)) { $applications = $item->applications; } foreach ($applications as $k => $value) { $value = object_to_array($value); //_error_log("Live::isLiveFromKey applications [$k] ". json_encode($value)); if (!is_array($value) || empty($value) || empty($value['key'])) { continue; } $namesFound[] = "({$value['key']})"; if (preg_match("/{$key}.*/", $value['key'])) { if (empty($live_servers_id)) { $_isLiveFromKey[$index] = true; $_isLiveFromKey[$index] = $_isLiveFromKey[$index]; break 2; } else { if (intval(@$value['live_servers_id']) == $live_servers_id) { $_isLiveFromKey[$index] = true; $_isLiveFromKey[$index] = $_isLiveFromKey[$index]; break 2; } } } } if (!empty($item->hidden_applications)) { $applications = $item->hidden_applications; foreach ($applications as $value) { $value = object_to_array($value); if (!is_array($value) || empty($value) || empty($value['key'])) { continue; } $namesFound[] = "({$value['key']})"; if (preg_match("/{$key}.*/", $value['key'])) { if (empty($live_servers_id)) { $_isLiveFromKey[$index] = true; $_isLiveFromKey[$index] = $_isLiveFromKey[$index]; break 2; } else { if (intval(@$value['live_servers_id']) == $live_servers_id) { $_isLiveFromKey[$index] = true; $_isLiveFromKey[$index] = $_isLiveFromKey[$index]; break 2; } } } } } } _error_log("Live::isLiveFromKey namesFound " . json_encode($namesFound)); } if (empty($_isLiveFromKey[$index])) { _error_log("Live::isLiveFromKey is NOT online [{$key}]"); } else { _error_log("Live::isLiveFromKey is online [{$key}]"); } return $_isLiveFromKey[$index]; } static function isLiveAndIsReadyFromKey($key, $live_servers_id = 0, $live_index = '', $force_recreate = false) { global $_isLiveAndIsReadyFromKey; if (!isset($_isLiveAndIsReadyFromKey)) { $_isLiveAndIsReadyFromKey = array(); } $name = "getStats" . DIRECTORY_SEPARATOR . "isLiveAndIsReadyFromKey{$key}_{$live_servers_id}"; if (empty($force_recreate)) { if (isset($_isLiveAndIsReadyFromKey[$name])) { return $_isLiveAndIsReadyFromKey[$name]; } $cache = ObjectYPT::getCache($name, 60, true); } if (!empty($cache)) { $json = _json_decode($cache); } if (!empty($json) && is_object($json)) { $_isLiveAndIsReadyFromKey[$name] = $json->result; } else { $json = new stdClass(); $key = self::getLiveKeyFromRequest($key, $live_index); //_error_log('getStats execute isKeyLiveInStats: ' . __LINE__ . ' ' . __FILE__); //_error_log("isLiveAndIsReadyFromKey::key: {$key}"); $isLiveFromKey = self::isKeyLiveInStats($key, $live_servers_id, $live_index, $force_recreate); $_isLiveAndIsReadyFromKey[$name] = true; if (empty($isLiveFromKey)) { _error_log("isLiveAndIsReadyFromKey the key {$key} is not present on the stats"); $_isLiveAndIsReadyFromKey[$name] = false; } else { $ls = @$_REQUEST['live_servers_id']; $_REQUEST['live_servers_id'] = $live_servers_id; $m3u8 = self::getM3U8File($key); $_REQUEST['live_servers_id'] = $ls; //_error_log('getStats execute isURL200: ' . __LINE__ . ' ' . __FILE__); $is200 = isValidM3U8Link($m3u8); if (empty($is200)) { _error_log("isLiveAndIsReadyFromKey the m3u8 file is not present {$m3u8}"); $_isLiveAndIsReadyFromKey[$name] = false; } } $json->result = $_isLiveAndIsReadyFromKey[$name]; ObjectYPT::setCache($name, json_encode($json)); } return $_isLiveAndIsReadyFromKey[$name]; } static function getOnlineLivesFromUser($users_id) { $key = self::getLiveKey($users_id); return self::getOnlineLivesFromKey($key); } static function getOnlineLivesFromKey($key) { $json = getStatsNotifications(); $lives = array(); if (!empty($json) && is_object($json) && !empty($json->applications)) { foreach ($json->applications as $value) { if (preg_match("/{$key}.*/", $value['key'])) { $lives[] = $value; } } } return $lives; } static function keyIsFromPlaylist($key) { $parts = explode("_", $key); if (empty($parts[1])) { return false; } return array('key' => $parts[0], 'playlists_id' => $parts[1]); } static function getLiveKey($users_id) { $lt = new LiveTransmition(0); $lt->loadByUser($users_id); return $lt->getKey(); } static function getLiveKeyFromUser($users_id, $live_index = '', $playlists_id_live = '') { $key = self::getLiveKey($users_id); return self::getLiveKeyFromRequest($key, $live_index, $playlists_id_live); } static function getLiveKeyFromRequest($key, $live_index = '', $playlists_id_live = '') { if (strpos($key, '-') === false) { if (!empty($live_index)) { $key .= '-' . preg_replace('/[^0-9a-z]/i', '', $live_index); } else if (!empty($_REQUEST['live_index'])) { $key .= '-' . preg_replace('/[^0-9a-z]/i', '', $_REQUEST['live_index']); } } if (strpos($key, '_') === false) { if (!empty($playlists_id_live)) { $key .= '_' . preg_replace('/[^0-9]/', '', $_REQUEST['playlists_id_live']); } else if (!empty($_REQUEST['playlists_id_live'])) { $key .= '_' . preg_replace('/[^0-9]/', '', $_REQUEST['playlists_id_live']); } } return $key; } public function getImageGif($users_id, $live_servers_id = 0, $playlists_id_live = 0, $live_index = '') { global $global; if (empty($live_servers_id)) { $live_servers_id = self::getCurrentLiveServersId(); } if ($live_index === 'false') { $live_index = ''; } $u = new User($users_id); $username = $u->getUser(); $file = "plugin/Live/getImage.php"; $url = $global['webSiteRootURL'] . $file; $url = addQueryStringParameter($url, "live_servers_id", $live_servers_id); $url = addQueryStringParameter($url, "playlists_id_live", $playlists_id_live); $url = addQueryStringParameter($url, "live_index", $live_index); $url = addQueryStringParameter($url, "u", $username); $url = addQueryStringParameter($url, "format", 'gif'); return $url; } public static function getPosterImage($users_id, $live_servers_id) { global $global; $file = self::_getPosterImage($users_id, $live_servers_id); if (!file_exists($global['systemRootPath'] . $file)) { $file = self::getOnAirImage(false); } return $file; } public static function getPosterImageOrFalse($users_id, $live_servers_id) { $poster = self::getPosterImage($users_id, $live_servers_id); if (preg_match('/OnAir.jpg$/', $poster)) { return false; } return $poster; } public function getLivePosterImage($users_id, $live_servers_id = 0, $playlists_id_live = 0, $live_index = '', $format = 'jpg') { global $global; return $global['webSiteRootURL'] . self::getLivePosterImageRelativePath($users_id, $live_servers_id, $playlists_id_live, $live_index, $format); } public function getLivePosterImageRelativePath($users_id, $live_servers_id = 0, $playlists_id_live = 0, $live_index = '', $format = 'jpg') { global $global; if (empty($live_servers_id)) { $live_servers_id = self::getCurrentLiveServersId(); } if (self::isLiveThumbsDisabled()) { $file = self::_getPosterImage($users_id, $live_servers_id); if (!file_exists($global['systemRootPath'] . $file)) { $file = self::getOnAirImage(false); } } else { $u = new User($users_id); $username = $u->getUser(); $file = "plugin/Live/getImage.php?live_servers_id={$live_servers_id}&playlists_id_live={$playlists_id_live}&live_index={$live_index}&u={$username}&format={$format}"; } return $file; } public static function isLiveThumbsDisabled() { $obj = AVideoPlugin::getDataObject("Live"); if (!empty($obj->disableLiveThumbs)) { return true; } return false; } public static function getPosterThumbsImage($users_id, $live_servers_id, $cominsoon=false) { global $global; if(empty($_REQUEST['live_schedule'])){ $file = self::_getPosterThumbsImage($users_id, $live_servers_id); }else{ $array = Live_schedule::getPosterPaths($live_schedule_id); $file = $array['relative_path']; } if (!file_exists($global['systemRootPath'] . $file)) { if($cominsoon){ $file = self::getComingSoonImage(false); }else{ $file = self::getOnAirImage(false); } } return $file; } public static function getPoster($users_id, $live_servers_id, $key = '') { _error_log("getPoster($users_id, $live_servers_id, $key)"); $lh = LiveTransmitionHistory::getActiveLiveFromUser($users_id, $live_servers_id, $key); $live_index = self::getLiveIndexFromKey($lh['key']); $poster = self::getPosterImageOrFalse($users_id, $live_servers_id, $live_index); if (empty($poster)) { $poster = self::getOfflineImage(false); } if (empty($lh)) { _error_log("getPoster empty activity"); return $poster; } $parameters = self::getLiveParametersFromKey($lh['key']); $live_index = $parameters['live_index']; $playlists_id_live = $parameters['playlists_id_live']; if (self::isLiveAndIsReadyFromKey($lh['key'], $lh['live_servers_id'])) { return self::getLivePosterImageRelativePath($users_id, $live_servers_id, $playlists_id_live, $live_index); _error_log('getImage: ' . ("[{$lh['key']}, {$lh['live_servers_id']}]") . ' is live and ready'); } else { if (self::isKeyLiveInStats($lh['key'], $lh['live_servers_id'])) { _error_log('getImage: ' . ("[{$lh['key']}, {$lh['live_servers_id']}]") . ' key is in the stats'); return self::getPosterImage($users_id, $live_servers_id, $live_index); } else { _error_log('getImage: ' . ("[{$lh['key']}, {$lh['live_servers_id']}]") . ' key is NOT in the stats'); return $poster; } } } public static function getPosterFromKey($key, $live_servers_id, $live_index = '') { $key = self::getLatestKeyFromUser($users_id); } static function getOfflineImage($includeURL = true) { global $global; $img = "plugin/Live/view/Offline.jpg"; if ($includeURL) { $img = getCDN() . $img; } return $img; } static function getOnAirImage($includeURL = true) { global $global; $img = "plugin/Live/view/OnAir.jpg"; if ($includeURL) { $img = getCDN() . $img; } return $img; } static function getComingSoonImage($includeURL = true) { global $global; $img = "plugin/Live/view/ComingSoon.jpg"; if ($includeURL) { $img = getCDN() . $img; } return $img; } public static function _getPosterImage($users_id, $live_servers_id) { $file = "videos/userPhoto/Live/user_{$users_id}_bg_{$live_servers_id}.jpg"; return $file; } public static function _getPosterThumbsImage($users_id, $live_servers_id) { $file = "videos/userPhoto/Live/user_{$users_id}_thumbs_{$live_servers_id}.jpg"; return $file; } public static function on_publish($liveTransmitionHistory_id) { $obj = AVideoPlugin::getDataObject("Live"); if (empty($obj->disableRestream)) { self::restream($liveTransmitionHistory_id); } $lt = new LiveTransmitionHistory($liveTransmitionHistory_id); AVideoPlugin::onLiveStream($lt->getUsers_id(), $lt->getLive_servers_id()); } public static function deleteStatsCache($clearFirstPage = false) { global $getStatsLive, $_getStats, $getStatsObject, $_getStatsNotifications, $__getAVideoCache, $_isLiveFromKey, $_isLiveAndIsReadyFromKey; _error_log_debug("Live::deleteStatsCache"); $tmpDir = ObjectYPT::getCacheDir(); $cacheDir = $tmpDir . "getstats" . DIRECTORY_SEPARATOR; if (isset($live_servers_id)) { $cacheDir .= "live_servers_id_{$live_servers_id}"; $pattern = "/.getStats.{$live_servers_id}.*/i"; ObjectYPT::deleteCachePattern($pattern); } //_error_log("Live::deleteStatsCache [{$cacheDir}]"); rrmdir($cacheDir); exec('rm -R ' . $cacheDir); if (is_dir($cacheDir)) { //_error_log("Live::deleteStatsCache [{$cacheDir}] looks like the cache was not deleted", AVideoLog::$ERROR); exec('rm -R ' . $cacheDir); } else { //_error_log("Live::deleteStatsCache [{$cacheDir}] Success"); } if ($clearFirstPage) { clearCache(true); } isURL200Clear(); unset($__getAVideoCache); unset($getStatsLive); unset($getStatsObject); unset($_getStats); unset($_getStatsNotifications); unset($_isLiveFromKey); unset($_isLiveAndIsReadyFromKey); } public static function getReverseRestreamObject($m3u8, $users_id, $live_servers_id = -1, $forceIndex = false) { if (!isValidURL($m3u8)) { return false; } $obj = new stdClass(); $obj->m3u8 = $m3u8; $obj->restreamerURL = self::getRestreamer($live_servers_id); $obj->restreamsDestinations = array(Live::getRTMPLink($users_id, $forceIndex)); $obj->token = getToken(60); $obj->users_id = $users_id; return $obj; } public static function getRestreamObject($liveTransmitionHistory_id) { if (empty($liveTransmitionHistory_id)) { return false; } $lth = new LiveTransmitionHistory($liveTransmitionHistory_id); if (empty($lth->getKey())) { return false; } $_REQUEST['live_servers_id'] = $lth->getLive_servers_id(); $obj = new stdClass(); $obj->m3u8 = self::getM3U8File($lth->getKey(), true); $obj->restreamerURL = self::getRestreamer($lth->getLive_servers_id()); $obj->restreamsDestinations = array(); $obj->token = getToken(60); $obj->users_id = $lth->getUsers_id(); $rows = Live_restreams::getAllFromUser($lth->getUsers_id()); foreach ($rows as $value) { $value['stream_url'] = rtrim($value['stream_url'], "/") . '/'; $obj->restreamsDestinations[] = "{$value['stream_url']}{$value['stream_key']}"; } return $obj; } public static function reverseRestream($m3u8, $users_id, $live_servers_id = -1, $forceIndex = false) { _error_log("Live:reverseRestream start"); $obj = self::getReverseRestreamObject($m3u8, $users_id, $live_servers_id, $forceIndex); _error_log("Live:reverseRestream obj " . _json_encode($obj)); return self::sendRestream($obj); } public static function restream($liveTransmitionHistory_id) { outputAndContinueInBackground(); $obj = self::getRestreamObject($liveTransmitionHistory_id); return self::sendRestream($obj); } private static function sendRestream($obj) { _error_log("Live:sendRestream start"); try { if (empty($obj)) { _error_log("Live:sendRestream object is empty"); return false; } $data_string = json_encode($obj); _error_log("Live:sendRestream ({$obj->restreamerURL}) {$data_string}"); //open connection $ch = curl_init(); //set the url, number of POST vars, POST data curl_setopt($ch, CURLOPT_URL, $obj->restreamerURL); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST"); curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string); curl_setopt($ch, CURLOPT_POSTREDIR, 3); curl_setopt($ch, CURLOPT_POST, 1); //curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); //curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST"); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, array( 'Content-Type: application/json', 'Content-Length: ' . strlen($data_string)) ); $output = curl_exec($ch); if (empty($output)) { _error_log('Live:sendRestream ERROR ' . curl_error($ch)); curl_close($ch); return false; } curl_close($ch); $json = _json_decode($output); if (empty($output)) { _error_log('Live:sendRestream JSON ERROR ' . $output); return false; } _error_log('Live:sendRestream complete ' . $output); return $json; } catch (Exception $exc) { _error_log("Live:sendRestream " . $exc->getTraceAsString()); return false; } return false; } public static function canStreamWithWebRTC(){ if (!User::canStream()) { return false; } $obj = AVideoPlugin::getObjectDataIfEnabled("Live"); if (!empty($obj->webRTC_isDisabled)) { return false; } return true; } public static function canScheduleLive(){ if (!User::canStream()) { return false; } $obj = AVideoPlugin::getObjectDataIfEnabled("Live"); if (!empty($obj->disable_live_schedule)) { return false; } return true; } public static function canStreamWithMeet() { if (!User::canStream()) { return false; } if (!User::canCreateMeet()) { return false; } $mobj = AVideoPlugin::getObjectDataIfEnabled("Meet"); if (empty($mobj)) { return false; } $obj = AVideoPlugin::getObjectDataIfEnabled("Live"); if (!empty($obj->disableMeetCamera)) { return false; } return true; } public function getUploadMenuButton() { global $global; $obj = $this->getDataObject(); if (!empty(!User::canStream())) { return ''; } $buttonTitle = $this->getButtonTitle(); include $global['systemRootPath'] . 'plugin/Live/getUploadMenuButton.php'; } public static function getAllVideos($status = "", $showOnlyLoggedUserVideos = false, $activeUsersOnly = true) { global $global, $config, $advancedCustom; if (AVideoPlugin::isEnabledByName("VideoTags")) { if (!empty($_GET['tags_id']) && empty($videosArrayId)) { TimeLogStart("video::getAllVideos::getAllVideosIdFromTagsId({$_GET['tags_id']})"); $videosArrayId = VideoTags::getAllVideosIdFromTagsId($_GET['tags_id']); TimeLogEnd("video::getAllVideos::getAllVideosIdFromTagsId({$_GET['tags_id']})", __LINE__); } } $status = str_replace("'", "", $status); $sql = "SELECT u.*, v.*, c.iconClass, c.name as category, c.clean_name as clean_category,c.description as category_description, v.created as videoCreation, v.modified as videoModified " . " FROM live_transmitions as v " . " LEFT JOIN categories c ON categories_id = c.id " . " LEFT JOIN users u ON v.users_id = u.id " . " WHERE 1=1 "; if ($showOnlyLoggedUserVideos === true && !Permissions::canModerateVideos()) { $uid = intval(User::getId()); $sql .= " AND v.users_id = '{$uid}'"; } elseif (!empty($showOnlyLoggedUserVideos)) { $uid = intval($showOnlyLoggedUserVideos); $sql .= " AND v.users_id = '{$uid}'"; } elseif (!empty($_GET['channelName'])) { $user = User::getChannelOwner($_GET['channelName']); $uid = intval($user['id']); $sql .= " AND v.users_id = '{$uid}' "; } if ($activeUsersOnly) { $sql .= " AND u.status = 'a' "; } if ($status == "publicOnly") { $sql .= " AND v.public = 1 "; } elseif (!empty($status)) { $sql .= " AND v.`public` = '{$status}'"; } if (!empty($_GET['catName'])) { $catName = $global['mysqli']->real_escape_string($_GET['catName']); $sql .= " AND (c.clean_name = '{$catName}' OR c.parentId IN (SELECT cs.id from categories cs where cs.clean_name = '{$catName}' ))"; } if (!empty($_GET['modified'])) { $_GET['modified'] = str_replace("'", "", $_GET['modified']); $sql .= " AND v.modified >= '{$_GET['modified']}'"; } $sql .= AVideoPlugin::getVideoWhereClause(); if (strpos(strtolower($sql), 'limit') === false) { if (!empty($_GET['limitOnceToOne'])) { $sql .= " LIMIT 1"; unset($_GET['limitOnceToOne']); } else { $_REQUEST['rowCount'] = getRowCount(); if (!empty($_REQUEST['rowCount'])) { $sql .= " LIMIT {$_REQUEST['rowCount']}"; } else { _error_log("getAllVideos without limit " . json_encode(debug_backtrace())); if (empty($global['limitForUnlimitedVideos'])) { $global['limitForUnlimitedVideos'] = 100; } if ($global['limitForUnlimitedVideos'] > 0) { $sql .= " LIMIT {$global['limitForUnlimitedVideos']}"; } } } } //echo $sql;exit; //_error_log("getAllVideos($status, $showOnlyLoggedUserVideos , $ignoreGroup , ". json_encode($videosArrayId).")" . $sql); $res = sqlDAL::readSql($sql); $fullData = sqlDAL::fetchAllAssoc($res); sqlDAL::close($res); $videos = array(); if ($res != false) { foreach ($fullData as $row) { $row = cleanUpRowFromDatabase($row); $row['live_servers_id'] = self::getLastServersIdFromUser($row['users_id']); if (empty($otherInfo)) { $otherInfo = array(); $otherInfo['category'] = xss_esc_back($row['category']); $otherInfo['groups'] = UserGroups::getVideoGroups($row['id']); //$otherInfo['title'] = UTF8encode($row['title']); $otherInfo['description'] = UTF8encode($row['description']); $otherInfo['descriptionHTML'] = Video::htmlDescription($otherInfo['description']); $otherInfo['filesize'] = 0; } foreach ($otherInfo as $key => $value) { $row[$key] = $value; } $row['rotation'] = 0; $row['filename'] = ''; $row['type'] = 'live'; $row['duration'] = ''; $row['isWatchLater'] = 0; $row['isFavorite'] = 0; $row['views_count'] = 0; $videos[] = $row; } //$videos = $res->fetch_all(MYSQLI_ASSOC); } else { $videos = false; die($sql . '\nError : (' . $global['mysqli']->errno . ') ' . $global['mysqli']->error); } return $videos; } static function finishLive($key) { $lh = LiveTransmitionHistory::finish($key); } static function updateVideosUserGroup($videos_id, $key) { $lt = LiveTransmition::keyExists($key); if (!empty($lt)) { $lt = new LiveTransmition($lt['id']); $groups = $lt->getGroups(); if (!empty($groups)) { UserGroups::updateVideoGroups($videos_id, $groups); } } } static function notifySocketStats($callBack = 'socketLiveONCallback', $array = array()) { if (empty($array['stats'])) { $array['stats'] = getStatsNotifications(); } _error_log("NGINX Live::on_publish_socket_notification sendSocketMessageToAll Start"); $socketObj = sendSocketMessageToAll($array, $callBack); _error_log("NGINX Live::on_publish_socket_notification SocketMessageToAll END"); return $socketObj; } static public function getImageType($content) { global $global; if (empty($content)) { return LiveImageType::$UNKNOWN; } $contentLen = strlen($content); if ($contentLen < 255) { // check if it is a file if (file_exists($content)) { $contentLen = strlen(file_get_contents($content)); } } if ($contentLen >= 2095335 && $contentLen <= 2095350) { return LiveImageType::$DEFAULTGIF; } if ($contentLen >= 70805 && $contentLen <= 70810) { return LiveImageType::$ONAIRENCODER; } $filesize = file_get_contents($global['systemRootPath'] . self::getOnAirImage(false)); if ($contentLen === $filesize) { return LiveImageType::$ONAIR; } $filesize = file_get_contents($global['systemRootPath'] . self::getOfflineImage(false)); if ($contentLen === $filesize) { return LiveImageType::$OFFLINE; } //_error_log('getImageType: is not defined yet ('.$contentLen.')'); return LiveImageType::$LIVE; } static function isLiveImage($content) { return self::getImageType($content) === LiveImageType::$LIVE; } static function isDefaultImage($content) { $type = self::getImageType($content); return $type === LiveImageType::$ONAIRENCODER || $type === LiveImageType::$ONAIR || $type === LiveImageType::$OFFLINE || $type === LiveImageType::$DEFAULTGIF; } static function iskeyOnline($key) { $stats = getStatsNotifications(); foreach ($stats["applications"] as $value) { if (empty($value['key'])) { continue; } if (preg_match('/' . $key . '/', $value['key'])) { return true; } } return false; } static function getValidNotOnlineLiveIndex($key, $live_index) { if (empty($live_index)) { return 1; } if (!Live::iskeyOnline("{$key}-{$live_index}")) { return $live_index; } else { if (is_numeric($live_index)) { return self::getValidNotOnlineLiveIndex($key, ++$live_index); } else { return self::getValidNotOnlineLiveIndex($key, $live_index . 'New'); } } } static function getLatestValidNotOnlineLiveIndex($key) { $live_index = LiveTransmitionHistory::getLatestIndexFromKey($key); $live_index = self::getValidNotOnlineLiveIndex($key, $live_index); return $live_index; } static function getLivesOnlineFromKey($key) { global $_getLivesOnlineFromKey; if (!isset($_getLivesOnlineFromKey)) { $_getLivesOnlineFromKey = array(); } if (!isset($_getLivesOnlineFromKey[$key])) { $stats = getStatsNotifications(); $_getLivesOnlineFromKey[$key] = array(); foreach ($stats["applications"] as $value) { if (empty($value['key'])) { continue; } if (preg_match('/' . $key . '/', $value['key'])) { $_getLivesOnlineFromKey[$key][] = $value; } } } return $_getLivesOnlineFromKey[$key]; } static function getFirstLiveOnlineFromKey($key) { $onliveApplications = self::getLivesOnlineFromKey($key); if (!empty($onliveApplications[0])) { return $onliveApplications[0]; } return false; } static function getUserHash($users_id) { return encryptString(_json_encode(array('users_id' => $users_id, 'time' => time()))); } static function decryptHash($hash) { $string = decryptString($hash); $json = _json_decode($string); return object_to_array($json); } static function getServerURL($key, $users_id){ global $global; $obj = new stdClass(); $obj->users_id = $users_id; $obj->key = $key; $encrypt = encryptString($obj); $url = Live::getServer(); $url = addQueryStringParameter($url, 'e', $encrypt); $url = addQueryStringParameter($url, 'webSiteRootURL', $global['webSiteRootURL']); $o = AVideoPlugin::getObjectDataIfEnabled("Live"); if(empty($o->server_type->value)){ $url = addQueryStringParameter($url, 'webSiteRootURL', $global['webSiteRootURL']); } return $url; } } class LiveImageType { static $UNKNOWN = 'unknown'; static $OFFLINE = 'offline'; static $ONAIR = 'onair'; static $ONAIRENCODER = 'onair_encoder'; static $DEFAULTGIF = 'defaultgif'; static $LIVE = 'live'; } class LiveStreamObject { private $key, $live_servers_id, $live_index, $playlists_id_live; function __construct($key, $live_servers_id = 0, $live_index = 0, $playlists_id_live = 0) { $this->key = $key; $this->live_servers_id = intval($live_servers_id); $this->live_index = $live_index; $this->playlists_id_live = intval($playlists_id_live); $parts = Live::getLiveParametersFromKey($this->key); $objLive = AVideoPlugin::getDataObject("Live"); if (empty($live_servers_id) && !empty($objLive->useLiveServers)) { $live_servers_id = Live::getLiveServersIdRequest(); } if (empty($this->live_index)) { // check if the index is on the key already if (!empty($parts['live_index'])) { $this->live_index = $parts['live_index']; } else if (!empty($_REQUEST['live_index'])) { $this->live_index = $_REQUEST['live_index']; } } $this->key = $parts['cleanKey']; $this->live_index = preg_replace('/[^0-9a-z]/i', '', $this->live_index); } function getKey() { return $this->key; } function getKeyWithIndex($forceIndexIfEnabled = false, $allowOnlineIndex = false) { if (!empty($forceIndexIfEnabled)) { if (is_string($forceIndexIfEnabled)) { $this->live_index = $forceIndexIfEnabled; } else { $objLive = AVideoPlugin::getDataObject("Live"); if (!empty($objLive->allowMultipleLivesPerUser)) { if (empty($allowOnlineIndex)) { $this->live_index = Live::getLatestValidNotOnlineLiveIndex($this->key); } else { $this->live_index = LiveTransmitionHistory::getLatestIndexFromKey($this->key); } } } } return Live::getLiveKeyFromRequest($this->key, $this->live_index, $this->playlists_id_live); } function getLive_servers_id() { return $this->live_servers_id; } function getLive_index() { return $this->live_index; } function getPlaylists_id_live() { return $this->playlists_id_live; } function getURL() { global $global; $lt = LiveTransmition::getFromKey($this->key); if (empty($lt)) { return false; } $user = new User($lt['users_id']); $channelName = $user->getChannelName(); if (empty($channelName)) { return false; } $url = "{$global['webSiteRootURL']}live/{$this->live_servers_id}/" . urlencode($channelName); if (!empty($this->live_index)) { $url .= '/' . urlencode($this->live_index); } if (!empty($this->playlists_id_live)) { $url = addQueryStringParameter($url, 'playlists_id_live', $this->playlists_id_live); } return $url; } function getURLEmbed() { $url = $this->getURL(); return addQueryStringParameter($url, 'embed', 1); } function getM3U8($doNotProtect = false, $allowOnlineIndex = false) { global $global; $o = AVideoPlugin::getObjectData("Live"); $uuid = $this->getKeyWithIndex(false, $allowOnlineIndex); if(empty($o->server_type->value)){ $row = LiveTransmitionHistory::getLatest($this->key, $this->live_servers_id); if(!empty($row['domain'])){ return "https://{$row['domain']}/live/{$uuid}.m3u8"; } } $playerServer = Live::getPlayerServer(); if (!empty($this->live_servers_id)) { $liveServer = new Live_servers($this->live_servers_id); if ($liveServer->getStats_url()) { $o->protectLive = $liveServer->getProtectLive(); $o->useAadaptiveMode = $liveServer->getUseAadaptiveMode(); } } $playerServer = addLastSlash($playerServer); if ($o->protectLive && empty($doNotProtect)) { return "{$global['webSiteRootURL']}plugin/Live/m3u8.php?live_servers_id={$this->live_servers_id}&uuid=" . encryptString($uuid); } else if ($o->useAadaptiveMode) { return $playerServer . "{$uuid}.m3u8"; } else { return $playerServer . "{$uuid}/index.m3u8"; } } function getOnlineM3U8($users_id, $doNotProtect = false) { $li = $this->live_index; if (empty($this->live_index)) { $online = Live::getFirstLiveOnlineFromKey($this->key); if (!empty($online)) { $parameters = Live::getLiveParametersFromKey($online['key']); //var_dump($parameters, $this->live_index, $li, $online);exit; } else { $key = Live::getLatestKeyFromUser($users_id); $parameters = Live::getLiveParametersFromKey($key); } $this->live_index = $parameters['live_index']; } $m3u8 = $this->getM3U8($doNotProtect, true); $this->live_index = $li; return $m3u8; } function getRTMPLink($forceIndex = false) { $key = $this->getKeyWithIndex(true); if (!empty($forceIndex)) { // make sure the key is unique $parts = explode('-', $key); $key = $parts[0] . "-{$forceIndex}"; } $url = addLastSlash($this->getRTMPLinkWithOutKey()) . $key; _error_log("getRTMPLink: {$url}"); return $url; } function getRTMPLinkWithOutKey() { $lt = LiveTransmition::getFromKey($this->key); return Live::getServerURL($this->key, $lt['users_id']); } } diff --git a/plugin/Live/Objects/LiveTransmitionHistory.php b/plugin/Live/Objects/LiveTransmitionHistory.php index 1e9be1f5d..be95d2296 100644 --- a/plugin/Live/Objects/LiveTransmitionHistory.php +++ b/plugin/Live/Objects/LiveTransmitionHistory.php @@ -1,480 +1,495 @@ id; } function getTitle() { return $this->title; } function getDescription() { return $this->description; } function getKey() { return $this->key; } function getCreated() { return $this->created; } function getModified() { return $this->modified; } function getUsers_id() { return $this->users_id; } function setId($id) { $this->id = $id; } function getFinished() { return $this->finished; } function getDomain() { return $this->domain; } function getJson() { return $this->json; } function setDomain($domain) { $this->domain = $domain; } function setJson($json) { $this->json = $json; } function setTitle($title) { global $global; $title = $global['mysqli']->real_escape_string($title); $this->title = $title; } function setDescription($description) { global $global; $description = $global['mysqli']->real_escape_string($description); $this->description = $description; } function setKey($key) { $this->key = $key; } function setCreated($created) { $this->created = $created; } function setModified($modified) { $this->modified = $modified; } function setUsers_id($users_id) { $this->users_id = $users_id; } function getLive_servers_id() { return intval($this->live_servers_id); } function getLive_index() { if (empty($this->key)) { return ''; } $parameters = Live::getLiveParametersFromKey($this->key); return $parameters['live_index']; } function getLive_cleanKey() { if (empty($this->key)) { return ''; } $parameters = Live::getLiveParametersFromKey($this->key); return $parameters['cleanKey']; } static function getApplicationObject($liveTransmitionHistory_id) { global $global; $lth = new LiveTransmitionHistory($liveTransmitionHistory_id); $users_id = $lth->getUsers_id(); $key = $lth->getKey(); $title = $lth->getTitle(); $live_servers_id = $lth->getLive_servers_id(); $playlists_id_live = 0; $type = 'LiveObject'; if (preg_match("/.*_([0-9]+)/", $key, $matches)) { if (!empty($matches[1])) { $_REQUEST['playlists_id_live'] = intval($matches[1]); $playlists_id_live = $_REQUEST['playlists_id_live']; $imgJPG = PlayLists::getImage($_REQUEST['playlists_id_live']); $title = PlayLists::getNameOrSerieTitle($_REQUEST['playlists_id_live']); } } $p = AVideoPlugin::loadPlugin("Live"); $imgJPG = $p->getLivePosterImage($users_id, $live_servers_id, $playlists_id_live, $lth->getLive_index()); $imgGIF = $p->getLivePosterImage($users_id, $live_servers_id, $playlists_id_live, $lth->getLive_index(), 'webp'); $link = Live::getLinkToLiveFromUsers_idAndLiveServer($users_id, $live_servers_id, $lth->getLive_index()); $liveUsersEnabled = AVideoPlugin::isEnabledByName("LiveUsers"); $LiveUsersLabelLive = ($liveUsersEnabled ? getLiveUsersLabelLive($key, $live_servers_id) : ''); $uid = "{$type}_{$liveTransmitionHistory_id}"; return Live::getLiveApplicationModelArray($users_id, $title, $link, $imgJPG, $imgGIF, $type, $LiveUsersLabelLive, $uid); } static function getStatsAndAddApplication($liveTransmitionHistory_id) { $stats = getStatsNotifications(); $lth = new LiveTransmitionHistory($liveTransmitionHistory_id); $key = $lth->getKey(); if (!empty($stats['applications'])) { foreach ($stats['applications'] as $value) { if (empty($value['key'])) { continue; } $value = object_to_array($value); $value['key'] = self::getCleankeyName($value['key']); if (!empty($value['key']) && $value['key'] == $key) { // application is already in the list return $stats; } } } if (!empty($stats['hidden_applications'])) { foreach ($stats['hidden_applications'] as $value) { if (empty($value['key'])) { continue; } $value = object_to_array($value); $value['key'] = self::getCleankeyName($value['key']); if ($value['key'] == $key) { // application is already in the list return $stats; } } } $application = self::getApplicationObject($liveTransmitionHistory_id); if ($application->isPrivate) { $stats['hidden_applications'][] = $application; } else { $stats['applications'][] = $application; } $stats['countLiveStream']++; $cacheName = "getStats" . DIRECTORY_SEPARATOR . "getStatsNotifications"; $cache = ObjectYPT::setCache($cacheName, $stats); // update the cache //_error_log("NGINX getStatsAndAddApplication ". json_encode($stats)); //_error_log("NGINX getStatsAndAddApplication ". json_encode($cache)); return $stats; } static function getCleankeyName($key) { $parts = explode("_", $key); if (!empty($parts[1])) { $adaptive = array('hi', 'low', 'mid'); if (in_array($parts[1], $adaptive)) { return $parts[0]; } } return $key; } static function getStatsAndRemoveApplication($liveTransmitionHistory_id) { $stats = getStatsNotifications(); $lth = new LiveTransmitionHistory($liveTransmitionHistory_id); $key = $lth->getKey(); foreach ($stats['applications'] as $k => $value) { $value = object_to_array($value); if (!empty($value['key']) && $value['key'] == $key) { // application is already in the list unset($stats['applications'][$k]); $stats['countLiveStream']--; } } if (empty($stats['hidden_applications'])) { $stats['hidden_applications'] = array(); } else { foreach ($stats['hidden_applications'] as $k => $value) { $value = object_to_array($value); if ($value['key'] == $key) { // application is already in the list unset($stats['hidden_applications'][$k]); } } } $cacheName = "getStats" . DIRECTORY_SEPARATOR . "getStatsNotifications"; $cache = ObjectYPT::setCache($cacheName, $stats); // update the cache return $stats; } function setLive_servers_id($live_servers_id) { $this->live_servers_id = intval($live_servers_id); } static function getAllFromUser($users_id) { global $global; $sql = "SELECT * FROM " . static::getTableName() . " WHERE users_id = ? "; $sql .= self::getSqlFromPost(); $res = sqlDAL::readSql($sql, "i", array($users_id)); $fullData = sqlDAL::fetchAllAssoc($res); sqlDAL::close($res); $rows = array(); if ($res != false) { foreach ($fullData as $row) { $log = LiveTransmitionHistoryLog::getAllFromHistory($row['id']); $row['totalUsers'] = count($log); $rows[] = $row; } } else { die($sql . '\nError : (' . $global['mysqli']->errno . ') ' . $global['mysqli']->error); } return $rows; } static function isLive($key) { global $global; $row = self::getActiveLiveFromUser(0, '', $key); if (empty($row)) { return false; } return self::getApplicationObject($row['id']); } static function getLatest($key, $live_servers_id = null) { global $global; $key = $global['mysqli']->real_escape_string($key); if (empty($key)) { return false; } $sql = "SELECT * FROM " . static::getTableName() . " WHERE `key` LIKE '{$key}%' "; if (isset($live_servers_id)) { $sql .= " AND (live_servers_id = " . intval($live_servers_id); if (empty($live_servers_id)) { $sql .= " OR live_servers_id IS NULL "; } $sql .= " )"; } $sql .= " ORDER BY created DESC LIMIT 1"; //var_dump($sql, $key);exit; $res = sqlDAL::readSql($sql); $data = sqlDAL::fetchAssoc($res); sqlDAL::close($res); if ($res) { $row = $data; } else { $row = false; } return $row; } static function finish($key) { $row = self::getLatest($key); if (empty($row) || empty($row['id']) || !empty($row['finished'])) { return false; } return self::finishFromTransmitionHistoryId($row['id']); } static function finishFromTransmitionHistoryId($live_transmitions_history_id) { $live_transmitions_history_id = intval($live_transmitions_history_id); if (empty($live_transmitions_history_id)) { return false; } $sql = "UPDATE " . static::getTableName() . " SET finished = now() WHERE id = {$live_transmitions_history_id} "; $insert_row = sqlDAL::writeSql($sql); return $insert_row; } + + + static function finishALL($olderThan = '') { + $sql = "UPDATE " . static::getTableName() . " SET finished = now() WHERE finished IS NULL "; + + if(!empty($olderThan)){ + $sql .= " modified < ".date('Y-m-d H:i:s', strtotime($olderThan)); + } + + $insert_row = sqlDAL::writeSql($sql); + + return $insert_row; + } static function getLatestFromUser($users_id) { $rows = self::getLastsLiveHistoriesFromUser($users_id, 1); return @$rows[0]; } static function getLatestFromKey($key) { global $global; $parts = Live::getLiveParametersFromKey($key); $key = $parts['cleanKey']; $sql = "SELECT * FROM " . static::getTableName() . " WHERE `key` LIKE '{$key}%' "; $sql .= " ORDER BY created DESC LIMIT 1"; $res = sqlDAL::readSql($sql); $data = sqlDAL::fetchAssoc($res); sqlDAL::close($res); if ($res) { $row = $data; } else { $row = false; } return $row; } static function getLatestIndexFromKey($key) { $row = self::getLatestFromKey($key); return Live::getLiveIndexFromKey(@$row['key']); } static function getLastsLiveHistoriesFromUser($users_id, $count = 10) { global $global; $sql = "SELECT * FROM " . static::getTableName() . " WHERE `users_id` = ? ORDER BY created DESC LIMIT ?"; $res = sqlDAL::readSql($sql, "ii", array($users_id, $count)); $fullData = sqlDAL::fetchAllAssoc($res); sqlDAL::close($res); $rows = array(); if ($res != false) { foreach ($fullData as $row) { $log = LiveTransmitionHistoryLog::getAllFromHistory($row['id']); $row['totalUsers'] = count($log); $rows[] = $row; } } else { die($sql . '\nError : (' . $global['mysqli']->errno . ') ' . $global['mysqli']->error); } return $rows; } static function getActiveLiveFromUser($users_id, $live_servers_id = '', $key = '', $count = 1) { global $global; $sql = "SELECT * FROM " . static::getTableName() . " WHERE finished IS NULL "; $formats = ""; $values = array(); if (!empty($users_id)) { $sql .= ' AND `users_id` = ? '; $formats .= "i"; $values[] = $users_id; } if (!empty($live_servers_id)) { $sql .= ' AND `live_servers_id` = ? '; $formats .= "i"; $values[] = $live_servers_id; } if (!empty($key)) { $sql .= ' AND `key` = ? '; $formats .= "s"; $values[] = $key; } $sql .= " ORDER BY created DESC LIMIT {$count}"; $res = sqlDAL::readSql($sql, $formats, $values); if ($count == 1) { $data = sqlDAL::fetchAssoc($res); sqlDAL::close($res); if ($res) { $row = $data; } else { $row = false; } if (empty($row)) { _error_log('LiveTransmitionHistory::getActiveLiveFromUser: ' . $sql . " [$users_id, $live_servers_id, $key]"); } return $row; } else { $fullData = sqlDAL::fetchAllAssoc($res); sqlDAL::close($res); $rows = array(); if ($res != false) { + $total = count($fullData); foreach ($fullData as $row) { - if (strtotime($row['modified']) < strtotime('-1 hour')) { + if ($total<10 && strtotime($row['modified']) < strtotime('-1 hour')) { // check if the m3u8 file still exists $m3u8 = Live::getM3U8File($row['key']); $isURL200 = isValidM3U8Link($m3u8); if(empty($isURL200)){ self::finishFromTransmitionHistoryId($row['id']); + //var_dump($isURL200, $m3u8, $row);exit; continue; }else{ // update it to make sure the modified date is updated $lth = new LiveTransmitionHistory($row['id']); $lth->save(); } } $log = LiveTransmitionHistoryLog::getAllFromHistory($row['id']); $row['totalUsers'] = count($log); $rows[] = $row; } } else { die($sql . '\nError : (' . $global['mysqli']->errno . ') ' . $global['mysqli']->error); } return $rows; } } public function save() { if (empty($this->live_servers_id)) { $this->live_servers_id = 'NULL'; } if (empty($this->finished)) { $this->finished = 'NULL'; } return parent::save(); } static function deleteAllFromLiveServer($live_servers_id) { global $global; $live_servers_id = intval($live_servers_id); if (!empty($live_servers_id)) { global $global; $sql = "SELECT id FROM " . static::getTableName() . " WHERE live_servers_id = ? "; $sql .= self::getSqlFromPost(); $res = sqlDAL::readSql($sql, "i", array($live_servers_id)); $fullData = sqlDAL::fetchAllAssoc($res); sqlDAL::close($res); $rows = array(); if ($res != false) { foreach ($fullData as $row) { $lt = new LiveTransmitionHistory($row['id']); $lt->delete(); } } } } public function delete() { if (!empty($this->id)) { LiveTransmitionHistoryLog::deleteAllFromHistory($this->id); } return parent::delete(); } } diff --git a/plugin/Live/view/finishAll.json.php b/plugin/Live/view/finishAll.json.php new file mode 100644 index 000000000..6815b5c55 --- /dev/null +++ b/plugin/Live/view/finishAll.json.php @@ -0,0 +1,27 @@ +error = true; +$obj->msg = ""; + +$objP = AVideoPlugin::getDataObjectIfEnabled('Live'); +if(empty($objP)){ + $obj->msg = __('Live plugin is disabled'); + die(json_encode($obj)); +} + +if(!User::isAdmin()){ + $obj->msg = __('Not Admin'); + die(json_encode($obj)); +} +$obj->error = !LiveTransmitionHistory::finishALL(); + +if(empty($obj->error)){ + $obj->msg = __('All lives were marked as finished'); +} + +die(json_encode($obj)); +?>