Merge branch 'master' of dev.sourcefabric.org:campcaster

This commit is contained in:
Naomi 2011-03-05 11:54:05 -05:00
commit 4b4174fe50
66 changed files with 977 additions and 18743 deletions

View file

@ -1,41 +1,56 @@
<?php
define('CAMPCASTER_VERSION', '1.6.1-GA');
define('CAMPCASTER_COPYRIGHT_DATE', '2010');
define('AIRTIME_VERSION', '1.7.0 alpha');
define('AIRTIME_COPYRIGHT_DATE', '2010-2011');
// These are the default values for the config.
global $CC_CONFIG;
$values = load_airtime_config();
// **********************************
// ***** START CUSTOMIZING HERE *****
// **********************************
// Set the location where you want to store all of your audio files.
//
// For example:
// $baseFilesDir = '/home/john/radio-files';
$baseFilesDir = __DIR__.'/../../files';
$CC_CONFIG = array(
// Database config
'dsn' => $values['database'],
// Set the URL of your installation
'storageUrlHost' => 'localhost',
'storageUrlPort' => 80,
// Name of the web server user
'webServerUser' => 'www-data',
// ***********************************************************************
// STOP CUSTOMIZING HERE
//
// You don't need to touch anything below this point.
// ***********************************************************************
'baseFilesDir' => $baseFilesDir,
// main directory for storing binary media files
'storageDir' => "$baseFilesDir/stor",
// Database config
'dsn' => $values['database'],
// prefix for table names in the database
'tblNamePrefix' => 'cc_',
/* ================================================ storage configuration */
'apiKey' => $values['api_key'],
'apiPath' => '/api/',
'baseFilesDir' => $baseFilesDir,
// main directory for storing binary media files
'storageDir' => "$baseFilesDir/stor",
"rootDir" => __DIR__."/../..",
'pearPath' => dirname(__FILE__).'/../../library/pear',
'zendPath' => dirname(__FILE__).'/../../library/Zend',
'phingPath' => dirname(__FILE__).'/../../library/phing',
// secret token cookie name
'authCookieName'=> 'campcaster_session_id',
// name of admin group
//'AdminsGr' => 'Admins',
@ -44,47 +59,6 @@ $CC_CONFIG = array(
// name of 'all users' group
//'AllGr' => 'All',
'TrashName' => 'trash_',
// enable/disable validator
'validate' => TRUE,
// enable/disable safe delete (move to trash)
'useTrash' => FALSE,
/* ==================================================== URL configuration */
// path-URL-part of storageServer base dir
'storageUrlPath' => '/campcaster/backend',
// XMLRPC server script address relative to storageUrlPath
'storageXMLRPC' => 'xmlrpc/xrLocStor.php',
// host and port of storageServer
'storageUrlHost' => 'localhost',
'storageUrlPort' => 80,
/* ================================================ remote link configuration */
// path-URL-part of remote server base dir
'archiveUrlPath' => '/campcaster/backend',
// XMLRPC server script address relative to archiveUrlPath
'archiveXMLRPC' => 'xmlrpc/xrLocStor.php',
// host and port of archiveServer
'archiveUrlHost' => 'localhost',
// 'archiveUrlHost' => '192.168.30.166',
'archiveUrlPort' => 80,
// account info for login to archive
'archiveAccountLogin' => 'root',
'archiveAccountPass' => 'q',
/* ============================================== scheduler configuration */
'schedulerUrlPath' => '',
'schedulerXMLRPC' => 'RC2',
'schedulerUrlHost' => 'localhost',
'schedulerUrlPort' => 3344,
'schedulerPass' => 'change_me',
/* ==================================== application-specific configuration */
'objtypes' => array(
@ -92,22 +66,16 @@ $CC_CONFIG = array(
'File' => array(),
'audioclip' => array(),
'playlist' => array(),
// 'Replica' => array(),
),
'allowedActions'=> array(
'File' => array('editPrivs', 'write', 'read'),
'audioclip' => array('editPrivs', 'write', 'read'),
'playlist' => array('editPrivs', 'write', 'read'),
// 'Replica' => array('editPrivs', 'write', 'read'),
// '_class' => array('editPrivs', 'write', 'read'),
),
'allActions' => array(
'editPrivs', 'write', 'read', /*'classes',*/ 'subjects'
'editPrivs', 'write', 'read', 'subjects'
),
/* ============================================== auxiliary configuration */
'tmpRootPass' => 'q',
/* =================================================== cron configuration */
'cronUserName' => 'www-data',
# 'lockfile' => dirname(__FILE__).'/cron/cron.lock',

View file

@ -31,7 +31,7 @@ class ApiController extends Zend_Controller_Action
print 'You are not allowed to access this resource.';
exit;
}
$jsonStr = json_encode(array("version"=>CAMPCASTER_VERSION));
$jsonStr = json_encode(array("version"=>AIRTIME_VERSION));
echo $jsonStr;
}
@ -126,7 +126,11 @@ class ApiController extends Zend_Controller_Action
$from = $this->_getParam("from");
$to = $this->_getParam("to");
if (Schedule::ValidPypoTimeFormat($from) && Schedule::ValidPypoTimeFormat($to)) {
echo Schedule::ExportRangeAsJson($from, $to);
$result = Schedule::ExportRangeAsJson($from, $to);
$result['stream_metadata'] = array();
$result['stream_metadata']['format'] = Application_Model_Preference::GetStreamLabelFormat();
$result['stream_metadata']['station_name'] = Application_Model_Preference::GetStationName();
echo json_encode($result);
}
}

View file

@ -61,7 +61,8 @@ class LoginController extends Zend_Controller_Action
$this->view->message = $message;
$this->view->form = $form;
$this->view->airtimeVersion = AIRTIME_VERSION;
$this->view->airtimeCopyright = AIRTIME_COPYRIGHT_DATE;
}
public function logoutAction()

View file

@ -36,8 +36,6 @@ class NowplayingController extends Zend_Controller_Action
$this->view->headScript()->appendFile('/js/playlist/nowplayingdatagrid.js','text/javascript');
$this->view->headScript()->appendFile('/js/playlist/dayview.js','text/javascript');
}
}

View file

@ -29,6 +29,7 @@ class PreferenceController extends Zend_Controller_Action
$values = $form->getValues();
Application_Model_Preference::SetHeadTitle($values["stationName"], $this->view);
Application_Model_Preference::SetDefaultFade($values["stationDefaultFade"]);
Application_Model_Preference::SetStreamLabelFormat($values["streamFormat"]);
$this->view->statusMsg = "Preferences Updated.";
}

View file

@ -34,10 +34,20 @@ class Application_Form_Preferences extends Zend_Form
'value' => $defaultFade
));
$stream_format = new Zend_Form_Element_Radio('streamFormat');
$stream_format->setLabel('Stream Label:');
$stream_format->setMultiOptions(array("Artist - Title",
"Show - Artist - Title",
"Show",
"Station name - Show name"));
$stream_format->setValue(Application_Model_Preference::GetStreamLabelFormat());
$this->addElement($stream_format);
$this->addElement('submit', 'submit', array(
'class' => 'ui-button ui-state-default',
'ignore' => true,
'label' => 'Submit',
));
}
}

View file

@ -1,183 +0,0 @@
<?
/**
* AccessRecur class
*
* Handles recursive accessPlaylist/releasePlaylist.
* Should be 'required_once' from LocStor.php only.
*
* @package Airtime
* @subpackage StorageServer
* @copyright 2010 Sourcefabric O.P.S.
* @license http://www.gnu.org/licenses/gpl.txt
*/
class AccessRecur {
public $ls;
public $sessid;
public function __construct(&$ls, $sessid)
{
$this->ls =& $ls;
$this->sessid = $sessid;
}
public static function accessPlaylist(&$ls, $sessid, $plid, $parent='0')
{
$ppa = new AccessRecur($ls, $sessid);
$r = $ls->accessPlaylist($sessid, $plid, FALSE, $parent);
if (PEAR::isError($r)) {
return $r;
}
$plRes = $r;
$r = StoredFile::RecallByGunid($plid);
if (is_null($r) || PEAR::isError($r)) {
return $r;
}
$ac = $r;
$r = $ac->md->genPhpArray();
if (PEAR::isError($r)) {
return $r;
}
$pla = $r;
$r = $ppa->processPlaylist($pla, $plRes['token']);
if (PEAR::isError($r)) {
return $r;
}
$plRes['content'] = $r;
return $plRes;
}
public static function releasePlaylist(&$ls, $sessid, $token)
{
global $CC_CONFIG, $CC_DBC;
$ppa = new AccessRecur($ls, $sessid);
$r = $CC_DBC->getAll("
SELECT to_hex(token)as token2, to_hex(gunid)as gunid
FROM ".$CC_CONFIG['accessTable']."
WHERE parent=x'{$token}'::bigint
");
if (PEAR::isError($r)) {
return $r;
}
$arr = $r;
foreach ($arr as $i => $item) {
extract($item); // token2, gunid
$r = BasicStor::GetType($gunid);
if (PEAR::isError($r)) {
return $r;
}
$ftype = $r;
# echo "$ftype/$token2\n";
switch (strtolower($ftype)) {
case "audioclip":
$r = $ppa->ls->releaseRawAudioData($ppa->sessid, $token2);
if (PEAR::isError($r)) {
return $r;
}
# var_dump($r);
break;
case "playlist":
$r = $ppa->releasePlaylist($ppa->ls, $ppa->sessid, $token2);
if (PEAR::isError($r)) {
return $r;
}
# var_dump($r);
break;
default:
}
}
$r = $ppa->ls->releasePlaylist($ppa->sessid, $token, FALSE);
if (PEAR::isError($r)) {
return $r;
}
return $r;
}
private function processPlaylist($pla, $parent)
{
$res = array();
foreach ($pla['children'] as $ple) {
switch ($ple['elementname']) {
case "playlistElement":
$r = $this->processPlaylistElement($ple, $parent);
if (PEAR::isError($r)) {
return $r;
}
// $res = array_merge($res, $r);
$res[] = $r;
break;
default:
}
}
return $res;
}
private function processAudioClip($gunid, $parent)
{
$r = $this->ls->accessRawAudioData($this->sessid, $gunid, $parent);
if (PEAR::isError($r)) {
return $r;
}
return $r;
}
private function processPlaylistElement($ple, $parent='0')
{
foreach ($ple['children'] as $ac) {
switch ($ac['elementname']) {
case "audioClip":
$r = $this->processAudioClip($ac['attrs']['id'], $parent);
if (PEAR::isError($r)) {
return $r;
}
return $r;
case "playlist":
// if(empty($ac['children'])){
$r = $this->accessPlaylist($this->ls, $this->sessid,
$ac['attrs']['id'], $parent);
if (PEAR::isError($r)) {
if ($r->getCode() != GBERR_NOTF) {
return $r;
} else {
$r = $this->processPlaylist($ac, $parent);
if (PEAR::isError($r)) {
return $r;
}
$r = array(
'content' => $r,
'url' => NULL,
'token' => NULL,
'chsum' => NULL,
'size' => NULL,
'warning' => 'inline playlist?',
);
}
}
return $r;
/*
}else{
$r = $this->processPlaylist($ac, $parent);
if(PEAR::isError($r)) return $r;
$res = array(
'content' => $r,
'url' => NULL,
'token' => NULL,
'chsum' => NULL,
'size' => NULL,
'warning' => 'inline playlist',
);
return $res;
}
*/
break;
default:
}
}
return array();
}
} // class AccessRecur

View file

@ -18,127 +18,7 @@ class Alib {
/* ----------------------------------------------- session/authentication */
/**
* Authenticate and create session
*
* @param string $login
* @param string $pass
* @return boolean|sessionId|PEAR_Error
*/
public static function Login($login, $pass)
{
global $CC_CONFIG, $CC_DBC;
if (FALSE === Subjects::Authenticate($login, $pass)) {
Subjects::SetTimeStamp($login, TRUE);
return FALSE;
}
$sessid = Alib::_createSessid();
if (PEAR::isError($sessid)) {
return $sessid;
}
$userid = Subjects::GetSubjId($login);
$sql = "INSERT INTO ".$CC_CONFIG['sessTable']." (sessid, userid, login, ts)"
." VALUES('$sessid', '$userid', '$login', now())";
$r = $CC_DBC->query($sql);
if (PEAR::isError($r)) {
return $r;
}
Subjects::SetTimeStamp($login, FALSE);
return $sessid;
} // fn login
/**
* Logout and destroy session
*
* @param string $sessid
* @return true|PEAR_Error
*/
public static function Logout($sessid)
{
global $CC_CONFIG, $CC_DBC;
$ct = Alib::CheckAuthToken($sessid);
if ($ct === FALSE) {
return PEAR::raiseError("Alib::logout: not logged ($sessid)",
ALIBERR_NOTLOGGED, PEAR_ERROR_RETURN);
} elseif (PEAR::isError($ct)) {
return $ct;
} else {
$sql = "DELETE FROM ".$CC_CONFIG['sessTable']
." WHERE sessid='$sessid'";
$r = $CC_DBC->query($sql);
if (PEAR::isError($r)) {
return $r;
}
return TRUE;
}
} // fn logout
/**
* Return true if the token is valid
*
* @param string $sessid
* @return boolean|PEAR_Error
*/
private static function CheckAuthToken($sessid)
{
global $CC_CONFIG, $CC_DBC;
$sql = "SELECT count(*) as cnt FROM ".$CC_CONFIG['sessTable']
." WHERE sessid='$sessid'";
$c = $CC_DBC->getOne($sql);
return ($c == 1 ? TRUE : (PEAR::isError($c) ? $c : FALSE ));
} //fn checkAuthToken
/**
* Set valid token in alib object
*
* @param string $sessid
* @return TRUE|PEAR_Error
*/
// public function setAuthToken($sessid)
// {
// $r = $this->checkAuthToken($sessid);
// if (PEAR::isError($r)) {
// return $r;
// }
// if (!$r) {
// return PEAR::raiseError("ALib::setAuthToken: invalid token ($sessid)");
// }
// //$this->sessid = $sessid;
// return TRUE;
// } // fn setAuthToken
/* -------------------------------------------------------- authorization */
/**
* Insert permission record
*
* @param int $sid
* local user/group id
* @param string $action
* @param int $oid
* local object id
* @param string $type
* 'A'|'D' (allow/deny)
* @return int
* local permission id
*/
public static function AddPerm($sid, $action, $oid, $type='A')
{
global $CC_CONFIG, $CC_DBC;
$permid = $CC_DBC->nextId($CC_CONFIG['permSequence']);
$sql = "INSERT INTO ".$CC_CONFIG['permTable']." (permid, subj, action, obj, type)"
." VALUES ($permid, $sid, '$action', $oid, '$type')";
$r = $CC_DBC->query($sql);
if (PEAR::isError($r)) {
return($r);
}
return $permid;
} // fn addPerm
/**
* Remove permission record
*
@ -172,170 +52,10 @@ class Alib {
} // fn removePerm
/**
* Return object related with permission record
*
* @param int $permid
* local permission id
* @return int
* local object id
*/
public static function GetPermOid($permid)
{
global $CC_CONFIG, $CC_DBC;
$sql = "SELECT obj FROM ".$CC_CONFIG['permTable']." WHERE permid=$permid";
$res = $CC_DBC->getOne($sql);
return $res;
} // fn GetPermOid
/**
* Check if specified subject have permission to specified action
* on specified object
*
* Look for sequence of corresponding permissions and order it by
* relevence, then test the most relevant for result.
* High relevence have direct permission (directly for specified subject
* and object. Relevance order is done by level distance in the object
* tree, level distance in subjects (user/group system).
* Similar way is used for permissions related to object classes.
* But class-related permissions have lower priority then
* object-tree-related.
* Support for object classes can be disabled by USE_ALIB_CLASSES const.
*
* @param int $sid
* subject id (user or group id)
* @param string $action
* from set defined in config
* @param int $oid
* object id (default: root node)
* @return boolean|PEAR_Error
*/
public static function CheckPerm($sid, $action, $oid=NULL)
{
return TRUE;
// global $CC_DBC;
// global $CC_CONFIG;
// if (!is_numeric($sid)) {
// return FALSE;
// }
//// if (is_null($oid) or $oid=='') {
//// $oid = M2tree::GetRootNode();
//// }
//// if (PEAR::isError($oid)) {
//// return $oid;
//// }
// if (!is_numeric($oid)) {
// return FALSE;
// }
// // query construction
// // shortcuts:
// // p: permTable,
// // s: subjTable, m smembTable,
// // t: treeTable ts: structTable,
// // c: classTable, cm: cmembTable
// // main query elements:
// $q_flds = "m.level , p.subj, s.login, action, p.type, p.obj";
// $q_from = $CC_CONFIG['permTable']." p ";
// // joins for solving users/groups:
// $q_join = "LEFT JOIN ".$CC_CONFIG['subjTable']." s ON s.id=p.subj ";
// $q_join .= "LEFT JOIN ".$CC_CONFIG['smembTable']." m ON m.gid=p.subj ";
// $q_cond = "p.action in('_all', '$action') AND
// (s.id=$sid OR m.uid=$sid) ";
// // coalesce -1 for higher priority of nongroup rows:
// // action DESC order for lower priority of '_all':
// $q_ordb = "ORDER BY coalesce(m.level,-1), action DESC, p.type DESC";
// $q_flds0 = $q_flds;
// $q_from0 = $q_from;
// $q_join0 = $q_join;
// $q_cond0 = $q_cond;
// $q_ordb0 = $q_ordb;
// // joins for solving object tree:
// $q_flds .= ", t.name, ts.level as tlevel";
// //$q_join .= "LEFT JOIN ".$CC_CONFIG['treeTable']." t ON t.id=p.obj ";
// //$q_join .= "LEFT JOIN ".$CC_CONFIG['structTable']." ts ON ts.parid=p.obj ";
// //$q_cond .= " AND (t.id=$oid OR ts.objid=$oid)";
// // action DESC order is hack for lower priority of '_all':
// $q_ordb = "ORDER BY coalesce(ts.level,0), m.level, action DESC, p.type DESC";
// // query by tree:
// $query1 = "SELECT $q_flds FROM $q_from $q_join WHERE $q_cond $q_ordb";
// $r1 = $CC_DBC->getAll($query1);
// if (PEAR::isError($r1)) {
// return($r1);
// }
// // if there is row with type='A' on the top => permit
// //$AllowedByTree =
// // (is_array($r1) && count($r1)>0 && $r1[0]['type']=='A');
// //$DeniedByTree =
// // (is_array($r1) && count($r1)>0 && $r1[0]['type']=='D');
//
// if (!USE_ALIB_CLASSES) {
// return $AllowedbyTree;
// }
//
// // joins for solving object classes:
// $q_flds = $q_flds0.", c.cname ";
// $q_join = $q_join0."LEFT JOIN ".$CC_CONFIG['classTable']." c ON c.id=p.obj ";
// $q_join .= "LEFT JOIN ".$CC_CONFIG['cmembTable']." cm ON cm.cid=p.obj ";
// $q_cond = $q_cond0." AND (c.id=$oid OR cm.objid=$oid)";
// $q_ordb = $q_ordb0;
// // query by class:
// $query2 = "SELECT $q_flds FROM $q_from $q_join WHERE $q_cond $q_ordb";
// $r2 = $CC_DBC->getAll($query2);
// if (PEAR::isError($r2)) {
// return $r2;
// }
// $AllowedByClass =
// (is_array($r2) && count($r2)>0 && $r2[0]['type']=='A');
// // not used now:
// // $DeniedByClass =
// // (is_array($r2) && count($r2)>0 && $r2[0]['type']=='D');
// $res = ($AllowedByTree || (!$DeniedByTree && $AllowedByClass));
// return $res;
} // fn CheckPerm
/* ---------------------------------------------------------- object tree */
/**
* Remove all permissions on object and then remove object itself
*
* @param int $id
* @return void|PEAR_Error
*/
public static function RemoveObj($id)
{
$r = Alib::RemovePerm(NULL, NULL, $id);
return $r;
} // fn removeObj
/* --------------------------------------------------------- users/groups */
/**
* Remove all permissions of subject and then remove subject itself
*
* @param string $login
* @return void|PEAR_Error
*/
public static function RemoveSubj($login)
{
global $CC_CONFIG, $CC_DBC;
$uid = Subjects::GetSubjId($login);
if (PEAR::isError($uid)) {
return $uid;
}
if (is_null($uid)){
return $CC_DBC->raiseError("Alib::removeSubj: Subj not found ($login)",
ALIBERR_NOTEXISTS, PEAR_ERROR_RETURN);
}
$r = Alib::RemovePerm(NULL, $uid);
if (PEAR::isError($r)) {
return $r;
}
return Subjects::RemoveSubj($login, $uid);
} // fn RemoveSubj
/* ------------------------------------------------------------- sessions */
/**
* Get login from session id (token)
@ -411,9 +131,6 @@ class Alib {
$sql = "SELECT *"
." FROM ".$CC_CONFIG['permTable']
." WHERE p.subj=$sid";
// $sql = "SELECT t.name, t.type as otype , p.*"
// ." FROM ".$CC_CONFIG['permTable']." p, ".$CC_CONFIG['treeTable']." t"
// ." WHERE t.id=p.obj AND p.subj=$sid";
$a1 = $CC_DBC->getAll($sql);
return $a1;
} // fn GetSubjPerms
@ -425,31 +142,6 @@ class Alib {
* (only very simple structure definition - in $CC_CONFIG - supported now)
*/
/**
* Get all actions
*
* @return array
*/
public static function GetAllActions()
{
global $CC_CONFIG;
return $CC_CONFIG['allActions'];
} // fn GetAllActions
/**
* Get all allowed actions on specified object type.
*
* @param string $type
* @return array
*/
public static function GetAllowedActions($type)
{
global $CC_CONFIG;
return $CC_CONFIG['allowedActions'][$type];
} // fn GetAllowedActions
/* ====================================================== private methods */
/**
@ -473,149 +165,4 @@ class Alib {
} // fn _createSessid
/* =============================================== test and debug methods */
/**
* Dump all permissions for debug
*
* @param string $indstr
* indentation string
* @param string $ind
* actual indentation
* @return string
*/
public static function DumpPerms($indstr=' ', $ind='')
{
global $CC_CONFIG, $CC_DBC;
$sql = "SELECT s.login, p.action, p.type"
." FROM ".$CC_CONFIG['permTable']." p, ".$CC_CONFIG['subjTable']." s"
." WHERE s.id=p.subj"
." ORDER BY p.permid";
$arr = $CC_DBC->getAll($sql);
if (PEAR::isError($arr)) {
return $arr;
}
$r = $ind.join(', ', array_map(create_function('$v',
'return "{$v[\'login\']}/{$v[\'action\']}/{$v[\'type\']}";'
),
$arr
))."\n";
return $r;
} // fn dumpPerms
/**
* Delete everything form the permission table and session table.
*
* @return void
*/
public static function DeleteData()
{
global $CC_CONFIG, $CC_DBC;
$CC_DBC->query("DELETE FROM ".$CC_CONFIG['permTable']);
$CC_DBC->query("DELETE FROM ".$CC_CONFIG['sessTable']);
Subjects::DeleteData();
} // fn deleteData
/**
* Insert test permissions
*
* @return array
*/
public static function TestData()
{
global $CC_CONFIG, $CC_DBC;
$tdata = Subjects::TestData();
$t =& $tdata['tree'];
$c =& $tdata['classes'];
$s =& $tdata['subjects'];
$CC_DBC->setErrorHandling(PEAR_ERROR_PRINT);
$perms = array(
array($s['root'], '_all', $t['root'], 'A'),
array($s['test1'], '_all', $t['pa'], 'A'),
array($s['test1'], 'read', $t['s2b'], 'D'),
array($s['test2'], 'addChilds', $t['pa'], 'D'),
array($s['test2'], 'read', $t['i2'], 'A'),
array($s['test2'], 'edit', $t['s1a'], 'A'),
array($s['test1'], 'addChilds', $t['s2a'], 'D'),
array($s['test1'], 'addChilds', $t['s2c'], 'D'),
array($s['gr2'], 'addChilds', $t['i2'], 'A'),
array($s['test3'], '_all', $t['t1'], 'D'),
);
if (USE_ALIB_CLASSES){
$perms[] = array($s['test3'], 'read', $c['cl_sa'], 'D');
$perms[] = array($s['test4'], 'editPerms', $c['cl2'], 'A');
}
foreach ($perms as $p){
$o[] = $r = Alib::AddPerm($p[0], $p[1], $p[2], $p[3]);
if (PEAR::isError($r)) {
return $r;
}
}
$tdata['perms'] = $o;
return $tdata;
} // fn testData
/**
* Make basic test
*
* @return boolean|PEAR_Error
*/
public static function Test()
{
$p = Subjects::test();
if (PEAR::isError($p)) {
return $p;
}
Alib::DeleteData();
$tdata = Alib::TestData();
if (PEAR::isError($tdata)) {
return $tdata;
}
$test_correct = "root/_all/A, test1/_all/A, test1/read/D,".
" test2/addChilds/D, test2/read/A, test2/edit/A,".
" test1/addChilds/D, test1/addChilds/D, gr2/addChilds/A,".
" test3/_all/D";
if (USE_ALIB_CLASSES){
$test_correct .= ", test3/read/D, test4/editPerms/A";
}
$test_correct .= "\nno, yes\n";
$r = Alib::DumpPerms();
if (PEAR::isError($r)) {
return $r;
}
$test_dump = $r.
(Alib::CheckPerm(
$tdata['subjects']['test1'], 'read',
$tdata['tree']['t1']
)? 'yes':'no').", ".
(Alib::CheckPerm(
$tdata['subjects']['test1'], 'addChilds',
$tdata['tree']['i2']
)? 'yes':'no')."\n"
;
Alib::RemovePerm($tdata['perms'][1]);
Alib::RemovePerm($tdata['perms'][3]);
$test_correct .= "root/_all/A, test1/read/D,".
" test2/read/A, test2/edit/A,".
" test1/addChilds/D, test1/addChilds/D, gr2/addChilds/A,".
" test3/_all/D";
if (USE_ALIB_CLASSES) {
$test_correct .= ", test3/read/D, test4/editPerms/A";
}
$test_correct .= "\n";
$test_dump .= Alib::DumpPerms();
Alib::DeleteData();
if ($test_dump == $test_correct) {
$test_log .= "alib: OK\n";
return TRUE;
} else {
return PEAR::raiseError('Alib::test', 1, PEAR_ERROR_DIE, '%s'.
"<pre>\ncorrect:\n{$test_correct}\n".
"dump:\n{$test_dump}\n</pre>\n");
}
} // fn test
} // class Alib

View file

@ -1,486 +0,0 @@
<?php
define('BACKUP_EXT', 'tar');
define('ACCESS_TYPE', 'backup');
/**
* @package Airtime
* @subpackage StorageServer
* @copyright 2010 Sourcefabric O.P.S.
* @license http://www.gnu.org/licenses/gpl.txt
*/
class Backup
{
/**
* Name of logfile
* @var string
*/
private $logFile;
/**
* Session id
* @var string
*/
private $sessid;
/**
* struct - see search criteria
* @var array
*/
private $criteria;
/**
* @var string
*/
private $token;
/**
* name of statusfile
* @var string
*/
private $statusFile;
/**
* Affected gunids
* @var array
*/
private $ids;
/**
* Array of affected filenames
* @var array
*/
private $filenames = array();
/**
* Base tmp name
* @var string
*/
private $tmpName;
/**
* Name of temporary tarball file
* @var string
*/
private $tmpFile;
/**
* Name of temporary directory
* @var string
*/
private $tmpDir;
/**
* Name of temporary playlist directory
* @var string
*/
private $tmpDirPlaylist;
/**
* Name of temporary audioclip directory
* @var string
*/
private $tmpDirClip;
/**
* Name of temporary metafile directory
* @var string
*/
private $tmpDirMeta;
/**
* @var string
*/
private $loglevel = 'warn'; # 'debug';
/**
* @var GreenBox
*/
private $gb;
/**
* @param GreeenBox $gb
*/
public function __construct(&$gb)
{
global $CC_CONFIG;
$this->gb =& $gb;
$this->token = null;
$this->logFile = $CC_CONFIG['bufferDir'].'/'.ACCESS_TYPE.'.log';
$this->addLogItem("-I- ".date("Ymd-H:i:s")." construct\n");
}
/**
* Open a backup
* Create a backup file (tarball)
*
* @param string $sessid
* @param array $criteria
* struct - see search criteria
* @return array
* hasharray with field:
* token string: backup token
*/
public function openBackup($sessid, $criteria='')
{
if ($this->loglevel=='debug') {
$this->addLogItem("-I- ".date("Ymd-H:i:s")." openBackup - sessid:$sessid\n");
}
$this->sessid = $sessid;
$this->criteria = $criteria;
// get ids (and real filenames) which files match with criteria
$srch = $this->gb->localSearch($this->criteria,$this->sessid);
if (PEAR::isError($srch)) {
return $srch;
}
$this->setIDs($srch);
// get real filenames
if (is_array($this->ids)) {
$this->setFilenames();
$this->setEnviroment(true);
// write a status file
file_put_contents($this->statusFile, 'working');
// save the metafile to tmpdir
$hostname = trim(`hostname`);
$ctime = time();
$ctime_f = date("Ymd-H:i:s");
file_put_contents("{$this->tmpDirMeta}/storage.xml",
"<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n".
"<storage\n".
" type=\"".ACCESS_TYPE."\"\n".
" version=\"1.0\"\n".
" ctime=\"$ctime\"\n".
" hostname=\"$hostname\"\n".
"/><!-- $ctime_f -->\n"
);
// copy all file to tmpdir
$this->copyAllFiles();
// do everything
$this->doIt();
return array('token'=>$this->token);
} else {
return false;
}
}
/**
* Check the status of backup.
*
* @param unknown $token
* @return array
* status : string - susccess | working | fault
* faultString: string - description of fault
* token : stirng - backup token
* url : string - access url
* tmpfile : string - access filename
*/
public function checkBackup($token)
{
global $CC_CONFIG;
if ($this->loglevel=='debug') {
$this->addLogItem("-I- ".date("Ymd-H:i:s")." checkBackup - token:$token\n");
}
$this->token = $token;
$this->setEnviroment();
$status = file_get_contents($this->statusFile);
if (strpos($status,'fault')!==false) {
list($status,$faultString) = explode('|',$status);
}
switch ($status) {
case 'success':
$r['url'] = BasicStor::GetUrlPart()."access/$token.".BACKUP_EXT;
$r['tmpfile'] = $CC_CONFIG['accessDir']."/$token.".BACKUP_EXT;
case 'working':
case 'fault':
$r['status'] = $status;
$r['faultString'] = $faultString;
$r['token'] = $token;
break;
}
return $r;
}
/**
* Close a backup
*
* @param unknown $token
* @return boolean
*/
public function closeBackup($token)
{
if ($this->loglevel=='debug') {
$this->addLogItem("-I- ".date("Ymd-H:i:s")." closeBackup - token:$token\n");
}
# post procedures
$this->token = $token;
$this->setEnviroment();
BasicStor::bsRelease($token, ACCESS_TYPE);
Backup::rRmDir($this->tmpDir);
unlink($this->statusFile);
unlink($this->tmpFile);
if (is_file($this->tmpName)) {
unlink($this->tmpName);
}
return !is_file($this->tmpFile);
}
/**
* list of unclosed backups
*
* @param string $stat
* if this parameter is not set, then return with all unclosed backups
* @return array of hasharray with field:
* status : string - susccess | working | fault
* token : stirng - backup token
* url : string - access url
*/
public function listBackups($stat='')
{
if ($this->loglevel=='debug') {
$this->addLogItem("-I- ".date("Ymd-H:i:s")." listBackups - stat:$stat\n");
}
// open temporary dir
$tokens = BasicStor::GetTokensByType(ACCESS_TYPE);
// echo '<XMP>tokens:'; print_r($tokens); echo '</XMP>';
foreach ($tokens as $token) {
$st = $this->checkBackup($token);
if ($stat=='' || $st['status']==$stat) {
$r[] = $st;
}
}
return $r;
}
/**
* Set the ids from searchResult
*
* @param array $searchResult : array of gunids
*/
private function setIDs($searchResult)
{
if ($this->loglevel=='debug') {
$this->addLogItem("-I- ".date("Ymd-H:i:s")." setIDs\n");
}
if (is_array($searchResult['results'])) {
$this->ids = $searchResult['results'];
} else {
$this->addLogItem("-E- ".date("Ymd-H:i:s")." setIDs - the parameter is not array!\n");
return PEAR::raiseError('The IDs variable isn\'t array.');
}
}
/**
* Set the filenames from ids.
*
*/
private function setFilenames()
{
// if ($this->loglevel=='debug') {
// $this->addLogItem("-I- ".date("Ymd-H:i:s")." setFilenames\n");
// }
// if (is_array($this->ids)) {
// foreach ($this->ids as $i => $item) {
// $gunid = $item['gunid'];
// // get a stored file object of this gunid
// $sf = StoredFile::RecallByGunid($gunid);
// if (is_null($sf) || PEAR::isError($sf)) {
// return $sf;
// }
// $lid = BasicStor::IdFromGunid($gunid);
// if (($res = BasicStor::Authorize('read', $lid, $this->sessid)) !== TRUE) {
// $this->addLogItem("-E- ".date("Ymd-H:i:s")." setFilenames - authorize gunid:$gunid\n");
// return PEAR::raiseError('Backup::setFilenames : Authorize ... error.');
// }
// // if the file is a playlist then it has only a meta file
// if (strtolower($sf->md->format) != 'playlist') {
// $this->filenames[] = array(
// 'filename' => $sf->getRealFileName(),
// 'format' => $sf->md->format
// );
// }
// $this->filenames[] = array(
// 'filename' => $sf->getRealMetadataFileName(),
// 'format' => $sf->md->format
// );
// if ($this->loglevel=='debug') {
// $this->addLogItem("-I- ".date("Ymd-H:i:s")." setFilenames - add file: {$sf->md->format}|".$sf->getRealMetadataFileName()."\n");
// }
// }
// return $this->filenames;
// } else {
// $this->addLogItem("-E- ".date("Ymd-H:i:s")." setFilenames - The IDs variable isn't array.\n");
// return PEAR::raiseError('Backup::setFilenames : The IDs variable isn\'t array.');
// }
}
/**
* Create the tarball - call the shell script
*
*/
private function doIt()
{
if ($this->loglevel=='debug') {
$this->addLogItem("-I- ".date("Ymd-H:i:s")." doIt\n");
}
$command = dirname(__FILe__)."/../bin/backup.sh"
." {$this->tmpDir}"
." {$this->tmpFile}"
." {$this->statusFile}"
." >> {$this->logFile} &";
$res = system("$command");
sleep(2);
if ($this->loglevel=='debug') {
$this->addLogItem("-I- ".date("Ymd-H:i:s")." doIt - command:$command\n");
}
}
/**
* Copy the real files into the tmp dirs to tar they.
*
*/
private function copyAllFiles()
{
if ($this->loglevel=='debug') {
$this->addLogItem("-I- ".date("Ymd-H:i:s")." copyAllFiles\n");
}
//echo '<XMP>this->filenames:'; print_r($this->filenames); echo '</XMP>';
if (is_array($this->filenames)) {
foreach ($this->filenames as $v) {
# get the filename from full path
$fn = substr($v['filename'],strrpos($v['filename'],'/'));
switch (strtolower($v['format'])) {
case 'playlist':
# if playlist then copy to the playlist dir
copy($v['filename'],$this->tmpDirPlaylist.$fn);
break;
case 'audioclip':
# if audioclip then copy to the audioclip dir
copy($v['filename'],$this->tmpDirClip.$fn);
break;
}
}
}
}
/**
* Figure out the enviroment to the backup
*
*/
private function setEnviroment($createDir=false)
{
global $CC_CONFIG;
if ($this->loglevel=='debug') {
$this->addLogItem("-I- ".date("Ymd-H:i:s")." setEnviroment - createDirs:$createDir\n");
}
// create temporary directories
if (is_null($this->token) && $createDir) {
$this->tmpName = tempnam($CC_CONFIG['bufferDir'], ACCESS_TYPE.'_');
$this->tmpFile = $this->tmpName.'.'.BACKUP_EXT;
$this->tmpDir = $this->tmpName.'.dir';
$this->tmpDirPlaylist = $this->tmpDir. '/playlist';
$this->tmpDirClip = $this->tmpDir. '/audioClip';
$this->tmpDirMeta = $this->tmpDir. '/meta-inf';
touch($this->tmpFile);
mkdir($this->tmpDir);
mkdir($this->tmpDirPlaylist);
mkdir($this->tmpDirClip);
mkdir($this->tmpDirMeta);
$this->genToken();
} else {
$symlink = $CC_CONFIG['accessDir'].'/'.$this->token.'.'.BACKUP_EXT;
if (is_link($symlink) && is_file(readlink($symlink))) {
$this->tmpName = str_replace('.tar','',readlink($symlink));
$this->tmpFile = $this->tmpName.'.'.BACKUP_EXT;
$this->tmpDir = $this->tmpName.'.dir';
$this->tmpDirPlaylist = $this->tmpDir. '/playlist';
$this->tmpDirClip = $this->tmpDir. '/audioClip';
$this->tmpDirMeta = $this->tmpDir. '/meta-inf';
} else {
$this->addLogItem("-E- ".date("Ymd-H:i:s")." setEnviroment - Corrupt symbolic link.\n");
return false;
}
}
$this->statusFile = $CC_CONFIG['accessDir'].'/'.$this->token.'.'.BACKUP_EXT.'.status';
if ($this->loglevel=='debug') {
$this->addLogItem("this->tmpName: $this->tmpName\n");
$this->addLogItem("this->tmpFile: $this->tmpFile\n");
$this->addLogItem("this->tmpDir: $this->tmpDir\n");
$this->addLogItem("this->tmpDirPlaylist: $this->tmpDirPlaylist\n");
$this->addLogItem("this->tmpDirClip: $this->tmpDirClip\n");
$this->addLogItem("this->tmpDirMeta: $this->tmpDirMeta\n");
$this->addLogItem("this->token: $this->token\n");
$this->addLogItem("this->statusFile: $this->statusFile\n");
}
}
/**
* Generate a new token.
* @return void
*/
private function genToken()
{
$acc = BasicStor::bsAccess($this->tmpFile, BACKUP_EXT, null, ACCESS_TYPE);
if (PEAR::isError($acc)) {
return $acc;
}
$this->token = $acc['token'];
}
/**
* Add a line to the logfile.
*
* @param string $item
* the new row of log file
*/
private function addLogItem($item)
{
$f = fopen($this->logFile,'a');
fwrite($f,$item);
fclose($f);
}
/**
* Delete a directory recursive
*
* @param string $dirname
* path of dir.
*/
private static function rRmDir($dirname)
{
if (is_dir($dirname)) {
$dir_handle = opendir($dirname);
}
while ($file = readdir($dir_handle)) {
if ( ($file != ".") && ($file != "..") ) {
if (!is_dir($dirname."/".$file)) {
unlink ($dirname."/".$file);
} else {
Backup::rRmDir($dirname."/".$file);
}
}
}
closedir($dir_handle);
rmdir($dirname);
return true;
}
} // classs Backup

File diff suppressed because it is too large Load diff

View file

@ -30,6 +30,14 @@ class Application_Model_DateHelper
return $dayEndTS - $this->_timestamp;
}
function getEpochTime(){
return $this->_timestamp;
}
public static function TimeDiff($time1, $time2){
return strtotime($time2) - strtotime($time1);
}
public static function ConvertMSToHHMMSSmm($time){
$hours = floor($time / 3600000);
$time -= 3600000*$hours;

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,351 +0,0 @@
<?
define('INDCH', ' ');
/**
* M3uPlaylist class
*
* @package Airtime
* @subpackage StorageServer
* @copyright 2010 Sourcefabric O.P.S.
* @license http://www.gnu.org/licenses/gpl.txt
*/
class M3uPlaylist {
/**
* Parse M3U file or string
*
* @param string $data
* local path to M3U file or M3U string
* @param string $loc
* location: 'file'|'string'
* @return array
* reference, parse result tree (or PEAR::error)
*/
function &parse($data='', $loc='file')
{
switch ($loc) {
case "file":
if (!is_file($data)) {
return PEAR::raiseError(
"M3uPlaylist::parse: file not found ($data)"
);
}
if (!is_readable($data)) {
return PEAR::raiseError(
"M3uPlaylist::parse: can't read file ($data)"
);
}
$data = file_get_contents($data);
case "string":
$arr = preg_split("|\n#EXTINF: |", $data);
if ($arr[0] != '#EXTM3U') {
return PEAR::raiseError(
"M3uPlaylist::parse: invalid M3U header"
);
}
array_shift($arr);
break;
default:
return PEAR::raiseError(
"M3uPlaylist::parse: unsupported data location ($loc)"
);
}
return $arr;
}
/**
* Import M3U file to storage
*
* @param GreenBox $gb
* @param string $aPath
* absolute path part of imported file (e.g. /home/user/airtime)
* @param string $rPath
* relative path/filename part of imported file
* (e.g. playlists/playlist_1.smil)
* @param array $gunids
* hash relation from filenames to gunids
* @param string $plid
* playlist gunid
* @param int $subjid
* local subject (user) id (id of user doing the import)
* @return Playlist
*/
function import(&$gb, $aPath, $rPath, &$gunids, $plid, $subjid=NULL)
{
// $path = realpath("$aPath/$rPath");
// if (FALSE === $path) {
// return PEAR::raiseError(
// "M3uPlaylist::import: file doesn't exist ($aPath/$rPath)"
// );
// }
// $arr = M3uPlaylist::parse($path);
// if (PEAR::isError($arr)) {
// return $arr;
// }
// require_once("Playlist.php");
// $pl =& Playlist::create($gb, $plid, "imported_M3U");
// if (PEAR::isError($pl)) {
// return $pl;
// }
// $r = $pl->lock($gb, $subjid);
// if (PEAR::isError($r)) {
// return $r;
// }
// foreach ($arr as $i => $it) {
// list($md, $uri) = preg_split("|\n|", $it);
// list($length, $title) = preg_split("|, *|", $md);
// // $gunid = StoredFile::CreateGunid();
// $gunid = ( isset($gunids[basename($uri)]) ? $gunids[basename($uri)] : NULL);
// $acId = BasicStor::IdFromGunid($gunid);
// if (PEAR::isError($acId)) {
// return $acId;
// }
// $length = Playlist::secondsToPlaylistTime($length);
// $offset = '???';
// if (preg_match("|\.([a-zA-Z0-9]+)$|", $uri, $va)) {
// switch (strtolower($ext = $va[1])) {
// case "lspl":
// case "xml":
// case "smil":
// case "m3u":
// $acId = $gb->bsImportPlaylistRaw($gunid,
// $aPath, $uri, $ext, $gunids, $subjid);
// if (PEAR::isError($acId)) {
// break;
// }
// //no break!
// default:
// if (is_null($gunid)) {
// return PEAR::raiseError(
// "M3uPlaylist::import: no gunid");
// }
// $r = $pl->addAudioClip($acId);
// if (PEAR::isError($r)) {
// return $r;
// }
// }
// }
// }
// $r = $pl->unlock($gb);
// if (PEAR::isError($r)) {
// return $r;
// }
// return $pl;
}
/**
* Import M3U file to storage
*
* @param GreenBox $gb
* @param string $data
* local path to M3U file
* @return string
* XML playlist in Airtime playlist format
*/
function convert2lspl(&$gb, $data)
{
$arr = M3uPlaylist::parse($data);
if (PEAR::isError($arr)) {
return $arr;
}
$ind = '';
$ind2 = $ind.INDCH;
$ind3 = $ind2.INDCH;
$res = '';
foreach ($arr as $i => $it) {
list($md, $uri) = preg_split("|\n|", $it);
list($length, $title) = preg_split("|, *|", $md);
$gunid = StoredFile::CreateGunid();
$gunid2 = StoredFile::CreateGunid();
$length = Playlist::secondsToPlaylistTime($length);
$offset = '???';
$clipStart = '???';
$clipEnd = '???';
$clipLength = '???';
$uri_h = preg_replace("|--|", "&#2d;&#2d;", htmlspecialchars("$uri"));
if (preg_match("|\.([a-zA-Z0-9]+)$|", $uri, $va)) {
switch (strtolower($ext = $va[1])) {
case "lspl":
case "xml":
case "smil":
case "m3u":
$acOrPl = "$ind3<playlist id=\"$gunid2\" ".
"playlength=\"$length\" title=\"$title\"/> ".
"<!-- $uri_h -->\n";
break;
default:
$acOrPl = "$ind3<audioClip id=\"$gunid2\" ".
"playlength=\"$length\" title=\"$title\"/> ".
"<!-- $uri_h -->\n";
break;
}
}
$res .= "$ind2<playlistElement id=\"$gunid\" relativeOffset=\"$offset\" clipStart=\"$clipStart\" clipEnd=\"$clipEnd\" clipLength=\"$clipLength\">\n".
$acOrPl.
"$ind2</playlistElement>\n";
}
$res = "$ind<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n".
"$ind<playlist id=\"$gunid\" playlength=\"$playlength\" title=\"\">\n".
"$ind2<metadata/>\n".
"$res".
"$ind</playlist>\n";
return $res;
}
} // class M3uPlaylist
/**
* @package Airtime
* @subpackage StorageServer
* @copyright 2010 Sourcefabric O.P.S.
* @license http://www.gnu.org/licenses/gpl.txt
*/
class M3uPlaylistBodyElement {
function convert2lspl(&$tree, $ind='')
{
$ind2 = $ind.INDCH;
if ($tree->name != 'body') {
return PEAR::raiseError("M3uPlaylist::parse: body tag expected");
}
if (isset($tree->children[1])) {
return PEAR::raiseError(sprintf(
"M3uPlaylist::parse: unexpected tag %s in tag body",
$tree->children[1]->name
));
}
$res = M3uPlaylistParElement::convert2lspl($tree->children[0], $ind2);
if (PEAR::isError($res)) {
return $res;
}
$gunid = StoredFile::CreateGunid();
$playlength = '???'; // ***
$res = "$ind<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n".
"$ind<playlist id=\"$gunid\" playlength=\"$playlength\" title=\"\">\n".
"$ind2<metadata/>\n".
"$res".
"$ind</playlist>\n";
return $res;
}
}
/**
* @package Airtime
* @subpackage StorageServer
* @copyright 2010 Sourcefabric O.P.S.
* @license http://www.gnu.org/licenses/gpl.txt
*/
class M3uPlaylistParElement {
function convert2lspl(&$tree, $ind='')
{
if ($tree->name != 'par') {
return PEAR::raiseError("M3uPlaylist::parse: par tag expected");
}
$res = '';
foreach ($tree->children as $i => $ch) {
$ch =& $tree->children[$i];
$r = M3uPlaylistAudioElement::convert2lspl($ch, $ind.INDCH);
if (PEAR::isError($r)) {
return $r;
}
$res .= $r;
}
return $res;
}
}
/**
* @package Airtime
* @subpackage StorageServer
* @copyright 2010 Sourcefabric O.P.S.
* @license http://www.gnu.org/licenses/gpl.txt
*/
class M3uPlaylistAudioElement {
function convert2lspl(&$tree, $ind='')
{
$ind2 = $ind.INDCH;
if ($tree->name != 'audio') {
return PEAR::raiseError("M3uPlaylist::parse: audio tag expected");
}
if (isset($tree->children[2])) {
return PEAR::raiseError(sprintf(
"M3uPlaylist::parse: unexpected tag %s in tag audio",
$tree->children[2]->name
));
}
$res = ''; $fadeIn = 0; $fadeOut = 0;
foreach ($tree->children as $i => $ch) {
$ch =& $tree->children[$i];
$r = M3uPlaylistAnimateElement::convert2lspl($ch, $ind2);
if (PEAR::isError($r)) {
return $r;
}
switch ($r['type']) {
case "fadeIn":
$fadeIn = $r['val'];
break;
case "fadeOut":
$fadeOut = $r['val'];
break;
}
}
if ($fadeIn > 0 || $fadeOut > 0) {
$fadeIn = Playlist::secondsToPlaylistTime($fadeIn);
$fadeOut = Playlist::secondsToPlaylistTime($fadeOut);
$fInfo = "$ind2<fadeInfo fadeIn=\"$fadeIn\" fadeOut=\"$fadeOut\"/>\n";
} else {
$fInfo = '';
}
$plElGunid = StoredFile::CreateGunid();
$aGunid = StoredFile::CreateGunid();
$title = basename($tree->attrs['src']->val);
$offset = Playlist::secondsToPlaylistTime($tree->attrs['begin']->val);
$playlength = '???'; # ***
$res = "$ind<playlistElement id=\"$plElGunid\" relativeOffset=\"$offset\">\n".
"$ind2<audioClip id=\"$aGunid\" playlength=\"$playlength\" title=\"$title\"/>\n".
$fInfo.
"$ind</playlistElement>\n";
return $res;
}
} // class M3uPlaylistAudioElement
/**
* @package Airtime
* @subpackage StorageServer
* @copyright 2010 Sourcefabric O.P.S.
* @license http://www.gnu.org/licenses/gpl.txt
*/
class M3uPlaylistAnimateElement {
function convert2lspl(&$tree, $ind='') {
if ($tree->name != 'animate') {
return PEAR::raiseError("M3uPlaylist::parse: animate tag expected");
}
if ($tree->attrs['attributeName']->val == 'soundLevel' &&
$tree->attrs['from']->val == '0%' &&
$tree->attrs['to']->val == '100%' &&
$tree->attrs['calcMode']->val == 'linear' &&
$tree->attrs['fill']->val == 'freeze' &&
$tree->attrs['begin']->val == '0s' &&
preg_match("|^([0-9.]+)s$|", $tree->attrs['end']->val, $va)
) {
return array('type'=>'fadeIn', 'val'=>$va[1]);
}
if ($tree->attrs['attributeName']->val == 'soundLevel' &&
$tree->attrs['from']->val == '100%' &&
$tree->attrs['to']->val == '0%' &&
$tree->attrs['calcMode']->val == 'linear' &&
$tree->attrs['fill']->val == 'freeze' &&
preg_match("|^([0-9.]+)s$|", $tree->attrs['begin']->val, $vaBegin) &&
preg_match("|^([0-9.]+)s$|", $tree->attrs['end']->val, $vaEnd)
) {
return array('type'=>'fadeOut', 'val'=>($vaEnd[1] - $vaBegin[1]));
}
return PEAR::raiseError(
"M3uPlaylistAnimateElement::convert2lspl: animate parameters too general"
);
}
}

View file

@ -2,7 +2,7 @@
class Application_Model_Nowplaying
{
/*
public static function InsertBlankRow($i, $rows){
$startDateFull = $rows[$i-1][3];
$endDateFull = $rows[$i][2];
@ -44,58 +44,105 @@ class Application_Model_Nowplaying
return $rows;
}
*/
/*
public static function FindGapsBetweenShows($showsMap){
$previousShow = null;
foreach($showsMap as $k => $show){
$currentShow = $showsMap[$k];
if (!is_null($previousShow)){
$diff = strtotime($currentShow['starts']) - strtotime($previousShow['ends'])
if ($$diff != 0){
//array_splice($showsMap, $i, 0, $blankRow);
}
}
$previousShow = $showsMap[$k];
}
return $showsMap;
}
*/
public static function FindGapAtEndOfShow($show, $rows){
$showStartTime = $show['starts'];
$showEndTime = $show['ends'];
if (count($rows) > 1){
$lastItem = $rows[count($rows)-1];
$lastItemEndTime = $lastItem['ends'];
} else {
$lastItemEndTime = $showStartTime;
}
$diff = Application_Model_DateHelper::TimeDiff($lastItemEndTime, $showEndTime);
if ($diff <= 0){
//ok!
return null;
} else {
//There is a gap at the end of the show. Return blank row
return array("b", $diff, "-", "-", "-", "-", "-", "-", "-", "-", "-", "-");
}
}
public static function GetDataGridData($viewType, $dateString){
//echo $dateString;
if ($viewType == "now"){
$date = new Application_Model_DateHelper;
$timeNow = $date->getDate();
/* When do "ORDER BY x DESC LIMIT 5" to ensure that we get the last 5 previously scheduled items.
* However using DESC, puts our scheduled items in reverse order, so we need to reverse it again
* with array_reverse.
*/
$previous = array_reverse(Schedule::Get_Scheduled_Item_Data($timeNow, -1, 1, "60 seconds"));
$current = Schedule::Get_Scheduled_Item_Data($timeNow, 0);
$next = Schedule::Get_Scheduled_Item_Data($timeNow, 1, 10, "24 hours");
$startCutoff = 60;
$endCutoff = 86400; //60*60*24 - seconds in a day
} else {
$date = new Application_Model_DateHelper;
$time = $date->getTime();
$date->setDate($dateString." ".$time);
$timeNow = $date->getDate();
$previous = array_reverse(Schedule::Get_Scheduled_Item_Data($timeNow, -1, "ALL", $date->getNowDayStartDiff()." seconds"));
$current = Schedule::Get_Scheduled_Item_Data($timeNow, 0);
$next = Schedule::Get_Scheduled_Item_Data($timeNow, 1, "ALL", $date->getNowDayEndDiff()." seconds");
$startCutoff = $date->getNowDayStartDiff();
$endCutoff = $date->getNowDayEndDiff();
}
$rows = array();
foreach ($previous as $item){
array_push($rows, array("p", $item["starts"], $item["starts"], $item["ends"], $item["clip_length"], $item["track_title"], $item["artist_name"],
$showsMap = Show_DAL::GetShowsInRange($timeNow, $startCutoff, $endCutoff);
//iterate over each show, and calculate information for it.
foreach($showsMap as $k => $show){
$rows = Schedule::GetShowInstanceItems($k);
$gapRow = Application_Model_Nowplaying::FindGapAtEndOfShow($showsMap[$k], $rows);
foreach ($rows as $item){
//check if this item is in todays date range
if (strtotime($item['ends']) > $date->getEpochTime() - $startCutoff
&& strtotime($item['starts']) < $date->getEpochTime() + $endCutoff){
if ($item['ends'] < $timeNow){
$type = "p";
} else if ($item['starts'] < $timeNow && $timeNow < $item['ends']){
$type = "c";
} else {
$type = "n";
}
array_push($showsMap[$k]['items'], array($type, $item["starts"], $item["starts"], $item["ends"], $item["clip_length"], $item["track_title"], $item["artist_name"],
$item["album_title"], $item["name"], $item["show_name"], $item["instance_id"], $item["group_id"]));
}
foreach ($current as $item){
array_push($rows, array("c", $item["starts"], $item["starts"], $item["ends"], $item["clip_length"], $item["track_title"], $item["artist_name"],
$item["album_title"], $item["name"], $item["show_name"], $item["instance_id"], $item["group_id"]));
}
foreach ($next as $item){
array_push($rows, array("n", $item["starts"], $item["starts"], $item["ends"], $item["clip_length"], $item["track_title"], $item["artist_name"],
$item["album_title"], $item["name"], $item["show_name"], $item["instance_id"], $item["group_id"]));
if (!is_null($gapRow))
array_push($showsMap[$k]['items'], $gapRow);
}
//$showsMap = Application_Model_Nowplaying::FindGapsBetweenShows($showsMap);
$rows = Application_Model_Nowplaying::FindGaps($rows);
$date = new Application_Model_DateHelper;
$timeNow = $date->getDate();
$data = array("currentShow"=>Show_DAL::GetCurrentShow($timeNow), "rows"=>$rows);
return $data;
return array("currentShow"=>Show_DAL::GetCurrentShow($timeNow), "rows"=>$showsMap);
}
}

View file

@ -1,10 +1,7 @@
<?php
define('INDCH', ' ');
/**
* Auxiliary class for GreenBox playlist editing methods.
*
* remark: dcterms:extent format: hh:mm:ss.ssssss
*
* @package Airtime

View file

@ -86,5 +86,16 @@ class Application_Model_Preference
return Application_Model_Preference::GetValue("default_fade");
}
public static function SetStreamLabelFormat($type){
Application_Model_Preference::SetValue("stream_label_format", $type);
}
public static function GetStreamLabelFormat(){
return Application_Model_Preference::getValue("stream_label_format");
}
public static function GetStationName(){
return Application_Model_Preference::getValue("station_name");
}
}

View file

@ -1,7 +1,4 @@
<?php
require_once("GreenBox.php");
/**
* Preference storage class.
*
@ -14,17 +11,11 @@ require_once("GreenBox.php");
/* ================== Prefs ================== */
class Prefs {
public $gb;
/**
* Constructor
*
* @param GreenBox $gb
* GreenBox object reference
*/
public function __construct(&$gb)
public function __construct()
{
$this->gb =& $gb;
}
@ -42,7 +33,7 @@ class Prefs {
*/
function loadPref($sessid, $key)
{
$subjid = GreenBox::GetSessUserId($sessid);
$subjid = Alib::GetSessUserId($sessid);
if (PEAR::isError($subjid)) {
return $subjid;
}
@ -75,7 +66,7 @@ class Prefs {
*/
function savePref($sessid, $key, $value)
{
$subjid = GreenBox::GetSessUserId($sessid);
$subjid = Alib::GetSessUserId($sessid);
if (PEAR::isError($subjid)) {
return $subjid;
}
@ -107,7 +98,7 @@ class Prefs {
*/
function delPref($sessid, $key)
{
$subjid = GreenBox::GetSessUserId($sessid);
$subjid = Alib::GetSessUserId($sessid);
if (PEAR::isError($subjid)) {
return $subjid;
}
@ -180,7 +171,7 @@ class Prefs {
*/
function saveGroupPref($sessid, $group, $key, $value)
{
$uid = GreenBox::GetSessUserId($sessid);
$uid = Alib::GetSessUserId($sessid);
if (PEAR::isError($uid)) {
return $uid;
}
@ -230,7 +221,7 @@ class Prefs {
*/
function delGroupPref($sessid, $group, $key)
{
$uid = GreenBox::GetSessUserId($sessid);
$uid = Alib::GetSessUserId($sessid);
if (PEAR::isError($uid)) {
return $uid;
}
@ -406,37 +397,5 @@ class Prefs {
}
/* ==================================================== auxiliary methods */
/**
* Test method
*
*/
function test()
{
global $CC_CONFIG;
$sessid = Alib::Login('root', $CC_CONFIG['tmpRootPass']);
$testkey = 'testKey';
$testVal = 'abcDef 0123 ěščřžýáíé ĚŠČŘŽÝÁÍÉ';
$r = savePref($sessid, $testKey, $testVal);
if (PEAR::isError($r)) {
return $r;
}
$val = loadPref($sessid, $testKey);
if ($val != $testVal) {
echo "ERROR: preference storage test failed.\n ($testVal / $val)\n";
return FALSE;
}
$r = savePref($sessid, $testKey, '');
if (PEAR::isError($r)) {
return $r;
}
$val = loadPref($sessid, $testKey);
if ($val != $testVal) {
echo "ERROR: preference storage test failed.\n ('' / '$val')\n";
return FALSE;
}
return TRUE;
}
} // class Prefs

View file

@ -1,289 +0,0 @@
<?php
define('RENDER_EXT', 'ogg');
require_once("Playlist.php");
/**
* Renderer caller class
*
* Playlist to file rendering - PHP layer, caller to the renderer executable
*
* @package Airtime
* @subpackage StorageServer
* @copyright 2010 Sourcefabric O.P.S.
* @license http://www.gnu.org/licenses/gpl.txt
* @see LocStor
*/
class Renderer
{
/**
* Render playlist to ogg file (open handle)
*
* @param GreenBox $gb
* greenbox object reference
* @param string $plid
* playlist gunid
* @param int $owner
* local subject id, owner of token
* @return array
* token: string - render token
*/
function rnRender2FileOpen(&$gb, $plid, $owner=NULL)
{
global $CC_CONFIG;
// recall playlist:
$pl = StoredFile::RecallByGunid($plid);
if (is_null($pl) || PEAR::isError($pl)) {
return $pl;
}
// smil export:
$smil = $pl->outputToSmil();
if (PEAR::isError($smil)) {
return $smil;
}
// temporary file for smil:
$tmpn = tempnam($CC_CONFIG['bufferDir'], 'plRender_');
$smilf = "$tmpn.smil";
file_put_contents($smilf, $smil);
$url = "file://$smilf";
// output file:
$outf = "$tmpn.".RENDER_EXT;
touch($outf);
// logging:
$logf = $CC_CONFIG['bufferDir']."/renderer.log";
file_put_contents($logf, "--- ".date("Ymd-H:i:s")."\n", FILE_APPEND);
// open access to output file: /*gunid*/ /*parent*/
$acc = BasicStor::bsAccess($outf, RENDER_EXT, $plid, 'render', 0, $owner);
if (PEAR::isError($acc)) {
return $acc;
}
extract($acc);
$statf = Renderer::getStatusFile($gb, $token);
file_put_contents($statf, "working");
// command:
$stServDir = dirname(__FILE__)."/..";
$renderExe = "$stServDir/bin/renderer.sh";
$command = "$renderExe -p $url -o $outf -s $statf >> $logf &";
file_put_contents($logf, "$command\n", FILE_APPEND);
$res = system($command);
if ($res === FALSE) {
return PEAR::raiseError(
'Renderer::rnRender2File: Error running renderer'
);
}
return array('token'=>$token);
}
/**
* Render playlist to ogg file (check results)
*
* @param GreenBox $gb
* GreenBox object reference
* @param string $token
* render token
* @return array
* status : string - success | working | fault
* url : string - readable url
*/
function rnRender2FileCheck(&$gb, $token)
{
$statf = Renderer::getStatusFile($gb, $token);
if (!file_exists($statf)) {
return PEAR::raiseError(
'Renderer::rnRender2FileCheck: Invalid token'
);
}
$status = trim(file_get_contents($statf));
$url = Renderer::getUrl($gb, $token);
$tmpfile= Renderer::getLocalFile($gb, $token);
return array('status'=>$status, 'url'=>$url, 'tmpfile'=>$tmpfile);
}
/**
* Render playlist to ogg file (list results)
*
* @param GreenBox $gb
* greenbox object reference
* @param string $stat
* status (optional) if this parameter is not set, then return with all unclosed backups
* @return array
* array of hasharray:
* status : string - success | working | fault
* url : string - readable url
*/
function rnRender2FileList(&$gb,$stat='') {
// open temporary dir
$tokens = BasicStor::GetTokensByType('render');
foreach ($tokens as $token) {
$st = Renderer::rnRender2FileCheck($gb, $token);
if ( ($stat=='') || ($st['status']==$stat) ) {
$r[] = $st;
}
}
return $r;
}
/**
* Render playlist to ogg file (close handle)
*
* @param GreenBox $gb
* greenbox object reference
* @param string $token
* render token
* @return mixed
* TRUE or PEAR_Error
*/
function rnRender2FileClose(&$gb, $token)
{
global $CC_CONFIG;
$r = BasicStor::bsRelease($token, 'render');
if (PEAR::isError($r)) {
return $r;
}
$realOgg = $r['realFname'];
$tmpn = $CC_CONFIG['bufferDir']."/".basename($realOgg, '.'.RENDER_EXT);
$smilf = "$tmpn.smil";
$statf = Renderer::getStatusFile($gb, $token);
@unlink($statf);
@unlink($realOgg);
@unlink($smilf);
@unlink($tmpn);
return TRUE;
}
/**
* Render playlist to storage as audioClip (check results)
*
* @param GreenBox $gb
* greenbox object reference
* @param string $token
* render token
* @return array
* status : string - success | working | fault
* gunid: string - global unique id of result file
*/
function rnRender2StorageCheck(&$gb, $token)
{
$r = Renderer::rnRender2FileCheck($gb, $token);
if (PEAR::isError($r)) {
return $r;
}
$status = $r['status'];
$res = array('status' => $status, 'gunid'=>'NULL');
switch ($status) {
case "fault":
$res['faultString'] = "Error runing renderer";
break;
case "success":
$r = Renderer::rnRender2StorageCore($gb, $token);
if (PEAR::isError($r)) {
return $r;
}
$res['gunid'] = $r['gunid'];
break;
default:
break;
}
return $res;
}
/**
* Render playlist to storage as audioClip (core method)
*
* @param GreenBox $gb
* greenbox object reference
* @param string $token
* render token
* @return array:
* gunid: string - global unique id of result file
*/
function rnRender2StorageCore(&$gb, $token)
{
// $r = BasicStor::bsRelease($token, 'render');
// if (PEAR::isError($r)) {
// return $r;
// }
// $realOgg = $r['realFname'];
// $owner = $r['owner'];
// $gunid = $r['gunid'];
// $fileName = 'rendered_playlist';
// $id = BasicStor::IdFromGunid($gunid);
// if (PEAR::isError($id)) {
// return $id;
// }
// $mdata = '';
// foreach (array('dc:title', 'dcterms:extent', 'dc:creator', 'dc:description') as $item) {
// $val = $gb->bsGetMetadataValue($id, $item);
// $mdata .= " <$item>$val</$item>\n";
// }
// $mdata = "<audioClip>\n <metadata>\n$mdata </metadata>\n</audioClip>\n";
// //$mdata = "<audioClip>\n <metadata>\n$mdata<dcterms:extent>0</dcterms:extent>\n</metadata>\n</audioClip>\n";
// $values = array(
// "filename" => $fileName,
// "filepath" => $realOgg,
// "metadata" => $mdata,
// "filetype" => "audioclip"
// );
// $storedFile = $gb->bsPutFile($values);
// if (PEAR::isError($storedFile)) {
// return $storedFile;
// }
// return array('gunid' => $storedFile->getGunid());
}
/**
* Return local filepath of rendered file
*
* @param Greenbox $gb
* greenbox object reference
* @param string $token
* render token
* @return array
*/
function getLocalFile(&$gb, $token)
{
global $CC_CONFIG;
$token = StoredFile::NormalizeGunid($token);
return $CC_CONFIG['accessDir']."/$token.".RENDER_EXT;
}
/**
* Return filepath of render status file
*
* @param GreenBox $gb
* greenbox object reference
* @param string $token
* render token
* @return array
*/
function getStatusFile(&$gb, $token)
{
return Renderer::getLocalFile($gb, $token).".status";
}
/**
* Return remote accessible URL for rendered file
*
* @param GreenBox $gb
* greenbox object reference
* @param string $token
* render token
* @return array
*/
function getUrl(&$gb, $token)
{
$token = StoredFile::NormalizeGunid($token);
return BasicStor::GetUrlPart()."access/$token.".RENDER_EXT;
}
} // class Renderer

View file

@ -1,436 +0,0 @@
<?php
/**
* @package Airtime
* @subpackage StorageServer
* @copyright 2010 Sourcefabric O.P.S.
* @license http://www.gnu.org/licenses/gpl.txt
*/
class Restore {
/**
* Name of logfile
* @var string
*/
private $logFile;
/**
* session id
* @var string
*/
private $sessid;
/**
* @var string
*/
private $token;
/**
* Name of statusfile
* @var string
*/
private $statusFile;
/**
* Name of temporary directory, to here extract the backup tarball
* @var string
*/
private $tmpDir;
/**
* @var string
*/
// private $loglevel = 'warn';
public $loglevel = 'warn';
// public $loglevel = 'debug';
/**
* @var GreenBox
*/
private $gb;
private $ACCESS_TYPE = 'restore';
/**
* @param GreenBox $gb
* greenbox object reference
*/
public function __construct(&$gb)
{
global $CC_CONFIG;
$this->gb =& $gb;
$this->token = null;
$this->logFile = $CC_CONFIG['bufferDir'].'/'.$this->ACCESS_TYPE.'.log';
if ($this->loglevel == 'debug') {
$this->addLogItem("-I- ".date("Ymd-H:i:s")." construct\n");
}
}
/**
* Call asyncronously the restore procedure. Restore from backup.
*
* @param string $sessid
* session id
* @param string $backup_file
* path of the backup file
* @return array
* hasharray with field:
* token string: backup token
*/
function openRestore($sessid, $backup_file)
{
if ($this->loglevel=='debug') {
$this->addLogItem("-I-".date("Ymd-H:i:s")." doRestore - sessid:$sessid\n");
}
$this->sessid = $sessid;
// generate token
$this->token = StoredFile::CreateGunid();
// status file -> working
$this->setEnviroment();
file_put_contents($this->statusFile, 'working');
//call the restore script in background
$command = dirname(__FILE__).'/../bin/restore.php';
$runLog = "/dev/null";
$params = "{$backup_file} {$this->statusFile} {$this->token} {$sessid}>> $runLog &";
$ret = system("$command $params", $st);
if ($this->loglevel=='debug') {
$this->addLogItem("-I-".date("Ymd-H:i:s")." restore.php call: $st/$ret\n");
}
return array('token'=>$this->token);
}
/**
* Check the status of restore
*
* @param string $token
* @return array
* hasharray with field:
* status : string - susccess | working | fault
* faultString : string - description of fault
* token : stirng - backup token
* url : string - access url
* tmpfile : string - access filename
*/
function checkRestore($token)
{
if ($this->loglevel == 'debug') {
$this->addLogItem("-I- ".date("Ymd-H:i:s")." checkBackup - token:$token\n");
}
$this->token = $token;
$this->setEnviroment();
if (is_file($this->statusFile)) {
$r = array();
$stat = file_get_contents($this->statusFile);
if (strpos($stat,'fault|') !== false) {
list($stat,$message) = explode('|',$stat);
}
$r['status'] = $stat;
if ($stat=='fault') {
$r['faultString'] = $message;
} else {
$r['faultString'] = '';
}
return $r;
} else {
return PEAR::raiseError('Restore::checkRestore: invalid token!');
}
}
/**
* Check the status of restore.
*
* @param string $token
* @return array
* hasharray with field:
* status : boolean - is success
*/
function closeRestore($token)
{
if ($this->loglevel=='debug') {
$this->addLogItem("-I- ".date("Ymd-H:i:s")." checkBackup - token:$token\n");
}
$this->token = $token;
$this->setEnviroment();
$this->rRmDir($this->tmpDir);
unlink($this->statusFile);
return array("status" => !is_file($this->statusFile));
}
/**
* Do restore in background
*
* this function is called from the asyncron commandline script
* ../bin/restore.php
*
* @param string $backupfile
* path of backupfile
* @param string $token
* restore token
* @param string $sessid
* session id
*/
function startRestore($backupfile, $token, $sessid)
{
if ($this->loglevel=='debug') {
$this->addLogItem("-I- ".date("Ymd-H:i:s")." startRestore - bufile:$backupfile | token:$token\n");
}
$this->token = $token;
$this->sessid = $sessid;
$this->setEnviroment();
// extract tarball
$command = 'tar -xf '.$backupfile .' --directory '.$this->tmpDir;
$res = system($command);
//$this->addLogItem('command: '.$command."\n");
//$this->addLogItem('res: '.$res."\n");
//simple check of archive format
if (is_dir($this->tmpDir.'audioClip/') &&
is_dir($this->tmpDir.'meta-inf/') &&
is_dir($this->tmpDir.'playlist/')) {
//search metafiles
$this->metafiles = $this->getMetaFiles();
#$this->addLogItem('metafiles:'.print_r($this->metafiles,true));
//add to storage server
foreach ($this->metafiles as $info) {
$r = $this->addFileToStorage($info['file'],$info['type'],$info['id']);
if (PEAR::isError($r)) {
$this->addLogItem("-E- ".date("Ymd-H:i:s").
" startRestore - addFileToStorage \n".
"(".$put->getMessage()."/".$put->getUserInfo().")\n"
);
file_put_contents($this->statusFile, 'fault|'.$put->getMessage()."/".$put->getUserInfo());
return;
}
}
} else {
$this->addLogItem("-E- ".date("Ymd-H:i:s")." startRestore - invalid archive format\n");
file_put_contents($this->statusFile, 'fault|invalid archive format');
return;
}
file_put_contents($this->statusFile, 'success');
// unlink($backupfile);
}
/**
* Get the metafiles.
*
* @return array
* array of hasharray with field:
* file : string - metafile path
* type : stirng - audioClip | playlist
* id : string - the backuped gunid
*/
function getMetaFiles()
{
if ($this->loglevel=='debug') {
$this->addLogItem("-I- ".date("Ymd-H:i:s")." getMetaFiles - tmpDir:{$this->tmpDir}\n");
}
$audioclips = scandir($this->tmpDir.'audioClip/');
$playlists = scandir($this->tmpDir.'playlist/');
for ($i = 0; $i < count($audioclips); $i++) {
if (strpos($audioclips[$i],'xml')!==false)
$r[] = array('file' => $this->tmpDir.'audioClip/'.$audioclips[$i],
'type' => 'audioClip',
'id' => str_replace('.xml','',$audioclips[$i]));
}
for ($i = 0; $i < count($playlists); $i++) {
if (strpos($playlists[$i],'xml') !== false)
$r[] = array('file' => $this->tmpDir.'playlist/'.$playlists[$i],
'type' => 'playlist',
'id' => str_replace('.xml','',$playlists[$i]));
}
return $r;
}
/**
* Add the file to the storage server.
*
* @param string $file
* path of metafile
* @param string $type
* restore token
* @param string $sessid
* session id
*
* @return mixed
* true if success or PEAR_error
*/
// function addFileToStorage($file,$type,$gunid)
// {
// if ($this->loglevel=='debug') {
// $this->addLogItem("-I- ".date("Ymd-H:i:s")." addFileToStorage - file:$file | type:$type | id:$gunid\n");
// }
// require_once("XmlParser.php");
// $tree = XmlParser::parse($file);
// $mediaFileLP = str_replace('.xml','',$file);
// $mediaFileLP = ($type=='audioClip' && is_file($mediaFileLP))?$mediaFileLP:'';
// $ex = $this->gb->existsFile($this->sessid,$gunid);
// if (PEAR::isError($ex)) {
// $this->addLogItem("-E- ".date("Ymd-H:i:s").
// " addFileToStorage - existsFile($gunid) ".
// "(".$ex->getMessage()."/".$ex->getUserInfo().")\n"
// );
// }
// if (!PEAR::isError($ex) && $ex) { // file is exists in storage server
// //replace it
// $id = BasicStor::IdFromGunid($gunid);
// $replace = $this->gb->replaceFile(
// $id, # id int, virt.file's local id
// $mediaFileLP, # mediaFileLP string, local path of media file
// $file, # mdataFileLP string, local path of metadata file
// $this->sessid); # sessid string, session id
// if (PEAR::isError($replace)) {
// $this->addLogItem("-E- ".date("Ymd-H:i:s").
// " addFileToStorage - replaceFile Error ".
// "(".$replace->getMessage()."/".$replace->getUserInfo().")\n"
// );
// file_put_contents($this->statusFile, 'fault|'.$replace->getMessage()."/".$replace->getUserInfo());
// return $replace;
// }
// #$this->addLogItem("replace it \n");
// } else {
// // add as new
// $name = $tree->children[0]->children[0]->content;
// if (empty($name)) {
// $name = $tree->attrs['title']->val;
// }
// if (empty($name)) {
// $name = '???';
// }
// if ($this->loglevel=='debug') {
// $this->addLogItem("-I- ".date("Ymd-H:i:s")." putFile\n".
// "$name, $mediaFileLP, $file, {$this->sessid}, $gunid, $type \n"
// );
// }
// $values = array(
// "filename" => $name,
// "filepath" => $mediaFileLP,
// "metadata" => $file,
// "gunid" => $gunid,
// "filetype" => $type
// );
// $put = $this->gb->putFile($values, $this->sessid);
// //$this->addLogItem("add as new \n");
// if (PEAR::isError($put)) {
// $this->addLogItem("-E- ".date("Ymd-H:i:s").
// " addFileToStorage - putFile Error ".
// "(".$put->getMessage()."/".$put->getUserInfo().")\n"
// ."\n---\n".file_get_contents($file)."\n---\n"
// );
// file_put_contents($this->statusFile, 'fault|'.$put->getMessage()."/".$put->getUserInfo());
// //$this->addLogItem("Error Object: ".print_r($put,true)."\n");
// return $put;
// }
// }
// $ac = StoredFile::RecallByGunid($gunid);
// if (is_null($ac) || PEAR::isError($ac)) {
// return $ac;
// }
// $res = $ac->setState('ready');
// if (PEAR::isError($res)) {
// return $res;
// }
// return true;
// }
/**
* Figure out the environment to the backup.
*
*/
function setEnviroment()
{
global $CC_CONFIG;
if ($this->loglevel=='debug') {
$this->addLogItem("-I- ".date("Ymd-H:i:s")." setEnviroment\n");
}
$this->statusFile = $CC_CONFIG['accessDir'].'/'.$this->token.'.status';
$this->tmpDir = '/tmp/ls_restore/'.$this->token.'/';
$this->rMkDir($this->tmpDir);
}
/**
* Add a line to the logfile.
*
* @param string $item
* the new row of log file
*/
function addLogItem($item)
{
$f = fopen ($this->logFile,'a');
flock($f,LOCK_SH);
fwrite($f,$item);
flock($f,LOCK_UN);
fclose($f);
//echo file_get_contents($this->logFile)."<BR><BR>\n\n";
}
/**
* Delete a directory recursive
*
* @param string $dirname
* path of dir
*
* @return boolean
* is success
*/
function rRmDir($dirname)
{
if (is_dir($dirname)) {
$dir_handle = opendir($dirname);
}
while ($file = readdir($dir_handle)) {
if ($file!="." && $file!="..") {
if (!is_dir($dirname."/".$file)) {
unlink ($dirname."/".$file);
} else {
Restore::rRmDir($dirname."/".$file);
}
}
}
closedir($dir_handle);
rmdir($dirname);
return true;
}
/**
* Create a directory recursive
*
* @param string $dirname
* path of dir.
* @param int $mode
* octal - rights of dir.
* @param boolean $recursive
* do it recursive.
*
* @return boolean
*/
function rMkDir($dirname, $mode=0777, $recursive=true)
{
if (is_null($dirname) || $dirname === "" ) {
return false;
}
if (is_dir($dirname) || $dirname === "/" ) {
return true;
}
if ($this->rMkDir(dirname($dirname), $mode, $recursive)) {
return mkdir($dirname, $mode);
}
return false;
}
} // class Restore

View file

@ -396,16 +396,28 @@ class Schedule {
$row["id"] = $row["group_id"];
}
} else {
$sql = "SELECT MIN(name) AS name, MIN(creator) AS creator, group_id, "
." SUM(clip_length) AS clip_length,"
." MIN(file_id) AS file_id, COUNT(*) as count,"
." MIN(playlist_id) AS playlist_id, MIN(starts) AS starts, MAX(ends) AS ends"
." FROM $CC_CONFIG[scheduleTable]"
." LEFT JOIN $CC_CONFIG[playListTable] ON playlist_id = $CC_CONFIG[playListTable].id"
." WHERE (starts >= TIMESTAMP '$p_fromDateTime') AND (ends <= TIMESTAMP '$p_toDateTime')"
." GROUP BY group_id"
$sql = "SELECT MIN(st.name) AS name,"
." MIN(pt.creator) AS creator,"
." st.group_id, "
." SUM(st.clip_length) AS clip_length,"
." MIN(st.file_id) AS file_id,"
." COUNT(*) as count,"
." MIN(st.playlist_id) AS playlist_id,"
." MIN(st.starts) AS starts,"
." MAX(st.ends) AS ends,"
." MIN(sh.name) AS show_name"
." FROM $CC_CONFIG[scheduleTable] as st"
." LEFT JOIN $CC_CONFIG[playListTable] as pt"
." ON st.playlist_id = pt.id"
." LEFT JOIN $CC_CONFIG[showInstances] as si"
." ON st.instance_id = si.id"
." LEFT JOIN $CC_CONFIG[showTable] as sh"
." ON si.show_id = sh.id"
." WHERE (st.starts >= TIMESTAMP '$p_fromDateTime')"
." AND (st.ends <= TIMESTAMP '$p_toDateTime')"
." GROUP BY st.group_id"
." ORDER BY starts";
//var_dump($sql);
$rows = $CC_DBC->GetAll($sql);
if (!PEAR::isError($rows)) {
foreach ($rows as &$row) {
@ -499,6 +511,22 @@ class Schedule {
return $rows;
}
public static function GetShowInstanceItems($instance_id){
global $CC_CONFIG, $CC_DBC;
$sql = "SELECT DISTINCT pt.name, ft.track_title, ft.artist_name, ft.album_title, st.starts, st.ends, st.clip_length, st.media_item_played, st.group_id, show.name as show_name, st.instance_id"
." FROM $CC_CONFIG[scheduleTable] st, $CC_CONFIG[filesTable] ft, $CC_CONFIG[playListTable] pt, $CC_CONFIG[showInstances] si, $CC_CONFIG[showTable] show"
." WHERE st.playlist_id = pt.id"
." AND st.file_id = ft.id"
." AND st.instance_id = si.id"
." AND si.show_id = show.id"
." AND instance_id = $instance_id"
." ORDER BY st.starts";
$rows = $CC_DBC->GetAll($sql);
return $rows;
}
public static function UpdateMediaPlayedStatus($id){
global $CC_CONFIG, $CC_DBC;
$sql = "UPDATE ".$CC_CONFIG['scheduleTable']
@ -618,26 +646,24 @@ class Schedule {
public static function ExportRangeAsJson($p_fromDateTime, $p_toDateTime)
{
global $CC_CONFIG, $CC_DBC;
$range_start = Schedule::PypoTimeToCcTime($p_fromDateTime);
$range_end = Schedule::PypoTimeToCcTime($p_toDateTime);
$range_dt = array('start' => $range_start, 'end' => $range_end);
//var_dump($range_dt);
// Scheduler wants everything in a playlist
$data = Schedule::GetItems($range_start, $range_end, true);
//echo "<pre>";var_dump($data);
$playlists = array();
if (is_array($data) && count($data) > 0)
if (is_array($data))
{
foreach ($data as $dx)
{
// Is this the first item in the playlist?
$start = $dx['start'];
// chop off subseconds
//chop off subseconds
$start = substr($start, 0, 19);
// Start time is the array key, needs to be in the format "YYYY-MM-DD-HH-mm-ss"
//Start time is the array key, needs to be in the format "YYYY-MM-DD-HH-mm-ss"
$pkey = Schedule::CcTimeToPypoTime($start);
$timestamp = strtotime($start);
$playlists[$pkey]['source'] = "PLAYLIST";
@ -647,6 +673,7 @@ class Schedule {
$playlists[$pkey]['duration'] = $dx['clip_length'];
$playlists[$pkey]['played'] = '0';
$playlists[$pkey]['schedule_id'] = $dx['group_id'];
$playlists[$pkey]['show_name'] = $dx['show_name'];
$playlists[$pkey]['user_id'] = 0;
$playlists[$pkey]['id'] = $dx["playlist_id"];
$playlists[$pkey]['start'] = Schedule::CcTimeToPypoTime($dx["start"]);
@ -686,11 +713,11 @@ class Schedule {
}
$result = array();
$result['status'] = array('range' => $range_dt, 'version' => "0.2");
$result['status'] = array('range' => array('start' => $range_start, 'end' => $range_end), 'version' => "1.1");
$result['playlists'] = $playlists;
$result['check'] = 1;
print json_encode($result);
return $result;
}

View file

@ -768,4 +768,34 @@ class Show_DAL{
return $rows;
}
public static function GetShowsInRange($timeNow, $start, $end){
global $CC_CONFIG, $CC_DBC;
$sql = "SELECT *,"
." si.starts as start_timestamp,"
." si.ends as end_timestamp,"
." si.id as instance_id"
." FROM "
." $CC_CONFIG[showInstances] si,"
." $CC_CONFIG[showTable] s"
." WHERE si.show_id = s.id"
." AND ((si.starts < TIMESTAMP '$timeNow' - INTERVAL '$start seconds' AND si.ends > TIMESTAMP '$timeNow' - INTERVAL '$start seconds')"
." OR (si.starts > TIMESTAMP '$timeNow' - INTERVAL '$start seconds' AND si.ends < TIMESTAMP '$timeNow' + INTERVAL '$end seconds')"
." OR (si.starts < TIMESTAMP '$timeNow' + INTERVAL '$end seconds' AND si.ends > TIMESTAMP '$timeNow' + INTERVAL '$end seconds'))"
." ORDER BY si.starts";
$rows = $CC_DBC->GetAll($sql);
$showsMap = array();
$rowsCount = count($rows);
for ($i=0; $i<$rowsCount; $i++){
$rows[$i]['items'] = array();
array_push($rows[$i]['items'],
array("s", $rows[$i]["starts"], $rows[$i]["starts"], $rows[$i]["ends"], "", "", "", "", "", $rows[$i]["name"], $rows[$i]["instance_id"], ""));
$showsMap[$rows[$i]['instance_id']] = $rows[$i];
}
return $showsMap;
}
}

View file

@ -13,80 +13,11 @@ define('ALIBERR_BADSMEMB', 21);
* @subpackage Alib
* @copyright 2010 Sourcefabric O.P.S.
* @license http://www.gnu.org/licenses/gpl.txt
* @see ObjClasses
* @see Alib
*/
class Subjects {
/* ======================================================= public methods */
/**
* Add new subject (a.k.a. "user")
*
* @param string $p_login
* @param string $p_pass
* @param string $p_realname
* @param boolean $p_passenc
* password already encrypted if true
* @return int|PEAR_Error
*/
public static function AddSubj($p_login, $p_pass=NULL, $p_realname='', $p_passenc=FALSE)
{
global $CC_CONFIG, $CC_DBC;
if (!$p_login) {
return $CC_DBC->raiseError("Subjects::AddSubj: empty login");
}
$id = $CC_DBC->nextId($CC_CONFIG['subjSequence']);
if (PEAR::isError($id)) {
return $id;
}
if (!is_null($p_pass) && !$p_passenc) {
$p_pass = md5($p_pass);
}
$sql = "INSERT INTO ".$CC_CONFIG['subjTable']." (id, login, pass, type, realname)"
." VALUES ($id, '$p_login', ".
(is_null($p_pass) ? "'!', 'G'" : "'$p_pass', 'U'").",
'$p_realname')";
$r = $CC_DBC->query($sql);
if (PEAR::isError($r)) {
return $r;
}
return $id;
}
/**
* Remove subject by uid or by login
*
* @param string $login
* @param int $uid
* @return boolean|PEAR_Error
*/
public static function RemoveSubj($login, $uid=NULL)
{
global $CC_CONFIG, $CC_DBC;
if (is_null($uid)) {
$uid = Subjects::GetSubjId($login);
}
if (PEAR::isError($uid)) {
return $uid;
}
$sql = "DELETE FROM ".$CC_CONFIG['smembTable']
." WHERE (uid='$uid' OR gid='$uid') AND mid is null";
$r = $CC_DBC->query($sql);
if (PEAR::isError($r)) {
return $r;
}
$sql2 = "DELETE FROM ".$CC_CONFIG['subjTable']
." WHERE login='$login'";
$r = $CC_DBC->query($sql2);
if (PEAR::isError($r)) {
return $r;
}
return Subjects::_rebuildRels();
} // fn removeSubj
/**
* Check login and password
*
@ -109,28 +40,6 @@ class Subjects {
} // fn authenticate
/**
* Set lastlogin or lastfail timestamp
*
* @param string $login
* @param boolean $failed
* true=> set lastfail, false=> set lastlogin
* @return boolean|int|PEAR_Error
*/
public static function SetTimeStamp($login, $failed=FALSE)
{
global $CC_CONFIG, $CC_DBC;
$fld = ($failed ? 'lastfail' : 'lastlogin');
$sql = "UPDATE ".$CC_CONFIG['subjTable']." SET $fld=now()"
." WHERE login='$login'";
$r = $CC_DBC->query($sql);
if (PEAR::isError($r)) {
return $r;
}
return TRUE;
} // fn setTimeStamp
/**
* Change user password
*
@ -169,93 +78,6 @@ class Subjects {
/* --------------------------------------------------------------- groups */
/**
* Add {login} and direct/indirect members to {gname} and to groups,
* where {gname} is [in]direct member
*
* @param string $login
* @param string $gname
* @return int|PEAR_Error
*/
public static function AddSubjectToGroup($login, $gname)
{
$uid = Subjects::GetSubjId($login);
if (PEAR::isError($uid)) {
return $uid;
}
$gid = Subjects::GetSubjId($gname);
if (PEAR::isError($gid)) {
return $gid;
}
$isgr = Subjects::IsGroup($gid);
if (PEAR::isError($isgr)) {
return $isgr;
}
if (!$isgr) {
return PEAR::raiseError("Subjects::addSubj2Gr: Not a group ($gname)", ALIBERR_NOTGR);
}
// add subject and all [in]direct members to group $gname:
$mid = Subjects::_plainAddSubjectToGroup($uid, $gid);
if (PEAR::isError($mid)) {
return $mid;
}
// add it to all groups where $gname is [in]direct member:
$marr = Subjects::_listRMemb($gid);
if (PEAR::isError($marr)) {
return $marr;
}
foreach ($marr as $k => $v) {
$r = Subjects::_plainAddSubjectToGroup(
$uid, $v['gid'], intval($v['level'])+1, $v['id']);
if (PEAR::isError($r)) {
return $r;
}
}
return $mid;
} // fn addSubj2Gr
/**
* Remove subject from group
*
* @param string $login
* @param string $gname
* @return boolean|PEAR_Error
*/
public static function RemoveSubjectFromGroup($login, $gname)
{
global $CC_CONFIG, $CC_DBC;
$uid = Subjects::GetSubjId($login);
if (PEAR::isError($uid)) {
return $uid;
}
$gid = Subjects::GetSubjId($gname);
if (PEAR::isError($gid)) {
return $gid;
}
$sql = "SELECT id FROM ".$CC_CONFIG['smembTable']
." WHERE uid='$uid' AND gid='$gid' AND mid is null";
$mid = $CC_DBC->getOne($sql);
if (is_null($mid)) {
return FALSE;
}
if (PEAR::isError($mid)) {
return $mid;
}
// remove it:
$r = Subjects::_removeMemb($mid);
if (PEAR::isError($r)) {
return $r;
}
// and rebuild indirect memberships:
$r = Subjects::_rebuildRels();
if (PEAR::isError($r)) {
return $r;
}
return TRUE;
} // fn removeSubjFromGr
/* --------------------------------------------------------- info methods */
/**
@ -274,114 +96,6 @@ class Subjects {
} // fn getSubjId
/**
* Get subject name (login) from id
*
* @param int $id
* @param string $fld
* @return string|PEAR_Error
*/
public static function GetSubjName($id, $fld='login')
{
global $CC_CONFIG;
global $CC_DBC;
$sql = "SELECT $fld FROM ".$CC_CONFIG['subjTable']
." WHERE id='$id'";
return $CC_DBC->getOne($sql);
} // fn getSubjName
/**
* Get one subject from the table.
*
* @param string $p_fieldValue
* @param string $p_fieldName
* @return array
*/
public static function GetSubject($p_fieldValue, $p_fieldName='login')
{
global $CC_CONFIG, $CC_DBC;
if (!in_array($p_fieldName, array("login", "id"))) {
return null;
}
$escapedValue = pg_escape_string($p_fieldValue);
$sql = "SELECT * FROM ".$CC_CONFIG['subjTable']
." WHERE $p_fieldName='$escapedValue'";
$row = $CC_DBC->GetRow($sql);
return $row;
}
/**
* Get all subjects
*
* @param string $flds
* @return array|PEAR_Error
*/
public static function GetSubjects($flds='id, login')
{
global $CC_CONFIG, $CC_DBC;
$sql = "SELECT $flds FROM ".$CC_CONFIG['subjTable'];
return $CC_DBC->getAll($sql);
} // fn getSubjects
/**
* Get subjects with count of direct members
*
* @return array|PEAR_Error
*/
public static function GetSubjectsWCnt()
{
global $CC_CONFIG, $CC_DBC;
$sql = "SELECT count(m.uid)as cnt, s.id, s.login, s.type"
." FROM ".$CC_CONFIG['subjTable']." s"
." LEFT JOIN ".$CC_CONFIG['smembTable']." m ON m.gid=s.id"
." WHERE m.mid is null"
." GROUP BY s.id, s.login, s.type"
." ORDER BY s.id";
return $CC_DBC->getAll($sql);
} // fn getSubjectsWCnt
/**
* Return true if subject is a group
*
* @param int $gid
* @return boolean|PEAR_Error
*/
public static function IsGroup($gid)
{
global $CC_CONFIG, $CC_DBC;
if (empty($gid)) {
return FALSE;
}
$sql = "SELECT type FROM ".$CC_CONFIG['subjTable']
." WHERE id='$gid'";
$r = $CC_DBC->getOne($sql);
if (PEAR::isError($r)) {
return $r;
}
return ($r === 'G');
} // fn isGroup
/**
* List direct members of group
*
* @param int $gid
* @return array|PEAR_Error
*/
public static function ListGroup($gid)
{
global $CC_CONFIG, $CC_DBC;
$sql = "SELECT s.id, s.login, s.type"
." FROM ".$CC_CONFIG['smembTable']." m, ".$CC_CONFIG['subjTable']." s"
." WHERE m.uid=s.id AND m.mid is null AND m.gid='$gid'";
return $CC_DBC->getAll($sql);
} // fn listGroup
/**
* Return true if uid is [id]direct member of gid
*
@ -405,279 +119,5 @@ class Subjects {
} // fn isMemberOf
/* ==================================================== "private" methods */
/**
* Create membership record
*
* @param int $uid
* @param int $gid
* @param int $level
* @param int $mid
* @return int|PEAR_Error
*/
private static function _addMemb($uid, $gid, $level=0, $mid='null')
{
global $CC_CONFIG, $CC_DBC;
if ($uid == $gid) {
return PEAR::raiseError("Subjects::_addMemb: uid==gid ($uid)", ALIBERR_BADSMEMB);
}
$sql = "SELECT id, level, mid FROM ".$CC_CONFIG['smembTable']
." WHERE uid='$uid' AND gid='$gid' ORDER BY level ASC";
$a = $CC_DBC->getAll($sql);
if (PEAR::isError($a)) {
return $a;
}
if (count($a) > 0) {
$a0 = $a[0];
$id = $a0['id'];
if ($level < intval($a0['level'])){
$sql2 = "UPDATE ".$CC_CONFIG['smembTable']
." SET level='$level', mid=$mid WHERE id='{$a0['id']}'";
$r = $CC_DBC->query($sql2);
if (PEAR::isError($r)) {
return $r;
}
}
} else {
$id = $CC_DBC->nextId($CC_CONFIG['smembSequence']);
if (PEAR::isError($id)) {
return $id;
}
$sql3 = "INSERT INTO ".$CC_CONFIG['smembTable']." (id, uid, gid, level, mid)"
." VALUES ($id, $uid, $gid, $level, $mid)";
$r = $CC_DBC->query($sql3);
if (PEAR::isError($r)) {
return $r;
}
}
return $id;
} // fn _addMemb
/**
* Remove membership record
*
* @param int $mid
* @return null|PEAR_Error
*/
private static function _removeMemb($mid)
{
global $CC_CONFIG, $CC_DBC;
$sql = "DELETE FROM ".$CC_CONFIG['smembTable']
." WHERE id='$mid'";
return $CC_DBC->query($sql);
} // fn _removeMemb
/**
* List [in]direct members of group
*
* @param int $gid
* @param int $uid
* @return array|PEAR_Error
*/
private static function _listMemb($gid, $uid=NULL)
{
global $CC_CONFIG, $CC_DBC;
$sql = "SELECT id, uid, level FROM ".$CC_CONFIG['smembTable']
." WHERE gid='$gid'".(is_null($uid) ? '' : " AND uid='$uid'");
return $CC_DBC->getAll($sql);
} // fn _listMemb
/**
* List groups where uid is [in]direct member
*
* @param int $gid
* @param int $uid
* @return array|PEAR_Error
*/
private static function _listRMemb($uid, $gid=NULL)
{
global $CC_CONFIG, $CC_DBC;
$sql = "SELECT id, gid, level FROM ".$CC_CONFIG['smembTable']
." WHERE uid='$uid'".(is_null($gid) ? '' : " AND gid='$gid'");
return $CC_DBC->getAll($sql);
} // fn listRMemb
/**
* Add uid and its [in]direct members to gid
*
* @param int $uid
* @param int $gid
* @param int $level
* @param int $rmid
* @return int|PEAR_Error
*/
private static function _plainAddSubjectToGroup($uid, $gid, $level=0, $rmid='null')
{
$mid = Subjects::_addMemb($uid, $gid, $level, $rmid);
if (PEAR::isError($mid)) {
return $mid;
}
$marr = Subjects::_listMemb($uid);
if (PEAR::isError($marr)) {
return $marr;
}
foreach ($marr as $k => $v) {
$r = Subjects::_addMemb(
$v['uid'], $gid, intval($v['level'])+$level+1, $mid
);
if (PEAR::isError($r)) {
return $r;
}
}
return $mid;
}
/**
* Rebuild indirect membership records<br>
* it's probably more complicated to do removing without rebuild ...
*
* @return true|PEAR_Error
*/
private static function _rebuildRels()
{
global $CC_CONFIG, $CC_DBC;
$CC_DBC->query("BEGIN");
$r = $CC_DBC->query("LOCK TABLE ".$CC_CONFIG['smembTable']);
if (PEAR::isError($r)) {
return $r;
}
$sql = "DELETE FROM ".$CC_CONFIG['smembTable']
." WHERE mid is not null";
$r = $CC_DBC->query($sql);
if (PEAR::isError($r)) {
return $r;
}
$arr = $CC_DBC->getAll("SELECT uid, gid FROM ".$CC_CONFIG['smembTable']);
// WHERE mid is null
if (PEAR::isError($arr)) {
return $arr;
}
foreach ($arr as $it) {
$marr = Subjects::_listRMemb($it['gid']);
if (PEAR::isError($marr)) {
return $marr;
}
foreach ($marr as $k => $v) {
$r = Subjects::_plainAddSubjectToGroup(
$it['uid'], $v['gid'], intval($v['level'])+1, $v['id']
);
if (PEAR::isError($r)) {
return $r;
}
}
}
$r = $CC_DBC->query("COMMIT");
if (PEAR::isError($r)) {
return $r;
}
return TRUE;
} // fn _rebuildRels
/* =============================================== test and debug methods */
/**
* Dump subjects for debug
*
* @param string $indstr
* indentation string
* @param string $ind
* actual indentation
* @return string
*/
public static function DumpSubjects($indstr=' ', $ind='')
{
$r = $ind.join(', ', array_map(
create_function('$v', 'return "{$v[\'login\']}({$v[\'cnt\']})";'),
Subjects::GetSubjectsWCnt()
))."\n";
return $r;
} // fn dumpSubjects
/**
* Delete all subjects and membership records
*
* @return void
*/
public static function DeleteData()
{
global $CC_CONFIG, $CC_DBC;
$CC_DBC->query("DELETE FROM ".$CC_CONFIG['subjTable']);
$CC_DBC->query("DELETE FROM ".$CC_CONFIG['smembTable']);
//ObjClasses::DeleteData();
} // fn deleteData
/**
* Insert test data
*
* @return array
*/
public function TestData()
{
// $tdata = ObjClasses::TestData();
// $o['root'] = Subjects::AddSubj('root', 'q');
// $o['test1'] = Subjects::AddSubj('test1', 'a');
// $o['test2'] = Subjects::AddSubj('test2', 'a');
// $o['test3'] = Subjects::AddSubj('test3', 'a');
// $o['test4'] = Subjects::AddSubj('test4', 'a');
// $o['test5'] = Subjects::AddSubj('test5', 'a');
// $o['gr1'] = Subjects::AddSubj('gr1');
// $o['gr2'] = Subjects::AddSubj('gr2');
// $o['gr3'] = Subjects::AddSubj('gr3');
// $o['gr4'] = Subjects::AddSubj('gr4');
// Subjects::AddSubjectToGroup('test1', 'gr1');
// Subjects::AddSubjectToGroup('test2', 'gr2');
// Subjects::AddSubjectToGroup('test3', 'gr3');
// Subjects::AddSubjectToGroup('test4', 'gr4');
// Subjects::AddSubjectToGroup('test5', 'gr1');
// Subjects::AddSubjectToGroup('gr4', 'gr3');
// Subjects::AddSubjectToGroup('gr3', 'gr2');
// $tdata['subjects'] = $o;
// return $tdata;
} // fn TestData
/**
* Make basic test
*
*/
public static function Test()
{
// $p = ObjClasses::Test();
// if (PEAR::isError($p)) {
// return $p;
// }
// Subjects::DeleteData();
// Subjects::TestData();
// $test_correct = "root(0), test1(0), test2(0), test3(0),".
// " test4(0), test5(0), gr1(2), gr2(2), gr3(2), gr4(1)\n";
// $test_dump = Subjects::DumpSubjects();
// Subjects::RemoveSubj('test1');
// Subjects::RemoveSubj('test3');
// Subjects::RemoveSubjectFromGroup('test5', 'gr1');
// Subjects::RemoveSubjectFromGroup('gr3', 'gr2');
// $test_correct .= "root(0), test2(0), test4(0), test5(0),".
// " gr1(0), gr2(1), gr3(1), gr4(1)\n";
// $test_dump .= Subjects::DumpSubjects();
// Subjects::DeleteData();
// if ($test_dump == $test_correct) {
// $test_log .= "subj: OK\n";
// return TRUE;
// } else {
// return PEAR::raiseError(
// 'Subjects::test:', 1, PEAR_ERROR_DIE, '%s'.
// "<pre>\ncorrect:\n{$test_correct}\n".
// "dump:\n{$test_dump}\n</pre>\n");
// }
} // fn test
} // class Subjects

File diff suppressed because it is too large Load diff

View file

@ -1,419 +0,0 @@
<?php
define('TR_LEAVE_CLOSED', TRUE);
/**
* Auxiliary class for transport records
*
* @package Airtime
* @subpackage StorageServer
* @copyright 2010 Sourcefabric O.P.S.
* @license http://www.gnu.org/licenses/gpl.txt
*/
class TransportRecord
{
/**
* @var DB
*/
//public $dbc;
/**
* @var GreenBox
*/
private $gb;
/**
* @var array
*/
//private $config;
/**
* @var Transport
*/
private $tr;
/**
* @var boolean
*/
private $recalled = FALSE;
/**
* @var boolean
*/
private $dropped = FALSE;
/**
* @param Transport $tr
* @return TransportRecord
*/
public function __construct(&$tr)
{
$this->tr =& $tr;
$this->gb =& $tr->gb;
}
/**
* Factory method
*
* @param Transport $tr
* @param string $trtype
* transport type (see Transport::install)
* @param string $direction
* 'up' | 'down'
* @param array $defaults
* default parameters (optional, internal use)
* @return TransportRecord
*/
function create(&$tr, $trtype, $direction='up', $defaults=array())
{
global $CC_DBC, $CC_CONFIG;
$trec = new TransportRecord($tr);
$trec->trtok = $trtok = $tr->_createTransportToken();
$trec->row = array_merge($defaults,
array('trtype'=>$trtype, 'direction'=>$direction));
$trec->recalled = TRUE;
if (!isset($defaults['title'])) {
$defaults['title'] = $trec->getTitle();
if (PEAR::isError($defaults['title'])) {
return $defaults['title'];
}
}
$id = $CC_DBC->nextId($CC_CONFIG['transSequence']);
$names = "id, trtok, direction, state, trtype, start, ts";
$values = "$id, '$trtok', '$direction', 'init', '$trtype', now(), now()";
foreach ($defaults as $k => $v) {
$sqlVal = $trec->_getSqlVal($k, $v);
$names .= ", $k";
$values .= ", $sqlVal";
}
$query = "
INSERT INTO ".$CC_CONFIG['transTable']."
($names)
VALUES
($values)
";
$res = $CC_DBC->query($query);
if (PEAR::isError($res)) {
return $res;
}
return $trec;
}
/**
* Recall transport record from DB
*
* @param Transport $tr
* @param string $trtok
* transport token
* @return TransportRecord
*/
function recall(&$tr, $trtok)
{
global $CC_DBC, $CC_CONFIG;
$trec = new TransportRecord($tr);
$trec->trtok = $trtok;
$row = $CC_DBC->getRow("
SELECT
id, trtok, state, trtype, direction,
to_hex(gunid)as gunid, to_hex(pdtoken)as pdtoken,
fname, localfile, url, rtrtok, mdtrtok, uid,
expectedsize, realsize, expectedsum, realsum,
errmsg, title, jobpid
FROM ".$CC_CONFIG['transTable']."
WHERE trtok='$trtok'
");
if (PEAR::isError($row)) {
return $row;
}
if (is_null($row)) {
return PEAR::raiseError("TransportRecord::recall:".
" invalid transport token ($trtok)", TRERR_TOK
);
}
$row['pdtoken'] = StoredFile::NormalizeGunid($row['pdtoken']);
$row['gunid'] = StoredFile::NormalizeGunid($row['gunid']);
$trec->row = $row;
$trec->recalled = TRUE;
return $trec;
}
/**
* Set state of transport record
*
* @param string $newState
* @param array $data
* other data fields to set
* @param string $oldState
* check old state and do nothing if differ
* @param boolean $lock
* check lock and do nothing if differ
* @return boolean success
*/
function setState($newState, $data=array(), $oldState=NULL, $lock=NULL)
{
global $CC_CONFIG, $CC_DBC;
$set = " state='$newState', ts=now()";
if (!is_null($lock)) {
$slock = ($lock ? 'Y' : 'N');
$nlock = (!$lock);
$snlock = ($nlock ? 'Y' : 'N');
$set .= ", lock='$snlock'";
}
foreach ($data as $k => $v) {
$set .= ", $k=".$this->_getSqlVal($k, $v);
}
$r = $CC_DBC->query("
UPDATE ".$CC_CONFIG['transTable']."
SET $set
WHERE trtok='{$this->trtok}'".
(is_null($oldState) ? '' : " AND state='$oldState'").
(is_null($lock) ? '' : " AND lock = '$slock'")
);
if (PEAR::isError($r)) {
return $r;
}
// return TRUE;
$affRows = $CC_DBC->affectedRows();
if (PEAR::isError($affRows)) {
return $affRows;
}
return ($affRows == 1);
}
/**
* Return state of transport record
*
* @return string
* state
*/
function getState()
{
if (!$this->recalled) {
return PEAR::raiseError("TransportRecord::getState:".
" not recalled ({$this->trtok})", TRERR_TOK
);
}
return $this->row['state'];
}
/**
* Set lock on transport record and save/clear process id
*
* @param boolean $lock
* lock if true, release lock if false
* @param int $pid
* process id
* @return mixed
* true or error
*/
function setLock($lock, $pid=NULL)
{
global $CC_CONFIG, $CC_DBC;
$pidsql = (is_null($pid) ? "NULL" : "$pid" );
if ($this->dropped) {
return TRUE;
}
$slock = ($lock ? 'Y' : 'N');
$nlock = (!$lock);
$snlock = ($nlock ? 'Y' : 'N');
$r = $CC_DBC->query("
UPDATE ".$CC_CONFIG['transTable']."
SET lock='$slock', jobpid=$pidsql, ts=now()
WHERE trtok='{$this->trtok}' AND lock = '$snlock'"
);
if (PEAR::isError($r)) {
return $r;
}
$affRows = $CC_DBC->affectedRows();
if (PEAR::isError($affRows)) {
return $affRows;
}
if ($affRows === 0) {
$ltxt = ($lock ? 'lock' : 'unlock' );
return PEAR::raiseError(
"TransportRecord::setLock: can't $ltxt ({$this->trtok})"
);
}
return TRUE;
}
/**
* Return type of transport
*
* @return string
* Transport type
*/
function getTransportType()
{
if (!$this->recalled) {
return PEAR::raiseError("TransportRecord::getTransportType:".
" not recalled ({$this->trtok})", TRERR_TOK
);
}
return $this->row['trtype'];
}
/**
* Kill transport job (on pause or cancel)
*
* @return string
* Transport type
*/
function killJob()
{
if (!$this->recalled) {
return PEAR::raiseError("TransportRecord::getTransportType:".
" not recalled ({$this->trtok})", TRERR_TOK
);
}
$jobpid = $this->row['jobpid'];
$res = system("pkill -P $jobpid", $status);
}
/**
* Set state to failed and set error message in transport record
*
* @param string $txt
* base part of error message
* @param PEAR_Error $eo
* (opt.) error msg can be construct from it
* @return mixed
* boolean true or error
*/
function fail($txt='', $eo=NULL)
{
if (!$this->recalled) {
return PEAR::raiseError("TransportRecord::fail:".
" not recalled ({$this->trtok})", TRERR_TOK
);
}
$msg = $txt;
if (!is_null($eo)) {
$msg .= $eo->getMessage()." ".$eo->getUserInfo().
" [".$eo->getCode()."]";
}
$r = $this->setState('failed', array('errmsg'=>$msg));
if (PEAR::isError($r)) {
return $r;
}
return TRUE;
}
/**
* Close transport record
*
* @return mixed
* boolean true or error
*/
function close()
{
global $CC_CONFIG, $CC_DBC;
if (!$this->recalled) {
return PEAR::raiseError("TransportRecord::close:".
" not recalled ({$this->trtok})", TRERR_TOK
);
}
if (TR_LEAVE_CLOSED) {
$r = $this->setState('closed');
if (PEAR::isError($r)) {
return $r;
}
} else {
$r = $CC_DBC->query("
DELETE FROM ".$CC_CONFIG['transTable']."
WHERE trtok='{$this->trtok}'
");
if (PEAR::isError($r)) {
return $r;
}
$this->recalled = FALSE;
$this->dropped = TRUE;
}
return TRUE;
}
/**
* Add field specific envelopes to values (e.g. ' around strings)
*
* @param string $fldName
* field name
* @param mixed $fldVal
* field value
* @return string
*/
function _getSqlVal($fldName, $fldVal)
{
switch ($fldName) {
case 'realsize':
case 'expectedsize':
case 'uid':
return ("$fldVal"!='' ? "$fldVal" : "NULL");
break;
case 'gunid':
case 'pdtoken':
return "x'$fldVal'::bigint";
break;
default:
$fldVal = pg_escape_string($fldVal);
return "'$fldVal'";
break;
}
}
/**
* Get title from transported object's metadata (if exists)
*
* @return string
* the title or descriptive string
*/
function getTitle()
{
$defStr = 'unknown';
$trtype = $this->getTransportType(); //contains recall check
if (PEAR::isError($trtype)) {
return $trtype;
}
switch ($trtype) {
case "audioclip":
case "playlist":
case "playlistPkg":
case "metadata":
$title = $this->gb->bsGetTitle(NULL, $this->row['gunid']);
if (is_null($title)) {
$title = $defStr;
}
if (PEAR::isError($title)) {
if ($title->getCode() == GBERR_FOBJNEX) {
$title = $defStr;
} else {
return $title;
}
}
break;
case "searchjob":
$title = 'searchjob';
break;
case "file":
$title = ( isset($this->row['localfile']) ?
basename($this->row['localfile']) : 'regular file');
break;
default:
$title = $defStr;
}
return $title;
}
} // class TransportRecord

View file

@ -1,385 +0,0 @@
<?php
define('VAL_ROOT', 110);
define('VAL_NOREQE', 111);
define('VAL_NOONEOF', 112);
define('VAL_UNKNOWNE', 113);
define('VAL_UNKNOWNA', 114);
define('VAL_NOTDEF', 115);
define('VAL_UNEXPONEOF', 116);
define('VAL_FORMAT', 117);
define('VAL_CONTENT', 118);
define('VAL_NOREQA', 119);
define('VAL_ATTRIB', 120);
define('VAL_PREDXML', 121);
/**
* Simple XML validator against structure stored in PHP hash-array hierarchy.
*
* Basic format files:
* <ul>
* <li>audioClipFormat.php</li>
* <li>webstreamFormat.php</li>
* <li>playlistFormat.php</li>
* </ul>
* It probably should be replaced by XML schema validation in the future.
*
* @package Airtime
* @subpackage StorageServer
* @copyright 2010 Sourcefabric O.P.S.
* @license http://www.gnu.org/licenses/gpl.txt
*/
class Validator {
/**
* Format type of validated document
* @var string
*/
private $format = NULL;
/**
* Preloaded format tree structure
* @var array
*/
private $formTree = NULL;
/**
* Gunid of validated file for identification in mass input
* @var string
*/
private $gunid = NULL;
/**
* Constructor
*
* @param string $format
* format type of validated document
* @param string $gunid
* gunid of validated file for identification in mass input
*/
public function __construct($format, $gunid)
{
$format = strtolower($format);
$this->format = $format;
$this->gunid = $gunid;
$formats = array(
'audioclip' => "audioClipFormat",
'playlist' => "playlistFormat",
'webstream' => "webstreamFormat",
);
if (!isset($formats[$format])) {
return $this->_err(VAL_FORMAT);
}
$formatName = $formats[$format];
$formatFile = dirname(__FILE__)."/$formatName.php";
if (!file_exists($formatFile)) {
return $this->_err(VAL_FORMAT);
}
require($formatFile);
$this->formTree = $$formatName;
}
/**
* Validate document - only wrapper for validateNode method
*
* @param object $data
* validated object tree
* @return mixed
* TRUE or PEAR::error
*/
function validate(&$data)
{
$r = $this->validateNode($data, $this->formTree['_root']);
return $r;
}
/**
* Validate one metadata value (on insert/update)
*
* @param string $fname
* parent element name
* @param string $category
* qualif.category name
* @param string $predxml
* 'A' | 'T' (attr or tag)
* @param string $value
* validated element value
* @return TRUE|PEAR_Error
*/
function validateOneValue($fname, $category, $predxml, $value)
{
$formTree =& $this->formTree;
switch ($predxml) {
case 'T':
if (!$this->isChildInFormat($fname, $category)) {
return $this->_err(VAL_UNKNOWNE, "$category in $fname");
}
break;
case 'A':
if (!$this->isAttrInFormat($fname, $category)) {
return $this->_err(VAL_UNKNOWNA, "$category in $fname");
}
break;
case 'N':
return TRUE;
break;
default:
return $this->_err(VAL_PREDXML, $predxml);
}
if (isset($formTree[$category]['regexp'])) {
// echo "XXX {$formTree[$fname]['regexp']} / ".$node->content."\n";
if (!preg_match("|{$formTree[$category]['regexp']}|", $value)) {
return $this->_err(VAL_CONTENT, "$category/$value");
}
}
}
/**
* Validation of one element node from object tree
*
* @param object $node
* validated node
* @param string $fname
* actual name in format structure
* @return mixed
* TRUE or PEAR::error
*/
function validateNode(&$node, $fname)
{
$dname = (($node->ns? $node->ns.":" : '').$node->name);
$formTree =& $this->formTree;
if (DEBUG) {
echo"\nVAL::validateNode: 1 $dname/$fname\n";
}
// check root node name:
if ($dname != $fname) {
return $this->_err(VAL_ROOT, $fname);
}
// check if this element is defined in format:
if (!isset($formTree[$fname])) {
return $this->_err(VAL_NOTDEF, $fname);
}
// check element content
if (isset($formTree[$fname]['regexp'])) {
// echo "XXX {$formTree[$fname]['regexp']} / ".$node->content."\n";
if (!preg_match("|{$formTree[$fname]['regexp']}|", $node->content)) {
return $this->_err(VAL_CONTENT, "$fname/{$node->content}");
}
}
// validate attributes:
$ra = $this->validateAttributes($node, $fname);
if (PEAR::isError($ra)) {
return $ra;
}
// validate children:
$r = $this->validateChildren($node, $fname);
if (PEAR::isError($r)) {
return $r;
}
return TRUE;
}
/**
* Validation of attributes
*
* @param object $node
* validated node
* @param string $fname
* actual name in format structure
* @return mixed
* TRUE or PEAR::error
*/
function validateAttributes(&$node, $fname)
{
$formTree =& $this->formTree;
$attrs = array();
// check if all attrs are permitted here:
foreach ($node->attrs as $i => $attr) {
$aname = (($attr->ns? $attr->ns.":" : '').$attr->name);
$attrs[$aname] =& $node->attrs[$i];
if (!$this->isAttrInFormat($fname, $aname)) {
return $this->_err(VAL_UNKNOWNA, $aname);
}
// check attribute format
// echo "XXA $aname\n";
if (isset($formTree[$aname]['regexp'])) {
// echo "XAR {$formTree[$fname]['regexp']} / ".$node->content."\n";
if (!preg_match("|{$formTree[$aname]['regexp']}|", $attr->val)) {
return $this->_err(VAL_ATTRIB, "$aname [".var_export($attr->val,TRUE)."]");
}
}
}
// check if all required attrs are here:
if (isset($formTree[$fname]['attrs'])) {
$fattrs =& $formTree[$fname]['attrs'];
if (isset($fattrs['required'])) {
foreach ($fattrs['required'] as $i => $attr) {
if (!isset($attrs[$attr])) {
return $this->_err(VAL_NOREQA, $attr);
}
}
}
}
return TRUE;
}
/**
* Validation children nodes
*
* @param object $node
* validated node
* @param string $fname
* actual name in format structure
* @return mixed
* TRUE or PEAR::error
*/
function validateChildren(&$node, $fname)
{
$formTree =& $this->formTree;
$childs = array();
// check if all children are permitted here:
foreach ($node->children as $i => $ch) {
$chname = (($ch->ns? $ch->ns.":" : '').$ch->name);
// echo "XXE $chname\n";
if (!$this->isChildInFormat($fname, $chname)) {
return $this->_err(VAL_UNKNOWNE, $chname);
}
// call children recursive:
$r = $this->validateNode($node->children[$i], $chname);
if (PEAR::isError($r)) {
return $r;
}
$childs[$chname] = TRUE;
}
// check if all required children are here:
if (isset($formTree[$fname]['childs'])) {
$fchilds =& $formTree[$fname]['childs'];
if (isset($fchilds['required'])) {
foreach ($fchilds['required'] as $i => $ch) {
if (!isset($childs[$ch])) return $this->_err(VAL_NOREQE, $ch);
}
}
// required one from set
if (isset($fchilds['oneof'])) {
$one = FALSE;
foreach ($fchilds['oneof'] as $i => $ch) {
if (isset($childs[$ch])) {
if ($one) {
return $this->_err(VAL_UNEXPONEOF, "$ch in $fname");
}
$one = TRUE;
}
}
if (!$one) {
return $this->_err(VAL_NOONEOF);
}
}
}
return TRUE;
}
/**
* Test if child is presented in format structure
*
* @param string $fname
* node name in format structure
* @param string $chname
* child node name
* @return boolean
*/
function isChildInFormat($fname, $chname)
{
$listo = $this->isInFormatAs($fname, $chname, 'childs', 'optional');
$listr = $this->isInFormatAs($fname, $chname, 'childs', 'required');
$list1 = $this->isInFormatAs($fname, $chname, 'childs', 'oneof');
return ($listo!==FALSE || $listr!==FALSE || $list1!==FALSE);
}
/**
* Test if attribute is presented in format structure
*
* @param string $fname
* node name in format structure
* @param string $aname
* attribute name
* @return boolean
*/
function isAttrInFormat($fname, $aname)
{
$listr = $this->isInFormatAs($fname, $aname, 'attrs', 'required');
$listi = $this->isInFormatAs($fname, $aname, 'attrs', 'implied');
$listn = $this->isInFormatAs($fname, $aname, 'attrs', 'normal');
return ($listr!==FALSE || $listi!==FALSE || $listn!==FALSE);
}
/**
* Check if node/attribute is presented in format structure
*
* @param string $fname
* node name in format structure
* @param string $chname
* node/attribute name
* @param string $nType
* 'childs' | 'attrs'
* @param string $reqType
* <ul>
* <li>for elements: 'required' | 'optional' | 'oneof'</li>
* <li>for attributes: 'required' | 'implied' | 'normal'</li>
* </ul>
* @return mixed
* boolean/int (index int format array returned if found)
*/
function isInFormatAs($fname, $chname, $nType='childs', $reqType='required')
{
$formTree =& $this->formTree;
$listed = (
isset($formTree[$fname][$nType][$reqType]) ?
array_search($chname, $formTree[$fname][$nType][$reqType]) :
FALSE
);
return $listed;
}
/**
* Error exception generator
*
* @param int $errno
* erron code
* @param string $par
* optional string for more descriptive error messages
* @return PEAR_Error
*/
function _err($errno, $par='')
{
$msg = array(
VAL_ROOT => 'Wrong root element',
VAL_NOREQE => 'Required element missing',
VAL_NOONEOF => 'One-of element missing',
VAL_UNKNOWNE => 'Unknown element',
VAL_UNKNOWNA => 'Unknown attribute',
VAL_NOTDEF => 'Not defined',
VAL_UNEXPONEOF => 'Unexpected second object from one-of set',
VAL_FORMAT => 'Unknown format',
VAL_CONTENT => 'Invalid content',
VAL_NOREQA => 'Required attribute missing',
VAL_ATTRIB => 'Invalid attribute format',
VAL_PREDXML => 'Invalid predicate type',
);
return PEAR::raiseError(
"Validator: {$msg[$errno]} #$errno ($par, gunid={$this->gunid})",
$errno
);
}
} // class Validator

View file

@ -1,326 +0,0 @@
<?php
$audioClipFormat = array(
'_root'=>'audioClip',
'audioClip'=>array(
'childs'=>array(
'required'=>array('metadata'),
),
),
'metadata'=>array(
'childs'=>array(
'required'=>array(
'dc:title', 'dcterms:extent'
),
'optional'=>array(
'dc:identifier',
'dc:creator', 'dc:source', 'ls:genre',
'ls:year', 'dc:type', 'dc:description', 'dc:format',
'ls:bpm', 'ls:rating', 'ls:encoded_by', 'ls:track_num',
'ls:disc_num', 'ls:disc_num', 'dc:publisher', 'ls:composer',
'ls:bitrate', 'ls:channels', 'ls:samplerate', 'ls:encoder',
'ls:crc', 'ls:lyrics', 'ls:orchestra', 'ls:conductor',
'ls:lyricist', 'ls:originallyricist', 'ls:radiostationname',
'ls:audiofileinfourl', 'ls:artisturl', 'ls:audiosourceurl',
'ls:radiostationurl', 'ls:buycdurl', 'ls:isrcnumber',
'ls:catalognumber', 'ls:originalartist', 'dc:rights',
'ls:license', 'dc:title', 'dcterms:temporal',
'dcterms:spatial', 'dcterms:entity', 'dc:description',
'dc:creator', 'dc:subject', 'dc:type', 'dc:format',
'dc:contributor', 'dc:language', 'dc:rights',
'dcterms:isPartOf', 'dc:date',
'dc:publisher',
// extra
'dcterms:alternative', 'ls:filename', 'ls:mtime',
// added lately by sebastian
'ls:mood',
),
),
'namespaces'=>array(
'dc'=>"http://purl.org/dc/elements/1.1/",
'dcterms'=>"http://purl.org/dc/terms/",
'xbmf'=>"http://www.streamonthefly.org/xbmf",
'xsi'=>"http://www.w3.org/2001/XMLSchema-instance",
'xml'=>"http://www.w3.org/XML/1998/namespace",
),
),
'dc:identifier'=>array(
'type'=>'Text',
'auto'=>TRUE,
),
'dc:title'=>array(
'type'=>'Text',
'attrs'=>array('implied'=>array('xml:lang')),
),
'dcterms:alternative'=>array(
'type'=>'Text',
'attrs'=>array('implied'=>array('xml:lang')),
),
'dcterms:extent'=>array(
'type'=>'Time',
// 'regexp'=>'^\d{2}:\d{2}:\d{2}.\d{6}$',
'regexp'=>'^((\d{1,2}:)?\d{1,2}:)?\d{1,20}(.\d{1,6})?$',
),
'dc:creator'=>array(
'type'=>'Text',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'dc:source'=>array(
'type'=>'Text',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:genre'=>array(
'type'=>'Menu',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:year'=>array(
'type'=>'Menu',
'area'=>'Music',
),
'dc:type'=>array(
'type'=>'Menu',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'dc:description'=>array(
'type'=>'Longtext',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'dc:format'=>array(
'type'=>'Menu',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:bpm'=>array(
'type'=>'Number',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:rating'=>array(
'type'=>'Number',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:encoded_by'=>array(
'type'=>'Text',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:track_num'=>array(
'type'=>'Menu',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:disc_num'=>array(
'type'=>'Menu',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:disc_num'=>array(
'type'=>'Menu',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'dc:publisher'=>array(
'type'=>'Text',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:composer'=>array(
'type'=>'Text',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:bitrate'=>array(
'type'=>'Number',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:channels'=>array(
'type'=>'Menu',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:samplerate'=>array(
'type'=>'Menu',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:encoder'=>array(
'type'=>'Text',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:crc'=>array(
'type'=>'Number',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:lyrics'=>array(
'type'=>'Longtext',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:orchestra'=>array(
'type'=>'Text',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:conductor'=>array(
'type'=>'Text',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:lyricist'=>array(
'type'=>'Text',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:originallyricist'=>array(
'type'=>'Text',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:radiostationname'=>array(
'type'=>'Text',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:audiofileinfourl'=>array(
'type'=>'URL',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:artisturl'=>array(
'type'=>'URL',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:audiosourceurl'=>array(
'type'=>'URL',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:radiostationurl'=>array(
'type'=>'URL',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:buycdurl'=>array(
'type'=>'URL',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:isrcnumber'=>array(
'type'=>'Number',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:catalognumber'=>array(
'type'=>'Number',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:originalartist'=>array(
'type'=>'Text',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'dc:rights'=>array(
'type'=>'Text',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:license'=>array(
'type'=>'Text',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'dc:title'=>array(
'type'=>'Text',
'area'=>'Talk',
'attrs'=>array('implied'=>array('xml:lang')),
),
'dcterms:temporal'=>array(
'type'=>'Time/Date',
'area'=>'Talk',
'attrs'=>array('implied'=>array('xml:lang')),
),
'dcterms:spatial'=>array(
'type'=>'Menu',
'area'=>'Talk',
'attrs'=>array('implied'=>array('xml:lang')),
),
'dcterms:entity'=>array(
'type'=>'Text',
'area'=>'Talk',
'attrs'=>array('implied'=>array('xml:lang')),
),
'dc:description'=>array(
'type'=>'Longtext',
'area'=>'Talk',
'attrs'=>array('implied'=>array('xml:lang')),
),
'dc:creator'=>array(
'type'=>'Menu',
'area'=>'Talk',
'attrs'=>array('implied'=>array('xml:lang')),
),
'dc:subject'=>array(
'type'=>'Text',
'area'=>'Talk',
'attrs'=>array('implied'=>array('xml:lang')),
),
'dc:type'=>array(
'type'=>'Menu',
'area'=>'Talk',
'attrs'=>array('implied'=>array('xml:lang')),
),
'dc:format'=>array(
'type'=>'Menu',
'area'=>'Talk',
'attrs'=>array('implied'=>array('xml:lang')),
),
'dc:contributor'=>array(
'type'=>'Text',
'area'=>'Talk',
'attrs'=>array('implied'=>array('xml:lang')),
),
'dc:language'=>array(
'type'=>'Menu',
'area'=>'Talk',
'attrs'=>array('implied'=>array('xml:lang')),
),
'dc:rights'=>array(
'type'=>'Menu',
'area'=>'Talk',
'attrs'=>array('implied'=>array('xml:lang')),
),
'dcterms:isPartOf'=>array(
'type'=>'Text',
'area'=>'Talk',
'attrs'=>array('implied'=>array('xml:lang')),
),
'dc:date'=>array(
'type'=>'Date',
'area'=>'Talk',
'attrs'=>array('implied'=>array('xml:lang')),
),
'dc:publisher'=>array(
'type'=>'Text',
'area'=>'Talk',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:filename'=>array(
'type'=>'Text',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:mtime'=>array(
'type'=>'Int',
// 'regexp'=>'^\d{4}(-\d{2}(-\d{2}(T\d{2}:\d{2}(:\d{2}\.\d+)?(Z)|([\+\-]?\d{2}:\d{2}))?)?)?$',
),
);

View file

@ -1,20 +0,0 @@
#!/usr/bin/php
<?php
require_once(dirname(__FILE__).'/../../conf.php');
require_once('DB.php');
require_once(dirname(__FILE__).'/../LocStor.php');
PEAR::setErrorHandling(PEAR_ERROR_RETURN);
$CC_DBC = DB::connect($CC_CONFIG['dsn'], TRUE);
$CC_DBC->setErrorHandling(PEAR_ERROR_RETURN);
$CC_DBC->setFetchMode(DB_FETCHMODE_ASSOC);
$gb = new LocStor();
$tr = new Transport($gb);
$r = $tr->cronMain();
if (!$r) {
exit(1);
}
exit(0);

View file

@ -1,41 +0,0 @@
#!/usr/bin/php
<?php
require_once(dirname(__FILE__).'/../conf.php');
require_once('DB.php');
require_once(dirname(__FILE__).'/../LocStor.php');
PEAR::setErrorHandling(PEAR_ERROR_RETURN);
$CC_DBC = DB::connect($CC_CONFIG['dsn'], TRUE);
$CC_DBC->setErrorHandling(PEAR_ERROR_RETURN);
$CC_DBC->setFetchMode(DB_FETCHMODE_ASSOC);
$gb = new LocStor();
$tr = new Transport($gb);
$pid = getmypid();
list(, $trtok) = $_SERVER['argv'];
if (TR_LOG_LEVEL > 1) {
$tr->trLog("transportCronJob($pid) start ($trtok)");
}
// 4-pass on job:
$cnt = 4;
for ($i = 0; $i < $cnt; $i++, sleep(1)) {
// run the action:
$r = $tr->cronCallMethod($trtok);
if (PEAR::isError($r)) {
$tr->trLogPear("transportCronJob($pid): ($trtok): ", $r);
} else {
# $tr->trLog("X transportCronJob: ".var_export($r, TRUE));
if ($r !== TRUE) {
$tr->trLog("transportCronJob($pid): ($trtok): nonTRUE returned");
}
}
#if(!$r) exit(1);
#sleep(2);
}
if (TR_LOG_LEVEL>1) {
$tr->trLog("transportCronJob($pid) end ($trtok)");
}
exit(0);

View file

@ -1,112 +0,0 @@
<?php
/**
* @package Airtime
* @subpackage StorageServer
* @copyright 2010 Sourcefabric O.P.S.
* @license http://www.gnu.org/licenses/gpl.txt
*/
$playlistFormat = array(
'_root'=>'playlist',
'playlist'=>array(
'childs'=>array(
// 'repeatable'=>array('playlistElement'),
'optional'=>array('metadata', 'playlistElement'),
),
'attrs'=>array(
'required'=>array('id'),
'implied'=>array('title', 'playlength'),
),
),
'playlistElement'=>array(
'childs'=>array(
'oneof'=>array('audioClip', 'playlist'),
'optional'=>array('fadeInfo'),
),
'attrs'=>array(
'required'=>array('id', 'relativeOffset', 'clipStart', 'clipEnd', 'clipLength'),
),
),
'audioClip'=>array(
'childs'=>array(
'optional'=>array('metadata'),
),
'attrs'=>array(
'implied'=>array('id', 'title', 'playlength', 'uri'),
),
),
'fadeInfo'=>array(
'attrs'=>array(
'required'=>array('id', 'fadeIn', 'fadeOut'),
),
),
'metadata'=>array(
'childs'=>array(
'optional'=>array(
'dc:title', 'dcterms:extent', 'dc:creator', 'dc:description',
'dcterms:alternative', 'ls:filename', 'ls:mtime',
),
),
'namespaces'=>array(
'dc'=>"http://purl.org/dc/elements/1.1/",
'dcterms'=>"http://purl.org/dc/terms/",
'xbmf'=>"http://www.streamonthefly.org/xbmf",
'xsi'=>"http://www.w3.org/2001/XMLSchema-instance",
'xml'=>"http://www.w3.org/XML/1998/namespace",
),
),
'dc:title'=>array(
'type'=>'Text',
'attrs'=>array('implied'=>array('xml:lang')),
),
'dcterms:alternative'=>array(
'type'=>'Text',
'attrs'=>array('implied'=>array('xml:lang')),
),
'dcterms:extent'=>array(
'type'=>'Time',
'regexp'=>'^\d{2}:\d{2}:\d{2}.\d{6}$',
),
'dc:creator'=>array(
'type'=>'Text',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'dc:description'=>array(
'type'=>'Longtext',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'playlength'=>array(
'type'=>'Time',
'regexp'=>'^((\d{2}:)?\d{2}:)?\d{1,2}(.\d{6})?$',
),
'id'=>array(
'type'=>'Attribute',
'regexp'=>'^[0-9a-f]{16}$',
),
'fadeIn'=>array(
'type'=>'Attribute',
'regexp'=>'^((\d{2}:)?\d{2}:)?\d{1,2}(.\d{6})?$',
),
'fadeOut'=>array(
'type'=>'Attribute',
'regexp'=>'^((\d{2}:)?\d{2}:)?\d{1,2}(.\d{6})?$',
),
'ls:filename'=>array(
'type'=>'Text',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:mtime'=>array(
'type'=>'Int',
// 'regexp'=>'^\d{4}(-\d{2}(-\d{2}(T\d{2}:\d{2}(:\d{2}\.\d+)?(Z)|([\+\-]?\d{2}:\d{2}))?)?)?$',
),
/*
''=>array(
'childs'=>array(''),
'attrs'=>array('implied'=>array()),
),
*/
);

View file

@ -1,181 +0,0 @@
<?php
$path = dirname(__FILE__).'/../../library/pear';
set_include_path(get_include_path() . PATH_SEPARATOR . $path);
require_once(dirname(__FILE__).'/../../../library/propel/runtime/lib/Propel.php');
// Initialize Propel with the runtime configuration
Propel::init(__DIR__."/../../configs/propel-config.php");
// Add the generated 'classes' directory to the include path
set_include_path(dirname(__FILE__)."/../" . PATH_SEPARATOR . get_include_path());
require_once('DB.php');
require_once('PHPUnit.php');
require_once(dirname(__FILE__).'/../../configs/conf.php');
require_once(dirname(__FILE__).'/../GreenBox.php');
require_once(dirname(__FILE__).'/../Playlist.php');
$tz = ini_get('date.timezone') ? ini_get('date.timezone') : 'America/Toronto';
date_default_timezone_set($tz);
//old database connection still needed to get a session instance.
$dsn = $CC_CONFIG['dsn'];
$CC_DBC = DB::connect($dsn, TRUE);
if (PEAR::isError($CC_DBC)) {
echo "ERROR: ".$CC_DBC->getMessage()." ".$CC_DBC->getUserInfo()."\n";
exit(1);
}
$CC_DBC->setFetchMode(DB_FETCHMODE_ASSOC);
class PlaylistTests extends PHPUnit_TestCase {
private $greenbox;
private $storedFile;
private $storedFile2;
function __construct($name) {
parent::__construct($name);
}
function setup() {
global $CC_CONFIG, $CC_DBC;
$this->greenbox = new GreenBox();
// Add a file
$values = array("filepath" => dirname(__FILE__)."/test10001.mp3");
$this->storedFile = StoredFile::Insert($values, false);
// Add a file
$values = array("filepath" => dirname(__FILE__)."/test10002.mp3");
$this->storedFile2 = StoredFile::Insert($values, false);
}
function testGBCreatePlaylist() {
$pl = new Playlist();
$pl_id = $pl->create("Playlist UnitTest: create ".date("g:i a"));
if (!is_int($pl_id)) {
$this->fail("problems creating playlist.");
return;
}
}
function testGBLock() {
$pl = new Playlist();
$pl_id = $pl->create("Playlist Metadata: lock ".date("g:i a"));
$sessid = Alib::Login('root', 'q');
$res = $this->greenbox->lockPlaylistForEdit($pl_id, $sessid);
if($res !== TRUE) {
$this->fail("problems locking playlist for editing.");
return;
}
}
function testGBUnLock() {
$pl = new Playlist();
$pl_id = $pl->create("Playlist UnitTest: unlock ".date("g:i a"));
$sessid = Alib::Login('root', 'q');
$this->greenbox->lockPlaylistForEdit($pl_id, $sessid);
$res = $this->greenbox->releaseLockedPlaylist($pl_id, $sessid);
if($res !== TRUE) {
$this->fail("problems unlocking playlist.");
return;
}
}
function testGBSetPLMetaData() {
$pl = new Playlist();
$pl_id = $pl->create("Playlist UnitTest: Set Metadata ".date("g:i a"));
$res = $this->greenbox->setPLMetadataValue($pl_id, "dc:title", "Playlist Unit Test: Updated Title ".date("g:i a"));
if($res !== TRUE) {
$this->fail("problems setting playlist metadata.");
return;
}
}
function testGBGetPLMetaData() {
$pl = new Playlist();
$name = "Playlist UnitTest: GetMetadata ".date("g:i a");
$pl_id = $pl->create($name);
$res = $this->greenbox->getPLMetadataValue($pl_id, "dc:title");
if($res !== $name) {
$this->fail("problems getting playlist metadata.");
return;
}
}
function testAddAudioClip() {
$pl = new Playlist();
$pl_id = $pl->create("Playlist Unit Test ". date("g:i a"));
$res = $this->greenbox->addAudioClipToPlaylist($pl_id, $this->storedFile->getId());
if($res !== TRUE) {
$this->fail("problems adding audioclip to playlist.");
return;
}
$res = $this->greenbox->addAudioClipToPlaylist($pl_id, $this->storedFile2->getId());
if($res !== TRUE) {
$this->fail("problems adding audioclip 2 to playlist.");
return;
}
}
function testMoveAudioClip() {
$pl = new Playlist();
$pl_id = $pl->create("Playlist Unit Test: Move ". date("g:i a"));
$this->greenbox->addAudioClipToPlaylist($pl_id, $this->storedFile->getId());
$this->greenbox->addAudioClipToPlaylist($pl_id, $this->storedFile2->getId());
$res = $this->greenbox->moveAudioClipInPlaylist($pl_id, 0, 1);
if($res !== TRUE) {
$this->fail("problems moving audioclip in playlist.");
return;
}
}
function testDeleteAudioClip() {
$pl = new Playlist();
$pl_id = $pl->create("Playlist UnitTest: Delete ".date("g:i a"));
$this->greenbox->addAudioClipToPlaylist($pl_id, $this->storedFile->getId());
$res = $this->greenbox->delAudioClipFromPlaylist($pl_id, 0);
if($res !== TRUE) {
$this->fail("problems deleting audioclip from playlist.");
return;
}
}
function testFadeInfo() {
$pl = new Playlist();
$pl_id = $pl->create("Playlist Unit Test: Fade Info " . date("g:i a"));
$this->greenbox->addAudioClipToPlaylist($pl_id, $this->storedFile2->getId());
$res = $this->greenbox->changeFadeInfo($pl_id, 0, '00:00:01.14', null);
if(!is_array($res) && count($res) !== 2) {
$this->fail("problems setting fade in playlist.");
return;
}
}
}

View file

@ -1,24 +0,0 @@
#!/usr/bin/php -q
<?php
header("Content-type: text/plain");
echo "TEST\n";
#$gunid = "5716b53127c3761f92fddde3412c7773";
$gunid = $argv[1];
echo "GUNID: $gunid\n";
require_once('../../conf.php');
require_once('DB.php');
require_once('../GreenBox.php');
$rmd = new StoredFile($gunid, '../stor/'.substr($gunid, 0, 3));
$r = $rmd->analyzeFile();
echo "r=$r (".gettype($r).")\n";
if (PEAR::isError($r)) {
echo "ERR: ".$r->getMessage()."\n".$r->getUserInfo()."\n";
}
if (is_array($r)) {
print_r($r);
}
echo"\n";

View file

@ -1,142 +0,0 @@
<?php
/*
header("Content-type: text/plain");
require_once('../../conf.php');
require_once('DB.php');
require_once('../GreenBox.php');
require_once('../LocStor.php');
#PEAR::setErrorHandling(PEAR_ERROR_PRINT, "%s<hr>\n");
PEAR::setErrorHandling(PEAR_ERROR_RETURN);
$CC_DBC = DB::connect($CC_CONFIG['dsn'], TRUE);
$CC_DBC->setFetchMode(DB_FETCHMODE_ASSOC);
$gb = new GreenBox();
$tr = new Transport($gb);
$ls = new LocStor();
@unlink($CC_CONFIG['transDir']."/activity.log");
@unlink($CC_CONFIG['transDir']."/debug.log");
$tr->_cleanUp();
$gunid = 'a23456789abcdefb';
$mediaFile = '../tests/ex1.mp3';
$mdataFile = '../tests/mdata1.xml';
// Test remote search
$result = $tr->remoteSearch("");
if (PEAR::isError($result)) {
echo $result->message."\n";
} else {
var_dump($result);
}
// ========== STORE ==========
echo"# Store: ";
//$parid = $gb->_getHomeDirIdFromSess($sessid);
$values = array(
"filename" => "xx1.mp3",
"filepath" => $mediaFile,
"metadata" => $mdataFile,
"gunid" => $gunid,
"filetype" => "audioclip"
);
$storedFile = StoredFile::Insert($values);
if (PEAR::isError($storedFile)) {
if ($storedFile->getCode()!=GBERR_GUNID) {
echo "ERROR: ".$storedFile->getMessage()."\n";
exit(1);
}
}
$oid = $storedFile->getId();
$comm = "ls -l ".$CC_CONFIG['storageDir']."/a23"; echo `$comm`;
echo "$oid\n";
// ========== DELETE FROM HUB ==========
echo"# loginToArchive: ";
$r = $tr->loginToArchive();
if(PEAR::isError($r)){ echo "ERROR: ".$r->getMessage()." / ".$r->getUserInfo()."\n"; exit(1); }
echo "{$r['sessid']}\n";
$asessid = $r['sessid'];
echo"# deleteAudioClip on Hub: ";
$r = $tr->xmlrpcCall(
'archive.deleteAudioClip',
array(
'sessid' => $asessid,
'gunid' => $gunid,
'forced' => TRUE,
)
);
if(PEAR::isError($r)){ echo "ERROR: ".$r->getMessage()." / ".$r->getUserInfo()."\n"; if($r->getCode()!=800+GBERR_FILENEX) exit(1); }
else{ echo " {$r['status']}\n"; }
echo"# logoutFromArchive: ";
$r = $tr->logoutFromArchive($asessid);
if(PEAR::isError($r)){ echo "ERROR: ".$r->getMessage()." / ".$r->getUserInfo()."\n"; exit(1); }
var_export($r); echo"\n";
// ========== UPLOAD ==========
echo "# UPLOAD test:\n";
echo"# uploadAudioClip2Hub: ";
$r = $gb->upload2Hub($gunid);
if(PEAR::isError($r)){ echo "ERROR: ".$r->getMessage()."/".$r->getUserInfo()."\n"; exit(1); }
var_export($r); echo"\n";
$trtok = $r;
echo"# logout: "; $r = Alib::Logout($sessid);
if(PEAR::isError($r)){ echo "ERROR: ".$r->getMessage()."/".$r->getUserInfo()."\n"; exit(1); }
echo "$r\n";
#$trtok='280a6f1c18389620';
for($state='', $nu=1; ($state!='closed' && $state!='failed' && $nu<=12); $nu++, sleep(2)){
echo"# getTransportInfo: "; $r = $gb->getTransportInfo($trtok);
if(PEAR::isError($r)){ echo "ERROR: ".$r->getMessage()."/".$r->getUserInfo()."\n"; exit(1); }
$state = $r['state'];
echo "# state=$state, title={$r['title']}\n";
}
if($state=='failed') exit(1);
// === DELETE LOCAL ===
echo "# Login: ".($sessid = Alib::Login('root', 'q'))."\n";
echo "# Delete: "; $r = $ls->deleteAudioClip($sessid, $gunid, TRUE);
if (PEAR::isError($r)) {
echo "ERROR: ".$r->getMessage()."\n";
exit(1);
}
echo "$r\n";
echo "# logout: "; $r = Alib::Logout($sessid);
if (PEAR::isError($r)) {
echo "ERROR: ".$r->getMessage()."\n";
exit(1);
}
echo "$r\n";
$comm = "ls -l ".$CC_CONFIG['storageDir']."/a23";
echo `$comm`;
// === DOWNLOAD ===
echo "# DOWNLOAD test:\n";
echo"# Login: ".($sessid = Alib::Login('root', 'q'))."\n";
echo"# downloadAudioClipFromHub: ";
$r = $gb->downloadFromHub($sessid, $gunid);
if(PEAR::isError($r)){ echo "ERROR: ".$r->getMessage()."/".$r->getUserInfo()."\n"; exit(1); }
var_export($r); echo"\n";
$trtok = $r;
echo"# logout: "; $r = Alib::Logout($sessid);
if(PEAR::isError($r)){ echo "ERROR: ".$r->getMessage()."\n"; exit(1); }
echo "$r\n";
for($state='', $nu=1; ($state!='closed' && $state!='failed' && $nu<=12); $nu++, sleep(2)){
echo"# getTransportInfo: "; $r = $gb->getTransportInfo($trtok);
if(PEAR::isError($r)){ echo "ERROR: ".$r->getMessage()."/".$r->getUserInfo()."\n"; exit(1); }
$state = $r['state'];
echo "# state=$state, title={$r['title']}\n";
}
if($state=='failed') exit(1);
$comm = "ls -l ".$CC_CONFIG['storageDir']."/a23"; echo `$comm`;
if(file_exists("../trans/log")) echo `tail -n 25 ../trans/log`;
echo "#Transport test: OK.\n\n";
*/

View file

@ -1,61 +0,0 @@
<?php
/*
header("Content-type: text/plain");
echo "\n#StorageServer storeWebstream test:\n";
require_once('../../conf.php');
require_once('DB.php');
require_once('../GreenBox.php');
#PEAR::setErrorHandling(PEAR_ERROR_PRINT, "%s<hr>\n");
PEAR::setErrorHandling(PEAR_ERROR_RETURN);
$CC_DBC = DB::connect($CC_CONFIG['dsn'], TRUE);
$CC_DBC->setFetchMode(DB_FETCHMODE_ASSOC);
$gb = new GreenBox();
#$gunid = "123456789abcdee0";
$gunid = "";
#$mdataFileLP = '../tests/mdata1.xml';
$mdataFileLP = NULL;
echo "# Login: ".($sessid = Alib::Login('root', 'q'))."\n";
$parid = $gb->_getHomeDirId($sessid);
echo "# storeWebstream: ";
$r = $gb->storeWebstream(
$parid, 'test stream', $mdataFileLP, $sessid, $gunid, 'http://localhost/y');
if (PEAR::isError($r)) {
echo "ERROR: ".$r->getMessage()." ".$r->getUserInfo()."\n";
exit(1);
}
echo "";
var_dump($r);
//$id = BasicStor::IdFromGunid($gunid);
$id = $r;
echo "# getMdata: ";
$r = $gb->getMetadata($id, $sessid);
if (PEAR::isError($r)) {
echo "ERROR: ".$r->getMessage()." ".$r->getUserInfo()."\n";
exit(1);
}
echo "\n$r\n";
echo "# deleteFile: ";
$r = $gb->deleteFile($id, $sessid);
if (PEAR::isError($r)) {
echo "ERROR: ".$r->getMessage()." ".$r->getUserInfo()."\n";
exit(1);
}
echo "\n$r\n";
echo "# logout: ";
$r = Alib::Logout($sessid);
if (PEAR::isError($r)) {
echo "ERROR: ".$r->getMessage()."\n";
exit(1);
}
echo "$r\n";
echo "#storeWebstream test: OK.\n\n"
*/

View file

@ -1,340 +0,0 @@
<?php
/**
* @copyright 2010 Sourcefabric O.P.S.
* @license http://www.gnu.org/licenses/gpl.txt
*/
$webstreamFormat = array(
'_root'=>'audioClip',
'audioClip'=>array(
'childs'=>array(
'required'=>array('metadata'),
),
),
'metadata'=>array(
'childs'=>array(
'required'=>array(
'dc:title', 'dcterms:extent', 'ls:url'
),
'optional'=>array(
'dc:identifier',
'dc:creator', 'dc:source', 'ls:genre',
'ls:year', 'dc:type', 'dc:description', 'dc:format',
'ls:bpm', 'ls:rating', 'ls:encoded_by', 'ls:track_num',
'ls:disc_num', 'ls:disc_num', 'dc:publisher', 'ls:composer',
'ls:bitrate', 'ls:channels', 'ls:samplerate', 'ls:encoder',
'ls:crc', 'ls:lyrics', 'ls:orchestra', 'ls:conductor',
'ls:lyricist', 'ls:originallyricist', 'ls:radiostationname',
'ls:audiofileinfourl', 'ls:artisturl', 'ls:audiosourceurl',
'ls:radiostationurl', 'ls:buycdurl', 'ls:isrcnumber',
'ls:catalognumber', 'ls:originalartist', 'dc:rights',
'ls:license', 'dc:title', 'dcterms:temporal',
'dcterms:spatial', 'dcterms:entity', 'dc:description',
'dc:creator', 'dc:subject', 'dc:type', 'dc:format',
'dc:contributor', 'dc:language', 'dc:rights',
'dcterms:isPartOf', 'dc:date',
'dc:publisher',
// extra
'dcterms:alternative', 'ls:filename', 'ls:mtime',
// added lately by sebastian
'ls:mood',
),
),
'namespaces'=>array(
'dc'=>"http://purl.org/dc/elements/1.1/",
'dcterms'=>"http://purl.org/dc/terms/",
'xbmf'=>"http://www.streamonthefly.org/xbmf",
'xsi'=>"http://www.w3.org/2001/XMLSchema-instance",
'xml'=>"http://www.w3.org/XML/1998/namespace",
),
),
'ls:url'=>array(
'type'=>'URL',
),
'dc:identifier'=>array(
'type'=>'Text',
'auto'=>TRUE,
),
'dc:title'=>array(
'type'=>'Text',
'attrs'=>array('implied'=>array('xml:lang')),
),
'dcterms:alternative'=>array(
'type'=>'Text',
'attrs'=>array('implied'=>array('xml:lang')),
),
'dcterms:extent'=>array(
'type'=>'Time',
'regexp'=>'^\d{2}:\d{2}:\d{2}.\d{6}$',
),
'dc:creator'=>array(
'type'=>'Text',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'dc:source'=>array(
'type'=>'Text',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:genre'=>array(
'type'=>'Menu',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:year'=>array(
'type'=>'Menu',
'area'=>'Music',
),
'dc:type'=>array(
'type'=>'Menu',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'dc:description'=>array(
'type'=>'Longtext',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'dc:format'=>array(
'type'=>'Menu',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:bpm'=>array(
'type'=>'Number',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:rating'=>array(
'type'=>'Number',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:encoded_by'=>array(
'type'=>'Text',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:track_num'=>array(
'type'=>'Menu',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:disc_num'=>array(
'type'=>'Menu',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:disc_num'=>array(
'type'=>'Menu',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'dc:publisher'=>array(
'type'=>'Text',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:composer'=>array(
'type'=>'Text',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:bitrate'=>array(
'type'=>'Number',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:channels'=>array(
'type'=>'Menu',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:samplerate'=>array(
'type'=>'Menu',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:encoder'=>array(
'type'=>'Text',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:crc'=>array(
'type'=>'Number',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:lyrics'=>array(
'type'=>'Longtext',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:orchestra'=>array(
'type'=>'Text',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:conductor'=>array(
'type'=>'Text',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:lyricist'=>array(
'type'=>'Text',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:originallyricist'=>array(
'type'=>'Text',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:radiostationname'=>array(
'type'=>'Text',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:audiofileinfourl'=>array(
'type'=>'URL',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:artisturl'=>array(
'type'=>'URL',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:audiosourceurl'=>array(
'type'=>'URL',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:radiostationurl'=>array(
'type'=>'URL',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:buycdurl'=>array(
'type'=>'URL',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:isrcnumber'=>array(
'type'=>'Number',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:catalognumber'=>array(
'type'=>'Number',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:originalartist'=>array(
'type'=>'Text',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'dc:rights'=>array(
'type'=>'Text',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:license'=>array(
'type'=>'Text',
'area'=>'Music',
'attrs'=>array('implied'=>array('xml:lang')),
),
'dc:title'=>array(
'type'=>'Text',
'area'=>'Talk',
'attrs'=>array('implied'=>array('xml:lang')),
),
'dcterms:temporal'=>array(
'type'=>'Time/Date',
'area'=>'Talk',
'attrs'=>array('implied'=>array('xml:lang')),
),
'dcterms:spatial'=>array(
'type'=>'Menu',
'area'=>'Talk',
'attrs'=>array('implied'=>array('xml:lang')),
),
'dcterms:entity'=>array(
'type'=>'Text',
'area'=>'Talk',
'attrs'=>array('implied'=>array('xml:lang')),
),
'dc:description'=>array(
'type'=>'Longtext',
'area'=>'Talk',
'attrs'=>array('implied'=>array('xml:lang')),
),
'dc:creator'=>array(
'type'=>'Menu',
'area'=>'Talk',
'attrs'=>array('implied'=>array('xml:lang')),
),
'dc:subject'=>array(
'type'=>'Text',
'area'=>'Talk',
'attrs'=>array('implied'=>array('xml:lang')),
),
'dc:type'=>array(
'type'=>'Menu',
'area'=>'Talk',
'attrs'=>array('implied'=>array('xml:lang')),
),
'dc:format'=>array(
'type'=>'Menu',
'area'=>'Talk',
'attrs'=>array('implied'=>array('xml:lang')),
),
'dc:contributor'=>array(
'type'=>'Text',
'area'=>'Talk',
'attrs'=>array('implied'=>array('xml:lang')),
),
'dc:language'=>array(
'type'=>'Menu',
'area'=>'Talk',
'attrs'=>array('implied'=>array('xml:lang')),
),
'dc:rights'=>array(
'type'=>'Menu',
'area'=>'Talk',
'attrs'=>array('implied'=>array('xml:lang')),
),
'dcterms:isPartOf'=>array(
'type'=>'Text',
'area'=>'Talk',
'attrs'=>array('implied'=>array('xml:lang')),
),
'dc:date'=>array(
'type'=>'Date',
'area'=>'Talk',
'attrs'=>array('implied'=>array('xml:lang')),
),
'dc:publisher'=>array(
'type'=>'Text',
'area'=>'Talk',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:filename'=>array(
'type'=>'Text',
'attrs'=>array('implied'=>array('xml:lang')),
),
'ls:mtime'=>array(
'type'=>'Int',
// 'regexp'=>'^\d{4}(-\d{2}(-\d{2}(T\d{2}:\d{2}(:\d{2}\.\d+)?(Z)|([\+\-]?\d{2}:\d{2}))?)?)?$',
),
/*
''=>array(
'type'=>'',
'area'=>'',
'attrs'=>array(),
),
*/
);

File diff suppressed because it is too large Load diff

View file

@ -1,3 +0,0 @@
<?php
header ("location: xrLocStor.php");
exit;

View file

@ -1,99 +0,0 @@
<?php
/**
* Store PUT data as temporary file.
*
* put.php is remote callable script through HTTP PUT method.
* Requires token returned by appropriate storageServer XMLRPC call.
* Appropriate closing XMLRPC call should follow.
*
* This script accepts following HTTP GET parameter:
* <ul>
* <li>token : string, put token returned by appropriate
* XMLRPC call</li>
* </ul>
*
* On success, returns HTTP return code 200.
*
* On errors, returns HTTP return code &gt;200
* The possible error codes are:
* <ul>
* <li> 400 - Incorrect parameters passed to method</li>
* <li> 403 - Access denied</li>
* <li> 500 - Application error</li>
* </ul>
*
* @see XR_LocStor
* @package Airtime
* @subpackage storageServer
*/
define('USE_FLOCK', TRUE);
require_once(dirname(__FILE__).'/../../conf.php');
require_once('DB.php');
require_once(dirname(__FILE__).'/../LocStor.php');
PEAR::setErrorHandling(PEAR_ERROR_RETURN);
$CC_DBC = DB::connect($CC_CONFIG['dsn'], TRUE);
$CC_DBC->setFetchMode(DB_FETCHMODE_ASSOC);
$gb = new LocStor();
function http_error($code, $err)
{
header("HTTP/1.1 $code");
header("Content-type: text/plain; charset=UTF-8");
echo "$err\r\n";
flush();
exit;
}
if (preg_match("|^[0-9a-fA-F]{16}$|", $_REQUEST['token'])) {
$token = $_REQUEST['token'];
} else {
http_error(400, "Error on token parameter. ({$_REQUEST['token']})");
}
$tc = BasicStor::bsCheckToken($token, 'put');
if (PEAR::isError($tc)) {
http_error(500, $ex->getMessage());
}
if (!$tc) {
http_error(403, "put.php: Token not valid ($token).");
}
header("Content-type: text/plain");
$destfile = $CC_CONFIG['accessDir']."/{$token}";
/* PUT data comes in on the input stream */
$putdata = @fopen("php://input", "r") or
http_error(500, "put.php: Can't read input");
/* Open a file for writing */
$fp = @fopen($destfile, "ab") or
http_error(500, "put.php: Can't write to destination file (token=$token)");
if ( USE_FLOCK ) {
// lock the file
$lockres = flock($fp,LOCK_EX+LOCK_NB);
if ($lockres !== TRUE) {
http_error(409, "put.php: file locked (token=$token)");
}
}
/* Read the data 1 KB at a time and write to the file */
while ($data = fread($putdata, 1024)){
fwrite($fp, $data);
}
if ( USE_FLOCK ) {
// unlock the file
flock($fp,LOCK_UN);
}
/* Close the streams */
fclose($fp);
fclose($putdata);
header("HTTP/1.1 200");

View file

@ -1,510 +0,0 @@
<?php
/* ================================================================= includes */
include_once(dirname(__FILE__)."/../conf.php");
require_once('DB.php');
include_once("XML/RPC.php");
/* ================================================== method definition array */
/**
* Array with methods description
*
* Each element has method name as key and contains four subfields:
* <ul>
* <li>m</li> full method name (include optional prefix)
* <li>p</li> array of input parameter names
* <li>t</li> array of input parameter types
* <li>r</li> array of result element names (not used there at present)
* <li>e</li> array of error codes/messages (not used there at present)
* </ul>
*/
$mdefs = array(
"listMethods" => array('m'=>"system.listMethods", 'p'=>NULL, 't'=>NULL),
"AddAudioClipToPlaylistMethod" => array(
'm'=>'addAudioClipToPlaylist',
'p'=>array('sessionId'/*string*/, 'playlistId'/*string*/, 'audioClipId'/*string*/, 'relativeOffset'/*int*/, 'clipStart'/*int*/, 'clipEnd'/*int*/, 'clipLength'/*int*/),
't'=>array('string', 'string', 'string', 'int', 'int', 'int', 'int'),
'r'=>array('playlistElementId'/*string*/),
'e'=>array(
'301'=>'invalid argument format',
'302'=>'missing playlist ID argument',
'303'=>'missing audio clip ID argument',
'304'=>'missing relative offset argument',
'305'=>'playlist not found',
'306'=>'playlist has not been opened for editing',
'307'=>'audio clip does not exist',
'308'=>'two audio clips at the same relative offset',
'320'=>'missing session ID argument',
)
),
"CreatePlaylistMethod" => array(
'm'=>'createPlaylist',
'p'=>array('sessionId'/*string*/),
't'=>array('string'),
'r'=>array('playlist'/*string*/),
'e'=>array(
'201'=>'invalid argument format',
'202'=>'could not create playlist',
'220'=>'missing session ID argument',
)
),
"DeletePlaylistMethod" => array(
'm'=>'deletePlaylist',
'p'=>array('sessionId'/*string*/, 'playlistId'/*string*/),
't'=>array('string', 'string'),
'r'=>array(),
'e'=>array(
'901'=>'invalid argument format',
'902'=>'missing playlist ID argument',
'903'=>'playlist not found',
'904'=>'playlist is locked',
'905'=>'playlist could not be deleted',
'920'=>'missing session ID argument',
)
),
"DisplayAudioClipMethod" => array(
'm'=>'displayAudioClip',
'p'=>array('sessionId'/*string*/, 'audioClipId'/*string*/),
't'=>array('string', 'string'),
'r'=>array('audioClip'/*string*/),
'e'=>array(
'601'=>'invalid argument format',
'602'=>'argument is not an audio clip ID',
'603'=>'audio clip not found',
'620'=>'missing session ID argument',
)
),
"DisplayAudioClipsMethod" => array(
'm'=>'displayAudioClips',
'p'=>array('sessionId'/*string*/),
't'=>array('string'),
'r'=>array(array('audioClip'/*string*/)),
'e'=>array(
'1801'=>'invalid argument format',
'1802'=>'XML-RPC error',
'1820'=>'missing session ID argument',
)
),
"DisplayPlaylistMethod" => array(
'm'=>'displayPlaylist',
'p'=>array('sessionId'/*string*/, 'playlistId'/*string*/),
't'=>array('string', 'string'),
'r'=>array('playlist'/*string*/),
'e'=>array(
'1001'=>'invalid argument format',
'1002'=>'argument is not a playlist ID',
'1003'=>'playlist not found',
'1020'=>'missing session ID argument',
)
),
"DisplayPlaylistsMethod" => array(
'm'=>'displayPlaylists',
'p'=>array('sessionId'/*string*/),
't'=>array('string'),
'r'=>array(array('playlist'/*string*/)),
'e'=>array(
'1701'=>'invalid argument format',
'1702'=>'XML-RPC error',
'1720'=>'missing session ID argument',
)
),
"DisplayScheduleMethod" => array(
'm'=>'displaySchedule',
'p'=>array('sessionId'/*string*/, 'from'/*datetime*/, 'to'/*datetime*/),
't'=>array('string', 'dateTime.iso8601', 'dateTime.iso8601'),
'r'=>array(array('id'/*int*/, 'playlistId'/*string*/, 'start'/*datetime*/, 'end'/*datetime*/)),
'e'=>array(
'1101'=>'invalid argument format',
'1102'=>"missing or invalid 'from' argument",
'1103'=>"missing or invalid 'to' argument",
'1120'=>'missing session ID argument',
)
),
"GeneratePlayReportMethod" => array(
'm'=>'generatePlayReport',
'p'=>array('sessionId'/*string*/, 'from'/*datetime*/, 'to'/*datetime*/),
't'=>array('string', 'dateTime.iso8601', 'dateTime.iso8601'),
'r'=>array(array('audioClipId'/*string*/, 'timestamp'/*datetime*/)),
'e'=>array(
'1501'=>'invalid argument format',
'1502'=>"missing or invalid 'from' argument",
'1503'=>"missing or invalid 'to' argument",
'1520'=>'missing session ID argument',
)
),
"GetSchedulerTimeMethod" => array(
'm'=>'getSchedulerTime',
'p'=>array(),
't'=>array(),
'r'=>array('schedulerTime'/*datetime*/),
'e'=>array(
)
),
"GetVersionMethod" => array(
'm'=>'getVersion',
'p'=>array(),
't'=>array(),
'r'=>array('version'/*string*/),
'e'=>array()
),
"LoginMethod" => array(
'm'=>'login',
'p'=>array('login'/*string*/, 'password'/*string*/),
't'=>array('string', 'string'),
'r'=>array('sessionId'/*string*/),
'e'=>array(
'2001'=>'invalid argument format',
'2002'=>'missing login argument',
'2003'=>'missing password argument',
'2004'=>'the authentication server reported an error',
)
),
"LogoutMethod" => array(
'm'=>'logout',
'p'=>array('sessionId'/*string*/),
't'=>array('string'),
'r'=>array(),
'e'=>array(
'2101'=>'invalid argument format',
'2120'=>'missing session ID argument',
'2104'=>'the authentication server reported an error',
)
),
"OpenPlaylistForEditingMethod" => array(
'm'=>'openPlaylistForEditing',
'p'=>array('sessionId'/*string*/, 'playlistId'/*string*/),
't'=>array('string', 'string'),
'r'=>array('playlist'/*string*/),
'e'=>array(
'101'=>'invalid argument format',
'102'=>'argument is not a playlist ID',
'104'=>'could not open playlist for editing',
'120'=>'missing session ID argument',
)
),
"RemoveAudioClipFromPlaylistMethod" => array(
'm'=>'removeAudioClipFromPlaylist',
'p'=>array('sessionId'/*string*/, 'playlistId'/*string*/, 'playlistElementId'/*string*/),
't'=>array('string', 'string', 'string'),
'r'=>array(),
'e'=>array(
'401'=>'invalid argument format',
'402'=>'missing playlist ID argument',
'403'=>'missing relative offset argument',
'404'=>'playlist does not exist',
'405'=>'playlist has not been opened for editing',
'406'=>'no audio clip at the specified relative offset',
'420'=>'missing session ID argument',
)
),
"RemoveFromScheduleMethod" => array(
'm'=>'removeFromSchedule',
'p'=>array('sessionId'/*string*/, 'scheduleEntryId'/*string*/),
't'=>array('string', 'string'),
'r'=>array(),
'e'=>array(
'1201'=>'invalid argument format',
'1202'=>'missing schedule entry ID argument',
'1203'=>'schedule entry not found',
'1220'=>'missing session ID argument',
)
),
"RescheduleMethod" => array(
'm'=>'reschedule',
'p'=>array('sessionId'/*string*/, 'scheduleEntryId'/*string*/, 'playtime'/*datetime*/),
't'=>array('string', 'string', 'dateTime.iso8601'),
'r'=>array(),
'e'=>array(
'1301'=>'invalid argument format',
'1302'=>'missing schedule entry ID argument',
'1303'=>'missing playtime argument',
'1304'=>'schedule entry not found',
'1305'=>'could not reschedule entry',
'1320'=>'missing session ID argument',
)
),
// "ResetStorageMethod" => array(
// 'm'=>'resetStorage',
// 'p'=>array(),
// 't'=>array(),
// 'r'=>array(),
// 'e'=>array('3001'=>'storage client reported an error'),
// ),
"RevertEditedPlaylistMethod" => array(
'm'=>'revertEditedPlaylist',
'p'=>array('sessionId'/*string*/, 'playlistId'/*string*/),
't'=>array('string', 'string'),
'r'=>array(),
'e'=>array(
'801'=>'invalid argument format',
'802'=>'argument is not a playlist ID',
'803'=>'playlist not found',
'804'=>'could not revert playlist',
'820'=>'missing session ID argument',
)
),
"SavePlaylistMethod" => array(
'm'=>'savePlaylist',
'p'=>array('sessionId'/*string*/, 'playlistId'/*string*/),
't'=>array('string', 'string'),
'r'=>array(),
'e'=>array(
'701'=>'invalid argument format',
'702'=>'argument is not a playlist ID',
'703'=>'playlist not found',
'705'=>'could not save playlist',
'720'=>'missing session ID argument',
)
),
"UpdateFadeInFadeOutMethod" => array(
'm'=>'updateFadeInFadeOut',
'p'=>array('sessionId'/*string*/, 'playlistId'/*string*/, 'playlistElementId'/*string*/, 'fadeIn'/*int*/, 'fadeOut'/*int*/),
't'=>array('string', 'string', 'string', 'int', 'int'),
'r'=>array(),
'e'=>array(
'1601'=>'invalid argument format',
'1602'=>'missing playlist ID argument',
'1603'=>'missing playlist element ID argument',
'1604'=>'missing fade in argument',
'1605'=>'missing fade out argument',
'1606'=>'playlist does not exist',
'1607'=>'playlist has not been opened for editing',
'1608'=>'error executing setFadeInfo() method',
'1620'=>'missing session ID argument',
)
),
"UploadPlaylistMethod" => array(
'm'=>'uploadPlaylist',
'p'=>array('sessionId'/*string*/, 'playlistId'/*string*/, 'playtime'/*datetime*/),
't'=>array('string', 'string', 'dateTime.iso8601'),
'r'=>array('scheduleEntryId'/*string*/),
'e'=>array(
'1401'=>'invalid argument format',
'1402'=>'missing playlist ID argument',
'1403'=>'missing playtime argument',
'1404'=>'playlist not found',
'1405'=>'timeframe not available',
'1406'=>'could not schedule playlist',
'1420'=>'missing session ID argument',
)
),
"ValidatePlaylistMethod" => array(
'm'=>'validatePlaylist',
'p'=>array('sessionId'/*string*/, 'playlistId'/*string*/),
't'=>array('string', 'string'),
'r'=>array('valid'/*bool*/),
'e'=>array(
'501'=>'invalid argument format',
'502'=>'missing playlist ID argument',
'503'=>'playlist does not exist',
'504'=>'playlist has not been opened for editing',
'520'=>'missing session ID argument',
)
),
"LoginGB" => array(
'm'=>'locstor.login',
'p'=>array('login'/*string*/, 'pass'/*string*/),
't'=>array('string', 'string'),
'r'=>array('sessid'/*string*/),
'e'=>array(
'2001'=>'invalid argument format',
'2002'=>'missing login argument',
'2003'=>'missing password argument',
'2004'=>'the authentication server reported an error',
)
),
"LogoutGB" => array(
'm'=>'locstor.logout',
'p'=>array('sessid'/*string*/),
't'=>array('string'),
'r'=>array('status'/*boolean*/),
'e'=>array(
'2001'=>'invalid argument format',
'2002'=>'missing login argument',
'2003'=>'missing password argument',
'2004'=>'the authentication server reported an error',
)
),
);
/* ======================================================== class definitions */
class SchedulerPhpClient {
/**
* Array with methods description
* @var array
*/
private $mdefs = array();
/**
* XMLRPC client object reference
*/
private $client = NULL;
/**
* Verbosity flag
*/
private $verbose = FALSE;
/**
* XMLRPC debug flag
*/
private $debug = 0;
/**
* Constructor - please DON'T CALL IT, use factory method instead
*
* @param DB $dbc
* @param array $mdefs
* hash array with methods description
* @param array $config
* hash array with configuration
* @param int $debug
* XMLRPC debug flag
* @param boolean $verbose
* verbosity flag
*/
public function __construct($mdefs, $debug=0, $verbose=FALSE)
{
global $CC_DBC, $CC_CONFIG;
$this->mdefs = $mdefs;
$this->debug = $debug;
$this->verbose = $verbose;
$confPrefix = "scheduler";
//$confPrefix = "storage";
$serverPath =
"http://{$CC_CONFIG["{$confPrefix}UrlHost"]}:{$CC_CONFIG["{$confPrefix}UrlPort"]}".
"{$CC_CONFIG["{$confPrefix}UrlPath"]}/{$CC_CONFIG["{$confPrefix}XMLRPC"]}";
//$serverPath = "http://localhost:80/campcasterStorageServerCVS/xmlrpc/xrLocStor.php";
if ($this->verbose) {
echo "serverPath: $serverPath\n";
}
$url = parse_url($serverPath);
$this->client = new XML_RPC_Client($url['path'], $url['host'], $url['port']);
}
/**
* Factory, create object instance
*
* In fact it doesn't create instance of SchedulerPhpClient, but
* dynamically extend this class with set of methods based on $mdefs array
* (using eval function) and instantiate resulting class
* SchedulerPhpClientCore instead.
* Each new method in this subclass accepts parameters according to $mdefs
* array, call wrapper callMethod(methodname, parameters) and return its
* result.
*
* @param array $mdefs
* hash array with methods description
* @param int $debug
* XMLRPC debug flag
* @param boolean $verbose
* verbosity flag
* @return SchedulerPhpClientCore
*/
function &factory($mdefs, $debug=0, $verbose=FALSE)
{
global $CC_DBC, $CC_CONFIG;
$f = '';
foreach ($mdefs as $fn => $farr) {
$f .=
' function '.$fn.'(){'."\n".
' $pars = func_get_args();'."\n".
' $r = $this->callMethod("'.$fn.'", $pars);'."\n".
' return $r;'."\n".
' }'."\n";
}
$e =
"class SchedulerPhpClientCore extends SchedulerPhpClient{\n".
"$f\n".
"}\n";
# echo $e;
if (FALSE === eval($e)) {
return $CC_DBC->raiseError("Eval failed");
}
$spc = new SchedulerPhpClientCore($mdefs, $debug, $verbose);
return $spc;
}
/**
* XMLRPC methods wrapper
* Encode XMLRPC request message, send it, receive and decode response.
*
* @param string $method
* method name
* @param array $gettedPars
* returned by func_get_args() in called method
* @return array
* PHP hash with response
*/
function callMethod($method, $gettedPars)
{
$parr = array();
$XML_RPC_val = new XML_RPC_Value;
foreach ($this->mdefs[$method]['p'] as $i => $p) {
$parr[$p] = new XML_RPC_Value;
$parr[$p]->addScalar($gettedPars[$i], $this->mdefs[$method]['t'][$i]);
}
$XML_RPC_val->addStruct($parr);
$fullmethod = $this->mdefs[$method]['m'];
$msg = new XML_RPC_Message($fullmethod, array($XML_RPC_val));
if ($this->verbose) {
echo "parr:\n";
var_dump($parr);
echo "message:\n";
echo $msg->serialize()."\n";
}
$this->client->setDebug($this->debug);
$res = $this->client->send($msg);
if ($res->faultCode() > 0) {
return PEAR::raiseError(
"SchedulerPhpClient::$method:".$res->faultString()." ".
$res->faultCode()."\n", $res->faultCode(),
PEAR_ERROR_RETURN
);
}
if ($this->verbose) {
echo "result:\n";
echo $res->serialize();
}
$val = $res->value();
$resp = XML_RPC_decode($res->value());
return $resp;
}
} // class SchedulerPhpClient
/* ======================================================== class definitions */
/**
* Example of use:
*
* /
// db object handling:
$CC_DBC = DB::connect($CC_CONFIG['dsn'], TRUE);
$CC_DBC->setFetchMode(DB_FETCHMODE_ASSOC);
$CC_DBC->setErrorHandling(PEAR_ERROR_RETURN);
// scheduler client instantiation:
$spc = SchedulerPhpClient::factory($mdefs);
#$spc = SchedulerPhpClient::factory($mdefs, 0, TRUE);
if(PEAR::isError($spc)){ echo $spc->getMessage."\n"; exit; }
// call of chosen function by name according to key values in $mdefs array:
// (for testing on storageServer XMLRPC I've changes confPrefix in
// SchedulerPhpClient constructor from 'scheduler' to 'storage' value)
#$r = $spc->LoginGB('root', 'q'); var_dump($r);
#$r = $spc->LogoutGB(''); var_dump($r);
#$r = $spc->DisplayScheduleMethod($this->Base->sessid, '2005-01-01 00:00:00.000000', '2005-02-01 00:00:00.000000'); var_dump($r);
#$r = $spc->DisplayScheduleMethod('dummySessionId2-1681692777', '2005-01-01 00:00:00.000000', '2005-02-01 00:00:00.000000'); var_dump($r);
$r = $spc->DisplayScheduleMethod($this->Base->sessid, '20040101T00:00:00', '20050401T00:00:00'); var_dump($r);
#$r = $spc->LoginMethod('root', 'q'); var_dump($r);
#$r = $spc->LogoutMethod('dummySessionId3-1714636915'); var_dump($r);
#$r = $spc->listMethods(); var_dump($r);
#$r = $spc->GetSchedulerTimeMethod(); var_dump($r);
================= */

View file

@ -1,127 +0,0 @@
<?php
/**
* Returns stored media file identified by global unique ID.
*
* simpleGet.php is remote callable script through HTTP GET method.
* Requires valid session ID with read permission for requested file.
*
* This script accepts following HTTP GET parameters:
* <ul>
* <li>sessid : string, session ID</li>
* <li>id : string, global unique ID of requested file</li>
* </ul>
*
* On success, returns HTTP return code 200 and requested file.
*
* On errors, returns HTTP return code &gt;200
* The possible error codes are:
* <ul>
* <li> 400 - Incorrect parameters passed to method</li>
* <li> 403 - Access denied</li>
* <li> 404 - File not found</li>
* <li> 500 - Application error</li>
* </ul>
*
*/
require_once(dirname(__FILE__).'/../../conf.php');
require_once('DB.php');
require_once(dirname(__FILE__).'/../LocStor.php');
require_once(dirname(__FILE__).'/../MetaData.php');
$CC_DBC = DB::connect($CC_CONFIG['dsn'], TRUE);
$CC_DBC->setErrorHandling(PEAR_ERROR_RETURN);
$CC_DBC->setFetchMode(DB_FETCHMODE_ASSOC);
$locStor = new LocStor();
function http_error($code, $err)
{
header("HTTP/1.1 $code");
header("Content-type: text/plain; charset=UTF-8");
echo "$err\r\n";
exit;
}
/**
* This function encodes an filename to
* be transferred via HTTP header.
*
* @param string $p_string utf8 filename
* @return string HTTP header encoded filename
*/
function sg_2hexstring($p_string)
{
for ($x=0; $x < strlen($p_string); $x++) {
$return .= '%' . bin2hex($p_string[$x]);
}
return $return;
}
// parameter checking:
if (preg_match("|^[0-9a-fA-F]{32}$|", $_REQUEST['sessid'])) {
$sessid = $_REQUEST['sessid'];
} else {
http_error(400, "Error on sessid parameter. ({$_REQUEST['sessid']})");
}
if (preg_match("|^[0-9a-fA-F]{16}$|", $_REQUEST['id'])) {
$gunid = $_REQUEST['id'];
} else {
http_error(400, "Error on id parameter. ({$_REQUEST['id']})");
}
// stored file recall:
$ac = StoredFile::RecallByGunid($gunid);
if (PEAR::isError($ac)) {
switch ($ac->getCode()) {
case GBERR_DENY:
http_error(403, "403 ".$ac->getMessage());
case GBERR_FILENEX:
case GBERR_FOBJNEX:
http_error(404, "404 File not found");
default:
http_error(500, "500 ".$ac->getMessage());
}
}
$lid = BasicStor::IdFromGunid($gunid);
if (PEAR::isError($lid)) {
http_error(500, $lid->getMessage());
}
if (($res = BasicStor::Authorize('read', $lid, $sessid)) !== TRUE) {
http_error(403, "403 Access denied");
}
$ftype = BasicStor::GetObjType($lid);
if (PEAR::isError($ftype)) {
http_error(500, $ftype->getMessage());
}
switch ($ftype) {
case "audioclip":
$realFname = $ac->getRealFileName();
$mime = $ac->getMime();
$md = new MetaData($ac->getGunId(), null);
$fileName = $md->getMetadataValue('dc:title').'.'.$ac->getFileExtension();
header("Content-type: $mime");
header("Content-length: ".filesize($realFname));
header("Content-Disposition: attachment; filename*=".sg_2hexstring($fileName).";");
readfile($realFname);
break;
case "webstream":
$url = $locStor->bsGetMetadataValue($lid, 'ls:url');
if (empty($url)) {
http_error(500, "Unable to get ls:url value");
}
$txt = "Location: $url";
header($txt);
// echo "$txt\n";
break;
case "playlist";
// $md = $locStor->bsGetMetadata($ac->getId(), $sessid);
$md = $locStor->getAudioClip($sessid, $gunid);
// header("Content-type: text/xml");
header("Content-type: application/smil");
echo $md;
break;
default:
// var_dump($ftype);
http_error(500, "500 Unknown ftype ($ftype)");
}

View file

@ -1,7 +0,0 @@
#!/usr/bin/php -q
<?
$fp = fopen("/dev/stdin", "r");
$data = '';
while($part = fgets($fp, 1024)) $data .= $part;
echo urldecode($data);
?>

View file

@ -1,172 +0,0 @@
<?php
/* ====================================================== specific PHP config */
ini_set("mbstring.internal_encoding", 'UTF-8');
ini_set("html_errors", FALSE);
ini_set("error_prepend_string", "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<methodResponse>
<fault>
<value>
<struct>
<member>
<name>faultCode</name>
<value><int>804</int></value>
</member>
<member>
<name>faultString</name>
<value><string>");
ini_set("error_append_string", "</string></value>
</member>
</struct>
</value>
</fault>
</methodResponse>");
header("Content-type: text/xml");
/* ================================================================= includes */
require_once(dirname(__FILE__).'/../../conf.php');
require_once('DB.php');
require_once("XML/RPC/Server.php");
require_once('XR_LocStor.php');
/* ============================================ setting default error handler */
function errHndl($errno, $errmsg, $filename, $linenum, $vars)
{
switch ($errno) {
case E_WARNING:
case E_NOTICE:
case E_USER_WARNING:
case E_USER_NOTICE:
return;
break;
default:
$xr = new XML_RPC_Response(0, 805,
htmlspecialchars("ERROR:xrLocStor: $errno $errmsg ($filename:$linenum)"));
header("Content-type: text/xml");
echo $xr->serialize();
exit($errno);
}
}
$old_error_handler = set_error_handler("errHndl", E_ALL);
/* ============================================================= runable code */
$CC_DBC = DB::connect($CC_CONFIG['dsn'], TRUE);
if (PEAR::isError($CC_DBC)) {
trigger_error("DB::connect: ".$CC_DBC->getMessage()." ".$CC_DBC->getUserInfo(),E_USER_ERROR);
}
$CC_DBC->setErrorHandling(PEAR_ERROR_RETURN);
$CC_DBC->setFetchMode(DB_FETCHMODE_ASSOC);
$locStor = new XR_LocStor();
$methods = array(
'test' => 'Tests toupper and checks sessid, params: '.
'teststring, sessid.',
'getVersion' => 'Get version of Airtime.',
// 'authenticate' => 'Checks authentication.',
'login' => 'Login to storage.',
'logout' => 'Logout from storage.',
'existsAudioClip' => 'Checks if an audio clip with the specified '.
'id is stored in local storage.',
'storeAudioClipOpen' => 'Open channel to store a new audio clip '.
'or replace an existing one.',
'storeAudioClipClose' => 'Close channel to store a new audio clip'.
' or replace an existing one.',
'downloadRawAudioDataOpen'=> 'Create and return downloadable URL'.
'for audio file',
'downloadRawAudioDataClose'=>'Discard downloadable URL for audio file',
'downloadMetadataOpen' => 'Create and return downloadable URL'.
'for metadata',
'downloadMetadataClose' => 'Discard downloadable URL for metadata',
'openPut' => 'openPut',
'closePut' => 'closePut',
'deleteAudioClip' => 'Delete an existing Audio clip.',
'updateAudioClipMetadata' => 'Update the metadata of an Audio clip '.
'stored in Local storage.',
'searchMetadata' => 'Search through the metadata of stored '.
'files, return all matching clip ids.',
'browseCategory' =>'Return values of specified metadata category.',
'accessRawAudioData' => 'Get access to raw audio data.',
'releaseRawAudioData' => 'Release access to raw audio data.',
'getAudioClip' => 'Return the contents of an Audio clip.',
// 'resetStorage' => 'Reset storageServer for debugging.',
'storeWebstream' => 'Store audio stream identified by URL',
'createPlaylist' => 'Create a new Playlist metafile.',
'editPlaylist' => 'Open a Playlist metafile for editing.',
'savePlaylist' => 'Save a Playlist metafile.',
'revertEditedPlaylist' => 'RollBack playlist changes to the locked state.',
'deletePlaylist' => 'Delete a Playlist metafile.',
'accessPlaylist' => 'Open readable URL to a Playlist metafile.',
'releasePlaylist' => 'Release readable URL from accessPlaylist.',
'existsPlaylist' => 'Check whether a Playlist exists.',
'playlistIsAvailable' => 'Check whether a Playlist is available '.
'for editing.',
'exportPlaylistOpen' => 'Create a tarfile with playlist export.',
'exportPlaylistClose' => 'Close playlist export.',
'importPlaylistOpen' => 'Open writable handle for playlist import.',
'importPlaylistClose' => 'Close import-handle and import playlist.',
'renderPlaylistToFileOpen' => 'Render playlist to ogg file (open handle)',
'renderPlaylistToFileCheck' => 'Render playlist to ogg file (check results)',
'renderPlaylistToFileClose' => 'Render playlist to ogg file (close handle)',
'renderPlaylistToStorageOpen' => 'Render playlist to storage media clip (open handle)',
'renderPlaylistToStorageCheck' => 'Render playlist to storage media clip (check results)',
'renderPlaylistToRSSOpen' => 'Render playlist to RSS file (open handle)',
'renderPlaylistToRSSCheck' => 'Render playlist to RSS file (check results)',
'renderPlaylistToRSSClose' => 'Render playlist to RSS file (close handle)',
'createBackupOpen' => 'Create backup of storage (open handle)',
'createBackupCheck' => 'Create backup of storage (check results)',
'createBackupClose' => 'Create backup of storage (close handle)',
'restoreBackupOpen' => 'Restore a backup file (open handle)',
'restoreBackupClosePut' => 'Restore a backup file (close PUT handle)',
'restoreBackupCheck' => 'Restore a backup file (check results)',
'restoreBackupClose' => 'Restore a backup file (close handle)',
'loadPref' => 'Load user preference value.',
'savePref' => 'Save user preference value.',
'delPref' => 'Delete user preference record.',
'loadGroupPref' => 'Read group preference record.',
'saveGroupPref' => 'Delete user preference record.',
'getTransportInfo' => 'Common "check" method and info getter for transports',
'turnOnOffTransports' => 'Turn transports on/off, optionaly return current state',
'doTransportAction' => 'Pause, resume or cancel transport',
'uploadFile2Hub' => 'Open async file transfer from local storageServer to network hub',
'getHubInitiatedTransfers' => 'Get list of prepared transfers initiated by hub',
'startHubInitiatedTransfer' => 'Start of download initiated by hub',
'upload2Hub' => 'Start upload of audioclip or playlist from local storageServer to hub',
'downloadFromHub' => 'Start download of audioclip or playlist from hub to local storageServer',
// 'globalSearch' => 'Start search job on network hub',
// 'getSearchResults' => 'Get results from search job on network hub',
'uploadOpen' => 'Open file-layer upload',
'uploadCheck' => 'Check the checksum of uploaded file',
'uploadClose' => 'Close file-layer upload',
'downloadOpen' => 'Open file-layer download',
// 'downloadCheck' => 'Check the checksum of downloaded file',
'downloadClose' => 'Close file-layer download',
'prepareHubInitiatedTransfer' => 'Prepare hub initiated transfer',
'listHubInitiatedTransfers' => 'List hub initiated transfers',
'setHubInitiatedTransfer' => 'Set state of hub initiated transfers',
'ping' => 'Echo request',
);
$defs = array();
foreach ($methods as $method => $description) {
$defs["locstor.$method"] = array(
"function" => array(&$locStor, "xr_$method"),
// NOTE: the way this signature is set up, every function must take at least one parameter!
"signature" => array(
array($GLOBALS['XML_RPC_Struct'], $GLOBALS['XML_RPC_Struct'])
),
"docstring" => $description
);
}
$s = new XML_RPC_Server($defs);

View file

@ -1,367 +0,0 @@
<?php
require_once(dirname(__FILE__).'/../../conf.php');
include_once("XML/RPC.php");
include_once("Console/Getopt.php");
function printUsage()
{
echo "Usage:\n";
echo " -v Verbose output\n";
echo " -s arg Server Path\n";
echo " -o arg1:value1,arg2:value2 Function Arguments\n";
echo " -h Help\n";
echo "\n";
}
$verbose = TRUE;
$parsedCommandLine = Console_Getopt::getopt($argv, "vs:o:h");
$options = null;
$cmdLineOptions = $parsedCommandLine[0];
if (count($parsedCommandLine[1]) == 0) {
printUsage();
exit;
}
$method = array_pop($parsedCommandLine[1]);
foreach ($cmdLineOptions as $tmpValue) {
$optionName = $tmpValue[0];
$optionValue = $tmpValue[1];
switch ($optionName) {
case "h":
printUsage();
exit;
case "v":
$verbose = TRUE;
break;
case "s":
$serverPath = $optionValue;
break;
case "o":
$optStr = $optionValue;
$optArr = split(",", $optStr);
foreach ($optArr as $opt) {
list($k, $v) = split(':', $opt);
$options[$k] = $v;
}
}
}
if (!isset($serverPath)) {
$serverPath =
"http://{$CC_CONFIG['storageUrlHost']}:{$CC_CONFIG['storageUrlPort']}".
"{$CC_CONFIG['storageUrlPath']}/{$CC_CONFIG['storageXMLRPC']}";
}
$url = parse_url($serverPath);
$client = new XML_RPC_Client($url['path'], $url['host']);
if ($verbose) {
$client->debug = 1;
echo "ServerPath: $serverPath\n";
echo "Host: {$url['host']}, path: {$url['path']}\n";
echo "Method: $method\n";
echo "Parameters:\n";
//var_dump($pars);
}
$infos = array(
"listMethods" => array('m'=>"system.listMethods", 'p'=>NULL),
"methodHelp" => array('m'=>"system.methodHelp", 'p'=>0),
"methodSignature" => array('m'=>"system.methodSignature", 'p'=>0),
"test" => array('m'=>"locstor.test", 'p'=>array('sessid', 'teststring')),
"ping" => array('m'=>"locstor.ping", 'p'=>array("par")),
"getVersion" => array('m'=>"locstor.getVersion", 'p'=>array("str"), 'r'=>'version'),
"authenticate" => array('m'=>"locstor.authenticate", 'p'=>array('login', 'pass'), 'r'=>'authenticate'),
"login" => array('m'=>"locstor.login", 'p'=>array('login', 'pass'), 'r'=>'sessid'),
"logout" => array('m'=>"locstor.logout", 'p'=>array('sessid'), 'r'=>'status'),
"storeAudioClipOpen" => array('m'=>"locstor.storeAudioClipOpen",
'p'=>array('sessid', 'gunid', 'metadata', 'fname', 'chsum'),
'r'=>array('url', 'token')
),
"storeAudioClipClose" => array('m'=>"locstor.storeAudioClipClose",
'p'=>array('sessid', 'token'), 'r'=>'gunid'),
"accessRawAudioData" => array('m'=>"locstor.accessRawAudioData",
'p'=>array('sessid', 'gunid'), 'r'=>array('url', 'token')),
"releaseRawAudioData" => array('m'=>"locstor.releaseRawAudioData",
'p'=>array('token'), 'r'=>'status'),
"downloadRawAudioDataOpen" =>
array('m'=>"locstor.downloadRawAudioDataOpen",
'p'=>array('sessid', 'gunid'), 'r'=>array('url', 'token')),
"downloadRawAudioDataClose" =>
array('m'=>"locstor.downloadRawAudioDataClose",
'p'=>array('sessid', 'token'), 'r'=>'gunid'),
"downloadMetadataOpen" => array('m'=>"locstor.downloadMetadataOpen",
'p'=>array('sessid', 'gunid'), 'r'=>array('url', 'token')),
"downloadMetadataClose" => array('m'=>"locstor.downloadMetadataClose",
'p'=>array('sessid', 'token'), 'r'=>'gunid'),
"deleteAudioClip" =>
array('m'=>"locstor.deleteAudioClip",
'p'=>array('sessid', 'gunid', 'forced'), 'r'=>'status'),
"existsAudioClip" => array('m'=>"locstor.existsAudioClip",
'p'=>array('sessid', 'gunid'), 'r'=>'exists'),
"getAudioClip" => array('m'=>"locstor.getAudioClip",
'p'=>array('sessid', 'gunid'), 'r'=>'metadata'),
"updateAudioClipMetadata" => array('m'=>"locstor.updateAudioClipMetadata",
'p'=>array('sessid', 'gunid', 'metadata'), 'r'=>'status'),
"searchMetadata" => array('m'=>"locstor.searchMetadata", 'p'=>NULL),
"browseCategory" => array('m'=>"locstor.browseCategory", 'p'=>NULL),
// "resetStorage" => array('m'=>"locstor.resetStorage",
// 'p'=>array()),
# 'p'=>array('loadSampleData', 'invalidateSessionIds')),
"storeWebstream" => array('m'=>"locstor.storeWebstream",
'p'=>array('sessid', 'gunid', 'metadata', 'fname', 'url'),
'r'=>array('gunid')
),
"createPlaylist" => array('m'=>"locstor.createPlaylist",
'p'=>array('sessid', 'plid', 'fname'), 'r'=>'plid'),
"editPlaylist" => array('m'=>"locstor.editPlaylist",
'p'=>array('sessid', 'plid'), 'r'=>array('url', 'token')),
"savePlaylist" => array('m'=>"locstor.savePlaylist",
'p'=>array('sessid', 'token', 'newPlaylist'), 'r'=>'plid'),
"revertEditedPlaylist" => array('m'=>"locstor.revertEditedPlaylist",
'p'=>array('sessid', 'token'), 'r'=>'plid'),
"deletePlaylist" => array('m'=>"locstor.deletePlaylist",
'p'=>array('sessid', 'plid', 'forced'), 'r'=>'status'),
"accessPlaylist" => array('m'=>"locstor.accessPlaylist",
'p'=>array('sessid', 'plid'), 'r'=>array('url', 'token')),
"releasePlaylist" => array('m'=>"locstor.releasePlaylist",
'p'=>array('token'), 'r'=>'plid'),
"existsPlaylist" => array('m'=>"locstor.existsPlaylist",
'p'=>array('sessid', 'plid'), 'r'=>'exists'),
"playlistIsAvailable" => array('m'=>"locstor.playlistIsAvailable",
'p'=>array('sessid', 'plid'), 'r'=>array('available', 'ownerid', 'ownerlogin')),
"exportPlaylistOpen" => array('m'=>"locstor.exportPlaylistOpen",
'p'=>array('sessid', 'plids', 'type', 'standalone'),
'r'=>array('url', 'token')),
"exportPlaylistClose" => array('m'=>"locstor.exportPlaylistClose",
'p'=>array('token'), 'r'=>array('status')),
"importPlaylistOpen" => array('m'=>"locstor.importPlaylistOpen",
'p'=>array('sessid', 'chsum'), 'r'=>array('url', 'token')),
"importPlaylistClose" => array('m'=>"locstor.importPlaylistClose",
'p'=>array('token'), 'r'=>array('gunid')),
"renderPlaylistToFileOpen" => array('m'=>"locstor.renderPlaylistToFileOpen",
'p'=>array('sessid', 'plid'),
'r'=>array('token')),
"renderPlaylistToFileCheck" => array('m'=>"locstor.renderPlaylistToFileCheck",
'p'=>array('token'), 'r'=>array('status', 'url')),
"renderPlaylistToFileClose" => array('m'=>"locstor.renderPlaylistToFileClose",
'p'=>array('token'), 'r'=>array('status')),
"renderPlaylistToStorageOpen" => array('m'=>"locstor.renderPlaylistToStorageOpen",
'p'=>array('sessid', 'plid'),
'r'=>array('token')),
"renderPlaylistToStorageCheck" => array('m'=>"locstor.renderPlaylistToStorageCheck",
'p'=>array('token'), 'r'=>array('status', 'gunid')),
"renderPlaylistToRSSOpen" => array('m'=>"locstor.renderPlaylistToRSSOpen",
'p'=>array('sessid', 'plid'),
'r'=>array('token')),
"renderPlaylistToRSSCheck" => array('m'=>"locstor.renderPlaylistToRSSCheck",
'p'=>array('token'), 'r'=>array('status', 'url')),
"renderPlaylistToRSSClose" => array('m'=>"locstor.renderPlaylistToRSSClose",
'p'=>array('token'), 'r'=>array('status')),
"loadPref" => array('m'=>"locstor.loadPref",
'p'=>array('sessid', 'key'), 'r'=>'value'),
"savePref" => array('m'=>"locstor.savePref",
'p'=>array('sessid', 'key', 'value'), 'r'=>'status'),
"delPref" => array('m'=>"locstor.delPref",
'p'=>array('sessid', 'key'), 'r'=>'status'),
"loadGroupPref" => array('m'=>"locstor.loadGroupPref",
'p'=>array('sessid', 'group', 'key'), 'r'=>'value'),
"saveGroupPref" => array('m'=>"locstor.saveGroupPref",
'p'=>array('sessid', 'group', 'key', 'value'), 'r'=>'status'),
"getTransportInfo" => array('m'=>"locstor.getTransportInfo",
'p'=>array('trtok'),
'r'=>array('state', 'realsize', 'expectedsize', 'realsum', 'expectedsum')),
"turnOnOffTransports" => array('m'=>"locstor.turnOnOffTransports",
'p'=>array('sessid', 'onOff'), 'r'=>array('state')),
"doTransportAction" => array('m'=>"locstor.doTransportAction",
'p'=>array('sessid', 'trtok', 'action'), 'r'=>array('state')),
"uploadFile2Hub" => array('m'=>"locstor.uploadFile2Hub",
'p'=>array('sessid', 'filePath'), 'r'=>array('trtok')),
"getHubInitiatedTransfers" => array('m'=>"locstor.getHubInitiatedTransfers",
'p'=>array('sessid'), 'r'=>array()),
"startHubInitiatedTransfer" => array('m'=>"locstor.startHubInitiatedTransfer",
'p'=>array('trtok'), 'r'=>array()),
"upload2Hub" => array('m'=>"locstor.upload2Hub",
'p'=>array('sessid', 'gunid'), 'r'=>array('trtok')),
"downloadFromHub" => array('m'=>"locstor.downloadFromHub",
'p'=>array('sessid', 'gunid'), 'r'=>array('trtok')),
// "globalSearch" => array('m'=>"locstor.globalSearch",
// 'p'=>array('sessid', 'criteria'), 'r'=>array('trtok')),
// "getSearchResults" => array('m'=>"locstor.getSearchResults",
// 'p'=>array('trtok')),
"createBackupOpen" => array('m'=>"locstor.createBackupOpen",
'p'=>array('sessid', 'criteria'), 'r'=>array('token')),
"createBackupCheck" => array('m'=>"locstor.createBackupCheck",
# 'p'=>array('token'), 'r'=>array('status', 'url', 'metafile', 'faultString')),
'p'=>array('token'), 'r'=>array('status', 'url', 'tmpfile')),
"createBackupClose" => array('m'=>"locstor.createBackupClose",
'p'=>array('token'), 'r'=>array('status')),
"restoreBackupOpen" => array('m'=>"locstor.restoreBackupOpen",
'p'=>array('sessid', 'chsum'), 'r'=>array('url', 'token')),
"restoreBackupClosePut" => array('m'=>"locstor.restoreBackupClosePut",
'p'=>array('sessid', 'token'), 'r'=>array('token')),
"restoreBackupCheck" => array('m'=>"locstor.restoreBackupCheck",
'p'=>array('token'), 'r'=>array('status', 'faultString')),
"restoreBackupClose" => array('m'=>"locstor.restoreBackupClose",
'p'=>array('token'), 'r'=>array('status')),
/*
"uploadToArchive" => array('m'=>"locstor.uploadToArchive",
'p'=>array('sessid', 'gunid'), 'r'=>'trtok'),
"downloadFromArchive" => array('m'=>"locstor.downloadFromArchive",
'p'=>array('sessid', 'gunid'), 'r'=>'trtok'),
*/
"openPut" => array('m'=>"locstor.openPut", 'p'=>array()),
"closePut" => array('m'=>"locstor.closePut", 'p'=>array()),
);
switch ($method) {
case "searchMetadata":
// case "globalSearch":
case "createBackupOpen":
$parr = array(
'sessid'=>$pars[0],
'criteria'=>array(
'filetype'=>'audioclip',
'operator'=>'and',
'limit'=> 0,
'offset'=> 0,
'conditions'=>array(
array('cat'=>$pars[1], 'op'=>'partial', 'val'=>$pars[2])
)
),
);
break;
case "browseCategory":
$parr = array(
'sessid'=>$pars[0],
'category'=>$pars[1],
'criteria'=>array(
'filetype'=>'audioclip',
'operator'=>'and',
'limit'=> 0,
'offset'=> 0,
'conditions'=>array(
array('cat'=>$pars[2], 'op'=>'partial', 'val'=>$pars[3])
)
),
);
break;
// case "resetStorage":
// $parr = array(
// 'loadSampleData'=>(boolean)$pars[0],
// 'invalidateSessionIds'=>(boolean)$pars[1],
// );
// break;
default:
$pinfo = $infos[$method]['p'];
if (is_null($pinfo)) {
$parr = NULL;
} elseif(!is_array($pinfo)) {
$parr = $pars[0];
#echo "pinfo not null and not array.\n"; exit;
} elseif(count($pinfo) == 0) {
$parr = (object)array();
} else {
$parr = array(); $i=0;
foreach($pinfo as $it){
if(isset($pars[$i])) $parr[$it] = $pars[$i];
$i++;
}
}
} // switch
$fullmethod = $infos[$method]['m'];
if (is_array($options)) {
$msg = new XML_RPC_Message($fullmethod, array(XML_RPC_encode($options)));
} else {
$msg = new XML_RPC_Message($fullmethod);
}
//$msg = new XML_RPC_Message($fullmethod, array(XML_RPC_encode($parr)));
if ($verbose) {
echo "parr:\n";
var_dump($parr);
echo "message:\n";
echo $msg->serialize()."\n";
}
#$client->setDebug(1);
$res = $client->send($msg);
if ($res->faultCode() > 0) {
echo "xr_cli_test.php: ".$res->faultString()." ".$res->faultCode()."\n";
# echo var_export($res);
exit(1);
}
if ($verbose) {
echo "result:\n";
echo $res->serialize();
}
$resp = XML_RPC_decode($res->value());
if (isset($infos[$method]['r'])) {
$pom = $infos[$method]['r'];
if (is_array($pom)) {
foreach ($pom as $k => $it) {
$pom[$k] = $resp[$it];
}
echo join(' ', $pom)."\n";
} else {
switch ($pom) {
case "status":
case "exists":
echo ($resp[$pom]=='1' ? "TRUE" : "FALSE" )."\n";
break;
default:
echo "{$resp[$pom]}\n";
}
}
} else {
switch ($method) {
case "searchMetadata":
// case "getSearchResults":
$acCnt = 0;
$acGunids = array();
$plCnt = 0;
$plGunids = array();
$fld = (isset($options['category']) ? $options['category'] : 'gunid' );
foreach ($resp['results'] as $k => $v) {
if ($v['type']=='audioclip') {
$acCnt++;
$acGunids[] = $v[$fld];
}
if ($v['type']=='playlist') {
$plCnt++;
$plGunids[] = $v[$fld];
}
}
echo "AC({$acCnt}): ".
join(", ", $acGunids).
" | PL({$plCnt}): ".
join(", ", $plGunids).
"\n";
break;
case "browseCategory":
echo "RES({$resp['cnt']}): ".
join(", ", $resp['results']).
"\n";
break;
default:
print_r($resp);
echo "\n";
}
}

View file

@ -1,373 +0,0 @@
<?php
require_once(dirname(__FILE__).'/../../conf.php');
include_once("XML/RPC.php");
session_start();
/**
* Get a persistant value. If the value is present in the $_REQUEST
* array, the session variable will be set to this value and returned.
* If the value is not yet set, it will be set to the default value.
* In all other cases the value from the session variable is returned.
*
* @param string $p_name
* @param mixed $p_defaultValue
* @return mixed
*/
function camp_session_get($p_name, $p_defaultValue)
{
// Use the REQUEST variable if it is set.
if (isset($_REQUEST[$p_name])) {
$_SESSION[$p_name] = $_REQUEST[$p_name];
}
elseif (!isset($_SESSION[$p_name])) {
$_SESSION[$p_name] = $p_defaultValue;
}
return $_SESSION[$p_name];
} // fn camp_session_get
/**
* Print out an HTML OPTION element.
*
* @param string $p_value
* @param string $p_selectedValue
* @param string $p_printValue
* @return boolean
* Return TRUE if the option is selected, FALSE if not.
*/
function camp_html_select_option($p_value, $p_selectedValue, $p_printValue)
{
$selected = false;
$str = '<OPTION VALUE="'.htmlspecialchars($p_value, ENT_QUOTES).'"';
if (!strcmp($p_value, $p_selectedValue)) {
$str .= ' SELECTED';
$selected = true;
}
$str .= '>'.htmlspecialchars($p_printValue)."</OPTION>\n";
echo $str;
return $selected;
} // fn camp_html_select_option
$serverPath =
"http://{$CC_CONFIG['storageUrlHost']}:{$CC_CONFIG['storageUrlPort']}".
"{$CC_CONFIG['storageUrlPath']}/{$CC_CONFIG['storageXMLRPC']}";
$serverPath = camp_session_get("storageserver_xmlrpc_path", $serverPath);
$f_selectedMethod = camp_session_get("f_selectedMethod", "listMethods");
$url = parse_url($serverPath);
$client = new XML_RPC_Client($url['path'], $url['host']);
$methodDefs = array(
"listMethods" => array('m'=>"system.listMethods", 'p'=>NULL),
"methodHelp" => array('m'=>"system.methodHelp", 'p'=>0),
"methodSignature" => array('m'=>"system.methodSignature", 'p'=>0),
"test" => array('m'=>"locstor.test", 'p'=>array('sessid', 'teststring')),
"getVersion" => array('m'=>"locstor.getVersion", 'p'=>array(), 'r'=>'version'),
"authenticate" => array('m'=>"locstor.authenticate", 'p'=>array('login', 'pass'), 'r'=>'authenticate'),
"login" => array('m'=>"locstor.login", 'p'=>array('login', 'pass'), 'r'=>'sessid'),
"logout" => array('m'=>"locstor.logout", 'p'=>array('sessid'), 'r'=>'status'),
"storeAudioClipOpen" => array('m'=>"locstor.storeAudioClipOpen",
'p'=>array('sessid', 'gunid', 'metadata', 'fname', 'chsum'),
'r'=>array('url', 'token')
),
"storeAudioClipClose" => array('m'=>"locstor.storeAudioClipClose",
'p'=>array('sessid', 'token'), 'r'=>'gunid'),
"accessRawAudioData" => array('m'=>"locstor.accessRawAudioData",
'p'=>array('sessid', 'gunid'), 'r'=>array('url', 'token')),
"releaseRawAudioData" => array('m'=>"locstor.releaseRawAudioData",
'p'=>array('token'), 'r'=>'status'),
"downloadRawAudioDataOpen" =>
array('m'=>"locstor.downloadRawAudioDataOpen",
'p'=>array('sessid', 'gunid'), 'r'=>array('url', 'token')),
"downloadRawAudioDataClose" =>
array('m'=>"locstor.downloadRawAudioDataClose",
'p'=>array('sessid', 'token'), 'r'=>'gunid'),
"downloadMetadataOpen" => array('m'=>"locstor.downloadMetadataOpen",
'p'=>array('sessid', 'gunid'), 'r'=>array('url', 'token')),
"downloadMetadataClose" => array('m'=>"locstor.downloadMetadataClose",
'p'=>array('sessid', 'token'), 'r'=>'gunid'),
"deleteAudioClip" =>
array('m'=>"locstor.deleteAudioClip",
'p'=>array('sessid', 'gunid', 'forced'), 'r'=>'status'),
"existsAudioClip" => array('m'=>"locstor.existsAudioClip",
'p'=>array('sessid', 'gunid'), 'r'=>'exists'),
"getAudioClip" => array('m'=>"locstor.getAudioClip",
'p'=>array('sessid', 'gunid'), 'r'=>'metadata'),
"updateAudioClipMetadata" => array('m'=>"locstor.updateAudioClipMetadata",
'p'=>array('sessid', 'gunid', 'metadata'), 'r'=>'status'),
"searchMetadata" => array('m'=>"locstor.searchMetadata", 'p'=>NULL),
"browseCategory" => array('m'=>"locstor.browseCategory", 'p'=>NULL),
// "resetStorage" => array('m'=>"locstor.resetStorage",
// 'p'=>array()),
"storeWebstream" => array('m'=>"locstor.storeWebstream",
'p'=>array('sessid', 'gunid', 'metadata', 'fname', 'url'),
'r'=>array('gunid')
),
"createPlaylist" => array('m'=>"locstor.createPlaylist",
'p'=>array('sessid', 'plid', 'fname'), 'r'=>'plid'),
"editPlaylist" => array('m'=>"locstor.editPlaylist",
'p'=>array('sessid', 'plid'), 'r'=>array('url', 'token')),
"savePlaylist" => array('m'=>"locstor.savePlaylist",
'p'=>array('sessid', 'token', 'newPlaylist'), 'r'=>'plid'),
"revertEditedPlaylist" => array('m'=>"locstor.revertEditedPlaylist",
'p'=>array('sessid', 'token'), 'r'=>'plid'),
"deletePlaylist" => array('m'=>"locstor.deletePlaylist",
'p'=>array('sessid', 'plid', 'forced'), 'r'=>'status'),
"accessPlaylist" => array('m'=>"locstor.accessPlaylist",
'p'=>array('sessid', 'plid'), 'r'=>array('url', 'token')),
"releasePlaylist" => array('m'=>"locstor.releasePlaylist",
'p'=>array('token'), 'r'=>'plid'),
"existsPlaylist" => array('m'=>"locstor.existsPlaylist",
'p'=>array('sessid', 'plid'), 'r'=>'exists'),
"playlistIsAvailable" => array('m'=>"locstor.playlistIsAvailable",
'p'=>array('sessid', 'plid'), 'r'=>array('available', 'ownerid', 'ownerlogin')),
"exportPlaylistOpen" => array('m'=>"locstor.exportPlaylistOpen",
'p'=>array('sessid', 'plids', 'type', 'standalone'),
'r'=>array('url', 'token')),
"exportPlaylistClose" => array('m'=>"locstor.exportPlaylistClose",
'p'=>array('token'), 'r'=>array('status')),
"importPlaylistOpen" => array('m'=>"locstor.importPlaylistOpen",
'p'=>array('sessid', 'chsum'), 'r'=>array('url', 'token')),
"importPlaylistClose" => array('m'=>"locstor.importPlaylistClose",
'p'=>array('token'), 'r'=>array('gunid')),
"renderPlaylistToFileOpen" => array('m'=>"locstor.renderPlaylistToFileOpen",
'p'=>array('sessid', 'plid'),
'r'=>array('token')),
"renderPlaylistToFileCheck" => array('m'=>"locstor.renderPlaylistToFileCheck",
'p'=>array('token'), 'r'=>array('status', 'url')),
"renderPlaylistToFileClose" => array('m'=>"locstor.renderPlaylistToFileClose",
'p'=>array('token'), 'r'=>array('status')),
"renderPlaylistToStorageOpen" => array('m'=>"locstor.renderPlaylistToStorageOpen",
'p'=>array('sessid', 'plid'),
'r'=>array('token')),
"renderPlaylistToStorageCheck" => array('m'=>"locstor.renderPlaylistToStorageCheck",
'p'=>array('token'), 'r'=>array('status', 'gunid')),
"renderPlaylistToRSSOpen" => array('m'=>"locstor.renderPlaylistToRSSOpen",
'p'=>array('sessid', 'plid'),
'r'=>array('token')),
"renderPlaylistToRSSCheck" => array('m'=>"locstor.renderPlaylistToRSSCheck",
'p'=>array('token'), 'r'=>array('status', 'url')),
"renderPlaylistToRSSClose" => array('m'=>"locstor.renderPlaylistToRSSClose",
'p'=>array('token'), 'r'=>array('status')),
"loadPref" => array('m'=>"locstor.loadPref",
'p'=>array('sessid', 'key'), 'r'=>'value'),
"savePref" => array('m'=>"locstor.savePref",
'p'=>array('sessid', 'key', 'value'), 'r'=>'status'),
"delPref" => array('m'=>"locstor.delPref",
'p'=>array('sessid', 'key'), 'r'=>'status'),
"loadGroupPref" => array('m'=>"locstor.loadGroupPref",
'p'=>array('sessid', 'group', 'key'), 'r'=>'value'),
"saveGroupPref" => array('m'=>"locstor.saveGroupPref",
'p'=>array('sessid', 'group', 'key', 'value'), 'r'=>'status'),
"getTransportInfo" => array('m'=>"locstor.getTransportInfo",
'p'=>array('trtok'),
'r'=>array('state', 'realsize', 'expectedsize', 'realsum', 'expectedsum')),
"turnOnOffTransports" => array('m'=>"locstor.turnOnOffTransports",
'p'=>array('sessid', 'onOff'), 'r'=>array('state')),
"doTransportAction" => array('m'=>"locstor.doTransportAction",
'p'=>array('sessid', 'trtok', 'action'), 'r'=>array('state')),
"uploadFile2Hub" => array('m'=>"locstor.uploadFile2Hub",
'p'=>array('sessid', 'filePath'), 'r'=>array('trtok')),
"getHubInitiatedTransfers" => array('m'=>"locstor.getHubInitiatedTransfers",
'p'=>array('sessid'), 'r'=>array()),
"startHubInitiatedTransfer" => array('m'=>"locstor.startHubInitiatedTransfer",
'p'=>array('trtok'), 'r'=>array()),
"upload2Hub" => array('m'=>"locstor.upload2Hub",
'p'=>array('sessid', 'gunid'), 'r'=>array('trtok')),
"downloadFromHub" => array('m'=>"locstor.downloadFromHub",
'p'=>array('sessid', 'gunid'), 'r'=>array('trtok')),
// "globalSearch" => array('m'=>"locstor.globalSearch",
// 'p'=>array('sessid', 'criteria'), 'r'=>array('trtok')),
// "getSearchResults" => array('m'=>"locstor.getSearchResults",
// 'p'=>array('trtok')),
"createBackupOpen" => array('m'=>"locstor.createBackupOpen",
'p'=>array('sessid', 'criteria'), 'r'=>array('token')),
"createBackupCheck" => array('m'=>"locstor.createBackupCheck",
# 'p'=>array('token'), 'r'=>array('status', 'url', 'metafile', 'faultString')),
'p'=>array('token'), 'r'=>array('status', 'url', 'tmpfile')),
"createBackupClose" => array('m'=>"locstor.createBackupClose",
'p'=>array('token'), 'r'=>array('status')),
"restoreBackupOpen" => array('m'=>"locstor.restoreBackupOpen",
'p'=>array('sessid', 'chsum'), 'r'=>array('url', 'token')),
"restoreBackupClosePut" => array('m'=>"locstor.restoreBackupClosePut",
'p'=>array('sessid', 'token'), 'r'=>array('token')),
"restoreBackupCheck" => array('m'=>"locstor.restoreBackupCheck",
'p'=>array('token'), 'r'=>array('status', 'faultString')),
"restoreBackupClose" => array('m'=>"locstor.restoreBackupClose",
'p'=>array('token'), 'r'=>array('status')),
"openPut" => array('m'=>"locstor.openPut", 'p'=>array()),
"closePut" => array('m'=>"locstor.closePut", 'p'=>array()),
);
if (isset($_REQUEST['go_button'])) {
// Get the parameters
$methodParams = $methodDefs[$f_selectedMethod]['p'];
foreach ($methodParams as $methodParamName) {
$inputParamName = "param_".$methodParamName;
$xmlParameters[$methodParamName] = $_REQUEST[$inputParamName];
$_SESSION[$inputParamName] = $_REQUEST[$inputParamName];
}
// Create the XML-RPC message
$actualMethod = $methodDefs[$f_selectedMethod]['m'];
$msg = new XML_RPC_Message($actualMethod, array(XML_RPC_encode($xmlParameters)));
$sentMessage = $msg->serialize();
// Send it
$sendResult = $client->send($msg);
if ($sendResult->faultCode() > 0) {
$errorMsg = "xr_cli_test.php: ".$sendResult->faultString()." ".$sendResult->faultCode()."\n";
} else {
// If successful
$xmlResponse = XML_RPC_decode($sendResult->value());
// Special case state handling
switch ($f_selectedMethod) {
case "login":
// Remember the login session ID so we can use it to call
// other methods.
$loggedIn = true;
$_SESSION['xmlrpc_session_id'] = $xmlResponse['sessid'];
break;
case "logout":
unset($_SESSION['xmlrpc_session_id']);
break;
case "storeAudioClipOpen":
$_SESSION['xmlrpc_token'] = $xmlResponse['token'];
$_SESSION['xmlrpc_put_url'] = $xmlResponse['url'];
break;
}
if (isset($methodDefs[$method]['r'])) {
$expectedResult = $methodDefs[$method]['r'];
if (is_array($expectedResult)) {
foreach ($expectedResult as $resultName) {
$actualResults[$resultName] = $xmlResponse[$resultName];
}
echo join(' ', $actualResults)."\n";
} else {
switch ($expectedResult) {
case "status":
case "exists":
echo ($xmlResponse[$expectedResult]=='1' ? "TRUE" : "FALSE" )."\n";
break;
default:
echo "{$xmlResponse[$expectedResult]}\n";
}
}
} else {
switch ($method) {
case "searchMetadata":
// case "getSearchResults":
$acCnt = 0;
$acGunids = array();
$plCnt = 0;
$plGunids = array();
$fld = (isset($options['category']) ? $options['category'] : 'gunid' );
foreach ($xmlResponse['results'] as $k => $v) {
if ($v['type']=='audioclip') {
$acCnt++;
$acGunids[] = $v[$fld];
}
if ($v['type']=='playlist') {
$plCnt++;
$plGunids[] = $v[$fld];
}
}
echo "AC({$acCnt}): ".
join(", ", $acGunids).
" | PL({$plCnt}): ".
join(", ", $plGunids).
"\n";
break;
case "browseCategory":
echo "RES({$xmlResponse['cnt']}): ".
join(", ", $xmlResponse['results']).
"\n";
break;
default:
//print_r($xmlResponse);
}
}
}
}
?>
<html>
<body bgcolor="#dddddd">
<form>
StorageServer path : <INPUT type="text" name="f_storageserver_xmlrpc_path" value="<?php echo $serverPath; ?>" size="100"><br>
Method:
<select name="f_selectedMethod" onchange="this.form.submit();">
<?php
foreach ($methodDefs as $methodName => $methodDef) {
camp_html_select_option($methodName, $f_selectedMethod, $methodName);
}
?>
</select>
<br>
Parameters:
<?PHP
$methodParams = $methodDefs[$f_selectedMethod]['p'];
if (!is_array($methodParams) || count($methodParams) == 0) {
echo "This method requires no parameters.<br>";
} else {
echo "<table cellpadding=3>";
foreach ($methodParams as $methodParamName) {
$value = "";
if ($methodParamName == "sessid" && isset($_SESSION['xmlrpc_session_id'])) {
$value = $_SESSION['xmlrpc_session_id'];
} elseif ($methodParamName == "token" && isset($_SESSION['xmlrpc_token'])) {
$value = $_SESSION['xmlrpc_token'];
} elseif (isset($_SESSION["param_".$methodParamName])) {
$value = $_SESSION["param_".$methodParamName];
}
echo "<tr>";
echo "<td>$methodParamName</td>"; ?> <td><INPUT type="text" name="param_<?php echo $methodParamName; ?>" value="<?php echo $value; ?>"><td></tr>
<?php
}
echo "</table>";
}
?>
<br>
<INPUT type="submit" name="go_button" value="Send Message">
</form>
<?PHP
if ($loggedIn) {
echo "You have logged in with session ID: ".$_SESSION['xmlrpc_session_id']."<br><br>";
}
if (isset($sentMessage)) {
?>
Sent message:<br>
<TEXTAREA cols="60" rows="8">Method name: <?php echo $actualMethod; ?>
<?php print_r($xmlParameters);?></TEXTAREA>
<br>
<?PHP
}
if (isset($errorMsg)) {
?>
Error:<br>
<TEXTAREA cols="60" rows="8"><?php print_r($errorMsg);?></TEXTAREA>
<br>
<?php
}
if (isset($xmlResponse)) {
?>
Response:<br>
<TEXTAREA cols="60" rows="8"><?php print_r($xmlResponse);?></TEXTAREA>
<br>
<?php
}
?>
</body>
</html>

View file

@ -7,5 +7,5 @@
<?php echo $this->form; ?>
</div>
</div>
<div class="footer"> Airtime&nbsp;1.7.0-alpha&nbsp;Copyright &copy; Sourcefabric o.p.s 2011. All rights reserved.<br/>
Maintained and distributed under GNU GPL v.2 by <a href="http://www.sourcefabric.org"> Sourcefabric o.p.s </a> </div>
<div class="footer"> Airtime&nbsp;<?php echo $this->airtimeVersion ?>&nbsp;Copyright &copy; Sourcefabric o.p.s <?php echo $this->airtimeCopyright ?>. All rights reserved.<br/>
Maintained and distributed under GNU GPL v.3 by <a href="http://www.sourcefabric.org"> Sourcefabric o.p.s </a> </div>

3
dev/pf.sh Executable file
View file

@ -0,0 +1,3 @@
#!/bin/sh
su -l pypo -c "tail -F /etc/service/pypo-fetch/log/main/current"

3
dev/pl.sh Executable file
View file

@ -0,0 +1,3 @@
#!/bin/sh
su -l pypo -c "tail -F /etc/service/pypo-liquidsoap/log/main/current"

3
dev/pp.sh Executable file
View file

@ -0,0 +1,3 @@
#!/bin/sh
su -l pypo -c "tail -F /etc/service/pypo-push/log/main/current"

View file

@ -7,7 +7,7 @@
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-1.9.xsd">
<!--
<changeSet id="1" author="bob">
<changeSet id="2011-03-01-16-30-00" author="bob">
<createTable tableName="department">
<column name="id" type="int">
<constraints primaryKey="true" nullable="false"/>

View file

@ -60,7 +60,7 @@ var columns = [{"sTitle": "type", "bVisible":false},
{"sTitle":"Album"},
{"sTitle":"Playlist"},
{"sTitle":"Show"},
{"sTitle":"bgcolor", "bVisible":false},
{"sTitle":"instance_id", "bVisible":true},
{"sTitle":"group_id", "bVisible":false}];
function getDateString(){
@ -85,7 +85,9 @@ function updateDataTable(){
//function can be called before ajax call has been returned.
if (datagridData != null){
table.fnClearTable(false);
table.fnAddData(datagridData.rows, false);
for (var show in datagridData.rows){
table.fnAddData(datagridData.rows[show].items, false);
}
table.fnDraw(true);
}
}
@ -133,6 +135,45 @@ function createDataGrid(){
$(nRow).attr("class", "gap");
return nRow;
},
"fnDrawCallback": function(oSettings){
//check if there are any rows to display
if (oSettings.aiDisplay.length == 0)
return;
var nTrs = $('#nowplayingtable tbody tr');
var iColspan = nTrs[0].getElementsByTagName('td').length;
for (var i=0; i<nTrs.length; i++){
var iDisplayIndex = oSettings._iDisplayStart + i;
var sType = oSettings.aoData[ oSettings.aiDisplay[iDisplayIndex]]._aData[0];
if ( sType == "s" ){
var showName = oSettings.aoData[ oSettings.aiDisplay[iDisplayIndex]]._aData[9];
var startTime = oSettings.aoData[ oSettings.aiDisplay[iDisplayIndex]]._aData[2];
var endTime = oSettings.aoData[ oSettings.aiDisplay[iDisplayIndex]]._aData[3];
var nGroup = document.createElement('tr');
var nCell = document.createElement('td');
nCell.colSpan = iColspan;
nCell.className = "group";
nCell.innerHTML = showName + ": " + startTime + " - " + endTime;
nGroup.appendChild(nCell);
nTrs[i].parentNode.replaceChild(nGroup, nTrs[i]);
} else if ( sType == "b" ){
var gapTime = oSettings.aoData[ oSettings.aiDisplay[iDisplayIndex]]._aData[1];
var nGroup = document.createElement('tr');
var nCell = document.createElement('td');
nCell.colSpan = iColspan;
nCell.className = "gap";
nCell.innerHTML = "Gap until show end: " + gapTime + " seconds";
nGroup.appendChild(nCell);
nTrs[i].parentNode.replaceChild(nGroup, nTrs[i]);
}
}
},
"bAutoWidth":false
} );
}

View file

@ -174,7 +174,7 @@ class AirTimeApiClient(ApiClientInterface):
print 'Unable to get Airtime version number.'
print
return False
elif (version[0:4] != "1.6."):
elif (version[0:4] != "1.7."):
if (verbose):
print 'Airtime version: ' + str(version)
print 'pypo not compatible with this version of Airtime.'

View file

@ -5,62 +5,45 @@
Python part of radio playout (pypo)
The main functions are "fetch" (./pypo_cli.py -f) and "push" (./pypo_cli.py -p)
There are two layers: scheduler & daypart (fallback)
The daypart is a fallback-layer generated by the playlists daypart-settings
(eg a playlist creator can say that the list is good for Monday and Tues,
between 14:00 and 16:00). So if there is nothing in the schedule, pypo will
still play something (instead of silence..) This layer is optional.
It is there so that you dont have a fallback player which plays the same 100
tracks over and over again.
Attention & ToDos
- liquidsoap does not like mono files! So we have to make sure that only files with
2 channels are fed to LiquidSoap
(solved: current = audio_to_stereo(current) - maybe not with ultimate performance)
"""
# python defaults (debian default)
import time
import calendar
#import calendar
import os
import traceback
#import traceback
from optparse import *
import sys
import time
import datetime
#import datetime
import logging
import logging.config
import shutil
import urllib
import urllib2
import pickle
import telnetlib
import random
import string
import operator
import inspect
#import shutil
#import urllib
#import urllib2
#import pickle
#import telnetlib
#import random
#import string
#import operator
#import inspect
from pypopush import PypoPush
from pypofetch import PypoFetch
# additional modules (should be checked)
from configobj import ConfigObj
# custom imports
from util import *
from api_clients import *
from util import CueFile
from api_clients import api_client
PYPO_VERSION = '0.2'
PYPO_MEDIA_SKIP = 1
PYPO_MEDIA_LIVE_SESSION = 2
PYPO_MEDIA_STREAM = 3
PYPO_MEDIA_FILE_URL = 4
PYPO_MEDIA_FILE_LOCAL = 5
PYPO_VERSION = '1.1'
# Set up command-line options
parser = OptionParser()
# help screeen / info
# help screen / info
usage = "%prog [options]" + " - python playout system"
parser = OptionParser(usage=usage)
@ -71,11 +54,7 @@ parser.add_option("-t", "--test", help="Do a test to make sure everything is wor
parser.add_option("-f", "--fetch-scheduler", help="Fetch the schedule from server. This is a polling process that runs forever.", default=False, action="store_true", dest="fetch_scheduler")
parser.add_option("-p", "--push-scheduler", help="Push the schedule to Liquidsoap. This is a polling process that runs forever.", default=False, action="store_true", dest="push_scheduler")
parser.add_option("-F", "--fetch-daypart", help="Fetch from daypart - scheduler (loop, interval in config file)", default=False, action="store_true", dest="fetch_daypart")
parser.add_option("-P", "--push-daypart", help="Push daypart to Liquidsoap (loop, interval in config file)", default=False, action="store_true", dest="push_daypart")
parser.add_option("-b", "--cleanup", help="Cleanup", default=False, action="store_true", dest="cleanup")
#parser.add_option("-j", "--jingles", help="Get new jingles from server, comma separated list if jingle-id's as argument", metavar="LIST")
parser.add_option("-c", "--check", help="Check the cached schedule and exit", default=False, action="store_true", dest="check")
# parse options
@ -98,677 +77,27 @@ except Exception, e:
class Global:
def __init__(self):
print
self.api_client = api_client.api_client_factory(config)
self.cue_file = CueFile()
self.set_export_source('scheduler')
def selfcheck(self):
self.api_client = api_client.api_client_factory(config)
if (not self.api_client.is_server_compatible()):
sys.exit()
class Playout:
def __init__(self):
self.api_client = api_client.api_client_factory(config)
self.cue_file = CueFile()
self.silence_file = config["file_dir"] + 'basic/silence.mp3'
"""
push_ahead2 MUST be < push_ahead. The difference in these two values
gives the number of seconds of the window of opportunity for the scheduler
to catch when a playlist is to be played.
"""
self.push_ahead = 15
self.push_ahead2 = 10
self.range_updated = False
def test_api(self):
self.api_client.test()
def set_export_source(self, export_source):
self.export_source = export_source
self.cache_dir = config["cache_dir"] + self.export_source + '/'
self.schedule_file = self.cache_dir + 'schedule.pickle'
self.schedule_tracker_file = self.cache_dir + "schedule_tracker.pickle"
"""
Fetching part of pypo
- Reads the scheduled entries of a given range (actual time +/- "prepare_ahead" / "cache_for")
- Saves a serialized file of the schedule
- playlists are prepared. (brought to liquidsoap format) and, if not mounted via nsf, files are copied
to the cache dir (Folder-structure: cache/YYYY-MM-DD-hh-mm-ss)
- runs the cleanup routine, to get rid of unused cashed files
"""
def fetch(self, export_source):
"""
wrapper script for fetching the whole schedule (in json)
"""
logger = logging.getLogger()
self.set_export_source(export_source)
try: os.mkdir(self.cache_dir)
except Exception, e: pass
"""
Trigger daypart range-generation. (Only if daypart-instance)
"""
if self.export_source == 'daypart':
print '******************************'
print '*** TRIGGER DAYPART UPDATE ***'
print '******************************'
try:
self.generate_range_dp()
except Exception, e:
logger.error("%s", e)
# get schedule
try:
while self.get_schedule() != 1:
logger.warning("failed to read from export url")
time.sleep(1)
except Exception, e: logger.error("%s", e)
# prepare the playlists
if config["cue_style"] == 'pre':
try: self.prepare_playlists_cue()
except Exception, e: logger.error("%s", e)
elif config["cue_style"] == 'otf':
try: self.prepare_playlists(self.export_source)
except Exception, e: logger.error("%s", e)
# cleanup
try: self.cleanup(self.export_source)
except Exception, e: logger.error("%s", e)
#logger.info("fetch loop completed")
"""
This is actually a bit ugly (again feel free to improve!!)
The generate_range_dp function should be called once a day,
we do this at 18h. The hour before the state is set back to 'False'
"""
def generate_range_dp(self):
logger = logging.getLogger()
logger.debug("trying to trigger daypart update")
tnow = time.localtime(time.time())
if (tnow[3] == 16):
self.range_updated = False
if (tnow[3] == 17 and self.range_updated == False):
try:
print self.api_client.generate_range_dp()
logger.info("daypart updated")
self.range_updated = True
except Exception, e:
print e
def get_schedule(self):
logger = logging.getLogger()
status, response = self.api_client.get_schedule()
if status == 1:
logger.info("dump serialized schedule to %s", self.schedule_file)
schedule = response['playlists']
try:
schedule_file = open(self.schedule_file, "w")
pickle.dump(schedule, schedule_file)
schedule_file.close()
except Exception, e:
logger.critical("Exception %s", e)
status = 0
return status
"""
Alternative version of playout preparation. Every playlist entry is
pre-cued if neccessary (cue_in/cue_out != 0) and stored in the
playlist folder.
file is eg 2010-06-23-15-00-00/17_cue_10.132-123.321.mp3
"""
def prepare_playlists_cue(self):
logger = logging.getLogger()
# Load schedule from disk
schedule = self.load_schedule()
# Dont do anything if schedule is empty
if (not schedule):
logger.debug("Schedule is empty.")
return
scheduleKeys = sorted(schedule.iterkeys())
try:
for pkey in scheduleKeys:
logger.info("found playlist at %s", pkey)
playlist = schedule[pkey]
# create playlist directory
try:
os.mkdir(self.cache_dir + str(pkey))
except Exception, e:
pass
ls_playlist = '';
logger.debug('*****************************************')
logger.debug('pkey: ' + str(pkey))
logger.debug('cached at : ' + self.cache_dir + str(pkey))
logger.debug('subtype: ' + str(playlist['subtype']))
logger.debug('played: ' + str(playlist['played']))
logger.debug('schedule id: ' + str(playlist['schedule_id']))
logger.debug('duration: ' + str(playlist['duration']))
logger.debug('source id: ' + str(playlist['x_ident']))
logger.debug('*****************************************')
# Creating an API call like the next two lines would make this more flexible
# mediaType = api_client.get_media_type(playlist)
# if (mediaType == PYPO_MEDIA_SKIP):
if int(playlist['played']) == 1:
logger.info("playlist %s already played / sent to liquidsoap, so will ignore it", pkey)
elif int(playlist['subtype']) == 5:
ls_playlist = self.handle_live_session(playlist, pkey, ls_playlist)
elif int(playlist['subtype']) == 6:
ls_playlist = self.handle_live_cast(playlist, pkey, ls_playlist)
elif int(playlist['subtype']) > 0 and int(playlist['subtype']) < 5:
ls_playlist = self.handle_media_file(playlist, pkey, ls_playlist)
# write playlist file
plfile = open(self.cache_dir + str(pkey) + '/list.lsp', "w")
plfile.write(ls_playlist)
plfile.close()
logger.info('ls playlist file written to %s', self.cache_dir + str(pkey) + '/list.lsp')
except Exception, e:
logger.info("%s", e)
def handle_live_session(self, playlist, pkey, ls_playlist):
"""
This is a live session, so silence is scheduled.
Maybe not the most elegant solution :)
It adds 20 times 30min silence to the playlist
Silence file has to be in <file_dir>/basic/silence.mp3
"""
logger = logging.getLogger()
logger.debug("found %s seconds of live/studio session at %s", pkey, playlist['duration'])
if os.path.isfile(self.silence_file):
logger.debug('file stored at: %s' + self.silence_file)
for i in range (0, 19):
ls_playlist += self.silence_file + "\n"
else:
print 'Could not find silence file!'
print 'File is expected to be at: ' + self.silence_file
logger.critical('File is expected to be at: %s', self.silence_file)
sys.exit()
return ls_playlist
def handle_live_cast(self, playlist, pkey, ls_playlist):
"""
This is a live-cast session
Create a silence list. (could eg also be a fallback list..)
"""
logger = logging.getLogger()
logger.debug("found %s seconds of live-cast session at %s", pkey, playlist['duration'])
if os.path.isfile(self.silence_file):
logger.debug('file stored at: %s' + self.silence_file)
for i in range (0, 19):
ls_playlist += self.silence_file + "\n"
else:
print 'Could not find silence file!'
print 'File is expected to be at: ' + self.silence_file
logger.critical('File is expected to be at: %s', self.silence_file)
sys.exit()
return ls_playlist
def handle_media_file(self, playlist, pkey, ls_playlist):
"""
This handles both remote and local files.
Returns an updated ls_playlist string.
"""
logger = logging.getLogger()
for media in playlist['medias']:
logger.debug("Processing track %s", media['uri'])
fileExt = os.path.splitext(media['uri'])[1]
try:
if str(media['cue_in']) == '0' and str(media['cue_out']) == '0':
logger.debug('No cue in/out detected for this file')
dst = "%s%s/%s%s" % (self.cache_dir, str(pkey), str(media['id']), str(fileExt))
do_cue = False
else:
logger.debug('Cue in/out detected')
dst = "%s%s/%s_cue_%s-%s%s" % \
(self.cache_dir, str(pkey), str(media['id']), str(float(media['cue_in']) / 1000), str(float(media['cue_out']) / 1000), str(fileExt))
do_cue = True
# check if it is a remote file, if yes download
if media['uri'][0:4] == 'http':
self.handle_remote_file(media, dst, do_cue)
else:
# Assume local file
self.handle_local_file(media, dst, do_cue)
if True == os.access(dst, os.R_OK):
# check filesize (avoid zero-byte files)
try: fsize = os.path.getsize(dst)
except Exception, e:
logger.error("%s", e)
fsize = 0
if fsize > 0:
pl_entry = \
'annotate:export_source="%s",media_id="%s",liq_start_next="%s",liq_fade_in="%s",liq_fade_out="%s",schedule_table_id="%s":%s'\
% (str(media['export_source']), media['id'], 0, str(float(media['fade_in']) / 1000), \
str(float(media['fade_out']) / 1000), media['row_id'],dst)
logger.debug(pl_entry)
"""
Tracks are only added to the playlist if they are accessible
on the file system and larger than 0 bytes.
So this can lead to playlists shorter than expectet.
(there is a hardware silence detector for this cases...)
"""
ls_playlist += pl_entry + "\n"
logger.debug("everything ok, adding %s to playlist", pl_entry)
else:
print 'zero-file: ' + dst + ' from ' + media['uri']
logger.warning("zero-size file - skiping %s. will not add it to playlist", dst)
else:
logger.warning("something went wrong. file %s not available. will not add it to playlist", dst)
except Exception, e: logger.info("%s", e)
return ls_playlist
def handle_remote_file(self, media, dst, do_cue):
logger = logging.getLogger()
if do_cue == False:
if os.path.isfile(dst):
logger.debug("file already in cache: %s", dst)
else:
logger.debug("try to download %s", media['uri'])
self.api_client.get_media(media['uri'], dst)
else:
if os.path.isfile(dst):
logger.debug("file already in cache: %s", dst)
else:
logger.debug("try to download and cue %s", media['uri'])
fileExt = os.path.splitext(media['uri'])[1]
dst_tmp = config["tmp_dir"] + "".join([random.choice(string.letters) for i in xrange(10)]) + fileExt
self.api_client.get_media(media['uri'], dst_tmp)
# cue
logger.debug("STARTING CUE")
debugDst = self.cue_file.cue(dst_tmp, dst, float(media['cue_in']) / 1000, float(media['cue_out']) / 1000)
logger.debug(debugDst)
logger.debug("END CUE")
if True == os.access(dst, os.R_OK):
try: fsize = os.path.getsize(dst)
except Exception, e:
logger.error("%s", e)
fsize = 0
if fsize > 0:
logger.debug('try to remove temporary file: %s' + dst_tmp)
try: os.remove(dst_tmp)
except Exception, e:
logger.error("%s", e)
else:
logger.warning('something went wrong cueing: %s - using uncued file' + dst)
try: os.rename(dst_tmp, dst)
except Exception, e:
logger.error("%s", e)
def handle_local_file(self, media, dst, do_cue):
"""
Handle files on NAS. Pre-cueing not implemented at the moment.
(not needed by openbroadcast, feel free to add this)
Here's an implementation for locally stored files.
Works the same as with remote files, just replaced API-download with
file copy.
"""
logger = logging.getLogger()
if do_cue == False:
if os.path.isfile(dst):
logger.debug("file already in cache: %s", dst)
else:
logger.debug("try to copy file to cache %s", media['uri'])
try:
shutil.copy(media['uri'], dst)
logger.info("copied %s to %s", media['uri'], dst)
except Exception, e:
logger.error("%s", e)
else:
if os.path.isfile(dst):
logger.debug("file already in cache: %s", dst)
else:
logger.debug("try to copy and cue %s", media['uri'])
print '***'
dst_tmp = config["tmp_dir"] + "".join([random.choice(string.letters) for i in xrange(10)])
print dst_tmp
print '***'
try:
shutil.copy(media['uri'], dst_tmp)
logger.info("copied %s to %s", media['uri'], dst_tmp)
except Exception, e:
logger.error("%s", e)
# cue
print "STARTING CUE"
print self.cue_file.cue(dst_tmp, dst, float(media['cue_in']) / 1000, float(media['cue_out']) / 1000)
print "END CUE"
if True == os.access(dst, os.R_OK):
try: fsize = os.path.getsize(dst)
except Exception, e:
logger.error("%s", e)
fsize = 0
if fsize > 0:
logger.debug('try to remove temporary file: %s' + dst_tmp)
try: os.remove(dst_tmp)
except Exception, e:
logger.error("%s", e)
else:
logger.warning('something went wrong cueing: %s - using uncued file' + dst)
try: os.rename(dst_tmp, dst)
except Exception, e:
logger.error("%s", e)
def cleanup(self, export_source):
"""
Cleans up folders in cache_dir. Look for modification date older than "now - CACHE_FOR"
and deletes them.
"""
logger = logging.getLogger()
self.set_export_source(export_source)
offset = 3600 * int(config["cache_for"])
now = time.time()
for r, d, f in os.walk(self.cache_dir):
for dir in d:
try:
timestamp = time.mktime(time.strptime(dir, "%Y-%m-%d-%H-%M-%S"))
#logger.debug('dir : %s', (dir))
#logger.debug('age : %s', (round((now - timestamp),1)))
#logger.debug('delete in : %ss', (round((offset - (now - timestamp)),1)))
#logger.debug('Folder "Age": %s - %s', round((((now - offset) - timestamp) / 60), 2), os.path.join(r, dir))
if (now - timestamp) > offset:
try:
logger.debug('trying to remove %s - timestamp: %s', os.path.join(r, dir), timestamp)
shutil.rmtree(os.path.join(r, dir))
except Exception, e:
logger.error("%s", e)
pass
else:
logger.info('sucessfully removed %s', os.path.join(r, dir))
except Exception, e:
print e
logger.error("%s", e)
"""
The Push Loop - the push loop periodically (minimal 1/2 of the playlist-grid)
checks if there is a playlist that should be scheduled at the current time.
If yes, the temporary liquidsoap playlist gets replaced with the corresponding one,
then liquidsoap is asked (via telnet) to reload and immediately play it.
"""
def push(self, export_source):
logger = logging.getLogger()
self.set_export_source(export_source)
#try:
# dummy = self.schedule
# logger.debug('schedule already loaded')
#except Exception, e:
# self.schedule = self.push_init(self.export_source)
self.schedule = self.load_schedule()
playedItems = self.load_schedule_tracker()
tcoming = time.localtime(time.time() + self.push_ahead)
tcoming2 = time.localtime(time.time() + self.push_ahead2)
tnow = time.localtime(time.time())
str_tcoming_s = "%04d-%02d-%02d-%02d-%02d-%02d" % (tcoming[0], tcoming[1], tcoming[2], tcoming[3], tcoming[4], tcoming[5])
str_tcoming2_s = "%04d-%02d-%02d-%02d-%02d-%02d" % (tcoming2[0], tcoming2[1], tcoming2[2], tcoming2[3], tcoming2[4], tcoming2[5])
if self.schedule == None:
logger.warn('Unable to loop schedule - maybe write in progress?')
logger.warn('Will try again in next loop.')
else:
for pkey in self.schedule:
playedFlag = (pkey in playedItems) and playedItems[pkey].get("played", 0)
if pkey[0:19] == str_tcoming_s or (pkey[0:19] < str_tcoming_s and pkey[0:19] > str_tcoming2_s and not playedFlag):
logger.debug('Preparing to push playlist scheduled at: %s', pkey)
playlist = self.schedule[pkey]
ptype = playlist['subtype']
# We have a match, replace the current playlist and
# force liquidsoap to refresh.
if (self.push_liquidsoap(pkey, self.schedule, ptype) == 1):
logger.debug("Pushed to liquidsoap, updating 'played' status.")
# Marked the current playlist as 'played' in the schedule tracker
# so it is not called again in the next push loop.
# Write changes back to tracker file.
playedItems[pkey] = playlist
playedItems[pkey]['played'] = 1
schedule_tracker = open(self.schedule_tracker_file, "w")
pickle.dump(playedItems, schedule_tracker)
schedule_tracker.close()
logger.debug("Wrote schedule to disk: "+str(playedItems))
# Call API to update schedule states
logger.debug("Doing callback to server to update 'played' status.")
self.api_client.notify_scheduled_item_start_playing(pkey, self.schedule)
def load_schedule(self):
logger = logging.getLogger()
schedule = None
# create the file if it doesnt exist
if (not os.path.exists(self.schedule_file)):
logger.debug('creating file ' + self.schedule_file)
open(self.schedule_file, 'w').close()
else:
# load the schedule from cache
#logger.debug('loading schedule file '+self.schedule_file)
try:
schedule_file = open(self.schedule_file, "r")
schedule = pickle.load(schedule_file)
schedule_file.close()
except Exception, e:
logger.error('%s', e)
return schedule
def load_schedule_tracker(self):
logger = logging.getLogger()
playedItems = dict()
# create the file if it doesnt exist
if (not os.path.exists(self.schedule_tracker_file)):
logger.debug('creating file ' + self.schedule_tracker_file)
schedule_tracker = open(self.schedule_tracker_file, 'w')
pickle.dump(playedItems, schedule_tracker)
schedule_tracker.close()
else:
try:
#logger.debug('loading schedule tracker file '+ self.schedule_tracker_file)
schedule_tracker = open(self.schedule_tracker_file, "r")
playedItems = pickle.load(schedule_tracker)
schedule_tracker.close()
except Exception, e:
logger.error('Unable to load schedule tracker file: %s', e)
return playedItems
def push_liquidsoap(self, pkey, schedule, ptype):
logger = logging.getLogger()
src = self.cache_dir + str(pkey) + '/list.lsp'
try:
if True == os.access(src, os.R_OK):
logger.debug('OK - Can read playlist file')
pl_file = open(src, "r")
#strptime returns struct_time in local time
#mktime takes a time_struct and returns a floating point
#gmtime Convert a time expressed in seconds since the epoch to a struct_time in UTC
#mktime: expresses the time in local time, not UTC. It returns a floating point number, for compatibility with time().
epoch_start = calendar.timegm(time.gmtime(time.mktime(time.strptime(pkey, '%Y-%m-%d-%H-%M-%S'))))
#Return the time as a floating point number expressed in seconds since the epoch, in UTC.
epoch_now = time.time()
logger.debug("Epoch start: " + str(epoch_start))
logger.debug("Epoch now: " + str(epoch_now))
sleep_time = epoch_start - epoch_now;
if sleep_time < 0:
sleep_time = 0
logger.debug('sleeping for %s s' % (sleep_time))
time.sleep(sleep_time)
tn = telnetlib.Telnet(LS_HOST, 1234)
# Get any extra information for liquidsoap (which will be sent back to us)
liquidsoap_data = self.api_client.get_liquidsoap_data(pkey, schedule)
logger.debug("Sending additional telnet data to liquidsoap: "+str(liquidsoap_data["schedule_id"]))
#skip the currently playing song if any.
logger.debug("source.skip\n")
tn.write("source.skip\n")
#Sending schedule table row id string.
logger.debug("vars.pypo_data %s\n"%(str(liquidsoap_data["schedule_id"])))
tn.write("vars.pypo_data %s\n"%(str(liquidsoap_data["schedule_id"])))
for line in pl_file.readlines():
line = line.strip()
logger.debug(line)
tn.write('queue.push %s' % (line))
tn.write("\n")
tn.write("exit\n")
logger.debug(tn.read_all())
"""
tn = telnetlib.Telnet(LS_HOST, 1234)
# Get any extra information for liquidsoap (which will be sent back to us)
liquidsoap_data = self.api_client.get_liquidsoap_data(pkey, schedule)
logger.debug("Sending additional data to liquidsoap: "+liquidsoap_data)
#Sending JSON string. Example: {"schedule_id":"13"}
tn.write("vars.pypo_data "+liquidsoap_data+"\n")
tn.write(self.export_source + '.flip')
tn.write("\n")
tn.write("exit\n")
tn.read_all()
"""
status = 1
except Exception, e:
logger.error('%s', e)
status = 0
return status
"""
Updates the jingles. Give comma separated list of jingle tracks.
NOTE: commented out because it needs to be converted to use the API client. - Paul
"""
#def update_jingles(self, options):
# print 'jingles'
#
# jingle_list = string.split(options, ',')
# print jingle_list
# for media_id in jingle_list:
# # api path maybe should not be hard-coded
# src = API_BASE + 'api/pypo/get_media/' + str(media_id)
# print src
# # include the hourly jungles for the moment
# dst = "%s%s/%s.mp3" % (config["file_dir"], 'jingles/hourly', str(media_id))
# print dst
#
# try:
# print '** urllib auth with: ',
# print self.api_auth
# opener = urllib.URLopener()
# opener.retrieve (src, dst, False, self.api_auth)
# logger.info("downloaded %s to %s", src, dst)
# except Exception, e:
# print e
# logger.error("%s", e)
def test_api(self):
self.api_client.test()
def check_schedule(self, export_source):
logger = logging.getLogger()
self.set_export_source(export_source)
try:
schedule_file = open(self.schedule_file, "r")
schedule = pickle.load(schedule_file)
@ -793,108 +122,62 @@ class Playout:
for media in playlist['medias']:
print media
print
if __name__ == '__main__':
print
print '###########################################'
print '# *** pypo *** #'
print '# Liquidsoap + External Scheduler #'
print '# Playout System #'
print '###########################################'
print
# initialize
g = Global()
g.selfcheck()
po = Playout()
run = True
while run == True:
logger = logging.getLogger()
loops = 0
if options.test:
po.test_api()
g.test_api()
sys.exit()
while options.fetch_scheduler:
try: po.fetch('scheduler')
if options.fetch_scheduler:
pf = PypoFetch()
while True:
try: pf.fetch('scheduler')
except Exception, e:
print e
sys.exit()
#print 'ZZzZzZzzzzZZZz.... sleeping for ' + str(POLL_INTERVAL) + ' seconds'
#logger.info('fetch loop %s - ZZzZzZzzzzZZZz.... sleeping for %s seconds', loops, POLL_INTERVAL)
if (loops%2 == 0):
logger.info("heartbeat\n\n\n\n")
logger.info("heartbeat")
loops += 1
time.sleep(POLL_INTERVAL)
while options.fetch_daypart:
try: po.fetch('daypart')
except Exception, e:
print e
sys.exit()
#print 'ZZzZzZzzzzZZZz.... sleeping for ' + str(POLL_INTERVAL) + ' seconds'
#logger.info('fetch loop %s - ZZzZzZzzzzZZZz.... sleeping for %s seconds', loops, POLL_INTERVAL)
loops += 1
time.sleep(POLL_INTERVAL)
while options.push_scheduler:
po.push('scheduler')
try: po.push('scheduler')
if options.push_scheduler:
pp = PypoPush()
while True:
try: pp.push('scheduler')
except Exception, e:
print 'PUSH ERROR!! WILL EXIT NOW:('
print e
sys.exit()
if (loops%20 == 0):
if (loops%60 == 0):
logger.info("heartbeat")
#logger.info('push loop %s - ZZzZzZzzzzZZZz.... sleeping for %s seconds', loops, PUSH_INTERVAL)
loops += 1
time.sleep(PUSH_INTERVAL)
while options.push_daypart:
po.push('daypart')
try: po.push('daypart')
if options.check:
try: g.check_schedule()
except Exception, e:
print 'PUSH ERROR!! WILL EXIT NOW:('
print e
sys.exit()
#logger.info('push loop %s - ZZzZzZzzzzZZZz.... sleeping for %s seconds', loops, PUSH_INTERVAL)
loops += 1
time.sleep(PUSH_INTERVAL)
#while options.jingles:
# try: po.update_jingles(options.jingles)
# except Exception, e:
# print e
# sys.exit()
while options.check:
try: po.check_schedule()
if options.cleanup:
try: pf.cleanup('scheduler')
except Exception, e:
print e
sys.exit()
while options.cleanup:
try: po.cleanup('scheduler')
except Exception, e:
print e
sys.exit()
sys.exit()

View file

@ -39,8 +39,6 @@ from configobj import ConfigObj
from util import *
from obp import *
PYPO_VERSION = '0.9'
#set up command-line options
parser = OptionParser()

View file

@ -39,9 +39,6 @@ from util import *
from api_clients import *
from dls import *
PYPO_VERSION = '0.9'
# Set up command-line options
parser = OptionParser()

324
pypo/pypofetch.py Normal file
View file

@ -0,0 +1,324 @@
import os
import sys
import time
import logging
import logging.config
import shutil
import pickle
import random
import string
import json
import telnetlib
from api_clients import api_client
from util import CueFile
from configobj import ConfigObj
# loading config file
try:
config = ConfigObj('config.cfg')
POLL_INTERVAL = float(config['poll_interval'])
PUSH_INTERVAL = 0.5
#PUSH_INTERVAL = float(config['push_interval'])
LS_HOST = config['ls_host']
LS_PORT = config['ls_port']
except Exception, e:
print 'Error loading config file: ', e
sys.exit()
class PypoFetch:
def __init__(self):
self.api_client = api_client.api_client_factory(config)
self.cue_file = CueFile()
self.set_export_source('scheduler')
def set_export_source(self, export_source):
self.export_source = export_source
self.cache_dir = config["cache_dir"] + self.export_source + '/'
self.schedule_file = self.cache_dir + 'schedule.pickle'
self.schedule_tracker_file = self.cache_dir + "schedule_tracker.pickle"
"""
Fetching part of pypo
- Reads the scheduled entries of a given range (actual time +/- "prepare_ahead" / "cache_for")
- Saves a serialized file of the schedule
- playlists are prepared. (brought to liquidsoap format) and, if not mounted via nsf, files are copied
to the cache dir (Folder-structure: cache/YYYY-MM-DD-hh-mm-ss)
- runs the cleanup routine, to get rid of unused cashed files
"""
def fetch(self, export_source):
"""
wrapper script for fetching the whole schedule (in json)
"""
logger = logging.getLogger()
try: os.mkdir(self.cache_dir)
except Exception, e: pass
# get schedule
try:
while self.get_schedule() != 1:
logger.warning("failed to read from export url")
time.sleep(1)
except Exception, e: logger.error("%s", e)
# prepare the playlists
if config["cue_style"] == 'pre':
try: self.prepare_playlists_cue()
except Exception, e: logger.error("%s", e)
elif config["cue_style"] == 'otf':
try: self.prepare_playlists(self.export_source)
except Exception, e: logger.error("%s", e)
# cleanup
try: self.cleanup(self.export_source)
except Exception, e: logger.error("%s", e)
def get_schedule(self):
logger = logging.getLogger()
status, response = self.api_client.get_schedule()
if status == 1:
logger.info("dump serialized schedule to %s", self.schedule_file)
schedule = response['playlists']
stream_metadata = response['stream_metadata']
try:
schedule_file = open(self.schedule_file, "w")
pickle.dump(schedule, schedule_file)
schedule_file.close()
tn = telnetlib.Telnet(LS_HOST, LS_PORT)
#encode in latin-1 due to this bug: http://bugs.python.org/issue1772794
tn.write(('vars.stream_metadata_type %s\n' % stream_metadata['format']).encode('latin-1'))
tn.write(('vars.station_name %s\n' % stream_metadata['station_name']).encode('latin-1'))
tn.write('exit\n')
logger.debug(tn.read_all())
except Exception, e:
logger.critical("Exception %s", e)
status = 0
return status
#TODO this is a duplicate function!!!
def load_schedule(self):
logger = logging.getLogger()
schedule = None
# create the file if it doesnt exist
if (not os.path.exists(self.schedule_file)):
logger.debug('creating file ' + self.schedule_file)
open(self.schedule_file, 'w').close()
else:
# load the schedule from cache
#logger.debug('loading schedule file '+self.schedule_file)
try:
schedule_file = open(self.schedule_file, "r")
schedule = pickle.load(schedule_file)
schedule_file.close()
except Exception, e:
logger.error('%s', e)
return schedule
"""
Alternative version of playout preparation. Every playlist entry is
pre-cued if neccessary (cue_in/cue_out != 0) and stored in the
playlist folder.
file is eg 2010-06-23-15-00-00/17_cue_10.132-123.321.mp3
"""
def prepare_playlists_cue(self):
logger = logging.getLogger()
# Load schedule from disk
schedule = self.load_schedule()
# Dont do anything if schedule is empty
if (not schedule):
logger.debug("Schedule is empty.")
return
scheduleKeys = sorted(schedule.iterkeys())
try:
for pkey in scheduleKeys:
logger.info("found playlist at %s", pkey)
playlist = schedule[pkey]
# create playlist directory
try:
os.mkdir(self.cache_dir + str(pkey))
except Exception, e:
pass
logger.debug('*****************************************')
logger.debug('pkey: ' + str(pkey))
logger.debug('cached at : ' + self.cache_dir + str(pkey))
logger.debug('subtype: ' + str(playlist['subtype']))
logger.debug('played: ' + str(playlist['played']))
logger.debug('schedule id: ' + str(playlist['schedule_id']))
logger.debug('duration: ' + str(playlist['duration']))
logger.debug('source id: ' + str(playlist['x_ident']))
logger.debug('*****************************************')
if int(playlist['played']) == 1:
logger.info("playlist %s already played / sent to liquidsoap, so will ignore it", pkey)
elif int(playlist['subtype']) > 0 and int(playlist['subtype']) < 5:
ls_playlist = self.handle_media_file(playlist, pkey)
# write playlist file
plfile = open(self.cache_dir + str(pkey) + '/list.lsp', "w")
plfile.write(json.dumps(ls_playlist))
plfile.close()
logger.info('ls playlist file written to %s', self.cache_dir + str(pkey) + '/list.lsp')
except Exception, e:
logger.info("%s", e)
def handle_media_file(self, playlist, pkey):
"""
This handles both remote and local files.
Returns an updated ls_playlist string.
"""
ls_playlist = []
logger = logging.getLogger()
for media in playlist['medias']:
logger.debug("Processing track %s", media['uri'])
fileExt = os.path.splitext(media['uri'])[1]
try:
if str(media['cue_in']) == '0' and str(media['cue_out']) == '0':
logger.debug('No cue in/out detected for this file')
dst = "%s%s/%s%s" % (self.cache_dir, str(pkey), str(media['id']), str(fileExt))
do_cue = False
else:
logger.debug('Cue in/out detected')
dst = "%s%s/%s_cue_%s-%s%s" % \
(self.cache_dir, str(pkey), str(media['id']), str(float(media['cue_in']) / 1000), str(float(media['cue_out']) / 1000), str(fileExt))
do_cue = True
# check if it is a remote file, if yes download
if media['uri'][0:4] == 'http':
self.handle_remote_file(media, dst, do_cue)
else:
logger.debug("invalid media uri: %s", media['uri'])
if True == os.access(dst, os.R_OK):
# check filesize (avoid zero-byte files)
try: fsize = os.path.getsize(dst)
except Exception, e:
logger.error("%s", e)
fsize = 0
if fsize > 0:
pl_entry = \
'annotate:export_source="%s",media_id="%s",liq_start_next="%s",liq_fade_in="%s",liq_fade_out="%s",schedule_table_id="%s":%s'\
% (str(media['export_source']), media['id'], 0, str(float(media['fade_in']) / 1000), \
str(float(media['fade_out']) / 1000), media['row_id'],dst)
logger.debug(pl_entry)
"""
Tracks are only added to the playlist if they are accessible
on the file system and larger than 0 bytes.
So this can lead to playlists shorter than expectet.
(there is a hardware silence detector for this cases...)
"""
entry = dict()
entry['type'] = 'file'
entry['annotate'] = pl_entry
entry['show_name'] = playlist['show_name']
ls_playlist.append(entry)
logger.debug("everything ok, adding %s to playlist", pl_entry)
else:
print 'zero-file: ' + dst + ' from ' + media['uri']
logger.warning("zero-size file - skipping %s. will not add it to playlist", dst)
else:
logger.warning("something went wrong. file %s not available. will not add it to playlist", dst)
except Exception, e: logger.info("%s", e)
return ls_playlist
def handle_remote_file(self, media, dst, do_cue):
logger = logging.getLogger()
if do_cue == False:
if os.path.isfile(dst):
logger.debug("file already in cache: %s", dst)
else:
logger.debug("try to download %s", media['uri'])
self.api_client.get_media(media['uri'], dst)
else:
if os.path.isfile(dst):
logger.debug("file already in cache: %s", dst)
else:
logger.debug("try to download and cue %s", media['uri'])
fileExt = os.path.splitext(media['uri'])[1]
dst_tmp = config["tmp_dir"] + "".join([random.choice(string.letters) for i in xrange(10)]) + fileExt
self.api_client.get_media(media['uri'], dst_tmp)
# cue
logger.debug("STARTING CUE")
debugDst = self.cue_file.cue(dst_tmp, dst, float(media['cue_in']) / 1000, float(media['cue_out']) / 1000)
logger.debug(debugDst)
logger.debug("END CUE")
if True == os.access(dst, os.R_OK):
try: fsize = os.path.getsize(dst)
except Exception, e:
logger.error("%s", e)
fsize = 0
if fsize > 0:
logger.debug('try to remove temporary file: %s' + dst_tmp)
try: os.remove(dst_tmp)
except Exception, e:
logger.error("%s", e)
else:
logger.warning('something went wrong cueing: %s - using uncued file' + dst)
try: os.rename(dst_tmp, dst)
except Exception, e:
logger.error("%s", e)
def cleanup(self, export_source):
"""
Cleans up folders in cache_dir. Look for modification date older than "now - CACHE_FOR"
and deletes them.
"""
logger = logging.getLogger()
offset = 3600 * int(config["cache_for"])
now = time.time()
for r, d, f in os.walk(self.cache_dir):
for dir in d:
try:
timestamp = time.mktime(time.strptime(dir, "%Y-%m-%d-%H-%M-%S"))
if (now - timestamp) > offset:
try:
logger.debug('trying to remove %s - timestamp: %s', os.path.join(r, dir), timestamp)
shutil.rmtree(os.path.join(r, dir))
except Exception, e:
logger.error("%s", e)
pass
else:
logger.info('sucessfully removed %s', os.path.join(r, dir))
except Exception, e:
print e
logger.error("%s", e)

204
pypo/pypopush.py Normal file
View file

@ -0,0 +1,204 @@
import os
import sys
import time
import logging
import logging.config
import pickle
import telnetlib
import calendar
import json
from api_clients import api_client
from util import CueFile
from configobj import ConfigObj
# loading config file
try:
config = ConfigObj('config.cfg')
POLL_INTERVAL = float(config['poll_interval'])
PUSH_INTERVAL = 0.5
#PUSH_INTERVAL = float(config['push_interval'])
LS_HOST = config['ls_host']
LS_PORT = config['ls_port']
except Exception, e:
print 'Error loading config file: ', e
sys.exit()
class PypoPush:
def __init__(self):
self.api_client = api_client.api_client_factory(config)
self.cue_file = CueFile()
self.set_export_source('scheduler')
"""
push_ahead2 MUST be < push_ahead. The difference in these two values
gives the number of seconds of the window of opportunity for the scheduler
to catch when a playlist is to be played.
"""
self.push_ahead = 15
self.push_ahead2 = 10
def set_export_source(self, export_source):
self.export_source = export_source
self.cache_dir = config["cache_dir"] + self.export_source + '/'
self.schedule_file = self.cache_dir + 'schedule.pickle'
self.schedule_tracker_file = self.cache_dir + "schedule_tracker.pickle"
"""
The Push Loop - the push loop periodically (minimal 1/2 of the playlist-grid)
checks if there is a playlist that should be scheduled at the current time.
If yes, the temporary liquidsoap playlist gets replaced with the corresponding one,
then liquidsoap is asked (via telnet) to reload and immediately play it.
"""
def push(self, export_source):
logger = logging.getLogger()
self.schedule = self.load_schedule()
playedItems = self.load_schedule_tracker()
tcoming = time.localtime(time.time() + self.push_ahead)
tcoming2 = time.localtime(time.time() + self.push_ahead2)
tnow = time.localtime(time.time())
str_tcoming_s = "%04d-%02d-%02d-%02d-%02d-%02d" % (tcoming[0], tcoming[1], tcoming[2], tcoming[3], tcoming[4], tcoming[5])
str_tcoming2_s = "%04d-%02d-%02d-%02d-%02d-%02d" % (tcoming2[0], tcoming2[1], tcoming2[2], tcoming2[3], tcoming2[4], tcoming2[5])
if self.schedule == None:
logger.warn('Unable to loop schedule - maybe write in progress?')
logger.warn('Will try again in next loop.')
else:
for pkey in self.schedule:
playedFlag = (pkey in playedItems) and playedItems[pkey].get("played", 0)
if pkey[0:19] == str_tcoming_s or (pkey[0:19] < str_tcoming_s and pkey[0:19] > str_tcoming2_s and not playedFlag):
logger.debug('Preparing to push playlist scheduled at: %s', pkey)
playlist = self.schedule[pkey]
ptype = playlist['subtype']
# We have a match, replace the current playlist and
# force liquidsoap to refresh.
if (self.push_liquidsoap(pkey, self.schedule, ptype) == 1):
logger.debug("Pushed to liquidsoap, updating 'played' status.")
# Marked the current playlist as 'played' in the schedule tracker
# so it is not called again in the next push loop.
# Write changes back to tracker file.
playedItems[pkey] = playlist
playedItems[pkey]['played'] = 1
schedule_tracker = open(self.schedule_tracker_file, "w")
pickle.dump(playedItems, schedule_tracker)
schedule_tracker.close()
logger.debug("Wrote schedule to disk: "+str(json.dumps(playedItems)))
# Call API to update schedule states
logger.debug("Doing callback to server to update 'played' status.")
self.api_client.notify_scheduled_item_start_playing(pkey, self.schedule)
def push_liquidsoap(self, pkey, schedule, ptype):
logger = logging.getLogger()
src = self.cache_dir + str(pkey) + '/list.lsp'
try:
if True == os.access(src, os.R_OK):
logger.debug('OK - Can read playlist file')
pl_file = open(src, "r")
file_content = pl_file.read()
pl_file.close()
logger.debug('file content: %s' % (file_content))
playlist = json.loads(file_content)
#strptime returns struct_time in local time
#mktime takes a time_struct and returns a floating point
#gmtime Convert a time expressed in seconds since the epoch to a struct_time in UTC
#mktime: expresses the time in local time, not UTC. It returns a floating point number, for compatibility with time().
epoch_start = calendar.timegm(time.gmtime(time.mktime(time.strptime(pkey, '%Y-%m-%d-%H-%M-%S'))))
#Return the time as a floating point number expressed in seconds since the epoch, in UTC.
epoch_now = time.time()
logger.debug("Epoch start: " + str(epoch_start))
logger.debug("Epoch now: " + str(epoch_now))
sleep_time = epoch_start - epoch_now;
if sleep_time < 0:
sleep_time = 0
logger.debug('sleeping for %s s' % (sleep_time))
time.sleep(sleep_time)
tn = telnetlib.Telnet(LS_HOST, LS_PORT)
#skip the currently playing song if any.
logger.debug("source.skip\n")
tn.write("source.skip\n")
# Get any extra information for liquidsoap (which will be sent back to us)
liquidsoap_data = self.api_client.get_liquidsoap_data(pkey, schedule)
#Sending schedule table row id string.
logger.debug("vars.pypo_data %s\n"%(str(liquidsoap_data["schedule_id"])))
tn.write(("vars.pypo_data %s\n"%str(liquidsoap_data["schedule_id"])).encode('latin-1'))
for item in playlist:
annotate = str(item['annotate'])
logger.debug(annotate)
tn.write(('queue.push %s\n' % annotate).encode('latin-1'))
tn.write(('vars.show_name %s\n' % item['show_name']).encode('latin-1'))
tn.write("exit\n")
logger.debug(tn.read_all())
status = 1
except Exception, e:
logger.error('%s', e)
status = 0
return status
def load_schedule(self):
logger = logging.getLogger()
schedule = None
# create the file if it doesnt exist
if (not os.path.exists(self.schedule_file)):
logger.debug('creating file ' + self.schedule_file)
open(self.schedule_file, 'w').close()
else:
# load the schedule from cache
#logger.debug('loading schedule file '+self.schedule_file)
try:
schedule_file = open(self.schedule_file, "r")
schedule = pickle.load(schedule_file)
schedule_file.close()
except Exception, e:
logger.error('%s', e)
return schedule
def load_schedule_tracker(self):
logger = logging.getLogger()
playedItems = dict()
# create the file if it doesnt exist
if (not os.path.exists(self.schedule_tracker_file)):
logger.debug('creating file ' + self.schedule_tracker_file)
schedule_tracker = open(self.schedule_tracker_file, 'w')
pickle.dump(playedItems, schedule_tracker)
schedule_tracker.close()
else:
try:
schedule_tracker = open(self.schedule_tracker_file, "r")
playedItems = pickle.load(schedule_tracker)
schedule_tracker.close()
except Exception, e:
logger.error('Unable to load schedule tracker file: %s', e)
return playedItems

51
pypo/scripts/lib.liq Normal file
View file

@ -0,0 +1,51 @@
def notify(m)
system("./notify.sh --data='#{!pypo_data}' --media-id=#{m['schedule_table_id']}")
print("./notify.sh --data='#{!pypo_data}' --media-id=#{m['schedule_table_id']}")
end
# A function applied to each metadata chunk
def append_title(m) =
if !stream_metadata_type == 1 then
[("artist","#{!show_name} - #{m['title']}")]
elsif !stream_metadata_type == 2 then
[("artist", ""), ("title", !show_name)]
elsif !stream_metadata_type == 3 then
[("artist",!station_name), ("title", !show_name)]
else
[]
end
end
def crossfade(s)
s = fade.in(type="log", s)
s = fade.out(type="log", s)
fader = fun (a,b) -> add(normalize=false,[b,a])
cross(fader,s)
end
# Define a transition that fades out the
# old source, adds a single, and then
# plays the new source
def to_live(old,new) =
# Fade out old source
old = fade.final(old)
# Compose this in sequence with
# the new source
sequence([old,new])
end
# Add a skip function to a source
# when it does not have one
# by default
def add_skip_command(s)
# A command to skip
def skip(_)
source.skip(s)
"Done!"
end
# Register the command:
server.register(namespace="source",
usage="skip",
description="Skip the current song.",
"skip",skip)
end

View file

@ -5,63 +5,51 @@ set("log.file.path", log_file)
set("log.stdout", true)
set("server.telnet", true)
queue = request.queue(id="queue")
queue = request.queue(id="queue", conservative=true)
queue = audio_to_stereo(queue)
pypo_data = ref '0'
web_stream_enabled = ref false
stream_metadata_type = ref 0
station_name = ref ''
show_name = ref ''
def notify(m)
system("./notify.sh --data='#{!pypo_data}' --media-id=#{m['schedule_table_id']}")
print("./notify.sh --data='#{!pypo_data}' --media-id=#{m['schedule_table_id']}")
end
def crossfade(s)
s = fade.in(type="log", s)
s = fade.out(type="log", s)
fader = fun (a,b) -> add(normalize=false,[b,a])
cross(fader,s)
end
# Add a skip function to a source
# when it does not have one
# by default
def add_skip_command(s) =
# A command to skip
def skip(_) =
source.skip(s)
"Done!"
end
# Register the command:
server.register(namespace="source",
usage="skip",
description="Skip the current song.",
"skip",skip)
end
%include "lib.liq"
server.register(namespace="vars", "pypo_data", fun (s) -> begin pypo_data := s "Done" end)
server.register(namespace="vars", "web_stream_enabled", fun (s) -> begin web_stream_enabled := (s == "true") string_of(!web_stream_enabled) end)
server.register(namespace="vars", "stream_metadata_type", fun (s) -> begin stream_metadata_type := int_of_string(s) s end)
server.register(namespace="vars", "show_name", fun (s) -> begin show_name := s s end)
server.register(namespace="vars", "station_name", fun (s) -> begin station_name := s s end)
default = single("/opt/pypo/files/basic/silence.mp3")
default = single(conservative=true, "/opt/pypo/files/basic/silence.mp3")
default = rewrite_metadata([("artist","Airtime"), ("title", "offline")],default)
s = fallback(track_sensitive=false, [queue, default])
s = on_metadata(notify, s)
s = crossfade(s)
# Attach a skip command to the source s:
add_skip_command(s)
web_stream_source = input.http(id="web_stream", autostart = false, "")
web_stream_source = input.http(id="web_stream", autostart = false, buffer=0.5, max=20., "")
#once the stream is started, give it a sink so that liquidsoap doesn't
#create buffer overflow warnings in the log file.
output.dummy(fallible=true, web_stream_source)
s = switch(track_sensitive = false,
transitions=[to_live,to_live],
[
({ !web_stream_enabled }, web_stream_source),
({ true }, s)
]
)
s = map_metadata(append_title, s)
if output_sound_device then
out_device = out(s)
end

View file

@ -1,112 +0,0 @@
#!/bin/bash
#-------------------------------------------------------------------------------
# Copyright (c) 2010 Sourcefabric O.P.S.
#
# This file is part of the Airtime project.
# http://airtime.sourcefabric.org/
#
# Airtime is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# Airtime is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Airtime; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
#-------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
# This script creates a tgz archive of the Airtime storage.
#
# To get usage help, try the -h option
#-------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
# Determine directories, files
#-------------------------------------------------------------------------------
reldir=`dirname $0`
phpdir=$reldir
mkdir -p $reldir/tmp
tmpmaindir=`cd $reldir/tmp; pwd`
dbxml="db.xml"
datestr=`date '+%Y%m%d%H%M%S'`
xmltar="xmls.tar"
destfile="storage$datestr.tar"
#-------------------------------------------------------------------------------
# Print the usage information for this script.
#-------------------------------------------------------------------------------
printUsage()
{
echo "This script creates a tgz archive of the Airtime storage.";
echo "parameters:";
echo "";
echo " -d, --destination Destination directory [default:$tmpmaindir].";
echo " -h, --help Print this message and exit.";
echo "";
}
#-------------------------------------------------------------------------------
# Process command line parameters
#-------------------------------------------------------------------------------
CMD=${0##*/}
opts=$(getopt -o hd: -l help,destinantion: -n $CMD -- "$@") || exit 1
eval set -- "$opts"
while true; do
case "$1" in
-h|--help)
printUsage;
exit 0;;
-d|--destinantion)
destdir=$2
shift; shift;;
--)
shift;
break;;
*)
echo "Unrecognized option $1.";
printUsage;
exit 1;
esac
done
if [ "x$destdir" == "x" ]; then
destdir=$tmpmaindir
fi
destdir=`cd $destdir; pwd`
#-------------------------------------------------------------------------------
# Do backup
#-------------------------------------------------------------------------------
tmpdir=`mktemp -d $tmpmaindir/tmp.XXXXXX`
echo "Backuping to $destdir/$destfile :"
echo "Dumping database ..."
cd $phpdir
php -q airtime_backup.php > $tmpdir/$dbxml
echo "Packaging stored files ..."
cd $phpdir
storpath=`php -q getStorPath.php`
cd $storpath/..
find stor -name "*.xml" -print | tar cf $tmpdir/$xmltar -T -
find stor ! -name "*.xml" -a -type f -print | tar cf $tmpdir/$destfile -T -
cd $tmpdir
tar rf $xmltar $dbxml --remove-files
echo "Compressing XML part ..."
bzip2 $xmltar
tar rf $destfile $xmltar.bz2 --remove-files
mv $destfile "$destdir"
rmdir $tmpdir
#-------------------------------------------------------------------------------
# Say goodbye
#-------------------------------------------------------------------------------
echo "done"

View file

@ -1,194 +0,0 @@
<?php
define('NSPACE', 'lse');
header("Content-type: text/plain");
require_once('DB.php');
require_once("XML/Util.php");
require_once("XML/Beautifier.php");
require_once(dirname(__FILE__)."/../application/configs/conf.php");
require_once(dirname(__FILE__)."/../application/models/BasicStor.php");
require_once(dirname(__FILE__)."/../application/models/Prefs.php");
PEAR::setErrorHandling(PEAR_ERROR_RETURN);
$CC_DBC = DB::connect($CC_CONFIG['dsn'], TRUE);
$CC_DBC->setFetchMode(DB_FETCHMODE_ASSOC);
$bs = new BasicStor();
$stid = $bs->storId;
#var_dump($stid); exit;
#$farr = $bs->bsListFolder($stid); var_dump($farr); exit;
function admDumpFolder(&$bs, $fid, $ind='')
{
// NOTE: need to fix this, removed due to tree removal
// $name = M2tree::GetObjName($fid);
// if (PEAR::isError($name)) {
// echo $name->getMessage();
// exit;
// }
$media = StoredFile::Recall($fid);
$type = $media->getType();
$gunid = $media->getGunid();
$pars = array();
if ($gunid) {
$pars['id']="$gunid";
}
$pars['name'] = "$name";
switch ($type) {
case "audioclip":
return XML_Util::createTagFromArray(array(
'namespace' => NSPACE,
'localPart' => 'audioClip',
'attributes'=> $pars,
));
break;
case "webstream":
return XML_Util::createTagFromArray(array(
'namespace' => NSPACE,
'localPart' => 'webstream',
'attributes'=> $pars,
));
break;
case "playlist":
return XML_Util::createTagFromArray(array(
'namespace' => NSPACE,
'localPart' => 'playlist',
'attributes'=> $pars,
));
break;
default:
return "";
}
}
function admDumpGroup(&$bs, $gid, $ind='')
{
$name = Subjects::GetSubjName($gid);
if (PEAR::isError($name)) {
echo $name->getMessage();
exit;
}
$isGr = Subjects::IsGroup($gid);
if (PEAR::isError($isGr)) {
echo $isGr->getMessage();
exit;
}
$pars = array('name'=>"$name");
$pars['id'] = $gid;
if (!$isGr) {
return XML_Util::createTagFromArray(array(
'namespace' => NSPACE,
'localPart' => 'member',
'attributes'=> $pars,
));
}
$garr = Subjects::ListGroup($gid);
if (PEAR::isError($garr)) {
echo $garr->getMessage();
exit;
}
$res = '';
foreach ($garr as $i => $member) {
$fid2 = $member['id'];
$res .= admDumpGroup($bs, $fid2, "$ind ");
}
$tagarr = array(
'namespace' => NSPACE,
'localPart' => 'group',
'attributes'=> $pars,
);
$prefs = admDumpPrefs($bs, $gid);
if (!is_null($prefs)) {
$res .= $prefs;
}
if ($res) {
$tagarr['content'] = $res;
}
return XML_Util::createTagFromArray($tagarr, $res === '');
// if (!$res) {
// } else {
// return XML_Util::createTagFromArray(array(
// 'namespace' => NSPACE,
// 'localPart' => 'group',
// 'attributes'=> $pars,
// 'content' => $res,
// ), FALSE);
// }
}
function admDumpSubjects(&$bs, $ind='')
{
$res ='';
$subjs = Subjects::GetSubjects('id, login, pass, type');
foreach ($subjs as $i => $member) {
switch ($member['type']) {
case "U":
$prefs = admDumpPrefs($bs, $member['id']);
$pars = array('login'=>"{$member['login']}", 'pass'=>"{$member['pass']}");
$pars['id'] = $member['id'];
$tagarr = array(
'namespace' => NSPACE,
'localPart' => 'user',
'attributes'=> $pars,
);
if (!is_null($prefs)) {
$tagarr['content'] = $prefs;
}
$res .= XML_Util::createTagFromArray($tagarr , FALSE);
break;
case "G":
$res .= admDumpGroup($bs, $member['id'], "$ind ");
break;
}
}
# return "$ind<subjects>\n$res$ind</subjects>\n";
return XML_Util::createTagFromArray(array(
'namespace' => NSPACE,
'localPart' => 'subjects',
'content'=> $res,
), FALSE);
}
function admDumpPrefs(&$bs, $subjid)
{
$res ='';
$pr = new Prefs($bs);
$prefkeys = $pr->readKeys($subjid);
# var_dump($subjid); var_dump($prefkeys); #exit;
foreach ($prefkeys as $i => $prefk) {
$keystr = $prefk['keystr'];
$prefval = $pr->readVal($subjid, $keystr);
$pars = array('name'=>"$keystr", 'val'=>"$prefval");
$res .= XML_Util::createTagFromArray(array(
'namespace' => NSPACE,
'localPart' => 'pref',
'attributes'=> $pars,
));
}
if (!$res) {
return NULL;
}
return XML_Util::createTagFromArray(array(
'namespace' => NSPACE,
'localPart' => 'preferences',
'content'=> $res,
), FALSE);
}
$subjects = admDumpSubjects($bs, ' ');
$tree = admDumpFolder($bs, $stid, ' ');
$res = XML_Util::getXMLDeclaration("1.0", "UTF-8")."\n";
$node = XML_Util::createTagFromArray(array(
'namespace' => NSPACE,
'localPart' => 'storageServer',
'content' => "$subjects$tree",
), FALSE);
$res .= $node;
$fmt = new XML_Beautifier();
$res = $fmt->formatString($res);
#var_export($res);
#var_dump($res);
echo "$res";

View file

@ -13,7 +13,7 @@ error_reporting(E_ALL);
set_error_handler("camp_import_error_handler", E_ALL & !E_NOTICE);
require_once(dirname(__FILE__)."/../application/configs/conf.php");
require_once(dirname(__FILE__)."/../application/models/GreenBox.php");
require_once(dirname(__FILE__)."/../application/models/StoredFile.php");
require_once('DB.php');
require_once('Console/Getopt.php');
@ -104,8 +104,6 @@ function camp_import_audio_file($p_filepath, $p_importMode = null, $p_testOnly =
return;
}
$greenbox = new GreenBox();
$fileCount = 0;
$duplicates = 0;

View file

@ -1,110 +0,0 @@
#!/bin/bash
#-------------------------------------------------------------------------------
# Copyright (c) 2010 Sourcefabric O.P.S.
#
# This file is part of the Airtime project.
# http://airtime.sourcefabric.org/
#
# Airtime is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# Airtime is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Airtime; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
#-------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
# This script restores the data which was backed up with airtime-backup.
#
# To get usage help, try the -h option
#-------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
# Determine directories, files
#-------------------------------------------------------------------------------
reldir=`dirname $0`
phpdir=$reldir
mkdir -p $reldir/tmp
tmpmaindir=`cd $reldir/tmp; pwd`
dbxml="db.xml"
tarfile0="xmls.tar"
#-------------------------------------------------------------------------------
# Print the usage information for this script.
#-------------------------------------------------------------------------------
printUsage()
{
echo "This script restores the data which was backed up with airtime-backup."
echo "parameters:";
echo "";
echo " -f, --file File with the backed up data, required.";
echo " -h, --help Print this message and exit.";
echo "";
}
#-------------------------------------------------------------------------------
# Process command line parameters
#-------------------------------------------------------------------------------
CMD=${0##*/}
opts=$(getopt -o hf: -l help,file -n $CMD -- "$@") || exit 1
eval set -- "$opts"
while true; do
case "$1" in
-h|--help)
printUsage;
exit 0;;
-f|--file)
tarfile=$2
shift; shift;;
--)
shift;
break;;
*)
echo "Unrecognized option $1.";
printUsage;
exit 1;
esac
done
if [ "x$tarfile" == "x" ]; then
echo "Required parameter file not specified.";
printUsage;
exit 1;
fi
tfdir=`dirname $tarfile`
tfdir=`cd $tfdir; pwd`
tfbname=`basename $tarfile`
tarfile="$tfdir/$tfbname"
#-------------------------------------------------------------------------------
# Do restore
#-------------------------------------------------------------------------------
tmpdir=`mktemp -d $tmpmaindir/tmp.XXXXXX`
echo "Restoring database from $tarfile ..."
cd $tmpdir
tar xf $tarfile
tar xjf $tarfile0.bz2
rm -f $tarfile0.bz2
cd $phpdir
php -q restore.php $tmpdir/$dbxml $tmpdir
rm -rf "$tmpdir/stor"
rm -f $tmpdir/*
rmdir "$tmpdir"
#-------------------------------------------------------------------------------
# Say goodbye
#-------------------------------------------------------------------------------
echo "done"

View file

@ -1,254 +0,0 @@
<?php
define('NSPACE', 'lse');
define('VERBOSE', FALSE);
#define('VERBOSE', TRUE);
header("Content-type: text/plain");
require_once 'DB.php';
require_once "XML/Util.php";
require_once "XML/Beautifier.php";
require_once dirname(__FILE__)."/../application/configs/conf.php";
require_once dirname(__FILE__)."/../application/models/BasicStor.php";
require_once dirname(__FILE__)."/../application/models/Prefs.php";
/* =========================================================== misc functions */
function ls_restore_processObject($el)
{
$res = array(
'name' => $el->attrs['name']->val,
'type' => $el->name,
);
switch ($res['type']) {
case 'folder':
foreach ($el->children as $i => $o) {
$res['children'][] = ls_restore_processObject($o);
}
break;
default:
$res['gunid'] = $el->attrs['id']->val;
break;
}
return $res;
}
function ls_restore_checkErr($r, $ln='')
{
if (PEAR::isError($r)) {
echo "ERROR $ln: ".$r->getMessage()." ".$r->getUserInfo()."\n";
exit;
}
}
function ls_restore_restoreObject($obj, /*$parid,*/ $reallyInsert=TRUE){
global $tmpdir, $bs;
switch ($obj['type']) {
case "audioClip";
case "webstream";
case "playlist";
$gunid = $obj['gunid'];
if (is_null($gunid)) {
break;
}
$gunid3 = substr($gunid, 0, 3);
$mediaFile = "$tmpdir/stor/$gunid3/$gunid";
# echo "X1 $gunid, $gunid3, $mediaFile\n";
if (!file_exists($mediaFile)) {
$mediaFile = NULL;
}
$mdataFile = "$tmpdir/stor/$gunid3/$gunid.xml";
if (!file_exists($mdataFile)) {
$mdataFile = NULL;
}
if ($reallyInsert) {
if (VERBOSE) {
echo " creating file {$obj['name']} ...\n";
}
$values = array(
"filename" => $obj['name'],
"filepath" => $mediaFile,
"metadata" => $mdataFile,
"gunid" => $obj['gunid'],
"filetype" => strtolower($obj['type'])
);
$r = StoredFile::Insert($values);
ls_restore_checkErr($r, __LINE__);
}
break;
}
}
/* =============================================================== processing */
PEAR::setErrorHandling(PEAR_ERROR_RETURN);
$CC_DBC = DB::connect($CC_CONFIG['dsn'], TRUE);
$CC_DBC->setFetchMode(DB_FETCHMODE_ASSOC);
$bs = new BasicStor();
$pr = new Prefs($bs);
$dbxml = file_get_contents($argv[1]);
$tmpdir = $argv[2];
require_once("$STORAGE_SERVER_PATH/var/XmlParser.php");
$parser = new XmlParser($dbxml);
if ($parser->isError()) {
return PEAR::raiseError(
"MetaData::parse: ".$parser->getError()
);
}
$xmlTree = $parser->getTree();
/* ----------------------------------------- processing storageServer element */
$subjArr = FALSE;
//$tree = FALSE;
foreach ($xmlTree->children as $i => $el) {
switch ($el->name) {
case "subjects":
if ($subjArr !== FALSE) {
echo "ERROR: unexpected subjects element\n";
}
$subjArr = $el->children;
break;
// case "folder":
// if ($tree !== FALSE) {
// echo "ERROR: unexpected folder element\n";
// }
// $tree = ls_restore_processObject($el);
// break;
default:
echo "ERROR: unknown element name {$el->name}\n";
exit;
}
// echo "{$el->name}\n";
}
/* ---------------------------------------------- processing subjects element */
$subjects = array();
$groups = array();
foreach ($subjArr as $i => $el) {
switch ($el->name) {
case "group":
$grname = $el->attrs['name']->val;
$groups[$grname] = $el->children;
$subjects[$grname] = array(
'type' => 'group',
);
break;
case "user":
$login = $el->attrs['login']->val;
$subjects[$login] = array(
'type' => 'user',
'pass' => $el->attrs['pass']->val,
# 'realname' => $el->attrs['realname']->val,
'realname' => '',
'prefs' => (isset($el->children[0]) ? $el->children[0]->children : NULL),
);
break;
}
}
/* -------------------------------------------------------- processing groups */
foreach ($groups as $grname => $group) {
foreach ($group as $i => $el) {
switch ($el->name) {
case "member":
$groups[$grname][$i] = $el->attrs['name']->val;
break;
case "preferences":
$subjects[$grname]['prefs'] = $el->children;
unset($groups[$grname][$i]);
break;
}
}
}
#var_dump($xmlTree);
#var_dump($subjArr);
#var_dump($groups);
#var_dump($subjects);
#var_dump($tree);
#exit;
/* ================================================================ restoring */
if (VERBOSE) {
echo " resetting storage ...\n";
}
$bs->resetStorage(FALSE);
$storId = $bs->storId;
/* ------------------------------------------------------- restoring subjects */
foreach ($subjects as $login => $subj) {
$uid0 = Subjects::GetSubjId($login);
ls_restore_checkErr($uid0);
switch ($subj['type']) {
case "user":
if ($login=='root') {
$r = $bs->passwd($login, NULL, $subj['pass'], TRUE);
ls_restore_checkErr($r, __LINE__);
$uid = $uid0;
} else {
if (!is_null($uid0)) {
$r = $bs->removeSubj($login);
ls_restore_checkErr($r, __LINE__);
}
if (VERBOSE) {
echo " adding user $login ...\n";
}
$uid = BasicStor::addSubj($login, $subj['pass'], $subj['realname'], TRUE);
ls_restore_checkErr($uid, __LINE__);
}
break;
case "group":
if (!is_null($uid0)) {
$r = $bs->removeSubj($login);
if (PEAR::isError($r)) {
$uid = $uid0;
break;
}
//ls_restore_checkErr($r, __LINE__);
}
if (VERBOSE) {
echo " adding group $login ...\n";
}
$uid = BasicStor::addSubj($login, NULL);
ls_restore_checkErr($uid, __LINE__);
// var_export($uid); echo " ";
break;
} // switch
// echo "$login/$uid :\n";
if (isset($subj['prefs'])) {
// var_dump($subj['prefs']); exit;
foreach ($subj['prefs'] as $i => $el) {
switch ($el->name) {
case "pref":
$prefkey = $el->attrs['name']->val;
$prefval = $el->attrs['val']->val;
// echo" PREF($prefkey)=$prefval\n";
$res = $pr->insert($uid, $prefkey, $prefval);
ls_restore_checkErr($res, __LINE__);
break;
default:
var_dump($el);
}
}
}
}
/* --------------------------------------------------------- restoring groups */
#var_dump($groups);
foreach ($groups as $grname => $group) {
foreach ($group as $i => $login) {
if (VERBOSE) {
echo " adding subject $login to group $grname ...\n";
}
$r = Subjects::AddSubjectToGroup($login, $grname);
ls_restore_checkErr($r, __LINE__);
}
}
/* -------------------------------------------------------- restoring objects */
ls_restore_restoreObject($tree, /*$storId,*/ FALSE);

View file

@ -1,36 +0,0 @@
<?php
/**
* Do database restore in background. - command line php application
*
* required command line parameters:
* @param 1. backup file
* @param 2. status file
* @param 3. token
* @param 4. sessid
*
*/
require_once(dirname(__FILE__).'/../application/configs/conf.php');
require_once(dirname(__FILE__).'/../application/models/GreenBox.php');
require_once(dirname(__FILE__).'/../application/models/Restore.php');
include_once('DB.php');
PEAR::setErrorHandling(PEAR_ERROR_RETURN);
$CC_DBC = DB::connect($CC_CONFIG['dsn'], TRUE);
if (DB::isError($CC_DBC)) {
die($CC_DBC->getMessage());
}
$CC_DBC->setFetchMode(DB_FETCHMODE_ASSOC);
$gb = new GreenBox();
$rs = new Restore($gb);
if ($rs->loglevel=='debug') {
$rs->addLogItem('argv:'.print_r($argv,true));
}
$backupfile = $argv[1];
$token = $argv[3];
$sessid = $argv[4];
$rs->startRestore($backupfile,$token,$sessid);

3
utils/upgrade-sql.php Normal file
View file

@ -0,0 +1,3 @@
<?php
DROP TABLE cc_backup;
DROP TABLE cc_trans;