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
|
|
|
{
|
2012-08-22 00:55:38 +02:00
|
|
|
//TODO: hacky...
|
|
|
|
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-10 18:40:28 +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-08-03 21:59:34 +02:00
|
|
|
public function getLastModified($p_type)
|
2012-07-26 00:41:52 +02:00
|
|
|
{
|
2012-07-18 03:07:57 +02:00
|
|
|
return "modified";
|
|
|
|
}
|
|
|
|
|
2012-08-03 21:59:34 +02:00
|
|
|
public function getDefaultLength()
|
|
|
|
{
|
2012-08-03 22:18:45 +02:00
|
|
|
$dateString = $this->webstream->getDbLength();
|
|
|
|
$arr = explode(":", $dateString);
|
|
|
|
if (count($arr) == 3) {
|
|
|
|
list($hours, $min, $sec) = $arr;
|
|
|
|
$di = new DateInterval("PT{$hours}H{$min}M{$sec}S");
|
2012-08-04 00:06:47 +02:00
|
|
|
return $di->format("%Hh %Im");
|
2012-08-03 22:18:45 +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();
|
|
|
|
return array(
|
2012-08-03 21:59:34 +02:00
|
|
|
"name" => $this->webstream->getDbName(),
|
|
|
|
"length" => $this->webstream->getDbLength(),
|
|
|
|
"description" => $this->webstream->getDbDescription(),
|
2012-07-31 03:48:04 +02:00
|
|
|
"login"=> $username,
|
2012-08-03 21:59:34 +02:00
|
|
|
"url" => $this->webstream->getDbUrl(),
|
2012-07-31 03:48:04 +02:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static function deleteStreams($p_ids, $p_userId)
|
|
|
|
{
|
|
|
|
$leftOver = self::streamsNotOwnedByUser($p_ids, $p_userId);
|
|
|
|
if (count($leftOver) == 0) {
|
|
|
|
CcWebstreamQuery::create()->findPKs($p_ids)->delete();
|
|
|
|
} else {
|
|
|
|
throw new Exception("Invalid user permissions");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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();
|
|
|
|
$ownedStreams = array();
|
|
|
|
foreach ($ownedByUser as $pl) {
|
|
|
|
if (in_array($pl->getDbId(), $p_ids)) {
|
|
|
|
$ownedStreams[] = $pl->getDbId();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$leftOvers = array_diff($p_ids, $ownedStreams);
|
|
|
|
return $leftOvers;
|
|
|
|
}
|
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
|
|
|
{
|
|
|
|
$valid = array("length" => array(true, ''),
|
2012-08-03 21:59:34 +02:00
|
|
|
"url" => array(true, ''),
|
|
|
|
"name" => array(true, ''));
|
2012-08-02 21:45:15 +02:00
|
|
|
|
2012-08-13 21:26:32 +02:00
|
|
|
$di = null;
|
2012-08-10 18:40:28 +02:00
|
|
|
$length = $parameters["length"];
|
2012-08-28 18:30:33 +02:00
|
|
|
$result = preg_match("/^(?:([0-9]{1,2})h)?\s*(?:([0-6]?[0-9])m)?$/", $length, $matches);
|
|
|
|
|
|
|
|
$invalid_date_interval = false;
|
|
|
|
if ($result == 1 && count($matches) == 2) {
|
|
|
|
$hours = $matches[1];
|
|
|
|
$minutes = 0;
|
|
|
|
} else if ($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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!$invalid_date_interval) {
|
|
|
|
|
|
|
|
if (!is_numeric($hours)) {
|
|
|
|
$hours = 0;
|
|
|
|
}
|
|
|
|
if (!is_numeric($minutes)) {
|
|
|
|
$minutes = 0;
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
$valid['length'][1] = 'Length needs to be greater than 0 minutes';
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
2012-08-02 21:45:15 +02:00
|
|
|
$valid['length'][0] = false;
|
|
|
|
$valid['length'][1] = 'Length should be of form "00h 00m"';
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-08-10 18:40:28 +02:00
|
|
|
$url = $parameters["url"];
|
2012-08-10 18:42:56 +02: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
|
|
|
|
$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-02 21:45:15 +02:00
|
|
|
if ($result == 0) {
|
|
|
|
$valid['url'][0] = false;
|
2012-08-13 18:59:26 +02:00
|
|
|
$valid['url'][1] = 'URL should be of form "http://domain"';
|
|
|
|
} else {
|
2012-08-02 21:45:15 +02:00
|
|
|
|
2012-08-13 18:59:26 +02:00
|
|
|
try {
|
2012-08-25 01:25:19 +02:00
|
|
|
list($mime, $content_length_found) = self::discoverStreamMime($url);
|
|
|
|
if (is_null($mime)) {
|
|
|
|
throw new Exception("No MIME type found for webstream.");
|
|
|
|
}
|
|
|
|
//TODO: return url
|
|
|
|
$mediaUrl = self::getMediaUrl($url, $mime, $content_length_found);
|
|
|
|
|
2012-08-28 19:14:13 +02:00
|
|
|
if (preg_match("/(x-mpegurl)|(xspf\+xml)/", $mime)) {
|
2012-08-25 01:25:19 +02:00
|
|
|
list($mime, $content_length_found) = self::discoverStreamMime($mediaUrl);
|
|
|
|
}
|
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
|
|
|
|
2012-08-10 18:40:28 +02:00
|
|
|
$name = $parameters["name"];
|
2012-08-02 21:45:15 +02:00
|
|
|
if (strlen($name) == 0) {
|
|
|
|
$valid['name'][0] = false;
|
|
|
|
$valid['name'][1] = 'Webstream name cannot be empty';
|
|
|
|
}
|
|
|
|
|
2012-08-10 18:40:28 +02:00
|
|
|
$id = $parameters["id"];
|
2012-08-03 21:59:34 +02:00
|
|
|
|
2012-08-25 01:25:19 +02:00
|
|
|
return array($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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
2012-07-31 03:48:04 +02:00
|
|
|
|
2012-08-21 22:54:14 +02:00
|
|
|
public function setMetadata($key, $val)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public function setName($name)
|
|
|
|
{
|
|
|
|
|
|
|
|
|
2012-08-25 01:25:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private static function getXspfUrl($url)
|
|
|
|
{
|
|
|
|
$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
|
|
|
|
//TODO: What if invalid url?
|
|
|
|
$content = curl_exec($ch);
|
|
|
|
|
|
|
|
Logging::info($content);
|
|
|
|
|
|
|
|
// close cURL resource, and free up system resources
|
|
|
|
curl_close($ch);
|
|
|
|
|
|
|
|
$dom = new DOMDocument;
|
|
|
|
//TODO: What if invalid xml?
|
|
|
|
$dom->loadXML($content);
|
|
|
|
$tracks = $dom->getElementsByTagName('track');
|
|
|
|
|
|
|
|
foreach ($tracks as $track) {
|
|
|
|
$locations = $track->getElementsByTagName('location');
|
|
|
|
foreach ($locations as $loc) {
|
|
|
|
return $loc->nodeValue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
throw new Exception("Could not parse XSPF playlist");
|
|
|
|
}
|
|
|
|
|
2012-08-28 19:14:13 +02:00
|
|
|
private static function getM3uUrl($url)
|
|
|
|
{
|
|
|
|
$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
|
|
|
|
//TODO: What if invalid url?
|
|
|
|
$content = curl_exec($ch);
|
|
|
|
Logging::info($content);
|
|
|
|
curl_close($ch);
|
|
|
|
|
|
|
|
//split into lines:
|
|
|
|
$delim = "\n";
|
|
|
|
if (strpos($content, "\r\n") !== false) {
|
|
|
|
$delim = "\r\n";
|
|
|
|
}
|
|
|
|
$lines = explode("$delim", $content);
|
|
|
|
#$lines = preg_split('/$\R?^/m', $content);
|
|
|
|
|
|
|
|
if (count($lines) > 0) {
|
|
|
|
return $lines[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
throw new Exception("Could not parse M3U playlist");
|
|
|
|
}
|
|
|
|
|
2012-08-25 01:25:19 +02:00
|
|
|
private static function getMediaUrl($url, $mime, $content_length_found)
|
|
|
|
{
|
2012-08-28 19:14:13 +02:00
|
|
|
|
|
|
|
if (preg_match("/x-mpegurl/", $mime)) {
|
|
|
|
$media_url = self::getM3uUrl($url);
|
|
|
|
} else if (preg_match("/xspf\+xml/", $mime)) {
|
|
|
|
$media_url = self::getXspfUrl($url);
|
|
|
|
} else if (preg_match("/(mpeg|ogg)/", $mime)) {
|
2012-08-25 01:25:19 +02:00
|
|
|
if ($content_length_found) {
|
|
|
|
throw new Exception("Invalid webstream - This appears to be a file download.");
|
|
|
|
}
|
|
|
|
$media_url = $url;
|
|
|
|
} else {
|
|
|
|
throw new Exception("Unrecognized stream type: $mime");
|
|
|
|
}
|
|
|
|
|
|
|
|
return $media_url;
|
|
|
|
|
2012-08-21 22:54:14 +02:00
|
|
|
}
|
|
|
|
|
2012-08-13 18:59:26 +02:00
|
|
|
private static function discoverStreamMime($url)
|
2012-08-10 06:57:03 +02:00
|
|
|
{
|
2012-08-25 01:25:19 +02:00
|
|
|
//TODO: What if invalid URL?
|
2012-08-13 18:59:26 +02:00
|
|
|
$headers = get_headers($url);
|
|
|
|
$mime = null;
|
2012-08-25 01:25:19 +02:00
|
|
|
$content_length_found = false;
|
2012-08-13 18:59:26 +02:00
|
|
|
foreach ($headers as $h) {
|
|
|
|
if (preg_match("/^content-type:/i", $h)) {
|
|
|
|
list(, $value) = explode(":", $h, 2);
|
|
|
|
$mime = trim($value);
|
|
|
|
}
|
|
|
|
if (preg_match("/^content-length:/i", $h)) {
|
2012-08-25 01:25:19 +02:00
|
|
|
$content_length_found = true;
|
2012-08-13 18:59:26 +02:00
|
|
|
//if content-length appears, this is not a web stream!!!!
|
|
|
|
//Aborting the save process.
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-08-25 01:25:19 +02:00
|
|
|
return array($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();
|
|
|
|
}
|
|
|
|
|
2012-08-10 18:40:28 +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
|
|
|
|
2012-08-13 21:26:32 +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);
|
2012-07-27 20:47:15 +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-10 06:57: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
|
|
|
}
|
2012-07-18 03:07:57 +02:00
|
|
|
}
|