2012-07-18 03:07:57 +02:00
|
|
|
<?php
|
|
|
|
|
2012-08-21 22:54:14 +02:00
|
|
|
class Application_Model_Webstream implements Application_Model_LibraryEditable
|
|
|
|
{
|
2012-07-31 03:48:04 +02:00
|
|
|
private $id;
|
|
|
|
|
2012-08-10 18:40:28 +02:00
|
|
|
public function __construct($webstream)
|
2012-07-31 03:48:04 +02:00
|
|
|
{
|
2022-03-14 11:15:04 +01:00
|
|
|
// TODO: hacky...
|
2012-08-22 00:55:38 +02:00
|
|
|
if (is_int($webstream)) {
|
|
|
|
$this->webstream = CcWebstreamQuery::create()->findPK($webstream);
|
2012-08-22 20:04:01 +02:00
|
|
|
if (is_null($this->webstream)) {
|
|
|
|
throw new Exception();
|
|
|
|
}
|
2012-08-22 00:55:38 +02:00
|
|
|
} else {
|
2012-08-29 16:58:03 +02:00
|
|
|
$this->webstream = $webstream;
|
2012-08-22 00:55:38 +02:00
|
|
|
}
|
2012-07-31 03:48:04 +02:00
|
|
|
}
|
|
|
|
|
2012-08-10 06:57:03 +02:00
|
|
|
public function getOrm()
|
|
|
|
{
|
|
|
|
return $this->webstream;
|
|
|
|
}
|
|
|
|
|
2012-08-03 21:59:34 +02:00
|
|
|
public function getName()
|
2012-07-26 00:41:52 +02:00
|
|
|
{
|
2012-08-03 21:59:34 +02:00
|
|
|
return $this->webstream->getDbName();
|
2012-07-18 03:07:57 +02:00
|
|
|
}
|
|
|
|
|
2012-08-03 21:59:34 +02:00
|
|
|
public function getId()
|
2012-07-26 00:41:52 +02:00
|
|
|
{
|
2012-08-03 21:59:34 +02:00
|
|
|
return $this->webstream->getDbId();
|
2012-07-18 03:07:57 +02:00
|
|
|
}
|
|
|
|
|
2012-09-14 20:51:50 +02:00
|
|
|
public function getCreatorId()
|
|
|
|
{
|
2012-12-03 17:06:56 +01:00
|
|
|
return $this->webstream->getDbCreatorId();
|
2012-09-14 20:51:50 +02:00
|
|
|
}
|
|
|
|
|
2012-08-03 21:59:34 +02:00
|
|
|
public function getLastModified($p_type)
|
2012-07-26 00:41:52 +02:00
|
|
|
{
|
2012-09-18 18:40:44 +02:00
|
|
|
return $this->webstream->getDbMtime();
|
2012-07-18 03:07:57 +02:00
|
|
|
}
|
|
|
|
|
2012-08-03 21:59:34 +02:00
|
|
|
public function getDefaultLength()
|
|
|
|
{
|
2012-08-03 22:18:45 +02:00
|
|
|
$dateString = $this->webstream->getDbLength();
|
2021-10-11 16:10:47 +02:00
|
|
|
$arr = explode(':', $dateString);
|
2012-08-03 22:18:45 +02:00
|
|
|
if (count($arr) == 3) {
|
Feature: Support php7.4 (#1354)
* Run CI tests against php 7.4
* Sort composer dependencies
* Remove unused Aws S3 php library
* Pin simplepie dependency to ^1.5
* Pin getid3 dependency to ^1.9
* Pin composer semver to ^3.2
* Pin php-amqplib to ^2.12
* Drop sentry logging support
* Update composer dependencies
* Move propel regenerate to Makefile
* Regenerate propel files with v1.7.0
* Pin propel orm to ^1.7
* Regenerate propel files with v1.7.2
* fix: generator_version in airtime-conf-production.php
* Replace propel/propel1 with jooola/propel1
* Regenerate propel files with v1.7.3-dev
* Fix php7.4 compatibility
Using php-cs-fixer:
'@PhpCsFixer' => true,
'concat_space' => ['spacing' => 'one'],
'ordered_class_elements' => false,
'yoda_style' => false,
'@PHP74Migration' => true,
'assign_null_coalescing_to_coalesce_equal' => false,
'ternary_to_null_coalescing' => false,
'heredoc_indentation' => false,
'@PHP74Migration:risky' => true,
'declare_strict_types' => false,
'void_return' => false,
'use_arrow_functions' => false,
* Fix pre-commit
2021-10-17 17:19:53 +02:00
|
|
|
[$hours, $min, $sec] = $arr;
|
2012-08-03 22:18:45 +02:00
|
|
|
$di = new DateInterval("PT{$hours}H{$min}M{$sec}S");
|
2012-08-29 16:58:03 +02:00
|
|
|
|
2021-10-11 16:10:47 +02:00
|
|
|
return $di->format('%Hh %Im');
|
2012-12-03 17:06:56 +01:00
|
|
|
}
|
2012-08-29 16:58:03 +02:00
|
|
|
|
2021-10-11 16:10:47 +02:00
|
|
|
return '';
|
2012-08-03 21:59:34 +02:00
|
|
|
}
|
|
|
|
|
2012-08-22 00:55:38 +02:00
|
|
|
public function getLength()
|
|
|
|
{
|
|
|
|
return $this->getDefaultLength();
|
|
|
|
}
|
|
|
|
|
2012-08-03 21:59:34 +02:00
|
|
|
public function getDescription()
|
2012-07-26 00:41:52 +02:00
|
|
|
{
|
2012-08-03 21:59:34 +02:00
|
|
|
return $this->webstream->getDbDescription();
|
2012-07-18 03:07:57 +02:00
|
|
|
}
|
|
|
|
|
2012-08-03 21:59:34 +02:00
|
|
|
public function getUrl()
|
2012-07-26 00:41:52 +02:00
|
|
|
{
|
2012-08-03 21:59:34 +02:00
|
|
|
return $this->webstream->getDbUrl();
|
2012-07-18 03:07:57 +02:00
|
|
|
}
|
2012-07-19 00:27:39 +02:00
|
|
|
|
2012-07-31 03:48:04 +02:00
|
|
|
public function getMetadata()
|
|
|
|
{
|
2012-08-10 20:37:32 +02:00
|
|
|
$subjs = CcSubjsQuery::create()->findPK($this->webstream->getDbCreatorId());
|
2012-07-31 03:48:04 +02:00
|
|
|
|
|
|
|
$username = $subjs->getDbLogin();
|
2012-08-29 16:58:03 +02:00
|
|
|
|
2021-10-11 16:10:47 +02:00
|
|
|
return [
|
|
|
|
'name' => $this->webstream->getDbName(),
|
|
|
|
'length' => $this->webstream->getDbLength(),
|
|
|
|
'description' => $this->webstream->getDbDescription(),
|
|
|
|
'login' => $username,
|
|
|
|
'url' => $this->webstream->getDbUrl(),
|
|
|
|
];
|
2012-07-31 03:48:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public static function deleteStreams($p_ids, $p_userId)
|
|
|
|
{
|
2015-01-21 17:31:28 +01:00
|
|
|
$userInfo = Zend_Auth::getInstance()->getStorage()->read();
|
|
|
|
$user = new Application_Model_User($userInfo->id);
|
2021-10-11 16:10:47 +02:00
|
|
|
$isAdminOrPM = $user->isUserType([UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER]);
|
|
|
|
|
2015-01-21 17:31:28 +01:00
|
|
|
if (!$isAdminOrPM) {
|
2022-03-14 11:15:04 +01:00
|
|
|
// Make sure the user has ownership of ALL the selected webstreams before
|
2015-01-21 17:31:28 +01:00
|
|
|
$leftOver = self::streamsNotOwnedByUser($p_ids, $p_userId);
|
|
|
|
if (count($leftOver) == 0) {
|
|
|
|
CcWebstreamQuery::create()->findPKs($p_ids)->delete();
|
|
|
|
} else {
|
2021-10-11 16:10:47 +02:00
|
|
|
throw new WebstreamNoPermissionException();
|
2015-01-21 17:31:28 +01:00
|
|
|
}
|
2012-07-31 03:48:04 +02:00
|
|
|
} else {
|
2015-01-21 17:31:28 +01:00
|
|
|
CcWebstreamQuery::create()->findPKs($p_ids)->delete();
|
2012-07-31 03:48:04 +02:00
|
|
|
}
|
|
|
|
}
|
2012-08-29 16:58:03 +02:00
|
|
|
|
2012-07-31 03:48:04 +02:00
|
|
|
// This function returns that are not owen by $p_user_id among $p_ids
|
|
|
|
private static function streamsNotOwnedByUser($p_ids, $p_userId)
|
|
|
|
{
|
|
|
|
$ownedByUser = CcWebstreamQuery::create()->filterByDbCreatorId($p_userId)->find()->getData();
|
2021-10-11 16:10:47 +02:00
|
|
|
$ownedStreams = [];
|
2012-07-31 03:48:04 +02:00
|
|
|
foreach ($ownedByUser as $pl) {
|
|
|
|
if (in_array($pl->getDbId(), $p_ids)) {
|
|
|
|
$ownedStreams[] = $pl->getDbId();
|
|
|
|
}
|
|
|
|
}
|
2012-08-29 16:58:03 +02:00
|
|
|
|
2021-10-11 16:10:47 +02:00
|
|
|
return array_diff($p_ids, $ownedStreams);
|
2012-07-31 03:48:04 +02:00
|
|
|
}
|
2012-08-02 21:45:15 +02:00
|
|
|
|
2012-08-10 18:40:28 +02:00
|
|
|
public static function analyzeFormData($parameters)
|
2012-08-02 21:45:15 +02:00
|
|
|
{
|
2022-07-07 20:01:15 +02:00
|
|
|
$valid = [
|
|
|
|
'length' => [true, ''],
|
2021-10-11 16:10:47 +02:00
|
|
|
'url' => [true, ''],
|
2022-07-07 20:01:15 +02:00
|
|
|
'name' => [true, ''],
|
|
|
|
];
|
2012-08-02 21:45:15 +02:00
|
|
|
|
2012-08-13 21:26:32 +02:00
|
|
|
$di = null;
|
2021-10-11 16:10:47 +02:00
|
|
|
$length = $parameters['length'];
|
2021-10-12 11:09:46 +02:00
|
|
|
$result = preg_match('/^(?:([0-9]{1,2})h)?\s*(?:([0-9]{1,2})m)?$/', $length, $matches);
|
2012-08-28 18:30:33 +02:00
|
|
|
|
|
|
|
$invalid_date_interval = false;
|
|
|
|
if ($result == 1 && count($matches) == 2) {
|
|
|
|
$hours = $matches[1];
|
|
|
|
$minutes = 0;
|
2012-08-29 16:58:03 +02:00
|
|
|
} elseif ($result == 1 && count($matches) == 3) {
|
2012-08-13 21:26:32 +02:00
|
|
|
$hours = $matches[1];
|
|
|
|
$minutes = $matches[2];
|
2012-08-28 18:30:33 +02:00
|
|
|
} else {
|
|
|
|
$invalid_date_interval = true;
|
|
|
|
}
|
|
|
|
|
2012-08-29 16:58:03 +02:00
|
|
|
if (!$invalid_date_interval) {
|
2022-03-14 11:15:04 +01:00
|
|
|
// Due to the way our Regular Expression is set up, we could have $minutes or $hours
|
|
|
|
// not set. Do simple test here
|
2012-08-28 18:30:33 +02:00
|
|
|
if (!is_numeric($hours)) {
|
|
|
|
$hours = 0;
|
|
|
|
}
|
|
|
|
if (!is_numeric($minutes)) {
|
|
|
|
$minutes = 0;
|
|
|
|
}
|
|
|
|
|
2022-03-14 11:15:04 +01:00
|
|
|
// minutes cannot be over 59. Need to convert anything > 59 minutes into hours.
|
2021-10-11 16:10:47 +02:00
|
|
|
$hours += intval($minutes / 60);
|
2023-09-17 17:14:59 +02:00
|
|
|
$minutes %= 60;
|
2012-08-28 23:22:48 +02:00
|
|
|
|
2012-08-13 21:26:32 +02:00
|
|
|
$di = new DateInterval("PT{$hours}H{$minutes}M");
|
|
|
|
|
|
|
|
$totalMinutes = $di->h * 60 + $di->i;
|
|
|
|
|
|
|
|
if ($totalMinutes == 0) {
|
|
|
|
$valid['length'][0] = false;
|
2012-11-15 21:52:51 +01:00
|
|
|
$valid['length'][1] = _('Length needs to be greater than 0 minutes');
|
2012-08-13 21:26:32 +02:00
|
|
|
}
|
|
|
|
} else {
|
2012-08-02 21:45:15 +02:00
|
|
|
$valid['length'][0] = false;
|
2012-11-15 21:52:51 +01:00
|
|
|
$valid['length'][1] = _('Length should be of form "00h 00m"');
|
2012-08-02 21:45:15 +02:00
|
|
|
}
|
|
|
|
|
2021-10-11 16:10:47 +02:00
|
|
|
$url = $parameters['url'];
|
2022-03-14 11:15:04 +01:00
|
|
|
// simple validator that checks to make sure that the url starts with
|
|
|
|
// http(s),
|
|
|
|
// and that the domain is at least 1 letter long
|
2021-10-12 11:09:46 +02:00
|
|
|
$result = preg_match('/^(http|https):\/\/.+/', $url, $matches);
|
2012-08-02 21:45:15 +02:00
|
|
|
|
2012-08-13 21:26:32 +02:00
|
|
|
$mime = null;
|
2012-08-28 23:03:20 +02:00
|
|
|
$mediaUrl = null;
|
2012-08-02 21:45:15 +02:00
|
|
|
if ($result == 0) {
|
|
|
|
$valid['url'][0] = false;
|
2022-09-21 00:44:42 +02:00
|
|
|
$valid['url'][1] = _('URL should be of form "https://example.org"');
|
2012-09-04 22:15:07 +02:00
|
|
|
} elseif (strlen($url) > 512) {
|
|
|
|
$valid['url'][0] = false;
|
2012-11-15 21:52:51 +01:00
|
|
|
$valid['url'][1] = _('URL should be 512 characters or less');
|
2012-08-13 18:59:26 +02:00
|
|
|
} else {
|
|
|
|
try {
|
Feature: Support php7.4 (#1354)
* Run CI tests against php 7.4
* Sort composer dependencies
* Remove unused Aws S3 php library
* Pin simplepie dependency to ^1.5
* Pin getid3 dependency to ^1.9
* Pin composer semver to ^3.2
* Pin php-amqplib to ^2.12
* Drop sentry logging support
* Update composer dependencies
* Move propel regenerate to Makefile
* Regenerate propel files with v1.7.0
* Pin propel orm to ^1.7
* Regenerate propel files with v1.7.2
* fix: generator_version in airtime-conf-production.php
* Replace propel/propel1 with jooola/propel1
* Regenerate propel files with v1.7.3-dev
* Fix php7.4 compatibility
Using php-cs-fixer:
'@PhpCsFixer' => true,
'concat_space' => ['spacing' => 'one'],
'ordered_class_elements' => false,
'yoda_style' => false,
'@PHP74Migration' => true,
'assign_null_coalescing_to_coalesce_equal' => false,
'ternary_to_null_coalescing' => false,
'heredoc_indentation' => false,
'@PHP74Migration:risky' => true,
'declare_strict_types' => false,
'void_return' => false,
'use_arrow_functions' => false,
* Fix pre-commit
2021-10-17 17:19:53 +02:00
|
|
|
[$mime, $content_length_found] = self::discoverStreamMime($url);
|
2012-08-25 01:25:19 +02:00
|
|
|
if (is_null($mime)) {
|
2021-10-11 16:10:47 +02:00
|
|
|
throw new Exception(_('No MIME type found for webstream.'));
|
2012-08-25 01:25:19 +02:00
|
|
|
}
|
|
|
|
$mediaUrl = self::getMediaUrl($url, $mime, $content_length_found);
|
|
|
|
|
2021-10-12 11:09:46 +02:00
|
|
|
if (preg_match('/(x-mpegurl)|(xspf\+xml)|(pls\+xml)|(x-scpls)/', $mime)) {
|
Feature: Support php7.4 (#1354)
* Run CI tests against php 7.4
* Sort composer dependencies
* Remove unused Aws S3 php library
* Pin simplepie dependency to ^1.5
* Pin getid3 dependency to ^1.9
* Pin composer semver to ^3.2
* Pin php-amqplib to ^2.12
* Drop sentry logging support
* Update composer dependencies
* Move propel regenerate to Makefile
* Regenerate propel files with v1.7.0
* Pin propel orm to ^1.7
* Regenerate propel files with v1.7.2
* fix: generator_version in airtime-conf-production.php
* Replace propel/propel1 with jooola/propel1
* Regenerate propel files with v1.7.3-dev
* Fix php7.4 compatibility
Using php-cs-fixer:
'@PhpCsFixer' => true,
'concat_space' => ['spacing' => 'one'],
'ordered_class_elements' => false,
'yoda_style' => false,
'@PHP74Migration' => true,
'assign_null_coalescing_to_coalesce_equal' => false,
'ternary_to_null_coalescing' => false,
'heredoc_indentation' => false,
'@PHP74Migration:risky' => true,
'declare_strict_types' => false,
'void_return' => false,
'use_arrow_functions' => false,
* Fix pre-commit
2021-10-17 17:19:53 +02:00
|
|
|
[$mime, $content_length_found] = self::discoverStreamMime($mediaUrl);
|
2012-08-25 01:25:19 +02:00
|
|
|
}
|
2012-08-13 18:59:26 +02:00
|
|
|
} catch (Exception $e) {
|
|
|
|
$valid['url'][0] = false;
|
|
|
|
$valid['url'][1] = $e->getMessage();
|
|
|
|
}
|
|
|
|
}
|
2012-08-02 21:45:15 +02:00
|
|
|
|
2021-10-11 16:10:47 +02:00
|
|
|
$name = $parameters['name'];
|
2012-08-02 21:45:15 +02:00
|
|
|
if (strlen($name) == 0) {
|
|
|
|
$valid['name'][0] = false;
|
2012-11-15 21:52:51 +01:00
|
|
|
$valid['name'][1] = _('Webstream name cannot be empty');
|
2012-08-02 21:45:15 +02:00
|
|
|
}
|
|
|
|
|
2021-10-11 16:10:47 +02:00
|
|
|
$id = $parameters['id'];
|
2012-08-03 21:59:34 +02:00
|
|
|
|
2021-10-11 16:10:47 +02:00
|
|
|
return [$valid, $mime, $mediaUrl, $di];
|
2012-08-02 21:45:15 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public static function isValid($analysis)
|
|
|
|
{
|
|
|
|
foreach ($analysis as $k => $v) {
|
2012-08-10 06:57:03 +02:00
|
|
|
if ($v[0] === false) {
|
2012-08-02 21:45:15 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2021-10-11 16:10:47 +02:00
|
|
|
|
2012-08-02 21:45:15 +02:00
|
|
|
return true;
|
|
|
|
}
|
2012-07-31 03:48:04 +02:00
|
|
|
|
2012-09-18 18:40:44 +02:00
|
|
|
// TODO : Fix this interface
|
2022-03-14 11:15:04 +01:00
|
|
|
// This function should not be defined in the interface.
|
2012-08-29 16:58:03 +02:00
|
|
|
public function setMetadata($key, $val)
|
2012-08-21 22:54:14 +02:00
|
|
|
{
|
2021-10-11 16:10:47 +02:00
|
|
|
throw new Exception('Not implemented.');
|
2012-08-21 22:54:14 +02:00
|
|
|
}
|
|
|
|
|
2012-08-29 16:58:03 +02:00
|
|
|
public function setName($name)
|
2012-08-21 22:54:14 +02:00
|
|
|
{
|
2012-09-18 18:40:44 +02:00
|
|
|
$this->webstream->setDbName($name);
|
2012-08-25 01:25:19 +02:00
|
|
|
}
|
2021-10-11 16:10:47 +02:00
|
|
|
|
2012-09-11 00:07:12 +02:00
|
|
|
public function setLastPlayed($timestamp)
|
2012-09-11 00:01:36 +02:00
|
|
|
{
|
|
|
|
$this->webstream->setDbLPtime($timestamp);
|
|
|
|
$this->webstream->save();
|
|
|
|
}
|
2012-08-25 01:25:19 +02:00
|
|
|
|
2012-09-10 18:18:19 +02:00
|
|
|
private static function getUrlData($url)
|
2012-08-25 01:25:19 +02:00
|
|
|
{
|
|
|
|
$ch = curl_init();
|
|
|
|
curl_setopt($ch, CURLOPT_URL, $url);
|
|
|
|
curl_setopt($ch, CURLOPT_HEADER, 0);
|
|
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
|
|
|
|
|
|
|
// grab URL and pass it to the browser
|
2022-03-14 11:15:04 +01:00
|
|
|
// TODO: What if invalid url?
|
2012-08-25 01:25:19 +02:00
|
|
|
$content = curl_exec($ch);
|
|
|
|
|
|
|
|
// close cURL resource, and free up system resources
|
|
|
|
curl_close($ch);
|
2021-10-11 16:10:47 +02:00
|
|
|
|
2012-09-10 18:18:19 +02:00
|
|
|
return $content;
|
|
|
|
}
|
|
|
|
|
|
|
|
private static function getXspfUrl($url)
|
|
|
|
{
|
2012-09-11 00:01:36 +02:00
|
|
|
$content = self::getUrlData($url);
|
2012-08-25 01:25:19 +02:00
|
|
|
|
2021-10-11 16:10:47 +02:00
|
|
|
$dom = new DOMDocument();
|
2022-03-14 11:15:04 +01:00
|
|
|
// TODO: What if invalid xml?
|
2012-08-25 01:25:19 +02:00
|
|
|
$dom->loadXML($content);
|
|
|
|
$tracks = $dom->getElementsByTagName('track');
|
|
|
|
|
|
|
|
foreach ($tracks as $track) {
|
|
|
|
$locations = $track->getElementsByTagName('location');
|
|
|
|
foreach ($locations as $loc) {
|
|
|
|
return $loc->nodeValue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-11 16:10:47 +02:00
|
|
|
throw new Exception(_('Could not parse XSPF playlist'));
|
2012-08-25 01:25:19 +02:00
|
|
|
}
|
2021-10-11 16:10:47 +02:00
|
|
|
|
2012-09-10 18:18:19 +02:00
|
|
|
private static function getPlsUrl($url)
|
|
|
|
{
|
2012-09-11 00:01:36 +02:00
|
|
|
$content = self::getUrlData($url);
|
2012-09-10 18:18:19 +02:00
|
|
|
|
2021-10-11 16:10:47 +02:00
|
|
|
$matches = [];
|
2022-03-14 11:15:04 +01:00
|
|
|
$numStreams = 0; // Number of streams explicitly listed in the PLS.
|
2021-10-11 16:10:47 +02:00
|
|
|
|
|
|
|
if (preg_match('/NumberOfEntries=([0-9]*)/', $content, $matches) !== false) {
|
2015-05-11 17:08:43 +02:00
|
|
|
$numStreams = $matches[1];
|
2012-09-10 18:18:19 +02:00
|
|
|
}
|
|
|
|
|
2022-03-14 11:15:04 +01:00
|
|
|
// Find all the stream URLs in the playlist
|
2021-10-11 16:10:47 +02:00
|
|
|
if (preg_match_all('/File[0-9]*=(.*)/', $content, $matches) !== false) {
|
2022-03-14 11:15:04 +01:00
|
|
|
// This array contains all the streams! If we need fallback stream URLs in the future,
|
|
|
|
// they're already in this array...
|
2015-05-11 17:08:43 +02:00
|
|
|
return $matches[1][0];
|
|
|
|
}
|
2021-10-11 16:10:47 +02:00
|
|
|
|
|
|
|
throw new Exception(_('Could not parse PLS playlist'));
|
2012-09-10 18:18:19 +02:00
|
|
|
}
|
2012-08-25 01:25:19 +02:00
|
|
|
|
2012-08-28 19:14:13 +02:00
|
|
|
private static function getM3uUrl($url)
|
|
|
|
{
|
2012-09-11 00:01:36 +02:00
|
|
|
$content = self::getUrlData($url);
|
2012-08-28 19:14:13 +02:00
|
|
|
|
2022-03-14 11:15:04 +01:00
|
|
|
// split into lines:
|
2012-08-28 19:14:13 +02:00
|
|
|
$delim = "\n";
|
|
|
|
if (strpos($content, "\r\n") !== false) {
|
|
|
|
$delim = "\r\n";
|
2012-08-29 16:58:03 +02:00
|
|
|
}
|
2021-10-11 16:10:47 +02:00
|
|
|
$lines = explode("{$delim}", $content);
|
2022-03-14 11:15:04 +01:00
|
|
|
// $lines = preg_split('/$\R?^/m', $content);
|
2012-08-28 19:14:13 +02:00
|
|
|
|
|
|
|
if (count($lines) > 0) {
|
|
|
|
return $lines[0];
|
|
|
|
}
|
|
|
|
|
2021-10-11 16:10:47 +02:00
|
|
|
throw new Exception(_('Could not parse M3U playlist'));
|
2012-08-28 19:14:13 +02:00
|
|
|
}
|
|
|
|
|
2012-08-25 01:25:19 +02:00
|
|
|
private static function getMediaUrl($url, $mime, $content_length_found)
|
2012-08-29 16:58:03 +02:00
|
|
|
{
|
2021-10-11 16:10:47 +02:00
|
|
|
if (preg_match('/x-mpegurl/', $mime)) {
|
2012-08-29 16:58:03 +02:00
|
|
|
$media_url = self::getM3uUrl($url);
|
2021-10-12 11:09:46 +02:00
|
|
|
} elseif (preg_match('/xspf\+xml/', $mime)) {
|
2012-08-29 16:58:03 +02:00
|
|
|
$media_url = self::getXspfUrl($url);
|
2021-10-12 11:09:46 +02:00
|
|
|
} elseif (preg_match('/pls\+xml/', $mime) || preg_match('/x-scpls/', $mime)) {
|
2012-09-10 18:18:19 +02:00
|
|
|
$media_url = self::getPlsUrl($url);
|
2021-10-12 11:09:46 +02:00
|
|
|
} elseif (preg_match('/(mpeg|ogg|audio\/aacp|audio\/aac)/', $mime)) {
|
2012-08-25 01:25:19 +02:00
|
|
|
if ($content_length_found) {
|
2021-10-11 16:10:47 +02:00
|
|
|
throw new Exception(_('Invalid webstream - This appears to be a file download.'));
|
2012-08-29 16:58:03 +02:00
|
|
|
}
|
2012-08-25 01:25:19 +02:00
|
|
|
$media_url = $url;
|
|
|
|
} else {
|
2021-10-11 16:10:47 +02:00
|
|
|
throw new Exception(sprintf(_('Unrecognized stream type: %s'), $mime));
|
2012-08-25 01:25:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return $media_url;
|
2012-08-21 22:54:14 +02:00
|
|
|
}
|
|
|
|
|
2021-10-11 16:10:47 +02:00
|
|
|
/* PHP get_headers has an annoying property where if the passed in URL is
|
2012-12-27 23:18:47 +01:00
|
|
|
* a redirect, then it goes to the new URL, and returns headers from both
|
|
|
|
* requests. We only want the headers from the final request. Here's an
|
|
|
|
* example:
|
|
|
|
*
|
|
|
|
* 0 => "HTTP/1.1 302 Moved Temporarily",
|
|
|
|
* 1 => "X-Powered-By: Servlet/3.0 JSP/2.2 (GlassFish Server Open Source Edition 3.1.1 Java/Sun Microsystems Inc./1.6)",
|
|
|
|
* 2 => "Server: GlassFish Server Open Source Edition 3.1.1",
|
2022-09-21 00:44:42 +02:00
|
|
|
* 3 => "Location: https://example.org/SAM04AAC89_SC",
|
2012-12-27 23:18:47 +01:00
|
|
|
* 4 => "Content-Type: text/html;charset=ISO-8859-1",
|
|
|
|
* 5 => "Content-Language: en-US",
|
|
|
|
* 6 => "Content-Length: 202",
|
|
|
|
* 7 => "Date: Thu, 27 Dec 2012 21:52:59 GMT",
|
|
|
|
* 8 => "Connection: close",
|
|
|
|
* 9 => "HTTP/1.0 200 OK",
|
|
|
|
* 10 => "Expires: Thu, 01 Dec 2003 16:00:00 GMT",
|
|
|
|
* 11 => "Cache-Control: no-cache, must-revalidate",
|
|
|
|
* 12 => "Pragma: no-cache",
|
|
|
|
* 13 => "Content-Type: audio/aacp",
|
|
|
|
* 14 => "icy-br: 68",
|
|
|
|
* 15 => "Server: MediaGateway 3.2.1-04",
|
|
|
|
* */
|
2021-10-11 16:10:47 +02:00
|
|
|
private static function cleanHeaders($headers)
|
|
|
|
{
|
2022-03-14 11:15:04 +01:00
|
|
|
// find the position of HTTP/1 200 OK
|
2012-12-27 23:18:47 +01:00
|
|
|
//
|
|
|
|
$position = 0;
|
|
|
|
foreach ($headers as $i => $v) {
|
2021-10-11 16:10:47 +02:00
|
|
|
if (preg_match('/^HTTP.*200 OK$/i', $v)) {
|
2012-12-27 23:18:47 +01:00
|
|
|
$position = $i;
|
2021-10-11 16:10:47 +02:00
|
|
|
|
2012-12-27 23:18:47 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-11 16:10:47 +02:00
|
|
|
return array_slice($headers, $position);
|
2012-12-27 23:18:47 +01:00
|
|
|
}
|
|
|
|
|
2012-08-13 18:59:26 +02:00
|
|
|
private static function discoverStreamMime($url)
|
2012-08-10 06:57:03 +02:00
|
|
|
{
|
2014-01-29 18:09:05 +01:00
|
|
|
try {
|
|
|
|
$headers = @get_headers($url);
|
2012-12-27 23:18:47 +01:00
|
|
|
|
2014-01-29 18:09:05 +01:00
|
|
|
$mime = null;
|
|
|
|
$content_length_found = false;
|
2021-10-11 16:10:47 +02:00
|
|
|
|
2014-01-29 18:09:05 +01:00
|
|
|
if ($headers !== false) {
|
|
|
|
$headers = self::cleanHeaders($headers);
|
|
|
|
foreach ($headers as $h) {
|
2021-10-11 16:10:47 +02:00
|
|
|
if (preg_match('/^content-type:/i', $h)) {
|
Feature: Support php7.4 (#1354)
* Run CI tests against php 7.4
* Sort composer dependencies
* Remove unused Aws S3 php library
* Pin simplepie dependency to ^1.5
* Pin getid3 dependency to ^1.9
* Pin composer semver to ^3.2
* Pin php-amqplib to ^2.12
* Drop sentry logging support
* Update composer dependencies
* Move propel regenerate to Makefile
* Regenerate propel files with v1.7.0
* Pin propel orm to ^1.7
* Regenerate propel files with v1.7.2
* fix: generator_version in airtime-conf-production.php
* Replace propel/propel1 with jooola/propel1
* Regenerate propel files with v1.7.3-dev
* Fix php7.4 compatibility
Using php-cs-fixer:
'@PhpCsFixer' => true,
'concat_space' => ['spacing' => 'one'],
'ordered_class_elements' => false,
'yoda_style' => false,
'@PHP74Migration' => true,
'assign_null_coalescing_to_coalesce_equal' => false,
'ternary_to_null_coalescing' => false,
'heredoc_indentation' => false,
'@PHP74Migration:risky' => true,
'declare_strict_types' => false,
'void_return' => false,
'use_arrow_functions' => false,
* Fix pre-commit
2021-10-17 17:19:53 +02:00
|
|
|
[, $value] = explode(':', $h, 2);
|
2014-01-29 18:09:05 +01:00
|
|
|
$mime = trim($value);
|
|
|
|
}
|
2021-10-11 16:10:47 +02:00
|
|
|
if (preg_match('/^content-length:/i', $h)) {
|
2014-01-29 18:09:05 +01:00
|
|
|
$content_length_found = true;
|
|
|
|
}
|
|
|
|
}
|
2012-08-13 18:59:26 +02:00
|
|
|
}
|
2014-01-29 18:09:05 +01:00
|
|
|
} catch (Exception $e) {
|
2021-10-11 16:10:47 +02:00
|
|
|
Logging::info('Invalid stream URL');
|
2014-01-29 18:09:05 +01:00
|
|
|
Logging::info($e->getMessage());
|
2012-08-13 18:59:26 +02:00
|
|
|
}
|
|
|
|
|
2021-10-11 16:10:47 +02:00
|
|
|
return [$mime, $content_length_found];
|
2012-08-10 06:57:03 +02:00
|
|
|
}
|
|
|
|
|
2012-08-25 01:25:19 +02:00
|
|
|
public static function save($parameters, $mime, $mediaUrl, $di)
|
2012-07-26 00:41:52 +02:00
|
|
|
{
|
|
|
|
$userInfo = Zend_Auth::getInstance()->getStorage()->read();
|
|
|
|
|
2012-08-16 23:49:07 +02:00
|
|
|
$id = $parameters['id'];
|
|
|
|
if ($id != -1) {
|
|
|
|
$webstream = CcWebstreamQuery::create()->findPK($id);
|
|
|
|
} else {
|
|
|
|
$webstream = new CcWebstream();
|
|
|
|
}
|
|
|
|
|
2021-10-11 16:10:47 +02:00
|
|
|
$webstream->setDbName($parameters['name']);
|
|
|
|
$webstream->setDbDescription($parameters['description']);
|
2012-08-25 01:25:19 +02:00
|
|
|
$webstream->setDbUrl($mediaUrl);
|
2012-07-26 00:41:52 +02:00
|
|
|
|
2021-10-11 16:10:47 +02:00
|
|
|
$dblength = $di->format('%H:%I');
|
2012-07-26 00:41:52 +02:00
|
|
|
$webstream->setDbLength($dblength);
|
2012-07-31 03:48:04 +02:00
|
|
|
$webstream->setDbCreatorId($userInfo->id);
|
2021-10-11 16:10:47 +02:00
|
|
|
$webstream->setDbUtime(new DateTime('now', new DateTimeZone('UTC')));
|
|
|
|
$webstream->setDbMtime(new DateTime('now', new DateTimeZone('UTC')));
|
2012-08-10 06:57:03 +02:00
|
|
|
|
2012-08-10 18:40:28 +02:00
|
|
|
$ws = new Application_Model_Webstream($webstream);
|
2012-08-29 16:58:03 +02:00
|
|
|
|
2012-08-13 18:59:26 +02:00
|
|
|
$webstream->setDbMime($mime);
|
2012-08-10 06:57:03 +02:00
|
|
|
$webstream->save();
|
2012-08-16 23:49:07 +02:00
|
|
|
|
|
|
|
return $webstream->getDbId();
|
2012-07-19 00:27:39 +02:00
|
|
|
}
|
2021-10-11 16:10:47 +02:00
|
|
|
|
|
|
|
// method is not used, webstreams aren't currently kept track of for isScheduled.
|
|
|
|
public static function setIsScheduled($p_webstreamId, $p_status)
|
|
|
|
{
|
|
|
|
$webstream = CcWebstreamQuery::create()->findPK($p_webstreamId);
|
|
|
|
$updateIsScheduled = false;
|
|
|
|
|
|
|
|
if (isset($webstream) && !in_array(
|
|
|
|
$p_webstreamId,
|
|
|
|
Application_Model_Schedule::getAllFutureScheduledWebstreams()
|
|
|
|
)) {
|
2022-03-14 11:15:04 +01:00
|
|
|
// $webstream->setDbIsScheduled($p_status)->save();
|
2021-10-11 16:10:47 +02:00
|
|
|
$updateIsScheduled = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return $updateIsScheduled;
|
2013-10-02 17:24:48 +02:00
|
|
|
}
|
2012-07-18 03:07:57 +02:00
|
|
|
}
|
2012-10-31 22:19:27 +01:00
|
|
|
|
2023-09-08 15:45:24 +02:00
|
|
|
class WebstreamNoPermissionException extends Exception {}
|