diff --git a/objects/Encoder.php b/objects/Encoder.php index 9116a2d5..e5d3d7b7 100644 --- a/objects/Encoder.php +++ b/objects/Encoder.php @@ -682,7 +682,7 @@ public static function downloadFile($queue_id) return $obj; } - if (file_exists($obj->pathFileName)) { + if (file_exists($obj->pathFileName) && filesize($obj->pathFileName) > 20) { if ($q->getStatus() == 'queue') { self::setDownloaded($queue_id, $obj->pathFileName); } @@ -708,25 +708,34 @@ public static function downloadFile($queue_id) if (!empty($q->getVideoDownloadedLink())) { $videoURL = $q->getVideoDownloadedLink(); - $downloadWithPytubeFilename = ''; - if (self::isPythonAndPytubeInstalled() && isYouTubeUrl($videoURL)) { - $downloadWithPytubeFilename = 'video_download_' . $queue_id; - $response = self::downloadWithPytube($videoURL, $downloadWithPytubeFilename); - } - if(empty($downloadWithPytubeFilename) || $response->error){ - //begin youtube-dl downloading and symlink it to the video temp file - $response = static::getYoutubeDl($videoURL, $queue_id, $obj->pathFileName); - if (!empty($response)) { - _error_log("downloadFile:getYoutubeDl SUCCESS queue_id = {$queue_id}"); - $obj->pathFileName = $response; - $obj->error = false; - } else { - _error_log("downloadFile:getYoutubeDl ERROR queue_id = {$queue_id}"); - $obj->error = false; - } + + if(isFTPURL($videoURL)){ + require_once __DIR__ . '/FTPDownloader.php'; + FTPDownloader::copy($videoURL, $obj->pathFileName); + $obj->error = !file_exists($obj->pathFileName); }else{ - $obj->pathFileName = "{$global['systemRootPath']}videos/pytube/{$downloadWithPytubeFilename}/video.mp4"; + + $downloadWithPytubeFilename = ''; + if (self::isPythonAndPytubeInstalled() && isYouTubeUrl($videoURL)) { + $downloadWithPytubeFilename = 'video_download_' . $queue_id; + $response = self::downloadWithPytube($videoURL, $downloadWithPytubeFilename); + } + if(empty($downloadWithPytubeFilename) || $response->error){ + //begin youtube-dl downloading and symlink it to the video temp file + $response = static::getYoutubeDl($videoURL, $queue_id, $obj->pathFileName); + if (!empty($response)) { + _error_log("downloadFile:getYoutubeDl SUCCESS queue_id = {$queue_id}"); + $obj->pathFileName = $response; + $obj->error = false; + } else { + _error_log("downloadFile:getYoutubeDl ERROR queue_id = {$queue_id}"); + $obj->error = false; + } + }else{ + $obj->pathFileName = "{$global['systemRootPath']}videos/pytube/{$downloadWithPytubeFilename}/video.mp4"; + } } + } else { _error_log("downloadFile: not using getYoutubeDl"); //symlink the downloaded file to the video temp file ($obj-pathFileName) @@ -980,9 +989,9 @@ public static function getQueue($status = array(), $streamers_id = 0) $sql .= " AND streamers_id = {$streamers_id} "; } - $sql .= " ORDER BY - CASE WHEN priority IS NULL THEN 1 ELSE 0 END ASC, - priority ASC, + $sql .= " ORDER BY + CASE WHEN priority IS NULL THEN 1 ELSE 0 END ASC, + priority ASC, e.id ASC "; //var_dump($sql); /** @@ -2794,7 +2803,7 @@ public static function getTitleFromLink($link, $streamers_id, $addOauthFromProvi if (!isWindows()) { $prepend = 'LC_ALL=en_US.UTF-8 '; } - + $link = str_replace("'", '', $link); $link = escapeshellarg($link); $response = array('error' => true, 'output' => ''); @@ -2896,7 +2905,7 @@ public static function getDescriptionFromLink($link, $streamers_id, $addOauthFro if (empty($link)) { return ''; } - + if (self::isPythonAndPytubeInstalled() && isYouTubeUrl($link)) { $resp = self::getDescriptionFromLinkWithPytube($link); if(!empty($resp)){ diff --git a/objects/FTPDownloader.php b/objects/FTPDownloader.php new file mode 100644 index 00000000..8e828857 --- /dev/null +++ b/objects/FTPDownloader.php @@ -0,0 +1,84 @@ +ftpUrl = addLastSlash($ftpUrl); + $this->parseFtpUrl($ftpUrl); + } + + private function parseFtpUrl($ftpUrl) + { + $parsedUrl = parse_url($ftpUrl); + if (!$parsedUrl || !isset($parsedUrl['scheme']) || $parsedUrl['scheme'] !== 'ftp') { + throw new Exception("Invalid FTP URL"); + } + + $this->ftpHost = $parsedUrl['host'] ?? ''; + $this->ftpUser = $parsedUrl['user'] ?? 'anonymous'; + $this->ftpPass = $parsedUrl['pass'] ?? ''; + $this->ftpPort = $parsedUrl['port'] ?? 21; + $this->remotePath = $parsedUrl['path'] ?? '/'; + } + + public function connect() + { + $this->ftpConn = ftp_connect($this->ftpHost, $this->ftpPort); + if (!$this->ftpConn) { + throw new Exception("Could not connect to FTP server"); + } + + if (!ftp_login($this->ftpConn, $this->ftpUser, $this->ftpPass)) { + throw new Exception("Could not log in to FTP server"); + } + + ftp_pasv($this->ftpConn, true); // Enable passive mode + } + + public function queueFiles() + { + $files = ftp_nlist($this->ftpConn, $this->remotePath); + if ($files === false) { + throw new Exception("Could not list files in directory"); + } + + foreach ($files as $file) { + if (preg_match('/\.(mp4|mp3)$/i', $file)) { + $basename = basename($file); + $link = "{$this->ftpUrl}{$basename}"; + addVideo($link, Login::getStreamerId(), $basename); + } + } + } + + static function copy($ftpUrl, $savePath) + { + _error_log("FTP copy($ftpUrl, $savePath)"); + + $savePath = str_replace('..', '', $savePath); + + $command = "wget -O \"$savePath\" \"$ftpUrl\" "; + + exec($command); + + return file_exists($savePath) && filesize($savePath) > 20; + } + + + public function close() + { + if ($this->ftpConn) { + ftp_close($this->ftpConn); + } + } +} diff --git a/objects/functions.php b/objects/functions.php index 552bd0e7..d2268666 100644 --- a/objects/functions.php +++ b/objects/functions.php @@ -1432,6 +1432,10 @@ function _error_log($message) error_log($str); } +function isFTPURL($url){ + return preg_match('/^ftps?:/i', $url); +} + function addVideo($link, $streamers_id, $title = "") { $obj = new stdClass(); // remove list parameter from @@ -1599,7 +1603,7 @@ function addQueryStringParameter($url, $varname, $value) parse_str($parsedUrl['query'], $query); } $query[$varname] = $value; - + // Ensure 'current' is the last parameter $currentValue = null; if (isset($query['current'])) { diff --git a/objects/security.php b/objects/security.php index 5abe6a06..0b27c20f 100644 --- a/objects/security.php +++ b/objects/security.php @@ -28,7 +28,7 @@ foreach ($filterURL as $key => $value) { if (!empty($scanThis[$value])) { - if (!filter_var($scanThis[$value], FILTER_VALIDATE_URL) || !preg_match("/^http.*/i", $scanThis[$value])) { + if (!filter_var($scanThis[$value], FILTER_VALIDATE_URL) || !preg_match("/^(http|ftp).*/i", $scanThis[$value])) { //_error_log($value.' attack ' . json_encode($_SERVER), AVideoLog::$SECURITY); unset($scanThis[$value]); } else { diff --git a/view/youtubeDl.json.php b/view/youtubeDl.json.php index b36bae9a..c9b4484a 100644 --- a/view/youtubeDl.json.php +++ b/view/youtubeDl.json.php @@ -10,51 +10,68 @@ session_write_close(); -if (!empty($_REQUEST['webSiteRootURL']) && !empty($_REQUEST['user']) && !empty($_REQUEST['pass']) && empty($_REQUEST['justLogin'])) { - error_log("youtubeDl.json: Login::run"); - Login::run($_REQUEST['user'], $_REQUEST['pass'], $_REQUEST['webSiteRootURL'], true); -} - -if (!Login::canUpload()) { - $obj->msg = "This user can not upload files"; +if (empty($_REQUEST['videoURL'])) { + $obj->msg = "videoURL is empty"; } else { - if (!($streamers_id = Login::getStreamerId())) { - $obj->msg = "There is no streamer site"; + if (!empty($_REQUEST['webSiteRootURL']) && !empty($_REQUEST['user']) && !empty($_REQUEST['pass']) && empty($_REQUEST['justLogin'])) { + error_log("youtubeDl.json: Login::run"); + Login::run($_REQUEST['user'], $_REQUEST['pass'], $_REQUEST['webSiteRootURL'], true); + } + + if (!Login::canUpload()) { + $obj->msg = "This user can not upload files"; } else { - // if it is a channel - $rexexp = "/^(http(s)?:\/\/)?((w){3}.)?youtu(be|.be)?(\.com)?\/(channel|user).+/"; - if (preg_match($rexexp, $_REQUEST['videoURL'])) { - if (!Login::canBulkEncode()) { - $obj->msg = "Channel Import is disabled"; - die(json_encode($obj)); - } - $start = 0; - $end = 100; - if (!empty($_REQUEST['startIndex'])) { - $start = $current = intval($_REQUEST['startIndex']); - } - if (!empty($_REQUEST['endIndex'])) { - $end = intval($_REQUEST['endIndex']); - } - error_log("Processing Channel {$start} to {$end}"); - $list = Encoder::getReverseVideosJsonListFromLink($_REQUEST['videoURL'], Login::getStreamerId()); - $i = $start; - for (; $i <= $end; $i++) { - if (is_object($list[$i]) && empty($list[$i]->id)) { - error_log(($i) . " Not Object " . print_r($list[$i], true)); - continue; + if (!($streamers_id = Login::getStreamerId())) { + $obj->msg = "There is no streamer site"; + } else { + // if it is a channel + $rexexp = "/^(http(s)?:\/\/)?((w){3}.)?youtu(be|.be)?(\.com)?\/(channel|user).+/"; + if (preg_match($rexexp, $_REQUEST['videoURL'])) { + if (!Login::canBulkEncode()) { + $obj->msg = "Channel Import is disabled"; + die(json_encode($obj)); + } + $start = 0; + $end = 100; + if (!empty($_REQUEST['startIndex'])) { + $start = $current = intval($_REQUEST['startIndex']); + } + if (!empty($_REQUEST['endIndex'])) { + $end = intval($_REQUEST['endIndex']); + } + error_log("Processing Channel {$start} to {$end}"); + $list = Encoder::getReverseVideosJsonListFromLink($_REQUEST['videoURL'], Login::getStreamerId()); + $i = $start; + for (; $i <= $end; $i++) { + if (is_object($list[$i]) && empty($list[$i]->id)) { + error_log(($i) . " Not Object " . print_r($list[$i], true)); + continue; + } + error_log(($i) . " Process Video {$list[$i]->id}"); + $url = "https://www.youtube.com/watch?v={$list[$i]->url}"; + $obj = addVideo($url, $streamers_id, $list[$i]->title); + } + error_log("Process Done Total {$i}"); + } else { + if (isFTPURL($_REQUEST['videoURL'])) { + require_once __DIR__ . '/../objects/FTPDownloader.php'; + try { + $downloader = new FTPDownloader($_REQUEST['videoURL']); + $downloader->connect(); + $downloader->queueFiles(); + $downloader->close(); + } catch (Exception $e) { + echo "Error: " . $e->getMessage() . "\n"; + } + } else { + $obj = addVideo($_REQUEST['videoURL'], $streamers_id, @$_REQUEST['videoTitle']); } - error_log(($i) . " Process Video {$list[$i]->id}"); - $url = "https://www.youtube.com/watch?v={$list[$i]->url}"; - $obj = addVideo($url, $streamers_id, $list[$i]->title); } - error_log("Process Done Total {$i}"); - } else { - $obj = addVideo($_REQUEST['videoURL'], $streamers_id, @$_REQUEST['videoTitle']); } } } -if(empty($doNotDie)){ + +if (empty($doNotDie)) { echo (json_encode($obj)); exit; }