diff --git a/objects/sites.php b/objects/sites.php index 5889049ae..49ef0309c 100644 --- a/objects/sites.php +++ b/objects/sites.php @@ -1,76 +1,97 @@ name; } function getUrl() { return $this->url; } function getStatus() { return $this->status; } function setName($name) { $this->name = $name; } function setUrl($url) { $this->url = $url; } function setStatus($status) { $this->status = $status; } function getSecret() { return $this->secret; } function setSecret($secret) { $this->secret = $secret; } function save() { if(empty($this->getSecret())){ $this->setSecret(md5(uniqid())); } $siteURL = $this->getUrl(); if (substr($siteURL, -1) !== '/') { $siteURL .= "/"; } $this->setUrl($siteURL); return parent::save(); } static function getFromFileName($fileName){ $obj = new stdClass(); $obj->url = ""; $obj->secret = ""; $obj->filename = $fileName; $video = Video::getVideoFromFileNameLight($fileName); if(!empty($video['sites_id'])){ $site = new Sites($video['sites_id']); $obj->url = $site->getUrl(); $obj->secret = $site->getSecret(); } return $obj; } + + static function getFromStatus($status) { + global $global; + if (!static::isTableInstalled()) { + return false; + } + $sql = "SELECT * FROM " . static::getTableName() . " WHERE status = ? "; + + $res = sqlDAL::readSql($sql, 's', array($status)); + $fullData = sqlDAL::fetchAllAssoc($res); + sqlDAL::close($res); + $rows = array(); + if ($res != false) { + foreach ($fullData as $row) { + $rows[] = $row; + } + } else { + die($sql . '\nError : (' . $global['mysqli']->errno . ') ' . $global['mysqli']->error); + } + return $rows; + } } diff --git a/plugin/AD_Server/AD_Server.php b/plugin/AD_Server/AD_Server.php index f0ea97146..27014b2da 100644 --- a/plugin/AD_Server/AD_Server.php +++ b/plugin/AD_Server/AD_Server.php @@ -1,469 +1,469 @@ Help"; } public function getName() { return "AD_Server"; } public function getUUID() { return "3f2a707f-3c06-4b78-90f9-a22f2fda92ef"; } public function getPluginVersion() { return "1.0"; } public function getEmptyDataObject() { $obj = new stdClass(); $obj->start = true; self::addDataObjectHelper('start', 'Show Pre-Roll ads'); $obj->mid25Percent = true; self::addDataObjectHelper('mid25Percent', 'Show Mid-Roll ads at 25%'); $obj->mid50Percent = true; self::addDataObjectHelper('mid50Percent', 'Show Mid-Roll ads at 50%'); $obj->mid75Percent = true; self::addDataObjectHelper('mid75Percent', 'Show Mid-Roll ads at 75%'); $obj->end = true; self::addDataObjectHelper('end', 'Show Post-Roll ads'); $o = new stdClass(); $o->type = array(); for ($i = 0; $i <= 100; $i++) { $o->type[$i . '%'] = "The skip button will appear when you watch {$i}% of the video"; } $o->value = '10%'; $obj->skipoffset = $o; self::addDataObjectHelper('skipoffset', 'Skip Offset', 'This is the percentage where the skip button should appear'); $obj->showMarkers = true; self::addDataObjectHelper('showMarkers', 'Show Markers', 'Check it if you want to show the yellow markers on the video, where the advertising should appear'); $o = new stdClass(); $o->type = array(1 => 'Every video'); for ($i = 2; $i < 10; $i++) { $o->type[$i] = "Show ads on each {$i} videos"; } $o->value = 1; $obj->showAdsOnEachVideoView = $o; self::addDataObjectHelper('showAdsOnEachVideoView', 'Show Ads on', 'This defines how often advertisements will appear, for example: if it is set to 2, you will see ads each 2 videos, but if it is set to 1 you will see ads on every video'); $o = new stdClass(); $o->type = array(0 => 'All positions'); for ($i = 1; $i < 5; $i++) { $o->type[$i] = "Show ads on {$i} random positions"; } $o->value = 2; $obj->showAdsOnRandomPositions = $o; self::addDataObjectHelper('showAdsOnRandomPositions', 'Show Ads On Positions', 'This will pick random positions to display the ads, but it will pic only the positions you have checked above. For example, if you want to have 2 random positions, but do not want to have videos on the start position, you must uncheck the start video position checkbox;'); $o = new stdClass(); $o->type = array(0 => 'Do not auto add new videos on campaign'); $rows = VastCampaigns::getAllActive(); foreach ($rows as $row) { $o->type[$row['id']] = '- ' . $row['name']; } $o->value = 0; $obj->autoAddNewVideosInCampaignId = $o; self::addDataObjectHelper('autoAddNewVideosInCampaignId', 'Auto Add New Videos In Campaign'); return $obj; } public function afterNewVideo($videos_id) { _error_log("AD_Server:afterNewVideo start"); $obj = $this->getDataObject(); if (!empty($obj->autoAddNewVideosInCampaignId)) { $vc = new VastCampaigns($obj->autoAddNewVideosInCampaignId); if (!empty($vc->getName())) { $video = new Video("", "", $videos_id); - if (!empty($video->getTitle())) { + if (!empty($video->getTitle()) && !empty($obj->autoAddNewVideosInCampaignId)) { _error_log("AD_Server:afterNewVideo saving"); $o = new VastCampaignsVideos(0); $o->setVast_campaigns_id($obj->autoAddNewVideosInCampaignId); $o->setVideos_id($videos_id); $o->setLink(""); $o->setAd_title($video->getTitle()); $o->setStatus('a'); $id = $o->save(); _error_log("AD_Server:afterNewVideo saved {$id}"); } else { _error_log("AD_Server:afterNewVideo videos_id NOT found {$videos_id}"); } } else { _error_log("AD_Server:afterNewVideo autoAddNewVideosInCampaignId NOT found {$obj->autoAddNewVideosInCampaignId}"); } } else { _error_log("AD_Server:afterNewVideo is disabled"); } return true; } public function canLoadAds() { //if (empty($_GET['videoName']) && empty($_GET['u'])) { $videos_id = getVideos_id(); if (!empty($videos_id)) { $showAds = AVideoPlugin::showAds($videos_id); if (!$showAds) { return false; } } if (empty($_GET['videoName'])) { return false; } // count it each 2 seconds if (empty($_SESSION['lastAdShowed']) || $_SESSION['lastAdShowed'] + 2 <= time()) { _session_start(); $_SESSION['lastAdShowed'] = time(); if (!isset($_SESSION['showAdsCount'])) { //_error_log("Show Ads Count started"); $_SESSION['showAdsCount'] = 1; } else { $_SESSION['showAdsCount']++; } } //_error_log("Show Ads Count {$_SESSION['showAdsCount']}"); $obj = $this->getDataObject(); if (!empty($obj->showAdsOnEachVideoView->value) && $_SESSION['showAdsCount'] % $obj->showAdsOnEachVideoView->value === 0) { return true; } return false; } public function getHeadCode() { $obj = $this->getDataObject(); if (!$this->canLoadAds()) { return ""; } global $global; $_GET['vmap_id'] = session_id(); $css = '' . ''; if (!empty($obj->showMarkers)) { $css .= ''; } $css .= ''; return $css; } private static function getVideoLength() { $video_length = 3600; // 1 hour $videos_id = getVideos_id(); $video = new Video('', '', $videos_id); $duration = $video->getDuration(); if (!empty($duration)) { $video_length = parseDurationToSeconds($duration); } return $video_length; } static function getVMAPSFromRequest() { if (!empty($_REQUEST['vmaps'])) { $vmaps = _json_decode(base64_decode($_REQUEST['vmaps'])); } else { $video_length = self::getVideoLength(); $ad_server = AVideoPlugin::loadPlugin('AD_Server'); $vmaps = $ad_server->getVMAPs($video_length); } return object_to_array($vmaps); } static function addVMAPS($url, $vmaps) { if (empty($vmaps)) { $vmaps = self::getVMAPSFromRequest(); } $base64 = base64_encode(_json_encode($vmaps)); $vmapURL = addQueryStringParameter($url, 'vmaps', $base64); return $vmapURL; } public function afterVideoJS() { $obj = $this->getDataObject(); if (!$this->canLoadAds() || empty($_GET['vmap_id'])) { return ""; } global $global; $vmap_id = @$_GET['vmap_id']; $vmaps = self::getVMAPSFromRequest(); $video_length = self::getVideoLength(); $vmapURL = "{$global['webSiteRootURL']}plugin/AD_Server/VMAP.php"; $vmapURL = addQueryStringParameter($vmapURL, 'video_length', $video_length); $vmapURL = addQueryStringParameter($vmapURL, 'vmap_id', $vmap_id); $vmapURL = addQueryStringParameter($vmapURL, 'random', uniqid()); $vmapURL = self::addVMAPS($vmapURL, $vmaps); //var_dump($vmapURL, $vmaps);exit; PlayerSkins::setIMAADTag($vmapURL); $onPlayerReady = ""; if (!empty($obj->showMarkers)) { $onPlayerReady .= " player.markers({ markerStyle: { 'width': '5px', 'background-color': 'yellow' }, markerTip: { display: true, text: function (marker) { return marker.text; } }, markers: ["; foreach ($vmaps as $value) { $vastCampaingVideos = new VastCampaignsVideos($value['VAST']['campaing']); $video = new Video("", "", $vastCampaingVideos->getVideos_id()); if(!empty($video_length) && $value['timeOffsetSeconds'] >= $video_length){ $value['timeOffsetSeconds'] = $video_length-5; } $onPlayerReady .= "{time: {$value['timeOffsetSeconds']}, text: \"" . addcslashes($video->getTitle(), '"') . "\"},"; } $onPlayerReady .= "]});"; } PlayerSkins::getStartPlayerJS($onPlayerReady); $js = ''; $js .= ''; $js .= ''; $js .= ''; if (!empty($obj->showMarkers)) { $js .= ''; } return $js; } private function getRandomPositions() { if (empty($_GET['vmap_id'])) { return ""; } $obj = $this->getDataObject(); $oldId = session_id(); if (session_status() !== PHP_SESSION_NONE) { session_write_close(); } session_id($_GET['vmap_id']); if (session_status() == PHP_SESSION_NONE) { session_start(); } $options = array(); if (!empty($obj->start)) { $options[] = 1; } if (!empty($obj->mid25Percent)) { $options[] = 2; } if (!empty($obj->mid50Percent)) { $options[] = 3; } if (!empty($obj->mid75Percent)) { $options[] = 4; } if (!empty($obj->end)) { $options[] = 5; } $selectedOptions = array(); if (empty($_SESSION['lastAdRandomPositions']) || $_SESSION['lastAdRandomPositions'] + 20 <= time()) { $_SESSION['lastAdRandomPositions'] = time(); if (empty($obj->showAdsOnRandomPositions->value)) { $selectedOptions = $options; } else { for ($i = 0; $i < $obj->showAdsOnRandomPositions->value; $i++) { shuffle($options); $selectedOptions[] = array_pop($options); } } $_SESSION['adRandomPositions'] = $selectedOptions; } $adRandomPositions = $_SESSION['adRandomPositions']; if (session_status() !== PHP_SESSION_NONE) { session_write_close(); } session_id($oldId); if (session_status() == PHP_SESSION_NONE) { session_start(); } //_error_log("VMAP select those options: " . print_r($adRandomPositions, true)); return $adRandomPositions; } public function getVMAPs($video_length) { $vmaps = array(); $obj = $this->getDataObject(); $selectedOptions = $this->getRandomPositions(); if (!empty($obj->start) && in_array(1, $selectedOptions)) { $vmaps[] = new VMAP("start", new VAST(1)); } if (!empty($obj->mid25Percent) && in_array(2, $selectedOptions)) { $val = $video_length * (25 / 100); $vmaps[] = new VMAP($val, new VAST(2)); } if (!empty($obj->mid50Percent) && in_array(3, $selectedOptions)) { $val = $video_length * (50 / 100); $vmaps[] = new VMAP($val, new VAST(3)); } if (!empty($obj->mid75Percent) && in_array(4, $selectedOptions)) { $val = $video_length * (75 / 100); $vmaps[] = new VMAP($val, new VAST(4)); } if (!empty($obj->end) && in_array(5, $selectedOptions)) { $vmaps[] = new VMAP("end", new VAST(5), $video_length); } return $vmaps; } public function VMAPsHasVideos() { $vmaps = $this->getVMAPs(100); //var_dump($vmaps);exit; foreach ($vmaps as $value) { if (empty($value->VAST->campaing)) { return false; } } return true; } public function showAdsNow() { if (!$this->VMAPsHasVideos()) { return false; } } static public function getVideos() { $campaings = VastCampaigns::getValidCampaigns(); //var_dump($campaings); $videos = array(); foreach ($campaings as $key => $value) { $v = VastCampaignsVideos::getValidVideos($value['id']); $videos = array_merge($videos, $v); $campaings[$key]['videos'] = $v; } return array('campaigns' => $campaings, 'videos' => $videos); } static public function getRandomVideo() { $result = static::getVideos(); $videos = $result['videos']; shuffle($videos); return array_pop($videos); } static public function getRandomCampaign() { $result = static::getVideos(); $campaing = $result['campaigns']; shuffle($campaing); return array_pop($campaing); } public function getPluginMenu() { global $global; $filename = $global['systemRootPath'] . 'plugin/AD_Server/pluginMenu.html'; return file_get_contents($filename); } public function getValidCampaignsFromVideo($videos_id) { return VastCampaigns::getValidCampaignsFromVideo($videos_id); } } class VMAP { public $timeOffset; public $timeOffsetSeconds; public $VAST; public $idTag = "preroll-ad"; function __construct($time, VAST $VAST, $video_length = 0) { if ($time === 'start') { $this->timeOffsetSeconds = 0; } else if ($time === 'end') { $this->timeOffsetSeconds = $video_length; } else { $this->timeOffsetSeconds = $time; } $this->VAST = $VAST; $this->setTimeOffset($time); } function setTimeOffset($time) { if (empty($time)) { //$time = "start"; } // if is longer then the video lenght will be END if (empty($time) || $time == "start") { $this->idTag = "preroll-ad-" . $this->VAST->id; } else if ($time == "end") { $this->idTag = "postroll-ad-" . $this->VAST->id; } else if (is_numeric($time)) { $time = $this->format($time); $this->idTag = "midroll-" . $this->VAST->id; } // format to 00:00:15.000 $this->timeOffset = $time; } private function format($seconds) { $hours = floor($seconds / 3600); $mins = floor($seconds / 60 % 60); $secs = floor($seconds % 60); return sprintf('%02d:%02d:%02d.000', $hours, $mins, $secs); } } class VAST { public $id; public $campaing; function __construct($id) { $this->id = $id; $row = AD_Server::getRandomVideo(); if (!empty($row)) { $this->campaing = $row['id']; } else { $this->campaing = false; } } } diff --git a/plugin/CDN/FtpClient/FtpClient.php b/plugin/CDN/FtpClient/FtpClient.php new file mode 100644 index 000000000..2c5b26e83 --- /dev/null +++ b/plugin/CDN/FtpClient/FtpClient.php @@ -0,0 +1,886 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @copyright Nicolas Tallefourtane http://nicolab.net + */ +namespace FtpClient; + +use \Countable; + +/** + * The FTP and SSL-FTP client for PHP. + * + * @method bool alloc() alloc(int $filesize, string &$result = null) Allocates space for a file to be uploaded + * @method bool cdup() cdup() Changes to the parent directory + * @method bool chdir() chdir(string $directory) Changes the current directory on a FTP server + * @method int chmod() chmod(int $mode, string $filename) Set permissions on a file via FTP + * @method bool delete() delete(string $path) Deletes a file on the FTP server + * @method bool exec() exec(string $command) Requests execution of a command on the FTP server + * @method bool fget() fget(resource $handle, string $remote_file, int $mode, int $resumepos = 0) Downloads a file from the FTP server and saves to an open file + * @method bool fput() fput(string $remote_file, resource $handle, int $mode, int $startpos = 0) Uploads from an open file to the FTP server + * @method mixed get_option() get_option(int $option) Retrieves various runtime behaviours of the current FTP stream + * @method bool get() get(string $local_file, string $remote_file, int $mode, int $resumepos = 0) Downloads a file from the FTP server + * @method int mdtm() mdtm(string $remote_file) Returns the last modified time of the given file + * @method int nb_continue() nb_continue() Continues retrieving/sending a file (non-blocking) + * @method int nb_fget() nb_fget(resource $handle, string $remote_file, int $mode, int $resumepos = 0) Retrieves a file from the FTP server and writes it to an open file (non-blocking) + * @method int nb_fput() nb_fput(string $remote_file, resource $handle, int $mode, int $startpos = 0) Stores a file from an open file to the FTP server (non-blocking) + * @method int nb_get() nb_get(string $local_file, string $remote_file, int $mode, int $resumepos = 0) Retrieves a file from the FTP server and writes it to a local file (non-blocking) + * @method int nb_put() nb_put(string $remote_file, string $local_file, int $mode, int $startpos = 0) Stores a file on the FTP server (non-blocking) + * @method bool pasv() pasv(bool $pasv) Turns passive mode on or off + * @method bool put() put(string $remote_file, string $local_file, int $mode, int $startpos = 0) Uploads a file to the FTP server + * @method string pwd() pwd() Returns the current directory name + * @method bool quit() quit() Closes an FTP connection + * @method array raw() raw(string $command) Sends an arbitrary command to an FTP server + * @method bool rename() rename(string $oldname, string $newname) Renames a file or a directory on the FTP server + * @method bool set_option() set_option(int $option, mixed $value) Set miscellaneous runtime FTP options + * @method bool site() site(string $command) Sends a SITE command to the server + * @method int size() size(string $remote_file) Returns the size of the given file + * @method string systype() systype() Returns the system type identifier of the remote FTP server + * + * @author Nicolas Tallefourtane + */ +class FtpClient implements Countable +{ + /** + * The connection with the server. + * + * @var resource + */ + protected $conn; + + /** + * PHP FTP functions wrapper. + * + * @var FtpWrapper + */ + private $ftp; + + /** + * Constructor. + * + * @param resource|null $connection + * @throws FtpException If FTP extension is not loaded. + */ + public function __construct($connection = null) + { + if (!extension_loaded('ftp')) { + throw new FtpException('FTP extension is not loaded!'); + } + + if ($connection) { + $this->conn = $connection; + } + + $this->setWrapper(new FtpWrapper($this->conn)); + } + + /** + * Close the connection when the object is destroyed. + */ + public function __destruct() + { + if ($this->conn) { + $this->ftp->close(); + } + } + + /** + * Call an internal method or a FTP method handled by the wrapper. + * + * Wrap the FTP PHP functions to call as method of FtpClient object. + * The connection is automaticaly passed to the FTP PHP functions. + * + * @param string $method + * @param array $arguments + * @return mixed + * @throws FtpException When the function is not valid + */ + public function __call($method, array $arguments) + { + return $this->ftp->__call($method, $arguments); + } + + /** + * Overwrites the PHP limit + * + * @param string|null $memory The memory limit, if null is not modified + * @param int $time_limit The max execution time, unlimited by default + * @param bool $ignore_user_abort Ignore user abort, true by default + * @return FtpClient + */ + public function setPhpLimit($memory = null, $time_limit = 0, $ignore_user_abort = true) + { + if (null !== $memory) { + ini_set('memory_limit', $memory); + } + + ignore_user_abort($ignore_user_abort); + set_time_limit($time_limit); + + return $this; + } + + /** + * Get the help information of the remote FTP server. + * + * @return array + */ + public function help() + { + return $this->ftp->raw('help'); + } + + /** + * Open a FTP connection. + * + * @param string $host + * @param bool $ssl + * @param int $port + * @param int $timeout + * + * @return FTPClient + * @throws FtpException If unable to connect + */ + public function connect($host, $ssl = false, $port = 21, $timeout = 90) + { + if ($ssl) { + $this->conn = @$this->ftp->ssl_connect($host, $port, $timeout); + } else { + $this->conn = @$this->ftp->connect($host, $port, $timeout); + } + + if (!$this->conn) { + throw new FtpException('Unable to connect'); + } + + return $this; + } + + /** + * Closes the current FTP connection. + * + * @return bool + */ + public function close() + { + if ($this->conn) { + $this->ftp->close(); + $this->conn = null; + } + } + + /** + * Get the connection with the server. + * + * @return resource + */ + public function getConnection() + { + return $this->conn; + } + + /** + * Get the wrapper. + * + * @return FtpWrapper + */ + public function getWrapper() + { + return $this->ftp; + } + + /** + * Logs in to an FTP connection. + * + * @param string $username + * @param string $password + * + * @return FtpClient + * @throws FtpException If the login is incorrect + */ + public function login($username = 'anonymous', $password = '') + { + $result = $this->ftp->login($username, $password); + + if ($result === false) { + throw new FtpException('Login incorrect'); + } + + return $this; + } + + /** + * Returns the last modified time of the given file. + * Return -1 on error + * + * @param string $remoteFile + * @param string|null $format + * + * @return int + */ + public function modifiedTime($remoteFile, $format = null) + { + $time = $this->ftp->mdtm($remoteFile); + + if ($time !== -1 && $format !== null) { + return date($format, $time); + } + + return $time; + } + + /** + * Changes to the parent directory. + * + * @throws FtpException + * @return FtpClient + */ + public function up() + { + $result = @$this->ftp->cdup(); + + if ($result === false) { + throw new FtpException('Unable to get parent folder'); + } + + return $this; + } + + /** + * Returns a list of files in the given directory. + * + * @param string $directory The directory, by default is "." the current directory + * @param bool $recursive + * @param callable $filter A callable to filter the result, by default is asort() PHP function. + * The result is passed in array argument, + * must take the argument by reference ! + * The callable should proceed with the reference array + * because is the behavior of several PHP sorting + * functions (by reference ensure directly the compatibility + * with all PHP sorting functions). + * + * @return array + * @throws FtpException If unable to list the directory + */ + public function nlist($directory = '.', $recursive = false, $filter = 'sort') + { + if (!$this->isDir($directory)) { + throw new FtpException('"'.$directory.'" is not a directory'); + } + + $files = $this->ftp->nlist($directory); + + if ($files === false) { + throw new FtpException('Unable to list directory'); + } + + $result = array(); + $dir_len = strlen($directory); + + // if it's the current + if (false !== ($kdot = array_search('.', $files))) { + unset($files[$kdot]); + } + + // if it's the parent + if(false !== ($kdot = array_search('..', $files))) { + unset($files[$kdot]); + } + + if (!$recursive) { + foreach ($files as $file) { + $result[] = $directory.'/'.$file; + } + + // working with the reference (behavior of several PHP sorting functions) + $filter($result); + + return $result; + } + + // utils for recursion + $flatten = function (array $arr) use (&$flatten) { + $flat = []; + + foreach ($arr as $k => $v) { + if (is_array($v)) { + $flat = array_merge($flat, $flatten($v)); + } else { + $flat[] = $v; + } + } + + return $flat; + }; + + foreach ($files as $file) { + $file = $directory.'/'.$file; + + // if contains the root path (behavior of the recursivity) + if (0 === strpos($file, $directory, $dir_len)) { + $file = substr($file, $dir_len); + } + + if ($this->isDir($file)) { + $result[] = $file; + $items = $flatten($this->nlist($file, true, $filter)); + + foreach ($items as $item) { + $result[] = $item; + } + + } else { + $result[] = $file; + } + } + + $result = array_unique($result); + + $filter($result); + + return $result; + } + + /** + * Creates a directory. + * + * @see FtpClient::rmdir() + * @see FtpClient::remove() + * @see FtpClient::put() + * @see FtpClient::putAll() + * + * @param string $directory The directory + * @param bool $recursive + * @return array + */ + public function mkdir($directory, $recursive = false) + { + if (!$recursive or $this->isDir($directory)) { + return $this->ftp->mkdir($directory); + } + + $result = false; + $pwd = $this->ftp->pwd(); + $parts = explode('/', $directory); + + foreach ($parts as $part) { + if ($part == '') { + continue; + } + + if (!@$this->ftp->chdir($part)) { + $result = $this->ftp->mkdir($part); + $this->ftp->chdir($part); + } + } + + $this->ftp->chdir($pwd); + + return $result; + } + + /** + * Remove a directory. + * + * @see FtpClient::mkdir() + * @see FtpClient::cleanDir() + * @see FtpClient::remove() + * @see FtpClient::delete() + * @param string $directory + * @param bool $recursive Forces deletion if the directory is not empty + * @return bool + * @throws FtpException If unable to list the directory to remove + */ + public function rmdir($directory, $recursive = true) + { + if ($recursive) { + $files = $this->nlist($directory, false, 'rsort'); + + // remove children + foreach ($files as $file) { + $this->remove($file, true); + } + } + + // remove the directory + return $this->ftp->rmdir($directory); + } + + /** + * Empty directory. + * + * @see FtpClient::remove() + * @see FtpClient::delete() + * @see FtpClient::rmdir() + * + * @param string $directory + * @return bool + */ + public function cleanDir($directory) + { + if (!$files = $this->nlist($directory)) { + return $this->isEmpty($directory); + } + + // remove children + foreach ($files as $file) { + $this->remove($file, true); + } + + return $this->isEmpty($directory); + } + + /** + * Remove a file or a directory. + * + * @see FtpClient::rmdir() + * @see FtpClient::cleanDir() + * @see FtpClient::delete() + * @param string $path The path of the file or directory to remove + * @param bool $recursive Is effective only if $path is a directory, {@see FtpClient::rmdir()} + * @return bool + */ + public function remove($path, $recursive = false) + { + try { + if (@$this->ftp->delete($path) + or ($this->isDir($path) and @$this->rmdir($path, $recursive))) { + return true; + } + + return false; + } catch (\Exception $e) { + return false; + } + } + + /** + * Check if a directory exist. + * + * @param string $directory + * @return bool + * @throws FtpException + */ + public function isDir($directory) + { + $pwd = $this->ftp->pwd(); + + if ($pwd === false) { + throw new FtpException('Unable to resolve the current directory'); + } + + if (@$this->ftp->chdir($directory)) { + $this->ftp->chdir($pwd); + return true; + } + + $this->ftp->chdir($pwd); + + return false; + } + + /** + * Check if a directory is empty. + * + * @param string $directory + * @return bool + */ + public function isEmpty($directory) + { + return $this->count($directory, null, false) === 0 ? true : false; + } + + /** + * Scan a directory and returns the details of each item. + * + * @see FtpClient::nlist() + * @see FtpClient::rawlist() + * @see FtpClient::parseRawList() + * @see FtpClient::dirSize() + * @param string $directory + * @param bool $recursive + * @return array + */ + public function scanDir($directory = '.', $recursive = false) + { + return $this->parseRawList($this->rawlist($directory, $recursive)); + } + + /** + * Returns the total size of the given directory in bytes. + * + * @param string $directory The directory, by default is the current directory. + * @param bool $recursive true by default + * @return int The size in bytes. + */ + public function dirSize($directory = '.', $recursive = true) + { + $items = $this->scanDir($directory, $recursive); + $size = 0; + + foreach ($items as $item) { + $size += (int) $item['size']; + } + + return $size; + } + + /** + * Count the items (file, directory, link, unknown). + * + * @param string $directory The directory, by default is the current directory. + * @param string|null $type The type of item to count (file, directory, link, unknown) + * @param bool $recursive true by default + * @return int + */ + public function count($directory = '.', $type = null, $recursive = true) + { + $items = (null === $type ? $this->nlist($directory, $recursive) + : $this->scanDir($directory, $recursive)); + + $count = 0; + foreach ($items as $item) { + if (null === $type or $item['type'] == $type) { + $count++; + } + } + + return $count; + } + + /** + * Uploads a file to the server from a string. + * + * @param string $remote_file + * @param string $content + * @return FtpClient + * @throws FtpException When the transfer fails + */ + public function putFromString($remote_file, $content) + { + $handle = fopen('php://temp', 'w'); + + fwrite($handle, $content); + rewind($handle); + + if ($this->ftp->fput($remote_file, $handle, FTP_BINARY)) { + return $this; + } + + throw new FtpException('Unable to put the file "'.$remote_file.'"'); + } + + /** + * Uploads a file to the server. + * + * @param string $local_file + * @return FtpClient + * @throws FtpException When the transfer fails + */ + public function putFromPath($local_file) + { + $remote_file = basename($local_file); + $handle = fopen($local_file, 'r'); + + if ($this->ftp->fput($remote_file, $handle, FTP_BINARY)) { + rewind($handle); + return $this; + } + + throw new FtpException( + 'Unable to put the remote file from the local file "'.$local_file.'"' + ); + } + + /** + * Upload files. + * + * @param string $source_directory + * @param string $target_directory + * @param int $mode + * @return FtpClient + */ + public function putAll($source_directory, $target_directory, $mode = FTP_BINARY) + { + $d = dir($source_directory); + + // do this for each file in the directory + while ($file = $d->read()) { + + // to prevent an infinite loop + if ($file != "." && $file != "..") { + + // do the following if it is a directory + if (is_dir($source_directory.'/'.$file)) { + + if (!$this->isDir($target_directory.'/'.$file)) { + + // create directories that do not yet exist + $this->ftp->mkdir($target_directory.'/'.$file); + } + + // recursive part + $this->putAll( + $source_directory.'/'.$file, $target_directory.'/'.$file, + $mode + ); + } else { + + // put the files + $this->ftp->put( + $target_directory.'/'.$file, $source_directory.'/'.$file, + $mode + ); + } + } + } + + return $this; + } + + public function put($source_directory, $target_directory, $mode = FTP_BINARY) + { + $this->ftp->put($source_directory, $target_directory, $mode); + + return $this; + } + + + /** + * Returns a detailed list of files in the given directory. + * + * @see FtpClient::nlist() + * @see FtpClient::scanDir() + * @see FtpClient::dirSize() + * @param string $directory The directory, by default is the current directory + * @param bool $recursive + * @return array + * @throws FtpException + */ + public function rawlist($directory = '.', $recursive = false) + { + if (!$this->isDir($directory)) { + throw new FtpException('"'.$directory.'" is not a directory.'); + } + + $list = $this->ftp->rawlist($directory); + $items = array(); + + if (!$list) { + return $items; + } + + if (false == $recursive) { + foreach ($list as $path => $item) { + $chunks = preg_split("/\s+/", $item); + + // if not "name" + if (empty($chunks[8]) || $chunks[8] == '.' || $chunks[8] == '..') { + continue; + } + + $path = $directory.'/'.$chunks[8]; + + if (isset($chunks[9])) { + $nbChunks = count($chunks); + + for ($i = 9; $i < $nbChunks; $i++) { + $path .= ' '.$chunks[$i]; + } + } + + + if (substr($path, 0, 2) == './') { + $path = substr($path, 2); + } + + $items[ $this->rawToType($item).'#'.$path ] = $item; + } + + return $items; + } + + $path = ''; + + foreach ($list as $item) { + $len = strlen($item); + + if (!$len + + // "." + || ($item[$len-1] == '.' && $item[$len-2] == ' ' + + // ".." + or $item[$len-1] == '.' && $item[$len-2] == '.' && $item[$len-3] == ' ') + ){ + + continue; + } + + $chunks = preg_split("/\s+/", $item); + + // if not "name" + if (empty($chunks[8]) || $chunks[8] == '.' || $chunks[8] == '..') { + continue; + } + + $path = $directory.'/'.$chunks[8]; + + if (isset($chunks[9])) { + $nbChunks = count($chunks); + + for ($i = 9; $i < $nbChunks; $i++) { + $path .= ' '.$chunks[$i]; + } + } + + if (substr($path, 0, 2) == './') { + $path = substr($path, 2); + } + + $items[$this->rawToType($item).'#'.$path] = $item; + + if ($item[0] == 'd') { + $sublist = $this->rawlist($path, true); + + foreach ($sublist as $subpath => $subitem) { + $items[$subpath] = $subitem; + } + } + } + + return $items; + } + + /** + * Parse raw list. + * + * @see FtpClient::rawlist() + * @see FtpClient::scanDir() + * @see FtpClient::dirSize() + * @param array $rawlist + * @return array + */ + public function parseRawList(array $rawlist) + { + $items = array(); + $path = ''; + + foreach ($rawlist as $key => $child) { + $chunks = preg_split("/\s+/", $child, 9); + + if (isset($chunks[8]) && ($chunks[8] == '.' or $chunks[8] == '..')) { + continue; + } + + if (count($chunks) === 1) { + $len = strlen($chunks[0]); + + if ($len && $chunks[0][$len-1] == ':') { + $path = substr($chunks[0], 0, -1); + } + + continue; + } + + // Prepare for filename that has space + $nameSlices = array_slice($chunks, 8, true); + + $item = [ + 'permissions' => $chunks[0], + 'number' => $chunks[1], + 'owner' => $chunks[2], + 'group' => $chunks[3], + 'size' => $chunks[4], + 'month' => $chunks[5], + 'day' => $chunks[6], + 'time' => $chunks[7], + 'name' => implode(' ', $nameSlices), + 'type' => $this->rawToType($chunks[0]), + ]; + + if ($item['type'] == 'link') { + $item['target'] = $chunks[10]; // 9 is "->" + } + + // if the key is not the path, behavior of ftp_rawlist() PHP function + if (is_int($key) || false === strpos($key, $item['name'])) { + array_splice($chunks, 0, 8); + + $key = $item['type'].'#' + .($path ? $path.'/' : '') + .implode(' ', $chunks); + + if ($item['type'] == 'link') { + + // get the first part of 'link#the-link.ext -> /path/of/the/source.ext' + $exp = explode(' ->', $key); + $key = rtrim($exp[0]); + } + + $items[$key] = $item; + + } else { + + // the key is the path, behavior of FtpClient::rawlist() method() + $items[$key] = $item; + } + } + + return $items; + } + + /** + * Convert raw info (drwx---r-x ...) to type (file, directory, link, unknown). + * Only the first char is used for resolving. + * + * @param string $permission Example : drwx---r-x + * + * @return string The file type (file, directory, link, unknown) + * @throws FtpException + */ + public function rawToType($permission) + { + if (!is_string($permission)) { + throw new FtpException('The "$permission" argument must be a string, "' + .gettype($permission).'" given.'); + } + + if (empty($permission[0])) { + return 'unknown'; + } + + switch ($permission[0]) { + case '-': + return 'file'; + + case 'd': + return 'directory'; + + case 'l': + return 'link'; + + default: + return 'unknown'; + } + } + + /** + * Set the wrapper which forward the PHP FTP functions to use in FtpClient instance. + * + * @param FtpWrapper $wrapper + * @return FtpClient + */ + protected function setWrapper(FtpWrapper $wrapper) + { + $this->ftp = $wrapper; + + return $this; + } +} diff --git a/plugin/CDN/FtpClient/FtpException.php b/plugin/CDN/FtpClient/FtpException.php new file mode 100644 index 000000000..f17ed7f8a --- /dev/null +++ b/plugin/CDN/FtpClient/FtpException.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @copyright Nicolas Tallefourtane http://nicolab.net + */ +namespace FtpClient; + +/** + * The FtpException class. + * Exception thrown if an error on runtime of the FTP client occurs. + * @inheritDoc + * @author Nicolas Tallefourtane + */ +class FtpException extends \Exception {} diff --git a/plugin/CDN/FtpClient/FtpWrapper.php b/plugin/CDN/FtpClient/FtpWrapper.php new file mode 100644 index 000000000..cd12de03a --- /dev/null +++ b/plugin/CDN/FtpClient/FtpWrapper.php @@ -0,0 +1,115 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @copyright Nicolas Tallefourtane http://nicolab.net + */ +namespace FtpClient; + +/** + * Wrap the PHP FTP functions + * + * @method bool alloc() alloc(int $filesize, string &$result = null) Allocates space for a file to be uploaded + * @method bool cdup() cdup() Changes to the parent directory + * @method bool chdir() chdir(string $directory) Changes the current directory on a FTP server + * @method int chmod() chmod(int $mode, string $filename) Set permissions on a file via FTP + * @method bool close() close() Closes an FTP connection + * @method bool delete() delete(string $path) Deletes a file on the FTP server + * @method bool exec() exec(string $command) Requests execution of a command on the FTP server + * @method bool fget() fget(resource $handle, string $remote_file, int $mode, int $resumepos = 0) Downloads a file from the FTP server and saves to an open file + * @method bool fput() fput(string $remote_file, resource $handle, int $mode, int $startpos = 0) Uploads from an open file to the FTP server + * @method mixed get_option() get_option(int $option) Retrieves various runtime behaviours of the current FTP stream + * @method bool get() get(string $local_file, string $remote_file, int $mode, int $resumepos = 0) Downloads a file from the FTP server + * @method bool login() login(string $username, string $password) Logs in to an FTP connection + * @method int mdtm() mdtm(string $remote_file) Returns the last modified time of the given file + * @method string mkdir() mkdir(string $directory) Creates a directory + * @method int nb_continue() nb_continue() Continues retrieving/sending a file (non-blocking) + * @method int nb_fget() nb_fget(resource $handle, string $remote_file, int $mode, int $resumepos = 0) Retrieves a file from the FTP server and writes it to an open file (non-blocking) + * @method int nb_fput() nb_fput(string $remote_file, resource $handle, int $mode, int $startpos = 0) Stores a file from an open file to the FTP server (non-blocking) + * @method int nb_get() nb_get(string $local_file, string $remote_file, int $mode, int $resumepos = 0) Retrieves a file from the FTP server and writes it to a local file (non-blocking) + * @method int nb_put() nb_put(string $remote_file, string $local_file, int $mode, int $startpos = 0) Stores a file on the FTP server (non-blocking) + * @method array nlist() nlist(string $directory) Returns a list of files in the given directory + * @method bool pasv() pasv(bool $pasv) Turns passive mode on or off + * @method bool put() put(string $remote_file, string $local_file, int $mode, int $startpos = 0) Uploads a file to the FTP server + * @method string pwd() pwd() Returns the current directory name + * @method bool quit() quit() Closes an FTP connection + * @method array raw() raw(string $command) Sends an arbitrary command to an FTP server + * @method array rawlist() rawlist(string $directory, bool $recursive = false) Returns a detailed list of files in the given directory + * @method bool rename() rename(string $oldname, string $newname) Renames a file or a directory on the FTP server + * @method bool rmdir() rmdir(string $directory) Removes a directory + * @method bool set_option() set_option(int $option, mixed $value) Set miscellaneous runtime FTP options + * @method bool site() site(string $command) Sends a SITE command to the server + * @method int size() size(string $remote_file) Returns the size of the given file + * @method string systype() systype() Returns the system type identifier of the remote FTP server + * + * @author Nicolas Tallefourtane + */ +class FtpWrapper +{ + /** + * The connection with the server + * + * @var resource + */ + protected $conn; + + /** + * Constructor. + * + * @param resource &$connection The FTP (or SSL-FTP) connection (takes by reference). + */ + public function __construct(&$connection) + { + $this->conn = &$connection; + } + + /** + * Forward the method call to FTP functions + * + * @param string $function + * @param array $arguments + * @return mixed + * @throws FtpException When the function is not valid + */ + public function __call($function, array $arguments) + { + $function = 'ftp_' . $function; + + if (function_exists($function)) { + array_unshift($arguments, $this->conn); + return call_user_func_array($function, $arguments); + } + + throw new FtpException("{$function} is not a valid FTP function"); + } + + /** + * Opens a FTP connection + * + * @param string $host + * @param int $port + * @param int $timeout + * @return resource + */ + public function connect($host, $port = 21, $timeout = 90) + { + return ftp_connect($host, $port, $timeout); + } + + /** + * Opens a Secure SSL-FTP connection + * @param string $host + * @param int $port + * @param int $timeout + * @return resource + */ + public function ssl_connect($host, $port = 21, $timeout = 90) + { + return ftp_ssl_connect($host, $port, $timeout); + } +} diff --git a/plugin/CDN/Storage/CDNStorage.php b/plugin/CDN/Storage/CDNStorage.php new file mode 100644 index 000000000..67efb4bb0 --- /dev/null +++ b/plugin/CDN/Storage/CDNStorage.php @@ -0,0 +1,468 @@ +connect('storage.ypt.me'); + $CDNstorage->login($obj->storage_username, $obj->storage_password); + $CDNstorage->pasv(true); + } catch (Exception $exc) { + _error_log("FTP:getClient fail " . $exc->getMessage()); + } + _error_log("FTP:getClient finish"); + return $CDNstorage; + } + + public function xsendfilePreVideoPlay() { + global $global; + + $path_parts = pathinfo($_GET['file']); + + $filename = Video::getCleanFilenameFromFile($path_parts['filename']); + + if (in_array(strtolower($path_parts['extension']), CDNStorage::$allowedFiles)) { + $paths = Video::getPaths($_GET['file']); + $localFile = $paths['path']; + if (!file_exists($localFile) || filesize($localFile) < 1024) { + $url = self::getURL($path_parts["basename"]); + header("Location: {$url}"); + exit; + } + } + } + + static function getFilesListBoth($videos_id) { + global $_getFilesListBoth; + if (!isset($_getFilesListBoth)) { + $_getFilesListBoth = array(); + } + if (!empty($_getFilesListBoth[$videos_id])) { + return $_getFilesListBoth[$videos_id]; + } + $remoteList = self::getFilesListRemote($videos_id); + $localList = self::getFilesListLocal($videos_id, false); + + $searchThis = $localList; + $compareThis = $remoteList; + $searchingLocal = true; + + if (count($remoteList) > count($localList)) { + $searchThis = $remoteList; + $compareThis = $localList; + $searchingLocal = false; + } + $files = array(); + foreach ($searchThis as $key => $value) { + $isLocal = true; + + if ($localList[$key]['local_filesize'] < $remoteList[$key]['remote_filesize']) { + $isLocal = false; + } + + $files[$key] = array('isLocal' => $isLocal, 'local' => @$localList[$key], 'remote' => $remoteList[$key]); + } + $_getFilesListBoth[$videos_id] = $files; + return $files; + } + + static function getFilesListRemote($videos_id, $client = null) { + global $global, $_getFilesListRemote; + if (!isset($_getFilesListRemote)) { + $_getFilesListRemote = array(); + } + if (!empty($_getFilesListRemote[$videos_id])) { + return $_getFilesListRemote[$videos_id]; + } + $video = Video::getVideoLight($videos_id); + //$paths = Video::getPaths($video['filename']); + if (empty($client)) { + $client = self::getStorageClient(); + } + if (!$client->isDir($video['filename'])) { + return array(); + } + + $obj = AVideoPlugin::getDataObject('CDN'); + $pz = addLastSlash($obj->storage_pullzone); + + $list = $client->rawlist($video['filename'], true); + $files = array(); + foreach ($list as $key => $value) { + $parts1 = explode('#', $key); + if ($parts1[0] == 'directory') { + continue; + } + + preg_match('/ ([0-9]+) [a-zA-z]+ [0-9]{1,2} [0-9]{1,2}:[0-9]{1,2}/', $value, $matches); + + $remote_filesize = $matches[1]; + $relative = $parts1[1]; + $local_path = "{$global['systemRootPath']}videos/{$relative}"; + $local_filesize = filesize($local_path); + $remote_path = "/{$obj->storage_username}/" . $relative; + $path_parts = pathinfo($local_path); + $extension = $path_parts['extension']; + + $file = array( + 'extension' => $path_parts['extension'], + 'videos_id' => $videos_id, + 'local_path' => $local_path, + 'remote_path' => $remote_path, + 'local_url' => "{$global['webSiteRootURL']}videos/{$relative}", + 'remote_utl' => "https://{$pz}{$relative}", + 'relative' => $relative, + 'local_filesize' => $local_filesize, + 'remote_filesize' => $remote_filesize, + 'video' => $video); + + $files[$relative] = $file; + } + $_getFilesListRemote[$videos_id] = $files; + return $files; + } + + static function getRemoteDirectorySize($videos_id, $client = null) { + $list = self::getFilesListRemote($videos_id, $client); + $total = 0; + foreach ($list as $value) { + $total += $value['remote_filesize']; + } + return $total; + } + + static function getFilesListInfo($local_path, $storage_username, $storage_pullzone, $videos_id, $skipDummyFiles = true) { + global $global; + if ($skipDummyFiles && filesize($local_path) < 20) { + return false; + } + + $path_parts = pathinfo($local_path); + $extension = $path_parts['extension']; + if (!in_array(strtolower($extension), CDNStorage::$allowedFiles)) { + return false; + } + $videosDir = Video::getStoragePath(); + $relative = str_replace($videosDir, '', $local_path); + $relative = str_replace('\\', '/', $relative); + $local_filesize = filesize($local_path); + $remote_path = "/{$storage_username}/" . $relative; + + $file = array( + 'extension' => $path_parts['extension'], + 'videos_id' => $videos_id, + 'local_path' => $local_path, + 'remote_path' => $remote_path, + 'local_url' => "{$global['webSiteRootURL']}videos/{$relative}", + 'remote_utl' => "https://{$pz}{$relative}", + 'relative' => $relative, + 'local_filesize' => $local_filesize, + 'video' => $video); + return $file; + } + + static function getLocalFolder($videos_id) { + $video = Video::getVideoLight($videos_id); + $paths = Video::getPaths($video['filename']); + + return listFolderFiles($paths['path']); + } + + static function getOrCreateSite() { + $status = 'y'; + $row = Sites::getFromStatus($status); + if (empty($row)) { + $row['name'] = 'Storage'; + $row['url'] = 'url'; + $row['status'] = $status; + $row['secret'] = 'no secret'; + $s = new Sites(0); + $s->setName($row['name']); + $s->setURL($row['url']); + $s->setStatus($row['status']); + $s->setSecret($row['secret']); + $row['id'] = $s->save(); + + return $row; + } + return $row[0]; + } + + public static function setSite($videos_id, $isOnTheStorage) { + _mysql_connect(); + $v = new Video('', '', $videos_id); + if ($isOnTheStorage) { + $site = self::getOrCreateSite(); + $v->setSites_id($site['id']); + } else { + $v->setSites_id(0); + } + + return $v->save(); + } + + static function moveRemoteToLocal($videos_id, $runInBackground= true) { + $start = microtime(true); + self::addToLog($videos_id, "Start moveRemoteToLocal videos_id={$videos_id}"); + $client = self::getStorageClient(); + $list = self::getFilesListRemote($videos_id, $client); + $totalFiles = count($list); + if (empty($totalFiles)) { + $msg = 'There is not file to transfer (' . $totalFiles . ')'; + _error_log($msg); + self::addToLog($videos_id, $msg); + self::setProgress($videos_id, true, true); + self::deleteRemoteDirectory($videos_id, $client); + return false; + } + self::addToLog($videos_id, 'Found ' . $totalFiles . ' Files'); + $video = Video::getVideoLight($videos_id); + if($runInBackground){ + outputAndContinueInBackground(); + } + @session_write_close(); + _mysql_close(); + ini_set('max_execution_time', 0); + set_time_limit(0); + $fails = 0; + foreach ($list as $value) { + $remote_filesize = $client->size($value['remote_path']); + if ($local_filesize >= $remote_filesize) { + self::addToLog($value['videos_id'], $value['local_path'] . ' is NOT a dummy file local_filesize=' . $value['local_filesize'] . ' Bytes'); + //$client->delete($value['remote_path']); + continue; + } + try { + $response = $client->get($value['local_path'], $value['remote_path']); + $msg = "File moved from {$value['remote_path']} to {$value['local_path']} "; + self::addToLog($videos_id, $msg); + $filesCopied++; + } catch (Exception $exc) { + $fails++; + _error_log($exc->getTraceAsString()); + _error_log(json_encode(error_get_last())); + self::addToLog($videos_id, "ERROR 1 " . $exc->getTraceAsString()); + self::addToLog($videos_id, "ERROR 2 " . json_encode(error_get_last())); + } + } + if (empty($fails)) { + self::deleteRemoteDirectory($videos_id, $client); + self::setProgress($videos_id, true, true); + _error_log("ERROR moveRemoteToLocal had {$fails} fails videos_id=($videos_id) filesCopied={$filesCopied} in {$end} Seconds"); + } + $end = microtime(true) - $start; + _error_log("Finish moveRemoteToLocal videos_id=($videos_id) filesCopied={$filesCopied} in {$end} Seconds"); + return $filesCopied; + } + + static function deleteRemoteDirectory($videos_id, $client = null, $recursive = true) { + if(empty($videos_id)){ + return false; + } + $video = Video::getVideoLight($videos_id); + if(empty($video['filename'])){ + return false; + } + return self::deleteRemoteDirectoryFromFilename($video['filename'], $client, $recursive); + } + + static function deleteRemoteDirectoryFromFilename($filename, $client = null, $recursive = true) { + if(empty($filename)){ + return false; + } + $obj = AVideoPlugin::getDataObject('CDN'); + if (empty($client)) { + $client = self::getStorageClient(); + } + $dir = "/{$obj->storage_username}/{$filename}"; + if(!$client->isDir($dir)){ + return false; + } + _error_log("CDNStorage::deleteRemoteDirectoryFromFilename {$dir}"); + return $client->rmdir($dir, $recursive); + } + + static function moveLocalToRemote($videos_id, $runInBackground= true) { + $start = microtime(true); + self::addToLog($videos_id, "Start moveLocalToRemote videos_id={$videos_id}"); + $list = self::getFilesListLocal($videos_id); + $totalFiles = count($list); + if (empty($totalFiles)) { + self::addToLog($videos_id, 'There is not file to transfer (' . $totalFiles . ')'); + self::setProgress($videos_id, true, true); + return false; + } + self::addToLog($videos_id, 'Found ' . $totalFiles . ' Files'); + $client = self::getStorageClient(); + $video = Video::getVideoLight($videos_id); + $client->mkdir($video['filename'], true); + if($runInBackground){ + outputAndContinueInBackground(); + } + @session_write_close(); + _mysql_close(); + ini_set('max_execution_time', 0); + set_time_limit(0); + self::addToLog($videos_id, 'Directory ' . $video['filename'] . ' Created'); + foreach ($list as $value) { + if ($value['local_filesize'] < 20) { + self::addToLog($value['videos_id'], $value['local_path'] . ' is a dummy file local_filesize=' . $value['local_filesize'] . ' Bytes'); + continue; + } + try { + $response = $client->put($value['remote_path'], $value['local_path']); + $msg = "File moved from {$value['local_path']} to {$value['remote_path']} "; + self::addToLog($videos_id, $msg); + $filesCopied++; + $remote_filesize = $client->size($value['remote_path']); + if ($remote_filesize == $value['local_filesize']) { + self::createDummy($value['local_path']); + } + } catch (Exception $exc) { + _error_log($exc->getTraceAsString()); + _error_log(json_encode(error_get_last())); + self::addToLog($videos_id, "ERROR 1 " . $exc->getTraceAsString()); + self::addToLog($videos_id, "ERROR 2 " . json_encode(error_get_last())); + } + } + + self::setProgress($videos_id, true, true); + $end = microtime(true) - $start; + _error_log("Finish moveLocalToRemote videos_id=($videos_id) filesCopied={$filesCopied} in {$end} Seconds"); + + return $filesCopied; + } + + private static function setProgress($videos_id, $isOnTheStorage, $finished) { + self::setSite($videos_id, $isOnTheStorage); + if ($finished) { + Video::updateFilesize($videos_id); + self::deleteLog($videos_id); + } + } + + static function isMoving($videos_id) { + $file = self::getLogFile($videos_id); + if (empty($file) || !file_exists($file)) { + return false; + } + return true; + } + + static function createDummy($file_path) { + global $global; + $path_parts = pathinfo($file_path); + $extension = strtolower($path_parts['extension']); + + if ($extension == 'ts') { + unlink($file_path); + } else if (in_array($extension, CDNStorage::$allowedFiles)) { + file_put_contents($file_path, 'Dummy File'); + } else { + return false; + } + + return true; + } + + static function getFilesListLocal($videos_id, $skipDummyFiles = true) { + global $global, $_getFilesList_CDNSTORAGE; + if (!isset($_getFilesList_CDNSTORAGE)) { + $_getFilesList_CDNSTORAGE = array(); + } + if (!empty($_getFilesList_CDNSTORAGE[$videos_id])) { + return $_getFilesList_CDNSTORAGE[$videos_id]; + } + $obj = AVideoPlugin::getDataObject('CDN'); + $pz = addLastSlash($obj->storage_pullzone); + $files = self::getLocalFolder($videos_id); + $video = Video::getVideoLight($videos_id); + $filesList = array(); + foreach ($files as $value) { + if (is_array($value)) { + foreach ($value as $value2) { + $file = self::getFilesListInfo($value2, $obj->storage_username, $pz, $videos_id, $skipDummyFiles); + if (!empty($file)) { + $filesList[$file['relative']] = $file; + } + } + } else { + $file = self::getFilesListInfo($value, $obj->storage_username, $pz, $videos_id, $skipDummyFiles); + if (!empty($file)) { + $filesList[$file['relative']] = $file; + } + } + } + $_getFilesList_CDNSTORAGE[$videos_id] = $filesList; + return $filesList; + } + + public function getAddress($filename) { + global $global; + require_once $global['systemRootPath'] . 'objects/video.php'; + $obj = $this->getDataObject(); + $file = Video::getPathToFile($filename); + $address = array('path' => $file, 'url' => $this->getURL($filename)); + return $address; + } + + static function getURL($filename) { + global $global; + $paths = Video::getPaths($filename); + $file = $paths['path'] . $filename; + if (!file_exists($file)) { + $file = $paths['path'] . $filename; + } + if (!file_exists($file)) { + $file = $paths['path'] . 'index.m3u8'; + } + if (is_dir($file)) { + return false; + } + if (!file_exists($file)) { + return false; + } + if (filesize($file) > 20) { + return Video::getURLToFile($filename); + } + if (preg_match('/m3u8$/', $filename)) { + $relativeFilename = $filename; + } else { + $relativeFilename = "{$paths['filename']}/{$filename}"; + } + $obj = AVideoPlugin::getDataObject('CDN'); + $pz = addLastSlash($obj->storage_pullzone); + return "https://{$pz}{$relativeFilename}"; + } + + static function getLogFile($videos_id) { + $video = Video::getVideoLight($videos_id); + $path = Video::getPathToFile($video['filename']); + + $path .= '_cdnStorage.log'; + return $path; + } + + static function addToLog($videos_id, $message) { + $file = self::getLogFile($videos_id); + return file_put_contents($file, date('Y-m-d H:i:s: ') . $message . PHP_EOL, FILE_APPEND); + } + + static function deleteLog($videos_id) { + $file = self::getLogFile($videos_id); + return unlink($file); + } + +} diff --git a/plugin/CDN/Storage/moveLocalToRemote.json.php b/plugin/CDN/Storage/moveLocalToRemote.json.php new file mode 100644 index 000000000..265460992 --- /dev/null +++ b/plugin/CDN/Storage/moveLocalToRemote.json.php @@ -0,0 +1,37 @@ +error = true; +$obj->msg = ""; + +$isEnabled = AVideoPlugin::isEnabledByName('CDN'); +if(!$isEnabled){ + $obj->msg = "CDN is disabled"; + die(json_encode($obj)); +} + +if(empty($_REQUEST['videos_id'])){ + $_REQUEST['videos_id'] = intval(@$argv[1]); +} + +if (empty($_REQUEST['videos_id'])) { + $obj->msg = "Video ID is empty"; + die(json_encode($obj)); +} + +if(!isCommandLineInterface()){ + if(!Video::canEdit($_REQUEST['videos_id'])){ + $obj->msg = "Command line only"; + die(json_encode($obj)); + } +} + +$obj->error = false; +$obj->response = CDNStorage::moveLocalToRemote($_REQUEST['videos_id']); + +echo json_encode($obj); diff --git a/plugin/CDN/Storage/moveRemoteToLocal.json.php b/plugin/CDN/Storage/moveRemoteToLocal.json.php new file mode 100644 index 000000000..25e71aa6d --- /dev/null +++ b/plugin/CDN/Storage/moveRemoteToLocal.json.php @@ -0,0 +1,37 @@ +error = true; +$obj->msg = ""; + +$isEnabled = AVideoPlugin::isEnabledByName('CDN'); +if(!$isEnabled){ + $obj->msg = "CDN is disabled"; + die(json_encode($obj)); +} + +if(empty($_REQUEST['videos_id'])){ + $_REQUEST['videos_id'] = intval(@$argv[1]); +} + +if (empty($_REQUEST['videos_id'])) { + $obj->msg = "Video ID is empty"; + die(json_encode($obj)); +} + +if(!isCommandLineInterface()){ + if(!Video::canEdit($_REQUEST['videos_id'])){ + $obj->msg = "Command line only"; + die(json_encode($obj)); + } +} + +$obj->error = false; +$obj->response = CDNStorage::moveRemoteToLocal($_REQUEST['videos_id']); + +echo json_encode($obj); diff --git a/plugin/CDN/Storage/pluginMenu.html b/plugin/CDN/Storage/pluginMenu.html new file mode 100644 index 000000000..c5cdc3767 --- /dev/null +++ b/plugin/CDN/Storage/pluginMenu.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/plugin/CDN/Storage/syncVideo.php b/plugin/CDN/Storage/syncVideo.php new file mode 100644 index 000000000..60429ce2a --- /dev/null +++ b/plugin/CDN/Storage/syncVideo.php @@ -0,0 +1,134 @@ + + + + + <?php echo $config->getWebSiteTitle(); ?> :: Move Storage + + + + +
+
+
+ +
+
+
+ $value) { + if (!empty($value['local']['local_filesize']) && $value['local']['local_filesize'] > 20 && $value['local']['local_filesize'] > 0) { + $totalL++; + $totalFileSizeL += $value['local']['local_filesize']; + $humanSize = humanFileSize($value['local']['local_filesize']); + $listString[] = ' ' . __('Local') . ''; + $listString[] = '' . $humanSize . ''; + } + if (!empty($value['remote']['remote_filesize']) && $value['remote']['remote_filesize'] > 0) { + $totalR++; + $totalFileSizeR += $value['remote']['remote_filesize']; + $humanSize = humanFileSize($value['remote']['remote_filesize']); + $listString[] = ' ' . __('Storage') . ''; + $listString[] = '' . $humanSize . ''; + } + + $listString[] = " {$key}
"; + } + + if ($totalL) { + ?> + + + + + + +
+
+ +
+
+ + + diff --git a/plugin/CDN/Storage/test.php b/plugin/CDN/Storage/test.php new file mode 100644 index 000000000..8254fe215 --- /dev/null +++ b/plugin/CDN/Storage/test.php @@ -0,0 +1,42 @@ +Transfering...' . PHP_EOL; + +echo '

Test 1 Default configuration

' . PHP_EOL; +$CDNstorage = new \FtpClient\FtpClient(); +$CDNstorage->connect('storage.bunnycdn.com'); +$CDNstorage->login($obj->storage_username, $obj->storage_password); +$CDNstorage->pasv(true); +if ($CDNstorage->modifiedTime($remote_file) > 0) { + $CDNstorage->delete($filename); + if ($CDNstorage->modifiedTime($remote_file) > 0) { + die("Please first delete the file {$remote_file} from the FTP dir"); + } +} +$response = $CDNstorage->put($remote_file, $tmp_name); +if ($CDNstorage->modifiedTime($remote_file) > 0) { + echo "The default configuration works"; +} else { + echo '

Default configuration fail

' . PHP_EOL; +} + +$pz = addLastSlash($obj->storage_pullzone); + +echo "
{$filename}
"; diff --git a/plugin/CDN/Storage/test.txt b/plugin/CDN/Storage/test.txt new file mode 100644 index 000000000..3cfd9654d --- /dev/null +++ b/plugin/CDN/Storage/test.txt @@ -0,0 +1 @@ +CDN storage test file \ No newline at end of file diff --git a/plugin/PlayerSkins/PlayerSkins.php b/plugin/PlayerSkins/PlayerSkins.php index f702273e2..e568a94c4 100644 --- a/plugin/PlayerSkins/PlayerSkins.php +++ b/plugin/PlayerSkins/PlayerSkins.php @@ -1,619 +1,619 @@ The Skis options are: "; $dir = $global['systemRootPath'] . 'plugin/PlayerSkins/skins/'; $names = array(); foreach (glob($dir . '*.css') as $file) { $path_parts = pathinfo($file); $names[] = $path_parts['filename']; } return $desc . "" . implode(" or ", $names) . ""; } public function getName() { return "PlayerSkins"; } public function getUUID() { return "e9a568e6-ef61-4dcc-aad0-0109e9be8e36"; } public function getPluginVersion() { return "1.1"; } public function getEmptyDataObject() { global $global; $obj = new stdClass(); $obj->skin = "avideo"; $obj->playbackRates = "[0.5, 1, 1.5, 2]"; $obj->playerCustomDataSetup = ""; $obj->showSocialShareOnEmbed = true; $obj->showLoopButton = true; $obj->showLogo = false; $obj->showShareSocial = true; $obj->showShareAutoplay = true; $obj->showLogoOnEmbed = false; $obj->showLogoAdjustScale = "0.4"; $obj->showLogoAdjustLeft = "-74px"; $obj->showLogoAdjustTop = "-22px;"; $obj->disableEmbedTopInfo = false; $obj->contextMenuDisableEmbedOnly = false; $obj->contextMenuLoop = true; $obj->contextMenuCopyVideoURL = true; $obj->contextMenuCopyVideoURLCurrentTime = true; $obj->contextMenuCopyEmbedCode = true; $obj->contextMenuShare = true; $obj->playerFullHeight = false; return $obj; } static function getMediaTag($filename, $htmlMediaTag = false) { global $autoPlayURL, $global, $config, $isVideoTypeEmbed, $advancedCustom; $obj = AVideoPlugin::getObjectData('PlayerSkins'); $html = ''; if (empty($htmlMediaTag)) { $video = Video::getVideoFromFileName($filename, true); $vType = Video::getIncludeType($video); $_GET['isMediaPlaySite'] = $video['id']; if (is_object($video['externalOptions'])) { if (!empty($video['externalOptions']->videoStartSeconds)) { $video['externalOptions']->videoStartSeconds = parseDurationToSeconds($video['externalOptions']->videoStartSeconds); } else { $video['externalOptions']->videoStartSeconds = 0; } } else { //_error_log('externalOptions Error '.$video['externalOptions'], AVideoLog::$WARNING); $video['externalOptions'] = new stdClass(); $video['externalOptions']->videoStartSeconds = 0; } $images = Video::getImageFromFilename($filename); if ($vType == 'video') { $htmlMediaTag = ''; - } else if ($vType == 'audio') { + } else if ($vType == 'audio') { $htmlMediaTag = ''; } else if ($vType == 'embed') { $disableYoutubeIntegration = false; if (!empty($advancedCustom->disableYoutubePlayerIntegration) || isMobile()) { $disableYoutubeIntegration = true; } $_GET['isEmbedded'] = ""; if (($disableYoutubeIntegration) || ((strpos($video['videoLink'], "youtu.be") == false) && (strpos($video['videoLink'], "youtube.com") == false) && (strpos($video['videoLink'], "vimeo.com") == false))) { $_GET['isEmbedded'] = "e"; $isVideoTypeEmbed = 1; $url = parseVideos($video['videoLink']); if ($config->getAutoplay()) { $url = addQueryStringParameter($url, 'autoplay', 1); } $htmlMediaTag = ""; $htmlMediaTag .= ''; $htmlMediaTag .= '
'; $htmlMediaTag .= ''; $htmlMediaTag .= ''; $htmlMediaTag .= '
'; } else { // youtube! if ((stripos($video['videoLink'], "youtube.com") != false) || (stripos($video['videoLink'], "youtu.be") != false)) { $_GET['isEmbedded'] = "y"; } else if ((stripos($video['videoLink'], "vimeo.com") != false)) { $_GET['isEmbedded'] = "v"; } $_GET['isMediaPlaySite'] = $video['id']; PlayerSkins::playerJSCodeOnLoad($video['id'], @$video['url']); $htmlMediaTag = ""; $htmlMediaTag .= ''; $htmlMediaTag .= ''; } } else if ($vType == 'serie') { $isVideoTypeEmbed = 1; $link = "{$global['webSiteRootURL']}plugin/PlayLists/embed.php"; $link = addQueryStringParameter($link, 'playlists_id', $video['serie_playlists_id']); $link = addQueryStringParameter($link, 'autoplay', $config->getAutoplay()); $link = addQueryStringParameter($link, 'playlist_index', @$_REQUEST['playlist_index']); $htmlMediaTag = ""; $htmlMediaTag .= ''; $htmlMediaTag .= ''; $htmlMediaTag .= ''; } $html .= "'; } $col1Classes = 'col-md-2 firstC'; $col2Classes = 'col-md-8 secC'; $col3Classes = 'col-md-2 thirdC'; if ($obj->playerFullHeight) { $col2Classes .= ' text-center playerFullHeight'; } $html .= '
' . $htmlMediaTag . '
'; $html .= showCloseButton() . '
'; return $html; } public function getHeadCode() { if (isWebRTC()) { return ''; } global $global, $config, $video; $obj = $this->getDataObject(); $css = ""; $js = ""; if (isLive()) { $js .= ""; } if (isVideo() || !empty($_GET['videoName']) || !empty($_GET['u']) || !empty($_GET['evideo']) || !empty($_GET['playlists_id'])) { if (!empty($_REQUEST['autoplay'])) { $js .= ""; } else if (self::isAutoplayEnabled()) { $js .= ""; } else { $js .= ""; } $js .= ""; if (!empty($obj->skin)) { $url = "plugin/PlayerSkins/skins/{$obj->skin}.css"; $css .= ""; } if ($obj->showLoopButton && isVideoPlayerHasProgressBar()) { $css .= ""; } $css .= ""; $css .= ""; if ($obj->showLogoOnEmbed && isEmbed() || $obj->showLogo) { $logo = "{$global['webSiteRootURL']}" . $config->getLogo(true); $css .= ""; } if ($obj->showShareSocial && CustomizeUser::canShareVideosFromVideo(@$video['id'])) { $css .= ""; } if ($obj->showShareAutoplay && isVideoPlayerHasProgressBar()) { $css .= ""; } } $url = urlencode(getSelfURI()); $oembed = ''; $oembed .= ''; return $js . $css . $oembed; } public function getFooterCode() { if (isWebRTC()) { return ''; } global $global, $config, $getStartPlayerJSWasRequested, $video, $url, $title; $js = ""; $obj = $this->getDataObject(); if (!empty($_GET['videoName']) || !empty($_GET['u']) || !empty($_GET['evideo']) || !empty($_GET['playlists_id'])) { if (empty($obj->showLoopButton) && empty($playerSkinsObj->contextMenuLoop)) { $js .= ""; } if ($obj->showLogoOnEmbed && isEmbed() || $obj->showLogo) { $title = $config->getWebSiteTitle(); $url = "{$global['webSiteRootURL']}{$config->getLogo(true)}"; $js .= ""; PlayerSkins::getStartPlayerJS(file_get_contents("{$global['systemRootPath']}plugin/PlayerSkins/logo.js")); //$js .= ""; } if ($obj->showShareSocial && CustomizeUser::canShareVideosFromVideo(@$video['id'])) { $social = getSocialModal(@$video['id'], @$url, @$title); PlayerSkins::getStartPlayerJS(file_get_contents("{$global['systemRootPath']}plugin/PlayerSkins/shareButton.js")); //$js .= ""; $js .= $social['html']; $js .= ""; } if ($obj->showShareAutoplay && isVideoPlayerHasProgressBar()) { PlayerSkins::getStartPlayerJS(file_get_contents("{$global['systemRootPath']}plugin/PlayerSkins/autoplayButton.js")); } } if (isAudio()) { $videos_id = getVideos_id(); $video = Video::getVideoLight($videos_id); $spectrumSource = Video::getSourceFile($video['filename'], "_spectrum.jpg"); if (!empty($spectrumSource["path"])) { $onPlayerReady = "startAudioSpectrumProgress('{$spectrumSource["url"]}');"; self::prepareStartPlayerJS($onPlayerReady); } } if (!empty($getStartPlayerJSWasRequested) || isVideo()) { $js .= ""; $js .= ""; } return $js; } static function getDataSetup($str = "") { global $video, $disableYoutubeIntegration, $global; $obj = AVideoPlugin::getObjectData('PlayerSkins'); $dataSetup = array(); $dataSetup[] = "errorDisplay: false"; if (isVideoPlayerHasProgressBar() && !empty($obj->playbackRates)) { $dataSetup[] = "'playbackRates':{$obj->playbackRates}"; } if (isVideoPlayerHasProgressBar() && (isset($_GET['isEmbedded'])) && ($disableYoutubeIntegration == false) && !empty($video['videoLink'])) { if ($_GET['isEmbedded'] == "y") { $dataSetup[] = "techOrder:[\"youtube\"]"; $dataSetup[] = "sources:[{type: \"video/youtube\", src: \"{$video['videoLink']}\"}]"; $dataSetup[] = "youtube:{customVars: {wmode: \"transparent\", origin: \"{$global['webSiteRootURL']}\"}}"; } else if ($_GET['isEmbedded'] == "v") { $dataSetup[] = "techOrder:[\"vimeo\"]"; $dataSetup[] = "sources:[{type: \"video/vimeo\", src: \"{$video['videoLink']}\"}]"; $dataSetup[] = "vimeo:{customVars: {wmode: \"transparent\", origin: \"{$global['webSiteRootURL']}\"}}"; } } $pluginsDataSetup = AVideoPlugin::dataSetup(); if (!empty($pluginsDataSetup)) { $dataSetup[] = $pluginsDataSetup; } if (!empty($dataSetup)) { return ",{" . implode(",", $dataSetup) . "{$str}{$obj->playerCustomDataSetup}}"; } return ""; } // this function was modified, maybe removed in the future static function getStartPlayerJS($onPlayerReady = "", $getDataSetup = "", $noReadyFunction = false) { global $prepareStartPlayerJS_onPlayerReady, $prepareStartPlayerJS_getDataSetup; global $getStartPlayerJSWasRequested; self::prepareStartPlayerJS($onPlayerReady, $getDataSetup); //var_dump('getStartPlayerJSWasRequested', debug_backtrace()); $getStartPlayerJSWasRequested = true; //return '/* getStartPlayerJS $prepareStartPlayerJS_onPlayerReady = "' . count($prepareStartPlayerJS_onPlayerReady) . '", $prepareStartPlayerJS_getDataSetup = "' . count($prepareStartPlayerJS_getDataSetup) . '", $onPlayerReady = "' . $onPlayerReady . '", $getDataSetup = "' . $getDataSetup . '" */'; return '/* getStartPlayerJS $prepareStartPlayerJS_onPlayerReady = "' . count($prepareStartPlayerJS_onPlayerReady) . '", $prepareStartPlayerJS_getDataSetup = "' . count($prepareStartPlayerJS_getDataSetup) . '" */'; } static function addOnPlayerReady($onPlayerReady) { return self::getStartPlayerJS($onPlayerReady); } static function getStartPlayerJSCode($noReadyFunction = false, $currentTime = 0) { if (isWebRTC()) { return ''; } global $config, $global, $prepareStartPlayerJS_onPlayerReady, $prepareStartPlayerJS_getDataSetup, $IMAADTag; $obj = AVideoPlugin::getObjectData('PlayerSkins'); $js = ""; if (empty($currentTime) && isVideoPlayerHasProgressBar()) { $currentTime = self::getCurrentTime(); } if (!empty($global['doNotLoadPlayer'])) { return ''; } if (empty($prepareStartPlayerJS_onPlayerReady)) { $prepareStartPlayerJS_onPlayerReady = array(); } if (empty($prepareStartPlayerJS_getDataSetup)) { $prepareStartPlayerJS_getDataSetup = array(); } if (empty($noReadyFunction)) { $js .= "var originalVideo; var adTagOptions; var _adTagUrl = '{$IMAADTag}'; var player; " . "$(document).ready(function () {"; } $js .= " originalVideo = $('#mainVideo').clone(); /* prepareStartPlayerJS_onPlayerReady = " . count($prepareStartPlayerJS_onPlayerReady) . ", prepareStartPlayerJS_getDataSetup = " . count($prepareStartPlayerJS_getDataSetup) . " */ if (typeof player === 'undefined') { player = videojs('mainVideo'" . (self::getDataSetup(implode(" ", $prepareStartPlayerJS_getDataSetup))) . "); "; if (!empty($IMAADTag) && isVideoPlayerHasProgressBar()) { $js .= "adTagOptions = {id: 'mainVideo', adTagUrl: '{$IMAADTag}', autoPlayAdBreaks:false}; player.ima(adTagOptions);"; $js .= "setInterval(function(){ fixAdSize(); }, 300); // first time it's clicked. var startEvent = 'click';"; if (isMobile()) { $js .= "// Remove controls from the player on iPad to stop native controls from stealing // our click var contentPlayer = document.getElementById('content_video_html5_api'); if (contentPlayer && (navigator.userAgent.match(/iPad/i) || navigator.userAgent.match(/Android/i)) && contentPlayer.hasAttribute('controls')) { contentPlayer.removeAttribute('controls'); } // Initialize the ad container when the video player is clicked, but only the if (navigator.userAgent.match(/iPhone/i) || navigator.userAgent.match(/iPad/i) || navigator.userAgent.match(/Android/i)) { startEvent = 'touchend'; }"; } $js .= " player.on('adsready', function () { console.log('reloadAds adIsReady '); player.ima.setAdBreakReadyListener(function() {console.log('Ads playAdBreak()');player.ima.playAdBreak();}); });player.on('ads-ad-started', function () { console.log('ads-ad-started'); });player.on('ads-manager', function (a) { console.log('ads-manager', a); });player.on('ads-manager', function (a) { console.log('ads-loader', a); });player.on('ads-manager', function (a) { console.log('ads-request', a); });player.one(startEvent, function () {player.ima.initializeAdDisplayContainer();});"; } $js .= "} player.ready(function () {"; $js .= "var err = this.error(); if (err && err.code) { $('.vjs-error-display').hide(); $('#mainVideo').find('.vjs-poster').css({'background-image': 'url({$global['webSiteRootURL']}plugin/Live/view/Offline.jpg)'}); } " . implode(PHP_EOL, $prepareStartPlayerJS_onPlayerReady) . " playerPlayIfAutoPlay({$currentTime}); }); player.persistvolume({ namespace: 'AVideo' });"; if ($obj->showLoopButton && isVideoPlayerHasProgressBar()) { $js .= file_get_contents($global['systemRootPath'] . 'plugin/PlayerSkins/loopbutton.js'); } $js .= file_get_contents($global['systemRootPath'] . 'plugin/PlayerSkins/fixCurrentSources.js'); if (empty($noReadyFunction)) { $js .= "});"; } //var_dump('getStartPlayerJSWasRequested', debug_backtrace()); $getStartPlayerJSWasRequested = true; return $js; } static private function getCurrentTime() { $currentTime = 0; if (isset($_GET['t'])) { $currentTime = intval($_GET['t']); } else { $videos_id = getVideos_id(); if (!empty($videos_id)) { $video = Video::getVideoLight($videos_id); $progress = Video::getVideoPogressPercent($videos_id); if (!empty($progress) && !empty($progress['lastVideoTime'])) { $currentTime = intval($progress['lastVideoTime']); } else if (!empty($video['externalOptions'])) { $json = _json_decode($video['externalOptions']); if (!empty($json->videoStartSeconds)) { $currentTime = intval(parseDurationToSeconds($json->videoStartSeconds)); } else { $currentTime = 0; } } $maxCurrentTime = parseDurationToSeconds($video['duration']); if ($maxCurrentTime <= $currentTime + 5) { $currentTime = 0; } } } return $currentTime; } static function setIMAADTag($tag) { global $IMAADTag; $IMAADTag = $tag; } static function playerJSCodeOnLoad($videos_id, $nextURL = "") { $js = ""; $videos_id = intval($videos_id); if (empty($videos_id)) { return false; } $video = new Video("", "", $videos_id); if (!empty($video) && empty($nextURL)) { if (!empty($video->getNext_videos_id())) { $next_video = Video::getVideo($video->getNext_videos_id()); if (!empty($next_video['id'])) { $nextURL = Video::getURLFriendly($next_video['id'], isEmbed()); } } else { $catName = @$_GET['catName']; $cat = new Category($video->getCategories_id()); $_GET['catName'] = $cat->getClean_name(); $next_video = Video::getVideo('', 'viewable', false, true); $_GET['catName'] = $catName; if (!empty($next_video['id'])) { $nextURL = Video::getURLFriendly($next_video['id'], isEmbed()); } } } $url = Video::getURLFriendly($videos_id); $js .= " player.on('play', function () { addView({$videos_id}, this.currentTime()); _addViewBeaconAdded = false; }); player.on('timeupdate', function () { var time = Math.round(this.currentTime()); playerCurrentTime = time; var url = '{$url}'; if (url.indexOf('?') > -1) { url += '&t=' + time; } else { url += '?t=' + time; } $('#linkCurrentTime, .linkCurrentTime').val(url); if (time >= 5 && time % 5 === 0) { addView({$videos_id}, time); } }); player.on('ended', function () { var time = Math.round(this.currentTime()); addView({$videos_id}, time); });"; if (!empty($nextURL)) { $js .= "playNextURL = '{$nextURL}';"; $js .= "player.on('ended', function () {setTimeout(function(){if(playNextURL){playNext(playNextURL);}},playerHasAds()?10000:500);});"; } self::getStartPlayerJS($js); return true; } static private function prepareStartPlayerJS($onPlayerReady = "", $getDataSetup = "") { global $prepareStartPlayerJS_onPlayerReady, $prepareStartPlayerJS_getDataSetup; if (empty($prepareStartPlayerJS_onPlayerReady)) { $prepareStartPlayerJS_onPlayerReady = array(); } if (empty($prepareStartPlayerJS_getDataSetup)) { $prepareStartPlayerJS_getDataSetup = array(); } if (!empty($onPlayerReady)) { $prepareStartPlayerJS_onPlayerReady[] = $onPlayerReady; } if (!empty($getDataSetup)) { $prepareStartPlayerJS_getDataSetup[] = $getDataSetup; } } static function isAutoplayEnabled() { global $config; if (isLive()) { return true; } if (!empty($_COOKIE['autoplay'])) { if (strtolower($_COOKIE['autoplay']) === 'false') { return false; } else { return true; } } return $config->getAutoplay(); } public static function getVideoTags($videos_id) { if (empty($videos_id)) { return array(); } $name = "PlayeSkins_getVideoTags{$videos_id}"; $tags = ObjectYPT::getCache($name, 0); if (empty($tags)) { //_error_log("Cache not found $name"); $video = new Video("", "", $videos_id); $fileName = $video->getFilename(); $resolution = Video::getHigestResolution($fileName); $obj = new stdClass(); if (empty($resolution) || empty($resolution['resolution_text'])) { $obj->label = ''; $obj->type = ""; $obj->text = ""; } else { $obj->label = 'Plugin'; $obj->type = "danger"; $obj->text = $resolution['resolution_text']; $obj->tooltip = $resolution['resolution'] . 'p'; } $tags = $obj; ObjectYPT::setCache($name, $tags); } return array($tags); } } diff --git a/view/managerVideos_body.php b/view/managerVideos_body.php index 52aa13af2..57c417975 100644 --- a/view/managerVideos_body.php +++ b/view/managerVideos_body.php @@ -1,2217 +1,2227 @@
doNotShowEncoderButton)) { if (!empty($config->getEncoderURL())) { } ?>
doNotShowUploadMP4Button)) { ?> doNotShowEmbedButton)) { ?>
$secondsTotal) { $percent = intval($secondsTotal / $secondsLimit * 100); } else { $percent = 100; } ?> and you have minutes of storage
% of your storage limit used
getDisable_youtubeupload()) { ?> userCanNotChangeCategory) || User::isAdmin()) { ?> userCanNotChangeUserGroup) || User::isAdmin()) { ?> disableVideoSwap) && (empty($advancedCustom->makeSwapVideosOnlyForAdmin) || User::isAdmin())) { ?>
+
+ '); ?> + '); ?> '); ?> '); ?> '); ?>
disableDownloadVideosList)) { ?> getDisable_youtubeupload())) { ?>

:

  1. " . __("Google ID and Key") . ""; ?>
  2. " . __("YouTube Data API") . " v3"; ?>
  3. : objects/youtubeUpload.json.php
  4. :
disableHTMLDescription)) { echo getTinyMCE("inputDescription"); } ?> diff --git a/view/videoEmbeded.php b/view/videoEmbeded.php index a875ba7b8..d0cbd547b 100644 --- a/view/videoEmbeded.php +++ b/view/videoEmbeded.php @@ -1,600 +1,587 @@ thumbnails; $poster = $evideo->thumbnails; $imgw = 1280; $imgh = 720; $autoPlaySources = array(); $autoPlayURL = ''; $autoPlayPoster = ''; $autoPlayThumbsSprit = ''; } else if (!empty($_GET['v'])) { $video = Video::getVideo($_GET['v'], "", true, false, false, true); //$video['id'] = $_GET['v']; } else if (!empty($_GET['videoName'])) { $video = Video::getVideoFromCleanTitle($_GET['videoName']); } Video::unsetAddView($video['id']); AVideoPlugin::getEmbed($video['id']); if (empty($video)) { forbiddenPage("Video not found"); } if (empty($video['users_id'])) { $video['users_id'] = User::getId(); } if (empty($customizedAdvanced)) { $customizedAdvanced = AVideoPlugin::getObjectDataIfEnabled('CustomizeAdvanced'); } if (!isSameDomain(@$_SERVER['HTTP_REFERER'], $global['webSiteRootURL']) && !isAVideoMobileApp()) { if (!empty($advancedCustomUser->blockEmbedFromSharedVideos) && !CustomizeUser::canShareVideosFromVideo($video['id'])) { if (!empty($advancedCustomUser->blockEmbedFromSharedVideos)) { error_log("Embed is forbidden: \$advancedCustomUser->blockEmbedFromSharedVideos"); } if (!CustomizeUser::canShareVideosFromVideo($video['id'])) { error_log("Embed is forbidden: !CustomizeUser::canShareVideosFromVideo(\$video['id'])"); } forbiddenPage("Embed is forbidden"); } } $source = array(); $img = ""; $imgw = 1280; $imgh = 720; if ($video['type'] !== "pdf") { if (!empty($video['filename'])) { $source = Video::getSourceFile($video['filename']); $poster = $img = $source['url']; $data = getimgsize($source['path']); $imgw = $data[0]; $imgh = $data[1]; } } if (empty($poster)) { $poster = ""; if (!empty($video['filename'])) { $images = Video::getImageFromFilename($video['filename']); $poster = $images->poster; if (!empty($images->posterPortrait)) { $img = $images->posterPortrait; $data = getimgsize($source['path']); $imgw = $data[0]; $imgh = $data[1]; } } else { $images = array(); $poster = ""; $imgw = 0; $imgh = 0; } if (empty($poster) && !empty($video['filename'])) { if (($video['type'] !== "audio") && ($video['type'] !== "linkAudio")) { $poster = "{$global['webSiteRootURL']}videos/{$video['filename']}.jpg"; } else { $poster = "" . getCDN() . "view/img/audio_wave.jpg"; } } } require_once $global['systemRootPath'] . 'plugin/AVideoPlugin.php'; /* * Swap aspect ratio for rotated (vvs) videos if ($video['rotation'] === "90" || $video['rotation'] === "270") { $embedResponsiveClass = "embed-responsive-9by16"; $vjsClass = "vjs-9-16"; } else { $embedResponsiveClass = "embed-responsive-16by9"; $vjsClass = "vjs-16-9"; } */ $vjsClass = ""; $obj = new Video("", "", $video['id']); $resp = $obj->addView(); //https://.../vEmbed/527?modestbranding=1&showinfo=0&autoplay=1&controls=0&loop=1&mute=1&t=0 $modestbranding = false; $autoplay = false; $controls = "controls"; $showOnlyBasicControls = false; $loop = ""; $mute = ""; $objectFit = ""; $t = 0; if (isset($_GET['modestbranding']) && $_GET['modestbranding'] == "1") { $modestbranding = true; } if (!empty($_GET['autoplay']) || $config->getAutoplay()) { $autoplay = true; } if (isset($_GET['controls'])) { if ($_GET['controls'] == "0") { $controls = ""; } else if ($_GET['controls'] == "-1") { $showOnlyBasicControls = true; } else if ($_GET['controls'] == "-2") { $showOnlyBasicControls = true; $hideProgressBarAndUnPause = true; } } if (!empty($_GET['loop'])) { $loop = "loop"; } if (!empty($_GET['mute'])) { $mute = 'muted="muted"'; } if (!empty($_GET['objectFit']) && (intval($_GET['objectFit']) == 1 || $_GET['objectFit'] == 'true')) { $objectFit = 'object-fit: ' . $_GET['objectFit']; } if (!empty($_GET['t'])) { $t = intval($_GET['t']); } else if (!empty($video['progress']['lastVideoTime'])) { $t = intval($video['progress']['lastVideoTime']); } else if (!empty($video['externalOptions']->videoStartSeconds)) { $t = parseDurationToSeconds($video['externalOptions']->videoStartSeconds); } $playerSkinsO = AVideoPlugin::getObjectData("PlayerSkins"); $disableEmbedTopInfo = $playerSkinsO->disableEmbedTopInfo; if (isset($_REQUEST['showinfo']) && empty($_REQUEST['showinfo'])) { $disableEmbedTopInfo = true; $modestbranding = true; } $url = Video::getLink($video['id'], $video['clean_title'], false); $title = str_replace('"', '', $video['title']) . ' - ' . $config->getWebSiteTitle(); $photo = User::getPhoto($video['users_id']); if (empty($currentTime)) { $currentTime = 0; } if (User::hasBlockedUser($video['users_id'])) { $disableEmbedTopInfo = true; $video['type'] = "blockedUser"; } ?> <?php echo $video['title'] . $config->getPageTitleSeparator() . $config->getWebSiteTitle(); ?>


You've blocked user ()
You won't see any comments or videos from this user


" class="img img-responsive" style="height: 100%;" >
    open($sources['zip']["path"]); for ($i = 0; $i < $za->numFiles; $i++) { $stat = $za->statIndex($i); $fname = basename($stat['name']); ?>