diff --git a/src/admin.php b/src/admin.php new file mode 100644 index 0000000..b6ddecd --- /dev/null +++ b/src/admin.php @@ -0,0 +1,7 @@ +run(); +?> \ No newline at end of file diff --git a/src/attplan.php b/src/attplan.php new file mode 100644 index 0000000..478e2be --- /dev/null +++ b/src/attplan.php @@ -0,0 +1,7 @@ +run(); +?> \ No newline at end of file diff --git a/src/classes/Assert.php b/src/classes/Assert.php new file mode 100644 index 0000000..6b25388 --- /dev/null +++ b/src/classes/Assert.php @@ -0,0 +1,71 @@ + 0) { + for($i = 0; $i < count($num);$i++) { + Assert::isId($num[$i],$message.", id at index ".$i." invalid"); + } + } else { + trigger_error($message.", id array is empty",E_USER_ERROR); + } + } else { + Assert::isId($num,$message.", "); + } + } + + public function isTrue($value, $message=null) { + if($value !== true) { + if(!$message) { + $message = "expected true"; + } + trigger_error($message,E_USER_ERROR); + } + } + + public function notEmpty($value, $message=null) { + $result = false; + if( !is_numeric($value) ) { + if( is_array($value) ) { // Is array? + if( count($value, 1) < 1 ) $result = true; + } + elseif(!isset($value) || strlen(trim($value)) == 0) { + $result = true; + } + } + if($result === true) { + if(!$message) { + $message = "expected non empty value"; + } + trigger_error($message,E_USER_ERROR); + } + } +} + +?> \ No newline at end of file diff --git a/src/classes/admin.class.php b/src/classes/admin.class.php new file mode 100644 index 0000000..2cc0bc5 --- /dev/null +++ b/src/classes/admin.class.php @@ -0,0 +1,1965 @@ +action]) { + eval("\$this->".$functions[$this->action].";"); + } + #default + $this->_header("index.php"); + } + + /** \brief Logfile anzeigen + + Listet alle Einträge des Logfile auf + */ + function Logfile_list() { + if (!$this->userdata['rights']['logfile']) { + #no permission + $this->_header("","no permission"); + } + $logfilefilter = $_SESSION['logfilefilter']; + if ($_REQUEST['subaction'] == 'newsearch' && $logfilefilter) { + unset($logfilefilter); + unset($_SESSION['logfilefilter']); + } + $page = param_num("page",1); + $rows = 12; + if ($_REQUEST['sort'] && $_REQUEST['order'] && $logfilefilter) { + $sort = trim($_REQUEST['sort']); + $order = trim($_REQUEST['order']); + if ($sort != 'username' && $sort != 'cat' && $sort != 'date') $sort = 'date'; + if ($order != "asc" && $order != "desc") $order = "desc"; + $logfilefilter['sort'] = $sort; + $logfilefilter['order'] = $order; + $_SESSION['logfilefilter'] = $logfilefilter; + } + if ($_REQUEST['subaction'] == "search") { + $logfilefilter['username'] = param_str("username"); + $logfilefilter['gala'] = param_str("gala"); + $logfilefilter['cat'] = $_REQUEST['cat']; + $logfilefilter['sort'] = "date"; + $logfilefilter['order'] = "desc"; + $_SESSION['logfilefilter'] = $logfilefilter; + } + if (!$logfilefilter) { + $catlist = getLogFilecatList(); + $this->template->assign('catlist',$catlist); + $this->forms['logfile']['action'] = "logfile"; + $this->forms['logfile']['url'] = "admin.php"; + $this->show('logfile_list_form','Logfile durchsuchen'); + } + $this->forms['logfile'][$logfilefilter['sort']][$logfilefilter['order']] = '_active'; + $logfile = listLogFile($logfilefilter,&$pages,&$page,$rows); + $this->forms['logfile']['pages'] = showPageBar($page,$pages,"admin.php?action=logfile","page","menu"); + for ($i=0;$itemplate->assign('logfile',$logfile); + $this->show('logfile_list','Logfile'); + } + /** \brief User anzeigen + + Listet alle User auf, vorher wird ein Filter angeboten. + Filter ist abhängig von den Rechten die der User hat. + */ + function User_list() { + #check rights + $rank = $this->userdata['rights']['useredit']['rank']; + if (!$rank){ + #no permission + $this->_header("","no permission"); + } + $userlistfilter = $_SESSION['userlistfilter']; + $page = param_num("page",1); + $rows = 12; + if ($_REQUEST['subaction'] == 'newsearch' && $userlistfilter) { + unset($userlistfilter); + unset($_SESSION['userlistfilter']); + } + if ($_REQUEST['sort'] && $_REQUEST['order'] && $userlistfilter) { + $sort = trim($_REQUEST['sort']); + $order = trim($_REQUEST['order']); + if ($sort != 'username' && $sort != 'koords' + && $sort != 'group' && $sort != 'phone') $sort = 'koords'; + if ($order != "asc" && $order != "desc") $order = "asc"; + $userlistfilter['sort'] = $sort; + $userlistfilter['order'] = $order; + $_SESSION['userlistfilter'] = $userlistfilter; + } + + if ($_REQUEST['subaction'] == "search") { + $userlistfilter['username'] = param_str("username"); + $userlistfilter['gala'] = param_str("gala"); + if ($rank > 1) { + $userlistfilter['ally'] = $this->userdata["aid"]; + #checken ob galas auch zur allys gehören + $userlistfilter['checkallygalas'] = true; + } else { + $userlistfilter['ally'] = param_num("ally"); + } + $userlistfilter['group'] = $_REQUEST['group']; + $userlistfilter['phone'] = param_str("phone"); + $userlistfilter['sort'] = "koords"; + $userlistfilter['order'] = "asc"; + $_SESSION['userlistfilter'] = $userlistfilter; + } + if (!$userlistfilter) { + if ($rank == 1) { + $this->template->assign('allylist',getAllyList()); + $this->template->assign('rank1',1); + } else { + $this->template->assign('ally',$this->userdata['tag']); + } + $this->template->assign('grouplist',getGroupList()); + $this->forms['userlist']['action'] = "user"; + $this->forms['userlist']['url'] = "admin.php"; + $this->show('user_list_form','Benutzer suchen'); + exit(); + } + #nochmal rang check + if ($rank > 1 && $userlistfilter['ally'] != $this->userdata["aid"]) { + $userlistfilter['ally'] = $this->userdata["aid"]; + #checken ob galas auch zur allys gehören + $userlistfilter['checkallygalas'] = true; + $_SESSION['userlistfilter'] = $userlistfilter; + } + $this->forms['userlist'][$userlistfilter['sort']][$userlistfilter['order']] = '_active'; + $userlist = listUser($userlistfilter,&$pages,&$page,$rows); + $this->forms['userlist']['pages'] = showPageBar($page,$pages,"admin.php?action=user","page","menu"); + $setback = "admin.php?action=user&page=".$page; + $_SESSION['setback'] = $setback; + $this->template->assign('userlist',$userlist); + $this->show('user_list','Benutzerliste'); + } + /** + \brief Zeigt Userstatistiken + + zeigt Statistiken zu den Usern an + */ + function User_Stats() { + if (!$this->_checkUserRights(array("admin"))) + $this->_header("index.php"); + $userstatsfilter = $_SESSION['userstatsfilter']; + $page = param_num("page",1); + $rows = 12; + if ($_REQUEST['sort'] && $_REQUEST['order'] && $userstatsfilter) { + $sort = trim($_REQUEST['sort']); + $order = trim($_REQUEST['order']); + if ($sort != 'username' && $sort != 'koords' && $sort != 'login') $sort = 'username'; + if ($order != "asc" && $order != "desc") $order = "asc"; + $userstatsfilter['sort'] = $sort; + $userstatsfilter['order'] = $order; + $_SESSION['userstatsfilter'] = $userstatsfilter; + } + if (!$userstatsfilter) { + $userstatsfilter['sort'] = 'koords'; + $userstatsfilter['order'] = 'asc'; + $_SESSION['userstatsfilter'] = $userstatsfilter; + } + $this->forms['userlist'][$userstatsfilter['sort']][$userstatsfilter['order']] = '_active'; + $userlist = listUser($userstatsfilter,&$pages,&$page,$rows); + for($i=0;$iforms['userlist']['pages'] = showPageBar($page,$pages,"admin.php?action=userstats","page","menu"); + $this->template->assign('userlist',$userlist); + $this->show('user_stats','Benutzerstatistik'); + } + /** + \brief Gruppen auflisten + + Listet die Rechtegruppen des TC auf + */ + function Group_list() + { + if (!$this->userdata['rights']['groupedit']) { + #no permission + $this->_header("","no permission"); + } + $page = param_num("page",1); + $rows = 6; + $grouplistfilter = $_SESSION['grouplistfilter']; + if (($_REQUEST['sort'] && $_REQUEST['order']) || !$grouplistfilter) { + $sort = trim($_REQUEST['sort']); + $order = trim($_REQUEST['order']); + if ($sort != 'name' && $sort != 'descr' && $sort != 'member') $sort = 'name'; + if ($order != "asc" && $order != "desc") $order = "asc"; + $grouplistfilter['sort'] = $sort; + $grouplistfilter['order'] = $order; + $_SESSION['grouplistfilter'] = $grouplistfilter; + } + $this->forms['grouplist'][$grouplistfilter['sort']][$grouplistfilter['order']] = '_active'; + $grouplist = listGroups($grouplistfilter,&$pages,&$page,$rows); + $this->forms['grouplist']['pages'] = showPageBar($page,$pages,"admin.php?action=groups","page","menu"); + $this->template->assign('grouplist',$grouplist); + $this->show('group_list','Gruppenliste'); + } + /** + \brief Gruppeninfos + + Zeigt Informationen zu einer Gruppe an + */ + function Group_details(){ + if (!$this->userdata['rights']['groupedit']) { + #no permission + $this->_header("","no permission"); + } + $id = param_num("id"); + if (!$id) $this->_header(); + $return = getGroup($id); + if (!$return) $this->_header(); + $this->template->assign("searchlink","admin.php"); + $this->template->assign("editlink","admin.php?action=editgroup&id=$id"); + $this->template->assign("deletelink","admin.php?action=deletegroup&id=$id"); + $this->template->assign("groupid",$id); + $this->forms['groupdetails']['fields'] = $return; + $this->show('group_details_admin',"Gruppendetails"); + } + + /** + \brief Gruppe bearbeiten + + Ändert die Daten einer Gruppe + */ + function Group_edit() { + if (!$this->userdata['rights']['groupedit']) { + #no permission + $this->_header("","no permission"); + } + $id = param_num("id"); + if (!$id) $this->_header(); + $page = param_num("page",1); + $return = getGroup($id); + if (!$return) $this->_header(); + $data = $_SESSION['steps']; + #information message, step 2 + if ($data['groupedit']) { + #save step + unset($data['groupedit']); + $_SESSION['steps'] = $data; + $this->forms['information']['action'] = "groupdetails"; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['title'] = "Gruppe bearbeiten"; + $this->forms['information']['message'] = "Änderung erfolgreich"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Gruppe bearbeiten"); + } + #formular send + if ($_REQUEST['send']) { + $items['name'] = param_str("name",true); + $items['descr'] = param_str("descr",true); + if (!$items['name']) { + $errors[] = "Name darf nicht leer sein!"; + $this->forms['addgroup']['fields']['name']['bgrd'] = '_error'; + } + if (!$items['descr']) { + $errors[] = "Beschreibung darf nicht leer sein!"; + $this->forms['addgroup']['fields']['descr']['bgrd'] = '_error'; + } + #optional parameters + $items['usertitle'] = param_str("usertitle",true); + if (!$errors && $items['name'] != $return['name'] && getGroupByName($items['name'])) { + $errors[] = 'Gruppe existiert bereits!'; + $this->forms['addgroup']['fields']['name']['bgrd'] = '_error'; + } + if (!$errors) { + #save step + $data['groupedit'] = 1; + $_SESSION['steps'] = $data; + addToLogfile("Gruppe ".$return['name']." bearbeitet","Admin",$this->userdata['uid']); + updateGroup($return['gid'],$items['name'],$items['descr'],$items['usertitle']); + $this->_header("admin.php?action=editgroup&id=".$return['gid']."&send"); + } else { + $this->template->assign("errors",$errors); + } + } else { + $this->forms['groupedit']['fields']['usertitle']['value'] = $return['usertitle']; + $this->forms['groupedit']['fields']['name']['value'] = $return['name']; + $this->forms['groupedit']['fields']['descr']['value'] = $return['descr']; + } + $this->forms['groupedit']['id'] = $return['gid']; + $this->forms['groupedit']['name'] = $return['name']; + $this->forms['groupedit']['url'] = 'admin.php?id='.$return['gid']; + $this->forms['groupedit']['action'] = 'editgroup'; + $this->show('group_edit_form',"Gruppe bearbeiten"); + } + /** + \brief Gruppe hinzufügen + + Fügt eine neue Gruppe hinzu + */ + function Group_add() { + if (!$this->userdata['rights']['groupedit']) { + #no permission + $this->_header("","no permission"); + } + $page = param_num("page",1); + $data = $_SESSION['steps']; + #information message, step 2 + if ($data['addgroup']) { + $id = param_num("id"); + if ($id) { + $return = getGroup($id); + if (!$return) $this->_header(); + } + #save step + unset($data['addgroup']); + $_SESSION['steps'] = $data; + $this->forms['information']['action'] = "groupdetails"; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['title'] = "Gruppe hinzufügen"; + $this->forms['information']['message'] = "Gruppe ".$return['name']." hinzugefügt"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Gruppe hinzufügen"); + } + #formular send + if ($_REQUEST['send']) { + $items['name'] = param_str("name",true); + $items['descr'] = param_str("descr",true); + $errors = false; + #check if empty + if (!$items['name']) { + $errors[] = "Name darf nicht leer sein!"; + $this->forms['addgroup']['fields']['name']['bgrd'] = '_error'; + } + if (!$items['descr']) { + $errors[] = "Beschreibung darf nicht leer sein!"; + $this->forms['addgroup']['fields']['descr']['bgrd'] = '_error'; + } + #optional parameters + $items['usertitle'] = param_str("usertitle",true); +# for ($i=0;$iforms['addgroup']['fields']['name']['bgrd'] = '_error'; + } + if (!$errors) { + #save step + $data['addgroup'] = 1; + $_SESSION['steps'] = $data; + $gid = addGroup($items['name'],$items['descr'],$items['usertitle']); + if ($gid) { + addToLogfile("Gruppe ".$items['name']." hinzugefügt","Admin",$this->userdata['uid']); + $this->_header("admin.php?action=addgroup&id=".$gid."&send"); + } + } else { + $this->forms['addgroup']['fields']['descr']['value'] = $items['descr']; + $this->forms['addgroup']['fields']['name']['value'] = $items['name']; + $this->forms['addgroup']['fields']['usertitle']['value'] = $items['usertitle']; + $this->template->assign("errors",$errors); + } + } + $this->forms['addgroup']['name'] = $return['name']; + $this->forms['addgroup']['url'] = "admin.php"; + $this->forms['addgroup']['action'] = 'addgroup'; + $this->show('group_add_form',"Gruppe hinzufügen"); + } + /** + \brief Userinfos + + Zeigt ausführliche Informationen zu einem User + */ + function User_details() { + #check rights + $rank = $this->userdata['rights']['useredit']['rank']; + if (!$rank){ + #no permission + $this->_header("","no permission"); + } + $id = param_num("id"); + if (!$id) $this->_header(); + $return = getUserByID($id); + if (!$return) $this->_header(); + #ally/galaxyebene + if ($rank > 1 && $return['aid'] != $this->userdata['aid']){ + #no permission + $this->_header("","no permission"); + } + if ($rank == 1 || + ($rank == 2 && $return['aid'] == $this->userdata['aid']) || + ($rank == 3 && $return['gala'] == $this->userdata['gala'])) + { + $this->template->assign("editlink","admin.php?action=edituser&id=$id"); + $this->template->assign("deletelink","admin.php?action=deleteuser&id=$id"); + } + $this->template->assign("user",$return); + $this->template->assign("koords",$return['gala'].":".$return['pos']); + $this->show('user_details_admin',"Benutzerdetails"); + } + /** + \brief User bearbeiten + + Ändert die Daten eines Users + */ + function User_edit() { + #check rights + $rank = $this->userdata['rights']['useredit']['rank']; + if (!$rank){ + #no permission + $this->_header("","no permission"); + } + $page = param_num("page",1); + $id = param_num("id"); + if (!$id) $this->_header(); + $return = getUserByID($id); + if (!$return) $this->_header(); + #check rights + if (($rank > 1 && $this->userdata['aid'] != $return['aid']) || + ($rank > 2 && $this->userdata['gala'] != $return['gala'])){ + #no permission + $this->_header("","no permission"); + } + $data = $_SESSION['steps']; + #information message, step 2 + if ($data['useredit']) { + #save step + unset($data['useredit']); + $_SESSION['steps'] = $data; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['title'] = "Benutzerdaten ändern"; + $this->forms['information']['message'] = "Änderung erfolgreich"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Benutzerdaten ändern"); + } + #formular send + if ($this->userdata['rights']['changegroup']) { + $grouplist = getGroupList($this->userdata['rights']['changegroup']['rank']); + if ($return['gid']) { + for($i=0;$i < count($grouplist);$i++){ + if ($grouplist[$i]['gid'] == $return['gid']) { + $canchangegroup = true; + break; + } + } + } else { + $canchangegroup = true; + } + } + if($canchangegroup) { + $this->template->assign("changegroup",1); + } else { + $this->template->assign("group",$return['groupname']); + } + if ($rank == 1) { + $allylist = getAllyList(); + } else { + $this->template->assign("ally",$this->userdata['tag']); + } + $this->template->assign("rank",$rank); + $galalist = array(); + if ($_REQUEST['send']) { + $items['login']['value'] = param_str("login",true); + $items['nick']['value'] = param_str("nick",true); + $items['ircauth']['value'] = param_str("ircauth",true); + $items['pos']['value'] = param_num("pos",null,true); + $items['gala']['value'] = param_num("gala",null,true); + $password = param_str("password",true); + if ($rank == 1) { + $items['aid']['value'] = param_num("ally",0,true); + #check allyid + if ($items['aid']['value']) { + $ally = 0; + for ($i=0;$i < count($allylist);$i++) { + if ($items['aid']['value'] == $allylist[$i]['aid']) { + $ally = &$allylist[$i]; + $ally['selected'] = "selected"; + break; + } + } + } + if (!$ally) $this->_header("","Ungültige Allianzid!"); + } else { + $items['aid']['value'] = $this->userdata['aid']; + } + #check gala + if ($rank < 3) { + $galalist = getGalaListbyAlly($items['aid']['value']); + if (!$galalist){ + $errors[] = "Die Allianz hat keine Galaxien!"; + $galalist[] = array("gala" => "keine"); + } + } else { + $items['gala']['value'] = $this->userdata['gala']; + $this->template->assign("gala",$this->userdata['gala']); + } + if ($_REQUEST['next_x']) { + if (!$items['nick']['value']) { + $errors[] = "Nickname darf nicht leer sein!"; + $items['nick']['bgrd'] = '_error'; + } + if (!$items['login']['value']) { + $errors[] = "Login darf nicht leer sein!"; + $items['login']['bgrd'] = '_error'; + } + if (!$items['pos']['value']) { + $items['pos']['bgrd'] = '_error'; + $errors[] = "Die Position darf nicht leer sein!"; + } + if ($canchangegroup) { + #check gid + $items['gid']['value'] = param_num('group',0,true); + if ($items['gid']['value']) { + $group = 0; + for ($i=0;$i < count($grouplist);$i++) { + if ($items['gid']['value'] == $grouplist[$i]['gid']) { + $group = &$grouplist[$i]; + $group['selected'] = "selected"; + break; + } + } + if (!$group) $this->_header(); + } + } else { + $items['gid']['value'] = $return['gid']; + } + #check nickname + if ($items['nick']['value'] && strtolower($items['nick']['value']) != strtolower($return['nick']) + && getUserByNick($items['nick']['value'])) { + $errors[] = 'User existiert bereits!'; + $items['nick']['bgrd'] = '_error'; + } + #check login + if ($items['login']['value'] && strtolower($items['login']['value']) != strtolower($return['login']) + && getUserByLogin($items['login']['value'])) { + $errors[] = 'Login existiert bereits!'; + $items['login']['bgrd'] = '_error'; + } + #check galaid + if ($items['gala']['value'] && $rank < 3) { + $galaxy = 0; + for ($i=0;$i < count($galalist);$i++) { + if ($items['gala']['value'] == $galalist[$i]['gala']) { + $galaxy = &$galalist[$i]; + $galaxy['selected'] = "selected"; + break; + } + } + if (!$galaxy) $this->_header("index.php","Ungültige Galaid!"); + } + if (!$errors && ($return['gala'] != $items['gala']['value'] || $return['pos'] != $items['pos']['value'])){ + $chkuser = getUserByPos($items['gala']['value'],$items['pos']['value']); + if ($chkuser) { + $errors[] = "User existiert bereits, ".$chkuser['nick']." (".$chkuser['gala'].":".$chkuser['pos'].")"; + $items['pos']['bgrd'] = '_error'; + } + } + if (!$errors) { + #save step + $data['useredit'] = 1; + $_SESSION['steps'] = $data; + if ($password) { + #eigenes pw geändert + if ($return['uid'] == $this->userdata['uid']) { + updateUserPassword($return['uid'],$password); + $sessionuserdata['id'] = $this->userdata['uid']; + $sessionuserdata['password'] = md5($password); + $_SESSION['sessionuserdata'] = $sessionuserdata; + } else { + updatePassword($return['uid'],$password); + } + addToLogfile("Passwort von ".$return['nick']." geändert","Admin",$this->userdata['uid']); + } + addToLogfile("User ".$return['nick']." bearbeitet","Admin",$this->userdata['uid']); + updateAdminUser($return['uid'], + $items['nick']['value'], + $items['login']['value'], + $items['gala']['value'], + $items['pos']['value'], + $items['gid']['value'], + $items['ircauth']['value'] + ); + $this->_header("admin.php?action=edituser&id=".$return['uid']."&send"); + } + } + } else { + if ($return['gid'] && $this->userdata['rights']['changegroup']) { + for ($i=0;$i < count($grouplist);$i++) { + if ($return['gid'] == $grouplist[$i]['gid']) { + $grouplist[$i]['selected'] = "selected"; + break; + } + } + } + if ($rank == 1) { + #select ally + for ($i=0;$i < count($allylist);$i++) { + if ($return['aid'] == $allylist[$i]['aid']) { + $ally = &$allylist[$i]; + $ally['selected'] = "selected"; + break; + } + } + } + if ($rank < 3) { + $galalist = getGalaListbyAlly($return['aid']); + if (!$galalist){ + $errors[] = "Die Allianz hat keine Galaxien!"; + $galalist[] = array("gala" => "keine"); + } else { + #select gala + for ($i=0;$i < count($galalist);$i++) { + if ($return['gala'] == $galalist[$i]['gala']) { + $galalist[$i]['selected'] = "selected"; + break; + } + } + } + } else { + $this->template->assign("gala",$this->userdata['gala']); + } + $items['ircauth']['value'] = $return['ircauth']; + $items['nick']['value'] = $return['nick']; + $items['login']['value'] = $return['login']; + $items['pos']['value'] = $return['pos']; + } + $this->template->assign("errors",$errors); + $this->template->assign("galalist",$galalist); + $this->template->assign("allylist",$allylist); + if (!$items['ircauth']['value']) { + $items['ircauth']['bgrd'] = "_optional"; + } + if (!$items['password']['value']) { + $items['password']['bgrd'] = "_optional"; + } + $this->template->assign("items",$items); + $this->template->assign("grouplist",$grouplist); + $this->template->assign("id",$return['uid']); + $this->template->assign("username",$return['nickname']); + $this->show('user_edit_form',"Benutzerdaten ändern"); + } + /** + \brief User hinzufügen + + Fügt eines User hinzu. + */ + function User_add() { + #check rights + $rank = $this->userdata['rights']['useredit']['rank']; + if (!$rank){ + #no permission + $this->_header("","no permission"); + } + $page = param_num("page",1); + $id = param_num("id"); + $data = $_SESSION['steps']; + #information message, step 2 + if ($data['adduser']) { + if ($id) { + $return = getUserByID($id); + } + if ($return) { + $this->forms['information']['url'] = "admin.php?action=showdetails&id=".$return['uid']."&force"; + } else { + $this->forms['information']['url'] = $this->backtracking->backlink(); + } + #save step + unset($data['adduser']); + $_SESSION['steps'] = $data; + $this->forms['information']['action'] = "userdetails"; + $this->forms['information']['title'] = "Benutzer hinzufügen"; + $this->forms['information']['message'] = "Erfolgreich hinzugefügt"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Benutzer hinzufügen"); + } + #formular send + if ($this->userdata['rights']['changegroup']) { + $grouplist = getGroupList($this->userdata['rights']['changegroup']['rank']); + $this->template->assign("changegroup",1); + } + if ($rank == 1) { + $allylist = getAllyList(); + } else { + $this->template->assign("ally",$this->userdata['tag']); + } + $this->template->assign("rank",$rank); + $galalist = array(); + if ($_REQUEST['send']) { + $items['nickname']['value'] = param_str("nickname",true); + $items['password']['value'] = param_str("password",true); + $items['ircauth']['value']= param_str("ircauth",true); + $items['login']['value']= param_str("login",true); + $items['gala']['value'] = param_num("gala",null,true); + $items['pos']['value'] = param_num("pos",null,true); + $items['gala']['value'] = param_num("gala",0,true); + if ($rank == 1) { + $items['aid']['value'] = param_num("ally",0,true); + #check allyid + if ($items['aid']['value']) { + $ally = 0; + for ($i=0;$i < count($allylist);$i++) { + if ($items['aid']['value'] == $allylist[$i]['aid']) { + $ally = &$allylist[$i]; + $ally['selected'] = "selected"; + break; + } + } + } + if (!$ally) $this->_header("","Ungültige Allianzid!"); + } else { + $items['aid']['value'] = $this->userdata['aid']; + } + if ($rank < 3) { + $galalist = getGalaListbyAlly($items['aid']['value']); + if (!$galalist){ + $errors[] = "Die Allianz hat keine Galaxien!"; + $galalist[] = array("gala" => "keine"); + } + } else { + $items['gala']['value'] = $this->userdata['gala']; + $this->template->assign("gala",$this->userdata['gala']); + } + #auf weiter geklickt + if ($_REQUEST['next_x']) { + if (!$items['login']['value']) { + $items['login']['bgrd'] = '_error'; + $errors[] = "Login darf nicht leer sein!"; + } + if (!$items['nickname']['value']) { + $items['nickname']['bgrd'] = '_error'; + $errors[] = "Nickname darf nicht leer sein!"; + } + if (!$items['password']['value']) { + $items['password']['bgrd'] = '_error'; + $errors[] = "Password darf nicht leer sein!"; + } + if (!$items['pos']['value']) { + $items['pos']['bgrd'] = '_error'; + $errors[] = "Position leer oder ungültig!"; + } + if ($items['nickname']['value'] && getUserByNick($items['nickname']['value'])) { + $items['nickname']['bgrd'] = '_error'; + $errors[] = "User existiert bereits!"; + } + if ($items['login']['value'] && getUserByLogin($items['login']['value'])) { + $items['login']['bgrd'] = '_error'; + $errors[] = "Login existiert bereits!"; + } + if ($this->userdata['rights']['changegroup']) { + #check gid + $items['gid']['value'] = param_num("group",0,true); + if ($items['gid']['value']) { + $group = 0; + for ($i=0;$i < count($grouplist);$i++) { + if ($items['gid']['value'] == $grouplist[$i]['gid']) { + $group = &$grouplist[$i]; + $group['selected'] = "selected"; + break; + } + } + if (!$group) $this->_header("","Ungültige Gruppe, gid!"); + } + } else { + $items['gid']['value'] = 0; + } + #check galaid + if ($items['gala']['value'] && $rank < 3) { + $galaxy = 0; + for ($i=0;$i < count($galalist);$i++) { + if ($items['gala']['value'] == $galalist[$i]['gala']) { + $galaxy = &$galalist[$i]; + $galaxy['selected'] = "selected"; + break; + } + } + if (!$galaxy) $this->_header("","Ungültige Galaid!"); + } + if (!$errors){ + $chkuser = getUserByPos($items['gala']['value'],$items['pos']['value']); + if ($chkuser) { + $errors[] = "User existiert bereits, ".$chkuser['nick']." (".$chkuser['gala'].":".$chkuser['pos'].")"; + $items['pos']['bgrd'] = '_error'; + } + } + if (!$errors) { + #save step + $data['adduser'] = 1; + $_SESSION['steps'] = $data; + $id = addUser( + $items['nickname']['value'], + $items['login']['value'], + $items['password']['value'], + $items['gid']['value'], + $items['gala']['value'], + $items['pos']['value'], + $items['ircauth']['value'] + ); + addToLogfile("User ".$items['nickname']['value']." hinzugefügt","Admin",$this->userdata['uid']); + $this->_header("admin.php?action=adduser&id=$id&send"); + } + } + $this->template->assign("errors",$errors); + } else { + if ($rank == 1) { + $galalist = getGalaListbyAlly($allylist[0]['aid']); + if (!$galalist){ + $errors[] = "Die Allianz hat keine Galaxien!"; + $this->template->assign("errors",$errors); + $galalist[] = array("gala" => "keine"); + } + } elseif ($rank == 2) { + $galalist = getGalaListbyAlly($this->userdata['aid']); + if (!$galalist){ + $errors[] = "Die Allianz hat keine Galaxien!"; + $this->template->assign("errors",$errors); + $galalist[] = array("gala" => "keine"); + } + } elseif ($rank == 3) { + $this->template->assign("gala",$this->userdata['gala']); + } + } + if (!$items['ircauth']['value']) { + $items['ircauth']['bgrd'] = "_optional"; + } + $this->template->assign("items",$items); + $this->template->assign("galalist",$galalist); + $this->template->assign("allylist",$allylist); + $this->template->assign("grouplist",$grouplist); + $this->show('user_add_form',"Benutzer hinzufügen"); + } + /** + \brief User löschen + + Löscht einen User aus dem TC + */ + function User_delete() { + #check rights + $rank = $this->userdata['rights']['useredit']['rank']; + if (!$rank){ + #no permission + $this->_header("","no permission"); + } + $data = $_SESSION['steps']; + #information message, step 2 + if ($data['deleteuser']) { + #save step + unset($data['deleteuser']); + $_SESSION['steps'] = $data; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['title'] = "Benutzer löschen"; + $this->forms['information']['message'] = "Benutzer erfolgreich gelöscht"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Benutzer löschen"); + } + $id = param_num("id"); + if (!$id) $this->_header(); + $return = getUserByID($id); + if (!$return) $this->_header(); + #check rights + if (($rank > 1 && $this->userdata['aid'] != $return['aid']) || + ($rank > 2 && $this->userdata['gala'] != $return['gala'])){ + #no permission + $this->_header("","no permission"); + } + #deleteuser, send + if ($_REQUEST['send']) { + if ($_REQUEST['yes_x']) { + addToLogfile("User ".$return['nick']." gelöscht","Admin",$this->userdata['uid']); + deleteUser($return['uid']); + #save step + $data['deleteuser'] = 1; + $_SESSION['steps'] = $data; + $this->_header("admin.php?action=deleteuser&send"); + } else { + $this->_header(); + } + } else { + $this->forms['information']['url'] = "admin.php?id=".$return['uid']; + $this->forms['information']['action'] = "deleteuser"; + $this->forms['information']['title'] = "Benutzer löschen"; + $this->forms['information']['message'] = "Benutzer ".$return['nick']." (".$return['tag'].") löschen ?"; + if ($return['uid'] == $this->userdata['uid']) { + $this->forms['information']['message'] .= " +

WARNUNG!!
+ Sie sind im Begriff sich selbst zu löschen!
+ Sie können sich danach nicht mehr einloggen!
+ "; + } + $this->forms['information']['style'] = "red"; + $this->show('message_question', "Benutzer löschen"); + } + } + /** + \brief Gruppe löschen + + Löscht eine Gruppe. + */ + function Group_delete() { + if (!$this->userdata['rights']['groupedit']) { + #no permission + $this->_header("","no permission"); + } + $data = $_SESSION['steps']; + #information message, step 2 + if ($data['deletegroup']) { + #save step + unset($data['deletegroup']); + $_SESSION['steps'] = $data; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['title'] = "Gruppe löschen"; + $this->forms['information']['message'] = "Gruppe erfolgreich gelöscht"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Gruppe löschen"); + } + $id = param_num("id"); + if (!$id) $this->_header("","id fehlt"); + $return = getGroup($id); + if (!$return) $this->_header("","ungültige Gruppe"); + #deletegroup, send + if ($_REQUEST['send']) { + if ($_REQUEST['yes_x']) { + addToLogfile("Gruppe ".$return['name']." gelöscht","Admin",$this->userdata['uid']); + deletegroup($return['gid']); + #save step + $data['deletegroup'] = 1; + $_SESSION['steps'] = $data; + $this->_header("admin.php?action=deletegroup&send"); + } else { + $this->_header(); + } + } else { + $this->forms['information']['url'] = "admin.php?id=".$return['gid']; + $this->forms['information']['action'] = "deletegroup"; + $this->forms['information']['title'] = "Gruppe löschen"; + $this->forms['information']['message'] = "Gruppe ".$return['name']." löschen ?"; + if ($return['gid'] == $this->userdata['gid']) { + $this->forms['information']['message'] .= " +

WARNUNG!!
+ Sie sind im Begriff ihre eigene Gruppe zu löschen,
+ Sie könnten dadurch wichtige Rechte unwiederbringlich verlieren!
+ "; + } + $this->forms['information']['style'] = "red"; + $this->show('message_question', "Gruppe löschen"); + } + } + /** + \brief Gruppenrechte anzeigen + + Zeigt die Rechte der Gruppen in einer Übersicht an. + */ + function Group_rights() { + if (!$this->userdata['rights']['groupedit']) { + #no permission + $this->_header("","no permission"); + } + $this->template->assign("rank1",listGroupsbyRank(1)); + $this->template->assign("rank2",listGroupsbyRank(2)); + $this->template->assign("rank3",listGroupsbyRank(3)); + $this->show('group_rights',"Gruppenrechte"); + } + /** + * Ändert die rechte eienr Gruppe + */ + function Group_rights_edit() { + if (!$this->userdata['rights']['groupedit']) { + #no permission + $this->_header("","no permission"); + } + $rank = param_num("rank",1); + $gid = param_num("id"); + $grouplist = getGroupList(); + if (!$grouplist) $this->_header("","Keine Gruppen vorhanden"); + if ($gid) { + $hasfound = false; + for($i=0;$i < count($grouplist);$i++){ + if ($gid == $grouplist[$i]['gid']) { + $hasfound = true; + $grouplist[$i]['selected'] = "selected"; + break; + } + } + if (!$hasfound) $this->_header("","Ungültige gid"); + } else { + $grouplist[0]['selected'] = "selected"; + $gid = $grouplist[0]['gid']; + } + $rightslist = listRightsbyGroup($gid); + if (!$rightslist) $this->_header("","Keine Rechte vorhanden"); + #formular abgeschickt + if ($_POST{'send'} && $_POST['next_x']) { + for($i=0;$i < count($rightslist);$i++){ + $right = &$rightslist[$i]; + #nicht gesetzt und maxlevel überschritten + if ($rank > $right['maxrank'] && !$right['isset']) { + unset($rightslist[$i]['rid']); + continue; + } + if ($right['isset'] && $right['rank'] < $rank) { + $right['disabled'] = "disabled"; + $right['vererbt'] = "(vererbt)"; + if ($right['isset']) { + $right['isset'] = "checked"; + } else { + $right['notset'] = "checked"; + unset($right['isset']); + } + continue; + } + if ($_POST["r_".$right['rid']]) { + $right['isset'] = "checked"; + $ids[] = $right['rid']; + } else { + $right['notset'] = "checked"; + unset($right['isset']); + } + } + updateRights($gid,$rank,$ids); + } else { + for($i=0;$i < count($rightslist);$i++){ + $right = &$rightslist[$i]; + #nicht gesetzt und maxlevel überschritten + if ($rank > $right['maxrank'] && !$right['isset']) { + unset($rightslist[$i]['rid']); +# for($j=$i;$j < count($rightslist)-1;$j++){ +# $rightslist[$j]= $rightslist[$j+1]; +# } + continue; + } + if ($right['isset'] && $right['rank'] < $rank) { + $right['disabled'] = "disabled"; + $right['vererbt'] = "(vererbt)"; + } + if ($right['isset'] && $right['rank'] <= $rank) { + $right['isset'] = "checked"; + } else { + $right['notset'] = "checked"; + unset($right['isset']); + } + } + } + switch ($rank) { + case 1: $ebene = "(Global)"; + break; + case 2: $ebene = "(Allianzebene)"; + break; + case 3: $ebene = "(Galaxieebene)"; + break; + } +# for($i=0;$i < count($rightslist);$i++){ +# echo "rid: ".$rightslist[$i]['rid']."
"; +# echo "isset: ".$rightslist[$i]['isset']."
"; +# echo "rank: ".$rightslist[$i]['rank']."
"; +# echo "descr: ".$rightslist[$i]['descr']."
"; +# } + $this->template->assign("ebene",$ebene); + $this->template->assign("grouplist",$grouplist); + $this->template->assign("rightslist",$rightslist); + $this->template->assign("rank",$rank); + $this->template->assign("url","admin.php"); + $this->template->assign("action","editgrouprights"); + $this->show('group_editrights',"Gruppenrechte bearbeiten"); + } + /** + \brief Allianzen anzeigen + + Listet die Allianzen des TCs auf + */ + function Ally_list() { + #check rights + if (!$this->_checkUserRights(array("addally","editally","deleteally"))){ + #no permission + $this->_header("","no permission"); + } + $allylistfilter = $_SESSION['allylistfilter']; + $page = param_num("page",1); + $rows = 6; + if (($_REQUEST['sort'] && $_REQUEST['order']) || !$allylistfilter) { + $sort = trim($_REQUEST['sort']); + $order = trim($_REQUEST['order']); + if ($sort != 'name' && $sort != 'tag' && $sort != 'member') $sort = 'tag'; + if ($order != "asc" && $order != "desc") $order = "asc"; + $allylistfilter['sort'] = $sort; + $allylistfilter['order'] = $order; + $_SESSION['allylistfilter'] = $allylistfilter; + } + $this->forms['list'][$allylistfilter['sort']][$allylistfilter['order']] = '_active'; + $allylist = listAllys($allylistfilter,&$pages,&$page,$rows); + $this->forms['list']['pages'] = showPageBar($page,$pages,"admin.php?action=ally","page","menu"); + $this->template->assign("allylist",$allylist); + $this->show('ally_list',"Allianzen"); + } + /** + \brief Allianzinfos + + Zeigt Informationen zu einer Allianz an + */ + function Ally_details() { + #check rights + if (!$this->_checkUserRights(array("addally","editally","deleteally"))){ + #no permission + $this->_header("","no permission"); + } + $id = param_num("id"); + if (!$id) $this->_header("","Fehlende allyid!"); + $ally = getAlly($id); + if (!$ally) $this->_header("","Ungültige allyid!"); + $ally[id]= $id; + if ($ally['url']) $ally['url'] = formaturl($ally['url']); + #can edit + if ($this->userdata['rights']['editally']['rank'] == 1 || + ($this->userdata['rights']['editally']['rank'] == 2 && + $this->userdata['aid'] == $ally['aid'])) + { + $this->template->assign("editlink","admin.php?action=editally&id=$id"); + } + #can delete + if ($this->userdata['rights']['deleteally']['rank'] == 1 || + ($this->userdata['rights']['deleteally']['rank'] == 2 && + $this->userdata['aid'] == $ally['aid'])) + { + $this->template->assign("deletelink","admin.php?action=deleteally&id=$id"); + } + $this->template->assign("ally",$ally); + $this->show('ally_details',"Allianzdetails"); + } + /** + \brief Allianz hinzufügen + + Fügt eine Allianz hinzu + */ + function Ally_add() { + #check rgihts + if ($this->userdata['rights']['addally']['rank'] != 1) + { + #no permission + $this->_header("","no permission"); + } + $data = $_SESSION['steps']; + #information message, step 2 + if ($data['addally']) { + $id = param_num("id"); + if ($id) { + $return = getAlly($id); + } + if (!$return) $this->_header(); + #save step + unset($data['addally']); + $_SESSION['steps'] = $data; + $this->forms['information']['action'] = "allydetails"; + $this->forms['information']['url'] = "admin.php?action=allydetails&id=".$return['aid']."&force"; + $this->forms['information']['title'] = "Allianz hinzufügen"; + $this->forms['information']['message'] = "Allianz ".$return['name']." hinzugefügt"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Allianz hinzufügen"); + } + #formular send + if ($_REQUEST['send']) { + $name = param_str("name",true); + $tag = param_str("tag",true); + $irc = param_str("irc",true); + $url = param_str("url",true); + $descr = param_str("descr",true); + $errors = false; + #check if empty + if (!$name) { + $errors[] = "Name darf nicht leer sein!"; + $items['name']['class'] = '_error'; + } + if (!$tag) { + $errors[] = "Tag darf nicht leer sein!"; + $items['tag']['class'] = '_error'; + } + if (!$errors && getAllyByTag($tag)) { + $errors[] = "Allianz mit diesem Tag existiert bereits!"; + $items['tag']['class'] = '_error'; + } + if (!$errors) { + #save step + $data['addally'] = 1; + $_SESSION['steps'] = $data; + $id = addAlly($name,$tag,$descr,$url,$irc); + if ($id) { + addToLogfile("Allianz ".$name." hinzugefügt","Admin",$this->userdata['uid']); + $this->_header("admin.php?action=addally&id=".$id."&send"); + } + } else { + $items['descr']['value'] = $descr; + $items['tag']['value'] = $tag; + $items['name']['value'] = $name; + $items['irc']['value'] = $irc; + $items['url']['value'] = $url; + $this->template->assign("items",$items); + $this->template->assign("errors",$errors); + } + } + $this->show('ally_add',"Allianz hinzufügen"); + } + /** + \brief Allianz bearbeiten + + Ändert die Daten einer Allianz + */ + function Ally_edit() { + $page = param_num("page",1); + $data = $_SESSION['steps']; + $id = param_num("id"); + if ($id) { + $return = getAlly($id); + } + if (!$return) $this->_header("","Ungültige oder fehlende Allyid!"); + #check rgihts + if ($this->userdata['rights']['editally']['rank'] != 1 && + ($this->userdata['rights']['editally']['rank'] != 2 || + $this->userdata['aid'] != $id)) + { + #no permission + $this->_header("","no permission"); + } + #information message, step 2 + if ($data['editally']) { + #save step + unset($data['editally']); + $_SESSION['steps'] = $data; + $this->forms['information']['action'] = "allydetails"; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['title'] = "Allianz bearbeiten"; + $this->forms['information']['message'] = "Daten der Allianz ".$return['name']." geändert"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Allianz bearbeiten"); + } + #formular send + if ($_REQUEST['send']) { + $name = param_str("name",true); + $tag = param_str("tag",true); + $irc = param_str("irc",true); + $url = param_str("url",true); + $descr = param_str("descr",true); + $errors = false; + #check if empty + if (!$name) { + $errors[] = "Name darf nicht leer sein!"; + $items['name']['class'] = '_error'; + } + if (!$tag) { + $errors[] = "Tag darf nicht leer sein!"; + $items['tag']['class'] = '_error'; + } + if (!$errors && $tag != $return['tag'] && getAllyByTag($tag)) { + $errors[] = "Allianz mit diesem Tag existiert bereits!"; + $items['tag']['class'] = '_error'; + } + if (!$errors) { + #save step + $data['editally'] = 1; + $_SESSION['steps'] = $data; + updateAlly($id,$name,$tag,$descr,$url,$irc); + addToLogfile("Allianz ".$name." bearbeitet","Admin",$this->userdata['uid']); + $this->_header("admin.php?action=editally&id=".$id."&send"); + } else { + $items['descr']['value'] = $descr; + $items['tag']['value'] = $tag; + $items['name']['value'] = $name; + $items['irc']['value'] = $irc; + $items['url']['value'] = $url; + $this->template->assign("errors",$errors); + } + } else { + $items['descr']['value'] = $return['descr']; + $items['tag']['value'] = $return['tag']; + $items['name']['value'] = $return['name']; + $items['irc']['value'] = $return['irc']; + $items['url']['value'] = $return['url']; + } + $this->template->assign("id",$id); + $this->template->assign("items",$items); + $this->show('ally_edit',"Allianz bearbeiten"); + } + /** + \brief Galaxie hinzufügen + + Fügt eine Galaxie hinzu. + */ + function Galaxy_add() { + #check rights + $rank = $this->userdata['rights']['addgala']['rank']; + if ($rank != 1 && $rank != 2){ + #no permission + $this->_header("","no permission"); + } + $page = param_num("page",1); + $data = $_SESSION['steps']; + #information message, step 2 + if ($data['addgala']) { + $id = param_num("id"); + if ($id) { + $return = getGala($id); + } + if (!$return) $this->_header(); + #save step + unset($data['addgala']); + $_SESSION['steps'] = $data; + $this->forms['information']['action'] = "galadetails"; + $this->forms['information']['url'] = "admin.php?id=".$return['gala']."&force"; + $this->forms['information']['title'] = "Galaxie hinzufügen"; + $this->forms['information']['message'] = "Galaxie ".$return['gala']." (".$return['tag'].") hinzugefügt"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Galaxie hinzufügen"); + } + if ($rank == 1) { + #global + $allylist = getAllyList(); + } else { + #allianz + $this->template->assign("ally",$this->userdata['tag']); + } + $this->template->assign("rank",$rank); + #formular send + if ($_REQUEST['send']) { + $gala = param_num("gala"); + $errors = false; + #check if empty + if (!$gala) { + $errors[] = "Galaxie darf nicht leer sein!"; + $items['gala']['class'] = '_error'; + } + if (!$errors && getGala($gala)) { + $errors[] = "Galaxie existiert bereits!"; + $items['gala']['class'] = '_error'; + } + if ($rank == 1) { + $allyid = param_num("allyid",true); + if ($allyid){ + for($i=0;$i < count($allylist);$i++){ + if ($allylist[$i]['aid'] == $allyid) { + $ally = &$allylist[$i]; + $ally['selected'] = "selected"; + break; + } + } + } + if (!$ally) $this->_header("","Ungültige oder fehlende Allyid"); + } else { + $allyid = $this->userdata['aid']; + } + if (!$errors) { + #save step + $data['addgala'] = 1; + $_SESSION['steps'] = $data; + addGala($gala,$allyid); + addToLogfile("Galaxie ".$gala." hinzugefügt","Admin",$this->userdata['uid']); + $this->_header("admin.php?action=addgala&id=".$gala."&send"); + } else { + $items['gala']['value'] = $gala; + $this->template->assign("items",$items); + $this->template->assign("errors",$errors); + } + } + $this->template->assign("allylist",$allylist); + $this->show('gala_add',"Galaxie hinzufügen"); + } + /** + \brief Galaxien anzeigen + + Listet die Galaxien auf, nach Allianzen sortiert + je nach Rechten des Users. + */ + function Galaxy_list() { + #check rights + $rank = $this->_getMinRightRank(array("addgala","editgala","deletegala")); + if (!$rank){ + #no permission + $this->_header("","no permission"); + } + $galaxylistfilter = $_SESSION['galaxylistfilter']; + $page = param_num("page",1); + $rows = 12; + #allianzebene & galaxieebene + if ($rank > 1) { + $galaxylistfilter['ally'] = $this->userdata['aid']; + } + if (($_REQUEST['sort'] && $_REQUEST['order']) || !$galaxylistfilter) { + $sort = trim($_REQUEST['sort']); + $order = trim($_REQUEST['order']); + if ($sort != 'gala' && $sort != 'tag' && $sort != 'member') $sort = 'gala'; + if ($order != "asc" && $order != "desc") $order = "asc"; + $galaxylistfilter['sort'] = $sort; + $galaxylistfilter['order'] = $order; + $_SESSION['galaxylistfilter'] = $galaxylistfilter; + } + $this->forms['list'][$galaxylistfilter['sort']][$galaxylistfilter['order']] = '_active'; + $galaxylist = listGalaxys($galaxylistfilter,&$pages,&$page,$rows); + $this->forms['list']['pages'] = showPageBar($page,$pages,"admin.php?action=galaxy","page","menu"); + $this->template->assign("galaxylist",$galaxylist); + $this->show('gala_list',"Galaxien"); + } + /** + \brief Galaxieinformationen + + Zeigt Informationen zu einer Galaxie + */ + function Galaxy_details() { + #check rights + $rank = $this->_getMinRightRank(array("addgala","editgala","deletegala")); + if (!$rank){ + #no permission + $this->_header("","no permission"); + } + $id = param_num("id"); + if (!$id) $this->_header("","Fehlende galaid!"); + $galaxy = getGala($id); + if (!$galaxy) $this->_header("","Ungültige galaid!"); + #allianz & galaxieebene + if ($rank > 1 && $galaxy['aid'] != $this->userdata['aid']) { + #no permission + $this->_header("","no permission"); + } + if ($this->userdata['rights']['editgala']['rank'] == 1 || + ($this->userdata['rights']['editgala']['rank'] == 2 && + $this->userdata['aid'] == $galaxy['aid']) || + ($this->userdata['rights']['editgala']['rank'] == 3 && + $this->userdata['gala'] == $galaxy['gala'])) + { + $this->template->assign("editlink","admin.php?action=editgala&id=$id"); + } + $this->template->assign("searchlink","admin.php"); + if ($this->userdata['rights']['deletegala']['rank'] == 1 || + ($this->userdata['rights']['deletegala']['rank'] == 2 && + $this->userdata['aid'] == $galaxy['aid'])) + { + $this->template->assign("deletelink","admin.php?action=deletegala&id=$id"); + } + $this->template->assign("galaxy",$galaxy); + $this->show('gala_details',"Galaxiedetails"); + } + /** + \brief Galaxie hinzugügen + + Fügt eine Galaxie hinzu + */ + function Galaxy_edit() { + $page = param_num("page",1); + $data = $_SESSION['steps']; + $id = param_num("id"); + if ($id) { + $return = getGala($id); + } + if (!$return) $this->_header("","ungültige id"); + #check rights + $rank = $this->userdata['rights']['editgala']['rank']; + if (!$rank || + ($rank > 1 && $return['aid'] != $this->userdata['aid']) || + ($rank > 2 && $return['gala'] != $this->userdata['gala'])){ + #no permission + $this->_header("","no permission"); + } + #information message, step 2 + if ($data['editgala']) { + #save step + unset($data['editgala']); + $_SESSION['steps'] = $data; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['title'] = "Galaxie bearbeiten"; + $this->forms['information']['message'] = "Galaxie ".$return['gala']." bearbeitet"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Galaxie bearbeitet"); + } + if ($rank > 1) { + #allianz + $this->template->assign("ally",$this->userdata['tag']); + } else { + $allylist = getAllyList(); + } + $this->template->assign("rank",$rank); + #formular send + if ($_REQUEST['send']) { + $gala = param_num("gala"); + $errors = false; + #check if empty + if (!$gala) { + $errors[] = "Galaxie darf nicht leer sein!"; + $items['gala']['class'] = '_error'; + } + if (!$errors && $return['gala'] != $gala && getGala($gala)) { + $errors[] = "Galaxie existiert bereits!"; + $items['gala']['class'] = '_error'; + } + if ($rank == 1) { + $allyid = param_num("allyid",true); + if ($allyid){ + for($i=0;$i < count($allylist);$i++){ + if ($allylist[$i]['aid'] == $allyid) { + $ally = &$allylist[$i]; + $ally['selected'] = "selected"; + break; + } + } + } + if (!$ally) $this->_header("","Ungültige oder fehlende Allyid"); + } else { + $allyid = $this->userdata['aid']; + } + if (!$errors) { + #save step + $data['editgala'] = 1; + $_SESSION['steps'] = $data; + updateGala($id,$gala,$allyid); + addToLogfile("Galaxie ".$gala." bearbeitet","Admin",$this->userdata['uid']); + $this->_header("admin.php?action=editgala&id=".$gala."&send"); + } else { + $items['gala']['value'] = $gala; + $this->template->assign("errors",$errors); + } + } else { + $items['gala']['value'] = $return['gala']; + for($i=0;$i < count($allylist);$i++){ + if ($allylist[$i]['aid'] == $return['aid']) { + $ally = &$allylist[$i]; + $ally['selected'] = "selected"; + break; + } + } + } + $this->template->assign("items",$items); + $this->template->assign("id",$id); + $this->template->assign("allylist",$allylist); + $this->show('gala_edit',"Galaxie bearbeiten"); + } + /** + \brief Allianz löschen + + Löscht eine Allianz mit allen Mitgliedern und Galaxien + */ + function Ally_delete() { + #check rgihts + if ($this->userdata['rights']['deleteally']['rank'] != 1) + { + #no permission + $this->_header("","no permission"); + } + $data = $_SESSION['steps']; + #information message, step 2 + if ($data['deleteally']) { + #save step + unset($data['deleteally']); + $_SESSION['steps'] = $data; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['title'] = "Allianz löschen"; + $this->forms['information']['message'] = "Allianz erfolgreich gelöscht"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Allianz löschen"); + } + $id = param_num("id"); + if (!$id) $this->_header(); + $return = getAlly($id); + if (!$return) $this->_header(); + #deleteally, send + if ($_REQUEST['send']) { + if ($_REQUEST['yes_x']) { + addToLogfile("Allianz ".$return['name']." gelöscht","Admin",$this->userdata['uid']); + deleteAlly($return['aid']); + #save step + $data['deleteally'] = 1; + $_SESSION['steps'] = $data; + $this->_header("admin.php?action=deleteally&send"); + } else { + $this->_header(); + } + } else { + $this->forms['information']['url'] = "admin.php?id=".$return['aid']; + $this->forms['information']['action'] = "deleteally"; + $this->forms['information']['title'] = "Allianz löschen"; + $this->forms['information']['message'] = "Allianz ".$return['name']." (".$return['tag'].") löschen ?"; + if ($return['galas']) { + if ($return['galas'] == 1) { + $this->forms['information']['message'] .= " +

".$return['galas']." Galaxie wird mitgelöscht."; + } else { + $this->forms['information']['message'] .= " +

".$return['galas']." Galaxien werden mitgelöscht. + "; + } + if ($return['member']) { + if ($return['member'] == 1) { + $s = "wird"; + } else { + $s = "werden"; + } + $this->forms['information']['message'] .= " +
Es $s ".$return['member']." User gelöscht ! + "; + } + } + if ($return['aid'] == $this->userdata['aid']) { + $this->forms['information']['message'] .= " +

WARNUNG!!
+ Sie sind im Begriff ihre eigene Allianz (und damit sich selbst) zu löschen,
+ Sie können sich danach nicht mehr einloggen!
+ "; + } + $this->forms['information']['style'] = "red"; + $this->show('message_question', "Allianz löschen"); + } + } + /** + \brief Galaxie löschen + + Löscht eine Galaxie + */ + function Galaxy_delete() { + $data = $_SESSION['steps']; + #information message, step 2 + if ($data['deletegala']) { + #save step + unset($data['deletegala']); + $_SESSION['steps'] = $data; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['title'] = "Galaxie löschen"; + $this->forms['information']['message'] = "Galaxie erfolgreich gelöscht"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Galaxie löschen"); + } + $id = param_num("id"); + if (!$id) $this->_header(); + $return = getGala($id); + if (!$return) $this->_header(); + #check rights + $rank = $this->userdata['rights']['deletegala']['rank']; + if (!$rank || ($rank > 2) || + ($rank == 2 && $return['aid'] != $this->userdata['aid'])){ + #no permission + $this->_header("","no permission"); + } + #deletegala, send + if ($_REQUEST['send']) { + if ($_REQUEST['yes_x']) { + addToLogfile("Galaxie ".$return['gala']." gelöscht","Admin",$this->userdata['uid']); + deletegalaxy($return['gala']); + #save step + $data['deletegala'] = 1; + $_SESSION['steps'] = $data; + $this->_header("admin.php?action=deletegala&send"); + } else { + $this->_header(); + } + } else { + $this->forms['information']['url'] = "admin.php?id=".$return['gala']; + $this->forms['information']['action'] = "deletegala"; + $this->forms['information']['title'] = "Galaxie löschen"; + $this->forms['information']['message'] = "Galaxie ".$return['gala']." (".$return['tag'].") löschen ?"; + if ($return['member']) { + if ($return['member'] == 1) { + $s = "wird"; + } else { + $s = "werden"; + } + $this->forms['information']['message'] .= " +

Es $s ".$return['member']." User gelöscht ! + "; + } + if ($return['gala'] == $this->userdata['gala']) { + $this->forms['information']['message'] .= " +

WARNUNG!!
+ Sie sind im Begriff ihre eigene Galaxie (und damit sich selbst) zu löschen,
+ Sie können sich danach nicht mehr einloggen!
+ "; + } + $this->forms['information']['style'] = "red"; + $this->show('message_question', "Galaxie löschen"); + } + } + /** + \brief IRCBots auflisten + + Listet die IRCBots auf + */ + function Bot_list() + { + if (!$this->userdata['rights']['bots']) { + #no permission + $this->_header("","no permission"); + } + $list = bot_list(); + for($i=0;$i < count($list);$i++){ + $list[$i]['firstauth'] = date("H:i d.m",$list[$i]['firstauth']); + if($list[$i]['lastauth']) $list[$i]['lastauth'] = date("H:i d.m",$list[$i]['lastauth']); + } + $this->template->assign('list',$list); + $this->show('bot_list','IRC Bots'); + } + + /** + \brief IRC bot hinzufügen + + Fügt einen IRC Bot hinzu + */ + function Bot_add() { + if (!$this->userdata['rights']['bots']) { + #no permission + $this->_header("","no permission"); + } + $data = $_SESSION['steps']; + #information message, step 2 + if ($data['addbot']) { + #save step + unset($data['addbot']); + $_SESSION['steps'] = $data; + $id = param_num("id"); + if (!$id) $this->_header(); + $bot = bot_get($id); + if (!$bot) $this->_header(); + $this->forms['information']['url'] = "admin.php?action=bots&force"; + $this->forms['information']['title'] = "IRC Bot hinzufügen"; + $this->forms['information']['message'] = "Bot '".$bot['name']."' hinzugefügt"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "IRC Bot hinzufügen"); + } + if ($_REQUEST['send']) { + $name = param_str("name",true); + $login = param_str("login",true); + $password = param_str("password",true); + $soapurl = param_str("soapurl",true); + $host = param_str("host",true); + $errors = false; + #check if empty + if (!$name) { + $errors[] = "Name darf nicht leer sein!"; + $items['name']['class'] = '_error'; + } + if (!$login) { + $errors[] = "Login darf nicht leer sein!"; + $items['login']['class'] = '_error'; + } + if (!$password) { + $errors[] = "Passwort darf nicht leer sein!"; + $items['password']['class'] = '_error'; + } + if (!$soapurl){ + $errors[] = "Es muss eine Adresse für den SOAP Server angegeben werden!"; + $items['soapurl']['class'] = '_error'; + } + if (!$host){ + $items['host']['class'] = '_optional'; + } + if (!$errors && bot_get_bylogin($login,$password)){ + $errors[] = "Diese Login - Passwort Paarung ist bereits vergeben!"; + $items['login']['class'] = '_error'; + $items['password']['class'] = '_error'; + } + if (!$errors) { + #save step + $data['addbot'] = 1; + $_SESSION['steps'] = $data; + $id = bot_add($name,$login,$password,$soapurl,$host); + addToLogfile("IRC Bot ".$name." hinzugefügt","Bots",$this->userdata['uid']); + $this->_header("admin.php?action=addbot&id=$id&send"); + } else { + $items['login']['value'] = $login; + $items['password']['value'] = $password; + $items['name']['value'] = $name; + $items['host']['value'] = $host; + $items['soapurl']['value'] = $soapurl; + $this->template->assign("errors",$errors); + } + } else { + $items['host']['class'] = '_optional'; + } + $this->template->assign("items",$items); + $this->show('bot_add',"IRC Bot hinzufügen"); + } + /** + \brief IRC bot bearbeiten + + Ändert die Daten von einem IRC Bot + */ + function Bot_edit() { + if (!$this->userdata['rights']['bots']) { + #no permission + $this->_header("","no permission"); + } + $id = param_num("id"); + if (!$id) $this->_header(); + $bot = bot_get($id); + if (!$bot) $this->_header(); + $data = $_SESSION['steps']; + #information message, step 2 + if ($data['editbot']) { + #save step + unset($data['editbot']); + $_SESSION['steps'] = $data; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['title'] = "IRC Bot bearbeiten"; + $this->forms['information']['message'] = "Bot '".$bot['name']."' bearbeitet"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "IRC Bot bearbeiten"); + } + if ($_REQUEST['send']) { + $name = param_str("name",true); + $login = param_str("login",true); + $password = param_str("password",true); + $soapurl = param_str("soapurl",true); + $host = param_str("host",true); + $errors = false; + #check if empty + if (!$name) { + $errors[] = "Name darf nicht leer sein!"; + $items['name']['class'] = '_error'; + } + if (!$login) { + $errors[] = "Login darf nicht leer sein!"; + $items['login']['class'] = '_error'; + } + if (!$password) { + $errors[] = "Passwort darf nicht leer sein!"; + $items['password']['class'] = '_error'; + } + if (!$soapurl){ + $errors[] = "Es muss eine Adresse für den SOAP Server angegeben werden!"; + $items['soapurl']['class'] = '_error'; + } + if (!$host){ + $items['host']['class'] = '_optional'; + } + if (!$errors && ($login != $bot['login'] || $password != $bot['password']) && bot_get_bylogin($login,$password)){ + $errors[] = "Diese Login - Passwort Paarung ist bereits vergeben!"; + $items['login']['class'] = '_error'; + $items['password']['class'] = '_error'; + } + if (!$errors) { + #save step + $data['editbot'] = 1; + $_SESSION['steps'] = $data; + bot_update($id,$name,$login,$password,$soapurl,$host); + addToLogfile("IRC Bot ".$bot['name']." bearbeitet","Bots",$this->userdata['uid']); + $this->_header("admin.php?action=editbot&id=$id&send"); + } else { + $items['login']['value'] = $login; + $items['password']['value'] = $password; + $items['name']['value'] = $name; + $items['host']['value'] = $host; + $items['soapurl']['value'] = $soapurl; + $this->template->assign("errors",$errors); + } + } else { + $items['login']['value'] = $bot['login']; + $items['password']['value'] = $bot['password']; + $items['name']['value'] = $bot['name']; + $items['host']['value'] = $bot['host']; + $items['soapurl']['value'] = $bot['soapurl']; + if (!$bot['host']) $items['host']['class'] = '_optional'; + } + $this->template->assign("id",$id); + $this->template->assign("items",$items); + $this->show('bot_edit',"IRC Bot bearbeiten"); + } + /** + \brief IRC bot löschen + + Löscht einen IRC Bot + */ + function Bot_delete() { + if (!$this->userdata['rights']['bots']) { + #no permission + $this->_header("","no permission"); + } + $data = $_SESSION['steps']; + #information message, step 2 + if ($data['deletebot']) { + #save step + unset($data['deletebot']); + $_SESSION['steps'] = $data; + $name = param_str("name"); + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['title'] = "IRC Bot löschen"; + $this->forms['information']['message'] = "Bot '$name' erfolgreich gelöscht"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "IRC Bot löschen"); + } + $id = param_num("id"); + if (!$id) $this->_header(); + $bot = bot_get($id); + if (!$bot) $this->_header(); + #deletenews, send + if ($_REQUEST['send']) { + if ($_REQUEST['yes_x']) { + addToLogfile("Bot ".$bot['name']." gelöscht","Bots", + $this->userdata['uid']); + bot_delete($id); + #save step + $data['deletebot'] = 1; + $_SESSION['steps'] = $data; + $this->_header("admin.php?action=deletebot&name=".$bot['name']."&send"); + } else { + $this->_header(); + } + } else { + $this->forms['information']['url'] = "admin.php?id=".$bot['botid']; + $this->forms['information']['action'] = "deletebot"; + $this->forms['information']['title'] = "IRC Bot löschen"; + $this->forms['information']['message'] = "Bot '".$bot['name']."' löschen ?"; + $this->forms['information']['style'] = "red"; + $this->show('message_question', "IRC Bot löschen"); + } + } +} +?> \ No newline at end of file diff --git a/src/classes/attplan.class.php b/src/classes/attplan.class.php new file mode 100644 index 0000000..455c482 --- /dev/null +++ b/src/classes/attplan.class.php @@ -0,0 +1,728 @@ +action]) { + eval("\$this->".$functions[$this->action].";"); + } + #default + $this->Attack_list(); + } + + # + # Attacklist + # + function Attack_list() { + $list = attack_list(); + foreach ($list as $item) { + if(!$item['isopen']) { + $item['scan_time'] = "Scans ab ".date("H:i",$item['access_time'])." Uhr ".date("d.m.Y",$item['access_time']); + } + + if($item['isopen'] || + $item['owner'] == $this->userdata['uid'] || + $this->_checkUserRights("attorga")) + { + $item['showlink'] = true; + } + if($item['isopen'] || + !$item['hidden'] || + $item['owner'] == $this->userdata['uid'] || + $this->_checkUserRights("attorga")) + { + if(!$items['list']) $items['list'] = array(); + $items['list'][] = $item; + } + } + $this->template->assign("items",$items); + $this->show("attplan_list","Attplaner"); + } + + function Attack_targets_add() { + $attid = param_num("id"); + if(!$attid) $this->_header(); + $attplan = attack_get($attid); + + //rightcheck + if($this->userdata['uid'] != $attplan['owner'] && + !$this->_checkUserRights("attorga")) + $this->_header(); + + $steps = $_SESSION['steps']; + if($steps['addtargets']) { + unset($_SESSION['steps']['addtargets']); + $sids = trim($_REQUEST['sids']); + if($sids){ + $sids = split(",",urldecode($sids)); + if(count($sids)){ + $message[] = "Folgende Ziele wurden hinzugefügt:
"; + $scans = getScansBySid($sids); + foreach($scans as $scan){ + $message[] = "(".$scan['gala'].":".$scan['pos'].")"; + } + $message[] = "
fehlende Ziele sind möglicherweise in diesem oder anderen Plänen schon vorhanden"; + } + } else { + $message[] = "Alle Ziele sind bereits in diesem oder anderen Attplänen vorhanden"; + } + $this->forms['information']['action'] =""; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['title'] = "Ziele hinzufügen"; + $this->forms['information']['message'] = join("
",$message); + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Ziele hinzufügen"); + } + + $form = new formContainer(); + $form->add(new formInput("galaxy_1","Galaxie","numeric",true,5)); + $form->add(new formInput("galaxy_2","Galaxie","numeric",true,5)); + $form->add(new formInput("galaxy_3","Galaxie","numeric",true,5)); + $form->add(new formInput("start_2","Start","numeric",true,5)); + $form->add(new formInput("end_2","Ende","numeric",true,5)); + $form->add(new formInput("pos_3","Position","numeric",true,5)); + $form->add(new formRadio("addtyp","Auswahltyp","numeric",array(1,2,3),3)); + + if($_POST['send']) { + $form->submit("addtyp"); + switch($form->get("addtyp")) { + case 1 : + $form->submit(array("galaxy_1")); + if(!$form->hasErrors()) { + $galaxy = $form->get("galaxy_1"); + $addtarget = array(1,2,3,4,5,6,7,8,9,10,11,12); + } + break; + case 2 : + $form->submit(array("galaxy_2","start_2","end_2")); + if(!$form->hasErrors() && $form->get("start_2") > $form->get("end_2")) { + $form->addError("die Startposition sollte niedriger sein als das Ende"); + $form->setError(array("start_2","end_2")); + } + if(!$form->hasErrors()) { + $galaxy = $form->get("galaxy_2"); + $start = $form->get("start_2"); + $end = $form->get("end_2"); + for($i=$start;$i <= $end;$i++) { + $addtarget[] = $i; + } + } + break; + default : + $form->submit(array("galaxy_3","pos_3")); + if(!$form->hasErrors()) { + $galaxy = $form->get("galaxy_3"); + $addtarget[] = $form->get("pos_3"); + } + break; + } + if(!$form->hasErrors()) { + $sid_list = targets_add($attid,$galaxy,$addtarget); + $steps['addtargets'] = 1; + $_SESSION['steps'] = $steps; + if(count($sid_list)){ + $sids = urlencode(join(",",$sid_list)); + } + $this->_header("attplan.php?action=addtargets&id=$attid&sids=$sids&send"); + } + } else { + $form->select("addtyp",1); + } + + $form->registerVars(&$this->template); + + $this->template->assign("attplan",$attplan); + + $this->show("attplan_targets_add","Ziele hinzufügen"); + } + + function Attack_targets() { + $attid = param_num("id"); + $page = param_num("page",1); + if(!$attid) $this->_header(); + $attplan = attack_get($attid); + + //rightcheck + if($this->userdata['uid'] != $attplan['owner'] && + !$this->_checkUserRights("attorga")) + $this->_header(); + + + $gala_list = attack_get_galalist($attid,&$pages,$page); + $pagebar = showPageBar($page,$pages,"attplan.php?action=targets&id=$attid","page","menu"); + + if(count($gala_list) < 5) { + $spacer['colspan'] = 5 - count($gala_list); + $spacer['width'] = $spacer['colspan']*20; + $this->template->assign("spacer",$spacer); + } + + $list = target_list(array("attid"=>$attid,"gala"=>$gala_list)); + $count = count($list); + $gala = ""; + for($i=0;$i<$count;$i++) { + if($list[$i]['gala'] != $gala){ + $gala = $list[$i]['gala']; + } + $targets[$gala][] = $list[$i]; + } + + $this->template->assign("pagebar",$pagebar); + $this->template->assign("targets",$targets); + $this->template->assign("attplan",$attplan); + $this->show("attplan_targets","Ziele festlegen"); + } + + function Attack_targets_delete() { + $attid = param_num("id"); + if(!$attid) $this->_header(); + $attplan = attack_get($attid); + + //rightcheck + if($this->userdata['uid'] != $attplan['owner'] && + !$this->_checkUserRights("attorga")) + $this->_header(); + + if($_SESSION['steps']['deletetargets']) { + unset($_SESSION['steps']['deletetargets']); + $this->forms['information']['action'] =""; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['title'] = "Ziele löschen"; + $this->forms['information']['message'] = "Angriffsziele wurden gelöscht!"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Ziele löschen"); + } + if ($_POST['send']) { + if ($_REQUEST['yes_x']) { + $sids = $_REQUEST['sids']; + if(empty($sids)) $this->_header(); + $sids = split(",",urldecode($sids)); + if(!count($sids)) $this->_header(); + targets_delete_bysid($sids); + #save step + $_SESSION['steps']['deletetargets'] = 1; + $this->_header("attplan.php?action=deletetargets&id=$attid&send"); + } else { + $this->_header(); + } + } else { + $sids = $_REQUEST['sids']; + if(empty($sids)) $this->_header(); + if(!is_array($sids)) { + $sids = split(",",urldecode($sids)); + } + if(!count($sids)) $this->_header(); + $scans = getScansBySid($sids); + foreach($scans as $scan){ + if($gala != $scan['gala']) { + if($gala) $message[$gala] = join(", ",$message[$gala]); + $gala = $scan['gala']; + } + $message[$gala][] = "(".$scan['gala'].":".$scan['pos'].") ".$scan['nick']; + } + if($gala) $message[$gala] = join(", ",$message[$gala]); + $this->forms['information']['url'] = "attplan.php?id=$attid&sids=".urlencode(join(",",$sids)); + $this->forms['information']['action'] = "deletetargets"; + $this->forms['information']['title'] = "Angriffsziele löschen"; + $this->forms['information']['message'] = " + ".$attplan{'title'}."

+ Folgende Ziele werden gelöscht:
".join("
",$message); + $this->forms['information']['style'] = "red"; + $this->show('message_question', "Angriffsziele löschen"); + } + } + + function Attack_atter_deleteall() { + $attid = param_num("id"); + if(!$attid) $this->_header(); + $attplan = attack_get($attid); + + $steps = $_SESSION['steps']; + + if($steps['deleteallatter']) { + unset($steps['deleteallatter']); + $_SESSION['steps'] = $steps; + $this->forms['information']['action'] =""; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['title'] = "alle Angreifer löschen"; + $this->forms['information']['message'] = "Angreifer wurden gelöscht!"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "alle Angreifer löschen"); + } + if ($_POST['send']) { + if ($_REQUEST['yes_x']) { + $sids = split(",",urldecode($_REQUEST['sids'])); + if(!count($sids)) $this->_header(); + atter_delete_bysid($attid,$sids); + #save step + $steps['deleteallatter'] = 1; + $_SESSION['steps'] = $steps; + $this->_header("attplan.php?action=deleteallatter&id=$attid&send"); + } else { + $this->_header(); + } + } else { + $sids = $_REQUEST['sids']; + if(empty($sids)) $this->_header(); + if(!is_array($sids)) { + $sids = split(",",urldecode($sids)); + } + if(!count($sids)) $this->_header(); + $scans = getScansBySid($sids); + foreach($scans as $scan){ + if($gala != $scan['gala']) { + if($gala) $message[$gala] = join(", ",$message[$gala]); + $gala = $scan['gala']; + } + $message[$gala][] = "(".$scan['gala'].":".$scan['pos'].") ".$scan['nick']; + } + if($gala) $message[$gala] = join(", ",$message[$gala]); + $this->forms['information']['url'] = "attplan.php?id=$attid&sids=".urlencode(join(",",$sids)); + $this->forms['information']['action'] = "deleteallatter"; + $this->forms['information']['title'] = "alle Angreifer löschen"; + $this->forms['information']['message'] = " + ".$attplan{'title'}."

+ zu folgenden Zielen werden die Angreifer gelöscht:
".join("
",$message); + $this->forms['information']['style'] = "red"; + $this->show('message_question', "alle Angreifer löschen"); + } + } + + function Attack_targets_close() { + $attid = param_num("id"); + if(!$attid) $this->_header(); + $attplan = attack_get($attid); + + //rightcheck + if($this->userdata['uid'] != $attplan['owner'] && + !$this->_checkUserRights("attorga")) + $this->_header(); + + + $steps = $_SESSION['steps']; + + if($steps['closetargets']) { + unset($steps['closetargets']); + $_SESSION['steps'] = $steps; + $this->forms['information']['action'] =""; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['title'] = "Ziele schliessen"; + $this->forms['information']['message'] = "Angriffsziele wurden als geschlossen markiert, es können sich keine weiteren Angreifer eintragen!"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Ziele schliessen"); + } + if ($_POST['send']) { + if ($_REQUEST['yes_x']) { + $sids = $_REQUEST['sids']; + if(empty($sids)) $this->_header(); + $sids = split(",",urldecode($sids)); + if(!count($sids)) $this->_header(); + targets_close($sids); + #save step + $steps['closetargets'] = 1; + $_SESSION['steps'] = $steps; + $this->_header("attplan.php?action=closetargets&id=$attid&send"); + } else { + $this->_header(); + } + } else { + $sids = $_REQUEST['sids']; + if(empty($sids)) $this->_header(); + if(!is_array($sids)) { + $sids = split(",",urldecode($sids)); + } + if(!count($sids)) $this->_header(); + $scans = getScansBySid($sids); + foreach($scans as $scan){ + if($gala != $scan['gala']) { + if($gala) $message[$gala] = join(", ",$message[$gala]); + $gala = $scan['gala']; + } + $message[$gala][] = "(".$scan['gala'].":".$scan['pos'].") ".$scan['nick']; + } + if($gala) $message[$gala] = join(", ",$message[$gala]); + $this->forms['information']['url'] = "attplan.php?id=$attid&sids=".urlencode(join(",",$sids)); + $this->forms['information']['action'] = "closetargets"; + $this->forms['information']['title'] = "Angriffsziele schliessen"; + $this->forms['information']['message'] = " + ".$attplan{'title'}."

+ Folgende Ziele werden als geschlossen markiert:
".join("
",$message); + $this->forms['information']['style'] = "red"; + $this->show('message_question', "Angriffsziele schliessen"); + } + } + + function Attack_targets_open() { + $attid = param_num("id"); + if(!$attid) $this->_header(); + $attplan = attack_get($attid); + + //rightcheck + if($this->userdata['uid'] != $attplan['owner'] && + !$this->_checkUserRights("attorga")) + $this->_header(); + + $steps = $_SESSION['steps']; + + if($steps['opentargets']) { + unset($steps['opentargets']); + $_SESSION['steps'] = $steps; + $this->forms['information']['action'] =""; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['title'] = "Ziele öffnen"; + $this->forms['information']['message'] = "Angriffsziele wurden als offen markiert, es können sich weitere Angreifer eintragen!"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Ziele öffnen"); + } + if ($_POST['send']) { + if ($_REQUEST['yes_x']) { + $sids = $_REQUEST['sids']; + if(empty($sids)) $this->_header(); + $sids = split(",",urldecode($sids)); + if(!count($sids)) $this->_header(); + targets_open($sids); + #save step + $steps['opentargets'] = 1; + $_SESSION['steps'] = $steps; + $this->_header("attplan.php?action=opentargets&id=$attid&send"); + } else { + $this->_header(); + } + } else { + $sids = $_REQUEST['sids']; + if(empty($sids)) $this->_header(); + if(!is_array($sids)) { + $sids = split(",",urldecode($sids)); + } + if(!count($sids)) $this->_header(); + $scans = getScansBySid($sids); + foreach($scans as $scan){ + if($gala != $scan['gala']) { + if($gala) $message[$gala] = join(", ",$message[$gala]); + $gala = $scan['gala']; + } + $message[$gala][] = "(".$scan['gala'].":".$scan['pos'].") ".$scan['nick']; + } + if($gala) $message[$gala] = join(", ",$message[$gala]); + $this->forms['information']['url'] = "attplan.php?id=$attid&sids=".urlencode(join(",",$sids)); + $this->forms['information']['action'] = "opentargets"; + $this->forms['information']['title'] = "Angriffsziele öffnen"; + $this->forms['information']['message'] = " + ".$attplan{'title'}."

+ Folgende Ziele werden für weitere Angreifer geöffnet:
".join("
",$message); + $this->forms['information']['style'] = "red"; + $this->show('message_question', "Angriffsziele öffnen"); + } + } + + function Attack_mytargets() { + $attplan['content'] = $this->template->fetch("attplan_content_mytargets.html"); + $this->template->assign("attplan",$attplan); + $this->show("attplan_view","Angriffsplan"); + } + + function Attack_tactic() { + $attplan['content'] = $this->template->fetch("attplan_content_tactic.html"); + $this->template->assign("attplan",$attplan); + $this->show("attplan_view","Angriffsplan"); + } + + function Attack_search() { + $attplan['content'] = $this->template->fetch("attplan_content_search.html"); + $this->template->assign("attplan",$attplan); + $this->show("attplan_view","Angriffsplan"); + } + + /** + * Scanansicht von einem Att + **/ + function Attack_view() { + if(!($attid = param_num("id")) || !($attplan = attack_get($attid))) $this->_header(); + $form = new formContainer(); + + $attplan['isadmin'] = $this->userdata['uid'] == $attplan['owner'] || + $this->_checkUserRights("attorga"); + + if(!$attplan['isopen'] && !$attplan['isadmin']) $this->_header(); + + $galalist = attack_gala_list($attid); + // ziele vorhanden ? + if($galalist) { + $list = array(); + foreach ($galalist as $item) { + $list[] = array("value" => $item['gala'],"title" => $item['gala']); + } + $form->add(new formSelectBox("gala","Galaxie","numeric",$list,false)); + + if($_POST['send'] && $_POST['subaction'] == "changegala") { + $form->submit(); + if(!$form->hasErrors()) $_SESSION['attplanfilter'][$attid]['gala'] = $form->get("gala"); + $gala = $form->get("gala"); + } else { + if($_SESSION['attplanfilter'][$attid]['gala']) { + $form->select("gala",$_SESSION['attplanfilter'][$attid]['gala']); + $gala = $_SESSION['attplanfilter'][$attid]['gala']; + } else { + $gala = $galalist[0]['gala']; + } + } + + $sids = target_list(array("gala" => $gala),"sid"); + $scanlist = listScans(array("sids" => $sids,"order"=>"asc","sort"=>"koords","hassektor" => true,"showattackscans" => true),&$pages,1,15); + + for ($i=0;$iuserdata['uid'] == $scanlist[$i]['uid'] || $this->_checkUserRights("attorga")) { + $scanlist[$i]['candelete'] = true; + } + if($this->userdata['uid'] == $scanlist[$i]['uid']) { + $scanlist[$i]['reserveclass'] = "green"; + } else { + $scanlist[$i]['reserveclass'] = "red"; + } + } else { + $scanlist[$i]['canreserve'] = true; + } + $scanlist[$i] = scan_format($scanlist[$i]); + } + + $this->template->assign("scanlist",$scanlist); + $this->template->assign("hastargets",true); + $this->template->assign("selectedgala",$gala); + } + + + $form->registerVars($this->template); + $this->template->assign("attplan",$attplan); + $this->template->assign("type","ziele"); + $this->show("attplan_view","Angriffsplan"); + } + + function Target_reserve() { + if (!($sid = param_num("id"))) $this->_header(); + + $reservation = getScanById($sid,true); + // gibts den att ? + if(!$reservation['attid'] || $reservation['closed']) $this->_header(); + // is noch offen ? + if(!$reservation['isopen'] && + !$this->_checkUserRights('attorga') + && $this->userdata['uid'] != $reservation['owner'] + ) $this->_header(); + if ($reservation['uid']) { + if ($reservation['uid'] == $this->userdata['uid']) { + $this->show_message("Reservierung","Ziel bereits von DIR reserviert",$this->backtracking->backlink(),"red",array("send" => 1)); + } else { + $this->show_message("Reservierung","Ziel bereits von jmd. reserviert",$this->backtracking->backlink(),"red",array("send" => 1)); + } + } + target_reserve($sid, $this->userdata['uid']); + $this->_header(); + } + + function Target_unreserve() { + if (!($sid = param_num("id"))) $this->_header(); + + $reservation = getScanById($sid,true); + // gibts den att ? + if(!$reservation['attid'] || !$reservation['uid'] || $reservation['closed']) $this->_header(); + //att is offen für reservierungen ? + if(!$reservation['isopen'] && + !$this->_checkUserRights('attorga') + && $this->userdata['uid'] != $reservation['owner'] + ) $this->_header(); + if ($reservation['uid'] == $this->userdata['uid'] || $this->_checkUserRights('attorga')) { + target_unreserve($sid); + } + $this->_header(); + } + + function Attack_add() { + + $data = $_SESSION['steps']; + if($data['addattack']) { + unset($_SESSION['steps']['addattack']); + $attid = param_num("id"); + if(!$attid) $this->_header(); + $this->forms['information']['action'] =""; + $this->forms['information']['url'] = "attplan.php?action=view&id=$attid"; + $this->forms['information']['title'] = "Angriffsplan erstellen"; + $this->forms['information']['message'] = "Angriffsplan wurde hinzugefügt"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Angriffsplan erstellen"); + } + $form = new formContainer(); + $form->add(new formInput("title","Titel","string",true,255)); + $form->add(new formInput("descr","Beschreibung","string",true,null,true)); + $form->add(new formInput("reserve_date","Datum für die Reservierung","date",false,40,true,"'(\d{1,2})\.(\d{1,2})\.(\d{2,4})'is")); + $form->add(new formInput("reserve_time","Startzeit für die Reservierung","time",false,40,true,"'(\d{1,2}):(\d{2})'is")); + $form->add(new formRadio("hidden","Plan verstecken","numeric",array(1,0))); + + if($_POST['send']) { + $form->submit(); + if(($form->get("reserve_date") && !$form->get("reserve_time")) || + (!$form->get("reserve_date") && $form->get("reserve_time")) + ) { + $form->setError("reserve_date"); + $form->setError("reserve_time"); + $form->addError("Datum und Uhrzeit für den Start der Reservierung müssen beide ausgefüllt sein"); + } + if(!$form->hasErrors()) { + if($form->get("reserve_date")) { + $date = $form->getregex("reserve_date"); + $time = $form->getregex("reserve_time"); + $reserve = mktime($time[1],$time[2],0,$date[2],$date[1],$date[3]); + } + $id = attack_add( + $form->get("title"), + $this->userdata['uid'], + $form->get("descr"), + $reserve, + $form->get("hidden") + ); + $_SESSION['steps']['addattack'] = 1; + $this->_header("attplan.php?action=add&id=$id&send"); + } + } else { + $form->select("hidden",0); + $form->set("reserve_date",date("d.m.Y")); + $form->set("reserve_time",date("H:i")); + } + $form->registerVars(&$this->template); + $this->show("attplan_add","Attplaner"); + } + + function Attack_edit() { + $attid = param_num("id"); + if(!$attid) $this->_header(); + $attplan = attack_get($attid); + if(empty($attplan))$this->_header(); + + //rightcheck + if($this->userdata['uid'] != $attplan['owner'] && + !$this->_checkUserRights("attorga")) + $this->_header(); + + if($_SESSION['steps']['editattack']) { + unset($_SESSION['steps']['editattack']); + $this->forms['information']['action'] =""; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['title'] = "Angriffsplan bearbeiten"; + $this->forms['information']['message'] = "Daten wurden erfolgreich geändert!"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Angriffsplan bearbeiten"); + } + $form = new formContainer(); + $form->add(new formInput("title","Titel","string",true,255)); + $form->add(new formInput("descr","Beschreibung","string",true,null,true)); + $form->add(new formInput("reserve_date","Datum für die Reservierung","date",false,40,true,"'(\d{1,2})\.(\d{1,2})\.(\d{2,4})'is")); + $form->add(new formInput("reserve_time","Startzeit für die Reservierung","time",false,40,true,"'(\d{1,2}):(\d{2})'is")); + $form->add(new formRadio("hidden","Plan verstecken","numeric",array(1,0))); + + if($_POST['send']) { + $form->submit(); + if(!$form->hasErrors()) { + if($form->get("reserve_date")) { + $date = $form->getregex("reserve_date"); + $time = $form->getregex("reserve_time"); + $reserve = mktime($time[1],$time[2],0,$date[2],$date[1],$date[3]); + } + attack_edit( + $attid, + $form->get("title"), + $form->get("descr"), + $reserve, + $form->get("hidden") + ); + $_SESSION['steps']['editattack'] = 1; + $this->_header("attplan.php?action=edit&id=$attid&send"); + } + } else { + $form->select("hidden",$attplan['hidden']); + $form->set("title",$attplan['title']); + $form->set("descr",$attplan['descr']); + $form->set("reserve_date",date("d.m.Y",$attplan['access_time'])); + $form->set("reserve_time",date("H:i",$attplan['access_time'])); + } + $form->registerVars(&$this->template); + $this->template->assign("attplan",$attplan); + $this->show("attplan_edit","Attplaner"); + } + + function Attack_delete() { + + if($_SESSION['steps']['deleteattack']) { + unset($_SESSION['steps']['deleteattack']); + $this->forms['information']['action'] =""; + $this->forms['information']['url'] = "attplan.php"; + $this->forms['information']['title'] = "Plan gelöscht"; + $this->forms['information']['message'] = "Plan wurde gelöscht"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Angriffsplan löschen"); + } + + $attid = param_num("id"); + if(!$attid) $this->_header(); + $attplan = attack_get($attid); + if(empty($attplan))$this->_header(); + + //rightcheck + if($this->userdata['uid'] != $attplan['owner'] && + !$this->_checkUserRights("attorga")) + $this->_header(); + + if($_POST['send']) { + if($_POST['yes_x']) { + attack_delete($attid); + $_SESSION['steps']['deleteattack'] = 1; + $this->_header("attplan.php?action=delete"); + } + $this->_header(); + } else { + $this->forms['information']['url'] = "attplan.php?id=$attid"; + $this->forms['information']['action'] = "delete"; + $this->forms['information']['title'] = "Angriffsplan löschen"; + $this->forms['information']['message'] = " + '".$attplan{'title'}."' komplett löschen ?"; + $this->forms['information']['style'] = "red"; + $this->show('message_question', "Angriffsplan löschen"); + } + } +} +?> \ No newline at end of file diff --git a/src/classes/backtracking.php b/src/classes/backtracking.php new file mode 100644 index 0000000..bb83e4d --- /dev/null +++ b/src/classes/backtracking.php @@ -0,0 +1,326 @@ +debug[] = $msg; + } + + + /** + * @return backtracking + * @param string $default Default Rücksprungadresse, index.php + * @param integer $buffer Grösse des Rücksprungbuffers + * @desc Konstruktor + */ + function backtracking(&$session,$default="index.php",$buffer = 10) { + + + $this->debug = array(); + $this->session = $session; + $this->buffer = $buffer; + $this->default = $default; + $this->execludes = array(); + } + + /** + * @return void + * @param unknown $params + * @desc mit Execlude können Urls mit bestimmten Parameter/werten vom tracking ausgeschlossen werden. + * Möglichkeiten: + * params(param => value) : parameter mit wert wird nicht getrackt + * params(param => "*") : parameter wird generell nicht getrackt, egal was fürn wert + * params(parameter => array()) : parameter mit den jeweiligen Werten im Array wird nicht getrackt + */ + function execlude($params) { + if(!$params || !is_array($params)) return; + $this->execludes = $params; + } + + /** + * @return void + * @desc Analysiert die aktuelle url und erstellt eine Rücksprungadresse + */ + function run() { + + $this->backlinks = $this->_get(); + + $backlink = urldecode($_REQUEST['backlink']); + $link = "http://".$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI']; +# if(preg_match("'^(?:(.*?\/)|)([^\/]*?)$'is",$link,$subs)) { +# $backlink = $subs[1].$backlink; +# } + $back = $_REQUEST['back']; + + $notrack = isset($_REQUEST['notrack']); + if(strcmp($link,"http://".$_SERVER['SERVER_NAME']."/") == 0) { + $this->_debugmsg("double: $link"); + } else { + if($backlink) {$this->_set($backlink);} + + if(isset($back)) { + //rücksprung + $this->_pop($link); + $this->_refresh(); + $this->backlink = $this->_generate_backlink(); + } else { + // formular abgeschickt, kein tracking + if(isset($_REQUEST['send'])) {$this->backlink = $this->_generate_backlink();return;} + // ausnahmen + if(!$notrack && count($this->execludes)) { + foreach ($this->execludes as $param => $value) { + if(is_array($value)) { + if($_REQUEST[$param] && in_array($_REQUEST[$param],$value)) { + $notrack = true; + break; + } + } elseif($value == "*") { + if(isset($_REQUEST[$param])) {$notrack = true;break;} + } else { + if($_REQUEST[$param] == $value) {$notrack = true;break;} + } + } + } + if($notrack == false) { + // neuer link + $this->_push($link); + $this->_refresh(); + $this->backlink = $this->_generate_backlink(); + } + } + } + if($notrack && !isset($back)) { + $this->backlink = $this->last(); + } + } + + /** + * @return void, false bei fehlschlag + * @param string $link + * @param integer $index + * @desc Ändert einen Link im stack + */ + function _set($link,$index=null) { + if(!$link) return false; + $backlinks_count = count($this->backlinks); + if($backlinks_count == 0) return false; + if(!$index || !is_numeric($index) || $index >= $backlinks_count || $index < 0) { + $index = $backlinks_count-1; + } + + if(($link = $this->_decode_url($link)) === false) return false; + + if($url['actual']['params'][$this->sessionname]) unset($url['actual']['params'][$this->sessionname]); + + $this->backlinks[$index] = urlencode($this->_encode_url($link)); + } + + /** + * @return array + * @desc Liefert den Trackingbuffer, muss überschrieben werden + * @protected + */ + function _get() { + $tracking = array(); + return $tracking; + } + + /** + * @return void + * @desc Sichert den aktuellen Stack, muss überschrieben werden + * @protected + */ + function _refresh() { + } + + /** + * @return unknown + * @param unknown $link + * @desc decodiert eine Url und liefert ein array mit server,params und ancer als felder zurück + */ + function _decode_url($link) { + $result = array(); + if(preg_match("/^([^\?&]*?)(?:\?([^\?#]*?)|)(?:#([^\?&#]*?)|)$/is",$link,$matches)) { + $result['server'] = $matches[1]; + if($matches[2]) { + foreach (split("&",$matches[2]) as $item) { + $param = split("=",$item); + if(strlen($param[0])) { + $result['params'][$param[0]] = $param[1]; + } + } + } + if($matches[3]) { + $result['ancer'] = $matches[3]; + } + } else { + return false; + } + return $result; + } + + /** + * @return string + * @param array $url + * @desc codiert eine voher decodierte url + */ + function _encode_url($url) { + $link = $url['server']; + if($url['params']) { + $params = array(); + foreach ($url['params'] as $key => $val) { + if(strlen($val)) { + $params[] = "$key=$val"; + } else { + $params[] = "$key"; + } + } + $link .= "?".join("&",$params); + } + if($url['ancer']) { + $link .= "#".$url['ancer']; + } + return $link; + } + + /** + * @return boolean + * @param array $params1 + * @param array $params2 + * @param array|string $param parameter, die beim vergleich nicht berücksichtigt werden sollen + * @desc Vergleicht 2 arrays mit parametern auf gleichniss + */ + function _diff_params($params1,$params2,$param=null) { + if($param) { + if(is_array($param)) { + foreach($param as $name) { + unset($params1[$name]); + unset($params2[$name]); + } + } else { + unset($params1[$param]); + unset($params2[$param]); + } + } + if(!$params1) $params1 = array(); + if(!$params2) $params2 = array(); + return (!array_diff_assoc($params1,$params2) && + !array_diff_assoc($params2,$params1)); + } + + /** + * @return void + * @param string $link + * @desc packt einen neuen Link auf den Stack + */ + function _push($link) { + + if(!$link) return false; + + $backlinks_count = count($this->backlinks); + + $url['actual'] = $this->_decode_url($link); + + unset($url['actual']['params']['backlink']); + unset($url['actual']['params'][$this->session['name']]); + + foreach ($_POST as $key => $val) { + if(is_array($val)) { + $url['actual']['params'][$key] = urlencode(join(",",$val)); + } elseif(isset($_POST[$key])) $url['actual']['params'][$key] = $val; + } + if($url['actual']['params'][$this->sessionname]) unset($url['actual']['params'][$this->sessionname]); + + if($backlinks_count > 0) { + $last = urldecode(end($this->backlinks)); + + $url['last'] = $this->_decode_url($last); + + $servercheck = $url['last']['server'] == $url['actual']['server']; + #$paramcheck = _diff_params($url['last']['params'],$url['actual']['params']); + $pagecheck = $this->_diff_params($url['last']['params'],$url['actual']['params'],"page"); + + if($servercheck && $pagecheck) { + $url['last']['params']['page'] = $url['actual']['params']['page']; + $this->backlinks[$backlinks_count-1] = urlencode($this->_encode_url($url['last'])); + return; + } + } + array_push($this->backlinks,urlencode($this->_encode_url($url['actual']))); + if($backlinks_count+1 > $this->buffer){ + array_shift($this->backlinks); + } + } + + /** + * @return void + * @param string $link + * @desc Rücksprung, entfernt den letzten Eintrag + */ + function _pop($link) { + if(count($this->backlinks) > 0) { + $link = $this->_decode_url($link); + $last = $this->_decode_url(urldecode(end($this->backlinks))); + $check = $this->_diff_params($link['params'],$last['params'],array("page",$this->session['name'],"back")); + if(!$check) { + array_pop($this->backlinks); + } + } + } + + /** + * @return string + * @desc Erzeugt die Rücksprungadresse + */ + function _generate_backlink() { + $backlink = $this->default; + $backlinks_count= count($this->backlinks); + if($backlinks_count > 1) { + $url = $this->_decode_url(urldecode($this->backlinks[$backlinks_count-2])); + $url['params']['back'] = ""; + $url['params'][$this->session['name']] = $this->session['id']; + $backlink = $this->_encode_url($url); + } + return $backlink; + } + + /** + * @return string + * @desc Liefert den letzten Eintrag im Buffer + */ + function last() { + $backlinks_count= count($this->backlinks); + if($backlinks_count > 0) { + return urldecode($this->backlinks[$backlinks_count-1]); + } else { + return $this->default; + } + } + + /** + * @return string + * @desc Gibt die Rücksprungadresse zurück + */ + function backlink() { + return $this->backlink; + } +} +?> \ No newline at end of file diff --git a/src/classes/form.handler.php b/src/classes/form.handler.php new file mode 100644 index 0000000..dac9044 --- /dev/null +++ b/src/classes/form.handler.php @@ -0,0 +1,609 @@ +name = $name; + $this->title = $title; + $this->onlypost = $onlypost; + $this->format = $format; + $this->classes = array("error" => "form_error", "optional" => "form_optional", "default" => "form"); + $this->value = null; + $this->isSubmit = false; + $this->has_error = false; + } + + function getName() { + return $this->name; + } + + function get() { + return $this->value; + } + + function title() { + return $this->title; + } + + function is_set() { + return isset($this->value); + } + + function set($value) { + $this->value = $value; + return $value; + } + + function submit() { + if($this->onlypost) { + $this->value = $_POST[$this->getName()]; + #echo"post wert: ";var_dump($this->value);echo"
"; + } else { + $this->value = $_REQUEST[$this->getName()]; + #echo"request wert: ";var_dump($this->value);echo"
"; + } + $this->isSubmit = true; + } + + function setError($msg="") { + if($msg){ + $this->error = $this->title.": ".$msg; + } + $this->has_error = true; + return false; + } + + function checkFormat() { + if(is_array($this->value)) { + foreach($this->value as $key => $value) { + if($this->format == "string") { + $this->value[$key] = trim($this->value[$key]); + } elseif($this->format == "numeric") { + if(!is_numeric($this->value[$key]) || $this->value[$key] < 0) { + return false; + break; + } + } elseif($this->format == "integer") { + if(!is_numeric($this->value[$key])) { + return false; + break; + } + } + } + } else { + if($this->format == "string" || $this->format == "time" || $this->format == "date") { + $this->value = trim($this->value); + } elseif($this->format == "numeric") { + if(!is_numeric($this->value) || $this->value < 0) { + return false; + } + } elseif($this->format == "integer") { + if(!is_numeric($this->value)) { + return false; + } + } + } + return true; + } + + function getError() { + return $this->error; + } + + function hasError() { + return $this->has_error; + } + + function getClass() { + if($this->hasError()) { + return $this->classes['error']; + } else { + return $this->classes['default']; + } + } + + function registerSmarty() { + //dummy + $item['title'] = $this->title; + return $item; + } + + function select($value) { + // dummy + } + + function isSubmit() { + return $this->isSubmit; + } +} + +// text,password,textarea felder +class formInput extends formItem { + var $optional; + var $length; + + var $regex; + var $regex_matchings; + var $regex_result; + + + function formInput($name,$title,$format,$onlypost=true,$length=null,$optional=false,$regex="") { + parent::formItem($name,$title,$format,$onlypost); + $this->length = $length; + $this->optional = $optional; + $this->regex = $regex; + $this->regex_result = false; + } + + function submit() { + parent::submit(); + if(is_array($this->get())) return $this->setError("Wert ist ungültig"); + if($this->optional && strlen($this->get()) == 0) return true; + if(!$this->optional && strlen(trim($this->get())) == 0) return $this->setError("Feld ist leer"); + if(!$this->checkFormat()) return $this->setError("Wert ist ungültig"); + if($this->length && strlen($this->get()) > $this->length) return $this->setError("Eingabe zu lang"); + if($this->format == "time") { + $this->regex_result = preg_match("'^(\d{1,2}):(\d{2})$'is",$this->get(),$this->regex_matchings); + if(!$this->regex_result) return $this->setError("Wert ist eine ungültige Zeit"); + if( $this->regex_matchings[1] < 0 || $this->regex_matchings[1] > 24 || + $this->regex_matchings[2] < 0 || $this->regex_matchings[2] > 59 + ) { + return $this->setError("Wert ist eine ungültige Zeit"); + } + } + if($this->format == "date") { + $this->regex_result = preg_match("'^(\d{1,2})\.(\d{1,2})\.(\d{4})$'is",$this->get(),$this->regex_matchings); + if(!$this->regex_result) return $this->setError("Wert ist ein ungültiges Datum"); + if( $this->regex_matchings[1] < 1 || $this->regex_matchings[1] > 31 || + $this->regex_matchings[2] < 1 || $this->regex_matchings[2] > 12 || + $this->regex_matchings[3] < 2004 || $this->regex_matchings[3] > 2020 + ) { + return $this->setError("Wert ist ein ungültiges Datum"); + } + } + if($this->regex) { + $this->regex_result = preg_match($this->regex,$this->get(),$this->regex_matchings); + if(!$this->regex_result) return $this->setError("Wert entspricht nicht der vorgegebenen Formatierung"); + } + return true; + } + + function getMatching() { + if($this->regex_result) { + return $this->regex_matchings; + } + } + + /** + * @return array smarty daten + * @desc liefert Daten für die Smartyengine + * @protected + */ + function registerSmarty() { + $item = parent::registerSmarty(); + if($this->optional) $item['title'] .= " (optional)"; + $item['value'] = $this->get(); + if($this->hasError()) { + $item['class'] = $this->classes['error']; + } else { + if(strlen($this->get()) || !$this->optional) { + $item['class'] = $this->classes['default']; + } else { + $item['class'] = $this->classes['optional']; + } + } + return $item; + } +} + +// radio +class formRadio extends formItem { + // liste der werte, list[i]['value'] + var $list; + // ausgewählter wert per default + var $default; + + //liste = array() + function formRadio($name,$title,$format,$list,$default="",$onlypost=true) { + parent::formItem($name,$title,$format,$onlypost); + // liste baun + for($i=0;$i < count($list);$i++) { + $this->list[] = array("value" => $list[$i]); + } + // defaultwert überhaupt in der liste ? + if($default && in_array($default,$list)) { + $this->default = $default; + } + } + + function submit() { + parent::submit(); + // darf kein array sein + if(is_array($this->get())) return $this->setError("Wert ungültig"); + // muss da sein, nicht optional + if(strlen(trim($this->get())) == 0) return $this->setError("Feld leer"); + // formatcheck + if(!$this->checkFormat()) return $this->setError("Wert ungültig"); + // ist in den Vorgaben vorhanden + if(($key = array_search(array("value" => $this->get()),$this->list)) === FALSE) { + return $this->setError("Wert existiert nicht in den Vorgaben"); + } else { + // selektiertes Element auswählen + $this->select($this->get()); + } +# var_dump($this->list); +# echo "
wert: ".$this->get()."
result: ".in_array($this->get(),array_keys($this->list))."
"; + return true; + } + + function registerSmarty() { + $item = parent::registerSmarty(); + // falls kein Wert gesetzt oder Fehler da ist, default wert auswählen + if($this->default && $this->isSubmit() && (!$this->get() || $this->getError())) { + $this->select($this->default); + } + $item['value'] = $this->get(); + $item['default'] = $this->default; + $item['list'] = $this->list; + return $item; + } + + function select($value) { + if(is_array($value)) return; + if(!(($key = array_search(array("value" => $value),$this->list)) === FALSE)) { + $this->list[$key]['checked'] = 'checked'; + } + } +} + +// checkbox +class formCheckBox extends formItem { + // liste der werte, list[i]['value'] + var $list; + // ausgewählte werte per default + var $default; + // erwartet ein Array als HTTP variable + var $is_array; + + //liste = array() + function formCheckBox($name,$title,$format,$list,$multiple=true,$default=null,$onlypost=true) { + parent::formItem($name,$title,$format,$onlypost); + if(!$list) $list = array(); + if(!is_array($list)) $list = array($list); + if($multiple) { + // liste baun + for($i=0;$i < count($list);$i++) { + $this->list[] = array("value" => $list[$i]); + } + } else { + $this->list[0] = array("value" => $list[0]); + } + $this->is_array = $multiple; + // defaultwerte überhaupt in der liste ? + if(is_array($default)) { + for($i=0;$i < count($default);$i++) { + if(in_array($default[$i],$list)) { + $this->default[] = $default[$i]; + } + } + } else { + if(in_array($default,$list)) { + $this->default = $default; + } + } + } + + function submit() { + parent::submit(); + // darf kein array sein + if(!$this->is_array) { + if(is_array($this->get())) return $this->setError("Wert ungültig"); + // optional + if(strlen(trim($this->get())) > 0) { + // formatcheck + if(!$this->checkFormat()) return $this->setError("Wert ungültig"); + // ist in den Vorgaben vorhanden + if(($key = array_search(array("value" => $this->get()),$this->list)) === FALSE) { + return $this->setError("Wert existiert nicht in den Vorgaben"); + } else { + // selektiertes Element auswählen + $this->select($this->get()); + } + } + } else { + if($this->get() && !is_array($this->get())) return $this->setError("Wert ungültig"); + // optional + if(count($this->get()) > 0) { + // formatcheck + if(!$this->checkFormat()) return $this->setError("Wert(e) ungültig"); + // ist in den Vorgaben vorhanden + $noerror = true; + foreach($this->get() as $key => $value) { + if(($result = array_search(array("value" => $value),$this->list)) === FALSE) { + $noerror = false; + break; + } + } + if(!$noerror) return $this->setError("Wert existiert nicht in den Vorgaben"); + $this->select($this->get()); + } + } +# var_dump($this->list); +# echo "
wert: ".$this->get()."
result: ".in_array($this->get(),array_keys($this->list))."
"; + return true; + } + + function registerSmarty() { + $item = parent::registerSmarty(); + // falls kein Wert gesetzt oder Fehler da ist, default wert(e) auswählen + if($this->default && $this->isSubmit() && (!$this->get() || $this->getError())) { + $this->select($this->default); + } + $item['default'] = $this->default; + if($this->is_array) { + $item['list'] = $this->list; + $item['value'] = $this->get(); + } else { + $item['value'] = $this->list[0]['value']; + $item['checked'] = $this->list[0]['checked']; + } + return $item; + } + + function select($value) { + if(is_array($value)) { + foreach($value as $key => $val) { + if(!(($result = array_search(array("value" => $val),$this->list)) === FALSE)) { + // selektiertes Element auswählen + $this->list[$result]['checked'] = 'checked'; + } + } + } else { + if(!(($result = array_search(array("value" => $value),$this->list)) === FALSE)) { + // selektiertes Element auswählen + $this->list[$result]['checked'] = 'checked'; + } + } + } +} + +// selectBox +class formSelectBox extends formItem { + // liste der werte, list[i]['value'],$list[i][title] + var $list; + // ausgewählte werte per default + var $default; + // erwartet ein Array als HTTP variable, multiple auswahl + var $is_array; + + // sucht den Wert in der Liste und gibt den Index zurück + function _findItem($val) { + $count = count($this->list); + for($i=0;$i < $count;$i++) { + if($this->list[$i]['value'] == $val) { + return $i; + break; + } + } + return false; + } + + // liste[] = array('value' => wert, 'title' => title) + function formSelectBox($name,$title,$format,$list,$multiple=true,$default=null,$onlypost=true) { + parent::formItem($name,$title,$format,$onlypost); + // liste baun + $this->list = array(); + if($list && is_array($list)) { + foreach($list as $value) { + $this->list[] = array("value" => $value['value'],"title" => $value['title']); + } + } + $this->is_array = $multiple; + // defaultwerte überhaupt in der liste ? + if(is_array($default)) { + for($i=0;$i < count($default);$i++) { + if(!($this->_findItem($default[$i]) === false)) { + $this->default[] = $default[$i]; + } + } + } else { + if(!($this->_findItem($default) === false)) { + $this->default = $default; + } + } + } + + function submit() { + parent::submit(); + if(!$this->is_array) { + // darf kein array sein + if(is_array($this->get())) return $this->setError("Wert ungültig"); + // optional + if(strlen(trim($this->get())) > 0) { + // formatcheck + if(!$this->checkFormat()) return $this->setError("Wert ungültig"); + // ist in den Vorgaben vorhanden + if($this->_findItem($this->get()) === FALSE) { + return $this->setError("Wert existiert nicht in den Vorgaben"); + } else { + // selektiertes Element auswählen + $this->select($this->get()); + } + } + } else { + if($this->get() && !is_array($this->get())) return $this->setError("Wert ungültig"); + // optional + if(count($this->get()) > 0) { + // formatcheck + if(!$this->checkFormat()) return $this->setError("Wert(e) ungültig"); + // ist in den Vorgaben vorhanden + $error = false; + foreach($this->get() as $key => $value) { + if($this->_findItem($value) === FALSE) { + $error = true; + break; + } + } + if ($error) return $this->setError("Wert existiert nicht in den Vorgaben"); + $this->select($this->get()); + } + } +# var_dump($this->list); +# echo "
wert: ".$this->get()."
result: ".in_array($this->get(),array_keys($this->list))."
"; + return true; + } + + function registerSmarty() { + $item = parent::registerSmarty(); + // falls kein Wert gesetzt oder Fehler da ist, default wert(e) auswählen + if($this->default && $this->isSubmit() && (!$this->get() || $this->getError())) { + $this->select($this->default); + } + $item['default'] = $this->default; + $item['list'] = $this->list; + $item['value'] = $this->get(); + return $item; + } + + function select($value) { + if(is_array($value)) { + foreach($value as $key => $val) { + if(!(($result = $this->_findItem($val)) === FALSE)) { + // selektiertes Element auswählen + $this->list[$result]['selected'] = 'selected'; + $this->value = $value; + } + } + } else { + if(!(($result = $this->_findItem($value)) === FALSE)) { + // selektiertes Element auswählen + $this->list[$result]['selected'] = 'selected'; + $this->value = $value; + } + } + } +} + + +class formContainer { + var $items; + var $errors; + + function formContainer() { + $this->items = array(); + $this->errors = array(); + } + + function add($obj) { + if(is_a($obj,"formItem")) { + $this->items[$obj->getName()] = $obj; + } + } + + function get($name) { + if(is_object($this->items[$name])) { + return $this->items[$name]->get(); + } + } + + function is_set($name) { + if(is_object($this->items[$name])) { + return $this->items[$name]->is_set(); + } + } + + function get_obj($name,$obj) { + if(is_object($this->items[$name])) { + $obj = $this->items[$name]; + } + } + + function select($name,$value) { + if(is_object($this->items[$name])) { + $this->items[$name]->select($value); + } + } + + function set($name,$value) { + if(is_object($this->items[$name])) { + $this->items[$name]->set($value); + } + } + + function submit($names="") { + if($names && !is_array($names))$names = array($names); + if($names){ + foreach($names as $name) { + if(is_a($this->items[$name],"formItem")) { + if(!$this->items[$name]->submit()) { + $this->errors[] = $this->items[$name]->getError(); + } + } + } + } else { + $this->errors = array(); + foreach($this->items as $name => $obj) { + if(!$this->items[$name]->submit()) { + $this->errors[] = $this->items[$name]->getError(); + } + } + } + if(count($this->errors)) return false; + else return true; + } + + function getRegex($name){ + if(is_a($this->items[$name],"formInput")) { + return $this->items[$name]->getMatching(); + } + } + + function setError($names) { + if(!$names) return; + if(!is_array($names)) $names = array($names); + foreach ($names as $name) { + if(is_a($this->items[$name],"formItem")){ + $this->items[$name]->setError(); + } + } + } + + function addError($msg){ + $this->errors[] = $msg; + } + + function hasErrors() { + foreach($this->items as $name => $obj) { + if($this->items[$name]->hasError()) return true; + } + return false; + } + + function getErrors() { + return $this->errors; + } + + // smartyklasse per referenz übergeben + function registerVars(&$smarty) { + $items = array(); + $this->smartyitems = array(); + foreach($this->items as $name => $obj) { + $this->smartyitems[$name] = $this->items[$name]->registerSmarty(); + } +# echo"items:";var_dump($this->items);echo"
"; + $smarty->assign("items",$this->smartyitems); + $smarty->assign("errors",$this->getErrors()); + } +} + +?> diff --git a/src/classes/gnsimu.php b/src/classes/gnsimu.php new file mode 100644 index 0000000..56125a7 --- /dev/null +++ b/src/classes/gnsimu.php @@ -0,0 +1,438 @@ +name[0] = "Jäger"; + $this->attackpower[0] = array(0.0246, 0.392, 0.0263); // Wie viele Schiffe ein Schiff mit 100% Feuerkrafft zerstören würde + $this->shiptoattack[0] = array(11,1,4); // Welche Schiffe/Geschütze angegriffen werden + $this->percent[0] = array(0.35,0.30,0.35); // Die Verteilung der Prozente, mit der auf die Schiffe geschoßen wird. + $this->mcost[0] = 4000; + $this->kcost[0] = 6000; + + // Daten Für Bomber Nr. 1 + $this->attackpower[1] = array(0.0080,0.0100,0.0075); + $this->shiptoattack[1] = array(12,5,6); + $this->percent[1] = array(0.35,0.35,0.30); + $this->name[1] = "Bomber"; + $this->mcost[1] = 2000; + $this->kcost[1] = 8000; + + // Daten Für Fregatte Nr. 2 + $this->attackpower[2] = array(4.5,0.85); + $this->shiptoattack[2] = array(13,0); + $this->percent[2] = array(0.6,0.4); + $this->name[2] = "Fregatte"; + $this->mcost[2] = 15000; + $this->kcost[2] = 7500; + + // Daten Für Zerstörer Nr. 3 + $this->attackpower[3] = array(3.5,1.2444); + $this->shiptoattack[3] = array(9,2); + $this->percent[3] = array(0.6,0.4); + $this->name[3] = "Zerstörer"; + $this->mcost[3] = 40000; + $this->kcost[3] = 30000; + + // Daten Für Kreuzer Nr. 4 + $this->attackpower[4] = array(2.0,0.8571,10.0); + $this->shiptoattack[4] = array(10,3,8); + $this->percent[4] = array(0.35,0.30,0.35); + $this->name[4] = "Kreuzer"; + $this->mcost[4] = 65000; + $this->kcost[4] = 85000; + + // Daten Für Schalchtschiff Nr. 5 + $this->attackpower[5] = array(1.0,1.0666,0.4,0.3019,26.6667); + $this->shiptoattack[5] = array(11,4,5,6,8); + $this->percent[5] = array(0.2,0.2,0.2,0.2,0.2); + $this->name[5] = "Schlachtschiff"; + $this->mcost[5] = 250000; + $this->kcost[5] = 150000; + + // Daten Für Trägerschiff Nr. 6 + $this->attackpower[6] = array(25.0,14.0); + $this->shiptoattack[6] = array(7,8); + $this->percent[6] = array(0.5,0.5); + $this->mcost[6] = 200000; + $this->kcost[6] = 50000; + $this->name[6] = "Trägerschiff"; + + + // Daten für Kaperschiff + $this->mcost[7] = 1500; + $this->kcost[7] = 1000; + $this->name[7] = "Kaperschiff"; + + + // Daten für Schutzschiff + $this->mcost[8] = 1000; + $this->kcost[8] = 1500; + $this->name[8] = "Schutzschiff"; + + + // Daten Für Leichtes Obligtalgeschütz Nr. 9 + $this->attackpower[9] = array(0.3,1.28); + $this->shiptoattack[9] = array(0,7); + $this->percent[9] = array(0.6,0.4); + $this->mcost[9] = 6000; + $this->kcost[9] = 2000; + $this->name[9] = "Leichtes Orbitalgeschütz"; + + + // Daten Für Leichtes Raumgeschütz Nr. 10 + $this->attackpower[10] = array(1.2,0.5334); + $this->shiptoattack[10] = array(1,2); + $this->percent[10] = array(0.4,0.6); + $this->pretick[10] = array(0,0.5); + $this->pretickattack[10] = array(2); + $this->mcost[10] = 20000; + $this->kcost[10] = 10000; + $this->name[10] = "Leichtes Raumgeschütz"; + + + // Daten Für Mittleres Raumgeschütz Nr. 11 + $this->attackpower[11] = array(0.9143,0.4267); + $this->shiptoattack[11] = array(3,4); + $this->percent[11] = array(0.4,0.6); + $this->pretick[11] = array(0,0.5); + $this->pretickattack[11] = array(3,4); + $this->mcost[11] = 60000; + $this->kcost[11] = 100000; + $this->name[11] = "Mittleres Raumgeschütz"; + + + // Daten Für Schweres Raumgeschütz Nr. 12 + $this->attackpower[12] = array(0.5,0.3774); + $this->shiptoattack[12] = array(5,6); + $this->percent[12] = array(0.5,0.5); + $this->pretick[12] = array(0.2,0.6); + $this->pretickattack[12] = array(5,6); + $this->mcost[12] = 200000; + $this->kcost[12] = 300000; + $this->name[12] = "Schweres Raumgeschütz"; + + + // Daten Für Abfangjäger Nr. 13 + $this->attackpower[13] = array(0.0114,0.32); + $this->shiptoattack[13] = array(3,7); + $this->percent[13] = array(0.4,0.6); + $this->mcost[13] = 1000; + $this->kcost[13] = 1000; + $this->name[13] = "Abfangjäger"; + + for ($i=0;$i<14;$i++) { + $this->geslostshipsatt[$i] = 0; + $this->geslostshipsdeff[$i] = 0; + } + $this->getlostkristall[0] = 0; + $this->getlostkristall[1] = 0; + $this->getlostmetall[0] = 0; + $this->getlostmetall[1] = 0; + $this->gesstolenexenk = 0; + $this->gesstolenexenm = 0; + } + + + + function Compute($lasttick) // Dieses ist sie also die mytische Funktion, die Werte in äh ja äh andere Werte verwandeln kann. $lasttick dient dazu im letzten tick die Jäger und Bomber zu zerstören, die über sind. + { + // Wenn man tolle Debug informationen sehen will einfach auf 1 setzen + $debug = 0; + // "Sicherheitskopie" der Anzahl der Schiffe machen + for($i=0;$i<14;$i++) + { + $this->Olddeff[$i] = $this->deffending[$i]; + if($i<9) + $this->Oldatt[$i] = $this->attacking[$i]; + } + + //Schleife über alle Schiffe + for($i=0;$i<14;$i++) + { + //Variablen für das nächste Schiff "nullen" + $RestPercentatt = 0; + $Restpoweratt = $this->Oldatt[$i]; //Die Power ist gleich der Anzahl der Schiffe die angreifen + $OldRestpoweratt = 0; + $RestPercentdeff = 0; + $Restpowerdeff = $this->Olddeff[$i]; + $OldRestpowerdeff = 0; + $strike=0; + //Berechnen wie viele Strikes der aktuelle Schiffstyp hat(eins geteilet durch den kleinsten Prozentwert, mit dem das Schiff feuert und das ganz aufrunden und noch +3) + if($this->percent[$i]) + $curstrikes = ceil(1/min($this->percent[$i]))+3; + else + $curstrikes = 0; + while($strike < $curstrikes ) + { + if($debug) echo "Strike".($strike-$curstrikes)."
"; + $OldRestpoweratt = $Restpoweratt; + $OldRestpowerdeff = $Restpowerdeff; + // Schleife über alle Schiffe die angeriffen werden sollen + for($j=0;$jattackpower[$i]);$j++) + { + if($debug) echo $this->name[$i]." gegen ".$this->name[$this->shiptoattack[$i][$j]]."
"; + // Angreifer + if($Restpoweratt>0) + { + $del = 0; + // Dafür sorgen, dass nicht mit einem Prozentsatz von größer als 100% angerifen wird + if($RestPercentatt+$this->percent[$i][$j] > 1) + $RestPercentatt = 1.0 - $this->percent[$i][$j]; + // Maximale Zerstörung die Angerichtet werden kann. Die Power der Prozentsatz mal die Power der Schiffe mal wie viele Schiffe vom andern tyo von einem zerstört werden + $MaxDestruction = floor(($RestPercentatt+$this->percent[$i][$j]) * $OldRestpoweratt * $this->attackpower[$i][$j]); + if($debug) + { + echo "- Angreifende Schiffe: ".$this->Oldatt[$i]." Verteidigende Schiffe:".($this->deffending[$this->shiptoattack[$i][$j]])."
"; + echo "- Maximale Zerstörung: floor(($RestPercentatt+".$this->percent[$i][$j].") * $OldRestpoweratt * ".$this->attackpower[$i][$j].")=$MaxDestruction
"; + } + // Wie viele Schiffe dann zerstört werden, nich mehr als die maximale zerstörung und nich mehr als mit 100%(was oben eigentlich schon geprüft wird) und nich mehr als Schiffe noch über sind. + $del= floor(max(min($MaxDestruction, $Restpoweratt * $this->attackpower[$i][$j], $this->deffending[$this->shiptoattack[$i][$j]]), 0)); + // Im 4ten Strike wird unter bestimmten Umständen(s.u) der Prozentsatz, der beim feuern nicht zum Einsatz gekommen ist zu einer Variable addiert, die zum normalen Prozentsatz dazugerechnet wird. + if($strike==3) + { + // Wenn es das letzte Schiff im Tick ist oder keine Schiffe zerstört wurden wird Rest-Prozent um den Prozentsatz, der nich verbraucht wird erhöht. + // Alles könnte schön und gut sein, wenn da nicht die Schlachter wären, die flogen der Regel nämlich nur wenn sie auf sich selbst oder Kreuzer schießen, sonnst wird immer der Prozentsatz der nicht gebraucht wurde dazugerechnet, warum auch immer... + if ( $j == count($this->attackpower[$i])-1 || $del == 0 || ($i == 5 && $this->shiptoattack[$i][$j]!=5 && $this->shiptoattack[$i][$j]!=4)) + { + $RestPercentatt += $this->percent[$i][$j] - ($del / $OldRestpoweratt / $this->attackpower[$i][$j]); + } + } + // Benutze Feuerkraft berechnen und subtrahiren + $Firepower = $del/$this->attackpower[$i][$j]; + $Restpoweratt -= $Firepower; + // Schiffe zerstören + $this->deffending[$this->shiptoattack[$i][$j]] -=$del; + $this->geslostshipsdeff[$this->shiptoattack[$i][$j]] += $del; + $this->getlostmetall[1] += ($del*$this->mcost[$this->shiptoattack[$i][$j]]); + $this->getlostkristall[1] += ($del*$this->kcost[$this->shiptoattack[$i][$j]]); + if($debug) + { + echo "- Zerstörte Schiffe: $del
+ - Benutzte Firepower = $del/".$this->attackpower[$i][$j]." = $Firepower; Restpower = $Restpoweratt
"; + } + } + // Nochmal genau das selbe nur mit Angreifer/Verteidiger vertauschten Variablen. + if($Restpowerdeff>0) + { + $del = 0; + if($RestPercentdeff+$this->percent[$i][$j] > 1) + $RestPercentdeff = 1.0 - $this->percent[$i][$j]; + $MaxDestruction = floor(($RestPercentdeff+$this->percent[$i][$j]) * $OldRestpowerdeff * $this->attackpower[$i][$j]); + if($debug) + { + echo "- Angreifende Schiffe: ".$this->Olddeff[$i]." Verteidigende Schiffe:".($this->attacking[$this->shiptoattack[$i][$j]])."
"; + echo "- Maximale Zerstörung: floor(($RestPercentdeff+".$this->percent[$i][$j].") * $OldRestpowerdeff * ".$this->attackpower[$i][$j].")=$MaxDestruction
"; + } + $del= floor(max(min($MaxDestruction, $Restpowerdeff * $this->attackpower[$i][$j], $this->attacking[$this->shiptoattack[$i][$j]]), 0)); + if($strike==3) + { + if ( $j == count($this->attackpower[$i])-1 || $del == 0 || ($i == 5 && $this->shiptoattack[$i][$j]!=5 && $this->shiptoattack[$i][$j]!=4)) + { + $RestPercentdeff += $this->percent[$i][$j] - ($del / $OldRestpowerdeff / $this->attackpower[$i][$j]); + } + } + $Firepower = $del/$this->attackpower[$i][$j]; + $Restpowerdeff -= $Firepower; + $this->attacking[$this->shiptoattack[$i][$j]] -= $del; + $this->geslostshipsatt[$this->shiptoattack[$i][$j]] += $del; + $this->getlostmetall[0] += $del*$this->mcost[$this->shiptoattack[$i][$j]]; + $this->getlostkristall[0] += $del*$this->kcost[$this->shiptoattack[$i][$j]]; + if($debug) + { + echo "- Zerstörte Schiffe: $del
+ - Benutzte Firepower = $del/".$this->attackpower[$i][$j]." = $Firepower; Restpower = $Restpowerdeff
"; + } + } + } + $strike++; + } + } + //Wenn wir im letzen Tick sind wird geprüft ob auch alle Jäger und Bomber mit nach hause fliegn dürfen + + if($lasttick) + { + $jaeger = $this->attacking[0]; + $bomber = $this->attacking[1]; + $traeger = $this->attacking[6]; + if ( $bomber + $jaeger > $traeger*100) + { + $todel = $jaeger + $bomber - $traeger*100; + $deletejaeger = round($todel*($jaeger/($jaeger + $bomber))); + $deletebomber = round($todel*($bomber/($jaeger + $bomber))); + $this->attacking[0] -= $deletejaeger; + $this->attacking[1] -= $deletebomber; + + $this->geslostshipsatt[0] += $deletejaeger; + $this->geslostshipsatt[1] += $deletebomber; + + $this->getlostmetall[0] += $deletejaeger*$this->mcost[0]; + $this->getlostkristall[0] += $deletejaeger*$this->kcost[0]; + $this->getlostmetall[0] += $deletebomber*$this->mcost[1]; + $this->getlostkristall[0] += $deletebomber*$this->kcost[1]; + } + } + //Dann noch mal eben schnell paar exen klauen + //Erstmall ausrechnen, wie viele maximal mitgenommen werden können, bin der Meinung mal Iregndwo im Forum gelesen zu haben, dass Metall- auf- und Kristallexen abgerundet werden + $maxmexen = ceil((max($this->attacking[7]-$this->deffending[8],0))/2); + $maxkexen = floor((max($this->attacking[7]-$this->deffending[8],0))/2); + + //Dann wie viele Metallexen in den meißten fällen geklaut würden + $rmexen = min($maxmexen, floor($this->mexen*0.1)); + + + //Wenn nich alle Schiffe, die für Metallexenlau bereitgestellt waren benutz werden, dürfen diezum Kristallexen klauen Benutzt werden + if($rmexen != $maxmexen) + $maxkexen += $maxmexen-$rmexen; + + //Kristallexen in den meißten fällen + $rkexen = min($maxkexen, floor($this->kexen*0.1)); + + // Wenn nich alle zum Kristallexen bereitgestellten Cleps benutzt wurden, rechnen wir nochmal Metallexen ob nich evtl mehr mit genommen werden können. + if($rkexen != $maxkexen) + { + $maxmexen += $maxkexen-$rkexen; + $rmexen = min($maxmexen, floor($this->mexen*0.1)); + } + + + // Exen vom bestand abziehen und auch die benutzen Cleps "zerstören" + $this->mexen -=$rmexen; + $this->kexen -=$rkexen; + $this->attacking[7] -= $rmexen+$rkexen; + $this->geslostshipsatt[7] += $rmexen+$rkexen; + + $this->getlostmetall[0] += ($rmexen+$rkexen)*$this->mcost[7]; + $this->getlostkristall[0] += ($rmexen+$rkexen)*$this->kcost[7]; + + //Für die Statistik, wie viele Exen insgesammt gestohlen wurden. + $this->gesstolenexenm+=$this->stolenmexen = $rmexen; + $this->gesstolenexenk+=$this->stolenkexen = $rkexen; + } + + function vorticks($pretick=0) // berechnet die Vorticks + { + // Wenn man tolle Debug informationen sehen will einfach auf 1 setzen + $debug = 0; + if (!$pretick) $pretick=0; + + // "Sicherheitskopie" der Anzahl der Schiffe machen + for($i=0;$i<14;$i++) + { + $this->Olddeff[$i] = $this->deffending[$i]; + if($i<9) + $this->Oldatt[$i] = $this->attacking[$i]; + $tempattack[$i] = $this->attacking[$i]; + } + + //Schleife über Geschütze mit Preticks + for($i=10;$i<13;$i++) + { + unset($templost); + if (!$this->pretick[$i][$pretick]) continue; + //Variablen für das nächste Schiff "nullen" + $RestPercentatt = 0; + $Restpoweratt = $this->Oldatt[$i]; //Die Power ist gleich der Anzahl der Schiffe die angreifen + $OldRestpoweratt = 0; + $RestPercentdeff = 0; + $Restpowerdeff = $this->Olddeff[$i]; + $OldRestpowerdeff = 0; + $strike=0; + //Berechnen wie viele Strikes der aktuelle Schiffstyp hat(eins geteilet durch den kleinsten Prozentwert, mit dem das Schiff feuert und das ganz aufrunden und noch +3) + if($this->percent[$i]) + $curstrikes = ceil(1/min($this->percent[$i]))+3; + else + $curstrikes = 0; + while($strike < $curstrikes ) + { + if($debug) echo "Strike".($strike-$curstrikes)."
"; + $OldRestpoweratt = $Restpoweratt; + $OldRestpowerdeff = $Restpowerdeff; + // Schleife über alle Schiffe die angeriffen werden sollen + for($j=0;$jattackpower[$i]);$j++) + { + if($debug) echo $this->name[$i]." gegen ".$this->name[$this->shiptoattack[$i][$j]]."
"; + if($Restpowerdeff>0) + { + $del = 0; + if($RestPercentdeff+$this->percent[$i][$j] > 1) + $RestPercentdeff = 1.0 - $this->percent[$i][$j]; + $MaxDestruction = floor(($RestPercentdeff+$this->percent[$i][$j]) * $OldRestpowerdeff * $this->attackpower[$i][$j]); + if($debug) + { + echo "- Angreifende Schiffe: ".$this->Olddeff[$i]." Verteidigende Schiffe:".($tempattack[$this->shiptoattack[$i][$j]])."
"; + echo "- Maximale Zerstörung: floor(($RestPercentdeff+".$this->percent[$i][$j].") * $OldRestpowerdeff * ".$this->attackpower[$i][$j].")=$MaxDestruction
"; + } + $del= floor(max(min($MaxDestruction, $Restpowerdeff * $this->attackpower[$i][$j], $tempattack[$this->shiptoattack[$i][$j]]), 0)); + if($strike==3) + { + if ( $j == count($this->attackpower[$i])-1 || $del == 0 || ($i == 5 && $this->shiptoattack[$i][$j]!=5 && $this->shiptoattack[$i][$j]!=4)) + { + $RestPercentdeff += $this->percent[$i][$j] - ($del / $OldRestpowerdeff / $this->attackpower[$i][$j]); + } + } + $Firepower = $del/$this->attackpower[$i][$j]; + $Restpowerdeff -= $Firepower; + $tempattack[$this->shiptoattack[$i][$j]] -= $del; + $templost[$this->shiptoattack[$i][$j]] += $del; + if($debug) + { + echo "- Zerstörte Schiffe: $del
+ - Benutzte Firepower = $del/".$this->attackpower[$i][$j]." = $Firepower; Restpower = $Restpowerdeff
"; + } + } + } + $strike++; + } + for ($j=2;$j<7;$j++) { + $this->attacking[$j] -= floor($templost[$j] * $this->pretick[$i][$pretick]); + $this->geslostshipsatt[$j] += floor($templost[$j] * $this->pretick[$i][$pretick]); + } + } + $jaeger = $this->attacking[0]; + $bomber = $this->attacking[1]; + $traeger = $this->attacking[6]; + if ( $bomber + $jaeger > $traeger*100) + { + $todel = $jaeger + $bomber - $traeger*100; + $deletejaeger = round($todel*($jaeger/($jaeger + $bomber))); + $deletebomber = round($todel*($bomber/($jaeger + $bomber))); + $this->attacking[0] -= $deletejaeger; + $this->attacking[1] -= $deletebomber; + + $this->getlostmetall[0] += $deletejaeger*$this->mcost[0]; + $this->getlostkristall[0] += $deletejaeger*$this->kcost[0]; + $this->getlostmetall[0] += $deletebomber*$this->mcost[1]; + $this->getlostkristall[0] += $deletebomber*$this->kcost[1]; + } + $this->stolenmexen = 0; + $this->stolenkexen = 0; + } +} + +?> \ No newline at end of file diff --git a/src/classes/index.class.php b/src/classes/index.class.php new file mode 100644 index 0000000..4309c93 --- /dev/null +++ b/src/classes/index.class.php @@ -0,0 +1,449 @@ +action]) { + eval("\$this->".$functions[$this->action].";"); + } + #default + $this->_News_list(); + } + + function highscore_list() { + $page = param_num("page",1); + $show = param_str("show"); + if($show == "day") { + $highscore['list'] = highscore_list(array("hours"=>24),&$pages,&$page); + $highscore['title'] = "Meisten Punkte in den letzten 24 Stunden"; + } elseif($show =="week") { + $highscore['list'] = highscore_list(array("days"=>7),&$pages,&$page); + $highscore['title'] = "Meisten Punkte in der letzten Woche"; + } else { + $highscore['list'] = highscore_list(null,&$pages,&$page); + $highscore['title'] = "Komplette Übersicht"; + } + $this->template->assign('pages',showPageBar($page,$pages,"index.php?action=highscore&show=$show","page","menu")); + $this->template->assign('page',$page); + $this->template->assign('highscore',$highscore); + $this->show('highscore_index','Highscoreliste'); + } + + function Scanner_list() { + $this->template->assign('mililist',user_get_scannerlist(1,10)); + $this->template->assign('newslist',user_get_scannerlist(0,10)); + $this->show('scanner_list','Nachrichten'); + } + + # + # Newsliste + # + function _News_list() { + $page = param_num("page",1); + $newslist = listNews(&$pages,&$page); + for ($i=0;$iuserdata['rights']['news']) { + $this->forms['newslist']['canedit'] = 1; + } + $this->forms['newslist']['pages'] = showPageBar($page,$pages,"index.php","page","menu"); + $this->template->assign('page',$page); + $this->template->assign('newslist',$newslist); + $this->template->assign('title','Nachrichten'); + $this->show('news_list','Nachrichten'); + } + + # + # listet die Member auf + # + function _Member_list() { + $page = param_num("page",1); + $rows = 12; + + $filter = $_SESSION['memberfilter']; + if (!$filter){ + $filter['sort'] = "koords"; + $filter['order'] = "asc"; + $filter['page'] = 1; + $_SESSION['memberfilter'] = $filter; + } + if ($_REQUEST['sort'] && $_REQUEST['order']) { + $filter['sort'] = $_REQUEST['sort']; + $filter['order'] = $_REQUEST['order']; + $_SESSION['memberfilter'] = $filter; + } + if($_POST['send']) { + if ($_POST['ally'] && is_numeric($_POST['ally']) + && getAlly($_POST['ally'])) { + $filter['ally'] = $_POST['ally']; + } else { + unset($filter['ally']); + } + $_SESSION['memberfilter'] = $filter; + } + $sort[$filter['sort']][$filter['order']] = '_active'; + + $allylist = getAllyList(); + if ($filter['ally']) { + for($i=0;$i < count($allylist);$i++){ + if ($allylist[$i]['aid'] == $filter['ally']) { + $allylist[$i]['selected'] = "selected"; + break; + } + } + } else { + $this->template->assign("ally0","selected"); + } + + + $userlist = listUser($filter,&$pages,&$page,$rows); + $this->template->assign("pages",showPageBar($page,$pages,"index.php?action=members","page","menu")); + $setback = "index.php?action=members&page=".$page."&".$this->session['link']; + $_SESSION['setback'] = $setback; + $this->template->assign("sort",$sort); + $this->template->assign('userlist',$userlist); + $this->template->assign('allylist',$allylist); + $this->show('member_list','Memberliste'); + } + + # + # fügt neue Nachrichten hinzu + # + function _News_add() { + if (!$this->userdata['rights']['news']) { + $this->_header("index.php"); + } + $data = $_SESSION['steps']; + $page = param_num("page",1); + #information message, step 2 + if ($data['addnews']) { + #save step + unset($data['addnews']); + $_SESSION['steps'] = $data; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['title'] = "Nachrichten hinzufügen"; + $this->forms['information']['message'] = "Nachricht hinzugefügt"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Nachrichten hinzufügen"); + } + #addnews, step 1 + #formular send + if ($_REQUEST['send']) { + if ($_REQUEST['next_x']) { + $items['title'] = param_str("title",true); + $items['message'] = param_str("message",true); + $errors = false; + #check if empty + foreach ( $items as $key => $value) { + if (!$value) { + $this->forms['addnews']['fields'][$key]['error'] = 'Feld darf nicht leer sein!'; + $this->forms['addnews']['fields'][$key]['bgrd'] = '_error'; + $errors = true; + } else { + $this->forms['addnews']['fields'][$key]['value'] = $value; + } + } + if (!$errors) { + #save step + $data['addnews'] = 1; + $_SESSION['steps'] = $data; + $id = addnews($items['title'],editpostdata($items['message']),$this->userdata['uid']); + addToLogfile("Nachricht ".$items['title']." hinzugefügt", + "News",$this->userdata['uid']); + $this->_header("index.php?action=addnews&send"); + } + } else { + $this->_header("index.php?page=".$page); + } + } + $this->forms['addnews']['name'] = $return['name']; + $this->forms['addnews']['url'] = "index.php"; + $this->forms['addnews']['action'] = 'addnews'; + $this->template->assign("backlink",$this->backtracking->backlink()); + $this->show('news_add_form',"Nachricht hinzufügen"); + } + # + # bearbeitet eine Nachricht + # + function _News_edit() { + if (!$this->userdata['rights']['news']) { + $this->_header("index.php"); + } + $id = param_num("id"); + if (!$id) $this->_header("index.php"); + $newsdata = getNews($id); + if (!$newsdata) $this->_header("index.php"); + $page = param_num("page",1); + $data = $_SESSION['steps']; + #information message, step 2 + if ($data['editnews']) { + #save step + unset($data['editnews']); + $_SESSION['steps'] = $data; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['title'] = "Nachrichten bearbeiten"; + $this->forms['information']['message'] = "Nachricht erfolgreich bearbeitet"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Nachrichten bearbeiten"); + } + #editnews, step 1 + #formular send + if ($_REQUEST['send']) { + if ($_REQUEST['next_x']) { + $items['title'] = param_str("title",true); + $items['message'] = param_str("message",true); + $errors = false; + #check if empty + foreach ( $items as $key => $value) { + if (!$value) { + $this->forms['editnews']['fields'][$key]['error'] = 'Feld darf nicht leer sein!'; + $this->forms['editnews']['fields'][$key]['bgrd'] = '_error'; + $errors = true; + } else { + $this->forms['editnews']['fields'][$key]['value'] = $value; + } + } + #optional parameters + if (!$errors) { + #save step + $data['editnews'] = 1; + $_SESSION['steps'] = $data; + addToLogfile("Nachricht ".$newsdata['title']." bearbeitet", + "News",$this->userdata['uid']); + updatenews($newsdata['nid'],$items['title'], + editpostdata($items['message']),$this->userdata['uid']); + $this->_header("index.php?action=editnews&id=".$newsdata['nid']."&send"); + } + } + } else { + $this->forms['editnews']['fields']['message']['value'] = editdbdata($newsdata['content']); + $this->forms['editnews']['fields']['title']['value'] = editdbdata($newsdata['title']); + } + $this->forms['editnews']['url'] = "index.php?id=".$newsdata['nid']; + $this->forms['editnews']['action'] = 'editnews'; + $this->show('news_edit_form',"Nachricht bearbeiten"); + } + # + # löscht eine Nachricht + # + function _News_delete() { + if (!$this->userdata['rights']['news']) { + $this->_header("index.php"); + } + $data = $_SESSION['steps']; + $page = param_num("page",1); + #information message, step 2 + if ($data['deletenews']) { + #save step + unset($data['deletenews']); + $_SESSION['steps'] = $data; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['title'] = "Nachrichten löschen"; + $this->forms['information']['message'] = "Nachricht erfolgreich gelöscht"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Nachrichten löschen"); + } + $id = param_num("id"); + if (!$id) $this->_header("index.php"); + $return = getNews($id); + if (!$return) $this->_header("index.php"); + #deletenews, send + if ($_REQUEST['send']) { + if ($_REQUEST['yes_x']) { + addToLogfile("Nachricht ".$return['title']." gelöscht","News", + $this->userdata['uid']); + deletenews($return['nid']); + #save step + $data['deletenews'] = 1; + $_SESSION['steps'] = $data; + $this->_header("index.php?action=deletenews&send"); + } else { + $this->_header($this->backtracking->backlink()); + } + } else { + $this->forms['information']['url'] = "index.php?id=".$return['nid']."&page=".$page; + $this->forms['information']['action'] = "deletenews"; + $this->forms['information']['title'] = "Nachricht löschen"; + $this->forms['information']['message'] = "Nachricht ".$return['title']." löschen ?"; + $this->forms['information']['style'] = "red"; + $this->show('message_question', "Nachricht löschen"); + } + } + # + # list Comments + # + function _Comment_list() { + $id = param_num("id"); + if (!$id) $this->_header("index.php"); + $newsdata = getNews($id); + if (!$newsdata) $this->_header("index.php"); + $newsdata['content'] = formatTextData($newsdata['content']); + + $page = param_num("page",1); + $comrows = 6; + #commentlist + $comlist = listNewsComments($id,&$pages,&$page,$comrows); + for ($i=0;$iuserdata['rights']['news']) { + $this->template->assign('canedit',1); + } + $this->forms['comlist']['pages'] = + showPageBar($page,$pages,"index.php?action=comments&id=".$id + ,"page","menu"); + + $this->template->assign('comlist',$comlist); + $this->template->assign('news',$newsdata); + $this->template->assign('page',$page); + $this->show('com_list', "Kommentare"); + } + + # + # add Comment + # + function _Comment_add() { + $nid = param_num("nid"); + if (!$nid) $this->_header("index.php"); + $newsdata = getNews($nid); + if (!$newsdata) $this->_header("index.php"); + + $comrows = 6; + + $data = $_SESSION['steps']; + #information message, step 2 + if ($data['addcom']) { + #save step + unset($data['addcom']); + $_SESSION['steps'] = $data; + $pages = getNewsCommentsPages($nid,$comrows); + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['title'] = "Kommentar hinzufügen"; + $this->forms['information']['message'] = "Kommentar hinzugefügt"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Kommentar hinzufügen"); + } + #formular send + if ($_REQUEST['send']) { + if ($_REQUEST['next_x']) { + $items['message'] = param_str("message",true); + $errors = false; + #check if empty + foreach ( $items as $key => $value) { + if (!$value) { + $this->forms['addcom']['fields'][$key]['error'] = 'Feld darf nicht leer sein!'; + $this->forms['addcom']['fields'][$key]['bgrd'] = '_error'; + $errors = true; + } else { + $this->forms['addcom']['fields'][$key]['value'] = $value; + } + } + #optional parameters + if (!$errors) { + #save step + $data['addcom'] = 1; + $_SESSION['steps'] = $data; + $id = addcom($nid,editPostdata($items['message']),$this->userdata['uid']); + addToLogfile("Kommentar zu News ".$newsdata['title']. + " hinzugefügt","News",$this->userdata['uid']); + $this->_header("index.php?action=addcom&nid=".$nid."&send"); + } + } else { + $this->_header($this->backtracking->backlink()); + } + } + $this->forms['addcom']['name'] = $return['name']; + $this->forms['addcom']['url'] = "index.php?nid=".$nid; + $this->forms['addcom']['action'] = 'addcom'; + $this->show('com_add_form',"Kommentar hinzufügen"); + } + + # + # delete Comment + # + function _Comment_delete() { + if (!$this->userdata['rights']['news']) { + $this->_header("index.php"); + } + $data = $_SESSION['steps']; + $nid = param_num("nid"); + $cid = param_num("cid"); + #information message, step 2 + if ($data['deletecom']) { + #save step + unset($data['deletecom']); + $_SESSION['steps'] = $data; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['action'] ="comments"; + $this->forms['information']['title'] = "Kommentar löschen"; + $this->forms['information']['message'] = "Kommentar erfolgreich gelöscht"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Kommentar löschen"); + } + if (!$cid) $this->_header($this->backtracking->backlink()); + $return = getNewsComment($cid); + if (!$return) $this->_header($this->backtracking->backlink()); + $newsdata = getNews($nid); + if (!$newsdata) $this->_header($this->backtracking->backlink()); + #deletecom, send + if ($_REQUEST['send']) { + if ($_REQUEST['yes_x']) { + addToLogfile("Kommentar bei ".$newsdata['title']." gelöscht","News", + $this->userdata['uid']); + deleteNewsCom($return['cid']); + #save step + $data['deletecom'] = 1; + $_SESSION['steps'] = $data; + $this->_header("index.php?action=deletecom&nid=".$nid."&send"); + } else { + $this->_header($this->backtracking->backlink()); + } + } else { + $this->forms['information']['url'] = "index.php?nid=$nid&cid=$cid"; + $this->forms['information']['action'] = "deletecom"; + $this->forms['information']['title'] = "Kommentar löschen"; + $this->forms['information']['message'] = "Kommentar löschen ?

". + formatTextData($return['content']); + $this->forms['information']['style'] = "black"; + $this->show('message_question', "Kommentar löschen"); + } + } +} +?> \ No newline at end of file diff --git a/src/classes/kibo.backtracking.php b/src/classes/kibo.backtracking.php new file mode 100644 index 0000000..8340344 --- /dev/null +++ b/src/classes/kibo.backtracking.php @@ -0,0 +1,50 @@ +uid = $uid; + parent::run(); + + } + + /** + * @return array + * @desc Liefert den Trackingbuffer + * @private + */ + function _get() { + $tracking = array(); + $result = selectsqlline("select backtracking from useronline where uid = ".$this->uid); + if($result['backtracking']) { + $tracking = split("\n",$result['backtracking']); + } + return $tracking; + } + + /** + * @return void + * @desc Schreibt den aktuellen Stack in die db + */ + function _refresh() { + query("update useronline set backtracking = '".join("\n",$this->backlinks)."' where uid = ".$this->uid); + } + +} +?> \ No newline at end of file diff --git a/src/classes/kibo.page.class.php b/src/classes/kibo.page.class.php new file mode 100644 index 0000000..5705a43 --- /dev/null +++ b/src/classes/kibo.page.class.php @@ -0,0 +1,510 @@ +forms = array(); + $this->box = array(); + $this->userdata = array(); + + $this->backtracking = new kibo_backtracking($this->session); + + $this->version = TIC_VERSION; + $this->template->assign('version',TIC_VERSION." ".TIC_COPYRIGHT); + + } + + function run() { + + parent::run(1); + + //loads Userdata from session + $this->_loadUserData(); + + //check loginstatus + if (!$this->userdata) { + //login + $this->_loginUser(); + } else { + //logout + if ($this->action == "logout") + { + $this->_logoutUser(); + } + $this->backtracking->run($this->userdata['uid']); + $this->template->assign("backlink",$this->backtracking->backlink()); + } + + //botrefresh + bot_refresh(); + //flotten refresh + fleetstatus_refresh(); + //user has to change pw + if ($this->userdata['changepw'] && $this->action != "changepwd") $this->_header("user.php?action=changepwd"); + + //checkt die incs auf undertime +// inc_check_undertime(); + //läd die Takscreenbox + $this->_loadTakscreenBox(); + //läd die Aktivitätsbox + $this->_loadActivityBox(); + //lädt die Flottenbox + $this->_loadFleetBox(); + //creates mainmenu + $this->_createMenu(); + } + + function _header($link="",$msg="") { + if(!$link) $link = $this->backtracking->backlink(); + parent::_header($link,$msg); + } + + # + # Zeigt die Seite an, lädt vorher die Content Boxen + # + function show($content,$title="") { + $this->box['mainbox']['template'] = $content.".html"; + $this->box['mainbox']['title'] = $title; + $this->template->assign('htmlpagetitle',TIC_VERSION." -- ".$title); + $this->template->assign('forms',$this->forms); + $this->template->assign('box',$this->box); + #show page + $this->template->display('index.html'); + exit(); + } + + # + # Zeigt eine Fehlerseite an + # + function show_error($content="Fehler",$title="Fehler") { + $this->template->assign('message',$content); + $this->show('error',$title); + } + + # + # lädt die Userdaten aus der Session + # + function _loadUserData () { + $data = $_SESSION['sessionuserdata']; + #check session UserData + if ($data) { + $return = getUserByID($data['id'],$data['password']); + if ($return) { + $this->userdata = $return; + updateUserOnline($this->userdata['uid']); + #load login/logout box, useronlinebox + refreshUserOnline(); + + $this->box['userbox']['title'] = 'Benutzerinfo'; + $this->box['userbox']['username'] = $this->userdata['nick']; + $this->box['userbox']['gala'] = $this->userdata['gala']; + $this->box['userbox']['pos'] = $this->userdata['pos']; + $this->box['userbox']['userid'] = $this->userdata['uid']; + $this->box['userbox']['template'] = 'box_userdata_content.html'; + + $this->box['useronline']['title'] = 'User Online'; + $list = listUserOnline(); + for($i=0;$i < count($list);$i++){ + $len = 11-strlen($list[$i]['gala'])-strlen($list[$i]['pos']); + if(strlen($list[$i]['nick'])>$len) { + $list[$i]['name'] = substr($list[$i]['nick'],0,$len).".."; + } else { + $list[$i]['name'] = $list[$i]['nick']; + } + } + $this->box['useronline']['list'] = $list; + $this->box['useronline']['template'] = 'box_useronline_content.html'; + + } else { + deleteUserOnline($this->userdata['uid']); + unset($_SESSION['sessionuserdata']); + unset($data); + } + } + } + + # + # lädt die Flottenbox + # + function _loadFleetBox() { + $list = user_fleet_list_byuser($this->userdata['uid']); + for($i=1;$i < 3;$i++){ + $item = $list[$i]; + if ($item['arrival']) { + $item['eta'] = $item['arrival']-time(); + $item['orbit'] = $item['ticks']*15*60; + if ($item['eta'] < 0) { + $item['orbit'] = $item['orbit'] + $item['eta']; + $item['eta'] = 0; + if ($item['orbit']< 0) $item['orbit'] = 0; + } + $item['eta'] = $this->formattime($item['eta'],true); + $item['orbit'] = $this->formattime($item['orbit'],true); + } + $item['num'] = $i; + $fleets[] = $item; + } + $this->box['fleets']['title'] = 'Flottenstatus'; + $this->box['fleets']['list'] = $fleets; + $this->box['fleets']['template'] = 'box_fleets_content.html'; + } + + # + # lädt die Takscreenbox + # + function _loadTakscreenBox() { + $this->box['takscreen']['title'] = 'Taktikschirm'; + $this->box['takscreen']['info'] = takscreen_info(); + $this->box['takscreen']['template'] = 'box_takscreen_content.html'; + } + + # + # lädt die Aktivitätsbox + # + function _loadActivityBox() { + $this->box['activity']['title'] = 'Aktivitätscheck'; + if(!($this->box['activity']['docheck'] = do_check_activity($this->userdata))) { + $this->box['activity']['nextcheck'] = date("H:i",$this->userdata['activity_check']+get_activity_timeout())." Uhr"; + } + if($this->userdata['activity_check']) { + $this->box['activity']['lastcheck'] = date("H:i d.m.Y",$this->userdata['activity_check']); + } else { + $this->box['activity']['lastcheck'] = "noch nie!"; + } + $this->box['activity']['points'] = $this->userdata['activity_points']; + $this->box['activity']['template'] = 'box_activity_content.html'; + } + + # + # Erstellt das Hauptmenu + # + function _createMenu() { + global $debug; + #selected menu + if ($_REQUEST['mod']) { + $_SESSION['mod'] = $_REQUEST['mod']; + } + + #create globalmenu + $entry = 0; + $menu[$entry] = array("caption" => "Startseite", "link" => "index.php?mod=index", "module" => "index","id" => $entry); + $menu[$entry]['items'] = array(); + $menu[$entry]['items'][] = array("caption" => "
Member
", "link" => "index.php?action=members"); + $menu[$entry]['items'][] = array("caption" => "
Scanner
", "link" => "index.php?action=scanner"); + $menu[$entry]['items'][] = array("caption" => "
Highscore
", "link" => "index.php?action=highscore"); + + $entry++; + $menu[$entry] = array("caption" => "Taktikschirm", "link" => "takscreen.php?mod=takscreen", "module" => "takscreen","id" => $entry); + $menu[$entry]['items'][] = array("caption" => "
Neuer Atter
", "link" => "takscreen.php?action=addatter"); + $menu[$entry]['items'][] = array("caption" => "
Neuer Deffer
", "link" => "takscreen.php?action=adddeffer"); + $menu[$entry]['items'][] = array("caption" => "
Miliparser
", "link" => "takscreen.php?action=miliparser"); + $menu[$entry]['items'][] = array("caption" => "
Takscreenparser
", "link" => "takscreen.php?action=takparser"); + + $entry++; + $menu[$entry] = array("caption" => "Flottenpflege", "link" => "user.php?mod=fleets&action=fleets", "module" => "fleets","id" => $entry); + $menu[$entry]['items'][] = array("caption" => "
Flottenparser
", "link" => "takscreen.php?action=fleetparser"); + + $entry++; + $menu[$entry] = array("caption" => "Simulator", "link" => "simulator.php?mod=simulator", "module" => "simulator","id" => $entry); + + $entry++; + $menu[$entry] = array("caption" => "Attplaner", "link" => "attplan.php?mod=attplan", "module" => "attplan","id" => $entry); + $menu[$entry]['items'][] = array("caption" => "
Hinzufügen
", "link" => "attplan.php?action=add"); + + $entry++; + $menu[$entry] = array("caption" => "Scancenter", "link" => "scans.php?mod=scans", "module" => "scans","id" => $entry); + $menu[$entry]['items'][] = array("caption" => "
Ziele suchen
", "link" => "scans.php?action=targets"); + $menu[$entry]['items'][] = array("caption" => "
Hinzufügen
", "link" => "scans.php?action=add", "class" => "'admin'"); + + $entry++; + $menu[$entry] = array("caption" => "Allianz", "link" => "admin.php?action=ally&mod=ally", "module" => "ally", "admin" => true,"id" => $entry); + $menu[$entry]['rights'] = array("addally","deleteally","editallay"); + $menu[$entry]['items'][] = array( + "caption" => "
Hinzufügen
", + "link" => "admin.php?action=addally", + "admin" => true, + "rights" => array("addally") + ); + + $entry++; + $menu[$entry] = array("caption" => "Galaxie", "link" => "admin.php?action=galaxy&mod=galaxy", "module" => "galaxy", "admin" => true,"id" => $entry); + $menu[$entry]['rights'] = array("addgala","deletegala","editgala"); + $menu[$entry]['items'][] = array( + "caption" => "
Hinzufügen
", + "link" => "admin.php?action=addgala", + "admin" => true, + "rights" => array("addgala") + ); + $entry++; + $menu[$entry] = array("caption" => "Benutzer", "link" => "admin.php?action=user&mod=user", "module" => "user", "admin" => true,"id" => $entry); + $menu[$entry]['rights'] = array("useredit"); +# $menu[$entry]['items'][$item_entry]['rights'][] = "fleetedit"; + $menu[$entry]['items'][] = array( + "caption" => "
Hinzufügen
", + "admin" => true, + "link" => "admin.php?action=adduser", + "rights" => array("useredit") + ); + $menu[$entry]['items'][] = array( + "caption" => "
Logfile
", + "admin" => true, + "link" => "admin.php?action=logfile", + "rights" => array("logfile","resetlogfile") + ); + $entry++; + $menu[$entry] = array("caption" => "Gruppen", "link" => "admin.php?action=groups&mod=groups", "module" => "groups", "admin" => true,"id" => $entry); + $menu[$entry]['rights'] = array("groupedit"); + $menu[$entry]['items'][] = array( + "caption" => "
Hinzufügen
", + "admin" => true, + "link" => "admin.php?action=addgroup", + "rights" => array("groupedit") + ); + $menu[$entry]['items'][] = array( + "caption" => "
Rechte
", + "admin" => true, + "link" => "admin.php?action=grouprights", + "rights" => array("groupedit") + ); + $entry++; + $menu[$entry] = array("caption" => "IRCBots", "link" => "admin.php?action=bots&mod=bots", "module" => "bots", "admin" => true, "rights" => array("bots"),"id" => $entry); + $menu[$entry]['items'][] = array( + "caption" => "
Rechte
", + "admin" => true, + "link" => "admin.php?action=grouprights", + "rights" => array("groupedit") + ); + + $menucount = count($menu); + $open_menus = $_COOKIE['menuitems']; + if($open_menus) { + $open_menus = explode(",",$open_menus); + } else { + $open_menus = array(); + } + for($i = 0;$i < $menucount; $i++) { + if(!in_array($menu[$i]['id'],$open_menus)) { + $menu[$i]['closed'] = true; + } + if(count($menu[$i]['rights'])) { + #check rights for the menu + $hasright = false; + if(count($this->userdata['rights'])) { + for($j=0;$j < count($menu[$i]['rights']);$j++) { + if(array_key_exists($menu[$i]['rights'][$j],$this->userdata['rights'])) { + $hasright = true; + break; + } + } + } + #delete menu and submenus + if(!$hasright) {unset($menu[$i]);continue;} + } + #check submenus + if(count($menu[$i]['items'])) { + $items = &$menu[$i]['items']; + $itemcount = count($items); + for($j=0;$j < $itemcount;$j++) { + #check rights for the submenu + if(count($items[$j]['rights'])) { + $hasright = false; + if(count($this->userdata['rights'])) { + for($k=0;$k < count($items[$j]['rights']);$k++) { + if(array_key_exists($items[$j]['rights'][$k],$this->userdata['rights'])) { + $hasright = true; + break; + } + } + } + #delete submenu + if(!$hasright) {unset($items[$j]);continue;} + } + } + } + } + $this->box['menu']['template'] = 'menu.html'; + $this->box['menu']['title'] = 'Menu'; + $this->template->assign('menu',$menu); + } + + # + # User Login + # + + function _loginUser() { + if ($_POST['userlogin']) { + #check fields + $logindata['username'] = trim($_POST['login_username']); + $logindata['password'] = trim($_POST['login_password']); + $errors = false; + foreach ( $logindata as $key => $value) { + if (!$value) { + $this->forms['userlogin']['fields'][$key]['bgrd'] = '_error'; + $errors = true; + } else { + $this->forms['userlogin']['fields'][$key]['value'] = $value; + } + } + #empty fields + if ($errors) { + $this->forms['userlogin']['errormessage'] = "Feld leer!"; + } else { + $return = getUserByLogin($logindata['username'],$logindata['password']); + if (!$return || $return['activation']) { + #login wrong + $this->forms['userlogin']['errormessage'] = "Login/Passwort falsch!"; + addToLogfile("Login fehlgeschlagen, User ".$logindata['username'],"Login/Logout"); + } else { + #login ok + #save id and password in session + $sessionuserdata['id'] = $return['uid']; + $sessionuserdata['password'] = $return['password']; + $_SESSION['sessionuserdata'] = $sessionuserdata; + LoggedIn($return['uid']); + addToLogfile("Login","Login/Logout",$return['uid']); + setcookie('menuitems'); + $this->_header("index.php"); + } + } + } + $this->template->assign('title','Login'); + $this->template->assign('forms',$this->forms); + $this->template->display('index_login.html'); + exit(); + } + + # + # User Logout + # + function _logoutUser() { + addToLogfile("Logout","Login/Logout",$this->userdata['uid']); + deleteUserOnline($this->userdata['uid']); + unset($_SESSION['sessionuserdata']); + setcookie('menuitems'); + $this->_header("index.php"); + exit(); + } + # + # liefert null wenn der user das Recht nicht besitzt, sonst den minimalen rank + # + function _getMinRightRank($rights) { + $rank = null; + if ($this->userdata) { + if (is_array($rights)) { + for($i=0;$iuserdata['rights'][$rights[$i]]['rank'])) { + $rank[] = $this->userdata['rights'][$rights[$i]]['rank']; + } + } + if ($rank){ + $rank = min($rank); + } + } else { + $rank = $this->userdata['rights'][$rights]['rank']; + } + } + return $rank; + } + + # + # liefert TRUE wenn der User das Recht oder eins der Rechte hat + # (für Zugangscheck) + # param $rights = right|array of rights + # + function _checkUserRights($rights) { + if ($this->userdata) { + if (is_array($rights)) { + for($i=0;$iuserdata['rights'][$rights[$i]]) { + return true; + } + } + } else { + if ($this->userdata['rights'][$rights]) return true; + } + } + return false; + } + + function getTickList($ticks=1,$select=-1) { + $list=array(); + for($i=1;$i <= $ticks;$i++){ + if($select == $i) { + $list[] = array("value"=>$i,"title"=>$this->formattime($i*15*60,true), "selected" => "selected"); + } else { + $list[] = array("value"=>$i,"title"=>$this->formattime($i*15*60,true)); + } + } + return $list; + } + + function formattime($time,$string=false) { + if (!is_numeric($time)) return; + if($time >= 0) { + $switch = $this->userdata['timeview']; + } else { + $switch = 0; + } + switch ($switch) { + case 1: + $hour = floor($time/3600); + $minutes = floor(($time-$hour*3600)/60); + if ($hour < 10 && $hour > 0) $hour = "0".$hour; + if ($hour == 0) $hour = "00"; + if ($minutes < 10) $minutes = "0".$minutes; + $time = "$hour:$minutes"; + if ($string) $time .= " Std"; + break; + default: + $time = floor($time/60); + if ($string) $time .= " min"; + break; + } + return $time; + } + + function show_message($title,$message,$link,$class=null,$params=null) { + $this->template->assign( + array("title" => $title, + "message" => $message, + "link" => $link, + "class" => $class, + "params" => $params) + ); + $this->show('message',$title); + } +} +?> diff --git a/src/classes/page.class.php b/src/classes/page.class.php new file mode 100644 index 0000000..a165aec --- /dev/null +++ b/src/classes/page.class.php @@ -0,0 +1,162 @@ +"; + if(is_array($msg)) { + var_dump($msg); + } else { + echo $msg."\n"; + } + if($tracking) { + $debug_tracking = debug_backtrace(); + for ($i=0;$i < $tracking;$i++) { + echo $debug_tracking[$i]['file'].":".$debug_tracking[$i]['line']."\n"; + } + } + echo ""; + } + + class Page { + /** + \brief Templateobjekt + + Smarty templateobjekt, hilfe unter http.smarty.php.net + */ + var $template; + /** + \brief Sessiondaten + + Sessiondaten als Array + */ + var $session; + + /** + \brief Aktion + + per GET oder POST �bergebener "action" Parameter + */ + var $action; + + /** + \brief debugmodus + + true setzen f�r debugmodus AN + */ + var $debug; + + + /** + \brief Constructor + + Initialisiert das system. + */ + function Page () { + + //load Template Engine + $this->template = new Smarty(); + $this->template->plugins_dir = SMARTY_DIR."plugins/"; + if (!$this->template) $this->_error("Templateengine l�sst sich nicht starten!"); + + //start session + $this->_startSession("ssid"); + + } + + function _error($msg) { + #$this->_dump($msg); + exit(); + } + + + # + # Run & Eventhandler + # + function run ($debug=0) { + + #debugmode + $this->debug = $debug; + $this->action = $_REQUEST["action"]; + } + + # + # Sendet einen Redirect Header + # + function _header($link,$message="") { + if(preg_match("/^(.*?)(#.*?)$/is",$link,$items)) { + $link = $items[1]; + $anker = $items[2]; + } + if (strpos($link,"?")) { + header("Location: ".$link."&".$this->session['link'].$anker); + } else { + header("Location: ".$link."?".$this->session['link'].$anker); + } + exit(); + } + + # + # startet die Session + # + function _startSession ($name="") { + global $session_save_path; + #start session + if($name) session_name($name); + else $name = session_name(); + session_save_path($session_save_path); + session_start(); + $this->session = array(); + $this->session['id'] = $_SESSION[$name]; + $this->session['name'] = $name; + if(!$this->session['id']) { + $this->session['id'] = $_REQUEST[$name]; + if (!$this->session['id']) { + $this->session['id'] = session_id(); + } + $_SESSION[$name] = $this->session['id']; + } + $this->session['link'] = "$name=".$this->session['id']; + $this->template->assign('session',$this->session); + } +} + +?> diff --git a/src/classes/scans.class.php b/src/classes/scans.class.php new file mode 100644 index 0000000..554cfd6 --- /dev/null +++ b/src/classes/scans.class.php @@ -0,0 +1,367 @@ +action]) { + eval("\$this->".$functions[$this->action].";"); + } + #default + $this->_listScans("scans"); + } + + # + # fügt einen oder mehrere Scans hinzu + # + function _addScan() { + if ($_REQUEST['send']) { + $data = $_POST['data']; + if ($data) { + $scans = parseScan($data); + if ($scans) { + $this->forms['addscan']['message'] ="Folgende Scans wurden erkannt:

"; + $this->template->assign("scanlist",$scans); + for ($i=0;$iforms['addscan']['message'] = "
Scan(s) nicht erkannt
"; + } + # $this->forms['addscan']['fields']['data']['value'] = $data; + } else { + $this->forms['addscan']['message'] = "
Feld leer
"; + } + } else { + $this->forms['addscan']['message'] = "Der Scanner arbeitet mit Copy&Paste. Dabei ist es egal ob ihr + den Scan aus dem IRC Channel kopiert, oder den IRC Copy Knopf benutzt.Beim Kopieren aus dem IRC heraus ist nur wichtig, + daß ihr die kompletten Zeilen kopiert. (mit nickname, uhrzeit, was weiß ich nicht noch alles).Zeilen die nicht zum scan gehören + werden vom Parser ignoriert. Vorhandene Scans werden upgedated, fehlende neu hinzugefügt.Weiterhin werden beliebig viele Scans +gleichzeitig +geparst, + ihr könnt also alle Scans mit einem Mal einfügen.

+ Unterstütze Formate:
+ Galaxy Network Scan
"; + } + $this->forms['addscan']['action'] = "add"; + $this->forms['addscan']['url'] = "scans.php"; + $this->show('scan_add_form','Scan hinzufügen/updaten'); + } + # + # zeigt scandetails an + # + function scan_details($gala,$pos) { + $scan = getScan(array("gala" => $gala, "pos" => $pos)); + $this->template->assign("gala",$gala); + $this->template->assign("pos",$pos); + $this->template->assign("scan",scan_format($scan)); + $this->show('scan_details',"Details von ($gala:$pos)"); + } + + # + # Listet die Scans auf + # + function _listScans($option) { + $gala = param_num("gala"); + $pos = param_num("pos"); + #scandetails + if($gala && $pos) $this->scan_details($gala,$pos); + #scanlist + $page = param_num("page",1); + $rows = 20; + + $link_options = array(); + + if ($option == "targets") { + $scanlistfilter = & $_SESSION['targetlistfilter']; + $this->template->assign("showtargets",1); + $this->template->assign("scantitle","Ziele suchen"); + #zielsuche + if ($_REQUEST['subaction'] == 'newsearch' && $scanlistfilter) { + unset($_SESSION['targetlistfilter']); + unset($scanlistfilter); + } +/* if ($_REQUEST['subaction'] == "search") { + $scanlistfilter['exen'] = param_num("exen"); + $scanlistfilter['punkte'] = param_num("punkte"); + } + */ + if (!$scanlistfilter || $_POST['subaction'] == "search") { + $form = new formContainer(); + $form->add(new formInput("exen","Exenmindestanzahl","numeric",true,10,true)); + $form->add(new formInput("macht","Machtmindestwert","numeric",true,10,true)); + $form->add(new formCheckbox("hideold","Alte Scans nicht berücksichtigen","numeric",array(1),false)); + if($_POST['send']) { + $form->submit(); + if(!$form->hasErrors()) { + if($form->get("macht")) $scanlistfilter['macht'] = $form->get("macht"); + if($form->get("exen")) $scanlistfilter['exen'] = $form->get("exen"); + $scanlistfilter['sort'] = "exen"; + $scanlistfilter['order'] = "desc"; + $scanlistfilter['hassektor'] = "1"; + $scanlistfilter['hideold'] = $form->get("hideold"); + $scanlistfilter['except_galas'] = getGalaList(true); + $this->_header("scans.php?action=targets&send"); + } + } else { + $form->select("hideold",1); + } + + $form->registerVars($this->template); + $this->show('scan_target_form','Ziele suchen'); + } + #sortierung + if ($_REQUEST['sort'] && $_REQUEST['order'] && $scanlistfilter) { + $sort = trim($_REQUEST['sort']); + $order = trim($_REQUEST['order']); + if ($sort != 'koords' && $sort != 'exen') $sort = 'koords'; + if ($order != "asc" && $order != "desc") $order = "asc"; + $scanlistfilter['sort'] = $sort; + $scanlistfilter['order'] = $order; + } + $link_options[] = "action=targets"; + $link2 = "?action=targets"; + #normale Scananzeige, galaweise + } else { + $scanlistfilter = &$_SESSION['scanlistfilter']; + $this->template->assign("scantitle","Scans"); + if (!$scanlistfilter) { + $scanlistfilter['gala'] = 1; + $scanlistfilter['sort'] = "koords"; + $scanlistfilter['order'] = "asc"; + $scanlistfilter['hideold'] = 1; + } + #alte einblenden/ausblenden + if (isset($_REQUEST["hideold"]) && is_numeric($_REQUEST["hideold"])) { + $scanlistfilter['hideold'] = $_REQUEST["hideold"]; + } + $hideold = $scanlistfilter["hideold"]; + if ($hideold){ + $title = "Alle Anzeigen"; + $subtitle = "Zeigt alle Scans an"; + $param = 0; + } else { + $title = "Alte Ausblenden"; + $subtitle = "Scans die älter als 1 Tag sind werden nicht angezeigt"; + $param = 1; + } + $this->template->assign("hideoldtitle",$title); + $this->template->assign("hideoldparam",$param); + $this->template->assign("hideoldsubtitle",$subtitle); + #neue gala anzeigen + if ($gala = param_num("gala")) { + $scanlistfilter['gala'] = $gala; + } else { + $gala = $scanlistfilter["gala"]; + } + if ($this->userdata["gid"] == 1) { $hideblock = false; } else { $hideblock = true; } + $next = getNextGala($gala,$hideold,$hideblock); + $prev = getPrevGala($gala,$hideold,$hideblock); + if ($next && $prev) { + #gala suche anzeigen + $this->template->assign("showform",1); + } + #zeigen beide auf die selbe, -> die aktuelle + if ($next == $prev && $next == $gala) { + unset($prev); + unset($next); + } + $this->template->assign("prev",$prev); + $this->template->assign("next",$next); + #sortierung + if ($_REQUEST['sort'] && $_REQUEST['order'] && $scanlistfilter) { + $sort = trim($_REQUEST['sort']); + $order = trim($_REQUEST['order']); + if ($sort != 'koords' && $sort != 'exen') $sort = 'koords'; + if ($order != "asc" && $order != "desc") $order = "asc"; + $scanlistfilter['sort'] = $sort; + $scanlistfilter['order'] = $order; + } + $link_options[] = "gala=".$scanlistfilter['gala']; + } + #mili & news ausklappen + $expand = param_num("expand"); + #scans holen + $this->forms['scanlist'][$scanlistfilter['sort']][$scanlistfilter['order']] = '_active'; + $scanlist = listScans($scanlistfilter,&$pages,&$page,$rows); + for ($i=0;$iuserdata['uid']) { + $scanlist[$i]['atter_class'] = "green"; + } else { + $scanlist[$i]['atter_class'] = "red"; + } + } + $scanlist[$i] = scan_format($scanlist[$i]); + } + + $this->forms['scanlist']['pages'] = showPageBar($page,$pages,"scans.php".$link2,"page","menu"); + $this->forms['scanlist']['gala'] = $scanlistfilter['gala']; + + $this->template->assign('scanlist',$scanlist); + $this->template->assign('page',$page); + + $this->show('scan_list','Scans'); + } + + ################################### + + + + + /*function _Target_set() { + $id = param_num("id"); + if (!$id) { + #kein target da + if ($_POST['step']) { + $items['gala']['value'] = param_num("gala"); + $items['pos']['value'] = param_num("pos"); + if (!$items['pos']['value']) { + $errors[] = "Position fehlt oder ungültig!"; + $items['pos']['class'] = "_error"; + } + if (!$items['gala']['value']) { + $errors[] = "Galaxie fehlt oder ungültig!"; + $items['gala']['class'] = "_error"; + } + if (!$errors){ + $scan = getScan($items['gala']['value'],$items['pos']['value']); + if (!$scan) { + $id = addMainScan($items['gala']['value'],$items['pos']['value']); + } else { + $id = $scan['sid']; + } + if ($scan['closed']) { + $errors[] = "Ziel ist bereits reserviert"; + } + } + } + $this->template->assign("showcomplete",1); + } else { + $scan = getScanbyId($id); + if (!$scan) $this->_header(back_link(),"ungültig: $id"); + if ($scan['closed']) $this->_header(back_link(),"Target geschlossen"); + } + if ($_POST['step']) { + $items['fleet']['value'] = param_num("fleet"); + $items['time']['value'] = $_POST['time']; + #flotte ungültig + if ($items['fleet']['value'] != 1 && $items['fleet']['value'] != 2) { + $this->_header(back_link(),"Ungültige flotte"); + } + if ($items['time']['value']) { + if (!preg_match("/(\d{1,2}):(\d{2})/i",$items['time']['value'],$data)) { + $errors[] = "Ungültige Zeit!"; + $items['time']['class'] ="_error"; + } + } + if (!$errors) { + if($atter = getAtter($this->userdata['uid'],$items['fleet']['value'])) { + $errors[] = "Flotte ".$items['fleet']['value']." bereits für (".$atter['gala'].":".$atter['pos'].") eingetragen"; + } + } + if (!$errors) { + if (addAtter($id,$this->userdata['uid'],$items['fleet']['value'],$items['time']['value']) != -1) { + $this->_header(back_link()); + } else { + $errors[] = "DB Error"; + } + } + $this->template->assign("errors",$errors); + } else { + $items['time']['class'] = "_optional"; + $items['fleet']['value'] = 1; + } + $this->template->assign("fleet".$items['fleet']['value'],"checked"); + $this->template->assign("items",$items); + $this->template->assign("id",$id); + $this->show('scan_target_set','Ziel reservieren'); + } + ############################################################### + function _Target_close() { + #exists id ? + $id = param_num("id"); + if (!$id) $this->_header(back_link(),"fehlende id"); + #exists scan ? + $scan = getScanbyId($id); + if (!$scan) $this->_header(back_link(),"ungültig: $id"); + # is atter ? + $atterlist = getAtterlist($id); + $isatter = 0; + for($j=0;$j < count($atterlist);$j++){ + $atter = &$atterlist[$j]; + if ($atter['uid'] == $this->userdata['uid']) { + $isatter = 1; + break; + } + } + if (!$isatter) $this->_header(back_link(),"no permission"); + if (!$scan['closed']) { + closeTarget($id); + } + $this->_header(back_link()); + } + ############################################################### + function _Target_open() { + #exists id ? + $id = param_num("id"); + if (!$id) $this->_header(back_link(),"fehlende id"); + #exists scan ? + $scan = getScanbyId($id); + if (!$scan) $this->_header(back_link(),"ungültig: $id"); + # is atter ? + $atterlist = getAtterlist($id); + $isatter = 0; + for($j=0;$j < count($atterlist);$j++){ + $atter = &$atterlist[$j]; + if ($atter['uid'] == $this->userdata['uid']) { + $isatter = 1; + break; + } + } + if (!$isatter) $this->_header(back_link(),"no permission"); + if ($scan['closed']) { + openTarget($id); + } + $this->_header(back_link()); + } + ############################################################### + function _Target_drop() { + #exists id ? + $uid = param_num("uid"); + $fleet = param_num("fleet"); + if (!$uid || !$fleet) $this->_header(back_link(),"fehlende id"); + if ($fleet != 1 && $fleet != 2) $this->_header(back_link(),"falsche flotte"); + #exists scan ? + $atter = getAtter($uid,$fleet); + # is atter ? + if (!$atter) $this->_header(back_link(),"atter nicht gefunden"); + if ($atter['uid'] != $this->userdata['uid']) + $this->_header(back_link(),"no permission"); + deleteAtter($uid,$fleet); + $this->_header(back_link()); + } */ + +} +?> diff --git a/src/classes/simulator.class.php b/src/classes/simulator.class.php new file mode 100644 index 0000000..f49bde9 --- /dev/null +++ b/src/classes/simulator.class.php @@ -0,0 +1,303 @@ +action]) { + # eval("\$this->".$functions[$this->action].";"); + # } + #default + $this->_showSimulator(); + } + # + # stellt den Simulator dar mit allen Funktionen + # + function _showSimulator() { + for ($i=0;$i < 14;$i++) { + if (isset($_REQUEST['deff'.$i]) && is_numeric($_REQUEST['deff'.$i]) && $_REQUEST['deff'.$i] >= 0) { + $deff[$i] = $_REQUEST['deff'.$i]; + } else { + $deff[$i] = 0; + } + } + for ($i=0;$i < 9;$i++) { + if (isset($_REQUEST['attack'.$i]) && is_numeric($_REQUEST['attack'.$i]) && $_REQUEST['attack'.$i] >= 0) { + $attack[$i] = $_REQUEST['attack'.$i]; + } else { + $attack[$i] = 0; + } + } + + $kristall = param_num("kristall",0); + $metall = param_num("metall",0); + + $Simu = new GNSimu(); + $Simu->attacking = $attack; + $Simu->deffending = $deff; + $Simu->mexen = $metall; + $Simu->kexen = $kristall; + + $ticks = param_num("ticks",1); + + $fleets_loaded = $_SESSION['fleets_loaded']; + + if ($_POST['send']) { + if ($fleets_loaded){ + for ($i=0;$i"; + $attack[0] -= $fleets_loaded[$i]['jaeger']; + $attack[1] -= $fleets_loaded[$i]['bomber']; + $attack[2] -= $fleets_loaded[$i]['fregatten']; + $attack[3] -= $fleets_loaded[$i]['zerstoerer']; + $attack[4] -= $fleets_loaded[$i]['kreuzer']; + $attack[5] -= $fleets_loaded[$i]['schlachter']; + $attack[6] -= $fleets_loaded[$i]['traeger']; + $attack[7] -= $fleets_loaded[$i]['kleptoren']; + $attack[8] -= $fleets_loaded[$i]['cancris']; + for ($j=0;$juserdata) { + unset($_SESSION['fleets_loaded']); + unset($fleets_loaded); + for ($i=0;$iuserdata) { + $loadattfleet = $_POST['loadattfleet']; + $userfleet = user_fleet_sum($loadattfleet); + $user = getUserByID($loadattfleet); + #user wrong or no fleet + if (!$userfleet) { + $this->_header("index.php","Userid falsch oder keine Flotte"); + } + #wrong attfleet, no permission + if (!$this->userdata['rights']['admin'] && !$this->userdata['rights']['attorga'] && $user['aid'] != $this->userdata['aid']){ + $this->_header("index.php","Keine Rechte zum Flotte laden"); + } + for ($i=0;$ivorticks(0); + if ($_POST['vorticks'] && $tickload != 0) { + $Simu->vorticks(1); + } + } + for ($i=2;($i< $tickload);$i++) { + $Simu->Compute(0); + } + if ($tickload > 1) { + if ($ticks == $tickload-1) { + #den letzten tick laden + $Simu->Compute(1); + } else { + #tick laden + $Simu->Compute(0); + } + } + $attack = $Simu->attacking; + $deff = $Simu->deffending; + } + if ($_POST['calculate']) { + if ($_POST['vorticks']) { + $Simu->vorticks(0); + $tick[1] = $Simu->attacking; + $tick[0] = $Simu->Oldatt; + $tick[3] = $Simu->deffending; + $tick[2] = $Simu->Olddeff; + $tick['metall'] = $Simu->stolenmexen; + $tick['kristall'] = $Simu->stolenkexen; + $tick['name'] = "Vortick 1"; + $tick['nr'] = 0; + $ticklist[] = $tick; + $Simu->vorticks(1); + $tick[1] = $Simu->attacking; + $tick[0] = $Simu->Oldatt; + $tick[3] = $Simu->deffending; + $tick[2] = $Simu->Olddeff; + $tick['metall'] = $Simu->stolenmexen; + $tick['kristall'] = $Simu->stolenkexen; + $tick['name'] = "Vortick 2"; + $tick['nr'] = 1; + $ticklist[] = $tick; + } + for ($i=0;$i<$ticks-1;$i++) { + $Simu->Compute(0); + $tick[1] = $Simu->attacking; + $tick[0] = $Simu->Oldatt; + $tick[3] = $Simu->deffending; + $tick[2] = $Simu->Olddeff; + $tick['metall'] = $Simu->stolenmexen; + $tick['kristall'] = $Simu->stolenkexen; + $tick['name'] = "Tick ".($i+1); + $tick['nr'] = $i+2; + $ticklist[] = $tick; + } + $Simu->Compute(1); + $tick[1] = $Simu->attacking; + $tick[0] = $Simu->Oldatt; + $tick[3] = $Simu->deffending; + $tick[2] = $Simu->Olddeff; + $tick['metall'] = $Simu->stolenmexen; + $tick['kristall'] = $Simu->stolenkexen; + $tick['name'] = "Tick ".$ticks; + $tick['nr'] = $ticks+1; + $ticklist[] = $tick; + $this->template->assign('ticklist',$ticklist); + $this->template->assign('attlost',$Simu->geslostshipsatt); + $this->template->assign('defflost',$Simu->geslostshipsdeff); + $ress[0][0] = $Simu->getlostmetall[0]; + $ress[1][0] = $Simu->getlostmetall[1]; + $ress[0][1] = $Simu->getlostkristall[0]; + $ress[1][1] = $Simu->getlostkristall[1]; + $ress[0][2] = $ress[0][1]+$ress[0][0]; + $ress[1][2] = $ress[1][1]+$ress[1][0]; + + for ($i=0;$i<2;$i++) { + for ($j=0;$j<3;$j++) { + $ress[$i][$j] = substr_replace(strrev(chunk_split(strrev($ress[$i][$j]),3,'.')),'',0,1); + } + } + $this->template->assign('ress',$ress); + $this->template->assign('metallstolen',$Simu->gesstolenexenm); + $this->template->assign('kristallstolen',$Simu->gesstolenexenk); + } + $this->template->assign('deffsel'.$ticks,'selected'); + if ($_POST['vorticks']) $this->template->assign('vortickssel','checked'); + $this->template->assign('attfleetselect'.$_POST['attfleetselect'],'selected'); + } else { + $this->template->assign('deffsel1','selected'); + $this->template->assign('attfleetselect1','selected'); + } + + $this->template->assign('metall',$metall); + $this->template->assign('kristall',$kristall); + $this->template->assign('deff',$deff); + $this->template->assign('attack',$attack); + + $attfleets = array(); + if ($this->userdata['rights']['attorga'] == 1) { + $except = array(); + #for ($i=0;$iuserdata['aid']); +# if ($this->userdata['fleetupdate']) { +# $attfleets[] = array("id" => $this->userdata['uid'],"wert" => $this->userdata['nick']." (".$this->userdata['gala'].":".$this->userdata['pos'].")"); +# } + # if (!$fleets_loaded[0] && $this->userdata['fleet']) { + # $attfleets[] = array("id" => $this->userdata['uid'],"wert" => $this->userdata['nick']." (".$this->userdata['gala'].":".$this->userdata['pos'].")"); + # } + } + for ($i=0;$itemplate->assign("fleets_loaded",$fleets_loaded); + $this->template->assign("attfleets",$attfleets); + $this->show('simulator_form','Kampfsimulator'); + } + +} +?> \ No newline at end of file diff --git a/src/classes/takscreen.class.php b/src/classes/takscreen.class.php new file mode 100644 index 0000000..8baf2d4 --- /dev/null +++ b/src/classes/takscreen.class.php @@ -0,0 +1,2012 @@ +action]) { + eval("\$this->".$functions[$this->action].";"); + } + #default + $this->Incoming_list(); + } + ############################################################################# + function _match_atter($gala,$pos,$line,$messages,$errors) { + $user_atterlist = fleetstatus_get_bytarget($gala,$pos,1); + $insert = array(); + if(preg_match_all("/(\d{1,4}):(\d{1,2})(.*?)
/ism",$line[8],$tak_atterlist,PREG_SET_ORDER)) { + if(count($tak_atterlist)){ + $tak_timelist = parse_time($line[9]); + #atterliste + for($j=0;$j < count($tak_atterlist);$j++){ + unset($atter); + $tak_eta = $tak_timelist[$j]; + if($tak_eta == "error") { + $errors[] = "atter (".$tak_atterlist[$j][1].":".$tak_atterlist[$j][2].") zeit nicht erkannt"; + continue; + } + #5 ticks im orbit + if ($tak_eta == 0) { + $tak_eta_low = -75; + $tak_eta_high = 0; + } else { + #toleranz von einem tick + $tak_eta_low = $tak_eta - 14; + $tak_eta_high = $tak_eta + 14; + } + #passenden Atter finden + for($k=0;$k < count($user_atterlist);$k++){ + $eta = floor(($user_atterlist[$k]['arrival'] - time())/60); + if( $user_atterlist[$k]['gala'] == $tak_atterlist[$j][1] && + $user_atterlist[$k]['pos'] == $tak_atterlist[$j][2] && + !($user_atterlist[$k]['checked']) && + $eta > $tak_eta_low && + $eta < $tak_eta_high + ) { + #passenden atter gefunden + $atter = &$user_atterlist[$k]; + break; + } + } + if (isset($atter)) { + #atter matched + $atter['checked'] = true; + } else { + $insert[] = array( + "gala" => trim($tak_atterlist[$j][1]), + "pos" => trim($tak_atterlist[$j][2]), + "tgala" => $gala, + "tpos" => $pos, + "fleetnum" => 2, + "eta" => $tak_eta, + "nick" => trim($tak_atterlist[$j][3]) + ); + } + } + } + } + if(!$errors) { + #incs auf recall prüfen + for($j=0;$j < count($user_atterlist);$j++){ + $atter = &$user_atterlist[$j]; + + if(!$atter['checked']) { + #nach zweiter flotte suchen die im selben tick fliegt aber nicht recallt hat + $eta = floor(($atter['arrival']-time())/60); + if ($eta > 0) { + $eta_high = $eta + 14; + $eta_low = $eta-14; + if($eta_low < 0) { + $eta_low = 1; + } + } else { + $eta_low = 0; + $eta_high = 0; + } + $found = false; + for($k=0;$k < count($user_atterlist);$k++){ + $eta_search = floor(($user_atterlist[$k]['arrival']-time())/60); + #im orbit + if($eta_search < 0) { + $eta_search = 0; + } + if( $user_atterlist[$k]['checked'] && + $user_atterlist[$k]['gala'] == $atter['gala'] && + $user_atterlist[$k]['pos'] == $atter['pos'] && + $eta_search >= $eta_low && + $eta_search <= $eta_high + ) { + #flotte gefunden die im selben tick fliegt und gematcht wurde + #-> unklar welche von beiden recallt hat + $messages[] = "(".$atter['gala'].":".$atter['pos'].") ".$atter['nick']." attet mit 2 Flotten und hat eine von beiden recallt, bitte überprüfen"; + $found = true; + break; + } + } + if(!$found){ + $messages[] = "Atter (".$atter['gala'].":".$atter['pos'].") ".$atter['nick']." Flotte ".$atter['fleetnum']." ETA ".$this->formattime($atter['arrival']-time(),true)." hat recalled"; + fleetstatus_recall($atter['fsid']); + } + } + } + foreach ($insert as $line) { + atter_add( + $line['gala'], + $line['pos'], + $line['tgala'], + $line['tpos'], + &$line['fleetnum'], + $line['eta'], + null, + $line['nick'] + ); + $messages[] = "Atter (".$line['gala'].":".$line['pos'].") ".$line['nick']." Flotte ".$line['fleetnum']." ETA ".$this->formattime($line['eta']*60,true)." hinzugefügt"; + } + } + } + + function _match_deffer($tgala,$tpos,$line,$messages,$errors) { + unset($defferadd_list); + $user_defferlist = fleetstatus_get_bytarget($tgala,$tpos,2); + if(preg_match_all("/(\d{1,4}):(\d{1,2})(.*?)
/ism",$line[10],$tak_list,PREG_SET_ORDER)) { + if(count($tak_list)){ + $tak_timelist = parse_time($line[11]); + #defferliste + for($j=0;$j < count($tak_list);$j++){ + unset($deffer); + $tak_eta = $tak_timelist[$j]; + if($tak_eta == "error") { + $errors[] = "deffer (".$tak_list[$j][1].":".$tak_list[$j][2].") zeit nicht erkannt"; + continue; + } + #20 ticks im orbit + if ($tak_eta == 0) { + $tak_eta_low = -300; + $tak_eta_high = 0; + } else { + #toleranz von einem tick + $tak_eta_low = $tak_eta - 14; + $tak_eta_high = $tak_eta + 14; + } + #passenden deffer finden + for($k=0;$k < count($user_defferlist);$k++){ + $eta = floor(($user_defferlist[$k]['arrival']-time())/60); + if( $user_defferlist[$k]['gala'] == $tak_list[$j][1] && + $user_defferlist[$k]['pos'] == $tak_list[$j][2] && + !($user_defferlist[$k]['checked']) && + $eta > $tak_eta_low && + $eta < $tak_eta_high + ) { + #passenden deffer gefunden! + $deffer = &$user_defferlist[$k]; + break; + } + } + if($deffer){ + $deffer['checked'] = true; + } else { + $gala = trim($tak_list[$j][1]); + $pos = trim($tak_list[$j][2]); + $nick = trim($tak_list[$j][3]); + $adddeffer = array( + "gala" => $gala,"pos" => $pos,"nick" => $nick,"fleetnum" => 1,"eta" => $tak_eta + ); + $messages[] = "Deffer (".$gala.":".$pos.") ".$nick." Flotte 1 ETA ".$this->formattime($tak_eta*60,true)." hinzugefügt"; + + + $defferadd_list[] = $adddeffer; + } #else + } #for + } #if count(tak:list) + } # if (pregmatchall) + if(!$errors) { + #deffer auf recall prüfen + for($j=0;$j < count($user_defferlist);$j++){ + $deffer = &$user_defferlist[$j]; + if(!$deffer['checked']) { + #nach zweiter flotte suchen die im selben tick fliegt aber nicht recallt hat + $eta = floor(($deffer['arrival']-time())/60); + $gala = $deffer['gala']; + $pos = $deffer['pos']; + $nick = $deffer['nick']; + if ($eta > 0) { + $eta_high = $eta + 14; + $eta_low = $eta-14; + if($eta_low < 0) { + $eta_low = 1; + } + } else { + $eta_low = 0; + $eta_high = 0; + } + $found = false; + for($k=0;$k < count($user_defferlist);$k++){ + $eta_search = floor(($user_defferlist[$k]['arrival']-time())/60); + #im orbit + if($eta_search < 0) { + $eta_search = 0; + } + if( $user_defferlist[$k]['checked'] && + $user_defferlist[$k]['gala'] == $gala && + $user_defferlist[$k]['pos'] == $pos && + $eta_search >= $eta_low && + $eta_search <= $eta_high + ) { + $found = true; + break; + } + } + if(!$found){ + $messages[] = "Deffer (".$gala.":".$pos.") ".$nick." Flotte ".$deffer['fleetnum']." ETA ".$this->formattime(($deffer['arrival']-time()),true)." hat recalled"; + fleetstatus_recall($deffer['fsid']); + } else { + #flotte gefunden die im selben tick fliegt und gematcht wurde + #-> unklar welche von beiden recallt hat + $messages[] = "(".$gala.":".$pos.") ".$nick." defft mit 2 Flotten im selben Tick und hat eine von beiden recallt, bitte überprüfen "; + } #else + } #if not deffer_checked + } #for + #deffer in die db eintragen + for($j=0;$j < count($defferadd_list);$j++){ + $deffer = &$defferadd_list[$j]; + if(($check = fleetstatus_get_bykoords($deffer['gala'],$deffer['pos'],$deffer['fleetnum']))) { + if($check['return_flight']){ + fleetstatus_delete($check['fsid']); + } else { + if($deffer['fleetnum'] == 1) $deffer['fleetnum'] = 2; + else $deffer['fleetnum'] = 1; + } + } + deffer_add( + $deffer['gala'], + $deffer['pos'], + $tgala, + $tpos, + $deffer['fleetnum'], + 360, + 300, + $deffer['eta'], + $deffer['nick'] + ); + } + } + } + + function _is_matched_fleet($db_fleet,$parsed_fleet) { + if( $db_fleet['return_flight'] != $parsed_fleet['return_flight'] || + $db_fleet['status'] != $parsed_fleet['status'] || + $db_fleet['gala'] != $parsed_fleet['gala'] || + $db_fleet['pos'] != $parsed_fleet['pos'] + ) { + return false; + } + $eta_db = ($db_fleet['arrival']-time())*60; + if(abs($eta_db - $parsed_fleet['eta']) > 14 && $eta_db > 0) return false; + return true; + } + + function _match_user(&$user,$line) { + #attflotten matching +# var_dump($line); +# echo "

"; + $fleet_list = array(); + if(preg_match_all("'(?:(Rückflug)\s*?
|)[\s\(]*?(\d{1,4}):(\d{1,2})\s*?([^\s\)<]+).*?
'is",$line[4],$att_fleets,PREG_SET_ORDER)) { + $timelist = parse_time($line[5]); + for($i=0;$i < count($att_fleets);$i++) { + $fleet = &$att_fleets[$i]; + if($fleet[1] == "Rückflug") { + $fleet['return_flight'] = 1; + } else { + $fleet['return_flight'] = 0; + } + $fleet['status'] = 1; + if($fleet['return_flight']) { + $title = "Angriff Rückflug von"; + $select = "Angriff Rückflug von"; + } else { + $title = "Angriff auf"; + $select = "Angriff auf"; + } + $eta = $timelist[$i]*60; + $title .= " $fleet[4] ($fleet[2]:$fleet[3]) ETA ".$this->formattime($eta,true); + $select .= " $fleet[4] ($fleet[2]:$fleet[3]) ETA ".$this->formattime($eta,true); + $fleet_list[] = array("status" => $fleet['status'],"gala" => $fleet[2],"pos" => $fleet[3],"nick" => $fleet[4], "eta" => $eta, + "return_flight" => $fleet['return_flight']); + $titles[] = $title; + $select_box[] = array("value" => $i+1, "title" => $select); + } + } + if(preg_match_all("'(?:(Rückflug)\s*?
|)[\s\(]*?(\d{1,4}):(\d{1,2})\s*?([^\s\)<]+).*?
'is",$line[6],$att_fleets,PREG_SET_ORDER)) { + $timelist = parse_time($line[7]); + for($i=0;$i < count($att_fleets);$i++) { + $fleet = &$att_fleets[$i]; + if($fleet[1] == "Rückflug") { + $fleet['return_flight'] = 1; + } else { + $fleet['return_flight'] = 0; + } + $fleet['status'] = 2; + if($fleet['return_flight']) { + $title = "Verteidigung Rückflug von"; + $select = "Verteidigung Rückflug von"; + } else { + $title = "Verteidigung von"; + $select = "Verteidigung von"; + } + $eta = $timelist[$i]*60; + $title .= " $fleet[4] ($fleet[2]:$fleet[3]) ETA ".$this->formattime($eta,true); + $select .= " $fleet[4] ($fleet[2]:$fleet[3]) ETA ".$this->formattime($eta,true); + + $fleet_list[] = array("status" => $fleet['status'], + "gala" => $fleet[2],"pos" => $fleet[3],"nick" => $fleet[4], + "eta" => $eta,"return_flight" => $fleet["return_flight"]); + + $titles[] = $title; + $select_box[] = array("value" => $i+1, "title" => $select); + } + } + $fleet = array(); + $userfleets = listFleetsByUser($user['uid']); + if(count($fleet_list) == 0) { + // beide flotten im orbit + $do_update = array(1,1); + $do_selectbox = array(0,0); + $fleet = array(); + } elseif ( count($fleet_list) == 1 && $user['fleettype'] && $fleet_list[0]['status'] == 1 && $user['fleettype'] == 2) { + // flotte 1 attet, flotte 2 im orbit + // mit db checken + if($this->_is_matched_fleet($userfleets[1],$fleet_list[0])) { + // is in db, kein update + $do_update = array(0,1); + } else { + // is nicht in db + $do_update = array(1,1); + } + $do_selectbox = array(0,0); + + $fleet[0] = $fleet_list[0]; + + } elseif ( count($fleet_list) == 1 && $user['fleettype'] && $fleet_list[0]['status'] == 2 && $user['fleettype'] == 1) { + // flotte 1 defft, flotte 2 im orbit + // mit db checken + if($this->_is_matched_fleet($userfleets[1],$fleet_list[0])) { + // is in db, kein update + $do_update = array(0,1); + } else { + // is nicht in db + $do_update = array(1,1); + } + $do_selectbox = array(0,0); + $fleet[0] = $fleet_list[0]; + #echo "flotte 1 defft, flotte 2 im orbit
"; + } elseif( count($fleet_list) == 2 && $user['fleettype'] && $fleet_list[0]['status'] != $fleet_list[1]['status']) { + // flotten beide unterwegs, status unterschiedlich + if($user['fleettype'] == 2) { + // flotte 2 defft, flotte 1 attet + $fleet[0] = $fleet_list[0]; + $fleet[1] = $fleet_list[1]; + } else { + // flotte 1 defft, flotte 2 attet + $fleet[0] = $fleet_list[1]; + $fleet[1] = $fleet_list[0]; + $title_dummy = $titles[0]; + $titles[0] = $titles[1]; + $titles[1] = $title_dummy; + } + if($this->_is_matched_fleet($userfleets[1],$fleet_list[0])) { + // is in db, kein update + $do_update[0] = 0; + } else { + // is nicht in db + $do_update[0] = 1; + } + if($this->_is_matched_fleet($userfleets[2],$fleet_list[1])) { + // is in db, kein update + $do_update[1] = 0; + } else { + // is nicht in db + $do_update[1] = 1; + } + } else { + // keine ahnung + $do_update = array(1,1); + $do_selectbox = array(1,1); + $fleet = $fleet_list; + if(!count($fleet[1])) { + $fleet[] = array("status" => 0); + $titles[] = "Im Orbit"; + $select_box[] = array("value" => 2, "title" => "Im Orbit"); + } + } + for($i=0;$i < 2; $i++) { + $hidden_string[$i]['do_update'] = $do_update[$i]; + $hidden_string[$i]['do_selectbox'] = $do_selectbox[$i]; + $hidden_string[$i]['status'] = $fleet[$i]['status']; + $hidden_string[$i]['gala'] = $fleet[$i]['gala']; + $hidden_string[$i]['pos'] = $fleet[$i]['pos']; + $hidden_string[$i]['eta'] = $fleet[$i]['eta']; + $hidden_string[$i]['return_flight'] = $fleet[$i]['return_flight']; +# var_dump($hidden_string[$i]);echo"
"; +# var_dump(join(",",$hidden_string[$i]));echo"
"; + $hidden_string[$i] = urlencode(join(",",$hidden_string[$i])); + if(!$titles[$i]) $titles[$i] = "Im Orbit"; + $user['form_data'][] = array( + "title" => $titles[$i], + "fleet" => $i+1, + "do_selectbox" => $do_selectbox[$i], + "select_box" => $select_box + ); + } + $user['hidden_string'] = join("#",$hidden_string); +# if($user['nick'] == "Schmog") { +# var_dump($fleet_list); +# echo "

"; +# echo "userfleettype: ".$user['fleettype']."
"; +# var_dump($fleet); +# echo "

"; +# var_dump($titles); +# echo "

"; +# exit(); +# } + } + + function parser_takscreen() { + + function parse_time($timedata) { + $timelist = array(); + #mode1 + preg_match_all("/(\d+?)\sMin/ism",$timedata,$tak_timelist,PREG_SET_ORDER); + if (count($tak_timelist)){ + for($j=0;$j < count($tak_timelist);$j++){ + $timelist[] = $tak_timelist[$j][1]; + } + } else { + #mode3 + preg_match_all("/(\d{1,2}):(\d{1,2}):(\d{1,2})/ism",$timedata,$tak_timelist_mode3,PREG_SET_ORDER); + if(count($tak_timelist_mode3)){ + for($j=0;$j < count($tak_timelist_mode3);$j++){ + $timelist[] = ($tak_timelist_mode3[$j][1])*60+$tak_timelist_mode3[$j][2]; + } + } else { + #mode4 + preg_match_all("/(\d{1,2}):(\d{1,2})/ism",$timedata,$tak_timelist_mode4,PREG_SET_ORDER); + if(count($tak_timelist_mode4)){ + for($j=0;$j < count($tak_timelist_mode4);$j++){ + $timelist[] = ($tak_timelist_mode4[$j][1])*60+$tak_timelist_mode4[$j][2]; + } + } else { + #mode 5 + preg_match_all("/(\d{1,2})/ism",$timedata,$tak_timelist_mode5,PREG_SET_ORDER); + if(count($tak_timelist_mode5)){ + for($j=0;$j < count($tak_timelist_mode5);$j++){ + $timelist[] = ($tak_timelist_mode5[$j][1])*15; + } + } else { + $timelist[] = "error"; + } + } + } + } + return $timelist; + } + + $form = new formContainer(); + + $form->add(new formCheckBox("parse_user","User parsen","numeric",array(1),false)); + $form->add(new formCheckBox("parse_atter","Atter parsen","numeric",array(1),false)); + $form->add(new formCheckBox("parse_deffer","Deffer parsen","numeric",array(1),false)); + $form->add(new formInput("data","Taktikschirmdaten","string")); + + if ($_POST['userparse_step2']) { + //parse userfleets, step 2 + $uids = split(",",urldecode($_POST['uids'])); + if($uids && is_array($uids) && count($uids)){ + $user = getUserbyID($uids[0]); + $allygalas = getGalaListByAlly($user['aid'],true); + $metagalas = getGalaList(true); + foreach($uids as $uid) { + $fleetdata = split("#",$_POST["user_".$uid]); + $fleetdata[0] = split(",",urldecode($fleetdata[0])); + $fleetdata[1] = split(",",urldecode($fleetdata[1])); +# echo "fleetdata:
"; +# echo "
"; + for($i=0;$i < 2; $i++) { +# echo"
";var_dump($fleetdata[$i]);echo"
"; + if($fleetdata[$i][0]) { + // do_update + if($fleetdata[$i][1]) { + // do selectbox + $id = $_POST["select_".$uid."_".($i+1)]; + if(!$id || !is_numeric($id)) continue; + if($_POST["select_".$uid."_1"] == $_POST["select_".$uid."_2"]) continue; + $id--; + } else { + // else + $id = $i; + } + $status = $fleetdata[$id][2]; + $gala = $fleetdata[$id][3]; + $pos = $fleetdata[$id][4]; + $eta = $fleetdata[$id][5]; + $return_flight = $fleetdata[$id][6]; + if(!$return_flight) { + if($status == 1) { + $ticks = 5; + $returntime = 450; + } elseif ($status == 2) { + $ticks = 20; + if($gala == $user['gala']) { + $returntime = 270; + } elseif(in_array($gala,$allygalas)){ + $returntime = 300; + } elseif(in_array($gala,$metagalas)){ + $returntime = 330; + } else { + $returntime = 360; + } + } + } +# echo "$uid: flotte ".($i+1).": do_update: ".$fleetdata[$i][0].", do_selectbox: ".$fleetdata[$i][1].", status: $status, gala: $gala, pos: $pos, eta: $eta, return_flight: $return_flight
"; + User_fleet_status_update( + $uid, + $id+1, + $status, + $return_flight, + floor($eta/60), + $gala, + $pos, + $ticks, + $returntime + ); + } + } + } // foreach + } // if uids + $this->_header("takscreen.php?action=takparser"); + exit(); + } elseif($_POST['takscreenparse_step1']) { + $form->submit(); + if (!$form->hasErrors()) { + #echo $data."

"; + $data = stripslashes($form->get("data")); + if (preg_match( + "/Sektor(.*?)<\/table>/ism", + $data,$res)){ + $res[1] = preg_replace("/(.*?)<\/a>/ism","\$1",$res[1]); + $res[1] = preg_replace("/(.*?)<\/nobr>/ism","\$1",$res[1]); + $res[1] = preg_replace("/(.*?)<\/span>/ism","\$1",$res[1]); + $res[1] = preg_replace("/\*/ism","",$res[1]); + $res[1] = html_entity_decode($res[1]); + preg_match_all("/]*?class=\"r\"\>\s*?". + ".*?(\d{1,4}):(\d{1,2}).*?<\/td>\s*?". + "(.*?)<\/td>\s*?". + "(.*?)<\/td>\s*?". + "(.*?)<\/td>\s*?". + "(.*?)<\/td>\s*?". + "(.*?)<\/td>\s*?". + "(.*?)<\/td>\s*?". + "(.*?)<\/td>\s*?". + "(.*?)<\/td>\s*?". + "(.*?)<\/td>\s*?". + "<\/tr>/ism",$res[1],$res,PREG_SET_ORDER); + $galalist = getGalaList(); + $parse_messages = array(); + for($i=0;$i < count($res);$i++){ + #print_r($res[$i]); + $line = &$res[$i]; + $gala = $line[1]; + $pos = $line[2]; + $nick = trim($line[3]); + $user = getUserByPos($gala,$pos); + if ($user){ + $parse_messages[] = "User ".$user['nick']." (".$user['gala'].":".$user['pos'].") aktualisiert"; + if(strtolower($user['nick']) != strtolower($nick)) { + $parse_errors[] = "".$user['nick']." (".$user['gala'].":".$user['pos'].") hat falschen GN Nick oder ist ungültig"; + #echo "'".strtolower($nick)."' <> '".strtolower($user['nick'])."'
"; + } + #atter matching + if($form->get("parse_atter")) { + $this->_match_atter($gala,$pos,$line,&$parse_messages,&$parse_errors); + } + + #deffer + if($form->get("parse_deffer")) { + $this->_match_deffer($gala,$pos,$line,&$parse_messages,&$parse_errors); + } +/* #parse user + if($form->get("parse_user")) { + $this->_match_user(&$user,$line,&$fleet_select); + $uids[] = $user['uid']; + $userparse_list[] = $user; + }*/ + } else { + $parse_errors[] = "User ".$nick." (".$gala.":".$pos.") existiert nicht in der Datenbank"; + } + } + // result + if($form->get("parse_user")) { + $this->template->assign("uids",urlencode(join(",",$uids))); + $this->template->assign("userparse",$form->get("parse_user")); + $this->template->assign("userparse_list",$userparse_list); + } + if($parse_errors) { + $this->template->assign("parse_errors",$parse_errors); + } else { + $this->template->assign("parse_messages",$parse_messages); + } + $form->registerVars(&$this->template); + $this->show('takscreen_parser_takscreen_step2','Taktikschirm parsen'); + exit(); + } else { + $parse_errors[] = "Taktikschirm nicht erkannt"; + } + } + } else { + $parse_errors[] = "ACHTUNG! Unbedingt darauf achten dass euer Taktikschirm nicht älter als 15 min ist!"; + $form->select("parse_user",0); + $form->select("parse_deffer",1); + $form->select("parse_atter",1); + } + $this->template->assign("parse_errors",$parse_errors); + $form->registerVars(&$this->template); + $this->show('takscreen_parser_takscreen','Taktikschirm parsen'); + } + ############################################################################# + function parser_fleet() { + $form = new formContainer(); + $form->add(new formInput("data","Flottendaten","string")); + if($_POST['send']) { + $form->submit(); + if(!$form->hasErrors()) { + $text = $form->get("data"); + $items = parse_taktikansicht($text); + if($items) { + foreach($items as $item) { + $nick = $item['nick']; + $gala = $item['gala']; + $pos = $item['pos']; + $user = getUserByPos($gala,$pos); + if(!$user) {$parse_errors[] = "($gala:$pos) $nick nicht im System";continue;} + if(strtolower($user['nick']) != strtolower($nick)) $parse_errors[] = "($gala:$pos) $nick hat falschen GN-Nick oder ist ungültig"; + + user_fleets_update($user['uid'],$item['fleets']); + user_deff_update($user['uid'],$item['deff']); + + $parse_messages[] = "($gala:$pos) $nick erkannt"; + } + $this->template->assign("parse_messages",$parse_messages); + $this->template->assign("parse_errors",$parse_errors); + } else { + $form->setError("data"); + $form->addError("Es wurde nichts erkannt!"); + } + } + } + $form->registerVars(&$this->template); + $this->show('takscreen_parser_fleet','Flotten/Deff parsen'); + } + ############################################################################# + /** + Blendet Flotten in der Incdetailansicht aus + **/ + function incoming_details_hidefleets() { + if(!($id = param_num("id")) || !($inc = getuserbyid($id))) $this->_header(); + $fleets = $_POST['hidefleets']; + if(!$fleets || !is_array($fleets) || !count($fleets)) $this->_header("takscreen.php?action=details&id=$id&send"); + $fleets = preg_grep("'^\d+?$'is",$fleets); + hide_fleets($fleets,$this->userdata); + $this->_header("takscreen.php?action=details&id=$id&send"); + } + ############################################################################# + function incoming_details_resetfilter() { + $id = param_num("id"); + if(!($id = param_num("id")) || !($inc = getuserbyid($id))) $this->_header(); + $fids = array(); + $fids = getArrayFromList(fleetstatus_get_bytarget($inc['gala'],$inc['pos']),"fsid"); + if(count($fids)) reset_fleet_filter($this->userdata,$fids); + $this->_header(); + } + ############################################################################# + function parser_mili() { + $step = param_num("step"); + $data = $_SESSION['steps']; + if($data['miliparser']) { + unset($data['miliparser']); + $_SESSION['steps'] = $data; + $this->forms['information']['action'] =""; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['title'] = "Miliscan laden"; + $this->forms['information']['message'] = "Miliscan wurde geladen und die Flotten aktualisiert"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Miliscan laden"); + exit(); + } + if (!$step){ + # parsen + if ($_POST['send']) { + $data = $_POST['data']; + if ($data) { + $scans = parseScan($data); + if($scans) { + $miliids = array(); + foreach ($scans as $scan) { + $sid = updateScan($scan); + if($scan['type'] == "mili") { + $miliids[] = $sid; + } + } + if($miliids) { + $_SESSION['parse_mili']['sids'] = $miliids; + $this->_header("takscreen.php?action=miliparser&send&step=1"); + } else { + $message = "
keine Miliscans erkannt
"; + } + } else { + $message = "
keine Scans erkannt
"; + } + } else { + $message = "
Feld leer
"; + } + } else { + $message = "Unterstützte Formate:

Galaxy Network Scan (IRC Copy)"; + $message .="
WurstScript Miliscan"; + } + $this->template->assign("message",$message); + $this->show('takscreen_miliparser','Mili parsen'); + }elseif($step==1) { + + $miliids = $_SESSION['parse_mili']['sids']; + if(!is_array($miliids) || !count($miliids)) $this->_header(); + // miliscan auswerten + + $mili = getScan(array("sid"=>reset($_SESSION['parse_mili']['sids']))); + + $fleets = &$mili['mili_fleets']; + + // mili formatieren + for($i=0;$i < count($fleets);$i++){ + if ($fleets[$i]['status'] == 1) { + $fleets[$i]['class'] = "red"; + } elseif($fleets[$i]['status'] == 2) { + $fleets[$i]['class'] = "green"; + } elseif ($fleets[$i]['return_flight']) { + $fleets[$i]['class'] = "blue"; + } + } + $form = new formContainer(); + + $formitems = array(); + + // darf kein intener user sein + if(!($user = getUserByPos($mili['gala'],$mili['pos']))) { + if(($status = fleetstatus_get_filter(array( + "gala" => $mili['gala'], + "pos" => $mili['pos'], + "return_flight" => "0" + )))) + { + $list = array(); + $fleetstatus = array(); + $list[] = array("title" => "nicht zuweisen","value" => 0); + foreach ($status as $key => $value) { + $item = &$status[$key]; + if(($eta = $item['arrival'] - time()) < 0) { + $eta = $eta + $item['orbittime']*60; + $item['eta'] = "noch ".$this->formattime($eta,true)." im Orbit"; + } else { + $item['eta'] = "ETA ".$this->formattime($eta,true); + } + if($item['status'] == 1) { + $type = "Angriff"; + } else { + $type = "Verteidigung"; + } + #$item['title'] = $type." ".$item['tnick']." (".$item['tgala'].":".$item['tpos'].") ".$item['eta']." Flotte ".$item['fleetnum']; + $list[] = array("value" => $item['fsid'],"title" => $type." ".$item['tnick']." (".$item['tgala'].":".$item['tpos'].") ".$item['eta']." Flotte ".$item['fleetnum']); + $fleetstatus[$item['fsid']] = $item; + } + for ($i=1;$i < 3;$i++) { + if($fleets[$i]['status'] == 1 || $fleets[$i]['status'] == 2) { + //if($status) $formitems[$i]['select_items'] = $status; + $form->add(new formSelectBox("fleet".$i,"Flotte $i","integer",$list,false)); + } + } + } + } else { + $form->setError("User ist Metamitglied, nicht erlaubt"); + } + if($_POST['send']) { + $form->submit(); + $fleet1 = $form->get("fleet1"); + $fleet2 = $form->get("fleet2"); + if($fleet1 && $fleet2 && $fleet1 == $fleet2) { + $form->addError("beide Flotten wurden auf den selben Eintrag gesetzt"); + $form->setError(array("fleet1","fleet2")); + } + if(!$form->hasErrors()) { + if($fleet1) { + if($fleetstatus[$fleet1]['fleetnum'] != 1) { + fleetstatus_change_fleetnum($fleet1,1); + // muss neu geladen werden + if($fleet2) $fleetstatus[$fleet2] = fleetstatus_get($fleet2); + } + fleetstatus_update_fleet($fleet1,$fleets[1],$mili['mili_svs'],$mili['mili_prec']); + } + if($fleet2) { + if($fleetstatus[$fleet2]['fleetnum'] != 2) { + fleetstatus_change_fleetnum($fleet2,2); + } + fleetstatus_update_fleet($fleet2,$fleets[2],$mili['mili_svs'],$mili['mili_prec']); + } + array_shift($_SESSION['parse_mili']['sids']); + $this->_header("takscreen.php?action=miliparser&send&step=1"); + } + } + + $this->template->assign("step",$step); + $form->registerVars($this->template); + #$this->template->assign("fleets",$fleets); + $this->template->assign("mili",$mili); + $this->show('takscreen_miliparser_step2','Mili parsen'); + } + } + ############################################################################# + function Incoming_setunsafe() { + if(!($id = param_num("id")) || !($user = getUserByID($id)) || !($user['safe'])) $this->_header(); + addToLogFile("Ziel not safe: (".$user['gala'].":".$user['pos'].")","Incomings",$this->userdata['uid']); + user_set_safe($id,0); + $this->_header($this->backtracking->backlink()); + } + ############################################################################# + function Incoming_setsafe() { + if(!($id = param_num("id")) || !($user = getUserByID($id)) || ($user['safe'])) $this->_header(); + addToLogFile("Ziel safe: (".$user['gala'].":".$user['pos'].")","Incomings",$this->userdata['uid']); + user_set_safe($id,1); + $this->_header($this->backtracking->backlink()); + } + ############################################################################# +/* function Deffer_recall() { + $id = param_num("id"); + if(!$id)$this->_header($this->backtracking->backlink(),"fehlende id"); + $deffer = deffer_get($id); + if(!$deffer)$this->_header($this->backtracking->backlink(),"deffer existiert nicht"); +# if ($deffer['gala'] != $this->userdata['gala'] && $deffer['ogala'] != $this->userdata['gala']) +# $this->_header("takscreen.php","keine Berechtigung zum recalln"); + if ($_REQUEST['send']) { + if ($_REQUEST['yes_x']) { + deffer_recall($id); + $inc = inc_get_data($deffer['incid']); + if ($deffer['isextern']) { + addToLogFile("externer Deffer (".$deffer['egala'].":".$deffer['epos'].") bei (".$inc['ogala'].":".$inc['opos'].") recallt","Incomings",$this->userdata['uid']); + } else { + addToLogFile("interner Deffer (".$deffer['gala'].":".$deffer['pos'].") bei (".$inc['ogala'].":".$inc['opos'].") recallt","Incomings",$this->userdata['uid']); + } + } + $this->_header(); + } else { + $this->forms['information']['url'] = "takscreen.php?id=$id"; + $this->forms['information']['action'] = "defferrecall"; + $this->forms['information']['title'] = "Deffer recalln"; + $this->forms['information']['message'] = "Deffer bei (".$deffer['ogala'].":".$deffer['opos'].") ".$deffer['onick']." recalln ?"; + $this->forms['information']['style'] = "red"; + $this->show('message_question', "Deffer recalln"); + } + } +*/ ############################################################################# + function Atter_recallall() { + if(!($id = param_num("id")) || !($user = getUserByID($id)) || !($atter = fleetstatus_get_bytarget($user['gala'],$user['pos']))) $this->_header();; + if ($_REQUEST['send']) { + if ($_REQUEST['yes_x']) { + foreach ($atter as $data) { + fleetstatus_recall($data['fsid']); + } + addToLogFile("alle Flotten bei (".$user['gala'].":".$user['pos'].") recallt","Incomings",$this->userdata['uid']); + } + $this->_header(); + } else { + $this->forms['information']['url'] = "takscreen.php?id=$id"; + $this->forms['information']['action'] = "recallall"; + $this->forms['information']['title'] = "alle Atter recalln"; + $this->forms['information']['message'] = "alle Flotten auf (".$user['gala'].":".$user['pos'].") ".$user['nick']." recalln ?"; + $this->forms['information']['style'] = "red"; + $this->show('message_question', "alle Atter recalln"); + } + } + ############################################################################# + + function Fleet_recall() { + $id = param_num("id"); + if(!$id || !($info = fleetstatus_get($id))) $this->_header(); + + if ($_REQUEST['send']) { + if ($_REQUEST['yes_x']) { + fleetstatus_recall($info['fsid']); + #addToLogFile("Atter (".$atter['igala'].":".$atter['ipos'].") bei: (".$atter['ogala'].":".$atter['opos'].") recallt","Incomings",$this->userdata['uid']); + } + $this->_header(); + } else { + $this->forms['information']['url'] = "takscreen.php?id=$id"; + $this->forms['information']['action'] = "recall"; + $this->forms['information']['title'] = "Flotte recalln"; + $this->forms['information']['message'] = " (".$info['gala'].":".$info['pos'].") ".$info['nick']." recalln ?"; + $this->forms['information']['style'] = "red"; + $this->show('message_question', "Flotte recalln"); + } + } + + ############################################################################# + function Incoming_details() { + if(!($id = param_num("id")) || !($inc = getuserbyid($id))) + $this->_header(); + + if(!($incfleets = inc_list_byuser($inc['gala'],$inc['pos']))) + $this->_header(); + + $result = user_fleet_list_byuser($id); + + //atter-deffersummen + $deffersum = array(); $attersum = array(); + + $checkfleet = array("jaeger" => "Jäger","bomber"=>"Bomber", + "fregatten" => "Fregatten","zerstoerer"=>"Zerstörer","kreuzer"=>"Kreuzer", + "schlachter"=>"Schlachter","traeger"=>"Träger","kleptoren"=>"Kleptoren", + "cancris"=>"Cancris"); + + for($i=0;$i < count($result);$i++){ + if($result[$i]['return_flight']) { + $result[$i]['name'] = "Rückflug"; + $result[$i]['class'] = "class=\"blue\""; + } else { + if ($result[$i]['status'] == 1) { + $result[$i]['name'] = "Angriff"; + $result[$i]['class'] = "class=\"red\""; + } elseif ($result[$i]['status'] == 2) { + $result[$i]['name'] = "Verteidigung"; + $result[$i]['class'] = "class=\"green\""; + } else { + $result[$i]['name'] = "Im Orbit"; + } + } + if($result[$i]['tgala']) $result[$i]['name'] .= " (".$result[$i]['tgala'].":".$result[$i]['tpos'].")"; + if($result[$i]['status']) { + if($result[$i]['arrival']) { + $eta = $result[$i]['arrival'] - time(); + if($eta < 0) { + $result[$i]['name'] .= " im Orbit: ".$this->formattime($result[$i]['orbittime']*60 + $eta,true); + } else { + $result[$i]['name'] .= " ETA ".$this->formattime($eta,true); + } + } else { + $result[$i]['name'] .= "ETA n/a"; + } + } + // flotte im orbit + if(!$result[$i]['status']) { + foreach($checkfleet as $key => $val) { + $deffersum[$key] += $result[$i][$key]; + } + } + } + $this->template->assign("userfleet",$result); + $fleetfilter = get_fleet_filter($this->userdata); + + // flottenfilter, eta formatierung + $atter = 0; $deffer = 0; + $atterlist = array(); $defferlist = array(); + + // kann editieren + if($inc['aid'] == $this->userdata['aid']) { + $inc['canedit'] = 1; + } + + $inc['cansetsafe'] = 1; + + foreach($incfleets as $fleet) { + if($fleet['status'] == 1) $inc['atter']++; + elseif($fleet['status'] == 2) $inc['deffer']++; + if(count($fleetfilter)) { + if($fleet['fsid'] && in_array($fleet['fsid'],$fleetfilter)) { + if($fleet['status'] == 1) $inc['atter_filter'] = 1; + elseif($fleet['status'] == 2) $inc['deffer_filter'] = 1; + continue; + } + } + if($fleet['arrival']) { + $eta = $fleet['arrival']-time(); + if($eta < 0) { + $fleet['eta'] = "im Orbit: ".$this->formattime($fleet['orbittime']*60 + $eta,true); + } else { + $fleet['eta'] = $this->formattime($eta); + $fleet['title'] = $this->formattime($fleet['orbittime']*60,true)." im Orbit"; + } + } + $fleet['canrecall'] = 1; + if($fleet['status'] == 2) { + + $deffer++; + if(!$fleet['uid'] || $fleet['aid'] == $this->userdata['aid']) { + $fleet['canedit'] = 1; + } + $defferlist[] = $fleet; + foreach($checkfleet as $key => $val) { + $deffersum[$key] += $fleet[$key]; + } + } elseif($fleet['status'] == 1) { + $atter++; + $fleet['canedit'] = 1; + $atterlist[] = $fleet; + foreach($checkfleet as $key => $val) { + $attersum[$key] += $fleet[$key]; + } + } + } + if(!$inc['atter']) $this->_header(); + + + + $inc['canupdateatter'] = 1; + $this->template->assign("attersum",$attersum); + $this->template->assign("deffersum",$deffersum); + $this->template->assign("ircattdata",generate_irc_inc_summary($inc,$attersum,$deffersum)); + $this->template->assign("defferlist",$defferlist); + if ($inc['fleetupdate']) { + $inc['fleetupdate'] = formatdate_unix("d.m.Y",$inc['fleetupdate']).", ".date("H:i",$inc['fleetupdate'])." Uhr"; + } else { + $inc['fleetupdate'] = "noch nie"; + } + if ($inc['deffupdate']) { + $inc['deffupdate'] = formatdate_unix("d.m.Y",$inc['deffupdate']).", ".date("H:i",$inc['deffupdate'])." Uhr"; + } else { + $inc['deffupdate'] = "noch nie"; + } + $inc['cansetsave'] = 1; + $inc['canrecallall'] = 1; + $inc['fleetfilter_set'] = 1; + $this->template->assign("inc",$inc); + $this->template->assign("atterlist",$atterlist); + #$_SESSION['backlink'] = urlencode("takscreen.php?action=details&id=$id"); + $this->show('takscreen_inc_details', "Taktikschirm"); + } + + ############################################################################# + function Incoming_list() { + $filter = &$_SESSION['incfilter']; + if (!$filter){ + $filter['sort'] = "koords"; + $filter['order'] = "asc"; + } + if ($_REQUEST['sort'] && $_REQUEST['order']) { + $filter['sort'] = $_REQUEST['sort']; + $filter['order'] = $_REQUEST['order']; + } + + $filter['page'] = param_num("page",1); + + $allylist = getAllyList(); + + $formlist = array(); + $formlist[] = array("title" => "Allianz", "value" => 0); + foreach ($allylist as $ally) { + $formlist[] = array("title" => "[".$ally['tag']."] ".$ally['name'],"value" => $ally['aid']); + } + + $form = new formContainer(); + + $form->add(new formSelectBox("ally","Allianz","numeric",$formlist,false)); + $form->add(new formCheckBox("safe","Safestatus","numeric",1,false)); + $form->add(new formCheckBox("undertime","unter der Deffzeit","numeric",1,false)); + if ($_POST['send']) { + $form->submit(array("ally","safe","undertime")); + $ally = $form->get("ally"); + $filter['undertime'] = $form->get("undertime"); + $filter['safe'] = $form->get("safe"); + + if ($ally && !getAlly($ally)) { + unset($ally); + } + if($ally) { + $galalist = getGalaListByAlly($ally,true); + } else { + $galalist = getGalaList(true); + } + if($filter['ally'] != $ally) { + $gala = 0; + } else { + $gala = $_POST['gala']; + } + $galaitems = array(array("title" => "Galaxie","value" => 0)); + $selectedgala = 0; + foreach ($galalist as $item) { + $galaitem = array("title" => $item, "value" => $item); + if($item == $gala) { + $galaitem['selected'] = "selected"; + $selectedgala = $gala; + } + $galaitems[] = $galaitem; + } + $filter['gala'] = $selectedgala; + $filter['ally'] = $ally; + } else { + if($filter['ally']) { + $form->select("ally",$filter['ally']); + $galalist = getGalaListByAlly($filter['ally'],true); + } else { + $galalist = getGalaList(true); + } + if($filter['undertime']) $form->select("undertime",1); + if($filter['safe']) $form->select("safe",1); + + $galaitems = array(array("title" => "Galaxie","value" => 0)); + $selectedgala = 0; + foreach ($galalist as $item) { + $galaitem = array("title" => $item, "value" => $item); + if($filter['gala'] == $item) { + $galaitem['selected'] = "selected"; + $selectedgala = $filter['gala']; + } + $galaitems[] = $galaitem; + } + $filter['gala'] = $selectedgala; + } + $this->template->assign("galalist",$galaitems); + $sort[$filter['sort']][$filter['order']] = '_active'; + + $list = inc_list($filter,&$pages,&$filter['page'],10,$this->userdata); + + for($i=0;$i < count($list);$i++){ + $canrecallall = 0; + $_incs = inc_list_byuser($list[$i]['gala'],$list[$i]['pos']); + + foreach ($_incs as $inc) { + if($inc['arrival']) { + if ($inc['unixeta'] < 0) { + $inc['orbit'] = true; + $inc['orbittime'] = $this->formattime($inc['unixeta']+$inc['orbittime']*60,true); + $inc['eta'] = 0; + } else { + $inc['eta'] = $this->formattime($inc['unixeta'],true); + $inc['orbittime'] = $this->formattime($inc['orbittime']*60,true); + } + } else { + $inc['eta'] = "n/a"; + } + if(strlen($inc['nick']) > 20){ + $inc['nick'] = substr($nick['nick'],0,20).".."; + } + $inc['canrecall'] = 1; + if($inc['status'] == 1) { + // atter + $list[$i]['atterlist'][] = $inc; + } else { + // deffer + if(!$inc['uid'] || $inc['aid'] == $this->userdata['aid']) { + $inc['canedit'] = 1; + } + $list[$i]['defferlist'][] = $inc; + } + $list[$i]['canrecallall'] = $canrecallall; + $list[$i]['cansetsave'] = 1; + $list[$i]['backlink'] = urlencode("takscreen.php#".$list[$i]['uid']); + } +/* $list[$i]['atterlist'] = atter_list($list[$i]['incid']); + $list[$i]['defferlist'] = deffer_list($list[$i]['incid']); + for($j=0;$j < count($list[$i]['atterlist']);$j++){ + $atter = &$list[$i]['atterlist'][$j]; + + if ($atter['unixeta'] < 0) { + $atter['orbit'] = $atter['unixeta']+75*60; + if ($atter['orbit'] < 0) $atter['orbit'] = 0; + $atter['orbit'] = $this->formattime($atter['orbit'],true); + $atter['unixeta'] = 0; + } + $atter['eta'] = $this->formattime($atter['unixeta'],true); + if(strlen($atter['inickname']) > 20){ + $atter['inickname'] = substr($atter['inickname'],0,20).".."; + } +# if ($atter['ogala'] == $this->userdata['gala']) { + $canrecallall=1; +# } + } + for($j=0;$j < count($list[$i]['defferlist']);$j++){ + $deffer = &$list[$i]['defferlist'][$j]; + if ($deffer['unixeta'] < 0) { + $deffer['orbit'] = $deffer['unixeta']+$deffer['ticks']*15*60; + if ($deffer['orbit'] < 0) $deffer['orbit'] = 0; + $deffer['orbit'] = $this->formattime($deffer['orbit'],true); + $deffer['unixeta'] = 0; + } + $deffer['eta'] = $this->formattime($deffer['unixeta'],true); + if($deffer['isextern']) { + $deffer['nick'] = $deffer['enickname']; + $deffer['gala'] = $deffer['egala']; + $deffer['pos'] = $deffer['epos']; + } + if($deffer['aid'] == $this->userdata['aid']) { + $deffer['canupdatefleet'] = 1; + } + if(strlen($deffer['nick']) > 15){ + $deffer['nick'] = substr($deffer['nick'],0,15).".."; + } + +# if ($deffer['uid'] == $this->userdata['uid'] || +# $deffer['ogala'] == $this->userdata['gala']) { + $deffer['canrecall'] = 1; +# } + } +# if ($list[$i]['gala'] == $this->userdata['gala']) { +# } + $list[$i]['backlink'] = urlencode("takscreen.php#".$list[$i]['incid']); + */ + } + + $form->registerVars($this->template); + $this->template->assign("pages",showPageBar($filter['page'],$pages,"takscreen.php?","page","menu")); + $this->template->assign("allylist",$allylist); + $this->template->assign("sort",$sort); + $this->template->assign("list",$list); + $this->show('takscreen_index', "Taktikschirm"); + } + ############################################################################# + function Incoming_adddeffer() { + $id = param_num("id"); + if ($id && !($inc = getUserByID($id))) $this->_header(); + + if ($_SESSION['steps']['adddeffer']) { + #save step + unset($_SESSION['steps']['adddeffer']); + $_SESSION['steps'] = $data; + $this->forms['information']['action'] =""; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['title'] = "Deffer hinzufügen"; + $this->forms['information']['message'] = "Deffer eingetragen"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Deffer hinzufügen"); + } + $form = new formContainer(); + $form->add(new formInput("tgala","Zielgala","numeric",true,4)); + $form->add(new formInput("tpos","Zielposition","numeric",true,2)); + $form->add(new formInput("gala","Gala vom Deffer","numeric",true,4)); + $form->add(new formInput("pos","Position vom Deffer","numeric",true,2)); + $list = array( + array("title" => "Flotte 1","value" => 1), + array("title" => "Flotte 2","value" => 2) + ); + $form->add(new formSelectBox("fleet","Flotte","numeric",$list,false)); + $form->add(new formInput("time","Flugzeit","string",true,20,false,"'^(?:(\d+?):(\d+?)|(\d+?))$'is")); + $list = array( + array("title" => "extern (360)","value" => 360), + array("title" => "Meta intern (330)","value" => 330), + array("title" => "Allianz intern (300)","value" => 300), + array("title" => "Galaxie intern (270)","value" => 270) + ); + $form->add(new formSelectBox("defftype","Verteidigung","numeric",$list,false)); + $form->add(new formInput("orbit","Zeit im Orbit","string",true,20,false,"'^(?:(\d+):(\d+)|(\d+))$'is")); + if ($_POST['send']) { + $form->submit(); + $tgala = $form->get("tgala"); + $tpos = $form->get("tpos"); + $gala = $form->get("gala"); + $pos = $form->get("pos"); + + #opfer existiert nicht + if (!$form->hasErrors() && !($deffer = getUserByPos($tgala,$tpos))) { + $form->addError("Member existiert nicht im System"); + $form->setError(array("tpos","tgala")); + } + + #kann sich net selber deff0rn + if (!$form->hasErrors() && $tgala == $gala && $tpos == $pos) { + $form->addError("Man kann sich nicht selber deffen"); + $form->setError(array("tgala","tpos","gala","pos")); + } + + #flotte schon eingetragen + if (!$form->hasErrors() && $form->get("fleet") && ($data = fleetstatus_get_bykoords($gala,$pos,$fleet))) { + $form->addError("Flotte ist bereits eingetragen"); + $form->setError(array("gala","pos","fleet")); + } + if(!$form->hasErrors() && ($check = fleetstatus_get_bykoords($gala,$pos)) && count($check) >= 2) { + $form->addError("Es sind bereits 2 Einträge zu ($gala:$pos) vorhanden"); + $form->setError(array("gala","pos","fleet")); + } + if (!$form->hasErrors()) { + $_SESSION['steps']['adddeffer'] = 1; + $time = $form->getRegex("time"); + if(strlen($time[1])) { + $eta = $time[1] * 60 + $time[2]; + } else $eta = $time[3]; + $time = $form->getRegex("orbit"); + if(strlen($time[1])) { + $orbit = $time[1] * 60 + $time[2]; + } else $orbit = $time[3]; + if($eta == 0) { + $orbit = gnticktime($orbit); + } + deffer_add( + $gala,$pos, + $tgala,$tpos, + $form->get("fleet"), + $form->get("defftype"), + $orbit, + $eta + ); + $this->_header("takscreen.php?action=adddeffer&send"); + } + $this->template->assign("errors",$errors); + $this->template->assign("defftype".$items['defftype']['value'],"selected"); + $this->template->assign("tick".$ticks,"selected"); + } else { + if ($inc) { + $form->set("gala",$this->userdata['gala']); + $form->set("pos",$this->userdata['pos']); + $form->set("tgala",$inc['gala']); + $form->set("tpos",$inc['pos']); + if($inc['gala'] == $this->userdata['gala']) { + $form->select("defftype",270); + $form->set("time",$this->formattime(270*60)); + } elseif ($inc['aid'] == $this->userdata['aid']) + { + $form->select("defftype",300); + $form->set("time",$this->formattime(300*60)); + } else { + $form->select("defftype",330); + $form->set("time",$this->formattime(330*60)); + } + if($this->userdata['fleettype'] == 1 || $this->userdata['fleettype'] == 3 || $this->userdata['fleettype'] == 0) { + $form->select("fleet",1); + } else { + $status = fleetstatus_get_byfleetnum($this->userdata['gala'],$this->userdata['pos']); + if(!$status || count($status) == 2 || $status[0]['fleetnum'] == 1) { + $form->select("fleet",2); + } else { + $form->select("fleet",1); + } + } + } else { + $form->select("defftype",330); + $form->set("time",$this->formattime(330*60)); + } + + $form->set("orbit",$this->formattime(300*60)); + } + $form->registerVars($this->template); + $this->show('takscreen_deffer_add', "Deffer hinzufügen"); + } + ############################################################################# +/* function Incoming_deffextern() { + $checkfleet = array("jaeger" => "Jäger","bomber"=>"Bomber", + "fregatten" => "Fregatten","zerstoerer"=>"Zerstörer","kreuzer"=>"Kreuzer", + "schlachter"=>"Schlachter","traeger"=>"Träger","kleptoren"=>"Kleptoren", + "cancris"=>"Cancris","prec"=>"Scangenauigkeit","svs"=>"Scanverstärker"); + $data = $_SESSION['steps']; + if ($data['externdeffer']) { + #save step + unset($data['externdeffer']); + $_SESSION['steps'] = $data; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['action'] =""; + $this->forms['information']['title'] = "externen Deffer melden"; + $this->forms['information']['message'] = "Deffer eingetragen"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "externen Deffer melden"); + } + if ($_POST['send']) { + $this->template->assign("errors",$errors); + $items['gala']['value'] = $_POST['gala']; + $items['pos']['value'] = $_POST['pos']; + #Opfer + if (!$items['gala']['value'] || !is_numeric($items['gala']['value'])) { + $errors[] = "Ungültige Opfergalaxie"; + $items['gala']['class'] = "_error"; + } + if (!$items['pos']['value'] || !is_numeric($items['pos']['value'])) { + $errors[] = "Ungültige Opferposition"; + $items['pos']['class'] = "_error"; + } + #ticks + $items['ticks']['value'] = param_num("ticks",20); + + #deffer + #koords + $items['agala']['value'] = $_POST['agala']; + $items['apos']['value'] = $_POST['apos']; + if (!$items['agala']['value'] || !is_numeric($items['agala']['value'])) { + $errors[] = "Ungültige Deffergalaxie"; + $items['agala']['class'] = "_error"; + } + if (!$items['apos']['value'] || !is_numeric($items['apos']['value'])) { + $errors[] = "Ungültige Defferposition"; + $items['apos']['class'] = "_error"; + } + #nickname + $items['nickname']['value'] = $_POST['nickname']; + if (!$items['nickname']['value']) { + $errors[] = "Fehlender Nickname"; + $items['nickname']['class'] = "_error"; + } + #eta + $items['time']['value'] = $_POST['time']; + if (!isset($items['time']['value'])) { + $errors[] = "Fehlende Ankunftzeit"; + $items['time']['class'] = "_error"; + } else { + if (preg_match("/^(\d+?):(\d+?)$/i",$items['time']['value'],$result)) { + $eta = ($result[1] * 60) + $result[2]; + } elseif (is_numeric($items['time']['value'])) { + $eta = $items['time']['value']; + } else { + $errors[] = "Ungültige Zeit"; + $items['time']['class'] = "_error"; + } + } + #flottendaten + $fleet = array(); + foreach ($checkfleet as $key => $value) { + $items[$key]['value'] = $_POST[$key]; + if ($items[$key]['value']) { + if (!is_numeric($items[$key]['value'])) { + $errors[] = "$value ungültig"; + $items[$key]['class'] = "_error"; + } else { + $fleet[$key] = $items[$key]['value']; + } + } else { + $items[$key]['class'] = "_optional"; + } + } + #flottenummer + $items['fleet']['value'] = $_POST['fleet']; + if ($items['fleet']['value'] != 1 && $items['fleet']['value'] != 2) { + $errors[] = "Flotte ungültig"; + } else { + $this->template->assign("fleet".$items['fleet']['value'],"selected"); + } + #opfer existiert nicht + if (!$errors && !($opfer = getUserByPos($items['gala']['value'],$items['pos']['value']))) { + $items['gala']['class'] = "_error"; + $items['pos']['class'] = "_error"; + $errors[] = "Ziel existiert nicht"; + } + #deffer ist benutzer des tps + if (!$errors && ($deffer = getUserByPos($items['agala']['value'],$items['apos']['value']))) { + $items['agala']['class'] = "_error"; + $items['apos']['class'] = "_error"; + $errors[] = "Koordinaten gehören zu einem Benutzer, muss als intern gemeldet werden !"; + } + #inc gibts net + if (!$errors && !($incdata = inc_get_data($opfer['uid']))) { + $items['gala']['class'] = "_error"; + $items['pos']['class'] = "_error"; + $errors[] = "Ziel hat kein Incoming"; + } + #kann sich net selber deff0rn + if (!$errors && ($items['agala']['value'] == $items['gala']['value'] + && $items['apos']['value'] == $items['pos']['value'])) { + $items['agala']['class'] = "_error"; + $items['apos']['class'] = "_error"; + $items['gala']['class'] = "_error"; + $items['pos']['class'] = "_error"; + $errors[] = "Man kann sich nicht selber deffen"; + } + if (!$errors) { + $data['externdeffer'] = 1; + $_SESSION['steps'] = $data; + deffer_extern_add( + $opfer['uid'], + $items['nickname']['value'], + $items['agala']['value'], + $items['apos']['value'], + $eta, + $items['fleet']['value'], + $fleet, + $items['ticks']['value'] + ); + $this->_header("takscreen.php?action=adddeffextern&send"); + } + $this->template->assign("errors",$errors); + } else { + foreach ($checkfleet as $key => $value) { + $items[$key]['class'] = "_optional"; + } + $items['ticks']['value'] = 20; + } + $this->template->assign("ticklist",$this->getTicklist(20,$items['ticks']['value'])); + $this->template->assign("items",$items); + $this->show('takscreen_deffer_extern', "externen Deffer melden"); + } + +*/ /* ############################################################################# + function Deffer_update() { + $id = param_num("id"); + if(!$id) $this->_header($this->backtracking->backlink(),"fehlende id"); + $deffer = deffer_get($id); + if(!$deffer) $this->_header($this->backtracking->backlink(),"deffer existiert nicht"); + if(!$deffer['isextern']) $this->_header($this->backtracking->backlink(),"deffer ist kein externer deffer"); + $checkfleet = array("jaeger" => "Jäger","bomber"=>"Bomber", + "fregatten" => "Fregatten","zerstoerer"=>"Zerstörer","kreuzer"=>"Kreuzer", + "schlachter"=>"Schlachter","traeger"=>"Träger","kleptoren"=>"Kleptoren", + "cancris"=>"Cancris"); + $data = $_SESSION['steps']; + if ($data['updatedeffer']) { + #save step + unset($data['updatedeffer']); + $_SESSION['steps'] = $data; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['title'] = "externen Deffer updaten"; + $this->forms['information']['message'] = "Deffer erfolgreich upgedated"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Deffer updaten"); + } + if ($_POST['send']) { + #eta + $items['eta']['value'] = $_POST['eta']; + if (!isset($items['eta']['value'])) { + $errors[] = "ETA leer"; + $items['eta']['class'] = "_error"; + } else { + if (preg_match("/^(\d+?):(\d+?)$/i",$items['eta']['value'],$result)) { + $etatime = ($result[1] * 60) + $result[2]; + } elseif (is_numeric($items['eta']['value'])) { + $etatime = $items['eta']['value']; + } else { + $errors[] = "Ungültige Zeit"; + $items['eta']['class'] = "_error"; + } + } + #flottendaten + foreach ($checkfleet as $key => $value) { + $items[$key]['value'] = $_POST[$key]; + if($items[$key]['value']) { + if (!is_numeric($items[$key]['value'])) { + $errors[] = "$value ungültig"; + $items[$key]['class'] = "_error"; + } else { + $fleet[$key] = $items[$key]['value']; + } + } else { + $fleet[$key] = 0; + $items[$key]['value'] = 0; + } + } + #flottenummer + $items['fleet']['value'] = $_POST['fleet']; + if ($items['fleet']['value'] != 1 && $items['fleet']['value'] != 2) { + $errors[] = "Flotte ungültig"; + } else { + $this->template->assign("fleet".$items['fleet']['value'],"selected"); + } + #ticks + $items['ticks']['value'] = param_num("ticks",20); + if (!$errors) { + deffer_extern_update( + $deffer['incid'], + $deffer['defferid'], + $items['fleet']['value'], + $etatime, + $fleet, + $items['ticks']['value'] + ); + $data['updatedeffer'] = 1; + $_SESSION['steps'] = $data; + $this->_header("takscreen.php?action=updatedeffer&id=$id&send"); + } + } else { + #flottendaten + foreach ($checkfleet as $key => $value) { + $items[$key]['value'] = $deffer[$key]; + } + $items['ticks']['value'] = $deffer['ticks']; + $items['eta']['value'] = $this->formattime($deffer['unixeta']); + $this->template->assign("fleet".$deffer['fleetnum'],"selected"); + } + $this->template->assign("ticklist",$this->getTicklist(20,$items['ticks']['value'])); + $this->template->assign("id",$id); + $this->template->assign("errors",$errors); + $this->template->assign("deffer",$deffer); + $this->template->assign("items",$items); + $this->show('takscreen_deffer_update', "Deffer updaten"); + }*/ + + function incoming_fleetstatus() { + if(!($fsid = param_num("id")) || !($status = fleetstatus_get($fsid))) $this->_header(); + if($status['uid']) $this->_header("user.php?action=fleet&id=".$status['uid']."&send"); + $page = param_num("page",1); + $form = new formContainer(); + $form_params = array(); + $form_params[] = array("value" => $this->session['id'],"name" => $this->session['name']); + $form_params[] = array("value" => "fleetstatus","name" => "action"); + $form_params[] = array("value" => $page,"name" => "page"); + $form_params[] = array("value" => 1,"name" => "send"); + $form_params[] = array("value" => $fsid,"name" => "id"); + if($_SESSION['steps']['fleetstatus']) { + $this->template->assign("message",$_SESSION['steps']['fleetstatus']); + unset($_SESSION['steps']['fleetstatus']); + } + + switch ($page) { + // daten ändern + case 1: { + $form->add(new formInput("eta","Verbleibene Flugzeit (ETA)","string",true,255,true,"'^(?:(\d+?):(\d+?)|(\d+?))$'is")); + $list = array( + array("title" => "Flotte 1","value" => 1), + array("title" => "Flotte 2","value" => 2) + ); + $form->add(new formSelectBox("fleetnum","Flotte","numeric",$list,false)); + $form->add(new formInput("orbit","Zeit im Orbit","string",true,255,true,"'^(?:(\d+?):(\d+?)|(\d+?))$'is")); + if($_POST['send']) { + $form->submit(); + $eta = $form->getRegex("eta"); + if(strlen($eta[1])) { + $eta = $eta[1] * 60 + $eta[2]; + } else { + $eta = $eta[3]; + } + if($eta < 0) $eta = 0; + $time = $form->getRegex("orbit"); + if(strlen($time[1])) { + $orbittime = $time[1] * 60 + $time[2]; + } else { + $orbittime = $time[3]; + } + if($orbittime < 0) $orbittime = 0; + if($eta == 0) $orbittime = gnticktime($orbittime); + if(!$form->hasErrors()) { + if($form->get("fleetnum") != $status['fleetnum']) { + fleetstatus_change_fleetnum($status['fsid'],$form->get("fleetnum")); + } + fleetstatus_update($fsid,array("arrival" => gnarrival($eta),"orbittime" => $orbittime)); + $_SESSION['steps']['fleetstatus'] = "Taktikdaten geändert"; + $this->_header("takscreen.php?action=fleetstatus&id=$fsid&page=$page&send"); + } + } else { + if($status['arrival']) { + $eta = $status['arrival'] - time(); + if($eta <= 0) { + if(isset($status['orbittime'])) $orbittime = $status['orbittime']*60+$eta; + $eta = 0; + } else { + $orbittime = $status['orbittime']*60; + } + $form->set("eta",$this->formattime($eta)); + $form->set("orbit",$this->formattime($orbittime)); + } + if($status['fleetnum']) $form->select("fleetnum",$status['fleetnum']); + } + break; + } + // scan laden + case 2: { + $scan = getScan(array("gala" => $status['gala'],"pos" => $status['pos'])); + if($scan['hasunit'] || $scan['hasmili']) { + $scantypes = array(); + if($scan['hasmili']) { + $scantypes[] = "mili"; + $list = array( + array("title" => "Flotte 1","value" => 1), + array("title" => "Flotte 2","value" => 2) + ); + $form->add(new formSelectBox("fleet","Flotte","numeric",$list,false)); + } + if($scan['hasunit']) $scantypes[] = "unit"; + $form->add(new formRadio("scan","Scan laden","string",$scantypes)); + if($_POST['send']) { + $form->submit(); + if(!$form->hasErrors()) { + if($form->get("scan") == "unit") { + // unit laden + $updatefleetdata = fleet_get($scan['unit_fid']); + $updatefleetdata['svs'] = $scan['unit_svs']; + $updatefleetdata['prec'] = $scan['unit_prec']; + $updatefleetdata['fleetnum'] = $status['fleetnum']; + $message = "Einheitenscan"; + } else { + // mili laden + $updatefleetdata = miliscan_fleet_get_bykoords($scan['gala'],$scan['pos'],$form->get("fleet")); + $updatefleetdata['svs'] = $scan['mili_svs']; + $updatefleetdata['prec'] = $scan['mili_prec']; + $updatefleetdata['fleetnum'] = $form->get("fleet"); + $message = "Militärscan Flotte ".$form->get("fleet"); + } + if($form->get("fleetnum") != $updatefleetdata['fleetnum']) { + fleetstatus_change_fleetnum($status['fsid'],$updatefleetdata["fleetnum"]); + } + fleetstatus_update_fleet($fsid,$updatefleetdata,$updatefleetdata['svs'],$updatefleetdata['prec']); + $_SESSION['steps']['fleetstatus'] = $message." wurde geladen"; + $this->_header("takscreen.php?action=fleetstatus&id=$fsid&page=2&send"); + } + } else { + $form->select("scan",$scantypes[0]); + if($scan['hasmili']) $form->select("fleet",$status['fleetnum']); + } + $this->template->assign("scan",scan_format($scan)); + } + break; + } + // manuelle flotteneingabe + case 3: { + $checkfleet = array( + "jaeger" => "Jäger", + "bomber"=>"Bomber", + "fregatten" => "Fregatten", + "zerstoerer"=>"Zerstörer", + "kreuzer"=>"Kreuzer", + "schlachter"=>"Schlachter", + "traeger"=>"Träger", + "kleptoren"=>"Kleptoren", + "cancris"=>"Cancris", + "prec"=>"Scangenauigkeit", + "svs"=>"Scanverstärker" + ); + foreach ($checkfleet as $key => $value) { + $form->add(new formInput($key,$value,"numeric")); + } + if($_POST['send']) { + $form->submit(); + if(!$form->hasErrors()) { + $updatefleetdata = array(); + foreach ($checkfleet as $key => $value) { + $updatefleetdata[$key] = $form->get($key); + } + fleetstatus_update_fleet($fsid,$updatefleetdata,$updatefleetdata['svs'],$updatefleetdata['prec']); + $_SESSION['steps']['fleetstatus'] = "Flottendaten gespeichert"; + $this->_header("takscreen.php?action=fleetstatus&id=$fsid&page=3&send"); + } + } else { + foreach ($checkfleet as $key => $value) { + $form->set($key,$status[$key]); + } + } + break; + } + case 4: { + $form->add(new formInput("code","Text","string")); + if($_POST['send']) { + $form->submit(); + if(!$form->hasErrors()) { + $result = parseWurstFleet($form->get("code")); + if($result !== false) { + fleetstatus_update_fleet($fsid,$result,"0","100"); + $_SESSION['steps']['fleetstatus'] = "Flottendaten gespeichert"; + $this->_header("takscreen.php?action=fleetstatus&id=$fsid&page=4&send"); + } else { + $form->addError("Fehler beim Parsen"); + $form->setError("code"); + } + } + } + } + } + $form->registerVars($this->template); + // baue manuelles flottenupdate formular + if($page == 3) { + $formitems = array(); + foreach($checkfleet as $key => $value) { + $formitems[] = array( + "value" => $form->smartyitems[$key]['value'], + "title" => $form->smartyitems[$key]['title'], + "name" => $key, + "class" => $form->smartyitems[$key]['class'] + ); + } + $this->template->assign("fleetupdateform",$formitems); + } + $this->template->assign(array("status" => $status,"page" => $page,"form_params" => $form_params)); + $this->show('takscreen_fleetstatus',"Flottendaten"); + } + + ############################################################ + function Incoming_addatter () { + $checkfleet = array( + "jaeger" => "Jäger", + "bomber"=>"Bomber", + "fregatten" => "Fregatten", + "zerstoerer"=>"Zerstörer", + "kreuzer"=>"Kreuzer", + "schlachter"=>"Schlachter", + "traeger"=>"Träger", + "kleptoren"=>"Kleptoren", + "cancris"=>"Cancris", + "prec"=>"Scangenauigkeit", + "svs"=>"Scanverstärker" + ); + if ($_SESSION['steps']['addatter']) { + unset($_SESSION['steps']['addatter']); + + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['action'] =""; + $this->forms['information']['title'] = "Incoming melden"; + $this->forms['information']['message'] = "Inc eingetragen"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Incoming melden"); + } + + $form = new formContainer(); + + foreach ($checkfleet as $key => $value) { + $form->add(new formInput($key,$value,"numeric",true,20,true)); + } + + $form->add(new formInput("gala","Zielgalaxie","numeric",true,20)); + $form->add(new formInput("pos","Zielposition","numeric",true,20)); + $form->add(new formInput("agala","Angreifergalaxie","numeric",true,20)); + $form->add(new formInput("apos","Angreiferposition","numeric",true,20)); + $form->add(new formInput("time","ETA bis zur Ankunft","string",true,255)); + + $form->add(new formSelectBox("fleet","Flottennummer","numeric",array(array("title" => "Flotte 1","value" => "1"),array("title" => "Flotte 2","value" => "2")),false)); + + if ($_POST['send']) { + $form->submit(); + if(!$form->hasErrors() && strlen($form->get("time"))) { + $time = $form->get("time"); + if (preg_match("/^(\d+?):(\d+?)$/i",$time,$result)) { + $eta = ($result[1] * 60) + $result[2]; + } elseif (is_numeric($time)) { + $eta = $time; + } else { + $form->setError("time"); + $form->addError("ETA: Ungültige Zeit"); + } + } + $tgala = $form->get("gala"); + $tpos = $form->get("pos"); + $gala = $form->get("agala"); + $pos = $form->get("apos"); + $fleetnum = $form->get("fleet"); + #user existiert nicht + if (!$form->hasErrors() && !($user = user_get_bypos($tgala,$tpos))) { + $form->setError(array("gala","pos")); + $form->adderror("User existiert nicht"); + } + if (!$form->hasErrors() && ($user = user_get_bypos($gala,$pos))) { + $form->setError(array("agala","apos")); + $form->adderror("Angreifer ist Metamitglied!"); + } + foreach ($checkfleet as $key => $item) { + if(strlen($form->get($key))>0) { + if(isset($fleetdata)) $fleetdata = array(); + $fleetdata[$key] = $form->get($key); + } + } + if (!$form->hasErrors() && (!$form->get("fleet") && $fleetdata)) { + $form->adderror("Flottendaten ohne Flottennummer ist nicht zulässig!"); + $form->setError("fleet"); + } + + if (!$form->hasErrors() && (count(fleetstatus_get_bykoords($gala,$pos)) == 2)) { + $form->adderror("Es sind bereits 2 Flotten von $gala:$pos eingetragen"); + $form->setError("fleet"); + } + if (!$form->hasErrors() && $fleetnum && ($info = fleetstatus_get_bykoords($gala,$pos,$fleetnum))) { + $form->adderror("Angreifer bereits eingetragen: attet (".$info['tgala'].":".$info['tpos'].")" ); + $form->setError("fleet"); + $form->setError("agala"); + $form->setError("apos"); + } + if (!$form->hasErrors()) { + atter_add( + $form->get("agala"), + $form->get("apos"), + $form->get("gala"), + $form->get("pos"), + $form->get("fleet"), + $eta, + $fleetdata + ); + + $_SESSION['steps']['addatter'] = 1; + $this->_header("takscreen.php?action=addatter&send"); + } + } + $form->registerVars($this->template); + $this->show('takscreen_atter_add', "Incoming melden"); + } + ############################################################ + /* function Atter_update () { + $id = param_num("id"); + if(!$id) $this->_header($this->backtracking->backlink(),"fehlende id"); + $atter = atter_get($id); + if(!$atter) $this->_header($this->backtracking->backlink(),"atter existiert nicht"); + $checkfleet = array("jaeger" => "Jäger","bomber"=>"Bomber", + "fregatten" => "Fregatten","zerstoerer"=>"Zerstörer","kreuzer"=>"Kreuzer", + "schlachter"=>"Schlachter","traeger"=>"Träger","kleptoren"=>"Kleptoren", + "cancris"=>"Cancris","prec"=>"Scangenauigkeit","svs"=>"Scanverstärker"); + $data = $_SESSION['steps']; + if ($data['updateatter']) { + #save step + unset($data['updateatter']); + $_SESSION['steps'] = $data; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['action'] =""; + $this->forms['information']['title'] = "Atter updaten"; + $this->forms['information']['message'] = "Atter erfolgreich upgedated"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Atter updaten"); + } + if ($_POST['send']) { + #eta + $items['eta']['value'] = $_POST['eta']; + if (!isset($items['eta']['value'])) { + $errors[] = "ETA leer"; + $items['eta']['class'] = "_error"; + } else { + if (preg_match("/^(\d+?):(\d+?)$/i",$items['eta']['value'],$result)) { + $etatime = ($result[1] * 60) + $result[2]; + } elseif (is_numeric($items['eta']['value'])) { + $etatime = $items['eta']['value']; + } else { + $errors[] = "Ungültige Zeit"; + $items['eta']['class'] = "_error"; + } + if (!$etatime) $etatime = 0; + } + #flottendaten + foreach ($checkfleet as $key => $value) { + $items[$key]['value'] = $_POST[$key]; + if($items[$key]['value']) { + if (!is_numeric($items[$key]['value'])) { + $errors[] = "$value ungültig"; + $items[$key]['class'] = "_error"; + } else { + $fleet[$key] = $items[$key]['value']; + } + } + } + if (!$items['prec']['value']) $items['prec']['value'] = 0; + if (!$items['svs']['value']) $items['svs']['value'] = 0; + if($items['prec']['value'] > 100) { + $items['prec']['value'] = 100; + } + #flottenummer + $items['fleet']['value'] = $_POST['fleet']; + if ($items['fleet']['value'] != 1 && $items['fleet']['value'] != 2) { + $errors[] = "Flotte ungültig"; + } else { + $this->template->assign("fleet".$items['fleet']['value'],"selected"); + } + if (!$errors) { + atter_update($id, + $items['prec']['value'], + $items['svs']['value'], + $items['fleet']['value'], + $etatime, + $fleet); + $data['updateatter'] = 1; + $_SESSION['steps'] = $data; + $this->_header("takscreen.php?action=updateatter&id=$id&send"); + } + $this->template->assign("errors",$errors); + } else { + #eta + $items['eta']['value'] = $this->formattime($atter['unixeta']); + #flottendaten + foreach ($checkfleet as $key => $value) { + $items[$key]['value'] = $atter[$key]; + } + $this->template->assign("fleet".$atter['fleetnum'],"selected"); + $items['prec']['value'] = $atter['prec']; + $items['svs']['value'] = $atter['svs']; + } + $this->template->assign("id",$id); + $this->template->assign("atter",$atter); + $this->template->assign("items",$items); + $this->show('takscreen_inc_update', "Atter updaten"); + }*/ +} +?> diff --git a/src/classes/user.class.php b/src/classes/user.class.php new file mode 100644 index 0000000..fafcf65 --- /dev/null +++ b/src/classes/user.class.php @@ -0,0 +1,836 @@ +action]) { + eval("\$this->".$functions[$this->action].";"); + } + #default + $this->_header("index.php"); + } + + function User_activity_check() { + if(!do_check_activity($this->userdata)) $this->_header(); + user_activity_check($this->userdata['uid']); + $this->_header(); + } + + ############################################################################# + function Fleets_list() { + $filter = $_SESSION['userfleetfilter']; + #filter setzen + if (!$filter){ + $galalist = getGalaListbyAlly($this->userdata['aid']); + if (count($galalist)){ + $filter['gala'] = $galalist[0]['gala']; + } + } + $filter['ally'] = $this->userdata['aid']; + $filter['order'] = "asc"; + $filter['sort'] = "koords"; + #filter neu setzen + if ($_POST['subaction'] == "filter") { + $gala = param_num("galaxy"); + } else { + $gala = $filter['gala']; + } + $ally = $filter['ally']; + $galalist = getGalaListbyAlly($ally); + if (count($galalist)) { + if ($gala) { + for($i=0;$i < count($galalist);$i++){ + if($galalist[$i]['gala'] == $gala){ + $filter['gala'] = $gala; + $galalist[$i]['selected'] = "selected"; + break; + } + } + } else { + $gala = $galalist[0]['gala']; + $filter['gala'] = $gala; + } + } else { + unset($filter['gala']); + } + if ($_POST['subaction'] == "filter") { + $_SESSION['userfleetfilter'] = $filter; + } + if ($gala){ + $list = listUser($filter,&$pages,1,12); + for($i=0;$i < count($list);$i++){ + $list[$i]['fleets'] = user_fleet_list_byuser($list[$i]['uid']); + $gesamt = array(); + $gesamt['dir'] = "Gesamt"; + $gesamt['name'] = "Gesamt"; + $gesamt['class'] = "bold"; + $list[$i]['fleets'][0]['name'] = "Orbit"; + $list[$i]['fleets'][1]['name'] = "Flotte 1"; + $list[$i]['fleets'][2]['name'] = "Flotte 2"; + for($j=0;$j < count($list[$i]['fleets']);$j++){ + $fleet = &$list[$i]['fleets'][$j]; + if($fleet['return_flight']) { + $fleet['dir'] = "Rückflug"; + $fleet['class'] = "blue"; + } else { + if ($fleet['status'] == 1) { + $fleet['dir'] = "Angriff"; + $fleet['class'] = "red"; + } + elseif ($fleet['status'] == 2) { + $fleet['dir'] = "Verteidigung"; + $fleet['class'] = "green"; + } else { + $fleet['dir'] = "Im Orbit"; + } + } + if($fleet['tgala']) $fleet['dir'] .= " (".$fleet['tgala'].":".$fleet['tpos'].")"; + $fleet['irc'] = generate_irc_user_fleet($j,$fleet,$list[$i]); + $gesamt['cancris'] += $fleet['cancris']; + $gesamt['kleptoren'] += $fleet['kleptoren']; + $gesamt['fregatten'] += $fleet['fregatten']; + $gesamt['zerstoerer'] += $fleet['zerstoerer']; + $gesamt['bomber'] += $fleet['bomber']; + $gesamt['jaeger'] += $fleet['jaeger']; + $gesamt['schlachter'] += $fleet['schlachter']; + $gesamt['traeger'] += $fleet['traeger']; + $gesamt['kreuzer'] += $fleet['kreuzer']; + } + $gesamt['irc'] = generate_irc_user_fleet(3,$gesamt,$list[$i]); + $list[$i]['fleets'][3] = $gesamt; + if($list[$i]['fleetupdate']) { + $list[$i]['fleetdate'] = formatdate_unix("d.m.Y",$list[$i]['fleetupdate']); + $list[$i]['fleettime'] = date("H:i",$list[$i]['fleetupdate']); + } + } + $this->template->assign('list',$list); + } + $this->template->assign("ally",getAlly($this->userdata['aid'])); + $this->template->assign('galalist',$galalist); + $this->show('userfleets_index',"Flottenpflege"); + } + + ############################################################################# + + function User_fleet() { + $id = param_num("id"); + if ($id) { + $user = getUserByID($id); + if(!$user || $user['aid'] != $this->userdata['aid']) $this->_header(); + $this->template->assign("id",$id); + } else { + $id = $this->userdata['uid']; + $user = $this->userdata; + } + + $deff['rubium'] = $user['rubium']; + $deff['pulsar'] = $user['pulsar']; + $deff['horus'] = $user['horus']; + $deff['coon'] = $user['coon']; + $deff['centurion'] = $user['centurion']; + $this->template->assign("deff",$deff); + $fleets = user_fleet_list_byuser($id); + if($user['fleetupdate']) { + $this->template->assign("fleettime",date("H:i",$user['fleetupdate'])); + $this->template->assign("fleetdate",formatdate_unix("d.m.Y",$user['fleetupdate'])); + } + if($user['deffupdate']) { + $this->template->assign("defftime",date("H:i",$user['deffupdate'])); + $this->template->assign("deffdate",formatdate_unix("d.m.Y",$user['deffupdate'])); + } + for($i=0;$i < 3;$i++){ + if($fleets[$i]['return_flight']) { + $fleets[$i]['dir'] = "Rückflug"; + $fleets[$i]['class'] = "blue"; + } else { + if ($fleets[$i]['status'] == 1) { + $fleets[$i]['dir'] = "Angriff"; + $fleets[$i]['class'] = "red"; + } + elseif ($fleets[$i]['status'] == 2) { + $fleets[$i]['dir'] = "Verteidigung"; + $fleets[$i]['class'] = "green"; + } else { + $fleets[$i]['dir'] = "Im Orbit"; + } + } + if($fleets[$i]['tgala']) $fleets[$i]['dir'] .= " (".$fleets[$i]['tgala'].":".$fleets[$i]['tpos'].")"; + if($fleets[$i]['arrival']) { + $fleets[$i]['eta'] = $fleets[$i]['arrival']-time(); + if ($fleets[$i]['eta'] < 0) { + $fleets[$i]['orbit'] = "noch ".$this->formattime($fleets[$i]['orbittime']*60 + $fleets[$i]['eta'],true)." im Orbit"; + $fleets[$i]['eta'] = 0; + } else { + $fleets[$i]['orbit'] = $this->formattime($fleets[$i]['orbittime']*60,true)." im Orbit"; + } + $fleets[$i]['eta'] = "ETA ".$this->formattime($fleets[$i]['eta'],true); + } + } + $this->template->assign("fleets",$fleets); + $this->template->assign("user",$user); + $this->show("user_fleetupdate","Flottenupdate"); + } + ############################################################################# + + function User_fleet_status() { + $id = param_num("id"); + if ($id) { $this->template->assign("id",$id); } else { $id = $this->userdata['uid']; } + + if(!($user = getUserByID($id)) || $user['aid'] != $this->userdata['aid']) $this->_header(); + + #information message, step 2 + if ($_SESSION['steps']['fleetstatus']) { + #unset step + unset($_SESSION['steps']['fleetstatus']); + $_SESSION['steps'] = $data; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['title'] = "Flottenstatus updaten"; + $this->forms['information']['message'] = "Flottenstatus aktualisiert"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Flottenstatus updaten"); + } + + $fleetnum = param_num("fleet"); + $fleet = user_fleet_bynum($id,$fleetnum); + + if(!$fleet) $this->_header("index.php"); + + $form = new formContainer(); + $form->add(new formInput("target","Zielkoordinaten","string",true,10,true,"'^\s*(\d{1,4}):(\d{1,2})\s*$'is")); + $form->add(new formInput("eta","Flugzeit (ETA)","string",true,10,false,"'^\s*(?:(\d{1,3})|(\d{1,2}):(\d{1,2}))\s*$'is")); + + $status_titles[] = array("title" => "Im Orbit","value"=>0); + $status_titles[] = array("title"=>"Angriffsflug","value" => 1); + $status_titles[] = array("title"=>"Verteidigung","value"=>2); + + if(!$fleet['status']) { + $status_titles[] = array("value"=>3,"title"=>"Rückflug"); + } else { + if($fleet['tgala'] && $fleet['tpos']) { + $galastr = " von ".$fleet['tgala'].":".$fleet['tpos']; + } + if($fleet['status'] == 1) $typestr = "Angriff"; + else $typestr = "Verteidigung"; + $status_titles[] = array("title"=>"Rückflug ".$typestr.$galastr,"value"=>3); + } + + $form->add(new formSelectBox("status","Flottenstatus","numeric",$status_titles,false)); + + $orbit = new formInput("orbit","Zeit im Orbit","string",true,10,false,"'^(?:(\d+):(\d+)|(\d+))$'is"); + $defftype = new formSelectBox("defftype","Verteidigung","numeric", + array( + array("title" => "Galaintern (".$this->formattime(270*60,true).")", "value" => 270), + array("title" => "Allyintern (".$this->formattime(300*60,true).")", "value" => 300), + array("title" => "Meta (".$this->formattime(330*60,true).")", "value" => 330), + array("title" => "extern (".$this->formattime(360*60,true).")", "value" => 360), + ),false); + + if ($_POST['send']) { + $form->submit("status"); + $data['status'] = $form->get("status"); + if($_POST['next_x']) { + switch ($data['status']) { + case 1: { + $form->add(&$orbit); + $form->submit(array("target","orbit","eta")); + $data['returntime'] = 450; + break; + } + case 2: { + $form->add(&$orbit); + $form->add(&$defftype); + $form->submit(array("target","orbit","defftype","eta")); + $data['returntime'] = $form->get("defftype"); + break; + } + case 3: { + $form->submit("eta"); + } + } + + if (!$form->hasErrors()) { + // save step + if($data['status'] == 3) { + $eta = $form->getregex("eta"); + if($eta[1]) $eta = $eta[1]; + else $eta = $eta[2]*60+$eta[3]; + if($eta < 0) $eta = 0; + $data['arrival'] = gnarrival($eta); + } + if($data['status'] == 1 || $data['status'] == 2) { + $eta = $form->getregex("eta"); + if($eta[1]) $eta = $eta[1]; + else $eta = $eta[2]*60+$eta[3]; + + $orbit = $form->getregex("orbit"); + if($orbit[1]) $orbit = $orbit[1]*60+$orbit[2]; + else $orbit = $orbit[3]; + + + if($eta == 0){ + $data['orbittime'] = gnticktime($orbit); + $data['arrival'] = time(); + } else { + $data['arrival'] = gnarrival($eta); + $data['orbittime'] = $orbit; + } + $target = $form->getRegex("target"); + $data['tgala'] = $target[1]; + $data['tpos'] = $target[2]; + $data['return_flight'] = 0; + } + if($data['status'] == 1 && $data['tgala'] && (user_get_bypos($data['tgala'],$data['tpos']))) { + $form->setError("target"); + $form->addError("Ziel ist Metamuitglied"); + } + } + if (!$form->hasErrors()) { + $_SESSION['steps']['fleetstatus'] = 1; + if($data['status'] == 3) { + $data['status'] = $fleet['status']; + $data['tgala'] = $fleet['tgala']; + $data['tpos'] = $fleet['tpos']; + $data['return_flight'] = 1; + } + $data['fleetnum'] = $fleetnum; + $data['gala'] = $user['gala']; + $data['pos'] = $user['pos']; + $data['fid'] = $fleet['fid']; + if($data['status'] || $data['return_flight']) { + if($fleet['fsid']) { + fleetstatus_update($fleet['fsid'],$data); + } else { + #$check = fleetstatus_get_byfleetnum($user['gala'],$user['pos'],true); + #if(count($check) >= 2) fleetstatus_delete($check[0]['fsid']); + fleetstatus_add($data); + } + } else { + if($fleet['fsid']) fleetstatus_delete($fleet['fsid']); + } + $this->_header("user.php?action=fleetstatus&send"); + } + } else { + if($data['status'] == 1) $form->add(&$orbit); + if($data['status'] == 2) {$form->add(&$orbit);$form->add(&$defftype);} + + if($data['status'] == 1) { + if($data['status'] == $fleet['status'] && !$fleet['return_flight']) { + $form->set("orbit",$this->formattime($fleet['orbittime']*60)); + if($fleet['tgala']) { + $form->set("target","$fleet[tgala]:$fleet[tpos]"); + } + } else { + $form->set("orbit",$this->formattime(75*60)); + } + } + if($data['status'] == 2) { + if($data['status'] == $fleet['status'] && !$fleet['return_flight']) { + $defftype->select($fleet['returntime']); + $form->set("orbit",$this->formattime($fleet['orbittime']*60)); + if($fleet['tgala']) { + $form->set("target",$fleet['tgala'].":".$fleet['tpos']); + } + } else { + $form->set("orbit",$this->formattime(300*60)); + $defftype->select(360); + } + } + if (($fleet['status'] == 2 || $fleet['status'] == 1) && $data['status'] == 3 && !$fleet['return_flight']) { + $eta = $fleet['arrival']-time(); + if($eta < 0) $eta = 0; + $form->set("eta",$this->formattime($fleet['returntime']*60-$eta)); + } + if($data['status'] == $fleet['status'] || $data['status'] == 3 && $fleet['return_flight']) { + $form->set("eta",$this->formattime($fleet['arrival']-time())); + } + } + } else { + if($fleet['return_flight'] ) { + $data['status'] = 3; + } else { + $data['status'] = $fleet['status']; + if(($fleet['status'] == 1 || $fleet['status'] == 2) && $fleet['tgala']) { + $form->set("target",$fleet['tgala'].":".$fleet['tpos']); + } + } + $form->select("status",$data['status']); + #$form->set("status",$data['status']); + if($data['status'] == 1 || $data['status'] == 2) { + $form->add(&$orbit); + } + if ($fleet['arrival']) { + $eta = $fleet['arrival']-time(); + if($eta < 0) $eta_exact = 0; else $eta_exact = $eta; + $form->set("eta",$this->formattime($eta_exact)); + } + if($data['status'] == 2) { + if($fleet['orbittime']) { + if($eta < 0) $orbittime = $fleet['orbittime']*60+$eta; else $orbittime = $fleet['orbittime']*60; + $form->set("orbit",$this->formattime($orbittime)); + } + } + if($data['status'] == 1) { + #echo "eta: ".($eta/60)."
"; + if($fleet['orbittime']) { + if($eta < 0) $orbittime = $fleet['orbittime']*60+$eta; else $orbittime = $fleet['orbittime']*60; + $form->set("orbit",$this->formattime($orbittime)); + } + } + if($data['status'] == 2) { + $form->add(&$defftype); + $form->select("defftype",$fleet['returntime']); + } + } + + $form->registerVars(&$this->template); + + $this->template->assign("fleet",$fleetnum); + $this->show("user_fleetstatus","Flottenstatus updaten"); + } + ############################################################################# + function User_fleet_parser() { + $id = param_num("id"); + if ($id) { + $user = getUserByID($id); + if(!$user) $this->_header(); + $this->template->assign("id",$id); + } else { + $id = $this->userdata['uid']; + } + $data = $_SESSION['steps']; + #information message, step 2 + if ($data['fleetparser']) { + #unset step + unset($data['fleetparser']); + $_SESSION['steps'] = $data; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['title'] = "Flotte/Deff updaten"; + $this->forms['information']['message'] = "Flotte/Deff aktualisiert"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Flotte/Deff updaten"); + } + $form = new formContainer(); + $form->add(new formInput("fleet","Text","string")); + if ($_POST['send'] && $_POST['next_x']) { + $form->submit(); + if(!$form->hasErrors()) { + $text = $form->get("fleet"); + if(!($taktik = parse_taktikansicht($text))) { + $fleets = parse_user_flottenbewegung($text,$this->userdata["gala"],$this->userdata["pos"]); + //echo "
".print_r($fleets,1)."
"; + $deff = parse_user_verteidigung($text); + if($fleets === false && $deff === false) { + $form->setError("fleet"); + $form->addError("es konnte nichts erkannt werden"); + } + } else { + $fleets = $taktik[0]['fleets']; + $deff = $taktik[0]['deff']; + } + if(!$form->hasErrors()) { + $_SESSION['steps']['fleetparser'] = 1; + if(!($fleets === false)) { + user_fleets_update($id,$fleets); + } + if(!($deff === false)) { + user_deff_update($id,$deff); + } + $this->_header("user.php?action=fleetparser&send"); + } + } + } + $form->registerVars($this->template); + $this->show("user_fleetupdate_parser","Flottenupdate"); + } + ############################################################################# + function User_fleet_manuell() { + $id = param_num("id"); + if ($id) { + $user = getUserByID($id); + if(!$user || $user['aid'] != $this->userdata['aid']) $this->_header(); + $this->template->assign("id",$id); + } else { + $id = $this->userdata['uid']; + } + $data = $_SESSION['steps']; + #information message, step 2 + if ($data['fleetmanuell']) { + #unset step + unset($data['fleetmanuell']); + $_SESSION['steps'] = $data; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['title'] = "Flotte updaten"; + $this->forms['information']['message'] = "Flotte aktualisiert"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Flotte updaten"); + } + $names = array("Jäger"=>"jaeger","Bomber"=>"bomber","Fregatten"=>"fregatten","Zerstörer"=>"zerstoerer","Kreuzer"=>"kreuzer","Schlachtschiffe"=>"schlachter","Träger"=>"traeger","Kleptoren"=>"kleptoren","Schutzschiffe"=>"cancris"); + $fleets = user_fleet_list_byuser($id); + $form = new formContainer(); + foreach ($names as $title => $name) { + for ($i=0;$i<3;$i++) { + $form->add(new formInput($name.$i,$title,"numeric")); + } + } + if ($_POST['send'] && $_POST['next_x']) { + $form->submit(); + if (!$form->hasErrors()){ + $_result = array(); + foreach ($fleets as $fleet) { + foreach ($names as $title => $name) { + $_result[$fleet['fleetnum']][$name] = $form->get($name.$fleet['fleetnum']); + } + } + user_fleets_update($id,$_result); + $_SESSION['steps']['fleetmanuell'] = 1; + $this->_header("user.php?action=fleetmanuell&send"); + } + } else { + foreach($fleets as $fleet){ + $num = $fleet['fleetnum']; + foreach ($names as $key => $name){ + $val = &$fleet[$name]; + if ($val){ + $form->set($name.$num,$val); + } else { + $form->set($name.$num,0); + } + } + } + } +# $this->template->assign("errors",$errors); +# $this->template->assign("items",$items); + $form->registerVars($this->template); + $this->show("user_fleetupdate_manuell","Flottenupdate"); + } + ############################################################################# + function User_orbit_manuell() { + $id = param_num("id"); + if ($id) { + $user = getUserByID($id); + if(!$user || $user['aid'] != $this->userdata['aid']) $this->_header(); + $this->template->assign("id",$id); + } else { + $id = $this->userdata['uid']; + } + $data = $_SESSION['steps']; + #information message, step 2 + if ($data['orbitmanuell']) { + #unset step + unset($data['orbitmanuell']); + $_SESSION['steps'] = $data; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['title'] = "Verteidigung updaten"; + $this->forms['information']['message'] = "Verteidigung aktualisiert"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Verteidigung updaten"); + } + $names = array("Abfangjäger"=>"horus","Rubis"=>"rubium","Pulsare"=>"pulsar","Coons"=>"coon","Centurions"=>"centurion"); + if ($_POST['send'] && $_POST['next_x']) { + foreach ($names as $key => $name){ + $val = trim($_POST[$name]); + if (strlen($val)){ + if ((is_numeric($val) && $val >= 0)) { + $deff[$name]= $val; + } else { + $errors[] = "$key ungültig"; + $items[$name]['class'] = "_error"; + } + $items[$name]['value'] = $val; + } + } + if (!$errors){ + $data['orbitmanuell'] = 1; + $_SESSION['steps'] = $data; + User_deff_update($id,$deff); + $this->_header("user.php?action=orbitmanuell&send"); + } + } else { + $deff = User_deff_get($id); + foreach ($names as $key => $name){ + $val = $deff[$name]; + if ($val){ + $items[$name]['value'] = $val; + } else { + $items[$name]['value'] = 0; + } + } + } + $this->template->assign("errors",$errors); + $this->template->assign("items",$items); + $this->show("user_orbitalupdate_manuell","Orbitalverteidigung updaten"); + } + ############################################################################# + function User_orbit_parser() { + $id = param_num("id"); + if ($id) { + $user = getUserByID($id); + if(!$user || $user['aid'] != $this->userdata['aid']) $this->_header(); + $this->template->assign("id",$id); + } else { + $id = $this->userdata['uid']; + } + $data = $_SESSION['steps']; + #information message, step 2 + if ($data['orbitparser']) { + #unset step + unset($data['orbitparser']); + $_SESSION['steps'] = $data; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['title'] = "Verteidigung updaten"; + $this->forms['information']['message'] = "Verteidigung aktualisiert"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Verteidigung updaten"); + } + $names = array("Horus"=>"horus","Rubium"=>"rubium","Pulsar"=>"pulsar","Coon"=>"coon","Centurion"=>"centurion"); + if ($_POST['send'] && $_POST['next_x']) { + $val = stripslashes(param_str("deff")); + $items['deff']['value'] = $val; + if (!$val){ + $errors[] = "Feld ist leer!"; + $items['deff']['class'] = "_error"; + } else { + if(preg_match("/^.*?". + "Leichtes Orbitalgeschütz \"Rubium\":.*?(\d+?)\s*?". + "Leichtes Raumgeschütz \"Pulsar\":.*?(\d+?)\s*?". + "Mittleres Raumgeschütz \"Coon\":.*?(\d+?)\s*?". + "Schweres Raumgeschütz \"Centurion\":.*?(\d+?)\s*?". + "Abfangjäger \"Horus\":.*?(\d+?)\s*?". + "$/si",$val,$result)) { + $deff['rubium'] = $result[1]; + $deff['pulsar'] = $result[2]; + $deff['coon'] = $result[3]; + $deff['centurion'] = $result[4]; + $deff['horus'] = $result[5]; + } else { + $errors[] = "Verteidigung nicht erkannt!"; + $items['deff']['class'] = "_error"; + } + } + if (!$errors){ + $data['orbitparser'] = 1; + $_SESSION['steps'] = $data; + User_deff_update($id,$deff); + $this->_header("user.php?action=orbitparser&send"); + } + } + $this->template->assign("errors",$errors); + $this->template->assign("items",$items); + $this->show("user_orbitalupdate_parser","Orbitalverteidigung updaten"); + } ############################################################################# + # + # Password ändern + # + function changePassword() { + $data = $_SESSION['steps']; + #information message, step 2 + if ($data['changepwd']) { + #save registration step + unset($data['changepwd']); + $_SESSION['steps'] = $data; + $this->forms['information']['action'] = ""; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['title'] = "Passwort ändern"; + $this->forms['information']['message'] = "Passwortänderung erfolgreich"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Passwort ändern"); + } + #formular send + if ($_REQUEST['step']) { + $items['oldpassword'] = param_str("oldpassword",true);; + $items['password'] = param_str("password",true); + $items['password2'] = param_str("password2",true); + $errors = false; + #check if empty + foreach ( $items as $key => $value) { + if (!$value) { + $this->forms['changepwd']['fields'][$key]['error'] = 'Feld darf nicht leer sein!'; + $this->forms['changepwd']['fields'][$key]['bgrd'] = '_error'; + $errors = true; + } else { + $this->forms['changepwd']['fields'][$key]['value'] = $value; + } + } + #check passwords + if (!$errors && $items['password'] != $items['password2']) { + $errors = true; + $this->forms['changepwd']['fields']['password']['error'] = 'Passwörter müssen gleich sein!'; + $this->forms['changepwd']['fields']['password']['bgrd'] = '_error'; + $this->forms['changepwd']['fields']['password2']['error'] = 'Passwörter müssen gleich sein!'; + $this->forms['changepwd']['fields']['password2']['bgrd'] = '_error'; + } + #check old password + if (!$errors && $this->userdata['password'] != md5($items['oldpassword'])) { + $errors = true; + $this->forms['changepwd']['fields']['oldpassword']['error'] = 'Passwort ungültig!'; + $this->forms['changepwd']['fields']['oldpassword']['bgrd'] = '_error'; + } + if (!$errors) { + updateUserPassword($this->userdata['uid'],$items['password']); + $sessionuserdata['id'] = $this->userdata['uid']; + $sessionuserdata['password'] = md5($items['password']); + $_SESSION['sessionuserdata'] = $sessionuserdata; + addToLogfile("Passwort geändert","User",$this->userdata['uid']); + + #save step + $data['changepwd'] = 1; + $_SESSION['steps'] = $data; + $this->_header("user.php?action=changepwd&send"); + } + } + if ($this->userdata['changepw']) { + $this->forms['changepwd']['message'] = "Sie müssen ihr Passwort jetzt ändern !"; + } + $this->forms['changepwd']['url'] = 'user.php'; + $this->forms['changepwd']['action'] = 'changepwd'; + $this->show('user_changepwd_form',"Passwort ändern"); + } + # + # ändert die Benutzerdaten + # + function UserSettings() { + $data = $_SESSION['steps']; + #information message, step 2 + if ($data['usersettings']) { + #save step + unset($data['usersettings']); + $_SESSION['steps'] = $data; + $this->forms['information']['action'] = ""; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['title'] = "Benutzerdaten ändern"; + $this->forms['information']['message'] = "Änderung erfolgreich"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Benutzerdaten ändern"); + } + #formular send + if ($_REQUEST['step']) { + $items['email']['value'] = param_str("email",true); + $items['nick']['value'] = param_str("nick",true); + $items['login']['value'] = param_str("login",true); + $items['svs']['value'] = param_num("svs",0); + $items['fleettype']['value'] = param_num("fleettype",1); + $items['scantype']['value'] = param_num("scantype",0); + $items['timeview']['value'] = param_num("timeview",0); + + if (!$items['email']['value']) { + $errors[] = "Email fehlt!"; + $items['email']['bgrd'] = "_error"; + } + if (!$items['nick']['value']) { + $errors[] = "GN Nickname fehlt!"; + $items['nick']['bgrd'] = "_error"; + } + if (!$items['login']['value']) { + $errors[] = "Login fehlt!"; + $items['login']['bgrd'] = "_error"; + } + if ($_POST['emailvisible']) { + $items['emailvisible']['value'] = 1; + } else { + $items['emailvisible']['value'] = 0; + } + #optional parameters + $items['phone']['value'] = param_str("phone",true); + + #check nickname + if ($items['nick']['value'] && strtolower($items['nick']['value']) != strtolower($this->userdata['nick']) && getUserByNick($items['nick']['value'])) { + $errors[] = "Nickname existiert bereits"; + $items['nick']['bgrd'] = "_error"; + } + #check login + if ($items['login']['value'] && strtolower($items['login']['value']) != strtolower($this->userdata['login']) && getUserByLogin($items['login']['value'])) { + $errors[] = "Login bereits vergeben"; + $items['login']['bgrd'] = "_error"; + } + if (!$errors) { + #save step + $data['usersettings'] = 1; + $_SESSION['steps'] = $data; + addToLogfile("Benutzereinstellungen geändert","User",$this->userdata['uid']); + updateUser($this->userdata['uid'], + $items['nick']['value'], + $items['login']['value'], + $items['email']['value'], + $items['emailvisible']['value'], + $items['phone']['value'], + $items['scantype']['value'], + $items['svs']['value'], + $items['timeview']['value'], + $items['fleettype']['value'] + ); + $this->_header("user.php?action=settings&send"); + } + } else { + $items['login']['value'] = $this->userdata['login']; + $items['nick']['value'] = $this->userdata['nick']; + $items['email']['value'] = $this->userdata['email']; + $items['emailvisible']['value'] = $this->userdata['emailvisible']; + $items['phone']['value'] = $this->userdata['phone']; + $items['scantype']['value'] = $this->userdata['scantype']; + $items['svs']['value'] = $this->userdata['svs']; + $items['timeview']['value'] = $this->userdata['timeview']; + $items['fleettype']['value'] = $this->userdata['fleettype']; + } + if (!$items['phone']['value']) { + $items['phone']['bgrd'] = "_optional"; + } + $this->template->assign("scantype".$items['scantype']['value'],"checked"); + $this->template->assign("timeview".$items['timeview']['value'],"checked"); + $this->template->assign("fleettype".$items['fleettype']['value'],"checked"); + $this->template->assign("errors",$errors); + $this->template->assign("items",$items); + $this->show('user_settings_form',"Benutzerdaten ändern"); + } + # + # Zeigt Benutzerinfos + # + function showUserDetails() { + $id = param_num("id"); + if (!$id) $this->_header($this->backtracking->backlink()); + $return = getUserByID($id); + if (!$return) $this->_header($this->backtracking->backlink()); + $this->forms['userdetails']['registerdate'] = $return['registerdate']; + $this->forms['userdetails']['nickname'] = $return['nick']; + $this->forms['userdetails']['allyname'] = $return['name']; + $this->forms['userdetails']['allytag'] = $return['tag']; + if($return['emailvisible']) { + $this->forms['userdetails']['email'] = $return['email']; + } + $this->forms['userdetails']['koords'] = $return['gala'].":".$return['pos']; + if($return['usertitle']) { + $this->forms['userdetails']['usertitle'] = $return['usertitle']; + } + if($return['phone']) { + $this->forms['userdetails']['phone'] = $return['phone']; + } + $this->show('user_details',"Benutzerdetails"); + } +} +?> \ No newline at end of file diff --git a/src/configs/config.php b/src/configs/config.php new file mode 100644 index 0000000..2092088 --- /dev/null +++ b/src/configs/config.php @@ -0,0 +1,20 @@ +Huhn 2004-2009"); + +?> \ No newline at end of file diff --git a/src/configs/log4php.xml b/src/configs/log4php.xml new file mode 100644 index 0000000..5c6092e --- /dev/null +++ b/src/configs/log4php.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/configs/style.css b/src/configs/style.css new file mode 100644 index 0000000..994e627 --- /dev/null +++ b/src/configs/style.css @@ -0,0 +1,391 @@ + +* { + font-family: Tahoma; + font-size: 11px; +} + +/* contentboxen */ +table.contentbox { + border-collapse: collapse; + border: 1px solid black; + empty-cells: hide; + margin-bottom: 7px; +} + +table.contentbox td.header { + background-image: url(../images/menu_topic_bg.gif); + font-size: 11px; + padding: 1px; + height: 15px; +} + +table.contentbox td.content { + padding: 0px; + border-bottom: 1px solid; + background-color: #EEEEEE; +} + +table.contentbox table.content { + padding-left: 3px; +} + +table.contentbox table.content tr.firstline td { + padding-top:5px; + padding-bottom:3px; +} + +table.contentbox table.content tr.line td { + padding-bottom:1px; + padding-top:1px; +} + +table.contentbox table.content tr.lastline td { + padding-top:3px; + padding-bottom:3px; +} + +/* contentformatierung*/ + +table.content td.header { + background: #DEE3E7; + color: #000000; + padding: 3px; +} + + +table.content td.footer { + background: #DEE3E7; + color: #000000; + padding: 3px; +} + + +table.content td.headline { + background: #E8E7E7; + color: #000000; + padding: 3px; +} + +td#hline { + border-top: 1px solid #9D9D9D; +} + +table.content td.color1 +{ + background: #E2F2E2; + color: #000000; +} + +table.content td.color2 +{ + background: #EFEFEF; + color: #000000; +} + +.form_left { + background: #E8E7E7; +} + +.form_right { + background: #EFEFEF; +} + +input.button +{ + color: Black; + border: 1px outset #E1E0E1; + background-color:#E1E0E1; + +} + +input.button_small +{ + font-size: 10px; + color: Black; + border: 2px outset #E1E0E1; + background-color:#E1E0E1; + +} + +table.small +{ + font-size: 9px; +} + + +.form_small +{ + font-size: 10px; + color: #000000; + border: 1px inset #E1E0E1; + background-color:#E1E0E1; + background-image:url(images/index_form_bg.gif); +} + +.form_optional +{ + color: #000000; + border: 1px inset #E2F2E2; + background-color:#E2F2E2; +} + +.form_error +{ + color: #000000; + border: 1px inset #FF9999; + background-color:#FF9999; +} + +.form +{ + color: #000000; + border: 1px inset #E1E0E1; + background-color:#E1E0E1; + +} + + + + + + +body +{ + background: #FFFFFF; +} + +.tbl_0 +{ + font-weight: normal; + color: #000000; + text-align: left; +} + +.tbl_1 +{ + background: #EFEFEF; + font-weight: normal; + color: #000000; + text-align: left; +} + +.tbl_2 +{ + background: #E2F2E2; + font-weight: normal; + color: #000000; + text-align: left; +} + +.tbl_4 +{ + background: #9D9D9D; + font-weight: normal; + color: #000000; + text-align: left; +} + +.tbl_5 +{ + background: #DEE3E7; + color: #000000; + text-align: left; +} + +.tbl_6 +{ + background: #E8E7E7; + font-weight: normal; + color: #000000; + text-align: left; +} + +.tbl_7 +{ + background: #fcfcfc; + font-weight: normal; + color: #000000; + text-align: left; +} + +.tbl_8 +{ + background: #000000; +} + +.tbl_9 +{ + background: #9CA8B6; + font-weight: normal; + color: #000000; + text-align: left; +} + +.tbl_helplet +{ + background: #FFFFFF; + font-weight: normal; + color: #000000; + text-align: left; +} + +.tbl_helplet_left +{ + background: #80ACF7; + font-weight: normal; + color: #000000; + text-align: left; +} + +.tbl_helplet_right +{ + background: #E4E4E4; + font-weight: normal; + color: #000000; + text-align: left; +} + +.tbl_important +{ + background: #FFDE9B; + font-weight: normal; + color: #000000; + text-align: left; +} + +.tbl_small +{ + font-size: 10px; + font-weight: normal; + color: #000000; +} + +.tbl_small2 +{ + font-size: 10px; + font-weight: normal; + color: #666666; +} + +.tbl_1_error +{ + background: #FFDE9B; + font-weight: normal; + color: #000000; + text-align: left; +} + +.tbl_1_off +{ + background: #EFEFEF; + font-weight: normal; + color: #a4a4a4; + text-align: left; +} + +.tbl_error +{ + font-weight: normal; + color: #FF0000; + text-align: left; +} + +.tbl_black +{ + font-weight: normal; + color: #000000; + text-align: left; +} + +.tbl_red +{ + font-weight: normal; + color: #FF0000; + text-align: left; +} +.bold { + font-weight: bold; +} +.red +{ + color: #FF0000; +} + +.tbl_green +{ + font-weight: normal; + color: #00A800; + text-align: left; +} + +.green +{ + color: #00A800; +} + +.tbl_blue +{ + font-weight: normal; + color: #2264DD; + text-align: left; +} + +.blue +{ + color: #2264DD; +} + +a.noline:link, a.noline:visited +{ + color: #000000; + text-decoration: none; +} + +a.noline:hover +{ + color: #FF9000; + text-decoration: none; +} + +a:link, a:visited, a.link:link, a.link:visited +{ + color: #000000; + text-decoration: underline; +} + +a:hover +{ + text-decoration: underline; +} + +a.menu:link, a.menu:visited +{ + color: #000000; + text-decoration: none; +} + +a.menu:hover +{ + color: #FF9000; + text-decoration: underline; +} + +a.admin:link, a.admin:visited +{ + color: #FF0000; + text-decoration: none; +} +a.admin:hover +{ + color: #FF0000; + text-decoration: underline; +} + + + + + +.img +{ + border-color: #000000; +} \ No newline at end of file diff --git a/src/database/database.php b/src/database/database.php new file mode 100644 index 0000000..ba3721a --- /dev/null +++ b/src/database/database.php @@ -0,0 +1,108 @@ +"; + var_dump($query); + $debug_tracking = debug_backtrace(); + for($i=1;$i < 3;$i++) { + $line = $debug_tracking[$i]; + $attrs = array(); + if(isset($line['function'])) $attrs[] = "function=\"".$line['function']."\""; + if(isset($line['file'])) $attrs[] = "file=\"".$line['file']."\""; + if(isset($line['line'])) $attrs[] = "line=\"".$line['line']."\""; + if(isset($line['class'])) $attrs[] = "class=\"".$line['class']."\""; + echo "".join(" ",$attrs)."\n"; + } + echo""; + } + + function selectsql($query,$col_name=null) { + global $debug_database, $firephp; + $result = mysql_query ($query) or db_error(array("ungültige Abfrage",$query)); + $lines = array(); + while(($row = mysql_fetch_array($result, MYSQL_ASSOC))) { + if(isset($col_name)) { + if(is_array($col_name)) { + foreach ($col_name as $col) { + $lines[$col][] = $row[$col]; + } + } else { + $lines[] = $row[$col_name]; + } + } else { + $lines[] = $row; + } + } + mysql_free_result($result); + if($debug_database) { + $firephp->group("select sql"); + $firephp->log($query,"query"); + $firephp->log($lines,"select sql result"); + $firephp->trace("stacktrace"); + $firephp->groupEnd(); + } + + return $lines; + } + + function selectsqlline($query) { + global $debug_database, $firephp; + $result = mysql_query ($query) or db_error(array("ungültige Abfrage",$query)); + $row = mysql_fetch_array($result, MYSQL_ASSOC); + mysql_free_result($result); + + if($debug_database) { + $firephp->group("select sql line"); + $firephp->log($query,"query"); + $firephp->log($row,"result"); + $firephp->trace("stacktrace"); + $firephp->groupEnd(); + } + return $row; + } + + function insertsql($query) { + global $debug_database, $firephp; + mysql_query ($query) or db_error(array("ungültige Abfrage",$query)); + $result = mysql_insert_id(); + if($debug_database) { + $firephp->group("insert sql"); + $firephp->log($query,"query"); + $firephp->log($result,"result"); + $firephp->trace("stacktrace"); + $firephp->groupEnd(); + } + return $result; + } + + function query($query) { + global $debug_database, $firephp; + mysql_query ($query) or db_error(array("ungültige Abfrage",$query)); + $result = mysql_affected_rows(); + if($debug_database) { + $firephp->group("query"); + $firephp->log($query,"query"); + $firephp->log($result,"result"); + $firephp->trace("stacktrace"); + $firephp->groupEnd(); + } + return $result; + } + + function db_error($msg) { + if(!is_array($msg)) { + $msg = trim(str_replace("\t", "", $msg)); + $msg = array($msg); + } + $msg[] = trim(mysql_error()); +// $firephp->error(join(",",$msg)); +// $firephp->trace("db error"); + trigger_error(join("\n",$msg),E_USER_ERROR); + die(); + } + + $db = mysql_connect($db_host, $db_user, $db_password) or die(); + mysql_select_db($db_database) or db_error("Auswahl der Datenbank fehlgeschlagen"); + + +?> \ No newline at end of file diff --git a/src/database/db.ally.php b/src/database/db.ally.php new file mode 100644 index 0000000..14aa092 --- /dev/null +++ b/src/database/db.ally.php @@ -0,0 +1,111 @@ + \ No newline at end of file diff --git a/src/database/db.attplan.php b/src/database/db.attplan.php new file mode 100644 index 0000000..e608c14 --- /dev/null +++ b/src/database/db.attplan.php @@ -0,0 +1,238 @@ + \ No newline at end of file diff --git a/src/database/db.bot.php b/src/database/db.bot.php new file mode 100644 index 0000000..98a0343 --- /dev/null +++ b/src/database/db.bot.php @@ -0,0 +1,65 @@ + \ No newline at end of file diff --git a/src/database/db.gala.php b/src/database/db.gala.php new file mode 100644 index 0000000..92f921a --- /dev/null +++ b/src/database/db.gala.php @@ -0,0 +1,129 @@ + \ No newline at end of file diff --git a/src/database/db.group.php b/src/database/db.group.php new file mode 100644 index 0000000..441c01c --- /dev/null +++ b/src/database/db.group.php @@ -0,0 +1,164 @@ +=$rank OR grouprank IS NULL + ORDER BY name ASC "); + } else { + return selectsql("select * from groups order by name asc"); + } +} + +function getGroup($gid) { + + if (!$gid || !is_numeric($gid)) return ; + $return = selectsqlLine("select * from groups where gid = $gid"); + return $return; +} + +function listRightsByGroup($gid) { + + return selectsql("select r.*,gr.rank,gr.gid as isset from + rights r + left join group_rights gr on(gr.rid = r.rid and gr.gid = $gid) + order by r.pos asc"); +} + +function updateRights($gid,$rank,$ids) { + + query("delete from group_rights where gid = $gid and rank = $rank"); + $rights = selectsql("select rid from group_rights + where gid = $gid and rank >= $rank"); + for($i=0;$i < count($ids);$i++){ + if (searchArray("rid",$ids[$i],$rights)){ + query("update group_rights + set rank = $rank where rid = ".$ids[$i]." AND gid = $gid"); + } else { + query("insert into group_rights(rank,rid,gid) + values ($rank,".$ids[$i].",$gid)"); + } + } +} + +function updateGroup($gid,$name,$descr,$title) { + + if (!$gid || !is_numeric($gid)) {echo "db.group:updateGroup Ungültiger Parameter!";return ;} + if (!$name || !$descr ) {echo "db.group:updateGroup Fehlender Parameter!";return ;} + query("update groups set name = '$name', descr = '$descr', usertitle = '$title' where gid = $gid"); +} + +function addGroup($name,$descr,$title) { + + if (!$name || !$descr) {echo "db.group:addGroup Fehlender Parameter!";return ;} + $gid = insertSQL("insert into groups (name, descr, usertitle) values('$name','$descr','$title')"); + if (!$gid) {echo "db.group:addGroup Einfügen fehlgeschlagen!";return ;} + return $gid; +} + +function deleteGroup($gid) { + + if (!$gid || !is_numeric($gid)) {echo "db.group:deleteGroup Ungültiger Parameter!";return ;} + query("update user set gid = 0 where gid = $gid"); + query("delete from group_rights where gid = $gid"); + query("delete from groups where gid = $gid"); +} + +function getGroupByName($name) { + + if (!$name ) {echo "db.group:getGroupByName Fehlender Parameter!";return ;} + return selectsqlLine("select * from groups where name = '$name'"); +} + +function listGroupsByRank($rank) { + + if (!isset($rank) || !is_numeric($rank)) {echo "db.group:listGroupByRank Ungültiger Parameter!";return ;} + $list = selectsql(" + SELECT * , max(rank) as maxrank, min(rank) as minrank FROM groups g, group_rights gr + WHERE gr.gid = g.gid + AND gr.rank <= $rank + group by g.gid + order by g.gid asc + "); + for($i=0;$i < count($list);$i++){ + if ($list[$i]['maxrank'] == $rank) { + $list[$i]['changed'] = 1; + } + } + return $list; +} + +# +# liefert den rank von einem Right eines Users +# + +function getUserRightLevel($uid,$right) { + + if (!isset($uid) || !is_numeric($uid)) {echo "db.group:getUserRightLevel Ungültiger Parameter!";return ;} + $result = selectsqlLIne(" + select gr.rank from user u, group g, group_rights gr, rights r + where + g.gid = u.gid AND + gr.gid = g.gid AND + r.rid = gr.rid AND + r.name = '$right'" + ); + if ($result) { + switch ($result) { + case 0: $result = "global"; + break; + case 1: $result = "ally"; + break; + case 2: $result = "gala"; + break; + } + return $result; + } else { + return; + } +} + +?> \ No newline at end of file diff --git a/src/database/db.logfile.php b/src/database/db.logfile.php new file mode 100644 index 0000000..c3ec89b --- /dev/null +++ b/src/database/db.logfile.php @@ -0,0 +1,59 @@ +IP: ".$_SERVER['REMOTE_ADDR']; + $descr = addslashes($descr); + return insertSQL("insert into actionlog (descr,uid,time,cat) values('$descr',$uid,Now(),'$cat')"); +} + +function listLogfile($filter,$pages,$page=1,$rows=10) { + + if ($page < 0 || $rows < 0 || !is_numeric($page) || !is_numeric($rows)) return; + #username + if ($filter['username']) { + if ($where) $where .= " and "; + $where .= " u.nick LIKE '".$filter['username']."%'"; + } + #koords + if ($filter['gala']) { + if ($where) $where .= " and "; + $where .= " u.gala = ".$filter['gala']." "; + } + #category + if ($filter['cat']) { + if ($where) $where .= " and "; + $where .= " l.cat = '".$filter['cat']."'"; + + } + if ($where) $where = " where ".$where; + + #order by + if ($filter['order'] == "asc") $order = " ASC "; + else $order = " DESC "; + if ($filter['sort'] == "username") $sort = " u.nick "; + elseif ($filter['sort'] == "cat") $sort = " l.cat "; + elseif ($filter['sort'] == "date") $sort = " l.time "; + else $sort = " l.time "; + $count = selectsqlLine("select count(*) as count from actionlog l left join user u using(uid) + ".$where); + #Seitenamzahl berechnen + $pages = ceil($count['count']/$rows); + #Seite checken + if ($pages < $page && $pages != 0) { + $page = $pages; + } + $return = selectsql("select * from actionlog l left join user u using(uid) + ".$where." + order by ".$sort." ".$order." + LIMIT ".($rows*($page-1)).",$rows"); + return $return; +} + + +?> \ No newline at end of file diff --git a/src/database/db.news.php b/src/database/db.news.php new file mode 100644 index 0000000..a06fd21 --- /dev/null +++ b/src/database/db.news.php @@ -0,0 +1,123 @@ + \ No newline at end of file diff --git a/src/database/db.scans.php b/src/database/db.scans.php new file mode 100644 index 0000000..0e6dcb6 --- /dev/null +++ b/src/database/db.scans.php @@ -0,0 +1,1198 @@ + $timeout) OR + (s.mili_time > $timeout) OR + (s.unit_time > $timeout) OR + (s.news_time > $timeout) OR + (s.gscan_time > $timeout)"; + $get = + "(s.sector_time > $timeout) as hassector, + (s.mili_time > $timeout) as hasmili, + (s.unit_time > $timeout) as hasunit, + (s.news_time > $timeout) as hasnews, + (s.gscan_time > $timeout) as hasgscan"; + + } else { + $get = + "(s.sector_time IS NOT NULL) as hassector, + (s.mili_time IS NOT NULL) as hasmili, + (s.unit_time IS NOT NULL) as hasunit, + (s.news_time IS NOT NULL) as hasnews, + (s.gscan_time IS NOT NULL) as hasgscan"; + $owhere = + "(s.sector_time is not null) OR + (s.mili_time is not null) OR + (s.unit_time is not null) OR + (s.news_time is not null) OR + (s.gscan_time is not null)"; + } + if ($filter['gala'] && is_numeric($filter['gala'])) { + $awhere[] = "s.gala = ".$filter['gala']; + } + // galaxien ausblenden + if ($filter['except_galas'] && is_array($filter['except_galas'])) { + $awhere[] = "s.gala NOT IN (".join(",",$filter['except_galas']).")"; + } + if ($filter['punkte'] && is_numeric($filter['punkte'])) { + $awhere[] = "s.sector_punkte >= ".$filter['punkte']; + } + if ($filter['macht'] && is_numeric($filter['macht'])) { + $awhere[] = "s.sector_macht >= ".$filter['macht']; + } + if ($filter['exen'] && is_numeric($filter['exen'])) { + $awhere[] = "(s.sector_metall + s.sector_kristall >= ".$filter['exen'].")"; + } + if ($filter['hassektor']) { + $awhere[] = "(s.sector_time is not null)"; + } + if ($filter['sids']) { + if(!is_array($filter['sids'])) $filter['sids'] = array($filter['sids']); + $awhere[] = "(s.sid IN (".join(",",$filter['sids'])."))"; + } + + if (!$filter['showattackscans']) { + $awhere[] = "(a.access_time is null or a.access_time < unix_timestamp())"; + } + if($owhere){ + $awhere[] = "(".$owhere.")"; + } + if ($awhere) { + $where = " WHERE ".join(" AND ",$awhere); + } + #order by + if ($filter['order'] == "asc") $order = " ASC "; + else $order = " DESC "; + if ($filter['sort'] == "koords") $sort = " s.gala ".$order.", s.pos ".$order; + elseif ($filter['sort'] == "exen") $sort = " sector_exen ".$order; + else $sort = " s.gala ".$order; + + $count = selectsqlLine(" + select count(s.sid) as count from scans s + left join attack_target at on (at.sid = s.sid) + left join attack a on (a.attid = at.attid) + ".$where); +# echo "count: ".$count['count']."
"; +# print_r($where."
"); + #Seitenamzahl berechnen + $pages = ceil($count['count']/$rows); + #Seite checken + if ($pages < $page && $pages != 0) { + $page = $pages; + } + $return = selectsql(" + select s.*,f.*,at.closed,(s.sector_metall+s.sector_kristall) as sector_exen,u.uid,u.gala as atter_gala,u.pos as atter_pos,u.nick as atter_nick, + ".$get." + from scans s + left join fleet f on (f.fid = s.unit_fid) + left join attack_target at on (at.sid = s.sid) + left join attack a on (a.attid = at.attid) + left join attack_atter aa on (aa.sid = s.sid) + left join user u on (u.uid = aa.uid) + ".$where." + order by ".$sort." + LIMIT ".($rows*($page-1)).",$rows + "); + if (count($return)) { + for($i=0;$i < count($return);$i++) { + $return[$i] = formatScan($return[$i]); + } + } + return $return; +} + +function getScan($filter,$timeout=null) { + + $awhere = array(); + $owhere = array(); + if ($filter['hideold']) { + if (!$timeout){ + # 10 stunden + $timeout = 600; + } + $timeout = time()-($timeout*60); + $owhere = + "(s.sector_time > $timeout) OR + (s.mili_time > $timeout) OR + (s.unit_time > $timeout) OR + (s.news_time > $timeout) OR + (s.gscan_time > $timeout)"; + $get = + "(s.sector_time > $timeout) as hassector, + (s.mili_time > $timeout) as hasmili, + (s.unit_time > $timeout) as hasunit, + (s.news_time > $timeout) as hasnews, + (s.gscan_time > $timeout) as hasgscan"; + + } else { + $get = + "(s.sector_time IS NOT NULL) as hassector, + (s.mili_time IS NOT NULL) as hasmili, + (s.unit_time IS NOT NULL) as hasunit, + (s.news_time IS NOT NULL) as hasnews, + (s.gscan_time IS NOT NULL) as hasgscan"; + } + if (is_numeric($filter['gala']) && $filter['gala'] > 0) { + $awhere[] = "s.gala = ".$filter['gala']; + } + if (is_numeric($filter['pos']) && $filter['pos'] > 0) { + $awhere[] = "s.pos = ".$filter['pos']; + } + if (is_numeric($filter['sid']) && $filter['sid'] > 0) { + $awhere[] = "s.sid = ".$filter['sid']; + } + if (strlen(trim($filter['nick'])) > 0) { + $awhere[] = "s.nick = ".addslashes(trim($filter['nick'])); + } + if($owhere){ + $awhere[] = "(".$owhere.")"; + } + if (!$filter['showattackscans']) { + $awhere[] = "(a.access_time is null or a.access_time < unix_timestamp())"; + } + if ($awhere) { + $where = " WHERE ".join(" AND ",$awhere); + } else { + #kein filter gesetzt + return; + } + $return = selectsqlLine(" + select s.*,f.*,(s.sector_metall+s.sector_kristall) as sector_exen,u.uid,u.gala as atter_gala,u.pos as atter_pos,u.nick as atter_nick,at.closed, + ".$get." + from scans s + left join fleet f on (f.fid = s.unit_fid) + left join attack_target at on (at.sid = s.sid) + left join attack a on (a.attid = at.attid) + left join attack_atter aa on (aa.sid = s.sid) + left join user u on (u.uid = aa.uid) + ".$where." + "); + return formatScan($return); +} + + +function getPrevGala($gala,$hideold) { + + $timeout = time()-(600*60); + if ($hideold) { + $result = selectsqlLine(" + SELECT DISTINCT max( gala ) AS prevgala + FROM scans s + WHERE + ( + (sector_time > $timeout) + OR + (mili_time > $timeout) + OR + (unit_time > $timeout) + OR + (news_time > $timeout) + OR + (gscan_time > $timeout) + ) + AND + s.gala < $gala + "); + if (!$result['prevgala']) + $result = selectsqlLine(" + SELECT DISTINCT max( gala ) AS prevgala + FROM scans s + WHERE + ( + (sector_time > $timeout) + OR + (mili_time > $timeout) + OR + (unit_time > $timeout) + OR + (news_time > $timeout) + OR + (gscan_time > $timeout) + ) + "); + } else { + $result = selectsqlLine(" + SELECT DISTINCT max( gala ) AS prevgala + FROM scans s + WHERE + ( + (sector_time IS NOT NULL) + OR + (mili_time IS NOT NULL) + OR + (unit_time IS NOT NULL) + OR + (news_time IS NOT NULL) + OR + (gscan_time IS NOT NULL) + ) + AND + s.gala < $gala + "); + if (!$result['prevgala']) + $result = selectsqlLine(" + SELECT DISTINCT max( gala ) AS prevgala + FROM scans s + WHERE + ( + (sector_time IS NOT NULL) + OR + (mili_time IS NOT NULL) + OR + (unit_time IS NOT NULL) + OR + (news_time IS NOT NULL) + OR + (gscan_time IS NOT NULL) + ) + "); + } + return $result['prevgala']; +} + +function getNextGala($gala,$hideold) { + + $timeout = time()-(600*60); + if ($hideold) { + $result = selectsqlLine(" + SELECT DISTINCT min( gala ) AS nextgala + FROM scans s + WHERE + ( + (sector_time > $timeout) + OR + (mili_time > $timeout) + OR + (unit_time > $timeout) + OR + (news_time > $timeout) + OR + (gscan_time > $timeout) + ) + AND + s.gala > $gala + group by s.gala + "); + if (!$result['nextgala']) + $result = selectsqlLine(" + SELECT DISTINCT min( gala ) AS nextgala + FROM scans s + WHERE + ( + (sector_time > $timeout) + OR + (mili_time > $timeout) + OR + (unit_time > $timeout) + OR + (news_time > $timeout) + OR + (gscan_time > $timeout) + ) + group by s.gala + "); + } else { + $result = selectsqlLine(" + SELECT DISTINCT min( gala ) AS nextgala + FROM scans s + WHERE + ( + (sector_time IS NOT NULL) + OR + (mili_time IS NOT NULL) + OR + (unit_time IS NOT NULL) + OR + (news_time IS NOT NULL) + OR + (gscan_time IS NOT NULL) + ) + AND + s.gala > $gala + group by s.gala + "); + if (!$result['nextgala']) + $result = selectsqlLine(" + SELECT DISTINCT min( gala ) AS nextgala + FROM scans s + WHERE + ( + (sector_time IS NOT NULL) + OR + (mili_time IS NOT NULL) + OR + (unit_time IS NOT NULL) + OR + (news_time IS NOT NULL) + OR + (gscan_time IS NOT NULL) + ) + group by s.gala + "); + } + return $result["nextgala"]; +} + +/* +function getScan($gala,$pos) { + + return selectsqlLine(" + select s.*, + (sector_metall+sector_kristall) as exen, + (sector_time IS NOT NULL) as hassector, + (mili_time IS NOT NULL) as hasmili, + (unit_time IS NOT NULL) as hasunit, + (news_time IS NOT NULL) as hasnews, + (gscan_time IS NOT NULL) as hasgscan + from scans s + where s.gala = $gala and s.pos = $pos"); +} +*/ + +function addScans($gala,$pos_list) { + + if (!is_numeric($gala)) return; + if(!$pos_list) return; + if(!is_array($pos_list)) $pos_list = array($pos_list); + $sid_list = array(); + foreach($pos_list as $pos) { + $sid_list[] = insertSQL("insert into scans (gala,pos) values ($gala,$pos)"); + } + return $sid_list; +} + +function getScansBySid($sid_list){ + + if(!$sid_list) return; + if(!is_array($sid_list)) $sid_list = array($sid_list); + if(!count($sid_list))return; + return selectsql("select * from scans where sid IN (".join(",",$sid_list).") order by gala,pos"); +} +/* +function updateMainScan($sid,$nick){ + + if (!is_numeric($sid)) return; + if (!$nick) $nick = "NULL"; else { + $nick = "'".addslashes($nick)."'"; + #nicknames unique halten + query("update scans set nick = NULL WHERE nick = $nick"); + } + return query("update scans set nick = $nick where sid = $sid"); +} +*/ + +function getScansByGala($gala) { + + if (!is_numeric($gala) || $gala < 1) return; + return selectsql("select s.* from scans s + where gala = $gala"); +} + +function formatScan($data,$timeout_hours=4) { + + if(!is_array($data) || !$data) return; + + // timeout + $timeout = time() - $timeout_hours*60*60; + $data['timeout_hours'] = $timeout_hours; + + if ($data['hassector']) { + $metall = $data['sector_metall']; + $kristall = $data['sector_kristall']; + for($i=0;$i < 5;$i++){ + $metalllost = (int)floor($metall * 0.1); + $kristalllost = (int)floor($kristall * 0.1); + $data['sector_metall_5'] += $metalllost; + $data['sector_kristall_5'] += $kristalllost; + $metall -= $metalllost; + $kristall -= $kristalllost; + } + $data['sector_metall_10'] = $data['sector_metall_5']; + $data['sector_kristall_10'] = $data['sector_kristall_5']; + for($i=0;$i < 5;$i++){ + $metalllost = (int)floor($metall * 0.1); + $kristalllost = (int)floor($kristall * 0.1); + $data['sector_metall_10'] += $metalllost; + $data['sector_kristall_10'] += $kristalllost; + $metall -= $metalllost; + $kristall -= $kristalllost; + } + $data['sector_exen_5'] = $data['sector_metall_5']+$data['sector_kristall_5']; + $data['sector_exen_10'] = $data['sector_metall_10']+$data['sector_kristall_10']; + $data['sector_attexen'] = $data['sector_exen'] * 3; + $data['sector_punkte2'] = substr_replace(strrev(chunk_split(strrev($data['sector_punkte']),3,'.')),'',0,1); + $data['sector_scanage'] = getscanage($data['sector_time']); + $data['sector_timeout'] = $data['sector_time'] < $timeout; + } + if ($data['hasunit']) { + $data['unit_scanage'] = getscanage($data['unit_time']);; + $data['unit_timeout'] = $data['unit_time'] < $timeout; + } + if ($data['hasgscan']) { + $data['gscan_scanage'] = getscanage($data['gscan_time']); + $data['gscan_timeout'] = $data['gscan_time'] < $timeout; + } + if ($data['hasmili']){ + $data['mili_fleets'] = miliscan_fleet_get($data['sid']); + $data['mili_scanage'] = getscanage($data['mili_time']); + $data['mili_timeout'] = $data['mili_time'] < $timeout; + } + if ($data['hasnews']){ + $data['news_scanage'] = getscanage($data['news_time']); + $data['news_timeout'] = $data['news_time'] < $timeout; + } + return $data; +} +/* +function getScan($sid,$time=null) { + + if (!is_numeric($sid) || $sid < 1) {return;} + if (is_numeric($time) && $time > 0) { + $timeout = time()-$time*60; + $owhere[] = + "(s.sector_time > $timeout) OR + (s.mili_time > $timeout) OR + (s.unit_time > $timeout) OR + (s.news_time > $timeout) OR + (s.gscan_time > $timeout)"; + $get = + "(s.sector_time > $timeout) as hassector, + (s.mili_time > $timeout) as hasmili, + (s.unit_time > $timeout) as hasunit, + (s.news_time > $timeout) as hasnews, + (s.gscan_time > $timeout) as hasgscan"; + + } else { + $get = + "(s.sector_time IS NOT NULL) as hassector, + (s.mili_time IS NOT NULL) as hasmili, + (s.unit_time IS NOT NULL) as hasunit, + (s.news_time IS NOT NULL) as hasnews, + (s.gscan_time IS NOT NULL) as hasgscan"; + } + if(count($owhere)) { + $awhere = " AND ".join(" AND ",$owhere); + } + $data = selectsqlLine("select *,".$get.", + (sector_kristall+sector_metall) as sector_exen + from scans s + where s.sid = $sid $awhere "); + return formatScan($data); +} +*/ +#get fleet, veraltet +function getFleet($fid) { + + if (!$fid || !is_numeric($fid)) return; + return selectsqlLine("select * from fleet where fid = $fid"); +} + + +// veraltet ! +function FleetCopy($src,$dst=0) { + + if (!$src || !is_numeric($src)) return; + $fleet = getFleet($src); + if (!$fleet) return; + if ($dst) { + return fleet_update($dst,$fleet); + } else { + return fleet_add($fleet); + } +} + +#add fleet +function addFleet($kleptoren=0, $cancris=0, $fregatten=0, $zerstoerer=0, $kreuzer=0, $schlachter=0, $traeger=0, + $jaeger=0, $bomber=0) +{ + + if (!is_numeric($kleptoren)) $kleptoren = 0; + if (!is_numeric($cancris)) $cancris = 0; + if (!is_numeric($fregatten)) $fregatten = 0; + if (!is_numeric($zerstoerer)) $zerstoerer = 0; + if (!is_numeric($kreuzer)) $kreuzer = 0; + if (!is_numeric($schlachter)) $schlachter = 0; + if (!is_numeric($traeger)) $traeger = 0; + if (!is_numeric($jaeger)) $jaeger = 0; + if (!is_numeric($bomber)) $bomber = 0; + return insertSQL("insert into fleet (kleptoren, cancris, fregatten, zerstoerer, kreuzer, + schlachter, traeger, jaeger, bomber) + values( $kleptoren, $cancris, $fregatten, $zerstoerer, $kreuzer, + $schlachter, $traeger, $jaeger, $bomber)"); +} + +function deleteFleet($fid) { + + if (is_array($fid)){ + $fids = join(",",$fid); + if ($fids) { + return query("delete from fleet where fid IN ($fids)"); + } + } else { + if (!is_numeric($fid)) return; + return query("delete from fleet where fid = $fid"); + } +} + +#update fleet +function updateFleet($fid,$kleptoren=0, $cancris=0, $fregatten=0, $zerstoerer=0, $kreuzer=0, $schlachter=0, $traeger=0, + $jaeger=0, $bomber=0) +{ + + if (!is_numeric($fid)) return; + if (!is_numeric($kleptoren)) $kleptoren = 0; + if (!is_numeric($cancris)) $cancris = 0; + if (!is_numeric($fregatten)) $fregatten = 0; + if (!is_numeric($zerstoerer)) $zerstoerer = 0; + if (!is_numeric($kreuzer)) $kreuzer = 0; + if (!is_numeric($schlachter)) $schlachter = 0; + if (!is_numeric($traeger)) $traeger = 0; + if (!is_numeric($jaeger)) $jaeger = 0; + if (!is_numeric($bomber)) $bomber = 0; + return query("update fleet set + kleptoren = $kleptoren, + cancris = $cancris, + fregatten = $fregatten, + zerstoerer = $zerstoerer, + kreuzer = $kreuzer, + schlachter = $schlachter, + traeger = $traeger, + jaeger = $jaeger, + bomber = $bomber + where fid = $fid"); +} + +/* +#add sector scan +function addSectorScan($sid,$punkte,$kristall, $metall, $roids, $ships, $deff, $prec, $svs, $scanner) { + + if (!$sid || !is_numeric($sid)) return; + if (!is_numeric($punkte)) return; + if (!is_numeric($kristall)) return; + if (!is_numeric($metall)) return; + if (!is_numeric($roids)) return; + if (!is_numeric($ships)) return; + if (!is_numeric($deff)) return; + if (!is_numeric($prec)) return; + if (!is_numeric($svs)) $svs = "NULL"; + if (isset($scanner) && strlen($scanner)) $scanner = "'".addslashes($scanner)."'"; else $scanner = "NULL"; + return insertSQL("insert into scansector (sid, kristall, metall, punkte, ships, prec, scanner, svs, roids, deff, time) + VALUES ($sid,$kristall,$metall,$punkte, $ships, $prec, $scanner, $svs, $roids, $deff, unix_timestamp())"); +} + +#update sector scan +function updateSectorScan($sid,$punkte,$kristall, $metall, $roids, $ships, $deff, $prec, $svs, $scanner) { + + if (!$sid || !is_numeric($sid)) return; + if (!is_numeric($punkte)) return; + if (!is_numeric($kristall)) return; + if (!is_numeric($metall)) return; + if (!is_numeric($roids)) return; + if (!is_numeric($ships)) return; + if (!is_numeric($deff)) return; + if (!is_numeric($prec)) return; + if (!is_numeric($svs)) $svs = "NULL"; + if (isset($scanner) && strlen($scanner)) $scanner = "'".addslashes($scanner)."'"; else $scanner = "NULL"; + return query("update scansector + SET punkte = $punkte, + kristall = $kristall, + metall = $metall, + roids = $roids, + ships = $ships, + deff = $deff, + prec = $prec, + svs = $svs, + scanner = $scanner, + time = unix_timestamp() + Where sid = $sid"); +} + +#add unitscan +function addUnitScan($sid,$fleet,$prec,$svs,$scanner) { + + if (!$sid || !is_numeric($sid)) return; + if (!is_numeric($prec)) return; + if (!is_numeric($svs)) $svs = "NULL"; + if (isset($scanner) && strlen($scanner)) $scanner = "'".addslashes($scanner)."'"; else $scanner = "NULL"; + $fid = addFleet($fleet['kleptoren'],$fleet['cancris'],$fleet['fregatten'],$fleet['zerstoerer'], + $fleet['kreuzer'],$fleet['schlachter'],$fleet['traeger'],$fleet['jaeger'],$fleet['bomber']); + if (!$fid) return; #irgendwas schiefgelaufen beim einf�gen + return insertSQL(" + insert into scanunit (sid,fid,prec,svs,scanner,time) + values($sid,$fid,$prec,$svs,$scanner,unix_timestamp()) + "); +} +#update unit scan +function updateUnitScan($sid,$fleet,$prec,$svs,$scanner) { + + if (!$sid || !is_numeric($sid)) return; + if (!is_numeric($prec)) return; + if (!is_numeric($svs)) $svs = "NULL"; + if (isset($scanner) && strlen($scanner)) $scanner = "'".addslashes($scanner)."'"; else $scanner = "NULL"; + + $fid = selectsqlline("select * from scanunit where sid = $sid"); + if (!$fid) return; + $fid = $fid['fid']; + updateFleet($fid,$fleet['kleptoren'],$fleet['cancris'],$fleet['fregatten'],$fleet['zerstoerer'], + $fleet['kreuzer'],$fleet['schlachter'],$fleet['traeger'],$fleet['jaeger'],$fleet['bomber']); + + return query(" + update scanunit set + prec = $prec, + svs = $svs, + scanner = $scanner, + time = unix_timestamp() + where sid = $sid + "); +} + +#add gscan +function addGScan($sid,$horus,$rubium,$pulsar,$coon,$centurion,$prec,$svs, $scanner) { + + if (!$sid || !is_numeric($sid)) return; + if (!is_numeric($horus)) $horus = 0; + if (!is_numeric($rubium)) $rubium = 0; + if (!is_numeric($pulsar)) $pulsar = 0; + if (!is_numeric($coon)) $coon = 0; + if (!is_numeric($centurion)) $centurion = 0; + if (!is_numeric($prec)) return; + if (!is_numeric($svs)) $svs = "NULL"; + if (isset($scanner) && strlen($scanner)) $scanner = "'".addslashes($scanner)."'"; else $scanner = "NULL"; + return insertSQL(" + insert into scangscan (sid,horus,rubium, pulsar, coon, centurion, prec, svs, scanner, time) + values($sid,$horus,$rubium,$pulsar,$coon,$centurion,$prec,$svs,$scanner,unix_timestamp()) + "); +} + +#update gscan +function updateGScan($sid,$horus,$rubium,$pulsar,$coon,$centurion,$prec,$svs, $scanner) { + + if (!$sid || !is_numeric($sid)) return; + if (!is_numeric($horus)) $horus = 0; + if (!is_numeric($rubium)) $rubium = 0; + if (!is_numeric($pulsar)) $pulsar = 0; + if (!is_numeric($coon)) $coon = 0; + if (!is_numeric($centurion)) $centurion = 0; + if (!is_numeric($prec)) return; + if (!is_numeric($svs)) $svs = "NULL"; + if (isset($scanner) && strlen($scanner)) $scanner = "'".addslashes($scanner)."'"; else $scanner = "NULL"; + return query(" + update scangscan set + horus = $horus, + rubium=$rubium, + pulsar = $pulsar, + coon = $coon, + centurion = $centurion, + prec = $prec, + svs = $svs, + scanner = scanner, + time = unix_timestamp() + where sid = $sid"); +} + +#add newsscan +function addNewsScan($sid,$newsdata,$prec,$svs,$scanner) { + + if (!$sid || !is_numeric($sid)) return; + if (!is_numeric($prec)) return; + if (!is_numeric($svs)) $svs = "NULL"; + if (isset($scanner) && strlen($scanner)) $scanner = "'".addslashes($scanner)."'"; else $scanner = "NULL"; + $newsdata = addslashes($newsdata); + return insertSQL(" + insert into scannews (sid,newsdata,prec,svs,scanner,time) + values($sid,'$newsdata',$prec,$svs,$scanner,unix_timestamp()) + "); +} + +#update news scan +function updateNewsScan($sid,$newsdata,$prec,$svs,$scanner) { + + if (!$sid || !is_numeric($sid)) return; + if (!is_numeric($prec)) return; + if (!is_numeric($svs)) $svs = "NULL"; + if (isset($scanner) && strlen($scanner)) $scanner = "'".addslashes($scanner)."'"; else $scanner = "NULL"; + $newsdata = addslashes($newsdata); + return query(" + update scannews set + newsdata = '$newsdata', + prec = $prec, + svs = $svs, + scanner = $scanner, + time = unix_timestamp() + where sid = $sid + "); +} + +#add mili +# orbit: orbithash +# fleet1: fleet1hash +# fleet2: fleet2hash +function addMiliScan($sid,$fleets,$prec,$svs,$scanner) { + + if (!$sid || !is_numeric($sid)) return; + if (!is_numeric($prec)) return; + if (!is_numeric($svs)) $svs = "NULL"; + if (isset($scanner) && strlen($scanner)) $scanner = "'".addslashes($scanner)."'"; else $scanner = "NULL"; + + for($i=0;$i < 3;$i++){ + miliscan_fleet_add($sid,$i,$fleets[$i]); + } + + return insertSQL(" + insert into scanmili (sid,scanner, prec, svs, time) + values($sid,$scanner, $prec, $svs, unix_timestamp()) + "); +} +*/ + +function miliscan_fleet_add($sid,$fleetnum,$fleet) { + $logger = & LoggerManager::getLogger("db.scans"); + $logger->debug(array( + "sid" => $sid, + "fleetnum" => $fleetnum, + "fleet" => $fleet + )); + + Assert::isId($sid); + Assert::isNumeric($fleetnum); + + $fid = fleet_add($fleet); + + $insert = array("sid" => $sid,"fid" => $fid,"num" => $fleetnum); + + if (strlen($fleet['type'])) $insert['type'] = "'".addslashes($fleet['type'])."'"; + if (strlen($fleet['dir'])) $insert['dir'] = "'".addslashes($fleet['dir'])."'"; + if (strlen($fleet['status'])) $insert['status'] = $fleet['status']; + if (strlen($fleet['return_flight'])) $insert['return_flight'] = $fleet['return_flight']; + insertSQL(" + insert into scanmili_fleet (".join(",",array_keys($insert)).") + values (".join(",",$insert).") + "); + return $fid; +} + +function miliscan_fleet_update($fid,$fleet) { + $logger = & LoggerManager::getLogger("db.scans"); + $logger->debug(array( + "function"=>"miliscan_fleet_update", + "fid" => $fid, + "fleet" => $fleet + )); + Assert::isId($fid); + + fleet_update($fid,$fleet); + + $update = array(); + + if (strlen($fleet['type'])) $update[] = "type = '".addslashes($fleet['type'])."'"; + else $update[] = "type = NULL"; + if (strlen($fleet['dir'])) $update[] = "dir = '".addslashes($fleet['dir'])."'"; + else $update[] = "dir = NULL"; + if (strlen($fleet['status'])) $update[] = "status = ".$fleet['status']; + else $update[] = "status = NULL"; + if (strlen($fleet['return_flight'])) $update[] = "return_flight = ".$fleet['return_flight']; + else $update[] = "return_flight = NULL"; + query(" + update scanmili_fleet + set ".join(",",$update)." + where fid = $fid + "); + $logger->debug("miliscan_fleet_update done"); +} + +function miliscan_fleet_get($sid) { + Assert::isId($sid); + return selectsql(" + select *,u.gala as tgala,u.pos as tpos,u.uid from scanmili_fleet mf + left join fleet f on (f.fid = mf.fid) + left join user u on(u.nick = mf.dir) + where mf.sid = $sid + order by mf.num ASC + "); +} + +function miliscan_fleet_get_bykoords($gala,$pos,$num) { + Assert::isId($gala); + Assert::isId($pos); + Assert::isNumeric($num); +return selectsqlline(" + select * from scans s + left join scanmili_fleet mf using(sid) + left join fleet f on (f.fid = mf.fid) + where s.gala = $gala and s.pos = $pos and mf.num = $num + "); +} + +/* +#update mili +function updateMiliScan($sid,$fleets,$prec,$svs,$scanner) { + + if (!$sid || !is_numeric($sid)) return; + if (!is_numeric($prec)) return; + if (!is_numeric($svs)) $svs = "NULL"; + if (isset($scanner) && strlen($scanner)) $scanner = "'".addslashes($scanner)."'"; else $scanner = "NULL"; + + $fleetlist = selectsql("select * from scanmili_fleet where sid = $sid order by num ASC"); + for($i=0;$i < 3;$i++){ + miliscan_fleet_update($fleetlist[$i]['fid'],$fleets[$i]); + } + + return query(" + update scanmili set + prec = $prec, + svs = $svs, + scanner = $scanner, + time = unix_timestamp() + where sid = $sid + "); +} +*/ + +function existScan($gala,$pos) { + + if (!is_numeric($gala) || $gala < 1) return; + if (!is_numeric($pos) || $pos < 1) return; + return selectsqlline(" + select *, + (s.sector_time IS NOT NULL) as hassector, + (s.mili_time IS NOT NULL) as hasmili, + (s.unit_time IS NOT NULL) as hasunit, + (s.news_time IS NOT NULL) as hasnews, + (s.gscan_time IS NOT NULL) as hasgscan + from scans s + where s.gala = $gala and s.pos = $pos + "); +} + +function updateScan($scan) { + $logger = & LoggerManager::getLogger("db.scans"); + $logger->debug(array("function" => "updateScan","scan" => $scan)); + if (!is_numeric($scan['gala']) || !is_numeric($scan['pos'])) return; + + #scan exists + $dbscan = existScan($scan['gala'],$scan['pos']); + if(!$dbscan) { + $sid = insertsql(" insert into scans (gala,pos,nick) values (".$scan['gala'].",".$scan['pos'].",'".addslashes($scan['nick'])."')"); + if(!$sid) return; + $dbscan = array("sid" => $sid, "gala" => $scan['gala'], "pos" => $scan['pos']); + } + #sektorscan + if ($scan['type'] == "sector") { + #existiert schon -> update + $val = array("sector_punkte" => $scan['punkte'], "sector_kristall" => $scan['kristall'], + "sector_metall" => $scan['metall'], "sector_roids" => $scan['roids'], + "sector_ships" => $scan['ships'], "sector_deff" => $scan['deff'], + "sector_prec" => $scan['prec'], "sector_svs" => $scan['svs'], + "sector_scanner" => $scan['scanner'], "sector_time" => time() + ); + } + if ($scan['type'] == "unit") { + if ($dbscan['hasunit'] && $dbscan['unit_fid']) { + updateFleet( + $dbscan['unit_fid'], + $scan['kleptoren'], + $scan['cancris'], + $scan['fregatten'], + $scan['zerstoerer'], + $scan['kreuzer'], + $scan['schlachter'], + $scan['traeger'], + $scan['jaeger'], + $scan['bomber'] + ); + $fid = $dbscan['unit_fid']; + } else { + $fid = addFleet( + $scan['kleptoren'], + $scan['cancris'], + $scan['fregatten'], + $scan['zerstoerer'], + $scan['kreuzer'], + $scan['schlachter'], + $scan['traeger'], + $scan['jaeger'], + $scan['bomber'] + ); + if(!$fid) return; + } + $val = array("unit_prec" => $scan['prec'], "unit_svs" => $scan['svs'], "unit_scanner" => $scan['scanner'],"unit_fid" => $fid, "unit_time" => +time()); + } + if ($scan['type'] == "gscan") { + $val = array( + "gscan_prec" => $scan['prec'], + "gscan_svs" => $scan['svs'], + "gscan_scanner" => $scan['scanner'], + "gscan_horus" => $scan['horus'], + "gscan_rubium" => $scan['rubium'], + "gscan_coon" => $scan['coon'], + "gscan_pulsar" => $scan['pulsar'], + "gscan_centurion" => $scan['centurion'], + "gscan_time" => time()); + } + // miliscan updaten + if ($scan['type'] == "mili") { + + if (miliscan_fleet_get($dbscan['sid'])) { + $fleetlist = selectsql("select * from scanmili_fleet where sid = ".$dbscan['sid']." order by num ASC"); + for($i=0;$i < 3;$i++){ + miliscan_fleet_update($fleetlist[$i]['fid'],$scan['fleets'][$i]); + } + } else { + for($i=0;$i < 3;$i++){ + miliscan_fleet_add($dbscan['sid'],$i,$scan['fleets'][$i]); + } + } + // 100% scan und user ist tic member +// if($scan['prec'] == "100" && ($user = user_get_bypos($scan['gala'],$scan['pos']))) { +// +// } + $val = array("mili_prec" => $scan['prec'], "mili_svs" => $scan['svs'], "mili_scanner" => $scan['scanner'], "mili_time" => time()); + $logger->debug(array("message"=>"mili update done","vals"=>$val)); + } + if ($scan['type'] == "news") { + $val = array("news_prec" => $scan['prec'], "news_svs" => $scan['svs'], "news_scanner" => $scan['scanner'],"news_newsdata" => $scan['newsdata'], + "news_time" => time()); + } + if(!$dbscan['nick'] || strtolower($dbscan['nick']) != strtolower($scan['nick'])) $val['nick'] = $scan['nick']; + if(strtolower($dbscan['nick']) != strtolower($scan['nick'])) { + query("update scans set nick = null where lower(nick) = lower('".mysql_escape_string($scan['nick'])."')"); + } + if(count($val)) { + $updates = array(); + foreach($val as $key => $value) { + if(!isset($value)) { + $value = "NULL"; + } else { + if(!is_numeric($value)) { + $value = "'".mysql_escape_string($value)."'"; + } + } + $updates[] = "$key = $value"; + } + $logger->debug(array("function"=>"updateScan","message"=>"before update scans","vals"=>$vals,"updates"=>$updates));; + query("update scans set ".join(",",$updates)." where sid = ".$dbscan['sid']); + } + $logger->debug("update scan done"); + return $dbscan['sid']; +} + +function scan_add($gala,$pos,$values=null) { + if(!is_numeric($gala) || !is_numeric($pos)) return false; + if($values && is_array($values)) { + $check = array( + "nick" + ); + $insert = array(); + foreach ($values as $key => $val) { + if(in_array($key,$check)) $insert[$key] = "'".mysql_escape_string($val)."'"; + } + if($insert) { + $sqlkeys = ",".join(",",array_keys($insert)); + $sqlvals = ",".join(",",array_values($insert)); + } + } + return insertsql(" + insert into scans (gala,pos".$sqlkeys.") values ($gala,$pos".$sqlvals.")"); +} + +function scan_update_nick($gala,$pos,$nick) { + if(!$nick || !is_numeric($pos) || !is_numeric($gala)) return false; + $scan = scan_get_bynick($nick); + if($scan) { + if($scan['gala'] != $gala || $scan['pos'] != $pos) { + query("update scans set nick = null where gala = ".$scan['gala']." and pos = ".$scan['pos']); + } + return query("update scans set nick = '".mysql_escape_string(trim($nick))."' where gala = ".$gala." and pos = ".$pos); + } else { + $scan = getScan(array("gala" => $gala, "pos" => $pos)); + if($scan) { + return query("update scans set nick = '".mysql_escape_string(trim($nick))."' where gala = ".$gala." and pos = ".$pos); + } else { + return scan_add($gala,$pos,array("nick" => $nick)); + } + } +} + +function scan_get_bynick($nick) { + if(!$nick) return false; + $nick = mysql_escape_string(trim($nick)); + return selectsqlline("select * from scans s where nick = '$nick'"); +} + +#liefert die Liste der Atter zu einem Target +/* +function getAtterlist($sid) { + + return selectsql(" + select u.nick,u.gala,u.pos,u.uid,a.time,a.fleetnum, + DATE_FORMAT(a.start, '%H:%i') as starttime, + DATE_FORMAT(a.start, '%d.%m.%y') as startdate, + al.tag + from atter a + left join user u on (u.uid = a.uid) + left join galaxy g on (g.gala = u.gala) + left join alliance al on (al.aid = g.aid) + where + a.sid = $sid + order by a.start ASC, a.fleetnum asc + "); +} + +#liefert das Target anhand uid/flotte oder liefert die targets eines users + +function getAtter($uid,$num=null) { + + if ($num) { + return selectsqlLine(" + select u.nick,u.uid,a.time,a.fleetnum, + DATE_FORMAT(a.start, '%H:%i') as starttime, + DATE_FORMAT(a.start, '%d.%m.%y') as startdate, + s.gala,s.pos + from atter a + left join user u on (u.uid = a.uid) + left join scans s on (s.sid = a.sid) + where + a.uid = $uid AND + a.fleetnum = $num + "); + } else { + return selectsql(" + select u.nick,u.uid,a.time,a.fleetnum, + DATE_FORMAT(a.start, '%H:%i') as starttime, + DATE_FORMAT(a.start, '%d.%m.%y') as startdate, + s.gala,s.pos + from atter a + left join user u on (u.uid = a.uid) + left join scans s on (s.sid = a.sid) + where + a.uid = $uid + order by a.start asc, a.fleetnum asc + "); + } +} + +#f�gt einen Atter hinzu + +function addAtter($sid,$uid,$fleet,$time=null) { + + if ($fleet != 1 && $fleet != 2) { + return -1; + } + if ($time) { + if (preg_match("/(\d{1,2}):(\d{2})/i",$time,$data)) { + $hour = date("G",mktime($data[1],$data[2],0,date("m"),date("d"),date("Y"))); + $acthour = date("G"); + if ( ($acthour > $hour) || + ($acthour == $hour && date("i") > $data[2])) { + $dayoffset = 1; + } + $date = "'".date("Y-m-d H-i-s",mktime($data[1],$data[2],0,date("m"),date("d")+$dayoffset,date("Y")))."'"; + } else { + return -1; + } + } else { + $date = "NULL"; + } + return insertsql(" + insert into atter (sid,uid,fleetnum,start,time) + values ($sid,$uid,$fleet,$date,Now()) + "); +} + +#setzt ein target auf closed +function closeTarget($id) { + + return query(" + update scans set closed = 1 where sid = $id + "); +} + +#setzt ein target auf open +function openTarget($id) { + + return query(" + update scans set closed = NULL where sid = $id + "); +} +*/ + +#liefert nen scan anhand der sid +function getScanById($sid,$attackscans=false) { + if(!$attackscans) { + $where = " AND (a.access_time is null or a.access_time < unix_timestamp())"; + } + return selectsqlline(" + select s.*,a.attid,a.owner,at.closed,u.uid,u.gala as atter_gala,u.pos as atter_pos,u.nick as atter_nick,(a.access_time is null or a.access_time < unix_timestamp()) as isopen + from scans s + left join attack_target at on (at.sid = s.sid) + left join attack_atter aa on (aa.sid = s.sid) + left join user u on (u.uid = aa.uid) + left join attack a on (a.attid = at.attid) + where s.sid = $sid $where + "); +} + + + +/* +#l�scht den atter +function deleteAtter($uid,$fleet) { + + $target = selectsqlline(" + select sid + from atter + where uid = $uid and fleetnum = $fleet"); + $target = $target['sid']; + if (!$target) return; + query(" + delete from atter + where uid = $uid and fleetnum = $fleet + "); + $atter = selectsql(" + select * from atter + where + sid = $target + "); + if (!$atter){ + query(" + update scans set closed = NULL where sid = $target + "); + } + return 1; +} +*/ + +/* +#l�scht veraltete reservierungen +function updateTargets($hours=8) { + + $date = $date = date("Y-m-d H-i-s",mktime(date("H")-$hours,date("i"),0,date("m"),date("d")+$dayoffset,date("Y"))); + query("delete from atter where time < '$date'"); + $targets = selectsql(" + select s.sid from scans s + left join atter t on (t.sid = s.sid) + where t.uid IS NULL and s.closed = 1 + group by s.sid + ","sid"); + if ($targets){ + $where = join(",",$targets); + query(" + update scans set closed = NULL where sid IN ($where) + "); + } +} +*/ + +?> diff --git a/src/database/db.takscreen.php b/src/database/db.takscreen.php new file mode 100644 index 0000000..f2b0c10 --- /dev/null +++ b/src/database/db.takscreen.php @@ -0,0 +1,1074 @@ + 15300)"; + $ohaving[] = "(u.gala IN (".join(",",$allygalas).") and max(fs.arrival)-unix_timestamp() > 17100)"; + $ohaving[] = "(max(fs.arrival)-unix_timestamp() > 18900)"; + $having = "HAVING (".join(" OR ",$ohaving).")"; + } + + if ($filter['ally']) { + $awhere[] = " g.aid = ".$filter['ally']." "; + } + if ($filter['gala']) { + $awhere[] = " fs.tgala = ".$filter['gala']." "; + } + if ($awhere){ + $where = " where ".join("AND",$awhere); + $where2 = join("AND",$awhere); + $where3 = "AND ".join("AND",$awhere); + } + + $victims = selectsql(" + select *,max(arrival) as maxtime + from fleet_status fs, user u, galaxy g + where + u.gala = fs.tgala and + u.pos = fs.tpos and + g.gala = u.gala and + fs.status = 1 + $where3 + group by u.uid + $having + order by $sort + ","uid"); + + #Seitenamzahl berechnen +# echo " pages: ".$pages; +# echo " page: ".$page; + $pages = ceil(count($victims)/$rows); + #Seite checken + if ($pages < $page && $pages != 0) { + $page = $pages; + } + if(!$victims) return array(); + $victims = array_splice($victims,($page-1)*$rows,$rows); + + #echo " pages: ".$pages; + #echo " page: ".$page; + return selectsql(" + select u.*,g.*,a.*,max(arrival) as maxtime + from fleet_status fs, user u,galaxy g, alliance a + where + u.gala = fs.tgala and + u.pos = fs.tpos and + g.gala = u.gala and + a.aid = g.aid and + fs.return_flight != 1 + and u.uid IN (".join(",",$victims).") + group by u.uid + order by $sort + " + ); +} + + +function inc_list_byuser($gala,$pos) { + if(!is_numeric($gala) || !is_numeric($pos)) return false; + return selectsql(" + select fs.*,fs.arrival - unix_timestamp() as unixeta,s.nick,u.uid,ga.aid,a.tag,f.* + from fleet_status fs + left join scans s on(s.gala = fs.gala and s.pos = fs.pos) + left join fleet f on(f.fid = fs.fid) + left join user u on(u.gala = fs.gala and u.pos = fs.pos) + left join galaxy ga on(ga.gala = u.gala) + left join alliance a on(a.aid = ga.aid) + where + fs.tgala = $gala and fs.tpos = $pos and fs.return_flight = 0 + ORDER BY status asc,arrival asc + "); +} + +/* +function atter_list($id,$fids=null) { + + if (!is_numeric($id)) return; + if(isset($fids) && is_array($fids)) { + $where = " AND ia.fid NOT IN (".join(",",$fids).")"; + } + return selectsql(" + select ia.*,f.*, + u.gala as ogala, + arrival-unix_timestamp() as unixeta, + s.sid,(s.mili_time > unix_timestamp()-60*450) as hasmili + from inc_atter ia + left join fleet f on (f.fid = ia.fid) + left join user u on (u.uid = ia.incid) + left join scans s on(s.gala = ia.igala AND s.pos = ia.ipos) + where ia.incid = $id ".$where." + order by arrival asc + "); +} + +function atter_list_bynick($nick) { + + return selectsql(" + select ia.*,f.*, + u.gala as ogala,u.pos as opos, u.nick as onick, + arrival-unix_timestamp() as unixeta + from inc_atter ia + left join fleet f on (f.fid = ia.fid) + left join user u on (u.uid = ia.incid) + where lower(ia.inickname) = lower('$nick') + order by arrival asc + "); +} + +function atter_list_bykoords($gala,$pos) { + + if(!is_numeric($gala)) return; + if(!is_numeric($pos)) return; + return selectsql(" + select ia.*,f.*, + u.gala as ogala,u.pos as opos, u.nick as onick, + arrival-unix_timestamp() as unixeta + from inc_atter ia + left join fleet f on (f.fid = ia.fid) + left join user u on (u.uid = ia.incid) + where ia.igala = $gala AND ia.ipos = $pos + order by arrival asc + "); +} + +#l�scht einen oder mehrere incs +function inc_recall_all($incid) { + + if (is_array($incid)){ + $where = join(",",$incid); + } else { + if (!is_numeric($incid)) return; + $where = $incid; + } + $fids = selectsql("select fid from inc_atter where incid IN ($where)","fid"); + deleteFleet($fids); + delete_fleet_filter($fids); + query("delete from inc_atter where incid IN ($where)"); + $externe = selectsql(" + select id.defferid + from inc_deffer id + where + id.enickname IS NOT NULL + AND id.incid IN ($where) + "); + if ($externe){ + $fids = getArrayFromList($externe,"defferid"); + deleteFleet($fids); + delete_fleet_filter($fids); + query("delete from fleetstatus where fid IN (".join(",",$fids).")"); + } + $interne = selectsql(" + select id.defferid + from inc_deffer id + where + id.enickname IS NULL + AND id.incid IN ($where) + "); + if ($interne){ + $fids = getArrayFromList($interne,"defferid"); + user_fleet_recall($fids); + delete_fleet_filter($fids); + } + query("delete from inc_deffer where incid IN ($where)"); + query("delete from incomings where incid IN ($where)"); +} + +function atter_recall($atterid) { + + if (is_array($atterid)){ + $atter = atter_get($atterid); + $fids = getArrayFromList($atter, "fid"); + deleteFleet($fids); + delete_fleet_filter($fids); + $where = join(",",$atterid); + query("delete from inc_atter where atterid IN ($where)"); + inc_check_empty(getArrayFromList($atter, "incid")); + } else { + if (!is_numeric($atterid)) return; + $atter = atter_get($atterid); + deleteFleet($atter['fid']); + delete_fleet_filter($atter['fid']); + query("delete from inc_atter where atterid = $atterid"); + inc_check_empty($atter['incid']); + } +} + +function inc_check_empty($incid) { + + if (is_array($incid) && count($incid)) { + $where = join(",",$incid); + $result = selectsql(" + select count(ia.atterid) as atter, i.incid + from incomings i + left join inc_atter ia on (ia.incid = i.incid) + where i.incid IN ($where) group by i.incid"); + foreach ($result as $incdetails) { + if (!$incdetails['atter']) $delete[] = $incdetails['incid']; + } + if (count($delete)) inc_recall_all($delete); + } else { + if (!is_numeric($incid)) return; + $result = selectsqlline(" + select count(ia.atterid) as atter, i.incid + from incomings i + left join inc_atter ia on (ia.incid = i.incid) + where i.incid = $incid group by i.incid + "); + if (!$result['atter']) inc_recall_all($incid); + } +} +# checkt die incs ob sie bereits 45min im Orbit sind +function inc_check_undertime() { + + $atterlist = selectsql(" + select atterid + from inc_atter + where + arrival+4500-unix_timestamp() < 0 + ","atterid"); + if (count($atterlist)) { + atter_recall($atterlist); + addToLogFile("System: ".count($atterlist)." Atter recallt","Incomings"); + } +} + +function atter_fleetnum_set($fid,$fleetnum) { + + if (!is_numeric($fid)) return; + if (!is_numeric($fleetnum)) return; + query("update inc_atter set fleetnum = $fleetnum where fid = $fid"); +} + +function atter_update($atterid,$prec,$svs,$fleetnum,$time,$fleet) { + + if (!is_numeric($atterid)) return; + if (!is_numeric($prec)) return; + if (!is_numeric($svs)) return; + if (!is_numeric($fleetnum)) return; + if (!is_numeric($time)) return; + $atter = atter_get($atterid); + if (!$atter) return; + updateFleet($atter['fid'], + $fleet['kleptoren'], + $fleet['cancris'], + $fleet['fregatten'], + $fleet['zerstoerer'], + $fleet['kreuzer'], + $fleet['schlachter'], + $fleet['traeger'], + $fleet['jaeger'], + $fleet['bomber'] + ); + if (!$prec) $prec = 0; + if (!$svs) $svs = 0; + $arrival = mktime(date("H"),date("i")+$time,0,date("m"),date("d"),date("Y")); + query(" + update inc_atter set prec = $prec, svs = $svs, fleetnum = $fleetnum, arrival = $arrival + where atterid = $atterid + "); +} + + + +function atter_update_bynick($nick,$prec,$svs) { + + if (!$prec) $prec = 0; + if (!$svs) $svs = 0; + query(" + update inc_atter set prec = $prec, svs = $svs + where lower(inickname) = lower('$nick') + "); +} + +function atter_update_bykoords($gala,$pos,$prec,$svs) { + + if (!$prec) $prec = 0; + if (!$svs) $svs = 0; + if(!is_numeric($gala)) return; + if(!is_numeric($pos)) return; + query(" + update inc_atter set prec = $prec, svs = $svs + where igala = $gala and ipos = $pos + "); +} + +function atter_get($atterid) { + + if (is_array($atterid)){ + $where = join(",",$atterid); + return selectsql(" + select ia.*,f.*, + u.gala as ogala,u.pos as opos, u.nick as onick, + arrival-unix_timestamp() as unixeta + from inc_atter ia + left join fleet f on (f.fid = ia.fid) + left join user u on (u.uid = ia.incid) + where ia.atterid IN ($where) + "); + } else { + if (!is_numeric($atterid)) return; + return selectsqlline(" + select ia.*,f.*, + u.gala as ogala,u.pos as opos, u.nick as onick, + arrival-unix_timestamp() as unixeta + from inc_atter ia + left join fleet f on (f.fid = ia.fid) + left join user u on (u.uid = ia.incid) + where ia.atterid = $atterid + "); + } +} + + +function inc_add($uid,$gala,$pos,$nickname,$time,$fleetnum,$prec,$svs,$fleet) { + + if (!$prec) $prec = 0; + if (!$svs) $svs = 0; + $inc = inc_get_data($uid); + if ($inc){ + if ($inc['save']) { + inc_set_unsave($inc['incid']); + } + } else { + inc_data_add($uid); + #vorhandene deffer eintragen + $user = getUserByID($uid); + insertsql(" + insert into inc_deffer (defferid,incid) + select fid,$uid from fleetstatus + where gala = ".$user['gala']." AND pos = ".$user['pos']); + } + $fid = addFleet($fleet['kleptoren'], + $fleet['cancris'], + $fleet['fregatten'], + $fleet['zerstoerer'], + $fleet['kreuzer'], + $fleet['schlachter'], + $fleet['traeger'], + $fleet['jaeger'], + $fleet['bomber'] + ); + $arrival = mktime(date("H"),date("i")+$time,0,date("m"),date("d"),date("Y")); + if (!$prec) $prec = 0; + if (!$svs) $svs = 0; + return insertsql(" + insert into inc_atter(incid,inickname,igala,ipos,time,arrival,svs,prec,fid,fleetnum) + values($uid,'$nickname',$gala,$pos,now(),$arrival,$svs,$prec,$fid,$fleetnum) + "); +} + +*/ + +function hide_fleets($fleets,$user) { + + if(!$fleets) return; + if(!is_array($fleets)) $fleets = array($fleets); + foreach($fleets as $fleet) { + if(!is_numeric($fleet)) continue; + insertsql("insert into fleet_filter (uid,fsid) values(".$user['uid'].",$fleet)"); + } +} + +function delete_fleet_filter($fsids) { + + if(!$fsids) return; + if(!is_array($fsids)) $fsids = array($fsids); + query("delete from fleet_filter where fsid IN (".join(",",$fsids).")"); +} + +function reset_fleet_filter($user,$fsids) { + + if(!$user) return; + if(!$fsids || (is_array($fsids) && !count($fsids))) { + query("delete from fleet_filter where uid = ".$user['uid']); + return; + } + if(!is_array($fsids)) $fsids = array($fsids); + query("delete from fleet_filter where uid = ".$user['uid']." AND fsid IN (".join(",",$fsids).")"); +} + +function get_fleet_filter($user) { + + if(!$user) return; + return selectsql("select fsid from fleet_filter where uid = ".$user['uid'],"fsid"); +} + + + +function atter_add($gala,$pos,$tgala,$tpos,$fleetnum,$eta=null,$fleet=null,$nick=null) { + $logger = & LoggerManager::getLogger("db.takscreen"); + if(!is_numeric($gala) || !is_numeric($pos) || !is_numeric($tgala) + || !is_numeric($tpos) || !is_numeric($fleetnum)) return false; + $insert = array(); + $insert['gala'] = $gala; + $insert['pos'] = $pos; + $insert['tgala'] = $tgala; + $insert['tpos'] = $tpos; + $insert['status'] = 1; + $insert['orbittime'] = 75; + $insert['returntime'] = 450; + + if(($check1 = fleetstatus_get_bykoords($gala,$pos,$fleetnum))) { + if($fleetnum == 1) $fleetnum = 2; + else $fleetnum = 1; + if($check2 = fleetstatus_get_bykoords($gala,$pos,$fleetnum)) { +// $maxupdate = selectsqlline(" +// select * from fleet_status where gala = $gala and pos = $pos +// order by lastupdate asc +// "); +// query("delete from fleet_status where fsid = ".$maxupdate['fsid']); +// $fleetnum = $maxupdate['fleetnum']; + return check1; + } + } + $insert['fleetnum'] = $fleetnum; + if($fleet) { + $insert['fid'] = fleet_add($fleet); + $insert['svs'] = $fleet['svs']; + $insert['prec'] = $fleet['prec']; + } + if($nick) { + scan_update_nick($gala,$pos,$nick); + } + + if(is_numeric($eta)) $insert['arrival'] = gnarrival($eta); + //_dump($insert); + return fleetstatus_add($insert); +} + +function deffer_add($gala,$pos,$tgala,$tpos,$fleetnum,$returntime,$orbittime,$eta=null,$nick=null) { + if(!is_numeric($gala) || !is_numeric($pos) || !is_numeric($tgala) + || !is_numeric($tpos) || !is_numeric($fleetnum)) return false; + $insert = array(); + $insert['gala'] = $gala; + $insert['pos'] = $pos; + $insert['tgala'] = $tgala; + $insert['tpos'] = $tpos; + $insert['status'] = 2; + $insert['orbittime'] = $orbittime; + $insert['returntime'] = $returntime; + + if($fleetnum) { + $insert['fleetnum'] = $fleetnum; + $user = user_fleet_get($gala,$pos,$fleetnum); + if($user['fid']) $insert['fid'] = $user['fid']; + } + + if($nick) { + scan_update_nick($gala,$pos,$nick); + } + + if(is_numeric($eta)) $insert['arrival'] = gnarrival($eta); + return fleetstatus_add($insert); +} + +function fleetstatus_get_byfleetnum($gala,$pos,$null=false) { + if($null) $null = "="; else $null = "!="; + return selectsql(" + select * from fleet_status fs + where gala = $gala and pos = $pos and fleetnum $null NULL + order by lastupdate asc + "); +} + +function fleetstatus_get_filter($filter=null) { + if($filter) { + $awhere = array(); + $_check = array("tgala" => "tgala","tpos" => "tpos","gala" => "fs.gala","pos" => "fs.pos","fleetnum" => "fleetnum"); + foreach($_check as $check => $sqlconst) { + if(is_numeric($filter[$check])) { + $awhere[] =$sqlconst." = ".$filter[$check]; + } + } + if($awhere) $where = "WHERE ".join(" AND ",$awhere); + } + return selectsql(" + select fs.*,u.nick as tnick from fleet_status fs + left join user u on (u.gala = fs.tgala and u.pos = fs.tpos) + $where + order by arrival asc + "); +} + +function fleet_update($fid,$fleet) { + Assert::isId($fid); + $logger = & LoggerManager::getLogger("db.takscreen"); + $logger->debug(array( + "function"=>"fleet_update", + "fid" => $fid, + "fleet" => $fleet + )); + $checkfleet = array( + "jaeger","bomber","fregatten", + "zerstoerer","kreuzer","schlachter", + "traeger","kleptoren","cancris" + ); + $update = array(); + foreach ($checkfleet as $key) { + if(isset($fleet[$key]) && is_numeric($fleet[$key])) { + $update[] = "$key = ".(int)$fleet[$key]; + }else { + $update[] = "$key = 0"; + } + } + return query(" + update fleet set ".join(",",$update)." where fid = $fid + "); + $logger->debug("fleetupdate done"); +} + +function fleet_copy($src,$dst=0) { + + if (!$src || !is_numeric($src)) return; + $fleet = getFleet($src); + if (!$fleet) return; + if ($dst) { + return fleet_update($dst,$fleet); + } else { + return fleet_add($fleet); + } +} + +function fleet_get($fid) { + + if (!$fid || !is_numeric($fid)) return; + return selectsqlLine("select * from fleet where fid = $fid"); +} + + +/** + * @return integer fid der Flotte + * @param array $fleet + * @desc F�gt eine Flotte hinzu +*/ +function fleet_add($fleet=null) { + $insert = array(); + if($fleet) { + $checkfleet = array( + "jaeger","bomber","fregatten", + "zerstoerer","kreuzer","schlachter", + "traeger","kleptoren","cancris" + ); + foreach ($checkfleet as $key) { + if($fleet[$key]) $insert[$key] = $fleet[$key]; + } + } + return insertsql(" + insert into fleet(".join(",",array_keys($insert)).") + values (".join(",",array_values($insert)).") + "); +} + +function fleetstatus_get_bykoords($gala,$pos,$num=null,$col=null) { + if(isset($num)) { + $result = selectsqlline(" + select fs.*,s.*,u.uid from + fleet_status fs + left join scans s on (s.gala = fs.gala and s.pos = fs.pos) + left join user u on(u.gala = fs.gala and u.pos = fs.pos) + where + fs.gala = $gala and fs.pos = $pos and fs.fleetnum = $num + "); + } else { + $result = selectsql(" + select fs.*,s.*,u.uid from + fleet_status fs + left join scans s on (s.gala = fs.gala and s.pos = fs.pos) + left join user u on(u.gala = fs.gala and u.pos = fs.pos) + where + fs.gala = $gala and fs.pos = $pos + "); + } + return $result; +} + +function fleetstatus_get($fsid) { + if(!$fsid || !is_numeric($fsid)) return false; + return selectsqlline(" + select fs.*,s.nick,f.*,u.uid + from fleet_status fs + left join scans s on (s.gala = fs.gala and s.pos = fs.pos) + left join user u on (u.gala = fs.gala and u.pos = fs.pos) + left join fleet f on (f.fid = fs.fid) + where fs.fsid = $fsid + "); +} + +function fleetstatus_recall($fsid) { + $status = fleetstatus_get($fsid); + + if($status['uid']) { + // interne flotte + if($status['fleetnum'] && $status['arrival']) { + $eta = $status['arrival'] - time(); + if($eta < 0) $eta = 0; + $eta = floor($eta/60); + $data = array(); + $data['orbittime'] = ""; + $data['returntime'] = ""; + $data['arrival'] = gnarrival($status['returntime'] - $eta); + $data['return_flight'] = 1; + fleetstatus_update($fsid,$data); + } else { + fleetstatus_delete($fsid); + } + } else { + // externe flotte + fleetstatus_delete($fsid); + if($status['fid']) fleet_delete($status['fid']); + } + //letzter atter recallt ? + if($status['status'] == 1 && !fleetstatus_get_bytarget($status['tgala'],$status['tpos'],1)) { + $user = getUserByPos($status['tgala'],$status['tpos']); + user_set_safe($user['uid'],0); + } +} + +function fleetstatus_update_fleet($fsid,$fleetdata,$svs=0,$prec=0) { + if(!$fsid || !is_numeric($fsid)) return false; + if(!($status = fleetstatus_get($fsid))) return false; + + if($status['fid']) { + $fid = $status['fid']; + fleet_update($fid,$fleetdata); + } else { + if($status['uid']) { + // intern neu, geht normalerweise gar net + } else { + // extern neu + $fid = fleet_add($fleetdata); + } + } + if(!strlen($svs)) $svs = "NULL"; + if(!strlen($prec)) $prec = "NULL"; + + return query("update fleet_status set + fid = $fid, + prec = $prec, + svs = $svs, + lastupdate = unix_timestamp() + where fsid = $fsid + "); +} + +/** + * �ndert die Nummer der Flotte beim Flottenstatus. + * + * Dabei wird beachtet, ob es bereits einen Eintrag f�r die Nummer gibt, und ob es sich + * um eine interne Flotte handelt. ggf. werden die Flottendaten vertauscht. + * + * @param (int|array) $fsid flottenstatus id + * @param int $fleetnum neue Flottennummer + */ +function fleetstatus_change_fleetnum($fsid,$fleetnum) { + + if(is_array($fsid)) $fsid = $fsid['fsid']; + if(!is_numeric($fsid)) return false; + + $status = fleetstatus_get($fsid); + if($status['fleetnum'] != $fleetnum) { + $check = fleetstatus_get_bykoords($status['gala'],$status['pos'],$fleetnum); + if($check) { + // es existiert ein anderer eintrag mit der flottennummer, flottendaten/nummern werden vertauscht + fleetstatus_update($check['fsid'],array("fleetnum" => $status['fleetnum'],"fid" => $status['fid'])); + $fid = $check['fid']; + } else { + // kein anderer eintrag da, check obs ne interne flotte is + if(($user = user_fleet_get($status['gala'],$status['pos'],$fleetnum))) { + // flottendaten der internen flotte werden geladen + $fid = $user['fid']; + } else { + // is eine externe + // flottendaten bleiben erhalten + $fid = $status['fid']; + } + } + #_dump("fsid: $fsid, fleetnum: $fleetnum,fid: $fid
"); + fleetstatus_update($fsid,array("fleetnum" => $fleetnum,"fid" => $fid)); + } +} + +function fleetstatus_update($fsid,$data) { + $update = array(); + $_values = array( + "orbittime" => "NULL", + "returntime" => "NULL", + "return_flight" => "0", + "arrival" => "NULL", + "tgala" => "NULL", + "tpos" => "NULL", + "gala" => null, + "pos" => null, + "status" => "0", + "fleetnum" => "NULL", + "fid" => "NULL", + "svs" => "NULL", + "prec" => "NULL" + ); + + foreach ($_values as $key => $default) { + if(isset($data[$key])) { + if(strlen($data[$key])) { + $update[] = $key." = ".$data[$key]; + } else { + $update[] = $key." = ".$default; + } + } + } + if($update) { + return query(" + update fleet_status set ".join(",",$update).",lastupdate = unix_timestamp() where fsid = $fsid + "); + } +} + +function fleetstatus_add($data) { + + if(!($data['status'] || $data['return_flight']) || !$data['gala'] || !$data['pos']) return false; + $insert = array(); + $insert['gala'] = $data['gala']; + $insert['pos'] = $data['pos']; + + $check = array("status","orbittime","returntime","return_flight","arrival","tgala","tpos","fid","svs","prec"); + + foreach ($check as $key) { + if(strlen($data[$key] > 0)) $insert[$key] = "'".$data[$key]."'"; + } + if($data['fleetnum']) $insert['fleetnum'] = $data['fleetnum']; + $insert['lastupdate'] = "unix_timestamp()"; + $query = "insert into fleet_status (".join(",",array_keys($insert)).") values (".join(",",array_values($insert)).")"; + + return query($query); +} + +function fleetstatus_delete($fsid) { + $intern = fleetstatus_get($fsid); + if(!$intern['uid'] && $intern['fid']) { + fleet_delete($intern['fid']); + } + return query("delete from fleet_status where fsid = $fsid"); +} + +function fleetstatus_delete_bykoords($gala,$pos) { + return query("delete from fleet_status where gala = $gala AND pos = $pos"); +} + +function fleet_delete($fid) { + if(!$fid) return false; + if(!is_array($fid)) $fid = array($fid); + return query(" + delete from fleet where fid IN (".join($fid).")"); +} + +function fleetstatus_get_bytarget($gala,$pos,$status=0,$returnflight = 0){ + + if(!is_numeric($gala)) return; + if(!is_numeric($pos)) return; + if($status && is_numeric($status)) $sqlstatus = "status = $status and"; + return selectsql("select * from fleet_status where $sqlstatus tgala = $gala and tpos = $pos and return_flight = $returnflight"); +} + +function fleetstatus_refresh(){ + + $ids = selectsql(" + select fs.fsid,fid from fleet_status fs + left join user u on (u.gala = fs.gala and u.pos = fs.pos) + where fs.arrival+(fs.orbittime*60)-unix_timestamp() < 0 and fs.arrival is not null and u.uid is null + "); + if(count($ids)) { +// addToLogFile("System: ".count($ids)." Deffer recallt","Incomings"); + $fids = array(); + $fsids = array(); + for($i=0;$i < count($ids);$i++) { + if($ids[$i]['fid']) $fids[] = $ids[$i]['fid']; + $fsids[] = $ids[$i]['fsid']; + } + if($fids) query("delete from fleet where fid IN (".join(",",$fids).")"); + query("delete from fleet_status where fsid IN (".join(",",$fsids).")"); + } + query(" + update fleet_status set return_flight = 1, + arrival = returntime*60+arrival+orbittime*60, + returntime = NULL, orbittime = NULL + where return_flight = 0 AND arrival+orbittime*60-unix_timestamp() < 0 and arrival is not null"); + query(" + delete from fleet_status + where return_flight = 1 AND arrival-unix_timestamp() < 0 and arrival is not null"); +} + +?> diff --git a/src/database/db.user.php b/src/database/db.user.php new file mode 100644 index 0000000..7f4493b --- /dev/null +++ b/src/database/db.user.php @@ -0,0 +1,817 @@ + 0) { + getUserRights($user['gid'],&$user); + } + } else { + $user = selectsqlLine("select * from user where lower(login) = lower('$login')"); + } + return $user; +} + +/** + * @return array von Userinformationen + * @param $id integer id des Users + * @param $password = "" Passwort des users in md5, (optional) + * @desc Liefert Userinformationen anhand von id und passwort + */ +function getUserByID($id, $password="") { + + Assert::isId($id); + if ($password) { + $user = selectsqlLine("select u.*,ga.aid,a.name,a.tag, + g.name as groupname, g.descr as groupdescr,g.usertitle + from user u + left join groups g using(gid) + left join galaxy ga on(ga.gala = u.gala) + left join alliance a on(a.aid = ga.aid) + where u.uid = $id and u.password = '$password' + "); + } else { + $user = selectsqlLine("select u.*,ga.aid,a.name,a.tag, + g.name as groupname, g.descr as groupdescr,g.usertitle + from user u + left join groups g using(gid) + left join galaxy ga on(ga.gala = u.gala) + left join alliance a on(a.aid = ga.aid) + where u.uid = $id + "); + } + if(is_numeric($user['gid']) && (int)$user['gid'] > 0) { + getUserRights($user['gid'],&$user); + } + return $user; +} + +function getUserByPos($gala,$pos) { + Assert::isId($gala); + Assert::isId($pos); + return selectsqlLine("select * from user where gala = $gala and pos = $pos"); +} + + +/** + * @return array der userdaten + * @param numeric $gala + * @param numeric $pos + * @desc Liefert den User anhand der galaxie/position +*/ +function user_get_bypos($gala,$pos) { + Assert::isId($gala); + Assert::isId($pos); + return selectsqlLine("select * from user where gala = $gala and pos = $pos"); +} + +function user_get_except($except,$aid=0) { + + $where = ""; + if ($except && is_array($except)) { + for($i=0;$i 1 || $scantype < 0) $scantype = 0; + if(!isset($svs) || !is_numeric($svs) || $svs < 0) $svs = 0; + if(!isset($timeview) || !is_numeric($timeview) || $timeview < 0) $timeview = 0; + if(!is_numeric($fleettype)) $fleettype = 0; + + return query("update user set email = '$email', emailvisible = $emailvisible, + phone = '$phone',nick='$nick' ,login = '$login', scantype = $scantype, svs = $svs, timeview = $timeview , fleettype = $fleettype where uid = '$id'"); +} + +function updatePassword($uid,$password) { + Assert::isId($uid); + Assert::notEmpty($password); + return query("update user set password = '".md5($password)."', changepw = 1 where uid = $uid"); +} + +function deleteUser($id) { + Assert::isIdArray($id); + if(!is_array($id)) $id = array($id); + $sql = "(".join(",",$id).")"; + #comments l�schen + query("update comments set uid = 0 where uid IN ".$sql); + #news auf unbekannt setzen + query("update news set uid = 0 where uid IN ".$sql); + + #flotten die zu hause sind l�schen + $fids = selectsql(" + select uf.fid from + user u + left join user_fleet uf on (uf.gala = u.gala and uf.pos = u.pos) + left join fleet_status fs on (fs.fid = uf.fid) + where u.uid IN $sql and fs.fid is null and uf.fid is not null + ","fid"); + if($fids) { + $fids = join(",",$fids); + query("delete from fleet where fid IN ($fids)"); + } + #userflotten l�schen + $fids = selectsql(" + select uf.fid from + user u,user_fleet uf + where u.uid IN $sql and uf.gala = u.gala and uf.pos = u.pos + ","fid"); + if($fids) { + $fids = join(",",$fids); + query("delete from user_fleet where fid IN ($fids)"); + } + //filter l�schen + query("delete from fleet_filter where uid IN ".$sql); + //stats l�schen + #user l�schen + query("delete from activity where uid IN $sql"); + query("delete from user where uid IN ".$sql); + // attplan s�ubern + query("update attack set owner = NULL where owner IN $sql"); + query("delete from attack_atter where uid IN $sql"); + + //actionlog + query("update actionlog set uid = NULL where uid IN $sql"); + return true; +} + +function updateAdminUser($id,$nick,$login,$gala,$pos,$gid=0,$ircauth) { + Assert::isId($id); + Assert::isId($gala); + Assert::isId($pos); + Assert::isNumeric($gid); + + $nick = mysql_real_escape_string($nick); + $ircauth= mysql_real_escape_string($ircauth); + $user = getUserByID($id); + if($user['gala'] != $gala || $user['pos'] != $pos) { + query("update user_fleet set gala = $gala, pos = $pos where gala = ".$user['gala']." and pos = ".$user['pos']); + } + return query("update user set nick = '$nick', login='$login',gala = $gala, pos = $pos, gid = $gid, ircauth = '$ircauth' where uid = $id"); +} + +/** + * @return unknown + * @param $nick unknown + * @param $password unknown + * @param $email unknown + * @param $phone unknown + * @param $koords unknown + * @desc Enter description here... + */ +function addUser($nick,$login,$password,$gid,$gala,$pos,$ircauth) { + Assert::isNumeric($gid); + Assert::isId($gala); + Assert::isId($pos); + + $nick = mysql_real_escape_string($nick); + $login = mysql_real_escape_string($login); + $ircauth= mysql_real_escape_string($ircauth); + $user = insertsql("insert into user (nick,login,password,gid,gala,pos,changepw,ircauth) values ('$nick','$login','".md5($password)."',$gid,$gala,$pos,1,'$ircauth')"); + for($i=0;$i < 3;$i++) { + if($i > 0) $status = fleetstatus_get_bykoords($gala,$pos,$i); + if($status['fid']) { + $fid = $status['fid']; + } else { + $fid = fleet_add(); + } + insertsql("insert into user_fleet (gala,pos,fid,fleetnum) values ($gala,$pos,$fid,$i)"); + } + $position = getScan(array("gala" => $gala, "pos" => $pos)); + if($position) { + scan_update_nick($gala,$pos,$nick); + } else { + scan_add($gala,$pos,array("nick" => $nick)); + } + return $user; +} + +/** + * @return array + * @param $gid integer + * @param $userarray array das user data arry per referenz + * @desc Liefert die Userrechte + */ +function getUserRights($gid,$userarray="") { + Assert::isId($gid); + $rights = selectsql("select r.*,gr.rank from groups g + left join group_rights gr using(gid) + left join rights r on(r.rid = gr.rid) + where g.gid = $gid"); + if ($userarray && $rights) { + for($i=0;$i < count($rights);$i++) { + $userarray['rights'][$rights[$i]['name']] = $rights[$i]; + } + } + return $rights; +} + +function listAllUser() { + + return selectsql("select u.*,a.*, + DATE_FORMAT(u.loggedin, '%d.%m.%y') as date, + DATE_FORMAT(u.loggedin, '%H:%i') as time + from user u + left join galaxy ga on (ga.gala = u.gala) + left join alliance a on (a.aid = ga.aid) + order by tag asc,nick asc"); +} + +function listUser($filter,$pages,$page=1,$rows=10) { + Assert::isId($page); + Assert::isId($rows); + + #username + if ($filter['username']) { + if ($where) $where .= " and "; + $where .= " u.nick LIKE '".mysql_real_escape_string($filter['username'])."%'"; + } + #gala + if ($filter['gala']) { + Assert::isId($filter['gala']); + if ($where) $where .= " and "; + $where .= " u.gala = ".(int)$filter['gala']." "; + } + #ally + if ($filter['ally']) { + Assert::isId($filter['ally']); + if ($where) $where .= " and "; + $where .= " ga.aid = ".(int)$filter['ally']." "; + if ($filter['checkallygalas']) { + $galalist = getGalaListByAlly($filter['ally']); + if ($galalist){ + $galalist = getArrayFromList($galalist,"gala"); + $galalist = "(".join(",",$galalist).")"; + $where .= " AND u.gala IN ".$galalist; + } else { + $page = 0; + $pages = 0; + return; + } + } + } + #phone + if ($filter['phone']) { + if ($where) $where .= " and "; + $where .= " u.phone LIKE '".mysql_real_escape_string($filter['phone'])."%'"; + } + #group + if ($filter['group']) { + Assert::isTrue((int)$filter['group'] >= -1); + if ($where) $where .= " and "; + if ((int)$filter['group'] == -1) $where .= " u.gid = 0 "; + else $where .= " u.gid = ".((int)$filter['group']); + } + if ($where) $where = " where ".$where; + + #order by + if ($filter['order'] == "asc") $order = " ASC "; + else $order = " DESC "; + if ($filter['sort'] == "username") $sort = " u.nick "; + elseif ($filter['sort'] == "group") $sort = " groupname "; + elseif ($filter['sort'] == "login") $sort = " u.loggedin "; + elseif ($filter['sort'] == "fleetupdate") $sort = " u.fleetupdate "; + elseif ($filter['sort'] == "koords") $sort = " u.gala ".$order.", u.pos "; + elseif ($filter['sort'] == "phone") $sort = " u.phone "; + else $sort = " u.nick "; + $count = selectsqlLine(" + select count(*) as count + from user u + left join galaxy ga on (ga.gala = u.gala) + ".$where); + #Seitenamzahl berechnen + $pages = ceil($count['count']/$rows); + #Seite checken + if ($pages < $page && $pages != 0) { + $page = $pages; + } + $return = selectsql("select u.*,a.tag, + DATE_FORMAT(u.loggedin, '%d.%m.%y') as date, + DATE_FORMAT(u.loggedin, '%H:%i') as time, + g.name as groupname, g.descr as groupdescr,g.usertitle + from user u + left join groups g using(gid) + left join galaxy ga on(ga.gala = u.gala) + left join alliance a on(a.aid = ga.aid) + ".$where." + order by ".$sort." ".$order." + LIMIT ".($rows*($page-1)).",$rows"); + return $return; +} + +# +# listet die userflotten auf +# +function user_fleet_list($filter,$pages,$page=1,$rows=10) { + Assert::isId($page); + Assert::isId($rows); + #order by + if ($filter['order'] == "asc") $order = " ASC "; + else $order = " DESC "; + if ($filter['sort'] == "username") $sort = " u.nick "; + elseif ($filter['sort'] == "fleetupdate") $sort = " u.fleetupdate "; + elseif ($filter['sort'] == "koords") $sort = " u.gala ".$order.", u.pos "; + else $sort = " u.nick "; + $count = selectsqlLine("select count(*) as count from user u + ".$where); + #Seitenamzahl berechnen + $pages = ceil($count['count']/$rows); + #Seite checken + if ($pages < $page && $pages != 0) { + $page = $pages; + } + $return = selectsql(" + select u.*, + sum(f.jaeger) as jaeger, + sum(f.bomber) as bomber, + sum(f.fregatten) fregatten, + sum(f.zerstoerer) as zerstoerer, + sum(f.kreuzer) as kreuzer, + sum(f.schlachter) as schlachter, + sum(f.traeger) as traeger, + sum(f.cancris) as cancris, + sum(f.kleptoren) as kleptoren + from user u + left join user_fleet uf on (uf.gala = u.gala and uf.pos = u.pos) + left join fleet f on (f.fid = uf.fid) + group by u.uid + order by ".$sort." ".$order." + LIMIT ".($rows*($page-1)).",$rows"); + return $return; +} + +# +# listet die userflotten auf +# +function user_fleet_sum($uid) { + Assert::isId($uid); + return selectsqlLine("select u.*, + sum(f.jaeger) as jaeger, + sum(f.bomber) as bomber, + sum(f.fregatten) fregatten, + sum(f.zerstoerer) as zerstoerer, + sum(f.kreuzer) as kreuzer, + sum(f.schlachter) as schlachter, + sum(f.traeger) as traeger, + sum(f.cancris) as cancris, + sum(f.kleptoren) as kleptoren + from user u + left join user_fleet uf on (uf.gala = u.gala and uf.pos = u.pos) + left join fleet f on (f.fid = uf.fid) + where u.uid = $uid + group by u.uid + "); +} + +#useronline +function refreshUserOnline($sec=300) { + $date = getdate(time()); + $date = date("Y.m.d H:i:s", mktime($date['hours'],$date['minutes'],$date['seconds']-(int)$sec,$date['mon'],$date['mday'],$date['year'])); + query("delete from useronline where time < '$date'"); +} + +function updateUserOnline($id) { + Assert::isId($id); + $result = selectsqlLine("select * from useronline where uid = $id"); + if ($result) { + query("update useronline set time = now() where uid = $id"); + } else { + insertsql("insert into useronline (uid,time) values($id,Now())"); + } +} + +function deleteUserOnline($id) { + Assert::isId($id); + query("delete from useronline where uid = $id"); +} + +function listUserOnline() { + + return selectsql("select * from useronline left join user using(uid) order by gala asc, pos asc"); +} + +function getGalas() { + + return selectsql("select distinct gala from user order by gala asc"); +} + +# +# updated die flotten eines users, fleets = array(id => flotte,...) +# +/*function updateUserFleet($uid,$fleets) { + + if (!$uid || !is_numeric($uid)) return; + $list = selectsql(" + select * from userfleet + left join fleetstatus using(fid) + where uid = $uid order by fleetnum asc + "); + for($i=0;$i < count($list);$i++){ + $fleet = &$fleets[$i]; + updateFleet($list[$i]['fid'],$fleet['kleptoren'],$fleet['cancris'], + $fleet['fregatten'],$fleet['zerstoerer'],$fleet['kreuzer'], + $fleet['schlachter'],$fleet['traeger'],$fleet['jaeger'],$fleet['bomber']); + } + query("update user set fleetupdate = unix_timestamp() where uid = $uid"); +} +*/ + +function user_fleets_update($uid,$fleets) { + Assert::isId($uid); + $user = getUserByID($uid); + if (!$user) { + trigger_error("user not found",E_USER_ERROR); + return false; + } + $userfleets = user_fleet_list_byuser($uid); + if(!$userfleets || !is_array($userfleets)) { + trigger_error("user fleets for user $uid not found",E_USER_ERROR); + return false; + } + #fleetstatus_delete_bykoords($user['gala'],$user['pos']); + foreach ($userfleets as $fleet) { + if(isset($fleets[$fleet['fleetnum']])) { + fleet_update($fleet['fid'],$fleets[$fleet['fleetnum']]); + #$fleets[$fleet['fleetnum']]['fleetnum'] = $fleet['fleetnum']; + #fleetstatus_add($fleets[$fleet['fleetnum']]); + } + } + query("update user set fleetupdate = unix_timestamp() where uid = $uid"); +} + +function getUserIdByAuth($auth) { + + $auth = mysql_real_escape_string($auth); + $res = selectsqlline(" + select u.uid + from user u + where u.ircauth LIKE '$auth' + "); + return $res['uid']; +} + +function user_deff_get($id) { + Assert::isId($id); + return selectsqlline(" + select rubium,horus,coon,pulsar,centurion,deffupdate from user where uid = $id + "); +} + +function user_deff_update($id,$deff) { + Assert::isId($id); + $_check = array( + "rubium", + "horus", + "pulsar", + "coon", + "centurion" + ); + $update = array(); + foreach ($_check as $key) { + if(is_numeric($deff[$key]) && (int) $deff[$key] > 0){ + $update[] = "$key = ".((int)$deff[$key]); + } else { + $update[] = "$key = 0"; + } + } + return query(" + update user set ".join(",",$update).", deffupdate = unix_timestamp() + where uid = $id + "); +} + +function user_fleet_bynum($id,$num) { + Assert::isId($id); + Assert::isNumeric($num); + return selectsqlline(" + select u.uid,uf.*,fs.fsid,fs.arrival,fs.return_flight,fs.returntime,fs.status,fs.tgala,fs.tpos,fs.orbittime from + user u + left join user_fleet uf on (uf.gala = u.gala and uf.pos = u.pos) + left join fleet f on (f.fid = uf.fid) + left join fleet_status fs on (fs.fid = uf.fid) + where + u.uid = $id AND uf.fleetnum = $num + "); +} + +/*function User_fleet_status_update($uid,$fleetnum,$status,$return_flight,$eta,$gala,$pos,$ticks,$return) { + + if(!is_numeric($uid)) return; + if(!is_numeric($fleetnum)) return; + if(!is_numeric($status)) $status = 0; + if(!is_numeric($return_flight)) $return_flight = 0; + + if (isset($eta)) $seconds = "unix_timestamp()+".$eta*60; else $seconds = "NULL"; + if (!$ticks) $ticks = "NULL"; + if (!$return || !is_numeric($return)) + { + $return = "NULL"; + } + + $fleet = selectsqlline("select * from userfleet uf left join fleetstatus fs on(fs.fid = uf.fid) where uf.uid = $uid AND fs.fleetnum = $fleetnum"); + if(!$fleet) return; + if($status != 2 || $return_flight) { + query("delete from inc_deffer where defferid = $fleet[fid]"); + } elseif(is_numeric($gala) && is_numeric($pos)) { + // m�glichen deffer eintragen + $inc = selectsqlline(" + select * from user u + left join incomings i on (i.incid = u.uid) + where u.gala = $gala and u.pos = $pos + "); + if($inc['incid']) { + $deffs = selectsqlline("select * from inc_deffer where defferid = ".$fleet['fid']); + if (!$deffs) insertsql("insert into inc_deffer(defferid,incid) values(".$fleet["fid"].",".$inc["incid"].")"); + else query("update inc_deffer set incid = ".$inc["incid"]." where defferid = ".$fleet["fid"]); + } + } + if(!$gala) $gala = "NULL"; + if(!$pos) $pos = "NULL"; + return query(" + update fleetstatus set status = $status,arrival = $seconds, gala = $gala,pos = $pos, ticks = $ticks, returntime = $return, return_flight = $return_flight + where fid = $fleet[fid] AND fleetnum = $fleetnum + "); +}*/ + +/* +function fleet_status_update($fid,$fleetnum,$status,$eta,$gala,$pos,$ticks,$return) { + + if(!is_numeric($fid)) {return;} + if(!is_numeric($fleetnum)) {return;}; + if(!is_numeric($status)) {return;}; + if(!$gala){ + $gala = "NULL"; + } + if(!$pos){ + $pos = "NULL"; + } + if (isset($eta)) $seconds = "unix_timestamp()+".$eta*60; else $seconds = "NULL"; + if (!$ticks) $ticks = "NULL"; + if (!$return || !is_numeric($return)) + { + $return = "NULL"; + } + return query(" + update fleetstatus set status = $status,arrival = $seconds, gala = $gala,pos = $pos, ticks = $ticks, returntime = $return + where fid = $fid + "); +} + +*/ + +#liefert die top scanner +function user_get_scannerlist($type,$top=10) { + Assert::isNumeric($type); + Assert::isNumeric($top); + Assert::isTrue((int)$top >= 0); + return selectsql(" + select * from user u + left join galaxy ga on(ga.gala = u.gala) + left join alliance a on(a.aid = ga.aid) + where scantype = ".(int)$type." and svs > 0 + order by u.svs desc + limit 0,".(int)$top." + "); +} + +function get_activity_points() { + $hour = (int)date("H",time()); + $day = date("l",time()); + if($day == "Saturday" || $day == "Sunday") { + $points = array(array(22,23,0,1,7,9,10),array(2,3,8),array(4,5,6,7)); + } else { + $points = array(array(22,23,0,7),array(1,2,6),array(3,4,5)); + } + $bonus = 0; + if(in_array($hour,$points[0])) $bonus = 3; + if(in_array($hour,$points[1])) $bonus = 5; + if(in_array($hour,$points[2])) $bonus = 8; + if(!$bonus) $bonus = 1; + return $bonus; +} + +function get_activity_timeout() { + return 60*45; +} + +function do_check_activity($userdata) { +# echo "hour: $hour"; + $timeout = get_activity_timeout(); + if($userdata['activity_check']+$timeout < time() && + get_activity_points() + ) { + return true; + } + return false; +} + +function user_activity_check($uid){ + Assert::isId($uid); + $check = time(); + $bonus = get_activity_points(); + if(!$bonus) return; + query(" + update user set activity_check = unix_timestamp(), activity_points = activity_points + $bonus + where uid = $uid + "); + query("insert into activity (uid,stamp,bonus) values($uid,now(),$bonus)"); +} + +function highscore_list($filter,$pages,$page=1,$rows=50) { + Assert::isId($page); + Assert::isId($rows); + if($filter['hours'] || $filter['days']) { + if($filter['hours']) { + Assert::isNumeric($filter['hours']); + $timeout = date("Y-m-d H:m:s",time()-(int)$filter['hours']*60*60); + } else { + Assert::isNumeric($filter['days']); + $timeout = date("Y-m-d H:m:s",time()-(int)$filter['days']*24*60*60); + } + $count = selectsql(" + select count(*) as count + from user u + left join activity a on (a.uid = u.uid) + where a.stamp > '$timeout' + group by u.uid + "); + $count = count($count); + #Seitenamzahl berechnen + $pages = ceil($count/$rows); + #Seite checken + if ($pages < $page && $pages != 0) { + $page = $pages; + } + $result = selectsql(" + select u.*,ga.*,a.*,sum(ac.bonus) as activity_points + from user u + left join activity ac on (ac.uid = u.uid) + left join galaxy ga on (ga.gala = u.gala) + left join alliance a on(a.aid = ga.aid) + where ac.stamp > '$timeout' + group by u.uid + order by activity_points desc, u.nick asc + LIMIT ".($rows*($page-1)).",$rows + "); + } else { + $count = selectsqlLine(" + select count(*) as count + from user u + "); + #Seitenamzahl berechnen + $pages = ceil($count['count']/$rows); + #Seite checken + if ($pages < $page && $pages != 0) { + $page = $pages; + } + $result = selectsql(" + select * from user u + left join galaxy ga on (ga.gala = u.gala) + left join alliance a on(a.aid = ga.aid) + order by u.activity_points desc, u.nick asc + LIMIT ".($rows*($page-1)).",$rows + "); + } + for($i=0;$i < count($result);$i++) { + $result[$i]['place'] = $rows*($page-1) + $i + 1; + } + return $result; +} +?> \ No newline at end of file diff --git a/src/functions/admin.class.php b/src/functions/admin.class.php new file mode 100644 index 0000000..2cc0bc5 --- /dev/null +++ b/src/functions/admin.class.php @@ -0,0 +1,1965 @@ +action]) { + eval("\$this->".$functions[$this->action].";"); + } + #default + $this->_header("index.php"); + } + + /** \brief Logfile anzeigen + + Listet alle Einträge des Logfile auf + */ + function Logfile_list() { + if (!$this->userdata['rights']['logfile']) { + #no permission + $this->_header("","no permission"); + } + $logfilefilter = $_SESSION['logfilefilter']; + if ($_REQUEST['subaction'] == 'newsearch' && $logfilefilter) { + unset($logfilefilter); + unset($_SESSION['logfilefilter']); + } + $page = param_num("page",1); + $rows = 12; + if ($_REQUEST['sort'] && $_REQUEST['order'] && $logfilefilter) { + $sort = trim($_REQUEST['sort']); + $order = trim($_REQUEST['order']); + if ($sort != 'username' && $sort != 'cat' && $sort != 'date') $sort = 'date'; + if ($order != "asc" && $order != "desc") $order = "desc"; + $logfilefilter['sort'] = $sort; + $logfilefilter['order'] = $order; + $_SESSION['logfilefilter'] = $logfilefilter; + } + if ($_REQUEST['subaction'] == "search") { + $logfilefilter['username'] = param_str("username"); + $logfilefilter['gala'] = param_str("gala"); + $logfilefilter['cat'] = $_REQUEST['cat']; + $logfilefilter['sort'] = "date"; + $logfilefilter['order'] = "desc"; + $_SESSION['logfilefilter'] = $logfilefilter; + } + if (!$logfilefilter) { + $catlist = getLogFilecatList(); + $this->template->assign('catlist',$catlist); + $this->forms['logfile']['action'] = "logfile"; + $this->forms['logfile']['url'] = "admin.php"; + $this->show('logfile_list_form','Logfile durchsuchen'); + } + $this->forms['logfile'][$logfilefilter['sort']][$logfilefilter['order']] = '_active'; + $logfile = listLogFile($logfilefilter,&$pages,&$page,$rows); + $this->forms['logfile']['pages'] = showPageBar($page,$pages,"admin.php?action=logfile","page","menu"); + for ($i=0;$itemplate->assign('logfile',$logfile); + $this->show('logfile_list','Logfile'); + } + /** \brief User anzeigen + + Listet alle User auf, vorher wird ein Filter angeboten. + Filter ist abhängig von den Rechten die der User hat. + */ + function User_list() { + #check rights + $rank = $this->userdata['rights']['useredit']['rank']; + if (!$rank){ + #no permission + $this->_header("","no permission"); + } + $userlistfilter = $_SESSION['userlistfilter']; + $page = param_num("page",1); + $rows = 12; + if ($_REQUEST['subaction'] == 'newsearch' && $userlistfilter) { + unset($userlistfilter); + unset($_SESSION['userlistfilter']); + } + if ($_REQUEST['sort'] && $_REQUEST['order'] && $userlistfilter) { + $sort = trim($_REQUEST['sort']); + $order = trim($_REQUEST['order']); + if ($sort != 'username' && $sort != 'koords' + && $sort != 'group' && $sort != 'phone') $sort = 'koords'; + if ($order != "asc" && $order != "desc") $order = "asc"; + $userlistfilter['sort'] = $sort; + $userlistfilter['order'] = $order; + $_SESSION['userlistfilter'] = $userlistfilter; + } + + if ($_REQUEST['subaction'] == "search") { + $userlistfilter['username'] = param_str("username"); + $userlistfilter['gala'] = param_str("gala"); + if ($rank > 1) { + $userlistfilter['ally'] = $this->userdata["aid"]; + #checken ob galas auch zur allys gehören + $userlistfilter['checkallygalas'] = true; + } else { + $userlistfilter['ally'] = param_num("ally"); + } + $userlistfilter['group'] = $_REQUEST['group']; + $userlistfilter['phone'] = param_str("phone"); + $userlistfilter['sort'] = "koords"; + $userlistfilter['order'] = "asc"; + $_SESSION['userlistfilter'] = $userlistfilter; + } + if (!$userlistfilter) { + if ($rank == 1) { + $this->template->assign('allylist',getAllyList()); + $this->template->assign('rank1',1); + } else { + $this->template->assign('ally',$this->userdata['tag']); + } + $this->template->assign('grouplist',getGroupList()); + $this->forms['userlist']['action'] = "user"; + $this->forms['userlist']['url'] = "admin.php"; + $this->show('user_list_form','Benutzer suchen'); + exit(); + } + #nochmal rang check + if ($rank > 1 && $userlistfilter['ally'] != $this->userdata["aid"]) { + $userlistfilter['ally'] = $this->userdata["aid"]; + #checken ob galas auch zur allys gehören + $userlistfilter['checkallygalas'] = true; + $_SESSION['userlistfilter'] = $userlistfilter; + } + $this->forms['userlist'][$userlistfilter['sort']][$userlistfilter['order']] = '_active'; + $userlist = listUser($userlistfilter,&$pages,&$page,$rows); + $this->forms['userlist']['pages'] = showPageBar($page,$pages,"admin.php?action=user","page","menu"); + $setback = "admin.php?action=user&page=".$page; + $_SESSION['setback'] = $setback; + $this->template->assign('userlist',$userlist); + $this->show('user_list','Benutzerliste'); + } + /** + \brief Zeigt Userstatistiken + + zeigt Statistiken zu den Usern an + */ + function User_Stats() { + if (!$this->_checkUserRights(array("admin"))) + $this->_header("index.php"); + $userstatsfilter = $_SESSION['userstatsfilter']; + $page = param_num("page",1); + $rows = 12; + if ($_REQUEST['sort'] && $_REQUEST['order'] && $userstatsfilter) { + $sort = trim($_REQUEST['sort']); + $order = trim($_REQUEST['order']); + if ($sort != 'username' && $sort != 'koords' && $sort != 'login') $sort = 'username'; + if ($order != "asc" && $order != "desc") $order = "asc"; + $userstatsfilter['sort'] = $sort; + $userstatsfilter['order'] = $order; + $_SESSION['userstatsfilter'] = $userstatsfilter; + } + if (!$userstatsfilter) { + $userstatsfilter['sort'] = 'koords'; + $userstatsfilter['order'] = 'asc'; + $_SESSION['userstatsfilter'] = $userstatsfilter; + } + $this->forms['userlist'][$userstatsfilter['sort']][$userstatsfilter['order']] = '_active'; + $userlist = listUser($userstatsfilter,&$pages,&$page,$rows); + for($i=0;$iforms['userlist']['pages'] = showPageBar($page,$pages,"admin.php?action=userstats","page","menu"); + $this->template->assign('userlist',$userlist); + $this->show('user_stats','Benutzerstatistik'); + } + /** + \brief Gruppen auflisten + + Listet die Rechtegruppen des TC auf + */ + function Group_list() + { + if (!$this->userdata['rights']['groupedit']) { + #no permission + $this->_header("","no permission"); + } + $page = param_num("page",1); + $rows = 6; + $grouplistfilter = $_SESSION['grouplistfilter']; + if (($_REQUEST['sort'] && $_REQUEST['order']) || !$grouplistfilter) { + $sort = trim($_REQUEST['sort']); + $order = trim($_REQUEST['order']); + if ($sort != 'name' && $sort != 'descr' && $sort != 'member') $sort = 'name'; + if ($order != "asc" && $order != "desc") $order = "asc"; + $grouplistfilter['sort'] = $sort; + $grouplistfilter['order'] = $order; + $_SESSION['grouplistfilter'] = $grouplistfilter; + } + $this->forms['grouplist'][$grouplistfilter['sort']][$grouplistfilter['order']] = '_active'; + $grouplist = listGroups($grouplistfilter,&$pages,&$page,$rows); + $this->forms['grouplist']['pages'] = showPageBar($page,$pages,"admin.php?action=groups","page","menu"); + $this->template->assign('grouplist',$grouplist); + $this->show('group_list','Gruppenliste'); + } + /** + \brief Gruppeninfos + + Zeigt Informationen zu einer Gruppe an + */ + function Group_details(){ + if (!$this->userdata['rights']['groupedit']) { + #no permission + $this->_header("","no permission"); + } + $id = param_num("id"); + if (!$id) $this->_header(); + $return = getGroup($id); + if (!$return) $this->_header(); + $this->template->assign("searchlink","admin.php"); + $this->template->assign("editlink","admin.php?action=editgroup&id=$id"); + $this->template->assign("deletelink","admin.php?action=deletegroup&id=$id"); + $this->template->assign("groupid",$id); + $this->forms['groupdetails']['fields'] = $return; + $this->show('group_details_admin',"Gruppendetails"); + } + + /** + \brief Gruppe bearbeiten + + Ändert die Daten einer Gruppe + */ + function Group_edit() { + if (!$this->userdata['rights']['groupedit']) { + #no permission + $this->_header("","no permission"); + } + $id = param_num("id"); + if (!$id) $this->_header(); + $page = param_num("page",1); + $return = getGroup($id); + if (!$return) $this->_header(); + $data = $_SESSION['steps']; + #information message, step 2 + if ($data['groupedit']) { + #save step + unset($data['groupedit']); + $_SESSION['steps'] = $data; + $this->forms['information']['action'] = "groupdetails"; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['title'] = "Gruppe bearbeiten"; + $this->forms['information']['message'] = "Änderung erfolgreich"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Gruppe bearbeiten"); + } + #formular send + if ($_REQUEST['send']) { + $items['name'] = param_str("name",true); + $items['descr'] = param_str("descr",true); + if (!$items['name']) { + $errors[] = "Name darf nicht leer sein!"; + $this->forms['addgroup']['fields']['name']['bgrd'] = '_error'; + } + if (!$items['descr']) { + $errors[] = "Beschreibung darf nicht leer sein!"; + $this->forms['addgroup']['fields']['descr']['bgrd'] = '_error'; + } + #optional parameters + $items['usertitle'] = param_str("usertitle",true); + if (!$errors && $items['name'] != $return['name'] && getGroupByName($items['name'])) { + $errors[] = 'Gruppe existiert bereits!'; + $this->forms['addgroup']['fields']['name']['bgrd'] = '_error'; + } + if (!$errors) { + #save step + $data['groupedit'] = 1; + $_SESSION['steps'] = $data; + addToLogfile("Gruppe ".$return['name']." bearbeitet","Admin",$this->userdata['uid']); + updateGroup($return['gid'],$items['name'],$items['descr'],$items['usertitle']); + $this->_header("admin.php?action=editgroup&id=".$return['gid']."&send"); + } else { + $this->template->assign("errors",$errors); + } + } else { + $this->forms['groupedit']['fields']['usertitle']['value'] = $return['usertitle']; + $this->forms['groupedit']['fields']['name']['value'] = $return['name']; + $this->forms['groupedit']['fields']['descr']['value'] = $return['descr']; + } + $this->forms['groupedit']['id'] = $return['gid']; + $this->forms['groupedit']['name'] = $return['name']; + $this->forms['groupedit']['url'] = 'admin.php?id='.$return['gid']; + $this->forms['groupedit']['action'] = 'editgroup'; + $this->show('group_edit_form',"Gruppe bearbeiten"); + } + /** + \brief Gruppe hinzufügen + + Fügt eine neue Gruppe hinzu + */ + function Group_add() { + if (!$this->userdata['rights']['groupedit']) { + #no permission + $this->_header("","no permission"); + } + $page = param_num("page",1); + $data = $_SESSION['steps']; + #information message, step 2 + if ($data['addgroup']) { + $id = param_num("id"); + if ($id) { + $return = getGroup($id); + if (!$return) $this->_header(); + } + #save step + unset($data['addgroup']); + $_SESSION['steps'] = $data; + $this->forms['information']['action'] = "groupdetails"; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['title'] = "Gruppe hinzufügen"; + $this->forms['information']['message'] = "Gruppe ".$return['name']." hinzugefügt"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Gruppe hinzufügen"); + } + #formular send + if ($_REQUEST['send']) { + $items['name'] = param_str("name",true); + $items['descr'] = param_str("descr",true); + $errors = false; + #check if empty + if (!$items['name']) { + $errors[] = "Name darf nicht leer sein!"; + $this->forms['addgroup']['fields']['name']['bgrd'] = '_error'; + } + if (!$items['descr']) { + $errors[] = "Beschreibung darf nicht leer sein!"; + $this->forms['addgroup']['fields']['descr']['bgrd'] = '_error'; + } + #optional parameters + $items['usertitle'] = param_str("usertitle",true); +# for ($i=0;$iforms['addgroup']['fields']['name']['bgrd'] = '_error'; + } + if (!$errors) { + #save step + $data['addgroup'] = 1; + $_SESSION['steps'] = $data; + $gid = addGroup($items['name'],$items['descr'],$items['usertitle']); + if ($gid) { + addToLogfile("Gruppe ".$items['name']." hinzugefügt","Admin",$this->userdata['uid']); + $this->_header("admin.php?action=addgroup&id=".$gid."&send"); + } + } else { + $this->forms['addgroup']['fields']['descr']['value'] = $items['descr']; + $this->forms['addgroup']['fields']['name']['value'] = $items['name']; + $this->forms['addgroup']['fields']['usertitle']['value'] = $items['usertitle']; + $this->template->assign("errors",$errors); + } + } + $this->forms['addgroup']['name'] = $return['name']; + $this->forms['addgroup']['url'] = "admin.php"; + $this->forms['addgroup']['action'] = 'addgroup'; + $this->show('group_add_form',"Gruppe hinzufügen"); + } + /** + \brief Userinfos + + Zeigt ausführliche Informationen zu einem User + */ + function User_details() { + #check rights + $rank = $this->userdata['rights']['useredit']['rank']; + if (!$rank){ + #no permission + $this->_header("","no permission"); + } + $id = param_num("id"); + if (!$id) $this->_header(); + $return = getUserByID($id); + if (!$return) $this->_header(); + #ally/galaxyebene + if ($rank > 1 && $return['aid'] != $this->userdata['aid']){ + #no permission + $this->_header("","no permission"); + } + if ($rank == 1 || + ($rank == 2 && $return['aid'] == $this->userdata['aid']) || + ($rank == 3 && $return['gala'] == $this->userdata['gala'])) + { + $this->template->assign("editlink","admin.php?action=edituser&id=$id"); + $this->template->assign("deletelink","admin.php?action=deleteuser&id=$id"); + } + $this->template->assign("user",$return); + $this->template->assign("koords",$return['gala'].":".$return['pos']); + $this->show('user_details_admin',"Benutzerdetails"); + } + /** + \brief User bearbeiten + + Ändert die Daten eines Users + */ + function User_edit() { + #check rights + $rank = $this->userdata['rights']['useredit']['rank']; + if (!$rank){ + #no permission + $this->_header("","no permission"); + } + $page = param_num("page",1); + $id = param_num("id"); + if (!$id) $this->_header(); + $return = getUserByID($id); + if (!$return) $this->_header(); + #check rights + if (($rank > 1 && $this->userdata['aid'] != $return['aid']) || + ($rank > 2 && $this->userdata['gala'] != $return['gala'])){ + #no permission + $this->_header("","no permission"); + } + $data = $_SESSION['steps']; + #information message, step 2 + if ($data['useredit']) { + #save step + unset($data['useredit']); + $_SESSION['steps'] = $data; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['title'] = "Benutzerdaten ändern"; + $this->forms['information']['message'] = "Änderung erfolgreich"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Benutzerdaten ändern"); + } + #formular send + if ($this->userdata['rights']['changegroup']) { + $grouplist = getGroupList($this->userdata['rights']['changegroup']['rank']); + if ($return['gid']) { + for($i=0;$i < count($grouplist);$i++){ + if ($grouplist[$i]['gid'] == $return['gid']) { + $canchangegroup = true; + break; + } + } + } else { + $canchangegroup = true; + } + } + if($canchangegroup) { + $this->template->assign("changegroup",1); + } else { + $this->template->assign("group",$return['groupname']); + } + if ($rank == 1) { + $allylist = getAllyList(); + } else { + $this->template->assign("ally",$this->userdata['tag']); + } + $this->template->assign("rank",$rank); + $galalist = array(); + if ($_REQUEST['send']) { + $items['login']['value'] = param_str("login",true); + $items['nick']['value'] = param_str("nick",true); + $items['ircauth']['value'] = param_str("ircauth",true); + $items['pos']['value'] = param_num("pos",null,true); + $items['gala']['value'] = param_num("gala",null,true); + $password = param_str("password",true); + if ($rank == 1) { + $items['aid']['value'] = param_num("ally",0,true); + #check allyid + if ($items['aid']['value']) { + $ally = 0; + for ($i=0;$i < count($allylist);$i++) { + if ($items['aid']['value'] == $allylist[$i]['aid']) { + $ally = &$allylist[$i]; + $ally['selected'] = "selected"; + break; + } + } + } + if (!$ally) $this->_header("","Ungültige Allianzid!"); + } else { + $items['aid']['value'] = $this->userdata['aid']; + } + #check gala + if ($rank < 3) { + $galalist = getGalaListbyAlly($items['aid']['value']); + if (!$galalist){ + $errors[] = "Die Allianz hat keine Galaxien!"; + $galalist[] = array("gala" => "keine"); + } + } else { + $items['gala']['value'] = $this->userdata['gala']; + $this->template->assign("gala",$this->userdata['gala']); + } + if ($_REQUEST['next_x']) { + if (!$items['nick']['value']) { + $errors[] = "Nickname darf nicht leer sein!"; + $items['nick']['bgrd'] = '_error'; + } + if (!$items['login']['value']) { + $errors[] = "Login darf nicht leer sein!"; + $items['login']['bgrd'] = '_error'; + } + if (!$items['pos']['value']) { + $items['pos']['bgrd'] = '_error'; + $errors[] = "Die Position darf nicht leer sein!"; + } + if ($canchangegroup) { + #check gid + $items['gid']['value'] = param_num('group',0,true); + if ($items['gid']['value']) { + $group = 0; + for ($i=0;$i < count($grouplist);$i++) { + if ($items['gid']['value'] == $grouplist[$i]['gid']) { + $group = &$grouplist[$i]; + $group['selected'] = "selected"; + break; + } + } + if (!$group) $this->_header(); + } + } else { + $items['gid']['value'] = $return['gid']; + } + #check nickname + if ($items['nick']['value'] && strtolower($items['nick']['value']) != strtolower($return['nick']) + && getUserByNick($items['nick']['value'])) { + $errors[] = 'User existiert bereits!'; + $items['nick']['bgrd'] = '_error'; + } + #check login + if ($items['login']['value'] && strtolower($items['login']['value']) != strtolower($return['login']) + && getUserByLogin($items['login']['value'])) { + $errors[] = 'Login existiert bereits!'; + $items['login']['bgrd'] = '_error'; + } + #check galaid + if ($items['gala']['value'] && $rank < 3) { + $galaxy = 0; + for ($i=0;$i < count($galalist);$i++) { + if ($items['gala']['value'] == $galalist[$i]['gala']) { + $galaxy = &$galalist[$i]; + $galaxy['selected'] = "selected"; + break; + } + } + if (!$galaxy) $this->_header("index.php","Ungültige Galaid!"); + } + if (!$errors && ($return['gala'] != $items['gala']['value'] || $return['pos'] != $items['pos']['value'])){ + $chkuser = getUserByPos($items['gala']['value'],$items['pos']['value']); + if ($chkuser) { + $errors[] = "User existiert bereits, ".$chkuser['nick']." (".$chkuser['gala'].":".$chkuser['pos'].")"; + $items['pos']['bgrd'] = '_error'; + } + } + if (!$errors) { + #save step + $data['useredit'] = 1; + $_SESSION['steps'] = $data; + if ($password) { + #eigenes pw geändert + if ($return['uid'] == $this->userdata['uid']) { + updateUserPassword($return['uid'],$password); + $sessionuserdata['id'] = $this->userdata['uid']; + $sessionuserdata['password'] = md5($password); + $_SESSION['sessionuserdata'] = $sessionuserdata; + } else { + updatePassword($return['uid'],$password); + } + addToLogfile("Passwort von ".$return['nick']." geändert","Admin",$this->userdata['uid']); + } + addToLogfile("User ".$return['nick']." bearbeitet","Admin",$this->userdata['uid']); + updateAdminUser($return['uid'], + $items['nick']['value'], + $items['login']['value'], + $items['gala']['value'], + $items['pos']['value'], + $items['gid']['value'], + $items['ircauth']['value'] + ); + $this->_header("admin.php?action=edituser&id=".$return['uid']."&send"); + } + } + } else { + if ($return['gid'] && $this->userdata['rights']['changegroup']) { + for ($i=0;$i < count($grouplist);$i++) { + if ($return['gid'] == $grouplist[$i]['gid']) { + $grouplist[$i]['selected'] = "selected"; + break; + } + } + } + if ($rank == 1) { + #select ally + for ($i=0;$i < count($allylist);$i++) { + if ($return['aid'] == $allylist[$i]['aid']) { + $ally = &$allylist[$i]; + $ally['selected'] = "selected"; + break; + } + } + } + if ($rank < 3) { + $galalist = getGalaListbyAlly($return['aid']); + if (!$galalist){ + $errors[] = "Die Allianz hat keine Galaxien!"; + $galalist[] = array("gala" => "keine"); + } else { + #select gala + for ($i=0;$i < count($galalist);$i++) { + if ($return['gala'] == $galalist[$i]['gala']) { + $galalist[$i]['selected'] = "selected"; + break; + } + } + } + } else { + $this->template->assign("gala",$this->userdata['gala']); + } + $items['ircauth']['value'] = $return['ircauth']; + $items['nick']['value'] = $return['nick']; + $items['login']['value'] = $return['login']; + $items['pos']['value'] = $return['pos']; + } + $this->template->assign("errors",$errors); + $this->template->assign("galalist",$galalist); + $this->template->assign("allylist",$allylist); + if (!$items['ircauth']['value']) { + $items['ircauth']['bgrd'] = "_optional"; + } + if (!$items['password']['value']) { + $items['password']['bgrd'] = "_optional"; + } + $this->template->assign("items",$items); + $this->template->assign("grouplist",$grouplist); + $this->template->assign("id",$return['uid']); + $this->template->assign("username",$return['nickname']); + $this->show('user_edit_form',"Benutzerdaten ändern"); + } + /** + \brief User hinzufügen + + Fügt eines User hinzu. + */ + function User_add() { + #check rights + $rank = $this->userdata['rights']['useredit']['rank']; + if (!$rank){ + #no permission + $this->_header("","no permission"); + } + $page = param_num("page",1); + $id = param_num("id"); + $data = $_SESSION['steps']; + #information message, step 2 + if ($data['adduser']) { + if ($id) { + $return = getUserByID($id); + } + if ($return) { + $this->forms['information']['url'] = "admin.php?action=showdetails&id=".$return['uid']."&force"; + } else { + $this->forms['information']['url'] = $this->backtracking->backlink(); + } + #save step + unset($data['adduser']); + $_SESSION['steps'] = $data; + $this->forms['information']['action'] = "userdetails"; + $this->forms['information']['title'] = "Benutzer hinzufügen"; + $this->forms['information']['message'] = "Erfolgreich hinzugefügt"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Benutzer hinzufügen"); + } + #formular send + if ($this->userdata['rights']['changegroup']) { + $grouplist = getGroupList($this->userdata['rights']['changegroup']['rank']); + $this->template->assign("changegroup",1); + } + if ($rank == 1) { + $allylist = getAllyList(); + } else { + $this->template->assign("ally",$this->userdata['tag']); + } + $this->template->assign("rank",$rank); + $galalist = array(); + if ($_REQUEST['send']) { + $items['nickname']['value'] = param_str("nickname",true); + $items['password']['value'] = param_str("password",true); + $items['ircauth']['value']= param_str("ircauth",true); + $items['login']['value']= param_str("login",true); + $items['gala']['value'] = param_num("gala",null,true); + $items['pos']['value'] = param_num("pos",null,true); + $items['gala']['value'] = param_num("gala",0,true); + if ($rank == 1) { + $items['aid']['value'] = param_num("ally",0,true); + #check allyid + if ($items['aid']['value']) { + $ally = 0; + for ($i=0;$i < count($allylist);$i++) { + if ($items['aid']['value'] == $allylist[$i]['aid']) { + $ally = &$allylist[$i]; + $ally['selected'] = "selected"; + break; + } + } + } + if (!$ally) $this->_header("","Ungültige Allianzid!"); + } else { + $items['aid']['value'] = $this->userdata['aid']; + } + if ($rank < 3) { + $galalist = getGalaListbyAlly($items['aid']['value']); + if (!$galalist){ + $errors[] = "Die Allianz hat keine Galaxien!"; + $galalist[] = array("gala" => "keine"); + } + } else { + $items['gala']['value'] = $this->userdata['gala']; + $this->template->assign("gala",$this->userdata['gala']); + } + #auf weiter geklickt + if ($_REQUEST['next_x']) { + if (!$items['login']['value']) { + $items['login']['bgrd'] = '_error'; + $errors[] = "Login darf nicht leer sein!"; + } + if (!$items['nickname']['value']) { + $items['nickname']['bgrd'] = '_error'; + $errors[] = "Nickname darf nicht leer sein!"; + } + if (!$items['password']['value']) { + $items['password']['bgrd'] = '_error'; + $errors[] = "Password darf nicht leer sein!"; + } + if (!$items['pos']['value']) { + $items['pos']['bgrd'] = '_error'; + $errors[] = "Position leer oder ungültig!"; + } + if ($items['nickname']['value'] && getUserByNick($items['nickname']['value'])) { + $items['nickname']['bgrd'] = '_error'; + $errors[] = "User existiert bereits!"; + } + if ($items['login']['value'] && getUserByLogin($items['login']['value'])) { + $items['login']['bgrd'] = '_error'; + $errors[] = "Login existiert bereits!"; + } + if ($this->userdata['rights']['changegroup']) { + #check gid + $items['gid']['value'] = param_num("group",0,true); + if ($items['gid']['value']) { + $group = 0; + for ($i=0;$i < count($grouplist);$i++) { + if ($items['gid']['value'] == $grouplist[$i]['gid']) { + $group = &$grouplist[$i]; + $group['selected'] = "selected"; + break; + } + } + if (!$group) $this->_header("","Ungültige Gruppe, gid!"); + } + } else { + $items['gid']['value'] = 0; + } + #check galaid + if ($items['gala']['value'] && $rank < 3) { + $galaxy = 0; + for ($i=0;$i < count($galalist);$i++) { + if ($items['gala']['value'] == $galalist[$i]['gala']) { + $galaxy = &$galalist[$i]; + $galaxy['selected'] = "selected"; + break; + } + } + if (!$galaxy) $this->_header("","Ungültige Galaid!"); + } + if (!$errors){ + $chkuser = getUserByPos($items['gala']['value'],$items['pos']['value']); + if ($chkuser) { + $errors[] = "User existiert bereits, ".$chkuser['nick']." (".$chkuser['gala'].":".$chkuser['pos'].")"; + $items['pos']['bgrd'] = '_error'; + } + } + if (!$errors) { + #save step + $data['adduser'] = 1; + $_SESSION['steps'] = $data; + $id = addUser( + $items['nickname']['value'], + $items['login']['value'], + $items['password']['value'], + $items['gid']['value'], + $items['gala']['value'], + $items['pos']['value'], + $items['ircauth']['value'] + ); + addToLogfile("User ".$items['nickname']['value']." hinzugefügt","Admin",$this->userdata['uid']); + $this->_header("admin.php?action=adduser&id=$id&send"); + } + } + $this->template->assign("errors",$errors); + } else { + if ($rank == 1) { + $galalist = getGalaListbyAlly($allylist[0]['aid']); + if (!$galalist){ + $errors[] = "Die Allianz hat keine Galaxien!"; + $this->template->assign("errors",$errors); + $galalist[] = array("gala" => "keine"); + } + } elseif ($rank == 2) { + $galalist = getGalaListbyAlly($this->userdata['aid']); + if (!$galalist){ + $errors[] = "Die Allianz hat keine Galaxien!"; + $this->template->assign("errors",$errors); + $galalist[] = array("gala" => "keine"); + } + } elseif ($rank == 3) { + $this->template->assign("gala",$this->userdata['gala']); + } + } + if (!$items['ircauth']['value']) { + $items['ircauth']['bgrd'] = "_optional"; + } + $this->template->assign("items",$items); + $this->template->assign("galalist",$galalist); + $this->template->assign("allylist",$allylist); + $this->template->assign("grouplist",$grouplist); + $this->show('user_add_form',"Benutzer hinzufügen"); + } + /** + \brief User löschen + + Löscht einen User aus dem TC + */ + function User_delete() { + #check rights + $rank = $this->userdata['rights']['useredit']['rank']; + if (!$rank){ + #no permission + $this->_header("","no permission"); + } + $data = $_SESSION['steps']; + #information message, step 2 + if ($data['deleteuser']) { + #save step + unset($data['deleteuser']); + $_SESSION['steps'] = $data; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['title'] = "Benutzer löschen"; + $this->forms['information']['message'] = "Benutzer erfolgreich gelöscht"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Benutzer löschen"); + } + $id = param_num("id"); + if (!$id) $this->_header(); + $return = getUserByID($id); + if (!$return) $this->_header(); + #check rights + if (($rank > 1 && $this->userdata['aid'] != $return['aid']) || + ($rank > 2 && $this->userdata['gala'] != $return['gala'])){ + #no permission + $this->_header("","no permission"); + } + #deleteuser, send + if ($_REQUEST['send']) { + if ($_REQUEST['yes_x']) { + addToLogfile("User ".$return['nick']." gelöscht","Admin",$this->userdata['uid']); + deleteUser($return['uid']); + #save step + $data['deleteuser'] = 1; + $_SESSION['steps'] = $data; + $this->_header("admin.php?action=deleteuser&send"); + } else { + $this->_header(); + } + } else { + $this->forms['information']['url'] = "admin.php?id=".$return['uid']; + $this->forms['information']['action'] = "deleteuser"; + $this->forms['information']['title'] = "Benutzer löschen"; + $this->forms['information']['message'] = "Benutzer ".$return['nick']." (".$return['tag'].") löschen ?"; + if ($return['uid'] == $this->userdata['uid']) { + $this->forms['information']['message'] .= " +

WARNUNG!!
+ Sie sind im Begriff sich selbst zu löschen!
+ Sie können sich danach nicht mehr einloggen!
+ "; + } + $this->forms['information']['style'] = "red"; + $this->show('message_question', "Benutzer löschen"); + } + } + /** + \brief Gruppe löschen + + Löscht eine Gruppe. + */ + function Group_delete() { + if (!$this->userdata['rights']['groupedit']) { + #no permission + $this->_header("","no permission"); + } + $data = $_SESSION['steps']; + #information message, step 2 + if ($data['deletegroup']) { + #save step + unset($data['deletegroup']); + $_SESSION['steps'] = $data; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['title'] = "Gruppe löschen"; + $this->forms['information']['message'] = "Gruppe erfolgreich gelöscht"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Gruppe löschen"); + } + $id = param_num("id"); + if (!$id) $this->_header("","id fehlt"); + $return = getGroup($id); + if (!$return) $this->_header("","ungültige Gruppe"); + #deletegroup, send + if ($_REQUEST['send']) { + if ($_REQUEST['yes_x']) { + addToLogfile("Gruppe ".$return['name']." gelöscht","Admin",$this->userdata['uid']); + deletegroup($return['gid']); + #save step + $data['deletegroup'] = 1; + $_SESSION['steps'] = $data; + $this->_header("admin.php?action=deletegroup&send"); + } else { + $this->_header(); + } + } else { + $this->forms['information']['url'] = "admin.php?id=".$return['gid']; + $this->forms['information']['action'] = "deletegroup"; + $this->forms['information']['title'] = "Gruppe löschen"; + $this->forms['information']['message'] = "Gruppe ".$return['name']." löschen ?"; + if ($return['gid'] == $this->userdata['gid']) { + $this->forms['information']['message'] .= " +

WARNUNG!!
+ Sie sind im Begriff ihre eigene Gruppe zu löschen,
+ Sie könnten dadurch wichtige Rechte unwiederbringlich verlieren!
+ "; + } + $this->forms['information']['style'] = "red"; + $this->show('message_question', "Gruppe löschen"); + } + } + /** + \brief Gruppenrechte anzeigen + + Zeigt die Rechte der Gruppen in einer Übersicht an. + */ + function Group_rights() { + if (!$this->userdata['rights']['groupedit']) { + #no permission + $this->_header("","no permission"); + } + $this->template->assign("rank1",listGroupsbyRank(1)); + $this->template->assign("rank2",listGroupsbyRank(2)); + $this->template->assign("rank3",listGroupsbyRank(3)); + $this->show('group_rights',"Gruppenrechte"); + } + /** + * Ändert die rechte eienr Gruppe + */ + function Group_rights_edit() { + if (!$this->userdata['rights']['groupedit']) { + #no permission + $this->_header("","no permission"); + } + $rank = param_num("rank",1); + $gid = param_num("id"); + $grouplist = getGroupList(); + if (!$grouplist) $this->_header("","Keine Gruppen vorhanden"); + if ($gid) { + $hasfound = false; + for($i=0;$i < count($grouplist);$i++){ + if ($gid == $grouplist[$i]['gid']) { + $hasfound = true; + $grouplist[$i]['selected'] = "selected"; + break; + } + } + if (!$hasfound) $this->_header("","Ungültige gid"); + } else { + $grouplist[0]['selected'] = "selected"; + $gid = $grouplist[0]['gid']; + } + $rightslist = listRightsbyGroup($gid); + if (!$rightslist) $this->_header("","Keine Rechte vorhanden"); + #formular abgeschickt + if ($_POST{'send'} && $_POST['next_x']) { + for($i=0;$i < count($rightslist);$i++){ + $right = &$rightslist[$i]; + #nicht gesetzt und maxlevel überschritten + if ($rank > $right['maxrank'] && !$right['isset']) { + unset($rightslist[$i]['rid']); + continue; + } + if ($right['isset'] && $right['rank'] < $rank) { + $right['disabled'] = "disabled"; + $right['vererbt'] = "(vererbt)"; + if ($right['isset']) { + $right['isset'] = "checked"; + } else { + $right['notset'] = "checked"; + unset($right['isset']); + } + continue; + } + if ($_POST["r_".$right['rid']]) { + $right['isset'] = "checked"; + $ids[] = $right['rid']; + } else { + $right['notset'] = "checked"; + unset($right['isset']); + } + } + updateRights($gid,$rank,$ids); + } else { + for($i=0;$i < count($rightslist);$i++){ + $right = &$rightslist[$i]; + #nicht gesetzt und maxlevel überschritten + if ($rank > $right['maxrank'] && !$right['isset']) { + unset($rightslist[$i]['rid']); +# for($j=$i;$j < count($rightslist)-1;$j++){ +# $rightslist[$j]= $rightslist[$j+1]; +# } + continue; + } + if ($right['isset'] && $right['rank'] < $rank) { + $right['disabled'] = "disabled"; + $right['vererbt'] = "(vererbt)"; + } + if ($right['isset'] && $right['rank'] <= $rank) { + $right['isset'] = "checked"; + } else { + $right['notset'] = "checked"; + unset($right['isset']); + } + } + } + switch ($rank) { + case 1: $ebene = "(Global)"; + break; + case 2: $ebene = "(Allianzebene)"; + break; + case 3: $ebene = "(Galaxieebene)"; + break; + } +# for($i=0;$i < count($rightslist);$i++){ +# echo "rid: ".$rightslist[$i]['rid']."
"; +# echo "isset: ".$rightslist[$i]['isset']."
"; +# echo "rank: ".$rightslist[$i]['rank']."
"; +# echo "descr: ".$rightslist[$i]['descr']."
"; +# } + $this->template->assign("ebene",$ebene); + $this->template->assign("grouplist",$grouplist); + $this->template->assign("rightslist",$rightslist); + $this->template->assign("rank",$rank); + $this->template->assign("url","admin.php"); + $this->template->assign("action","editgrouprights"); + $this->show('group_editrights',"Gruppenrechte bearbeiten"); + } + /** + \brief Allianzen anzeigen + + Listet die Allianzen des TCs auf + */ + function Ally_list() { + #check rights + if (!$this->_checkUserRights(array("addally","editally","deleteally"))){ + #no permission + $this->_header("","no permission"); + } + $allylistfilter = $_SESSION['allylistfilter']; + $page = param_num("page",1); + $rows = 6; + if (($_REQUEST['sort'] && $_REQUEST['order']) || !$allylistfilter) { + $sort = trim($_REQUEST['sort']); + $order = trim($_REQUEST['order']); + if ($sort != 'name' && $sort != 'tag' && $sort != 'member') $sort = 'tag'; + if ($order != "asc" && $order != "desc") $order = "asc"; + $allylistfilter['sort'] = $sort; + $allylistfilter['order'] = $order; + $_SESSION['allylistfilter'] = $allylistfilter; + } + $this->forms['list'][$allylistfilter['sort']][$allylistfilter['order']] = '_active'; + $allylist = listAllys($allylistfilter,&$pages,&$page,$rows); + $this->forms['list']['pages'] = showPageBar($page,$pages,"admin.php?action=ally","page","menu"); + $this->template->assign("allylist",$allylist); + $this->show('ally_list',"Allianzen"); + } + /** + \brief Allianzinfos + + Zeigt Informationen zu einer Allianz an + */ + function Ally_details() { + #check rights + if (!$this->_checkUserRights(array("addally","editally","deleteally"))){ + #no permission + $this->_header("","no permission"); + } + $id = param_num("id"); + if (!$id) $this->_header("","Fehlende allyid!"); + $ally = getAlly($id); + if (!$ally) $this->_header("","Ungültige allyid!"); + $ally[id]= $id; + if ($ally['url']) $ally['url'] = formaturl($ally['url']); + #can edit + if ($this->userdata['rights']['editally']['rank'] == 1 || + ($this->userdata['rights']['editally']['rank'] == 2 && + $this->userdata['aid'] == $ally['aid'])) + { + $this->template->assign("editlink","admin.php?action=editally&id=$id"); + } + #can delete + if ($this->userdata['rights']['deleteally']['rank'] == 1 || + ($this->userdata['rights']['deleteally']['rank'] == 2 && + $this->userdata['aid'] == $ally['aid'])) + { + $this->template->assign("deletelink","admin.php?action=deleteally&id=$id"); + } + $this->template->assign("ally",$ally); + $this->show('ally_details',"Allianzdetails"); + } + /** + \brief Allianz hinzufügen + + Fügt eine Allianz hinzu + */ + function Ally_add() { + #check rgihts + if ($this->userdata['rights']['addally']['rank'] != 1) + { + #no permission + $this->_header("","no permission"); + } + $data = $_SESSION['steps']; + #information message, step 2 + if ($data['addally']) { + $id = param_num("id"); + if ($id) { + $return = getAlly($id); + } + if (!$return) $this->_header(); + #save step + unset($data['addally']); + $_SESSION['steps'] = $data; + $this->forms['information']['action'] = "allydetails"; + $this->forms['information']['url'] = "admin.php?action=allydetails&id=".$return['aid']."&force"; + $this->forms['information']['title'] = "Allianz hinzufügen"; + $this->forms['information']['message'] = "Allianz ".$return['name']." hinzugefügt"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Allianz hinzufügen"); + } + #formular send + if ($_REQUEST['send']) { + $name = param_str("name",true); + $tag = param_str("tag",true); + $irc = param_str("irc",true); + $url = param_str("url",true); + $descr = param_str("descr",true); + $errors = false; + #check if empty + if (!$name) { + $errors[] = "Name darf nicht leer sein!"; + $items['name']['class'] = '_error'; + } + if (!$tag) { + $errors[] = "Tag darf nicht leer sein!"; + $items['tag']['class'] = '_error'; + } + if (!$errors && getAllyByTag($tag)) { + $errors[] = "Allianz mit diesem Tag existiert bereits!"; + $items['tag']['class'] = '_error'; + } + if (!$errors) { + #save step + $data['addally'] = 1; + $_SESSION['steps'] = $data; + $id = addAlly($name,$tag,$descr,$url,$irc); + if ($id) { + addToLogfile("Allianz ".$name." hinzugefügt","Admin",$this->userdata['uid']); + $this->_header("admin.php?action=addally&id=".$id."&send"); + } + } else { + $items['descr']['value'] = $descr; + $items['tag']['value'] = $tag; + $items['name']['value'] = $name; + $items['irc']['value'] = $irc; + $items['url']['value'] = $url; + $this->template->assign("items",$items); + $this->template->assign("errors",$errors); + } + } + $this->show('ally_add',"Allianz hinzufügen"); + } + /** + \brief Allianz bearbeiten + + Ändert die Daten einer Allianz + */ + function Ally_edit() { + $page = param_num("page",1); + $data = $_SESSION['steps']; + $id = param_num("id"); + if ($id) { + $return = getAlly($id); + } + if (!$return) $this->_header("","Ungültige oder fehlende Allyid!"); + #check rgihts + if ($this->userdata['rights']['editally']['rank'] != 1 && + ($this->userdata['rights']['editally']['rank'] != 2 || + $this->userdata['aid'] != $id)) + { + #no permission + $this->_header("","no permission"); + } + #information message, step 2 + if ($data['editally']) { + #save step + unset($data['editally']); + $_SESSION['steps'] = $data; + $this->forms['information']['action'] = "allydetails"; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['title'] = "Allianz bearbeiten"; + $this->forms['information']['message'] = "Daten der Allianz ".$return['name']." geändert"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Allianz bearbeiten"); + } + #formular send + if ($_REQUEST['send']) { + $name = param_str("name",true); + $tag = param_str("tag",true); + $irc = param_str("irc",true); + $url = param_str("url",true); + $descr = param_str("descr",true); + $errors = false; + #check if empty + if (!$name) { + $errors[] = "Name darf nicht leer sein!"; + $items['name']['class'] = '_error'; + } + if (!$tag) { + $errors[] = "Tag darf nicht leer sein!"; + $items['tag']['class'] = '_error'; + } + if (!$errors && $tag != $return['tag'] && getAllyByTag($tag)) { + $errors[] = "Allianz mit diesem Tag existiert bereits!"; + $items['tag']['class'] = '_error'; + } + if (!$errors) { + #save step + $data['editally'] = 1; + $_SESSION['steps'] = $data; + updateAlly($id,$name,$tag,$descr,$url,$irc); + addToLogfile("Allianz ".$name." bearbeitet","Admin",$this->userdata['uid']); + $this->_header("admin.php?action=editally&id=".$id."&send"); + } else { + $items['descr']['value'] = $descr; + $items['tag']['value'] = $tag; + $items['name']['value'] = $name; + $items['irc']['value'] = $irc; + $items['url']['value'] = $url; + $this->template->assign("errors",$errors); + } + } else { + $items['descr']['value'] = $return['descr']; + $items['tag']['value'] = $return['tag']; + $items['name']['value'] = $return['name']; + $items['irc']['value'] = $return['irc']; + $items['url']['value'] = $return['url']; + } + $this->template->assign("id",$id); + $this->template->assign("items",$items); + $this->show('ally_edit',"Allianz bearbeiten"); + } + /** + \brief Galaxie hinzufügen + + Fügt eine Galaxie hinzu. + */ + function Galaxy_add() { + #check rights + $rank = $this->userdata['rights']['addgala']['rank']; + if ($rank != 1 && $rank != 2){ + #no permission + $this->_header("","no permission"); + } + $page = param_num("page",1); + $data = $_SESSION['steps']; + #information message, step 2 + if ($data['addgala']) { + $id = param_num("id"); + if ($id) { + $return = getGala($id); + } + if (!$return) $this->_header(); + #save step + unset($data['addgala']); + $_SESSION['steps'] = $data; + $this->forms['information']['action'] = "galadetails"; + $this->forms['information']['url'] = "admin.php?id=".$return['gala']."&force"; + $this->forms['information']['title'] = "Galaxie hinzufügen"; + $this->forms['information']['message'] = "Galaxie ".$return['gala']." (".$return['tag'].") hinzugefügt"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Galaxie hinzufügen"); + } + if ($rank == 1) { + #global + $allylist = getAllyList(); + } else { + #allianz + $this->template->assign("ally",$this->userdata['tag']); + } + $this->template->assign("rank",$rank); + #formular send + if ($_REQUEST['send']) { + $gala = param_num("gala"); + $errors = false; + #check if empty + if (!$gala) { + $errors[] = "Galaxie darf nicht leer sein!"; + $items['gala']['class'] = '_error'; + } + if (!$errors && getGala($gala)) { + $errors[] = "Galaxie existiert bereits!"; + $items['gala']['class'] = '_error'; + } + if ($rank == 1) { + $allyid = param_num("allyid",true); + if ($allyid){ + for($i=0;$i < count($allylist);$i++){ + if ($allylist[$i]['aid'] == $allyid) { + $ally = &$allylist[$i]; + $ally['selected'] = "selected"; + break; + } + } + } + if (!$ally) $this->_header("","Ungültige oder fehlende Allyid"); + } else { + $allyid = $this->userdata['aid']; + } + if (!$errors) { + #save step + $data['addgala'] = 1; + $_SESSION['steps'] = $data; + addGala($gala,$allyid); + addToLogfile("Galaxie ".$gala." hinzugefügt","Admin",$this->userdata['uid']); + $this->_header("admin.php?action=addgala&id=".$gala."&send"); + } else { + $items['gala']['value'] = $gala; + $this->template->assign("items",$items); + $this->template->assign("errors",$errors); + } + } + $this->template->assign("allylist",$allylist); + $this->show('gala_add',"Galaxie hinzufügen"); + } + /** + \brief Galaxien anzeigen + + Listet die Galaxien auf, nach Allianzen sortiert + je nach Rechten des Users. + */ + function Galaxy_list() { + #check rights + $rank = $this->_getMinRightRank(array("addgala","editgala","deletegala")); + if (!$rank){ + #no permission + $this->_header("","no permission"); + } + $galaxylistfilter = $_SESSION['galaxylistfilter']; + $page = param_num("page",1); + $rows = 12; + #allianzebene & galaxieebene + if ($rank > 1) { + $galaxylistfilter['ally'] = $this->userdata['aid']; + } + if (($_REQUEST['sort'] && $_REQUEST['order']) || !$galaxylistfilter) { + $sort = trim($_REQUEST['sort']); + $order = trim($_REQUEST['order']); + if ($sort != 'gala' && $sort != 'tag' && $sort != 'member') $sort = 'gala'; + if ($order != "asc" && $order != "desc") $order = "asc"; + $galaxylistfilter['sort'] = $sort; + $galaxylistfilter['order'] = $order; + $_SESSION['galaxylistfilter'] = $galaxylistfilter; + } + $this->forms['list'][$galaxylistfilter['sort']][$galaxylistfilter['order']] = '_active'; + $galaxylist = listGalaxys($galaxylistfilter,&$pages,&$page,$rows); + $this->forms['list']['pages'] = showPageBar($page,$pages,"admin.php?action=galaxy","page","menu"); + $this->template->assign("galaxylist",$galaxylist); + $this->show('gala_list',"Galaxien"); + } + /** + \brief Galaxieinformationen + + Zeigt Informationen zu einer Galaxie + */ + function Galaxy_details() { + #check rights + $rank = $this->_getMinRightRank(array("addgala","editgala","deletegala")); + if (!$rank){ + #no permission + $this->_header("","no permission"); + } + $id = param_num("id"); + if (!$id) $this->_header("","Fehlende galaid!"); + $galaxy = getGala($id); + if (!$galaxy) $this->_header("","Ungültige galaid!"); + #allianz & galaxieebene + if ($rank > 1 && $galaxy['aid'] != $this->userdata['aid']) { + #no permission + $this->_header("","no permission"); + } + if ($this->userdata['rights']['editgala']['rank'] == 1 || + ($this->userdata['rights']['editgala']['rank'] == 2 && + $this->userdata['aid'] == $galaxy['aid']) || + ($this->userdata['rights']['editgala']['rank'] == 3 && + $this->userdata['gala'] == $galaxy['gala'])) + { + $this->template->assign("editlink","admin.php?action=editgala&id=$id"); + } + $this->template->assign("searchlink","admin.php"); + if ($this->userdata['rights']['deletegala']['rank'] == 1 || + ($this->userdata['rights']['deletegala']['rank'] == 2 && + $this->userdata['aid'] == $galaxy['aid'])) + { + $this->template->assign("deletelink","admin.php?action=deletegala&id=$id"); + } + $this->template->assign("galaxy",$galaxy); + $this->show('gala_details',"Galaxiedetails"); + } + /** + \brief Galaxie hinzugügen + + Fügt eine Galaxie hinzu + */ + function Galaxy_edit() { + $page = param_num("page",1); + $data = $_SESSION['steps']; + $id = param_num("id"); + if ($id) { + $return = getGala($id); + } + if (!$return) $this->_header("","ungültige id"); + #check rights + $rank = $this->userdata['rights']['editgala']['rank']; + if (!$rank || + ($rank > 1 && $return['aid'] != $this->userdata['aid']) || + ($rank > 2 && $return['gala'] != $this->userdata['gala'])){ + #no permission + $this->_header("","no permission"); + } + #information message, step 2 + if ($data['editgala']) { + #save step + unset($data['editgala']); + $_SESSION['steps'] = $data; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['title'] = "Galaxie bearbeiten"; + $this->forms['information']['message'] = "Galaxie ".$return['gala']." bearbeitet"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Galaxie bearbeitet"); + } + if ($rank > 1) { + #allianz + $this->template->assign("ally",$this->userdata['tag']); + } else { + $allylist = getAllyList(); + } + $this->template->assign("rank",$rank); + #formular send + if ($_REQUEST['send']) { + $gala = param_num("gala"); + $errors = false; + #check if empty + if (!$gala) { + $errors[] = "Galaxie darf nicht leer sein!"; + $items['gala']['class'] = '_error'; + } + if (!$errors && $return['gala'] != $gala && getGala($gala)) { + $errors[] = "Galaxie existiert bereits!"; + $items['gala']['class'] = '_error'; + } + if ($rank == 1) { + $allyid = param_num("allyid",true); + if ($allyid){ + for($i=0;$i < count($allylist);$i++){ + if ($allylist[$i]['aid'] == $allyid) { + $ally = &$allylist[$i]; + $ally['selected'] = "selected"; + break; + } + } + } + if (!$ally) $this->_header("","Ungültige oder fehlende Allyid"); + } else { + $allyid = $this->userdata['aid']; + } + if (!$errors) { + #save step + $data['editgala'] = 1; + $_SESSION['steps'] = $data; + updateGala($id,$gala,$allyid); + addToLogfile("Galaxie ".$gala." bearbeitet","Admin",$this->userdata['uid']); + $this->_header("admin.php?action=editgala&id=".$gala."&send"); + } else { + $items['gala']['value'] = $gala; + $this->template->assign("errors",$errors); + } + } else { + $items['gala']['value'] = $return['gala']; + for($i=0;$i < count($allylist);$i++){ + if ($allylist[$i]['aid'] == $return['aid']) { + $ally = &$allylist[$i]; + $ally['selected'] = "selected"; + break; + } + } + } + $this->template->assign("items",$items); + $this->template->assign("id",$id); + $this->template->assign("allylist",$allylist); + $this->show('gala_edit',"Galaxie bearbeiten"); + } + /** + \brief Allianz löschen + + Löscht eine Allianz mit allen Mitgliedern und Galaxien + */ + function Ally_delete() { + #check rgihts + if ($this->userdata['rights']['deleteally']['rank'] != 1) + { + #no permission + $this->_header("","no permission"); + } + $data = $_SESSION['steps']; + #information message, step 2 + if ($data['deleteally']) { + #save step + unset($data['deleteally']); + $_SESSION['steps'] = $data; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['title'] = "Allianz löschen"; + $this->forms['information']['message'] = "Allianz erfolgreich gelöscht"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Allianz löschen"); + } + $id = param_num("id"); + if (!$id) $this->_header(); + $return = getAlly($id); + if (!$return) $this->_header(); + #deleteally, send + if ($_REQUEST['send']) { + if ($_REQUEST['yes_x']) { + addToLogfile("Allianz ".$return['name']." gelöscht","Admin",$this->userdata['uid']); + deleteAlly($return['aid']); + #save step + $data['deleteally'] = 1; + $_SESSION['steps'] = $data; + $this->_header("admin.php?action=deleteally&send"); + } else { + $this->_header(); + } + } else { + $this->forms['information']['url'] = "admin.php?id=".$return['aid']; + $this->forms['information']['action'] = "deleteally"; + $this->forms['information']['title'] = "Allianz löschen"; + $this->forms['information']['message'] = "Allianz ".$return['name']." (".$return['tag'].") löschen ?"; + if ($return['galas']) { + if ($return['galas'] == 1) { + $this->forms['information']['message'] .= " +

".$return['galas']." Galaxie wird mitgelöscht."; + } else { + $this->forms['information']['message'] .= " +

".$return['galas']." Galaxien werden mitgelöscht. + "; + } + if ($return['member']) { + if ($return['member'] == 1) { + $s = "wird"; + } else { + $s = "werden"; + } + $this->forms['information']['message'] .= " +
Es $s ".$return['member']." User gelöscht ! + "; + } + } + if ($return['aid'] == $this->userdata['aid']) { + $this->forms['information']['message'] .= " +

WARNUNG!!
+ Sie sind im Begriff ihre eigene Allianz (und damit sich selbst) zu löschen,
+ Sie können sich danach nicht mehr einloggen!
+ "; + } + $this->forms['information']['style'] = "red"; + $this->show('message_question', "Allianz löschen"); + } + } + /** + \brief Galaxie löschen + + Löscht eine Galaxie + */ + function Galaxy_delete() { + $data = $_SESSION['steps']; + #information message, step 2 + if ($data['deletegala']) { + #save step + unset($data['deletegala']); + $_SESSION['steps'] = $data; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['title'] = "Galaxie löschen"; + $this->forms['information']['message'] = "Galaxie erfolgreich gelöscht"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Galaxie löschen"); + } + $id = param_num("id"); + if (!$id) $this->_header(); + $return = getGala($id); + if (!$return) $this->_header(); + #check rights + $rank = $this->userdata['rights']['deletegala']['rank']; + if (!$rank || ($rank > 2) || + ($rank == 2 && $return['aid'] != $this->userdata['aid'])){ + #no permission + $this->_header("","no permission"); + } + #deletegala, send + if ($_REQUEST['send']) { + if ($_REQUEST['yes_x']) { + addToLogfile("Galaxie ".$return['gala']." gelöscht","Admin",$this->userdata['uid']); + deletegalaxy($return['gala']); + #save step + $data['deletegala'] = 1; + $_SESSION['steps'] = $data; + $this->_header("admin.php?action=deletegala&send"); + } else { + $this->_header(); + } + } else { + $this->forms['information']['url'] = "admin.php?id=".$return['gala']; + $this->forms['information']['action'] = "deletegala"; + $this->forms['information']['title'] = "Galaxie löschen"; + $this->forms['information']['message'] = "Galaxie ".$return['gala']." (".$return['tag'].") löschen ?"; + if ($return['member']) { + if ($return['member'] == 1) { + $s = "wird"; + } else { + $s = "werden"; + } + $this->forms['information']['message'] .= " +

Es $s ".$return['member']." User gelöscht ! + "; + } + if ($return['gala'] == $this->userdata['gala']) { + $this->forms['information']['message'] .= " +

WARNUNG!!
+ Sie sind im Begriff ihre eigene Galaxie (und damit sich selbst) zu löschen,
+ Sie können sich danach nicht mehr einloggen!
+ "; + } + $this->forms['information']['style'] = "red"; + $this->show('message_question', "Galaxie löschen"); + } + } + /** + \brief IRCBots auflisten + + Listet die IRCBots auf + */ + function Bot_list() + { + if (!$this->userdata['rights']['bots']) { + #no permission + $this->_header("","no permission"); + } + $list = bot_list(); + for($i=0;$i < count($list);$i++){ + $list[$i]['firstauth'] = date("H:i d.m",$list[$i]['firstauth']); + if($list[$i]['lastauth']) $list[$i]['lastauth'] = date("H:i d.m",$list[$i]['lastauth']); + } + $this->template->assign('list',$list); + $this->show('bot_list','IRC Bots'); + } + + /** + \brief IRC bot hinzufügen + + Fügt einen IRC Bot hinzu + */ + function Bot_add() { + if (!$this->userdata['rights']['bots']) { + #no permission + $this->_header("","no permission"); + } + $data = $_SESSION['steps']; + #information message, step 2 + if ($data['addbot']) { + #save step + unset($data['addbot']); + $_SESSION['steps'] = $data; + $id = param_num("id"); + if (!$id) $this->_header(); + $bot = bot_get($id); + if (!$bot) $this->_header(); + $this->forms['information']['url'] = "admin.php?action=bots&force"; + $this->forms['information']['title'] = "IRC Bot hinzufügen"; + $this->forms['information']['message'] = "Bot '".$bot['name']."' hinzugefügt"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "IRC Bot hinzufügen"); + } + if ($_REQUEST['send']) { + $name = param_str("name",true); + $login = param_str("login",true); + $password = param_str("password",true); + $soapurl = param_str("soapurl",true); + $host = param_str("host",true); + $errors = false; + #check if empty + if (!$name) { + $errors[] = "Name darf nicht leer sein!"; + $items['name']['class'] = '_error'; + } + if (!$login) { + $errors[] = "Login darf nicht leer sein!"; + $items['login']['class'] = '_error'; + } + if (!$password) { + $errors[] = "Passwort darf nicht leer sein!"; + $items['password']['class'] = '_error'; + } + if (!$soapurl){ + $errors[] = "Es muss eine Adresse für den SOAP Server angegeben werden!"; + $items['soapurl']['class'] = '_error'; + } + if (!$host){ + $items['host']['class'] = '_optional'; + } + if (!$errors && bot_get_bylogin($login,$password)){ + $errors[] = "Diese Login - Passwort Paarung ist bereits vergeben!"; + $items['login']['class'] = '_error'; + $items['password']['class'] = '_error'; + } + if (!$errors) { + #save step + $data['addbot'] = 1; + $_SESSION['steps'] = $data; + $id = bot_add($name,$login,$password,$soapurl,$host); + addToLogfile("IRC Bot ".$name." hinzugefügt","Bots",$this->userdata['uid']); + $this->_header("admin.php?action=addbot&id=$id&send"); + } else { + $items['login']['value'] = $login; + $items['password']['value'] = $password; + $items['name']['value'] = $name; + $items['host']['value'] = $host; + $items['soapurl']['value'] = $soapurl; + $this->template->assign("errors",$errors); + } + } else { + $items['host']['class'] = '_optional'; + } + $this->template->assign("items",$items); + $this->show('bot_add',"IRC Bot hinzufügen"); + } + /** + \brief IRC bot bearbeiten + + Ändert die Daten von einem IRC Bot + */ + function Bot_edit() { + if (!$this->userdata['rights']['bots']) { + #no permission + $this->_header("","no permission"); + } + $id = param_num("id"); + if (!$id) $this->_header(); + $bot = bot_get($id); + if (!$bot) $this->_header(); + $data = $_SESSION['steps']; + #information message, step 2 + if ($data['editbot']) { + #save step + unset($data['editbot']); + $_SESSION['steps'] = $data; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['title'] = "IRC Bot bearbeiten"; + $this->forms['information']['message'] = "Bot '".$bot['name']."' bearbeitet"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "IRC Bot bearbeiten"); + } + if ($_REQUEST['send']) { + $name = param_str("name",true); + $login = param_str("login",true); + $password = param_str("password",true); + $soapurl = param_str("soapurl",true); + $host = param_str("host",true); + $errors = false; + #check if empty + if (!$name) { + $errors[] = "Name darf nicht leer sein!"; + $items['name']['class'] = '_error'; + } + if (!$login) { + $errors[] = "Login darf nicht leer sein!"; + $items['login']['class'] = '_error'; + } + if (!$password) { + $errors[] = "Passwort darf nicht leer sein!"; + $items['password']['class'] = '_error'; + } + if (!$soapurl){ + $errors[] = "Es muss eine Adresse für den SOAP Server angegeben werden!"; + $items['soapurl']['class'] = '_error'; + } + if (!$host){ + $items['host']['class'] = '_optional'; + } + if (!$errors && ($login != $bot['login'] || $password != $bot['password']) && bot_get_bylogin($login,$password)){ + $errors[] = "Diese Login - Passwort Paarung ist bereits vergeben!"; + $items['login']['class'] = '_error'; + $items['password']['class'] = '_error'; + } + if (!$errors) { + #save step + $data['editbot'] = 1; + $_SESSION['steps'] = $data; + bot_update($id,$name,$login,$password,$soapurl,$host); + addToLogfile("IRC Bot ".$bot['name']." bearbeitet","Bots",$this->userdata['uid']); + $this->_header("admin.php?action=editbot&id=$id&send"); + } else { + $items['login']['value'] = $login; + $items['password']['value'] = $password; + $items['name']['value'] = $name; + $items['host']['value'] = $host; + $items['soapurl']['value'] = $soapurl; + $this->template->assign("errors",$errors); + } + } else { + $items['login']['value'] = $bot['login']; + $items['password']['value'] = $bot['password']; + $items['name']['value'] = $bot['name']; + $items['host']['value'] = $bot['host']; + $items['soapurl']['value'] = $bot['soapurl']; + if (!$bot['host']) $items['host']['class'] = '_optional'; + } + $this->template->assign("id",$id); + $this->template->assign("items",$items); + $this->show('bot_edit',"IRC Bot bearbeiten"); + } + /** + \brief IRC bot löschen + + Löscht einen IRC Bot + */ + function Bot_delete() { + if (!$this->userdata['rights']['bots']) { + #no permission + $this->_header("","no permission"); + } + $data = $_SESSION['steps']; + #information message, step 2 + if ($data['deletebot']) { + #save step + unset($data['deletebot']); + $_SESSION['steps'] = $data; + $name = param_str("name"); + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['title'] = "IRC Bot löschen"; + $this->forms['information']['message'] = "Bot '$name' erfolgreich gelöscht"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "IRC Bot löschen"); + } + $id = param_num("id"); + if (!$id) $this->_header(); + $bot = bot_get($id); + if (!$bot) $this->_header(); + #deletenews, send + if ($_REQUEST['send']) { + if ($_REQUEST['yes_x']) { + addToLogfile("Bot ".$bot['name']." gelöscht","Bots", + $this->userdata['uid']); + bot_delete($id); + #save step + $data['deletebot'] = 1; + $_SESSION['steps'] = $data; + $this->_header("admin.php?action=deletebot&name=".$bot['name']."&send"); + } else { + $this->_header(); + } + } else { + $this->forms['information']['url'] = "admin.php?id=".$bot['botid']; + $this->forms['information']['action'] = "deletebot"; + $this->forms['information']['title'] = "IRC Bot löschen"; + $this->forms['information']['message'] = "Bot '".$bot['name']."' löschen ?"; + $this->forms['information']['style'] = "red"; + $this->show('message_question', "IRC Bot löschen"); + } + } +} +?> \ No newline at end of file diff --git a/src/functions/attplan.class.php b/src/functions/attplan.class.php new file mode 100644 index 0000000..455c482 --- /dev/null +++ b/src/functions/attplan.class.php @@ -0,0 +1,728 @@ +action]) { + eval("\$this->".$functions[$this->action].";"); + } + #default + $this->Attack_list(); + } + + # + # Attacklist + # + function Attack_list() { + $list = attack_list(); + foreach ($list as $item) { + if(!$item['isopen']) { + $item['scan_time'] = "Scans ab ".date("H:i",$item['access_time'])." Uhr ".date("d.m.Y",$item['access_time']); + } + + if($item['isopen'] || + $item['owner'] == $this->userdata['uid'] || + $this->_checkUserRights("attorga")) + { + $item['showlink'] = true; + } + if($item['isopen'] || + !$item['hidden'] || + $item['owner'] == $this->userdata['uid'] || + $this->_checkUserRights("attorga")) + { + if(!$items['list']) $items['list'] = array(); + $items['list'][] = $item; + } + } + $this->template->assign("items",$items); + $this->show("attplan_list","Attplaner"); + } + + function Attack_targets_add() { + $attid = param_num("id"); + if(!$attid) $this->_header(); + $attplan = attack_get($attid); + + //rightcheck + if($this->userdata['uid'] != $attplan['owner'] && + !$this->_checkUserRights("attorga")) + $this->_header(); + + $steps = $_SESSION['steps']; + if($steps['addtargets']) { + unset($_SESSION['steps']['addtargets']); + $sids = trim($_REQUEST['sids']); + if($sids){ + $sids = split(",",urldecode($sids)); + if(count($sids)){ + $message[] = "Folgende Ziele wurden hinzugefügt:
"; + $scans = getScansBySid($sids); + foreach($scans as $scan){ + $message[] = "(".$scan['gala'].":".$scan['pos'].")"; + } + $message[] = "
fehlende Ziele sind möglicherweise in diesem oder anderen Plänen schon vorhanden"; + } + } else { + $message[] = "Alle Ziele sind bereits in diesem oder anderen Attplänen vorhanden"; + } + $this->forms['information']['action'] =""; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['title'] = "Ziele hinzufügen"; + $this->forms['information']['message'] = join("
",$message); + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Ziele hinzufügen"); + } + + $form = new formContainer(); + $form->add(new formInput("galaxy_1","Galaxie","numeric",true,5)); + $form->add(new formInput("galaxy_2","Galaxie","numeric",true,5)); + $form->add(new formInput("galaxy_3","Galaxie","numeric",true,5)); + $form->add(new formInput("start_2","Start","numeric",true,5)); + $form->add(new formInput("end_2","Ende","numeric",true,5)); + $form->add(new formInput("pos_3","Position","numeric",true,5)); + $form->add(new formRadio("addtyp","Auswahltyp","numeric",array(1,2,3),3)); + + if($_POST['send']) { + $form->submit("addtyp"); + switch($form->get("addtyp")) { + case 1 : + $form->submit(array("galaxy_1")); + if(!$form->hasErrors()) { + $galaxy = $form->get("galaxy_1"); + $addtarget = array(1,2,3,4,5,6,7,8,9,10,11,12); + } + break; + case 2 : + $form->submit(array("galaxy_2","start_2","end_2")); + if(!$form->hasErrors() && $form->get("start_2") > $form->get("end_2")) { + $form->addError("die Startposition sollte niedriger sein als das Ende"); + $form->setError(array("start_2","end_2")); + } + if(!$form->hasErrors()) { + $galaxy = $form->get("galaxy_2"); + $start = $form->get("start_2"); + $end = $form->get("end_2"); + for($i=$start;$i <= $end;$i++) { + $addtarget[] = $i; + } + } + break; + default : + $form->submit(array("galaxy_3","pos_3")); + if(!$form->hasErrors()) { + $galaxy = $form->get("galaxy_3"); + $addtarget[] = $form->get("pos_3"); + } + break; + } + if(!$form->hasErrors()) { + $sid_list = targets_add($attid,$galaxy,$addtarget); + $steps['addtargets'] = 1; + $_SESSION['steps'] = $steps; + if(count($sid_list)){ + $sids = urlencode(join(",",$sid_list)); + } + $this->_header("attplan.php?action=addtargets&id=$attid&sids=$sids&send"); + } + } else { + $form->select("addtyp",1); + } + + $form->registerVars(&$this->template); + + $this->template->assign("attplan",$attplan); + + $this->show("attplan_targets_add","Ziele hinzufügen"); + } + + function Attack_targets() { + $attid = param_num("id"); + $page = param_num("page",1); + if(!$attid) $this->_header(); + $attplan = attack_get($attid); + + //rightcheck + if($this->userdata['uid'] != $attplan['owner'] && + !$this->_checkUserRights("attorga")) + $this->_header(); + + + $gala_list = attack_get_galalist($attid,&$pages,$page); + $pagebar = showPageBar($page,$pages,"attplan.php?action=targets&id=$attid","page","menu"); + + if(count($gala_list) < 5) { + $spacer['colspan'] = 5 - count($gala_list); + $spacer['width'] = $spacer['colspan']*20; + $this->template->assign("spacer",$spacer); + } + + $list = target_list(array("attid"=>$attid,"gala"=>$gala_list)); + $count = count($list); + $gala = ""; + for($i=0;$i<$count;$i++) { + if($list[$i]['gala'] != $gala){ + $gala = $list[$i]['gala']; + } + $targets[$gala][] = $list[$i]; + } + + $this->template->assign("pagebar",$pagebar); + $this->template->assign("targets",$targets); + $this->template->assign("attplan",$attplan); + $this->show("attplan_targets","Ziele festlegen"); + } + + function Attack_targets_delete() { + $attid = param_num("id"); + if(!$attid) $this->_header(); + $attplan = attack_get($attid); + + //rightcheck + if($this->userdata['uid'] != $attplan['owner'] && + !$this->_checkUserRights("attorga")) + $this->_header(); + + if($_SESSION['steps']['deletetargets']) { + unset($_SESSION['steps']['deletetargets']); + $this->forms['information']['action'] =""; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['title'] = "Ziele löschen"; + $this->forms['information']['message'] = "Angriffsziele wurden gelöscht!"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Ziele löschen"); + } + if ($_POST['send']) { + if ($_REQUEST['yes_x']) { + $sids = $_REQUEST['sids']; + if(empty($sids)) $this->_header(); + $sids = split(",",urldecode($sids)); + if(!count($sids)) $this->_header(); + targets_delete_bysid($sids); + #save step + $_SESSION['steps']['deletetargets'] = 1; + $this->_header("attplan.php?action=deletetargets&id=$attid&send"); + } else { + $this->_header(); + } + } else { + $sids = $_REQUEST['sids']; + if(empty($sids)) $this->_header(); + if(!is_array($sids)) { + $sids = split(",",urldecode($sids)); + } + if(!count($sids)) $this->_header(); + $scans = getScansBySid($sids); + foreach($scans as $scan){ + if($gala != $scan['gala']) { + if($gala) $message[$gala] = join(", ",$message[$gala]); + $gala = $scan['gala']; + } + $message[$gala][] = "(".$scan['gala'].":".$scan['pos'].") ".$scan['nick']; + } + if($gala) $message[$gala] = join(", ",$message[$gala]); + $this->forms['information']['url'] = "attplan.php?id=$attid&sids=".urlencode(join(",",$sids)); + $this->forms['information']['action'] = "deletetargets"; + $this->forms['information']['title'] = "Angriffsziele löschen"; + $this->forms['information']['message'] = " + ".$attplan{'title'}."

+ Folgende Ziele werden gelöscht:
".join("
",$message); + $this->forms['information']['style'] = "red"; + $this->show('message_question', "Angriffsziele löschen"); + } + } + + function Attack_atter_deleteall() { + $attid = param_num("id"); + if(!$attid) $this->_header(); + $attplan = attack_get($attid); + + $steps = $_SESSION['steps']; + + if($steps['deleteallatter']) { + unset($steps['deleteallatter']); + $_SESSION['steps'] = $steps; + $this->forms['information']['action'] =""; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['title'] = "alle Angreifer löschen"; + $this->forms['information']['message'] = "Angreifer wurden gelöscht!"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "alle Angreifer löschen"); + } + if ($_POST['send']) { + if ($_REQUEST['yes_x']) { + $sids = split(",",urldecode($_REQUEST['sids'])); + if(!count($sids)) $this->_header(); + atter_delete_bysid($attid,$sids); + #save step + $steps['deleteallatter'] = 1; + $_SESSION['steps'] = $steps; + $this->_header("attplan.php?action=deleteallatter&id=$attid&send"); + } else { + $this->_header(); + } + } else { + $sids = $_REQUEST['sids']; + if(empty($sids)) $this->_header(); + if(!is_array($sids)) { + $sids = split(",",urldecode($sids)); + } + if(!count($sids)) $this->_header(); + $scans = getScansBySid($sids); + foreach($scans as $scan){ + if($gala != $scan['gala']) { + if($gala) $message[$gala] = join(", ",$message[$gala]); + $gala = $scan['gala']; + } + $message[$gala][] = "(".$scan['gala'].":".$scan['pos'].") ".$scan['nick']; + } + if($gala) $message[$gala] = join(", ",$message[$gala]); + $this->forms['information']['url'] = "attplan.php?id=$attid&sids=".urlencode(join(",",$sids)); + $this->forms['information']['action'] = "deleteallatter"; + $this->forms['information']['title'] = "alle Angreifer löschen"; + $this->forms['information']['message'] = " + ".$attplan{'title'}."

+ zu folgenden Zielen werden die Angreifer gelöscht:
".join("
",$message); + $this->forms['information']['style'] = "red"; + $this->show('message_question', "alle Angreifer löschen"); + } + } + + function Attack_targets_close() { + $attid = param_num("id"); + if(!$attid) $this->_header(); + $attplan = attack_get($attid); + + //rightcheck + if($this->userdata['uid'] != $attplan['owner'] && + !$this->_checkUserRights("attorga")) + $this->_header(); + + + $steps = $_SESSION['steps']; + + if($steps['closetargets']) { + unset($steps['closetargets']); + $_SESSION['steps'] = $steps; + $this->forms['information']['action'] =""; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['title'] = "Ziele schliessen"; + $this->forms['information']['message'] = "Angriffsziele wurden als geschlossen markiert, es können sich keine weiteren Angreifer eintragen!"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Ziele schliessen"); + } + if ($_POST['send']) { + if ($_REQUEST['yes_x']) { + $sids = $_REQUEST['sids']; + if(empty($sids)) $this->_header(); + $sids = split(",",urldecode($sids)); + if(!count($sids)) $this->_header(); + targets_close($sids); + #save step + $steps['closetargets'] = 1; + $_SESSION['steps'] = $steps; + $this->_header("attplan.php?action=closetargets&id=$attid&send"); + } else { + $this->_header(); + } + } else { + $sids = $_REQUEST['sids']; + if(empty($sids)) $this->_header(); + if(!is_array($sids)) { + $sids = split(",",urldecode($sids)); + } + if(!count($sids)) $this->_header(); + $scans = getScansBySid($sids); + foreach($scans as $scan){ + if($gala != $scan['gala']) { + if($gala) $message[$gala] = join(", ",$message[$gala]); + $gala = $scan['gala']; + } + $message[$gala][] = "(".$scan['gala'].":".$scan['pos'].") ".$scan['nick']; + } + if($gala) $message[$gala] = join(", ",$message[$gala]); + $this->forms['information']['url'] = "attplan.php?id=$attid&sids=".urlencode(join(",",$sids)); + $this->forms['information']['action'] = "closetargets"; + $this->forms['information']['title'] = "Angriffsziele schliessen"; + $this->forms['information']['message'] = " + ".$attplan{'title'}."

+ Folgende Ziele werden als geschlossen markiert:
".join("
",$message); + $this->forms['information']['style'] = "red"; + $this->show('message_question', "Angriffsziele schliessen"); + } + } + + function Attack_targets_open() { + $attid = param_num("id"); + if(!$attid) $this->_header(); + $attplan = attack_get($attid); + + //rightcheck + if($this->userdata['uid'] != $attplan['owner'] && + !$this->_checkUserRights("attorga")) + $this->_header(); + + $steps = $_SESSION['steps']; + + if($steps['opentargets']) { + unset($steps['opentargets']); + $_SESSION['steps'] = $steps; + $this->forms['information']['action'] =""; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['title'] = "Ziele öffnen"; + $this->forms['information']['message'] = "Angriffsziele wurden als offen markiert, es können sich weitere Angreifer eintragen!"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Ziele öffnen"); + } + if ($_POST['send']) { + if ($_REQUEST['yes_x']) { + $sids = $_REQUEST['sids']; + if(empty($sids)) $this->_header(); + $sids = split(",",urldecode($sids)); + if(!count($sids)) $this->_header(); + targets_open($sids); + #save step + $steps['opentargets'] = 1; + $_SESSION['steps'] = $steps; + $this->_header("attplan.php?action=opentargets&id=$attid&send"); + } else { + $this->_header(); + } + } else { + $sids = $_REQUEST['sids']; + if(empty($sids)) $this->_header(); + if(!is_array($sids)) { + $sids = split(",",urldecode($sids)); + } + if(!count($sids)) $this->_header(); + $scans = getScansBySid($sids); + foreach($scans as $scan){ + if($gala != $scan['gala']) { + if($gala) $message[$gala] = join(", ",$message[$gala]); + $gala = $scan['gala']; + } + $message[$gala][] = "(".$scan['gala'].":".$scan['pos'].") ".$scan['nick']; + } + if($gala) $message[$gala] = join(", ",$message[$gala]); + $this->forms['information']['url'] = "attplan.php?id=$attid&sids=".urlencode(join(",",$sids)); + $this->forms['information']['action'] = "opentargets"; + $this->forms['information']['title'] = "Angriffsziele öffnen"; + $this->forms['information']['message'] = " + ".$attplan{'title'}."

+ Folgende Ziele werden für weitere Angreifer geöffnet:
".join("
",$message); + $this->forms['information']['style'] = "red"; + $this->show('message_question', "Angriffsziele öffnen"); + } + } + + function Attack_mytargets() { + $attplan['content'] = $this->template->fetch("attplan_content_mytargets.html"); + $this->template->assign("attplan",$attplan); + $this->show("attplan_view","Angriffsplan"); + } + + function Attack_tactic() { + $attplan['content'] = $this->template->fetch("attplan_content_tactic.html"); + $this->template->assign("attplan",$attplan); + $this->show("attplan_view","Angriffsplan"); + } + + function Attack_search() { + $attplan['content'] = $this->template->fetch("attplan_content_search.html"); + $this->template->assign("attplan",$attplan); + $this->show("attplan_view","Angriffsplan"); + } + + /** + * Scanansicht von einem Att + **/ + function Attack_view() { + if(!($attid = param_num("id")) || !($attplan = attack_get($attid))) $this->_header(); + $form = new formContainer(); + + $attplan['isadmin'] = $this->userdata['uid'] == $attplan['owner'] || + $this->_checkUserRights("attorga"); + + if(!$attplan['isopen'] && !$attplan['isadmin']) $this->_header(); + + $galalist = attack_gala_list($attid); + // ziele vorhanden ? + if($galalist) { + $list = array(); + foreach ($galalist as $item) { + $list[] = array("value" => $item['gala'],"title" => $item['gala']); + } + $form->add(new formSelectBox("gala","Galaxie","numeric",$list,false)); + + if($_POST['send'] && $_POST['subaction'] == "changegala") { + $form->submit(); + if(!$form->hasErrors()) $_SESSION['attplanfilter'][$attid]['gala'] = $form->get("gala"); + $gala = $form->get("gala"); + } else { + if($_SESSION['attplanfilter'][$attid]['gala']) { + $form->select("gala",$_SESSION['attplanfilter'][$attid]['gala']); + $gala = $_SESSION['attplanfilter'][$attid]['gala']; + } else { + $gala = $galalist[0]['gala']; + } + } + + $sids = target_list(array("gala" => $gala),"sid"); + $scanlist = listScans(array("sids" => $sids,"order"=>"asc","sort"=>"koords","hassektor" => true,"showattackscans" => true),&$pages,1,15); + + for ($i=0;$iuserdata['uid'] == $scanlist[$i]['uid'] || $this->_checkUserRights("attorga")) { + $scanlist[$i]['candelete'] = true; + } + if($this->userdata['uid'] == $scanlist[$i]['uid']) { + $scanlist[$i]['reserveclass'] = "green"; + } else { + $scanlist[$i]['reserveclass'] = "red"; + } + } else { + $scanlist[$i]['canreserve'] = true; + } + $scanlist[$i] = scan_format($scanlist[$i]); + } + + $this->template->assign("scanlist",$scanlist); + $this->template->assign("hastargets",true); + $this->template->assign("selectedgala",$gala); + } + + + $form->registerVars($this->template); + $this->template->assign("attplan",$attplan); + $this->template->assign("type","ziele"); + $this->show("attplan_view","Angriffsplan"); + } + + function Target_reserve() { + if (!($sid = param_num("id"))) $this->_header(); + + $reservation = getScanById($sid,true); + // gibts den att ? + if(!$reservation['attid'] || $reservation['closed']) $this->_header(); + // is noch offen ? + if(!$reservation['isopen'] && + !$this->_checkUserRights('attorga') + && $this->userdata['uid'] != $reservation['owner'] + ) $this->_header(); + if ($reservation['uid']) { + if ($reservation['uid'] == $this->userdata['uid']) { + $this->show_message("Reservierung","Ziel bereits von DIR reserviert",$this->backtracking->backlink(),"red",array("send" => 1)); + } else { + $this->show_message("Reservierung","Ziel bereits von jmd. reserviert",$this->backtracking->backlink(),"red",array("send" => 1)); + } + } + target_reserve($sid, $this->userdata['uid']); + $this->_header(); + } + + function Target_unreserve() { + if (!($sid = param_num("id"))) $this->_header(); + + $reservation = getScanById($sid,true); + // gibts den att ? + if(!$reservation['attid'] || !$reservation['uid'] || $reservation['closed']) $this->_header(); + //att is offen für reservierungen ? + if(!$reservation['isopen'] && + !$this->_checkUserRights('attorga') + && $this->userdata['uid'] != $reservation['owner'] + ) $this->_header(); + if ($reservation['uid'] == $this->userdata['uid'] || $this->_checkUserRights('attorga')) { + target_unreserve($sid); + } + $this->_header(); + } + + function Attack_add() { + + $data = $_SESSION['steps']; + if($data['addattack']) { + unset($_SESSION['steps']['addattack']); + $attid = param_num("id"); + if(!$attid) $this->_header(); + $this->forms['information']['action'] =""; + $this->forms['information']['url'] = "attplan.php?action=view&id=$attid"; + $this->forms['information']['title'] = "Angriffsplan erstellen"; + $this->forms['information']['message'] = "Angriffsplan wurde hinzugefügt"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Angriffsplan erstellen"); + } + $form = new formContainer(); + $form->add(new formInput("title","Titel","string",true,255)); + $form->add(new formInput("descr","Beschreibung","string",true,null,true)); + $form->add(new formInput("reserve_date","Datum für die Reservierung","date",false,40,true,"'(\d{1,2})\.(\d{1,2})\.(\d{2,4})'is")); + $form->add(new formInput("reserve_time","Startzeit für die Reservierung","time",false,40,true,"'(\d{1,2}):(\d{2})'is")); + $form->add(new formRadio("hidden","Plan verstecken","numeric",array(1,0))); + + if($_POST['send']) { + $form->submit(); + if(($form->get("reserve_date") && !$form->get("reserve_time")) || + (!$form->get("reserve_date") && $form->get("reserve_time")) + ) { + $form->setError("reserve_date"); + $form->setError("reserve_time"); + $form->addError("Datum und Uhrzeit für den Start der Reservierung müssen beide ausgefüllt sein"); + } + if(!$form->hasErrors()) { + if($form->get("reserve_date")) { + $date = $form->getregex("reserve_date"); + $time = $form->getregex("reserve_time"); + $reserve = mktime($time[1],$time[2],0,$date[2],$date[1],$date[3]); + } + $id = attack_add( + $form->get("title"), + $this->userdata['uid'], + $form->get("descr"), + $reserve, + $form->get("hidden") + ); + $_SESSION['steps']['addattack'] = 1; + $this->_header("attplan.php?action=add&id=$id&send"); + } + } else { + $form->select("hidden",0); + $form->set("reserve_date",date("d.m.Y")); + $form->set("reserve_time",date("H:i")); + } + $form->registerVars(&$this->template); + $this->show("attplan_add","Attplaner"); + } + + function Attack_edit() { + $attid = param_num("id"); + if(!$attid) $this->_header(); + $attplan = attack_get($attid); + if(empty($attplan))$this->_header(); + + //rightcheck + if($this->userdata['uid'] != $attplan['owner'] && + !$this->_checkUserRights("attorga")) + $this->_header(); + + if($_SESSION['steps']['editattack']) { + unset($_SESSION['steps']['editattack']); + $this->forms['information']['action'] =""; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['title'] = "Angriffsplan bearbeiten"; + $this->forms['information']['message'] = "Daten wurden erfolgreich geändert!"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Angriffsplan bearbeiten"); + } + $form = new formContainer(); + $form->add(new formInput("title","Titel","string",true,255)); + $form->add(new formInput("descr","Beschreibung","string",true,null,true)); + $form->add(new formInput("reserve_date","Datum für die Reservierung","date",false,40,true,"'(\d{1,2})\.(\d{1,2})\.(\d{2,4})'is")); + $form->add(new formInput("reserve_time","Startzeit für die Reservierung","time",false,40,true,"'(\d{1,2}):(\d{2})'is")); + $form->add(new formRadio("hidden","Plan verstecken","numeric",array(1,0))); + + if($_POST['send']) { + $form->submit(); + if(!$form->hasErrors()) { + if($form->get("reserve_date")) { + $date = $form->getregex("reserve_date"); + $time = $form->getregex("reserve_time"); + $reserve = mktime($time[1],$time[2],0,$date[2],$date[1],$date[3]); + } + attack_edit( + $attid, + $form->get("title"), + $form->get("descr"), + $reserve, + $form->get("hidden") + ); + $_SESSION['steps']['editattack'] = 1; + $this->_header("attplan.php?action=edit&id=$attid&send"); + } + } else { + $form->select("hidden",$attplan['hidden']); + $form->set("title",$attplan['title']); + $form->set("descr",$attplan['descr']); + $form->set("reserve_date",date("d.m.Y",$attplan['access_time'])); + $form->set("reserve_time",date("H:i",$attplan['access_time'])); + } + $form->registerVars(&$this->template); + $this->template->assign("attplan",$attplan); + $this->show("attplan_edit","Attplaner"); + } + + function Attack_delete() { + + if($_SESSION['steps']['deleteattack']) { + unset($_SESSION['steps']['deleteattack']); + $this->forms['information']['action'] =""; + $this->forms['information']['url'] = "attplan.php"; + $this->forms['information']['title'] = "Plan gelöscht"; + $this->forms['information']['message'] = "Plan wurde gelöscht"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Angriffsplan löschen"); + } + + $attid = param_num("id"); + if(!$attid) $this->_header(); + $attplan = attack_get($attid); + if(empty($attplan))$this->_header(); + + //rightcheck + if($this->userdata['uid'] != $attplan['owner'] && + !$this->_checkUserRights("attorga")) + $this->_header(); + + if($_POST['send']) { + if($_POST['yes_x']) { + attack_delete($attid); + $_SESSION['steps']['deleteattack'] = 1; + $this->_header("attplan.php?action=delete"); + } + $this->_header(); + } else { + $this->forms['information']['url'] = "attplan.php?id=$attid"; + $this->forms['information']['action'] = "delete"; + $this->forms['information']['title'] = "Angriffsplan löschen"; + $this->forms['information']['message'] = " + '".$attplan{'title'}."' komplett löschen ?"; + $this->forms['information']['style'] = "red"; + $this->show('message_question', "Angriffsplan löschen"); + } + } +} +?> \ No newline at end of file diff --git a/src/functions/backtracking.php b/src/functions/backtracking.php new file mode 100644 index 0000000..bb83e4d --- /dev/null +++ b/src/functions/backtracking.php @@ -0,0 +1,326 @@ +debug[] = $msg; + } + + + /** + * @return backtracking + * @param string $default Default Rücksprungadresse, index.php + * @param integer $buffer Grösse des Rücksprungbuffers + * @desc Konstruktor + */ + function backtracking(&$session,$default="index.php",$buffer = 10) { + + + $this->debug = array(); + $this->session = $session; + $this->buffer = $buffer; + $this->default = $default; + $this->execludes = array(); + } + + /** + * @return void + * @param unknown $params + * @desc mit Execlude können Urls mit bestimmten Parameter/werten vom tracking ausgeschlossen werden. + * Möglichkeiten: + * params(param => value) : parameter mit wert wird nicht getrackt + * params(param => "*") : parameter wird generell nicht getrackt, egal was fürn wert + * params(parameter => array()) : parameter mit den jeweiligen Werten im Array wird nicht getrackt + */ + function execlude($params) { + if(!$params || !is_array($params)) return; + $this->execludes = $params; + } + + /** + * @return void + * @desc Analysiert die aktuelle url und erstellt eine Rücksprungadresse + */ + function run() { + + $this->backlinks = $this->_get(); + + $backlink = urldecode($_REQUEST['backlink']); + $link = "http://".$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI']; +# if(preg_match("'^(?:(.*?\/)|)([^\/]*?)$'is",$link,$subs)) { +# $backlink = $subs[1].$backlink; +# } + $back = $_REQUEST['back']; + + $notrack = isset($_REQUEST['notrack']); + if(strcmp($link,"http://".$_SERVER['SERVER_NAME']."/") == 0) { + $this->_debugmsg("double: $link"); + } else { + if($backlink) {$this->_set($backlink);} + + if(isset($back)) { + //rücksprung + $this->_pop($link); + $this->_refresh(); + $this->backlink = $this->_generate_backlink(); + } else { + // formular abgeschickt, kein tracking + if(isset($_REQUEST['send'])) {$this->backlink = $this->_generate_backlink();return;} + // ausnahmen + if(!$notrack && count($this->execludes)) { + foreach ($this->execludes as $param => $value) { + if(is_array($value)) { + if($_REQUEST[$param] && in_array($_REQUEST[$param],$value)) { + $notrack = true; + break; + } + } elseif($value == "*") { + if(isset($_REQUEST[$param])) {$notrack = true;break;} + } else { + if($_REQUEST[$param] == $value) {$notrack = true;break;} + } + } + } + if($notrack == false) { + // neuer link + $this->_push($link); + $this->_refresh(); + $this->backlink = $this->_generate_backlink(); + } + } + } + if($notrack && !isset($back)) { + $this->backlink = $this->last(); + } + } + + /** + * @return void, false bei fehlschlag + * @param string $link + * @param integer $index + * @desc Ändert einen Link im stack + */ + function _set($link,$index=null) { + if(!$link) return false; + $backlinks_count = count($this->backlinks); + if($backlinks_count == 0) return false; + if(!$index || !is_numeric($index) || $index >= $backlinks_count || $index < 0) { + $index = $backlinks_count-1; + } + + if(($link = $this->_decode_url($link)) === false) return false; + + if($url['actual']['params'][$this->sessionname]) unset($url['actual']['params'][$this->sessionname]); + + $this->backlinks[$index] = urlencode($this->_encode_url($link)); + } + + /** + * @return array + * @desc Liefert den Trackingbuffer, muss überschrieben werden + * @protected + */ + function _get() { + $tracking = array(); + return $tracking; + } + + /** + * @return void + * @desc Sichert den aktuellen Stack, muss überschrieben werden + * @protected + */ + function _refresh() { + } + + /** + * @return unknown + * @param unknown $link + * @desc decodiert eine Url und liefert ein array mit server,params und ancer als felder zurück + */ + function _decode_url($link) { + $result = array(); + if(preg_match("/^([^\?&]*?)(?:\?([^\?#]*?)|)(?:#([^\?&#]*?)|)$/is",$link,$matches)) { + $result['server'] = $matches[1]; + if($matches[2]) { + foreach (split("&",$matches[2]) as $item) { + $param = split("=",$item); + if(strlen($param[0])) { + $result['params'][$param[0]] = $param[1]; + } + } + } + if($matches[3]) { + $result['ancer'] = $matches[3]; + } + } else { + return false; + } + return $result; + } + + /** + * @return string + * @param array $url + * @desc codiert eine voher decodierte url + */ + function _encode_url($url) { + $link = $url['server']; + if($url['params']) { + $params = array(); + foreach ($url['params'] as $key => $val) { + if(strlen($val)) { + $params[] = "$key=$val"; + } else { + $params[] = "$key"; + } + } + $link .= "?".join("&",$params); + } + if($url['ancer']) { + $link .= "#".$url['ancer']; + } + return $link; + } + + /** + * @return boolean + * @param array $params1 + * @param array $params2 + * @param array|string $param parameter, die beim vergleich nicht berücksichtigt werden sollen + * @desc Vergleicht 2 arrays mit parametern auf gleichniss + */ + function _diff_params($params1,$params2,$param=null) { + if($param) { + if(is_array($param)) { + foreach($param as $name) { + unset($params1[$name]); + unset($params2[$name]); + } + } else { + unset($params1[$param]); + unset($params2[$param]); + } + } + if(!$params1) $params1 = array(); + if(!$params2) $params2 = array(); + return (!array_diff_assoc($params1,$params2) && + !array_diff_assoc($params2,$params1)); + } + + /** + * @return void + * @param string $link + * @desc packt einen neuen Link auf den Stack + */ + function _push($link) { + + if(!$link) return false; + + $backlinks_count = count($this->backlinks); + + $url['actual'] = $this->_decode_url($link); + + unset($url['actual']['params']['backlink']); + unset($url['actual']['params'][$this->session['name']]); + + foreach ($_POST as $key => $val) { + if(is_array($val)) { + $url['actual']['params'][$key] = urlencode(join(",",$val)); + } elseif(isset($_POST[$key])) $url['actual']['params'][$key] = $val; + } + if($url['actual']['params'][$this->sessionname]) unset($url['actual']['params'][$this->sessionname]); + + if($backlinks_count > 0) { + $last = urldecode(end($this->backlinks)); + + $url['last'] = $this->_decode_url($last); + + $servercheck = $url['last']['server'] == $url['actual']['server']; + #$paramcheck = _diff_params($url['last']['params'],$url['actual']['params']); + $pagecheck = $this->_diff_params($url['last']['params'],$url['actual']['params'],"page"); + + if($servercheck && $pagecheck) { + $url['last']['params']['page'] = $url['actual']['params']['page']; + $this->backlinks[$backlinks_count-1] = urlencode($this->_encode_url($url['last'])); + return; + } + } + array_push($this->backlinks,urlencode($this->_encode_url($url['actual']))); + if($backlinks_count+1 > $this->buffer){ + array_shift($this->backlinks); + } + } + + /** + * @return void + * @param string $link + * @desc Rücksprung, entfernt den letzten Eintrag + */ + function _pop($link) { + if(count($this->backlinks) > 0) { + $link = $this->_decode_url($link); + $last = $this->_decode_url(urldecode(end($this->backlinks))); + $check = $this->_diff_params($link['params'],$last['params'],array("page",$this->session['name'],"back")); + if(!$check) { + array_pop($this->backlinks); + } + } + } + + /** + * @return string + * @desc Erzeugt die Rücksprungadresse + */ + function _generate_backlink() { + $backlink = $this->default; + $backlinks_count= count($this->backlinks); + if($backlinks_count > 1) { + $url = $this->_decode_url(urldecode($this->backlinks[$backlinks_count-2])); + $url['params']['back'] = ""; + $url['params'][$this->session['name']] = $this->session['id']; + $backlink = $this->_encode_url($url); + } + return $backlink; + } + + /** + * @return string + * @desc Liefert den letzten Eintrag im Buffer + */ + function last() { + $backlinks_count= count($this->backlinks); + if($backlinks_count > 0) { + return urldecode($this->backlinks[$backlinks_count-1]); + } else { + return $this->default; + } + } + + /** + * @return string + * @desc Gibt die Rücksprungadresse zurück + */ + function backlink() { + return $this->backlink; + } +} +?> \ No newline at end of file diff --git a/src/functions/bbcode.js b/src/functions/bbcode.js new file mode 100644 index 0000000..998ed8b --- /dev/null +++ b/src/functions/bbcode.js @@ -0,0 +1,218 @@ +tags = new Array(); + +function getarraysize(thearray) { + for (i = 0; i < thearray.length; i++) { + if ((thearray[i] == "undefined") || (thearray[i] == "") || (thearray[i] == null)) + return i; + } + return thearray.length; +} + +function arraypush(thearray,value) { + thearraysize = getarraysize(thearray); + thearray[thearraysize] = value; +} + +function arraypop(thearray) { + thearraysize = getarraysize(thearray); + retval = thearray[thearraysize - 1]; + delete thearray[thearraysize - 1]; + return retval; +} + +// ******************************************************* + +function setmode(modevalue) { + document.cookie = "bbcodemode="+modevalue+"; path=/; expires=Wed, 1 Jan 2020 00:00:00 GMT;"; +} + +function normalmode(theform) { + if (theform.mode[0].checked) return true; + else return false; +} + +function stat(thevalue) { + document.bbform.status.value = eval(thevalue+"_text"); +} + +// ******************************************************* + +function closetag(theform) { + if (normalmode(theform)) + stat('enhanced_only'); + else + if (tags[0]) { + theform.message.value += "[/"+ arraypop(tags) +"]"; + } + else { + stat('no_tags'); + } + theform.message.focus(); +} + +function closeall(theform) { + if (normalmode(theform)) + stat('enhanced_only'); + else { + if (tags[0]) { + while (tags[0]) { + theform.message.value += "[/"+ arraypop(tags) +"]"; + } + theform.message.value += " "; + } + else { + stat('no_tags'); + } + } + theform.message.focus(); +} + +// ******************************************************* +var text = ""; +AddTxt = ""; +function getActiveText(selectedtext) { + text = (document.all) ? document.selection.createRange().text : document.getSelection(); + if (selectedtext.createTextRange) { + selectedtext.caretPos = document.selection.createRange().duplicate(); + } + return true; +} + +function AddText(NewCode,theform) { + if (theform.message.createTextRange && theform.message.caretPos) { + var caretPos = theform.message.caretPos; + caretPos.text = caretPos.text.charAt(caretPos.text.length - 1) == ' ' ? NewCode + ' ' : NewCode; + } else { + theform.message.value+=NewCode + } + setfocus(theform); + AddTxt = ""; +} + + +function setfocus(theform) { +theform.message.focus(); +} + +function bbcode(theform,bbcode,prompttext) { + if ((normalmode(theform)) || (bbcode=="IMG")) { + if (text) { var dtext=text; } else { var dtext=prompttext; } + inserttext = prompt(tag_prompt+"\n["+bbcode+"]xxx[/"+bbcode+"]",dtext); + if ((inserttext != null) && (inserttext != "")) + AddTxt = "["+bbcode+"]"+inserttext+"[/"+bbcode+"] "; + AddText(AddTxt,theform); + + } + else { + donotinsert = false; + for (i = 0; i < tags.length; i++) { + if (tags[i] == bbcode) + donotinsert = true; + } + if (donotinsert) + stat("already_open"); + else { + theform.message.value += "["+bbcode+"]"; + arraypush(tags,bbcode); + } + } + theform.message.focus(); +} + +// ******************************************************* + +function fontformat(theform,thevalue,thetype) { + if (normalmode(theform)) { + if (thevalue != 0) { + if (text) { var dtext=text; } else { var dtext=""; } + inserttext = prompt(font_formatter_prompt+" "+thetype,dtext); + if ((inserttext != null) && (inserttext != "")) + AddTxt = "["+thetype+"="+thevalue+"]"+inserttext+"[/"+thetype+"] "; + AddText(AddTxt,theform); + + } + } + else { + theform.message.value += "["+thetype+"="+thevalue+"]"; + arraypush(tags,thetype); + } + theform.sizeselect.selectedIndex = 0; + theform.fontselect.selectedIndex = 0; + theform.colorselect.selectedIndex = 0; + theform.message.focus(); +} + +// ******************************************************* + +function namedlink(theform,thetype) { + if (text) { var dtext=text; } else { var dtext=""; } + linktext = prompt(link_text_prompt,dtext); + var prompttext; + if (thetype == "URL") { + prompt_text = link_url_prompt; + prompt_contents = "http://"; + } + else { + prompt_text = link_email_prompt; + prompt_contents = ""; + } + linkurl = prompt(prompt_text,prompt_contents); + if ((linkurl != null) && (linkurl != "")) { + if ((linktext != null) && (linktext != "")) { + AddTxt = "["+thetype+"="+linkurl+"]"+linktext+"[/"+thetype+"] "; + AddText(AddTxt,theform); + + } + else{ + AddTxt = "["+thetype+"]"+linkurl+"[/"+thetype+"] "; + AddText(AddTxt,theform); + + } + } +} + +// ******************************************************* + +function dolist(theform) { + listtype = prompt(list_type_prompt, ""); + if ((listtype == "a") || (listtype == "1")) { + thelist = "[list="+listtype+"]\n"; + listend = "[/list="+listtype+"] "; + } + else { + thelist = "[list]\n"; + listend = "[/list] "; + } + listentry = "initial"; + while ((listentry != "") && (listentry != null)) { + listentry = prompt(list_item_prompt, ""); + if ((listentry != "") && (listentry != null)) + thelist = thelist+"[*]"+listentry+"\n"; + } + AddTxt = thelist+listend; + AddText(AddTxt,theform); + +} + +// ******************************************************* + +function smilie(thesmilie) { + AddSmile = " "+thesmilie+" "; + theform = bbform; + AddText(AddSmile,theform); +} + +function opensmiliewindow(x,y) { + w = window.open("moresmilies.php", "smilies", "toolbar=no,scrollbars=yes,resizable=yes,width="+x+",height="+y); + w.focus() +} +function openpicturewindow(id) { + w = window.open("showpicture.php?picture="+id, "Vollbild", "toolbar=no,scrollbars=yes,resizable=yes"); +// w.focus() +} + +// ******************************************************* + +function gethelp() { + alert(HELPTEXT); +} \ No newline at end of file diff --git a/src/functions/bbcode.php b/src/functions/bbcode.php new file mode 100644 index 0000000..ae2643b --- /dev/null +++ b/src/functions/bbcode.php @@ -0,0 +1,257 @@ + ersetzen + $string = nl2br($string); + //Smilies + #$string = smilies($string); + if(!isset($searcharray) && !isset($replacearray)) { + //liste + $searcharray[]="/\[list=(['\"]?)([^\"']*)\\1]". + "(.*)\[\/list((=\\1[^\"']*\\1])|(\]))/esiU"; + $replacearray[]="formatlist('\\3', '\\2')"; + $searcharray[]="/\[list](.*)\[\/list\]/esiU"; + $replacearray[]="formatlist('\\1')"; + //url + $searcharray[]="/\[url=(['\"]?)([^\"']*)\\1](.*)\[\/url\]/esiU"; + $replacearray[]="formaturl('\\2','\\3')"; + $searcharray[]="/\[url]([^\"]*)\[\/url\]/esiU"; + $replacearray[]="formaturl('\\1')"; + //image + $searcharray[]="/\[img]([^\"]*)\[\/img\]/siU"; + $replacearray[]=""; + //email + $searcharray[] = "/\[email=(['\"]?)([^\"']*)\\1](.*)\[\/email\]/siU"; + $replacearray[] = "\\3"; + $searcharray[] = "/\[email](.*)\[\/email\]/siU"; + $replacearray[] = "\\1"; + //phpcode + $searcharray[]="/\[code](.*)\[\/code\]/esiU"; + $replacearray[]="formatcodetag('\\1')"; + //highlite + $searcharray[]="/\[php](.*)\[\/php\]/esiU"; + $replacearray[]="phphighlite('\\1')"; + //bold + $searcharray[] = "/\[B](.*)\[\/B\]/siU"; + $replacearray[] = "\\1"; + //underline + $searcharray[] = "/\[U](.*)\[\/U\]/siU"; + $replacearray[] = "\\1"; + //italic + $searcharray[] = "/\[I](.*)\[\/I\]/siU"; + $replacearray[] = "\\1"; + //fontsize + $searcharray[] = "/\[SIZE=(['\"]?)([^\"']*)\\1](.*)\[\/SIZE\]/siU"; + $replacearray[] = "\\3"; + //fontcolor + $searcharray[] = "/\[COLOR=(['\"]?)([^\"']*)\\1](.*)\[\/COLOR\]/siU"; + $replacearray[] = "\\3"; + //font + $searcharray[] = "/\[FONT=(['\"]?)([^\"']*)\\1](.*)\[\/FONT\]/siU"; + $replacearray[] = "\\3"; + //align + $searcharray[] = "/\[ALIGN=(['\"]?)([^\"']*)\\1](.*)\[\/ALIGN\]/siU"; + $replacearray[] = "
\\3
"; + //mark + $searcharray[] = "/\[MARK=(['\"]?)([^\"']*)\\1](.*)\[\/MARK\]/siU"; + $replacearray[] = "\\3"; + //quote + $searcharray[] = "/\[QUOTE](.*)\[\/QUOTE\]/siU"; + $replacearray[] = "
Zitat:". + "
\\1
"; + } + + $string = preg_replace($searcharray, $replacearray, $string); + $string = str_replace("\\'", "'", $string); + return $string; +} // end func + +/** + * Funktion formaturl + * + * Diese Funktion formatiert eine Url. + * @param string $url die Url + * @param string $title ein Titel (optional) + * @param integer maxwidth die maximle Länge der Url + * @param integer widthl die anzahl der linken zeichen + * @param integer width2 die Anzahl der zeichen, die rechts angezeigt + * werden + * @return string formatierte Url + */ +function formaturl($url, $title="", $maxwidth=60, $width1=40, $width2=-15) { + if(!trim($title)) $title=$url; + if(!preg_match("/[a-z]:\/\//si", $url)) $url = "http://$url"; + if(strlen($title)>$maxwidth) $title = substr($title,0,$width1)."...".substr($title,$width2); + return "".str_replace("\\\"", "\"", $title).""; +} + + +/** + * Funktion parseUrl + * + * Diese Funktion durchsucht den String nach Url's und email tags und ersetzt + * diese Teile durch BB Code. + * @param string $string der zu durchsuchende String + * @return string String, wo alle tags durch BBCode ersetzt sind + */ +function parseUrl($string) +{ + // nach url und email suchen + $urlsearch[]="/([^]_a-z0-9-=\"'\/])((https?|ftp):\/\/|www\.)([^". + "\r\n\(\)\*\^\$!`\"'\|\[\]\{\};<>]*)/si"; + $urlsearch[]="/^((https?|ftp):\/\/|www\.)([^". + "\r\n\(\)\*\^\$!`\"'\|\[\]\{\};<>]*)/si"; + $urlreplace[]="\\1[URL]\\2\\4[/URL]"; + $urlreplace[]="[URL]\\1\\3[/URL]"; + $emailsearch[]="/([\s])([_a-zA-Z0-9-]+(\.[_a-zA-Z0-9-]+)*@[a-zA-Z0-9-]+(\.[". + "a-zZ0-9-]+)*(\.[a-zA-Z]{2,}))/si"; + $emailsearch[]="/^([_a-zA-Z0-9-]+(\.[_a-zA-Z0-9-]+)*@[a-zA-Z0-9-]+(\.[a-z". + "A-Z0-9-]+)*(\.[a-zA-Z]{2,}))/si"; + $emailreplace[]="\\1[EMAIL]\\2[/EMAIL]"; + $emailreplace[]="[EMAIL]\\0[/EMAIL]"; + $string = preg_replace($urlsearch, $urlreplace, $string); + if (strpos($string, "@")) $string = preg_replace($emailsearch, $emailreplace, $string); + return $string; +} // end func + +function formatcodetag($code) { + return "
code:
".str_replace("
","",str_replace("\\\"","\"",$code))."
"; +} + +function formatlist($list, $listtype="") { + if ($listtype) { + $listtype = " type=\"$listtype\""; + } + $list = str_replace("\\\"","\"",$list); + if ($listtype) return "".str_replace("[*]","
  • ", $list).""; + else return "
      ".str_replace("[*]","
    • ", $list)."
    "; +} + +function phphighlite($code) { + + $code = str_replace(">", ">", $code); + $code = str_replace("<", "<", $code); + $code = str_replace("&", "&", $code); + $code = str_replace('$', '\$', $code); + $code = str_replace('\n', '\\\\n', $code); + $code = str_replace('\r', '\\\\r', $code); + $code = str_replace('\t', '\\\\t', $code); + $code = str_replace("
    ", "\r\n", $code); + $code = str_replace("
    ", "\r\n", $code); + + $code = stripslashes($code); + + ob_start(); + $oldlevel=error_reporting(0); + highlight_string($code); + error_reporting($oldlevel); + $buffer = ob_get_contents(); + ob_end_clean(); + //$buffer = str_replace(""", "\"", $buffer); + return "
    php:
    $buffer
    "; +} + +function smilies($out) { + global $smiliecache,$SmiliePath; + if(!$smiliecache) return; + for($i = 0; $i < count($smiliecache); $i++) + $out=str_replace ($smiliecache[$i]['smiliestext'], "", $out); + return $out; +} + +function editPostdata($data) { + $data = str_replace("\'","'", $data); + $data = str_replace("'","´", $data); + $data = str_replace("\"",""", $data); + return $data; +} + +function editDBdata($data) { + $data = str_replace("´","'", $data); + $data = str_replace(""","\"", $data); + return $data; +} + + +/** + * Short description. + * + * Detail description + * @param + * @since 1.0 + * @access private + * @return void + * @throws + */ +function getclickysmilies($tableRows,$tableColumns,$path,$css="") +{ + global $smiliecache; + global $smilie; + global $smiliebits; + global $url; + global $smiliegetmore; + global $cssclass; + global $Columns; + + if (!$smiliecache) return; + + $url = $path; + $Columns = $tableColumns; + if ($css) $cssclass = " class = \"".$css."\""; + + $totalSmilies = count($smiliecache); + + if(($tableRows*$tableColumns) < $totalSmilies) { + $smiliegetmore= getTemplate("admin.bbsmilie.getmore"); + } + + foreach($smiliecache as $smilie) { + $smilieArray[] = getTemplate("admin.bbsmilie.bit"); + } + unset($smilie); + + $count = 0; + for ($i=0; $i<$tableRows; $i++) { + if ($count < $totalSmilies) { + $smiliebits .= "\t\n"; + for ($j=0; $j<$tableColumns; $j++) { + if ($count == $totalSmilies) { + $smiliebits .= "\t ";break; + } + $smiliebits .= "\t".$smilieArray[$count]." \n"; + $count++; + } + $smiliebits .= "\t\n"; + } + } + + $bbcode_smilies = getTemplate("admin.bbsmilie"); + return $bbcode_smilies; +} // end func + +?> \ No newline at end of file diff --git a/src/functions/bbcode_language.js b/src/functions/bbcode_language.js new file mode 100644 index 0000000..bc90fa2 --- /dev/null +++ b/src/functions/bbcode_language.js @@ -0,0 +1,40 @@ +b_text = "fetten Text einfügen"; +i_text = "kursiven Text einfügen"; +u_text = "unterstrichenen Text einfügen"; + +size_text = "Textgröße ändern"; +font_text = "Schriftart ändern"; +color_text = "Schriftfarbe ändern"; +align_text = "Text-Ausrichtung ändern"; + +url_text = "Hyperlink einfügen"; +email_text = "Email Adresse einfügen"; +img_text = "Grafik einfügen"; + +code_text = "monospace Text einfügen"; +php_text = "PHP Code einfügen"; +list_text = "Liste einfügen"; +quote_text = "Zitat einfügen"; + +norm_text = "einfacher Modus"; +enha_text = "erweiterter Modus"; + +closecurrent_text = "aktuellen tag schließen"; +closeall_text = "alle tags schließen"; + +enhanced_only_text = "<< nur im erweiterten Modus verfügbar >>"; +no_tags_text = "<< keine offenen tags vorhanden >>"; +already_open_text = "<< es ist bereit der selbe tag offen >>"; + +HELPTEXT = "Einfaches Einfügen von BBCode und Smilies.\n\nDiese Kontrollen erlauben das schnelle und einfache Einfügen von BBcode in Nachrichten.\n\nEs gibt 2 Moden bei der Benutzung: einfacher and erweiterter Modus.\n\nBeim einfachen Modus öffnet sich beim drücken eines Buttons ein Pop-up Fenster,\nwo man den zu formatierenden Text eingeben kann\nDer Text wird dann automatisch an der aktuellen Position des Nachricht angehangen.\n\nBeim erweiterten Modus wird ein BBCode tag sofort in die Nachricht eingefügt.\nUm den entsprechenden tag dann wieder zu schließen,\nmuß man auf den 'aktuellen tag schließen' Button (alt+c) drücken.\nMan kann allerdings auch alle offenen tags auf einmal schließen,\nindem man den 'alle tags schließen' Button (alt+x) benutzt.\n\nUm einen Smilie in die Nachricht einzufügen, muß man einfach auf den Gewünschten klicken.\nAußerdem hat man mit einem Klick auf den Button 'mehr' alle Smilies zur Auswahl."; + +tag_prompt = "Gebe einen Text ein:"; + +font_formatter_prompt = "Gebe einen Text ein - "; + +link_text_prompt = "Gebe einen Linknamen ein (optional)"; +link_url_prompt = "Gebe die volle Adresse des Links ein"; +link_email_prompt = "Gebe eine Email Adesse ein"; + +list_type_prompt = "was für eine Liste möchtest du? Gebe '1' ein für eine nummerierte Liste, 'a' für ein alphabetische, oder gar nichts für eine einfache Punktliste."; +list_item_prompt = "Gebe eine Listepunkt ein.\nGebe nichts ein oder drücke 'Cancel' um die Liste fertigzustellen."; diff --git a/src/functions/bootstrap.php b/src/functions/bootstrap.php new file mode 100644 index 0000000..3e70aaf --- /dev/null +++ b/src/functions/bootstrap.php @@ -0,0 +1,23 @@ + \ No newline at end of file diff --git a/src/functions/debug.php b/src/functions/debug.php new file mode 100644 index 0000000..c4c1789 --- /dev/null +++ b/src/functions/debug.php @@ -0,0 +1,22 @@ + \ No newline at end of file diff --git a/src/functions/form.handler.php b/src/functions/form.handler.php new file mode 100644 index 0000000..dac9044 --- /dev/null +++ b/src/functions/form.handler.php @@ -0,0 +1,609 @@ +name = $name; + $this->title = $title; + $this->onlypost = $onlypost; + $this->format = $format; + $this->classes = array("error" => "form_error", "optional" => "form_optional", "default" => "form"); + $this->value = null; + $this->isSubmit = false; + $this->has_error = false; + } + + function getName() { + return $this->name; + } + + function get() { + return $this->value; + } + + function title() { + return $this->title; + } + + function is_set() { + return isset($this->value); + } + + function set($value) { + $this->value = $value; + return $value; + } + + function submit() { + if($this->onlypost) { + $this->value = $_POST[$this->getName()]; + #echo"post wert: ";var_dump($this->value);echo"
    "; + } else { + $this->value = $_REQUEST[$this->getName()]; + #echo"request wert: ";var_dump($this->value);echo"
    "; + } + $this->isSubmit = true; + } + + function setError($msg="") { + if($msg){ + $this->error = $this->title.": ".$msg; + } + $this->has_error = true; + return false; + } + + function checkFormat() { + if(is_array($this->value)) { + foreach($this->value as $key => $value) { + if($this->format == "string") { + $this->value[$key] = trim($this->value[$key]); + } elseif($this->format == "numeric") { + if(!is_numeric($this->value[$key]) || $this->value[$key] < 0) { + return false; + break; + } + } elseif($this->format == "integer") { + if(!is_numeric($this->value[$key])) { + return false; + break; + } + } + } + } else { + if($this->format == "string" || $this->format == "time" || $this->format == "date") { + $this->value = trim($this->value); + } elseif($this->format == "numeric") { + if(!is_numeric($this->value) || $this->value < 0) { + return false; + } + } elseif($this->format == "integer") { + if(!is_numeric($this->value)) { + return false; + } + } + } + return true; + } + + function getError() { + return $this->error; + } + + function hasError() { + return $this->has_error; + } + + function getClass() { + if($this->hasError()) { + return $this->classes['error']; + } else { + return $this->classes['default']; + } + } + + function registerSmarty() { + //dummy + $item['title'] = $this->title; + return $item; + } + + function select($value) { + // dummy + } + + function isSubmit() { + return $this->isSubmit; + } +} + +// text,password,textarea felder +class formInput extends formItem { + var $optional; + var $length; + + var $regex; + var $regex_matchings; + var $regex_result; + + + function formInput($name,$title,$format,$onlypost=true,$length=null,$optional=false,$regex="") { + parent::formItem($name,$title,$format,$onlypost); + $this->length = $length; + $this->optional = $optional; + $this->regex = $regex; + $this->regex_result = false; + } + + function submit() { + parent::submit(); + if(is_array($this->get())) return $this->setError("Wert ist ungültig"); + if($this->optional && strlen($this->get()) == 0) return true; + if(!$this->optional && strlen(trim($this->get())) == 0) return $this->setError("Feld ist leer"); + if(!$this->checkFormat()) return $this->setError("Wert ist ungültig"); + if($this->length && strlen($this->get()) > $this->length) return $this->setError("Eingabe zu lang"); + if($this->format == "time") { + $this->regex_result = preg_match("'^(\d{1,2}):(\d{2})$'is",$this->get(),$this->regex_matchings); + if(!$this->regex_result) return $this->setError("Wert ist eine ungültige Zeit"); + if( $this->regex_matchings[1] < 0 || $this->regex_matchings[1] > 24 || + $this->regex_matchings[2] < 0 || $this->regex_matchings[2] > 59 + ) { + return $this->setError("Wert ist eine ungültige Zeit"); + } + } + if($this->format == "date") { + $this->regex_result = preg_match("'^(\d{1,2})\.(\d{1,2})\.(\d{4})$'is",$this->get(),$this->regex_matchings); + if(!$this->regex_result) return $this->setError("Wert ist ein ungültiges Datum"); + if( $this->regex_matchings[1] < 1 || $this->regex_matchings[1] > 31 || + $this->regex_matchings[2] < 1 || $this->regex_matchings[2] > 12 || + $this->regex_matchings[3] < 2004 || $this->regex_matchings[3] > 2020 + ) { + return $this->setError("Wert ist ein ungültiges Datum"); + } + } + if($this->regex) { + $this->regex_result = preg_match($this->regex,$this->get(),$this->regex_matchings); + if(!$this->regex_result) return $this->setError("Wert entspricht nicht der vorgegebenen Formatierung"); + } + return true; + } + + function getMatching() { + if($this->regex_result) { + return $this->regex_matchings; + } + } + + /** + * @return array smarty daten + * @desc liefert Daten für die Smartyengine + * @protected + */ + function registerSmarty() { + $item = parent::registerSmarty(); + if($this->optional) $item['title'] .= " (optional)"; + $item['value'] = $this->get(); + if($this->hasError()) { + $item['class'] = $this->classes['error']; + } else { + if(strlen($this->get()) || !$this->optional) { + $item['class'] = $this->classes['default']; + } else { + $item['class'] = $this->classes['optional']; + } + } + return $item; + } +} + +// radio +class formRadio extends formItem { + // liste der werte, list[i]['value'] + var $list; + // ausgewählter wert per default + var $default; + + //liste = array() + function formRadio($name,$title,$format,$list,$default="",$onlypost=true) { + parent::formItem($name,$title,$format,$onlypost); + // liste baun + for($i=0;$i < count($list);$i++) { + $this->list[] = array("value" => $list[$i]); + } + // defaultwert überhaupt in der liste ? + if($default && in_array($default,$list)) { + $this->default = $default; + } + } + + function submit() { + parent::submit(); + // darf kein array sein + if(is_array($this->get())) return $this->setError("Wert ungültig"); + // muss da sein, nicht optional + if(strlen(trim($this->get())) == 0) return $this->setError("Feld leer"); + // formatcheck + if(!$this->checkFormat()) return $this->setError("Wert ungültig"); + // ist in den Vorgaben vorhanden + if(($key = array_search(array("value" => $this->get()),$this->list)) === FALSE) { + return $this->setError("Wert existiert nicht in den Vorgaben"); + } else { + // selektiertes Element auswählen + $this->select($this->get()); + } +# var_dump($this->list); +# echo "
    wert: ".$this->get()."
    result: ".in_array($this->get(),array_keys($this->list))."
    "; + return true; + } + + function registerSmarty() { + $item = parent::registerSmarty(); + // falls kein Wert gesetzt oder Fehler da ist, default wert auswählen + if($this->default && $this->isSubmit() && (!$this->get() || $this->getError())) { + $this->select($this->default); + } + $item['value'] = $this->get(); + $item['default'] = $this->default; + $item['list'] = $this->list; + return $item; + } + + function select($value) { + if(is_array($value)) return; + if(!(($key = array_search(array("value" => $value),$this->list)) === FALSE)) { + $this->list[$key]['checked'] = 'checked'; + } + } +} + +// checkbox +class formCheckBox extends formItem { + // liste der werte, list[i]['value'] + var $list; + // ausgewählte werte per default + var $default; + // erwartet ein Array als HTTP variable + var $is_array; + + //liste = array() + function formCheckBox($name,$title,$format,$list,$multiple=true,$default=null,$onlypost=true) { + parent::formItem($name,$title,$format,$onlypost); + if(!$list) $list = array(); + if(!is_array($list)) $list = array($list); + if($multiple) { + // liste baun + for($i=0;$i < count($list);$i++) { + $this->list[] = array("value" => $list[$i]); + } + } else { + $this->list[0] = array("value" => $list[0]); + } + $this->is_array = $multiple; + // defaultwerte überhaupt in der liste ? + if(is_array($default)) { + for($i=0;$i < count($default);$i++) { + if(in_array($default[$i],$list)) { + $this->default[] = $default[$i]; + } + } + } else { + if(in_array($default,$list)) { + $this->default = $default; + } + } + } + + function submit() { + parent::submit(); + // darf kein array sein + if(!$this->is_array) { + if(is_array($this->get())) return $this->setError("Wert ungültig"); + // optional + if(strlen(trim($this->get())) > 0) { + // formatcheck + if(!$this->checkFormat()) return $this->setError("Wert ungültig"); + // ist in den Vorgaben vorhanden + if(($key = array_search(array("value" => $this->get()),$this->list)) === FALSE) { + return $this->setError("Wert existiert nicht in den Vorgaben"); + } else { + // selektiertes Element auswählen + $this->select($this->get()); + } + } + } else { + if($this->get() && !is_array($this->get())) return $this->setError("Wert ungültig"); + // optional + if(count($this->get()) > 0) { + // formatcheck + if(!$this->checkFormat()) return $this->setError("Wert(e) ungültig"); + // ist in den Vorgaben vorhanden + $noerror = true; + foreach($this->get() as $key => $value) { + if(($result = array_search(array("value" => $value),$this->list)) === FALSE) { + $noerror = false; + break; + } + } + if(!$noerror) return $this->setError("Wert existiert nicht in den Vorgaben"); + $this->select($this->get()); + } + } +# var_dump($this->list); +# echo "
    wert: ".$this->get()."
    result: ".in_array($this->get(),array_keys($this->list))."
    "; + return true; + } + + function registerSmarty() { + $item = parent::registerSmarty(); + // falls kein Wert gesetzt oder Fehler da ist, default wert(e) auswählen + if($this->default && $this->isSubmit() && (!$this->get() || $this->getError())) { + $this->select($this->default); + } + $item['default'] = $this->default; + if($this->is_array) { + $item['list'] = $this->list; + $item['value'] = $this->get(); + } else { + $item['value'] = $this->list[0]['value']; + $item['checked'] = $this->list[0]['checked']; + } + return $item; + } + + function select($value) { + if(is_array($value)) { + foreach($value as $key => $val) { + if(!(($result = array_search(array("value" => $val),$this->list)) === FALSE)) { + // selektiertes Element auswählen + $this->list[$result]['checked'] = 'checked'; + } + } + } else { + if(!(($result = array_search(array("value" => $value),$this->list)) === FALSE)) { + // selektiertes Element auswählen + $this->list[$result]['checked'] = 'checked'; + } + } + } +} + +// selectBox +class formSelectBox extends formItem { + // liste der werte, list[i]['value'],$list[i][title] + var $list; + // ausgewählte werte per default + var $default; + // erwartet ein Array als HTTP variable, multiple auswahl + var $is_array; + + // sucht den Wert in der Liste und gibt den Index zurück + function _findItem($val) { + $count = count($this->list); + for($i=0;$i < $count;$i++) { + if($this->list[$i]['value'] == $val) { + return $i; + break; + } + } + return false; + } + + // liste[] = array('value' => wert, 'title' => title) + function formSelectBox($name,$title,$format,$list,$multiple=true,$default=null,$onlypost=true) { + parent::formItem($name,$title,$format,$onlypost); + // liste baun + $this->list = array(); + if($list && is_array($list)) { + foreach($list as $value) { + $this->list[] = array("value" => $value['value'],"title" => $value['title']); + } + } + $this->is_array = $multiple; + // defaultwerte überhaupt in der liste ? + if(is_array($default)) { + for($i=0;$i < count($default);$i++) { + if(!($this->_findItem($default[$i]) === false)) { + $this->default[] = $default[$i]; + } + } + } else { + if(!($this->_findItem($default) === false)) { + $this->default = $default; + } + } + } + + function submit() { + parent::submit(); + if(!$this->is_array) { + // darf kein array sein + if(is_array($this->get())) return $this->setError("Wert ungültig"); + // optional + if(strlen(trim($this->get())) > 0) { + // formatcheck + if(!$this->checkFormat()) return $this->setError("Wert ungültig"); + // ist in den Vorgaben vorhanden + if($this->_findItem($this->get()) === FALSE) { + return $this->setError("Wert existiert nicht in den Vorgaben"); + } else { + // selektiertes Element auswählen + $this->select($this->get()); + } + } + } else { + if($this->get() && !is_array($this->get())) return $this->setError("Wert ungültig"); + // optional + if(count($this->get()) > 0) { + // formatcheck + if(!$this->checkFormat()) return $this->setError("Wert(e) ungültig"); + // ist in den Vorgaben vorhanden + $error = false; + foreach($this->get() as $key => $value) { + if($this->_findItem($value) === FALSE) { + $error = true; + break; + } + } + if ($error) return $this->setError("Wert existiert nicht in den Vorgaben"); + $this->select($this->get()); + } + } +# var_dump($this->list); +# echo "
    wert: ".$this->get()."
    result: ".in_array($this->get(),array_keys($this->list))."
    "; + return true; + } + + function registerSmarty() { + $item = parent::registerSmarty(); + // falls kein Wert gesetzt oder Fehler da ist, default wert(e) auswählen + if($this->default && $this->isSubmit() && (!$this->get() || $this->getError())) { + $this->select($this->default); + } + $item['default'] = $this->default; + $item['list'] = $this->list; + $item['value'] = $this->get(); + return $item; + } + + function select($value) { + if(is_array($value)) { + foreach($value as $key => $val) { + if(!(($result = $this->_findItem($val)) === FALSE)) { + // selektiertes Element auswählen + $this->list[$result]['selected'] = 'selected'; + $this->value = $value; + } + } + } else { + if(!(($result = $this->_findItem($value)) === FALSE)) { + // selektiertes Element auswählen + $this->list[$result]['selected'] = 'selected'; + $this->value = $value; + } + } + } +} + + +class formContainer { + var $items; + var $errors; + + function formContainer() { + $this->items = array(); + $this->errors = array(); + } + + function add($obj) { + if(is_a($obj,"formItem")) { + $this->items[$obj->getName()] = $obj; + } + } + + function get($name) { + if(is_object($this->items[$name])) { + return $this->items[$name]->get(); + } + } + + function is_set($name) { + if(is_object($this->items[$name])) { + return $this->items[$name]->is_set(); + } + } + + function get_obj($name,$obj) { + if(is_object($this->items[$name])) { + $obj = $this->items[$name]; + } + } + + function select($name,$value) { + if(is_object($this->items[$name])) { + $this->items[$name]->select($value); + } + } + + function set($name,$value) { + if(is_object($this->items[$name])) { + $this->items[$name]->set($value); + } + } + + function submit($names="") { + if($names && !is_array($names))$names = array($names); + if($names){ + foreach($names as $name) { + if(is_a($this->items[$name],"formItem")) { + if(!$this->items[$name]->submit()) { + $this->errors[] = $this->items[$name]->getError(); + } + } + } + } else { + $this->errors = array(); + foreach($this->items as $name => $obj) { + if(!$this->items[$name]->submit()) { + $this->errors[] = $this->items[$name]->getError(); + } + } + } + if(count($this->errors)) return false; + else return true; + } + + function getRegex($name){ + if(is_a($this->items[$name],"formInput")) { + return $this->items[$name]->getMatching(); + } + } + + function setError($names) { + if(!$names) return; + if(!is_array($names)) $names = array($names); + foreach ($names as $name) { + if(is_a($this->items[$name],"formItem")){ + $this->items[$name]->setError(); + } + } + } + + function addError($msg){ + $this->errors[] = $msg; + } + + function hasErrors() { + foreach($this->items as $name => $obj) { + if($this->items[$name]->hasError()) return true; + } + return false; + } + + function getErrors() { + return $this->errors; + } + + // smartyklasse per referenz übergeben + function registerVars(&$smarty) { + $items = array(); + $this->smartyitems = array(); + foreach($this->items as $name => $obj) { + $this->smartyitems[$name] = $this->items[$name]->registerSmarty(); + } +# echo"items:";var_dump($this->items);echo"
    "; + $smarty->assign("items",$this->smartyitems); + $smarty->assign("errors",$this->getErrors()); + } +} + +?> diff --git a/src/functions/functions.php b/src/functions/functions.php new file mode 100644 index 0000000..399c7cc --- /dev/null +++ b/src/functions/functions.php @@ -0,0 +1,495 @@ +0); + } + } + if($scan['hasnews']) { + $newsdata = preg_replace("/(Angriff(?::|))/i","$1",$scan['news_newsdata']); + $newsdata = preg_replace("/(Verteidigung(?::|))/i","$1",$newsdata); + $newsdata = preg_replace("/(Rückzug(?::|))/i","$1",$newsdata); + $newsdata = preg_replace("/\s(\d{1,4}):(\d{1,2})\s(\w+)/i"," $1:$2 $3 ",$newsdata); + preg_match_all("/^(?:(.*?(?:<\/span>)|.*?)\s)(.*?)$/im",$newsdata,$lines,PREG_SET_ORDER); + $scan['news_formated_newsdata'] = $lines; + } + $maxrows = 0; + $simulator_link = array(); + if($scan['hasgscan']) { + array_push($simulator_link, + "deff9=".$scan['gscan_rubium'], + "deff10=".$scan['gscan_pulsar'], + "deff11=".$scan['gscan_coon'], + "deff12=".$scan['gscan_centurion'], + "deff13=".$scan['gscan_horus']); + $maxrows = 6; + $scan['colspan']++; + } + if($scan['hassector']) { + array_push($simulator_link, + "kristall=".$scan['sector_kristall'], + "metall=".$scan['sector_metall']); + $maxrows = 8; + $scan['colspan']++; + } + if($scan['hasunit']) { + array_push($simulator_link, + "deff0=".$scan['jaeger'], + "deff1=".$scan['bomber'], + "deff2=".$scan['fregatten'], + "deff3=".$scan['zerstoerer'], + "deff4=".$scan['kreuzer'], + "deff5=".$scan['schlachter'], + "deff6=".$scan['traeger'], + "deff7=".$scan['kleptoren'], + "deff8=".$scan['cancris']); + $maxrows = 10; + $scan['colspan']++; + } + if(count($simulator_link)) { + $scan['simulator_link'] = "simulator.php?".join("&",$simulator_link); + } + $scan['maxrows'] = $maxrows; + if($scan['colspan'] > 0) { + $scan['width'] = floor(100 / $scan['colspan']); + } + $scan = generateirclink($scan); + return $scan; +} + + +# +# liefert den numeric - Parameterwert oder default +# + +function param_num($param,$default=null,$post=false) { + if ($post) { + $value = $_POST[$param]; + } else { + $value = $_REQUEST[$param]; + } + if (!is_numeric($value) || !isset($value) || $value < 1) $value = $default; + return $value; +} + +# +# liefert den Stringwert +# +function param_str($param,$post=false) { + $value = ""; + if ($post) { + $value = trim($_POST[$param]); + } else { + $value = trim($_REQUEST[$param]); + } + return $value; +} + +# +# liefert den Wochentag +# +function getWeekday($id){ + $day = ""; + switch ($id) { + case 0 : {$day = "Montag";break;} + case 1 : {$day = "Dienstag";break;} + case 2 : {$day = "Mittwoch";break;} + case 3 : {$day = "Donnerstag";break;} + case 4 : {$day = "Freitag";break;} + case 5 : {$day = "Samstag";break;} + case 6 : {$day = "Sonntag";break;} + default: $day = "error"; + } + return $day; +} + +$co = "00"; +$bg = "14"; +$co2 = "01"; +$bg2 = "15"; + + +function generateIrcFleetLink($fleet,$username,$gala,$pos,$time,$date) { + $col1 = "01"; + $bg1 = "07"; + + $col2 = "01"; + $bg2 = "14"; + $col3 = "15"; + $bg3 = "14"; + + $link[] = "".$col1.",".$bg1."NL Flotte ".$username." (".$gala.":".$pos.")"; + $link[] = "".$col2.",".$bg2."Cleptoren: ".$col3.",".$bg3."".$fleet['kleptoren']."".$col2.",".$bg2." Cancris: +".$col3.",".$bg3."".$fleet['cancris']."".$col2.",".$bg2." Fregatten: ".$col3.",".$bg3."".$fleet['fregatten']."".$col2.",".$bg2; + $link[] = "".$col2.",".$bg2."Zerstörer: ".$col3.",".$bg3."".$fleet['zerstoerer']."".$col2.",".$bg2." Kreuzer: +".$col3.",".$bg3."".$fleet['kreuzer']."".$col2.",".$bg2." Träger: ".$col3.",".$bg3."".$fleet['traeger']."".$col2.",".$bg2; + $link[] = "".$col2.",".$bg2."Jäger: ".$col3.",".$bg3."".$fleet['jaeger']."".$col2.",".$bg2." Bomber: +".$col3.",".$bg3."".$fleet['bomber']."".$col2.",".$bg2." Schlachter: ".$col3.",".$bg3."".$fleet['schlachter']."".$col2.",".$bg2; + $link[] = "".$col2.",".$bg2."letztes update ".$col3.",".$bg3."".$date."".$col2.",".$bg2." um ".$col3.",".$bg3."".$time."".$col2.",".$bg2; + for ($i=0;$i ".$site." ["; + if ($page!=1) { + $page_link .= "  «  "; + } + + if ($page>=6) { + $page_link .= "  ..."; + } + + $pagex = ($page+4>=$pages) ? $pages : $page+4; + + for($i=$page-4 ; $i<=$pagex ; $i++) { + if($i<=0) $i=1; + if($i==$page) { + $page_link .= "  $i"; + } else { + $page_link .= "  ".$i.""; + } + } + if(($pages-$page)>=5) { + $page_link .= "  ..."; + } + + if($page!=$pages && $pages != 0) { + $page_link .= "    »"; + } + $page_link .= "  ]"; + + return $page_link; +} // end func + +function formatmiliscanline($fleet,$showstatus=true) { + $line = ""; + if ($fleet['jaeger']) $line .= " ".$fleet['jaeger']." Jäger "; + if ($fleet['bomber']) $line .= " ".$fleet['bomber']." Bomber "; + if ($fleet['fregatten']) $line .= " ".$fleet['fregatten']." Fregatten "; + if ($fleet['zerstoerer']) $line .= " ".$fleet['zerstoerer']." Zerstörer "; + if ($fleet['kreuzer']) $line .= " ".$fleet['kreuzer']." Kreuzer "; + if ($fleet['schlachter']) $line .= " ".$fleet['schlachter']." Schlachter "; + if ($fleet['traeger']) $line .= " ".$fleet['traeger']." Träger "; + if ($fleet['kleptoren']) $line .= " ".$fleet['kleptoren']." Kleptoren "; + if ($fleet['cancris']) $line .= " ".$fleet['cancris']." Cancris "; + if($showstatus) { + if ($fleet['type']) { + $fleet['type'] = preg_replace("/(Angriff\w+)/i","$1",$fleet['type']); + $fleet['type'] = preg_replace("/(Verteidigung\w+)/i","$1",$fleet['type']); + $fleet['type'] = preg_replace("/(Rück\w+)/i","$1",$fleet['type']); + $status[] = $fleet['type']; + } + if ($fleet['dir']) $status[] = "".$fleet['dir'].""; + if (!$fleet['type'] && !$fleet['dir']) $status[] = "n/a"; + $line .= " <".join(" ",$status).">"; + } + return $line; +} + +function _format_irc_miliscanline($fleet,$printstatus=true){ + $col2 = "01"; + $bg2 = "14"; + $col3 = "15"; + $bg3 = "14"; + + $col1 = "01"; + $bg1 = "07"; + $color1 = "".$col3.",".$bg3; + $color2 = "".$col2.",".$bg2; + $items = array ("Jäger"=>"jaeger","Bomber"=>"bomber","Fregatten"=>"fregatten","Zerstörer"=>"zerstoerer","Kreuzer"=>"kreuzer", + "Schlachter"=>"schlachter","Träger"=>"traeger","Kleptoren"=>"kleptoren","Cancris"=>"cancris"); + $line = array(); + foreach($items as $key => $val){ + if($fleet[$val]) { + $line[] = $color1.$fleet[$val].$color2." $key"; + } + } + $line = join(" ",$line); + if($printstatus) { + if ($fleet['type']) { + $fleet['type'] = preg_replace("/(Angriff\w+)/i", "04,".$bg2."$1".$color2,$fleet['type']); + $fleet['type'] = preg_replace("/(Verteid\w+)/i", "09,".$bg2."$1".$color2,$fleet['type']); + $fleet['type'] = preg_replace("/(Rück\w+)/i", "10,".$bg2."$1".$color2,$fleet['type']); + $status[] = $fleet['type']; + } + if ($fleet['dir']) $status[] = $fleet['dir']; + if (!$fleet['type'] && !$fleet['dir']) $status[] = "N/A"; + $line .= " $color1<".join(" ",$status).">$color2"; + } + return $line; +} + +function generateirclink($scan,$popup=false) { + + $col2 = "01"; + $bg2 = "14"; + $col3 = "15"; + $bg3 = "14"; + + + $col1 = "01"; + $bg1 = "07"; + + if ($scan['hassector']) { + #$scan['punkte'] = substr_replace(strrev(chunk_split(strrev($scan['punkte']),3,'.')),'',0,1); + $link = array(); + $link[] = "".$col1.",".$bg1."NL SektorScan (".$scan['sector_prec']."%) ".$scan['nick']." (".$scan['gala'].":".$scan['pos'].")"; + $link[] = "".$col2.",".$bg2."Punkte: ".$col3.",".$bg3.$scan['sector_punkte2']. + " ".$col2.",".$bg2."Asteroiden: ".$col3.",".$bg3.$scan['sector_roids']."".$col2.",".$bg2; + $link[] = "".$col2.",".$bg2."Schiffe: ".$col3.",".$bg3."".$scan['sector_ships']."". + $col2.",".$bg2." Geschütze: ".$col3.",".$bg3."".$scan['sector_deff']; + $link[] = "".$col2.",".$bg2."Metall-Exen: ".$col3.",".$bg3."".$scan['sector_metall']."". + $col2.",".$bg2." Kristall-Exen: ".$col3.",".$bg3."".$scan['sector_kristall']."".$col2.",".$bg2; + $link[] = "".$col1.",".$bg1."Alter: ".$scan['sector_scanage']." "; + $scan['sector_link'] = urlencode(join("
    ",$link)."
    "); + $scan['sector_copy'] = join("\\n",$link)."\\n"; + } + if ($scan['hasunit']) { + $link = array(); + $link[] = "".$col1.",".$bg1."NL Unitscan (".$scan['unit_prec']."%) ".$scan['nick']." (".$scan['gala'].":".$scan['pos'].")"; + $link[] = "".$col2.",".$bg2."Cleptoren: ".$col3.",".$bg3."".$scan['kleptoren']."".$col2.",".$bg2. + " Cancris: ".$col3.",".$bg3."".$scan['cancris']."".$col2.",".$bg2." Fregatten: ".$col3.",".$bg3."".$scan['fregatten']."".$col2.",".$bg2; + $link[] = "".$col2.",".$bg2."Zerstörer: ".$col3.",".$bg3."".$scan['zerstoerer']."".$col2.",".$bg2. + " Kreuzer: ".$col3.",".$bg3."".$scan['kreuzer']."".$col2.",".$bg2." Träger: ".$col3.",".$bg3."".$scan['traeger']."".$col2.",".$bg2; + $link[] = "".$col2.",".$bg2."Jäger: ".$col3.",".$bg3."".$scan['jaeger']."".$col2.",".$bg2. + " Bomber: ".$col3.",".$bg3."".$scan['bomber']."".$col2.",".$bg2." Schlachter: ".$col3.",".$bg3."".$scan['schlachter']."". + $col2.",".$bg2; + $link[] = "".$col1.",".$bg1."Alter: ".$scan['unit_scanage']." "; + + $scan['unit_link'] = urlencode(join("
    ",$link)."
    "); + $scan['unit_copy'] = join("\\n",$link)."\\n"; + } + if ($scan['hasgscan']) { + $link = array(); + $link[] = "".$col1.",".$bg1."NL Geschützscan (".$scan['gscan_prec']."%) ".$scan['nick']." (".$scan['gala'].":".$scan['pos'].")"; + $link[] = "".$col2.",".$bg2."Horus: ".$col3.",".$bg3."".$scan['gscan_horus']."".$col2.",".$bg2. + " Rubium: ".$col3.",".$bg3."".$scan['gscan_rubium']."".$col2.",".$bg2."".$col2.",".$bg2. + " Pulsar: ".$col3.",".$bg3."".$scan['gscan_pulsar']."".$col2.",".$bg2." Coon: ".$col3.",".$bg3."".$scan['gscan_coon']."". + $col2.",".$bg2." Centurion: ".$col3.",".$bg3."".$scan['gscan_centurion']."".$col2.",".$bg2; + $link[] = "".$col1.",".$bg1."Alter: ".$scan['gscan_scanage']." "; + + $scan['gscan_link'] = urlencode(join("
    ",$link)."
    "); + $scan['gscan_copy'] = join("\\n",$link)."\\n"; + } + if ($scan['hasnews']) { + $link = array(); + $link[] = "".$col1.",".$bg1."NL Newsscan (".$scan['news_prec']."%) ".$scan['nick']." (".$scan['gala'].":".$scan['pos'].")"; + $newsdata = $scan['news_newsdata']; + $newsdata = preg_replace("/Verteidigung/i","\x02\x0309,".$bg2."Verteidigung\x03$col2,$bg2\x02",$newsdata); + $newsdata = preg_replace("/Angriff/i","\x02\x0304,".$bg2."Angriff\x03$col2,$bg2\x02",$newsdata); + $newsdata = preg_replace("/Rückzug/i","\x02\x0310,".$bg2."Rückzug\x03$col2,$bg2\x02",$newsdata); + $newsdata = preg_replace("/Ankunft:/i","\x02Ankunft:\x02",$newsdata); + $newsdata = preg_replace("/Heute/i","\x02Heute\x02",$newsdata); + $newsdata = preg_replace("/[\f\r\t]/is","",$newsdata); + foreach ( split("\n",$newsdata) as $line){ + $link[] = "".$col2.",".$bg2.$line; + } + $link[] = "".$col1.",".$bg1."Alter: ".$scan['news_scanage']." "; + + $scan['news_link'] = urlencode(join("
    ",$link)."
    "); + $scan['news_copy'] = join("\\n",$link)."\\n"; + } + if ($scan['hasmili']) { + $link = array(); + $link[] = "".$col1.",".$bg1."NL Miliscan (".$scan['mili_prec']."%) ".$scan['nick']." (".$scan['gala'].":".$scan['pos'].")"; + $link[] = "".$col2.",".$bg2."Orbit "._format_irc_miliscanline($scan['mili_fleets'][0],false); + $link[] = "".$col2.",".$bg2."Flotte 1: "._format_irc_miliscanline($scan['mili_fleets'][1]); + $link[] = "".$col2.",".$bg2."Flotte 2: "._format_irc_miliscanline($scan['mili_fleets'][2]); + $link[] = "".$col1.",".$bg1."Alter: ".$scan['mili_scanage']." "; + + $scan['mili_link'] = urlencode(join("
    ",$link)."
    "); + $scan['mili_copy'] = join("\\n",$link)."\\n"; + } + return $scan; +} + +function searchArray($key,$value,$array) { + for ($i=0;$i < count($array);$i++) { + if ($array[$i][$key] == $value){ + return $array[$i]; + } + } + return; +} + +# liefert einen String mit den werten des arrys mit kommas getrennt + +function getSQLArray($array){ + $s = ""; + if (count($array)){ + $s = $array[0]; + for($i=1;$i < count($array);$i++){ + $s .= ",".$array[$i]; + } + $s = "(".$s.")"; + } + return $s; +} + +function getArrayFromList($list,$key=0){ + $return = array(); + if ($list) { + for($i=0;$i < count($list);$i++){ + if (isset($list[$i][$key])) { + $return[] = $list[$i][$key]; + } + } + } + return $return; +} + +function gnticktime($eta) { + //$diff = $eta % 15 - 15 + date("i") % 15; + $mod1 = $eta % 15; + if($mod1) $mod1 = 15 - $mod1; + $mod2 = date("i") % 15; + $diff = $mod2 - $mod1; + $eta = $eta - $diff; + return $eta; +} + +function gnarrival($eta) { + return mktime(date("H"),date("i") + gnticktime($eta)+1,0,date("m"),date("d"),date("Y")); +} + +function getScanAge($time) { + $duration = time() - $time; + $stunden = floor($duration / 3600); + $duration = $duration % 3600; + $minuten = floor($duration / 60); + return sprintf("%02d:%02d h",$stunden,$minuten); +} + +?> diff --git a/src/functions/gnsimu.php b/src/functions/gnsimu.php new file mode 100644 index 0000000..56125a7 --- /dev/null +++ b/src/functions/gnsimu.php @@ -0,0 +1,438 @@ +name[0] = "Jäger"; + $this->attackpower[0] = array(0.0246, 0.392, 0.0263); // Wie viele Schiffe ein Schiff mit 100% Feuerkrafft zerstören würde + $this->shiptoattack[0] = array(11,1,4); // Welche Schiffe/Geschütze angegriffen werden + $this->percent[0] = array(0.35,0.30,0.35); // Die Verteilung der Prozente, mit der auf die Schiffe geschoßen wird. + $this->mcost[0] = 4000; + $this->kcost[0] = 6000; + + // Daten Für Bomber Nr. 1 + $this->attackpower[1] = array(0.0080,0.0100,0.0075); + $this->shiptoattack[1] = array(12,5,6); + $this->percent[1] = array(0.35,0.35,0.30); + $this->name[1] = "Bomber"; + $this->mcost[1] = 2000; + $this->kcost[1] = 8000; + + // Daten Für Fregatte Nr. 2 + $this->attackpower[2] = array(4.5,0.85); + $this->shiptoattack[2] = array(13,0); + $this->percent[2] = array(0.6,0.4); + $this->name[2] = "Fregatte"; + $this->mcost[2] = 15000; + $this->kcost[2] = 7500; + + // Daten Für Zerstörer Nr. 3 + $this->attackpower[3] = array(3.5,1.2444); + $this->shiptoattack[3] = array(9,2); + $this->percent[3] = array(0.6,0.4); + $this->name[3] = "Zerstörer"; + $this->mcost[3] = 40000; + $this->kcost[3] = 30000; + + // Daten Für Kreuzer Nr. 4 + $this->attackpower[4] = array(2.0,0.8571,10.0); + $this->shiptoattack[4] = array(10,3,8); + $this->percent[4] = array(0.35,0.30,0.35); + $this->name[4] = "Kreuzer"; + $this->mcost[4] = 65000; + $this->kcost[4] = 85000; + + // Daten Für Schalchtschiff Nr. 5 + $this->attackpower[5] = array(1.0,1.0666,0.4,0.3019,26.6667); + $this->shiptoattack[5] = array(11,4,5,6,8); + $this->percent[5] = array(0.2,0.2,0.2,0.2,0.2); + $this->name[5] = "Schlachtschiff"; + $this->mcost[5] = 250000; + $this->kcost[5] = 150000; + + // Daten Für Trägerschiff Nr. 6 + $this->attackpower[6] = array(25.0,14.0); + $this->shiptoattack[6] = array(7,8); + $this->percent[6] = array(0.5,0.5); + $this->mcost[6] = 200000; + $this->kcost[6] = 50000; + $this->name[6] = "Trägerschiff"; + + + // Daten für Kaperschiff + $this->mcost[7] = 1500; + $this->kcost[7] = 1000; + $this->name[7] = "Kaperschiff"; + + + // Daten für Schutzschiff + $this->mcost[8] = 1000; + $this->kcost[8] = 1500; + $this->name[8] = "Schutzschiff"; + + + // Daten Für Leichtes Obligtalgeschütz Nr. 9 + $this->attackpower[9] = array(0.3,1.28); + $this->shiptoattack[9] = array(0,7); + $this->percent[9] = array(0.6,0.4); + $this->mcost[9] = 6000; + $this->kcost[9] = 2000; + $this->name[9] = "Leichtes Orbitalgeschütz"; + + + // Daten Für Leichtes Raumgeschütz Nr. 10 + $this->attackpower[10] = array(1.2,0.5334); + $this->shiptoattack[10] = array(1,2); + $this->percent[10] = array(0.4,0.6); + $this->pretick[10] = array(0,0.5); + $this->pretickattack[10] = array(2); + $this->mcost[10] = 20000; + $this->kcost[10] = 10000; + $this->name[10] = "Leichtes Raumgeschütz"; + + + // Daten Für Mittleres Raumgeschütz Nr. 11 + $this->attackpower[11] = array(0.9143,0.4267); + $this->shiptoattack[11] = array(3,4); + $this->percent[11] = array(0.4,0.6); + $this->pretick[11] = array(0,0.5); + $this->pretickattack[11] = array(3,4); + $this->mcost[11] = 60000; + $this->kcost[11] = 100000; + $this->name[11] = "Mittleres Raumgeschütz"; + + + // Daten Für Schweres Raumgeschütz Nr. 12 + $this->attackpower[12] = array(0.5,0.3774); + $this->shiptoattack[12] = array(5,6); + $this->percent[12] = array(0.5,0.5); + $this->pretick[12] = array(0.2,0.6); + $this->pretickattack[12] = array(5,6); + $this->mcost[12] = 200000; + $this->kcost[12] = 300000; + $this->name[12] = "Schweres Raumgeschütz"; + + + // Daten Für Abfangjäger Nr. 13 + $this->attackpower[13] = array(0.0114,0.32); + $this->shiptoattack[13] = array(3,7); + $this->percent[13] = array(0.4,0.6); + $this->mcost[13] = 1000; + $this->kcost[13] = 1000; + $this->name[13] = "Abfangjäger"; + + for ($i=0;$i<14;$i++) { + $this->geslostshipsatt[$i] = 0; + $this->geslostshipsdeff[$i] = 0; + } + $this->getlostkristall[0] = 0; + $this->getlostkristall[1] = 0; + $this->getlostmetall[0] = 0; + $this->getlostmetall[1] = 0; + $this->gesstolenexenk = 0; + $this->gesstolenexenm = 0; + } + + + + function Compute($lasttick) // Dieses ist sie also die mytische Funktion, die Werte in äh ja äh andere Werte verwandeln kann. $lasttick dient dazu im letzten tick die Jäger und Bomber zu zerstören, die über sind. + { + // Wenn man tolle Debug informationen sehen will einfach auf 1 setzen + $debug = 0; + // "Sicherheitskopie" der Anzahl der Schiffe machen + for($i=0;$i<14;$i++) + { + $this->Olddeff[$i] = $this->deffending[$i]; + if($i<9) + $this->Oldatt[$i] = $this->attacking[$i]; + } + + //Schleife über alle Schiffe + for($i=0;$i<14;$i++) + { + //Variablen für das nächste Schiff "nullen" + $RestPercentatt = 0; + $Restpoweratt = $this->Oldatt[$i]; //Die Power ist gleich der Anzahl der Schiffe die angreifen + $OldRestpoweratt = 0; + $RestPercentdeff = 0; + $Restpowerdeff = $this->Olddeff[$i]; + $OldRestpowerdeff = 0; + $strike=0; + //Berechnen wie viele Strikes der aktuelle Schiffstyp hat(eins geteilet durch den kleinsten Prozentwert, mit dem das Schiff feuert und das ganz aufrunden und noch +3) + if($this->percent[$i]) + $curstrikes = ceil(1/min($this->percent[$i]))+3; + else + $curstrikes = 0; + while($strike < $curstrikes ) + { + if($debug) echo "Strike".($strike-$curstrikes)."
    "; + $OldRestpoweratt = $Restpoweratt; + $OldRestpowerdeff = $Restpowerdeff; + // Schleife über alle Schiffe die angeriffen werden sollen + for($j=0;$jattackpower[$i]);$j++) + { + if($debug) echo $this->name[$i]." gegen ".$this->name[$this->shiptoattack[$i][$j]]."
    "; + // Angreifer + if($Restpoweratt>0) + { + $del = 0; + // Dafür sorgen, dass nicht mit einem Prozentsatz von größer als 100% angerifen wird + if($RestPercentatt+$this->percent[$i][$j] > 1) + $RestPercentatt = 1.0 - $this->percent[$i][$j]; + // Maximale Zerstörung die Angerichtet werden kann. Die Power der Prozentsatz mal die Power der Schiffe mal wie viele Schiffe vom andern tyo von einem zerstört werden + $MaxDestruction = floor(($RestPercentatt+$this->percent[$i][$j]) * $OldRestpoweratt * $this->attackpower[$i][$j]); + if($debug) + { + echo "- Angreifende Schiffe: ".$this->Oldatt[$i]." Verteidigende Schiffe:".($this->deffending[$this->shiptoattack[$i][$j]])."
    "; + echo "- Maximale Zerstörung: floor(($RestPercentatt+".$this->percent[$i][$j].") * $OldRestpoweratt * ".$this->attackpower[$i][$j].")=$MaxDestruction
    "; + } + // Wie viele Schiffe dann zerstört werden, nich mehr als die maximale zerstörung und nich mehr als mit 100%(was oben eigentlich schon geprüft wird) und nich mehr als Schiffe noch über sind. + $del= floor(max(min($MaxDestruction, $Restpoweratt * $this->attackpower[$i][$j], $this->deffending[$this->shiptoattack[$i][$j]]), 0)); + // Im 4ten Strike wird unter bestimmten Umständen(s.u) der Prozentsatz, der beim feuern nicht zum Einsatz gekommen ist zu einer Variable addiert, die zum normalen Prozentsatz dazugerechnet wird. + if($strike==3) + { + // Wenn es das letzte Schiff im Tick ist oder keine Schiffe zerstört wurden wird Rest-Prozent um den Prozentsatz, der nich verbraucht wird erhöht. + // Alles könnte schön und gut sein, wenn da nicht die Schlachter wären, die flogen der Regel nämlich nur wenn sie auf sich selbst oder Kreuzer schießen, sonnst wird immer der Prozentsatz der nicht gebraucht wurde dazugerechnet, warum auch immer... + if ( $j == count($this->attackpower[$i])-1 || $del == 0 || ($i == 5 && $this->shiptoattack[$i][$j]!=5 && $this->shiptoattack[$i][$j]!=4)) + { + $RestPercentatt += $this->percent[$i][$j] - ($del / $OldRestpoweratt / $this->attackpower[$i][$j]); + } + } + // Benutze Feuerkraft berechnen und subtrahiren + $Firepower = $del/$this->attackpower[$i][$j]; + $Restpoweratt -= $Firepower; + // Schiffe zerstören + $this->deffending[$this->shiptoattack[$i][$j]] -=$del; + $this->geslostshipsdeff[$this->shiptoattack[$i][$j]] += $del; + $this->getlostmetall[1] += ($del*$this->mcost[$this->shiptoattack[$i][$j]]); + $this->getlostkristall[1] += ($del*$this->kcost[$this->shiptoattack[$i][$j]]); + if($debug) + { + echo "- Zerstörte Schiffe: $del
    + - Benutzte Firepower = $del/".$this->attackpower[$i][$j]." = $Firepower; Restpower = $Restpoweratt
    "; + } + } + // Nochmal genau das selbe nur mit Angreifer/Verteidiger vertauschten Variablen. + if($Restpowerdeff>0) + { + $del = 0; + if($RestPercentdeff+$this->percent[$i][$j] > 1) + $RestPercentdeff = 1.0 - $this->percent[$i][$j]; + $MaxDestruction = floor(($RestPercentdeff+$this->percent[$i][$j]) * $OldRestpowerdeff * $this->attackpower[$i][$j]); + if($debug) + { + echo "- Angreifende Schiffe: ".$this->Olddeff[$i]." Verteidigende Schiffe:".($this->attacking[$this->shiptoattack[$i][$j]])."
    "; + echo "- Maximale Zerstörung: floor(($RestPercentdeff+".$this->percent[$i][$j].") * $OldRestpowerdeff * ".$this->attackpower[$i][$j].")=$MaxDestruction
    "; + } + $del= floor(max(min($MaxDestruction, $Restpowerdeff * $this->attackpower[$i][$j], $this->attacking[$this->shiptoattack[$i][$j]]), 0)); + if($strike==3) + { + if ( $j == count($this->attackpower[$i])-1 || $del == 0 || ($i == 5 && $this->shiptoattack[$i][$j]!=5 && $this->shiptoattack[$i][$j]!=4)) + { + $RestPercentdeff += $this->percent[$i][$j] - ($del / $OldRestpowerdeff / $this->attackpower[$i][$j]); + } + } + $Firepower = $del/$this->attackpower[$i][$j]; + $Restpowerdeff -= $Firepower; + $this->attacking[$this->shiptoattack[$i][$j]] -= $del; + $this->geslostshipsatt[$this->shiptoattack[$i][$j]] += $del; + $this->getlostmetall[0] += $del*$this->mcost[$this->shiptoattack[$i][$j]]; + $this->getlostkristall[0] += $del*$this->kcost[$this->shiptoattack[$i][$j]]; + if($debug) + { + echo "- Zerstörte Schiffe: $del
    + - Benutzte Firepower = $del/".$this->attackpower[$i][$j]." = $Firepower; Restpower = $Restpowerdeff
    "; + } + } + } + $strike++; + } + } + //Wenn wir im letzen Tick sind wird geprüft ob auch alle Jäger und Bomber mit nach hause fliegn dürfen + + if($lasttick) + { + $jaeger = $this->attacking[0]; + $bomber = $this->attacking[1]; + $traeger = $this->attacking[6]; + if ( $bomber + $jaeger > $traeger*100) + { + $todel = $jaeger + $bomber - $traeger*100; + $deletejaeger = round($todel*($jaeger/($jaeger + $bomber))); + $deletebomber = round($todel*($bomber/($jaeger + $bomber))); + $this->attacking[0] -= $deletejaeger; + $this->attacking[1] -= $deletebomber; + + $this->geslostshipsatt[0] += $deletejaeger; + $this->geslostshipsatt[1] += $deletebomber; + + $this->getlostmetall[0] += $deletejaeger*$this->mcost[0]; + $this->getlostkristall[0] += $deletejaeger*$this->kcost[0]; + $this->getlostmetall[0] += $deletebomber*$this->mcost[1]; + $this->getlostkristall[0] += $deletebomber*$this->kcost[1]; + } + } + //Dann noch mal eben schnell paar exen klauen + //Erstmall ausrechnen, wie viele maximal mitgenommen werden können, bin der Meinung mal Iregndwo im Forum gelesen zu haben, dass Metall- auf- und Kristallexen abgerundet werden + $maxmexen = ceil((max($this->attacking[7]-$this->deffending[8],0))/2); + $maxkexen = floor((max($this->attacking[7]-$this->deffending[8],0))/2); + + //Dann wie viele Metallexen in den meißten fällen geklaut würden + $rmexen = min($maxmexen, floor($this->mexen*0.1)); + + + //Wenn nich alle Schiffe, die für Metallexenlau bereitgestellt waren benutz werden, dürfen diezum Kristallexen klauen Benutzt werden + if($rmexen != $maxmexen) + $maxkexen += $maxmexen-$rmexen; + + //Kristallexen in den meißten fällen + $rkexen = min($maxkexen, floor($this->kexen*0.1)); + + // Wenn nich alle zum Kristallexen bereitgestellten Cleps benutzt wurden, rechnen wir nochmal Metallexen ob nich evtl mehr mit genommen werden können. + if($rkexen != $maxkexen) + { + $maxmexen += $maxkexen-$rkexen; + $rmexen = min($maxmexen, floor($this->mexen*0.1)); + } + + + // Exen vom bestand abziehen und auch die benutzen Cleps "zerstören" + $this->mexen -=$rmexen; + $this->kexen -=$rkexen; + $this->attacking[7] -= $rmexen+$rkexen; + $this->geslostshipsatt[7] += $rmexen+$rkexen; + + $this->getlostmetall[0] += ($rmexen+$rkexen)*$this->mcost[7]; + $this->getlostkristall[0] += ($rmexen+$rkexen)*$this->kcost[7]; + + //Für die Statistik, wie viele Exen insgesammt gestohlen wurden. + $this->gesstolenexenm+=$this->stolenmexen = $rmexen; + $this->gesstolenexenk+=$this->stolenkexen = $rkexen; + } + + function vorticks($pretick=0) // berechnet die Vorticks + { + // Wenn man tolle Debug informationen sehen will einfach auf 1 setzen + $debug = 0; + if (!$pretick) $pretick=0; + + // "Sicherheitskopie" der Anzahl der Schiffe machen + for($i=0;$i<14;$i++) + { + $this->Olddeff[$i] = $this->deffending[$i]; + if($i<9) + $this->Oldatt[$i] = $this->attacking[$i]; + $tempattack[$i] = $this->attacking[$i]; + } + + //Schleife über Geschütze mit Preticks + for($i=10;$i<13;$i++) + { + unset($templost); + if (!$this->pretick[$i][$pretick]) continue; + //Variablen für das nächste Schiff "nullen" + $RestPercentatt = 0; + $Restpoweratt = $this->Oldatt[$i]; //Die Power ist gleich der Anzahl der Schiffe die angreifen + $OldRestpoweratt = 0; + $RestPercentdeff = 0; + $Restpowerdeff = $this->Olddeff[$i]; + $OldRestpowerdeff = 0; + $strike=0; + //Berechnen wie viele Strikes der aktuelle Schiffstyp hat(eins geteilet durch den kleinsten Prozentwert, mit dem das Schiff feuert und das ganz aufrunden und noch +3) + if($this->percent[$i]) + $curstrikes = ceil(1/min($this->percent[$i]))+3; + else + $curstrikes = 0; + while($strike < $curstrikes ) + { + if($debug) echo "Strike".($strike-$curstrikes)."
    "; + $OldRestpoweratt = $Restpoweratt; + $OldRestpowerdeff = $Restpowerdeff; + // Schleife über alle Schiffe die angeriffen werden sollen + for($j=0;$jattackpower[$i]);$j++) + { + if($debug) echo $this->name[$i]." gegen ".$this->name[$this->shiptoattack[$i][$j]]."
    "; + if($Restpowerdeff>0) + { + $del = 0; + if($RestPercentdeff+$this->percent[$i][$j] > 1) + $RestPercentdeff = 1.0 - $this->percent[$i][$j]; + $MaxDestruction = floor(($RestPercentdeff+$this->percent[$i][$j]) * $OldRestpowerdeff * $this->attackpower[$i][$j]); + if($debug) + { + echo "- Angreifende Schiffe: ".$this->Olddeff[$i]." Verteidigende Schiffe:".($tempattack[$this->shiptoattack[$i][$j]])."
    "; + echo "- Maximale Zerstörung: floor(($RestPercentdeff+".$this->percent[$i][$j].") * $OldRestpowerdeff * ".$this->attackpower[$i][$j].")=$MaxDestruction
    "; + } + $del= floor(max(min($MaxDestruction, $Restpowerdeff * $this->attackpower[$i][$j], $tempattack[$this->shiptoattack[$i][$j]]), 0)); + if($strike==3) + { + if ( $j == count($this->attackpower[$i])-1 || $del == 0 || ($i == 5 && $this->shiptoattack[$i][$j]!=5 && $this->shiptoattack[$i][$j]!=4)) + { + $RestPercentdeff += $this->percent[$i][$j] - ($del / $OldRestpowerdeff / $this->attackpower[$i][$j]); + } + } + $Firepower = $del/$this->attackpower[$i][$j]; + $Restpowerdeff -= $Firepower; + $tempattack[$this->shiptoattack[$i][$j]] -= $del; + $templost[$this->shiptoattack[$i][$j]] += $del; + if($debug) + { + echo "- Zerstörte Schiffe: $del
    + - Benutzte Firepower = $del/".$this->attackpower[$i][$j]." = $Firepower; Restpower = $Restpowerdeff
    "; + } + } + } + $strike++; + } + for ($j=2;$j<7;$j++) { + $this->attacking[$j] -= floor($templost[$j] * $this->pretick[$i][$pretick]); + $this->geslostshipsatt[$j] += floor($templost[$j] * $this->pretick[$i][$pretick]); + } + } + $jaeger = $this->attacking[0]; + $bomber = $this->attacking[1]; + $traeger = $this->attacking[6]; + if ( $bomber + $jaeger > $traeger*100) + { + $todel = $jaeger + $bomber - $traeger*100; + $deletejaeger = round($todel*($jaeger/($jaeger + $bomber))); + $deletebomber = round($todel*($bomber/($jaeger + $bomber))); + $this->attacking[0] -= $deletejaeger; + $this->attacking[1] -= $deletebomber; + + $this->getlostmetall[0] += $deletejaeger*$this->mcost[0]; + $this->getlostkristall[0] += $deletejaeger*$this->kcost[0]; + $this->getlostmetall[0] += $deletebomber*$this->mcost[1]; + $this->getlostkristall[0] += $deletebomber*$this->kcost[1]; + } + $this->stolenmexen = 0; + $this->stolenkexen = 0; + } +} + +?> \ No newline at end of file diff --git a/src/functions/index.class.php b/src/functions/index.class.php new file mode 100644 index 0000000..4309c93 --- /dev/null +++ b/src/functions/index.class.php @@ -0,0 +1,449 @@ +action]) { + eval("\$this->".$functions[$this->action].";"); + } + #default + $this->_News_list(); + } + + function highscore_list() { + $page = param_num("page",1); + $show = param_str("show"); + if($show == "day") { + $highscore['list'] = highscore_list(array("hours"=>24),&$pages,&$page); + $highscore['title'] = "Meisten Punkte in den letzten 24 Stunden"; + } elseif($show =="week") { + $highscore['list'] = highscore_list(array("days"=>7),&$pages,&$page); + $highscore['title'] = "Meisten Punkte in der letzten Woche"; + } else { + $highscore['list'] = highscore_list(null,&$pages,&$page); + $highscore['title'] = "Komplette Übersicht"; + } + $this->template->assign('pages',showPageBar($page,$pages,"index.php?action=highscore&show=$show","page","menu")); + $this->template->assign('page',$page); + $this->template->assign('highscore',$highscore); + $this->show('highscore_index','Highscoreliste'); + } + + function Scanner_list() { + $this->template->assign('mililist',user_get_scannerlist(1,10)); + $this->template->assign('newslist',user_get_scannerlist(0,10)); + $this->show('scanner_list','Nachrichten'); + } + + # + # Newsliste + # + function _News_list() { + $page = param_num("page",1); + $newslist = listNews(&$pages,&$page); + for ($i=0;$iuserdata['rights']['news']) { + $this->forms['newslist']['canedit'] = 1; + } + $this->forms['newslist']['pages'] = showPageBar($page,$pages,"index.php","page","menu"); + $this->template->assign('page',$page); + $this->template->assign('newslist',$newslist); + $this->template->assign('title','Nachrichten'); + $this->show('news_list','Nachrichten'); + } + + # + # listet die Member auf + # + function _Member_list() { + $page = param_num("page",1); + $rows = 12; + + $filter = $_SESSION['memberfilter']; + if (!$filter){ + $filter['sort'] = "koords"; + $filter['order'] = "asc"; + $filter['page'] = 1; + $_SESSION['memberfilter'] = $filter; + } + if ($_REQUEST['sort'] && $_REQUEST['order']) { + $filter['sort'] = $_REQUEST['sort']; + $filter['order'] = $_REQUEST['order']; + $_SESSION['memberfilter'] = $filter; + } + if($_POST['send']) { + if ($_POST['ally'] && is_numeric($_POST['ally']) + && getAlly($_POST['ally'])) { + $filter['ally'] = $_POST['ally']; + } else { + unset($filter['ally']); + } + $_SESSION['memberfilter'] = $filter; + } + $sort[$filter['sort']][$filter['order']] = '_active'; + + $allylist = getAllyList(); + if ($filter['ally']) { + for($i=0;$i < count($allylist);$i++){ + if ($allylist[$i]['aid'] == $filter['ally']) { + $allylist[$i]['selected'] = "selected"; + break; + } + } + } else { + $this->template->assign("ally0","selected"); + } + + + $userlist = listUser($filter,&$pages,&$page,$rows); + $this->template->assign("pages",showPageBar($page,$pages,"index.php?action=members","page","menu")); + $setback = "index.php?action=members&page=".$page."&".$this->session['link']; + $_SESSION['setback'] = $setback; + $this->template->assign("sort",$sort); + $this->template->assign('userlist',$userlist); + $this->template->assign('allylist',$allylist); + $this->show('member_list','Memberliste'); + } + + # + # fügt neue Nachrichten hinzu + # + function _News_add() { + if (!$this->userdata['rights']['news']) { + $this->_header("index.php"); + } + $data = $_SESSION['steps']; + $page = param_num("page",1); + #information message, step 2 + if ($data['addnews']) { + #save step + unset($data['addnews']); + $_SESSION['steps'] = $data; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['title'] = "Nachrichten hinzufügen"; + $this->forms['information']['message'] = "Nachricht hinzugefügt"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Nachrichten hinzufügen"); + } + #addnews, step 1 + #formular send + if ($_REQUEST['send']) { + if ($_REQUEST['next_x']) { + $items['title'] = param_str("title",true); + $items['message'] = param_str("message",true); + $errors = false; + #check if empty + foreach ( $items as $key => $value) { + if (!$value) { + $this->forms['addnews']['fields'][$key]['error'] = 'Feld darf nicht leer sein!'; + $this->forms['addnews']['fields'][$key]['bgrd'] = '_error'; + $errors = true; + } else { + $this->forms['addnews']['fields'][$key]['value'] = $value; + } + } + if (!$errors) { + #save step + $data['addnews'] = 1; + $_SESSION['steps'] = $data; + $id = addnews($items['title'],editpostdata($items['message']),$this->userdata['uid']); + addToLogfile("Nachricht ".$items['title']." hinzugefügt", + "News",$this->userdata['uid']); + $this->_header("index.php?action=addnews&send"); + } + } else { + $this->_header("index.php?page=".$page); + } + } + $this->forms['addnews']['name'] = $return['name']; + $this->forms['addnews']['url'] = "index.php"; + $this->forms['addnews']['action'] = 'addnews'; + $this->template->assign("backlink",$this->backtracking->backlink()); + $this->show('news_add_form',"Nachricht hinzufügen"); + } + # + # bearbeitet eine Nachricht + # + function _News_edit() { + if (!$this->userdata['rights']['news']) { + $this->_header("index.php"); + } + $id = param_num("id"); + if (!$id) $this->_header("index.php"); + $newsdata = getNews($id); + if (!$newsdata) $this->_header("index.php"); + $page = param_num("page",1); + $data = $_SESSION['steps']; + #information message, step 2 + if ($data['editnews']) { + #save step + unset($data['editnews']); + $_SESSION['steps'] = $data; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['title'] = "Nachrichten bearbeiten"; + $this->forms['information']['message'] = "Nachricht erfolgreich bearbeitet"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Nachrichten bearbeiten"); + } + #editnews, step 1 + #formular send + if ($_REQUEST['send']) { + if ($_REQUEST['next_x']) { + $items['title'] = param_str("title",true); + $items['message'] = param_str("message",true); + $errors = false; + #check if empty + foreach ( $items as $key => $value) { + if (!$value) { + $this->forms['editnews']['fields'][$key]['error'] = 'Feld darf nicht leer sein!'; + $this->forms['editnews']['fields'][$key]['bgrd'] = '_error'; + $errors = true; + } else { + $this->forms['editnews']['fields'][$key]['value'] = $value; + } + } + #optional parameters + if (!$errors) { + #save step + $data['editnews'] = 1; + $_SESSION['steps'] = $data; + addToLogfile("Nachricht ".$newsdata['title']." bearbeitet", + "News",$this->userdata['uid']); + updatenews($newsdata['nid'],$items['title'], + editpostdata($items['message']),$this->userdata['uid']); + $this->_header("index.php?action=editnews&id=".$newsdata['nid']."&send"); + } + } + } else { + $this->forms['editnews']['fields']['message']['value'] = editdbdata($newsdata['content']); + $this->forms['editnews']['fields']['title']['value'] = editdbdata($newsdata['title']); + } + $this->forms['editnews']['url'] = "index.php?id=".$newsdata['nid']; + $this->forms['editnews']['action'] = 'editnews'; + $this->show('news_edit_form',"Nachricht bearbeiten"); + } + # + # löscht eine Nachricht + # + function _News_delete() { + if (!$this->userdata['rights']['news']) { + $this->_header("index.php"); + } + $data = $_SESSION['steps']; + $page = param_num("page",1); + #information message, step 2 + if ($data['deletenews']) { + #save step + unset($data['deletenews']); + $_SESSION['steps'] = $data; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['title'] = "Nachrichten löschen"; + $this->forms['information']['message'] = "Nachricht erfolgreich gelöscht"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Nachrichten löschen"); + } + $id = param_num("id"); + if (!$id) $this->_header("index.php"); + $return = getNews($id); + if (!$return) $this->_header("index.php"); + #deletenews, send + if ($_REQUEST['send']) { + if ($_REQUEST['yes_x']) { + addToLogfile("Nachricht ".$return['title']." gelöscht","News", + $this->userdata['uid']); + deletenews($return['nid']); + #save step + $data['deletenews'] = 1; + $_SESSION['steps'] = $data; + $this->_header("index.php?action=deletenews&send"); + } else { + $this->_header($this->backtracking->backlink()); + } + } else { + $this->forms['information']['url'] = "index.php?id=".$return['nid']."&page=".$page; + $this->forms['information']['action'] = "deletenews"; + $this->forms['information']['title'] = "Nachricht löschen"; + $this->forms['information']['message'] = "Nachricht ".$return['title']." löschen ?"; + $this->forms['information']['style'] = "red"; + $this->show('message_question', "Nachricht löschen"); + } + } + # + # list Comments + # + function _Comment_list() { + $id = param_num("id"); + if (!$id) $this->_header("index.php"); + $newsdata = getNews($id); + if (!$newsdata) $this->_header("index.php"); + $newsdata['content'] = formatTextData($newsdata['content']); + + $page = param_num("page",1); + $comrows = 6; + #commentlist + $comlist = listNewsComments($id,&$pages,&$page,$comrows); + for ($i=0;$iuserdata['rights']['news']) { + $this->template->assign('canedit',1); + } + $this->forms['comlist']['pages'] = + showPageBar($page,$pages,"index.php?action=comments&id=".$id + ,"page","menu"); + + $this->template->assign('comlist',$comlist); + $this->template->assign('news',$newsdata); + $this->template->assign('page',$page); + $this->show('com_list', "Kommentare"); + } + + # + # add Comment + # + function _Comment_add() { + $nid = param_num("nid"); + if (!$nid) $this->_header("index.php"); + $newsdata = getNews($nid); + if (!$newsdata) $this->_header("index.php"); + + $comrows = 6; + + $data = $_SESSION['steps']; + #information message, step 2 + if ($data['addcom']) { + #save step + unset($data['addcom']); + $_SESSION['steps'] = $data; + $pages = getNewsCommentsPages($nid,$comrows); + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['title'] = "Kommentar hinzufügen"; + $this->forms['information']['message'] = "Kommentar hinzugefügt"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Kommentar hinzufügen"); + } + #formular send + if ($_REQUEST['send']) { + if ($_REQUEST['next_x']) { + $items['message'] = param_str("message",true); + $errors = false; + #check if empty + foreach ( $items as $key => $value) { + if (!$value) { + $this->forms['addcom']['fields'][$key]['error'] = 'Feld darf nicht leer sein!'; + $this->forms['addcom']['fields'][$key]['bgrd'] = '_error'; + $errors = true; + } else { + $this->forms['addcom']['fields'][$key]['value'] = $value; + } + } + #optional parameters + if (!$errors) { + #save step + $data['addcom'] = 1; + $_SESSION['steps'] = $data; + $id = addcom($nid,editPostdata($items['message']),$this->userdata['uid']); + addToLogfile("Kommentar zu News ".$newsdata['title']. + " hinzugefügt","News",$this->userdata['uid']); + $this->_header("index.php?action=addcom&nid=".$nid."&send"); + } + } else { + $this->_header($this->backtracking->backlink()); + } + } + $this->forms['addcom']['name'] = $return['name']; + $this->forms['addcom']['url'] = "index.php?nid=".$nid; + $this->forms['addcom']['action'] = 'addcom'; + $this->show('com_add_form',"Kommentar hinzufügen"); + } + + # + # delete Comment + # + function _Comment_delete() { + if (!$this->userdata['rights']['news']) { + $this->_header("index.php"); + } + $data = $_SESSION['steps']; + $nid = param_num("nid"); + $cid = param_num("cid"); + #information message, step 2 + if ($data['deletecom']) { + #save step + unset($data['deletecom']); + $_SESSION['steps'] = $data; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['action'] ="comments"; + $this->forms['information']['title'] = "Kommentar löschen"; + $this->forms['information']['message'] = "Kommentar erfolgreich gelöscht"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Kommentar löschen"); + } + if (!$cid) $this->_header($this->backtracking->backlink()); + $return = getNewsComment($cid); + if (!$return) $this->_header($this->backtracking->backlink()); + $newsdata = getNews($nid); + if (!$newsdata) $this->_header($this->backtracking->backlink()); + #deletecom, send + if ($_REQUEST['send']) { + if ($_REQUEST['yes_x']) { + addToLogfile("Kommentar bei ".$newsdata['title']." gelöscht","News", + $this->userdata['uid']); + deleteNewsCom($return['cid']); + #save step + $data['deletecom'] = 1; + $_SESSION['steps'] = $data; + $this->_header("index.php?action=deletecom&nid=".$nid."&send"); + } else { + $this->_header($this->backtracking->backlink()); + } + } else { + $this->forms['information']['url'] = "index.php?nid=$nid&cid=$cid"; + $this->forms['information']['action'] = "deletecom"; + $this->forms['information']['title'] = "Kommentar löschen"; + $this->forms['information']['message'] = "Kommentar löschen ?

    ". + formatTextData($return['content']); + $this->forms['information']['style'] = "black"; + $this->show('message_question', "Kommentar löschen"); + } + } +} +?> \ No newline at end of file diff --git a/src/functions/kibo.backtracking.php b/src/functions/kibo.backtracking.php new file mode 100644 index 0000000..8340344 --- /dev/null +++ b/src/functions/kibo.backtracking.php @@ -0,0 +1,50 @@ +uid = $uid; + parent::run(); + + } + + /** + * @return array + * @desc Liefert den Trackingbuffer + * @private + */ + function _get() { + $tracking = array(); + $result = selectsqlline("select backtracking from useronline where uid = ".$this->uid); + if($result['backtracking']) { + $tracking = split("\n",$result['backtracking']); + } + return $tracking; + } + + /** + * @return void + * @desc Schreibt den aktuellen Stack in die db + */ + function _refresh() { + query("update useronline set backtracking = '".join("\n",$this->backlinks)."' where uid = ".$this->uid); + } + +} +?> \ No newline at end of file diff --git a/src/functions/kibo.page.class.php b/src/functions/kibo.page.class.php new file mode 100644 index 0000000..c119089 --- /dev/null +++ b/src/functions/kibo.page.class.php @@ -0,0 +1,510 @@ +forms = array(); + $this->box = array(); + $this->userdata = array(); + + $this->backtracking = new kibo_backtracking($this->session); + + $this->version = "TIC 1.6b , Copyright by Huhn 2004,2005"; + $this->template->assign('version',$this->version); + + } + + function run() { + + parent::run(1); + + //loads Userdata from session + $this->_loadUserData(); + + //check loginstatus + if (!$this->userdata) { + //login + $this->_loginUser(); + } else { + //logout + if ($this->action == "logout") + { + $this->_logoutUser(); + } + $this->backtracking->run($this->userdata['uid']); + $this->template->assign("backlink",$this->backtracking->backlink()); + } + + //botrefresh + bot_refresh(); + //flotten refresh + fleetstatus_refresh(); + //user has to change pw + if ($this->userdata['changepw'] && $this->action != "changepwd") $this->_header("user.php?action=changepwd"); + + //checkt die incs auf undertime +// inc_check_undertime(); + //läd die Takscreenbox + $this->_loadTakscreenBox(); + //läd die Aktivitätsbox + $this->_loadActivityBox(); + //lädt die Flottenbox + $this->_loadFleetBox(); + //creates mainmenu + $this->_createMenu(); + } + + function _header($link="",$msg="") { + if(!$link) $link = $this->backtracking->backlink(); + parent::_header($link,$msg); + } + + # + # Zeigt die Seite an, lädt vorher die Content Boxen + # + function show($content,$title="") { + $this->box['mainbox']['template'] = $content.".html"; + $this->box['mainbox']['title'] = $title; + $this->template->assign('htmlpagetitle',$this->version." -- ".$title); + $this->template->assign('forms',$this->forms); + $this->template->assign('box',$this->box); + #show page + $this->template->display('index.html'); + exit(); + } + + # + # Zeigt eine Fehlerseite an + # + function show_error($content="Fehler",$title="Fehler") { + $this->template->assign('message',$content); + $this->show('error',$title); + } + + # + # lädt die Userdaten aus der Session + # + function _loadUserData () { + $data = $_SESSION['sessionuserdata']; + #check session UserData + if ($data) { + $return = getUserByID($data['id'],$data['password']); + if ($return) { + $this->userdata = $return; + updateUserOnline($this->userdata['uid']); + #load login/logout box, useronlinebox + refreshUserOnline(); + + $this->box['userbox']['title'] = 'Benutzerinfo'; + $this->box['userbox']['username'] = $this->userdata['nick']; + $this->box['userbox']['gala'] = $this->userdata['gala']; + $this->box['userbox']['pos'] = $this->userdata['pos']; + $this->box['userbox']['userid'] = $this->userdata['uid']; + $this->box['userbox']['template'] = 'box_userdata_content.html'; + + $this->box['useronline']['title'] = 'User Online'; + $list = listUserOnline(); + for($i=0;$i < count($list);$i++){ + $len = 11-strlen($list[$i]['gala'])-strlen($list[$i]['pos']); + if(strlen($list[$i]['nick'])>$len) { + $list[$i]['name'] = substr($list[$i]['nick'],0,$len).".."; + } else { + $list[$i]['name'] = $list[$i]['nick']; + } + } + $this->box['useronline']['list'] = $list; + $this->box['useronline']['template'] = 'box_useronline_content.html'; + + } else { + deleteUserOnline($this->userdata['uid']); + unset($_SESSION['sessionuserdata']); + unset($data); + } + } + } + + # + # lädt die Flottenbox + # + function _loadFleetBox() { + $list = user_fleet_list_byuser($this->userdata['uid']); + for($i=1;$i < 3;$i++){ + $item = $list[$i]; + if ($item['arrival']) { + $item['eta'] = $item['arrival']-time(); + $item['orbit'] = $item['ticks']*15*60; + if ($item['eta'] < 0) { + $item['orbit'] = $item['orbit'] + $item['eta']; + $item['eta'] = 0; + if ($item['orbit']< 0) $item['orbit'] = 0; + } + $item['eta'] = $this->formattime($item['eta'],true); + $item['orbit'] = $this->formattime($item['orbit'],true); + } + $item['num'] = $i; + $fleets[] = $item; + } + $this->box['fleets']['title'] = 'Flottenstatus'; + $this->box['fleets']['list'] = $fleets; + $this->box['fleets']['template'] = 'box_fleets_content.html'; + } + + # + # lädt die Takscreenbox + # + function _loadTakscreenBox() { + $this->box['takscreen']['title'] = 'Taktikschirm'; + $this->box['takscreen']['info'] = takscreen_info(); + $this->box['takscreen']['template'] = 'box_takscreen_content.html'; + } + + # + # lädt die Aktivitätsbox + # + function _loadActivityBox() { + $this->box['activity']['title'] = 'Aktivitätscheck'; + if(!($this->box['activity']['docheck'] = do_check_activity($this->userdata))) { + $this->box['activity']['nextcheck'] = date("H:i",$this->userdata['activity_check']+get_activity_timeout())." Uhr"; + } + if($this->userdata['activity_check']) { + $this->box['activity']['lastcheck'] = date("H:i d.m.Y",$this->userdata['activity_check']); + } else { + $this->box['activity']['lastcheck'] = "noch nie!"; + } + $this->box['activity']['points'] = $this->userdata['activity_points']; + $this->box['activity']['template'] = 'box_activity_content.html'; + } + + # + # Erstellt das Hauptmenu + # + function _createMenu() { + global $debug; + #selected menu + if ($_REQUEST['mod']) { + $_SESSION['mod'] = $_REQUEST['mod']; + } + + #create globalmenu + $entry = 0; + $menu[$entry] = array("caption" => "Startseite", "link" => "index.php?mod=index", "module" => "index","id" => $entry); + $menu[$entry]['items'] = array(); + $menu[$entry]['items'][] = array("caption" => "
    Member
    ", "link" => "index.php?action=members"); + $menu[$entry]['items'][] = array("caption" => "
    Scanner
    ", "link" => "index.php?action=scanner"); + $menu[$entry]['items'][] = array("caption" => "
    Highscore
    ", "link" => "index.php?action=highscore"); + + $entry++; + $menu[$entry] = array("caption" => "Taktikschirm", "link" => "takscreen.php?mod=takscreen", "module" => "takscreen","id" => $entry); + $menu[$entry]['items'][] = array("caption" => "
    Neuer Atter
    ", "link" => "takscreen.php?action=addatter"); + $menu[$entry]['items'][] = array("caption" => "
    Neuer Deffer
    ", "link" => "takscreen.php?action=adddeffer"); + $menu[$entry]['items'][] = array("caption" => "
    Miliparser
    ", "link" => "takscreen.php?action=miliparser"); + $menu[$entry]['items'][] = array("caption" => "
    Takscreenparser
    ", "link" => "takscreen.php?action=takparser"); + + $entry++; + $menu[$entry] = array("caption" => "Flottenpflege", "link" => "user.php?mod=fleets&action=fleets", "module" => "fleets","id" => $entry); + $menu[$entry]['items'][] = array("caption" => "
    Flottenparser
    ", "link" => "takscreen.php?action=fleetparser"); + + $entry++; + $menu[$entry] = array("caption" => "Simulator", "link" => "simulator.php?mod=simulator", "module" => "simulator","id" => $entry); + + $entry++; + $menu[$entry] = array("caption" => "Attplaner", "link" => "attplan.php?mod=attplan", "module" => "attplan","id" => $entry); + $menu[$entry]['items'][] = array("caption" => "
    Hinzufügen
    ", "link" => "attplan.php?action=add"); + + $entry++; + $menu[$entry] = array("caption" => "Scancenter", "link" => "scans.php?mod=scans", "module" => "scans","id" => $entry); + $menu[$entry]['items'][] = array("caption" => "
    Ziele suchen
    ", "link" => "scans.php?action=targets"); + $menu[$entry]['items'][] = array("caption" => "
    Hinzufügen
    ", "link" => "scans.php?action=add", "class" => "'admin'"); + + $entry++; + $menu[$entry] = array("caption" => "Allianz", "link" => "admin.php?action=ally&mod=ally", "module" => "ally", "admin" => true,"id" => $entry); + $menu[$entry]['rights'] = array("addally","deleteally","editallay"); + $menu[$entry]['items'][] = array( + "caption" => "
    Hinzufügen
    ", + "link" => "admin.php?action=addally", + "admin" => true, + "rights" => array("addally") + ); + + $entry++; + $menu[$entry] = array("caption" => "Galaxie", "link" => "admin.php?action=galaxy&mod=galaxy", "module" => "galaxy", "admin" => true,"id" => $entry); + $menu[$entry]['rights'] = array("addgala","deletegala","editgala"); + $menu[$entry]['items'][] = array( + "caption" => "
    Hinzufügen
    ", + "link" => "admin.php?action=addgala", + "admin" => true, + "rights" => array("addgala") + ); + $entry++; + $menu[$entry] = array("caption" => "Benutzer", "link" => "admin.php?action=user&mod=user", "module" => "user", "admin" => true,"id" => $entry); + $menu[$entry]['rights'] = array("useredit"); +# $menu[$entry]['items'][$item_entry]['rights'][] = "fleetedit"; + $menu[$entry]['items'][] = array( + "caption" => "
    Hinzufügen
    ", + "admin" => true, + "link" => "admin.php?action=adduser", + "rights" => array("useredit") + ); + $menu[$entry]['items'][] = array( + "caption" => "
    Logfile
    ", + "admin" => true, + "link" => "admin.php?action=logfile", + "rights" => array("logfile","resetlogfile") + ); + $entry++; + $menu[$entry] = array("caption" => "Gruppen", "link" => "admin.php?action=groups&mod=groups", "module" => "groups", "admin" => true,"id" => $entry); + $menu[$entry]['rights'] = array("groupedit"); + $menu[$entry]['items'][] = array( + "caption" => "
    Hinzufügen
    ", + "admin" => true, + "link" => "admin.php?action=addgroup", + "rights" => array("groupedit") + ); + $menu[$entry]['items'][] = array( + "caption" => "
    Rechte
    ", + "admin" => true, + "link" => "admin.php?action=grouprights", + "rights" => array("groupedit") + ); + $entry++; + $menu[$entry] = array("caption" => "IRCBots", "link" => "admin.php?action=bots&mod=bots", "module" => "bots", "admin" => true, "rights" => array("bots"),"id" => $entry); + $menu[$entry]['items'][] = array( + "caption" => "
    Rechte
    ", + "admin" => true, + "link" => "admin.php?action=grouprights", + "rights" => array("groupedit") + ); + + $menucount = count($menu); + $open_menus = $_COOKIE['menuitems']; + if($open_menus) { + $open_menus = explode(",",$open_menus); + } else { + $open_menus = array(); + } + for($i = 0;$i < $menucount; $i++) { + if(!in_array($menu[$i]['id'],$open_menus)) { + $menu[$i]['closed'] = true; + } + if(count($menu[$i]['rights'])) { + #check rights for the menu + $hasright = false; + if(count($this->userdata['rights'])) { + for($j=0;$j < count($menu[$i]['rights']);$j++) { + if(array_key_exists($menu[$i]['rights'][$j],$this->userdata['rights'])) { + $hasright = true; + break; + } + } + } + #delete menu and submenus + if(!$hasright) {unset($menu[$i]);continue;} + } + #check submenus + if(count($menu[$i]['items'])) { + $items = &$menu[$i]['items']; + $itemcount = count($items); + for($j=0;$j < $itemcount;$j++) { + #check rights for the submenu + if(count($items[$j]['rights'])) { + $hasright = false; + if(count($this->userdata['rights'])) { + for($k=0;$k < count($items[$j]['rights']);$k++) { + if(array_key_exists($items[$j]['rights'][$k],$this->userdata['rights'])) { + $hasright = true; + break; + } + } + } + #delete submenu + if(!$hasright) {unset($items[$j]);continue;} + } + } + } + } + $this->box['menu']['template'] = 'menu.html'; + $this->box['menu']['title'] = 'Menu'; + $this->template->assign('menu',$menu); + } + + # + # User Login + # + + function _loginUser() { + if ($_POST['userlogin']) { + #check fields + $logindata['username'] = trim($_POST['login_username']); + $logindata['password'] = trim($_POST['login_password']); + $errors = false; + foreach ( $logindata as $key => $value) { + if (!$value) { + $this->forms['userlogin']['fields'][$key]['bgrd'] = '_error'; + $errors = true; + } else { + $this->forms['userlogin']['fields'][$key]['value'] = $value; + } + } + #empty fields + if ($errors) { + $this->forms['userlogin']['errormessage'] = "Feld leer!"; + } else { + $return = getUserByLogin($logindata['username'],$logindata['password']); + if (!$return || $return['activation']) { + #login wrong + $this->forms['userlogin']['errormessage'] = "Login/Passwort falsch!"; + addToLogfile("Login fehlgeschlagen, User ".$logindata['username'],"Login/Logout"); + } else { + #login ok + #save id and password in session + $sessionuserdata['id'] = $return['uid']; + $sessionuserdata['password'] = $return['password']; + $_SESSION['sessionuserdata'] = $sessionuserdata; + LoggedIn($return['uid']); + addToLogfile("Login","Login/Logout",$return['uid']); + setcookie('menuitems'); + $this->_header("index.php"); + } + } + } + $this->template->assign('title','Login'); + $this->template->assign('forms',$this->forms); + $this->template->display('index_login.html'); + exit(); + } + + # + # User Logout + # + function _logoutUser() { + addToLogfile("Logout","Login/Logout",$this->userdata['uid']); + deleteUserOnline($this->userdata['uid']); + unset($_SESSION['sessionuserdata']); + setcookie('menuitems'); + $this->_header("index.php"); + exit(); + } + # + # liefert null wenn der user das Recht nicht besitzt, sonst den minimalen rank + # + function _getMinRightRank($rights) { + $rank = null; + if ($this->userdata) { + if (is_array($rights)) { + for($i=0;$iuserdata['rights'][$rights[$i]]['rank'])) { + $rank[] = $this->userdata['rights'][$rights[$i]]['rank']; + } + } + if ($rank){ + $rank = min($rank); + } + } else { + $rank = $this->userdata['rights'][$rights]['rank']; + } + } + return $rank; + } + + # + # liefert TRUE wenn der User das Recht oder eins der Rechte hat + # (für Zugangscheck) + # param $rights = right|array of rights + # + function _checkUserRights($rights) { + if ($this->userdata) { + if (is_array($rights)) { + for($i=0;$iuserdata['rights'][$rights[$i]]) { + return true; + } + } + } else { + if ($this->userdata['rights'][$rights]) return true; + } + } + return false; + } + + function getTickList($ticks=1,$select=-1) { + $list=array(); + for($i=1;$i <= $ticks;$i++){ + if($select == $i) { + $list[] = array("value"=>$i,"title"=>$this->formattime($i*15*60,true), "selected" => "selected"); + } else { + $list[] = array("value"=>$i,"title"=>$this->formattime($i*15*60,true)); + } + } + return $list; + } + + function formattime($time,$string=false) { + if (!is_numeric($time)) return; + if($time >= 0) { + $switch = $this->userdata['timeview']; + } else { + $switch = 0; + } + switch ($switch) { + case 1: + $hour = floor($time/3600); + $minutes = floor(($time-$hour*3600)/60); + if ($hour < 10 && $hour > 0) $hour = "0".$hour; + if ($hour == 0) $hour = "00"; + if ($minutes < 10) $minutes = "0".$minutes; + $time = "$hour:$minutes"; + if ($string) $time .= " Std"; + break; + default: + $time = floor($time/60); + if ($string) $time .= " min"; + break; + } + return $time; + } + + function show_message($title,$message,$link,$class=null,$params=null) { + $this->template->assign( + array("title" => $title, + "message" => $message, + "link" => $link, + "class" => $class, + "params" => $params) + ); + $this->show('message',$title); + } +} +?> diff --git a/src/functions/logging.php b/src/functions/logging.php new file mode 100644 index 0000000..0763529 --- /dev/null +++ b/src/functions/logging.php @@ -0,0 +1,138 @@ +setEnabled($debug_firephp); +$options = array('maxObjectDepth' => 10, + 'maxArrayDepth' => 20, + 'useNativeJsonEncode' => false, + 'includeLineNumbers' => true); +$firephp->setOptions($options); +$firephp->registerExceptionHandler(); + +// we will do our own error handling +error_reporting(E_ALL & ~ E_NOTICE); + +// user defined error handling function +function userErrorHandler($errno, $errmsg, $filename, $linenum, $vars) { + global $firephp; + if(!(error_reporting() & $errno)) { + return; + } + //configparameter + global $debug, $error_log; +// $logger = & LoggerManager::getLogger("error"); + $dt = date("Y-m-d H:i:s (T)"); + + $errortype = array ( + + E_ERROR=>"Error", + E_WARNING=>"Warning", + E_PARSE=>"Parsing Error", + E_NOTICE=>"Notice", + E_CORE_ERROR=>"Core Error", + E_CORE_WARNING=>"Core Warning", + E_COMPILE_ERROR=>"Compile Error", + E_COMPILE_WARNING=>"Compile Warning", + E_USER_ERROR=>"User Error", + E_USER_WARNING=>"User Warning", + E_USER_NOTICE=>"User Notice", + E_STRICT=>"Runtime Notice" + ); + // set of errors for which a var trace will be saved + $user_errors = array (E_USER_ERROR, E_USER_WARNING, E_USER_NOTICE); + + $notices = array(E_NOTICE, E_USER_NOTICE,E_STRICT); + $warnings = array(E_WARNING,E_CORE_WARNING,E_COMPILE_WARNING,E_USER_WARNING); + + if($debug){ + $message = array(); + + $message[] = $errortype[$errno]; + + if (is_array(split("\n", $errmsg))) { + $errmsg = split("\n", $errmsg); + foreach ($errmsg as $line) { + $line = htmlspecialchars($line); + $message[] = "\t".$line; + } + } else { + $message[] = "\t".$errmsg; + } + $debug_tracking = debug_backtrace(); + if(is_array($debug_tracking) && count($debug_tracking) > 0) { + $message[] = "Caused by"; + foreach ($debug_tracking as $line) { + if((!isset($line["file"]) || substr($line["file"],-11,11) !== "logging.php") &&( + !isset($line["function"]) || $line["function"] !== "userErrorHandler" + )) { + $item = array(); + if ( isset ($line['file']))$item[] = $line['file']; + if ( isset ($line['class']))$item[] = $line['class']; + if ( isset ($line['function']))$item[] = $line['function']; + if ( isset ($line['line']))$item[] = $line['line']; + $message[] = "\t".join(":", $item); + } + } + } + if (in_array($errno, $user_errors)) { + $message[] = "variable trace:"; + $message[] = "\t".var_export($vars,true); + } + $message = join("\r\n",$message)."\r\n"; + //header("Content-Type: plain/text; charset=UTF-8"); + echo "
    ";
    +        echo $message;
    +        echo "
    "; + } + $message = array("type"=>$errortype[$errno],"message"=>$errmsg,"file"=>$filename,"line"=>$linenum,"vars"=>$vars); + $debug_tracking = debug_backtrace(); + if(is_array($debug_tracking) && count($debug_tracking) > 0) { + $message["trace"] = array(); + foreach ($debug_tracking as $line) { + if((!isset($line["file"]) || substr($line["file"],-11,11) !== "logging.php") &&( + !isset($line["function"]) || $line["function"] !== "userErrorHandler" + )) { + $item = array(); + if ( isset ($line['file']))$item[] = $line['file']; + if ( isset ($line['class']))$item[] = $line['class']; + if ( isset ($line['function']))$item[] = $line['function']; + if ( isset ($line['line']))$item[] = $line['line']; + $message["trace"][] = join(":", $item); + } + } + } + $logger = & LoggerManager::getLogger("error"); + if(in_array($errno, $notices)) { + //$firephp->info($message,$errortype[$errno]); + $logger->debug($message); + } else if(in_array($errno, $warnings)) { + $logger->warn($message); + //$firephp->warn($message,$errortype[$errno]); + } else { + $logger->fatal($message); +// $firephp->error($message,$errortype[$errno]); + $firephp->trace("fatal error stack trace"); + if(!$debug) { + //header("Content-Type: plain/text; charset=UTF-8"); + echo "
    ";
    +            echo "Es ist ein schwerwiegender Fehler im Skript aufgetreten, bitte wenden Sie sich an den Entwickler!";
    +            echo "
    "; + } + die(); + } + +} + +$old_error_handler = set_error_handler("userErrorHandler"); + +require_once(LOG4PHP_DIR . '/LoggerLog.php'); + +LoggerLog::internalDebugging($debug_logger); + +require_once(LOG4PHP_DIR . '/LoggerManager.php'); + +?> \ No newline at end of file diff --git a/src/functions/page.class.php b/src/functions/page.class.php new file mode 100644 index 0000000..faad0d0 --- /dev/null +++ b/src/functions/page.class.php @@ -0,0 +1,162 @@ +"; + if(is_array($msg)) { + var_dump($msg); + } else { + echo $msg."\n"; + } + if($tracking) { + $debug_tracking = debug_backtrace(); + for ($i=0;$i < $tracking;$i++) { + echo $debug_tracking[$i]['file'].":".$debug_tracking[$i]['line']."\n"; + } + } + echo ""; + } + + class Page { + /** + \brief Templateobjekt + + Smarty templateobjekt, hilfe unter http.smarty.php.net + */ + var $template; + /** + \brief Sessiondaten + + Sessiondaten als Array + */ + var $session; + + /** + \brief Aktion + + per GET oder POST übergebener "action" Parameter + */ + var $action; + + /** + \brief debugmodus + + true setzen für debugmodus AN + */ + var $debug; + + + /** + \brief Constructor + + Initialisiert das system. + */ + function Page () { + + //load Template Engine + $this->template = new Smarty(); + $this->template->plugins_dir = SMARTY_DIR."plugins/"; + if (!$this->template) $this->_error("Templateengine lässt sich nicht starten!"); + + //start session + $this->_startSession("ssid"); + + } + + function _error($msg) { + #$this->_dump($msg); + exit(); + } + + + # + # Run & Eventhandler + # + function run ($debug=0) { + + #debugmode + $this->debug = $debug; + $this->action = $_REQUEST["action"]; + } + + # + # Sendet einen Redirect Header + # + function _header($link,$message="") { + if(preg_match("/^(.*?)(#.*?)$/is",$link,$items)) { + $link = $items[1]; + $anker = $items[2]; + } + if (strpos($link,"?")) { + header("Location: ".$link."&".$this->session['link'].$anker); + } else { + header("Location: ".$link."?".$this->session['link'].$anker); + } + exit(); + } + + # + # startet die Session + # + function _startSession ($name="") { + #start session + if($name) session_name($name); + else $name = session_name(); + session_start(); + $this->session = array(); + $this->session['id'] = $_SESSION[$name]; + $this->session['name'] = $name; + if(!$this->session['id']) { + $this->session['id'] = $_REQUEST[$name]; + if (!$this->session['id']) { + $this->session['id'] = session_id(); + } + $_SESSION[$name] = $this->session['id']; + } + $this->session['link'] = "$name=".$this->session['id']; + $this->template->assign('session',$this->session); + } +} + +?> diff --git a/src/functions/parsing.php b/src/functions/parsing.php new file mode 100644 index 0000000..c020160 --- /dev/null +++ b/src/functions/parsing.php @@ -0,0 +1,1520 @@ + $key) { + $fleet[$key] = $subs[$i+1]; + } + return $fleet; + } else { + return false; + } +} + +# +# parst nach Flotteninfos +# +function parseFleet($line) { + $fleet_keys = array("jaeger","bomber","fregatten","zerstoerer","kreuzer","traeger","schlachter","kleptoren","cancris"); + $fleet = array(); + preg_match("/([\d,\.]+?)[^\d<]*?(?:Jäger|Jäg)/is",$line,$results); + if ($results[1]) $fleet['jaeger'] = $results[1]; + preg_match("/([\d,\.]+?)[^\d<]*?(?:Bomber|Bom)/is",$line,$results); + if ($results[1]) $fleet['bomber'] = $results[1]; + preg_match("/([\d,\.]+?)[^\d<]*?(?:Fregatten|Fre)/is",$line,$results); + if ($results[1]) $fleet['fregatten'] = $results[1]; + preg_match("/([\d,\.]+?)[^\d<]*?(?:Zerstörer|Zer)/is",$line,$results); + if ($results[1]) $fleet['zerstoerer'] = $results[1]; + preg_match("/([\d,\.]+?)[^\d<]*?(?:Kreuzer|Kre)/is",$line,$results); + if ($results[1]) $fleet['kreuzer'] = $results[1]; + preg_match("/([\d,\.]+?)[^\d<]*?(?:Träger|Trä|Trägerschiffe)/is",$line,$results); + if ($results[1]) $fleet['traeger'] = $results[1]; + preg_match("/([\d,\.]+?)[^\d<]*?(?:Schlachter|Ssch|Schlachtschiffe|Schl)/is",$line,$results); + if ($results[1]) $fleet['schlachter'] = $results[1]; + preg_match("/([\d,\.]+?)[^\d<]*?(?:Kleptoren|Clep|Kaperschiffe|Kaper|Kap)/is",$line,$results); + if ($results[1]) $fleet['kleptoren'] = $results[1]; + preg_match("/([\d,\.]+?)[^\d<]*?(?:Cancris|Schild|Schutz|Schutzschiffe|Schu)/is",$line,$results); + if ($results[1]) $fleet['cancris'] = $results[1]; + foreach($fleet_keys as $key) { + if($fleet[$key]) { + $fleet[$key] = preg_replace("/(?:\.|,)/is","",$fleet[$key]); + } + } + +/* if(preg_match("/[<\[]\s*?Im \s*?[>\]]/is",$line,$results)) { + $fleet['status'] = 0; + $fleet['return_flight'] = 0; + } elseif(preg_match("/[<\[]\s*?([^\s]+?)\s([^\s]+?)\s*?[>\]]/is",$line,$results)) { + $fleet['type'] = $results[1]; + $fleet['dir'] = $results[2]; + $type = strtolower($fleet['type']); + if($type == "angriffsflug") { + $fleet['status'] = 1; + $fleet['return_flight'] = 0; + }elseif($type == "verteidigungsflug") { + $fleet['status'] = 2; + $fleet['return_flight'] = 0; + }elseif($type == "rückflug") { + $fleet['status'] = 0; + $fleet['return_flight'] = 1; + } + }*/ + + if(preg_match("/[<\[]\s*?Orbit\s*?[>\]]/is",$line,$results)) { + $fleet['status'] = 0; + $fleet['return_flight'] = 0; + } elseif(preg_match("/[<\[]\s*?([^\s]+?)?\s([^\s]+?)?\s*?[>\]]/is",$line,$results)) { + $fleet['type'] = $results[1]; + $fleet['dir'] = $results[2]; + $type = strtolower($fleet['type']); + if($type == "angriffsflug") { + $fleet['status'] = 1; + $fleet['return_flight'] = 0; + }elseif($type == "verteidigungsflug") { + $fleet['status'] = 2; + $fleet['return_flight'] = 0; + }elseif($type == "rückflug") { + $fleet['status'] = 0; + $fleet['return_flight'] = 1; + } + } + +# echo "jäger: ".$fleet['jaeger']."
    "; +# echo "bomber: ".$fleet['bomber']."
    "; +# echo "fregatten: ".$fleet['fregatten']."
    "; + # echo "zerstoerer: ".$fleet['zerstoerer']."
    "; +# echo "kreuzer: ".$fleet['kreuzer']."
    "; +# echo "schlachter: ".$fleet['schlachter']."
    "; +# echo "träger: ".$fleet['traeger']."
    "; +# echo "kleptoren: ".$fleet['kleptoren']."
    "; +# echo "cancris: ".$fleet['cancris']."
    "; +# echo "type: ".$fleet['type']."
    "; +# echo "dir: ".$fleet['dir']."
    "; + return $fleet; +} + +function _deleteIrcTags($data) { + $data = preg_replace("/\x03\d{1,2},\d{1,2}/sm","",$data); + $data = preg_replace("/\x03\d{1,2}/sm","",$data); + $data = preg_replace("/\x02/sm","",$data); + $data = preg_replace("/\x0F/sm","",$data); + return $data; +} + +function removeColorAndFormat($data) { + $data = preg_replace("/\x03\d{1,2},\d{1,2}/sm","",$data); + $data = preg_replace("/\x03\d{1,2}/sm","",$data); + $data = preg_replace("/\x02/sm","",$data); + $data = preg_replace("/\x0F/sm","",$data); + $data = preg_replace("/\x03/sm","",$data); + return $data; +} + +# +# durchsucht einen textblock nach Scans +# +function parseScan($data) { +# $data=trim($data); + #lines + preg_match_all("/^(.*?)[\x0A]*$/sm",$data,$result,PREG_SET_ORDER); + #$colregex = "(?:\x03\d{1,2},\d{1,2}|)"; + + $scans = array(); + // parsing step + $step = 0; + $identregex = ""; + $type = ""; + $scan = array(); + + for($i=0;$i Punkte: 57.096.002 - Asteroiden: 63 +[23:11] Schiffe: 7.040 - Geschütze: 1.351 +[23:11] Metall-Exen: 515 - Kristall-Exen: 325 + */ + + if($type =="kerrigan_sector") { + switch ($step) { + case 1: + if(preg_match("/^".$identregex."Punkte:\s*?(.*?)\s\-\sAsteroiden:\s*?(\d+)/i",$nocolor,$line)) { + $scan['punkte'] = trim(preg_replace("/\./s","",$line[1])); + $scan['roids'] = trim($line[2]); + $step++; + } + continue; + break; + case 2: + if(preg_match("/^".$identregex."Schiffe:\s*?(.*?)\s\-\sGeschütze:\s*?(.*?)/i",$nocolor,$line)) { + $scan['ships'] = trim(preg_replace("/\./s","",$line[1])); + $scan['deff'] = trim(preg_replace("/\./s","",$line[2])); + $step++; + } + continue; + break; + case 3: + if(preg_match("/^".$identregex."Metall-Exen:\s*?(.*?)\s\-\sKristall-Exen:\s*?(\d+)/i",$nocolor,$line)) { + $scan['metall'] = trim($line[1]); + $scan['kristall'] = trim($line[2]); +// $step++; + $scans[] = $scan; + $step=0; + $type = ""; + + } + continue; + break; + + } + } + + + // kerrigan unit scan + + /* +Einheitenscan [100%] S4vi3r-.- [21:4] +Kaperschiffe: 4.500 - Schutzschiffe: 3.100 +Fregatten: 330 - Zerstörer: 0 - Kreuzer: 35 - Schlachtschiffe: 0 +Trägerschiffe: 30 - Jäger: 0 - Bomber: 0 +Res an 33:4 ; Alli nix , SC/PDX/NL 1x , Rest 2x , bis auf Lude , der 4x :p + */ + + if ($type == "kerrigan_unit") { + switch ($step) { + case 1: + //Kaperschiffe: 4.500 - Schutzschiffe: 3.100 + if(preg_match("/^".$identregex."Kaperschiffe:\s*?(.+)\s\-\sSchutzschiffe:\s*?(.+)/i",$nocolor,$line)) { + $scan['kleptoren'] = trim(preg_replace("/\./","",$line[1])); + $scan['cancris'] = trim(preg_replace("/\./","",$line[2])); +// $scan['cancris'] = trim($line[2]); + $step++; + } + continue; + break; + case 2: + + //Fregatten: 330 - Zerstörer: 0 - Kreuzer: 35 - Schlachtschiffe: 0 + //Fregatten: 466 - Zerstörer: 137 - Kreuzer: 0 - Schlachtschiffe: 0 + if(preg_match("/^".$identregex."Fregatten:\s*?(.+)\s\-\sZerstörer:\s*?(.+)\s\-\sKreuzer:\s*?(.+)\s\-\sSchlachtschiffe:\s*?(.+)/i",$nocolor,$line)) { + $scan['fregatten'] = trim(preg_replace("/\./","",$line[1])); +// $scan['fregatten'] = trim($line[1]); + $scan['zerstoerer'] = trim(preg_replace("/\./","",$line[2])); + $scan['kreuzer'] = trim(preg_replace("/\./","",$line[3])); + $scan['schlachter'] = trim(preg_replace("/\./","",$line[4])); + $step++; + } + continue; + break; + case 3: + + //Trägerschiffe: 30 - Jäger: 0 - Bomber: 0 + if(preg_match("/^".$identregex."Trägerschiffe:\s*?(.+)\s\-\sJäger:\s*?(.+)\s\-\sBomber:\s*?(.+)\s*?/i",$nocolor,$line)) { + $scan['traeger'] = trim(preg_replace("/\./","",$line[1])); + $scan['jaeger'] = trim(preg_replace("/\./","",$line[2])); + $scan['bomber'] = trim(preg_replace("/\./","",$line[3])); +// $step++; + $scans[] = $scan; + $step=0; + $type= ""; + } + continue; + break; + } + } + + // Kerrigan mili + +/* Militärscan [100%] S4vi3r-.- [21:4] + Orbit: 330 Fregatten - 35 Kreuzer + Flotte 1: 30 Träger - 3.100 Schutz [Verteidigungsflug ChefSmoka67] + Flotte 2: 4.500 Kaper [Im Orbit] + Res an 33:4 ; Alli nix , SC/PDX/NL 1x , Rest 2x , bis auf Lude , der 4x :p +*/ + + if($type == "kerrigan_mili") { + switch ($step) { + case 1: + // Orbit: 330 Fregatten - 35 Kreuzer + if(preg_match("/".$identregex.".*?Im Orbit:(.*?)$/i",$nocolor,$line)) { + $scan['fleets'][0] = parseFleet($line[1]);//." ".$line[2]." ".$line[3]." ".$line[4]); + $step++; + } + continue; + break; + case 2: + if(preg_match("/".$identregex.".*?Flotte 1:(.*?)$/i",$nocolor,$line)) { + $scan['fleets'][1] = parseFleet($line[1]); + $step++; + } + continue; + break; + case 3: + if(preg_match("/".$identregex.".*?Flotte 2:(.*?)$/i",$nocolor,$line)) { + $scan['fleets'][2] = parseFleet($line[1]); + $step++; + $scans[] = $scan; + $step=0; + $type = ""; + } + continue; + break; + + } + } + + // gn gscan + if($type == "wurst_gscan") { + switch ($step) { + case 1: + $found = false; + if(preg_match("/^".$identregex.".*?Abfangjäger:\s*?(\d+).*$/i",$nocolor,$line)) { + $scan['horus'] = trim($line[1]); + $found = true; + } + if(preg_match("/^".$identregex.".*?Rubium:\s*?(\d+)./i",$nocolor,$line)) { + $scan['rubium'] = trim($line[1]); + $found = true; + } + if(preg_match("/^".$identregex.".*?Pulsar:\s*?(\d+)./i",$nocolor,$line)) { + $scan['pulsar'] = trim($line[1]); + $found = true; + } + if(preg_match("/^".$identregex.".*?Coon:\s*?(\d+)./i",$nocolor,$line)) { + $scan['coon'] = trim($line[1]); + $found = true; + } + if(preg_match("/^".$identregex.".*?Centurion:\s*?(\d+)./i",$nocolor,$line)) { + $scan['centurion'] = trim($line[1]); + $found = true; + } + if(preg_match("/^".$identregex."Geschützscan \(\s*?(.+?)\s*?Svs\)(\s(.+?)\s\((\d+?):(\d+?)\)|)/i",$nocolor,$line)) { + $scan['svs'] = trim($line[1]); + if (strlen(trim($line[3]))) { + $scan['scanner'] = trim($line[3])." (".trim($line[4]).":".trim($line[5]).")"; + } + $scans[] = $scan; + $step=0; + $type = ""; + } + if($found) { + $step++; + $scans[] = $scan; + } + continue; + break; + case 2: + if(preg_match("/^".$identregex."Geschützscan \(\s*?(.+?)\s*?Svs\)(\s(.+?)\s\((\d+?):(\d+?)\)|)/i",$nocolor,$line)) { + $last_scan = &$scans[count($scans)-1]; + $last_scan['svs'] = trim($line[1]); + if (strlen(trim($line[3]))) { + $last_scan['scanner'] = trim($line[3])." (".trim($line[4]).":".trim($line[5]).")"; + } + $step=0; + $type = ""; + } + continue; + break; + } + } + + //wurst unit scan + if ($type == "wurst_unit") { + switch ($step) { + case 1: + if(preg_match("/^".$identregex."Kleptoren:\s*?(\d+?)\s*?Cancris:\s*?(\d+?)\s*?Fregatten:\s*?(\d+)/i",$nocolor,$line)) { + $scan['kleptoren'] = trim($line[1]); + $scan['cancris'] = trim($line[2]); + $scan['fregatten'] = trim($line[3]); + $step++; + } + continue; + break; + case 2: + if(preg_match("/^".$identregex."Zerstörer:\s*?(\d+?)\s*?Kreuzer:\s*?(\d+?)\s*?Träger:\s*?(\d+)/i",$nocolor,$line)) { + $scan['zerstoerer'] = trim($line[1]); + $scan['kreuzer'] = trim($line[2]); + $scan['traeger'] = trim($line[3]); + $step++; + } + continue; + break; + case 3: + if(preg_match("/^".$identregex."Jäger:\s*?(\d+?)\s*?Bomber:\s*?(\d+?)\s*?Schlachter:\s*?(\d+)/i",$nocolor,$line)) { + $scan['jaeger'] = trim($line[1]); + $scan['bomber'] = trim($line[2]); + $scan['schlachter'] = trim($line[3]); +// $step++; + $scans[] = $scan; + $step=0; + $type = ""; + + } + continue; + break; + + } + } + + //gn_ingame unit scan + if ($type == "ingame_unit") { + switch ($step) { + case 1: + if(preg_match("/^".$identregex."Name:\s*?(.*?)/i",$nocolor,$line)) { + $scan['nick'] = trim($line[1]); + $step++; + } + continue; + break; + case 2: + if(preg_match("/^".$identregex."Koordinaten:\s*?(\d+?):(\d+?)/i",$nocolor,$line)) { + $scan['gala'] = trim($line[1]); + $scan['pos'] = trim($line[2]); + $step++; + } + continue; + break; + case 3: + if(preg_match("/^".$identregex."Jäger\s*?.\s*?\"Leo\"\s*?(\d+?)/i",$nocolor,$line)) { + $scan['jaeger'] = trim($line[1]); + $step++; + } + continue; + break; + case 4: + if(preg_match("/^".$identregex."Bomber\s*?.\s*?\"Aquilae\"\s*?(\d+?)/i",$nocolor,$line)) { + $scan['bomber'] = trim($line[1]); + $step++; + } + continue; + break; + case 5: + if(preg_match("/^".$identregex."Fregatten\s*?.\s*?\"Fornax\"\s*?(\d+?)/i",$nocolor,$line)) { + $scan['fregatten'] = trim($line[1]); + $step++; + } + continue; + break; + case 6: + if(preg_match("/^".$identregex."Zerstörer\s*?.\s*?\"Draco\"\s*?(\d+?)/i",$nocolor,$line)) { + $scan['zerstoerer'] = trim($line[1]); + $step++; + } + continue; + break; + case 7: + if(preg_match("/^".$identregex."Kreuzer\s*?.\s*?\"Goron\"\s*?(\d+?)/i",$nocolor,$line)) { + $scan['kreuzer'] = trim($line[1]); + $step++; + } + continue; + break; + case 8: + if(preg_match("/^".$identregex."Schlachtschiff\s*?.\s*?\"Pentalin\"\s*?(\d+?)/i",$nocolor,$line)) { + $scan['traeger'] = trim($line[1]); + $step++; + } + continue; + break; + case 9: + if(preg_match("/^".$identregex."Trägerschiff\s*?.\s*?\"Zenit\"\s*?(\d+?)/i",$nocolor,$line)) { + $scan['schlachter'] = trim($line[1]); + $step++; + } + continue; + break; + case 10: + if(preg_match("/^".$identregex."Kaperschiff\s*?.\s*?\"Cleptor\"\s*?(\d+?)/i",$nocolor,$line)) { + $scan['kleptoren'] = trim($line[1]); + $step++; + } + continue; + break; + case 11: + if(preg_match("/^".$identregex."Schutzschiff\s*?.\s*?\"Cancri\"\s*?(\d+?)/i",$nocolor,$line)) { + $scan['cancris'] = trim($line[1]); + $step++; + } + continue; + break; + } + } + + +/* + +[18:54] Galaxy-Network SektorScan (100%) TheRealPredator (101:9) +[18:54] Punkte: 30.470.491 +[18:54] Schiffe: 5262 Verteidigung: 0 +[18:54] M-Extraktoren: 807 K-Extraktoren: 200 +[18:54] Asteroiden: 52 +[18:54] Galaxy-Network SektorScan (200 SVs) DaFrEaK (186:8) + +[18:30] Sektorscan [100%] Greenman [125:9] +[18:30] Punkte: 69.314.484 × Asteroiden: 90 +[18:30] Schiffsanzahl: 15.223 × Geschützanzahl: 1 +[18:30] Metallextraktoren: 608 × Kristallextraktoren: 143 +[18:30] Scan von: csL [566:7] - Sv: 300 +[18:30] Kristall verscannt, heute: 18.000, gesamt: 48.000 + + +*/ + + // yasp sector scan + if($type =="yasp_sector") { + switch ($step) { + case 1: + if(preg_match("/^".$identregex."Punkte:\s(.*?)\s×\sAsteroiden:\s(.*?)/i",$nocolor,$line)) { + $scan['punkte'] = trim(preg_replace("/\./s","",$line[1])); + $scan['roids'] = trim(preg_replace("/\./s","",$line[2])); + $step++; + } + continue; + break; + case 2: + if(preg_match("/^".$identregex."Schiffsanzahl:\s(.*?)\s×\sGeschützanzahl:\s(.*?)/i",$nocolor,$line)) { + $scan['ships'] = trim(preg_replace("/\./s","",$line[1])); + $scan['deff'] = trim(preg_replace("/\./s","",$line[2])); + $step++; + } + continue; + break; + case 3: + if(preg_match("/^".$identregex."Metallextraktoren:\s(.*?)\s×\sKristallextraktoren:\s(.*?)/i",$nocolor,$line)) { + $scan['metall'] = trim($line[1]); + $scan['kristall'] = trim($line[2]); + $step++; + } + continue; + break; + case 4: + if(preg_match("/^".$identregex."Scan\svon:\s(.*?)\s/i",$nocolor,$line)) { + $step++; + $scans[] = $scan; + + } + continue; + break; + + case 5: + if(preg_match("/^".$identregex."Galaxy-Network SektorScan \(\s*?(.+?)\s*?Svs\)(\s(.+?)\s\((\d+?):(\d+?)\)|)/i",$nocolor,$line)) { + $last_scan = &$scans[count($scans)-1]; + $last_scan['svs'] = trim($line[1]); + if (strlen(trim($line[3]))) { + $last_scan['scanner'] = trim($line[3])." (".trim($line[4]).":".trim($line[5]).")"; + } + $step=0; + $type = ""; + } + continue; + break; + } + } + + + + + + + + + +//################################## Edit Gonz ######################################### + + // gn news + if($type == "gn_news") { + switch ($step) { + case 1: + if(preg_match("/^".$identregex."(.*?(?:Rückzug|Angriff|Fehler|Verteidigung).*)/i",$nocolor,$line)) { + if(!$scan['newsdata']) $scan['newsdata'] = array(); + $scan['newsdata'][] = preg_replace("/[\n\f\r\t]/s","",$line[1]); + } elseif(preg_match("/".$identregex."Galaxy-Network NewsScan \((.+?)\s*?Svs\)(\s([^\s]+?)\s\((\d+?):(\d+?)\)|)/i",$nocolor,$line)) { + if($scan['newsdata']) $scan['newsdata'] = join("\n",$scan['newsdata']); + $scan['svs'] = trim($line[1]); + if (strlen(trim($line[3]))) { + $scan['scanner'] = trim($line[3])." (".trim($line[4]).":".trim($line[5]).")"; + } + $scans[] = $scan; + $step=0; + $type = ""; + } + continue; + } + } + } + return $scans; +} + +function parse_user_flottenbewegung(&$code,$gala,$pos) { + if(!preg_match("'\sflottenbewegung\s'is",$code)) return false; + $_fleet = array( + "jaeger" => "jäger","bomber"=>"bomber","fregatten"=>"fregatte","zerstoerer"=>"zerstörer","kreuzer"=>"kreuzer","schlachter"=>"schlachtschiff","traeger"=>"trägerschiff","kleptoren"=>"kaperschiff","cancris"=>"schutzschiff" + ); + $fleet = array(); + foreach ($_fleet as $key => $regex) { + if(preg_match("'".$regex."[^\d]+?([\d,]+)(?:\s*?([\d,]+)|)(?:\s*?([\d,]+)|)'is",$code,$matches)) { + $fleet[0][$key] = str_replace(",","",$matches[1]); + if(isset($matches[2])) $fleet[1][$key] = str_replace(",","",$matches[2]); + if(isset($matches[3])) $fleet[2][$key] = str_replace(",","",$matches[3]); + } + } + //status, tgala, tpos, return_flight, eta, ticks, defftype (bei verteidigung) +/* $_status = array( + "Flotte ([12])\s{1,3}Wartet auf Befehle", + "Flotte ([12])\s{1,3}Befindet sich auf dem R+ückflug von eine[rm] (\w*).\s{4}(\d{1,4}):(\d{1,2}) \w+ --> (\d{1,4}):(\d{1,2}) \w+ - ETA (?:(\d):(\d+)|(\d+))", + "Flotte ([12])\s{1,3}Ist auf dem (Angriff|Verteidigung)sflug\s{1,4}(\d{1,4}):(\d{1,2}) \w+ --> (\d{1,4}):(\d{1,2}) \w+ - ETA (?:(\d+):(\d+)|(\d+))(?: Minuten)?\s{1,}(?:Die Flotte wird in dem Sektor |Das Gefecht wird )(?:(\d+):(\d+)|(\d+))(?: Minuten)?", + "Flotte ([12])\s{1,3}Die Flotte kämpft für euch!\s{1,4}Das Gefecht mit (\d{1,4}):(\d{1,2}) \w+ wird noch (?:(\d+):(\d+)|(\d+))(?: Minuten)?" + ); + $type = 0; + foreach ($_status as $regex) { + if(preg_match_all("'".$regex."'is",$code,$matches,PREG_SET_ORDER)) { + //echo "
    \$matches:".print_r($matches,1)."\n\n\n\n\n\n\n\n
    "; + switch ($type) { + case 0: + // im orbit + break; + case 1: { + // rückflug + foreach ($matches as $line) { + $fleetnum = $line[1]; + $fleet[$fleetnum]['return_flight'] = 1; + if($line[2] == "Verteidigung") + $fleet[$fleetnum]['status'] = 2; + else + $fleet[$fleetnum]['status'] = 1; + $fleet[$fleetnum]['tgala'] = $line[3]; + $fleet[$fleetnum]['tpos'] = $line[4]; + $fleet[$fleetnum]['gala'] = $line[5]; + $fleet[$fleetnum]['pos'] = $line[6]; + if(strlen($line[7])){ + $fleet[$fleetnum]['eta'] = $line[7]*60+$line[8]; + } else { + $fleet[$fleetnum]['eta'] = $line[9]; + } + } + break; + } + case 2: { + // angriff/verteidigung + foreach ($matches as $line) { + $fleetnum = $line[1]; + if($line[2] == "Verteidigung") + $fleet[$fleetnum]['status'] = 2; + else { + $fleet[$fleetnum]['status'] = 1; + $fleet[$fleetnum]['returntime'] = 450; + } + $fleet[$fleetnum]['tgala'] = $line[5]; + $fleet[$fleetnum]['tpos'] = $line[6]; + $fleet[$fleetnum]['gala'] = $line[3]; + $fleet[$fleetnum]['pos'] = $line[4]; + if(strlen($line[7])){ + $fleet[$fleetnum]['eta'] = $line[7]*60+$line[8]; + } else { + $fleet[$fleetnum]['eta'] = $line[9]; + } + if(strlen($line[10])){ + $fleet[$fleetnum]['orbittime'] = $line[10]*60+$line[11]; + } else { + $fleet[$fleetnum]['orbittime'] = $line[12]; + } + } + break; + } + case 3: { + // im orbit, angriff + foreach ($matches as $line) { + $fleetnum = $line[1]; + $fleet[$fleetnum]['status'] = 1; + $fleet[$fleetnum]['returntime'] = 450; + $fleet[$fleetnum]['tgala'] = $line[2]; + $fleet[$fleetnum]['tpos'] = $line[3]; + + $fleet[$fleetnum]['eta'] = 0; + + if(strlen($line[4])){ + $fleet[$fleetnum]['orbittime'] = $line[4]*60+$line[5]; + } else { + $fleet[$fleetnum]['orbittime'] = $line[6]; + } + } + break; + } + } + /* + foreach ($_tmpfleet as $key => $val) { + if (!is_int($val)) { + $val = str_replace("_","",$val); + if ($key == "eta") { + //echo "
    ".print_r($matches,1)."
    "; + if (isset($matches[$val][0])) { $fleet[$matches[1][0]][$key] = $matches[$val][0] *60 + $matches[$val+1][0]; } + else { $fleet[$matches[1][0]][$key] = $matches[$val+2][0]; } + if (isset($matches[$val][1])) { $fleet[$matches[1][1]][$key] = $matches[$val][1] *60 + $matches[$val+1][1]; } + elseif (isset($matches[$val+2][1])) { $fleet[$matches[1][1]][$key] = $matches[$val+2][1]; } + } + if ($key == "ticks") { + if (isset($matches[$val][0])) { $fleet[$matches[1][0]][$key] = $matches[$val][0] *4 + (int)($matches[$val+1][0] /15); } + else { $fleet[$matches[1][0]][$key] = (int)($matches[$val+2][0] /15); } + if (isset($matches[$val][1])) { $fleet[$matches[1][1]][$key] = $matches[$val][1] *4 + (int)($matches[$val+1][1] /15); } + elseif (isset($matches[$val+2][1])) { $fleet[$matches[1][1]][$key] = (int)($matches[$val+2][1] / 15); } + } + elseif ($key == "status") { + $statusreplace = array("Angriff"=>1,"Verteidigung"=>2); + $fleet[$matches[1][0]][$key] = $statusreplace[$matches[$val][0]]; + if ($matches[1][1]) { $fleet[$matches[1][1]][$key] = $statusreplace[$matches[$val][1]]; } + } + else { + $fleet[$matches[1][0]][$key] = $matches[$val][0]; + if ($matches[1][1]) { $fleet[$matches[1][1]][$key] = $matches[$val][1]; } + } + } + else { + $fleet[$matches[1][0]][$key] = $val; + if ($matches[1][1]) { $fleet[$matches[1][1]][$key] = $val; } + } + } + } + $type++; + }*/ +/* if (isset($fleet[$matches[1][0]])) { + $fleet[$matches[1][0]]["gala"] = $gala; + $fleet[$matches[1][0]]["pos"] = $pos; + } + if (isset($fleet[$matches[1][1]])) { + $fleet[$matches[1][1]]["gala"] = $gala; + $fleet[$matches[1][1]]["pos"] = $pos; + }*/ + return $fleet; +} + +function parse_user_verteidigung(&$code) { + if(!preg_match("'\sverteidigung\s'is",$code)) return false; + $_check = array( + "rubium" => "leichtes Orbitalgeschütz", + "horus" => "abfangjäger", + "pulsar" => "leichtes raumgeschütz", + "coon" => "mittleres raumgeschütz", + "centurion" => "schweres raumgeschütz" + ); + $return = array(); + foreach ($_check as $key => $regex) { + if(preg_match("'".$regex.".*?k[^\d]*?(\d+)'is",$code,$matches)) { + $return[$key] = $matches[1]; + } + } + return $return; +} + +function parse_taktikansicht(&$code) { + if(!preg_match("'\sflottenzusammensetzung\s'is",$code) || !preg_match("'\sVerteidigungseinheiten\s'is",$code)) return false; + //flotte + $_fleet = array( + "jaeger" => "jäger","bomber"=>"bomber","fregatten"=>"fregatte","zerstoerer"=>"zerstörer","kreuzer"=>"kreuzer","schlachter"=>"schlachtschiff","traeger"=>"trägerschiff","kleptoren"=>"kaperschiff","cancris"=>"schutzschiff" + ); + $_deff = array( + "rubium" => "leichtes Orbitalgeschütz", + "horus" => "abfangjäger", + "pulsar" => "leichtes raumgeschütz", + "coon" => "mittleres raumgeschütz", + "centurion" => "schweres raumgeschütz" + ); + $result = array(); + if(preg_match_all("'flottenzusammensetzung von ([^\s]+?) \((\d+):(\d+)\)(.*?)galaxy-network'is",$code,$users,PREG_SET_ORDER)) { + foreach ($users as $user) { + $fleet = array(); + foreach ($_fleet as $key => $regex) { + if(preg_match("'".$regex."[^\d]+?([\d,]+)(?:\s*?([\d,]+)|)(?:\s*?([\d,]+)|)'is",$user[4],$matches)) { + $fleet[0][$key] = str_replace(",","",$matches[1]); + if(isset($matches[2])) $fleet[1][$key] = str_replace(",","",$matches[2]); else $fleet[1][$key] = 0; + if(isset($matches[3])) $fleet[2][$key] = str_replace(",","",$matches[3]); else $fleet[2][$key] = 0; + } + } + $deff = array(); + foreach ($_deff as $key => $regex) { + if(preg_match("'".$regex.".[^\d]*?(\d+)'is",$user[4],$matches)) { + $deff[$key] = $matches[1]; + } + } + $result[] = array("fleets" => $fleet,"deff" => $deff,"nick" => $user[1],"gala" => $user[2],"pos" => $user[3]); + } + $code = preg_replace("'flottenzusammensetzung von ([^\s]+?) \((\d+):(\d+)\)(.*?)galaxy-network'is"," ",$code); + } + return $result ; +} + + +?> \ No newline at end of file diff --git a/src/functions/scans.class.php b/src/functions/scans.class.php new file mode 100644 index 0000000..554cfd6 --- /dev/null +++ b/src/functions/scans.class.php @@ -0,0 +1,367 @@ +action]) { + eval("\$this->".$functions[$this->action].";"); + } + #default + $this->_listScans("scans"); + } + + # + # fügt einen oder mehrere Scans hinzu + # + function _addScan() { + if ($_REQUEST['send']) { + $data = $_POST['data']; + if ($data) { + $scans = parseScan($data); + if ($scans) { + $this->forms['addscan']['message'] ="Folgende Scans wurden erkannt:

    "; + $this->template->assign("scanlist",$scans); + for ($i=0;$iforms['addscan']['message'] = "
    Scan(s) nicht erkannt
    "; + } + # $this->forms['addscan']['fields']['data']['value'] = $data; + } else { + $this->forms['addscan']['message'] = "
    Feld leer
    "; + } + } else { + $this->forms['addscan']['message'] = "Der Scanner arbeitet mit Copy&Paste. Dabei ist es egal ob ihr + den Scan aus dem IRC Channel kopiert, oder den IRC Copy Knopf benutzt.Beim Kopieren aus dem IRC heraus ist nur wichtig, + daß ihr die kompletten Zeilen kopiert. (mit nickname, uhrzeit, was weiß ich nicht noch alles).Zeilen die nicht zum scan gehören + werden vom Parser ignoriert. Vorhandene Scans werden upgedated, fehlende neu hinzugefügt.Weiterhin werden beliebig viele Scans +gleichzeitig +geparst, + ihr könnt also alle Scans mit einem Mal einfügen.

    + Unterstütze Formate:
    + Galaxy Network Scan
    "; + } + $this->forms['addscan']['action'] = "add"; + $this->forms['addscan']['url'] = "scans.php"; + $this->show('scan_add_form','Scan hinzufügen/updaten'); + } + # + # zeigt scandetails an + # + function scan_details($gala,$pos) { + $scan = getScan(array("gala" => $gala, "pos" => $pos)); + $this->template->assign("gala",$gala); + $this->template->assign("pos",$pos); + $this->template->assign("scan",scan_format($scan)); + $this->show('scan_details',"Details von ($gala:$pos)"); + } + + # + # Listet die Scans auf + # + function _listScans($option) { + $gala = param_num("gala"); + $pos = param_num("pos"); + #scandetails + if($gala && $pos) $this->scan_details($gala,$pos); + #scanlist + $page = param_num("page",1); + $rows = 20; + + $link_options = array(); + + if ($option == "targets") { + $scanlistfilter = & $_SESSION['targetlistfilter']; + $this->template->assign("showtargets",1); + $this->template->assign("scantitle","Ziele suchen"); + #zielsuche + if ($_REQUEST['subaction'] == 'newsearch' && $scanlistfilter) { + unset($_SESSION['targetlistfilter']); + unset($scanlistfilter); + } +/* if ($_REQUEST['subaction'] == "search") { + $scanlistfilter['exen'] = param_num("exen"); + $scanlistfilter['punkte'] = param_num("punkte"); + } + */ + if (!$scanlistfilter || $_POST['subaction'] == "search") { + $form = new formContainer(); + $form->add(new formInput("exen","Exenmindestanzahl","numeric",true,10,true)); + $form->add(new formInput("macht","Machtmindestwert","numeric",true,10,true)); + $form->add(new formCheckbox("hideold","Alte Scans nicht berücksichtigen","numeric",array(1),false)); + if($_POST['send']) { + $form->submit(); + if(!$form->hasErrors()) { + if($form->get("macht")) $scanlistfilter['macht'] = $form->get("macht"); + if($form->get("exen")) $scanlistfilter['exen'] = $form->get("exen"); + $scanlistfilter['sort'] = "exen"; + $scanlistfilter['order'] = "desc"; + $scanlistfilter['hassektor'] = "1"; + $scanlistfilter['hideold'] = $form->get("hideold"); + $scanlistfilter['except_galas'] = getGalaList(true); + $this->_header("scans.php?action=targets&send"); + } + } else { + $form->select("hideold",1); + } + + $form->registerVars($this->template); + $this->show('scan_target_form','Ziele suchen'); + } + #sortierung + if ($_REQUEST['sort'] && $_REQUEST['order'] && $scanlistfilter) { + $sort = trim($_REQUEST['sort']); + $order = trim($_REQUEST['order']); + if ($sort != 'koords' && $sort != 'exen') $sort = 'koords'; + if ($order != "asc" && $order != "desc") $order = "asc"; + $scanlistfilter['sort'] = $sort; + $scanlistfilter['order'] = $order; + } + $link_options[] = "action=targets"; + $link2 = "?action=targets"; + #normale Scananzeige, galaweise + } else { + $scanlistfilter = &$_SESSION['scanlistfilter']; + $this->template->assign("scantitle","Scans"); + if (!$scanlistfilter) { + $scanlistfilter['gala'] = 1; + $scanlistfilter['sort'] = "koords"; + $scanlistfilter['order'] = "asc"; + $scanlistfilter['hideold'] = 1; + } + #alte einblenden/ausblenden + if (isset($_REQUEST["hideold"]) && is_numeric($_REQUEST["hideold"])) { + $scanlistfilter['hideold'] = $_REQUEST["hideold"]; + } + $hideold = $scanlistfilter["hideold"]; + if ($hideold){ + $title = "Alle Anzeigen"; + $subtitle = "Zeigt alle Scans an"; + $param = 0; + } else { + $title = "Alte Ausblenden"; + $subtitle = "Scans die älter als 1 Tag sind werden nicht angezeigt"; + $param = 1; + } + $this->template->assign("hideoldtitle",$title); + $this->template->assign("hideoldparam",$param); + $this->template->assign("hideoldsubtitle",$subtitle); + #neue gala anzeigen + if ($gala = param_num("gala")) { + $scanlistfilter['gala'] = $gala; + } else { + $gala = $scanlistfilter["gala"]; + } + if ($this->userdata["gid"] == 1) { $hideblock = false; } else { $hideblock = true; } + $next = getNextGala($gala,$hideold,$hideblock); + $prev = getPrevGala($gala,$hideold,$hideblock); + if ($next && $prev) { + #gala suche anzeigen + $this->template->assign("showform",1); + } + #zeigen beide auf die selbe, -> die aktuelle + if ($next == $prev && $next == $gala) { + unset($prev); + unset($next); + } + $this->template->assign("prev",$prev); + $this->template->assign("next",$next); + #sortierung + if ($_REQUEST['sort'] && $_REQUEST['order'] && $scanlistfilter) { + $sort = trim($_REQUEST['sort']); + $order = trim($_REQUEST['order']); + if ($sort != 'koords' && $sort != 'exen') $sort = 'koords'; + if ($order != "asc" && $order != "desc") $order = "asc"; + $scanlistfilter['sort'] = $sort; + $scanlistfilter['order'] = $order; + } + $link_options[] = "gala=".$scanlistfilter['gala']; + } + #mili & news ausklappen + $expand = param_num("expand"); + #scans holen + $this->forms['scanlist'][$scanlistfilter['sort']][$scanlistfilter['order']] = '_active'; + $scanlist = listScans($scanlistfilter,&$pages,&$page,$rows); + for ($i=0;$iuserdata['uid']) { + $scanlist[$i]['atter_class'] = "green"; + } else { + $scanlist[$i]['atter_class'] = "red"; + } + } + $scanlist[$i] = scan_format($scanlist[$i]); + } + + $this->forms['scanlist']['pages'] = showPageBar($page,$pages,"scans.php".$link2,"page","menu"); + $this->forms['scanlist']['gala'] = $scanlistfilter['gala']; + + $this->template->assign('scanlist',$scanlist); + $this->template->assign('page',$page); + + $this->show('scan_list','Scans'); + } + + ################################### + + + + + /*function _Target_set() { + $id = param_num("id"); + if (!$id) { + #kein target da + if ($_POST['step']) { + $items['gala']['value'] = param_num("gala"); + $items['pos']['value'] = param_num("pos"); + if (!$items['pos']['value']) { + $errors[] = "Position fehlt oder ungültig!"; + $items['pos']['class'] = "_error"; + } + if (!$items['gala']['value']) { + $errors[] = "Galaxie fehlt oder ungültig!"; + $items['gala']['class'] = "_error"; + } + if (!$errors){ + $scan = getScan($items['gala']['value'],$items['pos']['value']); + if (!$scan) { + $id = addMainScan($items['gala']['value'],$items['pos']['value']); + } else { + $id = $scan['sid']; + } + if ($scan['closed']) { + $errors[] = "Ziel ist bereits reserviert"; + } + } + } + $this->template->assign("showcomplete",1); + } else { + $scan = getScanbyId($id); + if (!$scan) $this->_header(back_link(),"ungültig: $id"); + if ($scan['closed']) $this->_header(back_link(),"Target geschlossen"); + } + if ($_POST['step']) { + $items['fleet']['value'] = param_num("fleet"); + $items['time']['value'] = $_POST['time']; + #flotte ungültig + if ($items['fleet']['value'] != 1 && $items['fleet']['value'] != 2) { + $this->_header(back_link(),"Ungültige flotte"); + } + if ($items['time']['value']) { + if (!preg_match("/(\d{1,2}):(\d{2})/i",$items['time']['value'],$data)) { + $errors[] = "Ungültige Zeit!"; + $items['time']['class'] ="_error"; + } + } + if (!$errors) { + if($atter = getAtter($this->userdata['uid'],$items['fleet']['value'])) { + $errors[] = "Flotte ".$items['fleet']['value']." bereits für (".$atter['gala'].":".$atter['pos'].") eingetragen"; + } + } + if (!$errors) { + if (addAtter($id,$this->userdata['uid'],$items['fleet']['value'],$items['time']['value']) != -1) { + $this->_header(back_link()); + } else { + $errors[] = "DB Error"; + } + } + $this->template->assign("errors",$errors); + } else { + $items['time']['class'] = "_optional"; + $items['fleet']['value'] = 1; + } + $this->template->assign("fleet".$items['fleet']['value'],"checked"); + $this->template->assign("items",$items); + $this->template->assign("id",$id); + $this->show('scan_target_set','Ziel reservieren'); + } + ############################################################### + function _Target_close() { + #exists id ? + $id = param_num("id"); + if (!$id) $this->_header(back_link(),"fehlende id"); + #exists scan ? + $scan = getScanbyId($id); + if (!$scan) $this->_header(back_link(),"ungültig: $id"); + # is atter ? + $atterlist = getAtterlist($id); + $isatter = 0; + for($j=0;$j < count($atterlist);$j++){ + $atter = &$atterlist[$j]; + if ($atter['uid'] == $this->userdata['uid']) { + $isatter = 1; + break; + } + } + if (!$isatter) $this->_header(back_link(),"no permission"); + if (!$scan['closed']) { + closeTarget($id); + } + $this->_header(back_link()); + } + ############################################################### + function _Target_open() { + #exists id ? + $id = param_num("id"); + if (!$id) $this->_header(back_link(),"fehlende id"); + #exists scan ? + $scan = getScanbyId($id); + if (!$scan) $this->_header(back_link(),"ungültig: $id"); + # is atter ? + $atterlist = getAtterlist($id); + $isatter = 0; + for($j=0;$j < count($atterlist);$j++){ + $atter = &$atterlist[$j]; + if ($atter['uid'] == $this->userdata['uid']) { + $isatter = 1; + break; + } + } + if (!$isatter) $this->_header(back_link(),"no permission"); + if ($scan['closed']) { + openTarget($id); + } + $this->_header(back_link()); + } + ############################################################### + function _Target_drop() { + #exists id ? + $uid = param_num("uid"); + $fleet = param_num("fleet"); + if (!$uid || !$fleet) $this->_header(back_link(),"fehlende id"); + if ($fleet != 1 && $fleet != 2) $this->_header(back_link(),"falsche flotte"); + #exists scan ? + $atter = getAtter($uid,$fleet); + # is atter ? + if (!$atter) $this->_header(back_link(),"atter nicht gefunden"); + if ($atter['uid'] != $this->userdata['uid']) + $this->_header(back_link(),"no permission"); + deleteAtter($uid,$fleet); + $this->_header(back_link()); + } */ + +} +?> diff --git a/src/functions/simulator.class.php b/src/functions/simulator.class.php new file mode 100644 index 0000000..f49bde9 --- /dev/null +++ b/src/functions/simulator.class.php @@ -0,0 +1,303 @@ +action]) { + # eval("\$this->".$functions[$this->action].";"); + # } + #default + $this->_showSimulator(); + } + # + # stellt den Simulator dar mit allen Funktionen + # + function _showSimulator() { + for ($i=0;$i < 14;$i++) { + if (isset($_REQUEST['deff'.$i]) && is_numeric($_REQUEST['deff'.$i]) && $_REQUEST['deff'.$i] >= 0) { + $deff[$i] = $_REQUEST['deff'.$i]; + } else { + $deff[$i] = 0; + } + } + for ($i=0;$i < 9;$i++) { + if (isset($_REQUEST['attack'.$i]) && is_numeric($_REQUEST['attack'.$i]) && $_REQUEST['attack'.$i] >= 0) { + $attack[$i] = $_REQUEST['attack'.$i]; + } else { + $attack[$i] = 0; + } + } + + $kristall = param_num("kristall",0); + $metall = param_num("metall",0); + + $Simu = new GNSimu(); + $Simu->attacking = $attack; + $Simu->deffending = $deff; + $Simu->mexen = $metall; + $Simu->kexen = $kristall; + + $ticks = param_num("ticks",1); + + $fleets_loaded = $_SESSION['fleets_loaded']; + + if ($_POST['send']) { + if ($fleets_loaded){ + for ($i=0;$i"; + $attack[0] -= $fleets_loaded[$i]['jaeger']; + $attack[1] -= $fleets_loaded[$i]['bomber']; + $attack[2] -= $fleets_loaded[$i]['fregatten']; + $attack[3] -= $fleets_loaded[$i]['zerstoerer']; + $attack[4] -= $fleets_loaded[$i]['kreuzer']; + $attack[5] -= $fleets_loaded[$i]['schlachter']; + $attack[6] -= $fleets_loaded[$i]['traeger']; + $attack[7] -= $fleets_loaded[$i]['kleptoren']; + $attack[8] -= $fleets_loaded[$i]['cancris']; + for ($j=0;$juserdata) { + unset($_SESSION['fleets_loaded']); + unset($fleets_loaded); + for ($i=0;$iuserdata) { + $loadattfleet = $_POST['loadattfleet']; + $userfleet = user_fleet_sum($loadattfleet); + $user = getUserByID($loadattfleet); + #user wrong or no fleet + if (!$userfleet) { + $this->_header("index.php","Userid falsch oder keine Flotte"); + } + #wrong attfleet, no permission + if (!$this->userdata['rights']['admin'] && !$this->userdata['rights']['attorga'] && $user['aid'] != $this->userdata['aid']){ + $this->_header("index.php","Keine Rechte zum Flotte laden"); + } + for ($i=0;$ivorticks(0); + if ($_POST['vorticks'] && $tickload != 0) { + $Simu->vorticks(1); + } + } + for ($i=2;($i< $tickload);$i++) { + $Simu->Compute(0); + } + if ($tickload > 1) { + if ($ticks == $tickload-1) { + #den letzten tick laden + $Simu->Compute(1); + } else { + #tick laden + $Simu->Compute(0); + } + } + $attack = $Simu->attacking; + $deff = $Simu->deffending; + } + if ($_POST['calculate']) { + if ($_POST['vorticks']) { + $Simu->vorticks(0); + $tick[1] = $Simu->attacking; + $tick[0] = $Simu->Oldatt; + $tick[3] = $Simu->deffending; + $tick[2] = $Simu->Olddeff; + $tick['metall'] = $Simu->stolenmexen; + $tick['kristall'] = $Simu->stolenkexen; + $tick['name'] = "Vortick 1"; + $tick['nr'] = 0; + $ticklist[] = $tick; + $Simu->vorticks(1); + $tick[1] = $Simu->attacking; + $tick[0] = $Simu->Oldatt; + $tick[3] = $Simu->deffending; + $tick[2] = $Simu->Olddeff; + $tick['metall'] = $Simu->stolenmexen; + $tick['kristall'] = $Simu->stolenkexen; + $tick['name'] = "Vortick 2"; + $tick['nr'] = 1; + $ticklist[] = $tick; + } + for ($i=0;$i<$ticks-1;$i++) { + $Simu->Compute(0); + $tick[1] = $Simu->attacking; + $tick[0] = $Simu->Oldatt; + $tick[3] = $Simu->deffending; + $tick[2] = $Simu->Olddeff; + $tick['metall'] = $Simu->stolenmexen; + $tick['kristall'] = $Simu->stolenkexen; + $tick['name'] = "Tick ".($i+1); + $tick['nr'] = $i+2; + $ticklist[] = $tick; + } + $Simu->Compute(1); + $tick[1] = $Simu->attacking; + $tick[0] = $Simu->Oldatt; + $tick[3] = $Simu->deffending; + $tick[2] = $Simu->Olddeff; + $tick['metall'] = $Simu->stolenmexen; + $tick['kristall'] = $Simu->stolenkexen; + $tick['name'] = "Tick ".$ticks; + $tick['nr'] = $ticks+1; + $ticklist[] = $tick; + $this->template->assign('ticklist',$ticklist); + $this->template->assign('attlost',$Simu->geslostshipsatt); + $this->template->assign('defflost',$Simu->geslostshipsdeff); + $ress[0][0] = $Simu->getlostmetall[0]; + $ress[1][0] = $Simu->getlostmetall[1]; + $ress[0][1] = $Simu->getlostkristall[0]; + $ress[1][1] = $Simu->getlostkristall[1]; + $ress[0][2] = $ress[0][1]+$ress[0][0]; + $ress[1][2] = $ress[1][1]+$ress[1][0]; + + for ($i=0;$i<2;$i++) { + for ($j=0;$j<3;$j++) { + $ress[$i][$j] = substr_replace(strrev(chunk_split(strrev($ress[$i][$j]),3,'.')),'',0,1); + } + } + $this->template->assign('ress',$ress); + $this->template->assign('metallstolen',$Simu->gesstolenexenm); + $this->template->assign('kristallstolen',$Simu->gesstolenexenk); + } + $this->template->assign('deffsel'.$ticks,'selected'); + if ($_POST['vorticks']) $this->template->assign('vortickssel','checked'); + $this->template->assign('attfleetselect'.$_POST['attfleetselect'],'selected'); + } else { + $this->template->assign('deffsel1','selected'); + $this->template->assign('attfleetselect1','selected'); + } + + $this->template->assign('metall',$metall); + $this->template->assign('kristall',$kristall); + $this->template->assign('deff',$deff); + $this->template->assign('attack',$attack); + + $attfleets = array(); + if ($this->userdata['rights']['attorga'] == 1) { + $except = array(); + #for ($i=0;$iuserdata['aid']); +# if ($this->userdata['fleetupdate']) { +# $attfleets[] = array("id" => $this->userdata['uid'],"wert" => $this->userdata['nick']." (".$this->userdata['gala'].":".$this->userdata['pos'].")"); +# } + # if (!$fleets_loaded[0] && $this->userdata['fleet']) { + # $attfleets[] = array("id" => $this->userdata['uid'],"wert" => $this->userdata['nick']." (".$this->userdata['gala'].":".$this->userdata['pos'].")"); + # } + } + for ($i=0;$itemplate->assign("fleets_loaded",$fleets_loaded); + $this->template->assign("attfleets",$attfleets); + $this->show('simulator_form','Kampfsimulator'); + } + +} +?> \ No newline at end of file diff --git a/src/functions/smarty/Config_File.class.php b/src/functions/smarty/Config_File.class.php new file mode 100644 index 0000000..414d865 --- /dev/null +++ b/src/functions/smarty/Config_File.class.php @@ -0,0 +1,365 @@ + + * @access public + * @package Smarty + */ + +/* $Id: Config_File.class.php,v 1.1.1.1 2004/06/26 15:22:01 Huhn Exp $ */ +/** + * Config file reading class + * @package Smarty + */ +class Config_File { + /**#@+ + * Options + * @var boolean + */ + /** + * Controls whether variables with the same name overwrite each other. + */ + var $overwrite = true; + + /** + * Controls whether config values of on/true/yes and off/false/no get + * converted to boolean values automatically. + */ + var $booleanize = true; + + /** + * Controls whether hidden config sections/vars are read from the file. + */ + var $read_hidden = true; + + /** + * Controls whether or not to fix mac or dos formatted newlines. + * If set to true, \r or \r\n will be changed to \n. + */ + var $fix_newlines = true; + /**#@-*/ + + /** @access private */ + var $_config_path = ""; + var $_config_data = array(); + /**#@-*/ + + /** + * Constructs a new config file class. + * + * @param string $config_path (optional) path to the config files + */ + function Config_File($config_path = NULL) + { + if (isset($config_path)) + $this->set_path($config_path); + } + + + /** + * Set the path where configuration files can be found. + * + * @param string $config_path path to the config files + */ + function set_path($config_path) + { + if (!empty($config_path)) { + if (!is_string($config_path) || !file_exists($config_path) || !is_dir($config_path)) { + $this->_trigger_error_msg("Bad config file path '$config_path'"); + return; + } + if(substr($config_path, -1) != DIRECTORY_SEPARATOR) { + $config_path .= DIRECTORY_SEPARATOR; + } + + $this->_config_path = $config_path; + } + } + + + /** + * Retrieves config info based on the file, section, and variable name. + * + * @param string $file_name config file to get info for + * @param string $section_name (optional) section to get info for + * @param string $var_name (optional) variable to get info for + * @return string|array a value or array of values + */ + function &get($file_name, $section_name = NULL, $var_name = NULL) + { + if (empty($file_name)) { + $this->_trigger_error_msg('Empty config file name'); + return; + } else { + $file_name = $this->_config_path . $file_name; + if (!isset($this->_config_data[$file_name])) + $this->load_file($file_name, false); + } + + if (!empty($var_name)) { + if (empty($section_name)) { + return $this->_config_data[$file_name]["vars"][$var_name]; + } else { + if(isset($this->_config_data[$file_name]["sections"][$section_name]["vars"][$var_name])) + return $this->_config_data[$file_name]["sections"][$section_name]["vars"][$var_name]; + else + return array(); + } + } else { + if (empty($section_name)) { + return (array)$this->_config_data[$file_name]["vars"]; + } else { + if(isset($this->_config_data[$file_name]["sections"][$section_name]["vars"])) + return (array)$this->_config_data[$file_name]["sections"][$section_name]["vars"]; + else + return array(); + } + } + } + + + /** + * Retrieves config info based on the key. + * + * @param $file_name string config key (filename/section/var) + * @return string|array same as get() + * @uses get() retrieves information from config file and returns it + */ + function &get_key($config_key) + { + list($file_name, $section_name, $var_name) = explode('/', $config_key, 3); + $result = &$this->get($file_name, $section_name, $var_name); + return $result; + } + + /** + * Get all loaded config file names. + * + * @return array an array of loaded config file names + */ + function get_file_names() + { + return array_keys($this->_config_data); + } + + + /** + * Get all section names from a loaded file. + * + * @param string $file_name config file to get section names from + * @return array an array of section names from the specified file + */ + function get_section_names($file_name) + { + $file_name = $this->_config_path . $file_name; + if (!isset($this->_config_data[$file_name])) { + $this->_trigger_error_msg("Unknown config file '$file_name'"); + return; + } + + return array_keys($this->_config_data[$file_name]["sections"]); + } + + + /** + * Get all global or section variable names. + * + * @param string $file_name config file to get info for + * @param string $section_name (optional) section to get info for + * @return array an array of variables names from the specified file/section + */ + function get_var_names($file_name, $section = NULL) + { + if (empty($file_name)) { + $this->_trigger_error_msg('Empty config file name'); + return; + } else if (!isset($this->_config_data[$file_name])) { + $this->_trigger_error_msg("Unknown config file '$file_name'"); + return; + } + + if (empty($section)) + return array_keys($this->_config_data[$file_name]["vars"]); + else + return array_keys($this->_config_data[$file_name]["sections"][$section]["vars"]); + } + + + /** + * Clear loaded config data for a certain file or all files. + * + * @param string $file_name file to clear config data for + */ + function clear($file_name = NULL) + { + if ($file_name === NULL) + $this->_config_data = array(); + else if (isset($this->_config_data[$file_name])) + $this->_config_data[$file_name] = array(); + } + + + /** + * Load a configuration file manually. + * + * @param string $file_name file name to load + * @param boolean $prepend_path whether current config path should be + * prepended to the filename + */ + function load_file($file_name, $prepend_path = true) + { + if ($prepend_path && $this->_config_path != "") + $config_file = $this->_config_path . $file_name; + else + $config_file = $file_name; + + ini_set('track_errors', true); + $fp = @fopen($config_file, "r"); + if (!is_resource($fp)) { + $this->_trigger_error_msg("Could not open config file '$config_file'"); + return false; + } + + $contents = fread($fp, filesize($config_file)); + fclose($fp); + + if($this->fix_newlines) { + // fix mac/dos formatted newlines + $contents = preg_replace('!\r\n?!',"\n",$contents); + } + + $config_data = array(); + + /* replace all multi-line values by placeholders */ + if (preg_match_all('/"""(.*)"""/Us', $contents, $match)) { + $_triple_quotes = $match[1]; + $_i = 0; + $contents = preg_replace('/""".*"""/Use', '"\x1b\x1b\x1b".$_i++."\x1b\x1b\x1b"', $contents); + } else { + $_triple_quotes = null; + } + + /* Get global variables first. */ + if ($contents{0} != '[' && preg_match("/^(.*?)(\n\[|\Z)/s", $contents, $match)) + $config_data["vars"] = $this->_parse_config_block($match[1], $_triple_quotes); + + /* Get section variables. */ + $config_data["sections"] = array(); + preg_match_all("/^\[(.*?)\]/m", $contents, $match); + foreach ($match[1] as $section) { + if ($section{0} == '.' && !$this->read_hidden) + continue; + if (preg_match("/\[".preg_quote($section, '/')."\](.*?)(\n\[|\Z)/s", $contents, $match)) + if ($section{0} == '.') + $section = substr($section, 1); + $config_data["sections"][$section]["vars"] = $this->_parse_config_block($match[1], $_triple_quotes); + } + + $this->_config_data[$config_file] = $config_data; + + return true; + } + + /**#@+ @access private */ + /** + * @var string $config_block + */ + function _parse_config_block($config_block, $triple_quotes) + { + $vars = array(); + + /* First we grab the multi-line values. */ + if (preg_match_all("/^([^=\n]+)=\s*\x1b\x1b\x1b(\d+)\x1b\x1b\x1b\s*$/ms", $config_block, $match, PREG_SET_ORDER)) { + for ($i = 0; $i < count($match); $i++) { + $this->_set_config_var($vars, trim($match[$i][1]), $triple_quotes[$match[$i][2]], false); + } + $config_block = preg_replace("/^[^=\n]+=\s*\x1b\x1b\x1b\d+\x1b\x1b\x1b\s*$/ms", "", $config_block); + } + + + $config_lines = preg_split("/\n+/", $config_block); + + foreach ($config_lines as $line) { + if (preg_match("/^\s*(\.?\w+)\s*=(.*)/", $line, $match)) { + $var_value = preg_replace('/^([\'"])(.*)\1$/', '\2', trim($match[2])); + $this->_set_config_var($vars, trim($match[1]), $var_value, $this->booleanize); + } + } + + return $vars; + } + + /** + * @param array &$container + * @param string $var_name + * @param mixed $var_value + * @param boolean $booleanize determines whether $var_value is converted to + * to true/false + */ + function _set_config_var(&$container, $var_name, $var_value, $booleanize) + { + if ($var_name{0} == '.') { + if (!$this->read_hidden) + return; + else + $var_name = substr($var_name, 1); + } + + if (!preg_match("/^[a-zA-Z_]\w*$/", $var_name)) { + $this->_trigger_error_msg("Bad variable name '$var_name'"); + return; + } + + if ($booleanize) { + if (preg_match("/^(on|true|yes)$/i", $var_value)) + $var_value = true; + else if (preg_match("/^(off|false|no)$/i", $var_value)) + $var_value = false; + } + + if (!isset($container[$var_name]) || $this->overwrite) + $container[$var_name] = $var_value; + else { + settype($container[$var_name], 'array'); + $container[$var_name][] = $var_value; + } + } + + /** + * @uses trigger_error() creates a PHP warning/error + * @param string $error_msg + * @param integer $error_type one of + */ + function _trigger_error_msg($error_msg, $error_type = E_USER_WARNING) + { + trigger_error("Config_File error: $error_msg", $error_type); + } + /**#@-*/ +} + +?> diff --git a/src/functions/smarty/Smarty.class.php b/src/functions/smarty/Smarty.class.php new file mode 100644 index 0000000..52a465b --- /dev/null +++ b/src/functions/smarty/Smarty.class.php @@ -0,0 +1,2010 @@ + + * @author Andrei Zmievski + * @package Smarty + * @version 2.6.0 + */ + +/* $Id: Smarty.class.php,v 1.1.1.1 2004/06/26 15:22:07 Huhn Exp $ */ + +/** + * DIR_SEP isn't used anymore, but third party apps might + */ +if(!defined('DIR_SEP')) { + define('DIR_SEP', DIRECTORY_SEPARATOR); +} + +/** + * set SMARTY_DIR to absolute path to Smarty library files. + * if not defined, include_path will be used. Sets SMARTY_DIR only if user + * application has not already defined it. + */ + +if (!defined('SMARTY_DIR')) { + define('SMARTY_DIR', dirname(__FILE__) . DIRECTORY_SEPARATOR); +} + +define('SMARTY_PHP_PASSTHRU', 0); +define('SMARTY_PHP_QUOTE', 1); +define('SMARTY_PHP_REMOVE', 2); +define('SMARTY_PHP_ALLOW', 3); + +/** + * @package Smarty + */ +class Smarty +{ + /**#@+ + * Smarty Configuration Section + */ + + /** + * The name of the directory where templates are located. + * + * @var string + */ + var $template_dir = 'templates'; + + /** + * The directory where compiled templates are located. + * + * @var string + */ + var $compile_dir = 'templates_c'; + + /** + * The directory where config files are located. + * + * @var string + */ + var $config_dir = 'configs'; + + /** + * An array of directories searched for plugins. + * + * @var array + */ + var $plugins_dir = array('plugins'); + + /** + * If debugging is enabled, a debug console window will display + * when the page loads (make sure your browser allows unrequested + * popup windows) + * + * @var boolean + */ + var $debugging = false; + + /** + * This is the path to the debug console template. If not set, + * the default one will be used. + * + * @var string + */ + var $debug_tpl = ''; + + /** + * This determines if debugging is enable-able from the browser. + *
      + *
    • NONE => no debugging control allowed
    • + *
    • URL => enable debugging when SMARTY_DEBUG is found in the URL.
    • + *
    + * @link http://www.foo.dom/index.php?SMARTY_DEBUG + * @var string + */ + var $debugging_ctrl = 'NONE'; + + /** + * This tells Smarty whether to check for recompiling or not. Recompiling + * does not need to happen unless a template or config file is changed. + * Typically you enable this during development, and disable for + * production. + * + * @var boolean + */ + var $compile_check = true; + + /** + * This forces templates to compile every time. Useful for development + * or debugging. + * + * @var boolean + */ + var $force_compile = false; + + /** + * This enables template caching. + *
      + *
    • 0 = no caching
    • + *
    • 1 = use class cache_lifetime value
    • + *
    • 2 = use cache_lifetime in cache file
    • + *
    + * @var integer + */ + var $caching = 0; + + /** + * The name of the directory for cache files. + * + * @var string + */ + var $cache_dir = 'cache'; + + /** + * This is the number of seconds cached content will persist. + *
      + *
    • 0 = always regenerate cache
    • + *
    • -1 = never expires
    • + *
    + * + * @var integer + */ + var $cache_lifetime = 3600; + + /** + * Only used when $caching is enabled. If true, then If-Modified-Since headers + * are respected with cached content, and appropriate HTTP headers are sent. + * This way repeated hits to a cached page do not send the entire page to the + * client every time. + * + * @var boolean + */ + var $cache_modified_check = false; + + /** + * This determines how Smarty handles "" tags in templates. + * possible values: + *
      + *
    • SMARTY_PHP_PASSTHRU -> print tags as plain text
    • + *
    • SMARTY_PHP_QUOTE -> escape tags as entities
    • + *
    • SMARTY_PHP_REMOVE -> remove php tags
    • + *
    • SMARTY_PHP_ALLOW -> execute php tags
    • + *
    + * + * @var integer + */ + var $php_handling = SMARTY_PHP_PASSTHRU; + + /** + * This enables template security. When enabled, many things are restricted + * in the templates that normally would go unchecked. This is useful when + * untrusted parties are editing templates and you want a reasonable level + * of security. (no direct execution of PHP in templates for example) + * + * @var boolean + */ + var $security = false; + + /** + * This is the list of template directories that are considered secure. This + * is used only if {@link $security} is enabled. One directory per array + * element. {@link $template_dir} is in this list implicitly. + * + * @var array + */ + var $secure_dir = array(); + + /** + * These are the security settings for Smarty. They are used only when + * {@link $security} is enabled. + * + * @var array + */ + var $security_settings = array( + 'PHP_HANDLING' => false, + 'IF_FUNCS' => array('array', 'list', + 'isset', 'empty', + 'count', 'sizeof', + 'in_array', 'is_array', + 'true','false'), + 'INCLUDE_ANY' => false, + 'PHP_TAGS' => false, + 'MODIFIER_FUNCS' => array('count'), + 'ALLOW_CONSTANTS' => false + ); + + /** + * This is an array of directories where trusted php scripts reside. + * {@link $security} is disabled during their inclusion/execution. + * + * @var array + */ + var $trusted_dir = array(); + + /** + * The left delimiter used for the template tags. + * + * @var string + */ + var $left_delimiter = '{'; + + /** + * The right delimiter used for the template tags. + * + * @var string + */ + var $right_delimiter = '}'; + + /** + * The order in which request variables are registered, similar to + * variables_order in php.ini E = Environment, G = GET, P = POST, + * C = Cookies, S = Server + * + * @var string + */ + var $request_vars_order = "EGPCS"; + + /** + * Indicates wether $HTTP_*_VARS[] (request_use_auto_globals=false) + * are uses as request-vars or $_*[]-vars. note: if + * request_use_auto_globals is true, then $request_vars_order has + * no effect, but the php-ini-value "gpc_order" + * + * @var boolean + */ + var $request_use_auto_globals = false; + + /** + * Set this if you want different sets of compiled files for the same + * templates. This is useful for things like different languages. + * Instead of creating separate sets of templates per language, you + * set different compile_ids like 'en' and 'de'. + * + * @var string + */ + var $compile_id = null; + + /** + * This tells Smarty whether or not to use sub dirs in the cache/ and + * templates_c/ directories. sub directories better organized, but + * may not work well with PHP safe mode enabled. + * + * @var boolean + * + */ + var $use_sub_dirs = true; + + /** + * This is a list of the modifiers to apply to all template variables. + * Put each modifier in a separate array element in the order you want + * them applied. example: array('escape:"htmlall"'); + * + * @var array + */ + var $default_modifiers = array(); + + /** + * This is the resource type to be used when not specified + * at the beginning of the resource path. examples: + * $smarty->display('file:index.tpl'); + * $smarty->display('db:index.tpl'); + * $smarty->display('index.tpl'); // will use default resource type + * {include file="file:index.tpl"} + * {include file="db:index.tpl"} + * {include file="index.tpl"} {* will use default resource type *} + * + * @var array + */ + var $default_resource_type = 'file'; + + /** + * The function used for cache file handling. If not set, built-in caching is used. + * + * @var null|string function name + */ + var $cache_handler_func = null; + + /** + * These are the variables from the globals array that are + * assigned to all templates automatically. This isn't really + * necessary any more, you can use the $smarty var to access them + * directly. + * + * @var array + */ + var $global_assign = array('HTTP_SERVER_VARS' => array('SCRIPT_NAME')); + + /** + * The value of "undefined". Leave it alone :-) + * + * @var null + */ + var $undefined = null; + + /** + * This indicates which filters are automatically loaded into Smarty. + * + * @var array array of filter names + */ + var $autoload_filters = array(); + + /**#@+ + * @var boolean + */ + /** + * This tells if config file vars of the same name overwrite each other or not. + * if disabled, same name variables are accumulated in an array. + */ + var $config_overwrite = true; + + /** + * This tells whether or not to automatically booleanize config file variables. + * If enabled, then the strings "on", "true", and "yes" are treated as boolean + * true, and "off", "false" and "no" are treated as boolean false. + */ + var $config_booleanize = true; + + /** + * This tells whether hidden sections [.foobar] are readable from the + * tempalates or not. Normally you would never allow this since that is + * the point behind hidden sections: the application can access them, but + * the templates cannot. + */ + var $config_read_hidden = false; + + /** + * This tells whether or not automatically fix newlines in config files. + * It basically converts \r (mac) or \r\n (dos) to \n + */ + var $config_fix_newlines = true; + /**#@-*/ + + /** + * If a template cannot be found, this PHP function will be executed. + * Useful for creating templates on-the-fly or other special action. + * + * @var string function name + */ + var $default_template_handler_func = ''; + + /** + * The file that contains the compiler class. This can a full + * pathname, or relative to the php_include path. + * + * @var string + */ + var $compiler_file = 'Smarty_Compiler.class.php'; + + /** + * The class used for compiling templates. + * + * @var string + */ + var $compiler_class = 'Smarty_Compiler'; + + /** + * The class used to load config vars. + * + * @var string + */ + var $config_class = 'Config_File'; + +/**#@+ + * END Smarty Configuration Section + * There should be no need to touch anything below this line. + * @access private + */ + /** + * error messages. true/false + * + * @var boolean + */ + var $_error_msg = false; + + /** + * where assigned template vars are kept + * + * @var array + */ + var $_tpl_vars = array(); + + /** + * stores run-time $smarty.* vars + * + * @var null|array + */ + var $_smarty_vars = null; + + /** + * keeps track of sections + * + * @var array + */ + var $_sections = array(); + + /** + * keeps track of foreach blocks + * + * @var array + */ + var $_foreach = array(); + + /** + * keeps track of tag hierarchy + * + * @var array + */ + var $_tag_stack = array(); + + /** + * configuration object + * + * @var Config_file + */ + var $_conf_obj = null; + + /** + * loaded configuration settings + * + * @var array + */ + var $_config = array(array('vars' => array(), 'files' => array())); + + /** + * md5 checksum of the string 'Smarty' + * + * @var string + */ + var $_smarty_md5 = 'f8d698aea36fcbead2b9d5359ffca76f'; + + /** + * Smarty version number + * + * @var string + */ + var $_version = '2.6.0'; + + /** + * current template inclusion depth + * + * @var integer + */ + var $_inclusion_depth = 0; + + /** + * for different compiled templates + * + * @var string + */ + var $_compile_id = null; + + /** + * text in URL to enable debug mode + * + * @var string + */ + var $_smarty_debug_id = 'SMARTY_DEBUG'; + + /** + * debugging information for debug console + * + * @var array + */ + var $_smarty_debug_info = array(); + + /** + * info that makes up a cache file + * + * @var array + */ + var $_cache_info = array(); + + /** + * default file permissions + * + * @var integer + */ + var $_file_perms = 0644; + + /** + * default dir permissions + * + * @var integer + */ + var $_dir_perms = 0771; + + /** + * registered objects + * + * @var array + */ + var $_reg_objects = array(); + + /** + * table keeping track of plugins + * + * @var array + */ + var $_plugins = array( + 'modifier' => array(), + 'function' => array(), + 'block' => array(), + 'compiler' => array(), + 'prefilter' => array(), + 'postfilter' => array(), + 'outputfilter' => array(), + 'resource' => array(), + 'insert' => array()); + + + /** + * cache serials + * + * @var array + */ + var $_cache_serials = array(); + + /** + * name of optional cache include file + * + * @var string + */ + var $_cache_include = null; + + /** + * indicate if the current code is used in a compiled + * include + * + * @var string + */ + var $_cache_including = false; + + /**#@-*/ + /** + * The class constructor. + * + * @uses $global_assign uses {@link assign()} to assign each corresponding + * value from $GLOBALS to the template vars + */ + function Smarty() + { + foreach ($this->global_assign as $key => $var_name) { + if (is_array($var_name)) { + foreach ($var_name as $var) { + if (isset($GLOBALS[$key][$var])) { + $this->assign($var, $GLOBALS[$key][$var]); + } else { + $this->assign($var, $this->undefined); + } + } + } else { + if (isset($GLOBALS[$var_name])) { + $this->assign($var_name, $GLOBALS[$var_name]); + } else { + $this->assign($var_name, $this->undefined); + } + } + } + } + + + /** + * assigns values to template variables + * + * @param array|string $tpl_var the template variable name(s) + * @param mixed $value the value to assign + */ + function assign($tpl_var, $value = null) + { + if (is_array($tpl_var)){ + foreach ($tpl_var as $key => $val) { + if ($key != '') { + $this->_tpl_vars[$key] = $val; + } + } + } else { + if ($tpl_var != '') + $this->_tpl_vars[$tpl_var] = $value; + } + } + + /** + * assigns values to template variables by reference + * + * @param string $tpl_var the template variable name + * @param mixed $value the referenced value to assign + */ + function assign_by_ref($tpl_var, &$value) + { + if ($tpl_var != '') + $this->_tpl_vars[$tpl_var] = &$value; + } + + /** + * appends values to template variables + * + * @param array|string $tpl_var the template variable name(s) + * @param mixed $value the value to append + */ + function append($tpl_var, $value=null, $merge=false) + { + if (is_array($tpl_var)) { + // $tpl_var is an array, ignore $value + foreach ($tpl_var as $_key => $_val) { + if ($_key != '') { + if(!@is_array($this->_tpl_vars[$_key])) { + settype($this->_tpl_vars[$_key],'array'); + } + if($merge && is_array($_val)) { + foreach($_val as $_mkey => $_mval) { + $this->_tpl_vars[$_key][$_mkey] = $_mval; + } + } else { + $this->_tpl_vars[$_key][] = $_val; + } + } + } + } else { + if ($tpl_var != '' && isset($value)) { + if(!@is_array($this->_tpl_vars[$tpl_var])) { + settype($this->_tpl_vars[$tpl_var],'array'); + } + if($merge && is_array($value)) { + foreach($value as $_mkey => $_mval) { + $this->_tpl_vars[$tpl_var][$_mkey] = $_mval; + } + } else { + $this->_tpl_vars[$tpl_var][] = $value; + } + } + } + } + + /** + * appends values to template variables by reference + * + * @param string $tpl_var the template variable name + * @param mixed $value the referenced value to append + */ + function append_by_ref($tpl_var, &$value, $merge=false) + { + if ($tpl_var != '' && isset($value)) { + if(!@is_array($this->_tpl_vars[$tpl_var])) { + settype($this->_tpl_vars[$tpl_var],'array'); + } + if ($merge && is_array($value)) { + foreach($value as $_key => $_val) { + $this->_tpl_vars[$tpl_var][$_key] = &$value[$_key]; + } + } else { + $this->_tpl_vars[$tpl_var][] = &$value; + } + } + } + + + /** + * clear the given assigned template variable. + * + * @param string $tpl_var the template variable to clear + */ + function clear_assign($tpl_var) + { + if (is_array($tpl_var)) + foreach ($tpl_var as $curr_var) + unset($this->_tpl_vars[$curr_var]); + else + unset($this->_tpl_vars[$tpl_var]); + } + + + /** + * Registers custom function to be used in templates + * + * @param string $function the name of the template function + * @param string $function_impl the name of the PHP function to register + */ + function register_function($function, $function_impl, $cacheable=true, $cache_attrs=null) + { + $this->_plugins['function'][$function] = + array($function_impl, null, null, false, $cacheable, $cache_attrs); + + } + + /** + * Unregisters custom function + * + * @param string $function name of template function + */ + function unregister_function($function) + { + unset($this->_plugins['function'][$function]); + } + + /** + * Registers object to be used in templates + * + * @param string $object name of template object + * @param object &$object_impl the referenced PHP object to register + * @param null|array $allowed list of allowed methods (empty = all) + * @param boolean $smarty_args smarty argument format, else traditional + * @param null|array $block_functs list of methods that are block format + */ + function register_object($object, &$object_impl, $allowed = array(), $smarty_args = true, $block_methods = array()) + { + settype($allowed, 'array'); + settype($smarty_args, 'boolean'); + $this->_reg_objects[$object] = + array(&$object_impl, $allowed, $smarty_args, $block_methods); + } + + /** + * Unregisters object + * + * @param string $object name of template object + */ + function unregister_object($object) + { + unset($this->_reg_objects[$object]); + } + + + /** + * Registers block function to be used in templates + * + * @param string $block name of template block + * @param string $block_impl PHP function to register + */ + function register_block($block, $block_impl, $cacheable=true, $cache_attrs=null) + { + $this->_plugins['block'][$block] = + array($block_impl, null, null, false, $cacheable, $cache_attrs); + } + + /** + * Unregisters block function + * + * @param string $block name of template function + */ + function unregister_block($block) + { + unset($this->_plugins['block'][$block]); + } + + /** + * Registers compiler function + * + * @param string $function name of template function + * @param string $function_impl name of PHP function to register + */ + function register_compiler_function($function, $function_impl, $cacheable=true) + { + $this->_plugins['compiler'][$function] = + array($function_impl, null, null, false, $cacheable); + } + + /** + * Unregisters compiler function + * + * @param string $function name of template function + */ + function unregister_compiler_function($function) + { + unset($this->_plugins['compiler'][$function]); + } + + /** + * Registers modifier to be used in templates + * + * @param string $modifier name of template modifier + * @param string $modifier_impl name of PHP function to register + */ + function register_modifier($modifier, $modifier_impl) + { + $this->_plugins['modifier'][$modifier] = + array($modifier_impl, null, null, false); + } + + /** + * Unregisters modifier + * + * @param string $modifier name of template modifier + */ + function unregister_modifier($modifier) + { + unset($this->_plugins['modifier'][$modifier]); + } + + /** + * Registers a resource to fetch a template + * + * @param string $type name of resource + * @param array $functions array of functions to handle resource + */ + function register_resource($type, $functions) + { + if (count($functions)==4) { + $this->_plugins['resource'][$type] = + array($functions, false); + + } elseif (count($functions)==5) { + $this->_plugins['resource'][$type] = + array(array(array(&$functions[0], $functions[1]) + ,array(&$functions[0], $functions[2]) + ,array(&$functions[0], $functions[3]) + ,array(&$functions[0], $functions[4])) + ,false); + + } else { + $this->trigger_error("malformed function-list for '$type' in register_resource"); + + } + } + + /** + * Unregisters a resource + * + * @param string $type name of resource + */ + function unregister_resource($type) + { + unset($this->_plugins['resource'][$type]); + } + + /** + * Registers a prefilter function to apply + * to a template before compiling + * + * @param string $function name of PHP function to register + */ + function register_prefilter($function) + { + $_name = (is_array($function)) ? $function[1] : $function; + $this->_plugins['prefilter'][$_name] + = array($function, null, null, false); + } + + /** + * Unregisters a prefilter function + * + * @param string $function name of PHP function + */ + function unregister_prefilter($function) + { + unset($this->_plugins['prefilter'][$function]); + } + + /** + * Registers a postfilter function to apply + * to a compiled template after compilation + * + * @param string $function name of PHP function to register + */ + function register_postfilter($function) + { + $_name = (is_array($function)) ? $function[1] : $function; + $this->_plugins['postfilter'][$_name] + = array($function, null, null, false); + } + + /** + * Unregisters a postfilter function + * + * @param string $function name of PHP function + */ + function unregister_postfilter($function) + { + unset($this->_plugins['postfilter'][$function]); + } + + /** + * Registers an output filter function to apply + * to a template output + * + * @param string $function name of PHP function + */ + function register_outputfilter($function) + { + $_name = (is_array($function)) ? $function[1] : $function; + $this->_plugins['outputfilter'][$_name] + = array($function, null, null, false); + } + + /** + * Unregisters an outputfilter function + * + * @param string $function name of PHP function + */ + function unregister_outputfilter($function) + { + unset($this->_plugins['outputfilter'][$function]); + } + + /** + * load a filter of specified type and name + * + * @param string $type filter type + * @param string $name filter name + */ + function load_filter($type, $name) + { + switch ($type) { + case 'output': + $_params = array('plugins' => array(array($type . 'filter', $name, null, null, false))); + require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.load_plugins.php'); + smarty_core_load_plugins($_params, $this); + break; + + case 'pre': + case 'post': + if (!isset($this->_plugins[$type . 'filter'][$name])) + $this->_plugins[$type . 'filter'][$name] = false; + break; + } + } + + /** + * clear cached content for the given template and cache id + * + * @param string $tpl_file name of template file + * @param string $cache_id name of cache_id + * @param string $compile_id name of compile_id + * @param string $exp_time expiration time + * @return boolean + */ + function clear_cache($tpl_file = null, $cache_id = null, $compile_id = null, $exp_time = null) + { + + if (!isset($compile_id)) + $compile_id = $this->compile_id; + + if (!isset($tpl_file)) + $compile_id = null; + + $_auto_id = $this->_get_auto_id($cache_id, $compile_id); + + if (!empty($this->cache_handler_func)) { + return call_user_func_array($this->cache_handler_func, + array('clear', &$this, &$dummy, $tpl_file, $cache_id, $compile_id, $exp_time)); + } else { + $_params = array('auto_base' => $this->cache_dir, + 'auto_source' => $tpl_file, + 'auto_id' => $_auto_id, + 'exp_time' => $exp_time); + require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.rm_auto.php'); + return smarty_core_rm_auto($_params, $this); + } + + } + + + /** + * clear the entire contents of cache (all templates) + * + * @param string $exp_time expire time + * @return boolean results of {@link smarty_core_rm_auto()} + */ + function clear_all_cache($exp_time = null) + { + if (!empty($this->cache_handler_func)) { + $dummy = null; + call_user_func_array($this->cache_handler_func, + array('clear', &$this, &$dummy, null, null, null, $exp_time)); + } else { + $_params = array('auto_base' => $this->cache_dir, + 'auto_source' => null, + 'auto_id' => null, + 'exp_time' => $exp_time); + require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.rm_auto.php'); + return smarty_core_rm_auto($_params, $this); + } + } + + + /** + * test to see if valid cache exists for this template + * + * @param string $tpl_file name of template file + * @param string $cache_id + * @param string $compile_id + * @return string|false results of {@link _read_cache_file()} + */ + function is_cached($tpl_file, $cache_id = null, $compile_id = null) + { + if (!$this->caching) + return false; + + if (!isset($compile_id)) + $compile_id = $this->compile_id; + + $_params = array( + 'tpl_file' => $tpl_file, + 'cache_id' => $cache_id, + 'compile_id' => $compile_id + ); + require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.read_cache_file.php'); + return smarty_core_read_cache_file($_params, $this); + } + + + /** + * clear all the assigned template variables. + * + */ + function clear_all_assign() + { + $this->_tpl_vars = array(); + } + + /** + * clears compiled version of specified template resource, + * or all compiled template files if one is not specified. + * This function is for advanced use only, not normally needed. + * + * @param string $tpl_file + * @param string $compile_id + * @param string $exp_time + * @return boolean results of {@link smarty_core_rm_auto()} + */ + function clear_compiled_tpl($tpl_file = null, $compile_id = null, $exp_time = null) + { + if (!isset($compile_id)) { + $compile_id = $this->compile_id; + } + $_params = array('auto_base' => $this->compile_dir, + 'auto_source' => $tpl_file, + 'auto_id' => $compile_id, + 'exp_time' => $exp_time, + 'extensions' => array('.inc', '.php')); + require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.rm_auto.php'); + return smarty_core_rm_auto($_params, $this); + } + + /** + * Checks whether requested template exists. + * + * @param string $tpl_file + * @return boolean + */ + function template_exists($tpl_file) + { + $_params = array('resource_name' => $tpl_file, 'quiet'=>true, 'get_source'=>false); + return $this->_fetch_resource_info($_params); + } + + /** + * Returns an array containing template variables + * + * @param string $name + * @param string $type + * @return array + */ + function &get_template_vars($name=null) + { + if(!isset($name)) { + return $this->_tpl_vars; + } + if(isset($this->_tpl_vars[$name])) { + return $this->_tpl_vars[$name]; + } + } + + /** + * Returns an array containing config variables + * + * @param string $name + * @param string $type + * @return array + */ + function &get_config_vars($name=null) + { + if(!isset($name) && is_array($this->_config[0])) { + return $this->_config[0]['vars']; + } else if(isset($this->_config[0]['vars'][$name])) { + return $this->_config[0]['vars'][$name]; + } + } + + /** + * trigger Smarty error + * + * @param string $error_msg + * @param integer $error_type + */ + function trigger_error($error_msg, $error_type = E_USER_WARNING) + { + trigger_error("Smarty error: $error_msg", $error_type); + } + + + /** + * executes & displays the template results + * + * @param string $resource_name + * @param string $cache_id + * @param string $compile_id + */ + function display($resource_name, $cache_id = null, $compile_id = null) + { + $this->fetch($resource_name, $cache_id, $compile_id, true); + } + + /** + * executes & returns or displays the template results + * + * @param string $resource_name + * @param string $cache_id + * @param string $compile_id + * @param boolean $display + */ + function fetch($resource_name, $cache_id = null, $compile_id = null, $display = false) + { + static $_cache_info = array(); + + $_smarty_old_error_level = $this->debugging ? error_reporting() : error_reporting(error_reporting() & ~E_NOTICE); + + if (!$this->debugging && $this->debugging_ctrl == 'URL' + && @strstr($GLOBALS['HTTP_SERVER_VARS']['QUERY_STRING'], $this->_smarty_debug_id)) { + // enable debugging from URL + $this->debugging = true; + } + + if ($this->debugging) { + // capture time for debugging info + $_params = array(); + require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.get_microtime.php'); + $_debug_start_time = smarty_core_get_microtime($_params, $this); + $this->_smarty_debug_info[] = array('type' => 'template', + 'filename' => $resource_name, + 'depth' => 0); + $_included_tpls_idx = count($this->_smarty_debug_info) - 1; + } + + if (!isset($compile_id)) { + $compile_id = $this->compile_id; + } + + $this->_compile_id = $compile_id; + $this->_inclusion_depth = 0; + + if ($this->caching) { + // save old cache_info, initialize cache_info + array_push($_cache_info, $this->_cache_info); + $this->_cache_info = array(); + $_params = array( + 'tpl_file' => $resource_name, + 'cache_id' => $cache_id, + 'compile_id' => $compile_id, + 'results' => null + ); + require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.read_cache_file.php'); + if (smarty_core_read_cache_file($_params, $this)) { + $_smarty_results = $_params['results']; + if (@count($this->_cache_info['insert_tags'])) { + $_params = array('plugins' => $this->_cache_info['insert_tags']); + require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.load_plugins.php'); + smarty_core_load_plugins($_params, $this); + $_params = array('results' => $_smarty_results); + require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.process_cached_inserts.php'); + $_smarty_results = smarty_core_process_cached_inserts($_params, $this); + } + if (@count($this->_cache_info['cache_serials'])) { + $_params = array('results' => $_smarty_results); + require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.process_compiled_include.php'); + $_smarty_results = smarty_core_process_compiled_include($_params, $this); + } + + + if ($display) { + if ($this->debugging) + { + // capture time for debugging info + $_params = array(); + require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.get_microtime.php'); + $this->_smarty_debug_info[$_included_tpls_idx]['exec_time'] = smarty_core_get_microtime($_params, $this) - $_debug_start_time; + require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.display_debug_console.php'); + $_smarty_results .= smarty_core_display_debug_console($_params, $this); + } + if ($this->cache_modified_check) { + $_last_modified_date = @substr($GLOBALS['HTTP_SERVER_VARS']['HTTP_IF_MODIFIED_SINCE'], 0, strpos($GLOBALS['HTTP_SERVER_VARS']['HTTP_IF_MODIFIED_SINCE'], 'GMT') + 3); + $_gmt_mtime = gmdate('D, d M Y H:i:s', $this->_cache_info['timestamp']).' GMT'; + if (@count($this->_cache_info['insert_tags']) == 0 + && !$this->_cache_serials + && $_gmt_mtime == $_last_modified_date) { + if (php_sapi_name()=='cgi') + header("Status: 304 Not Modified"); + else + header("HTTP/1.1 304 Not Modified"); + + } else { + header("Last-Modified: ".$_gmt_mtime); + echo $_smarty_results; + } + } else { + echo $_smarty_results; + } + error_reporting($_smarty_old_error_level); + // restore initial cache_info + $this->_cache_info = array_pop($_cache_info); + return true; + } else { + error_reporting($_smarty_old_error_level); + // restore initial cache_info + $this->_cache_info = array_pop($_cache_info); + return $_smarty_results; + } + } else { + $this->_cache_info['template'][$resource_name] = true; + if ($this->cache_modified_check) { + header("Last-Modified: ".gmdate('D, d M Y H:i:s', time()).' GMT'); + } + } + } + + // load filters that are marked as autoload + if (count($this->autoload_filters)) { + foreach ($this->autoload_filters as $_filter_type => $_filters) { + foreach ($_filters as $_filter) { + $this->load_filter($_filter_type, $_filter); + } + } + } + + $_smarty_compile_path = $this->_get_compile_path($resource_name); + + // if we just need to display the results, don't perform output + // buffering - for speed + $_cache_including = $this->_cache_including; + $this->_cache_including = false; + if ($display && !$this->caching && count($this->_plugins['outputfilter']) == 0) { + if ($this->_is_compiled($resource_name, $_smarty_compile_path) + || $this->_compile_resource($resource_name, $_smarty_compile_path)) + { + include($_smarty_compile_path); + } + } else { + ob_start(); + if ($this->_is_compiled($resource_name, $_smarty_compile_path) + || $this->_compile_resource($resource_name, $_smarty_compile_path)) + { + include($_smarty_compile_path); + } + $_smarty_results = ob_get_contents(); + ob_end_clean(); + + foreach ((array)$this->_plugins['outputfilter'] as $_output_filter) { + $_smarty_results = call_user_func_array($_output_filter[0], array($_smarty_results, &$this)); + } + } + + if ($this->caching) { + $_params = array('tpl_file' => $resource_name, + 'cache_id' => $cache_id, + 'compile_id' => $compile_id, + 'results' => $_smarty_results); + require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.write_cache_file.php'); + smarty_core_write_cache_file($_params, $this); + require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.process_cached_inserts.php'); + $_smarty_results = smarty_core_process_cached_inserts($_params, $this); + + if ($this->_cache_serials) { + // strip nocache-tags from output + $_smarty_results = preg_replace('!(\{/?nocache\:[0-9a-f]{32}#\d+\})!s' + ,'' + ,$_smarty_results); + } + // restore initial cache_info + $this->_cache_info = array_pop($_cache_info); + } + $this->_cache_including = $_cache_including; + + if ($display) { + if (isset($_smarty_results)) { echo $_smarty_results; } + if ($this->debugging) { + // capture time for debugging info + $_params = array(); + require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.get_microtime.php'); + $this->_smarty_debug_info[$_included_tpls_idx]['exec_time'] = (smarty_core_get_microtime($_params, $this) - $_debug_start_time); + require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.display_debug_console.php'); + echo smarty_core_display_debug_console($_params, $this); + } + error_reporting($_smarty_old_error_level); + return; + } else { + error_reporting($_smarty_old_error_level); + if (isset($_smarty_results)) { return $_smarty_results; } + } + } + + /** + * load configuration values + * + * @param string $file + * @param string $section + * @param string $scope + */ + function config_load($file, $section = null, $scope = 'global') + { + require_once($this->_get_plugin_filepath('function', 'config_load')); + smarty_function_config_load(array('file' => $file, 'section' => $section, 'scope' => $scope), $this); + } + + /** + * return a reference to a registered object + * + * @param string $name + * @return object + */ + function &get_registered_object($name) { + if (!isset($this->_reg_objects[$name])) + $this->_trigger_fatal_error("'$name' is not a registered object"); + + if (!is_object($this->_reg_objects[$name][0])) + $this->_trigger_fatal_error("registered '$name' is not an object"); + + return $this->_reg_objects[$name][0]; + } + + /** + * clear configuration values + * + * @param string $var + */ + function clear_config($var = null) + { + if(!isset($var)) { + // clear all values + $this->_config = array(array('vars' => array(), + 'files' => array())); + } else { + unset($this->_config[0]['vars'][$var]); + } + } + + /** + * get filepath of requested plugin + * + * @param string $type + * @param string $name + * @return string|false + */ + function _get_plugin_filepath($type, $name) + { + $_params = array('type' => $type, 'name' => $name); + require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.assemble_plugin_filepath.php'); + return smarty_core_assemble_plugin_filepath($_params, $this); + } + + /** + * test if resource needs compiling + * + * @param string $resource_name + * @param string $compile_path + * @return boolean + */ + function _is_compiled($resource_name, $compile_path) + { + if (!$this->force_compile && file_exists($compile_path)) { + if (!$this->compile_check) { + // no need to check compiled file + return true; + } else { + // get file source and timestamp + $_params = array('resource_name' => $resource_name, 'get_source'=>false); + if (!$this->_fetch_resource_info($_params, $this)) { + return false; + } + if ($_params['resource_timestamp'] <= filemtime($compile_path)) { + // template not expired, no recompile + return true; + } else { + // compile template + return false; + } + } + } else { + // compiled template does not exist, or forced compile + return false; + } + } + + /** + * compile the template + * + * @param string $resource_name + * @param string $compile_path + * @return boolean + */ + function _compile_resource($resource_name, $compile_path) + { + + $_params = array('resource_name' => $resource_name); + if (!$this->_fetch_resource_info($_params)) { + return false; + } + + $_source_content = $_params['source_content']; + $_resource_timestamp = $_params['resource_timestamp']; + $_cache_include = substr($compile_path, 0, -4).'.inc'; + + if ($this->_compile_source($resource_name, $_source_content, $_compiled_content, $_cache_include)) { + // if a _cache_serial was set, we also have to write an include-file: + if ($this->_cache_include_info) { + require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.write_compiled_include.php'); + smarty_core_write_compiled_include(array_merge($this->_cache_include_info, array('compiled_content'=>$_compiled_content)), $this); + } + + $_params = array('compile_path'=>$compile_path, 'compiled_content' => $_compiled_content, 'resource_timestamp' => $_resource_timestamp); + require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.write_compiled_resource.php'); + smarty_core_write_compiled_resource($_params, $this); + + return true; + } else { + $this->trigger_error($smarty_compiler->_error_msg); + return false; + } + + } + + /** + * compile the given source + * + * @param string $resource_name + * @param string $source_content + * @param string $compiled_content + * @return boolean + */ + function _compile_source($resource_name, &$source_content, &$compiled_content, $cache_include_path=null) + { + if (file_exists(SMARTY_DIR . $this->compiler_file)) { + require_once(SMARTY_DIR . $this->compiler_file); + } else { + // use include_path + require_once($this->compiler_file); + } + + + $smarty_compiler = new $this->compiler_class; + + $smarty_compiler->template_dir = $this->template_dir; + $smarty_compiler->compile_dir = $this->compile_dir; + $smarty_compiler->plugins_dir = $this->plugins_dir; + $smarty_compiler->config_dir = $this->config_dir; + $smarty_compiler->force_compile = $this->force_compile; + $smarty_compiler->caching = $this->caching; + $smarty_compiler->php_handling = $this->php_handling; + $smarty_compiler->left_delimiter = $this->left_delimiter; + $smarty_compiler->right_delimiter = $this->right_delimiter; + $smarty_compiler->_version = $this->_version; + $smarty_compiler->security = $this->security; + $smarty_compiler->secure_dir = $this->secure_dir; + $smarty_compiler->security_settings = $this->security_settings; + $smarty_compiler->trusted_dir = $this->trusted_dir; + $smarty_compiler->_reg_objects = &$this->_reg_objects; + $smarty_compiler->_plugins = &$this->_plugins; + $smarty_compiler->_tpl_vars = &$this->_tpl_vars; + $smarty_compiler->default_modifiers = $this->default_modifiers; + $smarty_compiler->compile_id = $this->_compile_id; + $smarty_compiler->_config = $this->_config; + $smarty_compiler->request_use_auto_globals = $this->request_use_auto_globals; + + $smarty_compiler->_cache_serial = null; + $smarty_compiler->_cache_include = $cache_include_path; + + + $_results = $smarty_compiler->_compile_file($resource_name, $source_content, $compiled_content); + + if ($smarty_compiler->_cache_serial) { + $this->_cache_include_info = array( + 'cache_serial'=>$smarty_compiler->_cache_serial + ,'plugins_code'=>$smarty_compiler->_plugins_code + ,'include_file_path' => $cache_include_path); + + } else { + $this->_cache_include_info = null; + + } + + return $_results; + } + + /** + * Get the compile path for this resource + * + * @param string $resource_name + * @return string results of {@link _get_auto_filename()} + */ + function _get_compile_path($resource_name) + { + return $this->_get_auto_filename($this->compile_dir, $resource_name, + $this->_compile_id) . '.php'; + } + + /** + * fetch the template info. Gets timestamp, and source + * if get_source is true + * + * sets $source_content to the source of the template, and + * $resource_timestamp to its time stamp + * @param string $resource_name + * @param string $source_content + * @param integer $resource_timestamp + * @param boolean $get_source + * @param boolean $quiet + * @return boolean + */ + + function _fetch_resource_info(&$params) + { + if(!isset($params['get_source'])) { $params['get_source'] = true; } + if(!isset($params['quiet'])) { $params['quiet'] = false; } + + $_return = false; + $_params = array('resource_name' => $params['resource_name']) ; + if (isset($params['resource_base_path'])) + $_params['resource_base_path'] = $params['resource_base_path']; + + if ($this->_parse_resource_name($_params)) { + $_resource_type = $_params['resource_type']; + $_resource_name = $_params['resource_name']; + switch ($_resource_type) { + case 'file': + if ($params['get_source']) { + $params['source_content'] = $this->_read_file($_resource_name); + } + $params['resource_timestamp'] = filemtime($_resource_name); + $_return = is_file($_resource_name); + break; + + default: + // call resource functions to fetch the template source and timestamp + if ($params['get_source']) { + $_source_return = isset($this->_plugins['resource'][$_resource_type]) && + call_user_func_array($this->_plugins['resource'][$_resource_type][0][0], + array($_resource_name, &$params['source_content'], &$this)); + } else { + $_source_return = true; + } + + $_timestamp_return = isset($this->_plugins['resource'][$_resource_type]) && + call_user_func_array($this->_plugins['resource'][$_resource_type][0][1], + array($_resource_name, &$params['resource_timestamp'], &$this)); + + $_return = $_source_return && $_timestamp_return; + break; + } + } + + if (!$_return) { + // see if we can get a template with the default template handler + if (!empty($this->default_template_handler_func)) { + if (!is_callable($this->default_template_handler_func)) { + $this->trigger_error("default template handler function \"$this->default_template_handler_func\" doesn't exist."); + } else { + $_return = call_user_func_array( + $this->default_template_handler_func, + array($_params['resource_type'], $_params['resource_name'], &$params['source_content'], &$params['resource_timestamp'], &$this)); + } + } + } + + if (!$_return) { + if (!$params['quiet']) { + $this->trigger_error('unable to read resource: "' . $params['resource_name'] . '"'); + } + } else if ($_return && $this->security) { + require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.is_secure.php'); + if (!smarty_core_is_secure($_params, $this)) { + if (!$params['quiet']) + $this->trigger_error('(secure mode) accessing "' . $params['resource_name'] . '" is not allowed'); + $params['source_content'] = null; + $params['resource_timestamp'] = null; + return false; + } + } + return $_return; + } + + + /** + * parse out the type and name from the resource + * + * @param string $resource_base_path + * @param string $resource_name + * @param string $resource_type + * @param string $resource_name + * @return boolean + */ + + function _parse_resource_name(&$params) + { + + // split tpl_path by the first colon + $_resource_name_parts = explode(':', $params['resource_name'], 2); + + if (count($_resource_name_parts) == 1) { + // no resource type given + $params['resource_type'] = $this->default_resource_type; + $params['resource_name'] = $_resource_name_parts[0]; + } else { + if(strlen($_resource_name_parts[0]) == 1) { + // 1 char is not resource type, but part of filepath + $params['resource_type'] = $this->default_resource_type; + $params['resource_name'] = $params['resource_name']; + } else { + $params['resource_type'] = $_resource_name_parts[0]; + $params['resource_name'] = $_resource_name_parts[1]; + } + } + + if ($params['resource_type'] == 'file') { + if (!preg_match("/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/", $params['resource_name'])) { + // relative pathname to $params['resource_base_path'] + // use the first directory where the file is found + if (isset($params['resource_base_path'])) { + $_resource_base_path = (array)$params['resource_base_path']; + } else { + $_resource_base_path = (array)$this->template_dir; + $_resource_base_path[] = '.'; + } + foreach ($_resource_base_path as $_curr_path) { + $_fullpath = $_curr_path . DIRECTORY_SEPARATOR . $params['resource_name']; + if (file_exists($_fullpath) && is_file($_fullpath)) { + $params['resource_name'] = $_fullpath; + return true; + } + // didn't find the file, try include_path + $_params = array('file_path' => $_fullpath); + require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.get_include_path.php'); + if(smarty_core_get_include_path($_params, $this)) { + $params['resource_name'] = $_params['new_file_path']; + return true; + } + } + return false; + } + } elseif (empty($this->_plugins['resource'][$params['resource_type']])) { + $_params = array('type' => $params['resource_type']); + require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.load_resource_plugin.php'); + smarty_core_load_resource_plugin($_params, $this); + } + + return true; + } + + + /** + * Handle modifiers + * + * @param string|null $modifier_name + * @param array|null $map_array + * @return string result of modifiers + */ + function _run_mod_handler() + { + $_args = func_get_args(); + list($_modifier_name, $_map_array) = array_splice($_args, 0, 2); + list($_func_name, $_tpl_file, $_tpl_line) = + $this->_plugins['modifier'][$_modifier_name]; + + $_var = $_args[0]; + foreach ($_var as $_key => $_val) { + $_args[0] = $_val; + $_var[$_key] = call_user_func_array($_func_name, $_args); + } + return $_var; + } + + /** + * Remove starting and ending quotes from the string + * + * @param string $string + * @return string + */ + function _dequote($string) + { + if (($string{0} == "'" || $string{0} == '"') && + $string{strlen($string)-1} == $string{0}) + return substr($string, 1, -1); + else + return $string; + } + + + /** + * read in a file from line $start for $lines. + * read the entire file if $start and $lines are null. + * + * @param string $filename + * @param integer $start + * @param integer $lines + * @return string + */ + function _read_file($filename, $start=null, $lines=null) + { + if (!($fd = @fopen($filename, 'r'))) { + return false; + } + flock($fd, LOCK_SH); + if ($start == null && $lines == null) { + // read the entire file + $contents = fread($fd, filesize($filename)); + } else { + if ( $start > 1 ) { + // skip the first lines before $start + for ($loop=1; $loop < $start; $loop++) { + fgets($fd, 65536); + } + } + if ( $lines == null ) { + // read the rest of the file + while (!feof($fd)) { + $contents .= fgets($fd, 65536); + } + } else { + // read up to $lines lines + for ($loop=0; $loop < $lines; $loop++) { + $contents .= fgets($fd, 65536); + if (feof($fd)) { + break; + } + } + } + } + fclose($fd); + return $contents; + } + + /** + * get a concrete filename for automagically created content + * + * @param string $auto_base + * @param string $auto_source + * @param string $auto_id + * @return string + * @staticvar string|null + * @staticvar string|null + */ + function _get_auto_filename($auto_base, $auto_source = null, $auto_id = null) + { + $_compile_dir_sep = $this->use_sub_dirs ? DIRECTORY_SEPARATOR : '^'; + + if(@is_dir($auto_base)) { + $_return = $auto_base . DIRECTORY_SEPARATOR; + } else { + // auto_base not found, try include_path + $_params = array('file_path' => $auto_base); + require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.get_include_path.php'); + smarty_core_get_include_path($_params, $this); + $_return = isset($_params['new_file_path']) ? $_params['new_file_path'] . DIRECTORY_SEPARATOR : null; + } + + if(isset($auto_id)) { + // make auto_id safe for directory names + $auto_id = str_replace('%7C',$_compile_dir_sep,(urlencode($auto_id))); + // split into separate directories + $_return .= $auto_id . $_compile_dir_sep; + } + + if(isset($auto_source)) { + // make source name safe for filename + $_filename = urlencode(basename($auto_source)); + $_crc32 = crc32($auto_source) . $_compile_dir_sep; + // prepend %% to avoid name conflicts with + // with $params['auto_id'] names + $_crc32 = '%%' . substr($_crc32,0,3) . $_compile_dir_sep . '%%' . $_crc32; + $_return .= $_crc32 . $_filename; + } + + return $_return; + } + + /** + * unlink a file, possibly using expiration time + * + * @param string $resource + * @param integer $exp_time + */ + function _unlink($resource, $exp_time = null) + { + if(isset($exp_time)) { + if(time() - @filemtime($resource) >= $exp_time) { + return @unlink($resource); + } + } else { + return @unlink($resource); + } + } + + /** + * returns an auto_id for auto-file-functions + * + * @param string $cache_id + * @param string $compile_id + * @return string|null + */ + function _get_auto_id($cache_id=null, $compile_id=null) { + if (isset($cache_id)) + return (isset($compile_id)) ? $cache_id . '|' . $compile_id : $cache_id; + elseif(isset($compile_id)) + return $compile_id; + else + return null; + } + + /** + * trigger Smarty plugin error + * + * @param string $error_msg + * @param string $tpl_file + * @param integer $tpl_line + * @param string $file + * @param integer $line + * @param integer $error_type + */ + function _trigger_fatal_error($error_msg, $tpl_file = null, $tpl_line = null, + $file = null, $line = null, $error_type = E_USER_ERROR) + { + if(isset($file) && isset($line)) { + $info = ' ('.basename($file).", line $line)"; + } else { + $info = null; + } + if (isset($tpl_line) && isset($tpl_file)) { + trigger_error("Smarty error: [in " . $tpl_file . " line " . + $tpl_line . "]: $error_msg$info", $error_type); + } else { + trigger_error("Smarty error: $error_msg$info", $error_type); + } + } + + + /** + * callback function for preg_replace, to call a non-cacheable block + * @return string + */ + function _process_compiled_include_callback($match) { + $_func = '_smarty_tplfunc_'.$match[2].'_'.$match[3]; + ob_start(); + $_func($this); + $_ret = ob_get_contents(); + ob_end_clean(); + return $_ret; + } + + + /** + * called for included templates + * + * @param string $_smarty_include_tpl_file + * @param string $_smarty_include_vars + */ + + // $_smarty_include_tpl_file, $_smarty_include_vars + + function _smarty_include($params) + { + if ($this->debugging) { + $_params = array(); + require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.get_microtime.php'); + $debug_start_time = smarty_core_get_microtime($_params, $this); + $this->_smarty_debug_info[] = array('type' => 'template', + 'filename' => $params['smarty_include_tpl_file'], + 'depth' => ++$this->_inclusion_depth); + $included_tpls_idx = count($this->_smarty_debug_info) - 1; + } + + $this->_tpl_vars = array_merge($this->_tpl_vars, $params['smarty_include_vars']); + + // config vars are treated as local, so push a copy of the + // current ones onto the front of the stack + array_unshift($this->_config, $this->_config[0]); + + $_smarty_compile_path = $this->_get_compile_path($params['smarty_include_tpl_file']); + + + if ($this->_is_compiled($params['smarty_include_tpl_file'], $_smarty_compile_path) + || $this->_compile_resource($params['smarty_include_tpl_file'], $_smarty_compile_path)) + { + include($_smarty_compile_path); + } + + // pop the local vars off the front of the stack + array_shift($this->_config); + + $this->_inclusion_depth--; + + if ($this->debugging) { + // capture time for debugging info + $_params = array(); + require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.get_microtime.php'); + $this->_smarty_debug_info[$included_tpls_idx]['exec_time'] = smarty_core_get_microtime($_params, $this) - $debug_start_time; + } + + if ($this->caching) { + $this->_cache_info['template'][$params['smarty_include_tpl_file']] = true; + } + } + + + /** + * get or set an array of cached attributes for function that is + * not cacheable + * @return array + */ + function &_smarty_cache_attrs($cache_serial, $count) { + $_cache_attrs =& $this->_cache_info['cache_attrs'][$cache_serial][$count]; + + if ($this->_cache_including) { + /* return next set of cache_attrs */ + $_return =& current($_cache_attrs); + next($_cache_attrs); + return $_return; + + } else { + /* add a reference to a new set of cache_attrs */ + $_cache_attrs[] = array(); + return $_cache_attrs[count($_cache_attrs)-1]; + + } + + } + + + /** + * wrapper for include() retaining $this + * @return mixed + */ + function _include($filename, $once=false, $params=null) + { + if ($once) { + return include_once($filename); + } else { + return include($filename); + } + } + + + /** + * wrapper for eval() retaining $this + * @return mixed + */ + function _eval($code, $params=null) + { + return eval($code); + } + /**#@-*/ + +} + +/* vim: set expandtab: */ + +?> diff --git a/src/functions/smarty/Smarty_Compiler.class.php b/src/functions/smarty/Smarty_Compiler.class.php new file mode 100644 index 0000000..c8e8e8f --- /dev/null +++ b/src/functions/smarty/Smarty_Compiler.class.php @@ -0,0 +1,2123 @@ + + * @author Andrei Zmievski + * @version 2.6.0 + * @copyright 2001-2003 ispi of Lincoln, Inc. + * @package Smarty + */ + +/* $Id: Smarty_Compiler.class.php,v 1.1.1.1 2004/06/26 15:22:12 Huhn Exp $ */ + +/** + * Template compiling class + * @package Smarty + */ +class Smarty_Compiler extends Smarty { + + // internal vars + /**#@+ + * @access private + */ + var $_sectionelse_stack = array(); // keeps track of whether section had 'else' part + var $_foreachelse_stack = array(); // keeps track of whether foreach had 'else' part + var $_literal_blocks = array(); // keeps literal template blocks + var $_php_blocks = array(); // keeps php code blocks + var $_current_file = null; // the current template being compiled + var $_current_line_no = 1; // line number for error messages + var $_capture_stack = array(); // keeps track of nested capture buffers + var $_plugin_info = array(); // keeps track of plugins to load + var $_init_smarty_vars = false; + var $_permitted_tokens = array('true','false','yes','no','on','off','null'); + var $_db_qstr_regexp = null; // regexps are setup in the constructor + var $_si_qstr_regexp = null; + var $_qstr_regexp = null; + var $_func_regexp = null; + var $_var_bracket_regexp = null; + var $_dvar_guts_regexp = null; + var $_dvar_regexp = null; + var $_cvar_regexp = null; + var $_svar_regexp = null; + var $_avar_regexp = null; + var $_mod_regexp = null; + var $_var_regexp = null; + var $_parenth_param_regexp = null; + var $_func_call_regexp = null; + var $_obj_ext_regexp = null; + var $_obj_start_regexp = null; + var $_obj_params_regexp = null; + var $_obj_call_regexp = null; + var $_cacheable_state = 0; + var $_cache_attrs_count = 0; + var $_nocache_count = 0; + var $_cache_serial = null; + var $_cache_include = null; + + var $_strip_depth = 0; + var $_additional_newline = "\n"; + + /**#@-*/ + /** + * The class constructor. + */ + function Smarty_Compiler() + { + // matches double quoted strings: + // "foobar" + // "foo\"bar" + $this->_db_qstr_regexp = '"[^"\\\\]*(?:\\\\.[^"\\\\]*)*"'; + + // matches single quoted strings: + // 'foobar' + // 'foo\'bar' + $this->_si_qstr_regexp = '\'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*\''; + + // matches single or double quoted strings + $this->_qstr_regexp = '(?:' . $this->_db_qstr_regexp . '|' . $this->_si_qstr_regexp . ')'; + + // matches bracket portion of vars + // [0] + // [foo] + // [$bar] + $this->_var_bracket_regexp = '\[\$?[\w\.]+\]'; + + // matches $ vars (not objects): + // $foo + // $foo.bar + // $foo.bar.foobar + // $foo[0] + // $foo[$bar] + // $foo[5][blah] + // $foo[5].bar[$foobar][4] + $this->_dvar_math_regexp = '[\+\-\*\/\%]'; + $this->_dvar_math_var_regexp = '[\$\w\.\+\-\*\/\%\d\>\[\]]'; + $this->_dvar_num_var_regexp = '\-?\d+(?:\.\d+)?' . $this->_dvar_math_var_regexp; + $this->_dvar_guts_regexp = '\w+(?:' . $this->_var_bracket_regexp + . ')*(?:\.\$?\w+(?:' . $this->_var_bracket_regexp . ')*)*(?:' . $this->_dvar_math_regexp . '(?:\-?\d+(?:\.\d+)?|' . $this->_dvar_math_var_regexp . ')*)?'; + $this->_dvar_regexp = '\$' . $this->_dvar_guts_regexp; + + // matches config vars: + // #foo# + // #foobar123_foo# + $this->_cvar_regexp = '\#\w+\#'; + + // matches section vars: + // %foo.bar% + $this->_svar_regexp = '\%\w+\.\w+\%'; + + // matches all valid variables (no quotes, no modifiers) + $this->_avar_regexp = '(?:' . $this->_dvar_regexp . '|' + . $this->_cvar_regexp . '|' . $this->_svar_regexp . ')'; + + // matches valid variable syntax: + // $foo + // $foo + // #foo# + // #foo# + // "text" + // "text" + $this->_var_regexp = '(?:' . $this->_avar_regexp . '|' . $this->_qstr_regexp . ')'; + + // matches valid object call (no objects allowed in parameters): + // $foo->bar + // $foo->bar() + // $foo->bar("text") + // $foo->bar($foo, $bar, "text") + // $foo->bar($foo, "foo") + // $foo->bar->foo() + // $foo->bar->foo->bar() + $this->_obj_ext_regexp = '\->(?:\$?' . $this->_dvar_guts_regexp . ')'; + $this->_obj_params_regexp = '\((?:\w+|' + . $this->_var_regexp . '(?:\s*,\s*(?:(?:\w+|' + . $this->_var_regexp . ')))*)?\)'; + $this->_obj_start_regexp = '(?:' . $this->_dvar_regexp . '(?:' . $this->_obj_ext_regexp . ')+)'; + $this->_obj_call_regexp = '(?:' . $this->_obj_start_regexp . '(?:' . $this->_obj_params_regexp . ')?)'; + + // matches valid modifier syntax: + // |foo + // |@foo + // |foo:"bar" + // |foo:$bar + // |foo:"bar":$foobar + // |foo|bar + // |foo:$foo->bar + $this->_mod_regexp = '(?:\|@?\w+(?::(?>-?\w+|' + . $this->_obj_call_regexp . '|' . $this->_avar_regexp . '|' . $this->_qstr_regexp .'))*)'; + + // matches valid function name: + // foo123 + // _foo_bar + $this->_func_regexp = '[a-zA-Z_]\w*'; + + // matches valid registered object: + // foo->bar + $this->_reg_obj_regexp = '[a-zA-Z_]\w*->[a-zA-Z_]\w*'; + + // matches valid parameter values: + // true + // $foo + // $foo|bar + // #foo# + // #foo#|bar + // "text" + // "text"|bar + // $foo->bar + $this->_param_regexp = '(?:\s*(?:' . $this->_obj_call_regexp . '|' + . $this->_var_regexp . '|\w+)(?>' . $this->_mod_regexp . '*)\s*)'; + + // matches valid parenthesised function parameters: + // + // "text" + // $foo, $bar, "text" + // $foo|bar, "foo"|bar, $foo->bar($foo)|bar + $this->_parenth_param_regexp = '(?:\((?:\w+|' + . $this->_param_regexp . '(?:\s*,\s*(?:(?:\w+|' + . $this->_param_regexp . ')))*)?\))'; + + // matches valid function call: + // foo() + // foo_bar($foo) + // _foo_bar($foo,"bar") + // foo123($foo,$foo->bar(),"foo") + $this->_func_call_regexp = '(?:' . $this->_func_regexp . '\s*(?:' + . $this->_parenth_param_regexp . '))'; + } + + /** + * compile a resource + * + * sets $compiled_content to the compiled source + * @param string $resource_name + * @param string $source_content + * @param string $compiled_content + * @return true + */ + function _compile_file($resource_name, $source_content, &$compiled_content) + { + + if ($this->security) { + // do not allow php syntax to be executed unless specified + if ($this->php_handling == SMARTY_PHP_ALLOW && + !$this->security_settings['PHP_HANDLING']) { + $this->php_handling = SMARTY_PHP_PASSTHRU; + } + } + + $this->_load_filters(); + + $this->_current_file = $resource_name; + $this->_current_line_no = 1; + $ldq = preg_quote($this->left_delimiter, '!'); + $rdq = preg_quote($this->right_delimiter, '!'); + + // run template source through prefilter functions + if (count($this->_plugins['prefilter']) > 0) { + foreach ($this->_plugins['prefilter'] as $filter_name => $prefilter) { + if ($prefilter === false) continue; + if ($prefilter[3] || is_callable($prefilter[0])) { + $source_content = call_user_func_array($prefilter[0], + array($source_content, &$this)); + $this->_plugins['prefilter'][$filter_name][3] = true; + } else { + $this->_trigger_fatal_error("[plugin] prefilter '$filter_name' is not implemented"); + } + } + } + + /* Annihilate the comments. */ + $source_content = preg_replace("!({$ldq})\*(.*?)\*({$rdq})!se", + "'\\1*'.str_repeat(\"\n\", substr_count('\\2', \"\n\")) .'*\\3'", + $source_content); + + /* Pull out the literal blocks. */ + preg_match_all("!{$ldq}\s*literal\s*{$rdq}(.*?){$ldq}\s*/literal\s*{$rdq}!s", $source_content, $_match); + $this->_literal_blocks = $_match[1]; + $source_content = preg_replace("!{$ldq}\s*literal\s*{$rdq}(.*?){$ldq}\s*/literal\s*{$rdq}!s", + $this->_quote_replace($this->left_delimiter.'literal'.$this->right_delimiter), $source_content); + + /* Pull out the php code blocks. */ + preg_match_all("!{$ldq}php{$rdq}(.*?){$ldq}/php{$rdq}!s", $source_content, $_match); + $this->_php_blocks = $_match[1]; + $source_content = preg_replace("!{$ldq}php{$rdq}(.*?){$ldq}/php{$rdq}!s", + $this->_quote_replace($this->left_delimiter.'php'.$this->right_delimiter), $source_content); + + /* Gather all template tags. */ + preg_match_all("!{$ldq}\s*(.*?)\s*{$rdq}!s", $source_content, $_match); + $template_tags = $_match[1]; + /* Split content by template tags to obtain non-template content. */ + $text_blocks = preg_split("!{$ldq}.*?{$rdq}!s", $source_content); + + /* loop through text blocks */ + for ($curr_tb = 0, $for_max = count($text_blocks); $curr_tb < $for_max; $curr_tb++) { + /* match anything resembling php tags */ + if (preg_match_all('!(<\?(?:\w+|=)?|\?>|language\s*=\s*[\"\']?php[\"\']?)!is', $text_blocks[$curr_tb], $sp_match)) { + /* replace tags with placeholders to prevent recursive replacements */ + $sp_match[1] = array_unique($sp_match[1]); + usort($sp_match[1], '_smarty_sort_length'); + for ($curr_sp = 0, $for_max2 = count($sp_match[1]); $curr_sp < $for_max2; $curr_sp++) { + $text_blocks[$curr_tb] = str_replace($sp_match[1][$curr_sp],'%%%SMARTYSP'.$curr_sp.'%%%',$text_blocks[$curr_tb]); + } + /* process each one */ + for ($curr_sp = 0, $for_max2 = count($sp_match[1]); $curr_sp < $for_max2; $curr_sp++) { + if ($this->php_handling == SMARTY_PHP_PASSTHRU) { + /* echo php contents */ + $text_blocks[$curr_tb] = str_replace('%%%SMARTYSP'.$curr_sp.'%%%', ''."\n", $text_blocks[$curr_tb]); + } else if ($this->php_handling == SMARTY_PHP_QUOTE) { + /* quote php tags */ + $text_blocks[$curr_tb] = str_replace('%%%SMARTYSP'.$curr_sp.'%%%', htmlspecialchars($sp_match[1][$curr_sp]), $text_blocks[$curr_tb]); + } else if ($this->php_handling == SMARTY_PHP_REMOVE) { + /* remove php tags */ + $text_blocks[$curr_tb] = str_replace('%%%SMARTYSP'.$curr_sp.'%%%', '', $text_blocks[$curr_tb]); + } else { + /* SMARTY_PHP_ALLOW, but echo non php starting tags */ + $sp_match[1][$curr_sp] = preg_replace('%(<\?(?!php|=|$))%i', ''."\n", $sp_match[1][$curr_sp]); + $text_blocks[$curr_tb] = str_replace('%%%SMARTYSP'.$curr_sp.'%%%', $sp_match[1][$curr_sp], $text_blocks[$curr_tb]); + } + } + } + } + + /* Compile the template tags into PHP code. */ + $compiled_tags = array(); + for ($i = 0, $for_max = count($template_tags); $i < $for_max; $i++) { + $this->_current_line_no += substr_count($text_blocks[$i], "\n"); + $compiled_tags[] = $this->_compile_tag($template_tags[$i]); + $this->_current_line_no += substr_count($template_tags[$i], "\n"); + } + + $compiled_content = ''; + + /* Interleave the compiled contents and text blocks to get the final result. */ + for ($i = 0, $for_max = count($compiled_tags); $i < $for_max; $i++) { + if ($compiled_tags[$i] == '') { + // tag result empty, remove first newline from following text block + $text_blocks[$i+1] = preg_replace('!^(\r\n|\r|\n)!', '', $text_blocks[$i+1]); + } + $compiled_content .= $text_blocks[$i].$compiled_tags[$i]; + } + $compiled_content .= $text_blocks[$i]; + + /* Reformat data between 'strip' and '/strip' tags, removing spaces, tabs and newlines. */ + if (preg_match_all("!{$ldq}strip{$rdq}.*?{$ldq}/strip{$rdq}!s", $compiled_content, $_match)) { + $strip_tags = $_match[0]; + $strip_tags_modified = preg_replace("!{$ldq}/?strip{$rdq}|[\t ]+$|^[\t ]+!m", '', $strip_tags); + $strip_tags_modified = preg_replace('![\r\n]+!m', '', $strip_tags_modified); + for ($i = 0, $for_max = count($strip_tags); $i < $for_max; $i++) + $compiled_content = preg_replace("!{$ldq}strip{$rdq}.*?{$ldq}/strip{$rdq}!s", + $this->_quote_replace($strip_tags_modified[$i]), + $compiled_content, 1); + } + + // remove \n from the end of the file, if any + if (($_len=strlen($compiled_content)) && ($compiled_content{$_len - 1} == "\n" )) { + $compiled_content = substr($compiled_content, 0, -1); + } + + if (!empty($this->_cache_serial)) { + $compiled_content = "_cache_serials['".$this->_cache_include."'] = '".$this->_cache_serial."'; ?>" . $compiled_content; + } + + // remove unnecessary close/open tags + $compiled_content = preg_replace('!\?>\n?<\?php!', '', $compiled_content); + + // run compiled template through postfilter functions + if (count($this->_plugins['postfilter']) > 0) { + foreach ($this->_plugins['postfilter'] as $filter_name => $postfilter) { + if ($postfilter === false) continue; + if ($postfilter[3] || is_callable($postfilter[0])) { + $compiled_content = call_user_func_array($postfilter[0], + array($compiled_content, &$this)); + $this->_plugins['postfilter'][$filter_name][3] = true; + } else { + $this->_trigger_fatal_error("Smarty plugin error: postfilter '$filter_name' is not implemented"); + } + } + } + + // put header at the top of the compiled template + $template_header = "_version.", created on ".strftime("%Y-%m-%d %H:%M:%S")."\n"; + $template_header .= " compiled from ".strtr(urlencode($resource_name), array('%2F'=>'/', '%3A'=>':'))." */ ?>\n"; + + /* Emit code to load needed plugins. */ + $this->_plugins_code = ''; + if (count($this->_plugin_info)) { + $_plugins_params = "array('plugins' => array("; + foreach ($this->_plugin_info as $plugin_type => $plugins) { + foreach ($plugins as $plugin_name => $plugin_info) { + $_plugins_params .= "array('$plugin_type', '$plugin_name', '$plugin_info[0]', $plugin_info[1], "; + $_plugins_params .= $plugin_info[2] ? 'true),' : 'false),'; + } + } + $_plugins_params .= '))'; + $plugins_code = "\n"; + $template_header .= $plugins_code; + $this->_plugin_info = array(); + $this->_plugins_code = $plugins_code; + } + + if ($this->_init_smarty_vars) { + $template_header .= "\n"; + $this->_init_smarty_vars = false; + } + + $compiled_content = $template_header . $compiled_content; + + return true; + } + + /** + * Compile a template tag + * + * @param string $template_tag + * @return string + */ + function _compile_tag($template_tag) + { + /* Matched comment. */ + if ($template_tag{0} == '*' && $template_tag{strlen($template_tag) - 1} == '*') + return ''; + + /* Split tag into two three parts: command, command modifiers and the arguments. */ + if(! preg_match('/^(?:(' . $this->_obj_call_regexp . '|' . $this->_var_regexp + . '|\/?' . $this->_reg_obj_regexp . '|\/?' . $this->_func_regexp . ')(' . $this->_mod_regexp . '*)) + (?:\s+(.*))?$ + /xs', $template_tag, $match)) { + $this->_syntax_error("unrecognized tag: $template_tag", E_USER_ERROR, __FILE__, __LINE__); + } + + $tag_command = $match[1]; + $tag_modifier = isset($match[2]) ? $match[2] : null; + $tag_args = isset($match[3]) ? $match[3] : null; + + if (preg_match('!^' . $this->_obj_call_regexp . '|' . $this->_var_regexp . '$!', $tag_command)) { + /* tag name is a variable or object */ + $_return = $this->_parse_var_props($tag_command . $tag_modifier, $this->_parse_attrs($tag_args)); + if(isset($_tag_attrs['assign'])) { + return "assign('" . $this->_dequote($_tag_attrs['assign']) . "', $_return ); ?>\n"; + } else { + return "" . $this->_additional_newline; + } + } + + /* If the tag name is a registered object, we process it. */ + if (preg_match('!^\/?' . $this->_reg_obj_regexp . '$!', $tag_command)) { + return $this->_compile_registered_object_tag($tag_command, $this->_parse_attrs($tag_args), $tag_modifier); + } + + switch ($tag_command) { + case 'include': + return $this->_compile_include_tag($tag_args); + + case 'include_php': + return $this->_compile_include_php_tag($tag_args); + + case 'if': + return $this->_compile_if_tag($tag_args); + + case 'else': + return ''; + + case 'elseif': + return $this->_compile_if_tag($tag_args, true); + + case '/if': + return ''; + + case 'capture': + return $this->_compile_capture_tag(true, $tag_args); + + case '/capture': + return $this->_compile_capture_tag(false); + + case 'ldelim': + return $this->left_delimiter; + + case 'rdelim': + return $this->right_delimiter; + + case 'section': + array_push($this->_sectionelse_stack, false); + return $this->_compile_section_start($tag_args); + + case 'sectionelse': + $this->_sectionelse_stack[count($this->_sectionelse_stack)-1] = true; + return ""; + + case '/section': + if (array_pop($this->_sectionelse_stack)) + return ""; + else + return ""; + + case 'foreach': + array_push($this->_foreachelse_stack, false); + return $this->_compile_foreach_start($tag_args); + break; + + case 'foreachelse': + $this->_foreachelse_stack[count($this->_foreachelse_stack)-1] = true; + return ""; + + case '/foreach': + if (array_pop($this->_foreachelse_stack)) + return ""; + else + return ""; + + case 'strip': + case '/strip': + if ($tag_command{0}=='/') { + if (--$this->_strip_depth==0) { /* outermost closing {/strip} */ + $this->_additional_newline = "\n"; + return $this->left_delimiter.$tag_command.$this->right_delimiter; + } + } else { + if ($this->_strip_depth++==0) { /* outermost opening {strip} */ + $this->_additional_newline = ""; + return $this->left_delimiter.$tag_command.$this->right_delimiter; + } + } + return ''; + + case 'literal': + list (,$literal_block) = each($this->_literal_blocks); + $this->_current_line_no += substr_count($literal_block, "\n"); + return "" . $this->_additional_newline; + + case 'php': + if ($this->security && !$this->security_settings['PHP_TAGS']) { + $this->_syntax_error("(secure mode) php tags not permitted", E_USER_WARNING, __FILE__, __LINE__); + return; + } + list (,$php_block) = each($this->_php_blocks); + $this->_current_line_no += substr_count($php_block, "\n"); + return ''; + + case 'insert': + return $this->_compile_insert_tag($tag_args); + + default: + if ($this->_compile_compiler_tag($tag_command, $tag_args, $output)) { + return $output; + } else if ($this->_compile_block_tag($tag_command, $tag_args, $tag_modifier, $output)) { + return $output; + } else { + return $this->_compile_custom_tag($tag_command, $tag_args, $tag_modifier); + } + } + } + + + /** + * compile the custom compiler tag + * + * sets $output to the compiled custom compiler tag + * @param string $tag_command + * @param string $tag_args + * @param string $output + * @return boolean + */ + function _compile_compiler_tag($tag_command, $tag_args, &$output) + { + $found = false; + $have_function = true; + + /* + * First we check if the compiler function has already been registered + * or loaded from a plugin file. + */ + if (isset($this->_plugins['compiler'][$tag_command])) { + $found = true; + $plugin_func = $this->_plugins['compiler'][$tag_command][0]; + if (!is_callable($plugin_func)) { + $message = "compiler function '$tag_command' is not implemented"; + $have_function = false; + } + } + /* + * Otherwise we need to load plugin file and look for the function + * inside it. + */ + else if ($plugin_file = $this->_get_plugin_filepath('compiler', $tag_command)) { + $found = true; + + include_once $plugin_file; + + $plugin_func = 'smarty_compiler_' . $tag_command; + if (!is_callable($plugin_func)) { + $message = "plugin function $plugin_func() not found in $plugin_file\n"; + $have_function = false; + } else { + $this->_plugins['compiler'][$tag_command] = array($plugin_func, null, null, null, true); + } + } + + /* + * True return value means that we either found a plugin or a + * dynamically registered function. False means that we didn't and the + * compiler should now emit code to load custom function plugin for this + * tag. + */ + if ($found) { + if ($have_function) { + $output = call_user_func_array($plugin_func, array($tag_args, &$this)); + if($output != '') { + $output = '_push_cacheable_state('compiler', $tag_command) + . $output + . $this->_pop_cacheable_state('compiler', $tag_command) . ' ?>'; + } + } else { + $this->_syntax_error($message, E_USER_WARNING, __FILE__, __LINE__); + } + return true; + } else { + return false; + } + } + + + /** + * compile block function tag + * + * sets $output to compiled block function tag + * @param string $tag_command + * @param string $tag_args + * @param string $tag_modifier + * @param string $output + * @return boolean + */ + function _compile_block_tag($tag_command, $tag_args, $tag_modifier, &$output) + { + if ($tag_command{0} == '/') { + $start_tag = false; + $tag_command = substr($tag_command, 1); + } else + $start_tag = true; + + $found = false; + $have_function = true; + + /* + * First we check if the block function has already been registered + * or loaded from a plugin file. + */ + if (isset($this->_plugins['block'][$tag_command])) { + $found = true; + $plugin_func = $this->_plugins['block'][$tag_command][0]; + if (!is_callable($plugin_func)) { + $message = "block function '$tag_command' is not implemented"; + $have_function = false; + } + } + /* + * Otherwise we need to load plugin file and look for the function + * inside it. + */ + else if ($plugin_file = $this->_get_plugin_filepath('block', $tag_command)) { + $found = true; + + include_once $plugin_file; + + $plugin_func = 'smarty_block_' . $tag_command; + if (!function_exists($plugin_func)) { + $message = "plugin function $plugin_func() not found in $plugin_file\n"; + $have_function = false; + } else { + $this->_plugins['block'][$tag_command] = array($plugin_func, null, null, null, true); + + } + } + + if (!$found) { + return false; + } else if (!$have_function) { + $this->_syntax_error($message, E_USER_WARNING, __FILE__, __LINE__); + return true; + } + + /* + * Even though we've located the plugin function, compilation + * happens only once, so the plugin will still need to be loaded + * at runtime for future requests. + */ + $this->_add_plugin('block', $tag_command); + + if ($start_tag) { + $output = '_push_cacheable_state('block', $tag_command); + $attrs = $this->_parse_attrs($tag_args); + $arg_list = $this->_compile_arg_list('block', $tag_command, $attrs, $_cache_attrs=''); + $output .= "$_cache_attrs\$_params = \$this->_tag_stack[] = array('$tag_command', array(".implode(',', $arg_list).')); '; + $output .= $this->_compile_plugin_call('block', $tag_command).'($_params[1], null, $this, $_block_repeat=true); unset($_params);'; + $output .= 'while ($_block_repeat) { ob_start(); ?>'; + } else { + $output = '_block_content = ob_get_contents(); ob_end_clean(); '; + $_out_tag_text = $this->_compile_plugin_call('block', $tag_command).'($this->_tag_stack[count($this->_tag_stack)-1][1], $this->_block_content, $this, $_block_repeat=false)'; + if ($tag_modifier != '') { + $this->_parse_modifiers($_out_tag_text, $tag_modifier); + } + $output .= 'echo '.$_out_tag_text.'; } '; + $output .= " array_pop(\$this->_tag_stack); " . $this->_pop_cacheable_state('block', $tag_command) . '?>'; + } + + return true; + } + + + /** + * compile custom function tag + * + * @param string $tag_command + * @param string $tag_args + * @param string $tag_modifier + * @return string + */ + function _compile_custom_tag($tag_command, $tag_args, $tag_modifier) + { + $this->_add_plugin('function', $tag_command); + + $_cacheable_state = $this->_push_cacheable_state('function', $tag_command); + $attrs = $this->_parse_attrs($tag_args); + $arg_list = $this->_compile_arg_list('function', $tag_command, $attrs, $_cache_attrs=''); + + $_return = $this->_compile_plugin_call('function', $tag_command).'(array('.implode(',', $arg_list)."), \$this)"; + if($tag_modifier != '') { + $this->_parse_modifiers($_return, $tag_modifier); + } + + if($_return != '') { + $_return = '_pop_cacheable_state('function', $tag_command) . "?>" . $this->_additional_newline; + } + + return $_return; + } + + /** + * compile a registered object tag + * + * @param string $tag_command + * @param array $attrs + * @param string $tag_modifier + * @return string + */ + function _compile_registered_object_tag($tag_command, $attrs, $tag_modifier) + { + if ($tag_command{0} == '/') { + $start_tag = false; + $tag_command = substr($tag_command, 1); + } else { + $start_tag = true; + } + + list($object, $obj_comp) = explode('->', $tag_command); + + $arg_list = array(); + if(count($attrs)) { + $_assign_var = false; + foreach ($attrs as $arg_name => $arg_value) { + if($arg_name == 'assign') { + $_assign_var = $arg_value; + unset($attrs['assign']); + continue; + } + if (is_bool($arg_value)) + $arg_value = $arg_value ? 'true' : 'false'; + $arg_list[] = "'$arg_name' => $arg_value"; + } + } + + if($this->_reg_objects[$object][2]) { + // smarty object argument format + $args = "array(".implode(',', (array)$arg_list)."), \$this"; + } else { + // traditional argument format + $args = implode(',', array_values($attrs)); + if (empty($args)) { + $args = 'null'; + } + } + + $prefix = ''; + $postfix = ''; + $newline = ''; + if(!is_object($this->_reg_objects[$object][0])) { + $this->_trigger_fatal_error("registered '$object' is not an object"); + } elseif(!empty($this->_reg_objects[$object][1]) && !in_array($obj_comp, $this->_reg_objects[$object][1])) { + $this->_trigger_fatal_error("'$obj_comp' is not a registered component of object '$object'"); + } elseif(method_exists($this->_reg_objects[$object][0], $obj_comp)) { + // method + if(in_array($obj_comp, $this->_reg_objects[$object][3])) { + // block method + if ($start_tag) { + $prefix = "\$this->_tag_stack[] = array('$obj_comp', $args); "; + $prefix .= "\$this->_reg_objects['$object'][0]->$obj_comp(\$this->_tag_stack[count(\$this->_tag_stack)-1][1], null, \$this, \$_block_repeat=true); "; + $prefix .= "while (\$_block_repeat) { ob_start();"; + $return = null; + $postfix = ''; + } else { + $prefix = "\$this->_obj_block_content = ob_get_contents(); ob_end_clean(); "; + $return = "\$this->_reg_objects['$object'][0]->$obj_comp(\$this->_tag_stack[count(\$this->_tag_stack)-1][1], \$this->_obj_block_content, \$this, \$_block_repeat=false)"; + $postfix = "} array_pop(\$this->_tag_stack);"; + } + } else { + // non-block method + $return = "\$this->_reg_objects['$object'][0]->$obj_comp($args)"; + } + } else { + // property + $return = "\$this->_reg_objects['$object'][0]->$obj_comp"; + } + + if($return != null) { + if($tag_modifier != '') { + $this->_parse_modifiers($return, $tag_modifier); + } + + if(!empty($_assign_var)) { + $output = "\$this->assign('" . $this->_dequote($_assign_var) ."', $return);"; + } else { + $output = 'echo ' . $return . ';'; + $newline = $this->_additional_newline; + } + } else { + $output = ''; + } + + return '" . $newline; + } + + /** + * Compile {insert ...} tag + * + * @param string $tag_args + * @return string + */ + function _compile_insert_tag($tag_args) + { + $attrs = $this->_parse_attrs($tag_args); + $name = $this->_dequote($attrs['name']); + + if (empty($name)) { + $this->_syntax_error("missing insert name", E_USER_ERROR, __FILE__, __LINE__); + } + + if (!empty($attrs['script'])) { + $delayed_loading = true; + } else { + $delayed_loading = false; + } + + foreach ($attrs as $arg_name => $arg_value) { + if (is_bool($arg_value)) + $arg_value = $arg_value ? 'true' : 'false'; + $arg_list[] = "'$arg_name' => $arg_value"; + } + + $this->_add_plugin('insert', $name, $delayed_loading); + + $_params = "array('args' => array(".implode(', ', (array)$arg_list)."))"; + + return "" . $this->_additional_newline; + } + + /** + * Compile {include ...} tag + * + * @param string $tag_args + * @return string + */ + function _compile_include_tag($tag_args) + { + $attrs = $this->_parse_attrs($tag_args); + $arg_list = array(); + + if (empty($attrs['file'])) { + $this->_syntax_error("missing 'file' attribute in include tag", E_USER_ERROR, __FILE__, __LINE__); + } + + foreach ($attrs as $arg_name => $arg_value) { + if ($arg_name == 'file') { + $include_file = $arg_value; + continue; + } else if ($arg_name == 'assign') { + $assign_var = $arg_value; + continue; + } + if (is_bool($arg_value)) + $arg_value = $arg_value ? 'true' : 'false'; + $arg_list[] = "'$arg_name' => $arg_value"; + } + + $output = '_tpl_vars;\n"; + + + $_params = "array('smarty_include_tpl_file' => " . $include_file . ", 'smarty_include_vars' => array(".implode(',', (array)$arg_list)."))"; + $output .= "\$this->_smarty_include($_params);\n" . + "\$this->_tpl_vars = \$_smarty_tpl_vars;\n" . + "unset(\$_smarty_tpl_vars);\n"; + + if (isset($assign_var)) { + $output .= "\$this->assign(" . $assign_var . ", ob_get_contents()); ob_end_clean();\n"; + } + + $output .= ' ?>'; + + return $output; + + } + + /** + * Compile {include ...} tag + * + * @param string $tag_args + * @return string + */ + function _compile_include_php_tag($tag_args) + { + $attrs = $this->_parse_attrs($tag_args); + + if (empty($attrs['file'])) { + $this->_syntax_error("missing 'file' attribute in include_php tag", E_USER_ERROR, __FILE__, __LINE__); + } + + $assign_var = (empty($attrs['assign'])) ? '' : $this->_dequote($attrs['assign']); + $once_var = (empty($attrs['once']) || $attrs['once']=='false') ? 'false' : 'true'; + + foreach($attrs as $arg_name => $arg_value) { + if($arg_name != 'file' AND $arg_name != 'once' AND $arg_name != 'assign') { + if(is_bool($arg_value)) + $arg_value = $arg_value ? 'true' : 'false'; + $arg_list[] = "'$arg_name' => $arg_value"; + } + } + + $_params = "array('smarty_file' => " . $attrs['file'] . ", 'smarty_assign' => '$assign_var', 'smarty_once' => $once_var, 'smarty_include_vars' => array(".implode(',', (array)$arg_list)."))"; + + return "" . $this->_additional_newline; + } + + + /** + * Compile {section ...} tag + * + * @param string $tag_args + * @return string + */ + function _compile_section_start($tag_args) + { + $attrs = $this->_parse_attrs($tag_args); + $arg_list = array(); + + $output = '_syntax_error("missing section name", E_USER_ERROR, __FILE__, __LINE__); + } + + $output .= "if (isset(\$this->_sections[$section_name])) unset(\$this->_sections[$section_name]);\n"; + $section_props = "\$this->_sections[$section_name]"; + + foreach ($attrs as $attr_name => $attr_value) { + switch ($attr_name) { + case 'loop': + $output .= "{$section_props}['loop'] = is_array(\$_loop=$attr_value) ? count(\$_loop) : max(0, (int)\$_loop); unset(\$_loop);\n"; + break; + + case 'show': + if (is_bool($attr_value)) + $show_attr_value = $attr_value ? 'true' : 'false'; + else + $show_attr_value = "(bool)$attr_value"; + $output .= "{$section_props}['show'] = $show_attr_value;\n"; + break; + + case 'name': + $output .= "{$section_props}['$attr_name'] = $attr_value;\n"; + break; + + case 'max': + case 'start': + $output .= "{$section_props}['$attr_name'] = (int)$attr_value;\n"; + break; + + case 'step': + $output .= "{$section_props}['$attr_name'] = ((int)$attr_value) == 0 ? 1 : (int)$attr_value;\n"; + break; + + default: + $this->_syntax_error("unknown section attribute - '$attr_name'", E_USER_ERROR, __FILE__, __LINE__); + break; + } + } + + if (!isset($attrs['show'])) + $output .= "{$section_props}['show'] = true;\n"; + + if (!isset($attrs['loop'])) + $output .= "{$section_props}['loop'] = 1;\n"; + + if (!isset($attrs['max'])) + $output .= "{$section_props}['max'] = {$section_props}['loop'];\n"; + else + $output .= "if ({$section_props}['max'] < 0)\n" . + " {$section_props}['max'] = {$section_props}['loop'];\n"; + + if (!isset($attrs['step'])) + $output .= "{$section_props}['step'] = 1;\n"; + + if (!isset($attrs['start'])) + $output .= "{$section_props}['start'] = {$section_props}['step'] > 0 ? 0 : {$section_props}['loop']-1;\n"; + else { + $output .= "if ({$section_props}['start'] < 0)\n" . + " {$section_props}['start'] = max({$section_props}['step'] > 0 ? 0 : -1, {$section_props}['loop'] + {$section_props}['start']);\n" . + "else\n" . + " {$section_props}['start'] = min({$section_props}['start'], {$section_props}['step'] > 0 ? {$section_props}['loop'] : {$section_props}['loop']-1);\n"; + } + + $output .= "if ({$section_props}['show']) {\n"; + if (!isset($attrs['start']) && !isset($attrs['step']) && !isset($attrs['max'])) { + $output .= " {$section_props}['total'] = {$section_props}['loop'];\n"; + } else { + $output .= " {$section_props}['total'] = min(ceil(({$section_props}['step'] > 0 ? {$section_props}['loop'] - {$section_props}['start'] : {$section_props}['start']+1)/abs({$section_props}['step'])), {$section_props}['max']);\n"; + } + $output .= " if ({$section_props}['total'] == 0)\n" . + " {$section_props}['show'] = false;\n" . + "} else\n" . + " {$section_props}['total'] = 0;\n"; + + $output .= "if ({$section_props}['show']):\n"; + $output .= " + for ({$section_props}['index'] = {$section_props}['start'], {$section_props}['iteration'] = 1; + {$section_props}['iteration'] <= {$section_props}['total']; + {$section_props}['index'] += {$section_props}['step'], {$section_props}['iteration']++):\n"; + $output .= "{$section_props}['rownum'] = {$section_props}['iteration'];\n"; + $output .= "{$section_props}['index_prev'] = {$section_props}['index'] - {$section_props}['step'];\n"; + $output .= "{$section_props}['index_next'] = {$section_props}['index'] + {$section_props}['step'];\n"; + $output .= "{$section_props}['first'] = ({$section_props}['iteration'] == 1);\n"; + $output .= "{$section_props}['last'] = ({$section_props}['iteration'] == {$section_props}['total']);\n"; + + $output .= "?>"; + + return $output; + } + + + /** + * Compile {foreach ...} tag. + * + * @param string $tag_args + * @return string + */ + function _compile_foreach_start($tag_args) + { + $attrs = $this->_parse_attrs($tag_args); + $arg_list = array(); + + if (empty($attrs['from'])) { + $this->_syntax_error("missing 'from' attribute", E_USER_ERROR, __FILE__, __LINE__); + } + + if (empty($attrs['item'])) { + $this->_syntax_error("missing 'item' attribute", E_USER_ERROR, __FILE__, __LINE__); + } + + $from = $attrs['from']; + $item = $this->_dequote($attrs['item']); + if (isset($attrs['name'])) + $name = $attrs['name']; + + $output = '_foreach[$name])) unset(\$this->_foreach[$name]);\n"; + $foreach_props = "\$this->_foreach[$name]"; + } + + $key_part = ''; + + foreach ($attrs as $attr_name => $attr_value) { + switch ($attr_name) { + case 'key': + $key = $this->_dequote($attrs['key']); + $key_part = "\$this->_tpl_vars['$key'] => "; + break; + + case 'name': + $output .= "{$foreach_props}['$attr_name'] = $attr_value;\n"; + break; + } + } + + if (isset($name)) { + $output .= "{$foreach_props}['total'] = count(\$_from = (array)$from);\n"; + $output .= "{$foreach_props}['show'] = {$foreach_props}['total'] > 0;\n"; + $output .= "if ({$foreach_props}['show']):\n"; + $output .= "{$foreach_props}['iteration'] = 0;\n"; + $output .= " foreach (\$_from as $key_part\$this->_tpl_vars['$item']):\n"; + $output .= " {$foreach_props}['iteration']++;\n"; + $output .= " {$foreach_props}['first'] = ({$foreach_props}['iteration'] == 1);\n"; + $output .= " {$foreach_props}['last'] = ({$foreach_props}['iteration'] == {$foreach_props}['total']);\n"; + } else { + $output .= "if (count(\$_from = (array)$from)):\n"; + $output .= " foreach (\$_from as $key_part\$this->_tpl_vars['$item']):\n"; + } + $output .= '?>'; + + return $output; + } + + + /** + * Compile {capture} .. {/capture} tags + * + * @param boolean $start true if this is the {capture} tag + * @param string $tag_args + * @return string + */ + + function _compile_capture_tag($start, $tag_args = '') + { + $attrs = $this->_parse_attrs($tag_args); + + if ($start) { + if (isset($attrs['name'])) + $buffer = $attrs['name']; + else + $buffer = "'default'"; + + if (isset($attrs['assign'])) + $assign = $attrs['assign']; + else + $assign = null; + $output = ""; + $this->_capture_stack[] = array($buffer, $assign); + } else { + list($buffer, $assign) = array_pop($this->_capture_stack); + $output = "_smarty_vars['capture'][$buffer] = ob_get_contents(); "; + if (isset($assign)) { + $output .= " \$this->assign($assign, ob_get_contents());"; + } + $output .= "ob_end_clean(); ?>"; + } + + return $output; + } + + /** + * Compile {if ...} tag + * + * @param string $tag_args + * @param boolean $elseif if true, uses elseif instead of if + * @return string + */ + function _compile_if_tag($tag_args, $elseif = false) + { + + /* Tokenize args for 'if' tag. */ + preg_match_all('/(?> + ' . $this->_obj_call_regexp . '(?:' . $this->_mod_regexp . '*)? | # valid object call + ' . $this->_var_regexp . '(?:' . $this->_mod_regexp . '*)? | # var or quoted string + \-?0[xX][0-9a-fA-F]+|\-?\d+(?:\.\d+)?|\.\d+|!==|===|==|!=|<>|<<|>>|<=|>=|\&\&|\|\||\(|\)|,|\!|\^|=|\&|\~|<|>|\||\%|\+|\-|\/|\*|\@ | # valid non-word token + \b\w+\b | # valid word token + \S+ # anything else + )/x', $tag_args, $match); + + $tokens = $match[0]; + + // make sure we have balanced parenthesis + $token_count = array_count_values($tokens); + if(isset($token_count['(']) && $token_count['('] != $token_count[')']) { + $this->_syntax_error("unbalanced parenthesis in if statement", E_USER_ERROR, __FILE__, __LINE__); + } + + $is_arg_stack = array(); + + for ($i = 0; $i < count($tokens); $i++) { + + $token = &$tokens[$i]; + + switch (strtolower($token)) { + case '!': + case '%': + case '!==': + case '==': + case '===': + case '>': + case '<': + case '!=': + case '<>': + case '<<': + case '>>': + case '<=': + case '>=': + case '&&': + case '||': + case '|': + case '^': + case '&': + case '~': + case ')': + case ',': + case '+': + case '-': + case '*': + case '/': + case '@': + break; + + case 'eq': + $token = '=='; + break; + + case 'ne': + case 'neq': + $token = '!='; + break; + + case 'lt': + $token = '<'; + break; + + case 'le': + case 'lte': + $token = '<='; + break; + + case 'gt': + $token = '>'; + break; + + case 'ge': + case 'gte': + $token = '>='; + break; + + case 'and': + $token = '&&'; + break; + + case 'or': + $token = '||'; + break; + + case 'not': + $token = '!'; + break; + + case 'mod': + $token = '%'; + break; + + case '(': + array_push($is_arg_stack, $i); + break; + + case 'is': + /* If last token was a ')', we operate on the parenthesized + expression. The start of the expression is on the stack. + Otherwise, we operate on the last encountered token. */ + if ($tokens[$i-1] == ')') + $is_arg_start = array_pop($is_arg_stack); + else + $is_arg_start = $i-1; + /* Construct the argument for 'is' expression, so it knows + what to operate on. */ + $is_arg = implode(' ', array_slice($tokens, $is_arg_start, $i - $is_arg_start)); + + /* Pass all tokens from next one until the end to the + 'is' expression parsing function. The function will + return modified tokens, where the first one is the result + of the 'is' expression and the rest are the tokens it + didn't touch. */ + $new_tokens = $this->_parse_is_expr($is_arg, array_slice($tokens, $i+1)); + + /* Replace the old tokens with the new ones. */ + array_splice($tokens, $is_arg_start, count($tokens), $new_tokens); + + /* Adjust argument start so that it won't change from the + current position for the next iteration. */ + $i = $is_arg_start; + break; + + default: + if(preg_match('!^' . $this->_func_regexp . '$!', $token) ) { + // function call + if($this->security && + !in_array($token, $this->security_settings['IF_FUNCS'])) { + $this->_syntax_error("(secure mode) '$token' not allowed in if statement", E_USER_ERROR, __FILE__, __LINE__); + } + } elseif(preg_match('!^' . $this->_obj_call_regexp . '|' . $this->_var_regexp . '(?:' . $this->_mod_regexp . '*)$!', $token)) { + // object or variable + $token = $this->_parse_var_props($token); + } elseif(is_numeric($token)) { + // number, skip it + } else { + $this->_syntax_error("unidentified token '$token'", E_USER_ERROR, __FILE__, __LINE__); + } + break; + } + } + + if ($elseif) + return ''; + else + return ''; + } + + + function _compile_arg_list($type, $name, $attrs, &$cache_code) { + $arg_list = array(); + + if (isset($type) && isset($name) + && isset($this->_plugins[$type]) + && isset($this->_plugins[$type][$name]) + && empty($this->_plugins[$type][$name][4]) + && is_array($this->_plugins[$type][$name][5]) + ) { + /* we have a list of parameters that should be cached */ + $_cache_attrs = $this->_plugins[$type][$name][5]; + $_count = $this->_cache_attrs_count++; + $cache_code = "\$_cache_attrs =& \$this->_smarty_cache_attrs('$this->_cache_serial','$_count');"; + + } else { + /* no parameters are cached */ + $_cache_attrs = null; + } + + foreach ($attrs as $arg_name => $arg_value) { + if (is_bool($arg_value)) + $arg_value = $arg_value ? 'true' : 'false'; + if (is_null($arg_value)) + $arg_value = 'null'; + if ($_cache_attrs && in_array($arg_name, $_cache_attrs)) { + $arg_list[] = "'$arg_name' => (\$this->_cache_including) ? \$_cache_attrs['$arg_name'] : (\$_cache_attrs['$arg_name']=$arg_value)"; + } else { + $arg_list[] = "'$arg_name' => $arg_value"; + } + } + return $arg_list; + } + + /** + * Parse is expression + * + * @param string $is_arg + * @param array $tokens + * @return array + */ + function _parse_is_expr($is_arg, $tokens) + { + $expr_end = 0; + $negate_expr = false; + + if (($first_token = array_shift($tokens)) == 'not') { + $negate_expr = true; + $expr_type = array_shift($tokens); + } else + $expr_type = $first_token; + + switch ($expr_type) { + case 'even': + if (@$tokens[$expr_end] == 'by') { + $expr_end++; + $expr_arg = $tokens[$expr_end++]; + $expr = "!(($is_arg / $expr_arg) % " . $this->_parse_var_props($expr_arg) . ")"; + } else + $expr = "!($is_arg % 2)"; + break; + + case 'odd': + if (@$tokens[$expr_end] == 'by') { + $expr_end++; + $expr_arg = $tokens[$expr_end++]; + $expr = "(($is_arg / $expr_arg) % ". $this->_parse_var_props($expr_arg) . ")"; + } else + $expr = "($is_arg % 2)"; + break; + + case 'div': + if (@$tokens[$expr_end] == 'by') { + $expr_end++; + $expr_arg = $tokens[$expr_end++]; + $expr = "!($is_arg % " . $this->_parse_var_props($expr_arg) . ")"; + } else { + $this->_syntax_error("expecting 'by' after 'div'", E_USER_ERROR, __FILE__, __LINE__); + } + break; + + default: + $this->_syntax_error("unknown 'is' expression - '$expr_type'", E_USER_ERROR, __FILE__, __LINE__); + break; + } + + if ($negate_expr) { + $expr = "!($expr)"; + } + + array_splice($tokens, 0, $expr_end, $expr); + + return $tokens; + } + + + /** + * Parse attribute string + * + * @param string $tag_args + * @return array + */ + function _parse_attrs($tag_args) + { + + /* Tokenize tag attributes. */ + preg_match_all('/(?:' . $this->_obj_call_regexp . '|' . $this->_qstr_regexp . ' | (?>[^"\'=\s]+) + )+ | + [=] + /x', $tag_args, $match); + $tokens = $match[0]; + + $attrs = array(); + /* Parse state: + 0 - expecting attribute name + 1 - expecting '=' + 2 - expecting attribute value (not '=') */ + $state = 0; + + foreach ($tokens as $token) { + switch ($state) { + case 0: + /* If the token is a valid identifier, we set attribute name + and go to state 1. */ + if (preg_match('!^\w+$!', $token)) { + $attr_name = $token; + $state = 1; + } else + $this->_syntax_error("invalid attribute name: '$token'", E_USER_ERROR, __FILE__, __LINE__); + break; + + case 1: + /* If the token is '=', then we go to state 2. */ + if ($token == '=') { + $state = 2; + } else + $this->_syntax_error("expecting '=' after attribute name '$last_token'", E_USER_ERROR, __FILE__, __LINE__); + break; + + case 2: + /* If token is not '=', we set the attribute value and go to + state 0. */ + if ($token != '=') { + /* We booleanize the token if it's a non-quoted possible + boolean value. */ + if (preg_match('!^(on|yes|true)$!', $token)) { + $token = 'true'; + } else if (preg_match('!^(off|no|false)$!', $token)) { + $token = 'false'; + } else if ($token == 'null') { + $token = 'null'; + } else if (preg_match('!^-?([0-9]+|0[xX][0-9a-fA-F]+)$!', $token)) { + /* treat integer literally */ + } else if (!preg_match('!^' . $this->_obj_call_regexp . '|' . $this->_var_regexp . '(?:' . $this->_mod_regexp . ')*$!', $token)) { + /* treat as a string, double-quote it escaping quotes */ + $token = '"'.addslashes($token).'"'; + } + + $attrs[$attr_name] = $token; + $state = 0; + } else + $this->_syntax_error("'=' cannot be an attribute value", E_USER_ERROR, __FILE__, __LINE__); + break; + } + $last_token = $token; + } + + if($state != 0) { + if($state == 1) { + $this->_syntax_error("expecting '=' after attribute name '$last_token'", E_USER_ERROR, __FILE__, __LINE__); + } else { + $this->_syntax_error("missing attribute value", E_USER_ERROR, __FILE__, __LINE__); + } + } + + $this->_parse_vars_props($attrs); + + return $attrs; + } + + /** + * compile multiple variables and section properties tokens into + * PHP code + * + * @param array $tokens + */ + function _parse_vars_props(&$tokens) + { + foreach($tokens as $key => $val) { + $tokens[$key] = $this->_parse_var_props($val); + } + } + + /** + * compile single variable and section properties token into + * PHP code + * + * @param string $val + * @param string $tag_attrs + * @return string + */ + function _parse_var_props($val) + { + $val = trim($val); + + if(preg_match('!^(' . $this->_obj_call_regexp . '|' . $this->_dvar_regexp . ')(' . $this->_mod_regexp . '*)$!', $val, $match)) { + // $ variable or object + $return = $this->_parse_var($match[1]); + if($match[2] != '') { + $this->_parse_modifiers($return, $match[2]); + } + return $return; + } + elseif(preg_match('!^' . $this->_db_qstr_regexp . '(?:' . $this->_mod_regexp . '*)$!', $val)) { + // double quoted text + preg_match('!^(' . $this->_db_qstr_regexp . ')('. $this->_mod_regexp . '*)$!', $val, $match); + $return = $this->_expand_quoted_text($match[1]); + if($match[2] != '') { + $this->_parse_modifiers($return, $match[2]); + } + return $return; + } + elseif(preg_match('!^' . $this->_si_qstr_regexp . '(?:' . $this->_mod_regexp . '*)$!', $val)) { + // single quoted text + preg_match('!^(' . $this->_si_qstr_regexp . ')('. $this->_mod_regexp . '*)$!', $val, $match); + if($match[2] != '') { + $this->_parse_modifiers($match[1], $match[2]); + return $match[1]; + } + } + elseif(preg_match('!^' . $this->_cvar_regexp . '(?:' . $this->_mod_regexp . '*)$!', $val)) { + // config var + return $this->_parse_conf_var($val); + } + elseif(preg_match('!^' . $this->_svar_regexp . '(?:' . $this->_mod_regexp . '*)$!', $val)) { + // section var + return $this->_parse_section_prop($val); + } + elseif(!in_array($val, $this->_permitted_tokens) && !is_numeric($val)) { + // literal string + return $this->_expand_quoted_text('"' . $val .'"'); + } + return $val; + } + + /** + * expand quoted text with embedded variables + * + * @param string $var_expr + * @return string + */ + function _expand_quoted_text($var_expr) + { + // if contains unescaped $, expand it + if(preg_match_all('%(?:\`(?_dvar_guts_regexp . '\`)|(?:(?_parse_var(str_replace('`','',$_var)) . ')."', $var_expr); + } + $_return = preg_replace('%\.""|(?_dvar_math_regexp.'|'.$this->_qstr_regexp.')!', $var_expr, -1, PREG_SPLIT_DELIM_CAPTURE); + + if(count($_math_vars) > 1) { + $_first_var = ""; + $_complete_var = ""; + // simple check if there is any math, to stop recursion (due to modifiers with "xx % yy" as parameter) + foreach($_math_vars as $_k => $_math_var) { + $_math_var = $_math_vars[$_k]; + + if(!empty($_math_var) || is_numeric($_math_var)) { + // hit a math operator, so process the stuff which came before it + if(preg_match('!^' . $this->_dvar_math_regexp . '$!', $_math_var)) { + $_has_math = true; + if(!empty($_complete_var) || is_numeric($_complete_var)) { + $_output .= $this->_parse_var($_complete_var); + } + + // just output the math operator to php + $_output .= $_math_var; + + if(empty($_first_var)) + $_first_var = $_complete_var; + + $_complete_var = ""; + } else { + // fetch multiple -> (like $foo->bar->baz ) which wouldn't get fetched else, because it would only get $foo->bar and treat the ->baz as "-" ">baz" then + for($_i = $_k + 1; $_i <= count($_math_vars); $_i += 2) { + // fetch -> because it gets splitted at - and move it back together + if( /* prevent notice */ (isset($_math_vars[$_i]) && isset($_math_vars[$_i+1])) && ($_math_vars[$_i] === '-' && $_math_vars[$_i+1]{0} === '>')) { + $_math_var .= $_math_vars[$_i].$_math_vars[$_i+1]; + $_math_vars[$_i] = $_math_vars[$_i+1] = ''; + } else { + break; + } + } + $_complete_var .= $_math_var; + } + } + } + if($_has_math) { + if(!empty($_complete_var) || is_numeric($_complete_var)) + $_output .= $this->_parse_var($_complete_var, true); + + // get the modifiers working (only the last var from math + modifier is left) + $var_expr = $_complete_var; + } + } + + // prevent cutting of first digit in the number (we _definitly_ got a number if the first char is a digit) + if(is_numeric($var_expr{0})) + $_var_ref = $var_expr; + else + $_var_ref = substr($var_expr, 1); + + if(!$_has_math) { + // get [foo] and .foo and ->foo and (...) pieces + preg_match_all('!(?:^\w+)|' . $this->_obj_params_regexp . '|(?:' . $this->_var_bracket_regexp . ')|->\$?\w+|\.\$?\w+|\S+!', $_var_ref, $match); + + $_indexes = $match[0]; + $_var_name = array_shift($_indexes); + + /* Handle $smarty.* variable references as a special case. */ + if ($_var_name == 'smarty') { + /* + * If the reference could be compiled, use the compiled output; + * otherwise, fall back on the $smarty variable generated at + * run-time. + */ + if (($smarty_ref = $this->_compile_smarty_ref($_indexes)) !== null) { + $_output = $smarty_ref; + } else { + $_var_name = substr(array_shift($_indexes), 1); + $_output = "\$this->_smarty_vars['$_var_name']"; + } + } elseif(is_numeric($_var_name) && is_numeric($var_expr{0})) { + // because . is the operator for accessing arrays thru inidizes we need to put it together again for floating point numbers + if(count($_indexes) > 0) + { + $_var_name .= implode("", $_indexes); + $_indexes = array(); + } + $_output = $_var_name; + } else { + $_output = "\$this->_tpl_vars['$_var_name']"; + } + + foreach ($_indexes as $_index) { + if ($_index{0} == '[') { + $_index = substr($_index, 1, -1); + if (is_numeric($_index)) { + $_output .= "[$_index]"; + } elseif ($_index{0} == '$') { + if (strpos($_index, '.') !== false) { + $_output .= '[' . $this->_parse_var($_index) . ']'; + } else { + $_output .= "[\$this->_tpl_vars['" . substr($_index, 1) . "']]"; + } + } else { + $_var_parts = explode('.', $_index); + $_var_section = $_var_parts[0]; + $_var_section_prop = isset($_var_parts[1]) ? $_var_parts[1] : 'index'; + $_output .= "[\$this->_sections['$_var_section']['$_var_section_prop']]"; + } + } else if ($_index{0} == '.') { + if ($_index{1} == '$') + $_output .= "[\$this->_tpl_vars['" . substr($_index, 2) . "']]"; + else + $_output .= "['" . substr($_index, 1) . "']"; + } else if (substr($_index,0,2) == '->') { + if(substr($_index,2,2) == '__') { + $this->_syntax_error('call to internal object members is not allowed', E_USER_ERROR, __FILE__, __LINE__); + } elseif($this->security && substr($_index, 2, 1) == '_') { + $this->_syntax_error('(secure) call to private object member is not allowed', E_USER_ERROR, __FILE__, __LINE__); + } elseif ($_index{2} == '$') { + if ($this->security) { + $this->_syntax_error('(secure) call to dynamic object member is not allowed', E_USER_ERROR, __FILE__, __LINE__); + } else { + $_output .= '->{(($_var=$this->_tpl_vars[\''.substr($_index,3).'\']) && substr($_var,0,2)!=\'__\') ? $_var : $this->trigger_error("cannot access property \\"$_var\\"")}'; + } + } else { + $_output .= $_index; + } + } elseif ($_index{0} == '(') { + $_index = $this->_parse_parenth_args($_index); + $_output .= $_index; + } else { + $_output .= $_index; + } + } + } + + return $_output; + } + + /** + * parse arguments in function call parenthesis + * + * @param string $parenth_args + * @return string + */ + function _parse_parenth_args($parenth_args) + { + preg_match_all('!' . $this->_param_regexp . '!',$parenth_args, $match); + $match = $match[0]; + rsort($match); + reset($match); + $orig_vals = $match; + $this->_parse_vars_props($match); + return str_replace($orig_vals, $match, $parenth_args); + } + + /** + * parse configuration variable expression into PHP code + * + * @param string $conf_var_expr + */ + function _parse_conf_var($conf_var_expr) + { + $parts = explode('|', $conf_var_expr, 2); + $var_ref = $parts[0]; + $modifiers = isset($parts[1]) ? $parts[1] : ''; + + $var_name = substr($var_ref, 1, -1); + + $output = "\$this->_config[0]['vars']['$var_name']"; + + $this->_parse_modifiers($output, $modifiers); + + return $output; + } + + /** + * parse section property expression into PHP code + * + * @param string $section_prop_expr + * @return string + */ + function _parse_section_prop($section_prop_expr) + { + $parts = explode('|', $section_prop_expr, 2); + $var_ref = $parts[0]; + $modifiers = isset($parts[1]) ? $parts[1] : ''; + + preg_match('!%(\w+)\.(\w+)%!', $var_ref, $match); + $section_name = $match[1]; + $prop_name = $match[2]; + + $output = "\$this->_sections['$section_name']['$prop_name']"; + + $this->_parse_modifiers($output, $modifiers); + + return $output; + } + + + /** + * parse modifier chain into PHP code + * + * sets $output to parsed modified chain + * @param string $output + * @param string $modifier_string + */ + function _parse_modifiers(&$output, $modifier_string) + { + preg_match_all('!\|(@?\w+)((?>:(?:'. $this->_qstr_regexp . '|[^|]+))*)!', '|' . $modifier_string, $_match); + list(, $_modifiers, $modifier_arg_strings) = $_match; + + for ($_i = 0, $_for_max = count($_modifiers); $_i < $_for_max; $_i++) { + $_modifier_name = $_modifiers[$_i]; + + if($_modifier_name == 'smarty') { + // skip smarty modifier + continue; + } + + preg_match_all('!:(' . $this->_qstr_regexp . '|[^:]+)!', $modifier_arg_strings[$_i], $_match); + $_modifier_args = $_match[1]; + + if ($_modifier_name{0} == '@') { + $_map_array = false; + $_modifier_name = substr($_modifier_name, 1); + } else { + $_map_array = true; + } + + $this->_add_plugin('modifier', $_modifier_name); + if (empty($this->_plugins['modifier'][$_modifier_name]) + && !$this->_get_plugin_filepath('modifier', $_modifier_name) + && function_exists($_modifier_name)) { + if ($this->security && !in_array($_modifier_name, $this->security_settings['MODIFIER_FUNCS'])) { + $this->_trigger_fatal_error("[plugin] (secure mode) modifier '$_modifier_name' is not allowed" , $_tpl_file, $_tpl_line, __FILE__, __LINE__); + } else { + $this->_plugins['modifier'][$_modifier_name] = array($_modifier_name, null, null, false); + } + } + + $this->_parse_vars_props($_modifier_args); + + if($_modifier_name == 'default') { + // supress notifications of default modifier vars and args + if($output{0} == '$') { + $output = '@' . $output; + } + if(isset($_modifier_args[0]) && $_modifier_args[0]{0} == '$') { + $_modifier_args[0] = '@' . $_modifier_args[0]; + } + } + if (count($_modifier_args) > 0) + $_modifier_args = ', '.implode(', ', $_modifier_args); + else + $_modifier_args = ''; + + if ($_map_array) { + $output = "((is_array(\$_tmp=$output)) ? \$this->_run_mod_handler('$_modifier_name', true, \$_tmp$_modifier_args) : " . $this->_compile_plugin_call('modifier', $_modifier_name) . "(\$_tmp$_modifier_args))"; + + } else { + + $output = $this->_compile_plugin_call('modifier', $_modifier_name)."($output$_modifier_args)"; + + } + } + } + + + /** + * add plugin + * + * @param string $type + * @param string $name + * @param boolean? $delayed_loading + */ + function _add_plugin($type, $name, $delayed_loading = null) + { + if (!isset($this->_plugin_info[$type])) { + $this->_plugin_info[$type] = array(); + } + if (!isset($this->_plugin_info[$type][$name])) { + $this->_plugin_info[$type][$name] = array($this->_current_file, + $this->_current_line_no, + $delayed_loading); + } + } + + + /** + * Compiles references of type $smarty.foo + * + * @param string $indexes + * @return string + */ + function _compile_smarty_ref(&$indexes) + { + /* Extract the reference name. */ + $_ref = substr($indexes[0], 1); + foreach($indexes as $_index_no=>$_index) { + if ($_index{0} != '.' && $_index_no<2 || !preg_match('!^(\.|\[|->)!', $_index)) { + $this->_syntax_error('$smarty' . implode('', array_slice($indexes, 0, 2)) . ' is an invalid reference', E_USER_ERROR, __FILE__, __LINE__); + } + } + + switch ($_ref) { + case 'now': + $compiled_ref = 'time()'; + $_max_index = 1; + break; + + case 'foreach': + case 'section': + array_shift($indexes); + $_var = $this->_parse_var_props(substr($indexes[0], 1)); + if ($_ref == 'foreach') + $compiled_ref = "\$this->_foreach[$_var]"; + else + $compiled_ref = "\$this->_sections[$_var]"; + break; + + case 'get': + $compiled_ref = ($this->request_use_auto_globals) ? '$_GET' : "\$GLOBALS['HTTP_GET_VARS']"; + break; + + case 'post': + $compiled_ref = ($this->request_use_auto_globals) ? '$_POST' : "\$GLOBALS['HTTP_POST_VARS']"; + break; + + case 'cookies': + $compiled_ref = ($this->request_use_auto_globals) ? '$_COOKIE' : "\$GLOBALS['HTTP_COOKIE_VARS']"; + break; + + case 'env': + $compiled_ref = ($this->request_use_auto_globals) ? '$_ENV' : "\$GLOBALS['HTTP_ENV_VARS']"; + break; + + case 'server': + $compiled_ref = ($this->request_use_auto_globals) ? '$_SERVER' : "\$GLOBALS['HTTP_SERVER_VARS']"; + break; + + case 'session': + $compiled_ref = ($this->request_use_auto_globals) ? '$_SESSION' : "\$GLOBALS['HTTP_SESSION_VARS']"; + break; + + /* + * These cases are handled either at run-time or elsewhere in the + * compiler. + */ + case 'request': + if ($this->request_use_auto_globals) { + $compiled_ref = '$_REQUEST'; + break; + } else { + $this->_init_smarty_vars = true; + } + return null; + + case 'capture': + return null; + + case 'template': + $compiled_ref = "'$this->_current_file'"; + $_max_index = 1; + break; + + case 'version': + $compiled_ref = "'$this->_version'"; + $_max_index = 1; + break; + + case 'const': + array_shift($indexes); + $_val = $this->_parse_var_props(substr($indexes[0],1)); + $compiled_ref = '@constant(' . $_val . ')'; + $_max_index = 1; + break; + + case 'config': + $compiled_ref = "\$this->_config[0]['vars']"; + $_max_index = 2; + break; + + default: + $this->_syntax_error('$smarty.' . $_ref . ' is an unknown reference', E_USER_ERROR, __FILE__, __LINE__); + break; + } + + if (isset($_max_index) && count($indexes) > $_max_index) { + $this->_syntax_error('$smarty' . implode('', $indexes) .' is an invalid reference', E_USER_ERROR, __FILE__, __LINE__); + } + + array_shift($indexes); + return $compiled_ref; + } + + /** + * compiles call to plugin of type $type with name $name + * returns a string containing the function-name or method call + * without the paramter-list that would have follow to make the + * call valid php-syntax + * + * @param string $type + * @param string $name + * @return string + */ + function _compile_plugin_call($type, $name) { + if (isset($this->_plugins[$type][$name])) { + /* plugin loaded */ + if (is_array($this->_plugins[$type][$name][0])) { + return ((is_object($this->_plugins[$type][$name][0][0])) ? + "\$this->_plugins['$type']['$name'][0][0]->" /* method callback */ + : (string)($this->_plugins[$type][$name][0][0]).'::' /* class callback */ + ). $this->_plugins[$type][$name][0][1]; + + } else { + /* function callback */ + return $this->_plugins[$type][$name][0]; + + } + } else { + /* plugin not loaded -> auto-loadable-plugin */ + return 'smarty_'.$type.'_'.$name; + + } + } + + /** + * load pre- and post-filters + */ + function _load_filters() + { + if (count($this->_plugins['prefilter']) > 0) { + foreach ($this->_plugins['prefilter'] as $filter_name => $prefilter) { + if ($prefilter === false) { + unset($this->_plugins['prefilter'][$filter_name]); + $_params = array('plugins' => array(array('prefilter', $filter_name, null, null, false))); + require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.load_plugins.php'); + smarty_core_load_plugins($_params, $this); + } + } + } + if (count($this->_plugins['postfilter']) > 0) { + foreach ($this->_plugins['postfilter'] as $filter_name => $postfilter) { + if ($postfilter === false) { + unset($this->_plugins['postfilter'][$filter_name]); + $_params = array('plugins' => array(array('postfilter', $filter_name, null, null, false))); + require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.load_plugins.php'); + smarty_core_load_plugins($_params, $this); + } + } + } + } + + + /** + * Quote subpattern references + * + * @param string $string + * @return string + */ + function _quote_replace($string) + { + return preg_replace('![\\$]\d!', '\\\\\\0', $string); + } + + /** + * display Smarty syntax error + * + * @param string $error_msg + * @param integer $error_type + * @param string $file + * @param integer $line + */ + function _syntax_error($error_msg, $error_type = E_USER_ERROR, $file=null, $line=null) + { + if(isset($file) && isset($line)) { + $info = ' ('.basename($file).", line $line)"; + } else { + $info = null; + } + trigger_error('Smarty: [in ' . $this->_current_file . ' line ' . + $this->_current_line_no . "]: syntax error: $error_msg$info", $error_type); + } + + + /** + * check if the compilation changes from cacheable to + * non-cacheable state with the beginning of the current + * plugin. return php-code to reflect the transition. + * @return string + */ + function _push_cacheable_state($type, $name) { + $_cacheable = !isset($this->_plugins[$type][$name]) || $this->_plugins[$type][$name][4]; + if ($_cacheable + || 0<$this->_cacheable_state++) return ''; + if (!isset($this->_cache_serial)) $this->_cache_serial = md5(uniqid('Smarty')); + $_ret = 'if ($this->caching) { echo \'{nocache:' + . $this->_cache_serial . '#' . $this->_nocache_count + . '}\';}'; + return $_ret; + } + + + /** + * check if the compilation changes from non-cacheable to + * cacheable state with the end of the current plugin return + * php-code to reflect the transition. + * @return string + */ + function _pop_cacheable_state($type, $name) { + $_cacheable = !isset($this->_plugins[$type][$name]) || $this->_plugins[$type][$name][4]; + if ($_cacheable + || --$this->_cacheable_state>0) return ''; + return 'if ($this->caching) { echo \'{/nocache:' + . $this->_cache_serial . '#' . ($this->_nocache_count++) + . '}\';}'; + } + +} + +/** + * compare to values by their string length + * + * @access private + * @param string $a + * @param string $b + * @return 0|-1|1 + */ +function _smarty_sort_length($a, $b) +{ + if($a == $b) + return 0; + + if(strlen($a) == strlen($b)) + return ($a > $b) ? -1 : 1; + + return (strlen($a) > strlen($b)) ? -1 : 1; +} + + +/* vim: set et: */ + +?> diff --git a/src/functions/smarty/core/core.assemble_plugin_filepath.php b/src/functions/smarty/core/core.assemble_plugin_filepath.php new file mode 100644 index 0000000..ec44f8e --- /dev/null +++ b/src/functions/smarty/core/core.assemble_plugin_filepath.php @@ -0,0 +1,62 @@ +plugins_dir as $_plugin_dir) { + + $_plugin_filepath = $_plugin_dir . DIRECTORY_SEPARATOR . $_plugin_filename; + + // see if path is relative + if (!preg_match("/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/", $_plugin_dir)) { + $_relative_paths[] = $_plugin_dir; + // relative path, see if it is in the SMARTY_DIR + if (@is_readable(SMARTY_DIR . $_plugin_filepath)) { + $_return = SMARTY_DIR . $_plugin_filepath; + break; + } + } + // try relative to cwd (or absolute) + if (@is_readable($_plugin_filepath)) { + $_return = $_plugin_filepath; + break; + } + } + + if($_return === false) { + // still not found, try PHP include_path + if(isset($_relative_paths)) { + foreach ((array)$_relative_paths as $_plugin_dir) { + + $_plugin_filepath = $_plugin_dir . DIRECTORY_SEPARATOR . $_plugin_filename; + + $_params = array('file_path' => $_plugin_filepath); + require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.get_include_path.php'); + if(smarty_core_get_include_path($_params, $smarty)) { + return $_params['new_file_path']; + } + } + } + } + + return $_return; +} + +/* vim: set expandtab: */ + +?> diff --git a/src/functions/smarty/core/core.assign_smarty_interface.php b/src/functions/smarty/core/core.assign_smarty_interface.php new file mode 100644 index 0000000..7e65a73 --- /dev/null +++ b/src/functions/smarty/core/core.assign_smarty_interface.php @@ -0,0 +1,43 @@ + + * Name: assign_smarty_interface
    + * Purpose: assign the $smarty interface variable + * @param array Format: null + * @param Smarty + */ +function smarty_core_assign_smarty_interface($params, &$smarty) +{ + if (isset($smarty->_smarty_vars) && isset($smarty->_smarty_vars['request'])) { + return; + } + + $_globals_map = array('g' => 'HTTP_GET_VARS', + 'p' => 'HTTP_POST_VARS', + 'c' => 'HTTP_COOKIE_VARS', + 's' => 'HTTP_SERVER_VARS', + 'e' => 'HTTP_ENV_VARS'); + + $_smarty_vars_request = array(); + + foreach (preg_split('!!', strtolower($smarty->request_vars_order)) as $_c) { + if (isset($_globals_map[$_c])) { + $_smarty_vars_request = array_merge($_smarty_vars_request, $GLOBALS[$_globals_map[$_c]]); + } + } + $_smarty_vars_request = @array_merge($_smarty_vars_request, $GLOBALS['HTTP_SESSION_VARS']); + + $smarty->_smarty_vars['request'] = $_smarty_vars_request; +} + +/* vim: set expandtab: */ + +?> diff --git a/src/functions/smarty/core/core.create_dir_structure.php b/src/functions/smarty/core/core.create_dir_structure.php new file mode 100644 index 0000000..999cf59 --- /dev/null +++ b/src/functions/smarty/core/core.create_dir_structure.php @@ -0,0 +1,79 @@ +_dir_perms) && !is_dir($_new_dir)) { + $smarty->trigger_error("problem creating directory '" . $_new_dir . "'"); + return false; + } + $_new_dir .= '/'; + } + } +} + +/* vim: set expandtab: */ + +?> diff --git a/src/functions/smarty/core/core.display_debug_console.php b/src/functions/smarty/core/core.display_debug_console.php new file mode 100644 index 0000000..c509ff7 --- /dev/null +++ b/src/functions/smarty/core/core.display_debug_console.php @@ -0,0 +1,60 @@ + + * Name: display_debug_console
    + * Purpose: display the javascript debug console window + * @param array Format: null + * @param Smarty + */ +function smarty_core_display_debug_console($params, &$smarty) +{ + // we must force compile the debug template in case the environment + // changed between separate applications. + + if(empty($smarty->debug_tpl)) { + // set path to debug template from SMARTY_DIR + $smarty->debug_tpl = SMARTY_DIR . 'debug.tpl'; + if($smarty->security && is_file($smarty->debug_tpl)) { + $smarty->secure_dir[] = dirname(realpath($smarty->debug_tpl)); + } + } + + $_ldelim_orig = $smarty->left_delimiter; + $_rdelim_orig = $smarty->right_delimiter; + + $smarty->left_delimiter = '{'; + $smarty->right_delimiter = '}'; + + $_compile_id_orig = $smarty->_compile_id; + $smarty->_compile_id = null; + + $_compile_path = $smarty->_get_compile_path($smarty->debug_tpl); + if ($smarty->_compile_resource($smarty->debug_tpl, $_compile_path)) + { + ob_start(); + $smarty->_include($_compile_path); + $_results = ob_get_contents(); + ob_end_clean(); + } else { + $_results = ''; + } + + $smarty->_compile_id = $_compile_id_orig; + + $smarty->left_delimiter = $_ldelim_orig; + $smarty->right_delimiter = $_rdelim_orig; + + return $_results; +} + +/* vim: set expandtab: */ + +?> diff --git a/src/functions/smarty/core/core.get_include_path.php b/src/functions/smarty/core/core.get_include_path.php new file mode 100644 index 0000000..941c981 --- /dev/null +++ b/src/functions/smarty/core/core.get_include_path.php @@ -0,0 +1,44 @@ + \ No newline at end of file diff --git a/src/functions/smarty/core/core.get_microtime.php b/src/functions/smarty/core/core.get_microtime.php new file mode 100644 index 0000000..f1a28e0 --- /dev/null +++ b/src/functions/smarty/core/core.get_microtime.php @@ -0,0 +1,23 @@ + diff --git a/src/functions/smarty/core/core.get_php_resource.php b/src/functions/smarty/core/core.get_php_resource.php new file mode 100644 index 0000000..8121acf --- /dev/null +++ b/src/functions/smarty/core/core.get_php_resource.php @@ -0,0 +1,80 @@ +trusted_dir; + $smarty->_parse_resource_name($params, $smarty); + + /* + * Find out if the resource exists. + */ + + if ($params['resource_type'] == 'file') { + $_readable = false; + if(file_exists($params['resource_name']) && is_readable($params['resource_name'])) { + $_readable = true; + } else { + // test for file in include_path + $_params = array('file_path' => $params['resource_name']); + require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.get_include_path.php'); + if(smarty_core_get_include_path($_params, $smarty)) { + $_include_path = $_params['new_file_path']; + $_readable = true; + } + } + } else if ($params['resource_type'] != 'file') { + $_template_source = null; + $_readable = is_callable($smarty->_plugins['resource'][$params['resource_type']][0][0]) + && call_user_func_array($smarty->_plugins['resource'][$params['resource_type']][0][0], + array($params['resource_name'], &$_template_source, &$smarty)); + } + + /* + * Set the error function, depending on which class calls us. + */ + if (method_exists($smarty, '_syntax_error')) { + $_error_funcc = '_syntax_error'; + } else { + $_error_funcc = 'trigger_error'; + } + + if ($_readable) { + if ($smarty->security) { + require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.is_trusted.php'); + if (!smarty_core_is_trusted($params, $smarty)) { + $smarty->$_error_funcc('(secure mode) ' . $params['resource_type'] . ':' . $params['resource_name'] . ' is not trusted'); + return false; + } + } + } else { + $smarty->$_error_funcc($params['resource_type'] . ':' . $params['resource_name'] . ' is not readable'); + return false; + } + + if ($params['resource_type'] == 'file') { + $params['php_resource'] = $params['resource_name']; + } else { + $params['php_resource'] = $_template_source; + } + return true; +} + +/* vim: set expandtab: */ + +?> diff --git a/src/functions/smarty/core/core.is_secure.php b/src/functions/smarty/core/core.is_secure.php new file mode 100644 index 0000000..877886b --- /dev/null +++ b/src/functions/smarty/core/core.is_secure.php @@ -0,0 +1,59 @@ +security || $smarty->security_settings['INCLUDE_ANY']) { + return true; + } + + $_smarty_secure = false; + if ($params['resource_type'] == 'file') { + if($check_template_dir) { + if (!in_array($smarty->template_dir, $smarty->secure_dir)) + // add template_dir to secure_dir array + array_unshift($smarty->secure_dir, $smarty->template_dir); + $check_template_dir = false; + } + if (!empty($smarty->secure_dir)) { + $_rp = realpath($params['resource_name']); + foreach ((array)$smarty->secure_dir as $curr_dir) { + if ( !empty($curr_dir) && is_readable ($curr_dir)) { + $_cd = realpath($curr_dir); + if (strncmp($_rp, $_cd, strlen($_cd)) == 0 + && $_rp{strlen($_cd)} == DIRECTORY_SEPARATOR ) { + $_smarty_secure = true; + break; + } + } + } + } + } else { + // resource is not on local file system + $_smarty_secure = call_user_func_array( + $smarty->_plugins['resource'][$params['resource_type']][0][2], + array($params['resource_name'], &$_smarty_secure, &$smarty)); + } + + return $_smarty_secure; +} + +/* vim: set expandtab: */ + +?> diff --git a/src/functions/smarty/core/core.is_trusted.php b/src/functions/smarty/core/core.is_trusted.php new file mode 100644 index 0000000..c90e3ef --- /dev/null +++ b/src/functions/smarty/core/core.is_trusted.php @@ -0,0 +1,50 @@ +trusted_dir)) { + $_rp = realpath($params['resource_name']); + foreach ((array)$smarty->trusted_dir as $curr_dir) { + if (!empty($curr_dir) && is_readable ($curr_dir)) { + $_cd = realpath($curr_dir); + if (strncmp($_rp, $_cd, strlen($_cd)) == 0 + && $_rp{strlen($_cd)} == DIRECTORY_SEPARATOR ) { + $_smarty_trusted = true; + break; + } + } + } + } + + } else { + // resource is not on local file system + $_smarty_trusted = call_user_func_array($smarty->_plugins['resource'][$params['resource_type']][0][3], + array($params['resource_name'], $smarty)); + } + + return $_smarty_trusted; +} + +/* vim: set expandtab: */ + +?> diff --git a/src/functions/smarty/core/core.load_plugins.php b/src/functions/smarty/core/core.load_plugins.php new file mode 100644 index 0000000..6db1dc5 --- /dev/null +++ b/src/functions/smarty/core/core.load_plugins.php @@ -0,0 +1,125 @@ +_plugins[$_type][$_name]; + + /* + * We do not load plugin more than once for each instance of Smarty. + * The following code checks for that. The plugin can also be + * registered dynamically at runtime, in which case template file + * and line number will be unknown, so we fill them in. + * + * The final element of the info array is a flag that indicates + * whether the dynamically registered plugin function has been + * checked for existence yet or not. + */ + if (isset($_plugin)) { + if (empty($_plugin[3])) { + if (!is_callable($_plugin[0])) { + $smarty->_trigger_fatal_error("[plugin] $_type '$_name' is not implemented", $_tpl_file, $_tpl_line, __FILE__, __LINE__); + } else { + $_plugin[1] = $_tpl_file; + $_plugin[2] = $_tpl_line; + $_plugin[3] = true; + if (!isset($_plugin[4])) $_plugin[4] = true; /* cacheable */ + } + } + continue; + } else if ($_type == 'insert') { + /* + * For backwards compatibility, we check for insert functions in + * the symbol table before trying to load them as a plugin. + */ + $_plugin_func = 'insert_' . $_name; + if (function_exists($_plugin_func)) { + $_plugin = array($_plugin_func, $_tpl_file, $_tpl_line, true, false); + continue; + } + } + + $_plugin_file = $smarty->_get_plugin_filepath($_type, $_name); + + if (! $_found = ($_plugin_file != false)) { + $_message = "could not load plugin file '$_type.$_name.php'\n"; + } + + /* + * If plugin file is found, it -must- provide the properly named + * plugin function. In case it doesn't, simply output the error and + * do not fall back on any other method. + */ + if ($_found) { + include_once $_plugin_file; + + $_plugin_func = 'smarty_' . $_type . '_' . $_name; + if (!function_exists($_plugin_func)) { + $smarty->_trigger_fatal_error("[plugin] function $_plugin_func() not found in $_plugin_file", $_tpl_file, $_tpl_line, __FILE__, __LINE__); + continue; + } + } + /* + * In case of insert plugins, their code may be loaded later via + * 'script' attribute. + */ + else if ($_type == 'insert' && $_delayed_loading) { + $_plugin_func = 'smarty_' . $_type . '_' . $_name; + $_found = true; + } + + /* + * Plugin specific processing and error checking. + */ + if (!$_found) { + if ($_type == 'modifier') { + /* + * In case modifier falls back on using PHP functions + * directly, we only allow those specified in the security + * context. + */ + if ($smarty->security && !in_array($_name, $smarty->security_settings['MODIFIER_FUNCS'])) { + $_message = "(secure mode) modifier '$_name' is not allowed"; + } else { + if (!function_exists($_name)) { + $_message = "modifier '$_name' is not implemented"; + } else { + $_plugin_func = $_name; + $_found = true; + } + } + } else if ($_type == 'function') { + /* + * This is a catch-all situation. + */ + $_message = "unknown tag - '$_name'"; + } + } + + if ($_found) { + $smarty->_plugins[$_type][$_name] = array($_plugin_func, $_tpl_file, $_tpl_line, true, true); + } else { + // output error + $smarty->_trigger_fatal_error('[plugin] ' . $_message, $_tpl_file, $_tpl_line, __FILE__, __LINE__); + } + } +} + +/* vim: set expandtab: */ + +?> diff --git a/src/functions/smarty/core/core.load_resource_plugin.php b/src/functions/smarty/core/core.load_resource_plugin.php new file mode 100644 index 0000000..a7d37d1 --- /dev/null +++ b/src/functions/smarty/core/core.load_resource_plugin.php @@ -0,0 +1,74 @@ +_plugins['resource'][$params['type']]; + if (isset($_plugin)) { + if (!$_plugin[1] && count($_plugin[0])) { + $_plugin[1] = true; + foreach ($_plugin[0] as $_plugin_func) { + if (!is_callable($_plugin_func)) { + $_plugin[1] = false; + break; + } + } + } + + if (!$_plugin[1]) { + $smarty->_trigger_fatal_error("[plugin] resource '" . $params['type'] . "' is not implemented", null, null, __FILE__, __LINE__); + } + + return; + } + + $_plugin_file = $smarty->_get_plugin_filepath('resource', $params['type']); + $_found = ($_plugin_file != false); + + if ($_found) { /* + * If the plugin file is found, it -must- provide the properly named + * plugin functions. + */ + include_once($_plugin_file); + + /* + * Locate functions that we require the plugin to provide. + */ + $_resource_ops = array('source', 'timestamp', 'secure', 'trusted'); + $_resource_funcs = array(); + foreach ($_resource_ops as $_op) { + $_plugin_func = 'smarty_resource_' . $params['type'] . '_' . $_op; + if (!function_exists($_plugin_func)) { + $smarty->_trigger_fatal_error("[plugin] function $_plugin_func() not found in $_plugin_file", null, null, __FILE__, __LINE__); + return; + } else { + $_resource_funcs[] = $_plugin_func; + } + } + + $smarty->_plugins['resource'][$params['type']] = array($_resource_funcs, true); + } +} + +/* vim: set expandtab: */ + +?> diff --git a/src/functions/smarty/core/core.process_cached_inserts.php b/src/functions/smarty/core/core.process_cached_inserts.php new file mode 100644 index 0000000..0e368fd --- /dev/null +++ b/src/functions/smarty/core/core.process_cached_inserts.php @@ -0,0 +1,71 @@ +_smarty_md5.'{insert_cache (.*)}'.$smarty->_smarty_md5.'!Uis', + $params['results'], $match); + list($cached_inserts, $insert_args) = $match; + + for ($i = 0, $for_max = count($cached_inserts); $i < $for_max; $i++) { + if ($smarty->debugging) { + $_params = array(); + require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.get_microtime.php'); + $debug_start_time = smarty_core_get_microtime($_params, $smarty); + } + + $args = unserialize($insert_args[$i]); + $name = $args['name']; + + if (isset($args['script'])) { + $_params = array('resource_name' => $smarty->_dequote($args['script'])); + require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.get_php_resource.php'); + if(!smarty_core_get_php_resource($_params, $smarty)) { + return false; + } + $resource_type = $_params['resource_type']; + $php_resource = $_params['php_resource']; + + + if ($resource_type == 'file') { + $smarty->_include($php_resource, true); + } else { + $smarty->_eval($php_resource); + } + } + + $function_name = $smarty->_plugins['insert'][$name][0]; + if (empty($args['assign'])) { + $replace = $function_name($args, $smarty); + } else { + $smarty->assign($args['assign'], $function_name($args, $smarty)); + $replace = ''; + } + + $params['results'] = str_replace($cached_inserts[$i], $replace, $params['results']); + if ($smarty->debugging) { + $_params = array(); + require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.get_microtime.php'); + $smarty->_smarty_debug_info[] = array('type' => 'insert', + 'filename' => 'insert_'.$name, + 'depth' => $smarty->_inclusion_depth, + 'exec_time' => smarty_core_get_microtime($_params, $smarty) - $debug_start_time); + } + } + + return $params['results']; +} + +/* vim: set expandtab: */ + +?> diff --git a/src/functions/smarty/core/core.process_compiled_include.php b/src/functions/smarty/core/core.process_compiled_include.php new file mode 100644 index 0000000..3e1d4c1 --- /dev/null +++ b/src/functions/smarty/core/core.process_compiled_include.php @@ -0,0 +1,32 @@ +_cache_including; + $smarty->_cache_including = true; + + $_return = $params['results']; + foreach ($smarty->_cache_serials as $_include_file_path=>$_cache_serial) { + $_return = preg_replace_callback('!(\{nocache\:('.$_cache_serial.')#(\d+)\})!s', + array(&$smarty, '_process_compiled_include_callback'), + $_return); + } + $smarty->_cache_including = $_cache_including; + return $_return; +} + +?> diff --git a/src/functions/smarty/core/core.read_cache_file.php b/src/functions/smarty/core/core.read_cache_file.php new file mode 100644 index 0000000..2ab4281 --- /dev/null +++ b/src/functions/smarty/core/core.read_cache_file.php @@ -0,0 +1,111 @@ +force_compile) { + // force compile enabled, always regenerate + return false; + } + + if (isset($content_cache[$params['tpl_file'].','.$params['cache_id'].','.$params['compile_id']])) { + list($params['results'], $smarty->_cache_info) = $content_cache[$params['tpl_file'].','.$params['cache_id'].','.$params['compile_id']]; + return true; + } + + if (!empty($smarty->cache_handler_func)) { + // use cache_handler function + call_user_func_array($smarty->cache_handler_func, + array('read', &$smarty, &$params['results'], $params['tpl_file'], $params['cache_id'], $params['compile_id'], null)); + } else { + // use local cache file + $_auto_id = $smarty->_get_auto_id($params['cache_id'], $params['compile_id']); + $_cache_file = $smarty->_get_auto_filename($smarty->cache_dir, $params['tpl_file'], $_auto_id); + $params['results'] = $smarty->_read_file($_cache_file); + } + + if (empty($params['results'])) { + // nothing to parse (error?), regenerate cache + return false; + } + + $cache_split = explode("\n", $params['results'], 2); + $cache_header = $cache_split[0]; + + $_cache_info = unserialize($cache_header); + + if ($smarty->caching == 2 && isset ($_cache_info['expires'])){ + // caching by expiration time + if ($_cache_info['expires'] > -1 && (time() > $_cache_info['expires'])) { + // cache expired, regenerate + return false; + } + } else { + // caching by lifetime + if ($smarty->cache_lifetime > -1 && (time() - $_cache_info['timestamp'] > $smarty->cache_lifetime)) { + // cache expired, regenerate + return false; + } + } + + if ($smarty->compile_check) { + $_params = array('get_source' => false, 'quiet'=>true); + foreach (array_keys($_cache_info['template']) as $_template_dep) { + $_params['resource_name'] = $_template_dep; + if (!$smarty->_fetch_resource_info($_params) || $_cache_info['timestamp'] < $_params['resource_timestamp']) { + // template file has changed, regenerate cache + return false; + } + } + + if (isset($_cache_info['config'])) { + $_params = array('resource_base_path' => $smarty->config_dir, 'get_source' => false, 'quiet'=>true); + foreach (array_keys($_cache_info['config']) as $_config_dep) { + $_params['resource_name'] = $_config_dep; + if (!$smarty->_fetch_resource_info($_params) || $_cache_info['timestamp'] < $_params['resource_timestamp']) { + // config file has changed, regenerate cache + return false; + } + } + } + } + + foreach ($_cache_info['cache_serials'] as $_include_file_path=>$_cache_serial) { + if (empty($smarty->_cache_serials[$_include_file_path])) { + $smarty->_include($_include_file_path, true); + } + + if ($smarty->_cache_serials[$_include_file_path] != $_cache_serial) { + /* regenerate */ + return false; + } + } + $params['results'] = $cache_split[1]; + $content_cache[$params['tpl_file'].','.$params['cache_id'].','.$params['compile_id']] = array($params['results'], $_cache_info); + + $smarty->_cache_info = $_cache_info; + return true; +} + +/* vim: set expandtab: */ + +?> diff --git a/src/functions/smarty/core/core.rm_auto.php b/src/functions/smarty/core/core.rm_auto.php new file mode 100644 index 0000000..b7cdaf8 --- /dev/null +++ b/src/functions/smarty/core/core.rm_auto.php @@ -0,0 +1,71 @@ + $params['auto_base'], + 'level' => 0, + 'exp_time' => $params['exp_time'] + ); + require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.rmdir.php'); + $_res = smarty_core_rmdir($_params, $smarty); + } else { + $_tname = $smarty->_get_auto_filename($params['auto_base'], $params['auto_source'], $params['auto_id']); + + if(isset($params['auto_source'])) { + if (isset($params['extensions'])) { + $_res = false; + foreach ((array)$params['extensions'] as $_extension) + $_res |= $smarty->_unlink($_tname.$_extension, $params['exp_time']); + } else { + $_res = $smarty->_unlink($_tname, $params['exp_time']); + } + } elseif ($smarty->use_sub_dirs) { + $_params = array( + 'dirname' => $_tname, + 'level' => 1, + 'exp_time' => $params['exp_time'] + ); + require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.rmdir.php'); + $_res = smarty_core_rmdir($_params, $smarty); + } else { + // remove matching file names + $_handle = opendir($params['auto_base']); + $_res = true; + while (false !== ($_filename = readdir($_handle))) { + if($_filename == '.' || $_filename == '..') { + continue; + } elseif (substr($params['auto_base'] . DIRECTORY_SEPARATOR . $_filename, 0, strlen($_tname)) == $_tname) { + $_res &= (bool)$smarty->_unlink($params['auto_base'] . DIRECTORY_SEPARATOR . $_filename, $params['exp_time']); + } + } + } + } + + return $_res; +} + +/* vim: set expandtab: */ + +?> diff --git a/src/functions/smarty/core/core.rmdir.php b/src/functions/smarty/core/core.rmdir.php new file mode 100644 index 0000000..38df822 --- /dev/null +++ b/src/functions/smarty/core/core.rmdir.php @@ -0,0 +1,55 @@ + keep root) + * WARNING: no tests, it will try to remove what you tell it! + * + * @param string $dirname + * @param integer $level + * @param integer $exp_time + * @return boolean + */ + +// $dirname, $level = 1, $exp_time = null + +function smarty_core_rmdir($params, &$smarty) +{ + if(!isset($params['level'])) { $params['level'] = 1; } + if(!isset($params['exp_time'])) { $params['exp_time'] = null; } + + if($_handle = @opendir($params['dirname'])) { + + while (false !== ($_entry = readdir($_handle))) { + if ($_entry != '.' && $_entry != '..') { + if (@is_dir($params['dirname'] . DIRECTORY_SEPARATOR . $_entry)) { + $_params = array( + 'dirname' => $params['dirname'] . DIRECTORY_SEPARATOR . $_entry, + 'level' => $params['level'] + 1, + 'exp_time' => $params['exp_time'] + ); + require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.rmdir.php'); + smarty_core_rmdir($_params, $smarty); + } + else { + $smarty->_unlink($params['dirname'] . DIRECTORY_SEPARATOR . $_entry, $params['exp_time']); + } + } + } + closedir($_handle); + } + + if ($params['level']) { + return @rmdir($params['dirname']); + } + return (bool)$_handle; + +} + +/* vim: set expandtab: */ + +?> diff --git a/src/functions/smarty/core/core.run_insert_handler.php b/src/functions/smarty/core/core.run_insert_handler.php new file mode 100644 index 0000000..aa391ab --- /dev/null +++ b/src/functions/smarty/core/core.run_insert_handler.php @@ -0,0 +1,71 @@ +debugging) { + $_params = array(); + $_debug_start_time = smarty_core_get_microtime($_params, $smarty); + } + + if ($smarty->caching) { + $_arg_string = serialize($params['args']); + $_name = $params['args']['name']; + if (!isset($smarty->_cache_info['insert_tags'][$_name])) { + $smarty->_cache_info['insert_tags'][$_name] = array('insert', + $_name, + $smarty->_plugins['insert'][$_name][1], + $smarty->_plugins['insert'][$_name][2], + !empty($params['args']['script']) ? true : false); + } + return $smarty->_smarty_md5."{insert_cache $_arg_string}".$smarty->_smarty_md5; + } else { + if (isset($params['args']['script'])) { + $_params = array('resource_name' => $smarty->_dequote($params['args']['script'])); + require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.get_php_resource.php'); + if(!smarty_core_get_php_resource($_params, $smarty)) { + return false; + } + + if ($_params['resource_type'] == 'file') { + $smarty->_include($_params['php_resource'], true); + } else { + $smarty->_eval($_params['php_resource']); + } + unset($params['args']['script']); + } + + $_funcname = $smarty->_plugins['insert'][$params['args']['name']][0]; + $_content = $_funcname($params['args'], $smarty); + if ($smarty->debugging) { + $_params = array(); + require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.get_microtime.php'); + $smarty->_smarty_debug_info[] = array('type' => 'insert', + 'filename' => 'insert_'.$params['args']['name'], + 'depth' => $smarty->_inclusion_depth, + 'exec_time' => smarty_core_get_microtime($_params, $smarty) - $_debug_start_time); + } + + if (!empty($params['args']["assign"])) { + $smarty->assign($params['args']["assign"], $_content); + } else { + return $_content; + } + } +} + +/* vim: set expandtab: */ + +?> diff --git a/src/functions/smarty/core/core.smarty_include_php.php b/src/functions/smarty/core/core.smarty_include_php.php new file mode 100644 index 0000000..4b31648 --- /dev/null +++ b/src/functions/smarty/core/core.smarty_include_php.php @@ -0,0 +1,50 @@ + $params['smarty_file']); + require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.get_php_resource.php'); + smarty_core_get_php_resource($_params, $smarty); + $_smarty_resource_type = $_params['resource_type']; + $_smarty_php_resource = $_params['php_resource']; + + if (!empty($params['smarty_assign'])) { + ob_start(); + if ($_smarty_resource_type == 'file') { + $smarty->_include($_smarty_php_resource, $params['smarty_once'], $params['smarty_include_vars']); + } else { + $smarty->_eval($_smarty_php_resource, $params['smarty_include_vars']); + } + $smarty->assign($params['smarty_assign'], ob_get_contents()); + ob_end_clean(); + } else { + if ($_smarty_resource_type == 'file') { + $smarty->_include($_smarty_php_resource, $params['smarty_once'], $params['smarty_include_vars']); + } else { + $smarty->_eval($_smarty_php_resource, $params['smarty_include_vars']); + } + } +} + + +/* vim: set expandtab: */ + +?> diff --git a/src/functions/smarty/core/core.write_cache_file.php b/src/functions/smarty/core/core.write_cache_file.php new file mode 100644 index 0000000..7429ad9 --- /dev/null +++ b/src/functions/smarty/core/core.write_cache_file.php @@ -0,0 +1,73 @@ +_cache_info['timestamp'] = time(); + if ($smarty->cache_lifetime > -1){ + // expiration set + $smarty->_cache_info['expires'] = $smarty->_cache_info['timestamp'] + $smarty->cache_lifetime; + } else { + // cache will never expire + $smarty->_cache_info['expires'] = -1; + } + + // collapse {nocache...}-tags + $params['results'] = preg_replace('!((\{nocache\:([0-9a-f]{32})#(\d+)\})' + .'.*' + .'{/nocache\:\\3#\\4\})!Us' + ,'\\2' + ,$params['results']); + $smarty->_cache_info['cache_serials'] = $smarty->_cache_serials; + + // prepend the cache header info into cache file + $params['results'] = serialize($smarty->_cache_info)."\n".$params['results']; + + if (!empty($smarty->cache_handler_func)) { + // use cache_handler function + call_user_func_array($smarty->cache_handler_func, + array('write', &$smarty, &$params['results'], $params['tpl_file'], $params['cache_id'], $params['compile_id'], null)); + } else { + // use local cache file + + if(!@is_writable($smarty->cache_dir)) { + // cache_dir not writable, see if it exists + if(!@is_dir($smarty->cache_dir)) { + $smarty->trigger_error('the $cache_dir \'' . $smarty->cache_dir . '\' does not exist, or is not a directory.', E_USER_ERROR); + return false; + } + $smarty->trigger_error('unable to write to $cache_dir \'' . realpath($smarty->cache_dir) . '\'. Be sure $cache_dir is writable by the web server user.', E_USER_ERROR); + return false; + } + + $_auto_id = $smarty->_get_auto_id($params['cache_id'], $params['compile_id']); + $_cache_file = $smarty->_get_auto_filename($smarty->cache_dir, $params['tpl_file'], $_auto_id); + $_params = array('filename' => $_cache_file, 'contents' => $params['results'], 'create_dirs' => true); + require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.write_file.php'); + smarty_core_write_file($_params, $smarty); + return true; + } +} + +/* vim: set expandtab: */ + +?> diff --git a/src/functions/smarty/core/core.write_compiled_include.php b/src/functions/smarty/core/core.write_compiled_include.php new file mode 100644 index 0000000..9c6a491 --- /dev/null +++ b/src/functions/smarty/core/core.write_compiled_include.php @@ -0,0 +1,59 @@ +caching\) \{ echo \'\{nocache\:('.$params['cache_serial'].')#(\d+)\}\';\}'; + $_tag_end = 'if \(\$this->caching\) \{ echo \'\{/nocache\:(\\2)#(\\3)\}\';\}'; + + preg_match_all('!('.$_tag_start.'(.*)'.$_tag_end.')!Us', + $params['compiled_content'], $_match_source, PREG_SET_ORDER); + + // no nocache-parts found: done + if (count($_match_source)==0) return; + + // convert the matched php-code to functions + $_include_compiled = "_cache_serials[$_compile_path] = $params['cache_serial']; + $_include_compiled .= "\$this->_cache_serials['".$_compile_path."'] = '".$params['cache_serial']."';\n\n?>"; + + $_include_compiled .= $params['plugins_code']; + $_include_compiled .= "\n"; + + $_params = array('filename' => $_compile_path, + 'contents' => $_include_compiled, 'create_dirs' => true); + + require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.write_file.php'); + smarty_core_write_file($_params, $smarty); + return true; +} + + +?> diff --git a/src/functions/smarty/core/core.write_compiled_resource.php b/src/functions/smarty/core/core.write_compiled_resource.php new file mode 100644 index 0000000..09b50d3 --- /dev/null +++ b/src/functions/smarty/core/core.write_compiled_resource.php @@ -0,0 +1,37 @@ +compile_dir)) { + // compile_dir not writable, see if it exists + if(!@is_dir($smarty->compile_dir)) { + $smarty->trigger_error('the $compile_dir \'' . $smarty->compile_dir . '\' does not exist, or is not a directory.', E_USER_ERROR); + return false; + } + $smarty->trigger_error('unable to write to $compile_dir \'' . realpath($smarty->compile_dir) . '\'. Be sure $compile_dir is writable by the web server user.', E_USER_ERROR); + return false; + } + + $_params = array('filename' => $params['compile_path'], 'contents' => $params['compiled_content'], 'create_dirs' => true); + require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.write_file.php'); + smarty_core_write_file($_params, $smarty); + touch($params['compile_path'], $params['resource_timestamp']); + return true; +} + +/* vim: set expandtab: */ + +?> diff --git a/src/functions/smarty/core/core.write_file.php b/src/functions/smarty/core/core.write_file.php new file mode 100644 index 0000000..c92454d --- /dev/null +++ b/src/functions/smarty/core/core.write_file.php @@ -0,0 +1,48 @@ + $_dirname); + require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.create_dir_structure.php'); + smarty_core_create_dir_structure($_params, $smarty); + } + + // write to tmp file, then rename it to avoid + // file locking race condition + $_tmp_file = $_dirname . DIRECTORY_SEPARATOR . uniqid(''); + + if (!($fd = @fopen($_tmp_file, 'w'))) { + $smarty->trigger_error("problem writing temporary file '$_tmp_file'"); + return false; + } + + fwrite($fd, $params['contents']); + fclose($fd); + if(file_exists($params['filename'])) { + @unlink($params['filename']); + } + @rename($_tmp_file, $params['filename']); + @chmod($params['filename'], $smarty->_file_perms); + + return true; +} + +/* vim: set expandtab: */ + +?> diff --git a/src/functions/smarty/debug.tpl b/src/functions/smarty/debug.tpl new file mode 100644 index 0000000..01265fb --- /dev/null +++ b/src/functions/smarty/debug.tpl @@ -0,0 +1,64 @@ +{* Smarty *} + +{* debug.tpl, last updated version 2.0.1 *} + +{assign_debug_info} + +{if isset($_smarty_debug_output) and $_smarty_debug_output eq "html"} + + + + {section name=templates loop=$_debug_tpls} + + {sectionelse} + + {/section} + + {section name=vars loop=$_debug_keys} + + {sectionelse} + + {/section} + + {section name=config_vars loop=$_debug_config_keys} + + {sectionelse} + + {/section} +
    Smarty Debug Console
    included templates & config files (load time in seconds):
    {section name=indent loop=$_debug_tpls[templates].depth}   {/section}{$_debug_tpls[templates].filename|escape:html}{if isset($_debug_tpls[templates].exec_time)} ({$_debug_tpls[templates].exec_time|string_format:"%.5f"}){if %templates.index% eq 0} (total){/if}{/if}
    no templates included
    assigned template variables:
    {ldelim}${$_debug_keys[vars]}{rdelim}{$_debug_vals[vars]|@debug_print_var}
    no template variables assigned
    assigned config file variables (outer template scope):
    {ldelim}#{$_debug_config_keys[config_vars]}#{rdelim}{$_debug_config_vals[config_vars]|@debug_print_var}
    no config vars assigned
    + +{else} + +{/if} diff --git a/src/functions/smarty/plugins/block.textformat.php b/src/functions/smarty/plugins/block.textformat.php new file mode 100644 index 0000000..7ddccc7 --- /dev/null +++ b/src/functions/smarty/plugins/block.textformat.php @@ -0,0 +1,83 @@ + + * Name: textformat
    + * Purpose: format text a certain way with preset styles + * or custom wrap/indent settings
    + * @link http://smarty.php.net/manual/en/language.function.textformat.php {textformat} + * (Smarty online manual) + * @param array + *
    + * Params:   style: string (email)
    + *           indent: integer (0)
    + *           wrap: integer (80)
    + *           wrap_char string ("\n")
    + *           indent_char: string (" ")
    + *           wrap_boundary: boolean (true)
    + * 
    + * @param string contents of the block + * @param Smarty clever simulation of a method + * @return string string $content re-formatted + */ +function smarty_block_textformat($params, $content, &$smarty) +{ + $style = null; + $indent = 0; + $indent_first = 0; + $indent_char = ' '; + $wrap = 80; + $wrap_char = "\n"; + $wrap_cut = false; + $assign = null; + + if($content == null) { + return true; + } + + extract($params); + + if($style == 'email') { + $wrap = 72; + } + + // split into paragraphs + $paragraphs = preg_split('![\r\n][\r\n]!',$content); + $output = ''; + + foreach($paragraphs as $paragraph) { + if($paragraph == '') { + continue; + } + // convert mult. spaces & special chars to single space + $paragraph = preg_replace(array('!\s+!','!(^\s+)|(\s+$)!'),array(' ',''),$paragraph); + // indent first line + if($indent_first > 0) { + $paragraph = str_repeat($indent_char,$indent_first) . $paragraph; + } + // wordwrap sentences + $paragraph = wordwrap($paragraph, $wrap - $indent, $wrap_char, $wrap_cut); + // indent lines + if($indent > 0) { + $paragraph = preg_replace('!^!m',str_repeat($indent_char,$indent),$paragraph); + } + $output .= $paragraph . $wrap_char . $wrap_char; + } + + if($assign != null) { + $smarty->assign($assign,$output); + } else { + return $output; + } +} + +/* vim: set expandtab: */ + +?> diff --git a/src/functions/smarty/plugins/function.assign.php b/src/functions/smarty/plugins/function.assign.php new file mode 100644 index 0000000..ad23f04 --- /dev/null +++ b/src/functions/smarty/plugins/function.assign.php @@ -0,0 +1,38 @@ + + * Name: assign
    + * Purpose: assign a value to a template variable + * @link http://smarty.php.net/manual/en/language.custom.functions.php#LANGUAGE.FUNCTION.ASSIGN {assign} + * (Smarty online manual) + * @param array Format: array('var' => variable name, 'value' => value to assign) + * @param Smarty + */ +function smarty_function_assign($params, &$smarty) +{ + extract($params); + + if (empty($var)) { + $smarty->trigger_error("assign: missing 'var' parameter"); + return; + } + + if (!in_array('value', array_keys($params))) { + $smarty->trigger_error("assign: missing 'value' parameter"); + return; + } + + $smarty->assign($var, $value); +} + +/* vim: set expandtab: */ + +?> diff --git a/src/functions/smarty/plugins/function.assign_debug_info.php b/src/functions/smarty/plugins/function.assign_debug_info.php new file mode 100644 index 0000000..c281ce8 --- /dev/null +++ b/src/functions/smarty/plugins/function.assign_debug_info.php @@ -0,0 +1,39 @@ + + * Name: assign_debug_info
    + * Purpose: assign debug info to the template
    + * @param array unused in this plugin, this plugin uses {@link Smarty::$_config}, + * {@link Smarty::$_tpl_vars} and {@link Smarty::$_smarty_debug_info} + * @param Smarty + */ +function smarty_function_assign_debug_info($params, &$smarty) +{ + $assigned_vars = $smarty->_tpl_vars; + ksort($assigned_vars); + if (@is_array($smarty->_config[0])) { + $config_vars = $smarty->_config[0]; + ksort($config_vars); + $smarty->assign("_debug_config_keys", array_keys($config_vars)); + $smarty->assign("_debug_config_vals", array_values($config_vars)); + } + + $included_templates = $smarty->_smarty_debug_info; + + $smarty->assign("_debug_keys", array_keys($assigned_vars)); + $smarty->assign("_debug_vals", array_values($assigned_vars)); + + $smarty->assign("_debug_tpls", $included_templates); +} + +/* vim: set expandtab: */ + +?> diff --git a/src/functions/smarty/plugins/function.config_load.php b/src/functions/smarty/plugins/function.config_load.php new file mode 100644 index 0000000..12b7462 --- /dev/null +++ b/src/functions/smarty/plugins/function.config_load.php @@ -0,0 +1,130 @@ + + * Name: config_load
    + * Purpose: load config file vars + * @link http://smarty.php.net/manual/en/language.function.config.load.php {config_load} + * (Smarty online manual) + * @param array Format: + *
    + * array('file' => required config file name,
    + *       'section' => optional config file section to load
    + *       'scope' => local/parent/global
    + *       'global' => overrides scope, setting to parent if true)
    + * 
    + * @param Smarty + */ +function smarty_function_config_load($params, &$smarty) +{ + if ($smarty->debugging) { + $_params = array(); + require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.get_microtime.php'); + $_debug_start_time = smarty_core_get_microtime($_params, $smarty); + } + + $_file = isset($params['file']) ? $smarty->_dequote($params['file']) : null; + $_section = isset($params['section']) ? $smarty->_dequote($params['section']) : null; + $_scope = isset($params['scope']) ? $smarty->_dequote($params['scope']) : 'global'; + $_global = isset($params['global']) ? $smarty->_dequote($params['global']) : false; + + if (!isset($_file) || strlen($_file) == 0) { + $smarty->_syntax_error("missing 'file' attribute in config_load tag", E_USER_ERROR, __FILE__, __LINE__); + } + + if (isset($_scope)) { + if ($_scope != 'local' && + $_scope != 'parent' && + $_scope != 'global') { + $smarty->_syntax_error("invalid 'scope' attribute value", E_USER_ERROR, __FILE__, __LINE__); + } + } else { + if ($_global) { + $_scope = 'parent'; + } else { + $_scope = 'local'; + } + } + + if(@is_dir($smarty->config_dir)) { + $_config_dir = $smarty->config_dir; + } else { + // config_dir not found, try include_path + $_params = array('file_path' => $smarty->config_dir); + require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.get_include_path.php'); + smarty_core_get_include_path($_params, $smarty); + $_config_dir = $_params['new_file_path']; + } + + $_file_path = $_config_dir . DIRECTORY_SEPARATOR . $_file; + if (isset($_section)) + $_compile_file = $smarty->_get_compile_path($_file_path.'|'.$_section); + else + $_compile_file = $smarty->_get_compile_path($_file_path); + + if($smarty->force_compile + || !file_exists($_compile_file) + || ($smarty->compile_check + && !$smarty->_is_compiled($_file_path, $_compile_file))) { + // compile config file + if(!is_object($smarty->_conf_obj)) { + require_once SMARTY_DIR . $smarty->config_class . '.class.php'; + $smarty->_conf_obj = new $smarty->config_class($_config_dir); + $smarty->_conf_obj->overwrite = $smarty->config_overwrite; + $smarty->_conf_obj->booleanize = $smarty->config_booleanize; + $smarty->_conf_obj->read_hidden = $smarty->config_read_hidden; + $smarty->_conf_obj->fix_newlines = $smarty->config_fix_newlines; + $smarty->_conf_obj->set_path = $_config_dir; + } + $_config_vars = array_merge($smarty->_conf_obj->get($_file), + $smarty->_conf_obj->get($_file, $_section)); + if(function_exists('var_export')) { + $_output = ''; + } else { + $_output = ''\\\'', '\\'=>'\\\\')) . '\'); ?>'; + } + $_params = (array('compile_path' => $_compile_file, 'compiled_content' => $_output, 'resource_timestamp' => filemtime($_file_path))); + require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.write_compiled_resource.php'); + smarty_core_write_compiled_resource($_params, $smarty); + } else { + include($_compile_file); + } + + if ($smarty->caching) { + $smarty->_cache_info['config'][$_file] = true; + } + + $smarty->_config[0]['vars'] = @array_merge($smarty->_config[0]['vars'], $_config_vars); + $smarty->_config[0]['files'][$_file] = true; + + if ($_scope == 'parent') { + $smarty->_config[1]['vars'] = @array_merge($smarty->_config[1]['vars'], $_config_vars); + $smarty->_config[1]['files'][$_file] = true; + } else if ($_scope == 'global') { + for ($i = 1, $for_max = count($smarty->_config); $i < $for_max; $i++) { + $smarty->_config[$i]['vars'] = @array_merge($smarty->_config[$i]['vars'], $_config_vars); + $smarty->_config[$i]['files'][$_file] = true; + } + } + + if ($smarty->debugging) { + $_params = array(); + require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.get_microtime.php'); + $smarty->_smarty_debug_info[] = array('type' => 'config', + 'filename' => $_file.' ['.$_section.'] '.$_scope, + 'depth' => $smarty->_inclusion_depth, + 'exec_time' => smarty_core_get_microtime($_params, $smarty) - $_debug_start_time); + } + +} + +/* vim: set expandtab: */ + +?> diff --git a/src/functions/smarty/plugins/function.counter.php b/src/functions/smarty/plugins/function.counter.php new file mode 100644 index 0000000..2536c14 --- /dev/null +++ b/src/functions/smarty/plugins/function.counter.php @@ -0,0 +1,88 @@ + + * Name: counter
    + * Purpose: print out a counter value + * @link http://smarty.php.net/manual/en/language.function.counter.php {counter} + * (Smarty online manual) + * @param array parameters + * @param Smarty + * @return string|null + */ +function smarty_function_counter($params, &$smarty) +{ + static $counters = array(); + + extract($params); + + if (!isset($name)) { + if(isset($id)) { + $name = $id; + } else { + $name = "default"; + } + } + + if (!isset($counters[$name])) { + $counters[$name] = array( + 'start'=>1, + 'skip'=>1, + 'direction'=>'up', + 'count'=>1 + ); + } + $counter =& $counters[$name]; + + if (isset($start)) { + $counter['start'] = $counter['count'] = $start; + } + + if (!empty($assign)) { + $counter['assign'] = $assign; + } + + if (isset($counter['assign'])) { + $smarty->assign($counter['assign'], $counter['count']); + } + + if (isset($print)) { + $print = (bool)$print; + } else { + $print = empty($counter['assign']); + } + + if ($print) { + $retval = $counter['count']; + } else { + $retval = null; + } + + if (isset($skip)) { + $counter['skip'] = $skip; + } + + if (isset($direction)) { + $counter['direction'] = $direction; + } + + if ($counter['direction'] == "down") + $counter['count'] -= $counter['skip']; + else + $counter['count'] += $counter['skip']; + + return $retval; + +} + +/* vim: set expandtab: */ + +?> diff --git a/src/functions/smarty/plugins/function.cycle.php b/src/functions/smarty/plugins/function.cycle.php new file mode 100644 index 0000000..d5909a6 --- /dev/null +++ b/src/functions/smarty/plugins/function.cycle.php @@ -0,0 +1,119 @@ + + * Name: cycle
    + * Date: May 3, 2002
    + * Purpose: cycle through given values
    + * Input: + * - name = name of cycle (optional) + * - values = comma separated list of values to cycle, + * or an array of values to cycle + * (this can be left out for subsequent calls) + * - reset = boolean - resets given var to true + * - print = boolean - print var or not. default is true + * - advance = boolean - whether or not to advance the cycle + * - delimiter = the value delimiter, default is "," + * - assign = boolean, assigns to template var instead of + * printed. + * + * Examples:
    + *
    + * {cycle values="#eeeeee,#d0d0d0d"}
    + * {cycle name=row values="one,two,three" reset=true}
    + * {cycle name=row}
    + * 
    + * @link http://smarty.php.net/manual/en/language.function.cycle.php {cycle} + * (Smarty online manual) + * @author Monte Ohrt + * @author credit to Mark Priatel + * @author credit to Gerard + * @author credit to Jason Sweat + * @version 1.3 + * @param array + * @param Smarty + * @return string|null + */ +function smarty_function_cycle($params, &$smarty) +{ + static $cycle_vars; + + extract($params); + + if (empty($name)) { + $name = 'default'; + } + + if (!isset($print)) { + $print = true; + } + + if (!isset($advance)) { + $advance = true; + } + + if (!isset($reset)) { + $reset = false; + } + + if (!in_array('values', array_keys($params))) { + if(!isset($cycle_vars[$name]['values'])) { + $smarty->trigger_error("cycle: missing 'values' parameter"); + return; + } + } else { + if(isset($cycle_vars[$name]['values']) + && $cycle_vars[$name]['values'] != $values ) { + $cycle_vars[$name]['index'] = 0; + } + $cycle_vars[$name]['values'] = $values; + } + + if (isset($delimiter)) { + $cycle_vars[$name]['delimiter'] = $delimiter; + } elseif (!isset($cycle_vars[$name]['delimiter'])) { + $cycle_vars[$name]['delimiter'] = ','; + } + + if(!is_array($cycle_vars[$name]['values'])) { + $cycle_array = explode($cycle_vars[$name]['delimiter'],$cycle_vars[$name]['values']); + } else { + $cycle_array = $cycle_vars[$name]['values']; + } + + if(!isset($cycle_vars[$name]['index']) || $reset ) { + $cycle_vars[$name]['index'] = 0; + } + + if (isset($assign)) { + $print = false; + $smarty->assign($assign, $cycle_array[$cycle_vars[$name]['index']]); + } + + if($print) { + $retval = $cycle_array[$cycle_vars[$name]['index']]; + } else { + $retval = null; + } + + if($advance) { + if ( $cycle_vars[$name]['index'] >= count($cycle_array) -1 ) { + $cycle_vars[$name]['index'] = 0; + } else { + $cycle_vars[$name]['index']++; + } + } + + return $retval; +} + +/* vim: set expandtab: */ + +?> diff --git a/src/functions/smarty/plugins/function.debug.php b/src/functions/smarty/plugins/function.debug.php new file mode 100644 index 0000000..2452d62 --- /dev/null +++ b/src/functions/smarty/plugins/function.debug.php @@ -0,0 +1,35 @@ + + * Name: debug
    + * Date: July 1, 2002
    + * Purpose: popup debug window + * @link http://smarty.php.net/manual/en/language.function.debug.php {debug} + * (Smarty online manual) + * @author Monte Ohrt + * @version 1.0 + * @param array + * @param Smarty + * @return string output from {@link Smarty::_generate_debug_output()} + */ +function smarty_function_debug($params, &$smarty) +{ + if($params['output']) { + $smarty->assign('_smarty_debug_output',$params['output']); + } + require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.display_debug_console.php'); + return smarty_core_display_debug_console(null, $smarty); +} + +/* vim: set expandtab: */ + +?> diff --git a/src/functions/smarty/plugins/function.eval.php b/src/functions/smarty/plugins/function.eval.php new file mode 100644 index 0000000..3a4b8b2 --- /dev/null +++ b/src/functions/smarty/plugins/function.eval.php @@ -0,0 +1,48 @@ + + * Name: eval
    + * Purpose: evaluate a template variable as a template
    + * @link http://smarty.php.net/manual/en/language.function.eval.php {eval} + * (Smarty online manual) + * @param array + * @param Smarty + */ +function smarty_function_eval($params, &$smarty) +{ + + if (!isset($params['var'])) { + $smarty->trigger_error("eval: missing 'var' parameter"); + return; + } + + if($params['var'] == '') { + return; + } + + $smarty->_compile_source('evaluated template', $params['var'], $_var_compiled); + + ob_start(); + $smarty->_eval('?>' . $_var_compiled); + $_contents = ob_get_contents(); + ob_end_clean(); + + if (!empty($params['assign'])) { + $smarty->assign($params['assign'], $_contents); + } else { + return $_contents; + } +} + +/* vim: set expandtab: */ + +?> diff --git a/src/functions/smarty/plugins/function.fetch.php b/src/functions/smarty/plugins/function.fetch.php new file mode 100644 index 0000000..b013b8c --- /dev/null +++ b/src/functions/smarty/plugins/function.fetch.php @@ -0,0 +1,217 @@ + + * Name: fetch
    + * Purpose: fetch file, web or ftp data and display results + * @link http://smarty.php.net/manual/en/language.function.fetch.php {fetch} + * (Smarty online manual) + * @param array + * @param Smarty + * @return string|null if the assign parameter is passed, Smarty assigns the + * result to a template variable + */ +function smarty_function_fetch($params, &$smarty) +{ + if (empty($params['file'])) { + $smarty->_trigger_fatal_error("[plugin] parameter 'file' cannot be empty"); + return; + } + + if ($smarty->security && !preg_match('!^(http|ftp)://!i', $params['file'])) { + $_params = array('resource_type' => 'file', 'resource_name' => $params['file']); + require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.is_secure.php'); + if(!smarty_core_is_secure($_params, $smarty)) { + $smarty->_trigger_fatal_error('[plugin] (secure mode) fetch \'' . $params['file'] . '\' is not allowed'); + return; + } + + // fetch the file + if($fp = @fopen($params['file'],'r')) { + while(!feof($fp)) { + $content .= fgets ($fp,4096); + } + fclose($fp); + } else { + $smarty->_trigger_fatal_error('[plugin] fetch cannot read file \'' . $params['file'] . '\''); + return; + } + } else { + // not a local file + if(preg_match('!^http://!i',$params['file'])) { + // http fetch + if($uri_parts = parse_url($params['file'])) { + // set defaults + $host = $server_name = $uri_parts['host']; + $timeout = 30; + $accept = "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*"; + $agent = "Smarty Template Engine ".$smarty->_version; + $referer = ""; + $uri = !empty($uri_parts['path']) ? $uri_parts['path'] : '/'; + $uri .= !empty($uri_parts['query']) ? '?' . $uri_parts['query'] : ''; + $_is_proxy = false; + if(empty($uri_parts['port'])) { + $port = 80; + } else { + $port = $uri_parts['port']; + } + if(empty($uri_parts['user'])) { + $user = ''; + } + // loop through parameters, setup headers + foreach($params as $param_key => $param_value) { + switch($param_key) { + case "file": + case "assign": + case "assign_headers": + break; + case "user": + if(!empty($param_value)) { + $user = $param_value; + } + break; + case "pass": + if(!empty($param_value)) { + $pass = $param_value; + } + break; + case "accept": + if(!empty($param_value)) { + $accept = $param_value; + } + break; + case "header": + if(!empty($param_value)) { + if(!preg_match('![\w\d-]+: .+!',$param_value)) { + $smarty->_trigger_fatal_error("[plugin] invalid header format '".$param_value."'"); + return; + } else { + $extra_headers[] = $param_value; + } + } + break; + case "proxy_host": + if(!empty($param_value)) { + $proxy_host = $param_value; + } + break; + case "proxy_port": + if(!preg_match('!\D!', $param_value)) { + $proxy_port = (int) $param_value; + } else { + $smarty->_trigger_fatal_error("[plugin] invalid value for attribute '".$param_key."'"); + return; + } + break; + case "agent": + if(!empty($param_value)) { + $agent = $param_value; + } + break; + case "referer": + if(!empty($param_value)) { + $referer = $param_value; + } + break; + case "timeout": + if(!preg_match('!\D!', $param_value)) { + $timeout = (int) $param_value; + } else { + $smarty->_trigger_fatal_error("[plugin] invalid value for attribute '".$param_key."'"); + return; + } + break; + default: + $smarty->_trigger_fatal_error("[plugin] unrecognized attribute '".$param_key."'"); + return; + } + } + if(!empty($proxy_host) && !empty($proxy_port)) { + $_is_proxy = true; + $fp = fsockopen($proxy_host,$proxy_port,$errno,$errstr,$timeout); + } else { + $fp = fsockopen($server_name,$port,$errno,$errstr,$timeout); + } + + if(!$fp) { + $smarty->_trigger_fatal_error("[plugin] unable to fetch: $errstr ($errno)"); + return; + } else { + if($_is_proxy) { + fputs($fp, 'GET ' . $params['file'] . " HTTP/1.0\r\n"); + } else { + fputs($fp, "GET $uri HTTP/1.0\r\n"); + } + if(!empty($host)) { + fputs($fp, "Host: $host\r\n"); + } + if(!empty($accept)) { + fputs($fp, "Accept: $accept\r\n"); + } + if(!empty($agent)) { + fputs($fp, "User-Agent: $agent\r\n"); + } + if(!empty($referer)) { + fputs($fp, "Referer: $referer\r\n"); + } + if(isset($extra_headers) && is_array($extra_headers)) { + foreach($extra_headers as $curr_header) { + fputs($fp, $curr_header."\r\n"); + } + } + if(!empty($user) && !empty($pass)) { + fputs($fp, "Authorization: BASIC ".base64_encode("$user:$pass")."\r\n"); + } + + $content = ''; + fputs($fp, "\r\n"); + while(!feof($fp)) { + $content .= fgets($fp,4096); + } + fclose($fp); + $csplit = split("\r\n\r\n",$content,2); + + $content = $csplit[1]; + + if(!empty($params['assign_headers'])) { + $smarty->assign($params['assign_headers'],split("\r\n",$csplit[0])); + } + } + } else { + $smarty->_trigger_fatal_error("[plugin] unable to parse URL, check syntax"); + return; + } + } else { + // ftp fetch + if($fp = @fopen($params['file'],'r')) { + while(!feof($fp)) { + $content .= fgets ($fp,4096); + } + fclose($fp); + } else { + $smarty->_trigger_fatal_error('[plugin] fetch cannot read file \'' . $params['file'] .'\''); + return; + } + } + + } + + + if (!empty($params['assign'])) { + $smarty->assign($params['assign'],$content); + } else { + return $content; + } +} + +/* vim: set expandtab: */ + +?> diff --git a/src/functions/smarty/plugins/function.html_checkboxes.php b/src/functions/smarty/plugins/function.html_checkboxes.php new file mode 100644 index 0000000..c146fc1 --- /dev/null +++ b/src/functions/smarty/plugins/function.html_checkboxes.php @@ -0,0 +1,135 @@ + + * Type: function
    + * Name: html_checkboxes
    + * Date: 24.Feb.2003
    + * Purpose: Prints out a list of checkbox input types
    + * Input:
    + * - name (optional) - string default "checkbox" + * - values (required) - array + * - options (optional) - associative array + * - checked (optional) - array default not set + * - separator (optional) - ie
    or   + * - output (optional) - without this one the buttons don't have names + * Examples: + *
    + * {html_checkboxes values=$ids output=$names}
    + * {html_checkboxes values=$ids name='box' separator='
    ' output=$names} + * {html_checkboxes values=$ids checked=$checked separator='
    ' output=$names} + *
    + * @link http://smarty.php.net/manual/en/language.function.html.checkboxes.php {html_checkboxes} + * (Smarty online manual) + * @author Christopher Kvarme + * @author credits to Monte Ohrt + * @version 1.0 + * @param array + * @param Smarty + * @return string + * @uses smarty_function_escape_special_chars() + */ +function smarty_function_html_checkboxes($params, &$smarty) +{ + require_once $smarty->_get_plugin_filepath('shared','escape_special_chars'); + + $name = 'checkbox'; + $values = null; + $options = null; + $selected = null; + $separator = ''; + $labels = true; + $output = null; + + $extra = ''; + + foreach($params as $_key => $_val) { + switch($_key) { + case 'name': + case 'separator': + $$_key = $_val; + break; + + case 'labels': + $$_key = (bool)$_val; + break; + + case 'options': + $$_key = (array)$_val; + break; + + case 'values': + case 'output': + $$_key = array_values((array)$_val); + break; + + case 'checked': + case 'selected': + $selected = array_values((array)$_val); + break; + + case 'checkboxes': + $smarty->trigger_error('html_checkboxes: the use of the "checkboxes" attribute is deprecated, use "options" instead', E_USER_WARNING); + $options = (array)$_val; + break; + + default: + if(!is_array($_val)) { + $extra .= ' '.$_key.'="'.smarty_function_escape_special_chars($_val).'"'; + } else { + $smarty->trigger_error("html_checkboxes: extra attribute '$_key' cannot be an array", E_USER_NOTICE); + } + break; + } + } + + if (!isset($options) && !isset($values)) + return ''; /* raise error here? */ + + settype($selected, 'array'); + $_html_result = ''; + + if (is_array($options)) { + + foreach ($options as $_key=>$_val) + $_html_result .= smarty_function_html_checkboxes_output($name, $_key, $_val, $selected, $extra, $separator, $labels); + + + } else { + foreach ($values as $_i=>$_key) { + $_val = isset($output[$_i]) ? $output[$_i] : ''; + $_html_result .= smarty_function_html_checkboxes_output($name, $_key, $_val, $selected, $extra, $separator, $labels); + } + + } + + return $_html_result; + +} + +function smarty_function_html_checkboxes_output($name, $value, $output, $selected, $extra, $separator, $labels) { + $_output = ''; + if ($labels) $_output .= ''; + $_output .= $separator . "\n"; + + return $_output; +} + +?> diff --git a/src/functions/smarty/plugins/function.html_image.php b/src/functions/smarty/plugins/function.html_image.php new file mode 100644 index 0000000..2fcdb4e --- /dev/null +++ b/src/functions/smarty/plugins/function.html_image.php @@ -0,0 +1,143 @@ + + * Name: html_image
    + * Date: Feb 24, 2003
    + * Purpose: format HTML tags for the image
    + * Input:
    + * - file = file (and path) of image (required) + * - border = border width (optional, default 0) + * - height = image height (optional, default actual height) + * - image =image width (optional, default actual width) + * - basedir = base directory for absolute paths, default + * is environment variable DOCUMENT_ROOT + * + * Examples: {html_image file="images/masthead.gif"} + * Output: + * @link http://smarty.php.net/manual/en/language.function.html.image.php {html_image} + * (Smarty online manual) + * @author Monte Ohrt + * @author credits to Duda - wrote first image function + * in repository, helped with lots of functionality + * @version 1.0 + * @param array + * @param Smarty + * @return string + * @uses smarty_function_escape_special_chars() + */ +function smarty_function_html_image($params, &$smarty) +{ + require_once $smarty->_get_plugin_filepath('shared','escape_special_chars'); + + $alt = ''; + $file = ''; + $border = 0; + $height = ''; + $width = ''; + $extra = ''; + $prefix = ''; + $suffix = ''; + $basedir = isset($GLOBALS['HTTP_SERVER_VARS']['DOCUMENT_ROOT']) + ? $GLOBALS['HTTP_SERVER_VARS']['DOCUMENT_ROOT'] : ''; + if(strstr($GLOBALS['HTTP_SERVER_VARS']['HTTP_USER_AGENT'], 'Mac')) { + $dpi_default = 72; + } else { + $dpi_default = 96; + } + + foreach($params as $_key => $_val) { + switch($_key) { + case 'file': + case 'border': + case 'height': + case 'width': + case 'dpi': + case 'basedir': + $$_key = $_val; + break; + + case 'alt': + if(!is_array($_val)) { + $$_key = smarty_function_escape_special_chars($_val); + } else { + $smarty->trigger_error("html_image: extra attribute '$_key' cannot be an array", E_USER_NOTICE); + } + break; + + case 'link': + case 'href': + $prefix = ''; + $suffix = ''; + break; + + default: + if(!is_array($_val)) { + $extra .= ' '.$_key.'="'.smarty_function_escape_special_chars($_val).'"'; + } else { + $smarty->trigger_error("html_image: extra attribute '$_key' cannot be an array", E_USER_NOTICE); + } + break; + } + } + + if (empty($file)) { + $smarty->trigger_error("html_image: missing 'file' parameter", E_USER_NOTICE); + return; + } + + if (substr($file,0,1) == '/') { + $_image_path = $basedir . $file; + } else { + $_image_path = $file; + } + + if(!isset($params['width']) || !isset($params['height'])) { + if(!$_image_data = @getimagesize($_image_path)) { + if(!file_exists($_image_path)) { + $smarty->trigger_error("html_image: unable to find '$_image_path'", E_USER_NOTICE); + return; + } else if(!is_readable($_image_path)) { + $smarty->trigger_error("html_image: unable to read '$_image_path'", E_USER_NOTICE); + return; + } else { + $smarty->trigger_error("html_image: '$_image_path' is not a valid image file", E_USER_NOTICE); + return; + } + } + $_params = array('resource_type' => 'file', 'resource_name' => $_image_path); + require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.is_secure.php'); + if(!$smarty->security && !smarty_core_is_secure($_params, $smarty)) { + $smarty->trigger_error("html_image: (secure) '$_image_path' not in secure directory", E_USER_NOTICE); + return; + } + + if(!isset($params['width'])) { + $width = $_image_data[0]; + } + if(!isset($params['height'])) { + $height = $_image_data[1]; + } + + } + + if(isset($params['dpi'])) { + $_resize = $dpi_default/$params['dpi']; + $width = round($width * $_resize); + $height = round($height * $_resize); + } + + return $prefix . ''.$alt.'' . $suffix; +} + +/* vim: set expandtab: */ + +?> diff --git a/src/functions/smarty/plugins/function.html_options.php b/src/functions/smarty/plugins/function.html_options.php new file mode 100644 index 0000000..1b10653 --- /dev/null +++ b/src/functions/smarty/plugins/function.html_options.php @@ -0,0 +1,118 @@ + + * Name: html_options
    + * Input:
    + * - name (optional) - string default "select" + * - values (required if no options supplied) - array + * - options (required if no values supplied) - associative array + * - selected (optional) - string default not set + * - output (required if not options supplied) - array + * Purpose: Prints the list of ' . "\n"; + foreach ($values as $key => $value) { + $optgroup_html .= smarty_function_html_options_optoutput($key, $value, $selected); + } + $optgroup_html .= "\n"; + return $optgroup_html; +} + +/* vim: set expandtab: */ + +?> diff --git a/src/functions/smarty/plugins/function.html_radios.php b/src/functions/smarty/plugins/function.html_radios.php new file mode 100644 index 0000000..b80e9bc --- /dev/null +++ b/src/functions/smarty/plugins/function.html_radios.php @@ -0,0 +1,138 @@ + + * Type: function
    + * Name: html_radios
    + * Date: 24.Feb.2003
    + * Purpose: Prints out a list of radio input types
    + * Input:
    + * - name (optional) - string default "radio" + * - values (required) - array + * - options (optional) - associative array + * - checked (optional) - array default not set + * - separator (optional) - ie
    or   + * - output (optional) - without this one the buttons don't have names + * Examples: + *
    + * {html_radios values=$ids output=$names}
    + * {html_radios values=$ids name='box' separator='
    ' output=$names} + * {html_radios values=$ids checked=$checked separator='
    ' output=$names} + *
    + * @link http://smarty.php.net/manual/en/language.function.html.radios.php {html_radios} + * (Smarty online manual) + * @author Christopher Kvarme + * @author credits to Monte Ohrt + * @version 1.0 + * @param array + * @param Smarty + * @return string + * @uses smarty_function_escape_special_chars() + */ +function smarty_function_html_radios($params, &$smarty) +{ + require_once $smarty->_get_plugin_filepath('shared','escape_special_chars'); + + $name = 'radio'; + $values = null; + $options = null; + $selected = null; + $separator = ''; + $labels = true; + $output = null; + $extra = ''; + + foreach($params as $_key => $_val) { + switch($_key) { + case 'name': + case 'separator': + $$_key = (string)$_val; + break; + + case 'checked': + case 'selected': + if(is_array($_val)) { + $smarty->trigger_error('html_radios: the "' . $_key . '" attribute cannot be an array', E_USER_WARNING); + } else { + $selected = (string)$_val; + } + break; + + case 'labels': + $$_key = (bool)$_val; + break; + + case 'options': + $$_key = (array)$_val; + break; + + case 'values': + case 'output': + $$_key = array_values((array)$_val); + break; + + case 'radios': + $smarty->trigger_error('html_radios: the use of the "radios" attribute is deprecated, use "options" instead', E_USER_WARNING); + $options = (array)$_val; + break; + + + default: + if(!is_array($_val)) { + $extra .= ' '.$_key.'="'.smarty_function_escape_special_chars($_val).'"'; + } else { + $smarty->trigger_error("html_radios: extra attribute '$_key' cannot be an array", E_USER_NOTICE); + } + break; + } + } + + if (!isset($options) && !isset($values)) + return ''; /* raise error here? */ + + $_html_result = ''; + + if (isset($options) && is_array($options)) { + + foreach ((array)$options as $_key=>$_val) + $_html_result .= smarty_function_html_radios_output($name, $_key, $_val, $selected, $extra, $separator, $labels); + + } else { + + foreach ((array)$values as $_i=>$_key) { + $_val = isset($output[$_i]) ? $output[$_i] : ''; + $_html_result .= smarty_function_html_radios_output($name, $_key, $_val, $selected, $extra, $separator, $labels); + } + + } + + return $_html_result; + +} + +function smarty_function_html_radios_output($name, $value, $output, $selected, $extra, $separator, $labels) { + $_output = ''; + if ($labels) $_output .= ''; + $_output .= $separator . "\n"; + + return $_output; +} + +?> diff --git a/src/functions/smarty/plugins/function.html_select_date.php b/src/functions/smarty/plugins/function.html_select_date.php new file mode 100644 index 0000000..dd90e92 --- /dev/null +++ b/src/functions/smarty/plugins/function.html_select_date.php @@ -0,0 +1,243 @@ + + * Name: html_select_date
    + * Purpose: Prints the dropdowns for date selection. + * + * ChangeLog:
    + * - 1.0 initial release + * - 1.1 added support for +/- N syntax for begin + * and end year values. (Monte) + * - 1.2 added support for yyyy-mm-dd syntax for + * time value. (Jan Rosier) + * - 1.3 added support for choosing format for + * month values (Gary Loescher) + * - 1.3.1 added support for choosing format for + * day values (Marcus Bointon) + * @link http://smarty.php.net/manual/en/language.function.html.select.date.php {html_select_date} + * (Smarty online manual) + * @version 1.3 + * @author Andrei Zmievski + * @param array + * @param Smarty + * @return string + */ +function smarty_function_html_select_date($params, &$smarty) +{ + require_once $smarty->_get_plugin_filepath('shared','make_timestamp'); + require_once $smarty->_get_plugin_filepath('function','html_options'); + /* Default values. */ + $prefix = "Date_"; + $start_year = strftime("%Y"); + $end_year = $start_year; + $display_days = true; + $display_months = true; + $display_years = true; + $month_format = "%B"; + /* Write months as numbers by default GL */ + $month_value_format = "%m"; + $day_format = "%02d"; + /* Write day values using this format MB */ + $day_value_format = "%d"; + $year_as_text = false; + /* Display years in reverse order? Ie. 2000,1999,.... */ + $reverse_years = false; + /* Should the select boxes be part of an array when returned from PHP? + e.g. setting it to "birthday", would create "birthday[Day]", + "birthday[Month]" & "birthday[Year]". Can be combined with prefix */ + $field_array = null; + /* tags. + If not set, uses default dropdown. */ + $day_size = null; + $month_size = null; + $year_size = null; + /* Unparsed attributes common to *ALL* the tags. + An example might be in the template: all_extra ='class ="foo"'. */ + $all_extra = null; + /* Separate attributes for the tags. */ + $day_extra = null; + $month_extra = null; + $year_extra = null; + /* Order in which to display the fields. + "D" -> day, "M" -> month, "Y" -> year. */ + $field_order = 'MDY'; + /* String printed between the different fields. */ + $field_separator = "\n"; + $time = time(); + + + extract($params); + + // If $time is not in format yyyy-mm-dd + if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $time)) { + // then $time is empty or unix timestamp or mysql timestamp + // using smarty_make_timestamp to get an unix timestamp and + // strftime to make yyyy-mm-dd + $time = strftime('%Y-%m-%d', smarty_make_timestamp($time)); + } + // Now split this in pieces, which later can be used to set the select + $time = explode("-", $time); + + // make syntax "+N" or "-N" work with start_year and end_year + if (preg_match('!^(\+|\-)\s*(\d+)$!', $end_year, $match)) { + if ($match[1] == '+') { + $end_year = strftime('%Y') + $match[2]; + } else { + $end_year = strftime('%Y') - $match[2]; + } + } + if (preg_match('!^(\+|\-)\s*(\d+)$!', $start_year, $match)) { + if ($match[1] == '+') { + $start_year = strftime('%Y') + $match[2]; + } else { + $start_year = strftime('%Y') - $match[2]; + } + } + + $field_order = strtoupper($field_order); + + $html_result = $month_result = $day_result = $year_result = ""; + + if ($display_months) { + $month_names = array(); + $month_values = array(); + + for ($i = 1; $i <= 12; $i++) { + $month_names[] = strftime($month_format, mktime(0, 0, 0, $i, 1, 2000)); + $month_values[] = strftime($month_value_format, mktime(0, 0, 0, $i, 1, 2000)); + } + + $month_result .= ''; + } + + if ($display_days) { + $days = array(); + for ($i = 1; $i <= 31; $i++) { + $days[] = sprintf($day_format, $i); + $day_values[] = sprintf($day_value_format, $i); + } + + $day_result .= ''; + } + + if ($display_years) { + if (null !== $field_array){ + $year_name = $field_array . '[' . $prefix . 'Year]'; + } else { + $year_name = $prefix . 'Year'; + } + if ($year_as_text) { + $year_result .= ' $years, + 'values' => $years, + 'selected' => $time[0], + 'print_result' => false), + $smarty); + $year_result .= ''; + } + } + + // Loop thru the field_order field + for ($i = 0; $i <= 2; $i++){ + $c = substr($field_order, $i, 1); + switch ($c){ + case 'D': + $html_result .= $day_result; + break; + + case 'M': + $html_result .= $month_result; + break; + + case 'Y': + $html_result .= $year_result; + break; + } + // Add the field seperator + if($i != 2) { + $html_result .= $field_separator; + } + } + + return $html_result; +} + +/* vim: set expandtab: */ + +?> diff --git a/src/functions/smarty/plugins/function.html_select_time.php b/src/functions/smarty/plugins/function.html_select_time.php new file mode 100644 index 0000000..969c13e --- /dev/null +++ b/src/functions/smarty/plugins/function.html_select_time.php @@ -0,0 +1,163 @@ + + * Name: html_select_time
    + * Purpose: Prints the dropdowns for time selection + * @link http://smarty.php.net/manual/en/language.function.html.select.time.php {html_select_time} + * (Smarty online manual) + * @param array + * @param Smarty + * @return string + * @uses smarty_make_timestamp() + */ +function smarty_function_html_select_time($params, &$smarty) +{ + require_once $smarty->_get_plugin_filepath('shared','make_timestamp'); + require_once $smarty->_get_plugin_filepath('function','html_options'); + /* Default values. */ + $prefix = "Time_"; + $time = time(); + $display_hours = true; + $display_minutes = true; + $display_seconds = true; + $display_meridian = true; + $use_24_hours = true; + $minute_interval = 1; + $second_interval = 1; + /* Should the select boxes be part of an array when returned from PHP? + e.g. setting it to "birthday", would create "birthday[Hour]", + "birthday[Minute]", "birthday[Seconds]" & "birthday[Meridian]". + Can be combined with prefix. */ + $field_array = null; + $all_extra = null; + $hour_extra = null; + $minute_extra = null; + $second_extra = null; + $meridian_extra = null; + + extract($params); + + $time = smarty_make_timestamp($time); + + $html_result = ''; + + if ($display_hours) { + $hours = $use_24_hours ? range(0, 23) : range(1, 12); + $hour_fmt = $use_24_hours ? '%H' : '%I'; + for ($i = 0, $for_max = count($hours); $i < $for_max; $i++) + $hours[$i] = sprintf('%02d', $hours[$i]); + $html_result .= '\n"; + } + + if ($display_minutes) { + $all_minutes = range(0, 59); + for ($i = 0, $for_max = count($all_minutes); $i < $for_max; $i+= $minute_interval) + $minutes[] = sprintf('%02d', $all_minutes[$i]); + $selected = intval(floor(strftime('%M', $time) / $minute_interval) * $minute_interval); + $html_result .= '\n"; + } + + if ($display_seconds) { + $all_seconds = range(0, 59); + for ($i = 0, $for_max = count($all_seconds); $i < $for_max; $i+= $second_interval) + $seconds[] = sprintf('%02d', $all_seconds[$i]); + $selected = intval(floor(strftime('%S', $time) / $second_interval) * $second_interval); + $html_result .= '\n"; + } + + if ($display_meridian && !$use_24_hours) { + $html_result .= '\n"; + } + + return $html_result; +} + +/* vim: set expandtab: */ + +?> diff --git a/src/functions/smarty/plugins/function.html_table.php b/src/functions/smarty/plugins/function.html_table.php new file mode 100644 index 0000000..33be01a --- /dev/null +++ b/src/functions/smarty/plugins/function.html_table.php @@ -0,0 +1,113 @@ + + * Name: html_table
    + * Date: Feb 17, 2003
    + * Purpose: make an html table from an array of data
    + * Input:
    + * - loop = array to loop through + * - cols = number of columns + * - rows = number of rows + * - table_attr = table attributes + * - tr_attr = table row attributes (arrays are cycled) + * - td_attr = table cell attributes (arrays are cycled) + * - trailpad = value to pad trailing cells with + * - vdir = vertical direction (default: "down", means top-to-bottom) + * - hdir = horizontal direction (default: "right", means left-to-right) + * - inner = inner loop (default "cols": print $loop line by line, + * $loop will be printed column by column otherwise) + * + * + * Examples: + *
    + * {table loop=$data}
    + * {table loop=$data cols=4 tr_attr='"bgcolor=red"'}
    + * {table loop=$data cols=4 tr_attr=$colors}
    + * 
    + * @author Monte Ohrt + * @version 1.0 + * @link http://smarty.php.net/manual/en/language.function.html.table.php {html_table} + * (Smarty online manual) + * @param array + * @param Smarty + * @return string + */ +function smarty_function_html_table($params, &$smarty) +{ + $table_attr = 'border="1"'; + $tr_attr = ''; + $td_attr = ''; + $cols = 3; + $rows = 3; + $trailpad = ' '; + $vdir = 'down'; + $hdir = 'right'; + $inner = 'cols'; + + extract($params); + + if (!isset($loop)) { + $smarty->trigger_error("html_table: missing 'loop' parameter"); + return; + } + + $loop_count = count($loop); + if (empty($params['rows'])) { + /* no rows specified */ + $rows = ceil($loop_count/$cols); + } elseif (empty($params['cols'])) { + if (!empty($params['rows'])) { + /* no cols specified, but rows */ + $cols = ceil($loop_count/$rows); + } + } + + $output = "\n"; + + for ($r=0; $r<$rows; $r++) { + $output .= "\n"; + $rx = ($vdir == 'down') ? $r*$cols : ($rows-1-$r)*$cols; + + for ($c=0; $c<$cols; $c++) { + $x = ($hdir == 'right') ? $rx+$c : $rx+$cols-1-$c; + if ($inner!='cols') { + /* shuffle x to loop over rows*/ + $x = floor($x/$cols) + ($x%$cols)*$rows; + } + + if ($x<$loop_count) { + $output .= "" . $loop[$x] . "\n"; + } else { + $output .= "$trailpad\n"; + } + } + $output .= "\n"; + } + $output .= "
    \n"; + + return $output; +} + +function smarty_function_html_table_cycle($name, $var, $no) { + if(!is_array($var)) { + $ret = $var; + } else { + $ret = $var[$no % count($var)]; + } + + return ($ret) ? ' '.$ret : ''; +} + + +/* vim: set expandtab: */ + +?> diff --git a/src/functions/smarty/plugins/function.mailto.php b/src/functions/smarty/plugins/function.mailto.php new file mode 100644 index 0000000..f6e3de0 --- /dev/null +++ b/src/functions/smarty/plugins/function.mailto.php @@ -0,0 +1,140 @@ + + * Name: mailto
    + * Date: May 21, 2002 + * Purpose: automate mailto address link creation, and optionally + * encode them.
    + * Input:
    + * - address = e-mail address + * - text = (optional) text to display, default is address + * - encode = (optional) can be one of: + * * none : no encoding (default) + * * javascript : encode with javascript + * * hex : encode with hexidecimal (no javascript) + * - cc = (optional) address(es) to carbon copy + * - bcc = (optional) address(es) to blind carbon copy + * - subject = (optional) e-mail subject + * - newsgroups = (optional) newsgroup(s) to post to + * - followupto = (optional) address(es) to follow up to + * - extra = (optional) extra tags for the href link + * + * Examples: + *
    + * {mailto address="me@domain.com"}
    + * {mailto address="me@domain.com" encode="javascript"}
    + * {mailto address="me@domain.com" encode="hex"}
    + * {mailto address="me@domain.com" subject="Hello to you!"}
    + * {mailto address="me@domain.com" cc="you@domain.com,they@domain.com"}
    + * {mailto address="me@domain.com" extra='class="mailto"'}
    + * 
    + * @link http://smarty.php.net/manual/en/language.function.mailto.php {mailto} + * (Smarty online manual) + * @version 1.2 + * @author Monte Ohrt + * @author credits to Jason Sweat (added cc, bcc and subject functionality) + * @param array + * @param Smarty + * @return string + */ +function smarty_function_mailto($params, &$smarty) +{ + $extra = ''; + extract($params); + + if (empty($address)) { + $smarty->trigger_error("mailto: missing 'address' parameter"); + return; + } + + if (empty($text)) { + $text = $address; + } + + // netscape and mozilla do not decode %40 (@) in BCC field (bug?) + // so, don't encode it. + + $mail_parms = array(); + if (!empty($cc)) { + $mail_parms[] = 'cc='.str_replace('%40','@',rawurlencode($cc)); + } + + if (!empty($bcc)) { + $mail_parms[] = 'bcc='.str_replace('%40','@',rawurlencode($bcc)); + } + + if (!empty($subject)) { + $mail_parms[] = 'subject='.rawurlencode($subject); + } + + if (!empty($newsgroups)) { + $mail_parms[] = 'newsgroups='.rawurlencode($newsgroups); + } + + if (!empty($followupto)) { + $mail_parms[] = 'followupto='.str_replace('%40','@',rawurlencode($followupto)); + } + + $mail_parm_vals = ''; + for ($i=0; $itrigger_error("mailto: 'encode' parameter must be none, javascript or hex"); + return; + } + + if ($encode == 'javascript' ) { + $string = 'document.write(\''.$text.'\');'; + + for ($x=0; $x < strlen($string); $x++) { + $js_encode .= '%' . bin2hex($string[$x]); + } + + return ''; + + } elseif ($encode == 'hex') { + + preg_match('!^(.*)(\?.*)$!',$address,$match); + if(!empty($match[2])) { + $smarty->trigger_error("mailto: hex encoding does not work with extra attributes. Try javascript."); + return; + } + for ($x=0; $x < strlen($address); $x++) { + if(preg_match('!\w!',$address[$x])) { + $address_encode .= '%' . bin2hex($address[$x]); + } else { + $address_encode .= $address[$x]; + } + } + for ($x=0; $x < strlen($text); $x++) { + $text_encode .= '&#x' . bin2hex($text[$x]).';'; + } + + return ''.$text_encode.''; + + } else { + // no encoding + return ''.$text.''; + + } + +} + +/* vim: set expandtab: */ + +?> diff --git a/src/functions/smarty/plugins/function.math.php b/src/functions/smarty/plugins/function.math.php new file mode 100644 index 0000000..c080d4d --- /dev/null +++ b/src/functions/smarty/plugins/function.math.php @@ -0,0 +1,82 @@ + + * Name: math
    + * Purpose: handle math computations in template
    + * @link http://smarty.php.net/manual/en/language.function.math.php {math} + * (Smarty online manual) + * @param array + * @param Smarty + * @return string + */ +function smarty_function_math($params, &$smarty) +{ + // be sure equation parameter is present + if (empty($params['equation'])) { + $smarty->trigger_error("math: missing equation parameter"); + return; + } + + $equation = $params['equation']; + + // make sure parenthesis are balanced + if (substr_count($equation,"(") != substr_count($equation,")")) { + $smarty->trigger_error("math: unbalanced parenthesis"); + return; + } + + // match all vars in equation, make sure all are passed + preg_match_all("!\!(0x)([a-zA-Z][a-zA-Z0-9_]*)!",$equation, $match); + $allowed_funcs = array('int','abs','ceil','cos','exp','floor','log','log10', + 'max','min','pi','pow','rand','round','sin','sqrt','srand','tan'); + foreach($match[2] as $curr_var) { + if (!in_array($curr_var,array_keys($params)) && !in_array($curr_var, $allowed_funcs)) { + $smarty->trigger_error("math: parameter $curr_var not passed as argument"); + return; + } + } + + foreach($params as $key => $val) { + if ($key != "equation" && $key != "format" && $key != "assign") { + // make sure value is not empty + if (strlen($val)==0) { + $smarty->trigger_error("math: parameter $key is empty"); + return; + } + if (!is_numeric($val)) { + $smarty->trigger_error("math: parameter $key: is not numeric"); + return; + } + $equation = preg_replace("/\b$key\b/",$val, $equation); + } + } + + eval("\$smarty_math_result = ".$equation.";"); + + if (empty($params['format'])) { + if (empty($params['assign'])) { + return $smarty_math_result; + } else { + $smarty->assign($params['assign'],$smarty_math_result); + } + } else { + if (empty($params['assign'])){ + printf($params['format'],$smarty_math_result); + } else { + $smarty->assign($params['assign'],sprintf($params['format'],$smarty_math_result)); + } + } +} + +/* vim: set expandtab: */ + +?> diff --git a/src/functions/smarty/plugins/function.popup.php b/src/functions/smarty/plugins/function.popup.php new file mode 100644 index 0000000..d1030a7 --- /dev/null +++ b/src/functions/smarty/plugins/function.popup.php @@ -0,0 +1,87 @@ + + * Name: popup
    + * Purpose: make text pop up in windows via overlib + * @link http://smarty.php.net/manual/en/language.function.popup.php {popup} + * (Smarty online manual) + * @param array + * @param Smarty + * @return string + */ +function smarty_function_popup($params, &$smarty) +{ + extract($params); + + if (empty($text) && !isset($inarray) && empty($function)) { + $smarty->trigger_error("overlib: attribute 'text' or 'inarray' or 'function' required"); + return false; + } + + if (empty($trigger)) { $trigger = "onmouseover"; } + + $retval = $trigger . '="return overlib(\''.preg_replace(array("!'!","![\r\n]!"),array("\'",'\r'),$text).'\''; + if ($sticky) { $retval .= ",STICKY"; } + if (!empty($caption)) { $retval .= ",CAPTION,'".str_replace("'","\'",$caption)."'"; } + if (!empty($fgcolor)) { $retval .= ",FGCOLOR,'$fgcolor'"; } + if (!empty($bgcolor)) { $retval .= ",BGCOLOR,'$bgcolor'"; } + if (!empty($textcolor)) { $retval .= ",TEXTCOLOR,'$textcolor'"; } + if (!empty($capcolor)) { $retval .= ",CAPCOLOR,'$capcolor'"; } + if (!empty($closecolor)) { $retval .= ",CLOSECOLOR,'$closecolor'"; } + if (!empty($textfont)) { $retval .= ",TEXTFONT,'$textfont'"; } + if (!empty($captionfont)) { $retval .= ",CAPTIONFONT,'$captionfont'"; } + if (!empty($closefont)) { $retval .= ",CLOSEFONT,'$closefont'"; } + if (!empty($textsize)) { $retval .= ",TEXTSIZE,$textsize"; } + if (!empty($captionsize)) { $retval .= ",CAPTIONSIZE,$captionsize"; } + if (!empty($closesize)) { $retval .= ",CLOSESIZE,$closesize"; } + if (!empty($width)) { $retval .= ",WIDTH,$width"; } + if (!empty($height)) { $retval .= ",HEIGHT,$height"; } + if (!empty($left)) { $retval .= ",LEFT"; } + if (!empty($right)) { $retval .= ",RIGHT"; } + if (!empty($center)) { $retval .= ",CENTER"; } + if (!empty($above)) { $retval .= ",ABOVE"; } + if (!empty($below)) { $retval .= ",BELOW"; } + if (isset($border)) { $retval .= ",BORDER,$border"; } + if (isset($offsetx)) { $retval .= ",OFFSETX,$offsetx"; } + if (isset($offsety)) { $retval .= ",OFFSETY,$offsety"; } + if (!empty($fgbackground)) { $retval .= ",FGBACKGROUND,'$fgbackground'"; } + if (!empty($bgbackground)) { $retval .= ",BGBACKGROUND,'$bgbackground'"; } + if (!empty($closetext)) { $retval .= ",CLOSETEXT,'".str_replace("'","\'",$closetext)."'"; } + if (!empty($noclose)) { $retval .= ",NOCLOSE"; } + if (!empty($status)) { $retval .= ",STATUS,'".str_replace("'","\'",$status)."'"; } + if (!empty($autostatus)) { $retval .= ",AUTOSTATUS"; } + if (!empty($autostatuscap)) { $retval .= ",AUTOSTATUSCAP"; } + if (isset($inarray)) { $retval .= ",INARRAY,'$inarray'"; } + if (isset($caparray)) { $retval .= ",CAPARRAY,'$caparray'"; } + if (!empty($capicon)) { $retval .= ",CAPICON,'$capicon'"; } + if (!empty($snapx)) { $retval .= ",SNAPX,$snapx"; } + if (!empty($snapy)) { $retval .= ",SNAPY,$snapy"; } + if (isset($fixx)) { $retval .= ",FIXX,$fixx"; } + if (isset($fixy)) { $retval .= ",FIXY,$fixy"; } + if (!empty($background)) { $retval .= ",BACKGROUND,'$background'"; } + if (!empty($padx)) { $retval .= ",PADX,$padx"; } + if (!empty($pady)) { $retval .= ",PADY,$pady"; } + if (!empty($fullhtml)) { $retval .= ",FULLHTML"; } + if (!empty($frame)) { $retval .= ",FRAME,'$frame'"; } + if (isset($timeout)) { $retval .= ",TIMEOUT,$timeout"; } + if (!empty($function)) { $retval .= ",FUNCTION,'$function'"; } + if (isset($delay)) { $retval .= ",DELAY,$delay"; } + if (!empty($hauto)) { $retval .= ",HAUTO"; } + if (!empty($vauto)) { $retval .= ",VAUTO"; } + $retval .= ');" onmouseout="nd();"'; + + return $retval; +} + +/* vim: set expandtab: */ + +?> diff --git a/src/functions/smarty/plugins/function.popup_init.php b/src/functions/smarty/plugins/function.popup_init.php new file mode 100644 index 0000000..d9b42bd --- /dev/null +++ b/src/functions/smarty/plugins/function.popup_init.php @@ -0,0 +1,39 @@ + + * Name: popup_init
    + * Purpose: initialize overlib + * @link http://smarty.php.net/manual/en/language.function.popup.init.php {popup_init} + * (Smarty online manual) + * @param array + * @param Smarty + * @return string + */ +function smarty_function_popup_init($params, &$smarty) +{ + $zindex = 1000; + + if (!empty($params['zindex'])) { + $zindex = $params['zindex']; + } + + if (!empty($params['src'])) { + return '' . "\n" + . '' . "\n"; + } else { + $smarty->trigger_error("popup_init: missing src parameter"); + } +} + +/* vim: set expandtab: */ + +?> diff --git a/src/functions/smarty/plugins/modifier.capitalize.php b/src/functions/smarty/plugins/modifier.capitalize.php new file mode 100644 index 0000000..41d63ed --- /dev/null +++ b/src/functions/smarty/plugins/modifier.capitalize.php @@ -0,0 +1,25 @@ + + * Name: capitalize
    + * Purpose: capitalize words in the string + * @link http://smarty.php.net/manual/en/language.modifiers.php#LANGUAGE.MODIFIER.CAPITALIZE + * capitalize (Smarty online manual) + * @param string + * @return string + */ +function smarty_modifier_capitalize($string) +{ + return ucwords($string); +} + +?> diff --git a/src/functions/smarty/plugins/modifier.cat.php b/src/functions/smarty/plugins/modifier.cat.php new file mode 100644 index 0000000..8dc7324 --- /dev/null +++ b/src/functions/smarty/plugins/modifier.cat.php @@ -0,0 +1,33 @@ + + * Name: cat
    + * Date: Feb 24, 2003 + * Purpose: catenate a value to a variable + * Input: string to catenate + * Example: {$var|cat:"foo"} + * @link http://smarty.php.net/manual/en/language.modifier.cat.php cat + * (Smarty online manual) + * @author Monte Ohrt + * @version 1.0 + * @param string + * @param string + * @return string + */ +function smarty_modifier_cat($string, $cat) +{ + return $string . $cat; +} + +/* vim: set expandtab: */ + +?> diff --git a/src/functions/smarty/plugins/modifier.count_characters.php b/src/functions/smarty/plugins/modifier.count_characters.php new file mode 100644 index 0000000..49ce655 --- /dev/null +++ b/src/functions/smarty/plugins/modifier.count_characters.php @@ -0,0 +1,31 @@ + + * Name: count_characteres
    + * Purpose: count the number of characters in a text + * @link http://smarty.php.net/manual/en/language.modifier.count.characters.php + * count_characters (Smarty online manual) + * @param string + * @param boolean include whitespace in the character count + * @return integer + */ +function smarty_modifier_count_characters($string, $include_spaces = false) +{ + if ($include_spaces) + return(strlen($string)); + + return preg_match_all("/[^\s]/",$string, $match); +} + +/* vim: set expandtab: */ + +?> diff --git a/src/functions/smarty/plugins/modifier.count_paragraphs.php b/src/functions/smarty/plugins/modifier.count_paragraphs.php new file mode 100644 index 0000000..6a9833c --- /dev/null +++ b/src/functions/smarty/plugins/modifier.count_paragraphs.php @@ -0,0 +1,28 @@ + + * Name: count_paragraphs
    + * Purpose: count the number of paragraphs in a text + * @link http://smarty.php.net/manual/en/language.modifier.count.paragraphs.php + * count_paragraphs (Smarty online manual) + * @param string + * @return integer + */ +function smarty_modifier_count_paragraphs($string) +{ + // count \r or \n characters + return count(preg_split('/[\r\n]+/', $string)); +} + +/* vim: set expandtab: */ + +?> diff --git a/src/functions/smarty/plugins/modifier.count_sentences.php b/src/functions/smarty/plugins/modifier.count_sentences.php new file mode 100644 index 0000000..0c210f0 --- /dev/null +++ b/src/functions/smarty/plugins/modifier.count_sentences.php @@ -0,0 +1,28 @@ + + * Name: count_sentences + * Purpose: count the number of sentences in a text + * @link http://smarty.php.net/manual/en/language.modifier.count.paragraphs.php + * count_sentences (Smarty online manual) + * @param string + * @return integer + */ +function smarty_modifier_count_sentences($string) +{ + // find periods with a word before but not after. + return preg_match_all('/[^\s]\.(?!\w)/', $string, $match); +} + +/* vim: set expandtab: */ + +?> diff --git a/src/functions/smarty/plugins/modifier.count_words.php b/src/functions/smarty/plugins/modifier.count_words.php new file mode 100644 index 0000000..42c8a74 --- /dev/null +++ b/src/functions/smarty/plugins/modifier.count_words.php @@ -0,0 +1,32 @@ + + * Name: count_words
    + * Purpose: count the number of words in a text + * @link http://smarty.php.net/manual/en/language.modifier.count.words.php + * count_words (Smarty online manual) + * @param string + * @return integer + */ +function smarty_modifier_count_words($string) +{ + // split text by ' ',\r,\n,\f,\t + $split_array = preg_split('/\s+/',$string); + // count matches that contain alphanumerics + $word_count = preg_grep('/[a-zA-Z0-9\\x80-\\xff]/', $split_array); + + return count($word_count); +} + +/* vim: set expandtab: */ + +?> diff --git a/src/functions/smarty/plugins/modifier.date_format.php b/src/functions/smarty/plugins/modifier.date_format.php new file mode 100644 index 0000000..dbe26a5 --- /dev/null +++ b/src/functions/smarty/plugins/modifier.date_format.php @@ -0,0 +1,43 @@ +_get_plugin_filepath('shared','make_timestamp'); +/** + * Smarty date_format modifier plugin + * + * Type: modifier
    + * Name: date_format
    + * Purpose: format datestamps via strftime
    + * Input:
    + * - string: input date string + * - format: strftime format for output + * - default_date: default date if $string is empty + * @link http://smarty.php.net/manual/en/language.modifier.date.format.php + * date_format (Smarty online manual) + * @param string + * @param string + * @param string + * @return string|void + * @uses smarty_make_timestamp() + */ +function smarty_modifier_date_format($string, $format="%b %e, %Y", $default_date=null) +{ + if($string != '') { + return strftime($format, smarty_make_timestamp($string)); + } elseif (isset($default_date) && $default_date != '') { + return strftime($format, smarty_make_timestamp($default_date)); + } else { + return; + } +} + +/* vim: set expandtab: */ + +?> diff --git a/src/functions/smarty/plugins/modifier.debug_print_var.php b/src/functions/smarty/plugins/modifier.debug_print_var.php new file mode 100644 index 0000000..3528311 --- /dev/null +++ b/src/functions/smarty/plugins/modifier.debug_print_var.php @@ -0,0 +1,57 @@ + + * Name: debug_print_var
    + * Purpose: formats variable contents for display in the console + * @link http://smarty.php.net/manual/en/language.modifier.debug.print.var.php + * debug_print_var (Smarty online manual) + * @param array|object + * @param integer + * @param integer + * @return string + */ +function smarty_modifier_debug_print_var($var, $depth = 0, $length = 40) +{ + $_replace = array("\n"=>'\n', "\r"=>'\r', "\t"=>'\t'); + if (is_array($var)) { + $results = "Array (".count($var).")"; + foreach ($var as $curr_key => $curr_val) { + $return = smarty_modifier_debug_print_var($curr_val, $depth+1, $length); + $results .= "
    ".str_repeat(' ', $depth*2)."".strtr($curr_key, $_replace)." => $return"; + } + return $results; + } else if (is_object($var)) { + $object_vars = get_object_vars($var); + $results = "".get_class($var)." Object (".count($object_vars).")"; + foreach ($object_vars as $curr_key => $curr_val) { + $return = smarty_modifier_debug_print_var($curr_val, $depth+1, $length); + $results .= "
    ".str_repeat(' ', $depth*2)."$curr_key => $return"; + } + return $results; + } else { + if (empty($var) && $var != "0") { + return 'empty'; + } + if (strlen($var) > $length ) { + $results = substr($var, 0, $length-3).'...'; + } else { + $results = $var; + } + $results = htmlspecialchars($results); + $results = strtr($results, $_replace); + return $results; + } +} + +/* vim: set expandtab: */ + +?> diff --git a/src/functions/smarty/plugins/modifier.default.php b/src/functions/smarty/plugins/modifier.default.php new file mode 100644 index 0000000..8268e39 --- /dev/null +++ b/src/functions/smarty/plugins/modifier.default.php @@ -0,0 +1,31 @@ + + * Name: default
    + * Purpose: designate default value for empty variables + * @link http://smarty.php.net/manual/en/language.modifier.default.php + * default (Smarty online manual) + * @param string + * @param string + * @return string + */ +function smarty_modifier_default($string, $default = '') +{ + if (!isset($string) || $string === '') + return $default; + else + return $string; +} + +/* vim: set expandtab: */ + +?> diff --git a/src/functions/smarty/plugins/modifier.escape.php b/src/functions/smarty/plugins/modifier.escape.php new file mode 100644 index 0000000..f9d0eed --- /dev/null +++ b/src/functions/smarty/plugins/modifier.escape.php @@ -0,0 +1,63 @@ + + * Name: escape
    + * Purpose: Escape the string according to escapement type + * @link http://smarty.php.net/manual/en/language.modifier.escape.php + * escape (Smarty online manual) + * @param string + * @param html|htmlall|url|quotes|hex|hexentity|javascript + * @return string + */ +function smarty_modifier_escape($string, $esc_type = 'html') +{ + switch ($esc_type) { + case 'html': + return htmlspecialchars($string, ENT_QUOTES); + + case 'htmlall': + return htmlentities($string, ENT_QUOTES); + + case 'url': + return urlencode($string); + + case 'quotes': + // escape unescaped single quotes + return preg_replace("%(?'\\\\',"'"=>"\\'",'"'=>'\\"',"\r"=>'\\r',"\n"=>'\\n')); + + default: + return $string; + } +} + +/* vim: set expandtab: */ + +?> diff --git a/src/functions/smarty/plugins/modifier.indent.php b/src/functions/smarty/plugins/modifier.indent.php new file mode 100644 index 0000000..552c3e1 --- /dev/null +++ b/src/functions/smarty/plugins/modifier.indent.php @@ -0,0 +1,27 @@ + + * Name: indent
    + * Purpose: indent lines of text + * @link http://smarty.php.net/manual/en/language.modifier.indent.php + * indent (Smarty online manual) + * @param string + * @param integer + * @param string + * @return string + */ +function smarty_modifier_indent($string,$chars=4,$char=" ") +{ + return preg_replace('!^!m',str_repeat($char,$chars),$string); +} + +?> diff --git a/src/functions/smarty/plugins/modifier.lower.php b/src/functions/smarty/plugins/modifier.lower.php new file mode 100644 index 0000000..ee37423 --- /dev/null +++ b/src/functions/smarty/plugins/modifier.lower.php @@ -0,0 +1,25 @@ + + * Name: lower
    + * Purpose: convert string to lowercase + * @link http://smarty.php.net/manual/en/language.modifier.lower.php + * lower (Smarty online manual) + * @param string + * @return string + */ +function smarty_modifier_lower($string) +{ + return strtolower($string); +} + +?> diff --git a/src/functions/smarty/plugins/modifier.nl2br.php b/src/functions/smarty/plugins/modifier.nl2br.php new file mode 100644 index 0000000..5a9b744 --- /dev/null +++ b/src/functions/smarty/plugins/modifier.nl2br.php @@ -0,0 +1,35 @@ + + * Name: nl2br
    + * Date: Feb 26, 2003 + * Purpose: convert \r\n, \r or \n to <
    > + * Input:
    + * - contents = contents to replace + * - preceed_test = if true, includes preceeding break tags + * in replacement + * Example: {$text|nl2br} + * @link http://smarty.php.net/manual/en/language.modifier.nl2br.php + * nl2br (Smarty online manual) + * @version 1.0 + * @author Monte Ohrt + * @param string + * @return string + */ +function smarty_modifier_nl2br($string) +{ + return nl2br($string); +} + +/* vim: set expandtab: */ + +?> diff --git a/src/functions/smarty/plugins/modifier.regex_replace.php b/src/functions/smarty/plugins/modifier.regex_replace.php new file mode 100644 index 0000000..b9cc865 --- /dev/null +++ b/src/functions/smarty/plugins/modifier.regex_replace.php @@ -0,0 +1,29 @@ + + * Name: regex_replace
    + * Purpose: regular epxression search/replace + * @link http://smarty.php.net/manual/en/language.modifier.regex.replace.php + * regex_replace (Smarty online manual) + * @param string + * @param string|array + * @param string|array + * @return string + */ +function smarty_modifier_regex_replace($string, $search, $replace) +{ + return preg_replace($search, $replace, $string); +} + +/* vim: set expandtab: */ + +?> diff --git a/src/functions/smarty/plugins/modifier.replace.php b/src/functions/smarty/plugins/modifier.replace.php new file mode 100644 index 0000000..2a43515 --- /dev/null +++ b/src/functions/smarty/plugins/modifier.replace.php @@ -0,0 +1,29 @@ + + * Name: replace
    + * Purpose: simple search/replace + * @link http://smarty.php.net/manual/en/language.modifier.replace.php + * replace (Smarty online manual) + * @param string + * @param string + * @param string + * @return string + */ +function smarty_modifier_replace($string, $search, $replace) +{ + return str_replace($search, $replace, $string); +} + +/* vim: set expandtab: */ + +?> diff --git a/src/functions/smarty/plugins/modifier.spacify.php b/src/functions/smarty/plugins/modifier.spacify.php new file mode 100644 index 0000000..dad057f --- /dev/null +++ b/src/functions/smarty/plugins/modifier.spacify.php @@ -0,0 +1,29 @@ + + * Name: spacify
    + * Purpose: add spaces between characters in a string + * @link http://smarty.php.net/manual/en/language.modifier.spacify.php + * spacify (Smarty online manual) + * @param string + * @param string + * @return string + */ +function smarty_modifier_spacify($string, $spacify_char = ' ') +{ + return implode($spacify_char, + preg_split('//', $string, -1, PREG_SPLIT_NO_EMPTY)); +} + +/* vim: set expandtab: */ + +?> diff --git a/src/functions/smarty/plugins/modifier.string_format.php b/src/functions/smarty/plugins/modifier.string_format.php new file mode 100644 index 0000000..efd6215 --- /dev/null +++ b/src/functions/smarty/plugins/modifier.string_format.php @@ -0,0 +1,28 @@ + + * Name: string_format
    + * Purpose: format strings via sprintf + * @link http://smarty.php.net/manual/en/language.modifier.string.format.php + * string_format (Smarty online manual) + * @param string + * @param string + * @return string + */ +function smarty_modifier_string_format($string, $format) +{ + return sprintf($format, $string); +} + +/* vim: set expandtab: */ + +?> diff --git a/src/functions/smarty/plugins/modifier.strip.php b/src/functions/smarty/plugins/modifier.strip.php new file mode 100644 index 0000000..0db2f8a --- /dev/null +++ b/src/functions/smarty/plugins/modifier.strip.php @@ -0,0 +1,33 @@ + + * Name: strip
    + * Purpose: Replace all repeated spaces, newlines, tabs + * with a single space or supplied replacement string.
    + * Example: {$var|strip} {$var|strip:" "} + * Date: September 25th, 2002 + * @link http://smarty.php.net/manual/en/language.modifier.strip.php + * strip (Smarty online manual) + * @author Monte Ohrt + * @version 1.0 + * @param string + * @param string + * @return string + */ +function smarty_modifier_strip($text, $replace = ' ') +{ + return preg_replace('!\s+!', $replace, $text); +} + +/* vim: set expandtab: */ + +?> diff --git a/src/functions/smarty/plugins/modifier.strip_tags.php b/src/functions/smarty/plugins/modifier.strip_tags.php new file mode 100644 index 0000000..45f1ec1 --- /dev/null +++ b/src/functions/smarty/plugins/modifier.strip_tags.php @@ -0,0 +1,31 @@ + + * Name: strip_tags
    + * Purpose: strip html tags from text + * @link http://smarty.php.net/manual/en/language.modifier.strip.tags.php + * strip_tags (Smarty online manual) + * @param string + * @param boolean + * @return string + */ +function smarty_modifier_strip_tags($string, $replace_with_space = true) +{ + if ($replace_with_space) + return preg_replace('!<[^>]*?>!', ' ', $string); + else + return strip_tags($string); +} + +/* vim: set expandtab: */ + +?> diff --git a/src/functions/smarty/plugins/modifier.truncate.php b/src/functions/smarty/plugins/modifier.truncate.php new file mode 100644 index 0000000..c82b14a --- /dev/null +++ b/src/functions/smarty/plugins/modifier.truncate.php @@ -0,0 +1,43 @@ + + * Name: truncate
    + * Purpose: Truncate a string to a certain length if necessary, + * optionally splitting in the middle of a word, and + * appending the $etc string. + * @link http://smarty.php.net/manual/en/language.modifier.truncate.php + * truncate (Smarty online manual) + * @param string + * @param integer + * @param string + * @param boolean + * @return string + */ +function smarty_modifier_truncate($string, $length = 80, $etc = '...', + $break_words = false) +{ + if ($length == 0) + return ''; + + if (strlen($string) > $length) { + $length -= strlen($etc); + if (!$break_words) + $string = preg_replace('/\s+?(\S+)?$/', '', substr($string, 0, $length+1)); + + return substr($string, 0, $length).$etc; + } else + return $string; +} + +/* vim: set expandtab: */ + +?> diff --git a/src/functions/smarty/plugins/modifier.upper.php b/src/functions/smarty/plugins/modifier.upper.php new file mode 100644 index 0000000..9d9ef35 --- /dev/null +++ b/src/functions/smarty/plugins/modifier.upper.php @@ -0,0 +1,25 @@ + + * Name: upper
    + * Purpose: convert string to uppercase + * @link http://smarty.php.net/manual/en/language.modifier.upper.php + * upper (Smarty online manual) + * @param string + * @return string + */ +function smarty_modifier_upper($string) +{ + return strtoupper($string); +} + +?> diff --git a/src/functions/smarty/plugins/modifier.wordwrap.php b/src/functions/smarty/plugins/modifier.wordwrap.php new file mode 100644 index 0000000..55b4a1d --- /dev/null +++ b/src/functions/smarty/plugins/modifier.wordwrap.php @@ -0,0 +1,28 @@ + + * Name: wordwrap
    + * Purpose: wrap a string of text at a given length + * @link http://smarty.php.net/manual/en/language.modifier.wordwrap.php + * wordwrap (Smarty online manual) + * @param string + * @param integer + * @param string + * @param boolean + * @return string + */ +function smarty_modifier_wordwrap($string,$length=80,$break="\n",$cut=false) +{ + return wordwrap($string,$length,$break,$cut); +} + +?> diff --git a/src/functions/smarty/plugins/outputfilter.trimwhitespace.php b/src/functions/smarty/plugins/outputfilter.trimwhitespace.php new file mode 100644 index 0000000..e82acc1 --- /dev/null +++ b/src/functions/smarty/plugins/outputfilter.trimwhitespace.php @@ -0,0 +1,75 @@ + + * Type: outputfilter
    + * Name: trimwhitespace
    + * Date: Jan 25, 2003
    + * Purpose: trim leading white space and blank lines from + * template source after it gets interpreted, cleaning + * up code and saving bandwidth. Does not affect + * <
    >
    and blocks.
    + * Install: Drop into the plugin directory, call + * $smarty->load_filter('output','trimwhitespace'); + * from application. + * @author Monte Ohrt + * @author Contributions from Lars Noschinski + * @version 1.3 + * @param string + * @param Smarty + */ + function smarty_outputfilter_trimwhitespace($source, &$smarty) + { + // Pull out the script blocks + preg_match_all("!]+>.*?!is", $source, $match); + $_script_blocks = $match[0]; + $source = preg_replace("!]+>.*?!is", + '@@@SMARTY:TRIM:SCRIPT@@@', $source); + + // Pull out the pre blocks + preg_match_all("!
    .*?
    !is", $source, $match); + $_pre_blocks = $match[0]; + $source = preg_replace("!
    .*?
    !is", + '@@@SMARTY:TRIM:PRE@@@', $source); + + // Pull out the textarea blocks + preg_match_all("!]+>.*?!is", $source, $match); + $_textarea_blocks = $match[0]; + $source = preg_replace("!]+>.*?!is", + '@@@SMARTY:TRIM:TEXTAREA@@@', $source); + + // remove all leading spaces, tabs and carriage returns NOT + // preceeded by a php close tag. + $source = trim(preg_replace('/((?)\n)[\s]+/m', '\1', $source)); + + // replace script blocks + smarty_outputfilter_trimwhitespace_replace("@@@SMARTY:TRIM:SCRIPT@@@",$_script_blocks, $source); + + // replace pre blocks + smarty_outputfilter_trimwhitespace_replace("@@@SMARTY:TRIM:PRE@@@",$_pre_blocks, $source); + + // replace textarea blocks + smarty_outputfilter_trimwhitespace_replace("@@@SMARTY:TRIM:TEXTAREA@@@",$_textarea_blocks, $source); + + return $source; + } + +function smarty_outputfilter_trimwhitespace_replace($search_str, $replace, &$subject) { + $_len = strlen($search_str); + $_pos = 0; + for ($_i=0, $_count=count($replace); $_i<$_count; $_i++) + if (($_pos=strpos($subject, $search_str, $_pos))!==false) + $subject = substr_replace($subject, $replace[$_i], $_pos, $_len); + else + break; + +} + +?> diff --git a/src/functions/smarty/plugins/shared.escape_special_chars.php b/src/functions/smarty/plugins/shared.escape_special_chars.php new file mode 100644 index 0000000..090ee9c --- /dev/null +++ b/src/functions/smarty/plugins/shared.escape_special_chars.php @@ -0,0 +1,30 @@ + + * Purpose: used by other smarty functions to escape + * special chars except for already escaped ones + * @param string + * @return string + */ +function smarty_function_escape_special_chars($string) +{ + if(!is_array($string)) { + $string = preg_replace('!&(#?\w+);!', '%%%SMARTY_START%%%\\1%%%SMARTY_END%%%', $string); + $string = htmlspecialchars($string); + $string = str_replace(array('%%%SMARTY_START%%%','%%%SMARTY_END%%%'), array('&',';'), $string); + } + return $string; +} + +/* vim: set expandtab: */ + +?> diff --git a/src/functions/smarty/plugins/shared.make_timestamp.php b/src/functions/smarty/plugins/shared.make_timestamp.php new file mode 100644 index 0000000..acdd777 --- /dev/null +++ b/src/functions/smarty/plugins/shared.make_timestamp.php @@ -0,0 +1,43 @@ + + * Purpose: used by other smarty functions to make a timestamp + * from a string. + * @param string + * @return string + */ +function smarty_make_timestamp($string) +{ + if(empty($string)) { + $string = "now"; + } + $time = strtotime($string); + if (is_numeric($time) && $time != -1) + return $time; + + // is mysql timestamp format of YYYYMMDDHHMMSS? + if (preg_match('/^\d{14}$/', $string)) { + $time = mktime(substr($string,8,2),substr($string,10,2),substr($string,12,2), + substr($string,4,2),substr($string,6,2),substr($string,0,4)); + + return $time; + } + + // couldn't recognize it, try to return a time + $time = (int) $string; + if ($time > 0) + return $time; + else + return time(); +} + +/* vim: set expandtab: */ + +?> diff --git a/src/functions/takscreen.class.php b/src/functions/takscreen.class.php new file mode 100644 index 0000000..603363c --- /dev/null +++ b/src/functions/takscreen.class.php @@ -0,0 +1,1999 @@ +action]) { + eval("\$this->".$functions[$this->action].";"); + } + #default + $this->Incoming_list(); + } + ############################################################################# + function _match_atter($gala,$pos,$line,$messages,$errors) { + $user_atterlist = fleetstatus_get_bytarget($gala,$pos,1); + $insert = array(); + if(preg_match_all("/(\d{1,4}):(\d{1,2})(.*?)
    /ism",$line[8],$tak_atterlist,PREG_SET_ORDER)) { + if(count($tak_atterlist)){ + $tak_timelist = parse_time($line[9]); + #atterliste + for($j=0;$j < count($tak_atterlist);$j++){ + unset($atter); + $tak_eta = $tak_timelist[$j]; + if($tak_eta == "error") {$errors[] = "atter (".$tak_atterlist[$j][1].":".$tak_atterlist[$j][2].") zeit nicht erkannt";continue;} + #5 ticks im orbit + if ($tak_eta == 0) { + $tak_eta_low = -75; + $tak_eta_high = 0; + } else { + #toleranz von einem tick + $tak_eta_low = $tak_eta - 14; + $tak_eta_high = $tak_eta + 14; + } + #passenden Atter finden + for($k=0;$k < count($user_atterlist);$k++){ + $eta = floor(($user_atterlist[$k]['arrival'] - time())/60); + if( $user_atterlist[$k]['gala'] == $tak_atterlist[$j][1] && + $user_atterlist[$k]['pos'] == $tak_atterlist[$j][2] && + !($user_atterlist[$k]['checked']) && + $eta > $tak_eta_low && + $eta < $tak_eta_high + ) { + #passenden atter gefunden + $atter = &$user_atterlist[$k]; + break; + } + } + if (isset($atter)) { + #atter matched + $atter['checked'] = true; + } else { + $insert[] = array( + "gala" => trim($tak_atterlist[$j][1]), + "pos" => trim($tak_atterlist[$j][2]), + "tgala" => $gala, + "tpos" => $pos, + "fleetnum" => 2, + "eta" => $tak_eta, + "nick" => trim($tak_atterlist[$j][3]) + ); + } + } + } + } + + #incs auf recall prüfen + for($j=0;$j < count($user_atterlist);$j++){ + $atter = &$user_atterlist[$j]; + + if(!$atter['checked']) { + #nach zweiter flotte suchen die im selben tick fliegt aber nicht recallt hat + $eta = floor(($atter['arrival']-time())/60); + if ($eta > 0) { + $eta_high = $eta + 14; + $eta_low = $eta-14; + if($eta_low < 0) { + $eta_low = 1; + } + } else { + $eta_low = 0; + $eta_high = 0; + } + $found = false; + for($k=0;$k < count($user_atterlist);$k++){ + $eta_search = floor(($user_atterlist[$k]['arrival']-time())/60); + #im orbit + if($eta_search < 0) { + $eta_search = 0; + } + if( $user_atterlist[$k]['checked'] && + $user_atterlist[$k]['gala'] == $atter['gala'] && + $user_atterlist[$k]['pos'] == $atter['pos'] && + $eta_search >= $eta_low && + $eta_search <= $eta_high + ) { + #flotte gefunden die im selben tick fliegt und gematcht wurde + #-> unklar welche von beiden recallt hat + $messages[] = "(".$atter['gala'].":".$atter['pos'].") ".$atter['nick']." attet mit 2 Flotten und hat eine von beiden recallt, bitte überprüfen"; + $found = true; + break; + } + } + if(!$found){ + $messages[] = "Atter (".$atter['gala'].":".$atter['pos'].") ".$atter['nick']." Flotte ".$atter['fleetnum']." ETA ".$this->formattime($atter['arrival']-time(),true)." hat recalled"; + fleetstatus_recall($atter['fsid']); + } + } + } + foreach ($insert as $line) { + atter_add( + $line['gala'], + $line['pos'], + $line['tgala'], + $line['tpos'], + &$line['fleetnum'], + $line['eta'], + null, + $line['nick'] + ); + $messages[] = "Atter (".$line['gala'].":".$line['pos'].") ".$line['nick']." Flotte ".$line['fleetnum']." ETA ".$this->formattime($line['eta']*60,true)." hinzugefügt"; + } + } + + function _match_deffer($tgala,$tpos,$line,$messages,$errors) { + unset($defferadd_list); + $user_defferlist = fleetstatus_get_bytarget($tgala,$tpos,2); + if(preg_match_all("/(\d{1,4}):(\d{1,2})(.*?)
    /ism",$line[10],$tak_list,PREG_SET_ORDER)) { + if(count($tak_list)){ + $tak_timelist = parse_time($line[11]); + #defferliste + for($j=0;$j < count($tak_list);$j++){ + unset($deffer); + $tak_eta = $tak_timelist[$j]; + if($tak_eta == "error") {$errors[] = "deffer (".$tak_list[$j][1].":".$tak_list[$j][2].") zeit nicht erkannt";continue;} + #20 ticks im orbit + if ($tak_eta == 0) { + $tak_eta_low = -300; + $tak_eta_high = 0; + } else { + #toleranz von einem tick + $tak_eta_low = $tak_eta - 14; + $tak_eta_high = $tak_eta + 14; + } + #passenden deffer finden + for($k=0;$k < count($user_defferlist);$k++){ + $eta = floor(($user_defferlist[$k]['arrival']-time())/60); + if( $user_defferlist[$k]['gala'] == $tak_list[$j][1] && + $user_defferlist[$k]['pos'] == $tak_list[$j][2] && + !($user_defferlist[$k]['checked']) && + $eta > $tak_eta_low && + $eta < $tak_eta_high + ) { + #passenden deffer gefunden! + $deffer = &$user_defferlist[$k]; + break; + } + } + if($deffer){ + $deffer['checked'] = true; + } else { + $gala = trim($tak_list[$j][1]); + $pos = trim($tak_list[$j][2]); + $nick = trim($tak_list[$j][3]); + $adddeffer = array( + "gala" => $gala,"pos" => $pos,"nick" => $nick,"fleetnum" => 1,"eta" => $tak_eta + ); + $messages[] = "Deffer (".$gala.":".$pos.") ".$nick." Flotte 1 ETA ".$this->formattime($tak_eta*60,true)." hinzugefügt"; + + + $defferadd_list[] = $adddeffer; + } #else + } #for + } #if count(tak:list) + } # if (pregmatchall) + #deffer auf recall prüfen + for($j=0;$j < count($user_defferlist);$j++){ + $deffer = &$user_defferlist[$j]; + if(!$deffer['checked']) { + #nach zweiter flotte suchen die im selben tick fliegt aber nicht recallt hat + $eta = floor(($deffer['arrival']-time())/60); + $gala = $deffer['gala']; + $pos = $deffer['pos']; + $nick = $deffer['nick']; + if ($eta > 0) { + $eta_high = $eta + 14; + $eta_low = $eta-14; + if($eta_low < 0) { + $eta_low = 1; + } + } else { + $eta_low = 0; + $eta_high = 0; + } + $found = false; + for($k=0;$k < count($user_defferlist);$k++){ + $eta_search = floor(($user_defferlist[$k]['arrival']-time())/60); + #im orbit + if($eta_search < 0) { + $eta_search = 0; + } + if( $user_defferlist[$k]['checked'] && + $user_defferlist[$k]['gala'] == $gala && + $user_defferlist[$k]['pos'] == $pos && + $eta_search >= $eta_low && + $eta_search <= $eta_high + ) { + $found = true; + break; + } + } + if(!$found){ + $messages[] = "Deffer (".$gala.":".$pos.") ".$nick." Flotte ".$deffer['fleetnum']." ETA ".$this->formattime(($deffer['arrival']-time()),true)." hat recalled"; + fleetstatus_recall($deffer['fsid']); + } else { + #flotte gefunden die im selben tick fliegt und gematcht wurde + #-> unklar welche von beiden recallt hat + $messages[] = "(".$gala.":".$pos.") ".$nick." defft mit 2 Flotten im selben Tick und hat eine von beiden recallt, bitte überprüfen "; + } #else + } #if not deffer_checked + } #for + #deffer in die db eintragen + for($j=0;$j < count($defferadd_list);$j++){ + $deffer = &$defferadd_list[$j]; + if(($check = fleetstatus_get_bykoords($deffer['gala'],$deffer['pos'],$deffer['fleetnum']))) { + if($check['return_flight']){ + fleetstatus_delete($check['fsid']); + } else { + if($deffer['fleetnum'] == 1) $deffer['fleetnum'] = 2; + else $deffer['fleetnum'] = 1; + } + } + deffer_add( + $deffer['gala'], + $deffer['pos'], + $tgala, + $tpos, + $deffer['fleetnum'], + 360, + 20, + $deffer['eta'], + $deffer['nick'] + ); + } + } + + function _is_matched_fleet($db_fleet,$parsed_fleet) { + if( $db_fleet['return_flight'] != $parsed_fleet['return_flight'] || + $db_fleet['status'] != $parsed_fleet['status'] || + $db_fleet['gala'] != $parsed_fleet['gala'] || + $db_fleet['pos'] != $parsed_fleet['pos'] + ) { + return false; + } + $eta_db = ($db_fleet['arrival']-time())*60; + if(abs($eta_db - $parsed_fleet['eta']) > 14 && $eta_db > 0) return false; + return true; + } + + function _match_user(&$user,$line) { + #attflotten matching +# var_dump($line); +# echo "

    "; + $fleet_list = array(); + if(preg_match_all("'(?:(Rückflug)\s*?
    |)[\s\(]*?(\d{1,4}):(\d{1,2})\s*?([^\s\)<]+).*?
    'is",$line[4],$att_fleets,PREG_SET_ORDER)) { + $timelist = parse_time($line[5]); + for($i=0;$i < count($att_fleets);$i++) { + $fleet = &$att_fleets[$i]; + if($fleet[1] == "Rückflug") { + $fleet['return_flight'] = 1; + } else { + $fleet['return_flight'] = 0; + } + $fleet['status'] = 1; + if($fleet['return_flight']) { + $title = "Angriff Rückflug von"; + $select = "Angriff Rückflug von"; + } else { + $title = "Angriff auf"; + $select = "Angriff auf"; + } + $eta = $timelist[$i]*60; + $title .= " $fleet[4] ($fleet[2]:$fleet[3]) ETA ".$this->formattime($eta,true); + $select .= " $fleet[4] ($fleet[2]:$fleet[3]) ETA ".$this->formattime($eta,true); + $fleet_list[] = array("status" => $fleet['status'],"gala" => $fleet[2],"pos" => $fleet[3],"nick" => $fleet[4], "eta" => $eta, + "return_flight" => $fleet['return_flight']); + $titles[] = $title; + $select_box[] = array("value" => $i+1, "title" => $select); + } + } + if(preg_match_all("'(?:(Rückflug)\s*?
    |)[\s\(]*?(\d{1,4}):(\d{1,2})\s*?([^\s\)<]+).*?
    'is",$line[6],$att_fleets,PREG_SET_ORDER)) { + $timelist = parse_time($line[7]); + for($i=0;$i < count($att_fleets);$i++) { + $fleet = &$att_fleets[$i]; + if($fleet[1] == "Rückflug") { + $fleet['return_flight'] = 1; + } else { + $fleet['return_flight'] = 0; + } + $fleet['status'] = 2; + if($fleet['return_flight']) { + $title = "Verteidigung Rückflug von"; + $select = "Verteidigung Rückflug von"; + } else { + $title = "Verteidigung von"; + $select = "Verteidigung von"; + } + $eta = $timelist[$i]*60; + $title .= " $fleet[4] ($fleet[2]:$fleet[3]) ETA ".$this->formattime($eta,true); + $select .= " $fleet[4] ($fleet[2]:$fleet[3]) ETA ".$this->formattime($eta,true); + + $fleet_list[] = array("status" => $fleet['status'], + "gala" => $fleet[2],"pos" => $fleet[3],"nick" => $fleet[4], + "eta" => $eta,"return_flight" => $fleet["return_flight"]); + + $titles[] = $title; + $select_box[] = array("value" => $i+1, "title" => $select); + } + } + $fleet = array(); + $userfleets = listFleetsByUser($user['uid']); + if(count($fleet_list) == 0) { + // beide flotten im orbit + $do_update = array(1,1); + $do_selectbox = array(0,0); + $fleet = array(); + } elseif ( count($fleet_list) == 1 && $user['fleettype'] && $fleet_list[0]['status'] == 1 && $user['fleettype'] == 2) { + // flotte 1 attet, flotte 2 im orbit + // mit db checken + if($this->_is_matched_fleet($userfleets[1],$fleet_list[0])) { + // is in db, kein update + $do_update = array(0,1); + } else { + // is nicht in db + $do_update = array(1,1); + } + $do_selectbox = array(0,0); + + $fleet[0] = $fleet_list[0]; + + } elseif ( count($fleet_list) == 1 && $user['fleettype'] && $fleet_list[0]['status'] == 2 && $user['fleettype'] == 1) { + // flotte 1 defft, flotte 2 im orbit + // mit db checken + if($this->_is_matched_fleet($userfleets[1],$fleet_list[0])) { + // is in db, kein update + $do_update = array(0,1); + } else { + // is nicht in db + $do_update = array(1,1); + } + $do_selectbox = array(0,0); + $fleet[0] = $fleet_list[0]; + #echo "flotte 1 defft, flotte 2 im orbit
    "; + } elseif( count($fleet_list) == 2 && $user['fleettype'] && $fleet_list[0]['status'] != $fleet_list[1]['status']) { + // flotten beide unterwegs, status unterschiedlich + if($user['fleettype'] == 2) { + // flotte 2 defft, flotte 1 attet + $fleet[0] = $fleet_list[0]; + $fleet[1] = $fleet_list[1]; + } else { + // flotte 1 defft, flotte 2 attet + $fleet[0] = $fleet_list[1]; + $fleet[1] = $fleet_list[0]; + $title_dummy = $titles[0]; + $titles[0] = $titles[1]; + $titles[1] = $title_dummy; + } + if($this->_is_matched_fleet($userfleets[1],$fleet_list[0])) { + // is in db, kein update + $do_update[0] = 0; + } else { + // is nicht in db + $do_update[0] = 1; + } + if($this->_is_matched_fleet($userfleets[2],$fleet_list[1])) { + // is in db, kein update + $do_update[1] = 0; + } else { + // is nicht in db + $do_update[1] = 1; + } + } else { + // keine ahnung + $do_update = array(1,1); + $do_selectbox = array(1,1); + $fleet = $fleet_list; + if(!count($fleet[1])) { + $fleet[] = array("status" => 0); + $titles[] = "Im Orbit"; + $select_box[] = array("value" => 2, "title" => "Im Orbit"); + } + } + for($i=0;$i < 2; $i++) { + $hidden_string[$i]['do_update'] = $do_update[$i]; + $hidden_string[$i]['do_selectbox'] = $do_selectbox[$i]; + $hidden_string[$i]['status'] = $fleet[$i]['status']; + $hidden_string[$i]['gala'] = $fleet[$i]['gala']; + $hidden_string[$i]['pos'] = $fleet[$i]['pos']; + $hidden_string[$i]['eta'] = $fleet[$i]['eta']; + $hidden_string[$i]['return_flight'] = $fleet[$i]['return_flight']; +# var_dump($hidden_string[$i]);echo"
    "; +# var_dump(join(",",$hidden_string[$i]));echo"
    "; + $hidden_string[$i] = urlencode(join(",",$hidden_string[$i])); + if(!$titles[$i]) $titles[$i] = "Im Orbit"; + $user['form_data'][] = array( + "title" => $titles[$i], + "fleet" => $i+1, + "do_selectbox" => $do_selectbox[$i], + "select_box" => $select_box + ); + } + $user['hidden_string'] = join("#",$hidden_string); +# if($user['nick'] == "Schmog") { +# var_dump($fleet_list); +# echo "

    "; +# echo "userfleettype: ".$user['fleettype']."
    "; +# var_dump($fleet); +# echo "

    "; +# var_dump($titles); +# echo "

    "; +# exit(); +# } + } + + function parser_takscreen() { + + function parse_time($timedata) { + $timelist = array(); + #mode1 + preg_match_all("/(\d+?)\sMin/ism",$timedata,$tak_timelist,PREG_SET_ORDER); + if (count($tak_timelist)){ + for($j=0;$j < count($tak_timelist);$j++){ + $timelist[] = $tak_timelist[$j][1]; + } + } else { + #mode3 + preg_match_all("/(\d{1,2}):(\d{1,2}):(\d{1,2})/ism",$timedata,$tak_timelist_mode3,PREG_SET_ORDER); + if(count($tak_timelist_mode3)){ + for($j=0;$j < count($tak_timelist_mode3);$j++){ + $timelist[] = ($tak_timelist_mode3[$j][1])*60+$tak_timelist_mode3[$j][2]; + } + } else { + #mode4 + preg_match_all("/(\d{1,2}):(\d{1,2})/ism",$timedata,$tak_timelist_mode4,PREG_SET_ORDER); + if(count($tak_timelist_mode4)){ + for($j=0;$j < count($tak_timelist_mode4);$j++){ + $timelist[] = ($tak_timelist_mode4[$j][1])*60+$tak_timelist_mode4[$j][2]; + } + } else { + #mode 5 + preg_match_all("/(\d{1,2})/ism",$timedata,$tak_timelist_mode5,PREG_SET_ORDER); + if(count($tak_timelist_mode5)){ + for($j=0;$j < count($tak_timelist_mode5);$j++){ + $timelist[] = ($tak_timelist_mode5[$j][1])*15; + } + } else { + $timelist[] = "error"; + } + } + } + } + return $timelist; + } + + $form = new formContainer(); + + $form->add(new formCheckBox("parse_user","User parsen","numeric",array(1),false)); + $form->add(new formCheckBox("parse_atter","Atter parsen","numeric",array(1),false)); + $form->add(new formCheckBox("parse_deffer","Deffer parsen","numeric",array(1),false)); + $form->add(new formInput("data","Taktikschirmdaten","string")); + + if ($_POST['userparse_step2']) { + //parse userfleets, step 2 + $uids = split(",",urldecode($_POST['uids'])); + if($uids && is_array($uids) && count($uids)){ + $user = getUserbyID($uids[0]); + $allygalas = getGalaListByAlly($user['aid'],true); + $metagalas = getGalaList(true); + foreach($uids as $uid) { + $fleetdata = split("#",$_POST["user_".$uid]); + $fleetdata[0] = split(",",urldecode($fleetdata[0])); + $fleetdata[1] = split(",",urldecode($fleetdata[1])); +# echo "fleetdata:
    "; +# echo "
    "; + for($i=0;$i < 2; $i++) { +# echo"
    ";var_dump($fleetdata[$i]);echo"
    "; + if($fleetdata[$i][0]) { + // do_update + if($fleetdata[$i][1]) { + // do selectbox + $id = $_POST["select_".$uid."_".($i+1)]; + if(!$id || !is_numeric($id)) continue; + if($_POST["select_".$uid."_1"] == $_POST["select_".$uid."_2"]) continue; + $id--; + } else { + // else + $id = $i; + } + $status = $fleetdata[$id][2]; + $gala = $fleetdata[$id][3]; + $pos = $fleetdata[$id][4]; + $eta = $fleetdata[$id][5]; + $return_flight = $fleetdata[$id][6]; + if(!$return_flight) { + if($status == 1) { + $ticks = 5; + $returntime = 450; + } elseif ($status == 2) { + $ticks = 20; + if($gala == $user['gala']) { + $returntime = 270; + } elseif(in_array($gala,$allygalas)){ + $returntime = 300; + } elseif(in_array($gala,$metagalas)){ + $returntime = 330; + } else { + $returntime = 360; + } + } + } +# echo "$uid: flotte ".($i+1).": do_update: ".$fleetdata[$i][0].", do_selectbox: ".$fleetdata[$i][1].", status: $status, gala: $gala, pos: $pos, eta: $eta, return_flight: $return_flight
    "; + User_fleet_status_update( + $uid, + $id+1, + $status, + $return_flight, + floor($eta/60), + $gala, + $pos, + $ticks, + $returntime + ); + } + } + } // foreach + } // if uids + $this->_header("takscreen.php?action=takparser"); + exit(); + } elseif($_POST['takscreenparse_step1']) { + $form->submit(); + if (!$form->hasErrors()) { + #echo $data."

    "; + $data = stripslashes($form->get("data")); + if (preg_match( + "/Sektor(.*?)<\/table>/ism", + $data,$res)){ + $res[1] = preg_replace("/(.*?)<\/a>/ism","\$1",$res[1]); + $res[1] = preg_replace("/
    (.*?)<\/nobr>/ism","\$1",$res[1]); + $res[1] = preg_replace("/(.*?)<\/span>/ism","\$1",$res[1]); + $res[1] = preg_replace("/\*/ism","",$res[1]); + $res[1] = html_entity_decode($res[1]); + preg_match_all("/]*?class=\"r\"\>\s*?". + ".*?(\d{1,4}):(\d{1,2}).*?<\/td>\s*?". + "(.*?)<\/td>\s*?". + "(.*?)<\/td>\s*?". + "(.*?)<\/td>\s*?". + "(.*?)<\/td>\s*?". + "(.*?)<\/td>\s*?". + "(.*?)<\/td>\s*?". + "(.*?)<\/td>\s*?". + "(.*?)<\/td>\s*?". + "(.*?)<\/td>\s*?". + "<\/tr>/ism",$res[1],$res,PREG_SET_ORDER); + $galalist = getGalaList(); + $parse_messages = array(); + for($i=0;$i < count($res);$i++){ + #print_r($res[$i]); + $line = &$res[$i]; + $gala = $line[1]; + $pos = $line[2]; + $nick = trim($line[3]); + $user = getUserByPos($gala,$pos); + if ($user){ + $parse_messages[] = "User ".$user['nick']." (".$user['gala'].":".$user['pos'].") aktualisiert"; + if(strtolower($user['nick']) != strtolower($nick)) { + $parse_errors[] = "".$user['nick']." (".$user['gala'].":".$user['pos'].") hat falschen GN Nick oder ist ungültig"; + #echo "'".strtolower($nick)."' <> '".strtolower($user['nick'])."'
    "; + } + #atter matching + if($form->get("parse_atter")) { + $this->_match_atter($gala,$pos,$line,&$parse_messages,&$parse_errors); + } + + #deffer + if($form->get("parse_deffer")) { + $this->_match_deffer($gala,$pos,$line,&$parse_messages,&$parse_errors); + } +/* #parse user + if($form->get("parse_user")) { + $this->_match_user(&$user,$line,&$fleet_select); + $uids[] = $user['uid']; + $userparse_list[] = $user; + }*/ + } else { + $parse_errors[] = "User ".$nick." (".$gala.":".$pos.") existiert nicht in der Datenbank"; + } + } + // result + if($form->get("parse_user")) { + $this->template->assign("uids",urlencode(join(",",$uids))); + $this->template->assign("userparse",$form->get("parse_user")); + $this->template->assign("userparse_list",$userparse_list); + } + $this->template->assign("parse_errors",$parse_errors); + $this->template->assign("parse_messages",$parse_messages); + $form->registerVars(&$this->template); + $this->show('takscreen_parser_takscreen_step2','Taktikschirm parsen'); + exit(); + } else { + $parse_errors[] = "Taktikschirm nicht erkannt"; + } + } + } else { + $parse_errors[] = "ACHTUNG! Unbedingt darauf achten dass euer Taktikschirm nicht älter als 15 min ist!"; + $form->select("parse_user",0); + $form->select("parse_deffer",1); + $form->select("parse_atter",1); + } + $this->template->assign("parse_errors",$parse_errors); + $form->registerVars(&$this->template); + $this->show('takscreen_parser_takscreen','Taktikschirm parsen'); + } + ############################################################################# + function parser_fleet() { + $form = new formContainer(); + $form->add(new formInput("data","Flottendaten","string")); + if($_POST['send']) { + $form->submit(); + if(!$form->hasErrors()) { + $text = $form->get("data"); + $items = parse_taktikansicht($text); + if($items) { + foreach($items as $item) { + $nick = $item['nick']; + $gala = $item['gala']; + $pos = $item['pos']; + $user = getUserByPos($gala,$pos); + if(!$user) {$parse_errors[] = "($gala:$pos) $nick nicht im System";continue;} + if(strtolower($user['nick']) != strtolower($nick)) $parse_errors[] = "($gala:$pos) $nick hat falschen GN-Nick oder ist ungültig"; + + user_fleets_update($user['uid'],$item['fleets']); + user_deff_update($user['uid'],$item['deff']); + + $parse_messages[] = "($gala:$pos) $nick erkannt"; + } + $this->template->assign("parse_messages",$parse_messages); + $this->template->assign("parse_errors",$parse_errors); + } else { + $form->setError("data"); + $form->addError("Es wurde nichts erkannt!"); + } + } + } + $form->registerVars(&$this->template); + $this->show('takscreen_parser_fleet','Flotten/Deff parsen'); + } + ############################################################################# + /** + Blendet Flotten in der Incdetailansicht aus + **/ + function incoming_details_hidefleets() { + if(!($id = param_num("id")) || !($inc = getuserbyid($id))) $this->_header(); + $fleets = $_POST['hidefleets']; + if(!$fleets || !is_array($fleets) || !count($fleets)) $this->_header("takscreen.php?action=details&id=$id&send"); + $fleets = preg_grep("'^\d+?$'is",$fleets); + hide_fleets($fleets,$this->userdata); + $this->_header("takscreen.php?action=details&id=$id&send"); + } + ############################################################################# + function incoming_details_resetfilter() { + $id = param_num("id"); + if(!($id = param_num("id")) || !($inc = getuserbyid($id))) $this->_header(); + $fids = array(); + $fids = getArrayFromList(fleetstatus_get_bytarget($inc['gala'],$inc['pos']),"fsid"); + if(count($fids)) reset_fleet_filter($this->userdata,$fids); + $this->_header(); + } + ############################################################################# + function parser_mili() { + $step = param_num("step"); + $data = $_SESSION['steps']; + if($data['miliparser']) { + unset($data['miliparser']); + $_SESSION['steps'] = $data; + $this->forms['information']['action'] =""; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['title'] = "Miliscan laden"; + $this->forms['information']['message'] = "Miliscan wurde geladen und die Flotten aktualisiert"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Miliscan laden"); + exit(); + } + if (!$step){ + # parsen + if ($_POST['send']) { + $data = $_POST['data']; + if ($data) { + $scans = parseScan($data); + if($scans) { + $miliids = array(); + foreach ($scans as $scan) { + $sid = updateScan($scan); + if($scan['type'] == "mili") { + $miliids[] = $sid; + } + } + if($miliids) { + $_SESSION['parse_mili']['sids'] = $miliids; + $this->_header("takscreen.php?action=miliparser&send&step=1"); + } else { + $message = "
    keine Miliscans erkannt
    "; + } + } else { + $message = "
    keine Scans erkannt
    "; + } + } else { + $message = "
    Feld leer
    "; + } + } else { + $message = "Unterstützte Formate:

    Galaxy Network Scan (IRC Copy)"; + } + $this->template->assign("message",$message); + $this->show('takscreen_miliparser','Mili parsen'); + }elseif($step==1) { + + $miliids = $_SESSION['parse_mili']['sids']; + if(!is_array($miliids) || !count($miliids)) $this->_header(); + // miliscan auswerten + + $mili = getScan(array("sid"=>reset($_SESSION['parse_mili']['sids']))); + + $fleets = &$mili['mili_fleets']; + + // mili formatieren + for($i=0;$i < count($fleets);$i++){ + if ($fleets[$i]['status'] == 1) { + $fleets[$i]['class'] = "red"; + } elseif($fleets[$i]['status'] == 2) { + $fleets[$i]['class'] = "green"; + } elseif ($fleets[$i]['return_flight']) { + $fleets[$i]['class'] = "blue"; + } + } + $form = new formContainer(); + + $formitems = array(); + + // darf kein intener user sein + if(!($user = getUserByPos($mili['gala'],$mili['pos']))) { + if(($status = fleetstatus_get_filter(array( + "gala" => $mili['gala'], + "pos" => $mili['pos'], + "return_flight" => "0" + )))) + { + $list = array(); + $fleetstatus = array(); + $list[] = array("title" => "nicht zuweisen","value" => 0); + foreach ($status as $key => $value) { + $item = &$status[$key]; + if(($eta = $item['arrival'] - time()) < 0) { + $eta = $eta + $item['orbittime']*60; + $item['eta'] = "noch ".$this->formattime($eta,true)." im Orbit"; + } else { + $item['eta'] = "ETA ".$this->formattime($eta,true); + } + if($item['status'] == 1) { + $type = "Angriff"; + } else { + $type = "Verteidigung"; + } + #$item['title'] = $type." ".$item['tnick']." (".$item['tgala'].":".$item['tpos'].") ".$item['eta']." Flotte ".$item['fleetnum']; + $list[] = array("value" => $item['fsid'],"title" => $type." ".$item['tnick']." (".$item['tgala'].":".$item['tpos'].") ".$item['eta']." Flotte ".$item['fleetnum']); + $fleetstatus[$item['fsid']] = $item; + } + for ($i=1;$i < 3;$i++) { + if($fleets[$i]['status'] == 1 || $fleets[$i]['status'] == 2) { + //if($status) $formitems[$i]['select_items'] = $status; + $form->add(new formSelectBox("fleet".$i,"Flotte $i","integer",$list,false)); + } + } + } + } else { + $form->setError("User ist Metamitglied, nicht erlaubt"); + } + if($_POST['send']) { + $form->submit(); + $fleet1 = $form->get("fleet1"); + $fleet2 = $form->get("fleet2"); + if($fleet1 && $fleet2 && $fleet1 == $fleet2) { + $form->addError("beide Flotten wurden auf den selben Eintrag gesetzt"); + $form->setError(array("fleet1","fleet2")); + } + if(!$form->hasErrors()) { + if($fleet1) { + if($fleetstatus[$fleet1]['fleetnum'] != 1) { + fleetstatus_change_fleetnum($fleet1,1); + // muss neu geladen werden + if($fleet2) $fleetstatus[$fleet2] = fleetstatus_get($fleet2); + } + fleetstatus_update_fleet($fleet1,$fleets[1],$mili['mili_svs'],$mili['mili_prec']); + } + if($fleet2) { + if($fleetstatus[$fleet2]['fleetnum'] != 2) { + fleetstatus_change_fleetnum($fleet2,2); + } + fleetstatus_update_fleet($fleet2,$fleets[2],$mili['mili_svs'],$mili['mili_prec']); + } + array_shift($_SESSION['parse_mili']['sids']); + $this->_header("takscreen.php?action=miliparser&send&step=1"); + } + } + + $this->template->assign("step",$step); + $form->registerVars($this->template); + #$this->template->assign("fleets",$fleets); + $this->template->assign("mili",$mili); + $this->show('takscreen_miliparser_step2','Mili parsen'); + } + } + ############################################################################# + function Incoming_setunsafe() { + if(!($id = param_num("id")) || !($user = getUserByID($id)) || !($user['safe'])) $this->_header(); + addToLogFile("Ziel not safe: (".$user['gala'].":".$user['pos'].")","Incomings",$this->userdata['uid']); + user_set_safe($id,0); + $this->_header($this->backtracking->backlink()); + } + ############################################################################# + function Incoming_setsafe() { + if(!($id = param_num("id")) || !($user = getUserByID($id)) || ($user['safe'])) $this->_header(); + addToLogFile("Ziel safe: (".$user['gala'].":".$user['pos'].")","Incomings",$this->userdata['uid']); + user_set_safe($id,1); + $this->_header($this->backtracking->backlink()); + } + ############################################################################# +/* function Deffer_recall() { + $id = param_num("id"); + if(!$id)$this->_header($this->backtracking->backlink(),"fehlende id"); + $deffer = deffer_get($id); + if(!$deffer)$this->_header($this->backtracking->backlink(),"deffer existiert nicht"); +# if ($deffer['gala'] != $this->userdata['gala'] && $deffer['ogala'] != $this->userdata['gala']) +# $this->_header("takscreen.php","keine Berechtigung zum recalln"); + if ($_REQUEST['send']) { + if ($_REQUEST['yes_x']) { + deffer_recall($id); + $inc = inc_get_data($deffer['incid']); + if ($deffer['isextern']) { + addToLogFile("externer Deffer (".$deffer['egala'].":".$deffer['epos'].") bei (".$inc['ogala'].":".$inc['opos'].") recallt","Incomings",$this->userdata['uid']); + } else { + addToLogFile("interner Deffer (".$deffer['gala'].":".$deffer['pos'].") bei (".$inc['ogala'].":".$inc['opos'].") recallt","Incomings",$this->userdata['uid']); + } + } + $this->_header(); + } else { + $this->forms['information']['url'] = "takscreen.php?id=$id"; + $this->forms['information']['action'] = "defferrecall"; + $this->forms['information']['title'] = "Deffer recalln"; + $this->forms['information']['message'] = "Deffer bei (".$deffer['ogala'].":".$deffer['opos'].") ".$deffer['onick']." recalln ?"; + $this->forms['information']['style'] = "red"; + $this->show('message_question', "Deffer recalln"); + } + } +*/ ############################################################################# + function Atter_recallall() { + if(!($id = param_num("id")) || !($user = getUserByID($id)) || !($atter = fleetstatus_get_bytarget($user['gala'],$user['pos'],1))) $this->_header();; + if ($_REQUEST['send']) { + if ($_REQUEST['yes_x']) { + foreach ($atter as $data) { + fleetstatus_recall($data['fsid']); + } + addToLogFile("alle Atter bei (".$user['gala'].":".$user['pos'].") recallt","Incomings",$this->userdata['uid']); + } + $this->_header(); + } else { + $this->forms['information']['url'] = "takscreen.php?id=$id"; + $this->forms['information']['action'] = "recallall"; + $this->forms['information']['title'] = "alle Atter recalln"; + $this->forms['information']['message'] = "alle Atter auf (".$user['gala'].":".$user['pos'].") ".$user['nick']." recalln ?"; + $this->forms['information']['style'] = "red"; + $this->show('message_question', "alle Atter recalln"); + } + } + ############################################################################# + + function Fleet_recall() { + $id = param_num("id"); + if(!$id || !($info = fleetstatus_get($id))) $this->_header(); + + if ($_REQUEST['send']) { + if ($_REQUEST['yes_x']) { + fleetstatus_recall($info['fsid']); + #addToLogFile("Atter (".$atter['igala'].":".$atter['ipos'].") bei: (".$atter['ogala'].":".$atter['opos'].") recallt","Incomings",$this->userdata['uid']); + } + $this->_header(); + } else { + $this->forms['information']['url'] = "takscreen.php?id=$id"; + $this->forms['information']['action'] = "recall"; + $this->forms['information']['title'] = "Flotte recalln"; + $this->forms['information']['message'] = " (".$info['gala'].":".$info['pos'].") ".$info['nick']." recalln ?"; + $this->forms['information']['style'] = "red"; + $this->show('message_question', "Flotte recalln"); + } + } + + ############################################################################# + function Incoming_details() { + if(!($id = param_num("id")) || !($inc = getuserbyid($id))) + $this->_header(); + + if(!($incfleets = inc_list_byuser($inc['gala'],$inc['pos']))) + $this->_header(); + + $result = user_fleet_list_byuser($id); + + //atter-deffersummen + $deffersum = array(); $attersum = array(); + + $checkfleet = array("jaeger" => "Jäger","bomber"=>"Bomber", + "fregatten" => "Fregatten","zerstoerer"=>"Zerstörer","kreuzer"=>"Kreuzer", + "schlachter"=>"Schlachter","traeger"=>"Träger","kleptoren"=>"Kleptoren", + "cancris"=>"Cancris"); + + for($i=0;$i < count($result);$i++){ + if($result[$i]['return_flight']) { + $result[$i]['name'] = "Rückflug"; + $result[$i]['class'] = "class=\"blue\""; + } else { + if ($result[$i]['status'] == 1) { + $result[$i]['name'] = "Angriff"; + $result[$i]['class'] = "class=\"red\""; + } elseif ($result[$i]['status'] == 2) { + $result[$i]['name'] = "Verteidigung"; + $result[$i]['class'] = "class=\"green\""; + } else { + $result[$i]['name'] = "Im Orbit"; + } + } + if($result[$i]['tgala']) $result[$i]['name'] .= " (".$result[$i]['tgala'].":".$result[$i]['tpos'].")"; + if($result[$i]['status']) { + if($result[$i]['arrival']) { + $eta = $result[$i]['arrival'] - time(); + if($eta < 0) { + $result[$i]['name'] .= " im Orbit: ".$this->formattime($result[$i]['orbittime']*60 + $eta,true); + } else { + $result[$i]['name'] .= " ETA ".$this->formattime($eta,true); + } + } else { + $result[$i]['name'] .= "ETA n/a"; + } + } + // flotte im orbit + if(!$result[$i]['status']) { + foreach($checkfleet as $key => $val) { + $deffersum[$key] += $result[$i][$key]; + } + } + } + $this->template->assign("userfleet",$result); + $fleetfilter = get_fleet_filter($this->userdata); + + // flottenfilter, eta formatierung + $atter = 0; $deffer = 0; + $atterlist = array(); $defferlist = array(); + + // kann editieren + if($inc['aid'] == $this->userdata['aid']) { + $inc['canedit'] = 1; + } + + $inc['cansetsafe'] = 1; + + foreach($incfleets as $fleet) { + if($fleet['status'] == 1) $inc['atter']++; + elseif($fleet['status'] == 2) $inc['deffer']++; + if(count($fleetfilter)) { + if($fleet['fsid'] && in_array($fleet['fsid'],$fleetfilter)) { + if($fleet['status'] == 1) $inc['atter_filter'] = 1; + elseif($fleet['status'] == 2) $inc['deffer_filter'] = 1; + continue; + } + } + if($fleet['arrival']) { + $eta = $fleet['arrival']-time(); + if($eta < 0) { + $fleet['eta'] = "im Orbit: ".$this->formattime($fleet['orbittime']*60 + $eta,true); + } else { + $fleet['eta'] = $this->formattime($eta); + $fleet['title'] = $this->formattime($fleet['orbittime']*60,true)." im Orbit"; + } + } + $fleet['canrecall'] = 1; + if($fleet['status'] == 2) { + + $deffer++; + if(!$fleet['uid'] || $fleet['aid'] == $this->userdata['aid']) { + $fleet['canedit'] = 1; + } + $defferlist[] = $fleet; + foreach($checkfleet as $key => $val) { + $deffersum[$key] += $fleet[$key]; + } + } elseif($fleet['status'] == 1) { + $atter++; + $fleet['canedit'] = 1; + $atterlist[] = $fleet; + foreach($checkfleet as $key => $val) { + $attersum[$key] += $fleet[$key]; + } + } + } + if(!$inc['atter']) $this->_header(); + + + + $inc['canupdateatter'] = 1; + $this->template->assign("attersum",$attersum); + $this->template->assign("deffersum",$deffersum); + $this->template->assign("ircattdata",generate_irc_inc_summary($inc,$attersum,$deffersum)); + $this->template->assign("defferlist",$defferlist); + if ($inc['fleetupdate']) { + $inc['fleetupdate'] = formatdate_unix("d.m.Y",$inc['fleetupdate']).", ".date("H:i",$inc['fleetupdate'])." Uhr"; + } else { + $inc['fleetupdate'] = "noch nie"; + } + if ($inc['deffupdate']) { + $inc['deffupdate'] = formatdate_unix("d.m.Y",$inc['deffupdate']).", ".date("H:i",$inc['deffupdate'])." Uhr"; + } else { + $inc['deffupdate'] = "noch nie"; + } + $inc['cansetsave'] = 1; + $inc['canrecallall'] = 1; + $inc['fleetfilter_set'] = 1; + $this->template->assign("inc",$inc); + $this->template->assign("atterlist",$atterlist); + #$_SESSION['backlink'] = urlencode("takscreen.php?action=details&id=$id"); + $this->show('takscreen_inc_details', "Taktikschirm"); + } + + ############################################################################# + function Incoming_list() { + $filter = &$_SESSION['incfilter']; + if (!$filter){ + $filter['sort'] = "koords"; + $filter['order'] = "asc"; + } + if ($_REQUEST['sort'] && $_REQUEST['order']) { + $filter['sort'] = $_REQUEST['sort']; + $filter['order'] = $_REQUEST['order']; + } + + $filter['page'] = param_num("page",1); + + $allylist = getAllyList(); + + $formlist = array(); + $formlist[] = array("title" => "Allianz", "value" => 0); + foreach ($allylist as $ally) { + $formlist[] = array("title" => "[".$ally['tag']."] ".$ally['name'],"value" => $ally['aid']); + } + + $form = new formContainer(); + + $form->add(new formSelectBox("ally","Allianz","numeric",$formlist,false)); + $form->add(new formCheckBox("safe","Safestatus","numeric",1,false)); + $form->add(new formCheckBox("undertime","unter der Deffzeit","numeric",1,false)); + if ($_POST['send']) { + $form->submit(array("ally","safe","undertime")); + $ally = $form->get("ally"); + $filter['undertime'] = $form->get("undertime"); + $filter['safe'] = $form->get("safe"); + + if ($ally && !getAlly($ally)) { + unset($ally); + } + if($ally) { + $galalist = getGalaListByAlly($ally,true); + } else { + $galalist = getGalaList(true); + } + if($filter['ally'] != $ally) { + $gala = 0; + } else { + $gala = $_POST['gala']; + } + $galaitems = array(array("title" => "Galaxie","value" => 0)); + $selectedgala = 0; + foreach ($galalist as $item) { + $galaitem = array("title" => $item, "value" => $item); + if($item == $gala) { + $galaitem['selected'] = "selected"; + $selectedgala = $gala; + } + $galaitems[] = $galaitem; + } + $filter['gala'] = $selectedgala; + $filter['ally'] = $ally; + } else { + if($filter['ally']) { + $form->select("ally",$filter['ally']); + $galalist = getGalaListByAlly($filter['ally'],true); + } else { + $galalist = getGalaList(true); + } + if($filter['undertime']) $form->select("undertime",1); + if($filter['safe']) $form->select("safe",1); + + $galaitems = array(array("title" => "Galaxie","value" => 0)); + $selectedgala = 0; + foreach ($galalist as $item) { + $galaitem = array("title" => $item, "value" => $item); + if($filter['gala'] == $item) { + $galaitem['selected'] = "selected"; + $selectedgala = $filter['gala']; + } + $galaitems[] = $galaitem; + } + $filter['gala'] = $selectedgala; + } + $this->template->assign("galalist",$galaitems); + $sort[$filter['sort']][$filter['order']] = '_active'; + + $list = inc_list($filter,&$pages,&$filter['page'],10,$this->userdata); + + for($i=0;$i < count($list);$i++){ + $canrecallall = 0; + $_incs = inc_list_byuser($list[$i]['gala'],$list[$i]['pos']); + + foreach ($_incs as $inc) { + if($inc['arrival']) { + if ($inc['unixeta'] < 0) { + $inc['orbit'] = true; + $inc['orbittime'] = $this->formattime($inc['unixeta']+$inc['orbittime']*60,true); + $inc['eta'] = 0; + } else { + $inc['eta'] = $this->formattime($inc['unixeta'],true); + $inc['orbittime'] = $this->formattime($inc['orbittime']*60,true); + } + } else { + $inc['eta'] = "n/a"; + } + if(strlen($inc['nick']) > 20){ + $inc['nick'] = substr($nick['nick'],0,20).".."; + } + $inc['canrecall'] = 1; + if($inc['status'] == 1) { + // atter + $list[$i]['atterlist'][] = $inc; + } else { + // deffer + if(!$inc['uid'] || $inc['aid'] == $this->userdata['aid']) { + $inc['canedit'] = 1; + } + $list[$i]['defferlist'][] = $inc; + } + $list[$i]['canrecallall'] = $canrecallall; + $list[$i]['cansetsave'] = 1; + $list[$i]['backlink'] = urlencode("takscreen.php#".$list[$i]['uid']); + } +/* $list[$i]['atterlist'] = atter_list($list[$i]['incid']); + $list[$i]['defferlist'] = deffer_list($list[$i]['incid']); + for($j=0;$j < count($list[$i]['atterlist']);$j++){ + $atter = &$list[$i]['atterlist'][$j]; + + if ($atter['unixeta'] < 0) { + $atter['orbit'] = $atter['unixeta']+75*60; + if ($atter['orbit'] < 0) $atter['orbit'] = 0; + $atter['orbit'] = $this->formattime($atter['orbit'],true); + $atter['unixeta'] = 0; + } + $atter['eta'] = $this->formattime($atter['unixeta'],true); + if(strlen($atter['inickname']) > 20){ + $atter['inickname'] = substr($atter['inickname'],0,20).".."; + } +# if ($atter['ogala'] == $this->userdata['gala']) { + $canrecallall=1; +# } + } + for($j=0;$j < count($list[$i]['defferlist']);$j++){ + $deffer = &$list[$i]['defferlist'][$j]; + if ($deffer['unixeta'] < 0) { + $deffer['orbit'] = $deffer['unixeta']+$deffer['ticks']*15*60; + if ($deffer['orbit'] < 0) $deffer['orbit'] = 0; + $deffer['orbit'] = $this->formattime($deffer['orbit'],true); + $deffer['unixeta'] = 0; + } + $deffer['eta'] = $this->formattime($deffer['unixeta'],true); + if($deffer['isextern']) { + $deffer['nick'] = $deffer['enickname']; + $deffer['gala'] = $deffer['egala']; + $deffer['pos'] = $deffer['epos']; + } + if($deffer['aid'] == $this->userdata['aid']) { + $deffer['canupdatefleet'] = 1; + } + if(strlen($deffer['nick']) > 15){ + $deffer['nick'] = substr($deffer['nick'],0,15).".."; + } + +# if ($deffer['uid'] == $this->userdata['uid'] || +# $deffer['ogala'] == $this->userdata['gala']) { + $deffer['canrecall'] = 1; +# } + } +# if ($list[$i]['gala'] == $this->userdata['gala']) { +# } + $list[$i]['backlink'] = urlencode("takscreen.php#".$list[$i]['incid']); + */ + } + + $form->registerVars($this->template); + $this->template->assign("pages",showPageBar($filter['page'],$pages,"takscreen.php?","page","menu")); + $this->template->assign("allylist",$allylist); + $this->template->assign("sort",$sort); + $this->template->assign("list",$list); + $this->show('takscreen_index', "Taktikschirm"); + } + ############################################################################# + function Incoming_adddeffer() { + $id = param_num("id"); + if ($id && !($inc = getUserByID($id))) $this->_header(); + + if ($_SESSION['steps']['adddeffer']) { + #save step + unset($_SESSION['steps']['adddeffer']); + $_SESSION['steps'] = $data; + $this->forms['information']['action'] =""; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['title'] = "Deffer hinzufügen"; + $this->forms['information']['message'] = "Deffer eingetragen"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Deffer hinzufügen"); + } + $form = new formContainer(); + $form->add(new formInput("tgala","Zielgala","numeric",true,4)); + $form->add(new formInput("tpos","Zielposition","numeric",true,2)); + $form->add(new formInput("gala","Gala vom Deffer","numeric",true,4)); + $form->add(new formInput("pos","Position vom Deffer","numeric",true,2)); + $list = array( + array("title" => "Flotte 1","value" => 1), + array("title" => "Flotte 2","value" => 2) + ); + $form->add(new formSelectBox("fleet","Flotte","numeric",$list,false)); + $form->add(new formInput("time","Flugzeit","string",true,20,false,"'^(?:(\d+?):(\d+?)|(\d+?))$'is")); + $list = array( + array("title" => "extern (360)","value" => 360), + array("title" => "Meta intern (330)","value" => 330), + array("title" => "Allianz intern (300)","value" => 300), + array("title" => "Galaxie intern (270)","value" => 270) + ); + $form->add(new formSelectBox("defftype","Verteidigung","numeric",$list,false)); + $form->add(new formInput("orbit","Zeit im Orbit","string",true,20,false,"'^(?:(\d+):(\d+)|(\d+))$'is")); + if ($_POST['send']) { + $form->submit(); + $tgala = $form->get("tgala"); + $tpos = $form->get("tpos"); + $gala = $form->get("gala"); + $pos = $form->get("pos"); + + #opfer existiert nicht + if (!$form->hasErrors() && !($deffer = getUserByPos($tgala,$tpos))) { + $form->addError("Member existiert nicht im System"); + $form->setError(array("tpos","tgala")); + } + + #kann sich net selber deff0rn + if (!$form->hasErrors() && $tgala == $gala && $tpos == $pos) { + $form->addError("Man kann sich nicht selber deffen"); + $form->setError(array("tgala","tpos","gala","pos")); + } + + #flotte schon eingetragen + if (!$form->hasErrors() && $form->get("fleet") && ($data = fleetstatus_get_bykoords($gala,$pos,$fleet))) { + $form->addError("Flotte ist bereits eingetragen"); + $form->setError(array("gala","pos","fleet")); + } + if(!$form->hasErrors() && ($check = fleetstatus_get_bykoords($gala,$pos)) && count($check) >= 2) { + $form->addError("Es sind bereits 2 Einträge zu ($gala:$pos) vorhanden"); + $form->setError(array("gala","pos","fleet")); + } + if (!$form->hasErrors()) { + $_SESSION['steps']['adddeffer'] = 1; + $time = $form->getRegex("time"); + if(strlen($time[1])) { + $eta = $time[1] * 60 + $time[2]; + } else $eta = $time[3]; + $time = $form->getRegex("orbit"); + if(strlen($time[1])) { + $orbit = $time[1] * 60 + $time[2]; + } else $orbit = $time[3]; + if($eta == 0) { + $orbit = gnticktime($orbit); + } + deffer_add( + $gala,$pos, + $tgala,$tpos, + $form->get("fleet"), + $form->get("defftype"), + $orbit, + $eta + ); + $this->_header("takscreen.php?action=adddeffer&send"); + } + $this->template->assign("errors",$errors); + $this->template->assign("defftype".$items['defftype']['value'],"selected"); + $this->template->assign("tick".$ticks,"selected"); + } else { + if ($inc) { + $form->set("gala",$this->userdata['gala']); + $form->set("pos",$this->userdata['pos']); + $form->set("tgala",$inc['gala']); + $form->set("tpos",$inc['pos']); + if($inc['gala'] == $this->userdata['gala']) { + $form->select("defftype",270); + $form->set("time",$this->formattime(270*60)); + } elseif ($inc['aid'] == $this->userdata['aid']) + { + $form->select("defftype",300); + $form->set("time",$this->formattime(300*60)); + } else { + $form->select("defftype",330); + $form->set("time",$this->formattime(330*60)); + } + if($this->userdata['fleettype'] == 1 || $this->userdata['fleettype'] == 3 || $this->userdata['fleettype'] == 0) { + $form->select("fleet",1); + } else { + $status = fleetstatus_get_byfleetnum($this->userdata['gala'],$this->userdata['pos']); + if(!$status || count($status) == 2 || $status[0]['fleetnum'] == 1) { + $form->select("fleet",2); + } else { + $form->select("fleet",1); + } + } + } else { + $form->select("defftype",330); + $form->set("time",$this->formattime(330*60)); + } + + $form->set("orbit",$this->formattime(300*60)); + } + $form->registerVars($this->template); + $this->show('takscreen_deffer_add', "Deffer hinzufügen"); + } + ############################################################################# +/* function Incoming_deffextern() { + $checkfleet = array("jaeger" => "Jäger","bomber"=>"Bomber", + "fregatten" => "Fregatten","zerstoerer"=>"Zerstörer","kreuzer"=>"Kreuzer", + "schlachter"=>"Schlachter","traeger"=>"Träger","kleptoren"=>"Kleptoren", + "cancris"=>"Cancris","prec"=>"Scangenauigkeit","svs"=>"Scanverstärker"); + $data = $_SESSION['steps']; + if ($data['externdeffer']) { + #save step + unset($data['externdeffer']); + $_SESSION['steps'] = $data; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['action'] =""; + $this->forms['information']['title'] = "externen Deffer melden"; + $this->forms['information']['message'] = "Deffer eingetragen"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "externen Deffer melden"); + } + if ($_POST['send']) { + $this->template->assign("errors",$errors); + $items['gala']['value'] = $_POST['gala']; + $items['pos']['value'] = $_POST['pos']; + #Opfer + if (!$items['gala']['value'] || !is_numeric($items['gala']['value'])) { + $errors[] = "Ungültige Opfergalaxie"; + $items['gala']['class'] = "_error"; + } + if (!$items['pos']['value'] || !is_numeric($items['pos']['value'])) { + $errors[] = "Ungültige Opferposition"; + $items['pos']['class'] = "_error"; + } + #ticks + $items['ticks']['value'] = param_num("ticks",20); + + #deffer + #koords + $items['agala']['value'] = $_POST['agala']; + $items['apos']['value'] = $_POST['apos']; + if (!$items['agala']['value'] || !is_numeric($items['agala']['value'])) { + $errors[] = "Ungültige Deffergalaxie"; + $items['agala']['class'] = "_error"; + } + if (!$items['apos']['value'] || !is_numeric($items['apos']['value'])) { + $errors[] = "Ungültige Defferposition"; + $items['apos']['class'] = "_error"; + } + #nickname + $items['nickname']['value'] = $_POST['nickname']; + if (!$items['nickname']['value']) { + $errors[] = "Fehlender Nickname"; + $items['nickname']['class'] = "_error"; + } + #eta + $items['time']['value'] = $_POST['time']; + if (!isset($items['time']['value'])) { + $errors[] = "Fehlende Ankunftzeit"; + $items['time']['class'] = "_error"; + } else { + if (preg_match("/^(\d+?):(\d+?)$/i",$items['time']['value'],$result)) { + $eta = ($result[1] * 60) + $result[2]; + } elseif (is_numeric($items['time']['value'])) { + $eta = $items['time']['value']; + } else { + $errors[] = "Ungültige Zeit"; + $items['time']['class'] = "_error"; + } + } + #flottendaten + $fleet = array(); + foreach ($checkfleet as $key => $value) { + $items[$key]['value'] = $_POST[$key]; + if ($items[$key]['value']) { + if (!is_numeric($items[$key]['value'])) { + $errors[] = "$value ungültig"; + $items[$key]['class'] = "_error"; + } else { + $fleet[$key] = $items[$key]['value']; + } + } else { + $items[$key]['class'] = "_optional"; + } + } + #flottenummer + $items['fleet']['value'] = $_POST['fleet']; + if ($items['fleet']['value'] != 1 && $items['fleet']['value'] != 2) { + $errors[] = "Flotte ungültig"; + } else { + $this->template->assign("fleet".$items['fleet']['value'],"selected"); + } + #opfer existiert nicht + if (!$errors && !($opfer = getUserByPos($items['gala']['value'],$items['pos']['value']))) { + $items['gala']['class'] = "_error"; + $items['pos']['class'] = "_error"; + $errors[] = "Ziel existiert nicht"; + } + #deffer ist benutzer des tps + if (!$errors && ($deffer = getUserByPos($items['agala']['value'],$items['apos']['value']))) { + $items['agala']['class'] = "_error"; + $items['apos']['class'] = "_error"; + $errors[] = "Koordinaten gehören zu einem Benutzer, muss als intern gemeldet werden !"; + } + #inc gibts net + if (!$errors && !($incdata = inc_get_data($opfer['uid']))) { + $items['gala']['class'] = "_error"; + $items['pos']['class'] = "_error"; + $errors[] = "Ziel hat kein Incoming"; + } + #kann sich net selber deff0rn + if (!$errors && ($items['agala']['value'] == $items['gala']['value'] + && $items['apos']['value'] == $items['pos']['value'])) { + $items['agala']['class'] = "_error"; + $items['apos']['class'] = "_error"; + $items['gala']['class'] = "_error"; + $items['pos']['class'] = "_error"; + $errors[] = "Man kann sich nicht selber deffen"; + } + if (!$errors) { + $data['externdeffer'] = 1; + $_SESSION['steps'] = $data; + deffer_extern_add( + $opfer['uid'], + $items['nickname']['value'], + $items['agala']['value'], + $items['apos']['value'], + $eta, + $items['fleet']['value'], + $fleet, + $items['ticks']['value'] + ); + $this->_header("takscreen.php?action=adddeffextern&send"); + } + $this->template->assign("errors",$errors); + } else { + foreach ($checkfleet as $key => $value) { + $items[$key]['class'] = "_optional"; + } + $items['ticks']['value'] = 20; + } + $this->template->assign("ticklist",$this->getTicklist(20,$items['ticks']['value'])); + $this->template->assign("items",$items); + $this->show('takscreen_deffer_extern', "externen Deffer melden"); + } + +*/ /* ############################################################################# + function Deffer_update() { + $id = param_num("id"); + if(!$id) $this->_header($this->backtracking->backlink(),"fehlende id"); + $deffer = deffer_get($id); + if(!$deffer) $this->_header($this->backtracking->backlink(),"deffer existiert nicht"); + if(!$deffer['isextern']) $this->_header($this->backtracking->backlink(),"deffer ist kein externer deffer"); + $checkfleet = array("jaeger" => "Jäger","bomber"=>"Bomber", + "fregatten" => "Fregatten","zerstoerer"=>"Zerstörer","kreuzer"=>"Kreuzer", + "schlachter"=>"Schlachter","traeger"=>"Träger","kleptoren"=>"Kleptoren", + "cancris"=>"Cancris"); + $data = $_SESSION['steps']; + if ($data['updatedeffer']) { + #save step + unset($data['updatedeffer']); + $_SESSION['steps'] = $data; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['title'] = "externen Deffer updaten"; + $this->forms['information']['message'] = "Deffer erfolgreich upgedated"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Deffer updaten"); + } + if ($_POST['send']) { + #eta + $items['eta']['value'] = $_POST['eta']; + if (!isset($items['eta']['value'])) { + $errors[] = "ETA leer"; + $items['eta']['class'] = "_error"; + } else { + if (preg_match("/^(\d+?):(\d+?)$/i",$items['eta']['value'],$result)) { + $etatime = ($result[1] * 60) + $result[2]; + } elseif (is_numeric($items['eta']['value'])) { + $etatime = $items['eta']['value']; + } else { + $errors[] = "Ungültige Zeit"; + $items['eta']['class'] = "_error"; + } + } + #flottendaten + foreach ($checkfleet as $key => $value) { + $items[$key]['value'] = $_POST[$key]; + if($items[$key]['value']) { + if (!is_numeric($items[$key]['value'])) { + $errors[] = "$value ungültig"; + $items[$key]['class'] = "_error"; + } else { + $fleet[$key] = $items[$key]['value']; + } + } else { + $fleet[$key] = 0; + $items[$key]['value'] = 0; + } + } + #flottenummer + $items['fleet']['value'] = $_POST['fleet']; + if ($items['fleet']['value'] != 1 && $items['fleet']['value'] != 2) { + $errors[] = "Flotte ungültig"; + } else { + $this->template->assign("fleet".$items['fleet']['value'],"selected"); + } + #ticks + $items['ticks']['value'] = param_num("ticks",20); + if (!$errors) { + deffer_extern_update( + $deffer['incid'], + $deffer['defferid'], + $items['fleet']['value'], + $etatime, + $fleet, + $items['ticks']['value'] + ); + $data['updatedeffer'] = 1; + $_SESSION['steps'] = $data; + $this->_header("takscreen.php?action=updatedeffer&id=$id&send"); + } + } else { + #flottendaten + foreach ($checkfleet as $key => $value) { + $items[$key]['value'] = $deffer[$key]; + } + $items['ticks']['value'] = $deffer['ticks']; + $items['eta']['value'] = $this->formattime($deffer['unixeta']); + $this->template->assign("fleet".$deffer['fleetnum'],"selected"); + } + $this->template->assign("ticklist",$this->getTicklist(20,$items['ticks']['value'])); + $this->template->assign("id",$id); + $this->template->assign("errors",$errors); + $this->template->assign("deffer",$deffer); + $this->template->assign("items",$items); + $this->show('takscreen_deffer_update', "Deffer updaten"); + }*/ + + function incoming_fleetstatus() { + if(!($fsid = param_num("id")) || !($status = fleetstatus_get($fsid))) $this->_header(); + if($status['uid']) $this->_header("user.php?action=fleet&id=".$status['uid']."&send"); + $page = param_num("page",1); + $form = new formContainer(); + $form_params = array(); + $form_params[] = array("value" => $this->session['id'],"name" => $this->session['name']); + $form_params[] = array("value" => "fleetstatus","name" => "action"); + $form_params[] = array("value" => $page,"name" => "page"); + $form_params[] = array("value" => 1,"name" => "send"); + $form_params[] = array("value" => $fsid,"name" => "id"); + if($_SESSION['steps']['fleetstatus']) { + $this->template->assign("message",$_SESSION['steps']['fleetstatus']); + unset($_SESSION['steps']['fleetstatus']); + } + + switch ($page) { + // daten ändern + case 1: { + $form->add(new formInput("eta","Verbleibene Flugzeit (ETA)","string",true,255,true,"'^(?:(\d+?):(\d+?)|(\d+?))$'is")); + $list = array( + array("title" => "Flotte 1","value" => 1), + array("title" => "Flotte 2","value" => 2) + ); + $form->add(new formSelectBox("fleetnum","Flotte","numeric",$list,false)); + $form->add(new formInput("orbit","Zeit im Orbit","string",true,255,true,"'^(?:(\d+?):(\d+?)|(\d+?))$'is")); + if($_POST['send']) { + $form->submit(); + $eta = $form->getRegex("eta"); + if(strlen($eta[1])) { + $eta = $eta[1] * 60 + $eta[2]; + } else { + $eta = $eta[3]; + } + if($eta < 0) $eta = 0; + $time = $form->getRegex("orbit"); + if(strlen($time[1])) { + $orbittime = $time[1] * 60 + $time[2]; + } else { + $orbittime = $time[3]; + } + if($orbittime < 0) $orbittime = 0; + if($eta == 0) $orbittime = gnticktime($orbittime); + if(!$form->hasErrors()) { + if($form->get("fleetnum") != $status['fleetnum']) { + fleetstatus_change_fleetnum($status['fsid'],$form->get("fleetnum")); + } + fleetstatus_update($fsid,array("arrival" => gnarrival($eta),"orbittime" => $orbittime)); + $_SESSION['steps']['fleetstatus'] = "Taktikdaten geändert"; + $this->_header("takscreen.php?action=fleetstatus&id=$fsid&page=$page&send"); + } + } else { + if($status['arrival']) { + $eta = $status['arrival'] - time(); + if($eta <= 0) { + if(isset($status['orbittime'])) $orbittime = $status['orbittime']*60+$eta; + $eta = 0; + } else { + $orbittime = $status['orbittime']*60; + } + $form->set("eta",$this->formattime($eta)); + $form->set("orbit",$this->formattime($orbittime)); + } + if($status['fleetnum']) $form->select("fleetnum",$status['fleetnum']); + } + break; + } + // scan laden + case 2: { + $scan = getScan(array("gala" => $status['gala'],"pos" => $status['pos'])); + if($scan['hasunit'] || $scan['hasmili']) { + $scantypes = array(); + if($scan['hasmili']) { + $scantypes[] = "mili"; + $list = array( + array("title" => "Flotte 1","value" => 1), + array("title" => "Flotte 2","value" => 2) + ); + $form->add(new formSelectBox("fleet","Flotte","numeric",$list,false)); + } + if($scan['hasunit']) $scantypes[] = "unit"; + $form->add(new formRadio("scan","Scan laden","string",$scantypes)); + if($_POST['send']) { + $form->submit(); + if(!$form->hasErrors()) { + if($form->get("scan") == "unit") { + // unit laden + $updatefleetdata = fleet_get($scan['unit_fid']); + $updatefleetdata['svs'] = $scan['unit_svs']; + $updatefleetdata['prec'] = $scan['unit_prec']; + $updatefleetdata['fleetnum'] = $status['fleetnum']; + $message = "Einheitenscan"; + } else { + // mili laden + $updatefleetdata = miliscan_fleet_get_bykoords($scan['gala'],$scan['pos'],$form->get("fleet")); + $updatefleetdata['svs'] = $scan['mili_svs']; + $updatefleetdata['prec'] = $scan['mili_prec']; + $updatefleetdata['fleetnum'] = $form->get("fleet"); + $message = "Militärscan Flotte ".$form->get("fleet"); + } + if($form->get("fleetnum") != $updatefleetdata['fleetnum']) { + fleetstatus_change_fleetnum($status['fsid'],$updatefleetdata["fleetnum"]); + } + fleetstatus_update_fleet($fsid,$updatefleetdata,$updatefleetdata['svs'],$updatefleetdata['prec']); + $_SESSION['steps']['fleetstatus'] = $message." wurde geladen"; + $this->_header("takscreen.php?action=fleetstatus&id=$fsid&page=2&send"); + } + } else { + $form->select("scan",$scantypes[0]); + if($scan['hasmili']) $form->select("fleet",$status['fleetnum']); + } + $this->template->assign("scan",scan_format($scan)); + } + break; + } + // manuelle flotteneingabe + case 3: { + $checkfleet = array( + "jaeger" => "Jäger", + "bomber"=>"Bomber", + "fregatten" => "Fregatten", + "zerstoerer"=>"Zerstörer", + "kreuzer"=>"Kreuzer", + "schlachter"=>"Schlachter", + "traeger"=>"Träger", + "kleptoren"=>"Kleptoren", + "cancris"=>"Cancris", + "prec"=>"Scangenauigkeit", + "svs"=>"Scanverstärker" + ); + foreach ($checkfleet as $key => $value) { + $form->add(new formInput($key,$value,"numeric")); + } + if($_POST['send']) { + $form->submit(); + if(!$form->hasErrors()) { + $updatefleetdata = array(); + foreach ($checkfleet as $key => $value) { + $updatefleetdata[$key] = $form->get($key); + } + fleetstatus_update_fleet($fsid,$updatefleetdata,$updatefleetdata['svs'],$updatefleetdata['prec']); + $_SESSION['steps']['fleetstatus'] = "Flottendaten gespeichert"; + $this->_header("takscreen.php?action=fleetstatus&id=$fsid&page=3&send"); + } + } else { + foreach ($checkfleet as $key => $value) { + $form->set($key,$status[$key]); + } + } + break; + } + case 4: { + $form->add(new formInput("code","Text","string")); + if($_POST['send']) { + $form->submit(); + if(!$form->hasErrors()) { + $result = parseWurstFleet($form->get("code")); + if($result !== false) { + fleetstatus_update_fleet($fsid,$result,"0","100"); + $_SESSION['steps']['fleetstatus'] = "Flottendaten gespeichert"; + $this->_header("takscreen.php?action=fleetstatus&id=$fsid&page=4&send"); + } else { + $form->addError("Fehler beim Parsen"); + $form->setError("code"); + } + } + } + } + } + $form->registerVars($this->template); + // baue manuelles flottenupdate formular + if($page == 3) { + $formitems = array(); + foreach($checkfleet as $key => $value) { + $formitems[] = array( + "value" => $form->smartyitems[$key]['value'], + "title" => $form->smartyitems[$key]['title'], + "name" => $key, + "class" => $form->smartyitems[$key]['class'] + ); + } + $this->template->assign("fleetupdateform",$formitems); + } + $this->template->assign(array("status" => $status,"page" => $page,"form_params" => $form_params)); + $this->show('takscreen_fleetstatus',"Flottendaten"); + } + + ############################################################ + function Incoming_addatter () { + $checkfleet = array( + "jaeger" => "Jäger", + "bomber"=>"Bomber", + "fregatten" => "Fregatten", + "zerstoerer"=>"Zerstörer", + "kreuzer"=>"Kreuzer", + "schlachter"=>"Schlachter", + "traeger"=>"Träger", + "kleptoren"=>"Kleptoren", + "cancris"=>"Cancris", + "prec"=>"Scangenauigkeit", + "svs"=>"Scanverstärker" + ); + if ($_SESSION['steps']['addatter']) { + unset($_SESSION['steps']['addatter']); + + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['action'] =""; + $this->forms['information']['title'] = "Incoming melden"; + $this->forms['information']['message'] = "Inc eingetragen"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Incoming melden"); + } + + $form = new formContainer(); + + foreach ($checkfleet as $key => $value) { + $form->add(new formInput($key,$value,"numeric",true,20,true)); + } + + $form->add(new formInput("gala","Zielgalaxie","numeric",true,20)); + $form->add(new formInput("pos","Zielposition","numeric",true,20)); + $form->add(new formInput("agala","Angreifergalaxie","numeric",true,20)); + $form->add(new formInput("apos","Angreiferposition","numeric",true,20)); + $form->add(new formInput("time","ETA bis zur Ankunft","string",true,255)); + + $form->add(new formSelectBox("fleet","Flottennummer","numeric",array(array("title" => "Flotte 1","value" => "1"),array("title" => "Flotte 2","value" => "2")),false)); + + if ($_POST['send']) { + $form->submit(); + if(!$form->hasErrors() && strlen($form->get("time"))) { + $time = $form->get("time"); + if (preg_match("/^(\d+?):(\d+?)$/i",$time,$result)) { + $eta = ($result[1] * 60) + $result[2]; + } elseif (is_numeric($time)) { + $eta = $time; + } else { + $form->setError("time"); + $form->addError("ETA: Ungültige Zeit"); + } + } + $tgala = $form->get("gala"); + $tpos = $form->get("pos"); + $gala = $form->get("agala"); + $pos = $form->get("apos"); + $fleetnum = $form->get("fleet"); + #user existiert nicht + if (!$form->hasErrors() && !($user = user_get_bypos($tgala,$tpos))) { + $form->setError(array("gala","pos")); + $form->adderror("User existiert nicht"); + } + if (!$form->hasErrors() && ($user = user_get_bypos($gala,$pos))) { + $form->setError(array("agala","apos")); + $form->adderror("Angreifer ist Metamitglied!"); + } + foreach ($checkfleet as $key => $item) { + if(strlen($form->get($key))>0) { + if(isset($fleetdata)) $fleetdata = array(); + $fleetdata[$key] = $form->get($key); + } + } + if (!$form->hasErrors() && (!$form->get("fleet") && $fleetdata)) { + $form->adderror("Flottendaten ohne Flottennummer ist nicht zulässig!"); + $form->setError("fleet"); + } + + if (!$form->hasErrors() && (count(fleetstatus_get_bykoords($gala,$pos)) == 2)) { + $form->adderror("Es sind bereits 2 Flotten von $gala:$pos eingetragen"); + $form->setError("fleet"); + } + if (!$form->hasErrors() && $fleetnum && ($info = fleetstatus_get_bykoords($gala,$pos,$fleetnum))) { + $form->adderror("Angreifer bereits eingetragen: attet (".$info['tgala'].":".$info['tpos'].")" ); + $form->setError("fleet"); + $form->setError("agala"); + $form->setError("apos"); + } + if (!$form->hasErrors()) { + atter_add( + $form->get("agala"), + $form->get("apos"), + $form->get("gala"), + $form->get("pos"), + $form->get("fleet"), + $eta, + $fleetdata + ); + + $_SESSION['steps']['addatter'] = 1; + $this->_header("takscreen.php?action=addatter&send"); + } + } + $form->registerVars($this->template); + $this->show('takscreen_atter_add', "Incoming melden"); + } + ############################################################ + /* function Atter_update () { + $id = param_num("id"); + if(!$id) $this->_header($this->backtracking->backlink(),"fehlende id"); + $atter = atter_get($id); + if(!$atter) $this->_header($this->backtracking->backlink(),"atter existiert nicht"); + $checkfleet = array("jaeger" => "Jäger","bomber"=>"Bomber", + "fregatten" => "Fregatten","zerstoerer"=>"Zerstörer","kreuzer"=>"Kreuzer", + "schlachter"=>"Schlachter","traeger"=>"Träger","kleptoren"=>"Kleptoren", + "cancris"=>"Cancris","prec"=>"Scangenauigkeit","svs"=>"Scanverstärker"); + $data = $_SESSION['steps']; + if ($data['updateatter']) { + #save step + unset($data['updateatter']); + $_SESSION['steps'] = $data; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['action'] =""; + $this->forms['information']['title'] = "Atter updaten"; + $this->forms['information']['message'] = "Atter erfolgreich upgedated"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Atter updaten"); + } + if ($_POST['send']) { + #eta + $items['eta']['value'] = $_POST['eta']; + if (!isset($items['eta']['value'])) { + $errors[] = "ETA leer"; + $items['eta']['class'] = "_error"; + } else { + if (preg_match("/^(\d+?):(\d+?)$/i",$items['eta']['value'],$result)) { + $etatime = ($result[1] * 60) + $result[2]; + } elseif (is_numeric($items['eta']['value'])) { + $etatime = $items['eta']['value']; + } else { + $errors[] = "Ungültige Zeit"; + $items['eta']['class'] = "_error"; + } + if (!$etatime) $etatime = 0; + } + #flottendaten + foreach ($checkfleet as $key => $value) { + $items[$key]['value'] = $_POST[$key]; + if($items[$key]['value']) { + if (!is_numeric($items[$key]['value'])) { + $errors[] = "$value ungültig"; + $items[$key]['class'] = "_error"; + } else { + $fleet[$key] = $items[$key]['value']; + } + } + } + if (!$items['prec']['value']) $items['prec']['value'] = 0; + if (!$items['svs']['value']) $items['svs']['value'] = 0; + if($items['prec']['value'] > 100) { + $items['prec']['value'] = 100; + } + #flottenummer + $items['fleet']['value'] = $_POST['fleet']; + if ($items['fleet']['value'] != 1 && $items['fleet']['value'] != 2) { + $errors[] = "Flotte ungültig"; + } else { + $this->template->assign("fleet".$items['fleet']['value'],"selected"); + } + if (!$errors) { + atter_update($id, + $items['prec']['value'], + $items['svs']['value'], + $items['fleet']['value'], + $etatime, + $fleet); + $data['updateatter'] = 1; + $_SESSION['steps'] = $data; + $this->_header("takscreen.php?action=updateatter&id=$id&send"); + } + $this->template->assign("errors",$errors); + } else { + #eta + $items['eta']['value'] = $this->formattime($atter['unixeta']); + #flottendaten + foreach ($checkfleet as $key => $value) { + $items[$key]['value'] = $atter[$key]; + } + $this->template->assign("fleet".$atter['fleetnum'],"selected"); + $items['prec']['value'] = $atter['prec']; + $items['svs']['value'] = $atter['svs']; + } + $this->template->assign("id",$id); + $this->template->assign("atter",$atter); + $this->template->assign("items",$items); + $this->show('takscreen_inc_update', "Atter updaten"); + }*/ +} +?> diff --git a/src/functions/user.class.php b/src/functions/user.class.php new file mode 100644 index 0000000..fafcf65 --- /dev/null +++ b/src/functions/user.class.php @@ -0,0 +1,836 @@ +action]) { + eval("\$this->".$functions[$this->action].";"); + } + #default + $this->_header("index.php"); + } + + function User_activity_check() { + if(!do_check_activity($this->userdata)) $this->_header(); + user_activity_check($this->userdata['uid']); + $this->_header(); + } + + ############################################################################# + function Fleets_list() { + $filter = $_SESSION['userfleetfilter']; + #filter setzen + if (!$filter){ + $galalist = getGalaListbyAlly($this->userdata['aid']); + if (count($galalist)){ + $filter['gala'] = $galalist[0]['gala']; + } + } + $filter['ally'] = $this->userdata['aid']; + $filter['order'] = "asc"; + $filter['sort'] = "koords"; + #filter neu setzen + if ($_POST['subaction'] == "filter") { + $gala = param_num("galaxy"); + } else { + $gala = $filter['gala']; + } + $ally = $filter['ally']; + $galalist = getGalaListbyAlly($ally); + if (count($galalist)) { + if ($gala) { + for($i=0;$i < count($galalist);$i++){ + if($galalist[$i]['gala'] == $gala){ + $filter['gala'] = $gala; + $galalist[$i]['selected'] = "selected"; + break; + } + } + } else { + $gala = $galalist[0]['gala']; + $filter['gala'] = $gala; + } + } else { + unset($filter['gala']); + } + if ($_POST['subaction'] == "filter") { + $_SESSION['userfleetfilter'] = $filter; + } + if ($gala){ + $list = listUser($filter,&$pages,1,12); + for($i=0;$i < count($list);$i++){ + $list[$i]['fleets'] = user_fleet_list_byuser($list[$i]['uid']); + $gesamt = array(); + $gesamt['dir'] = "Gesamt"; + $gesamt['name'] = "Gesamt"; + $gesamt['class'] = "bold"; + $list[$i]['fleets'][0]['name'] = "Orbit"; + $list[$i]['fleets'][1]['name'] = "Flotte 1"; + $list[$i]['fleets'][2]['name'] = "Flotte 2"; + for($j=0;$j < count($list[$i]['fleets']);$j++){ + $fleet = &$list[$i]['fleets'][$j]; + if($fleet['return_flight']) { + $fleet['dir'] = "Rückflug"; + $fleet['class'] = "blue"; + } else { + if ($fleet['status'] == 1) { + $fleet['dir'] = "Angriff"; + $fleet['class'] = "red"; + } + elseif ($fleet['status'] == 2) { + $fleet['dir'] = "Verteidigung"; + $fleet['class'] = "green"; + } else { + $fleet['dir'] = "Im Orbit"; + } + } + if($fleet['tgala']) $fleet['dir'] .= " (".$fleet['tgala'].":".$fleet['tpos'].")"; + $fleet['irc'] = generate_irc_user_fleet($j,$fleet,$list[$i]); + $gesamt['cancris'] += $fleet['cancris']; + $gesamt['kleptoren'] += $fleet['kleptoren']; + $gesamt['fregatten'] += $fleet['fregatten']; + $gesamt['zerstoerer'] += $fleet['zerstoerer']; + $gesamt['bomber'] += $fleet['bomber']; + $gesamt['jaeger'] += $fleet['jaeger']; + $gesamt['schlachter'] += $fleet['schlachter']; + $gesamt['traeger'] += $fleet['traeger']; + $gesamt['kreuzer'] += $fleet['kreuzer']; + } + $gesamt['irc'] = generate_irc_user_fleet(3,$gesamt,$list[$i]); + $list[$i]['fleets'][3] = $gesamt; + if($list[$i]['fleetupdate']) { + $list[$i]['fleetdate'] = formatdate_unix("d.m.Y",$list[$i]['fleetupdate']); + $list[$i]['fleettime'] = date("H:i",$list[$i]['fleetupdate']); + } + } + $this->template->assign('list',$list); + } + $this->template->assign("ally",getAlly($this->userdata['aid'])); + $this->template->assign('galalist',$galalist); + $this->show('userfleets_index',"Flottenpflege"); + } + + ############################################################################# + + function User_fleet() { + $id = param_num("id"); + if ($id) { + $user = getUserByID($id); + if(!$user || $user['aid'] != $this->userdata['aid']) $this->_header(); + $this->template->assign("id",$id); + } else { + $id = $this->userdata['uid']; + $user = $this->userdata; + } + + $deff['rubium'] = $user['rubium']; + $deff['pulsar'] = $user['pulsar']; + $deff['horus'] = $user['horus']; + $deff['coon'] = $user['coon']; + $deff['centurion'] = $user['centurion']; + $this->template->assign("deff",$deff); + $fleets = user_fleet_list_byuser($id); + if($user['fleetupdate']) { + $this->template->assign("fleettime",date("H:i",$user['fleetupdate'])); + $this->template->assign("fleetdate",formatdate_unix("d.m.Y",$user['fleetupdate'])); + } + if($user['deffupdate']) { + $this->template->assign("defftime",date("H:i",$user['deffupdate'])); + $this->template->assign("deffdate",formatdate_unix("d.m.Y",$user['deffupdate'])); + } + for($i=0;$i < 3;$i++){ + if($fleets[$i]['return_flight']) { + $fleets[$i]['dir'] = "Rückflug"; + $fleets[$i]['class'] = "blue"; + } else { + if ($fleets[$i]['status'] == 1) { + $fleets[$i]['dir'] = "Angriff"; + $fleets[$i]['class'] = "red"; + } + elseif ($fleets[$i]['status'] == 2) { + $fleets[$i]['dir'] = "Verteidigung"; + $fleets[$i]['class'] = "green"; + } else { + $fleets[$i]['dir'] = "Im Orbit"; + } + } + if($fleets[$i]['tgala']) $fleets[$i]['dir'] .= " (".$fleets[$i]['tgala'].":".$fleets[$i]['tpos'].")"; + if($fleets[$i]['arrival']) { + $fleets[$i]['eta'] = $fleets[$i]['arrival']-time(); + if ($fleets[$i]['eta'] < 0) { + $fleets[$i]['orbit'] = "noch ".$this->formattime($fleets[$i]['orbittime']*60 + $fleets[$i]['eta'],true)." im Orbit"; + $fleets[$i]['eta'] = 0; + } else { + $fleets[$i]['orbit'] = $this->formattime($fleets[$i]['orbittime']*60,true)." im Orbit"; + } + $fleets[$i]['eta'] = "ETA ".$this->formattime($fleets[$i]['eta'],true); + } + } + $this->template->assign("fleets",$fleets); + $this->template->assign("user",$user); + $this->show("user_fleetupdate","Flottenupdate"); + } + ############################################################################# + + function User_fleet_status() { + $id = param_num("id"); + if ($id) { $this->template->assign("id",$id); } else { $id = $this->userdata['uid']; } + + if(!($user = getUserByID($id)) || $user['aid'] != $this->userdata['aid']) $this->_header(); + + #information message, step 2 + if ($_SESSION['steps']['fleetstatus']) { + #unset step + unset($_SESSION['steps']['fleetstatus']); + $_SESSION['steps'] = $data; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['title'] = "Flottenstatus updaten"; + $this->forms['information']['message'] = "Flottenstatus aktualisiert"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Flottenstatus updaten"); + } + + $fleetnum = param_num("fleet"); + $fleet = user_fleet_bynum($id,$fleetnum); + + if(!$fleet) $this->_header("index.php"); + + $form = new formContainer(); + $form->add(new formInput("target","Zielkoordinaten","string",true,10,true,"'^\s*(\d{1,4}):(\d{1,2})\s*$'is")); + $form->add(new formInput("eta","Flugzeit (ETA)","string",true,10,false,"'^\s*(?:(\d{1,3})|(\d{1,2}):(\d{1,2}))\s*$'is")); + + $status_titles[] = array("title" => "Im Orbit","value"=>0); + $status_titles[] = array("title"=>"Angriffsflug","value" => 1); + $status_titles[] = array("title"=>"Verteidigung","value"=>2); + + if(!$fleet['status']) { + $status_titles[] = array("value"=>3,"title"=>"Rückflug"); + } else { + if($fleet['tgala'] && $fleet['tpos']) { + $galastr = " von ".$fleet['tgala'].":".$fleet['tpos']; + } + if($fleet['status'] == 1) $typestr = "Angriff"; + else $typestr = "Verteidigung"; + $status_titles[] = array("title"=>"Rückflug ".$typestr.$galastr,"value"=>3); + } + + $form->add(new formSelectBox("status","Flottenstatus","numeric",$status_titles,false)); + + $orbit = new formInput("orbit","Zeit im Orbit","string",true,10,false,"'^(?:(\d+):(\d+)|(\d+))$'is"); + $defftype = new formSelectBox("defftype","Verteidigung","numeric", + array( + array("title" => "Galaintern (".$this->formattime(270*60,true).")", "value" => 270), + array("title" => "Allyintern (".$this->formattime(300*60,true).")", "value" => 300), + array("title" => "Meta (".$this->formattime(330*60,true).")", "value" => 330), + array("title" => "extern (".$this->formattime(360*60,true).")", "value" => 360), + ),false); + + if ($_POST['send']) { + $form->submit("status"); + $data['status'] = $form->get("status"); + if($_POST['next_x']) { + switch ($data['status']) { + case 1: { + $form->add(&$orbit); + $form->submit(array("target","orbit","eta")); + $data['returntime'] = 450; + break; + } + case 2: { + $form->add(&$orbit); + $form->add(&$defftype); + $form->submit(array("target","orbit","defftype","eta")); + $data['returntime'] = $form->get("defftype"); + break; + } + case 3: { + $form->submit("eta"); + } + } + + if (!$form->hasErrors()) { + // save step + if($data['status'] == 3) { + $eta = $form->getregex("eta"); + if($eta[1]) $eta = $eta[1]; + else $eta = $eta[2]*60+$eta[3]; + if($eta < 0) $eta = 0; + $data['arrival'] = gnarrival($eta); + } + if($data['status'] == 1 || $data['status'] == 2) { + $eta = $form->getregex("eta"); + if($eta[1]) $eta = $eta[1]; + else $eta = $eta[2]*60+$eta[3]; + + $orbit = $form->getregex("orbit"); + if($orbit[1]) $orbit = $orbit[1]*60+$orbit[2]; + else $orbit = $orbit[3]; + + + if($eta == 0){ + $data['orbittime'] = gnticktime($orbit); + $data['arrival'] = time(); + } else { + $data['arrival'] = gnarrival($eta); + $data['orbittime'] = $orbit; + } + $target = $form->getRegex("target"); + $data['tgala'] = $target[1]; + $data['tpos'] = $target[2]; + $data['return_flight'] = 0; + } + if($data['status'] == 1 && $data['tgala'] && (user_get_bypos($data['tgala'],$data['tpos']))) { + $form->setError("target"); + $form->addError("Ziel ist Metamuitglied"); + } + } + if (!$form->hasErrors()) { + $_SESSION['steps']['fleetstatus'] = 1; + if($data['status'] == 3) { + $data['status'] = $fleet['status']; + $data['tgala'] = $fleet['tgala']; + $data['tpos'] = $fleet['tpos']; + $data['return_flight'] = 1; + } + $data['fleetnum'] = $fleetnum; + $data['gala'] = $user['gala']; + $data['pos'] = $user['pos']; + $data['fid'] = $fleet['fid']; + if($data['status'] || $data['return_flight']) { + if($fleet['fsid']) { + fleetstatus_update($fleet['fsid'],$data); + } else { + #$check = fleetstatus_get_byfleetnum($user['gala'],$user['pos'],true); + #if(count($check) >= 2) fleetstatus_delete($check[0]['fsid']); + fleetstatus_add($data); + } + } else { + if($fleet['fsid']) fleetstatus_delete($fleet['fsid']); + } + $this->_header("user.php?action=fleetstatus&send"); + } + } else { + if($data['status'] == 1) $form->add(&$orbit); + if($data['status'] == 2) {$form->add(&$orbit);$form->add(&$defftype);} + + if($data['status'] == 1) { + if($data['status'] == $fleet['status'] && !$fleet['return_flight']) { + $form->set("orbit",$this->formattime($fleet['orbittime']*60)); + if($fleet['tgala']) { + $form->set("target","$fleet[tgala]:$fleet[tpos]"); + } + } else { + $form->set("orbit",$this->formattime(75*60)); + } + } + if($data['status'] == 2) { + if($data['status'] == $fleet['status'] && !$fleet['return_flight']) { + $defftype->select($fleet['returntime']); + $form->set("orbit",$this->formattime($fleet['orbittime']*60)); + if($fleet['tgala']) { + $form->set("target",$fleet['tgala'].":".$fleet['tpos']); + } + } else { + $form->set("orbit",$this->formattime(300*60)); + $defftype->select(360); + } + } + if (($fleet['status'] == 2 || $fleet['status'] == 1) && $data['status'] == 3 && !$fleet['return_flight']) { + $eta = $fleet['arrival']-time(); + if($eta < 0) $eta = 0; + $form->set("eta",$this->formattime($fleet['returntime']*60-$eta)); + } + if($data['status'] == $fleet['status'] || $data['status'] == 3 && $fleet['return_flight']) { + $form->set("eta",$this->formattime($fleet['arrival']-time())); + } + } + } else { + if($fleet['return_flight'] ) { + $data['status'] = 3; + } else { + $data['status'] = $fleet['status']; + if(($fleet['status'] == 1 || $fleet['status'] == 2) && $fleet['tgala']) { + $form->set("target",$fleet['tgala'].":".$fleet['tpos']); + } + } + $form->select("status",$data['status']); + #$form->set("status",$data['status']); + if($data['status'] == 1 || $data['status'] == 2) { + $form->add(&$orbit); + } + if ($fleet['arrival']) { + $eta = $fleet['arrival']-time(); + if($eta < 0) $eta_exact = 0; else $eta_exact = $eta; + $form->set("eta",$this->formattime($eta_exact)); + } + if($data['status'] == 2) { + if($fleet['orbittime']) { + if($eta < 0) $orbittime = $fleet['orbittime']*60+$eta; else $orbittime = $fleet['orbittime']*60; + $form->set("orbit",$this->formattime($orbittime)); + } + } + if($data['status'] == 1) { + #echo "eta: ".($eta/60)."
    "; + if($fleet['orbittime']) { + if($eta < 0) $orbittime = $fleet['orbittime']*60+$eta; else $orbittime = $fleet['orbittime']*60; + $form->set("orbit",$this->formattime($orbittime)); + } + } + if($data['status'] == 2) { + $form->add(&$defftype); + $form->select("defftype",$fleet['returntime']); + } + } + + $form->registerVars(&$this->template); + + $this->template->assign("fleet",$fleetnum); + $this->show("user_fleetstatus","Flottenstatus updaten"); + } + ############################################################################# + function User_fleet_parser() { + $id = param_num("id"); + if ($id) { + $user = getUserByID($id); + if(!$user) $this->_header(); + $this->template->assign("id",$id); + } else { + $id = $this->userdata['uid']; + } + $data = $_SESSION['steps']; + #information message, step 2 + if ($data['fleetparser']) { + #unset step + unset($data['fleetparser']); + $_SESSION['steps'] = $data; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['title'] = "Flotte/Deff updaten"; + $this->forms['information']['message'] = "Flotte/Deff aktualisiert"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Flotte/Deff updaten"); + } + $form = new formContainer(); + $form->add(new formInput("fleet","Text","string")); + if ($_POST['send'] && $_POST['next_x']) { + $form->submit(); + if(!$form->hasErrors()) { + $text = $form->get("fleet"); + if(!($taktik = parse_taktikansicht($text))) { + $fleets = parse_user_flottenbewegung($text,$this->userdata["gala"],$this->userdata["pos"]); + //echo "
    ".print_r($fleets,1)."
    "; + $deff = parse_user_verteidigung($text); + if($fleets === false && $deff === false) { + $form->setError("fleet"); + $form->addError("es konnte nichts erkannt werden"); + } + } else { + $fleets = $taktik[0]['fleets']; + $deff = $taktik[0]['deff']; + } + if(!$form->hasErrors()) { + $_SESSION['steps']['fleetparser'] = 1; + if(!($fleets === false)) { + user_fleets_update($id,$fleets); + } + if(!($deff === false)) { + user_deff_update($id,$deff); + } + $this->_header("user.php?action=fleetparser&send"); + } + } + } + $form->registerVars($this->template); + $this->show("user_fleetupdate_parser","Flottenupdate"); + } + ############################################################################# + function User_fleet_manuell() { + $id = param_num("id"); + if ($id) { + $user = getUserByID($id); + if(!$user || $user['aid'] != $this->userdata['aid']) $this->_header(); + $this->template->assign("id",$id); + } else { + $id = $this->userdata['uid']; + } + $data = $_SESSION['steps']; + #information message, step 2 + if ($data['fleetmanuell']) { + #unset step + unset($data['fleetmanuell']); + $_SESSION['steps'] = $data; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['title'] = "Flotte updaten"; + $this->forms['information']['message'] = "Flotte aktualisiert"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Flotte updaten"); + } + $names = array("Jäger"=>"jaeger","Bomber"=>"bomber","Fregatten"=>"fregatten","Zerstörer"=>"zerstoerer","Kreuzer"=>"kreuzer","Schlachtschiffe"=>"schlachter","Träger"=>"traeger","Kleptoren"=>"kleptoren","Schutzschiffe"=>"cancris"); + $fleets = user_fleet_list_byuser($id); + $form = new formContainer(); + foreach ($names as $title => $name) { + for ($i=0;$i<3;$i++) { + $form->add(new formInput($name.$i,$title,"numeric")); + } + } + if ($_POST['send'] && $_POST['next_x']) { + $form->submit(); + if (!$form->hasErrors()){ + $_result = array(); + foreach ($fleets as $fleet) { + foreach ($names as $title => $name) { + $_result[$fleet['fleetnum']][$name] = $form->get($name.$fleet['fleetnum']); + } + } + user_fleets_update($id,$_result); + $_SESSION['steps']['fleetmanuell'] = 1; + $this->_header("user.php?action=fleetmanuell&send"); + } + } else { + foreach($fleets as $fleet){ + $num = $fleet['fleetnum']; + foreach ($names as $key => $name){ + $val = &$fleet[$name]; + if ($val){ + $form->set($name.$num,$val); + } else { + $form->set($name.$num,0); + } + } + } + } +# $this->template->assign("errors",$errors); +# $this->template->assign("items",$items); + $form->registerVars($this->template); + $this->show("user_fleetupdate_manuell","Flottenupdate"); + } + ############################################################################# + function User_orbit_manuell() { + $id = param_num("id"); + if ($id) { + $user = getUserByID($id); + if(!$user || $user['aid'] != $this->userdata['aid']) $this->_header(); + $this->template->assign("id",$id); + } else { + $id = $this->userdata['uid']; + } + $data = $_SESSION['steps']; + #information message, step 2 + if ($data['orbitmanuell']) { + #unset step + unset($data['orbitmanuell']); + $_SESSION['steps'] = $data; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['title'] = "Verteidigung updaten"; + $this->forms['information']['message'] = "Verteidigung aktualisiert"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Verteidigung updaten"); + } + $names = array("Abfangjäger"=>"horus","Rubis"=>"rubium","Pulsare"=>"pulsar","Coons"=>"coon","Centurions"=>"centurion"); + if ($_POST['send'] && $_POST['next_x']) { + foreach ($names as $key => $name){ + $val = trim($_POST[$name]); + if (strlen($val)){ + if ((is_numeric($val) && $val >= 0)) { + $deff[$name]= $val; + } else { + $errors[] = "$key ungültig"; + $items[$name]['class'] = "_error"; + } + $items[$name]['value'] = $val; + } + } + if (!$errors){ + $data['orbitmanuell'] = 1; + $_SESSION['steps'] = $data; + User_deff_update($id,$deff); + $this->_header("user.php?action=orbitmanuell&send"); + } + } else { + $deff = User_deff_get($id); + foreach ($names as $key => $name){ + $val = $deff[$name]; + if ($val){ + $items[$name]['value'] = $val; + } else { + $items[$name]['value'] = 0; + } + } + } + $this->template->assign("errors",$errors); + $this->template->assign("items",$items); + $this->show("user_orbitalupdate_manuell","Orbitalverteidigung updaten"); + } + ############################################################################# + function User_orbit_parser() { + $id = param_num("id"); + if ($id) { + $user = getUserByID($id); + if(!$user || $user['aid'] != $this->userdata['aid']) $this->_header(); + $this->template->assign("id",$id); + } else { + $id = $this->userdata['uid']; + } + $data = $_SESSION['steps']; + #information message, step 2 + if ($data['orbitparser']) { + #unset step + unset($data['orbitparser']); + $_SESSION['steps'] = $data; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['title'] = "Verteidigung updaten"; + $this->forms['information']['message'] = "Verteidigung aktualisiert"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Verteidigung updaten"); + } + $names = array("Horus"=>"horus","Rubium"=>"rubium","Pulsar"=>"pulsar","Coon"=>"coon","Centurion"=>"centurion"); + if ($_POST['send'] && $_POST['next_x']) { + $val = stripslashes(param_str("deff")); + $items['deff']['value'] = $val; + if (!$val){ + $errors[] = "Feld ist leer!"; + $items['deff']['class'] = "_error"; + } else { + if(preg_match("/^.*?". + "Leichtes Orbitalgeschütz \"Rubium\":.*?(\d+?)\s*?". + "Leichtes Raumgeschütz \"Pulsar\":.*?(\d+?)\s*?". + "Mittleres Raumgeschütz \"Coon\":.*?(\d+?)\s*?". + "Schweres Raumgeschütz \"Centurion\":.*?(\d+?)\s*?". + "Abfangjäger \"Horus\":.*?(\d+?)\s*?". + "$/si",$val,$result)) { + $deff['rubium'] = $result[1]; + $deff['pulsar'] = $result[2]; + $deff['coon'] = $result[3]; + $deff['centurion'] = $result[4]; + $deff['horus'] = $result[5]; + } else { + $errors[] = "Verteidigung nicht erkannt!"; + $items['deff']['class'] = "_error"; + } + } + if (!$errors){ + $data['orbitparser'] = 1; + $_SESSION['steps'] = $data; + User_deff_update($id,$deff); + $this->_header("user.php?action=orbitparser&send"); + } + } + $this->template->assign("errors",$errors); + $this->template->assign("items",$items); + $this->show("user_orbitalupdate_parser","Orbitalverteidigung updaten"); + } ############################################################################# + # + # Password ändern + # + function changePassword() { + $data = $_SESSION['steps']; + #information message, step 2 + if ($data['changepwd']) { + #save registration step + unset($data['changepwd']); + $_SESSION['steps'] = $data; + $this->forms['information']['action'] = ""; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['title'] = "Passwort ändern"; + $this->forms['information']['message'] = "Passwortänderung erfolgreich"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Passwort ändern"); + } + #formular send + if ($_REQUEST['step']) { + $items['oldpassword'] = param_str("oldpassword",true);; + $items['password'] = param_str("password",true); + $items['password2'] = param_str("password2",true); + $errors = false; + #check if empty + foreach ( $items as $key => $value) { + if (!$value) { + $this->forms['changepwd']['fields'][$key]['error'] = 'Feld darf nicht leer sein!'; + $this->forms['changepwd']['fields'][$key]['bgrd'] = '_error'; + $errors = true; + } else { + $this->forms['changepwd']['fields'][$key]['value'] = $value; + } + } + #check passwords + if (!$errors && $items['password'] != $items['password2']) { + $errors = true; + $this->forms['changepwd']['fields']['password']['error'] = 'Passwörter müssen gleich sein!'; + $this->forms['changepwd']['fields']['password']['bgrd'] = '_error'; + $this->forms['changepwd']['fields']['password2']['error'] = 'Passwörter müssen gleich sein!'; + $this->forms['changepwd']['fields']['password2']['bgrd'] = '_error'; + } + #check old password + if (!$errors && $this->userdata['password'] != md5($items['oldpassword'])) { + $errors = true; + $this->forms['changepwd']['fields']['oldpassword']['error'] = 'Passwort ungültig!'; + $this->forms['changepwd']['fields']['oldpassword']['bgrd'] = '_error'; + } + if (!$errors) { + updateUserPassword($this->userdata['uid'],$items['password']); + $sessionuserdata['id'] = $this->userdata['uid']; + $sessionuserdata['password'] = md5($items['password']); + $_SESSION['sessionuserdata'] = $sessionuserdata; + addToLogfile("Passwort geändert","User",$this->userdata['uid']); + + #save step + $data['changepwd'] = 1; + $_SESSION['steps'] = $data; + $this->_header("user.php?action=changepwd&send"); + } + } + if ($this->userdata['changepw']) { + $this->forms['changepwd']['message'] = "Sie müssen ihr Passwort jetzt ändern !"; + } + $this->forms['changepwd']['url'] = 'user.php'; + $this->forms['changepwd']['action'] = 'changepwd'; + $this->show('user_changepwd_form',"Passwort ändern"); + } + # + # ändert die Benutzerdaten + # + function UserSettings() { + $data = $_SESSION['steps']; + #information message, step 2 + if ($data['usersettings']) { + #save step + unset($data['usersettings']); + $_SESSION['steps'] = $data; + $this->forms['information']['action'] = ""; + $this->forms['information']['url'] = $this->backtracking->backlink(); + $this->forms['information']['title'] = "Benutzerdaten ändern"; + $this->forms['information']['message'] = "Änderung erfolgreich"; + $this->forms['information']['style'] = "green"; + $this->show('message_information', "Benutzerdaten ändern"); + } + #formular send + if ($_REQUEST['step']) { + $items['email']['value'] = param_str("email",true); + $items['nick']['value'] = param_str("nick",true); + $items['login']['value'] = param_str("login",true); + $items['svs']['value'] = param_num("svs",0); + $items['fleettype']['value'] = param_num("fleettype",1); + $items['scantype']['value'] = param_num("scantype",0); + $items['timeview']['value'] = param_num("timeview",0); + + if (!$items['email']['value']) { + $errors[] = "Email fehlt!"; + $items['email']['bgrd'] = "_error"; + } + if (!$items['nick']['value']) { + $errors[] = "GN Nickname fehlt!"; + $items['nick']['bgrd'] = "_error"; + } + if (!$items['login']['value']) { + $errors[] = "Login fehlt!"; + $items['login']['bgrd'] = "_error"; + } + if ($_POST['emailvisible']) { + $items['emailvisible']['value'] = 1; + } else { + $items['emailvisible']['value'] = 0; + } + #optional parameters + $items['phone']['value'] = param_str("phone",true); + + #check nickname + if ($items['nick']['value'] && strtolower($items['nick']['value']) != strtolower($this->userdata['nick']) && getUserByNick($items['nick']['value'])) { + $errors[] = "Nickname existiert bereits"; + $items['nick']['bgrd'] = "_error"; + } + #check login + if ($items['login']['value'] && strtolower($items['login']['value']) != strtolower($this->userdata['login']) && getUserByLogin($items['login']['value'])) { + $errors[] = "Login bereits vergeben"; + $items['login']['bgrd'] = "_error"; + } + if (!$errors) { + #save step + $data['usersettings'] = 1; + $_SESSION['steps'] = $data; + addToLogfile("Benutzereinstellungen geändert","User",$this->userdata['uid']); + updateUser($this->userdata['uid'], + $items['nick']['value'], + $items['login']['value'], + $items['email']['value'], + $items['emailvisible']['value'], + $items['phone']['value'], + $items['scantype']['value'], + $items['svs']['value'], + $items['timeview']['value'], + $items['fleettype']['value'] + ); + $this->_header("user.php?action=settings&send"); + } + } else { + $items['login']['value'] = $this->userdata['login']; + $items['nick']['value'] = $this->userdata['nick']; + $items['email']['value'] = $this->userdata['email']; + $items['emailvisible']['value'] = $this->userdata['emailvisible']; + $items['phone']['value'] = $this->userdata['phone']; + $items['scantype']['value'] = $this->userdata['scantype']; + $items['svs']['value'] = $this->userdata['svs']; + $items['timeview']['value'] = $this->userdata['timeview']; + $items['fleettype']['value'] = $this->userdata['fleettype']; + } + if (!$items['phone']['value']) { + $items['phone']['bgrd'] = "_optional"; + } + $this->template->assign("scantype".$items['scantype']['value'],"checked"); + $this->template->assign("timeview".$items['timeview']['value'],"checked"); + $this->template->assign("fleettype".$items['fleettype']['value'],"checked"); + $this->template->assign("errors",$errors); + $this->template->assign("items",$items); + $this->show('user_settings_form',"Benutzerdaten ändern"); + } + # + # Zeigt Benutzerinfos + # + function showUserDetails() { + $id = param_num("id"); + if (!$id) $this->_header($this->backtracking->backlink()); + $return = getUserByID($id); + if (!$return) $this->_header($this->backtracking->backlink()); + $this->forms['userdetails']['registerdate'] = $return['registerdate']; + $this->forms['userdetails']['nickname'] = $return['nick']; + $this->forms['userdetails']['allyname'] = $return['name']; + $this->forms['userdetails']['allytag'] = $return['tag']; + if($return['emailvisible']) { + $this->forms['userdetails']['email'] = $return['email']; + } + $this->forms['userdetails']['koords'] = $return['gala'].":".$return['pos']; + if($return['usertitle']) { + $this->forms['userdetails']['usertitle'] = $return['usertitle']; + } + if($return['phone']) { + $this->forms['userdetails']['phone'] = $return['phone']; + } + $this->show('user_details',"Benutzerdetails"); + } +} +?> \ No newline at end of file diff --git a/src/functions/xml.auth.php b/src/functions/xml.auth.php new file mode 100644 index 0000000..3a3d406 --- /dev/null +++ b/src/functions/xml.auth.php @@ -0,0 +1,32 @@ +getParam(0); + $login = $login->scalarval(); + $password = $p->getParam(1); + $password = $password->scalarval(); + $bot = bot_get_bylogin($login,$password); + if (!$bot) return new xmlrpcresp(new xmlrpcval("Oo")); + $authstring = md5(time().$bot['botid'].rand(1,100)."kibocenter botmanagement"); + bot_firstauth($bot['botid'],$authstring); + return new xmlrpcresp(new xmlrpcval($authstring)); +} + + + +function soap_refreshauth($auth){ + if (!($bot = check_auth($auth))) return null; + $authstring = md5(time().$bot['botid'].rand(1,100)."kibocenter botmanagement"); + bot_refreshauth($bot['botid'],$authstring); + return $authstring; +} +?> \ No newline at end of file diff --git a/src/functions/xml.scans.php b/src/functions/xml.scans.php new file mode 100644 index 0000000..41b4076 --- /dev/null +++ b/src/functions/xml.scans.php @@ -0,0 +1,208 @@ + "xmlrpc_scan_get","signature" => array(array("struct","int","int"))); + +/** + * Returns true if $string is valid UTF-8 and false otherwise. + * + * @since 1.14 + * @param [mixed] $string string to be tested + * @subpackage + */ +function is_utf8($string) { + + // From http://w3.org/International/questions/qa-forms-utf-8.html + return preg_match('%^(?: + [\x09\x0A\x0D\x20-\x7E] # ASCII + | [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte + | \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs + | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte + | \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates + | \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3 + | [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15 + | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16 + )*$%xs', $string); + +} + +function fleet2xml($fleet) { + $data = array(); + $data['kleptoren'] = new XML_RPC_Value($fleet['kleptoren'],"int"); + $data['cancris'] = new XML_RPC_Value($fleet['cancris'],"int"); + $data['fregatten'] = new XML_RPC_Value($fleet['fregatten'],"int"); + $data['zerstoerer'] = new XML_RPC_Value($fleet['zerstoerer'],"int"); + $data['kreuzer'] = new XML_RPC_Value($fleet['kreuzer'],"int"); + $data['schlachter'] = new XML_RPC_Value($fleet['schlachter'],"int"); + $data['traeger'] = new XML_RPC_Value($fleet['traeger'],"int"); + $data['jaeger'] = new XML_RPC_Value($fleet['jaeger'],"int"); + $data['bomber'] = new XML_RPC_Value($fleet['bomber'],"int"); + if(isset($fleet['status'])) $data['status'] = new XML_RPC_Value($fleet['status'],"int"); + if(isset($fleet['return_flight'])) $data['return_flight'] = new XML_RPC_Value($fleet['return_flight'],"int"); + if(isset($fleet['type'])) $data['type'] = new XML_RPC_Value(utf8_encode($fleet['type'])); + if(isset($fleet['dir'])) $data['dir'] = new XML_RPC_Value(utf8_encode($fleet['dir'])); + return new XML_RPC_Value($data,"struct"); +} + +function xmlrpc_scan_get($params) { + global $timeout,$xmlrpc_errors,$logger; + + $gala = $params->getParam(0); + $pos = $params->getParam(1); + $scan = getScan(array("gala"=>$gala->scalarval(),"pos"=>$pos->scalarval(),"hideold"=>1),$timeout); + if(!$scan) { + $logger->debug("scan not found"); + return new XML_RPC_Response(0,$xmlrpc_errors["scan_not_found"]["code"],$xmlrpc_errors["scan_not_found"]["msg"]); + } else { + $logger->debug(var_export($scan,true)); + } + $data = array(); + $data['nick'] = new XML_RPC_Value(utf8_encode($scan['nick'])); + $data['gala'] = new XML_RPC_Value($scan['gala'],"int"); + $data['pos'] = new XML_RPC_Value($scan['pos'],"int"); + if ($scan['hassector']) { + $data['hassector'] = new XML_RPC_Value(true,"boolean"); + $data['sector_prec'] = new XML_RPC_Value($scan['sector_prec'],"int"); + if($scan['sector_svs']) $data['sector_svs'] = new XML_RPC_Value($scan['sector_svs'],"int"); + if($scan['sector_scanner']) $data['sector_scanner'] = new XML_RPC_Value(utf8_encode($scan['sector_scanner'])); + $data['sector_scanage'] = new XML_RPC_Value($scan['sector_scanage']); + $data['sector_ships'] = new XML_RPC_Value($scan['sector_ships'],"int"); + $data['sector_deff'] = new XML_RPC_Value($scan['sector_deff'],"int"); + $data['sector_exen'] = new XML_RPC_Value($scan['sector_exen'],"int"); + $data['sector_kristall'] = new XML_RPC_Value($scan['sector_kristall'],"int"); + $data['sector_metall'] = new XML_RPC_Value($scan['sector_metall'],"int"); + $data['sector_roids'] = new XML_RPC_Value($scan['sector_roids'],"int"); + $data['sector_punkte2'] = new XML_RPC_Value($scan['sector_punkte2']); + $data['sector_timeout'] = new XML_RPC_Value((boolean)$scan['sector_timeout'],"boolean"); + } else { + $data['hassector'] = new XML_RPC_Value(false,"boolean"); + } + if($scan['hasgscan']) { + $data['hasgscan'] = new XML_RPC_Value(true,"boolean"); + + if($scan['gscan_horus']) $data['gscan_horus'] = new XML_RPC_Value($scan['gscan_horus'],"int"); + if($scan['gscan_rubium']) $data['gscan_rubium'] = new XML_RPC_Value($scan['gscan_rubium'],"int"); + if($scan['gscan_pulsar']) $data['gscan_pulsar'] = new XML_RPC_Value($scan['gscan_pulsar'],"int"); + if($scan['gscan_coon']) $data['gscan_coon'] = new XML_RPC_Value($scan['gscan_coon'],"int"); + if($scan['gscan_centurion']) $data['gscan_centurion'] = new XML_RPC_Value($scan['gscan_centurion'],"int"); + + $data['gscan_prec'] = new XML_RPC_Value($scan['gscan_prec'],"int"); + $data['gscan_scanage'] = new XML_RPC_Value($scan['gscan_scanage']); + $data['gscan_timeout'] = new XML_RPC_Value((boolean)$scan['gscan_timeout'],"boolean"); + + if($scan['gscan_svs']) $data['gscan_svs'] = new XML_RPC_Value($scan['gscan_svs'],"int"); + if($scan['gscan_scanner']) $data['gscan_scanner'] = new XML_RPC_Value(utf8_encode($scan['gscan_scanner'])); + } else { + $data['hasgscan'] = new XML_RPC_Value(false,"boolean"); + } + if($scan['hasunit']) { + $data['hasunit'] = new XML_RPC_Value(true,"boolean"); + $data['unit_prec'] = new XML_RPC_Value($scan['unit_prec'],"int"); + + $data['kleptoren'] = new XML_RPC_Value($scan['kleptoren'],"int"); + $data['cancris'] = new XML_RPC_Value($scan['cancris'],"int"); + $data['fregatten'] = new XML_RPC_Value($scan['fregatten'],"int"); + $data['zerstoerer'] = new XML_RPC_Value($scan['zerstoerer'],"int"); + $data['kreuzer'] = new XML_RPC_Value($scan['kreuzer'],"int"); + $data['schlachter'] = new XML_RPC_Value($scan['schlachter'],"int"); + $data['traeger'] = new XML_RPC_Value($scan['traeger'],"int"); + $data['jaeger'] = new XML_RPC_Value($scan['jaeger'],"int"); + $data['bomber'] = new XML_RPC_Value($scan['bomber'],"int"); + + $data['unit_scanage'] = new XML_RPC_Value($scan['unit_scanage']); + $data['unit_timeout'] = new XML_RPC_Value((boolean)$scan['unit_timeout'],"boolean"); + if($scan['unit_svs']) $data['unit_svs'] = new XML_RPC_Value($scan['unit_svs'],"int"); + if($scan['unit_scanner']) $data['unit_scanner'] = new XML_RPC_Value(utf8_encode($scan['unit_scanner'])); + } else { + $data['hasunit'] = new XML_RPC_Value(false,"boolean"); + } + if($scan['hasmili']) { + $data['hasmili'] = new XML_RPC_Value(true,"boolean"); + + $fleets = array(); + + $fleets[0] = fleet2xml($scan['mili_fleets'][0]); + $fleets[1] = fleet2xml($scan['mili_fleets'][1]); + $fleets[2] = fleet2xml($scan['mili_fleets'][2]); + + $data['mili_fleets'] = new XML_RPC_Value($fleets,"array"); + $data['mili_prec'] = new XML_RPC_Value($scan['mili_prec'],"int"); + $data['mili_scanage'] = new XML_RPC_Value($scan['mili_scanage']); + $data['mili_timeout'] = new XML_RPC_Value((boolean)$scan['mili_timeout'],"boolean"); + if($scan['mili_svs']) $data['mili_svs'] = new XML_RPC_Value($scan['mili_svs'],"int"); + if($scan['mili_scanner']) $data['mili_scanner'] = new XML_RPC_Value(utf8_encode($scan['mili_scanner'])); + } else { + $data['hasmili'] = new XML_RPC_Value(false,"boolean"); + } + if($scan['hasnews']) { + $data['hasnews'] = new XML_RPC_Value(true,"boolean"); + + $data['news_data'] = new XML_RPC_Value(utf8_encode($scan['news_newsdata'])); + $data['news_prec'] = new XML_RPC_Value($scan['news_prec'],"int"); + $data['news_scanage'] = new XML_RPC_Value($scan['news_scanage']); + $data['news_timeout'] = new XML_RPC_Value((boolean)$scan['news_timeout'],"boolean"); + if($scan['news_svs']) $data['news_svs'] = new XML_RPC_Value($scan['news_svs'],"int"); + if($scan['news_scanner']) $data['news_scanner'] = new XML_RPC_Value(utf8_encode($scan['news_scanner'])); + } else { + $data['hasnews'] = new XML_RPC_Value(false,"boolean"); + } + return new XML_RPC_Response(new XML_RPC_Value($data,"struct")); +} + +$xmlrpc_methods["scan.add"] = array("function" => "xmlrpc_scan_add","signature" => array(array("boolean","struct"))); + +function xmlrpc_scan_add($params) { + global $logger; + $data = XML_RPC_Decode($params->getParam(0)); + if($data['type'] == "mili") { + $data['fleets'][0] = $data['fleet'][0]; + $data['fleets'][1] = $data['fleet'][1]; + $data['fleets'][2] = $data['fleet'][2]; + for($i =0;$i < 3;$i++) { + $data['fleets'][$i]["type"] = utf8_decode($data['fleet'][$i]["type"]); + $data['fleets'][$i]["dir"] = utf8_decode($data['fleet'][$i]["dir"]); + } + unset($data['fleet']); + } + if($data['type'] == "news") { + $data["newsdata"] = utf8_decode($data["newsdata"]); + } + $logger->debug("add scan, data: ".var_export($data,true)); + updateScan($data); + return new XML_RPC_Response(new XML_RPC_Value(true,"boolean")); +} + + +function xmlrpc_scans_addmili($auth,$gala,$pos,$nick,$prec,$orbit,$fleet1,$fleet2,$svs,$scanner){ + $fleets[0] = tfa($orbit); + $fleets[1] = tfa($fleet1); + $fleets[2] = tfa($fleet2); + $scan = array("gala" => $gala, "pos" => $pos, "nick" => $nick, "prec" => trim($prec), "fleets"=>$fleets, "type" => "mili", "svs" => trim($svs) , "scanner" => trim($scanner)); + updateScan($scan); +} + +function xmlrpc_scans_addsector($auth,$scan){ + $scan = tfa($scan); + $scan['punkte'] = trim(preg_replace("/\./s","",$scan['punkte'])); + updateScan($scan); +} + +function xmlrpc_scans_addunit($auth,$scan){ + $scan = tfa($scan); + updateScan($scan); +} + +function xmlrpc_scans_addgscan($auth,$scan){ + $scan = tfa($scan); + updateScan($scan); +} + +function xmlrpc_scans_addnews($auth,$scan){ + $scan = tfa($scan); + updateScan($scan); +} + +?> diff --git a/src/functions/xml.user.php b/src/functions/xml.user.php new file mode 100644 index 0000000..be2836d --- /dev/null +++ b/src/functions/xml.user.php @@ -0,0 +1,42 @@ +getParam(0); + $auth = $auth->scalarval(); + if (check_auth($auth) == false) { return new xmlrpcresp(0, 801, "Bot not authed."); } + + $authnick = $p->getParam(1); + $authnick = $authnick->scalarval(); + if (($uid = getUseridbyAuth($authnick)) == null) { return new xmlrpcresp(0, 811, "No user found with this auth."); } + return new xmlrpcresp(new xmlrpcval($uid, "int")); +} + +function xml_user_get($id) { + if (!is_numeric($id)) { + #soap_fault('Client','',"Ung�ltiger Parameter: '$id'") + return null; + } + return getUserByID($id); +} + +function xml_userlist_get($allytag,$nick) { + if ($nick == "all") { $nick = "%"; } + $filter['username'] = '"$nick"'; + $filter['ally'] = '"$allytag"'; + $filter['checkallygalas'] = "true"; +# return ":C:CC :C:C"; + return listUser($filter,1,1,100); +} + +function xml_scannerlist($auth,$type,$items) { + if(!check_auth($auth)) return null; # not authenticated + if (!is_numeric($type)) return null;# new soap_fault('Client','',"Ung�ltiger Parameter: '$id'"); + return user_get_scannerlist($type,$items); +} + + +?> \ No newline at end of file diff --git a/src/images/arrows_add.gif b/src/images/arrows_add.gif new file mode 100644 index 0000000..c335875 Binary files /dev/null and b/src/images/arrows_add.gif differ diff --git a/src/images/arrows_content.gif b/src/images/arrows_content.gif new file mode 100644 index 0000000..eca8e0f Binary files /dev/null and b/src/images/arrows_content.gif differ diff --git a/src/images/arrows_data.gif b/src/images/arrows_data.gif new file mode 100644 index 0000000..fc3130b Binary files /dev/null and b/src/images/arrows_data.gif differ diff --git a/src/images/arrows_delete.gif b/src/images/arrows_delete.gif new file mode 100644 index 0000000..3501a1e Binary files /dev/null and b/src/images/arrows_delete.gif differ diff --git a/src/images/arrows_delete_2.gif b/src/images/arrows_delete_2.gif new file mode 100644 index 0000000..3466343 Binary files /dev/null and b/src/images/arrows_delete_2.gif differ diff --git a/src/images/arrows_help.gif b/src/images/arrows_help.gif new file mode 100644 index 0000000..03e343b Binary files /dev/null and b/src/images/arrows_help.gif differ diff --git a/src/images/arrows_info.gif b/src/images/arrows_info.gif new file mode 100644 index 0000000..967f911 Binary files /dev/null and b/src/images/arrows_info.gif differ diff --git a/src/images/arrows_menurow.gif b/src/images/arrows_menurow.gif new file mode 100644 index 0000000..6c9dc94 Binary files /dev/null and b/src/images/arrows_menurow.gif differ diff --git a/src/images/arrows_menurow_close.gif b/src/images/arrows_menurow_close.gif new file mode 100644 index 0000000..a961792 Binary files /dev/null and b/src/images/arrows_menurow_close.gif differ diff --git a/src/images/arrows_menutopicmax.gif b/src/images/arrows_menutopicmax.gif new file mode 100644 index 0000000..aac2987 Binary files /dev/null and b/src/images/arrows_menutopicmax.gif differ diff --git a/src/images/arrows_menutopicmini.gif b/src/images/arrows_menutopicmini.gif new file mode 100644 index 0000000..764be47 Binary files /dev/null and b/src/images/arrows_menutopicmini.gif differ diff --git a/src/images/arrows_message.gif b/src/images/arrows_message.gif new file mode 100644 index 0000000..6c9df43 Binary files /dev/null and b/src/images/arrows_message.gif differ diff --git a/src/images/arrows_message_blink.gif b/src/images/arrows_message_blink.gif new file mode 100644 index 0000000..119c066 Binary files /dev/null and b/src/images/arrows_message_blink.gif differ diff --git a/src/images/arrows_orderby_asc.gif b/src/images/arrows_orderby_asc.gif new file mode 100644 index 0000000..ceb5f8c Binary files /dev/null and b/src/images/arrows_orderby_asc.gif differ diff --git a/src/images/arrows_orderby_asc_active.gif b/src/images/arrows_orderby_asc_active.gif new file mode 100644 index 0000000..26015d8 Binary files /dev/null and b/src/images/arrows_orderby_asc_active.gif differ diff --git a/src/images/arrows_orderby_desc.gif b/src/images/arrows_orderby_desc.gif new file mode 100644 index 0000000..959fec6 Binary files /dev/null and b/src/images/arrows_orderby_desc.gif differ diff --git a/src/images/arrows_orderby_desc_active.gif b/src/images/arrows_orderby_desc_active.gif new file mode 100644 index 0000000..843af4f Binary files /dev/null and b/src/images/arrows_orderby_desc_active.gif differ diff --git a/src/images/arrows_search.gif b/src/images/arrows_search.gif new file mode 100644 index 0000000..3b1b7d9 Binary files /dev/null and b/src/images/arrows_search.gif differ diff --git a/src/images/arrows_search_2.gif b/src/images/arrows_search_2.gif new file mode 100644 index 0000000..5a75d7e Binary files /dev/null and b/src/images/arrows_search_2.gif differ diff --git a/src/images/arrows_user.gif b/src/images/arrows_user.gif new file mode 100644 index 0000000..5677fbc Binary files /dev/null and b/src/images/arrows_user.gif differ diff --git a/src/images/bar_center.gif b/src/images/bar_center.gif new file mode 100644 index 0000000..49d70a5 Binary files /dev/null and b/src/images/bar_center.gif differ diff --git a/src/images/bar_left.gif b/src/images/bar_left.gif new file mode 100644 index 0000000..d23fe0b Binary files /dev/null and b/src/images/bar_left.gif differ diff --git a/src/images/bar_right.gif b/src/images/bar_right.gif new file mode 100644 index 0000000..775984b Binary files /dev/null and b/src/images/bar_right.gif differ diff --git a/src/images/buttons_add.gif b/src/images/buttons_add.gif new file mode 100644 index 0000000..aeff5b4 Binary files /dev/null and b/src/images/buttons_add.gif differ diff --git a/src/images/buttons_back.gif b/src/images/buttons_back.gif new file mode 100644 index 0000000..0fc5ea6 Binary files /dev/null and b/src/images/buttons_back.gif differ diff --git a/src/images/buttons_comments.gif b/src/images/buttons_comments.gif new file mode 100644 index 0000000..17b4500 Binary files /dev/null and b/src/images/buttons_comments.gif differ diff --git a/src/images/buttons_delete.gif b/src/images/buttons_delete.gif new file mode 100644 index 0000000..aba99dc Binary files /dev/null and b/src/images/buttons_delete.gif differ diff --git a/src/images/buttons_details.gif b/src/images/buttons_details.gif new file mode 100644 index 0000000..ca07197 Binary files /dev/null and b/src/images/buttons_details.gif differ diff --git a/src/images/buttons_download.gif b/src/images/buttons_download.gif new file mode 100644 index 0000000..cb48053 Binary files /dev/null and b/src/images/buttons_download.gif differ diff --git a/src/images/buttons_edit.gif b/src/images/buttons_edit.gif new file mode 100644 index 0000000..2fe03b1 Binary files /dev/null and b/src/images/buttons_edit.gif differ diff --git a/src/images/buttons_login.gif b/src/images/buttons_login.gif new file mode 100644 index 0000000..2840fb2 Binary files /dev/null and b/src/images/buttons_login.gif differ diff --git a/src/images/buttons_new_post.gif b/src/images/buttons_new_post.gif new file mode 100644 index 0000000..53a981c Binary files /dev/null and b/src/images/buttons_new_post.gif differ diff --git a/src/images/buttons_new_search.gif b/src/images/buttons_new_search.gif new file mode 100644 index 0000000..3f0611d Binary files /dev/null and b/src/images/buttons_new_search.gif differ diff --git a/src/images/buttons_new_thread.gif b/src/images/buttons_new_thread.gif new file mode 100644 index 0000000..b8ebcd8 Binary files /dev/null and b/src/images/buttons_new_thread.gif differ diff --git a/src/images/buttons_next.gif b/src/images/buttons_next.gif new file mode 100644 index 0000000..0afec96 Binary files /dev/null and b/src/images/buttons_next.gif differ diff --git a/src/images/buttons_no.gif b/src/images/buttons_no.gif new file mode 100644 index 0000000..720db9a Binary files /dev/null and b/src/images/buttons_no.gif differ diff --git a/src/images/buttons_ok.gif b/src/images/buttons_ok.gif new file mode 100644 index 0000000..e840144 Binary files /dev/null and b/src/images/buttons_ok.gif differ diff --git a/src/images/buttons_open.gif b/src/images/buttons_open.gif new file mode 100644 index 0000000..003bff3 Binary files /dev/null and b/src/images/buttons_open.gif differ diff --git a/src/images/buttons_search.gif b/src/images/buttons_search.gif new file mode 100644 index 0000000..9d1c7d9 Binary files /dev/null and b/src/images/buttons_search.gif differ diff --git a/src/images/buttons_send.gif b/src/images/buttons_send.gif new file mode 100644 index 0000000..6197db8 Binary files /dev/null and b/src/images/buttons_send.gif differ diff --git a/src/images/buttons_skip.gif b/src/images/buttons_skip.gif new file mode 100644 index 0000000..df87ac6 Binary files /dev/null and b/src/images/buttons_skip.gif differ diff --git a/src/images/buttons_thread_delete.gif b/src/images/buttons_thread_delete.gif new file mode 100644 index 0000000..14fc7c0 Binary files /dev/null and b/src/images/buttons_thread_delete.gif differ diff --git a/src/images/buttons_yes.gif b/src/images/buttons_yes.gif new file mode 100644 index 0000000..976f70a Binary files /dev/null and b/src/images/buttons_yes.gif differ diff --git a/src/images/line_black.gif b/src/images/line_black.gif new file mode 100644 index 0000000..623fa76 Binary files /dev/null and b/src/images/line_black.gif differ diff --git a/src/images/menu_topic_bg.gif b/src/images/menu_topic_bg.gif new file mode 100644 index 0000000..e353e49 Binary files /dev/null and b/src/images/menu_topic_bg.gif differ diff --git a/src/images/menu_topic_help.gif b/src/images/menu_topic_help.gif new file mode 100644 index 0000000..fa4384a Binary files /dev/null and b/src/images/menu_topic_help.gif differ diff --git a/src/images/minus.gif b/src/images/minus.gif new file mode 100644 index 0000000..dcbeb0c Binary files /dev/null and b/src/images/minus.gif differ diff --git a/src/images/nix.gif b/src/images/nix.gif new file mode 100644 index 0000000..35d42e8 Binary files /dev/null and b/src/images/nix.gif differ diff --git a/src/images/password.jpg b/src/images/password.jpg new file mode 100644 index 0000000..dc02adc Binary files /dev/null and b/src/images/password.jpg differ diff --git a/src/images/plus.gif b/src/images/plus.gif new file mode 100644 index 0000000..5905adb Binary files /dev/null and b/src/images/plus.gif differ diff --git a/src/images/px.gif b/src/images/px.gif new file mode 100644 index 0000000..68b18e3 Binary files /dev/null and b/src/images/px.gif differ diff --git a/src/images/scan_done.gif b/src/images/scan_done.gif new file mode 100644 index 0000000..edd4dd0 Binary files /dev/null and b/src/images/scan_done.gif differ diff --git a/src/images/scan_undone.gif b/src/images/scan_undone.gif new file mode 100644 index 0000000..a3edc5a Binary files /dev/null and b/src/images/scan_undone.gif differ diff --git a/src/images/spacer.gif b/src/images/spacer.gif new file mode 100644 index 0000000..35d42e8 Binary files /dev/null and b/src/images/spacer.gif differ diff --git a/src/index.php b/src/index.php new file mode 100644 index 0000000..83b217d --- /dev/null +++ b/src/index.php @@ -0,0 +1,12 @@ +run(); + +?> \ No newline at end of file diff --git a/src/infophp.php b/src/infophp.php new file mode 100644 index 0000000..2e7d1cd --- /dev/null +++ b/src/infophp.php @@ -0,0 +1,5 @@ + diff --git a/src/lib/log4php/Logger.php b/src/lib/log4php/Logger.php new file mode 100644 index 0000000..e50215c --- /dev/null +++ b/src/lib/log4php/Logger.php @@ -0,0 +1,67 @@ +This framework is based on log4j (see {@link http://jakarta.apache.org/log4j log4j} for details).

    + *

    Design, strategies and part of the methods documentation are developed by log4j team + * (Ceki Gülcü as log4j project founder and + * {@link http://jakarta.apache.org/log4j/docs/contributors.html contributors}).

    + * + *

    PHP port, extensions and modifications by VxR. All rights reserved.
    + * For more information, please see {@link http://www.vxr.it/log4php/}.

    + * + *

    This software is published under the terms of the LGPL License + * a copy of which has been included with this distribution in the LICENSE file.

    + * + * @package log4php + */ + +/** + * @ignore + */ +if (!defined('LOG4PHP_DIR')) define('LOG4PHP_DIR', dirname(__FILE__)); + +require_once(LOG4PHP_DIR . '/LoggerCategory.php'); +require_once(LOG4PHP_DIR . '/LoggerManager.php'); + +/** + * Main class for logging operations + * + * @author VxR + * @version $Revision: 1.9 $ + * @package log4php + */ +class Logger extends LoggerCategory { + + /** + * Constructor + * @param string $name logger name + */ + function Logger($name) + { + $this->LoggerCategory($name); + } + + /** + * Get a Logger by name (Delegate to {@link LoggerManager}) + * @param string $name logger name + * @param LoggerFactory $factory a {@link LoggerFactory} instance or null + * @return Logger + * @static + */ + function &getLogger($name, $factory = null) + { + return LoggerManager::getLogger($name, $factory); + } + + /** + * get the Root Logger (Delegate to {@link LoggerManager}) + * @return LoggerRoot + * @static + */ + function &getRootLogger() + { + return LoggerManager::getRootLogger(); + } +} +?> \ No newline at end of file diff --git a/src/lib/log4php/LoggerAppender.php b/src/lib/log4php/LoggerAppender.php new file mode 100644 index 0000000..c952da9 --- /dev/null +++ b/src/lib/log4php/LoggerAppender.php @@ -0,0 +1,218 @@ +This framework is based on log4j (see {@link http://jakarta.apache.org/log4j log4j} for details).

    + *

    Design, strategies and part of the methods documentation are developed by log4j team + * (Ceki Gülcü as log4j project founder and + * {@link http://jakarta.apache.org/log4j/docs/contributors.html contributors}).

    + * + *

    PHP port, extensions and modifications by VxR. All rights reserved.
    + * For more information, please see {@link http://www.vxr.it/log4php/}.

    + * + *

    This software is published under the terms of the LGPL License + * a copy of which has been included with this distribution in the LICENSE file.

    + * + * @package log4php + */ + +/** + * @ignore + */ +if (!defined('LOG4PHP_DIR')) define('LOG4PHP_DIR', dirname(__FILE__)); + +/** + * Abstract class that defines output logs strategies. + * + * @author VxR + * @version $Revision: 1.14 $ + * @package log4php + * @abstract + */ +class LoggerAppender { + + /** + * Factory + * + * @param string $name appender name + * @param string $class create an instance of this appender class + * @return LoggerAppender + */ + function factory($name, $class) + { + $class = basename($class); + if (!empty($class)) { + if (!class_exists($class)) + @include_once(LOG4PHP_DIR . "/appenders/{$class}.php"); + if (class_exists($class)) + return new $class($name); + } + return null; + } + + /** + * Singleton + * + * @param string $name appender name + * @param string $class create or get a reference instance of this class + * @return LoggerAppender + */ + function &singleton($name, $class = '') + { + static $instances; + + if (!empty($name)) { + if (!isset($instances[$name])) { + if (!empty($class)) { + $appender = LoggerAppender::factory($name, $class); + if ($appender !== null) { + $instances[$name] = $appender; + return $instances[$name]; + } + } + return null; + } + return $instances[$name]; + } + return null; + } + + /* --------------------------------------------------------------------------*/ + /* --------------------------------------------------------------------------*/ + /* --------------------------------------------------------------------------*/ + + /** + * Add a filter to the end of the filter list. + * + * @param LoggerFilter $newFilter add a new LoggerFilter + * @abstract + */ + function addFilter($newFilter) + { + // override + } + + /** + * Clear the list of filters by removing all the filters in it. + * @abstract + */ + function clearFilters() + { + // override + } + + /** + * Return the first filter in the filter chain for this Appender. + * The return value may be null if no is filter is set. + * @return Filter + */ + function &getFilter() + { + // override + } + + /** + * Release any resources allocated. + * Subclasses of {@link LoggerAppender} should implement + * this method to perform proper closing procedures. + * @abstract + */ + function close() + { + //override me + } + + /** + * This method performs threshold checks and invokes filters before + * delegating actual logging to the subclasses specific append() method. + * @param LoggerLoggingEvent $event + * @abstract + */ + function doAppend($event) + { + //override me + } + + /** + * Get the name of this appender. + * @return string + */ + function getName() + { + //override me + } + + /** + * Do not use this method. + * + * @param object $errorHandler + */ + function setErrorHandler($errorHandler) + { + // override me + } + + /** + * Do not use this method. + * @return object Returns the ErrorHandler for this appender. + */ + function &getErrorHandler() + { + return $this->errorHandler; + } + + /** + * Set the Layout for this appender. + * + * @param LoggerLayout $layout + */ + function setLayout($layout) + { + // override me + } + + /** + * Returns this appender layout. + * @return LoggerLayout + */ + function &getLayout() + { + // override me + } + + /** + * Set the name of this appender. + * + * The name is used by other components to identify this appender. + * + * @param string $name + */ + function setName($name) + { + // override me + } + + /** + * Configurators call this method to determine if the appender + * requires a layout. + * + *

    If this method returns true, meaning that layout is required, + * then the configurator will configure a layout using the configuration + * information at its disposal. If this method returns false, + * meaning that a layout is not required, then layout configuration will be + * skipped even if there is available layout configuration + * information at the disposal of the configurator.

    + * + *

    In the rather exceptional case, where the appender + * implementation admits a layout but can also work without it, then + * the appender should return true.

    + * + * @return boolean + */ + function requiresLayout() + { + // override me + } + +} +?> \ No newline at end of file diff --git a/src/lib/log4php/LoggerAppenderSkeleton.php b/src/lib/log4php/LoggerAppenderSkeleton.php new file mode 100644 index 0000000..9290cf6 --- /dev/null +++ b/src/lib/log4php/LoggerAppenderSkeleton.php @@ -0,0 +1,355 @@ +This framework is based on log4j (see {@link http://jakarta.apache.org/log4j log4j} for details).

    + *

    Design, strategies and part of the methods documentation are developed by log4j team + * (Ceki G�lc� as log4j project founder and + * {@link http://jakarta.apache.org/log4j/docs/contributors.html contributors}).

    + * + *

    PHP port, extensions and modifications by VxR. All rights reserved.
    + * For more information, please see {@link http://www.vxr.it/log4php/}.

    + * + *

    This software is published under the terms of the LGPL License + * a copy of which has been included with this distribution in the LICENSE file.

    + * + * @package log4php + */ + +/** + * @ignore + */ +if (!defined('LOG4PHP_DIR')) define('LOG4PHP_DIR', dirname(__FILE__)); + +/** + */ +require_once(LOG4PHP_DIR . '/LoggerAppender.php'); +require_once(LOG4PHP_DIR . '/LoggerLog.php'); +require_once(LOG4PHP_DIR . '/helpers/LoggerOptionConverter.php'); + +/** + * Abstract superclass of the other appenders in the package. + * + * This class provides the code for common functionality, such as + * support for threshold filtering and support for general filters. + * + * @author VxR + * @author Sergio Strampelli + * @version $Revision: 1.15 $ + * @package log4php + * @abstract + */ +class LoggerAppenderSkeleton extends LoggerAppender { + + /** + * @var boolean closed appender flag + */ + var $closed; + + /** + * @var object unused + */ + var $errorHandler; + + /** + * The first filter in the filter chain + * @var LoggerFilter + */ + var $headFilter = null; + + /** + * LoggerLayout for this appender. It can be null if appender has its own layout + * @var LoggerLayout + */ + var $layout = null; + + /** + * @var string Appender name + */ + var $name; + + /** + * The last filter in the filter chain + * @var LoggerFilter + */ + var $tailFilter = null; + + /** + * @var LoggerLevel There is no level threshold filtering by default. + */ + var $threshold = null; + + /** + * @var boolean needs a layout formatting ? + */ + var $requiresLayout = false; + +/* --------------------------------------------------------------------------*/ +/* --------------------------------------------------------------------------*/ +/* --------------------------------------------------------------------------*/ + + /** + * Constructor + * + * @param string $name appender name + */ + function LoggerAppenderSkeleton($name) + { + $this->name = $name; + $this->clearFilters(); + } + + /** + * @param LoggerFilter $newFilter add a new LoggerFilter + * @see LoggerAppender::addFilter() + */ + function addFilter($newFilter) + { + if($this->headFilter === null) { + $this->headFilter = $newFilter; + $this->tailFilter =& $this->headFilter; + } else { + $this->tailFilter->next = $newFilter; + $this->tailFilter =& $this->tailFilter->next; + } + } + + /** + * Derived appenders should override this method if option structure + * requires it. + */ + function activateOptions() + { + + } + + /** + * Subclasses of {@link LoggerAppenderSkeleton} should implement + * this method to perform actual logging. + * + * @param LoggerLoggingEvent $event + * @see doAppend() + * @abstract + */ + function append($event) + { + // override me + } + + /** + * @see LoggerAppender::clearFilters() + */ + function clearFilters() + { + unset($this->headFilter); + unset($this->tailFilter); + $this->headFilter = null; + $this->tailFilter = null; + } + + /** + * @see LoggerAppender::close() + */ + function close() + { + //override me + } + + /** + * Finalize this appender by calling the derived class' close() method. + */ + function finalize() + { + // An appender might be closed then garbage collected. There is no + // point in closing twice. + if ($this->closed) return; + + LoggerLog::debug("LoggerAppenderSkeleton::finalize():name=[{$this->name}]."); + + $this->close(); + } + + /** + * Do not use this method. + * @see LoggerAppender::getErrorHandler() + * @return object + */ + function &getErrorHandler() + { + return $this->errorHandler; + } + + /** + * @see LoggerAppender::getFilter() + * @return Filter + */ + function &getFilter() + { + return $this->headFilter; + } + + /** + * Return the first filter in the filter chain for this Appender. + * The return value may be null if no is filter is set. + * @return Filter + */ + function &getFirstFilter() + { + return $this->headFilter; + } + + /** + * @see LoggerAppender::getLayout() + * @return LoggerLayout + */ + function &getLayout() + { + return $this->layout; + } + + /** + * @see LoggerAppender::getName() + * @return string + */ + function getName() + { + return $this->name; + } + + /** + * Returns this appenders threshold level. + * See the {@link setThreshold()} method for the meaning of this option. + * @return LoggerLevel + */ + function &getThreshold() + { + return $this->threshold; + } + + /** + * Check whether the message level is below the appender's threshold. + * + * + * If there is no threshold set, then the return value is always true. + * @param LoggerLevel $priority + * @return boolean true if priority is greater or equal than threshold + */ + function isAsSevereAsThreshold($priority) + { + if ($this->threshold === null) + return true; + + return $priority->isGreaterOrEqual($this->getThreshold()); + } + + /** + * @see LoggerAppender::doAppend() + * @param LoggerLoggingEvent $event + */ + function doAppend($event) + { + LoggerLog::debug("LoggerAppenderSkeleton::doAppend() ".$event->getMessage()); + + if ($this->closed) { + LoggerLog::debug("LoggerAppenderSkeleton::doAppend() Attempted to append to closed appender named [{$this->name}]."); + return; + } + if(!$this->isAsSevereAsThreshold($event->getLevel())) { + LoggerLog::debug("LoggerAppenderSkeleton::doAppend() event level is less severe than threshold."); + return; + } + + $f = $this->getFirstFilter(); + + while($f !== null) { + switch ($f->decide($event)) { + case LOG4PHP_LOGGER_FILTER_DENY: return; + case LOG4PHP_LOGGER_FILTER_ACCEPT: return $this->append($event); + case LOG4PHP_LOGGER_FILTER_NEUTRAL: $f = $f->next; + } + } + $this->append($event); + } + + + /** + * @see LoggerAppender::requiresLayout() + * @return boolean + */ + function requiresLayout() + { + return $this->requiresLayout; + } + + /** + * @see LoggerAppender::setErrorHandler() + * @param object + */ + function setErrorHandler($errorHandler) + { + if($errorHandler == null) { + // We do not throw exception here since the cause is probably a + // bad config file. + LoggerLog::warn("You have tried to set a null error-handler."); + } else { + $this->errorHandler = $errorHandler; + } + } + + /** + * @see LoggerAppender::setLayout() + * @param LoggerLayout $layout + */ + function setLayout($layout) + { + if ($this->requiresLayout()) + $this->layout = $layout; + } + + /** + * @see LoggerAppender::setName() + * @param string $name + */ + function setName($name) + { + $this->name = $name; + } + + /** + * Set the threshold level of this appender. + * + * @param mixed $threshold can be a {@link LoggerLevel} object or a string. + * @see LoggerOptionConverter::toLevel() + */ + function setThreshold($threshold) + { + if (is_string($threshold)) { + $this->threshold = LoggerOptionConverter::toLevel($threshold, null); + }elseif (is_a($threshold, 'loggerlevel')) { + $this->threshold = $threshold; + } + } + + /** + * Perform actions before object serialization. + * + * Call {@link finalize()} to properly close the appender. + */ + function __sleep() + { + $this->finalize(); + return array_keys(get_object_vars($this)); + } + + /** + * Perform actions after object deserialization. + * + * Call {@link activateOptions()} to properly setup the appender. + */ + function __wakeup() + { + $this->activateOptions(); + } + +} +?> \ No newline at end of file diff --git a/src/lib/log4php/LoggerBasicConfigurator.php b/src/lib/log4php/LoggerBasicConfigurator.php new file mode 100644 index 0000000..0dac542 --- /dev/null +++ b/src/lib/log4php/LoggerBasicConfigurator.php @@ -0,0 +1,80 @@ +This framework is based on log4j (see {@link http://jakarta.apache.org/log4j log4j} for details).

    + *

    Design, strategies and part of the methods documentation are developed by log4j team + * (Ceki Gülcü as log4j project founder and + * {@link http://jakarta.apache.org/log4j/docs/contributors.html contributors}).

    + * + *

    PHP port, extensions and modifications by VxR. All rights reserved.
    + * For more information, please see {@link http://www.vxr.it/log4php/}.

    + * + *

    This software is published under the terms of the LGPL License + * a copy of which has been included with this distribution in the LICENSE file.

    + * + * @package log4php + */ + +/** + * @ignore + */ +if (!defined('LOG4PHP_DIR')) define('LOG4PHP_DIR', dirname(__FILE__)); + +require_once(LOG4PHP_DIR . '/spi/LoggerConfigurator.php'); +require_once(LOG4PHP_DIR . '/LoggerLayout.php'); +require_once(LOG4PHP_DIR . '/LoggerAppender.php'); +require_once(LOG4PHP_DIR . '/LoggerManager.php'); + +/** + * Use this class to quickly configure the package. + * + *

    For file based configuration see {@link LoggerPropertyConfigurator}. + *

    For XML based configuration see {@link LoggerDOMConfigurator}. + * + * @author VxR + * @version $Revision: 1.2 $ + * @package log4php + * @since 0.5 + */ +class LoggerBasicConfigurator extends LoggerConfigurator { + + function LoggerBasicConfigurator() + { + return; + } + + /** + * Add a {@link LoggerAppenderConsole} that uses + * the {@link LoggerLayoutTTCC} to the root category. + * + * @param string $url not used here + * @static + */ + function configure($url = null) + { + $root =& LoggerManager::getRootLogger(); + + $appender =& LoggerAppender::singleton('A1', 'LoggerAppenderConsole'); + $layout = LoggerLayout::factory('LoggerLayoutTTCC'); + $appender->setLayout($layout); + + $root->addAppender($appender)); + } + + /** + * Reset the default hierarchy to its defaut. + * It is equivalent to + * + * LoggerManager::resetConfiguration(); + * + * + * @see LoggerHierarchy::resetConfiguration() + * @static + */ + function resetConfiguration() + { + LoggerManager::resetConfiguration(); + } +} +?> \ No newline at end of file diff --git a/src/lib/log4php/LoggerCategory.php b/src/lib/log4php/LoggerCategory.php new file mode 100644 index 0000000..572c7c9 --- /dev/null +++ b/src/lib/log4php/LoggerCategory.php @@ -0,0 +1,582 @@ +This framework is based on log4j (see {@link http://jakarta.apache.org/log4j log4j} for details).

    + *

    Design, strategies and part of the methods documentation are developed by log4j team + * (Ceki G�lc� as log4j project founder and + * {@link http://jakarta.apache.org/log4j/docs/contributors.html contributors}).

    + * + *

    PHP port, extensions and modifications by VxR. All rights reserved.
    + * For more information, please see {@link http://www.vxr.it/log4php/}.

    + * + *

    This software is published under the terms of the LGPL License + * a copy of which has been included with this distribution in the LICENSE file.

    + * + * @package log4php + */ + +/** + * @ignore + */ +if (!defined('LOG4PHP_DIR')) define('LOG4PHP_DIR', dirname(__FILE__)); + +/** + */ +require_once(LOG4PHP_DIR . '/LoggerLevel.php'); +require_once(LOG4PHP_DIR . '/spi/LoggerLoggingEvent.php'); +require_once('FirePHPCore/FirePHP.class.php'); + +/** + * This class has been deprecated and replaced by the Logger subclass. + * + * @author VxR + * @version $Revision: 1.17 $ + * @package log4php + * @see Logger + */ +class LoggerCategory { + + /** + * Additivity is set to true by default, that is children inherit the + * appenders of their ancestors by default. + * @var boolean + */ + var $additive = true; + + /** + * @var string fully qualified class name + */ + var $fqcn = 'LoggerCategory'; + + /** + * @var LoggerLevel The assigned level of this category. + */ + var $level = null; + + /** + * @var string name of this category. + */ + var $name = ''; + + /** + * @var Logger The parent of this category. + */ + var $parent = null; + + /** + * @var LoggerHierarchy the object repository + */ + var $repository = null; + + /** + * @var array collection of appenders + * @see LoggerAppender + */ + var $aai = array(); + +/* --------------------------------------------------------------------------*/ +/* --------------------------------------------------------------------------*/ +/* --------------------------------------------------------------------------*/ + + /** + * Constructor. + * + * @param string $name Category name + */ + function LoggerCategory($name) + { + global $debug; + $this->name = $name; + } + + /** + * Add a new Appender to the list of appenders of this Category instance. + * + * @param LoggerAppender $newAppender + */ + function addAppender(&$newAppender) + { + $appenderName = $newAppender->getName(); + $this->aai[$appenderName] =& $newAppender; + } + + /** + * If assertion parameter is false, then logs msg as an error statement. + * + * @param bool $assertion + * @param string $msg message to log + */ + function assertLog($assertion = true, $msg = '') + { + if ($assertion == false) { + $this->error($msg); + } + } + + /** + * Call the appenders in the hierarchy starting at this. + * + * @param LoggerLoggingEvent $event + */ + function callAppenders($event) + { + if (sizeof($this->aai) > 0) { + foreach (array_keys($this->aai) as $appenderName) { + $this->aai[$appenderName]->doAppend($event); + } + } + if ($this->parent != null and $this->getAdditivity()) { + $this->parent->callAppenders($event); + } + } + + /** + * Log a message object with the DEBUG level including the caller. + * + * @param mixed $message message + * @param mixed $caller caller object or caller string id + */ + function debug($message, $caller = null) + { +// global $firephp; +// $firephp->log($message); + $debugLevel = LoggerLevel::getLevelDebug(); + if ($this->repository->isDisabled($debugLevel)) { + return; + } + if ($debugLevel->isGreaterOrEqual($this->getEffectiveLevel())) { + $this->forcedLog($this->fqcn, $caller, $debugLevel, $message); + } + } + + /** + * Log a message object with the ERROR level including the caller. + * + * @param mixed $message message + * @param mixed $caller caller object or caller string id + */ + function error($message, $caller = null) + { +// global $firephp; +// $firephp->error($message); + $errorLevel = LoggerLevel::getLevelError(); + if ($this->repository->isDisabled($errorLevel)) { + return; + } + if ($errorLevel->isGreaterOrEqual($this->getEffectiveLevel())) { + $this->forcedLog($this->fqcn, $caller, $errorLevel, $message); + } + } + + /** + * Deprecated. Please use LoggerManager::exists() instead. + * + * @param string $name + * @see LoggerManager::exists() + * @deprecated + */ + function exists($name) + { + return LoggerManager::exists($name); + } + + /** + * Log a message object with the FATAL level including the caller. + * + * @param mixed $message message + * @param mixed $caller caller object or caller string id + */ + function fatal($message, $caller = null) + { +// global $firephp; +// $firephp->error($message); + $fatalLevel = LoggerLevel::getLevelFatal(); + if ($this->repository->isDisabled($fatalLevel)) { + return; + } + if ($fatalLevel->isGreaterOrEqual($this->getEffectiveLevel())) { + $this->forcedLog($this->fqcn, $caller, $fatalLevel, $message); + } + } + + /** + * This method creates a new logging event and logs the event without further checks. + * + * It should not be called directly. Use {@link info()}, {@link debug()}, {@link warn()}, + * {@link error()} and {@link fatal()} wrappers. + * + * @param string $fqcn Fully Qualified Class Name of the Logger + * @param mixed $caller caller object or caller string id + * @param LoggerLevel $level log level + * @param mixed $message message + * @see LoggerLoggingEvent + */ + function forcedLog($fqcn, $caller, $level, $message) + { + // $fqcn = is_object($caller) ? get_class($caller) : (string)$caller; + $this->callAppenders(new LoggerLoggingEvent($fqcn, $this, $level, $message)); + } + + /** + * Get the additivity flag for this Category instance. + * @return boolean + */ + function getAdditivity() + { + return $this->additive; + } + + /** + * Get the appenders contained in this category as an array. + * @return array collection of appenders + */ + function &getAllAppenders() + { + $appenders = array(); + $appenderNames = array_keys($this->aai); + $enumAppenders = sizeof($appenderNames); + for ($i = 0; $i < $enumAppenders; $i++) { + $appenderName = $appenderNames[$i]; + $appenders[] =& $this->aai[$appenderName]; + } + return $appenders; + } + + /** + * Look for the appender named as name. + * @return LoggerAppender + */ + function &getAppender($name) + { + return $this->aai[$name]; + } + + /** + * Please use the {@link getEffectiveLevel()} method instead. + * @deprecated + */ + function getChainedPriority() + { + return $this->getEffectiveLevel(); + } + + /** + * Please use {@link LoggerManager::getCurrentLoggers()} instead. + * @deprecated + */ + function getCurrentCategories() + { + return LoggerManager::getCurrentLoggers(); + } + + /** + * Please use {@link LoggerManager::getLoggerRepository()} instead. + * @deprecated + */ + function &getDefaultHierarchy() + { + return LoggerManager::getLoggerRepository(); + } + + /** + * @deprecated Use {@link getLoggerRepository()} + * @return LoggerHierarchy + */ + function &getHierarchy() + { + return $this->getLoggerRepository(); + } + + /** + * Starting from this category, search the category hierarchy for a non-null level and return it. + * @see LoggerLevel + * @return LoggerLevel or null + */ + function getEffectiveLevel() + { + for($c = $this; $c != null; $c = $c->parent) { + if($c->level !== null) + return $c->level; + } + return null; + } + + /** + * Retrieve a category with named as the name parameter. + * @return Logger + */ + function &getInstance($name) + { + return LoggerManager::getLogger($name); + } + + /** + * Returns the assigned Level, if any, for this Category. + * @return LoggerLevel or null + */ + function getLevel() + { + return $this->level; + } + + /** + * Return the the repository where this Category is attached. + * @return LoggerHierarchy + */ + function &getLoggerRepository() + { + return $this->repository; + } + + /** + * Return the category name. + * @return string + */ + function getName() + { + return $this->name; + } + + /** + * Returns the parent of this category. + * @return Logger + */ + function &getParent() + { + return $this->parent; + } + + /** + * Please use getLevel() instead. + * @deprecated + */ + function getPriority() + { + return $this->getLevel(); + } + + /** + * Return the inherited ResourceBundle for this category. + */ + function getResourceBundle() + { + return; + } + + /** + * Returns the string resource coresponding to key in this category's inherited resource bundle. + */ + function getResourceBundleString($key) + { + return; + } + + /** + * Return the root of the default category hierrachy. + * @return LoggerRoot + */ + function &getRoot() + { + return LoggerManager::getRootLogger(); + } + + /** + * Log a message object with the INFO Level. + * + * @param mixed $message message + * @param mixed $caller caller object or caller string id + */ + function info($message, $caller = null) + { +// global $firephp; +// $firephp->info($message); + $infoLevel = LoggerLevel::getLevelInfo(); + if ($this->repository->isDisabled($infoLevel)) { + return; + } + if ($infoLevel->isGreaterOrEqual($this->getEffectiveLevel())) { + $this->forcedLog($this->fqcn, $caller, $infoLevel, $message); + } + } + + /** + * Is the appender passed as parameter attached to this category? + * + * @param LoggerAppender $appender + */ + function isAttached($appender) + { + return in_array($appender->getName(), array_keys($this->aai)); + } + + /** + * Check whether this category is enabled for the DEBUG Level. + * @return boolean + */ + function isDebugEnabled() + { + $debugLevel = LoggerLevel::getLevelDebug(); + if ($this->repository->isDisabled($debugLevel)) { + return false; + } + return ($debugLevel->isGreaterOrEqual($this->getEffectiveLevel())); + } + + /** + * Check whether this category is enabled for a given Level passed as parameter. + * + * @param LoggerLevel level + * @return boolean + */ + function isEnabledFor($level) + { + if ($this->repository->isDisabled($level)) { + return false; + } + return (bool)($level->isGreaterOrEqual($this->getEffectiveLevel())); + } + + /** + * Check whether this category is enabled for the info Level. + * @return boolean + * @see LoggerLevel + */ + function isInfoEnabled() + { + $infoLevel = LoggerLevel::getLevelInfo(); + if ($this->repository->isDisabled($infoLevel)) { + return false; + } + return ($infoLevel->isGreaterOrEqual($this->getEffectiveLevel())); + } + + /** + * Log a localized and parameterized message. + */ + function l7dlog($priority, $key, $params, $t) + { + return; + } + + /** + * This generic form is intended to be used by wrappers. + * + * @param LoggerLevel $priority a valid level + * @param mixed $message message + * @param mixed $caller caller object or caller string id + */ + function log($priority, $message, $caller = null) + { + if ($this->repository->isDisabled($priority)) { + return; + } + if ($priority->isGreaterOrEqual($this->getEffectiveLevel())) { + $this->forcedLog($this->fqcn, $caller, $priority, $message); + } + } + + /** + * Remove all previously added appenders from this Category instance. + */ + function removeAllAppenders() + { + $appenderNames = array_keys($this->aai); + $enumAppenders = sizeof($appenderNames); + for ($i = 0; $i < $enumAppenders; $i++) { + $this->removeAppender($appenderNames[$i]); + } + } + + /** + * Remove the appender passed as parameter form the list of appenders. + * + * @param mixed $appender can be an appender name or a {@link LoggerAppender} object + */ + function removeAppender($appender) + { + if (is_a($appender, 'loggerappender')) { + $appender->close(); + unset($this->aai[$appender->getName()]); + } elseif (is_string($appender) and isset($this->aai[$appender])) { + $this->aai[$appender]->close(); + unset($this->aai[$appender]); + } + } + + /** + * Set the additivity flag for this Category instance. + * + * @param boolean $additive + */ + function setAdditivity($additive) + { + $this->additive = (bool)$additive; + } + + /** + * @deprecated Please use {@link setLevel()} instead. + * @see setLevel() + */ + function setPriority($priority) + { + $this->setLevel($priority); + } + + /** + * Only the Hiearchy class can set the hiearchy of a + * category. + * + * @param LoggerHierarchy &$repository + */ + function setHierarchy(&$repository) + { + $this->repository =& $repository; + } + + /** + * Set the level of this Category. + * + * @param LoggerLevel $level a level string or a level costant + */ + function setLevel($level) + { + $this->level = $level; + } + + /** + * Set the resource bundle to be used with localized logging methods + */ + function setResourceBundle($bundle) + { + return; + } + + /** + * @deprecated use {@link LoggerManager::shutdown()} instead. + * @see LoggerManager::shutdown() + */ + function shutdown() + { + LoggerManager::shutdown(); + } + + /** + * Log a message with the WARN level. + * + * @param mixed $message message + * @param mixed $caller caller object or caller string id + */ + function warn($message, $caller = null) + { + $warnLevel = LoggerLevel::getLevelWarn(); + if ($this->repository->isDisabled($warnLevel)) { + return; + } + if ($warnLevel->isGreaterOrEqual($this->getEffectiveLevel())) { + $this->forcedLog($this->fqcn, $caller, $warnLevel, $message); + } + } + +} +?> \ No newline at end of file diff --git a/src/lib/log4php/LoggerDefaultCategoryFactory.php b/src/lib/log4php/LoggerDefaultCategoryFactory.php new file mode 100644 index 0000000..4962466 --- /dev/null +++ b/src/lib/log4php/LoggerDefaultCategoryFactory.php @@ -0,0 +1,52 @@ +This framework is based on log4j (see {@link http://jakarta.apache.org/log4j log4j} for details).

    + *

    Design, strategies and part of the methods documentation are developed by log4j team + * (Ceki Gülcü as log4j project founder and + * {@link http://jakarta.apache.org/log4j/docs/contributors.html contributors}).

    + * + *

    PHP port, extensions and modifications by VxR. All rights reserved.
    + * For more information, please see {@link http://www.vxr.it/log4php/}.

    + * + *

    This software is published under the terms of the LGPL License + * a copy of which has been included with this distribution in the LICENSE file.

    + * + * @package log4php + */ + +/** + * @ignore + */ +if (!defined('LOG4PHP_DIR')) define('LOG4PHP_DIR', dirname(__FILE__)); + +require_once(LOG4PHP_DIR . '/spi/LoggerFactory.php'); +require_once(LOG4PHP_DIR . '/Logger.php'); + +/** + * Creates instances of {@link Logger} with a given name. + * + * @author VxR + * @version $Revision: 1.2 $ + * @package log4php + * @since 0.5 + */ +class LoggerDefaultCategoryFactory extends LoggerFactory { + + function LoggerDefaultCategoryFactory() + { + return; + } + + /** + * @param string $name + * @return Logger + */ + function makeNewLoggerInstance($name) + { + return new Logger($name); + } +} + +?> \ No newline at end of file diff --git a/src/lib/log4php/LoggerHierarchy.php b/src/lib/log4php/LoggerHierarchy.php new file mode 100644 index 0000000..b3b64e0 --- /dev/null +++ b/src/lib/log4php/LoggerHierarchy.php @@ -0,0 +1,388 @@ +This framework is based on log4j (see {@link http://jakarta.apache.org/log4j log4j} for details).

    + *

    Design, strategies and part of the methods documentation are developed by log4j team + * (Ceki Gülcü as log4j project founder and + * {@link http://jakarta.apache.org/log4j/docs/contributors.html contributors}).

    + * + *

    PHP port, extensions and modifications by VxR. All rights reserved.
    + * For more information, please see {@link http://www.vxr.it/log4php/}.

    + * + *

    This software is published under the terms of the LGPL License + * a copy of which has been included with this distribution in the LICENSE file.

    + * + * @package log4php + */ + +/** + * @ignore + */ +if (!defined('LOG4PHP_DIR')) define('LOG4PHP_DIR', dirname(__FILE__)); + +/** + */ +require_once(LOG4PHP_DIR . '/LoggerLog.php'); +require_once(LOG4PHP_DIR . '/LoggerLevel.php'); +require_once(LOG4PHP_DIR . '/LoggerRoot.php'); +require_once(LOG4PHP_DIR . '/or/LoggerRendererMap.php'); +require_once(LOG4PHP_DIR . '/LoggerDefaultCategoryFactory.php'); + +/** + * This class is specialized in retrieving loggers by name and also maintaining + * the logger hierarchy. + * + *

    The casual user does not have to deal with this class directly.

    + * + *

    The structure of the logger hierarchy is maintained by the + * getLogger method. The hierarchy is such that children link + * to their parent but parents do not have any pointers to their + * children. Moreover, loggers can be instantiated in any order, in + * particular descendant before ancestor.

    + * + *

    In case a descendant is created before a particular ancestor, + * then it creates a provision node for the ancestor and adds itself + * to the provision node. Other descendants of the same ancestor add + * themselves to the previously created provision node.

    + * + * @author VxR + * @version $Revision: 1.20 $ + * @package log4php + */ +class LoggerHierarchy { + + /** + * @var object currently unused + */ + var $defaultFactory; + + /** + * @var boolean activate internal logging + * @see LoggerLog + */ + var $debug = false; + + /** + * @var array hierarchy tree. saves here all loggers + */ + var $ht = array(); + + /** + * @var LoggerRoot + */ + var $root = null; + + /** + * @var LoggerRendererMap + */ + var $rendererMap; + + /** + * @var LoggerLevel main level threshold + */ + var $threshold; + + /** + * @var boolean currently unused + */ + var $emittedNoAppenderWarning = false; + + /** + * @var boolean currently unused + */ + var $emittedNoResourceBundleWarning = false; + + +/* --------------------------------------------------------------------------*/ +/* --------------------------------------------------------------------------*/ +/* --------------------------------------------------------------------------*/ + + function &singleton() + { + static $instance; + + if (!isset($instance)) + $instance = new LoggerHierarchy(new LoggerRoot()); + return $instance; + } + + /** + * Create a new logger hierarchy. + * @param object $root the root logger + */ + function LoggerHierarchy($root) + { + $this->root =& $root; + // Enable all level levels by default. + $this->setThreshold(LoggerLevel::getLevelAll()); + $this->root->setHierarchy($this); + $this->rendererMap = new LoggerRendererMap(); + $this->defaultFactory = new LoggerDefaultCategoryFactory(); + } + + /** + * Add a HierarchyEventListener event to the repository. + * Not Yet Impl. + */ + function addHierarchyEventListener($listener) + { + return; + } + + /** + * Add an object renderer for a specific class. + * Not Yet Impl. + */ + function addRenderer($classToRender, $or) + { + $this->rendererMap->put($classToRender, $or); + } + + /** + * This call will clear all logger definitions from the internal hashtable. + */ + function clear() + { + $this->ht = array(); + } + + function emitNoAppenderWarning($cat) + { + return; + } + + /** + * Check if the named logger exists in the hierarchy. + * @param string $name + * @return boolean + */ + function exists($name) + { + return in_array($name, array_keys($this->ht)); + } + + function fireAddAppenderEvent($logger, $appender) + { + return; + } + + /** + * @deprecated Please use {@link getCurrentLoggers()} instead. + */ + function &getCurrentCategories() + { + return $this->getCurrentLoggers(); + } + + /** + * Returns all the currently defined categories in this hierarchy as an array. + * @return array + */ + function &getCurrentLoggers() + { + $loggers = array(); + $loggerNames = array_keys($this->ht); + $enumLoggers = sizeof($loggerNames); + for ($i = 0; $i < $enumLoggers; $i++) { + $loggerName = $loggerNames[$i]; + $loggers[] =& $this->ht[$loggerName]; + } + return $loggers; + } + + /** + * Return a new logger instance named as the first parameter using the default factory. + * + * @param string $name logger name + * @param LoggerFactory $factory a {@link LoggerFactory} instance or null + * @return Logger + */ + function &getLogger($name, $factory = null) + { + if ($factory === null) { + return $this->getLoggerByFactory($name, $this->defaultFactory); + } else { + return $this->getLoggerByFactory($name, $factory); + } + } + + /** + * Return a new logger instance named as the first parameter using the default factory. + * + * @param string $name logger name + * @return Logger + * @todo merge with {@link getLogger()} + */ + function &getLoggerByFactory($name, $factory) + { + if (!isset($this->ht[$name])) { + LoggerLog::debug("LoggerHierarchy::getLoggerByFactory():name=[$name]:factory=[".get_class($factory)."] creating a new logger..."); + $this->ht[$name] = $factory->makeNewLoggerInstance($name); + $this->ht[$name]->setHierarchy($this); + $nodes = explode('.', $name); + $firstNode = array_shift($nodes); + if ( $firstNode != $name and isset($this->ht[$firstNode])) { + LoggerLog::debug("LoggerHierarchy::getLogger($name) parent is now [$firstNode]"); + $this->ht[$name]->parent =& $this->ht[$firstNode]; + } else { + LoggerLog::debug("LoggerHierarchy::getLogger($name) parent is now [root]"); + $this->ht[$name]->parent =& $this->root; + } + if (sizeof($nodes) > 0) { + // find parent node + foreach ($nodes as $node) { + $parentNode = "$firstNode.$node"; + if (isset($this->ht[$parentNode]) and $parentNode != $name) { + LoggerLog::debug("LoggerHierarchy::getLogger($name) parent is now [$parentNode]"); + $this->ht[$name]->parent =& $this->ht[$parentNode]; + } + $firstNode .= ".$node"; + } + } + // update children + /* + $children = array(); + foreach (array_keys($this->ht) as $nodeName) { + if ($nodeName != $name and substr($nodeName, 0, strlen($name)) == $name) { + $children[] = $nodeName; + } + } + */ + } + return $this->ht[$name]; + } + + /** + * @return LoggerRendererMap Get the renderer map for this hierarchy. + */ + function &getRendererMap() + { + return $this->rendererMap; + } + + /** + * @return LoggerRoot Get the root of this hierarchy. + */ + function &getRootLogger() + { + if (!isset($this->root) or $this->root == null) + $this->root = new LoggerRoot(); + return $this->root; + } + + /** + * @return LoggerLevel Returns the threshold Level. + */ + function getThreshold() + { + return $this->threshold; + } + + /** + * This method will return true if this repository is disabled + * for level object passed as parameter and false otherwise. + * @return boolean + */ + function isDisabled($level) + { + return ($this->threshold->level > $level->level); + } + + /** + * @deprecated Deprecated with no replacement. + */ + function overrideAsNeeded($override) + { + return; + } + + /** + * Reset all values contained in this hierarchy instance to their + * default. + * + * This removes all appenders from all categories, sets + * the level of all non-root categories to null, + * sets their additivity flag to true and sets the level + * of the root logger to {@link LOGGER_LEVEL_DEBUG}. Moreover, + * message disabling is set its default "off" value. + * + *

    Existing categories are not removed. They are just reset. + * + *

    This method should be used sparingly and with care as it will + * block all logging until it is completed.

    + */ + function resetConfiguration() + { + $root =& $this->getRootLogger(); + + $root->setLevel(LoggerLevel::getLevelDebug()); + $this->setThreshold(LoggerLevel::getLevelAll()); + $this->shutDown(); + $loggers =& $this->getCurrentLoggers(); + $enumLoggers = sizeof($loggers); + for ($i = 0; $i < $enumLoggers; $i++) { + $loggers[$i]->setLevel(null); + $loggers[$i]->setAdditivity(true); + $loggers[$i]->setResourceBundle(null); + } + $this->rendererMap->clear(); + } + + /** + * @deprecated Deprecated with no replacement. + */ + function setDisableOverride($override) + { + return; + } + + /** + * Used by subclasses to add a renderer to the hierarchy passed as parameter. + * @param string $renderedClass a LoggerRenderer class name + * @param LoggerRenderer $renderer + * + */ + function setRenderer($renderedClass, $renderer) + { + $this->rendererMap->put($renderedClass, $renderer); + } + + /** + * set a new threshold level + * + * @param LoggerLevel $l + */ + function setThreshold($l) + { + if ($l !== null) + $this->threshold = $l; + } + + /** + * Shutting down a hierarchy will safely close and remove + * all appenders in all categories including the root logger. + * + *

    Some appenders such as {@link LoggerSocketAppender} + * need to be closed before the + * application exists. Otherwise, pending logging events might be + * lost. + * + *

    The shutdown method is careful to close nested + * appenders before closing regular appenders. This is allows + * configurations where a regular appender is attached to a logger + * and again to a nested appender. + */ + function shutdown() + { + $this->root->removeAllAppenders(); + $cats =& $this->getCurrentLoggers(); + $enumCats = sizeof($cats); + if ($enumCats > 0) { + for ($i = 0; $i < $enumCats; $i++) { + $cats[$i]->removeAllAppenders(); + } + } + } +} +?> \ No newline at end of file diff --git a/src/lib/log4php/LoggerLayout.php b/src/lib/log4php/LoggerLayout.php new file mode 100644 index 0000000..a5f774f --- /dev/null +++ b/src/lib/log4php/LoggerLayout.php @@ -0,0 +1,98 @@ +This framework is based on log4j (see {@link http://jakarta.apache.org/log4j log4j} for details).

    + *

    Design, strategies and part of the methods documentation are developed by log4j team + * (Ceki Gülcü as log4j project founder and + * {@link http://jakarta.apache.org/log4j/docs/contributors.html contributors}).

    + * + *

    PHP port, extensions and modifications by VxR. All rights reserved.
    + * For more information, please see {@link http://www.vxr.it/log4php/}.

    + * + *

    This software is published under the terms of the LGPL License + * a copy of which has been included with this distribution in the LICENSE file.

    + * + * @package log4php + */ + +/** + * @ignore + */ +if (!defined('LOG4PHP_DIR')) define('LOG4PHP_DIR', dirname(__FILE__)); + +/** + * Extend this abstract class to create your own log layout format. + * + * @author VxR + * @version $Revision: 1.10 $ + * @package log4php + * @abstract + */ +class LoggerLayout { + + /** + * Creates LoggerLayout instances with the given class name. + * + * @param string $class + * @return LoggerLayout + */ + function factory($class) + { + if (!empty($class)) { + $class = basename($class); + if (!class_exists($class)) + @include_once(LOG4PHP_DIR . "/layouts/{$class}.php"); + if (class_exists($class)) + return new $class(); + } + return null; + } + + /** + * Override this method + */ + function activateOptions() + { + // override; + } + + /** + * Override this method to create your own layout format. + * + * @param LoggerLoggingEvent + * @return string + */ + function format($event) + { + return $event->getRenderedMessage(); + } + + /** + * Returns the content type output by this layout. + * @return string + */ + function getContentType() + { + return "text/plain"; + } + + /** + * Returns the footer for the layout format. + * @return string + */ + function getFooter() + { + return null; + } + + /** + * Returns the header for the layout format. + * @return string + */ + function getHeader() + { + return null; + } +} +?> \ No newline at end of file diff --git a/src/lib/log4php/LoggerLevel.php b/src/lib/log4php/LoggerLevel.php new file mode 100644 index 0000000..a3e4803 --- /dev/null +++ b/src/lib/log4php/LoggerLevel.php @@ -0,0 +1,264 @@ +This framework is based on log4j (see {@link http://jakarta.apache.org/log4j log4j} for details).

    + *

    Design, strategies and part of the methods documentation are developed by log4j team + * (Ceki Gülcü as log4j project founder and + * {@link http://jakarta.apache.org/log4j/docs/contributors.html contributors}).

    + * + *

    PHP port, extensions and modifications by VxR. All rights reserved.
    + * For more information, please see {@link http://www.vxr.it/log4php/}.

    + * + *

    This software is published under the terms of the LGPL License + * a copy of which has been included with this distribution in the LICENSE file.

    + * + * @package log4php + */ + +/** + * @ignore + */ +if (!defined('LOG4PHP_DIR')) define('LOG4PHP_DIR', dirname(__FILE__)); + +/** + */ +require_once(LOG4PHP_DIR . '/LoggerLog.php'); + +define('LOG4PHP_LEVEL_OFF_INT', 2147483647); +define('LOG4PHP_LEVEL_FATAL_INT', 50000); +define('LOG4PHP_LEVEL_ERROR_INT', 40000); +define('LOG4PHP_LEVEL_WARN_INT', 30000); +define('LOG4PHP_LEVEL_INFO_INT', 20000); +define('LOG4PHP_LEVEL_DEBUG_INT', 10000); +define('LOG4PHP_LEVEL_ALL_INT', -2147483648); + +/** + * Defines the minimum set of levels recognized by the system, that is + * OFF, FATAL, ERROR, + * WARN, INFODEBUG and + * ALL. + * + *

    The LoggerLevel class may be subclassed to define a larger + * level set.

    + * + * @author VxR + * @version $Revision: 1.11 $ + * @package log4php + * @since 0.5 + */ +class LoggerLevel { + + /** + * @var integer + */ + var $level; + + /** + * @var string + */ + var $levelStr; + + /** + * @var integer + */ + var $syslogEquivalent; + + /** + * Constructor + * + * @param integer $level + * @param string $levelStr + * @param integer $syslogEquivalent + */ + function LoggerLevel($level, $levelStr, $syslogEquivalent) + { + $this->level = $level; + $this->levelStr = $levelStr; + $this->syslogEquivalent = $syslogEquivalent; + } + + /** + * Two priorities are equal if their level fields are equal. + * + * @param object $o + * @return boolean + */ + function equals($o) + { + if (is_a($o, 'loggerlevel')) { + return ($this->level == $o->level); + } else { + return false; + } + } + + /** + * Returns an Off Level + * @static + * @return LoggerLevel + */ + function &getLevelOff() + { + static $level; + if (!isset($level)) $level = new LoggerLevel(LOG4PHP_LEVEL_OFF_INT, 'OFF', 0); + return $level; + } + + /** + * Returns a Fatal Level + * @static + * @return LoggerLevel + */ + function &getLevelFatal() + { + static $level; + if (!isset($level)) $level = new LoggerLevel(LOG4PHP_LEVEL_FATAL_INT, 'FATAL', 0); + return $level; + } + + /** + * Returns an Error Level + * @static + * @return LoggerLevel + */ + function &getLevelError() + { + static $level; + if (!isset($level)) $level = new LoggerLevel(LOG4PHP_LEVEL_ERROR_INT, 'ERROR', 3); + return $level; + } + + /** + * Returns a Warn Level + * @static + * @return LoggerLevel + */ + function &getLevelWarn() + { + static $level; + if (!isset($level)) $level = new LoggerLevel(LOG4PHP_LEVEL_WARN_INT, 'WARN', 4); + return $level; + } + + /** + * Returns an Info Level + * @static + * @return LoggerLevel + */ + function &getLevelInfo() + { + static $level; + if (!isset($level)) $level = new LoggerLevel(LOG4PHP_LEVEL_INFO_INT, 'INFO', 6); + return $level; + } + + /** + * Returns a Debug Level + * @static + * @return LoggerLevel + */ + function &getLevelDebug() + { + static $level; + if (!isset($level)) $level = new LoggerLevel(LOG4PHP_LEVEL_DEBUG_INT, 'DEBUG', 7); + return $level; + } + + /** + * Returns an All Level + * @static + * @return LoggerLevel + */ + function &getLevelAll() + { + static $level; + if (!isset($level)) $level = new LoggerLevel(LOG4PHP_LEVEL_ALL_INT, 'ALL', 7); + return $level; + } + + /** + * Return the syslog equivalent of this priority as an integer. + * @final + * @return integer + */ + function getSyslogEquivalent() + { + return $this->syslogEquivalent; + } + + /** + * Returns true if this level has a higher or equal + * level than the level passed as argument, false + * otherwise. + * + *

    You should think twice before overriding the default + * implementation of isGreaterOrEqual method. + * + * @param LoggerLevel $r + * @return boolean + */ + function isGreaterOrEqual($r) + { + return $this->level >= $r->level; + } + + /** + * Returns the string representation of this priority. + * @return string + * @final + */ + function toString() + { + return $this->levelStr; + } + + /** + * Returns the integer representation of this level. + * @return integer + */ + function toInt() + { + return $this->level; + } + + /** + * Convert the string passed as argument to a level. If the + * conversion fails, then this method returns a DEBUG Level. + * + * @param mixed $arg + * @param LoggerLevel $default + * @static + */ + function &toLevel($arg, $defaultLevel = null) + { + if ($defaultLevel === null) { + return LoggerLevel::toLevel($arg, LoggerLevel::getLevelDebug()); + } else { + if (is_int($arg)) { + switch($arg) { + case LOG4PHP_LEVEL_ALL_INT: return LoggerLevel::getLevelAll(); + case LOG4PHP_LEVEL_DEBUG_INT: return LoggerLevel::getLevelDebug(); + case LOG4PHP_LEVEL_INFO_INT: return LoggerLevel::getLevelInfo(); + case LOG4PHP_LEVEL_WARN_INT: return LoggerLevel::getLevelWarn(); + case LOG4PHP_LEVEL_ERROR_INT: return LoggerLevel::getLevelError(); + case LOG4PHP_LEVEL_FATAL_INT: return LoggerLevel::getLevelFatal(); + case LOG4PHP_LEVEL_OFF_INT: return LoggerLevel::getLevelOff(); + default: return $defaultLevel; + } + } else { + switch(strtoupper($arg)) { + case 'ALL': return LoggerLevel::getLevelAll(); + case 'DEBUG': return LoggerLevel::getLevelDebug(); + case 'INFO': return LoggerLevel::getLevelInfo(); + case 'WARN': return LoggerLevel::getLevelWarn(); + case 'ERROR': return LoggerLevel::getLevelError(); + case 'FATAL': return LoggerLevel::getLevelFatal(); + case 'OFF': return LoggerLevel::getLevelOff(); + default: return $defaultLevel; + } + } + } + } +} +?> \ No newline at end of file diff --git a/src/lib/log4php/LoggerLog.php b/src/lib/log4php/LoggerLog.php new file mode 100644 index 0000000..558129e --- /dev/null +++ b/src/lib/log4php/LoggerLog.php @@ -0,0 +1,99 @@ +This framework is based on log4j (see {@link http://jakarta.apache.org/log4j log4j} for details).

    + *

    Design, strategies and part of the methods documentation are developed by log4j team + * (Ceki Gülcü as log4j project founder and + * {@link http://jakarta.apache.org/log4j/docs/contributors.html contributors}).

    + * + *

    PHP port, extensions and modifications by VxR. All rights reserved.
    + * For more information, please see {@link http://www.vxr.it/log4php/}.

    + * + *

    This software is published under the terms of the LGPL License + * a copy of which has been included with this distribution in the LICENSE file.

    + * + * @package log4php + */ + +/** + * @ignore + */ +if (!defined('LOG4PHP_DIR')) define('LOG4PHP_DIR', dirname(__FILE__)); + +/** + * Helper class for internal logging + * + *

    It uses php {@link PHP_MANUAL#trigger_error trigger_error()} function + * to output messages.

    + *

    You need to recode methods to output messages in a different way.

    + * + * @author VxR + * @version $Revision: 1.9 $ + * @package log4php + */ +class LoggerLog { + + /** + * Log if debug is enabled. + * + * Log using php {@link PHP_MANUAL#trigger_error trigger_error()} function + * with E_USER_NOTICE level by default. + * + * @param string $message log message + * @param integer $errLevel level to log + * @static + */ + function log($message, $errLevel = E_USER_NOTICE) + { + if (LoggerLog::internalDebugging()) + trigger_error($message, $errLevel); + } + + function internalDebugging($value = null) + { + static $debug = false; + + if (is_bool($value)) + $debug = $value; + return $debug; + } + + /** + * Report a debug message. + * + * @param string $message log message + * @static + * @since 0.3 + */ + function debug($message) + { + LoggerLog::log($message, E_USER_NOTICE); + } + + /** + * Report an error message. + * + * @param string $message log message + * @static + * @since 0.3 + */ + function error($message) + { + trigger_error($message, E_USER_ERROR); + } + + /** + * Report a warning message. + * + * @param string $message log message + * @static + * @since 0.3 + */ + function warn($message) + { + trigger_error($message, E_USER_WARNING); + } + +} +?> \ No newline at end of file diff --git a/src/lib/log4php/LoggerMDC.php b/src/lib/log4php/LoggerMDC.php new file mode 100644 index 0000000..9ebca41 --- /dev/null +++ b/src/lib/log4php/LoggerMDC.php @@ -0,0 +1,129 @@ +This framework is based on log4j (see {@link http://jakarta.apache.org/log4j log4j} for details).

    + *

    Design, strategies and part of the methods documentation are developed by log4j team + * (Ceki Gülcü as log4j project founder and + * {@link http://jakarta.apache.org/log4j/docs/contributors.html contributors}).

    + * + *

    PHP port, extensions and modifications by VxR. All rights reserved.
    + * For more information, please see {@link http://www.vxr.it/log4php/}.

    + * + *

    This software is published under the terms of the LGPL License + * a copy of which has been included with this distribution in the LICENSE file.

    + * + * @package log4php + */ + +/** + * @ignore + */ +if (!defined('LOG4PHP_DIR')) define('LOG4PHP_DIR', dirname(__FILE__)); + +/** + */ +require_once(LOG4PHP_DIR . '/LoggerLog.php'); + + +define('LOGGER_MDC_HT_SIZE', 7); + +/** + * This is the global repository of user mappings + */ +$GLOBALS['log4php.LoggerMDC.ht'] = array(); + +/** + * The LoggerMDC class is similar to the {@link LoggerNDC} class except that it is + * based on a map instead of a stack. It provides mapped diagnostic contexts. + * + * A Mapped Diagnostic Context, or + * MDC in short, is an instrument for distinguishing interleaved log + * output from different sources. Log output is typically interleaved + * when a server handles multiple clients near-simultaneously. + * + *

    The MDC is managed on a per thread basis. + * + * @author VxR + * @version $Revision: 1.4 $ + * @since 0.3 + * @package log4php + */ +class LoggerMDC { + + /** + * Put a context value as identified with the key parameter into the current thread's + * context map. + * + *

    If the current thread does not have a context map it is + * created as a side effect.

    + * + *

    Note that you cannot put more than {@link LOGGER_MDC_HT_SIZE} keys.

    + * + * @param string $key the key + * @param string $value the value + * @static + */ + function put($key, $value) + { + if ( sizeof($GLOBALS['log4php.LoggerMDC.ht']) < LOGGER_MDC_HT_SIZE ) + $GLOBALS['log4php.LoggerMDC.ht'][$key] = $value; + } + + /** + * Get the context identified by the key parameter. + * + *

    You can use special key identifiers to map values in + * PHP $_SERVER and $_ENV vars. Just put a 'server.' or 'env.' + * followed by the var name you want to refer.

    + * + *

    This method has no side effects.

    + * + * @param string $key + * @return string + * @static + */ + function get($key) + { + LoggerLog::debug("LoggerMDC::get() key='$key'"); + + if (!empty($key)) { + if (strpos($key, 'server.') === 0) { + $varName = substr($key, 7); + + LoggerLog::debug("LoggerMDC::get() a _SERVER[$varName] is requested."); + + return $_SERVER[$varName]; + } elseif (strpos($key, 'env.') === 0) { + + $varName = substr($key, 4); + + LoggerLog::debug("LoggerMDC::get() a _ENV[$varName] is requested."); + + return $_ENV[$varName]; + } elseif (isset($GLOBALS['log4php.LoggerMDC.ht'][$key])) { + + LoggerLog::debug("LoggerMDC::get() a user key is requested."); + + return $GLOBALS['log4php.LoggerMDC.ht'][$key]; + } + } + return ''; + } + + /** + * Remove the the context identified by the key parameter. + * + * It only affects user mappings. + * + * @param string $key + * @return string + * @static + */ + function remove($key) + { + unset($GLOBALS['log4php.LoggerMDC.ht'][$key]); + } + +} +?> \ No newline at end of file diff --git a/src/lib/log4php/LoggerManager.php b/src/lib/log4php/LoggerManager.php new file mode 100644 index 0000000..cd208fc --- /dev/null +++ b/src/lib/log4php/LoggerManager.php @@ -0,0 +1,262 @@ +This framework is based on log4j (see {@link http://jakarta.apache.org/log4j log4j} for details).

    + *

    Design, strategies and part of the methods documentation are developed by log4j team + * (Ceki Gülcü as log4j project founder and + * {@link http://jakarta.apache.org/log4j/docs/contributors.html contributors}).

    + * + *

    PHP port, extensions and modifications by VxR. All rights reserved.
    + * For more information, please see {@link http://www.vxr.it/log4php/}.

    + * + *

    This software is published under the terms of the LGPL License + * a copy of which has been included with this distribution in the LICENSE file.

    + * + * @package log4php + */ + +/** + * LOG4PHP_DIR points to the log4php root directory. + * + * If not defined it will be set automatically when the first package classfile + * is included + * + * @var string + */ +if (!defined('LOG4PHP_DIR')) define('LOG4PHP_DIR', dirname(__FILE__)); + +require_once(LOG4PHP_DIR . '/LoggerHierarchy.php'); + +/** + * Use the LoggerManager to get Logger instances. + * + * @author VxR + * @version $Revision: 1.18 $ + * @package log4php + * @see Logger + * @todo create a configurator selector + */ +class LoggerManager { + + /** + * check if a given logger exists. + * + * @param string $name logger name + * @static + * @return boolean + */ + function exists($name) + { + $repository =& LoggerManager::getLoggerRepository(); + return $repository->exists($name); + } + + /** + * Returns an array this whole Logger instances. + * + * @static + * @see Logger + * @return array + */ + function getCurrentLoggers() + { + $repository =& LoggerManager::getLoggerRepository(); + return $repository->getCurrentLoggers(); + } + + /** + * Returns the root logger. + * + * @static + * @return object + * @see LoggerRoot + */ + function &getRootLogger() + { + $repository =& LoggerManager::getLoggerRepository(); + return $repository->getRootLogger(); + } + + /** + * Returns the specified Logger. + * + * @param string $name logger name + * @param LoggerFactory $factory a {@link LoggerFactory} instance or null + * @static + * @return Logger + */ + function &getLogger($name, $factory = null) + { + $repository =& LoggerManager::getLoggerRepository(); + return $repository->getLogger($name, $factory); + } + + /** + * Returns the LoggerHierarchy. + * + * @static + * @return LoggerHierarchy + */ + function &getLoggerRepository() + { + return LoggerHierarchy::singleton(); + } + + + /** + * Destroy loggers object tree. + * + * @static + * @return boolean + */ + function resetConfiguration() + { + $repository =& LoggerManager::getLoggerRepository(); + return $repository->resetConfiguration(); + } + + /** + * Does nothing. + * @static + */ + function setRepositorySelector($selector, $guard) + { + return; + } + + /** + * Safely close all appenders. + * @static + */ + function shutdown() + { + $repository =& LoggerManager::getLoggerRepository(); + return $repository->shutdown(); + } +} + +// --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- + +if (!defined('LOG4PHP_DEFAULT_INIT_OVERRIDE')) { + if (isset($_ENV['log4php.defaultInitOverride'])) { + /** + * @ignore + */ + define('LOG4PHP_DEFAULT_INIT_OVERRIDE', + LoggerOptionConverter::toBoolean($_ENV['log4php.defaultInitOverride'], false) + ); + } elseif (isset($GLOBALS['log4php.defaultInitOverride'])) { + /** + * @ignore + */ + define('LOG4PHP_DEFAULT_INIT_OVERRIDE', + LoggerOptionConverter::toBoolean($GLOBALS['log4php.defaultInitOverride'], false) + ); + } else { + /** + * Controls init execution + * + * With this constant users can skip the default init procedure that is + * called when this file is included. + * + *

    If it is not user defined, log4php tries to autoconfigure using (in order):

    + * + * - the $_ENV['log4php.defaultInitOverride'] variable. + * - the $GLOBALS['log4php.defaultInitOverride'] global variable. + * - defaults to false + * + * @var boolean + */ + define('LOG4PHP_DEFAULT_INIT_OVERRIDE', false); + } +} + +if (!defined('LOG4PHP_CONFIGURATION')) { + if (isset($_ENV['log4php.configuration'])) { + /** + * @ignore + */ + define('LOG4PHP_CONFIGURATION', trim($_ENV['log4php.configuration'])); + } else { + /** + * Configuration file. + * + *

    This constant tells configurator classes where the configuration + * file is located.

    + *

    If not set by user, log4php tries to set it automatically using + * (in order):

    + * + * - the $_ENV['log4php.configuration'] enviroment variable. + * - defaults to 'log4php.properties'. + * + * @var string + */ + define('LOG4PHP_CONFIGURATION', 'log4php.properties'); + } +} + +if (!defined('LOG4PHP_CONFIGURATOR_CLASS')) { + if ( strtolower(substr( LOG4PHP_CONFIGURATION, -4 )) == '.xml') { + /** + * @ignore + */ + define('LOG4PHP_CONFIGURATOR_CLASS', LOG4PHP_DIR . '/xml/LoggerDOMConfigurator'); + } else { + /** + * Holds the configurator class name. + * + *

    This constant is set with the fullname (path included but non the + * .php extension) of the configurator class that init procedure will use.

    + *

    If not set by user, log4php tries to set it automatically.

    + *

    If {@link LOG4PHP_CONFIGURATION} has '.xml' extension set the + * constants to '{@link LOG4PHP_DIR}/xml/{@link LoggerDOMConfigurator}'.

    + *

    Otherwise set the constants to + * '{@link LOG4PHP_DIR}/{@link LoggerPropertyConfigurator}'.

    + * + *

    Security Note: classfile pointed by this constant will be brutally + * included with a: + * @include_once(LOG4PHP_CONFIGURATOR_CLASS . ".php");

    + * + * @var string + */ + define('LOG4PHP_CONFIGURATOR_CLASS', LOG4PHP_DIR . '/LoggerPropertyConfigurator'); + } +} + +if (!LOG4PHP_DEFAULT_INIT_OVERRIDE) { + if (!LoggerManagerDefaultInit()) + LoggerLog::warn("LOG4PHP main() Default Init failed."); +} + +/** + * Default init procedure. + * + *

    This procedure tries to configure the {@link LoggerHierarchy} using the + * configurator class defined via {@link LOG4PHP_CONFIGURATOR_CLASS} that tries + * to load the configurator file defined in {@link LOG4PHP_CONFIGURATION}. + * If something goes wrong a warn is raised.

    + *

    Users can skip this procedure using {@link LOG4PHP_DEFAULT_INIT_OVERRIDE} + * constant.

    + * + * @return boolean + */ +function LoggerManagerDefaultInit() +{ + $configuratorClass = basename(LOG4PHP_CONFIGURATOR_CLASS); + if (!class_exists($configuratorClass)) { + @include_once(LOG4PHP_CONFIGURATOR_CLASS . ".php"); + } + if (class_exists($configuratorClass)) { + + return call_user_func(array($configuratorClass, 'configure'), LOG4PHP_CONFIGURATION); + + } else { + LoggerLog::warn("LoggerManagerDefaultInit() Configurator '{$configuratorClass}' doesnt exists"); + return false; + } +} + +?> \ No newline at end of file diff --git a/src/lib/log4php/LoggerNDC.php b/src/lib/log4php/LoggerNDC.php new file mode 100644 index 0000000..ac94ee4 --- /dev/null +++ b/src/lib/log4php/LoggerNDC.php @@ -0,0 +1,240 @@ +This framework is based on log4j (see {@link http://jakarta.apache.org/log4j log4j} for details).

    + *

    Design, strategies and part of the methods documentation are developed by log4j team + * (Ceki Gülcü as log4j project founder and + * {@link http://jakarta.apache.org/log4j/docs/contributors.html contributors}).

    + * + *

    PHP port, extensions and modifications by VxR. All rights reserved.
    + * For more information, please see {@link http://www.vxr.it/log4php/}.

    + * + *

    This software is published under the terms of the LGPL License + * a copy of which has been included with this distribution in the LICENSE file.

    + * + * @package log4php + */ + +/** + * @ignore + */ +if (!defined('LOG4PHP_DIR')) define('LOG4PHP_DIR', dirname(__FILE__)); + +/** + */ +require_once(LOG4PHP_DIR . '/LoggerLog.php'); + +define('LOGGER_NDC_HT_SIZE', 7); + +/** + * This is the global repository of NDC stack + */ +$GLOBALS['log4php.LoggerNDC.ht'] = array(); + +/** + * This is the max depth of NDC stack + */ +$GLOBALS['log4php.LoggerNDC.maxDepth'] = LOGGER_NDC_HT_SIZE; + + +/** + * The NDC class implements nested diagnostic contexts as + * defined by Neil Harrison in the article "Patterns for Logging + * Diagnostic Messages" part of the book "Pattern Languages of + * Program Design 3" edited by Martin et al. + * + *

    A Nested Diagnostic Context, or NDC in short, is an instrument + * to distinguish interleaved log output from different sources. Log + * output is typically interleaved when a server handles multiple + * clients near-simultaneously. + * + *

    Interleaved log output can still be meaningful if each log entry + * from different contexts had a distinctive stamp. This is where NDCs + * come into play. + * + *

    Note that NDCs are managed on a per thread + * basis. NDC operations such as {@link push()}, {@link pop()}, + * {@link clear()}, {@link getDepth()} and {@link setMaxDepth()} + * affect the NDC of the current thread only. NDCs of other + * threads remain unaffected. + * + *

    For example, a servlet can build a per client request NDC + * consisting the clients host name and other information contained in + * the the request. Cookies are another source of distinctive + * information. To build an NDC one uses the {@link push()} + * operation.

    + * + * Simply put, + * + * - Contexts can be nested. + * - When entering a context, call + * LoggerNDC::push() + * As a side effect, if there is no nested diagnostic context for the + * current thread, this method will create it. + * - When leaving a context, call + * LoggerNDC::pop() + * - When exiting a thread make sure to call {@link remove()} + * + *

    There is no penalty for forgetting to match each + * push operation with a corresponding pop, + * except the obvious mismatch between the real application context + * and the context set in the NDC.

    + * + *

    If configured to do so, {@link LoggerPatternLayout} and {@link LoggerLayoutTTCC} + * instances automatically retrieve the nested diagnostic + * context for the current thread without any user intervention. + * Hence, even if a servlet is serving multiple clients + * simultaneously, the logs emanating from the same code (belonging to + * the same category) can still be distinguished because each client + * request will have a different NDC tag.

    + * + * + * @author VxR + * @version $Revision: 1.5 $ + * @package log4php + * @since 0.3 + */ +class LoggerNDC { + + /** + * Clear any nested diagnostic information if any. This method is + * useful in cases where the same thread can be potentially used + * over and over in different unrelated contexts. + * + *

    This method is equivalent to calling the {@link setMaxDepth()} + * method with a zero maxDepth argument. + * + * @static + */ + function clear() + { + LoggerLog::debug("LoggerNDC::clear()"); + + $GLOBALS['log4php.LoggerNDC.ht'] = array(); + } + + /** + * Never use this method directly, use the {@link LoggerLoggingEvent::getNDC()} method instead. + * @static + * @return array + */ + function get() + { + LoggerLog::debug("LoggerNDC::get()"); + + return $GLOBALS['log4php.LoggerNDC.ht']; + } + + /** + * Get the current nesting depth of this diagnostic context. + * + * @see setMaxDepth() + * @return integer + * @static + */ + function getDepth() + { + LoggerLog::debug("LoggerNDC::getDepth()"); + + return sizeof($GLOBALS['log4php.LoggerNDC.ht']); + } + + /** + * Clients should call this method before leaving a diagnostic + * context. + * + *

    The returned value is the value that was pushed last. If no + * context is available, then the empty string "" is returned.

    + * + * @return string The innermost diagnostic context. + * @static + */ + function pop() + { + LoggerLog::debug("LoggerNDC::pop()"); + + if (sizeof($GLOBALS['log4php.LoggerNDC.ht']) > 0) { + return array_pop($GLOBALS['log4php.LoggerNDC.ht']); + } else { + return ''; + } + } + + /** + * Looks at the last diagnostic context at the top of this NDC + * without removing it. + * + *

    The returned value is the value that was pushed last. If no + * context is available, then the empty string "" is returned.

    + * @return string The innermost diagnostic context. + * @static + */ + function peek() + { + LoggerLog::debug("LoggerNDC::peek()"); + + if (sizeof($GLOBALS['log4php.LoggerNDC.ht']) > 0) { + return end($GLOBALS['log4php.LoggerNDC.ht']); + } else { + return ''; + } + } + + /** + * Push new diagnostic context information for the current thread. + * + *

    The contents of the message parameter is + * determined solely by the client. + * + * @param string $message The new diagnostic context information. + * @static + */ + function push($message) + { + LoggerLog::debug("LoggerNDC::push()"); + + array_push($GLOBALS['log4php.LoggerNDC.ht'], (string)$message); + } + + /** + * Remove the diagnostic context for this thread. + * @static + */ + function remove() + { + LoggerLog::debug("LoggerNDC::remove()"); + + LoggerNDC::clear(); + } + + /** + * Set maximum depth of this diagnostic context. If the current + * depth is smaller or equal to maxDepth, then no + * action is taken. + * + *

    This method is a convenient alternative to multiple + * {@link pop()} calls. Moreover, it is often the case that at + * the end of complex call sequences, the depth of the NDC is + * unpredictable. The {@link setMaxDepth()} method circumvents + * this problem. + * + * @param integer $maxDepth + * @see getDepth() + * @static + */ + function setMaxDepth($maxDepth) + { + LoggerLog::debug("LoggerNDC::setMaxDepth() maxDepth='$maxDepth'"); + + $maxDepth = (int)$maxDepth; + if ($maxDepth <= LOGGER_NDC_HT_SIZE) { + if (LoggerNDC::getDepth() > $maxDepth) { + $GLOBALS['log4php.LoggerNDC.ht'] = array_slice($GLOBALS['log4php.LoggerNDC.ht'], $maxDepth); + } + $GLOBALS['log4php.LoggerNDC.maxDepth'] = $maxDepth; + } + } + +} +?> \ No newline at end of file diff --git a/src/lib/log4php/LoggerPropertyConfigurator.php b/src/lib/log4php/LoggerPropertyConfigurator.php new file mode 100644 index 0000000..9896439 --- /dev/null +++ b/src/lib/log4php/LoggerPropertyConfigurator.php @@ -0,0 +1,650 @@ +This framework is based on log4j (see {@link http://jakarta.apache.org/log4j log4j} for details).

    + *

    Design, strategies and part of the methods documentation are developed by log4j team + * (Ceki Gülcü as log4j project founder and + * {@link http://jakarta.apache.org/log4j/docs/contributors.html contributors}).

    + * + *

    PHP port, extensions and modifications by VxR. All rights reserved.
    + * For more information, please see {@link http://www.vxr.it/log4php/}.

    + * + *

    This software is published under the terms of the LGPL License + * a copy of which has been included with this distribution in the LICENSE file.

    + * + * @package log4php + */ + +/** + * @ignore + */ +if (!defined('LOG4PHP_DIR')) define('LOG4PHP_DIR', dirname(__FILE__)); + +require_once(LOG4PHP_DIR . '/config/LoggerPropertySetter.php'); +require_once(LOG4PHP_DIR . '/helpers/LoggerOptionConverter.php'); +require_once(LOG4PHP_DIR . '/or/LoggerObjectRenderer.php'); +require_once(LOG4PHP_DIR . '/or/LoggerRendererMap.php'); +require_once(LOG4PHP_DIR . '/spi/LoggerConfigurator.php'); +require_once(LOG4PHP_DIR . '/spi/LoggerFilter.php'); +require_once(LOG4PHP_DIR . '/LoggerAppender.php'); +require_once(LOG4PHP_DIR . '/LoggerDefaultCategoryFactory.php'); +require_once(LOG4PHP_DIR . '/LoggerLayout.php'); +require_once(LOG4PHP_DIR . '/LoggerLevel.php'); +require_once(LOG4PHP_DIR . '/LoggerManager.php'); + +define('LOG4PHP_LOGGER_PROPERTY_CONFIGURATOR_CATEGORY_PREFIX', "log4php.category."); +define('LOG4PHP_LOGGER_PROPERTY_CONFIGURATOR_LOGGER_PREFIX', "log4php.logger."); +define('LOG4PHP_LOGGER_PROPERTY_CONFIGURATOR_FACTORY_PREFIX', "log4php.factory"); +define('LOG4PHP_LOGGER_PROPERTY_CONFIGURATOR_ADDITIVITY_PREFIX', "log4php.additivity."); +define('LOG4PHP_LOGGER_PROPERTY_CONFIGURATOR_ROOT_CATEGORY_PREFIX', "log4php.rootCategory"); +define('LOG4PHP_LOGGER_PROPERTY_CONFIGURATOR_ROOT_LOGGER_PREFIX', "log4php.rootLogger"); +define('LOG4PHP_LOGGER_PROPERTY_CONFIGURATOR_APPENDER_PREFIX', "log4php.appender."); +define('LOG4PHP_LOGGER_PROPERTY_CONFIGURATOR_RENDERER_PREFIX', "log4php.renderer."); +define('LOG4PHP_LOGGER_PROPERTY_CONFIGURATOR_THRESHOLD_PREFIX', "log4php.threshold"); + +/** + * Key for specifying the {@link LoggerFactory}. + */ +define('LOG4PHP_LOGGER_PROPERTY_CONFIGURATOR_LOGGER_FACTORY_KEY', "log4php.loggerFactory"); +define('LOG4PHP_LOGGER_PROPERTY_CONFIGURATOR_LOGGER_DEBUG_KEY', "log4php.debug"); +define('LOG4PHP_LOGGER_PROPERTY_CONFIGURATOR_INTERNAL_ROOT_NAME', "root"); + + + +/** + * Allows the configuration of log4php from an external file. + * + * See {@link doConfigure()} for the expected format. + * + *

    It is sometimes useful to see how log4php is reading configuration + * files. You can enable log4php internal logging by defining the + * log4php.debug variable.

    + * + *

    The LoggerPropertyConfigurator does not handle the + * advanced configuration features supported by the {@link LoggerDOMConfigurator} + * such as support for {@link LoggerFilter}, + custom {@link LoggerErrorHandlers}, nested appenders such as the + {@link Logger AsyncAppender}, + * etc. + * + *

    All option values admit variable substitution. The + * syntax of variable substitution is similar to that of Unix + * shells. The string between an opening "${" and + * closing "}" is interpreted as a key. The value of + * the substituted variable can be defined as a system property or in + * the configuration file itself. The value of the key is first + * searched in the defined constants, in the enviroments variables + * and if not found there, it is + * then searched in the configuration file being parsed. The + * corresponding value replaces the ${variableName} sequence.

    + *

    For example, if $_ENV['home'] env var is set to + * /home/xyz, then every occurrence of the sequence + * ${home} will be interpreted as + * /home/xyz. See {@link LoggerOptionConverter::getSystemProperty()} + * for details.

    + * + * @author VxR + * @version $Revision: 1.6 $ + * @package log4php + * @since 0.5 + */ +class LoggerPropertyConfigurator extends LoggerConfigurator { + + /** + * @var LoggerFactory + */ + var $loggerFactory = null; + + /** + * Constructor + */ + function LoggerPropertyConfigurator() + { + $this->loggerFactory = new LoggerDefaultCategoryFactory(); + } + + /** + * Configure the default repository using the resource pointed by url. + * Url is any valid resurce as defined in {@link PHP_MANUAL#file} function. + * Note that the resource will be search with use_include_path parameter + * set to "1". + * + * @param string $url + * @return boolean configuration result + * @static + */ + function configure($url = '') + { + $configurator = new LoggerPropertyConfigurator(); + $repository =& LoggerManager::getLoggerRepository(); + return $configurator->doConfigure($url, $repository); + } + + /** + * Read configuration from a file. + * + *

    The function {@link PHP_MANUAL#parse_ini_file} is used to read the + * file.

    + * + * The existing configuration is not cleared nor reset. + * If you require a different behavior, then call + * {@link LoggerManager::resetConfiguration()} + * method before calling {@link doConfigure()}. + * + *

    The configuration file consists of statements in the format + * key=value. The syntax of different configuration + * elements are discussed below. + * + *

    Repository-wide threshold

    + * + *

    The repository-wide threshold filters logging requests by level + * regardless of logger. The syntax is: + * + *

    +     * log4php.threshold=[level]
    +     * 
    + * + *

    The level value can consist of the string values OFF, FATAL, + * ERROR, WARN, INFO, DEBUG, ALL or a custom level value. A + * custom level value can be specified in the form + * level#classname. By default the repository-wide threshold is set + * to the lowest possible value, namely the level ALL. + *

    + * + * + *

    Appender configuration

    + * + *

    Appender configuration syntax is:

    + *
    +     * ; For appender named appenderName, set its class.
    +     * ; Note: The appender name can contain dots.
    +     * log4php.appender.appenderName=name_of_appender_class
    +     * 
    +     * ; Set appender specific options.
    +     * 
    +     * log4php.appender.appenderName.option1=value1
    +     * log4php.appender.appenderName.optionN=valueN
    +     * 
    + * + * For each named appender you can configure its {@link LoggerLayout}. The + * syntax for configuring an appender's layout is: + *
    +     * log4php.appender.appenderName.layout=name_of_layout_class
    +     * log4php.appender.appenderName.layout.option1=value1
    +     *  ....
    +     * log4php.appender.appenderName.layout.optionN=valueN
    +     * 
    + * + *

    Configuring loggers

    + * + *

    The syntax for configuring the root logger is: + *

    +     * log4php.rootLogger=[level], appenderName, appenderName, ...
    +     * 
    + * + *

    This syntax means that an optional level can be + * supplied followed by appender names separated by commas. + * + *

    The level value can consist of the string values OFF, FATAL, + * ERROR, WARN, INFO, DEBUG, ALL or a custom level value. A + * custom level value can be specified in the form

    + * + *
    level#classname
    + * + *

    If a level value is specified, then the root level is set + * to the corresponding level. If no level value is specified, + * then the root level remains untouched. + * + *

    The root logger can be assigned multiple appenders. + * + *

    Each appenderName (separated by commas) will be added to + * the root logger. The named appender is defined using the + * appender syntax defined above. + * + *

    For non-root categories the syntax is almost the same: + *

    +     * log4php.logger.logger_name=[level|INHERITED|NULL], appenderName, appenderName, ...
    +     * 
    + * + *

    The meaning of the optional level value is discussed above + * in relation to the root logger. In addition however, the value + * INHERITED can be specified meaning that the named logger should + * inherit its level from the logger hierarchy.

    + * + *

    If no level value is supplied, then the level of the + * named logger remains untouched.

    + * + *

    By default categories inherit their level from the + * hierarchy. However, if you set the level of a logger and later + * decide that that logger should inherit its level, then you should + * specify INHERITED as the value for the level value. NULL is a + * synonym for INHERITED.

    + * + *

    Similar to the root logger syntax, each appenderName + * (separated by commas) will be attached to the named logger.

    + * + *

    See the appender additivity rule in the user manual for + * the meaning of the additivity flag. + * + *

    ObjectRenderers

    + * + *

    You can customize the way message objects of a given type are + * converted to String before being logged. This is done by + * specifying a {@link LoggerObjectRenderer} + * for the object type would like to customize.

    + * + *

    The syntax is: + * + *

    +     * log4php.renderer.name_of_rendered_class=name_of_rendering.class
    +     * 
    + * + * As in, + *
    +     * log4php.renderer.myFruit=myFruitRenderer
    +     * 
    + * + *

    Logger Factories

    + * + * The usage of custom logger factories is discouraged and no longer + * documented. + * + *

    Example

    + * + *

    An example configuration is given below. Other configuration + * file examples are given in the tests folder. + * + *

    +     * ; Set options for appender named "A1".
    +     * ; Appender "A1" will be a SyslogAppender
    +     * log4php.appender.A1=SyslogAppender
    +     * 
    +     * ; The syslog daemon resides on www.abc.net
    +     * log4php.appender.A1.SyslogHost=www.abc.net
    +     * 
    +     * ; A1's layout is a LoggerPatternLayout, using the conversion pattern
    +     * ; %r %-5p %c{2} %M.%L %x - %m%n. Thus, the log output will
    +     * ; include the relative time since the start of the application in
    +     * ; milliseconds, followed by the level of the log request,
    +     * ; followed by the two rightmost components of the logger name,
    +     * ; followed by the callers method name, followed by the line number,
    +     * ; the nested disgnostic context and finally the message itself.
    +     * ; Refer to the documentation of LoggerPatternLayout} for further information
    +     * ; on the syntax of the ConversionPattern key.
    +     * log4php.appender.A1.layout=LoggerPatternLayout
    +     * log4php.appender.A1.layout.ConversionPattern="%-4r %-5p %c{2} %M.%L %x - %m%n"
    +     * 
    +     * ; Set options for appender named "A2"
    +     * ; A2 should be a LoggerAppenderRollingFile, with maximum file size of 10 MB
    +     * ; using at most one backup file. A2's layout is TTCC, using the
    +     * ; ISO8061 date format with context printing enabled.
    +     * log4php.appender.A2=LoggerAppenderRollingFile
    +     * log4php.appender.A2.MaxFileSize=10MB
    +     * log4php.appender.A2.MaxBackupIndex=1
    +     * log4php.appender.A2.layout=LoggerLayoutTTCC
    +     * log4php.appender.A2.layout.ContextPrinting="true"
    +     * log4php.appender.A2.layout.DateFormat="%c"
    +     * 
    +     * ; Root logger set to DEBUG using the A2 appender defined above.
    +     * log4php.rootLogger=DEBUG, A2
    +     * 
    +     * ; Logger definitions:
    +     * ; The SECURITY logger inherits is level from root. However, it's output
    +     * ; will go to A1 appender defined above. It's additivity is non-cumulative.
    +     * log4php.logger.SECURITY=INHERIT, A1
    +     * log4php.additivity.SECURITY=false
    +     * 
    +     * ; Only warnings or above will be logged for the logger "SECURITY.access".
    +     * ; Output will go to A1.
    +     * log4php.logger.SECURITY.access=WARN
    +     * 
    +     * 
    +     * ; The logger "class.of.the.day" inherits its level from the
    +     * ; logger hierarchy.  Output will go to the appender's of the root
    +     * ; logger, A2 in this case.
    +     * log4php.logger.class.of.the.day=INHERIT
    +     * 
    + * + *

    Refer to the setOption method in each Appender and + * Layout for class specific options.

    + * + *

    Use the ";" character at the + * beginning of a line for comments.

    + * + * @param string $url The name of the configuration file where the + * configuration information is stored. + * @param LoggerHierarchy &$repository the repository to apply the configuration + */ + function doConfigure($url, &$repository) + { + $properties = @parse_ini_file($url); + if ($properties === false) { + LoggerLog::warn("LoggerPropertyConfigurator::doConfigure() cannot load '$url' configuration."); + return false; + } + return $this->doConfigureProperties($properties, $repository); + } + + + /** + * Read configuration options from properties. + * + * @see doConfigure(). + * @param array $properties + * @param LoggerHierarchy &$hierarchy + */ + function doConfigureProperties($properties, &$hierarchy) + { + $value = @$properties[LOG4PHP_LOGGER_PROPERTY_CONFIGURATOR_LOGGER_DEBUG_KEY]; + + if (!empty($value)) { + LoggerLog::internalDebugging(LoggerOptionConverter::toBoolean($value, LoggerLog::internalDebugging())); + } + + $thresholdStr = @$properties[LOG4PHP_LOGGER_PROPERTY_CONFIGURATOR_THRESHOLD_PREFIX]; + $hierarchy->setThreshold(LoggerOptionConverter::toLevel($thresholdStr, LoggerLevel::getLevelAll())); + + $this->configureRootCategory($properties, $hierarchy); + $this->configureLoggerFactory($properties); + $this->parseCatsAndRenderers($properties, $hierarchy); + + LoggerLog::debug("LoggerPropertyConfigurator::doConfigureProperties() Finished configuring."); + + return true; + } + + // -------------------------------------------------------------------------- + // Internal stuff + // -------------------------------------------------------------------------- + + /** + * Check the provided Properties object for a + * {@link LoggerFactory} entry specified by + * {@link LOG4PHP_LOGGER_PROPERTY_CONFIGURATOR_LOGGER_FACTORY_KEY}. + * + * If such an entry exists, an attempt is made to create an instance using + * the default constructor. + * This instance is used for subsequent Category creations + * within this configurator. + * + * @see parseCatsAndRenderers() + * @param array $props array of properties + */ + function configureLoggerFactory($props) + { + $factoryFqcn = @$props[LOG4PHP_LOGGER_PROPERTY_CONFIGURATOR_LOGGER_FACTORY_KEY]; + if(!empty($factoryFqcn)) { + $factoryClassName = basename($factoryFqcn); + LoggerLog::debug( + "LoggerPropertyConfigurator::configureLoggerFactory() Trying to load factory [" . + $factoryClassName . + "]." + ); + + if (!class_exists($factoryClassName)) + @include_once("{$factoryFqcn}.php"); + if (class_exists($factoryClassName)) { + $loggerFactory = new $factoryClassName(); + } else { + LoggerLog::debug( + "LoggerPropertyConfigurator::configureLoggerFactory() Unable to load factory [" . + $factoryClassName . + "]. Using default." + ); + $loggerFactory = $this->loggerFactory; + } + + LoggerLog::debug( + "LoggerPropertyConfigurator::configureLoggerFactory() ". + "Setting properties for category factory [" . get_class($loggerFactory) . "]." + ); + + LoggerPropertySetter::setPropertiesByObject($loggerFactory, $props, LOG4PHP_LOGGER_PROPERTY_CONFIGURATOR_FACTORY_PREFIX . "."); + } + } + + /** + * @param array $props array of properties + * @param LoggerHierarchy &$hierarchy + */ + function configureRootCategory($props, &$hierarchy) + { + $effectivePrefix = LOG4PHP_LOGGER_PROPERTY_CONFIGURATOR_ROOT_LOGGER_PREFIX; + $value = @$props[LOG4PHP_LOGGER_PROPERTY_CONFIGURATOR_ROOT_LOGGER_PREFIX]; + + if(empty($value)) { + $value = @$props[LOG4PHP_LOGGER_PROPERTY_CONFIGURATOR_ROOT_CATEGORY_PREFIX]; + $effectivePrefix = LOG4PHP_LOGGER_PROPERTY_CONFIGURATOR_ROOT_CATEGORY_PREFIX; + } + + if (empty($value)) { + LoggerLog::debug( + "LoggerPropertyConfigurator::configureRootCategory() ". + "Could not find root logger information. Is this OK?" + ); + } else { + $root =& $hierarchy->getRootLogger(); + // synchronized(root) { + $this->parseCategory( + $props, + $root, + $effectivePrefix, + LOG4PHP_LOGGER_PROPERTY_CONFIGURATOR_INTERNAL_ROOT_NAME, + $value + ); + // } + } + } + + /** + * Parse non-root elements, such non-root categories and renderers. + * + * @param array $props array of properties + * @param LoggerHierarchy &$hierarchy + */ + function parseCatsAndRenderers($props, &$hierarchy) + { + while(list($key,$value) = each($props)) { + if( strpos($key, LOG4PHP_LOGGER_PROPERTY_CONFIGURATOR_CATEGORY_PREFIX) === 0 or + strpos($key, LOG4PHP_LOGGER_PROPERTY_CONFIGURATOR_LOGGER_PREFIX) === 0) { + if(strpos($key, LOG4PHP_LOGGER_PROPERTY_CONFIGURATOR_CATEGORY_PREFIX) === 0) { + $loggerName = substr($key, strlen(LOG4PHP_LOGGER_PROPERTY_CONFIGURATOR_CATEGORY_PREFIX)); + } elseif (strpos($key, LOG4PHP_LOGGER_PROPERTY_CONFIGURATOR_LOGGER_PREFIX) === 0) { + $loggerName = substr($key, strlen(LOG4PHP_LOGGER_PROPERTY_CONFIGURATOR_LOGGER_PREFIX)); + } + $logger =& $hierarchy->getLogger($loggerName, $this->loggerFactory); + // synchronized(logger) { + $this->parseCategory($props, $logger, $key, $loggerName, $value); + $this->parseAdditivityForLogger($props, $logger, $loggerName); + // } + } elseif (strpos($key, LOG4PHP_LOGGER_PROPERTY_CONFIGURATOR_RENDERER_PREFIX) === 0) { + $renderedClass = substr($key, strlen(LOG4PHP_LOGGER_PROPERTY_CONFIGURATOR_RENDERER_PREFIX)); + $renderingClass = $value; + if (method_exists($hierarchy, 'addrenderer')) { + LoggerRendererMap::addRenderer($hierarchy, $renderedClass, $renderingClass); + } + } + } + } + + /** + * Parse the additivity option for a non-root category. + * + * @param array $props array of properties + * @param Logger &$cat + * @param string $loggerName + */ + function parseAdditivityForLogger($props, &$cat, $loggerName) + { + $value = LoggerOptionConverter::findAndSubst( + LOG4PHP_LOGGER_PROPERTY_CONFIGURATOR_ADDITIVITY_PREFIX . $loggerName, + $props + ); + LoggerLog::debug( + "LoggerPropertyConfigurator::parseAdditivityForLogger() ". + "Handling " . LOG4PHP_LOGGER_PROPERTY_CONFIGURATOR_ADDITIVITY_PREFIX . $loggerName . "=[{$value}]" + ); + // touch additivity only if necessary + if(!empty($value)) { + $additivity = LoggerOptionConverter::toBoolean($value, true); + LoggerLog::debug( + "LoggerPropertyConfigurator::parseAdditivityForLogger() ". + "Setting additivity for [{$loggerName}] to [{$additivity}]" + ); + $cat->setAdditivity($additivity); + } + } + + /** + * This method must work for the root category as well. + * + * @param array $props array of properties + * @param Logger &$logger + * @param string $optionKey + * @param string $loggerName + * @param string $value + * @return Logger + */ + function &parseCategory($props, &$logger, $optionKey, $loggerName, $value) + { + LoggerLog::debug( + "LoggerPropertyConfigurator::parseCategory() ". + "Parsing for [{$loggerName}] with value=[{$value}]." + ); + + // We must skip over ',' but not white space + $st = explode(',', $value); + + // If value is not in the form ", appender.." or "", then we should set + // the level of the loggeregory. + + if(!(@$value{0} == ',' || empty($value))) { + // just to be on the safe side... + if(sizeof($st) == 0) + return; + + $levelStr = current($st); + LoggerLog::debug( + "LoggerPropertyConfigurator::parseCategory() ". + "Level token is [$levelStr]." + ); + + // If the level value is inherited, set category level value to + // null. We also check that the user has not specified inherited for the + // root category. + if('INHERITED' == strtoupper($levelStr) || 'NULL' == strtoupper($levelStr)) { + if ($loggerName == LOG4PHP_LOGGER_PROPERTY_CONFIGURATOR_INTERNAL_ROOT_NAME) { + LoggerLog::warn( + "LoggerPropertyConfigurator::parseCategory() ". + "The root logger cannot be set to null." + ); + } else { + $logger->setLevel(null); + } + } else { + $logger->setLevel(LoggerOptionConverter::toLevel($levelStr, LoggerLevel::getLevelDebug())); + } + } + + // Begin by removing all existing appenders. + $logger->removeAllAppenders(); + while($appenderName = next($st)) { + $appenderName = trim($appenderName); + if(empty($appenderName)) + continue; + LoggerLog::debug( + "LoggerPropertyConfigurator::parseCategory() ". + "Parsing appender named [{$appenderName}]." + ); + $appender =& $this->parseAppender($props, $appenderName); + if($appender !== null) { + $logger->addAppender($appender); + } + } + } + + /** + * @param array $props array of properties + * @param string $appenderName + * @return LoggerAppender + */ + function &parseAppender($props, $appenderName) + { + $appender =& LoggerAppender::singleton($appenderName); + if($appender !== null) { + LoggerLog::debug( + "LoggerPropertyConfigurator::parseAppender() ". + "Appender [{$appenderName}] was already parsed." + ); + return $appender; + } + // Appender was not previously initialized. + $prefix = LOG4PHP_LOGGER_PROPERTY_CONFIGURATOR_APPENDER_PREFIX . $appenderName; + $layoutPrefix = $prefix . ".layout"; + $appenderClass = @$props[$prefix]; + if (!empty($appenderClass)) { + $appender =& LoggerAppender::singleton($appenderName, $appenderClass); + if($appender === null) { + LoggerLog::warn( + "LoggerPropertyConfigurator::parseAppender() ". + "Could not instantiate appender named [$appenderName]." + ); + return null; + } + } else { + LoggerLog::warn( + "LoggerPropertyConfigurator::parseAppender() ". + "Could not instantiate appender named [$appenderName] with null className." + ); + return null; + } + + $appender->setName($appenderName); + if( $appender->requiresLayout() ) { + LoggerLog::debug( + "LoggerPropertyConfigurator::parseAppender() ". + "Parsing layout section for [$appenderName]." + ); + $layoutClass = @$props[$layoutPrefix]; + $layoutClass = LoggerOptionConverter::substVars($layoutClass, $props); + if (empty($layoutClass)) { + LoggerLog::warn( + "LoggerPropertyConfigurator::parseAppender() ". + "layout class is empty in '$layoutPrefix'. Using Simple layout" + ); + $layout = LoggerLayout::factory('LoggerLayoutSimple'); + } else { + $layout = LoggerLayout::factory($layoutClass); + + if($layout === null) { + LoggerLog::warn( + "LoggerPropertyConfigurator::parseAppender() ". + "cannot create layout '$layoutClass'. Using Simple layout" + ); + $layout = LoggerLayout::factory('LoggerLayoutSimple'); + } + } + + LoggerLog::debug( + "LoggerPropertyConfigurator::parseAppender() ". + "Parsing layout options for [$appenderName]." + ); + LoggerPropertySetter::setPropertiesByObject($layout, $props, $layoutPrefix . "."); + LoggerLog::debug( + "LoggerPropertyConfigurator::parseAppender() ". + "End Parsing layout options for [$appenderName]." + ); + $appender->setLayout($layout); + + } + LoggerPropertySetter::setPropertiesByObject($appender, $props, $prefix . "."); + LoggerLog::debug( + "LoggerPropertyConfigurator::parseAppender() ". + "Parsed [{$appenderName}] options." + ); + return $appender; + } + +} +?> \ No newline at end of file diff --git a/src/lib/log4php/LoggerRoot.php b/src/lib/log4php/LoggerRoot.php new file mode 100644 index 0000000..c25a401 --- /dev/null +++ b/src/lib/log4php/LoggerRoot.php @@ -0,0 +1,101 @@ +This framework is based on log4j (see {@link http://jakarta.apache.org/log4j log4j} for details).

    + *

    Design, strategies and part of the methods documentation are developed by log4j team + * (Ceki Gülcü as log4j project founder and + * {@link http://jakarta.apache.org/log4j/docs/contributors.html contributors}).

    + * + *

    PHP port, extensions and modifications by VxR. All rights reserved.
    + * For more information, please see {@link http://www.vxr.it/log4php/}.

    + * + *

    This software is published under the terms of the LGPL License + * a copy of which has been included with this distribution in the LICENSE file.

    + * + * @package log4php + */ + +/** + * @ignore + */ +if (!defined('LOG4PHP_DIR')) define('LOG4PHP_DIR', dirname(__FILE__)); + +/** + */ +require_once(LOG4PHP_DIR . '/Logger.php'); +require_once(LOG4PHP_DIR . '/LoggerLevel.php'); + +/** + * The root logger. + * + * @author VxR + * @version $Revision: 1.9 $ + * @package log4php + * @see Logger + */ +class LoggerRoot extends Logger { + + /** + * @var string name of logger + */ + var $name = 'root'; + + /** + * @var object must be null for LoggerRoot + */ + var $parent = null; + + + /** + * Constructor + * + * @param integer $level initial log level + */ + function LoggerRoot($level = null) + { + $this->Logger($this->name); + if ($level == null) + $level = LoggerLevel::getLevelAll(); + $this->setLevel($level); + } + + /** + * @return integer the level + */ + function getChainedLevel() + { + return $this->level; + } + + /** + * Setting a null value to the level of the root category may have catastrophic results. + * @param LoggerLevel $level + */ + function setLevel($level) + { + $this->level = $level; + } + + /** + * Please use setLevel() instead. + * @param LoggerLevel $level + * @deprecated + */ + function setPriority($level) + { + $this->setLevel($level); + } + + /** + * Always returns false. + * Because LoggerRoot has no parents, it returns false. + * @param Logger $parent + * @return boolean + */ + function setParent($parent) + { + return false; + } +} +?> \ No newline at end of file diff --git a/src/lib/log4php/appenders/LoggerAppenderConsole.php b/src/lib/log4php/appenders/LoggerAppenderConsole.php new file mode 100644 index 0000000..c0508c7 --- /dev/null +++ b/src/lib/log4php/appenders/LoggerAppenderConsole.php @@ -0,0 +1,139 @@ +This framework is based on log4j (see {@link http://jakarta.apache.org/log4j log4j} for details).

    + *

    Design, strategies and part of the methods documentation are developed by log4j team + * (Ceki Gülcü as log4j project founder and + * {@link http://jakarta.apache.org/log4j/docs/contributors.html contributors}).

    + * + *

    PHP port, extensions and modifications by VxR. All rights reserved.
    + * For more information, please see {@link http://www.vxr.it/log4php/}.

    + * + *

    This software is published under the terms of the LGPL License + * a copy of which has been included with this distribution in the LICENSE file.

    + * + * @package log4php + * @subpackage appenders + */ + +/** + * @ignore + */ +if (!defined('LOG4PHP_DIR')) define('LOG4PHP_DIR', dirname(__FILE__) . '/..'); + +/** + */ +require_once(LOG4PHP_DIR . '/LoggerAppenderSkeleton.php'); +require_once(LOG4PHP_DIR . '/LoggerLog.php'); + + +define('LOG4PHP_LOGGER_APPENDER_CONSOLE_STDOUT', 'php://stdout'); +define('LOG4PHP_LOGGER_APPENDER_CONSOLE_STDERR', 'php://stderr'); + +/** + * ConsoleAppender appends log events to STDOUT or STDERR using a layout specified by the user. + * + *

    Optional parameter is {@link $target}. The default target is Stdout.

    + *

    Note: Use this Appender with command-line php scripts. + * On web scripts this appender has no effects.

    + *

    This appender requires a layout.

    + * + * @author VxR + * @version $Revision: 1.11 $ + * @package log4php + * @subpackage appenders + */ +class LoggerAppenderConsole extends LoggerAppenderSkeleton { + + /** + * Can be 'php://stdout' or 'php://stderr'. But it's better to use keywords STDOUT and STDERR (case insensitive). + * Default is STDOUT + * @var string + */ + var $target = 'php://stdout'; + + /** + * @var boolean + * @access private + */ + var $requiresLayout = true; + + /** + * @var mixed the resource used to open stdout/stderr + * @access private + */ + var $fp = false; + + /** + * Constructor. + * + * @param string $name appender name + */ + function LoggerAppenderConsole($name) + { + $this->LoggerAppenderSkeleton($name); + } + + /** + * Set console target. + * @param mixed $value a constant or a string + */ + function setTarget($value) + { + $v = trim($value); + if ($v == LOG4PHP_LOGGER_APPENDER_CONSOLE_STDOUT or strtoupper($v) == 'STDOUT') { + $this->target = LOG4PHP_LOGGER_APPENDER_CONSOLE_STDOUT; + } elseif ($v == LOG4PHP_LOGGER_APPENDER_CONSOLE_STDOUT or strtoupper($v) == 'STDERR') { + $target = LOG4PHP_LOGGER_APPENDER_CONSOLE_STDOUT; + } else { + LoggerLog::debug( + "LoggerAppenderConsole::targetWarn() ". + "Invalid target. Using '".LOG4PHP_LOGGER_APPENDER_CONSOLE_STDOUT."' by default." + ); + } + } + + function getTarget() + { + return $this->target; + } + + function activateOptions() + { + LoggerLog::debug("LoggerAppenderConsole::activateOptions()"); + + $this->fp = @fopen($this->getTarget(), 'w'); + + if ($this->fp and $this->layout !== null) + @fwrite($this->fp, $this->layout->getHeader()); + + $this->closed = (bool)($this->fp === false); + } + + /** + * @see LoggerAppender::close() + */ + function close() + { + LoggerLog::debug("LoggerAppenderConsole::close()"); + + if ($this->fp and $this->layout !== null) { + @fwrite($this->fp, $this->layout->getFooter()); + } + @fclose($this->fp); + $this->closed = true; + } + + function append($event) + { + if ($this->fp and $this->layout !== null) { + + LoggerLog::debug("LoggerAppenderConsole::append()"); + + @fwrite($this->fp, $this->layout->format($event)); + } + } +} + +?> \ No newline at end of file diff --git a/src/lib/log4php/appenders/LoggerAppenderDailyFile.php b/src/lib/log4php/appenders/LoggerAppenderDailyFile.php new file mode 100644 index 0000000..3966bf6 --- /dev/null +++ b/src/lib/log4php/appenders/LoggerAppenderDailyFile.php @@ -0,0 +1,97 @@ +This framework is based on log4j (see {@link http://jakarta.apache.org/log4j log4j} for details).

    + *

    Design, strategies and part of the methods documentation are developed by log4j team + * (Ceki Gülcü as log4j project founder and + * {@link http://jakarta.apache.org/log4j/docs/contributors.html contributors}).

    + * + *

    PHP port, extensions and modifications by VxR. All rights reserved.
    + * For more information, please see {@link http://www.vxr.it/log4php/}.

    + * + *

    This software is published under the terms of the LGPL License + * a copy of which has been included with this distribution in the LICENSE file.

    + * + * @package log4php + * @subpackage appenders + */ + +/** + * @ignore + */ +if (!defined('LOG4PHP_DIR')) define('LOG4PHP_DIR', dirname(__FILE__) . '/..'); + +require_once(LOG4PHP_DIR . '/appenders/LoggerAppenderFile.php'); + +/** + * LoggerAppenderDailyFile appends log events to a file ne. + * + * A formatted version of the date pattern is used as to create the file name + * using the {@link PHP_MANUAL#sprintf} function. + *

    Parameters are {@link $datePattern}, {@link $file}. Note that file + * parameter should include a '%s' identifier and should always be set + * before {@link $file} param.

    + * + * @author Abel Gonzalez + * @version $Revision: 1.7 $ + * @package log4php + * @subpackage appenders + */ +class LoggerAppenderDailyFile extends LoggerAppenderFile { + + /** + * Format date. + * It follows the {@link PHP_MANUAL#date()} formatting rules and should always be set before {@link $file} param. + * @var string + */ + var $datePattern = "Ymd"; + + /** + * Constructor + * + * @param string $name appender name + */ + function LoggerAppenderDailyFile($name) + { + $this->LoggerAppenderFile($name); + } + + /** + * Sets date format for the file name. + * @param string $format a regular date() string format + */ + function setDatePattern ( $format ) + { + $this->datePattern = $format; + } + + /** + * @return string returns date format for the filename + */ + function getDatePattern ( ) + { + return $this->datePattern; + } + + /** + * The File property takes a string value which should be the name of the file to append to. + * Sets and opens the file where the log output will go. + * + * @see LoggerAppenderFile::setFile() + */ + function setFile() + { + $numargs = func_num_args(); + $args = func_get_args(); + + if ($numargs == 1 and is_string($args[0])) { + parent::setFile( sprintf((string)$args[0], date($this->getDatePattern())) ); + } elseif ($numargs == 2 and is_string($args[0]) and is_bool($args[1])) { + parent::setFile( sprintf((string)$args[0], date($this->getDatePattern())), $args[1] ); + } + } + +} + +?> \ No newline at end of file diff --git a/src/lib/log4php/appenders/LoggerAppenderDb.php b/src/lib/log4php/appenders/LoggerAppenderDb.php new file mode 100644 index 0000000..021d517 --- /dev/null +++ b/src/lib/log4php/appenders/LoggerAppenderDb.php @@ -0,0 +1,209 @@ +This framework is based on log4j (see {@link http://jakarta.apache.org/log4j log4j} for details).

    + *

    Design, strategies and part of the methods documentation are developed by log4j team + * (Ceki Gülcü as log4j project founder and + * {@link http://jakarta.apache.org/log4j/docs/contributors.html contributors}).

    + * + *

    PHP port, extensions and modifications by VxR. All rights reserved.
    + * For more information, please see {@link http://www.vxr.it/log4php/}.

    + * + *

    This software is published under the terms of the LGPL License + * a copy of which has been included with this distribution in the LICENSE file.

    + * + * @package log4php + * @subpackage appenders + */ + +/** + * @ignore + */ +if (!defined('LOG4PHP_DIR')) define('LOG4PHP_DIR', dirname(__FILE__) . '/..'); + +require_once(LOG4PHP_DIR . '/LoggerAppenderSkeleton.php'); +require_once(LOG4PHP_DIR . '/helpers/LoggerOptionConverter.php'); +require_once(LOG4PHP_DIR . '/LoggerLog.php'); +require_once('DB.php'); + +/** + * Appends log events to a db table using PEAR::DB class. + * + *

    This appender uses a table in a database to log events.

    + *

    Parameters are {@link $dsn}, {@link $createTable}, {@link table} and {@link $sql}.

    + *

    See examples in test directory.

    + * + * @author VxR + * @version $Revision: 1.7 $ + * @package log4php + * @subpackage appenders + * @since 0.3 + */ +class LoggerAppenderDb extends LoggerAppenderSkeleton { + + /** + * Create the log table if it does not exists (optional). + * @var boolean + */ + var $createTable = true; + + /** + * PEAR::Db Data source name. Read PEAR::Db for dsn syntax (mandatory). + * @var string + */ + var $dsn; + + /** + * A {@link LoggerPatternLayout} string used to format a valid insert query (mandatory). + * @var string + */ + var $sql; + + /** + * Table name to write events. Used only if {@link $createTable} is true. + * @var string + */ + var $table; + + /** + * @var object PEAR::Db instance + * @access private + */ + var $db = null; + + /** + * @var boolean used to check if all conditions to append are true + * @access private + */ + var $canAppend = true; + + /** + * @access private + */ + var $requiresLayout = false; + + /** + * Constructor. + * + * @param string $name appender name + */ + function LoggerAppenderDb($name) + { + $this->LoggerAppenderSkeleton($name); + } + + /** + * Setup db connection. + * Based on defined options, this method connects to db defined in {@link $dsn} + * and creates a {@link $table} table if {@link $createTable} is true. + * @return boolean true if all ok. + */ + function activateOptions() + { + $this->db = DB::connect($this->dsn); + + if (DB::isError($this->db)) { + LoggerLog::debug("LoggerAppenderDb::activateOptions() DB Connect Error [".$this->db->getMessage()."]"); + $this->db = null; + $this->closed = true; + $this->canAppend = false; + + } else { + + $this->layout = LoggerLayout::factory('LoggerPatternLayout'); + $this->layout->setConversionPattern($this->getSql()); + + // test if log table exists + $tableInfo = $this->db->tableInfo($this->table, $mode = null); + if (DB::isError($tableInfo) and $this->getCreateTable()) { + $query = "CREATE TABLE {$this->table} (timestamp varchar(32),logger varchar(32),level varchar(32),message varchar(64),thread varchar(32),file varchar(64),line varchar(4) );"; + + LoggerLog::debug("LoggerAppenderDb::activateOptions() creating table '{$this->table}'... using sql='$query'"); + + $result = $this->db->query($query); + if (DB::isError($result)) { + LoggerLog::debug("LoggerAppenderDb::activateOptions() error while creating '{$this->table}'. Error is ".$result->getMessage()); + $this->canAppend = false; + return; + } + } + $this->canAppend = true; + } + + } + + function append($event) + { + if ($this->canAppend) { + + $query = $this->layout->format($event); + + LoggerLog::debug("LoggerAppenderDb::append() query='$query'"); + + $this->db->query($query); + } + } + + function close() + { + if ($this->db !== null) + $this->db->disconnect(); + $this->closed = true; + } + + /** + * @return boolean + */ + function getCreateTable() + { + return $this->createTable; + } + + /** + * @return string the defined dsn + */ + function getDsn() + { + return $this->dsn; + } + + /** + * @return string the sql pattern string + */ + function getSql() + { + return $this->sql; + } + + /** + * @return string the table name to create + */ + function getTable() + { + return $this->table; + } + + function setCreateTable($flag) + { + $this->createTable = LoggerOptionConverter::toBoolean($flag, true); + } + + function setDsn($newDsn) + { + $this->dsn = $newDsn; + } + + function setSql($sql) + { + $this->sql = $sql; + } + + function setTable($table) + { + $this->table = $table; + } + +} + +?> \ No newline at end of file diff --git a/src/lib/log4php/appenders/LoggerAppenderEcho.php b/src/lib/log4php/appenders/LoggerAppenderEcho.php new file mode 100644 index 0000000..a615dfc --- /dev/null +++ b/src/lib/log4php/appenders/LoggerAppenderEcho.php @@ -0,0 +1,89 @@ +This framework is based on log4j (see {@link http://jakarta.apache.org/log4j log4j} for details).

    + *

    Design, strategies and part of the methods documentation are developed by log4j team + * (Ceki Gülcü as log4j project founder and + * {@link http://jakarta.apache.org/log4j/docs/contributors.html contributors}).

    + * + *

    PHP port, extensions and modifications by VxR. All rights reserved.
    + * For more information, please see {@link http://www.vxr.it/log4php/}.

    + * + *

    This software is published under the terms of the LGPL License + * a copy of which has been included with this distribution in the LICENSE file.

    + * + * @package log4php + * @subpackage appenders + */ + +/** + * @ignore + */ +if (!defined('LOG4PHP_DIR')) define('LOG4PHP_DIR', dirname(__FILE__) . '/..'); + +/** + */ +require_once(LOG4PHP_DIR . '/LoggerAppenderSkeleton.php'); +require_once(LOG4PHP_DIR . '/LoggerLog.php'); + +/** + * LoggerAppenderEcho uses {@link PHP_MANUAL#echo echo} function to output events. + * + *

    This appender requires a layout.

    + * + * @author VxR + * @version $Revision: 1.5 $ + * @package log4php + * @subpackage appenders + */ +class LoggerAppenderEcho extends LoggerAppenderSkeleton { + + /** + * @access private + */ + var $requiresLayout = true; + + /** + * @var boolean used internally to mark first append + * @access private + */ + var $firstAppend = true; + + /** + * Constructor. + * + * @param string $name appender name + */ + function LoggerAppenderEcho($name) + { + $this->LoggerAppenderSkeleton($name); + } + + function activateOptions() + { + return; + } + + function close() + { + if (!$this->firstAppend) + echo $this->layout->getFooter(); + $this->closed = true; + } + + function append($event) + { + LoggerLog::debug("LoggerAppenderEcho::append()"); + + if ($this->layout !== null) { + if ($this->firstAppend) { + echo $this->layout->getHeader(); + $this->firstAppend = false; + } + echo $this->layout->format($event); + } + } +} + +?> \ No newline at end of file diff --git a/src/lib/log4php/appenders/LoggerAppenderFile.php b/src/lib/log4php/appenders/LoggerAppenderFile.php new file mode 100644 index 0000000..b71c584 --- /dev/null +++ b/src/lib/log4php/appenders/LoggerAppenderFile.php @@ -0,0 +1,180 @@ +This framework is based on log4j (see {@link http://jakarta.apache.org/log4j log4j} for details).

    + *

    Design, strategies and part of the methods documentation are developed by log4j team + * (Ceki Gülcü as log4j project founder and + * {@link http://jakarta.apache.org/log4j/docs/contributors.html contributors}).

    + * + *

    PHP port, extensions and modifications by VxR. All rights reserved.
    + * For more information, please see {@link http://www.vxr.it/log4php/}.

    + * + *

    This software is published under the terms of the LGPL License + * a copy of which has been included with this distribution in the LICENSE file.

    + * + * @package log4php + * @subpackage appenders + */ + +/** + * @ignore + */ +if (!defined('LOG4PHP_DIR')) define('LOG4PHP_DIR', dirname(__FILE__) . '/..'); + +require_once(LOG4PHP_DIR . '/LoggerAppenderSkeleton.php'); +require_once(LOG4PHP_DIR . '/helpers/LoggerOptionConverter.php'); +require_once(LOG4PHP_DIR . '/LoggerLog.php'); + +/** + * FileAppender appends log events to a file. + * + * Parameters are ({@link $fileName} but option name is file), + * {@link $append}. + * + * @author VxR + * @version $Revision: 1.15 $ + * @package log4php + * @subpackage appenders + */ +class LoggerAppenderFile extends LoggerAppenderSkeleton { + + /** + * @var boolean if {@link $file} exists, appends events. + */ + var $append = true; + + /** + * @var string the file name used to append events + */ + var $fileName; + + /** + * @var mixed file resource + * @access private + */ + var $fp = false; + + /** + * @access private + */ + var $requiresLayout = true; + + /** + * Constructor. + * + * @param string $name appender name + */ + function LoggerAppenderFile($name) + { + $this->LoggerAppenderSkeleton($name); + } + + function activateOptions() + { + $fileName = $this->getFile(); + LoggerLog::debug("LoggerAppenderFile::activateOptions() opening file '{$fileName}'"); + $this->fp = @fopen($fileName, ($this->getAppend()? 'a':'w')); + if ($this->fp) { + if ($this->getAppend()) + fseek($this->fp, 0, SEEK_END); + @fwrite($this->fp, $this->layout->getHeader()); + $this->closed = false; + } else { + $this->closed = true; + } + } + + function close() + { + if ($this->fp and $this->layout !== null) + @fwrite($this->fp, $this->layout->getFooter()); + + $this->closeFile(); + $this->closed = true; + } + + /** + * Closes the previously opened file. + */ + function closeFile() + { + if ($this->fp) + @fclose($this->fp); + } + + /** + * @return boolean + */ + function getAppend() + { + return $this->append; + } + + /** + * @return string + */ + function getFile() + { + return $this->getFileName(); + } + + /** + * @return string + */ + function getFileName() + { + return $this->fileName; + } + + /** + * Close any previously opened file and call the parent's reset. + */ + function reset() + { + $this->closeFile(); + $this->fileName = null; + parent::reset(); + } + + function setAppend($flag) + { + $this->append = LoggerOptionConverter::toBoolean($flag, true); + } + + /** + * Sets and opens the file where the log output will go. + * + * This is an overloaded method. It can be called with: + * - setFile(string $fileName) to set filename. + * - setFile(string $fileName, boolean $append) to set filename and append. + */ + function setFile() + { + $numargs = func_num_args(); + $args = func_get_args(); + + if ($numargs == 1 and is_string($args[0])) { + $this->setFileName($args[0]); + } elseif ($numargs >=2 and is_string($args[0]) and is_bool($args[1])) { + $this->setFile($args[0]); + $this->setAppend($args[1]); + } + } + + function setFileName($fileName) + { + $this->fileName = $fileName; + } + + function append($event) + { + if ($this->fp and $this->layout !== null) { + + LoggerLog::debug("LoggerAppenderFile::append()"); + + @fwrite($this->fp, $this->layout->format($event)); + } + } +} +?> \ No newline at end of file diff --git a/src/lib/log4php/appenders/LoggerAppenderFirePHP.php b/src/lib/log4php/appenders/LoggerAppenderFirePHP.php new file mode 100644 index 0000000..9b5ae6e --- /dev/null +++ b/src/lib/log4php/appenders/LoggerAppenderFirePHP.php @@ -0,0 +1,110 @@ +LoggerAppenderSkeleton($name); + } + + function activateOptions() + { + global $debug_firephp; + $this->firephp = & FirePHP::getInstance(false); + if(!isset($this->firephp)) { + $this->firephp = & FirePHP::getInstance(true); + $this->firephp->setEnabled($debug_firephp); + $options = array('maxObjectDepth' => 10, + 'maxArrayDepth' => 20, + 'useNativeJsonEncode' => true, + 'includeLineNumbers' => true); + $this->firephp->setOptions($options); + // $this->firephp->registerErrorHandler(); + $this->firephp->registerExceptionHandler(); + } + return; + } + + function close() + { + } + + function get_ancestors ($class) { + $classes = array($class); + while($class = get_parent_class($class)) { $classes[] = $class; } + return $classes; + } + + function append($event) + { + LoggerLog::debug("LoggerAppenderFirePHP::append()"); + $message = array("message" => $event->getMessage()); + if (function_exists('debug_backtrace')) { + $prevHop = null; + $trace = debug_backtrace(); + // make a downsearch to identify the caller + $hop = array_pop($trace); + $step = array(); + while ($hop !== null) { + $className = @$hop['class']; + if ( !empty($className) and ($className == 'loggercategory' or in_array("LoggerCategory",$this->get_ancestors($className))) ) { + $step["file"] = str_replace("\\","/",str_replace(getcwd(), "", $hop["file"])); + $step["line"] = $hop['line']; + break; + } + $prevHop = $hop; + $hop = array_pop($trace); + } + $step['class'] = isset($prevHop['class']) ? $prevHop['class'] : 'main'; + if (isset($prevHop['function']) and + $prevHop['function'] !== 'include' and + $prevHop['function'] !== 'include_once' and + $prevHop['function'] !== 'require' and + $prevHop['function'] !== 'require_once') { + + $step['function'] = $prevHop['function']; + } else { + $step['function'] = 'main'; + } + $message["caller"] = join(":",array($step["file"],$step["class"],$step["function"],$step["line"])); + } + $label = ""; + if(isset($message["caller"])) { + $label = " ".$message["caller"]; + } + $level = & $event->getLevel(); + switch ($level->level) { + case LOG4PHP_LEVEL_INFO_INT: + $code = FirePHP::INFO; + break; + case LOG4PHP_LEVEL_WARN_INT: + $code = FirePHP::WARN; + break; + case LOG4PHP_LEVEL_ERROR_INT: + $code = FirePHP::ERROR; + break; + case LOG4PHP_LEVEL_FATAL_INT: + $code = FirePHP::ERROR; + break; + default: + $code = FirePHP::LOG; + break; + } + $this->firephp->fb($message,($level->levelStr).$label,$code); + } +} + +?> \ No newline at end of file diff --git a/src/lib/log4php/appenders/LoggerAppenderMail.php b/src/lib/log4php/appenders/LoggerAppenderMail.php new file mode 100644 index 0000000..c211e4a --- /dev/null +++ b/src/lib/log4php/appenders/LoggerAppenderMail.php @@ -0,0 +1,148 @@ +This framework is based on log4j (see {@link http://jakarta.apache.org/log4j log4j} for details).

    + *

    Design, strategies and part of the methods documentation are developed by log4j team + * (Ceki Gülcü as log4j project founder and + * {@link http://jakarta.apache.org/log4j/docs/contributors.html contributors}).

    + * + *

    PHP port, extensions and modifications by VxR. All rights reserved.
    + * For more information, please see {@link http://www.vxr.it/log4php/}.

    + * + *

    This software is published under the terms of the LGPL License + * a copy of which has been included with this distribution in the LICENSE file.

    + * + * @package log4php + * @subpackage appenders + */ + +/** + * @ignore + */ +if (!defined('LOG4PHP_DIR')) define('LOG4PHP_DIR', dirname(__FILE__) . '/..'); + +require_once(LOG4PHP_DIR . '/LoggerAppenderSkeleton.php'); +require_once(LOG4PHP_DIR . '/LoggerLog.php'); + +/** + * Appends log events to mail using php function {@link PHP_MANUAL#mail}. + * + *

    Parameters are {@link $from}, {@link $to}, {@link $subject}.

    + *

    This appender requires a layout.

    + * + * @author VxR + * @version $Revision: 1.8 $ + * @package log4php + * @subpackage appenders + */ +class LoggerAppenderMail extends LoggerAppenderSkeleton { + + /** + * @var string 'from' field + */ + var $from = null; + + /** + * @var string 'subject' field + */ + var $subject = 'Log4php Report'; + + /** + * @var string 'to' field + */ + var $to = null; + + /** + * @var string used to create mail body + * @access private + */ + var $body = ''; + + /** + * @access private + */ + var $requiresLayout = true; + + /** + * Constructor. + * + * @param string $name appender name + */ + function LoggerAppenderMail($name) + { + $this->LoggerAppenderSkeleton($name); + } + + function activateOptions() + { + $this->closed = false; + return; + } + + function close() + { + $from = $this->getFrom(); + $to = $this->getTo(); + + if (!empty($this->body) and $from !== null and $to !== null and $this->layout !== null) { + + $subject = $this->getSubject(); + + LoggerLog::debug("LoggerAppenderMail::close() sending mail from=[{$from}] to=[{$to}] subject=[{$subject}]"); + + @mail( + $to, $subject, + $this->layout->getHeader() . $this->body . $this->layout->getFooter(), + "From: {$from}\r\n" + ); + } + $this->closed = true; + } + + /** + * @return string + */ + function getFrom() + { + return $this->from; + } + + /** + * @return string + */ + function getSubject() + { + return $this->subject; + } + + /** + * @return string + */ + function getTo() + { + return $this->to; + } + + function setSubject($subject) + { + $this->subject = $subject; + } + + function setTo($to) + { + $this->to = $to; + } + + function setFrom($from) + { + $this->from = $from; + } + + function append($event) + { + if ($this->layout !== null) + $this->body .= $this->layout->format($event); + } +} +?> \ No newline at end of file diff --git a/src/lib/log4php/appenders/LoggerAppenderMailEvent.php b/src/lib/log4php/appenders/LoggerAppenderMailEvent.php new file mode 100644 index 0000000..1152255 --- /dev/null +++ b/src/lib/log4php/appenders/LoggerAppenderMailEvent.php @@ -0,0 +1,170 @@ +This framework is based on log4j (see {@link http://jakarta.apache.org/log4j log4j} for details).

    + *

    Design, strategies and part of the methods documentation are developed by log4j team + * (Ceki Gülcü as log4j project founder and + * {@link http://jakarta.apache.org/log4j/docs/contributors.html contributors}).

    + * + *

    PHP port, extensions and modifications by VxR. All rights reserved.
    + * For more information, please see {@link http://www.vxr.it/log4php/}.

    + * + *

    This software is published under the terms of the LGPL License + * a copy of which has been included with this distribution in the LICENSE file.

    + * + * @package log4php + * @subpackage appenders + */ + +/** + * @ignore + */ +if (!defined('LOG4PHP_DIR')) define('LOG4PHP_DIR', dirname(__FILE__) . '/..'); + +/** + */ +require_once(LOG4PHP_DIR . '/LoggerAppenderSkeleton.php'); +require_once(LOG4PHP_DIR . '/LoggerLog.php'); + +/** + * Log events to an email address. It will be created an email for each event. + * + *

    Parameters are + * {@link $smtpHost} (optional), + * {@link $port} (optional), + * {@link $from} (optional), + * {@link $to}, + * {@link $subject} (optional).

    + *

    A layout is required.

    + * + * @author Domenico Lordi + * @author VxR + * @version $Revision: 1.10 $ + * @package log4php + * @subpackage appenders + */ +class LoggerAppenderMailEvent extends LoggerAppenderSkeleton { + + /** + * @var string 'from' field + */ + var $from = null; + + /** + * @var integer 'from' field + */ + var $port = 25; + + /** + * @var string hostname. + */ + var $smtpHost = null; + + /** + * @var string 'subject' field + */ + var $subject = ''; + + /** + * @var string 'to' field + */ + var $to = null; + + /** + * @access private + */ + var $requiresLayout = true; + + /** + * Constructor. + * + * @param string $name appender name + */ + function LoggerAppenderMailEvent($name) + { + $this->LoggerAppenderSkeleton($name); + } + + function activateOptions() + { + $this->closed = false; + } + + function close() + { + $this->closed = true; + } + + /** + * @return string + */ + function getFrom() { return $this->from; } + + /** + * @return integer + */ + function getPort() { return $this->port; } + + /** + * @return string + */ + function getSmtpHost() { return $this->smtpHost; } + + /** + * @return string + */ + function getSubject() { return $this->subject; } + + /** + * @return string + */ + function getTo() { return $this->to; } + + function setFrom($from) { $this->from = $from; } + function setPort($port) { $this->port = (int)$port; } + function setSmtpHost($smtphost) { $this->smtpHost = $smtpHost; } + function setSubject($subject) { $this->subject = $subject; } + function setTo($to) { $this->to = $to; } + + function append($event) + { + $from = $this->getFrom(); + $to = $this->getTo(); + if (empty($from) or empty($to)) + return; + + $smtpHost = $this->getSmtpHost(); + $prevSmtpHost = ini_get('SMTP'); + if (!empty($smtpHost)) { + ini_set('SMTP', $smtpHost); + } else { + $smtpHost = $prevSmtpHost; + } + + $smtpPort = $this->getPort(); + $prevSmtpPort= ini_get('smtp_port'); + if ($smtpPort > 0 and $smtpPort < 65535) { + ini_set('smtp_port', $smtpPort); + } else { + $smtpPort = $prevSmtpPort; + } + + LoggerLog::debug( + "LoggerAppenderMailEvent::append()" . + ":from=[{$from}]:to=[{$to}]:smtpHost=[{$smtpHost}]:smtpPort=[{$smtpPort}]" + ); + + if (!@mail( $to, $this->getSubject(), + $this->layout->getHeader() . $this->layout->format($event) . $this->layout->getFooter($event), + "From: {$from}\r\n" + )) { + LoggerLog::debug("LoggerAppenderMailEvent::append() mail error"); + } + + ini_set('SMTP', $prevSmtpHost); + ini_set('smtp_port', $prevSmtpPort); + } +} + +?> \ No newline at end of file diff --git a/src/lib/log4php/appenders/LoggerAppenderNull.php b/src/lib/log4php/appenders/LoggerAppenderNull.php new file mode 100644 index 0000000..36a2f54 --- /dev/null +++ b/src/lib/log4php/appenders/LoggerAppenderNull.php @@ -0,0 +1,72 @@ +This framework is based on log4j (see {@link http://jakarta.apache.org/log4j log4j} for details).

    + *

    Design, strategies and part of the methods documentation are developed by log4j team + * (Ceki Gülcü as log4j project founder and + * {@link http://jakarta.apache.org/log4j/docs/contributors.html contributors}).

    + * + *

    PHP port, extensions and modifications by VxR. All rights reserved.
    + * For more information, please see {@link http://www.vxr.it/log4php/}.

    + * + *

    This software is published under the terms of the LGPL License + * a copy of which has been included with this distribution in the LICENSE file.

    + * + * @package log4php + * @subpackage appenders + */ + +/** + * @ignore + */ +if (!defined('LOG4PHP_DIR')) define('LOG4PHP_DIR', dirname(__FILE__) . '/..'); + +require_once(LOG4PHP_DIR . '/LoggerAppenderSkeleton.php'); +require_once(LOG4PHP_DIR . '/LoggerLog.php'); + +/** + * A NullAppender merely exists, it never outputs a message to any device. + * + * @author VxR + * @version $Revision: 1.4 $ + * @package log4php + * @subpackage appenders + */ +class LoggerAppenderNull extends LoggerAppenderSkeleton { + + /** + * @access private + */ + var $requiresLayout = false; + + /** + * Constructor. + * + * @param string $name appender name + */ + function LoggerAppenderNull($name) + { + $this->LoggerAppenderSkeleton($name); + } + + function activateOptions() + { + $this->closed = false; + } + + function close() + { + $this->closed = true; + } + + /** + * Do nothing. How I Love it !! :) + */ + function append($event) + { + LoggerLog::debug("LoggerAppenderNull::append()"); + } +} + +?> \ No newline at end of file diff --git a/src/lib/log4php/appenders/LoggerAppenderPhp.php b/src/lib/log4php/appenders/LoggerAppenderPhp.php new file mode 100644 index 0000000..69db345 --- /dev/null +++ b/src/lib/log4php/appenders/LoggerAppenderPhp.php @@ -0,0 +1,85 @@ +This framework is based on log4j (see {@link http://jakarta.apache.org/log4j log4j} for details).

    + *

    Design, strategies and part of the methods documentation are developed by log4j team + * (Ceki Gülcü as log4j project founder and + * {@link http://jakarta.apache.org/log4j/docs/contributors.html contributors}).

    + * + *

    PHP port, extensions and modifications by VxR. All rights reserved.
    + * For more information, please see {@link http://www.vxr.it/log4php/}.

    + * + *

    This software is published under the terms of the LGPL License + * a copy of which has been included with this distribution in the LICENSE file.

    + * + * @package log4php + * @subpackage appenders + */ + +/** + * @ignore + */ +if (!defined('LOG4PHP_DIR')) define('LOG4PHP_DIR', dirname(__FILE__) . '/..'); + +require_once(LOG4PHP_DIR . '/LoggerAppenderSkeleton.php'); +require_once(LOG4PHP_DIR . '/LoggerLevel.php'); +require_once(LOG4PHP_DIR . '/LoggerLog.php'); + +/** + * Log events using php {@link PHP_MANUAL#trigger_error} function and a {@link LoggerLayoutTTCC} default layout. + * + *

    Levels are mapped as follows:

    + * - level < WARN mapped to E_USER_NOTICE + * - WARN <= level < ERROR mapped to E_USER_WARNING + * - level >= ERROR mapped to E_USER_ERROR + * + * @author VxR + * @version $Revision: 1.11 $ + * @package log4php + * @subpackage appenders + */ +class LoggerAppenderPhp extends LoggerAppenderSkeleton { + + /** + * @access private + */ + var $requiresLayout = false; + + /** + * Constructor + * + * @param string $name appender name + */ + function LoggerAppenderPhp($name) + { + $this->LoggerAppenderSkeleton($name); + } + + function activateOptions() + { + $this->layout = LoggerLayout::factory('LoggerLayoutTTCC'); + $this->closed = false; + } + + function close() + { + $this->closed = true; + } + + function append($event) + { + if ($this->layout !== null) { + LoggerLog::debug("LoggerAppenderPhp::append()"); + $level = $event->getLevel(); + if ($level->isGreaterOrEqual(LoggerLevel::getLevelError())) { + trigger_error($this->layout->format($event), E_USER_ERROR); + } elseif ($level->isGreaterOrEqual(LoggerLevel::getLevelWarn())) { + trigger_error($this->layout->format($event), E_USER_WARNING); + } else { + trigger_error($this->layout->format($event), E_USER_NOTICE); + } + } + } +} +?> \ No newline at end of file diff --git a/src/lib/log4php/appenders/LoggerAppenderRollingFile.php b/src/lib/log4php/appenders/LoggerAppenderRollingFile.php new file mode 100644 index 0000000..885d134 --- /dev/null +++ b/src/lib/log4php/appenders/LoggerAppenderRollingFile.php @@ -0,0 +1,239 @@ +This framework is based on log4j (see {@link http://jakarta.apache.org/log4j log4j} for details).

    + *

    Design, strategies and part of the methods documentation are developed by log4j team + * (Ceki Gülcü as log4j project founder and + * {@link http://jakarta.apache.org/log4j/docs/contributors.html contributors}).

    + * + *

    PHP port, extensions and modifications by VxR. All rights reserved.
    + * For more information, please see {@link http://www.vxr.it/log4php/}.

    + * + *

    This software is published under the terms of the LGPL License + * a copy of which has been included with this distribution in the LICENSE file.

    + * + * @package log4php + * @subpackage appenders + */ + +/** + * @ignore + */ +if (!defined('LOG4PHP_DIR')) define('LOG4PHP_DIR', dirname(__FILE__) . '/..'); + +require_once(LOG4PHP_DIR . '/appenders/LoggerAppenderFile.php'); + +/** + * LoggerAppenderRollingFile extends LoggerAppenderFile to backup the log files + * when they reach a certain size. + * + *

    Parameters are {@link $maxFileSize}, {@link $maxBackupIndex}.

    + * + *

    Contributors: Sergio Strampelli.

    + * + * @author VxR + * @version $Revision: 1.14 $ + * @package log4php + * @subpackage appenders + */ +class LoggerAppenderRollingFile extends LoggerAppenderFile { + + /** + * Set the maximum size that the output file is allowed to reach + * before being rolled over to backup files. + * + *

    In configuration files, the MaxFileSize option takes a + * long integer in the range 0 - 2^63. You can specify the value + * with the suffixes "KB", "MB" or "GB" so that the integer is + * interpreted being expressed respectively in kilobytes, megabytes + * or gigabytes. For example, the value "10KB" will be interpreted + * as 10240.

    + *

    The default maximum file size is 10MB.

    + * + *

    Note that MaxFileSize cannot exceed 2 GB.

    + * + * @var integer + */ + var $maxFileSize = 10485760; + + /** + * Set the maximum number of backup files to keep around. + * + *

    The MaxBackupIndex option determines how many backup + * files are kept before the oldest is erased. This option takes + * a positive integer value. If set to zero, then there will be no + * backup files and the log file will be truncated when it reaches + * MaxFileSize.

    + *

    There is one backup file by default.

    + * + * @var integer + */ + var $maxBackupIndex = 1; + + /** + * @var string the filename expanded + * @access private + */ + var $expandedFileName = null; + + /** + * Constructor. + * + * @param string $name appender name + */ + function LoggerAppenderRollingFile($name) + { + $this->LoggerAppenderFile($name); + } + + /** + * Returns the value of the MaxBackupIndex option. + * @return integer + */ + function getExpandedFileName() { + return $this->expandedFileName; + } + + /** + * Returns the value of the MaxBackupIndex option. + * @return integer + */ + function getMaxBackupIndex() { + return $this->maxBackupIndex; + } + + /** + * Get the maximum size that the output file is allowed to reach + * before being rolled over to backup files. + * @return integer + */ + function getMaximumFileSize() { + return $this->maxFileSize; + } + + /** + * Implements the usual roll over behaviour. + * + *

    If MaxBackupIndex is positive, then files File.1, ..., File.MaxBackupIndex -1 are renamed to File.2, ..., File.MaxBackupIndex. + * Moreover, File is renamed File.1 and closed. A new File is created to receive further log output. + * + *

    If MaxBackupIndex is equal to zero, then the File is truncated with no backup files created. + */ + function rollOver() + { + // If maxBackups <= 0, then there is no file renaming to be done. + if($this->maxBackupIndex > 0) { + $fileName = $this->getExpandedFileName(); + // Delete the oldest file, to keep Windows happy. + $file = $fileName . '.' . $this->maxBackupIndex; + if (is_writable($file)) + unlink($file); + // Map {(maxBackupIndex - 1), ..., 2, 1} to {maxBackupIndex, ..., 3, 2} + for ($i = $this->maxBackupIndex - 1; $i >= 1; $i--) { + $file = $fileName . "." . $i; + if (is_readable($file)) { + $target = $fileName . '.' . ($i + 1); + rename($file, $target); + } + } + + // Rename fileName to fileName.1 + $target = $fileName . ".1"; + + $this->closeFile(); // keep windows happy. + + $file = $fileName; + rename($file, $target); + } + + $this->setFile($fileName, false); + unset($this->fp); + $this->activateOptions(); + } + + function setFileName($fileName) + { + $this->fileName = $fileName; + $this->expandedFileName = realpath($fileName); + LoggerLog::debug("LoggerAppenderRollingFile::setFileName():filename=[{$fileName}]:expandedFileName=[{$this->expandedFileName}]"); + } + + + /** + * Set the maximum number of backup files to keep around. + * + *

    The MaxBackupIndex option determines how many backup + * files are kept before the oldest is erased. This option takes + * a positive integer value. If set to zero, then there will be no + * backup files and the log file will be truncated when it reaches + * MaxFileSize. + * + * @param mixed $maxBackups + */ + function setMaxBackupIndex($maxBackups) + { + if (is_numeric($maxBackups)) + $this->maxBackupIndex = abs((int)$maxBackups); + } + + /** + * Set the maximum size that the output file is allowed to reach + * before being rolled over to backup files. + * + * @param mixed $maxFileSize + * @see setMaxFileSize() + */ + function setMaximumFileSize($maxFileSize) + { + $this->setMaxFileSize($maxFileSize); + } + + /** + * Set the maximum size that the output file is allowed to reach + * before being rolled over to backup files. + *

    In configuration files, the MaxFileSize option takes an + * long integer in the range 0 - 2^63. You can specify the value + * with the suffixes "KB", "MB" or "GB" so that the integer is + * interpreted being expressed respectively in kilobytes, megabytes + * or gigabytes. For example, the value "10KB" will be interpreted + * as 10240. + * + * @param mixed $value + */ + function setMaxFileSize($value) + { + $maxFileSize = null; + $numpart = substr($value,0, strlen($value) -2); + $suffix = strtoupper(substr($value, -2)); + + switch ($suffix) { + case 'KB': $maxFileSize = (int)((int)$numpart * 1024); break; + case 'MB': $maxFileSize = (int)((int)$numpart * 1024 * 1024); break; + case 'GB': $maxFileSize = (int)((int)$numpart * 1024 * 1024 * 1024); break; + default: + if (is_numeric($value)) { + $maxFileSize = (int)$value; + } + } + + if ($maxFileSize === null) { + LoggerLog::debug("LoggerAppenderRollingFile::setMaxFileSize():value=[$value] wrong declaration"); + } else { + $this->maxFileSize = abs($maxFileSize); + } + } + + /** + * @param LoggerLoggingEvent $event + */ + function append($event) + { + if ($this->fp) { + parent::append($event); + if (ftell($this->fp) > $this->getMaximumFileSize()) + $this->rollOver(); + } + } +} +?> \ No newline at end of file diff --git a/src/lib/log4php/appenders/LoggerAppenderSocket.php b/src/lib/log4php/appenders/LoggerAppenderSocket.php new file mode 100644 index 0000000..8bc9dcd --- /dev/null +++ b/src/lib/log4php/appenders/LoggerAppenderSocket.php @@ -0,0 +1,285 @@ +This framework is based on log4j (see {@link http://jakarta.apache.org/log4j log4j} for details).

    + *

    Design, strategies and part of the methods documentation are developed by log4j team + * (Ceki Gülcü as log4j project founder and + * {@link http://jakarta.apache.org/log4j/docs/contributors.html contributors}).

    + * + *

    PHP port, extensions and modifications by VxR. All rights reserved.
    + * For more information, please see {@link http://www.vxr.it/log4php/}.

    + * + *

    This software is published under the terms of the LGPL License + * a copy of which has been included with this distribution in the LICENSE file.

    + * + * @package log4php + * @subpackage appenders + */ + +/** + * @ignore + */ +if (!defined('LOG4PHP_DIR')) define('LOG4PHP_DIR', dirname(__FILE__) . '/..'); + +define('LOG4PHP_LOGGER_APPENDER_SOCKET_DEFAULT_PORT', 4446); +define('LOG4PHP_LOGGER_APPENDER_SOCKET_DEFAULT_TIMEOUT', 30); + +require_once(LOG4PHP_DIR . '/LoggerAppenderSkeleton.php'); +require_once(LOG4PHP_DIR . '/helpers/LoggerOptionConverter.php'); +require_once(LOG4PHP_DIR . '/LoggerLayout.php'); +require_once(LOG4PHP_DIR . '/LoggerLog.php'); + +/** + * Serialize events and send them to a network socket. + * + * Parameters are {@link $remoteHost}, {@link $port}, {@link $timeout}, + * {@link $locationInfo}, {@link $useXml} and {@link $log4jNamespace}. + * + * @author VxR + * @version $Revision: 1.17 $ + * @package log4php + * @subpackage appenders + */ +class LoggerAppenderSocket extends LoggerAppenderSkeleton { + + /** + * @var mixed socket connection resource + * @access private + */ + var $sp = false; + + /** + * Target host. On how to define remote hostaname see + * {@link PHP_MANUAL#fsockopen} + * @var string + */ + var $remoteHost = ''; + + /** + * @var integer the network port. + */ + var $port = LOG4PHP_LOGGER_APPENDER_SOCKET_DEFAULT_PORT; + + /** + * @var boolean get event's location info. + */ + var $locationInfo = false; + + /** + * @var integer connection timeout + */ + var $timeout = LOG4PHP_LOGGER_APPENDER_SOCKET_DEFAULT_TIMEOUT; + + /** + * @var boolean output events via {@link LoggerXmlLayout} + */ + var $useXml = false; + + /** + * @var boolean forward this option to {@link LoggerXmlLayout}. + * Ignored if {@link $useXml} is false. + */ + var $log4jNamespace = false; + + /** + * @var LoggerXmlLayout + * @access private + */ + var $xmlLayout = null; + + /** + * @var boolean + * @access private + */ + var $requiresLayout = false; + + /** + * Constructor + * + * @param string $name appender name + */ + function LoggerAppenderSocket($name) + { + $this->LoggerAppenderSkeleton($name); + } + + /** + * Create a socket connection using defined parameters + */ + function activateOptions() + { + LoggerLog::debug("LoggerAppenderSocket::activateOptions() creating a socket..."); + $errno = 0; + $errstr = ''; + $this->sp = @fsockopen($this->getRemoteHost(), $this->getPort(), $errno, $errstr, $this->getTimeout()); + if ($errno) { + LoggerLog::debug("LoggerAppenderSocket::activateOptions() socket error [$errno] $errstr"); + $this->closed = true; + } else { + LoggerLog::debug("LoggerAppenderSocket::activateOptions() socket created [".$this->sp."]"); + if ($this->getUseXml()) { + $this->xmlLayout = LoggerLayout::factory('LoggerXmlLayout'); + if ($this->xmlLayout === null) { + LoggerLog::debug("LoggerAppenderSocket::activateOptions() useXml is true but layout is null"); + $this->setUseXml(false); + } else { + $this->xmlLayout->setLocationInfo($this->getLocationInfo()); + $this->xmlLayout->setLog4jNamespace($this->getLog4jNamespace()); + $this->xmlLayout->activateOptions(); + } + } + $this->closed = false; + } + } + + function close() + { + @fclose($this->sp); + $this->closed = true; + } + + /** + * @return string + */ + function getHostname() + { + return $this->getRemoteHost(); + } + + /** + * @return boolean + */ + function getLocationInfo() + { + return $this->locationInfo; + } + + /** + * @return boolean + */ + function getLog4jNamespace() + { + return $this->log4jNamespace; + } + + /** + * @return integer + */ + function getPort() + { + return $this->port; + } + + function getRemoteHost() + { + return $this->remoteHost; + } + + /** + * @return integer + */ + function getTimeout() + { + return $this->timeout; + } + + /** + * @var boolean + */ + function getUseXml() + { + return $this->useXml; + } + + function reset() + { + $this->close(); + parent::reset(); + } + + /** + * @param string + * @deprecated Please, use {@link setRemoteHost} + */ + function setHostname($hostname) + { + $this->setRemoteHost($hostname); + } + + /** + * @param mixed + */ + function setLocationInfo($flag) + { + $this->locationInfo = LoggerOptionConverter::toBoolean($flag, $this->getLocationInfo()); + } + + /** + * @param mixed + */ + function setLog4jNamespace($flag) + { + $this->log4jNamespace = LoggerOptionConverter::toBoolean($flag, $this->getLog4jNamespace()); + } + + /** + * @param integer + */ + function setPort($port) + { + $port = LoggerOptionConverter::toInt($port, 0); + if ($port > 0 and $port < 65535) + $this->port = $port; + } + + /** + * @param string + */ + function setRemoteHost($hostname) + { + $this->remoteHost = $hostname; + } + + /** + * @param integer + */ + function setTimeout($timeout) + { + $this->timeout = LoggerOptionConverter::toInt($timeout, $this->getTimeout()); + } + + /** + * @param mixed + */ + function setUseXml($flag) + { + $this->useXml = LoggerOptionConverter::toBoolean($flag, $this->getUseXml()); + } + + /** + * @param LoggerLoggingEvent + */ + function append($event) + { + if ($this->sp) { + + LoggerLog::debug("LoggerAppenderSocket::append()"); + + if ($this->getLocationInfo()) + $event->getLocationInfo(); + + if (!$this->getUseXml()) { + $sEvent = serialize($event); + @fwrite($this->sp, $sEvent, strlen($sEvent)); + } else { + @fwrite($this->sp, $this->xmlLayout->format($event)); + } + + // not sure about it... + @fflush ($this->sp); + } + } +} + +?> \ No newline at end of file diff --git a/src/lib/log4php/appenders/LoggerAppenderSyslog.php b/src/lib/log4php/appenders/LoggerAppenderSyslog.php new file mode 100644 index 0000000..05195be --- /dev/null +++ b/src/lib/log4php/appenders/LoggerAppenderSyslog.php @@ -0,0 +1,85 @@ +This framework is based on log4j (see {@link http://jakarta.apache.org/log4j log4j} for details).

    + *

    Design, strategies and part of the methods documentation are developed by log4j team + * (Ceki Gülcü as log4j project founder and + * {@link http://jakarta.apache.org/log4j/docs/contributors.html contributors}).

    + * + *

    PHP port, extensions and modifications by VxR. All rights reserved.
    + * For more information, please see {@link http://www.vxr.it/log4php/}.

    + * + *

    This software is published under the terms of the LGPL License + * a copy of which has been included with this distribution in the LICENSE file.

    + * + * @package log4php + * @subpackage appenders + */ + +/** + * @ignore + */ +if (!defined('LOG4PHP_DIR')) define('LOG4PHP_DIR', dirname(__FILE__) . '/..'); + +require_once(LOG4PHP_DIR . '/LoggerAppenderSkeleton.php'); +require_once(LOG4PHP_DIR . '/LoggerLevel.php'); +require_once(LOG4PHP_DIR . '/LoggerLog.php'); + +/** + * Log events using php {@link PHP_MANUAL#syslog} function. + * + * Levels are mapped as follows: + * - level >= FATAL to LOG_ALERT + * - FATAL > level >= ERROR to LOG_ERR + * - ERROR > level >= WARN to LOG_WARNING + * - WARN > level >= INFO to LOG_INFO + * - INFO > level >= DEBUG to LOG_DEBUG + * + * @author VxR + * @version $Revision: 1.11 $ + * @package log4php + * @subpackage appenders + */ +class LoggerAppenderSyslog extends LoggerAppenderSkeleton { + + /** + * Constructor + * + * @param string $name appender name + */ + function LoggerAppenderSyslog($name) + { + $this->LoggerAppenderSkeleton($name); + } + + function activateOptions() + { + define_syslog_variables(); + $this->closed = false; + } + + function close() + { + closelog(); + $this->closed = true; + } + + function append($event) + { + $level = $event->getLevel(); + $message = $event->getRenderedMessage(); + if ($level->isGreaterOrEqual(LoggerLevel::getLevelFatal())) { + syslog(LOG_ALERT, $message); + } elseif ($level->isGreaterOrEqual(LoggerLevel::getLevelError())) { + syslog(LOG_ERR, $message); + } elseif ($level->isGreaterOrEqual(LoggerLevel::getLevelWarn())) { + syslog(LOG_WARNING, $message); + } elseif ($level->isGreaterOrEqual(LoggerLevel::getLevelInfo())) { + syslog(LOG_INFO, $message); + } elseif ($level->isGreaterOrEqual(LoggerLevel::getLevelDebug())) { + syslog(LOG_DEBUG, $message); + } + } +} +?> \ No newline at end of file diff --git a/src/lib/log4php/config/LoggerPropertyGetter.php b/src/lib/log4php/config/LoggerPropertyGetter.php new file mode 100644 index 0000000..9f4a380 --- /dev/null +++ b/src/lib/log4php/config/LoggerPropertyGetter.php @@ -0,0 +1,37 @@ +This framework is based on log4j (see {@link http://jakarta.apache.org/log4j log4j} for details).

    + *

    Design, strategies and part of the methods documentation are developed by log4j team + * (Ceki Gülcü as log4j project founder and + * {@link http://jakarta.apache.org/log4j/docs/contributors.html contributors}).

    + * + *

    PHP port, extensions and modifications by VxR. All rights reserved.
    + * For more information, please see {@link http://www.vxr.it/log4php/}.

    + * + *

    This software is published under the terms of the LGPL License + * a copy of which has been included with this distribution in the LICENSE file.

    + * + * @package log4php + * @subpackage config + */ + +/** + * @ignore + */ +if (!defined('LOG4PHP_DIR')) define('LOG4PHP_DIR', dirname(__FILE__) . '/..'); + +/** + * @author VxR + * @version $Revision: 1.2 $ + * @package log4php + * @subpackage config + * @since 0.5 + * @todo Ehm... try to guess... + */ +class LoggerPropertyGetter { + +} + +?> \ No newline at end of file diff --git a/src/lib/log4php/config/LoggerPropertySetter.php b/src/lib/log4php/config/LoggerPropertySetter.php new file mode 100644 index 0000000..08e3f05 --- /dev/null +++ b/src/lib/log4php/config/LoggerPropertySetter.php @@ -0,0 +1,161 @@ +This framework is based on log4j (see {@link http://jakarta.apache.org/log4j log4j} for details).

    + *

    Design, strategies and part of the methods documentation are developed by log4j team + * (Ceki Gülcü as log4j project founder and + * {@link http://jakarta.apache.org/log4j/docs/contributors.html contributors}).

    + * + *

    PHP port, extensions and modifications by VxR. All rights reserved.
    + * For more information, please see {@link http://www.vxr.it/log4php/}.

    + * + *

    This software is published under the terms of the LGPL License + * a copy of which has been included with this distribution in the LICENSE file.

    + * + * @package log4php + * @subpackage config + */ + +/** + * @ignore + */ +if (!defined('LOG4PHP_DIR')) define('LOG4PHP_DIR', dirname(__FILE__) . '/..'); + +require_once(LOG4PHP_DIR . '/LoggerLog.php'); +require_once(LOG4PHP_DIR . '/helpers/LoggerOptionConverter.php'); + +/** + * General purpose Object property setter. Clients repeatedly invokes + * {@link setProperty()} in order to invoke setters + * on the Object specified in the constructor. + * + * Usage: + * + * $ps = new LoggerPropertySetter($anObject); + * $ps->set("name", "Joe"); + * $ps->set("age", 32); + * $ps->set("isMale", true); + * + * will cause the invocations + * + * $anObject->setName("Joe"); + * $anObject->setAge(32); + * $anObject->setMale(true) + * + * if such methods exist. + * + * @author VxR + * @version $Revision: 1.4 $ + * @package log4php + * @subpackage config + * @since 0.5 + */ +class LoggerPropertySetter { + + /** + * @var object the target object + * @access private + */ + var $obj; + + /** + * Create a new LoggerPropertySetter for the specified Object. + * This is done in prepartion for invoking {@link setProperty()} + * one or more times. + * @param object &$obj the object for which to set properties + */ + function LoggerPropertySetter(&$obj) + { + $this->obj =& $obj; + } + + /** + * Set the properties of an object passed as a parameter in one + * go. The properties are parsed relative to a + * prefix. + * + * @param object &$obj The object to configure. + * @param array $properties An array containing keys and values. + * @param string $prefix Only keys having the specified prefix will be set. + * @static + */ + function setPropertiesByObject(&$obj, $properties, $prefix) + { + $pSetter = new LoggerPropertySetter($obj); + return $pSetter->setProperties($properties, $prefix); + } + + + /** + * Set the properites for the object that match the + * prefix passed as parameter. + * + * @param array $properties An array containing keys and values. + * @param string $prefix Only keys having the specified prefix will be set. + */ + function setProperties($properties, $prefix) + { + LoggerLog::debug("LoggerOptionConverter::setProperties():prefix=[{$prefix}]"); + + $len = strlen($prefix); + while (list($key,) = each($properties)) { + if (strpos($key, $prefix) === 0) { + if (strpos($key, '.', ($len + 1)) > 0) + continue; + $value = LoggerOptionConverter::findAndSubst($key, $properties); + $key = substr($key, $len); + if ($key == 'layout' and is_a($this->obj, 'loggerappender')) { + continue; + } + $this->setProperty($key, $value); + } + } + $this->activate(); + } + + /** + * Set a property on this PropertySetter's Object. If successful, this + * method will invoke a setter method on the underlying Object. The + * setter is the one for the specified property name and the value is + * determined partly from the setter argument type and partly from the + * value specified in the call to this method. + * + *

    If the setter expects a String no conversion is necessary. + * If it expects an int, then an attempt is made to convert 'value' + * to an int using new Integer(value). If the setter expects a boolean, + * the conversion is by new Boolean(value). + * + * @param string $name name of the property + * @param string $value String value of the property + */ + function setProperty($name, $value) + { + LoggerLog::debug("LoggerOptionConverter::setProperty():name=[{$name}]:value=[{$value}]"); + + if ($value === null) return; + + $method = "set" . ucfirst($name); + + if (!method_exists($this->obj, $method)) { + LoggerLog::warn( + "LoggerOptionConverter::setProperty() No such setter method for [{$name}] property in " . + get_class($this->obj) . "." + ); + } else { + return call_user_func(array(&$this->obj, $method), $value); + } + } + + function activate() + { + LoggerLog::debug("LoggerOptionConverter::activate()"); + + if (method_exists($this->obj, 'activateoptions')) { + return call_user_func(array(&$this->obj, 'activateoptions')); + } else { + LoggerLog::debug("LoggerOptionConverter::activate() Nothing to activate."); + } + } +} +?> \ No newline at end of file diff --git a/src/lib/log4php/helpers/LoggerFormattingInfo.php b/src/lib/log4php/helpers/LoggerFormattingInfo.php new file mode 100644 index 0000000..f642b63 --- /dev/null +++ b/src/lib/log4php/helpers/LoggerFormattingInfo.php @@ -0,0 +1,61 @@ +This framework is based on log4j (see {@link http://jakarta.apache.org/log4j log4j} for details).

    + *

    Design, strategies and part of the methods documentation are developed by log4j team + * (Ceki Gülcü as log4j project founder and + * {@link http://jakarta.apache.org/log4j/docs/contributors.html contributors}).

    + * + *

    PHP port, extensions and modifications by VxR. All rights reserved.
    + * For more information, please see {@link http://www.vxr.it/log4php/}.

    + * + *

    This software is published under the terms of the LGPL License + * a copy of which has been included with this distribution in the LICENSE file.

    + * + * @package log4php + * @subpackage helpers + */ + +/** + * @ignore + */ +if (!defined('LOG4PHP_DIR')) define('LOG4PHP_DIR', dirname(__FILE__) . '/..'); + +/** + */ +require_once(LOG4PHP_DIR . '/LoggerLog.php'); + +/** + * This class encapsulates the information obtained when parsing + * formatting modifiers in conversion modifiers. + * + * @author VxR + * @package log4php + * @subpackage spi + * @since 0.3 + */ +class LoggerFormattingInfo { + + var $min = -1; + var $max = 0x7FFFFFFF; + var $leftAlign = false; + + /** + * Constructor + */ + function LoggerFormattingInfo() {} + + function reset() + { + $this->min = -1; + $this->max = 0x7FFFFFFF; + $this->leftAlign = false; + } + + function dump() + { + LoggerLog::debug("LoggerFormattingInfo::dump() min={$this->min}, max={$this->max}, leftAlign={$this->leftAlign}"); + } +} +?> \ No newline at end of file diff --git a/src/lib/log4php/helpers/LoggerOptionConverter.php b/src/lib/log4php/helpers/LoggerOptionConverter.php new file mode 100644 index 0000000..0dd1439 --- /dev/null +++ b/src/lib/log4php/helpers/LoggerOptionConverter.php @@ -0,0 +1,350 @@ +This framework is based on log4j (see {@link http://jakarta.apache.org/log4j log4j} for details).

    + *

    Design, strategies and part of the methods documentation are developed by log4j team + * (Ceki Gülcü as log4j project founder and + * {@link http://jakarta.apache.org/log4j/docs/contributors.html contributors}).

    + * + *

    PHP port, extensions and modifications by VxR. All rights reserved.
    + * For more information, please see {@link http://www.vxr.it/log4php/}.

    + * + *

    This software is published under the terms of the LGPL License + * a copy of which has been included with this distribution in the LICENSE file.

    + * + * @package log4php + * @subpackage helpers + */ + +/** + * @ignore + */ +if (!defined('LOG4PHP_DIR')) define('LOG4PHP_DIR', dirname(__FILE__) . '/..'); + +require_once(LOG4PHP_DIR . '/LoggerLevel.php'); + +define('LOG4PHP_OPTION_CONVERTER_DELIM_START', '${'); +define('LOG4PHP_OPTION_CONVERTER_DELIM_STOP', '}'); +define('LOG4PHP_OPTION_CONVERTER_DELIM_START_LEN', 2); +define('LOG4PHP_OPTION_CONVERTER_DELIM_STOP_LEN', 1); + +/** + * A convenience class to convert property values to specific types. + * + * @author VxR + * @version $Revision: 1.6 $ + * @package log4php + * @subpackage helpers + * @static + * @since 0.5 + */ +class LoggerOptionConverter { + + /** + * OptionConverter is a static class. + */ + function OptionConverter() + { + return; + } + + /** + * @param array $l + * @param array $r + * @return array + * + * @static + */ + function concatanateArrays($l, $r) + { + return array_merge($l, $r); + } + + /** + * Read a predefined var. + * + * It returns a value referenced by $key using this search criteria: + * - if $key is a constant then return it. Else + * - if $key is set in $_ENV then return it. Else + * - return $def. + * + * @param string $key The key to search for. + * @param string $def The default value to return. + * @return string the string value of the system property, or the default + * value if there is no property with that key. + * + * @static + */ + function getSystemProperty($key, $def) + { + LoggerLog::debug("LoggerOptionConverter::getSystemProperty():key=[{$key}]:def=[{$def}]."); + + if (defined($key)) { + return (string)constant($key); + } elseif (isset($_ENV[$key])) { + return (string)$_ENV[$key]; + } else { + return $def; + } + } + + /** + * If $value is true, then true is + * returned. If $value is false, then + * true is returned. Otherwise, $default is + * returned. + * + *

    Case of value is unimportant.

    + * + * @param string $value + * @param boolean $default + * @return boolean + * + * @static + */ + function toBoolean($value, $default) + { + if($value === null) + return $default; + if ($value == 1) + return true; + $trimmedVal = strtolower(trim($value)); + if ("true" == $trimmedVal or "yes" == $trimmedVal) + return true; + if ("false" == $trimmedVal) + return false; + return $default; + } + + /** + * @param string $value + * @param integer $default + * @return integer + * @static + */ + function toInt($value, $default) + { + $value = trim($value); + if (is_numeric($value)) { + return (int)$value; + } else { + return $default; + } + } + + /** + * Converts a standard or custom priority level to a Level + * object. + * + *

    If $value is of form "level#full_file_classname", + * where full_file_classname means the class filename with path + * but without php extension, then the specified class' toLevel() method + * is called to process the specified level string; if no '#' + * character is present, then the default {@link LoggerLevel} + * class is used to process the level value.

    + * + *

    As a special case, if the $value parameter is + * equal to the string "NULL", then the value null will + * be returned.

    + * + *

    If any error occurs while converting the value to a level, + * the $defaultValue parameter, which may be + * null, is returned.

    + * + *

    Case of $value is insignificant for the level level, but is + * significant for the class name part, if present.

    + * + * @param string $value + * @param LoggerLevel $defaultValue + * @return LoggerLevel a {@link LoggerLevel} or null + * @static + */ + function toLevel($value, $defaultValue) + { + if($value === null) + return $defaultValue; + + $hashIndex = strpos($value, '#'); + if ($hashIndex === false) { + if("NULL" == strtoupper($value)) { + return null; + } else { + // no class name specified : use standard Level class + return LoggerLevel::toLevel($value, $defaultValue); + } + } + + $result = $defaultValue; + + $clazz = substr($value, ($hashIndex + 1)); + $levelName = substr($value, 0, $hashIndex); + + // This is degenerate case but you never know. + if("NULL" == strtoupper($levelName)) { + return null; + } + + LoggerLog::debug("LoggerOptionConverter::toLevel():class=[{$clazz}]:pri=[{$levelName}]"); + + if (!class_exists($clazz)) + @include_once("{$clazz}.php"); + + $clazz = basename($clazz); + + if (class_exists($clazz)) { + $result = @call_user_func(array($clazz, 'toLevel'), $value, $defaultValue); + if (!is_a($result, 'loggerlevel')) { + LoggerLog::debug("LoggerOptionConverter::toLevel():class=[{$clazz}] cannot call toLevel(). Returning default."); + $result = $defaultValue; + } + } else { + LoggerLog::warn("LoggerOptionConverter::toLevel() class '{$clazz}' doesnt exists."); + } + return $result; + } + + /** + * @param string $value + * @param float $default + * @return float + * + * @static + */ + function toFileSize($value, $default) + { + if ($value === null) + return $default; + + $s = strtoupper(trim($value)); + $multiplier = (float)1; + if(($index = strpos($s, 'KB')) !== false) { + $multiplier = 1024; + $s = substr($s, 0, $index); + } elseif(($index = strpos($s, 'MB')) !== false) { + $multiplier = 1024 * 1024; + $s = substr($s, 0, $index); + } elseif(($index = strpos($s, 'GB')) !== false) { + $multiplier = 1024 * 1024 * 1024; + $s = substr($s, 0, $index); + } + if(is_numeric($s)) { + return (float)$s * $multiplier; + } else { + LoggerLog::warn("LoggerOptionConverter::toFileSize() [{$s}] is not in proper form."); + } + return $default; + } + + /** + * Find the value corresponding to $key in + * $props. Then perform variable substitution on the + * found value. + * + * @param string $key + * @param array $props + * @return string + * + * @static + */ + function findAndSubst($key, $props) + { + $value = @$props[$key]; + if(empty($value)) { + return null; + } + return LoggerOptionConverter::substVars($value, $props); + } + + /** + * Perform variable substitution in string $val from the + * values of keys found with the {@link getSystemProperty()} method. + * + *

    The variable substitution delimeters are ${ and }. + * + *

    For example, if the "MY_CONSTANT" contains "value", then + * the call + * + * $s = LoggerOptionConverter::substituteVars("Value of key is ${MY_CONSTANT}."); + * + * will set the variable $s to "Value of key is value.".

    + * + *

    If no value could be found for the specified key, then the + * $props parameter is searched, if the value could not + * be found there, then substitution defaults to the empty string.

    + * + *

    For example, if {@link getSystemProperty()} cannot find any value for the key + * "inexistentKey", then the call + * + * $s = LoggerOptionConverter::substVars("Value of inexistentKey is [${inexistentKey}]"); + * + * will set $s to "Value of inexistentKey is []".

    + * + *

    A warn is thrown if $val contains a start delimeter "${" + * which is not balanced by a stop delimeter "}" and an empty string is returned.

    + * + * @log4j-author Avy Sharell + * + * @param string $val The string on which variable substitution is performed. + * @param array $props + * @return string + * + * @static + */ + function substVars($val, $props = null) + { + LoggerLog::debug("LoggerOptionConverter::substVars():val=[{$val}]"); + + $sbuf = ''; + $i = 0; + while(true) { + $j = strpos($val, LOG4PHP_OPTION_CONVERTER_DELIM_START, $i); + if ($j === false) { + LoggerLog::debug("LoggerOptionConverter::substVars() no more variables"); + // no more variables + if ($i == 0) { // this is a simple string + LoggerLog::debug("LoggerOptionConverter::substVars() simple string"); + return $val; + } else { // add the tail string which contails no variables and return the result. + $sbuf .= substr($val, $i); + LoggerLog::debug("LoggerOptionConverter::substVars():sbuf=[{$sbuf}]. Returning sbuf"); + return $sbuf; + } + } else { + + $sbuf .= substr($val, $i, $j-$i); + LoggerLog::debug("LoggerOptionConverter::substVars():sbuf=[{$sbuf}]:i={$i}:j={$j}."); + $k = strpos($val, LOG4PHP_OPTION_CONVERTER_DELIM_STOP, $j); + if ($k === false) { + LoggerLog::warn( + "LoggerOptionConverter::substVars() " . + "'{$val}' has no closing brace. Opening brace at position {$j}." + ); + return ''; + } else { + $j += LOG4PHP_OPTION_CONVERTER_DELIM_START_LEN; + $key = substr($val, $j, $k - $j); + // first try in System properties + $replacement = LoggerOptionConverter::getSystemProperty($key, null); + // then try props parameter + if($replacement == null and $props !== null) { + $replacement = @$props[$key]; + } + + if(!empty($replacement)) { + // Do variable substitution on the replacement string + // such that we can solve "Hello ${x2}" as "Hello p1" + // the where the properties are + // x1=p1 + // x2=${x1} + $recursiveReplacement = LoggerOptionConverter::substVars($replacement, $props); + $sbuf .= $recursiveReplacement; + } + $i = $k + LOG4PHP_OPTION_CONVERTER_DELIM_STOP_LEN; + } + } + } + } + +} +?> \ No newline at end of file diff --git a/src/lib/log4php/helpers/LoggerPatternConverter.php b/src/lib/log4php/helpers/LoggerPatternConverter.php new file mode 100644 index 0000000..3d68be8 --- /dev/null +++ b/src/lib/log4php/helpers/LoggerPatternConverter.php @@ -0,0 +1,504 @@ +This framework is based on log4j (see {@link http://jakarta.apache.org/log4j log4j} for details).

    + *

    Design, strategies and part of the methods documentation are developed by log4j team + * (Ceki Gülcü as log4j project founder and + * {@link http://jakarta.apache.org/log4j/docs/contributors.html contributors}).

    + * + *

    PHP port, extensions and modifications by VxR. All rights reserved.
    + * For more information, please see {@link http://www.vxr.it/log4php/}.

    + * + *

    This software is published under the terms of the LGPL License + * a copy of which has been included with this distribution in the LICENSE file.

    + * + * @package log4php + * @subpackage helpers + */ + +/** + * @ignore + */ +if (!defined('LOG4PHP_DIR')) define('LOG4PHP_DIR', dirname(__FILE__) . '/..'); + +/** + */ +require_once(LOG4PHP_DIR . '/LoggerLog.php'); + +/** + * Array for fast space padding + * Used by {@link LoggerPatternConverter::spacePad()}. + */ +$GLOBALS['log4php.LoggerPatternConverter.spaces'] = array(" ", " ", " ", " ", //1,2,4,8 spaces + " ", // 16 spaces + " " ); // 32 spaces + +/** + * LoggerPatternConverter is an abstract class that provides the formatting + * functionality that derived classes need. + * + *

    Conversion specifiers in a conversion patterns are parsed to + * individual PatternConverters. Each of which is responsible for + * converting a logging event in a converter specific manner.

    + * + * @author VxR + * @version $Revision: 1.13 $ + * @package log4php + * @subpackage helpers + * @abstract + * @since 0.3 + */ +class LoggerPatternConverter { + + /** + * @var LoggerPatternConverter next converter in converter chain + */ + var $next = null; + + var $min = -1; + var $max = 0x7FFFFFFF; + var $leftAlign = false; + + /** + * Constructor + * + * @param LoggerFormattingInfo $fi + */ + function LoggerPatternConverter($fi = null) + { + if ($fi !== null) { + $this->min = $fi->min; + $this->max = $fi->max; + $this->leftAlign = $fi->leftAlign; + } + } + + /** + * Derived pattern converters must override this method in order to + * convert conversion specifiers in the correct way. + * + * @param LoggerLoggingEvent $event + */ + function convert($event) {} + + /** + * A template method for formatting in a converter specific way. + * + * @param string &$sbuf string buffer + * @param LoggerLoggingEvent $e + */ + function format(&$sbuf, $e) + { + LoggerLog::debug("LoggerPatternConverter::format() sbuf='$sbuf'"); + + $s = $this->convert($e); + + LoggerLog::debug("LoggerPatternConverter::format() converted event is '$s'"); + + + if($s == null or empty($s)) { + if(0 < $this->min) + $this->spacePad($sbuf, $this->min); + return; + } + + $len = strlen($s); + + if($len > $this->max) { + $sbuf .= substr($s , 0, ($len - $this->max)); + } elseif($len < $this->min) { + if($this->leftAlign) { + $sbuf .= $s; + $this->spacePad($sbuf, ($this->min - $len)); + } else { + $this->spacePad($sbuf, ($this->min - $len)); + $sbuf .= $s; + } + } else { + $sbuf .= $s; + } + } + + + /** + * Fast space padding method. + * + * @param string &$sbuf string buffer + * @param integer $length pad length + * + * @todo reimplement using PHP string functions + */ + function spacePad(&$sbuf, $length) + { + LoggerLog::debug("LoggerPatternConverter::spacePad() sbuf='$sbuf' len='$length'"); + + while($length >= 32) { + $sbuf .= $GLOBALS['log4php.LoggerPatternConverter.spaces'][5]; + $length -= 32; + } + + for($i = 4; $i >= 0; $i--) { + if(($length & (1<<$i)) != 0) { + $sbuf .= $GLOBALS['log4php.LoggerPatternConverter.spaces'][$i]; + } + } + + // $sbuf = str_pad($sbuf, $length); + } +} + +// --------------------------------------------------------------------- +// PatternConverters +// --------------------------------------------------------------------- + +/** + * @author VxR + * @package log4php + * @subpackage helpers + */ +class LoggerBasicPatternConverter extends LoggerPatternConverter { + + /** + * @var integer + */ + var $type; + + /** + * Constructor + * + * @param string $formattingInfo + * @param integer $type + */ + function LoggerBasicPatternConverter($formattingInfo, $type) + { + LoggerLog::debug("LoggerBasicPatternConverter::LoggerBasicPatternConverter() type='$type'"); + + $this->LoggerPatternConverter($formattingInfo); + $this->type = $type; + } + + /** + * @param LoggerLoggingEvent $event + * @return string + */ + function convert($event) + { + switch($this->type) { + case LOG4PHP_LOGGER_PATTERN_PARSER_RELATIVE_TIME_CONVERTER: + $timeStamp = $event->getTimeStamp(); + $startTime = LoggerLoggingEvent::getStartTime(); + return (string)(int)($timeStamp * 1000 - $startTime * 1000); + + case LOG4PHP_LOGGER_PATTERN_PARSER_THREAD_CONVERTER: + return $event->getThreadName(); + + case LOG4PHP_LOGGER_PATTERN_PARSER_LEVEL_CONVERTER: + $level = $event->getLevel(); + return $level->toString(); + + case LOG4PHP_LOGGER_PATTERN_PARSER_NDC_CONVERTER: + return $event->getNDC(); + + case LOG4PHP_LOGGER_PATTERN_PARSER_MESSAGE_CONVERTER: + return $event->getRenderedMessage(); + + default: + return ''; + } + } +} + +/** + * @author VxR + * @package log4php + * @subpackage helpers + */ +class LoggerLiteralPatternConverter extends LoggerPatternConverter { + + /** + * @var string + */ + var $literal; + + /** + * Constructor + * + * @param string $value + */ + function LoggerLiteralPatternConverter($value) + { + LoggerLog::debug("LoggerLiteralPatternConverter::LoggerLiteralPatternConverter() value='$value'"); + + $this->literal = $value; + } + + /** + * @param string &$sbuf + * @param LoggerLoggingEvent $event + */ + function format(&$sbuf, $event) + { + $sbuf .= $this->literal; + } + + /** + * @param LoggerLoggingEvent $event + * @return string + */ + function convert($event) + { + return $this->literal; + } +} + +/** + * @author VxR + * @package log4php + * @subpackage helpers + */ +class LoggerDatePatternConverter extends LoggerPatternConverter { + + /** + * @var string + */ + var $df; + + /** + * Constructor + * + * @param string $formattingInfo + * @param string $df + */ + function LoggerDatePatternConverter($formattingInfo, $df) + { + LoggerLog::debug("LoggerDatePatternConverter::LoggerDatePatternConverter() dateFormat='$df'"); + + $this->LoggerPatternConverter($formattingInfo); + $this->df = $df; + } + + /** + * @param LoggerLoggingEvent $event + * @return string + */ + function convert($event) + { + $timeStamp = $event->getTimeStamp(); + $usecs = round(($timeStamp - (int)$timeStamp) * 1000); + $this->df = str_replace("\u", "u", ereg_replace("[^\\]u", sprintf(',%03d', $usecs), $this->df)); + + return date($this->df, $event->getTimeStamp()); + + } +} + +/** + * @author VxR + * @package log4php + * @subpackage helpers + */ +class LoggerMDCPatternConverter extends LoggerPatternConverter { + + /** + * @var string + */ + var $key; + + /** + * Constructor + * + * @param string $formattingInfo + * @param string $key + */ + function LoggerMDCPatternConverter($formattingInfo, $key) + { + LoggerLog::debug("LoggerMDCPatternConverter::LoggerMDCPatternConverter() key='$key'"); + + $this->LoggerPatternConverter($formattingInfo); + $this->key = $key; + } + + /** + * @param LoggerLoggingEvent $event + * @return string + */ + function convert($event) + { + return $event->getMDC($this->key); + } +} + +/** + * @author VxR + * @package log4php + * @subpackage helpers + */ +class LoggerLocationPatternConverter extends LoggerPatternConverter { + + /** + * @var integer + */ + var $type; + + /** + * Constructor + * + * @param string $formattingInfo + * @param integer $type + */ + function LoggerLocationPatternConverter($formattingInfo, $type) + { + LoggerLog::debug("LoggerLocationPatternConverter::LoggerLocationPatternConverter() type='$type'"); + + $this->LoggerPatternConverter($formattingInfo); + $this->type = $type; + } + + /** + * @param LoggerLoggingEvent $event + * @return string + */ + function convert($event) + { + $locationInfo = $event->getLocationInformation(); + switch($this->type) { + case LOG4PHP_LOGGER_PATTERN_PARSER_FULL_LOCATION_CONVERTER: + return $locationInfo->fullInfo; + case LOG4PHP_LOGGER_PATTERN_PARSER_METHOD_LOCATION_CONVERTER: + return $locationInfo->getMethodName(); + case LOG4PHP_LOGGER_PATTERN_PARSER_LINE_LOCATION_CONVERTER: + return $locationInfo->getLineNumber(); + case LOG4PHP_LOGGER_PATTERN_PARSER_FILE_LOCATION_CONVERTER: + return $locationInfo->getFileName(); + default: + return ''; + } + } +} + +/** + * @author VxR + * @package log4php + * @subpackage helpers + * @abstract + */ +class LoggerNamedPatternConverter extends LoggerPatternConverter { + + /** + * @var integer + */ + var $precision; + + /** + * Constructor + * + * @param string $formattingInfo + * @param integer $precision + */ + function LoggerNamedPatternConverter($formattingInfo, $precision) + { + LoggerLog::debug("LoggerNamedPatternConverter::LoggerNamedPatternConverter() precision='$precision'"); + + $this->LoggerPatternConverter($formattingInfo); + $this->precision = $precision; + } + + /** + * @param LoggerLoggingEvent $event + * @return string + * @abstract + */ + function getFullyQualifiedName($event) + { + // abstract + return; + } + + /** + * @param LoggerLoggingEvent $event + * @return string + */ + function convert($event) + { + $n = $this->getFullyQualifiedName($event); + if ($this->precision <= 0) { + return $n; + } else { + $len = strlen($n); + + // We substract 1 from 'len' when assigning to 'end' to avoid out of + // bounds exception in return r.substring(end+1, len). This can happen if + // precision is 1 and the category name ends with a dot. + $end = $len -1 ; + for($i = $this->precision; $i > 0; $i--) { + $end = strrpos(substr($n, 0, ($end - 1)), '.'); + if ($end == false) + return $n; + } + return substr($n, ($end + 1), $len); + } + } +} + +/** + * @author VxR + * @package log4php + * @subpackage helpers + */ +class LoggerClassNamePatternConverter extends LoggerNamedPatternConverter { + + /** + * Constructor + * + * @param string $formattingInfo + * @param integer $precision + */ + function LoggerClassNamePatternConverter($formattingInfo, $precision) + { + LoggerLog::debug("LoggerClassNamePatternConverter::LoggerClassNamePatternConverter() precision='$precision'"); + + $this->LoggerNamedPatternConverter($formattingInfo, $precision); + } + + /** + * @param LoggerLoggingEvent $event + * @return string + */ + function getFullyQualifiedName($event) + { + return $event->fqcn; + } +} + +/** + * @author VxR + * @package log4php + * @subpackage helpers + */ +class LoggerCategoryPatternConverter extends LoggerNamedPatternConverter { + + /** + * Constructor + * + * @param string $formattingInfo + * @param integer $precision + */ + function LoggerCategoryPatternConverter($formattingInfo, $precision) + { + LoggerLog::debug("LoggerCategoryPatternConverter::LoggerCategoryPatternConverter() precision='$precision'"); + + $this->LoggerNamedPatternConverter($formattingInfo, $precision); + } + + /** + * @param LoggerLoggingEvent $event + * @return string + */ + function getFullyQualifiedName($event) + { + return $event->getLoggerName(); + } +} + +?> \ No newline at end of file diff --git a/src/lib/log4php/helpers/LoggerPatternParser.php b/src/lib/log4php/helpers/LoggerPatternParser.php new file mode 100644 index 0000000..307fbd7 --- /dev/null +++ b/src/lib/log4php/helpers/LoggerPatternParser.php @@ -0,0 +1,419 @@ +This framework is based on log4j (see {@link http://jakarta.apache.org/log4j log4j} for details).

    + *

    Design, strategies and part of the methods documentation are developed by log4j team + * (Ceki Gülcü as log4j project founder and + * {@link http://jakarta.apache.org/log4j/docs/contributors.html contributors}).

    + * + *

    PHP port, extensions and modifications by VxR. All rights reserved.
    + * For more information, please see {@link http://www.vxr.it/log4php/}.

    + * + *

    This software is published under the terms of the LGPL License + * a copy of which has been included with this distribution in the LICENSE file.

    + * + * @package log4php + * @subpackage helpers + */ + +/** + * @ignore + */ +if (!defined('LOG4PHP_DIR')) define('LOG4PHP_DIR', dirname(__FILE__) . '/..'); + +if (!defined('LOG4PHP_LINE_SEP')) { + if (substr(php_uname(), 0, 7) == "Windows") { + /** + * @ignore + */ + define('LOG4PHP_LINE_SEP', "\r\n"); + } else { + /** + * @ignore + */ + define('LOG4PHP_LINE_SEP', "\n"); + } +} + +/** + */ +require_once(LOG4PHP_DIR . '/helpers/LoggerFormattingInfo.php'); +require_once(LOG4PHP_DIR . '/helpers/LoggerPatternConverter.php'); +require_once(LOG4PHP_DIR . '/LoggerLog.php'); + +define('LOG4PHP_LOGGER_PATTERN_PARSER_ESCAPE_CHAR', '%'); + +define('LOG4PHP_LOGGER_PATTERN_PARSER_LITERAL_STATE', 0); +define('LOG4PHP_LOGGER_PATTERN_PARSER_CONVERTER_STATE', 1); +define('LOG4PHP_LOGGER_PATTERN_PARSER_MINUS_STATE', 2); +define('LOG4PHP_LOGGER_PATTERN_PARSER_DOT_STATE', 3); +define('LOG4PHP_LOGGER_PATTERN_PARSER_MIN_STATE', 4); +define('LOG4PHP_LOGGER_PATTERN_PARSER_MAX_STATE', 5); + +define('LOG4PHP_LOGGER_PATTERN_PARSER_FULL_LOCATION_CONVERTER', 1000); +define('LOG4PHP_LOGGER_PATTERN_PARSER_METHOD_LOCATION_CONVERTER', 1001); +define('LOG4PHP_LOGGER_PATTERN_PARSER_CLASS_LOCATION_CONVERTER', 1002); +define('LOG4PHP_LOGGER_PATTERN_PARSER_FILE_LOCATION_CONVERTER', 1003); +define('LOG4PHP_LOGGER_PATTERN_PARSER_LINE_LOCATION_CONVERTER', 1004); + +define('LOG4PHP_LOGGER_PATTERN_PARSER_RELATIVE_TIME_CONVERTER', 2000); +define('LOG4PHP_LOGGER_PATTERN_PARSER_THREAD_CONVERTER', 2001); +define('LOG4PHP_LOGGER_PATTERN_PARSER_LEVEL_CONVERTER', 2002); +define('LOG4PHP_LOGGER_PATTERN_PARSER_NDC_CONVERTER', 2003); +define('LOG4PHP_LOGGER_PATTERN_PARSER_MESSAGE_CONVERTER', 2004); + +define('LOG4PHP_LOGGER_PATTERN_PARSER_DATE_FORMAT_ISO8601', 'Y-m-d H:i:s,u'); +define('LOG4PHP_LOGGER_PATTERN_PARSER_DATE_FORMAT_ABSOLUTE', 'H:i:s'); +define('LOG4PHP_LOGGER_PATTERN_PARSER_DATE_FORMAT_DATE', 'd M Y H:i:s,u'); + +/** + * Most of the work of the {@link LoggerPatternLayout} class + * is delegated to the {@link LoggerPatternParser} class. + * + *

    It is this class that parses conversion patterns and creates + * a chained list of {@link LoggerPatternConverter} converters.

    + * + * @author VxR + * @version $Revision: 1.10 $ + * @package log4php + * @subpackage helpers + * + * @since 0.3 + */ +class LoggerPatternParser { + + var $state; + var $currentLiteral; + var $patternLength; + var $i; + + /** + * @var LoggerPatternConverter + */ + var $head = null; + + /** + * @var LoggerPatternConverter + */ + var $tail = null; + + /** + * @var LoggerFormattingInfo + */ + var $formattingInfo; + + /** + * @var string pattern to parse + */ + var $pattern; + + /** + * Constructor + * + * @param string $pattern + */ + function LoggerPatternParser($pattern) + { + LoggerLog::debug("LoggerPatternParser::LoggerPatternParser() pattern='$pattern'"); + + $this->pattern = $pattern; + $this->patternLength = strlen($pattern); + $this->formattingInfo = new LoggerFormattingInfo(); + $this->state = LOG4PHP_LOGGER_PATTERN_PARSER_LITERAL_STATE; + } + + /** + * @param LoggerPatternConverter $pc + */ + function addToList($pc) + { + // LoggerLog::debug("LoggerPatternParser::addToList()"); + + if($this->head == null) { + $this->head = $pc; + $this->tail =& $this->head; + } else { + $this->tail->next = $pc; + $this->tail =& $this->tail->next; + } + } + + /** + * @return string + */ + function extractOption() + { + if(($this->i < $this->patternLength) and ($this->pattern{$this->i} == '{')) { + $end = strpos($this->pattern, '}' , $this->i); + if ($end !== false) { + $r = substr($this->pattern, ($this->i + 1), ($end - $this->i - 1)); + $this->i= $end + 1; + return $r; + } + } + return null; + } + + /** + * The option is expected to be in decimal and positive. In case of + * error, zero is returned. + */ + function extractPrecisionOption() + { + $opt = $this->extractOption(); + $r = 0; + if ($opt !== null) { + if (is_numeric($opt)) { + $r = (int)$opt; + if($r <= 0) { + LoggerLog::warn("Precision option ({$opt}) isn't a positive integer."); + $r = 0; + } + } else { + LoggerLog::warn("Category option \"{$opt}\" not a decimal integer."); + } + } + return $r; + } + + function parse() + { + LoggerLog::debug("LoggerPatternParser::parse()"); + + $c = ''; + $this->i = 0; + $this->currentLiteral = ''; + while ($this->i < $this->patternLength) { + $c = $this->pattern{$this->i++}; +// LoggerLog::debug("LoggerPatternParser::parse() char is now '$c' and currentLiteral is '{$this->currentLiteral}'"); + switch($this->state) { + case LOG4PHP_LOGGER_PATTERN_PARSER_LITERAL_STATE: + // LoggerLog::debug("LoggerPatternParser::parse() state is 'LOG4PHP_LOGGER_PATTERN_PARSER_LITERAL_STATE'"); + // In literal state, the last char is always a literal. + if($this->i == $this->patternLength) { + $this->currentLiteral .= $c; + continue; + } + if($c == LOG4PHP_LOGGER_PATTERN_PARSER_ESCAPE_CHAR) { + // LoggerLog::debug("LoggerPatternParser::parse() char is an escape char"); + // peek at the next char. + switch($this->pattern{$this->i}) { + case LOG4PHP_LOGGER_PATTERN_PARSER_ESCAPE_CHAR: + // LoggerLog::debug("LoggerPatternParser::parse() next char is an escape char"); + $this->currentLiteral .= $c; + $this->i++; // move pointer + break; + case 'n': + // LoggerLog::debug("LoggerPatternParser::parse() next char is 'n'"); + $this->currentLiteral .= LOG4PHP_LINE_SEP; + $this->i++; // move pointer + break; + default: + if(strlen($this->currentLiteral) != 0) { + $this->addToList(new LoggerLiteralPatternConverter($this->currentLiteral)); + LoggerLog::debug("LoggerPatternParser::parse() Parsed LITERAL converter: \"{$this->currentLiteral}\"."); + } + $this->currentLiteral = $c; + $this->state = LOG4PHP_LOGGER_PATTERN_PARSER_CONVERTER_STATE; + $this->formattingInfo->reset(); + } + } else { + $this->currentLiteral .= $c; + } + break; + case LOG4PHP_LOGGER_PATTERN_PARSER_CONVERTER_STATE: + // LoggerLog::debug("LoggerPatternParser::parse() state is 'LOG4PHP_LOGGER_PATTERN_PARSER_CONVERTER_STATE'"); + $this->currentLiteral .= $c; + switch($c) { + case '-': + $this->formattingInfo->leftAlign = true; + break; + case '.': + $this->state = LOG4PHP_LOGGER_PATTERN_PARSER_DOT_STATE; + break; + default: + if(ord($c) >= ord('0') and ord($c) <= ord('9')) { + $this->formattingInfo->min = ord($c) - ord('0'); + $this->state = LOG4PHP_LOGGER_PATTERN_PARSER_MIN_STATE; + } else { + $this->finalizeConverter($c); + } + } // switch + break; + case LOG4PHP_LOGGER_PATTERN_PARSER_MIN_STATE: + // LoggerLog::debug("LoggerPatternParser::parse() state is 'LOG4PHP_LOGGER_PATTERN_PARSER_MIN_STATE'"); + $this->currentLiteral .= $c; + if(ord($c) >= ord('0') and ord($c) <= ord('9')) { + $this->formattingInfo->min = ($this->formattingInfo->min * 10) + (ord(c) - ord('0')); + } elseif ($c == '.') { + $this->state = LOG4PHP_LOGGER_PATTERN_PARSER_DOT_STATE; + } else { + $this->finalizeConverter($c); + } + break; + case LOG4PHP_LOGGER_PATTERN_PARSER_DOT_STATE: + // LoggerLog::debug("LoggerPatternParser::parse() state is 'LOG4PHP_LOGGER_PATTERN_PARSER_DOT_STATE'"); + $this->currentLiteral .= $c; + if(ord($c) >= ord('0') and ord($c) <= ord('9')) { + $this->formattingInfo->max = ord($c) - ord('0'); + $this->state = LOG4PHP_LOGGER_PATTERN_PARSER_MAX_STATE; + } else { + LoggerLog::warn("LoggerPatternParser::parse() Error occured in position {$this->i}. Was expecting digit, instead got char \"{$c}\"."); + $this->state = LOG4PHP_LOGGER_PATTERN_PARSER_LITERAL_STATE; + } + break; + case LOG4PHP_LOGGER_PATTERN_PARSER_MAX_STATE: + // LoggerLog::debug("LoggerPatternParser::parse() state is 'LOG4PHP_LOGGER_PATTERN_PARSER_MAX_STATE'"); + $this->currentLiteral .= $c; + if(ord($c) >= ord('0') and ord($c) <= ord('9')) { + $this->formattingInfo->max = ($this->formattingInfo->max * 10) + (ord($c) - ord('0')); + } else { + $this->finalizeConverter($c); + $this->state = LOG4PHP_LOGGER_PATTERN_PARSER_LITERAL_STATE; + } + break; + } // switch + } // while + if(strlen($this->currentLiteral) != 0) { + $this->addToList(new LoggerLiteralPatternConverter($this->currentLiteral)); + // LoggerLog::debug("LoggerPatternParser::parse() Parsed LITERAL converter: \"{$this->currentLiteral}\"."); + } + return $this->head; + } + + function finalizeConverter($c) + { + LoggerLog::debug("LoggerPatternParser::finalizeConverter() with char '$c'"); + + $pc = null; + switch($c) { + case 'c': + $pc = new LoggerCategoryPatternConverter($this->formattingInfo, $this->extractPrecisionOption()); + LoggerLog::debug("LoggerPatternParser::finalizeConverter() CATEGORY converter."); + // $this->formattingInfo->dump(); + $this->currentLiteral = ''; + break; + case 'C': + $pc = new LoggerClassNamePatternConverter($this->formattingInfo, $this->extractPrecisionOption()); + LoggerLog::debug("LoggerPatternParser::finalizeConverter() CLASSNAME converter."); + //$this->formattingInfo->dump(); + $this->currentLiteral = ''; + break; + case 'd': + $dateFormatStr = LOG4PHP_LOGGER_PATTERN_PARSER_DATE_FORMAT_ISO8601; // ISO8601_DATE_FORMAT; + $dOpt = $this->extractOption(); + + if($dOpt !== null) + $dateFormatStr = $dOpt; + + if ($dateFormatStr == 'ISO8601') { + $df = LOG4PHP_LOGGER_PATTERN_PARSER_DATE_FORMAT_ISO8601; + } elseif($dateFormatStr == 'ABSOLUTE') { + $df = LOG4PHP_LOGGER_PATTERN_PARSER_DATE_FORMAT_ABSOLUTE; + } elseif($dateFormatStr == 'DATE') { + $df = LOG4PHP_LOGGER_PATTERN_PARSER_DATE_FORMAT_DATE; + } else { + $df = $dateFormatStr; + if ($df == null) { + $df = LOG4PHP_LOGGER_PATTERN_PARSER_DATE_FORMAT_ISO8601; + } + } + $pc = new LoggerDatePatternConverter($this->formattingInfo, $df); + $this->currentLiteral = ''; + break; + case 'F': + $pc = new LoggerLocationPatternConverter($this->formattingInfo, LOG4PHP_LOGGER_PATTERN_PARSER_FILE_LOCATION_CONVERTER); + LoggerLog::debug("LoggerPatternParser::finalizeConverter() File name converter."); + //formattingInfo.dump(); + $this->currentLiteral = ''; + break; + case 'l': + $pc = new LoggerLocationPatternConverter($this->formattingInfo, LOG4PHP_LOGGER_PATTERN_PARSER_FULL_LOCATION_CONVERTER); + LoggerLog::debug("LoggerPatternParser::finalizeConverter() Location converter."); + //formattingInfo.dump(); + $this->currentLiteral = ''; + break; + case 'L': + $pc = new LoggerLocationPatternConverter($this->formattingInfo, LOG4PHP_LOGGER_PATTERN_PARSER_LINE_LOCATION_CONVERTER); + LoggerLog::debug("LoggerPatternParser::finalizeConverter() LINE NUMBER converter."); + //formattingInfo.dump(); + $this->currentLiteral = ''; + break; + case 'm': + $pc = new LoggerBasicPatternConverter($this->formattingInfo, LOG4PHP_LOGGER_PATTERN_PARSER_MESSAGE_CONVERTER); + LoggerLog::debug("LoggerPatternParser::finalizeConverter() MESSAGE converter."); + //formattingInfo.dump(); + $this->currentLiteral = ''; + break; + case 'M': + $pc = new LoggerLocationPatternConverter($this->formattingInfo, LOG4PHP_LOGGER_PATTERN_PARSER_METHOD_LOCATION_CONVERTER); + //LogLog.debug("METHOD converter."); + //formattingInfo.dump(); + $this->currentLiteral = ''; + break; + case 'p': + $pc = new LoggerBasicPatternConverter($this->formattingInfo, LOG4PHP_LOGGER_PATTERN_PARSER_LEVEL_CONVERTER); + //LogLog.debug("LEVEL converter."); + //formattingInfo.dump(); + $this->currentLiteral = ''; + break; + case 'r': + $pc = new LoggerBasicPatternConverter($this->formattingInfo, LOG4PHP_LOGGER_PATTERN_PARSER_RELATIVE_TIME_CONVERTER); + LoggerLog::debug("LoggerPatternParser::finalizeConverter() RELATIVE TIME converter."); + //formattingInfo.dump(); + $this->currentLiteral = ''; + break; + case 't': + $pc = new LoggerBasicPatternConverter($this->formattingInfo, LOG4PHP_LOGGER_PATTERN_PARSER_THREAD_CONVERTER); + LoggerLog::debug("LoggerPatternParser::finalizeConverter() THREAD converter."); + //formattingInfo.dump(); + $this->currentLiteral = ''; + break; + case 'u': + if($this->i < $this->patternLength) { + $cNext = $this->pattern{$this->i}; + if(ord($cNext) >= ord('0') and ord($cNext) <= ord('9')) { + $pc = new LoggerUserFieldPatternConverter($this->formattingInfo, (string)(ord($cNext) - ord('0'))); + LoggerLog::debug("LoggerPatternParser::finalizeConverter() USER converter [{$cNext}]."); + // formattingInfo.dump(); + $this->currentLiteral = ''; + $this->i++; + } else { + LoggerLog::warn("LoggerPatternParser::finalizeConverter() Unexpected char '{$cNext}' at position {$this->i}."); + } + } + break; + case 'x': + $pc = new LoggerBasicPatternConverter($this->formattingInfo, LOG4PHP_LOGGER_PATTERN_PARSER_NDC_CONVERTER); + LoggerLog::debug("LoggerPatternParser::finalizeConverter() NDC converter."); + $this->currentLiteral = ''; + break; + + case 'X': + $xOpt = $this->extractOption(); + $pc = new LoggerMDCPatternConverter($this->formattingInfo, $xOpt); + LoggerLog::debug("LoggerPatternParser::finalizeConverter() MDC converter."); + $this->currentLiteral = ''; + break; + default: + LoggerLog::warn("LoggerPatternParser::finalizeConverter() Unexpected char [$c] at position {$this->i} in conversion pattern."); + $pc = new LoggerLiteralPatternConverter($this->currentLiteral); + $this->currentLiteral = ''; + } + $this->addConverter($pc); + } + + function addConverter($pc) + { + $this->currentLiteral = ''; + // Add the pattern converter to the list. + $this->addToList($pc); + // Next pattern is assumed to be a literal. + $this->state = LOG4PHP_LOGGER_PATTERN_PARSER_LITERAL_STATE; + // Reset formatting info + $this->formattingInfo->reset(); + } +} + +?> \ No newline at end of file diff --git a/src/lib/log4php/helpers/LoggerTransform.php b/src/lib/log4php/helpers/LoggerTransform.php new file mode 100644 index 0000000..6aef42d --- /dev/null +++ b/src/lib/log4php/helpers/LoggerTransform.php @@ -0,0 +1,95 @@ +This framework is based on log4j (see {@link http://jakarta.apache.org/log4j log4j} for details).

    + *

    Design, strategies and part of the methods documentation are developed by log4j team + * (Ceki Gülcü as log4j project founder and + * {@link http://jakarta.apache.org/log4j/docs/contributors.html contributors}).

    + * + *

    PHP port, extensions and modifications by VxR. All rights reserved.
    + * For more information, please see {@link http://www.vxr.it/log4php/}.

    + * + *

    This software is published under the terms of the LGPL License + * a copy of which has been included with this distribution in the LICENSE file.

    + * + * @package log4php + * @subpackage helpers + */ + +/** + * @ignore + */ +if (!defined('LOG4PHP_DIR')) define('LOG4PHP_DIR', dirname(__FILE__) . '/..'); + +define('LOG4PHP_LOGGER_TRANSFORM_CDATA_START', ''); +define('LOG4PHP_LOGGER_TRANSFORM_CDATA_PSEUDO_END', ']]>'); +define('LOG4PHP_LOGGER_TRANSFORM_CDATA_EMBEDDED_END', + LOG4PHP_LOGGER_TRANSFORM_CDATA_END . + LOG4PHP_LOGGER_TRANSFORM_CDATA_PSEUDO_END . + LOG4PHP_LOGGER_TRANSFORM_CDATA_START +); + +/** + * Utility class for transforming strings. + * + * @log4j-class org.apache.log4j.helpers.Transform + * + * @author VxR + * @package log4php + * @subpackage helpers + * @since 0.7 + */ +class LoggerTransform { + + /** + * This method takes a string which may contain HTML tags (ie, + * <b>, <table>, etc) and replaces any '<' and '>' + * characters with respective predefined entity references. + * + * @param string $input The text to be converted. + * @return string The input string with the characters '<' and '>' replaced with + * &lt; and &gt; respectively. + * @static + */ + function escapeTags($input) + { + //Check if the string is null or zero length -- if so, return + //what was sent in. + + if(empty($input)) + return $input; + + //Use a StringBuffer in lieu of String concatenation -- it is + //much more efficient this way. + + return htmlspecialchars($input, ENT_NOQUOTES); + } + + /** + * Ensures that embeded CDEnd strings (]]>) are handled properly + * within message, NDC and throwable tag text. + * + * @param string $buf String holding the XML data to this point. The + * initial CDStart () + * of the CDATA section are the responsibility of + * the calling method. + * @param string &str The String that is inserted into an existing + * CDATA Section within buf. + * @static + */ + function appendEscapingCDATA(&$buf, $str) + { + if(empty($str)) + return; + + $rStr = str_replace( + LOG4PHP_LOGGER_TRANSFORM_CDATA_END, + LOG4PHP_LOGGER_TRANSFORM_CDATA_EMBEDDED_END, + $str + ); + $buf .= $rStr; + } +} +?> \ No newline at end of file diff --git a/src/lib/log4php/layouts/LoggerLayoutHtml.php b/src/lib/log4php/layouts/LoggerLayoutHtml.php new file mode 100644 index 0000000..1c3410b --- /dev/null +++ b/src/lib/log4php/layouts/LoggerLayoutHtml.php @@ -0,0 +1,256 @@ +This framework is based on log4j (see {@link http://jakarta.apache.org/log4j log4j} for details).

    + *

    Design, strategies and part of the methods documentation are developed by log4j team + * (Ceki Gülcü as log4j project founder and + * {@link http://jakarta.apache.org/log4j/docs/contributors.html contributors}).

    + * + *

    PHP port, extensions and modifications by VxR. All rights reserved.
    + * For more information, please see {@link http://www.vxr.it/log4php/}.

    + * + *

    This software is published under the terms of the LGPL License + * a copy of which has been included with this distribution in the LICENSE file.

    + * + * @package log4php + * @subpackage layouts + */ + +/** + * @ignore + */ +if (!defined('LOG4PHP_DIR')) define('LOG4PHP_DIR', dirname(__FILE__) . '/..'); + +if (!defined('LOG4PHP_LINE_SEP')) { + if (substr(php_uname(), 0, 7) == "Windows") { + /** + * @ignore + */ + define('LOG4PHP_LINE_SEP', "\r\n"); + } else { + /** + * @ignore + */ + define('LOG4PHP_LINE_SEP', "\n"); + } +} + +/** + */ +require_once(LOG4PHP_DIR . '/LoggerLayout.php'); +require_once(LOG4PHP_DIR . '/spi/LoggerLoggingEvent.php'); + +/** + * This layout outputs events in a HTML table. + * + * Parameters are: {@link $title}, {@link $locationInfo}. + * + * @author VxR + * @version $Revision: 1.14 $ + * @package log4php + * @subpackage layouts + */ +class LoggerLayoutHtml extends LoggerLayout { + + /** + * The LocationInfo option takes a boolean value. By + * default, it is set to false which means there will be no location + * information output by this layout. If the the option is set to + * true, then the file name and line number of the statement + * at the origin of the log statement will be output. + * + *

    If you are embedding this layout within a {@link LoggerAppenderMail} + * or a {@link LoggerAppenderMailEvent} then make sure to set the + * LocationInfo option of that appender as well. + * @var boolean + */ + var $locationInfo = false; + + /** + * The Title option takes a String value. This option sets the + * document title of the generated HTML document. + * Defaults to 'Log4php Log Messages'. + * @var string + */ + var $title = "Log4php Log Messages"; + + /** + * Constructor + */ + function LoggerLayoutHtml() + { + return; + } + + /** + * The LocationInfo option takes a boolean value. By + * default, it is set to false which means there will be no location + * information output by this layout. If the the option is set to + * true, then the file name and line number of the statement + * at the origin of the log statement will be output. + * + *

    If you are embedding this layout within a {@link LoggerAppenderMail} + * or a {@link LoggerAppenderMailEvent} then make sure to set the + * LocationInfo option of that appender as well. + */ + function setLocationInfo($flag) + { + if (is_bool($flag)) { + $this->locationInfo = $flag; + } else { + $this->locationInfo = (bool)(strtolower($flag) == 'true'); + } + } + + /** + * Returns the current value of the LocationInfo option. + */ + function getLocationInfo() + { + return $this->locationInfo; + } + + /** + * The Title option takes a String value. This option sets the + * document title of the generated HTML document. + * Defaults to 'Log4php Log Messages'. + */ + function setTitle($title) + { + $this->title = $title; + } + + /** + * @return string Returns the current value of the Title option. + */ + function getTitle() + { + return $this->title; + } + + /** + * @return string Returns the content type output by this layout, i.e "text/html". + */ + function getContentType() + { + return "text/html"; + } + + /** + * No options to activate. + */ + function activateOptions() + { + return true; + } + + /** + * @param LoggerLoggingEvent $event + * @return string + */ + function format($event) + { + $sbuf = LOG4PHP_LINE_SEP . "" . LOG4PHP_LINE_SEP; + + $sbuf .= ""; + + $eventTime = (float)$event->getTimeStamp(); + $eventStartTime = (float)LoggerLoggingEvent::getStartTime(); + $sbuf .= number_format(($eventTime - $eventStartTime) * 1000, 0, '', ''); + $sbuf .= "" . LOG4PHP_LINE_SEP; + + $sbuf .= "getThreadName() . " thread\">"; + $sbuf .= $event->getThreadName(); + $sbuf .= "" . LOG4PHP_LINE_SEP; + + $sbuf .= ""; + + $level = $event->getLevel(); + + if ($level->equals(LoggerLevel::getLevelDebug())) { + $sbuf .= ""; + $sbuf .= $level->toString(); + $sbuf .= ""; + }elseif($level->equals(LoggerLevel::getLevelWarn())) { + $sbuf .= ""; + $sbuf .= $level->toString(); + $sbuf .= ""; + } else { + $sbuf .= $level->toString(); + } + $sbuf .= "" . LOG4PHP_LINE_SEP; + + $sbuf .= "getLoggerName(), ENT_QUOTES) . " category\">"; + $sbuf .= htmlentities($event->getLoggerName(), ENT_QUOTES); + $sbuf .= "" . LOG4PHP_LINE_SEP; + + if ($this->locationInfo) { + $locInfo = $event->getLocationInformation(); + $sbuf .= ""; + $sbuf .= htmlentities($locInfo->getFileName(), ENT_QUOTES). ':' . $locInfo->getLineNumber(); + $sbuf .= "" . LOG4PHP_LINE_SEP; + } + + $sbuf .= ""; + $sbuf .= htmlentities($event->getRenderedMessage(), ENT_QUOTES); + $sbuf .= "" . LOG4PHP_LINE_SEP; + + $sbuf .= "" . LOG4PHP_LINE_SEP; + + if ($event->getNDC() != null) { + $sbuf .= ""; + $sbuf .= "NDC: " . htmlentities($event->getNDC(), ENT_QUOTES); + $sbuf .= "" . LOG4PHP_LINE_SEP; + } + + return $sbuf; + } + + /** + * @return string Returns appropriate HTML headers. + */ + function getHeader() + { + $sbuf = "" . LOG4PHP_LINE_SEP; + $sbuf .= "" . LOG4PHP_LINE_SEP; + $sbuf .= "" . LOG4PHP_LINE_SEP; + $sbuf .= "" . $this->title . "" . LOG4PHP_LINE_SEP; + $sbuf .= "" . LOG4PHP_LINE_SEP; + $sbuf .= "" . LOG4PHP_LINE_SEP; + $sbuf .= "" . LOG4PHP_LINE_SEP; + $sbuf .= "


    " . LOG4PHP_LINE_SEP; + $sbuf .= "Log session start time " . strftime('%c', time()) . "
    " . LOG4PHP_LINE_SEP; + $sbuf .= "
    " . LOG4PHP_LINE_SEP; + $sbuf .= "" . LOG4PHP_LINE_SEP; + $sbuf .= "" . LOG4PHP_LINE_SEP; + $sbuf .= "" . LOG4PHP_LINE_SEP; + $sbuf .= "" . LOG4PHP_LINE_SEP; + $sbuf .= "" . LOG4PHP_LINE_SEP; + $sbuf .= "" . LOG4PHP_LINE_SEP; + if ($this->locationInfo) + $sbuf .= "" . LOG4PHP_LINE_SEP; + $sbuf .= "" . LOG4PHP_LINE_SEP; + $sbuf .= "" . LOG4PHP_LINE_SEP; + + return $sbuf; + } + + /** + * @return string Returns the appropriate HTML footers. + */ + function getFooter() + { + $sbuf = "
    TimeThreadLevelCategoryFile:LineMessage
    " . LOG4PHP_LINE_SEP; + $sbuf .= "
    " . LOG4PHP_LINE_SEP; + $sbuf .= ""; + + return $sbuf; + } +} +?> \ No newline at end of file diff --git a/src/lib/log4php/layouts/LoggerLayoutSimple.php b/src/lib/log4php/layouts/LoggerLayoutSimple.php new file mode 100644 index 0000000..3a479a3 --- /dev/null +++ b/src/lib/log4php/layouts/LoggerLayoutSimple.php @@ -0,0 +1,84 @@ +This framework is based on log4j (see {@link http://jakarta.apache.org/log4j log4j} for details).

    + *

    Design, strategies and part of the methods documentation are developed by log4j team + * (Ceki Gülcü as log4j project founder and + * {@link http://jakarta.apache.org/log4j/docs/contributors.html contributors}).

    + * + *

    PHP port, extensions and modifications by VxR. All rights reserved.
    + * For more information, please see {@link http://www.vxr.it/log4php/}.

    + * + *

    This software is published under the terms of the LGPL License + * a copy of which has been included with this distribution in the LICENSE file.

    + * + * @package log4php + * @subpackage layouts + */ + +/** + * @ignore + */ +if (!defined('LOG4PHP_DIR')) define('LOG4PHP_DIR', dirname(__FILE__) . '/..'); + +if (!defined('LOG4PHP_LINE_SEP')) { + if (substr(php_uname(), 0, 7) == "Windows") { + define('LOG4PHP_LINE_SEP', "\r\n"); + } else { + /** + * @ignore + */ + define('LOG4PHP_LINE_SEP', "\n"); + } +} + + +/** + */ +require_once(LOG4PHP_DIR . '/LoggerLayout.php'); + +/** + * A simple layout. + * + * Returns the log statement in a format consisting of the + * level, followed by " - " and then the message. + * For example, + * INFO - "A message" + * + * @author VxR + * @version $Revision: 1.8 $ + * @package log4php + * @subpackage layouts + */ +class LoggerLayoutSimple extends LoggerLayout { + + /** + * Constructor + */ + function LoggerLayoutSimple() + { + return; + } + + function activateOptions() + { + return; + } + + /** + * Returns the log statement in a format consisting of the + * level, followed by " - " and then the + * message. For example, + * INFO - "A message" + * + * @param LoggerLoggingEvent $event + * @return string + */ + function format($event) + { + $level = $event->getLevel(); + return $level->toString() . ' - ' . $event->getRenderedMessage(). LOG4PHP_LINE_SEP; + } +} +?> \ No newline at end of file diff --git a/src/lib/log4php/layouts/LoggerLayoutTTCC.php b/src/lib/log4php/layouts/LoggerLayoutTTCC.php new file mode 100644 index 0000000..e90524f --- /dev/null +++ b/src/lib/log4php/layouts/LoggerLayoutTTCC.php @@ -0,0 +1,240 @@ +This framework is based on log4j (see {@link http://jakarta.apache.org/log4j log4j} for details).

    + *

    Design, strategies and part of the methods documentation are developed by log4j team + * (Ceki Gülcü as log4j project founder and + * {@link http://jakarta.apache.org/log4j/docs/contributors.html contributors}).

    + * + *

    PHP port, extensions and modifications by VxR. All rights reserved.
    + * For more information, please see {@link http://www.vxr.it/log4php/}.

    + * + *

    This software is published under the terms of the LGPL License + * a copy of which has been included with this distribution in the LICENSE file.

    + * + * @package log4php + * @subpackage layouts + */ + +/** + * @ignore + */ +if (!defined('LOG4PHP_DIR')) define('LOG4PHP_DIR', dirname(__FILE__) . '/..'); + +if (!defined('LOG4PHP_LINE_SEP')) { + if (substr(php_uname(), 0, 7) == "Windows") { + /** + * @ignore + */ + define('LOG4PHP_LINE_SEP', "\r\n"); + } else { + /** + * @ignore + */ + define('LOG4PHP_LINE_SEP', "\n"); + } +} + +/** + */ +require_once(LOG4PHP_DIR . '/LoggerLayout.php'); + +/** + * String constant designating no time information. Current value of + * this constant is NULL. + */ +define ('LOG4PHP_LOGGER_LAYOUT_NULL_DATE_FORMAT', 'NULL'); + +/** + * String constant designating relative time. Current value of + * this constant is RELATIVE. + */ +define ('LOG4PHP_LOGGER_LAYOUT_RELATIVE_TIME_DATE_FORMAT', 'RELATIVE'); + +/** + * TTCC layout format consists of time, thread, category and nested + * diagnostic context information, hence the name. + * + *

    Each of the four fields can be individually enabled or + * disabled. The time format depends on the DateFormat used.

    + * + *

    If no dateFormat is specified it defaults to '%c'. + * See php {@link PHP_MANUAL#date} function for details.

    + * + * Params: + * - {@link $threadPrinting} (true|false) enable/disable pid reporting. + * - {@link $categoryPrefixing} (true|false) enable/disable logger category reporting. + * - {@link $contextPrinting} (true|false) enable/disable NDC reporting. + * - {@link $microSecondsPrinting} (true|false) enable/disable micro seconds reporting in timestamp. + * - {@link $dateFormat} (string) set date format. See php {@link PHP_MANUAL#date} function for details. + * + * @author VxR + * @version $Revision: 1.12 $ + * @package log4php + * @subpackage layouts + */ +class LoggerLayoutTTCC extends LoggerLayout { + + // Internal representation of options + var $threadPrinting = true; + var $categoryPrefixing = true; + var $contextPrinting = true; + var $microSecondsPrinting = true; + + /** + * @var string date format. See {@link PHP_MANUAL#strftime} for details + */ + var $dateFormat = '%c'; + + /** + * Constructor + * + * @param string date format + * @see dateFormat + */ + function LoggerLayoutTTCC($dateFormat = '') + { + if (!empty($dateFormat)) + $this->dateFormat = $dateFormat; + return; + } + + /** + * The ThreadPrinting option specifies whether the name of the + * current thread is part of log output or not. This is true by default. + */ + function setThreadPrinting($threadPrinting) + { + + $this->threadPrinting = is_bool($threadPrinting) ? + $threadPrinting : + (bool)(strtolower($threadPrinting) == 'true'); + } + + /** + * @return boolean Returns value of the ThreadPrinting option. + */ + function getThreadPrinting() { + return $this->threadPrinting; + } + + /** + * The CategoryPrefixing option specifies whether {@link Category} + * name is part of log output or not. This is true by default. + */ + function setCategoryPrefixing($categoryPrefixing) + { + $this->categoryPrefixing = is_bool($categoryPrefixing) ? + $categoryPrefixing : + (bool)(strtolower($categoryPrefixing) == 'true'); + } + + /** + * @return boolean Returns value of the CategoryPrefixing option. + */ + function getCategoryPrefixing() { + return $this->categoryPrefixing; + } + + /** + * The ContextPrinting option specifies log output will include + * the nested context information belonging to the current thread. + * This is true by default. + */ + function setContextPrinting($contextPrinting) { + $this->contextPrinting = is_bool($contextPrinting) ? + $contextPrinting : + (bool)(strtolower($contextPrinting) == 'true'); + } + + /** + * @return boolean Returns value of the ContextPrinting option. + */ + function getContextPrinting() + { + return $this->contextPrinting; + } + + /** + * The MicroSecondsPrinting option specifies if microseconds infos + * should be printed at the end of timestamp. + * This is true by default. + */ + function setMicroSecondsPrinting($microSecondsPrinting) { + $this->microSecondsPrinting = is_bool($microSecondsPrinting) ? + $microSecondsPrinting : + (bool)(strtolower($microSecondsPrinting) == 'true'); + } + + /** + * @return boolean Returns value of the MicroSecondsPrinting option. + */ + function getMicroSecondsPrinting() + { + return $this->microSecondsPrinting; + } + + + function setDateFormat($dateFormat) + { + $this->dateFormat = $dateFormat; + } + + /** + * @return string + */ + function getDateFormat() + { + return $this->dateFormat; + } + + /** + * In addition to the level of the statement and message, the + * returned string includes time, thread, category. + *

    Time, thread, category are printed depending on options. + * + * @param LoggerLoggingEvent $event + * @return string + */ + function format($event) + { + $timeStamp = (float)$event->getTimeStamp(); + $format = strftime($this->dateFormat, (int)$timeStamp); + + if ($this->microSecondsPrinting) { + $usecs = round(($timeStamp - (int)$timeStamp) * 1000); + $format .= sprintf(',%03d', $usecs); + } + + $format .= ' '; + + if ($this->threadPrinting) + $format .= '['.getmypid().'] '; + + $level = $event->getLevel(); + $format .= $level->toString().' '; + + if($this->categoryPrefixing) { + $format .= $event->getLoggerName().' '; + } + + if($this->contextPrinting) { + $ndc = $event->getNDC(); + if($ndc != null) { + $format .= $ndc.' '; + } + } + + $format .= '- '.$event->getRenderedMessage(); + $format .= LOG4PHP_LINE_SEP; + + return $format; + } + + function ignoresThrowable() + { + return true; + } +} +?> \ No newline at end of file diff --git a/src/lib/log4php/layouts/LoggerPatternLayout.php b/src/lib/log4php/layouts/LoggerPatternLayout.php new file mode 100644 index 0000000..6c21ef2 --- /dev/null +++ b/src/lib/log4php/layouts/LoggerPatternLayout.php @@ -0,0 +1,260 @@ +This framework is based on log4j (see {@link http://jakarta.apache.org/log4j log4j} for details).

    + *

    Design, strategies and part of the methods documentation are developed by log4j team + * (Ceki Gülcü as log4j project founder and + * {@link http://jakarta.apache.org/log4j/docs/contributors.html contributors}).

    + * + *

    PHP port, extensions and modifications by VxR. All rights reserved.
    + * For more information, please see {@link http://www.vxr.it/log4php/}.

    + * + *

    This software is published under the terms of the LGPL License + * a copy of which has been included with this distribution in the LICENSE file.

    + * + * @package log4php + * @subpackage layouts + */ + +/** + * @ignore + */ +if (!defined('LOG4PHP_DIR')) define('LOG4PHP_DIR', dirname(__FILE__) . '/..'); + +/** + */ +require_once(LOG4PHP_DIR . '/helpers/LoggerPatternParser.php'); +require_once(LOG4PHP_DIR . '/LoggerLayout.php'); +require_once(LOG4PHP_DIR . '/LoggerLog.php'); + +/** + * Default conversion Pattern + */ +define('LOG4PHP_LOGGER_PATTERN_LAYOUT_DEFAULT_CONVERSION_PATTERN', '%m%n'); + +define('LOG4PHP_LOGGER_PATTERN_LAYOUT_TTCC_CONVERSION_PATTERN', '%r [%t] %p %c %x - %m%n'); + +/** + * A flexible layout configurable with pattern string. + * + *

    The goal of this class is to {@link format()} a {@link LoggerLoggingEvent} and return the results as a string. + * The results depend on the conversion pattern. + * The conversion pattern is closely related to the conversion pattern of the printf function in C. + * A conversion pattern is composed of literal text and format control expressions called conversion specifiers. + * You are free to insert any literal text within the conversion pattern.

    + * + *

    Each conversion specifier starts with a percent sign (%) and is followed by optional + * format modifiers and a conversion character.

    + * + *

    The conversion character specifies the type of data, e.g. category, priority, date, thread name. + * The format modifiers control such things as field width, padding, left and right justification.

    + * + * The following is a simple example. + * + *

    Let the conversion pattern be "%-5p [%t]: %m%n" and assume that the log4php environment + * was set to use a LoggerPatternLayout.

    + * + * Then the statements + * + * $root =& LoggerManager::getRoot(); + * $root->debug("Message 1"); + * $root->warn("Message 2"); + * + * would yield the output + *
    + *  DEBUG [main]: Message 1
    + *  WARN  [main]: Message 2
    + * 
    + * + *

    Note that there is no explicit separator between text and conversion specifiers.

    + * + *

    The pattern parser knows when it has reached the end of a conversion specifier when it reads a conversion character. + * In the example above the conversion specifier %-5p means the priority of the logging event should be + * left justified to a width of five characters.

    + * + * Not all log4j conversion characters are implemented. The recognized conversion characters are: + * - c Used to output the category of the logging event. The category conversion specifier can be optionally followed by precision specifier, that is a decimal constant in brackets. + * If a precision specifier is given, then only the corresponding number of right most components of the category name will be printed. + * By default the category name is printed in full. + * For example, for the category name "a.b.c" the pattern %c{2} will output "b.c". + * - C Used to output the fully qualified class name of the caller issuing the logging request. + * This conversion specifier can be optionally followed by precision specifier, that is a decimal constant in brackets. + * If a precision specifier is given, then only the corresponding number of right most components of the class name will be printed. + * By default the class name is output in fully qualified form. + * For example, for the class name "org.apache.xyz.SomeClass", the pattern %C{1} will output "SomeClass". + * - d Used to output the date of the logging event. + * The date conversion specifier may be followed by a date format specifier enclosed between braces. + * The format specifier follows the {@link PHP_MANUAL#date} function. + * Note that the special character u is used to as microseconds replacement (to avoid replacement, + * use \u). + * For example, %d{H:i:s,u} or %d{d M Y H:i:s,u}. If no date format specifier is given then ISO8601 format is assumed. + * The date format specifier admits the same syntax as the time pattern string of the SimpleDateFormat. + * It is recommended to use the predefined log4php date formatters. + * These can be specified using one of the strings "ABSOLUTE", "DATE" and "ISO8601" for specifying + * AbsoluteTimeDateFormat, DateTimeDateFormat and respectively ISO8601DateFormat. + * For example, %d{ISO8601} or %d{ABSOLUTE}. + * - F Used to output the file name where the logging request was issued. + * - l Used to output location information of the caller which generated the logging event. + * - L Used to output the line number from where the logging request was issued. + * - m Used to output the application supplied message associated with the logging event. + * - M Used to output the method name where the logging request was issued. + * - p Used to output the priority of the logging event. + * - r Used to output the number of milliseconds elapsed since the start of + * the application until the creation of the logging event. + * - t Used to output the name of the thread that generated the logging event. + * - x Used to output the NDC (nested diagnostic context) associated with + * the thread that generated the logging event. + * - X Used to output the MDC (mapped diagnostic context) associated with + * the thread that generated the logging event. + * The X conversion character must be followed by the key for the map placed between braces, + * as in %X{clientNumber} where clientNumber is the key. + * The value in the MDC corresponding to the key will be output. + * See {@link LoggerMDC} class for more details. + * - % The sequence %% outputs a single percent sign. + * + *

    By default the relevant information is output as is. + * However, with the aid of format modifiers it is possible to change the minimum field width, + * the maximum field width and justification.

    + * + *

    The optional format modifier is placed between the percent sign and the conversion character.

    + *

    The first optional format modifier is the left justification flag which is just the minus (-) character. + * Then comes the optional minimum field width modifier. + * This is a decimal constant that represents the minimum number of characters to output. + * If the data item requires fewer characters, it is padded on either the left or the right until the minimum width is reached. The default is to pad on the left (right justify) but you can specify right padding with the left justification flag. The padding character is space. If the data item is larger than the minimum field width, the field is expanded to accommodate the data. + * The value is never truncated.

    + * + *

    This behavior can be changed using the maximum field width modifier which is designated by a period + * followed by a decimal constant. + * If the data item is longer than the maximum field, + * then the extra characters are removed from the beginning of the data item and not from the end. + * For example, it the maximum field width is eight and the data item is ten characters long, + * then the first two characters of the data item are dropped. + * This behavior deviates from the printf function in C where truncation is done from the end.

    + * + *

    Below are various format modifier examples for the category conversion specifier.

    + *
    + *   Format modifier  left justify  minimum width  maximum width  comment
    + *   %20c             false         20             none           Left pad with spaces if the category name 
    + *                                                                is less than 20 characters long.
    + *   %-20c            true          20             none           Right pad with spaces if the category name 
    + *                                                                is less than 20 characters long.  
    + *   %.30c            NA            none           30             Truncate from the beginning if the category name 
    + *                                                                is longer than 30 characters.  
    + *   %20.30c          false         20             30             Left pad with spaces if the category name 
    + *                                                                is shorter than 20 characters. 
    + *                                                                However, if category name is longer than 30 chars, 
    + *                                                                then truncate from the beginning.  
    + *   %-20.30c         true          20             30             Right pad with spaces if the category name is 
    + *                                                                shorter than 20 chars. 
    + *                                                                However, if category name is longer than 30 chars, 
    + *                                                                then truncate from the beginning.  
    + * 
    + * + * @author VxR + * @version $Revision: 1.7 $ + * @package log4php + * @subpackage layouts + * @since 0.3 + */ +class LoggerPatternLayout extends LoggerLayout { + + /** + * @var string output buffer appended to when format() is invoked + */ + var $sbuf; + + /** + * @var string + */ + var $pattern; + + /** + * @var LoggerPatternConverter head chain + */ + var $head; + + var $timezone; + + /** + * Constructs a PatternLayout using the + * {@link LOG4PHP_LOGGER_PATTERN_LAYOUT_DEFAULT_LAYOUT_PATTERN}. + * The default pattern just produces the application supplied message. + */ + function LoggerPatternLayout($pattern = null) + { + if ($pattern === null) { + $this->LoggerPatternLayout(LOG4PHP_LOGGER_PATTERN_LAYOUT_DEFAULT_CONVERSION_PATTERN); + } else { + $this->pattern = $pattern; + } + } + + /** + * Set the ConversionPattern option. This is the string which + * controls formatting and consists of a mix of literal content and + * conversion specifiers. + */ + function setConversionPattern($conversionPattern) + { + $this->pattern = $conversionPattern; + $patternParser = $this->createPatternParser($this->pattern); + $this->head = $patternParser->parse(); + } + + /** + * @return string Returns the value of the ConversionPattern option. + */ + function getConversionPattern() + { + return $this->pattern; + } + + /** + * Does not do anything as options become effective + */ + function activateOptions() + { + // nothing to do. + } + + function ignoresThrowable() + { + return true; + } + + /** + * Returns LoggerPatternParser used to parse the conversion string. Subclasses + * may override this to return a subclass of PatternParser which recognize + * custom conversion characters. + * + * @param string $pattern + * @return LoggerPatternParser + */ + function createPatternParser($pattern) + { + return new LoggerPatternParser($pattern); + } + + /** + * Produces a formatted string as specified by the conversion pattern. + * + * @param LoggerLoggingEvent $event + * @return string + */ + function format($event) + { + LoggerLog::debug("LoggerPatternLayout::format()"); + + // Reset working stringbuffer + $this->sbuf = ''; + $c = $this->head; + while($c !== null) { + $c->format($this->sbuf, $event); + $c = $c->next; + } + return $this->sbuf; + } + +} +?> \ No newline at end of file diff --git a/src/lib/log4php/layouts/LoggerXmlLayout.php b/src/lib/log4php/layouts/LoggerXmlLayout.php new file mode 100644 index 0000000..d8c61dd --- /dev/null +++ b/src/lib/log4php/layouts/LoggerXmlLayout.php @@ -0,0 +1,206 @@ +This framework is based on log4j (see {@link http://jakarta.apache.org/log4j log4j} for details).

    + *

    Design, strategies and part of the methods documentation are developed by log4j team + * (Ceki Gülcü as log4j project founder and + * {@link http://jakarta.apache.org/log4j/docs/contributors.html contributors}).

    + * + *

    PHP port, extensions and modifications by VxR. All rights reserved.
    + * For more information, please see {@link http://www.vxr.it/log4php/}.

    + * + *

    This software is published under the terms of the LGPL License + * a copy of which has been included with this distribution in the LICENSE file.

    + * + * @package log4php + * @subpackage layouts + */ + +/** + * @ignore + */ +if (!defined('LOG4PHP_DIR')) define('LOG4PHP_DIR', dirname(__FILE__) . '/..'); + +define('LOG4PHP_LOGGER_XML_LAYOUT_LOG4J_NS_PREFIX', 'log4j'); +define('LOG4PHP_LOGGER_XML_LAYOUT_LOG4J_NS', 'http://jakarta.apache.org/log4j/'); + +define('LOG4PHP_LOGGER_XML_LAYOUT_LOG4PHP_NS_PREFIX', 'log4php'); +define('LOG4PHP_LOGGER_XML_LAYOUT_LOG4PHP_NS', 'http://www.vxr.it/log4php/'); + +/** + */ +require_once(LOG4PHP_DIR . '/helpers/LoggerOptionConverter.php'); +require_once(LOG4PHP_DIR . '/helpers/LoggerTransform.php'); +require_once(LOG4PHP_DIR . '/LoggerLayout.php'); + +/** + * The output of the LoggerXmlLayout consists of a series of log4php:event elements. + * + *

    Parameters: {@link $locationInfo}.

    + * + *

    It does not output a complete well-formed XML file. + * The output is designed to be included as an external entity in a separate file to form + * a correct XML file.

    + * + * @author VxR + * @version $Revision: 1.16 $ + * @package log4php + * @subpackage layouts + */ +class LoggerXmlLayout extends LoggerLayout { + + /** + * The LocationInfo option takes a boolean value. By default, + * it is set to false which means there will be no location + * information output by this layout. If the the option is set to + * true, then the file name and line number of the statement at the + * origin of the log statement will be output. + * @var boolean + */ + var $locationInfo = true; + + /** + * @var boolean set the elements namespace + */ + var $log4jNamespace = false; + + + /** + * @var string namespace + * @private + */ + var $_namespace = LOG4PHP_LOGGER_XML_LAYOUT_LOG4PHP_NS; + + /** + * @var string namespace prefix + * @private + */ + var $_namespacePrefix = LOG4PHP_LOGGER_XML_LAYOUT_LOG4PHP_NS_PREFIX; + + /** + * No options to activate. + */ + function activateOptions() + { + if ($this->getLog4jNamespace()) { + $this->_namespace = LOG4PHP_LOGGER_XML_LAYOUT_LOG4J_NS; + $this->_namespacePrefix = LOG4PHP_LOGGER_XML_LAYOUT_LOG4J_NS_PREFIX; + } else { + $this->_namespace = LOG4PHP_LOGGER_XML_LAYOUT_LOG4PHP_NS; + $this->_namespacePrefix = LOG4PHP_LOGGER_XML_LAYOUT_LOG4PHP_NS_PREFIX; + } + } + + /** + * @return string + */ + function getHeader() + { + return "<{$this->_namespacePrefix}:eventSet ". + "xmlns:{$this->_namespacePrefix}=\"{$this->_namespace}\" ". + "version=\"0.3\" ". + "includesLocationInfo=\"".($this->getLocationInfo() ? "true" : "false")."\"". + ">\r\n"; + } + + /** + * Formats a {@link LoggerLoggingEvent} in conformance with the log4php.dtd. + * + * @param LoggerLoggingEvent $event + * @return string + */ + function format($event) + { + $loggerName = $event->getLoggerName(); + $timeStamp = number_format((float)($event->getTimeStamp() * 1000), 0, '', ''); + $thread = $event->getThreadName(); + $level = $event->getLevel(); + $levelStr = $level->toString(); + + $buf = "<{$this->_namespacePrefix}:event logger=\"{$loggerName}\" level=\"{$levelStr}\" thread=\"{$thread}\" timestamp=\"{$timeStamp}\">\r\n"; + $buf .= "<{$this->_namespacePrefix}:message>getRenderedMessage()); + $buf .= "]]>_namespacePrefix}:message>\r\n"; + + $ndc = $event->getNDC(); + if($ndc != null) { + $buf .= "<{$this->_namespacePrefix}:NDC>_namespacePrefix}:NDC>\r\n"; + } + + if ($this->getLocationInfo()) { + $locationInfo = $event->getLocationInformation(); + $buf .= "<{$this->_namespacePrefix}:locationInfo ". + "class=\"" . $locationInfo->getClassName() . "\" ". + "file=\"" . htmlentities($locationInfo->getFileName(), ENT_QUOTES) . "\" ". + "line=\"" . $locationInfo->getLineNumber() . "\" ". + "method=\"" . $locationInfo->getMethodName() . "\" "; + $buf .= "/>\r\n"; + + } + + $buf .= "_namespacePrefix}:event>\r\n\r\n"; + + return $buf; + + } + + /** + * @return string + */ + function getFooter() + { + + return "_namespacePrefix}:eventSet>\r\n"; + } + + /** + * @return boolean + */ + function getLocationInfo() + { + return $this->locationInfo; + } + + /** + * @return boolean + */ + function getLog4jNamespace() + { + return $this->log4jNamespace; + } + + /** + * The XMLLayout prints and does not ignore exceptions. Hence the + * return value false. + * @return boolean + */ + function ignoresThrowable() + { + return false; + } + + /** + * The {@link $locationInfo} option takes a boolean value. By default, + * it is set to false which means there will be no location + * information output by this layout. If the the option is set to + * true, then the file name and line number of the statement at the + * origin of the log statement will be output. + */ + function setLocationInfo($flag) + { + $this->locationInfo = LoggerOptionConverter::toBoolean($flag, true); + } + + /** + * @param boolean + */ + function setLog4jNamespace($flag) + { + $this->log4jNamespace = LoggerOptionConverter::toBoolean($flag, true); + } +} + +?> \ No newline at end of file diff --git a/src/lib/log4php/or/LoggerDefaultRenderer.php b/src/lib/log4php/or/LoggerDefaultRenderer.php new file mode 100644 index 0000000..c2e44c3 --- /dev/null +++ b/src/lib/log4php/or/LoggerDefaultRenderer.php @@ -0,0 +1,58 @@ +This framework is based on log4j (see {@link http://jakarta.apache.org/log4j log4j} for details).

    + *

    Design, strategies and part of the methods documentation are developed by log4j team + * (Ceki Gülcü as log4j project founder and + * {@link http://jakarta.apache.org/log4j/docs/contributors.html contributors}).

    + * + *

    PHP port, extensions and modifications by VxR. All rights reserved.
    + * For more information, please see {@link http://www.vxr.it/log4php/}.

    + * + *

    This software is published under the terms of the LGPL License + * a copy of which has been included with this distribution in the LICENSE file.

    + * + * @package log4php + * @subpackage or + */ + +/** + * @ignore + */ +if (!defined('LOG4PHP_DIR')) define('LOG4PHP_DIR', dirname(__FILE__) . '/..'); + +/** + */ +require_once(LOG4PHP_DIR . '/or/LoggerObjectRenderer.php'); + +/** + * The default Renderer renders objects by type casting + * + * @author VxR + * @package log4php + * @subpackage or + * @since 0.3 + */ +class LoggerDefaultRenderer extends LoggerObjectRenderer{ + + /** + * Constructor + */ + function LoggerDefaultRenderer() + { + return; + } + + /** + * Render objects by type casting + * + * @param mixed $o the object to render + * @return string + */ + function doRender($o) + { + return var_export($o, true); + } +} +?> \ No newline at end of file diff --git a/src/lib/log4php/or/LoggerObjectRenderer.php b/src/lib/log4php/or/LoggerObjectRenderer.php new file mode 100644 index 0000000..5279690 --- /dev/null +++ b/src/lib/log4php/or/LoggerObjectRenderer.php @@ -0,0 +1,63 @@ +This framework is based on log4j (see {@link http://jakarta.apache.org/log4j log4j} for details).

    + *

    Design, strategies and part of the methods documentation are developed by log4j team + * (Ceki Gülcü as log4j project founder and + * {@link http://jakarta.apache.org/log4j/docs/contributors.html contributors}).

    + * + *

    PHP port, extensions and modifications by VxR. All rights reserved.
    + * For more information, please see {@link http://www.vxr.it/log4php/}.

    + * + *

    This software is published under the terms of the LGPL License + * a copy of which has been included with this distribution in the LICENSE file.

    + * + * @package log4php + * @subpackage or + */ + +/** + * @ignore + */ +if (!defined('LOG4PHP_DIR')) define('LOG4PHP_DIR', dirname(__FILE__) . '/..'); + +/** + * Subclass this abstract class in order to render objects as strings. + * + * @author VxR + * @version $Revision: 1.3 $ + * @package log4php + * @subpackage or + * @abstract + * @since 0.3 + */ +class LoggerObjectRenderer { + + /** + * @param string $class classname + * @return LoggerObjectRenderer create LoggerObjectRenderer instances + */ + function factory($class) + { + if (!empty($class)) { + $class = basename($class); + @include_once(LOG4PHP_DIR . "/or/{$class}.php"); + if (class_exists($class)) { + return new $class(); + } + } + return null; + } + + /** + * Render the entity passed as parameter as a String. + * @param mixed $o entity to render + * @return string + */ + function doRender($o) + { + // abstract + } +} +?> \ No newline at end of file diff --git a/src/lib/log4php/or/LoggerRendererMap.php b/src/lib/log4php/or/LoggerRendererMap.php new file mode 100644 index 0000000..1d9d29e --- /dev/null +++ b/src/lib/log4php/or/LoggerRendererMap.php @@ -0,0 +1,184 @@ +This framework is based on log4j (see {@link http://jakarta.apache.org/log4j log4j} for details).

    + *

    Design, strategies and part of the methods documentation are developed by log4j team + * (Ceki Gülcü as log4j project founder and + * {@link http://jakarta.apache.org/log4j/docs/contributors.html contributors}).

    + * + *

    PHP port, extensions and modifications by VxR. All rights reserved.
    + * For more information, please see {@link http://www.vxr.it/log4php/}.

    + * + *

    This software is published under the terms of the LGPL License + * a copy of which has been included with this distribution in the LICENSE file.

    + * + * @package log4php + * @subpackage or + */ + +/** + * @ignore + */ +if (!defined('LOG4PHP_DIR')) define('LOG4PHP_DIR', dirname(__FILE__) . '/..'); + +/** + */ +require_once(LOG4PHP_DIR . '/or/LoggerDefaultRenderer.php'); +require_once(LOG4PHP_DIR . '/or/LoggerObjectRenderer.php'); +require_once(LOG4PHP_DIR . '/LoggerLog.php'); + +/** + * Map class objects to an {@link LoggerObjectRenderer}. + * + * @author VxR + * @version $Revision: 1.4 $ + * @package log4php + * @subpackage or + * @since 0.3 + */ +class LoggerRendererMap { + + /** + * @var array + */ + var $map; + + /** + * @var LoggerDefaultRenderer + */ + var $defaultRenderer; + + /** + * Constructor + */ + function LoggerRendererMap() + { + $this->map = array(); + $this->defaultRenderer = new LoggerDefaultRenderer(); + } + + /** + * Add a renderer to a hierarchy passed as parameter. + * Note that hierarchy must implement getRendererMap() and setRenderer() methods. + * + * @param LoggerHierarchy &$repository a logger repository. + * @param string &$renderedClassName + * @param string &$renderingClassName + * @static + */ + function addRenderer(&$repository, $renderedClassName, $renderingClassName) + { + LoggerLog::debug("LoggerRendererMap::addRenderer() Rendering class: [{$renderingClassName}], Rendered class: [{$renderedClassName}]."); + $renderer = LoggerObjectRenderer::factory($renderingClassName); + if($renderer == null) { + LoggerLog::warn("LoggerRendererMap::addRenderer() Could not instantiate renderer [{$renderingClassName}]."); + return; + } else { + $repository->setRenderer($renderedClassName, $renderer); + } + } + + + /** + * Find the appropriate renderer for the class type of the + * o parameter. + * + * This is accomplished by calling the {@link getByObject()} + * method if o is object or using {@link LoggerDefaultRenderer}. + * Once a renderer is found, it is applied on the object o and + * the result is returned as a string. + * + * @param mixed $o + * @return string + */ + function findAndRender($o) + { + if($o == null) { + return null; + } else { + if (is_object($o)) { + $renderer = $this->getByObject($o); + if ($renderer !== null) { + return $renderer->doRender($o); + } else { + return null; + } + } else { + $renderer = $this->defaultRenderer; + return $renderer->doRender($o); + } + } + } + + /** + * Syntactic sugar method that calls {@link PHP_MANUAL#get_class} with the + * class of the object parameter. + * + * @param mixed $o + * @return string + */ + function &getByObject($o) + { + return ($o == null) ? null : $this->getByClassName(get_class($o)); + } + + + /** + * Search the parents of clazz for a renderer. + * + * The renderer closest in the hierarchy will be returned. If no + * renderers could be found, then the default renderer is returned. + * + * @param string $class + * @return LoggerObjectRenderer + */ + function &getByClassName($class) + { + $r = null; + for($c = strtolower($class); !empty($c); $c = get_parent_class($c)) { + if (isset($this->map[$c])) { + return $this->map[$c]; + } + } + return $this->defaultRenderer; + } + + /** + * @return LoggerDefaultRenderer + */ + function &getDefaultRenderer() + { + return $this->defaultRenderer; + } + + + function clear() + { + $this->map = array(); + } + + /** + * Register a {@link LoggerObjectRenderer} for clazz. + * @param string $class + * @param LoggerObjectRenderer $or + */ + function put($class, $or) + { + $this->map[strtolower($class)] = $or; + } + + /** + * @param string $class + * @return boolean + */ + function rendererExists($class) + { + $class = basename($class); + if (!class_exists($class)) { + @include_once(LOG4PHP_DIR ."/or/{$class}.php"); + } + return class_exists($class); + } +} +?> \ No newline at end of file diff --git a/src/lib/log4php/spi/LoggerConfigurator.php b/src/lib/log4php/spi/LoggerConfigurator.php new file mode 100644 index 0000000..944f188 --- /dev/null +++ b/src/lib/log4php/spi/LoggerConfigurator.php @@ -0,0 +1,65 @@ +This framework is based on log4j (see {@link http://jakarta.apache.org/log4j log4j} for details).

    + *

    Design, strategies and part of the methods documentation are developed by log4j team + * (Ceki Gülcü as log4j project founder and + * {@link http://jakarta.apache.org/log4j/docs/contributors.html contributors}).

    + * + *

    PHP port, extensions and modifications by VxR. All rights reserved.
    + * For more information, please see {@link http://www.vxr.it/log4php/}.

    + * + *

    This software is published under the terms of the LGPL License + * a copy of which has been included with this distribution in the LICENSE file.

    + * + * @package log4php + * @subpackage spi + */ + +/** + * @ignore + */ +if (!defined('LOG4PHP_DIR')) define('LOG4PHP_DIR', dirname(__FILE__)); + +/** + * Special level value signifying inherited behaviour. The current + * value of this string constant is inherited. + * {@link LOG4PHP_LOGGER_CONFIGURATOR_NULL} is a synonym. + */ +define('LOG4PHP_LOGGER_CONFIGURATOR_INHERITED', 'inherited'); + +/** + * Special level signifying inherited behaviour, same as + * {@link LOG4PHP_LOGGER_CONFIGURATOR_INHERITED}. + * The current value of this string constant is null. + */ +define('LOG4PHP_LOGGER_CONFIGURATOR_NULL', 'null'); + +/** + * Implemented by classes capable of configuring log4php using a URL. + * + * @author VxR + * @version $Revision: 1.2 $ + * @package log4php + * @subpackage spi + * @since 0.5 + * @abstract + */ +class LoggerConfigurator { + + /** + * Interpret a resource pointed by a url and configure accordingly. + * + * The configuration is done relative to the repository + * parameter. + * + * @param string $url The URL to parse + * @param LoggerHierarchy &$repository The hierarchy to operation upon. + */ + function doConfigure($url, &$repository) + { + return; + } +} +?> \ No newline at end of file diff --git a/src/lib/log4php/spi/LoggerFactory.php b/src/lib/log4php/spi/LoggerFactory.php new file mode 100644 index 0000000..5a8164e --- /dev/null +++ b/src/lib/log4php/spi/LoggerFactory.php @@ -0,0 +1,52 @@ +This framework is based on log4j (see {@link http://jakarta.apache.org/log4j log4j} for details).

    + *

    Design, strategies and part of the methods documentation are developed by log4j team + * (Ceki Gülcü as log4j project founder and + * {@link http://jakarta.apache.org/log4j/docs/contributors.html contributors}).

    + * + *

    PHP port, extensions and modifications by VxR. All rights reserved.
    + * For more information, please see {@link http://www.vxr.it/log4php/}.

    + * + *

    This software is published under the terms of the LGPL License + * a copy of which has been included with this distribution in the LICENSE file.

    + * + * @package log4php + * @subpackage spi + */ + +/** + * @ignore + */ +if (!defined('LOG4PHP_DIR')) define('LOG4PHP_DIR', dirname(__FILE__)); + +require_once(LOG4PHP_DIR . '/LoggerLog.php'); + +/** + * Extend and implement this abstract class to create new instances of + * {@link Logger} or a sub-class of {@link Logger}. + * + * @author VxR + * @version $Revision: 1.3 $ + * @package log4php + * @subpackage spi + * @since 0.5 + * @abstract + */ +class LoggerFactory { + + /** + * @abstract + * @param string $name + * @return Logger + */ + function makeNewLoggerInstance($name) + { + LoggerLog::warn("LoggerFactory:: makeNewLoggerInstance() is abstract."); + return null; + } + +} +?> \ No newline at end of file diff --git a/src/lib/log4php/spi/LoggerFilter.php b/src/lib/log4php/spi/LoggerFilter.php new file mode 100644 index 0000000..8baf547 --- /dev/null +++ b/src/lib/log4php/spi/LoggerFilter.php @@ -0,0 +1,113 @@ +This framework is based on log4j (see {@link http://jakarta.apache.org/log4j log4j} for details).

    + *

    Design, strategies and part of the methods documentation are developed by log4j team + * (Ceki Gülcü as log4j project founder and + * {@link http://jakarta.apache.org/log4j/docs/contributors.html contributors}).

    + * + *

    PHP port, extensions and modifications by VxR. All rights reserved.
    + * For more information, please see {@link http://www.vxr.it/log4php/}.

    + * + *

    This software is published under the terms of the LGPL License + * a copy of which has been included with this distribution in the LICENSE file.

    + * + * @package log4php + * @subpackage spi + */ + +/** + * @ignore + */ +if (!defined('LOG4PHP_DIR')) define('LOG4PHP_DIR', dirname(__FILE__) . '/..'); + +/** + * The log event must be logged immediately without consulting with + * the remaining filters, if any, in the chain. + */ +define('LOG4PHP_LOGGER_FILTER_ACCEPT', 1); + +/** + * This filter is neutral with respect to the log event. The + * remaining filters, if any, should be consulted for a final decision. + */ +define('LOG4PHP_LOGGER_FILTER_NEUTRAL', 0); + +/** + * The log event must be dropped immediately without consulting + * with the remaining filters, if any, in the chain. + */ +define('LOG4PHP_LOGGER_FILTER_DENY', -1); + +/** + * Users should extend this class to implement customized logging + * event filtering. Note that {@link LoggerCategory} and {@link LoggerAppenderSkeleton}, + * the parent class of all standard + * appenders, have built-in filtering rules. It is suggested that you + * first use and understand the built-in rules before rushing to write + * your own custom filters. + * + *

    This abstract class assumes and also imposes that filters be + * organized in a linear chain. The {@link #decide + * decide(LoggerLoggingEvent)} method of each filter is called sequentially, + * in the order of their addition to the chain. + * + *

    The {@link decide()} method must return one + * of the integer constants {@link LOG4PHP_LOG4PHP_LOGGER_FILTER_DENY}, + * {@link LOG4PHP_LOGGER_FILTER_NEUTRAL} or {@link LOG4PHP_LOGGER_FILTER_ACCEPT}. + * + *

    If the value {@link LOG4PHP_LOGGER_FILTER_DENY} is returned, then the log event is + * dropped immediately without consulting with the remaining + * filters. + * + *

    If the value {@link LOG4PHP_LOGGER_FILTER_NEUTRAL} is returned, then the next filter + * in the chain is consulted. If there are no more filters in the + * chain, then the log event is logged. Thus, in the presence of no + * filters, the default behaviour is to log all logging events. + * + *

    If the value {@link LOG4PHP_LOGGER_FILTER_ACCEPT} is returned, then the log + * event is logged without consulting the remaining filters. + * + *

    The philosophy of log4php filters is largely inspired from the + * Linux ipchains. + * + * @author VxR + * @version $Revision: 1.4 $ + * @package log4php + * @subpackage spi + */ +class LoggerFilter { + + /** + * @var LoggerFilter Points to the next {@link LoggerFilter} in the filter chain. + */ + var $next; + + /** + * Usually filters options become active when set. We provide a + * default do-nothing implementation for convenience. + */ + function activateOptions() + { + return; + } + + /** + * Decide what to do. + *

    If the decision is {@link LOG4PHP_LOGGER_FILTER_DENY}, then the event will be + * dropped. If the decision is {@link LOG4PHP_LOGGER_FILTER_NEUTRAL}, then the next + * filter, if any, will be invoked. If the decision is {@link LOG4PHP_LOGGER_FILTER_ACCEPT} then + * the event will be logged without consulting with other filters in + * the chain. + * + * @param LoggerLoggingEvent $event The {@link LoggerLoggingEvent} to decide upon. + * @return integer {@link LOG4PHP_LOGGER_FILTER_NEUTRAL} or {@link LOG4PHP_LOGGER_FILTER_DENY}|{@link LOG4PHP_LOGGER_FILTER_ACCEPT} + */ + function decide($event) + { + return LOG4PHP_LOGGER_FILTER_NEUTRAL; + } + +} +?> \ No newline at end of file diff --git a/src/lib/log4php/spi/LoggerLocationInfo.php b/src/lib/log4php/spi/LoggerLocationInfo.php new file mode 100644 index 0000000..cc46133 --- /dev/null +++ b/src/lib/log4php/spi/LoggerLocationInfo.php @@ -0,0 +1,116 @@ +This framework is based on log4j (see {@link http://jakarta.apache.org/log4j log4j} for details).

    + *

    Design, strategies and part of the methods documentation are developed by log4j team + * (Ceki Gülcü as log4j project founder and + * {@link http://jakarta.apache.org/log4j/docs/contributors.html contributors}).

    + * + *

    PHP port, extensions and modifications by VxR. All rights reserved.
    + * For more information, please see {@link http://www.vxr.it/log4php/}.

    + * + *

    This software is published under the terms of the LGPL License + * a copy of which has been included with this distribution in the LICENSE file.

    + * + * @package log4php + * @subpackage spi + */ + +/** + * @ignore + */ +if (!defined('LOG4PHP_DIR')) define('LOG4PHP_DIR', dirname(__FILE__) . '/..'); + +/** + * When location information is not available the constant + * NA is returned. Current value of this string + * constant is ?. + */ +define('LOG4PHP_LOGGER_LOCATION_INFO_NA', 'NA'); + +/** + * The internal representation of caller location information. + * + * @author VxR + * @version $Revision: 1.5 $ + * @package log4php + * @subpackage spi + * @since 0.3 + */ +class LoggerLocationInfo { + + /** + * @var string Caller's line number. + */ + var $lineNumber = null; + + /** + * @var string Caller's file name. + */ + var $fileName = null; + + /** + * @var string Caller's fully qualified class name. + */ + var $className = null; + + /** + * @var string Caller's method name. + */ + var $methodName = null; + + /** + * @var string + */ + var $fullInfo = null; + + /** + * Instantiate location information based on a {@link PHP_MANUAL#debug_backtrace}. + * + * @param array $trace + * @param mixed $caller + */ + function LoggerLocationInfo($trace, $fqcn = null) + { + $this->lineNumber = isset($trace['line']) ? $trace['line'] : null; + $this->fileName = isset($trace['file']) ? $trace['file'] : null; + $this->className = isset($trace['class']) ? $trace['class'] : null; + $this->methodName = isset($trace['function']) ? $trace['function'] : null; + + $this->fullInfo = $this->getClassName() . '.' . $this->getMethodName() . + '(' . $this->getFileName() . ':' . $this->getLineNumber() . ')'; + } + + function getClassName() + { + return ($this->className === null) ? LOG4PHP_LOGGER_LOCATION_INFO_NA : $this->className; + } + + /** + * Return the file name of the caller. + *

    This information is not always available. + */ + function getFileName() + { + return ($this->fileName === null) ? LOG4PHP_LOGGER_LOCATION_INFO_NA : $this->fileName; + } + + /** + * Returns the line number of the caller. + *

    This information is not always available. + */ + function getLineNumber() + { + return ($this->lineNumber === null) ? LOG4PHP_LOGGER_LOCATION_INFO_NA : $this->lineNumber; + } + + /** + * Returns the method name of the caller. + */ + function getMethodName() + { + return ($this->methodName === null) ? LOG4PHP_LOGGER_LOCATION_INFO_NA : $this->methodName; + } +} +?> \ No newline at end of file diff --git a/src/lib/log4php/spi/LoggerLoggingEvent.php b/src/lib/log4php/spi/LoggerLoggingEvent.php new file mode 100644 index 0000000..b05b772 --- /dev/null +++ b/src/lib/log4php/spi/LoggerLoggingEvent.php @@ -0,0 +1,388 @@ +This framework is based on log4j (see {@link http://jakarta.apache.org/log4j log4j} for details).

    + *

    Design, strategies and part of the methods documentation are developed by log4j team + * (Ceki G�lc� as log4j project founder and + * {@link http://jakarta.apache.org/log4j/docs/contributors.html contributors}).

    + * + *

    PHP port, extensions and modifications by VxR. All rights reserved.
    + * For more information, please see {@link http://www.vxr.it/log4php/}.

    + * + *

    This software is published under the terms of the LGPL License + * a copy of which has been included with this distribution in the LICENSE file.

    + * + * @package log4php + * @subpackage spi + */ + +/** + * @ignore + */ +if (!defined('LOG4PHP_DIR')) define('LOG4PHP_DIR', dirname(__FILE__) . '/..'); + +/** + */ +require_once(LOG4PHP_DIR . '/spi/LoggerLocationInfo.php'); +require_once(LOG4PHP_DIR . '/LoggerManager.php'); +require_once(LOG4PHP_DIR . '/LoggerMDC.php'); +require_once(LOG4PHP_DIR . '/LoggerNDC.php'); + +/** + * The internal representation of logging event. + * + * @author VxR + * @version $Revision: 1.16 $ + * @package log4php + * @subpackage spi + */ +class LoggerLoggingEvent { + + /** + * @var string Fully Qualified Class Name of the calling category class. + */ + var $fqcn; + + /** + * @var Logger reference + */ + var $logger = null; + + /** + * The category (logger) name. + * This field will be marked as private in future + * releases. Please do not access it directly. + * Use the {@link getLoggerName()} method instead. + * @deprecated + */ + var $categoryName; + + /** + * Level of logging event. + *

    This field should not be accessed directly. You shoud use the + * {@link getLevel()} method instead. + * + * @deprecated + * @var LoggerLevel + */ + var $level; + + /** + * @var string The nested diagnostic context (NDC) of logging event. + */ + var $ndc; + + /** + * Have we tried to do an NDC lookup? If we did, there is no need + * to do it again. Note that its value is always false when + * serialized. Thus, a receiving SocketNode will never use it's own + * (incorrect) NDC. See also writeObject method. + * @var boolean + */ + var $ndcLookupRequired = true; + + /** + * Have we tried to do an MDC lookup? If we did, there is no need + * to do it again. Note that its value is always false when + * serialized. See also the getMDC and getMDCCopy methods. + * @var boolean + */ + var $mdcCopyLookupRequired = true; + + /** + * @var mixed The application supplied message of logging event. + */ + var $message; + + /** + * The application supplied message rendered through the log4php + * objet rendering mechanism. At present renderedMessage == message. + * @var string + */ + var $renderedMessage; + + /** + * The name of thread in which this logging event was generated. + * log4php saves here the process id via {@link PHP_MANUAL#getmypid getmypid()} + * @var mixed + */ + var $threadName = null; + + /** + * The number of seconds elapsed from 1/1/1970 until logging event + * was created plus microseconds if available. + * @var float + */ + var $timeStamp; + + /** + * @var LoggerLocationInfo Location information for the caller. + */ + var $locationInfo = null; + + // Serialization + /* + var $serialVersionUID = -868428216207166145L; + var $PARAM_ARRAY = array(); + var $TO_LEVEL = "toLevel"; + var $TO_LEVEL_PARAMS = null; + var $methodCache = array(); // use a tiny table + */ + + /** + * Instantiate a LoggingEvent from the supplied parameters. + * + *

    Except {@link $timeStamp} all the other fields of + * LoggerLoggingEvent are filled when actually needed. + * + * @param string $fqcn name of the caller class. + * @param mixed &$logger The {@link Logger} category of this event or the logger name. + * @param LoggerLevel $priority The level of this event. + * @param mixed $message The message of this event. + * @param integer $timeStamp the timestamp of this logging event. + */ + function LoggerLoggingEvent($fqcn, &$logger, $priority, $message, $timeStamp = null) + { + $this->fqcn = $fqcn; + if (is_a($logger, 'logger')) { + $this->logger =& $logger; + $this->categoryName = $logger->getName(); + } else { + $this->categoryName = (string)$logger; + } + $this->level = $priority; + $this->message = $message; + if ($timeStamp !== null and is_float($timeStamp)) { + $this->timeStamp = $timeStamp; + } else { + if (function_exists('microtime')) { + list($usecs, $secs) = explode(' ', microtime()); + $this->timeStamp = ((float)$usecs + (float)$secs); + } else { + $this->timeStamp = time(); + } + } + } + function get_ancestors ($class) { + $classes = array($class); + while($class = get_parent_class($class)) { $classes[] = $class; } + return $classes; + } + /** + * Set the location information for this logging event. The collected + * information is cached for future use. + * + *

    This method uses {@link PHP_MANUAL#debug_backtrace debug_backtrace()} function (if exists) + * to collect informations about caller.

    + *

    It only recognize informations generated by {@link Logger} and its subclasses.

    + * @return LoggerLocationInfo + */ + function getLocationInformation() + { + if($this->locationInfo === null) { + + $locationInfo = array(); + + if (function_exists('debug_backtrace')) { + $prevHop = null; + $trace = debug_backtrace(); + // make a downsearch to identify the caller + $hop = array_pop($trace); + while ($hop !== null) { + $className = @$hop['class']; + if ( !empty($className) and ($className == 'loggercategory' or in_array("LoggerCategory",$this->get_ancestors($className))) ) { + $locationInfo['line'] = $hop['line']; + $locationInfo['file'] = $hop['file']; + break; + } + $prevHop = $hop; + $hop = array_pop($trace); + } + $locationInfo['class'] = isset($prevHop['class']) ? $prevHop['class'] : 'main'; + if (isset($prevHop['function']) and + $prevHop['function'] !== 'include' and + $prevHop['function'] !== 'include_once' and + $prevHop['function'] !== 'require' and + $prevHop['function'] !== 'require_once') { + + $locationInfo['function'] = $prevHop['function']; + } else { + $locationInfo['function'] = 'main'; + } + } + + $this->locationInfo = new LoggerLocationInfo($locationInfo, $this->fqcn); + } + return $this->locationInfo; + } + + /** + * Return the level of this event. Use this form instead of directly + * accessing the {@link $level} field. + * @return LoggerLevel + */ + function getLevel() + { + return $this->level; + } + + /** + * Return the name of the logger. Use this form instead of directly + * accessing the {@link $categoryName} field. + * @return string + */ + function getLoggerName() + { + return $this->categoryName; + } + + /** + * Return the message for this logging event. + * + *

    Before serialization, the returned object is the message + * passed by the user to generate the logging event. After + * serialization, the returned value equals the String form of the + * message possibly after object rendering. + * @return mixed + */ + function getMessage() + { + if($this->message !== null) { + return $this->message; + } else { + return $this->getRenderedMessage(); + } + } + + /** + * This method returns the NDC for this event. It will return the + * correct content even if the event was generated in a different + * thread or even on a different machine. The {@link LoggerNDC::get()} method + * should never be called directly. + * @return string + */ + function getNDC() + { + if ($this->ndcLookupRequired) { + $this->ndcLookupRequired = false; + $this->ndc = implode(' ',LoggerNDC::get()); + } + return $this->ndc; + } + + + /** + * Returns the the context corresponding to the key + * parameter. + * @return string + */ + function getMDC($key) + { + return LoggerMDC::get($key); + } + + /** + * Render message. + * @return string + */ + function getRenderedMessage() + { + if($this->renderedMessage === null and $this->message !== null) { + if (is_string($this->message)) { + $this->renderedMessage = $this->message; + } else { + if ($this->logger !== null) { + $repository =& $this->logger->getLoggerRepository(); + } else { + $repository =& LoggerManager::getLoggerRepository(); + } + if (method_exists($repository, 'getrenderermap')) { + $rendererMap =& $repository->getRendererMap(); + $this->renderedMessage= $rendererMap->findAndRender($this->message); + } else { + $this->renderedMessage = (string)$this->message; + } + } + } + return $this->renderedMessage; + } + + /** + * Returns the time when the application started, in seconds + * elapsed since 01.01.1970 plus microseconds if available. + * + * @return float + * @static + */ + function getStartTime() + { + static $startTime; + + if (!isset($startTime)) { + if (function_exists('microtime')) { + list($usec, $sec) = explode(' ', microtime()); + $startTime = ((float)$usec + (float)$sec); + } else { + $startTime = time(); + } + } + return $startTime; + } + + /** + * @return float + */ + function getTimeStamp() + { + return $this->timeStamp; + } + + /** + * @return mixed + */ + function getThreadName() + { + if ($this->threadName === null) + $this->threadName = (string)getmypid(); + return $this->threadName; + } + + /** + * @return mixed null + */ + function getThrowableInformation() + { + return null; + } + + /** + * Serialize this object + * @return string + */ + function toString() + { + serialize($this); + } + + /** + * Avoid serialization of the {@link $logger} object + */ + function __sleep() + { + return array( + 'fqcn','categoryName', + 'level', + 'ndc','ndcLookupRequired', + 'message','renderedMessage', + 'threadName', + 'timestamp', + 'locationInfo' + ); + } + +} + +LoggerLoggingEvent::getStartTime(); + +?> \ No newline at end of file diff --git a/src/lib/log4php/varia/LoggerDenyAllFilter.php b/src/lib/log4php/varia/LoggerDenyAllFilter.php new file mode 100644 index 0000000..ce8699f --- /dev/null +++ b/src/lib/log4php/varia/LoggerDenyAllFilter.php @@ -0,0 +1,57 @@ +This framework is based on log4j (see {@link http://jakarta.apache.org/log4j log4j} for details).

    + *

    Design, strategies and part of the methods documentation are developed by log4j team + * (Ceki Gülcü as log4j project founder and + * {@link http://jakarta.apache.org/log4j/docs/contributors.html contributors}).

    + * + *

    PHP port, extensions and modifications by VxR. All rights reserved.
    + * For more information, please see {@link http://www.vxr.it/log4php/}.

    + * + *

    This software is published under the terms of the LGPL License + * a copy of which has been included with this distribution in the LICENSE file.

    + * + * @package log4php + * @subpackage varia + */ + +/** + * @ignore + */ +if (!defined('LOG4PHP_DIR')) define('LOG4PHP_DIR', dirname(__FILE__) . '/..'); + +/** + */ +require_once(LOG4PHP_DIR . '/spi/LoggerFilter.php'); + +/** + * This filter drops all logging events. + * + *

    You can add this filter to the end of a filter chain to + * switch from the default "accept all unless instructed otherwise" + * filtering behaviour to a "deny all unless instructed otherwise" + * behaviour.

    + * + * @author VxR + * @version $Revision: 1.4 $ + * @package log4php + * @subpackage varia + * @since 0.3 + */ +class LoggerDenyAllFilter extends LoggerFilter { + + /** + * Always returns the integer constant {@link LOG4PHP_LOGGER_FILTER_DENY} + * regardless of the {@link LoggerLoggingEvent} parameter. + * + * @param LoggerLoggingEvent $event The {@link LoggerLoggingEvent} to filter. + * @return LOG4PHP_LOGGER_FILTER_DENY Always returns {@link LOG4PHP_LOGGER_FILTER_DENY} + */ + function decide($event) + { + return LOG4PHP_LOGGER_FILTER_DENY; + } +} +?> \ No newline at end of file diff --git a/src/lib/log4php/varia/LoggerLevelMatchFilter.php b/src/lib/log4php/varia/LoggerLevelMatchFilter.php new file mode 100644 index 0000000..2b7af04 --- /dev/null +++ b/src/lib/log4php/varia/LoggerLevelMatchFilter.php @@ -0,0 +1,119 @@ +This framework is based on log4j (see {@link http://jakarta.apache.org/log4j log4j} for details).

    + *

    Design, strategies and part of the methods documentation are developed by log4j team + * (Ceki Gülcü as log4j project founder and + * {@link http://jakarta.apache.org/log4j/docs/contributors.html contributors}).

    + * + *

    PHP port, extensions and modifications by VxR. All rights reserved.
    + * For more information, please see {@link http://www.vxr.it/log4php/}.

    + * + *

    This software is published under the terms of the LGPL License + * a copy of which has been included with this distribution in the LICENSE file.

    + * + * @package log4php + * @subpackage varia + */ + +/** + * @ignore + */ +if (!defined('LOG4PHP_DIR')) define('LOG4PHP_DIR', dirname(__FILE__) . '/..'); + +/** + */ +require_once(LOG4PHP_DIR . '/helpers/LoggerOptionConverter.php'); +require_once(LOG4PHP_DIR . '/spi/LoggerFilter.php'); + +/** + * This is a very simple filter based on level matching. + * + *

    The filter admits two options LevelToMatch and + * AcceptOnMatch. If there is an exact match between the value + * of the LevelToMatch option and the level of the + * {@link LoggerLoggingEvent}, then the {@link decide()} method returns + * {@link LOG4PHP_LOGGER_FILTER_ACCEPT} in case the AcceptOnMatch + * option value is set to true, if it is false then + * {@link LOG4PHP_LOGGER_FILTER_DENY} is returned. If there is no match, + * {@link LOG4PHP_LOGGER_FILTER_NEUTRAL} is returned.

    + * + * @author VxR + * @version $Revision: 1.2 $ + * @package log4php + * @subpackage varia + * @since 0.6 + */ +class LoggerLevelMatchFilter extends LoggerFilter { + + /** + * @var boolean + */ + var $acceptOnMatch = true; + + /** + * @var LoggerLevel + */ + var $levelToMatch; + + /** + * @return boolean + */ + function getAcceptOnMatch() + { + return $this->acceptOnMatch; + } + + /** + * @param boolean $acceptOnMatch + */ + function setAcceptOnMatch($acceptOnMatch) + { + $this->acceptOnMatch = LoggerOptionConverter::toBoolean($acceptOnMatch, true); + } + + /** + * @return LoggerLevel + */ + function getLevelToMatch() + { + return $this->levelToMatch; + } + + /** + * @param string $l the level to match + */ + function setLevelToMatch($l) + { + $this->levelToMatch = LoggerOptionConverter::toLevel($l, null); + } + + /** + * Return the decision of this filter. + * + * Returns {@link LOG4PHP_LOGGER_FILTER_NEUTRAL} if the LevelToMatch + * option is not set or if there is not match. Otherwise, if there is a + * match, then the returned decision is {@link LOG4PHP_LOGGER_FILTER_ACCEPT} if the + * AcceptOnMatch property is set to true. The + * returned decision is {@link LOG4PHP_LOGGER_FILTER_DENY} if the + * AcceptOnMatch property is set to false. + * + * @param LoggerLoggingEvent $event + * @return integer + */ + function decide($event) + { + if($this->levelToMatch === null) + return LOG4PHP_LOGGER_FILTER_NEUTRAL; + + if ($this->levelToMatch->equals($event->getLevel())) { + return $this->getAcceptOnMatch() ? + LOG4PHP_LOGGER_FILTER_ACCEPT : + LOG4PHP_LOGGER_FILTER_DENY; + } else { + return LOG4PHP_LOGGER_FILTER_NEUTRAL; + } + } +} +?> \ No newline at end of file diff --git a/src/lib/log4php/varia/LoggerLevelRangeFilter.php b/src/lib/log4php/varia/LoggerLevelRangeFilter.php new file mode 100644 index 0000000..d54bedd --- /dev/null +++ b/src/lib/log4php/varia/LoggerLevelRangeFilter.php @@ -0,0 +1,168 @@ +This framework is based on log4j (see {@link http://jakarta.apache.org/log4j log4j} for details).

    + *

    Design, strategies and part of the methods documentation are developed by log4j team + * (Ceki Gülcü as log4j project founder and + * {@link http://jakarta.apache.org/log4j/docs/contributors.html contributors}).

    + * + *

    PHP port, extensions and modifications by VxR. All rights reserved.
    + * For more information, please see {@link http://www.vxr.it/log4php/}.

    + * + *

    This software is published under the terms of the LGPL License + * a copy of which has been included with this distribution in the LICENSE file.

    + * + * @package log4php + * @subpackage varia + */ + +/** + * @ignore + */ +if (!defined('LOG4PHP_DIR')) define('LOG4PHP_DIR', dirname(__FILE__) . '/..'); + +/** + */ +require_once(LOG4PHP_DIR . '/helpers/LoggerOptionConverter.php'); +require_once(LOG4PHP_DIR . '/spi/LoggerFilter.php'); + +/** + * This is a very simple filter based on level matching, which can be + * used to reject messages with priorities outside a certain range. + * + *

    The filter admits three options LevelMin, LevelMax + * and AcceptOnMatch.

    + * + *

    If the level of the {@link LoggerLoggingEvent} is not between Min and Max + * (inclusive), then {@link LOG4PHP_LOGGER_FILTER_DENY} is returned.

    + * + *

    If the Logging event level is within the specified range, then if + * AcceptOnMatch is true, + * {@link LOG4PHP_LOGGER_FILTER_ACCEPT} is returned, and if + * AcceptOnMatch is false, + * {@link LOG4PHP_LOGGER_FILTER_NEUTRAL} is returned.

    + * + *

    If LevelMin is not defined, then there is no + * minimum acceptable level (ie a level is never rejected for + * being too "low"/unimportant). If LevelMax is not + * defined, then there is no maximum acceptable level (ie a + * level is never rejected for beeing too "high"/important).

    + * + *

    Refer to the {@link LoggerAppenderSkeleton::setThreshold()} method + * available to all appenders extending {@link LoggerAppenderSkeleton} + * for a more convenient way to filter out events by level.

    + * + * @log4j-class org.apache.log4j.varia.LevelRangeFilter + * @log4j-author Simon Kitching + * @log4j-author based on code by Ceki Gülcü + * + * @author VxR + * @version $Revision: 1.2 $ + * @package log4php + * @subpackage varia + * @since 0.6 + */ +class LoggerLevelRangeFilter extends LoggerFilter { + + /** + * @var boolean + */ + var $acceptOnMatch = true; + + /** + * @var LoggerLevel + */ + var $levelMin; + + /** + * @var LoggerLevel + */ + var $levelMax; + + /** + * @return boolean + */ + function getAcceptOnMatch() + { + return $this->acceptOnMatch; + } + + /** + * @param boolean $acceptOnMatch + */ + function setAcceptOnMatch($acceptOnMatch) + { + $this->acceptOnMatch = LoggerOptionConverter::toBoolean($acceptOnMatch, true); + } + + /** + * @return LoggerLevel + */ + function getLevelMin() + { + return $this->levelMin; + } + + /** + * @param string $l the level min to match + */ + function setLevelMin($l) + { + $this->levelMin = LoggerOptionConverter::toLevel($l, null); + } + + /** + * @return LoggerLevel + */ + function getLevelMax() + { + return $this->levelMax; + } + + /** + * @param string $l the level max to match + */ + function setLevelMax($l) + { + $this->levelMax = LoggerOptionConverter::toLevel($l, null); + } + + /** + * Return the decision of this filter. + * + * @param LoggerLoggingEvent $event + * @return integer + */ + function decide($event) + { + $level = $event->getLevel(); + + if($this->levelMin !== null) { + if ($level->isGreaterOrEqual($this->levelMin) == false) { + // level of event is less than minimum + return LOG4PHP_LOGGER_FILTER_DENY; + } + } + + if($this->levelMax !== null) { + if ($level->toInt() > $this->levelMax->toInt()) { + // level of event is greater than maximum + // Alas, there is no Level.isGreater method. and using + // a combo of isGreaterOrEqual && !Equal seems worse than + // checking the int values of the level objects.. + return LOG4PHP_LOGGER_FILTER_DENY; + } + } + + if ($this->getAcceptOnMatch()) { + // this filter set up to bypass later filters and always return + // accept if level in range + return LOG4PHP_LOGGER_FILTER_ACCEPT; + } else { + // event is ok for this filter; allow later filters to have a look.. + return LOG4PHP_LOGGER_FILTER_NEUTRAL; + } + } +} +?> \ No newline at end of file diff --git a/src/lib/log4php/varia/LoggerStringMatchFilter.php b/src/lib/log4php/varia/LoggerStringMatchFilter.php new file mode 100644 index 0000000..9594e89 --- /dev/null +++ b/src/lib/log4php/varia/LoggerStringMatchFilter.php @@ -0,0 +1,108 @@ +This framework is based on log4j (see {@link http://jakarta.apache.org/log4j log4j} for details).

    + *

    Design, strategies and part of the methods documentation are developed by log4j team + * (Ceki Gülcü as log4j project founder and + * {@link http://jakarta.apache.org/log4j/docs/contributors.html contributors}).

    + * + *

    PHP port, extensions and modifications by VxR. All rights reserved.
    + * For more information, please see {@link http://www.vxr.it/log4php/}.

    + * + *

    This software is published under the terms of the LGPL License + * a copy of which has been included with this distribution in the LICENSE file.

    + * + * @package log4php + * @subpackage varia + */ + +/** + * @ignore + */ +if (!defined('LOG4PHP_DIR')) define('LOG4PHP_DIR', dirname(__FILE__) . '/..'); + +/** + */ +require_once(LOG4PHP_DIR . '/spi/LoggerFilter.php'); + +/** + * This is a very simple filter based on string matching. + * + *

    The filter admits two options {@link $stringToMatch} and + * {@link $acceptOnMatch}. If there is a match (using {@link PHP_MANUAL#strpos} + * between the value of the {@link $stringToMatch} option and the message + * of the {@link LoggerLoggingEvent}, + * then the {@link decide()} method returns {@link LOG4PHP_LOGGER_FILTER_ACCEPT} if + * the AcceptOnMatch option value is true, if it is false then + * {@link LOG4PHP_LOGGER_FILTER_DENY} is returned. If there is no match, {@link LOG4PHP_LOGGER_FILTER_NEUTRAL} + * is returned.

    + * + * @author VxR + * @version $Revision: 1.4 $ + * @package log4php + * @subpackage varia + * @since 0.3 + */ +class LoggerStringMatchFilter extends LoggerFilter { + + /** + * @var boolean + */ + var $acceptOnMatch = true; + + /** + * @var string + */ + var $stringToMatch = null; + + /** + * @return boolean + */ + function getAcceptOnMatch() + { + return $this->acceptOnMatch; + } + + /** + * @param mixed $acceptOnMatch a boolean or a string ('true' or 'false') + */ + function setAcceptOnMatch($acceptOnMatch) + { + $this->acceptOnMatch = is_bool($acceptOnMatch) ? + $acceptOnMatch : + (bool)(strtolower($acceptOnMatch) == 'true'); + } + + /** + * @return string + */ + function getStringToMatch() + { + return $this->stringToMatch; + } + + /** + * @param string $s the string to match + */ + function setStringToMatch($s) + { + $this->stringToMatch = $s; + } + + /** + * @return integer a {@link LOGGER_FILTER_NEUTRAL} is there is no string match. + */ + function decide($event) + { + $msg = $event->getRenderedMessage(); + + if($msg === null or $this->stringToMatch === null) + return LOG4PHP_LOGGER_FILTER_NEUTRAL; + if( strpos($msg, $this->stringToMatch) !== false ) { + return ($this->acceptOnMatch) ? LOG4PHP_LOGGER_FILTER_ACCEPT : LOG4PHP_LOGGER_FILTER_DENY ; + } + return LOG4PHP_LOGGER_FILTER_NEUTRAL; + } +} +?> \ No newline at end of file diff --git a/src/lib/log4php/xml/LoggerDOMConfigurator.php b/src/lib/log4php/xml/LoggerDOMConfigurator.php new file mode 100644 index 0000000..3337437 --- /dev/null +++ b/src/lib/log4php/xml/LoggerDOMConfigurator.php @@ -0,0 +1,609 @@ +This framework is based on log4j (see {@link http://jakarta.apache.org/log4j log4j} for details).

    + *

    Design, strategies and part of the methods documentation are developed by log4j team + * (Ceki Gülcü as log4j project founder and + * {@link http://jakarta.apache.org/log4j/docs/contributors.html contributors}).

    + * + *

    PHP port, extensions and modifications by VxR. All rights reserved.
    + * For more information, please see {@link http://www.vxr.it/log4php/}.

    + * + *

    This software is published under the terms of the LGPL License + * a copy of which has been included with this distribution in the LICENSE file.

    + * + * @package log4php + * @subpackage xml + */ + +/** + * @ignore + */ +if (!defined('LOG4PHP_DIR')) define('LOG4PHP_DIR', dirname(__FILE__) . '/..'); + +require_once(LOG4PHP_DIR . '/helpers/LoggerOptionConverter.php'); +require_once(LOG4PHP_DIR . '/or/LoggerObjectRenderer.php'); +require_once(LOG4PHP_DIR . '/spi/LoggerConfigurator.php'); +require_once(LOG4PHP_DIR . '/LoggerAppender.php'); +require_once(LOG4PHP_DIR . '/LoggerLayout.php'); +require_once(LOG4PHP_DIR . '/LoggerLog.php'); +require_once(LOG4PHP_DIR . '/LoggerManager.php'); + +define('LOG4PHP_LOGGER_DOM_CONFIGURATOR_APPENDER_STATE', 1000); +define('LOG4PHP_LOGGER_DOM_CONFIGURATOR_LAYOUT_STATE', 1010); +define('LOG4PHP_LOGGER_DOM_CONFIGURATOR_ROOT_STATE', 1020); +define('LOG4PHP_LOGGER_DOM_CONFIGURATOR_LOGGER_STATE', 1030); +define('LOG4PHP_LOGGER_DOM_CONFIGURATOR_FILTER_STATE', 1040); + +define('LOG4PHP_LOGGER_DOM_CONFIGURATOR_DEFAULT_FILENAME', './log4php.xml'); + +/** + * @var string the default configuration document + */ +define('LOG4PHP_LOGGER_DOM_CONFIGURATOR_DEFAULT_CONFIGURATION', +' + + + + + + + + +'); + +/** + * @var string the elements namespace + */ +define('LOG4PHP_LOGGER_DOM_CONFIGURATOR_XMLNS', 'HTTP://WWW.VXR.IT/LOG4PHP/'); + +/** + * Use this class to initialize the log4php environment using expat parser. + * + *

    Read the log4php.dtd included in the documentation directory. Note that + * php parser does not validate the document.

    + * + *

    Sometimes it is useful to see how log4php is reading configuration + * files. You can enable log4php internal logging by setting the debug + * attribute in the log4php:configuration element. As in + *

    + * <log4php:configuration debug="true" xmlns:log4php="http://www.vxr.it/log4php/">
    + * ...
    + * </log4php:configuration>
    + * 
    + * + *

    There are sample XML files included in the package under tests/ + * subdirectories.

    + * + * @author VxR + * @version $Revision: 1.12 $ + * @package log4php + * @subpackage xml + * @since 0.4 + */ +class LoggerDOMConfigurator extends LoggerConfigurator { + + /** + * @var LoggerHierarchy + */ + var $repository; + + /** + * @var array state stack + */ + var $state; + + /** + * @var Logger parsed Logger + */ + var $logger; + + /** + * @var LoggerAppender parsed LoggerAppender + */ + var $appender; + + /** + * @var LoggerFilter parsed LoggerFilter + */ + var $filter; + + /** + * @var LoggerLayout parsed LoggerLayout + */ + var $layout; + + /** + * Constructor + */ + function LoggerDOMConfigurator() + { + $this->state = array(); + $this->logger = null; + $this->appender = null; + $this->filter = null; + $this->layout = null; + } + + /** + * Configure the default repository using the resource pointed by url. + * Url is any valid resurce as defined in {@link PHP_MANUAL#file} function. + * Note that the resource will be search with use_include_path parameter + * set to "1". + * + * @param string $url + * @static + */ + function configure($url = '') + { + $configurator = new LoggerDOMConfigurator(); + $repository =& LoggerManager::getLoggerRepository(); + return $configurator->doConfigure($url, $repository); + } + + /** + * Configure the given repository using the resource pointed by url. + * Url is any valid resurce as defined in {@link PHP_MANUAL#file} function. + * Note that the resource will be search with use_include_path parameter + * set to "1". + * + * @param string $url + * @param LoggerHierarchy &$repository + */ + function doConfigure($url = '', &$repository) + { + $xmlData = ''; + if (!empty($url)) + $xmlData = implode('', file($url, 1)); + return $this->doConfigureByString($xmlData, $repository); + } + + /** + * Configure the given repository using the configuration written in xmlData. + * Do not call this method directly. Use {@link doConfigure()} instead. + * @param string $xmlData + * @param LoggerHierarchy &$repository + */ + function doConfigureByString($xmlData, &$repository) + { + return $this->parse($xmlData, $repository); + } + + /** + * @param LoggerHierarchy &$repository + */ + function doConfigureDefault(&$repository) + { + return $this->doConfigureByString(LOG4PHP_LOGGER_DOM_CONFIGURATOR_DEFAULT_CONFIGURATION, $repository); + } + + /** + * @param string $xmlData + */ + function parse($xmlData, &$repository) + { + // LoggerManager::resetConfiguration(); + $this->repository =& $repository; + + $parser = xml_parser_create_ns(); + + xml_set_object($parser, &$this); + xml_set_element_handler($parser, "tagOpen", "tagClose"); + + $result = xml_parse($parser, $xmlData, true); + if (!$result) { + $errorCode = xml_get_error_code($parser); + $errorStr = xml_error_string($errorCode); + $errorLine = xml_get_current_line_number($parser); + LoggerLog::warn( + "LoggerDOMConfigurator::parse() ". + "Parsing error [{$errorCode}] {$errorStr}, line {$errorLine}" + ); + $this->repository->resetConfiguration(); + } else { + xml_parser_free($parser); + } + return $result; + } + + /** + * @param mixed $parser + * @param string $tag + * @param array $attribs + * + * @todo In 'LOGGER' case find a better way to detect 'getLogger()' method + */ + function tagOpen($parser, $tag, $attribs) + { + switch ($tag) { + + case 'CONFIGURATION' : + case LOG4PHP_LOGGER_DOM_CONFIGURATOR_XMLNS.':CONFIGURATION': + + LoggerLog::debug("LoggerDOMConfigurator::tagOpen() CONFIGURATION"); + + if (isset($attribs['THRESHOLD'])) { + + $this->repository->setThreshold( + LoggerOptionConverter::toLevel( + $this->subst($attribs['THRESHOLD']), + $this->repository->getThreshold() + ) + ); + } + if (isset($attribs['DEBUG'])) { + $debug = LoggerOptionConverter::toBoolean($this->subst($attribs['DEBUG']), LoggerLog::internalDebugging()); + $this->repository->debug = $debug; + LoggerLog::internalDebugging($debug); + LoggerLog::debug("LoggerDOMConfigurator::tagOpen() LOG4PHP:CONFIGURATION. Internal Debug turned ".($debug ? 'on':'off')); + + } + break; + + case 'APPENDER' : + case LOG4PHP_LOGGER_DOM_CONFIGURATOR_XMLNS.':APPENDER': + + unset($this->appender); + $this->appender = null; + + $name = $this->subst(@$attribs['NAME']); + $class = $this->subst(@$attribs['CLASS']); + + LoggerLog::debug("LoggerDOMConfigurator::tagOpen():tag=[$tag]:name=[$name]:class=[$class]"); + + $this->appender =& LoggerAppender::singleton($name, $class); + if ($this->appender === null) { + LoggerLog::warn("LoggerDOMConfigurator::tagOpen() APPENDER cannot instantiate appender '$name'"); + } + $this->state[] = LOG4PHP_LOGGER_DOM_CONFIGURATOR_APPENDER_STATE; + break; + + case 'APPENDER_REF' : + case 'APPENDER-REF' : + case LOG4PHP_LOGGER_DOM_CONFIGURATOR_XMLNS.':APPENDER_REF': + case LOG4PHP_LOGGER_DOM_CONFIGURATOR_XMLNS.':APPENDER-REF': + + + if (isset($attribs['REF']) and !empty($attribs['REF'])) { + $appenderName = $this->subst($attribs['REF']); + + LoggerLog::debug("LoggerDOMConfigurator::tagOpen() APPENDER-REF ref='$appenderName'"); + + $appender =& LoggerAppender::singleton($appenderName); + if ($appender !== null) { + switch (end($this->state)) { + case LOG4PHP_LOGGER_DOM_CONFIGURATOR_LOGGER_STATE: + case LOG4PHP_LOGGER_DOM_CONFIGURATOR_ROOT_STATE: + $this->logger->addAppender($appender); + break; + } + } else { + LoggerLog::warn("LoggerDOMConfigurator::tagOpen() APPENDER-REF ref '$appenderName' points to a null appender"); + } + } else { + LoggerLog::warn("LoggerDOMConfigurator::tagOpen() APPENDER-REF ref not set or empty"); + } + break; + + case 'FILTER' : + case LOG4PHP_LOGGER_DOM_CONFIGURATOR_XMLNS.':FILTER': + + LoggerLog::debug("LoggerDOMConfigurator::tagOpen() FILTER"); + + unset($this->filter); + $this->filter = null; + + $filterName = basename($this->subst(@$attribs['CLASS'])); + if (!empty($filterName)) { + if (!class_exists($filterName)) { + @include_once(LOG4PHP_DIR . "/varia/{$filterName}.php"); + } + if (class_exists($filterName)) { + $this->filter = new $filterName(); + } else { + LoggerLog::warn("LoggerDOMConfigurator::tagOpen() FILTER. class '$filterName' doesnt exist"); + } + $this->state[] = LOG4PHP_LOGGER_DOM_CONFIGURATOR_FILTER_STATE; + } else { + LoggerLog::warn("LoggerDOMConfigurator::tagOpen() FILTER filter name cannot be empty"); + } + break; + + case 'LAYOUT': + case LOG4PHP_LOGGER_DOM_CONFIGURATOR_XMLNS.':LAYOUT': + + $class = @$attribs['CLASS']; + + LoggerLog::debug("LoggerDOMConfigurator::tagOpen() LAYOUT class='{$class}'"); + + $this->layout = LoggerLayout::factory($this->subst($class)); + if ($this->layout === null) + LoggerLog::warn("LoggerDOMConfigurator::tagOpen() LAYOUT unable to instanciate class='{$class}'"); + + $this->state[] = LOG4PHP_LOGGER_DOM_CONFIGURATOR_LAYOUT_STATE; + break; + + case 'LOGGER': + case LOG4PHP_LOGGER_DOM_CONFIGURATOR_XMLNS.':LOGGER': + + // $this->logger is assigned by reference. + // Only '$this->logger=null;' destroys referenced object + unset($this->logger); + $this->logger = null; + + $loggerName = $this->subst(@$attribs['NAME']); + if (!empty($loggerName)) { + LoggerLog::debug("LoggerDOMConfigurator::tagOpen() LOGGER. name='$loggerName'"); + + $class = $this->subst(@$attribs['CLASS']); + if (empty($class)) { + $this->logger =& $this->repository->getLogger($loggerName); + } else { + $className = basename($class); + if (!class_exists($className)) + @include_once("{$class}.php"); + if (!class_exists($className)) { + LoggerLog::warn( + "LoggerDOMConfigurator::tagOpen() LOGGER. ". + "cannot find '$className'." + ); + } else { + + if (in_array('getlogger', get_class_methods($className))) { + $this->logger =& call_user_func(array($className, 'getlogger'), $loggerName); + } else { + LoggerLog::warn( + "LoggerDOMConfigurator::tagOpen() LOGGER. ". + "class '$className' doesnt implement 'getLogger()' method." + ); + } + } + } + if ($this->logger !== null and isset($attribs['ADDITIVITY'])) { + $additivity = LoggerOptionConverter::toBoolean($this->subst($attribs['ADDITIVITY']), true); + $this->logger->setAdditivity($additivity); + } + } else { + LoggerLog::warn("LoggerDOMConfigurator::tagOpen() LOGGER. Attribute 'name' is not set or is empty."); + } + $this->state[] = LOG4PHP_LOGGER_DOM_CONFIGURATOR_LOGGER_STATE;; + break; + + case 'LEVEL': + case LOG4PHP_LOGGER_DOM_CONFIGURATOR_XMLNS.':LEVEL': + case 'PRIORITY': + case LOG4PHP_LOGGER_DOM_CONFIGURATOR_XMLNS.':PRIORITY': + + if (!isset($attribs['VALUE'])) { + LoggerLog::debug("LoggerDOMConfigurator::tagOpen() LEVEL value not set"); + break; + } + + LoggerLog::debug("LoggerDOMConfigurator::tagOpen() LEVEL value={$attribs['VALUE']}"); + + if ($this->logger === null) { + LoggerLog::warn("LoggerDOMConfigurator::tagOpen() LEVEL. parent logger is null"); + break; + } + + switch (end($this->state)) { + case LOG4PHP_LOGGER_DOM_CONFIGURATOR_ROOT_STATE: + $this->logger->setLevel( + LoggerOptionConverter::toLevel( + $this->subst($attribs['VALUE']), + $this->logger->getLevel() + ) + ); + LoggerLog::debug("LoggerDOMConfigurator::tagOpen() LEVEL root level is now '{$attribs['VALUE']}' "); + break; + case LOG4PHP_LOGGER_DOM_CONFIGURATOR_LOGGER_STATE: + $this->logger->setLevel( + LoggerOptionConverter::toLevel( + $this->subst($attribs['VALUE']), + $this->logger->getLevel() + ) + ); + break; + default: + LoggerLog::warn("LoggerDOMConfigurator::tagOpen() LEVEL state '{$this->state}' not allowed here"); + } + break; + + case 'PARAM': + case LOG4PHP_LOGGER_DOM_CONFIGURATOR_XMLNS.':PARAM': + + LoggerLog::debug("LoggerDOMConfigurator::tagOpen() PARAM"); + + if (!isset($attribs['NAME'])) { + LoggerLog::warn( + "LoggerDOMConfigurator::tagOpen() PARAM. ". + "attribute 'name' not defined." + ); + break; + } + if (!isset($attribs['VALUE'])) { + LoggerLog::warn( + "LoggerDOMConfigurator::tagOpen() PARAM. ". + "attribute 'value' not defined." + ); + break; + } + + switch (end($this->state)) { + case LOG4PHP_LOGGER_DOM_CONFIGURATOR_APPENDER_STATE: + if ($this->appender !== null) { + $this->setter($this->appender, $this->subst($attribs['NAME']), $this->subst($attribs['VALUE'])); + } else { + LoggerLog::warn( + "LoggerDOMConfigurator::tagOpen() PARAM. ". + " trying to set property to a null appender." + ); + } + break; + case LOG4PHP_LOGGER_DOM_CONFIGURATOR_LAYOUT_STATE: + if ($this->layout !== null) { + $this->setter($this->layout, $this->subst($attribs['NAME']), $this->subst($attribs['VALUE'])); + } else { + LoggerLog::warn( + "LoggerDOMConfigurator::tagOpen() PARAM. ". + " trying to set property to a null layout." + ); + } + break; + case LOG4PHP_LOGGER_DOM_CONFIGURATOR_FILTER_STATE: + if ($this->filter !== null) { + $this->setter($this->filter, $this->subst($attribs['NAME']), $this->subst($attribs['VALUE'])); + } else { + LoggerLog::warn( + "LoggerDOMConfigurator::tagOpen() PARAM. ". + " trying to set property to a null filter." + ); + } + break; + default: + LoggerLog::warn("LoggerDOMConfigurator::tagOpen() PARAM state '{$this->state}' not allowed here"); + } + break; + + case 'RENDERER': + case LOG4PHP_LOGGER_DOM_CONFIGURATOR_XMLNS.':RENDERER': + + $renderedClass = $this->subst(@$attribs['RENDEREDCLASS']); + $renderingClass = $this->subst(@$attribs['RENDERINGCLASS']); + + LoggerLog::debug("LoggerDOMConfigurator::tagOpen() RENDERER renderedClass='$renderedClass' renderingClass='$renderingClass'"); + + if (!empty($renderedClass) and !empty($renderingClass)) { + $renderer = LoggerObjectRenderer::factory($renderingClass); + if ($renderer === null) { + LoggerLog::warn("LoggerDOMConfigurator::tagOpen() RENDERER cannot instantiate '$renderingClass'"); + } else { + $this->repository->setRenderer($renderedClass, $renderer); + } + } else { + LoggerLog::warn("LoggerDOMConfigurator::tagOpen() RENDERER renderedClass or renderingClass is empty"); + } + break; + + case 'ROOT': + case LOG4PHP_LOGGER_DOM_CONFIGURATOR_XMLNS.':ROOT': + + LoggerLog::debug("LoggerDOMConfigurator::tagOpen() ROOT"); + + $this->logger =& LoggerManager::getRootLogger(); + + $this->state[] = LOG4PHP_LOGGER_DOM_CONFIGURATOR_ROOT_STATE; + break; + + } + + } + + + /** + * @param mixed $parser + * @param string $tag + */ + function tagClose($parser, $tag) + { + switch ($tag) { + + case 'CONFIGURATION' : + case LOG4PHP_LOGGER_DOM_CONFIGURATOR_XMLNS.':CONFIGURATION': + + LoggerLog::debug("LoggerDOMConfigurator::tagClose() CONFIGURATION"); + break; + + case 'APPENDER' : + case LOG4PHP_LOGGER_DOM_CONFIGURATOR_XMLNS.':APPENDER': + + LoggerLog::debug("LoggerDOMConfigurator::tagClose() APPENDER"); + + if ($this->appender !== null) { + if ($this->appender->requiresLayout() and $this->appender->layout === null) { + $appenderName = $this->appender->getName(); + LoggerLog::warn( + "LoggerDOMConfigurator::tagClose() APPENDER. ". + "'$appenderName' requires a layout that is not defined. ". + "Using a simple layout" + ); + $this->appender->setLayout(LoggerLayout::factory('LoggerLayoutSimple')); + } + $this->appender->activateOptions(); + } + array_pop($this->state); + break; + + case 'FILTER' : + case LOG4PHP_LOGGER_DOM_CONFIGURATOR_XMLNS.':FILTER': + + LoggerLog::debug("LoggerDOMConfigurator::tagClose() FILTER"); + + if ($this->filter !== null) { + $this->filter->activateOptions(); + $this->appender->addFilter($this->filter); + $this->filter = null; + } + array_pop($this->state); + break; + + case 'LAYOUT': + case LOG4PHP_LOGGER_DOM_CONFIGURATOR_XMLNS.':LAYOUT': + + LoggerLog::debug("LoggerDOMConfigurator::tagClose() LAYOUT"); + + if ($this->appender !== null and $this->layout !== null and $this->appender->requiresLayout()) { + $this->layout->activateOptions(); + $this->appender->setLayout($this->layout); + $this->layout = null; + } + array_pop($this->state); + break; + + case 'LOGGER': + case LOG4PHP_LOGGER_DOM_CONFIGURATOR_XMLNS.':LOGGER': + + LoggerLog::debug("LoggerDOMConfigurator::tagClose() LOGGER"); + + array_pop($this->state); + break; + + case 'ROOT': + case LOG4PHP_LOGGER_DOM_CONFIGURATOR_XMLNS.':ROOT': + + LoggerLog::debug("LoggerDOMConfigurator::tagClose() ROOT"); + + array_pop($this->state); + break; + } + } + + /** + * @param object $object + * @param string $name + * @param mixed $value + */ + function setter(&$object, $name, $value) + { + if (empty($name)) { + LoggerLog::debug("LoggerDOMConfigurator::setter() 'name' param cannot be empty"); + return false; + } + $methodName = 'set'.ucfirst($name); + if (method_exists($object, $methodName)) { + LoggerLog::debug("LoggerDOMConfigurator::setter() Calling ".get_class($object)."::{$methodName}({$value})"); + return call_user_func(array(&$object, $methodName), $value); + } else { + LoggerLog::warn("LoggerDOMConfigurator::setter() ".get_class($object)."::{$methodName}() does not exists"); + return false; + } + } + + function subst($value) + { + return LoggerOptionConverter::substVars($value); + } + +} +?> \ No newline at end of file diff --git a/src/lib/pear/PEAR/.channels/.alias/firephp.txt b/src/lib/pear/PEAR/.channels/.alias/firephp.txt new file mode 100644 index 0000000..f0561d4 --- /dev/null +++ b/src/lib/pear/PEAR/.channels/.alias/firephp.txt @@ -0,0 +1 @@ +pear.firephp.org \ No newline at end of file diff --git a/src/lib/pear/PEAR/.channels/.alias/pear.txt b/src/lib/pear/PEAR/.channels/.alias/pear.txt new file mode 100644 index 0000000..f4730b9 --- /dev/null +++ b/src/lib/pear/PEAR/.channels/.alias/pear.txt @@ -0,0 +1 @@ +pear.php.net \ No newline at end of file diff --git a/src/lib/pear/PEAR/.channels/.alias/pecl.txt b/src/lib/pear/PEAR/.channels/.alias/pecl.txt new file mode 100644 index 0000000..2de48f1 --- /dev/null +++ b/src/lib/pear/PEAR/.channels/.alias/pecl.txt @@ -0,0 +1 @@ +pecl.php.net \ No newline at end of file diff --git a/src/lib/pear/PEAR/.channels/__uri.reg b/src/lib/pear/PEAR/.channels/__uri.reg new file mode 100644 index 0000000..7225293 --- /dev/null +++ b/src/lib/pear/PEAR/.channels/__uri.reg @@ -0,0 +1 @@ +a:4:{s:4:"name";s:5:"__uri";s:7:"servers";a:1:{s:7:"primary";a:1:{s:6:"xmlrpc";a:1:{s:8:"function";a:2:{s:7:"attribs";a:1:{s:7:"version";s:3:"1.0";}s:8:"_content";s:4:"****";}}}}s:7:"summary";s:34:"Pseudo-channel for static packages";s:13:"_lastmodified";s:31:"Sun, 15 Feb 2009 00:54:38 +0100";} \ No newline at end of file diff --git a/src/lib/pear/PEAR/.channels/pear.firephp.org.reg b/src/lib/pear/PEAR/.channels/pear.firephp.org.reg new file mode 100644 index 0000000..64bf6ba --- /dev/null +++ b/src/lib/pear/PEAR/.channels/pear.firephp.org.reg @@ -0,0 +1 @@ +a:6:{s:7:"attribs";a:4:{s:7:"version";s:3:"1.0";s:5:"xmlns";s:31:"http://pear.php.net/channel-1.0";s:9:"xmlns:xsi";s:41:"http://www.w3.org/2001/XMLSchema-instance";s:18:"xsi:schemaLocation";s:75:"http://pear.php.net/dtd/channel-1.0 http://pear.php.net/dtd/channel-1.0.xsd";}s:4:"name";s:16:"pear.firephp.org";s:7:"summary";s:67:"Server code for FirePHP Firefox Extension (http://www.firephp.org/)";s:14:"suggestedalias";s:7:"firephp";s:7:"servers";a:1:{s:7:"primary";a:1:{s:4:"rest";a:1:{s:7:"baseurl";a:2:{i:0;a:2:{s:7:"attribs";a:1:{s:4:"type";s:7:"REST1.0";}s:8:"_content";s:48:"http://pear.firephp.org/Chiara_PEAR_Server_REST/";}i:1;a:2:{s:7:"attribs";a:1:{s:4:"type";s:7:"REST1.1";}s:8:"_content";s:48:"http://pear.firephp.org/Chiara_PEAR_Server_REST/";}}}}}s:13:"_lastmodified";a:2:{s:4:"ETag";s:21:""3a801d-2a6-5d04af00"";s:13:"Last-Modified";s:29:"Mon, 30 Jun 2008 23:10:20 GMT";}} \ No newline at end of file diff --git a/src/lib/pear/PEAR/.channels/pear.php.net.reg b/src/lib/pear/PEAR/.channels/pear.php.net.reg new file mode 100644 index 0000000..0b4b9b6 --- /dev/null +++ b/src/lib/pear/PEAR/.channels/pear.php.net.reg @@ -0,0 +1 @@ +a:6:{s:7:"attribs";a:4:{s:7:"version";s:3:"1.0";s:5:"xmlns";s:31:"http://pear.php.net/channel-1.0";s:9:"xmlns:xsi";s:41:"http://www.w3.org/2001/XMLSchema-instance";s:18:"xsi:schemaLocation";s:71:"http://pear.php.net/channel-1.0 http://pear.php.net/dtd/channel-1.0.xsd";}s:4:"name";s:12:"pear.php.net";s:14:"suggestedalias";s:4:"pear";s:7:"summary";s:40:"PHP Extension and Application Repository";s:7:"servers";a:2:{s:7:"primary";a:1:{s:4:"rest";a:1:{s:7:"baseurl";a:4:{i:0;a:2:{s:7:"attribs";a:1:{s:4:"type";s:7:"REST1.0";}s:8:"_content";s:25:"http://pear.php.net/rest/";}i:1;a:2:{s:7:"attribs";a:1:{s:4:"type";s:7:"REST1.1";}s:8:"_content";s:25:"http://pear.php.net/rest/";}i:2;a:2:{s:7:"attribs";a:1:{s:4:"type";s:7:"REST1.2";}s:8:"_content";s:25:"http://pear.php.net/rest/";}i:3;a:2:{s:7:"attribs";a:1:{s:4:"type";s:7:"REST1.3";}s:8:"_content";s:25:"http://pear.php.net/rest/";}}}}s:6:"mirror";a:2:{i:0;a:2:{s:7:"attribs";a:1:{s:4:"host";s:15:"us.pear.php.net";}s:4:"rest";a:1:{s:7:"baseurl";a:4:{i:0;a:2:{s:7:"attribs";a:1:{s:4:"type";s:7:"REST1.0";}s:8:"_content";s:28:"http://us.pear.php.net/rest/";}i:1;a:2:{s:7:"attribs";a:1:{s:4:"type";s:7:"REST1.1";}s:8:"_content";s:28:"http://us.pear.php.net/rest/";}i:2;a:2:{s:7:"attribs";a:1:{s:4:"type";s:7:"REST1.2";}s:8:"_content";s:28:"http://us.pear.php.net/rest/";}i:3;a:2:{s:7:"attribs";a:1:{s:4:"type";s:7:"REST1.3";}s:8:"_content";s:28:"http://us.pear.php.net/rest/";}}}}i:1;a:2:{s:7:"attribs";a:3:{s:4:"host";s:15:"de.pear.php.net";s:3:"ssl";s:3:"yes";s:4:"port";s:4:"3452";}s:4:"rest";a:1:{s:7:"baseurl";a:4:{i:0;a:2:{s:7:"attribs";a:1:{s:4:"type";s:7:"REST1.0";}s:8:"_content";s:34:"https://de.pear.php.net:3452/rest/";}i:1;a:2:{s:7:"attribs";a:1:{s:4:"type";s:7:"REST1.1";}s:8:"_content";s:34:"https://de.pear.php.net:3452/rest/";}i:2;a:2:{s:7:"attribs";a:1:{s:4:"type";s:7:"REST1.2";}s:8:"_content";s:34:"https://de.pear.php.net:3452/rest/";}i:3;a:2:{s:7:"attribs";a:1:{s:4:"type";s:7:"REST1.3";}s:8:"_content";s:34:"https://de.pear.php.net:3452/rest/";}}}}}}s:13:"_lastmodified";a:2:{s:4:"ETag";s:20:""2fafd-59a-44810840"";s:13:"Last-Modified";s:29:"Fri, 13 Feb 2009 12:49:29 GMT";}} \ No newline at end of file diff --git a/src/lib/pear/PEAR/.channels/pecl.php.net.reg b/src/lib/pear/PEAR/.channels/pecl.php.net.reg new file mode 100644 index 0000000..eb2594b --- /dev/null +++ b/src/lib/pear/PEAR/.channels/pecl.php.net.reg @@ -0,0 +1 @@ +a:7:{s:7:"attribs";a:4:{s:7:"version";s:3:"1.0";s:5:"xmlns";s:31:"http://pear.php.net/channel-1.0";s:9:"xmlns:xsi";s:41:"http://www.w3.org/2001/XMLSchema-instance";s:18:"xsi:schemaLocation";s:71:"http://pear.php.net/channel-1.0 http://pear.php.net/dtd/channel-1.0.xsd";}s:4:"name";s:12:"pecl.php.net";s:14:"suggestedalias";s:4:"pecl";s:7:"summary";s:31:"PHP Extension Community Library";s:15:"validatepackage";a:2:{s:7:"attribs";a:1:{s:7:"version";s:3:"1.0";}s:8:"_content";s:19:"PEAR_Validator_PECL";}s:7:"servers";a:1:{s:7:"primary";a:2:{s:6:"xmlrpc";a:1:{s:8:"function";a:8:{i:0;a:2:{s:7:"attribs";a:1:{s:7:"version";s:3:"1.0";}s:8:"_content";s:9:"logintest";}i:1;a:2:{s:7:"attribs";a:1:{s:7:"version";s:3:"1.0";}s:8:"_content";s:26:"package.listLatestReleases";}i:2;a:2:{s:7:"attribs";a:1:{s:7:"version";s:3:"1.0";}s:8:"_content";s:15:"package.listAll";}i:3;a:2:{s:7:"attribs";a:1:{s:7:"version";s:3:"1.0";}s:8:"_content";s:12:"package.info";}i:4;a:2:{s:7:"attribs";a:1:{s:7:"version";s:3:"1.0";}s:8:"_content";s:22:"package.getDownloadURL";}i:5;a:2:{s:7:"attribs";a:1:{s:7:"version";s:3:"1.0";}s:8:"_content";s:25:"package.getDepDownloadURL";}i:6;a:2:{s:7:"attribs";a:1:{s:7:"version";s:3:"1.0";}s:8:"_content";s:14:"package.search";}i:7;a:2:{s:7:"attribs";a:1:{s:7:"version";s:3:"1.0";}s:8:"_content";s:15:"channel.listAll";}}}s:4:"rest";a:1:{s:7:"baseurl";a:2:{i:0;a:2:{s:7:"attribs";a:1:{s:4:"type";s:7:"REST1.0";}s:8:"_content";s:25:"http://pecl.php.net/rest/";}i:1;a:2:{s:7:"attribs";a:1:{s:4:"type";s:7:"REST1.1";}s:8:"_content";s:25:"http://pecl.php.net/rest/";}}}}}s:13:"_lastmodified";a:2:{s:4:"ETag";s:21:""c3407b-46e-4365ba37"";s:13:"Last-Modified";s:29:"Mon, 31 Oct 2005 06:31:19 GMT";}} \ No newline at end of file diff --git a/src/lib/pear/PEAR/.depdb b/src/lib/pear/PEAR/.depdb new file mode 100644 index 0000000..e6113dc --- /dev/null +++ b/src/lib/pear/PEAR/.depdb @@ -0,0 +1 @@ +a:3:{s:8:"_version";s:3:"1.0";s:12:"dependencies";a:1:{s:12:"pear.php.net";a:4:{s:4:"pear";a:9:{i:0;a:3:{s:3:"dep";a:5:{s:4:"name";s:11:"Archive_Tar";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:3:"1.1";s:11:"recommended";s:5:"1.3.2";s:7:"exclude";s:5:"1.3.0";}s:4:"type";s:8:"required";s:5:"group";b:0;}i:1;a:3:{s:3:"dep";a:4:{s:4:"name";s:16:"Structures_Graph";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:5:"1.0.2";s:11:"recommended";s:5:"1.0.2";}s:4:"type";s:8:"required";s:5:"group";b:0;}i:2;a:3:{s:3:"dep";a:4:{s:4:"name";s:14:"Console_Getopt";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:3:"1.2";s:11:"recommended";s:5:"1.2.3";}s:4:"type";s:8:"required";s:5:"group";b:0;}i:3;a:3:{s:3:"dep";a:4:{s:4:"name";s:17:"PEAR_Frontend_Web";s:7:"channel";s:12:"pear.php.net";s:3:"max";s:3:"0.4";s:9:"conflicts";s:0:"";}s:4:"type";s:8:"required";s:5:"group";b:0;}i:4;a:3:{s:3:"dep";a:5:{s:4:"name";s:17:"PEAR_Frontend_Gtk";s:7:"channel";s:12:"pear.php.net";s:3:"max";s:5:"0.4.0";s:7:"exclude";s:5:"0.4.0";s:9:"conflicts";s:0:"";}s:4:"type";s:8:"required";s:5:"group";b:0;}i:5;a:3:{s:3:"dep";a:3:{s:4:"name";s:7:"XML_RPC";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:5:"1.4.0";}s:4:"type";s:8:"optional";s:5:"group";b:0;}i:6;a:3:{s:3:"dep";a:3:{s:4:"name";s:17:"PEAR_Frontend_Web";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:5:"0.5.1";}s:4:"type";s:8:"optional";s:5:"group";s:12:"webinstaller";}i:7;a:3:{s:3:"dep";a:3:{s:4:"name";s:17:"PEAR_Frontend_Gtk";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:5:"0.4.0";}s:4:"type";s:8:"optional";s:5:"group";s:12:"gtkinstaller";}i:8;a:3:{s:3:"dep";a:2:{s:4:"name";s:18:"PEAR_Frontend_Gtk2";s:7:"channel";s:12:"pear.php.net";}s:4:"type";s:8:"optional";s:5:"group";s:13:"gtk2installer";}}s:17:"pear_frontend_web";a:2:{i:0;a:3:{s:3:"dep";a:2:{s:4:"name";s:16:"HTML_Template_IT";s:7:"channel";s:12:"pear.php.net";}s:4:"type";s:8:"required";s:5:"group";b:0;}i:1;a:3:{s:3:"dep";a:3:{s:4:"name";s:4:"PEAR";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:5:"1.6.1";}s:4:"type";s:8:"required";s:5:"group";b:0;}}s:6:"config";a:2:{i:0;a:3:{s:3:"dep";a:2:{s:4:"name";s:10:"XML_Parser";s:7:"channel";s:12:"pear.php.net";}s:4:"type";s:8:"optional";s:5:"group";b:0;}i:1;a:3:{s:3:"dep";a:2:{s:4:"name";s:8:"XML_Util";s:7:"channel";s:12:"pear.php.net";}s:4:"type";s:8:"optional";s:5:"group";b:0;}}s:9:"mime_type";a:2:{i:0;a:3:{s:3:"dep";a:3:{s:4:"name";s:4:"PEAR";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:5:"1.4.0";}s:4:"type";s:8:"required";s:5:"group";b:0;}i:1;a:3:{s:3:"dep";a:2:{s:4:"name";s:14:"System_Command";s:7:"channel";s:12:"pear.php.net";}s:4:"type";s:8:"optional";s:5:"group";b:0;}}}}s:8:"packages";a:1:{s:12:"pear.php.net";a:12:{s:11:"archive_tar";a:1:{i:0;a:2:{s:7:"channel";s:12:"pear.php.net";s:7:"package";s:4:"pear";}}s:16:"structures_graph";a:1:{i:0;a:2:{s:7:"channel";s:12:"pear.php.net";s:7:"package";s:4:"pear";}}s:14:"console_getopt";a:1:{i:0;a:2:{s:7:"channel";s:12:"pear.php.net";s:7:"package";s:4:"pear";}}s:17:"pear_frontend_web";a:1:{i:0;a:2:{s:7:"channel";s:12:"pear.php.net";s:7:"package";s:4:"pear";}}s:17:"pear_frontend_gtk";a:1:{i:0;a:2:{s:7:"channel";s:12:"pear.php.net";s:7:"package";s:4:"pear";}}s:7:"xml_rpc";a:1:{i:0;a:2:{s:7:"channel";s:12:"pear.php.net";s:7:"package";s:4:"pear";}}s:18:"pear_frontend_gtk2";a:1:{i:0;a:2:{s:7:"channel";s:12:"pear.php.net";s:7:"package";s:4:"pear";}}s:16:"html_template_it";a:1:{i:0;a:2:{s:7:"channel";s:12:"pear.php.net";s:7:"package";s:17:"pear_frontend_web";}}s:4:"pear";a:2:{i:0;a:2:{s:7:"channel";s:12:"pear.php.net";s:7:"package";s:17:"pear_frontend_web";}i:1;a:2:{s:7:"channel";s:12:"pear.php.net";s:7:"package";s:9:"mime_type";}}s:10:"xml_parser";a:1:{i:0;a:2:{s:7:"channel";s:12:"pear.php.net";s:7:"package";s:6:"config";}}s:8:"xml_util";a:1:{i:0;a:2:{s:7:"channel";s:12:"pear.php.net";s:7:"package";s:6:"config";}}s:14:"system_command";a:1:{i:0;a:2:{s:7:"channel";s:12:"pear.php.net";s:7:"package";s:9:"mime_type";}}}}} \ No newline at end of file diff --git a/src/lib/pear/PEAR/.depdblock b/src/lib/pear/PEAR/.depdblock new file mode 100644 index 0000000..e69de29 diff --git a/src/lib/pear/PEAR/.filemap b/src/lib/pear/PEAR/.filemap new file mode 100644 index 0000000..b50d599 --- /dev/null +++ b/src/lib/pear/PEAR/.filemap @@ -0,0 +1 @@ +a:5:{s:3:"php";a:127:{s:29:"FirePHPCore/FirePHP.class.php";a:2:{i:0;s:16:"pear.firephp.org";i:1;s:11:"firephpcore";}s:18:"FirePHPCore/fb.php";a:2:{i:0;s:16:"pear.firephp.org";i:1;s:11:"firephpcore";}s:27:"PEAR/Command/Categories.php";s:17:"pear_frontend_web";s:27:"PEAR/Command/Categories.xml";s:17:"pear_frontend_web";s:31:"PEAR/Frontend/Web/Docviewer.php";s:17:"pear_frontend_web";s:21:"PEAR/Frontend/Web.php";s:17:"pear_frontend_web";s:19:"pearfrontendweb.php";s:17:"pear_frontend_web";s:15:"Archive/Tar.php";s:11:"archive_tar";s:20:"HTML/Template/IT.php";s:16:"html_template_it";s:21:"HTML/Template/ITX.php";s:16:"html_template_it";s:26:"HTML/Template/IT_Error.php";s:16:"html_template_it";s:16:"XML/RPC/Dump.php";s:7:"xml_rpc";s:11:"XML/RPC.php";s:7:"xml_rpc";s:18:"XML/RPC/Server.php";s:7:"xml_rpc";s:25:"docs/examples/example.php";s:9:"mime_type";s:23:"MIME/Type/Parameter.php";s:9:"mime_type";s:23:"MIME/Type/Extension.php";s:9:"mime_type";s:13:"MIME/Type.php";s:9:"mime_type";s:44:"Structures/Graph/Manipulator/AcyclicTest.php";s:16:"structures_graph";s:50:"Structures/Graph/Manipulator/TopologicalSorter.php";s:16:"structures_graph";s:25:"Structures/Graph/Node.php";s:16:"structures_graph";s:20:"Structures/Graph.php";s:16:"structures_graph";s:12:"OS/Guess.php";s:4:"pear";s:27:"PEAR/ChannelFile/Parser.php";s:4:"pear";s:21:"PEAR/Command/Auth.xml";s:4:"pear";s:21:"PEAR/Command/Auth.php";s:4:"pear";s:22:"PEAR/Command/Build.xml";s:4:"pear";s:22:"PEAR/Command/Build.php";s:4:"pear";s:25:"PEAR/Command/Channels.xml";s:4:"pear";s:25:"PEAR/Command/Channels.php";s:4:"pear";s:23:"PEAR/Command/Common.php";s:4:"pear";s:23:"PEAR/Command/Config.xml";s:4:"pear";s:23:"PEAR/Command/Config.php";s:4:"pear";s:24:"PEAR/Command/Install.xml";s:4:"pear";s:24:"PEAR/Command/Install.php";s:4:"pear";s:23:"PEAR/Command/Mirror.xml";s:4:"pear";s:23:"PEAR/Command/Mirror.php";s:4:"pear";s:24:"PEAR/Command/Package.xml";s:4:"pear";s:24:"PEAR/Command/Package.php";s:4:"pear";s:23:"PEAR/Command/Pickle.xml";s:4:"pear";s:23:"PEAR/Command/Pickle.php";s:4:"pear";s:25:"PEAR/Command/Registry.xml";s:4:"pear";s:25:"PEAR/Command/Registry.php";s:4:"pear";s:23:"PEAR/Command/Remote.xml";s:4:"pear";s:23:"PEAR/Command/Remote.php";s:4:"pear";s:21:"PEAR/Command/Test.xml";s:4:"pear";s:21:"PEAR/Command/Test.php";s:4:"pear";s:27:"PEAR/Downloader/Package.php";s:4:"pear";s:21:"PEAR/Frontend/CLI.php";s:4:"pear";s:30:"PEAR/Installer/Role/Common.php";s:4:"pear";s:27:"PEAR/Installer/Role/Cfg.xml";s:4:"pear";s:27:"PEAR/Installer/Role/Cfg.php";s:4:"pear";s:28:"PEAR/Installer/Role/Data.xml";s:4:"pear";s:28:"PEAR/Installer/Role/Data.php";s:4:"pear";s:27:"PEAR/Installer/Role/Doc.xml";s:4:"pear";s:27:"PEAR/Installer/Role/Doc.php";s:4:"pear";s:27:"PEAR/Installer/Role/Ext.xml";s:4:"pear";s:27:"PEAR/Installer/Role/Ext.php";s:4:"pear";s:27:"PEAR/Installer/Role/Php.xml";s:4:"pear";s:27:"PEAR/Installer/Role/Php.php";s:4:"pear";s:30:"PEAR/Installer/Role/Script.xml";s:4:"pear";s:30:"PEAR/Installer/Role/Script.php";s:4:"pear";s:27:"PEAR/Installer/Role/Src.xml";s:4:"pear";s:27:"PEAR/Installer/Role/Src.php";s:4:"pear";s:28:"PEAR/Installer/Role/Test.xml";s:4:"pear";s:28:"PEAR/Installer/Role/Test.php";s:4:"pear";s:27:"PEAR/Installer/Role/Www.xml";s:4:"pear";s:27:"PEAR/Installer/Role/Www.php";s:4:"pear";s:23:"PEAR/Installer/Role.php";s:4:"pear";s:33:"PEAR/PackageFile/Generator/v1.php";s:4:"pear";s:33:"PEAR/PackageFile/Generator/v2.php";s:4:"pear";s:30:"PEAR/PackageFile/Parser/v1.php";s:4:"pear";s:30:"PEAR/PackageFile/Parser/v2.php";s:4:"pear";s:26:"PEAR/PackageFile/v2/rw.php";s:4:"pear";s:33:"PEAR/PackageFile/v2/Validator.php";s:4:"pear";s:23:"PEAR/PackageFile/v1.php";s:4:"pear";s:23:"PEAR/PackageFile/v2.php";s:4:"pear";s:16:"PEAR/REST/10.php";s:4:"pear";s:16:"PEAR/REST/11.php";s:4:"pear";s:16:"PEAR/REST/13.php";s:4:"pear";s:34:"PEAR/Task/Postinstallscript/rw.php";s:4:"pear";s:24:"PEAR/Task/Replace/rw.php";s:4:"pear";s:24:"PEAR/Task/Unixeol/rw.php";s:4:"pear";s:27:"PEAR/Task/Windowseol/rw.php";s:4:"pear";s:20:"PEAR/Task/Common.php";s:4:"pear";s:31:"PEAR/Task/Postinstallscript.php";s:4:"pear";s:21:"PEAR/Task/Replace.php";s:4:"pear";s:21:"PEAR/Task/Unixeol.php";s:4:"pear";s:24:"PEAR/Task/Windowseol.php";s:4:"pear";s:23:"PEAR/Validator/PECL.php";s:4:"pear";s:19:"PEAR/Autoloader.php";s:4:"pear";s:16:"PEAR/Builder.php";s:4:"pear";s:20:"PEAR/ChannelFile.php";s:4:"pear";s:16:"PEAR/Command.php";s:4:"pear";s:15:"PEAR/Common.php";s:4:"pear";s:15:"PEAR/Config.php";s:4:"pear";s:19:"PEAR/Dependency.php";s:4:"pear";s:21:"PEAR/DependencyDB.php";s:4:"pear";s:20:"PEAR/Dependency2.php";s:4:"pear";s:19:"PEAR/Downloader.php";s:4:"pear";s:19:"PEAR/ErrorStack.php";s:4:"pear";s:18:"PEAR/Exception.php";s:4:"pear";s:28:"PEAR/FixPHP5PEARWarnings.php";s:4:"pear";s:17:"PEAR/Frontend.php";s:4:"pear";s:18:"PEAR/Installer.php";s:4:"pear";s:20:"PEAR/PackageFile.php";s:4:"pear";s:17:"PEAR/Packager.php";s:4:"pear";s:17:"PEAR/Registry.php";s:4:"pear";s:15:"PEAR/Remote.php";s:4:"pear";s:13:"PEAR/REST.php";s:4:"pear";s:16:"PEAR/RunTest.php";s:4:"pear";s:17:"PEAR/Validate.php";s:4:"pear";s:18:"PEAR/XMLParser.php";s:4:"pear";s:19:"scripts/pearcmd.php";s:4:"pear";s:19:"scripts/peclcmd.php";s:4:"pear";s:8:"PEAR.php";s:4:"pear";s:10:"System.php";s:4:"pear";s:27:"Config/Container/Apache.php";s:6:"config";s:32:"Config/Container/GenericConf.php";s:6:"config";s:33:"Config/Container/IniCommented.php";s:6:"config";s:28:"Config/Container/IniFile.php";s:6:"config";s:29:"Config/Container/PHPArray.php";s:6:"config";s:33:"Config/Container/PHPConstants.php";s:6:"config";s:24:"Config/Container/XML.php";s:6:"config";s:20:"Config/Container.php";s:6:"config";s:10:"Config.php";s:6:"config";s:18:"Console/Getopt.php";s:14:"console_getopt";}s:4:"data";a:47:{s:42:"pear_frontend_web/data/images/category.jpg";s:17:"pear_frontend_web";s:40:"pear_frontend_web/data/images/config.gif";s:17:"pear_frontend_web";s:42:"pear_frontend_web/data/images/download.gif";s:17:"pear_frontend_web";s:39:"pear_frontend_web/data/images/error.gif";s:17:"pear_frontend_web";s:38:"pear_frontend_web/data/images/info.gif";s:17:"pear_frontend_web";s:42:"pear_frontend_web/data/images/infoplus.gif";s:17:"pear_frontend_web";s:46:"pear_frontend_web/data/images/install_fail.gif";s:17:"pear_frontend_web";s:41:"pear_frontend_web/data/images/install.gif";s:17:"pear_frontend_web";s:44:"pear_frontend_web/data/images/install_ok.gif";s:17:"pear_frontend_web";s:46:"pear_frontend_web/data/images/install_wait.gif";s:17:"pear_frontend_web";s:39:"pear_frontend_web/data/images/login.gif";s:17:"pear_frontend_web";s:40:"pear_frontend_web/data/images/logout.gif";s:17:"pear_frontend_web";s:40:"pear_frontend_web/data/images/manual.gif";s:17:"pear_frontend_web";s:44:"pear_frontend_web/data/images/manualplus.gif";s:17:"pear_frontend_web";s:41:"pear_frontend_web/data/images/package.jpg";s:17:"pear_frontend_web";s:43:"pear_frontend_web/data/images/pearsmall.gif";s:17:"pear_frontend_web";s:41:"pear_frontend_web/data/images/pkglist.png";s:17:"pear_frontend_web";s:43:"pear_frontend_web/data/images/pkgsearch.png";s:17:"pear_frontend_web";s:39:"pear_frontend_web/data/images/trash.gif";s:17:"pear_frontend_web";s:52:"pear_frontend_web/data/templates/bottom.inc.tpl.html";s:17:"pear_frontend_web";s:49:"pear_frontend_web/data/templates/caption.tpl.html";s:17:"pear_frontend_web";s:57:"pear_frontend_web/data/templates/categories.list.tpl.html";s:17:"pear_frontend_web";s:54:"pear_frontend_web/data/templates/channel.list.tpl.html";s:17:"pear_frontend_web";s:47:"pear_frontend_web/data/templates/error.tpl.html";s:17:"pear_frontend_web";s:52:"pear_frontend_web/data/templates/footer.inc.tpl.html";s:17:"pear_frontend_web";s:66:"pear_frontend_web/data/templates/generic_table_horizontal.tpl.html";s:17:"pear_frontend_web";s:64:"pear_frontend_web/data/templates/generic_table_vertical.tpl.html";s:17:"pear_frontend_web";s:52:"pear_frontend_web/data/templates/header.inc.tpl.html";s:17:"pear_frontend_web";s:46:"pear_frontend_web/data/templates/info.tpl.html";s:17:"pear_frontend_web";s:54:"pear_frontend_web/data/templates/package.info.tpl.html";s:17:"pear_frontend_web";s:60:"pear_frontend_web/data/templates/package.list_nocat.tpl.html";s:17:"pear_frontend_web";s:54:"pear_frontend_web/data/templates/package.list.tpl.html";s:17:"pear_frontend_web";s:58:"pear_frontend_web/data/templates/package.manually.tpl.html";s:17:"pear_frontend_web";s:57:"pear_frontend_web/data/templates/package.submenu.tpl.html";s:17:"pear_frontend_web";s:48:"pear_frontend_web/data/templates/search.tpl.html";s:17:"pear_frontend_web";s:57:"pear_frontend_web/data/templates/tableofchannels.tpl.html";s:17:"pear_frontend_web";s:49:"pear_frontend_web/data/templates/top.inc.tpl.html";s:17:"pear_frontend_web";s:53:"pear_frontend_web/data/templates/upgrade_all.tpl.html";s:17:"pear_frontend_web";s:52:"pear_frontend_web/data/templates/userDialog.tpl.html";s:17:"pear_frontend_web";s:33:"pear_frontend_web/data/package.js";s:17:"pear_frontend_web";s:32:"pear_frontend_web/data/style.css";s:17:"pear_frontend_web";s:34:"structures_graph/genpackage.xml.pl";s:16:"structures_graph";s:24:"structures_graph/LICENSE";s:16:"structures_graph";s:27:"structures_graph/package.sh";s:16:"structures_graph";s:27:"structures_graph/publish.sh";s:16:"structures_graph";s:16:"pear/package.dtd";s:4:"pear";s:18:"pear/template.spec";s:4:"pear";}s:3:"doc";a:37:{s:36:"pear_frontend_web/docs/index.php.txt";s:17:"pear_frontend_web";s:34:"pear_frontend_web/docs/example.php";s:17:"pear_frontend_web";s:31:"pear_frontend_web/docs/htaccess";s:17:"pear_frontend_web";s:24:"pear_frontend_web/README";s:17:"pear_frontend_web";s:32:"archive_tar/docs/Archive_Tar.txt";s:11:"archive_tar";s:24:"html_template_it/LICENSE";s:16:"html_template_it";s:39:"html_template_it/examples/sample_it.php";s:16:"html_template_it";s:53:"html_template_it/examples/sample_itx_addblockfile.php";s:16:"html_template_it";s:48:"html_template_it/examples/templates/main.tpl.htm";s:16:"html_template_it";s:61:"html_template_it/examples/templates/addblockfile_list.tpl.htm";s:16:"html_template_it";s:61:"html_template_it/examples/templates/addblockfile_main.tpl.htm";s:16:"html_template_it";s:43:"structures_graph/docs/html/media/banner.css";s:16:"structures_graph";s:47:"structures_graph/docs/html/media/stylesheet.css";s:16:"structures_graph";s:65:"structures_graph/docs/html/Structures_Graph/Structures_Graph.html";s:16:"structures_graph";s:89:"structures_graph/docs/html/Structures_Graph/Structures_Graph_Manipulator_AcyclicTest.html";s:16:"structures_graph";s:95:"structures_graph/docs/html/Structures_Graph/Structures_Graph_Manipulator_TopologicalSorter.html";s:16:"structures_graph";s:70:"structures_graph/docs/html/Structures_Graph/Structures_Graph_Node.html";s:16:"structures_graph";s:78:"structures_graph/docs/html/Structures_Graph/tutorial_Structures_Graph.pkg.html";s:16:"structures_graph";s:94:"structures_graph/docs/html/Structures_Graph/_Structures_Graph_Manipulator_AcyclicTest_php.html";s:16:"structures_graph";s:100:"structures_graph/docs/html/Structures_Graph/_Structures_Graph_Manipulator_TopologicalSorter_php.html";s:16:"structures_graph";s:75:"structures_graph/docs/html/Structures_Graph/_Structures_Graph_Node_php.html";s:16:"structures_graph";s:70:"structures_graph/docs/html/Structures_Graph/_Structures_Graph_php.html";s:16:"structures_graph";s:59:"structures_graph/docs/html/classtrees_Structures_Graph.html";s:16:"structures_graph";s:44:"structures_graph/docs/html/elementindex.html";s:16:"structures_graph";s:61:"structures_graph/docs/html/elementindex_Structures_Graph.html";s:16:"structures_graph";s:38:"structures_graph/docs/html/errors.html";s:16:"structures_graph";s:37:"structures_graph/docs/html/index.html";s:16:"structures_graph";s:51:"structures_graph/docs/html/li_Structures_Graph.html";s:16:"structures_graph";s:40:"structures_graph/docs/html/packages.html";s:16:"structures_graph";s:40:"structures_graph/docs/html/todolist.html";s:16:"structures_graph";s:69:"structures_graph/docs/tutorials/Structures_Graph/Structures_Graph.pkg";s:16:"structures_graph";s:33:"structures_graph/docs/generate.sh";s:16:"structures_graph";s:12:"pear/INSTALL";s:4:"pear";s:11:"pear/README";s:4:"pear";s:22:"config/docs/Apache.php";s:6:"config";s:28:"config/docs/IniCommented.php";s:6:"config";s:30:"config/docs/IniFromScratch.php";s:6:"config";}s:4:"test";a:62:{s:46:"html_template_it/tests/templates/addblock.html";s:16:"html_template_it";s:52:"html_template_it/tests/templates/blockiteration.html";s:16:"html_template_it";s:44:"html_template_it/tests/templates/blocks.html";s:16:"html_template_it";s:45:"html_template_it/tests/templates/globals.html";s:16:"html_template_it";s:47:"html_template_it/tests/templates/__include.html";s:16:"html_template_it";s:45:"html_template_it/tests/templates/include.html";s:16:"html_template_it";s:54:"html_template_it/tests/templates/loadtemplatefile.html";s:16:"html_template_it";s:50:"html_template_it/tests/templates/replaceblock.html";s:16:"html_template_it";s:47:"html_template_it/tests/Console_TestListener.php";s:16:"html_template_it";s:42:"html_template_it/tests/IT_api_testcase.php";s:16:"html_template_it";s:44:"html_template_it/tests/IT_usage_testcase.php";s:16:"html_template_it";s:43:"html_template_it/tests/ITX_api_testcase.php";s:16:"html_template_it";s:45:"html_template_it/tests/ITX_usage_testcase.php";s:16:"html_template_it";s:31:"html_template_it/tests/test.php";s:16:"html_template_it";s:24:"xml_rpc/tests/allgot.inc";s:7:"xml_rpc";s:36:"xml_rpc/tests/empty-value-struct.php";s:7:"xml_rpc";s:29:"xml_rpc/tests/empty-value.php";s:7:"xml_rpc";s:29:"xml_rpc/tests/extra-lines.php";s:7:"xml_rpc";s:27:"xml_rpc/tests/protoport.php";s:7:"xml_rpc";s:27:"xml_rpc/tests/test_Dump.php";s:7:"xml_rpc";s:23:"xml_rpc/tests/types.php";s:7:"xml_rpc";s:33:"mime_type/tests/files/example.bmp";s:9:"mime_type";s:33:"mime_type/tests/files/example.gif";s:9:"mime_type";s:33:"mime_type/tests/files/example.jpg";s:9:"mime_type";s:33:"mime_type/tests/files/example.png";s:9:"mime_type";s:33:"mime_type/tests/files/example.txt";s:9:"mime_type";s:37:"mime_type/tests/files/example.txt.bz2";s:9:"mime_type";s:36:"mime_type/tests/files/example.txt.gz";s:9:"mime_type";s:28:"mime_type/tests/AllTests.php";s:9:"mime_type";s:28:"mime_type/tests/TypeTest.php";s:9:"mime_type";s:43:"mime_type/tests/MIME_Type_ExtensionTest.php";s:9:"mime_type";s:46:"structures_graph/tests/testCase/BasicGraph.php";s:16:"structures_graph";s:36:"structures_graph/tests/all-tests.php";s:16:"structures_graph";s:29:"structures_graph/tests/README";s:16:"structures_graph";s:23:"config/test/bug2742.ini";s:6:"config";s:24:"config/test/bug2742.phpt";s:6:"config";s:24:"config/test/bug2780.phpt";s:6:"config";s:24:"config/test/bug3051.phpt";s:6:"config";s:23:"config/test/bug3051.xml";s:6:"config";s:24:"config/test/bug3137.phpt";s:6:"config";s:24:"config/test/bug3298.phpt";s:6:"config";s:23:"config/test/bug3298.xml";s:6:"config";s:23:"config/test/bug3398.ini";s:6:"config";s:24:"config/test/bug3398.phpt";s:6:"config";s:29:"config/test/bug3590-input.php";s:6:"config";s:24:"config/test/bug3590.phpt";s:6:"config";s:24:"config/test/bug4623.conf";s:6:"config";s:24:"config/test/bug4623.phpt";s:6:"config";s:23:"config/test/bug6441.ini";s:6:"config";s:24:"config/test/bug6441.phpt";s:6:"config";s:37:"config/test/bug7544-inicommented.phpt";s:6:"config";s:32:"config/test/bug7544-inifile.phpt";s:6:"config";s:23:"config/test/bug7544.ini";s:6:"config";s:24:"config/test/bug7652.phpt";s:6:"config";s:23:"config/test/bug7652.xml";s:6:"config";s:37:"config/test/bug8357-inicommented.phpt";s:6:"config";s:32:"config/test/bug8357-inifile.phpt";s:6:"config";s:23:"config/test/bug8357.ini";s:6:"config";s:25:"config/test/bug10010.phpt";s:6:"config";s:25:"config/test/bug10185.phpt";s:6:"config";s:29:"config/test/phpt_test.php.inc";s:6:"config";s:25:"config/test/setup.php.inc";s:6:"config";}s:6:"script";a:3:{s:15:"scripts/pear.sh";s:4:"pear";s:18:"scripts/peardev.sh";s:4:"pear";s:15:"scripts/pecl.sh";s:4:"pear";}} \ No newline at end of file diff --git a/src/lib/pear/PEAR/.lock b/src/lib/pear/PEAR/.lock new file mode 100644 index 0000000..e69de29 diff --git a/src/lib/pear/PEAR/.registry/.channel.pear.firephp.org/firephpcore.reg b/src/lib/pear/PEAR/.registry/.channel.pear.firephp.org/firephpcore.reg new file mode 100644 index 0000000..6f45c29 --- /dev/null +++ b/src/lib/pear/PEAR/.registry/.channel.pear.firephp.org/firephpcore.reg @@ -0,0 +1 @@ +a:21:{s:7:"attribs";a:6:{s:15:"packagerversion";s:5:"1.7.1";s:7:"version";s:3:"2.0";s:5:"xmlns";s:35:"http://pear.php.net/dtd/package-2.0";s:11:"xmlns:tasks";s:33:"http://pear.php.net/dtd/tasks-1.0";s:9:"xmlns:xsi";s:41:"http://www.w3.org/2001/XMLSchema-instance";s:18:"xsi:schemaLocation";s:192:"http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd";}s:4:"name";s:11:"FirePHPCore";s:7:"channel";s:16:"pear.firephp.org";s:7:"summary";s:38:"Core feature and communication library";s:11:"description";s:145:"Handles all communication between the PHP code on the server and the FirePHP Firefox client extension. Also implements all core FirePHP features.";s:4:"lead";a:4:{s:4:"name";s:14:"Christoph Dorn";s:4:"user";s:6:"cadorn";s:5:"email";s:27:"christoph@christophdorn.com";s:6:"active";s:3:"yes";}s:4:"date";s:10:"2008-11-09";s:4:"time";s:8:"21:19:17";s:7:"version";a:2:{s:7:"release";s:5:"0.2.1";s:3:"api";s:3:"0.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";s:7:"New BSD";s:5:"notes";s:8:"No Notes";s:8:"contents";a:1:{s:3:"dir";a:2:{s:7:"attribs";a:2:{s:14:"baseinstalldir";s:11:"FirePHPCore";s:4:"name";s:1:"/";}s:4:"file";a:2:{i:0;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:11:"FirePHPCore";s:6:"md5sum";s:32:"fe3629adf23035ccf5e8231a2c025da3";s:4:"name";s:17:"FirePHP.class.php";s:4:"role";s:3:"php";}}i:1;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:11:"FirePHPCore";s:6:"md5sum";s:32:"dc54b628d8c101ce4a0968ecb2032121";s:4:"name";s:6:"fb.php";s:4:"role";s:3:"php";}}}}}s:12:"dependencies";a:1:{s:8:"required";a:2:{s:3:"php";a:1:{s:3:"min";s:3:"5.2";}s:13:"pearinstaller";a:1:{s:3:"min";s:5:"1.4.5";}}}s:10:"phprelease";s:0:"";s:8:"filelist";a:2:{s:17:"FirePHP.class.php";a:5:{s:14:"baseinstalldir";s:11:"FirePHPCore";s:6:"md5sum";s:32:"fe3629adf23035ccf5e8231a2c025da3";s:4:"name";s:17:"FirePHP.class.php";s:4:"role";s:3:"php";s:12:"installed_as";s:64:"/www/htdocs/w00acdb0/lib/pear/PEAR/FirePHPCore/FirePHP.class.php";}s:6:"fb.php";a:5:{s:14:"baseinstalldir";s:11:"FirePHPCore";s:6:"md5sum";s:32:"dc54b628d8c101ce4a0968ecb2032121";s:4:"name";s:6:"fb.php";s:4:"role";s:3:"php";s:12:"installed_as";s:53:"/www/htdocs/w00acdb0/lib/pear/PEAR/FirePHPCore/fb.php";}}s:12:"_lastversion";N;s:7:"dirtree";a:1:{s:46:"/www/htdocs/w00acdb0/lib/pear/PEAR/FirePHPCore";b:1;}s:3:"old";a:7:{s:7:"version";s:5:"0.2.1";s:12:"release_date";s:10:"2008-11-09";s:13:"release_state";s:6:"stable";s:15:"release_license";s:7:"New BSD";s:13:"release_notes";s:8:"No Notes";s:12:"release_deps";a:2:{i:0;a:4:{s:4:"type";s:3:"php";s:3:"rel";s:2:"ge";s:7:"version";s:3:"5.2";s:8:"optional";s:2:"no";}i:1;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:4:"PEAR";s:3:"rel";s:2:"ge";s:7:"version";s:5:"1.4.5";s:8:"optional";s:2:"no";}}s:11:"maintainers";a:1:{i:0;a:5:{s:4:"name";s:14:"Christoph Dorn";s:5:"email";s:27:"christoph@christophdorn.com";s:6:"active";s:3:"yes";s:6:"handle";s:6:"cadorn";s:4:"role";s:4:"lead";}}}s:10:"xsdversion";s:3:"2.0";s:13:"_lastmodified";i:1234656556;} \ No newline at end of file diff --git a/src/lib/pear/PEAR/.registry/archive_tar.reg b/src/lib/pear/PEAR/.registry/archive_tar.reg new file mode 100644 index 0000000..e30451b --- /dev/null +++ b/src/lib/pear/PEAR/.registry/archive_tar.reg @@ -0,0 +1,22 @@ +a:24:{s:7:"attribs";a:6:{s:15:"packagerversion";s:8:"1.5.0RC2";s:7:"version";s:3:"2.0";s:5:"xmlns";s:35:"http://pear.php.net/dtd/package-2.0";s:11:"xmlns:tasks";s:33:"http://pear.php.net/dtd/tasks-1.0";s:9:"xmlns:xsi";s:41:"http://www.w3.org/2001/XMLSchema-instance";s:18:"xsi:schemaLocation";s:147:"http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd";}s:4:"name";s:11:"Archive_Tar";s:7:"channel";s:12:"pear.php.net";s:7:"summary";s:25:"Tar file management class";s:11:"description";s:257:"This class provides handling of tar files in PHP. +It supports creating, listing, extracting and adding to tar files. +Gzip support is available if PHP has the zlib extension built-in or +loaded. Bz2 compression is also supported with the bz2 extension loaded.";s:4:"lead";a:2:{i:0;a:4:{s:4:"name";s:14:"Gregory Beaver";s:4:"user";s:6:"cellog";s:5:"email";s:14:"cellog@php.net";s:6:"active";s:3:"yes";}i:1;a:4:{s:4:"name";s:14:"Vincent Blavet";s:4:"user";s:7:"vblavet";s:5:"email";s:22:"vincent@phpconcept.net";s:6:"active";s:2:"no";}}s:6:"helper";a:4:{s:4:"name";s:11:"Stig Bakken";s:4:"user";s:3:"ssb";s:5:"email";s:12:"stig@php.net";s:6:"active";s:2:"no";}s:4:"date";s:10:"2007-01-03";s:4:"time";s:8:"15:31:40";s:7:"version";a:2:{s:7:"release";s:5:"1.3.2";s:3:"api";s:5:"1.3.2";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:485:"Correct Bug #4016 +Remove duplicate remove error display with '@' +Correct Bug #3909 : Check existence of OS_WINDOWS constant +Correct Bug #5452 fix for "lone zero block" when untarring packages +Change filemode (from pear-core/Archive/Tar.php v.1.21) +Correct Bug #6486 Can not extract symlinks +Correct Bug #6933 Archive_Tar (Tar file management class) Directory traversal +Correct Bug #8114 Files added on-the-fly not storing date +Correct Bug #9352 Bug on _dirCheck function over nfs path";s:8:"contents";a:1:{s:3:"dir";a:2:{s:7:"attribs";a:1:{s:4:"name";s:1:"/";}s:4:"file";a:2:{i:0;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"06409d39f4268a9aa9e2924c7f397a38";s:4:"name";s:15:"Archive/Tar.php";s:4:"role";s:3:"php";}}i:1;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"29b03715377b18b1fafcff98a99cc9a7";s:4:"name";s:20:"docs/Archive_Tar.txt";s:4:"role";s:3:"doc";}}}}}s:10:"compatible";a:4:{s:4:"name";s:4:"PEAR";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:5:"1.4.0";s:3:"max";s:8:"1.5.0RC2";}s:12:"dependencies";a:1:{s:8:"required";a:2:{s:3:"php";a:1:{s:3:"min";s:5:"4.0.0";}s:13:"pearinstaller";a:1:{s:3:"min";s:7:"1.4.0b1";}}}s:10:"phprelease";s:0:"";s:9:"changelog";a:1:{s:7:"release";a:10:{i:0;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.3.1";s:3:"api";s:5:"1.3.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2005-03-17";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:17:"Correct Bug #3855";}i:1;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.3.0";s:3:"api";s:5:"1.3.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2005-03-06";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:40:"Bugs correction (2475, 2488, 2135, 2176)";}i:2;a:5:{s:7:"version";a:2:{s:7:"release";s:3:"1.2";s:3:"api";s:3:"1.2";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2004-05-08";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:71:"Add support for other separator than the space char and bug + correction";}i:3;a:5:{s:7:"version";a:2:{s:7:"release";s:3:"1.1";s:3:"api";s:3:"1.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2003-05-28";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:141:"* Add support for BZ2 compression +* Add support for add and extract without using temporary files : methods addString() and extractInString()";}i:4;a:5:{s:7:"version";a:2:{s:7:"release";s:3:"1.0";s:3:"api";s:3:"1.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2003-01-24";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:23:"Change status to stable";}i:5;a:5:{s:7:"version";a:2:{s:7:"release";s:7:"0.10-b1";s:3:"api";s:7:"0.10-b1";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:4:"beta";}s:4:"date";s:10:"2003-01-08";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:59:"Add support for long filenames (greater than 99 characters)";}i:6;a:5:{s:7:"version";a:2:{s:7:"release";s:3:"0.9";s:3:"api";s:3:"0.9";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2002-05-27";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:25:"Auto-detect gzip'ed files";}i:7;a:5:{s:7:"version";a:2:{s:7:"release";s:3:"0.4";s:3:"api";s:3:"0.4";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2002-05-20";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:51:"Windows bugfix: use forward slashes inside archives";}i:8;a:5:{s:7:"version";a:2:{s:7:"release";s:3:"0.2";s:3:"api";s:3:"0.2";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2002-02-18";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:29:"From initial commit to stable";}i:9;a:5:{s:7:"version";a:2:{s:7:"release";s:3:"0.3";s:3:"api";s:3:"0.3";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2002-04-13";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:47:"Windows bugfix: used wrong directory separators";}}}s:8:"filelist";a:2:{s:15:"Archive/Tar.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"06409d39f4268a9aa9e2924c7f397a38";s:4:"name";s:15:"Archive/Tar.php";s:4:"role";s:3:"php";s:12:"installed_as";s:50:"/www/htdocs/w00acdb0/lib/pear/PEAR/Archive/Tar.php";}s:20:"docs/Archive_Tar.txt";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"29b03715377b18b1fafcff98a99cc9a7";s:4:"name";s:20:"docs/Archive_Tar.txt";s:4:"role";s:3:"doc";s:12:"installed_as";s:72:"/www/htdocs/w00acdb0/lib/pear/PEAR/docs/Archive_Tar/docs/Archive_Tar.txt";}}s:12:"_lastversion";N;s:7:"dirtree";a:3:{s:42:"/www/htdocs/w00acdb0/lib/pear/PEAR/Archive";b:1;s:56:"/www/htdocs/w00acdb0/lib/pear/PEAR/docs/Archive_Tar/docs";b:1;s:51:"/www/htdocs/w00acdb0/lib/pear/PEAR/docs/Archive_Tar";b:1;}s:3:"old";a:7:{s:7:"version";s:5:"1.3.2";s:12:"release_date";s:10:"2007-01-03";s:13:"release_state";s:6:"stable";s:15:"release_license";s:11:"PHP License";s:13:"release_notes";s:485:"Correct Bug #4016 +Remove duplicate remove error display with '@' +Correct Bug #3909 : Check existence of OS_WINDOWS constant +Correct Bug #5452 fix for "lone zero block" when untarring packages +Change filemode (from pear-core/Archive/Tar.php v.1.21) +Correct Bug #6486 Can not extract symlinks +Correct Bug #6933 Archive_Tar (Tar file management class) Directory traversal +Correct Bug #8114 Files added on-the-fly not storing date +Correct Bug #9352 Bug on _dirCheck function over nfs path";s:12:"release_deps";a:2:{i:0;a:4:{s:4:"type";s:3:"php";s:3:"rel";s:2:"ge";s:7:"version";s:5:"4.0.0";s:8:"optional";s:2:"no";}i:1;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:4:"PEAR";s:3:"rel";s:2:"ge";s:7:"version";s:7:"1.4.0b1";s:8:"optional";s:2:"no";}}s:11:"maintainers";a:3:{i:0;a:5:{s:4:"name";s:14:"Gregory Beaver";s:5:"email";s:14:"cellog@php.net";s:6:"active";s:3:"yes";s:6:"handle";s:6:"cellog";s:4:"role";s:4:"lead";}i:1;a:5:{s:4:"name";s:14:"Vincent Blavet";s:5:"email";s:22:"vincent@phpconcept.net";s:6:"active";s:2:"no";s:6:"handle";s:7:"vblavet";s:4:"role";s:4:"lead";}i:2;a:5:{s:4:"name";s:11:"Stig Bakken";s:5:"email";s:12:"stig@php.net";s:6:"active";s:2:"no";s:6:"handle";s:3:"ssb";s:4:"role";s:6:"helper";}}}s:10:"xsdversion";s:3:"2.0";s:13:"_lastmodified";i:1234655681;} \ No newline at end of file diff --git a/src/lib/pear/PEAR/.registry/config.reg b/src/lib/pear/PEAR/.registry/config.reg new file mode 100644 index 0000000..874c5ef --- /dev/null +++ b/src/lib/pear/PEAR/.registry/config.reg @@ -0,0 +1,94 @@ +a:23:{s:7:"attribs";a:6:{s:15:"packagerversion";s:5:"1.5.4";s:7:"version";s:3:"2.0";s:5:"xmlns";s:35:"http://pear.php.net/dtd/package-2.0";s:11:"xmlns:tasks";s:33:"http://pear.php.net/dtd/tasks-1.0";s:9:"xmlns:xsi";s:41:"http://www.w3.org/2001/XMLSchema-instance";s:18:"xsi:schemaLocation";s:147:"http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd";}s:4:"name";s:6:"Config";s:7:"channel";s:12:"pear.php.net";s:7:"summary";s:38:"Your configuration's swiss-army knife.";s:11:"description";s:394:"The Config package provides methods for configuration manipulation. +* Creates configurations from scratch +* Parses and outputs different formats (XML, PHP, INI, Apache...) +* Edits existing configurations +* Converts configurations to other formats +* Allows manipulation of sections, comments, directives... +* Parses configurations into a tree structure +* Provides XPath like access to directives";s:4:"lead";a:3:{i:0;a:4:{s:4:"name";s:16:"Bertrand Mansion";s:4:"user";s:7:"mansion";s:5:"email";s:20:"bmansion@mamasam.com";s:6:"active";s:2:"no";}i:1;a:4:{s:4:"name";s:9:"Ryan King";s:4:"user";s:9:"ryansking";s:5:"email";s:17:"ryansking@php.net";s:6:"active";s:2:"no";}i:2;a:4:{s:4:"name";s:11:"Adam Ashley";s:4:"user";s:7:"aashley";s:5:"email";s:15:"aashley@php.net";s:6:"active";s:3:"yes";}}s:9:"developer";a:4:{s:4:"name";s:11:"Adam Harvey";s:4:"user";s:7:"aharvey";s:5:"email";s:15:"aharvey@php.net";s:6:"active";s:3:"yes";}s:4:"date";s:10:"2007-06-12";s:4:"time";s:8:"05:29:14";s:7:"version";a:2:{s:7:"release";s:7:"1.10.11";s:3:"api";s:6:"1.10.8";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:149:"* Fixed Bug #11184: Knock on problems from fix for Bug #10185. Thanks to + Thomas Despoix and Carsten Wiedmann for helping me understand it properly.";s:8:"contents";a:1:{s:3:"dir";a:2:{s:7:"attribs";a:1:{s:4:"name";s:1:"/";}s:4:"file";a:40:{i:0;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"24c8aa0428acef34c3941da6e316ee64";s:4:"name";s:27:"Config/Container/Apache.php";s:4:"role";s:3:"php";}}i:1;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"97334aef3975512fe8820dd0577ec135";s:4:"name";s:32:"Config/Container/GenericConf.php";s:4:"role";s:3:"php";}}i:2;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"cea4ff38f7e4240e2c999be4aa1854e6";s:4:"name";s:33:"Config/Container/IniCommented.php";s:4:"role";s:3:"php";}}i:3;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"33e8495e6c8da599248193bf66f3b479";s:4:"name";s:28:"Config/Container/IniFile.php";s:4:"role";s:3:"php";}}i:4;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"86ddfaabf01eb9cb3d21e8afb5022930";s:4:"name";s:29:"Config/Container/PHPArray.php";s:4:"role";s:3:"php";}}i:5;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5754e39e081433aaf132c64db676a163";s:4:"name";s:33:"Config/Container/PHPConstants.php";s:4:"role";s:3:"php";}}i:6;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"957cbd88a70e34e94ed65ab7d3df5d7d";s:4:"name";s:24:"Config/Container/XML.php";s:4:"role";s:3:"php";}}i:7;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5cb17578402b866ed080a8e77a8a9a9b";s:4:"name";s:20:"Config/Container.php";s:4:"role";s:3:"php";}}i:8;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3f258a90dbd6371c52337d83e763bdb8";s:4:"name";s:15:"docs/Apache.php";s:4:"role";s:3:"doc";}}i:9;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"702edcddaf83d81196433887fa383a09";s:4:"name";s:21:"docs/IniCommented.php";s:4:"role";s:3:"doc";}}i:10;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"bce55b10d2e5ffef5a4a04aba92851ce";s:4:"name";s:23:"docs/IniFromScratch.php";s:4:"role";s:3:"doc";}}i:11;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d77a133b013cdc9794d0f6e09b6b88d1";s:4:"name";s:16:"test/bug2742.ini";s:4:"role";s:4:"test";}}i:12;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1c00244cdc36cff6960e394f1746c86d";s:4:"name";s:17:"test/bug2742.phpt";s:4:"role";s:4:"test";}}i:13;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a750197af925dcfbe4f30d493f43896d";s:4:"name";s:17:"test/bug2780.phpt";s:4:"role";s:4:"test";}}i:14;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"756ac177b9281c16a54d5beabe5ece9b";s:4:"name";s:17:"test/bug3051.phpt";s:4:"role";s:4:"test";}}i:15;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"61064633ed23cbec0f706fde3751a3e4";s:4:"name";s:16:"test/bug3051.xml";s:4:"role";s:4:"test";}}i:16;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ebe9d890f041a26b0a37f4b97355a7fd";s:4:"name";s:17:"test/bug3137.phpt";s:4:"role";s:4:"test";}}i:17;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2935e7e4362eca07908f005e92683460";s:4:"name";s:17:"test/bug3298.phpt";s:4:"role";s:4:"test";}}i:18;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7d577265dcdecebc67dee5118268ace5";s:4:"name";s:16:"test/bug3298.xml";s:4:"role";s:4:"test";}}i:19;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2b36a2cc7b70a10d13799c116a5536bb";s:4:"name";s:16:"test/bug3398.ini";s:4:"role";s:4:"test";}}i:20;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"373109b53b1b5129f68c7b81aa31f297";s:4:"name";s:17:"test/bug3398.phpt";s:4:"role";s:4:"test";}}i:21;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"08ec9d9f4649fefda49b1991d3fb20b1";s:4:"name";s:22:"test/bug3590-input.php";s:4:"role";s:4:"test";}}i:22;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"164099132d1dedf4ac03b3f4a5afba19";s:4:"name";s:17:"test/bug3590.phpt";s:4:"role";s:4:"test";}}i:23;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ad05c4a11c5b08b25488aab6248192a7";s:4:"name";s:17:"test/bug4623.conf";s:4:"role";s:4:"test";}}i:24;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9a8c732b18ec989dbf90c00bba4e0c55";s:4:"name";s:17:"test/bug4623.phpt";s:4:"role";s:4:"test";}}i:25;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f6fec7ec6187f591c51fc7b09130da7d";s:4:"name";s:16:"test/bug6441.ini";s:4:"role";s:4:"test";}}i:26;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7e9519b6ccfa0b8a3e369023add3ead1";s:4:"name";s:17:"test/bug6441.phpt";s:4:"role";s:4:"test";}}i:27;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8a3b57b2ae8d47ee78056b99e620c282";s:4:"name";s:30:"test/bug7544-inicommented.phpt";s:4:"role";s:4:"test";}}i:28;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"db33c7454539f9fbc02897f5de2b90b2";s:4:"name";s:25:"test/bug7544-inifile.phpt";s:4:"role";s:4:"test";}}i:29;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8aa8d748b9266e30028e75889ed5ff0c";s:4:"name";s:16:"test/bug7544.ini";s:4:"role";s:4:"test";}}i:30;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b293dee5fc7a375dbf72fae9b3d65bca";s:4:"name";s:17:"test/bug7652.phpt";s:4:"role";s:4:"test";}}i:31;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3fcbdf4ceabeca34357cfcd3266e5e6d";s:4:"name";s:16:"test/bug7652.xml";s:4:"role";s:4:"test";}}i:32;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"db3a27af6cf7afbeafb56e55ba63e601";s:4:"name";s:30:"test/bug8357-inicommented.phpt";s:4:"role";s:4:"test";}}i:33;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"68f5313a4cb289711453a2561ba1645a";s:4:"name";s:25:"test/bug8357-inifile.phpt";s:4:"role";s:4:"test";}}i:34;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"23285375454662259e5821eb991d124d";s:4:"name";s:16:"test/bug8357.ini";s:4:"role";s:4:"test";}}i:35;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e9ab76a4d81cc67d98aec18c049e93c0";s:4:"name";s:18:"test/bug10010.phpt";s:4:"role";s:4:"test";}}i:36;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"39174eaab97f7c97ac56dc8c99396947";s:4:"name";s:18:"test/bug10185.phpt";s:4:"role";s:4:"test";}}i:37;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"85a595db7562821ef50297502a50317b";s:4:"name";s:22:"test/phpt_test.php.inc";s:4:"role";s:4:"test";}}i:38;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1dce06e33ccfa8f55463450db8b4d365";s:4:"name";s:18:"test/setup.php.inc";s:4:"role";s:4:"test";}}i:39;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"a664418fa43875d263b20e611e4edee2";s:4:"name";s:10:"Config.php";s:4:"role";s:3:"php";}}}}}s:12:"dependencies";a:2:{s:8:"required";a:2:{s:3:"php";a:1:{s:3:"min";s:5:"4.3.0";}s:13:"pearinstaller";a:1:{s:3:"min";s:7:"1.4.0b1";}}s:8:"optional";a:1:{s:7:"package";a:2:{i:0;a:2:{s:4:"name";s:10:"XML_Parser";s:7:"channel";s:12:"pear.php.net";}i:1;a:2:{s:4:"name";s:8:"XML_Util";s:7:"channel";s:12:"pear.php.net";}}}}s:10:"phprelease";s:0:"";s:9:"changelog";a:1:{s:7:"release";a:27:{i:0;a:6:{s:4:"date";s:10:"2007-03-26";s:4:"time";s:8:"22:03:06";s:7:"version";a:2:{s:7:"release";s:7:"1.10.10";s:3:"api";s:6:"1.10.8";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:144:"* Fix Bug #10010: numeric index lost when parsing subarrays +* Fix Bug #10185: problem with addslashs in container "PHPArray" / method "toString"";}i:1;a:6:{s:4:"date";s:10:"2006-12-22";s:4:"time";s:8:"09:00:00";s:7:"version";a:2:{s:7:"release";s:6:"1.10.9";s:3:"api";s:6:"1.10.8";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:113:"* Fixed Bug #9632: PHPConstants container not registered. Thanks to + Clemens Lang ";}i:2;a:6:{s:4:"date";s:10:"2006-11-10";s:4:"time";s:8:"09:00:00";s:7:"version";a:2:{s:7:"release";s:6:"1.10.8";s:3:"api";s:6:"1.10.8";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:65:"* Fixed Bug #7097: writeConfig incorrect when root has attributes";}i:3;a:6:{s:4:"date";s:10:"2006-10-20";s:4:"time";s:8:"03:23:43";s:7:"version";a:2:{s:7:"release";s:9:"1.10.8RC1";s:3:"api";s:6:"1.10.8";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:178:"* Fixed Bug #7097: writeConfig incorrect when root has attributes + This fix has the potential to break other things as it is a big change to the + PHPArray backend. Please test.";}i:4;a:5:{s:7:"version";a:2:{s:7:"release";s:6:"1.10.7";s:3:"api";s:6:"1.10.7";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2006-08-11";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:411:"Changelog: + * Fixed Bug #7544: Empty attributes in IniCommented are being discarded (Luis Correa d'Almeida) + * Fixed Bug #7652: wrong xml to phparray convert. Caused by counting position + of directives and sections seperately. While when converting to some containers + we want to count them together. + * Add tests to confirm behaviour of Bug #8357. Do not believe it is fixable without removing + features.";}i:5;a:5:{s:7:"version";a:2:{s:7:"release";s:6:"1.10.6";s:3:"api";s:6:"1.10.6";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2006-02-14";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:361:"Changelog: + * More PHP 4.4 and 5.1 return by reference fixes + * Fixed bug #4477 fatal error when key of array is longer than 114 chars under PHP4.x + * Fixed bug #6385 Allow colon in directive name in IniCommented to match IniFile. + * Fixed bug #6441 true and false literals should be parsed appropriately. Booleans are now parsed the same as in parse_ini_file()";}i:6;a:5:{s:7:"version";a:2:{s:7:"release";s:6:"1.10.5";s:3:"api";s:6:"1.10.5";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2006-01-03";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:603:"Changelog: + * Make what we add quotes around consistent between IniFile and IniCommented. + * Fixed bug #3137 Adding a comment caused problems outputing in phparray format. + * Fixed bug #3590 Handling phparray formats with implicit numeric keys. + * Fixed bug #4623 Rendering to Apache format a second time looses section attributes. + * Fixed bug #5598 Allow '=' in values and output it correctly in IniFile format. + * Fixed bugs #5033, #5835, #6294 Return only variables by reference as required by PHP 4.4 and 5.1. + * Partial Fix for #6385 Allow colon in directive name in IniCommented to match IniFile.";}i:7;a:5:{s:7:"version";a:2:{s:7:"release";s:6:"1.10.4";s:3:"api";s:6:"1.10.4";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2005-02-10";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:416:"Changelog: + * Fixed bug #3298 which wouldn't parse arrays with numerical indexes correctly. + *Fixed bug #2742 which didn't trim variable names in Inicommented file + *changed XML_Parser and XML_Util dependencies to optional, since they're only needed + when parsing XML files (bug #2738) + *added a new container for editing files of php constants, courtesy of philip ortel [me@phillipoertel.com] (beta)";}i:8;a:5:{s:7:"version";a:2:{s:7:"release";s:6:"1.10.3";s:3:"api";s:6:"1.10.3";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2004-10-13";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:440:"Changelog: + *Fixed bug #2179 which prevented URL's containting ~ in ini files to be parsed correctly + *Fixed bug #2439 which caused Config_Containter::countChildren() to return a PEAR_ERROR + object when called on a non-section Config_Container object. This change brings + the object's behavior inline with the documentation. Beware, if your code relies + on the previous behavior, this change may break your code.";}i:9;a:5:{s:7:"version";a:2:{s:7:"release";s:6:"1.10.2";s:3:"api";s:6:"1.10.2";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2004-06-14";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:178:"* Fixed bug #1633 related to case-sensitivity of method names in PHP4. + causing PHPArray container not to work correctly. See also #1556. + Patch provided by m at tacker dotorg.";}i:10;a:5:{s:7:"version";a:2:{s:7:"release";s:6:"1.10.1";s:3:"api";s:6:"1.10.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2004-06-04";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:351:"* Fixed problems with PHP5 case sensitivity on class and method names. +* Added possibility to actually replace the root container by using method +Config::setRoot() with a container of type 'section' and name 'root'. +* XML parser now makes use of the encoding specified in the options array. +* Fixed a warning with array_splice() on an unset $children.";}i:11;a:5:{s:7:"version";a:2:{s:7:"release";s:4:"1.10";s:3:"api";s:4:"1.10";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2003-11-29";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:380:"* Added 'isFile' option to XML container +* Fix a bug when a directive has no content in XML configurations +* Fix slowdown caused by uniqid() on Linux +* Fix regular expression for directives in .ini files (Emil Biserov) +* Fix bug #132 concerning % in .ini files (Wagner netsols.de) +* Fix possible warning if text is empty in .ini commented (Dean Urmson) +* Small speed optimizations";}i:12;a:5:{s:7:"version";a:2:{s:7:"release";s:3:"1.9";s:3:"api";s:3:"1.9";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2003-09-21";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:235:"* Added a new boolean option/parameter in XML, PHPArray and toArray() to set + whether attributes should be rendered. +* Added comments rendering in XML. +* Fix typo in PHPArray when setting the configuration array name (Laurent Laville)";}i:13;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.8.1";s:3:"api";s:5:"1.8.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2003-09-07";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:94:"* Fix a bug in XML container related to cdata handler read by chunk, reported by Stephan Wentz";}i:14;a:5:{s:7:"version";a:2:{s:7:"release";s:3:"1.8";s:3:"api";s:3:"1.8";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2003-08-16";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:324:"* Fix a bug in setRoot() for the XML generator +* Added new method searchPath() to Config_Container (taken from Alan Knowles for XML_Tree) +* Added float detection in Config_Container_PHPArray (Sylvinus Prodi) +* Uses XML_Util in xml container for special entities translation, customizable linebreaks, indents, xml declaration";}i:15;a:5:{s:7:"version";a:2:{s:7:"release";s:3:"1.7";s:3:"api";s:3:"1.7";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2003-06-16";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:467:"* Added new method registerConfigType() (Greg Beaver) +* Root containers are not named 'root' anymore (Bertrand Mansion) +* IniCommented handles comma, quotes, slashes (Greg Beaver) +* IniFile and IniCommented take care of slashes (Greg Beaver) +* Method _parseArray() in PHPArray refactored and much faster (Bertrand Mansion) +* Fix bugs with certain type of arrays with PHPArray (Bertrand Mansion) +* PHPArray now returns values between single quotes (Jean-Marc Fontaine)";}i:16;a:5:{s:7:"version";a:2:{s:7:"release";s:3:"1.6";s:3:"api";s:3:"1.6";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2003-05-20";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:49:"* Fix bug #23690 in toArray reported by Rob Halff";}i:17;a:5:{s:7:"version";a:2:{s:7:"release";s:3:"1.5";s:3:"api";s:3:"1.5";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2003-04-14";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:93:"* Added an id private property for each node +* Fix a bug in toArray when items are duplicates";}i:18;a:5:{s:7:"version";a:2:{s:7:"release";s:3:"1.4";s:3:"api";s:3:"1.4";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2003-04-02";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:121:"* Fix setDirective method in Container +* Fix warnings in foreach loop when attributes are not set +* Added phpdoc comments";}i:19;a:5:{s:7:"version";a:2:{s:7:"release";s:3:"1.3";s:3:"api";s:3:"1.3";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2003-03-26";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:441:"* Fixed missing quote in xml generation (Nicolas Guennoc) +* Fixed warning in xml container when no attributes (Nicolas Guennoc) +* Added methods getAttribute and updateAttributes to container. +* Added possibility to get item by looking at its attributes in getItem() +* PHPArray container automatically generates array name when not specified in options +* XML Container can accept a name too that will generate the global root entity if needed";}i:20;a:5:{s:7:"version";a:2:{s:7:"release";s:3:"1.2";s:3:"api";s:3:"1.2";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2003-03-24";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:211:"First stable release. +* Added an XML container (uses XML_Parser), +* Possibility to convert from one format to another, +* Fixes in toArray(), +* Added attributes to containers, +* New methods for item manipulation.";}i:21;a:5:{s:7:"version";a:2:{s:7:"release";s:3:"1.1";s:3:"api";s:3:"1.1";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:4:"beta";}s:4:"date";s:10:"2002-10-08";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:60:"Fix bug in toArray(). +Thanks to Mark Polsen for noticing it.";}i:22;a:5:{s:7:"version";a:2:{s:7:"release";s:3:"1.0";s:3:"api";s:3:"1.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2006-10-20";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:284:"Complete rewrite : API has changed. +The class now uses a tree structure of container objects. +As a consequence, backward compatibility is not provided !!! +Look at the Apache.php and IniCommented.php scripts in 'docs' for usage examples. +Some containers are still missing : XML and DB.";}i:23;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"0.3.1";s:3:"api";s:5:"0.3.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2006-10-20";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:55:"Documentation is in README.Config. +0.3.1 +- E_ALL fixes";}i:24;a:5:{s:7:"version";a:2:{s:7:"release";s:3:"0.3";s:3:"api";s:3:"0.3";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2006-10-20";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:164:"- some fixes +- add WDDX-Container for config data in WDDX-files +- add phpIniFile, does the same like IniFile but based on the PHP build-in function parse_ini_file()";}i:25;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"0.2.2";s:3:"api";s:5:"0.2.2";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2006-10-20";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:291:"- Only the first char of ->feature['cc'] is taken as a comment deliminator +- quoting supports both methods: + [bla] + foo = "'bar'" + bar = '"foo"' +- Value parser only parser until first comment-char or the end of the string, therefore spaces surrounded by nonspaces don't have to be quoted.";}i:26;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"0.2.1";s:3:"api";s:5:"0.2.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2006-10-20";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:120:"- Bug fixed, when $feature in ParseInput was not set +- some e_warnings fixed +(thanks to Markus Fischer for the reports)";}}}s:8:"filelist";a:40:{s:27:"Config/Container/Apache.php";a:4:{s:6:"md5sum";s:32:"24c8aa0428acef34c3941da6e316ee64";s:4:"name";s:27:"Config/Container/Apache.php";s:4:"role";s:3:"php";s:12:"installed_as";s:62:"/www/htdocs/w00acdb0/lib/pear/PEAR/Config/Container/Apache.php";}s:32:"Config/Container/GenericConf.php";a:4:{s:6:"md5sum";s:32:"97334aef3975512fe8820dd0577ec135";s:4:"name";s:32:"Config/Container/GenericConf.php";s:4:"role";s:3:"php";s:12:"installed_as";s:67:"/www/htdocs/w00acdb0/lib/pear/PEAR/Config/Container/GenericConf.php";}s:33:"Config/Container/IniCommented.php";a:4:{s:6:"md5sum";s:32:"cea4ff38f7e4240e2c999be4aa1854e6";s:4:"name";s:33:"Config/Container/IniCommented.php";s:4:"role";s:3:"php";s:12:"installed_as";s:68:"/www/htdocs/w00acdb0/lib/pear/PEAR/Config/Container/IniCommented.php";}s:28:"Config/Container/IniFile.php";a:4:{s:6:"md5sum";s:32:"33e8495e6c8da599248193bf66f3b479";s:4:"name";s:28:"Config/Container/IniFile.php";s:4:"role";s:3:"php";s:12:"installed_as";s:63:"/www/htdocs/w00acdb0/lib/pear/PEAR/Config/Container/IniFile.php";}s:29:"Config/Container/PHPArray.php";a:4:{s:6:"md5sum";s:32:"86ddfaabf01eb9cb3d21e8afb5022930";s:4:"name";s:29:"Config/Container/PHPArray.php";s:4:"role";s:3:"php";s:12:"installed_as";s:64:"/www/htdocs/w00acdb0/lib/pear/PEAR/Config/Container/PHPArray.php";}s:33:"Config/Container/PHPConstants.php";a:4:{s:6:"md5sum";s:32:"5754e39e081433aaf132c64db676a163";s:4:"name";s:33:"Config/Container/PHPConstants.php";s:4:"role";s:3:"php";s:12:"installed_as";s:68:"/www/htdocs/w00acdb0/lib/pear/PEAR/Config/Container/PHPConstants.php";}s:24:"Config/Container/XML.php";a:4:{s:6:"md5sum";s:32:"957cbd88a70e34e94ed65ab7d3df5d7d";s:4:"name";s:24:"Config/Container/XML.php";s:4:"role";s:3:"php";s:12:"installed_as";s:59:"/www/htdocs/w00acdb0/lib/pear/PEAR/Config/Container/XML.php";}s:20:"Config/Container.php";a:4:{s:6:"md5sum";s:32:"5cb17578402b866ed080a8e77a8a9a9b";s:4:"name";s:20:"Config/Container.php";s:4:"role";s:3:"php";s:12:"installed_as";s:55:"/www/htdocs/w00acdb0/lib/pear/PEAR/Config/Container.php";}s:15:"docs/Apache.php";a:4:{s:6:"md5sum";s:32:"3f258a90dbd6371c52337d83e763bdb8";s:4:"name";s:15:"docs/Apache.php";s:4:"role";s:3:"doc";s:12:"installed_as";s:62:"/www/htdocs/w00acdb0/lib/pear/PEAR/docs/Config/docs/Apache.php";}s:21:"docs/IniCommented.php";a:4:{s:6:"md5sum";s:32:"702edcddaf83d81196433887fa383a09";s:4:"name";s:21:"docs/IniCommented.php";s:4:"role";s:3:"doc";s:12:"installed_as";s:68:"/www/htdocs/w00acdb0/lib/pear/PEAR/docs/Config/docs/IniCommented.php";}s:23:"docs/IniFromScratch.php";a:4:{s:6:"md5sum";s:32:"bce55b10d2e5ffef5a4a04aba92851ce";s:4:"name";s:23:"docs/IniFromScratch.php";s:4:"role";s:3:"doc";s:12:"installed_as";s:70:"/www/htdocs/w00acdb0/lib/pear/PEAR/docs/Config/docs/IniFromScratch.php";}s:16:"test/bug2742.ini";a:4:{s:6:"md5sum";s:32:"d77a133b013cdc9794d0f6e09b6b88d1";s:4:"name";s:16:"test/bug2742.ini";s:4:"role";s:4:"test";s:12:"installed_as";s:64:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/Config/test/bug2742.ini";}s:17:"test/bug2742.phpt";a:4:{s:6:"md5sum";s:32:"1c00244cdc36cff6960e394f1746c86d";s:4:"name";s:17:"test/bug2742.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:65:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/Config/test/bug2742.phpt";}s:17:"test/bug2780.phpt";a:4:{s:6:"md5sum";s:32:"a750197af925dcfbe4f30d493f43896d";s:4:"name";s:17:"test/bug2780.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:65:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/Config/test/bug2780.phpt";}s:17:"test/bug3051.phpt";a:4:{s:6:"md5sum";s:32:"756ac177b9281c16a54d5beabe5ece9b";s:4:"name";s:17:"test/bug3051.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:65:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/Config/test/bug3051.phpt";}s:16:"test/bug3051.xml";a:4:{s:6:"md5sum";s:32:"61064633ed23cbec0f706fde3751a3e4";s:4:"name";s:16:"test/bug3051.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:64:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/Config/test/bug3051.xml";}s:17:"test/bug3137.phpt";a:4:{s:6:"md5sum";s:32:"ebe9d890f041a26b0a37f4b97355a7fd";s:4:"name";s:17:"test/bug3137.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:65:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/Config/test/bug3137.phpt";}s:17:"test/bug3298.phpt";a:4:{s:6:"md5sum";s:32:"2935e7e4362eca07908f005e92683460";s:4:"name";s:17:"test/bug3298.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:65:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/Config/test/bug3298.phpt";}s:16:"test/bug3298.xml";a:4:{s:6:"md5sum";s:32:"7d577265dcdecebc67dee5118268ace5";s:4:"name";s:16:"test/bug3298.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:64:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/Config/test/bug3298.xml";}s:16:"test/bug3398.ini";a:4:{s:6:"md5sum";s:32:"2b36a2cc7b70a10d13799c116a5536bb";s:4:"name";s:16:"test/bug3398.ini";s:4:"role";s:4:"test";s:12:"installed_as";s:64:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/Config/test/bug3398.ini";}s:17:"test/bug3398.phpt";a:4:{s:6:"md5sum";s:32:"373109b53b1b5129f68c7b81aa31f297";s:4:"name";s:17:"test/bug3398.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:65:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/Config/test/bug3398.phpt";}s:22:"test/bug3590-input.php";a:4:{s:6:"md5sum";s:32:"08ec9d9f4649fefda49b1991d3fb20b1";s:4:"name";s:22:"test/bug3590-input.php";s:4:"role";s:4:"test";s:12:"installed_as";s:70:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/Config/test/bug3590-input.php";}s:17:"test/bug3590.phpt";a:4:{s:6:"md5sum";s:32:"164099132d1dedf4ac03b3f4a5afba19";s:4:"name";s:17:"test/bug3590.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:65:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/Config/test/bug3590.phpt";}s:17:"test/bug4623.conf";a:4:{s:6:"md5sum";s:32:"ad05c4a11c5b08b25488aab6248192a7";s:4:"name";s:17:"test/bug4623.conf";s:4:"role";s:4:"test";s:12:"installed_as";s:65:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/Config/test/bug4623.conf";}s:17:"test/bug4623.phpt";a:4:{s:6:"md5sum";s:32:"9a8c732b18ec989dbf90c00bba4e0c55";s:4:"name";s:17:"test/bug4623.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:65:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/Config/test/bug4623.phpt";}s:16:"test/bug6441.ini";a:4:{s:6:"md5sum";s:32:"f6fec7ec6187f591c51fc7b09130da7d";s:4:"name";s:16:"test/bug6441.ini";s:4:"role";s:4:"test";s:12:"installed_as";s:64:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/Config/test/bug6441.ini";}s:17:"test/bug6441.phpt";a:4:{s:6:"md5sum";s:32:"7e9519b6ccfa0b8a3e369023add3ead1";s:4:"name";s:17:"test/bug6441.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:65:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/Config/test/bug6441.phpt";}s:30:"test/bug7544-inicommented.phpt";a:4:{s:6:"md5sum";s:32:"8a3b57b2ae8d47ee78056b99e620c282";s:4:"name";s:30:"test/bug7544-inicommented.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:78:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/Config/test/bug7544-inicommented.phpt";}s:25:"test/bug7544-inifile.phpt";a:4:{s:6:"md5sum";s:32:"db33c7454539f9fbc02897f5de2b90b2";s:4:"name";s:25:"test/bug7544-inifile.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:73:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/Config/test/bug7544-inifile.phpt";}s:16:"test/bug7544.ini";a:4:{s:6:"md5sum";s:32:"8aa8d748b9266e30028e75889ed5ff0c";s:4:"name";s:16:"test/bug7544.ini";s:4:"role";s:4:"test";s:12:"installed_as";s:64:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/Config/test/bug7544.ini";}s:17:"test/bug7652.phpt";a:4:{s:6:"md5sum";s:32:"b293dee5fc7a375dbf72fae9b3d65bca";s:4:"name";s:17:"test/bug7652.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:65:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/Config/test/bug7652.phpt";}s:16:"test/bug7652.xml";a:4:{s:6:"md5sum";s:32:"3fcbdf4ceabeca34357cfcd3266e5e6d";s:4:"name";s:16:"test/bug7652.xml";s:4:"role";s:4:"test";s:12:"installed_as";s:64:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/Config/test/bug7652.xml";}s:30:"test/bug8357-inicommented.phpt";a:4:{s:6:"md5sum";s:32:"db3a27af6cf7afbeafb56e55ba63e601";s:4:"name";s:30:"test/bug8357-inicommented.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:78:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/Config/test/bug8357-inicommented.phpt";}s:25:"test/bug8357-inifile.phpt";a:4:{s:6:"md5sum";s:32:"68f5313a4cb289711453a2561ba1645a";s:4:"name";s:25:"test/bug8357-inifile.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:73:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/Config/test/bug8357-inifile.phpt";}s:16:"test/bug8357.ini";a:4:{s:6:"md5sum";s:32:"23285375454662259e5821eb991d124d";s:4:"name";s:16:"test/bug8357.ini";s:4:"role";s:4:"test";s:12:"installed_as";s:64:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/Config/test/bug8357.ini";}s:18:"test/bug10010.phpt";a:4:{s:6:"md5sum";s:32:"e9ab76a4d81cc67d98aec18c049e93c0";s:4:"name";s:18:"test/bug10010.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:66:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/Config/test/bug10010.phpt";}s:18:"test/bug10185.phpt";a:4:{s:6:"md5sum";s:32:"39174eaab97f7c97ac56dc8c99396947";s:4:"name";s:18:"test/bug10185.phpt";s:4:"role";s:4:"test";s:12:"installed_as";s:66:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/Config/test/bug10185.phpt";}s:22:"test/phpt_test.php.inc";a:4:{s:6:"md5sum";s:32:"85a595db7562821ef50297502a50317b";s:4:"name";s:22:"test/phpt_test.php.inc";s:4:"role";s:4:"test";s:12:"installed_as";s:70:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/Config/test/phpt_test.php.inc";}s:18:"test/setup.php.inc";a:4:{s:6:"md5sum";s:32:"1dce06e33ccfa8f55463450db8b4d365";s:4:"name";s:18:"test/setup.php.inc";s:4:"role";s:4:"test";s:12:"installed_as";s:66:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/Config/test/setup.php.inc";}s:10:"Config.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"a664418fa43875d263b20e611e4edee2";s:4:"name";s:10:"Config.php";s:4:"role";s:3:"php";s:12:"installed_as";s:45:"/www/htdocs/w00acdb0/lib/pear/PEAR/Config.php";}}s:12:"_lastversion";N;s:7:"dirtree";a:7:{s:51:"/www/htdocs/w00acdb0/lib/pear/PEAR/Config/Container";b:1;s:41:"/www/htdocs/w00acdb0/lib/pear/PEAR/Config";b:1;s:51:"/www/htdocs/w00acdb0/lib/pear/PEAR/docs/Config/docs";b:1;s:46:"/www/htdocs/w00acdb0/lib/pear/PEAR/docs/Config";b:1;s:52:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/Config/test";b:1;s:47:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/Config";b:1;s:34:"/www/htdocs/w00acdb0/lib/pear/PEAR";b:1;}s:3:"old";a:7:{s:7:"version";s:7:"1.10.11";s:12:"release_date";s:10:"2007-06-12";s:13:"release_state";s:6:"stable";s:15:"release_license";s:11:"PHP License";s:13:"release_notes";s:149:"* Fixed Bug #11184: Knock on problems from fix for Bug #10185. Thanks to + Thomas Despoix and Carsten Wiedmann for helping me understand it properly.";s:12:"release_deps";a:4:{i:0;a:4:{s:4:"type";s:3:"php";s:3:"rel";s:2:"ge";s:7:"version";s:5:"4.3.0";s:8:"optional";s:2:"no";}i:1;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:4:"PEAR";s:3:"rel";s:2:"ge";s:7:"version";s:7:"1.4.0b1";s:8:"optional";s:2:"no";}i:2;a:5:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:10:"XML_Parser";s:3:"rel";s:3:"has";s:8:"optional";s:3:"yes";}i:3;a:5:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:8:"XML_Util";s:3:"rel";s:3:"has";s:8:"optional";s:3:"yes";}}s:11:"maintainers";a:4:{i:0;a:5:{s:4:"name";s:16:"Bertrand Mansion";s:5:"email";s:20:"bmansion@mamasam.com";s:6:"active";s:2:"no";s:6:"handle";s:7:"mansion";s:4:"role";s:4:"lead";}i:1;a:5:{s:4:"name";s:9:"Ryan King";s:5:"email";s:17:"ryansking@php.net";s:6:"active";s:2:"no";s:6:"handle";s:9:"ryansking";s:4:"role";s:4:"lead";}i:2;a:5:{s:4:"name";s:11:"Adam Ashley";s:5:"email";s:15:"aashley@php.net";s:6:"active";s:3:"yes";s:6:"handle";s:7:"aashley";s:4:"role";s:4:"lead";}i:3;a:5:{s:4:"name";s:11:"Adam Harvey";s:5:"email";s:15:"aharvey@php.net";s:6:"active";s:3:"yes";s:6:"handle";s:7:"aharvey";s:4:"role";s:9:"developer";}}}s:10:"xsdversion";s:3:"2.0";s:13:"_lastmodified";i:1234655685;} \ No newline at end of file diff --git a/src/lib/pear/PEAR/.registry/console_getopt.reg b/src/lib/pear/PEAR/.registry/console_getopt.reg new file mode 100644 index 0000000..fb1bf67 --- /dev/null +++ b/src/lib/pear/PEAR/.registry/console_getopt.reg @@ -0,0 +1,4 @@ +a:25:{s:7:"attribs";a:6:{s:15:"packagerversion";s:5:"1.6.1";s:7:"version";s:3:"2.0";s:5:"xmlns";s:35:"http://pear.php.net/dtd/package-2.0";s:11:"xmlns:tasks";s:33:"http://pear.php.net/dtd/tasks-1.0";s:9:"xmlns:xsi";s:41:"http://www.w3.org/2001/XMLSchema-instance";s:18:"xsi:schemaLocation";s:147:"http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd";}s:4:"name";s:14:"Console_Getopt";s:7:"channel";s:12:"pear.php.net";s:7:"summary";s:26:"Command-line option parser";s:11:"description";s:80:"This is a PHP implementation of "getopt" supporting both +short and long options.";s:4:"lead";a:4:{s:4:"name";s:15:"Andrei Zmievski";s:4:"user";s:6:"andrei";s:5:"email";s:14:"andrei@php.net";s:6:"active";s:3:"yes";}s:9:"developer";a:4:{s:4:"name";s:11:"Stig Bakken";s:4:"user";s:3:"ssb";s:5:"email";s:12:"stig@php.net";s:6:"active";s:2:"no";}s:6:"helper";a:4:{s:4:"name";s:11:"Greg Beaver";s:4:"user";s:6:"cellog";s:5:"email";s:14:"cellog@php.net";s:6:"active";s:3:"yes";}s:4:"date";s:10:"2007-06-12";s:4:"time";s:8:"14:52:39";s:7:"version";a:2:{s:7:"release";s:5:"1.2.3";s:3:"api";s:5:"1.2.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:58:"* fix Bug #11068: No way to read plain "-" option [cardoe]";s:8:"contents";a:1:{s:3:"dir";a:2:{s:7:"attribs";a:1:{s:4:"name";s:1:"/";}s:4:"file";a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f2175a45c5e5bc7c97e174bdae55b671";s:4:"name";s:18:"Console/Getopt.php";s:4:"role";s:3:"php";}}}}s:10:"compatible";a:4:{s:4:"name";s:4:"PEAR";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:5:"1.4.0";s:3:"max";s:5:"1.6.0";}s:12:"dependencies";a:1:{s:8:"required";a:2:{s:3:"php";a:1:{s:3:"min";s:5:"4.3.0";}s:13:"pearinstaller";a:1:{s:3:"min";s:5:"1.4.3";}}}s:10:"phprelease";s:0:"";s:9:"changelog";a:1:{s:7:"release";a:7:{i:0;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.2.2";s:3:"api";s:5:"1.2.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2007-02-17";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:165:"* fix Bug #4475: An ambiguous error occurred when specifying similar longoption name. +* fix Bug #10055: Not failing properly on short options missing required values";}i:1;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.2.1";s:3:"api";s:5:"1.2.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2006-12-08";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:126:"Fixed bugs #4448 (Long parameter values truncated with longoption parameter) and #7444 (Trailing spaces after php closing tag)";}i:2;a:5:{s:7:"version";a:2:{s:7:"release";s:3:"1.2";s:3:"api";s:3:"1.2";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2003-12-11";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:69:"Fix to preserve BC with 1.0 and allow correct behaviour for new users";}i:3;a:5:{s:7:"version";a:2:{s:7:"release";s:3:"1.0";s:3:"api";s:3:"1.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2002-09-13";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:14:"Stable release";}i:4;a:5:{s:7:"version";a:2:{s:7:"release";s:4:"0.11";s:3:"api";s:4:"0.11";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:4:"beta";}s:4:"date";s:10:"2002-05-26";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:89:"POSIX getopt compatibility fix: treat first element of args + array as command name";}i:5;a:5:{s:7:"version";a:2:{s:7:"release";s:4:"0.10";s:3:"api";s:4:"0.10";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:4:"beta";}s:4:"date";s:10:"2002-05-12";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:13:"Packaging fix";}i:6;a:5:{s:7:"version";a:2:{s:7:"release";s:3:"0.9";s:3:"api";s:3:"0.9";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:4:"beta";}s:4:"date";s:10:"2002-05-12";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:15:"Initial release";}}}s:8:"filelist";a:1:{s:18:"Console/Getopt.php";a:4:{s:6:"md5sum";s:32:"f2175a45c5e5bc7c97e174bdae55b671";s:4:"name";s:18:"Console/Getopt.php";s:4:"role";s:3:"php";s:12:"installed_as";s:53:"/www/htdocs/w00acdb0/lib/pear/PEAR/Console/Getopt.php";}}s:12:"_lastversion";N;s:7:"dirtree";a:1:{s:42:"/www/htdocs/w00acdb0/lib/pear/PEAR/Console";b:1;}s:3:"old";a:7:{s:7:"version";s:5:"1.2.3";s:12:"release_date";s:10:"2007-06-12";s:13:"release_state";s:6:"stable";s:15:"release_license";s:11:"PHP License";s:13:"release_notes";s:58:"* fix Bug #11068: No way to read plain "-" option [cardoe]";s:12:"release_deps";a:2:{i:0;a:4:{s:4:"type";s:3:"php";s:3:"rel";s:2:"ge";s:7:"version";s:5:"4.3.0";s:8:"optional";s:2:"no";}i:1;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:4:"PEAR";s:3:"rel";s:2:"ge";s:7:"version";s:5:"1.4.3";s:8:"optional";s:2:"no";}}s:11:"maintainers";a:3:{i:0;a:5:{s:4:"name";s:15:"Andrei Zmievski";s:5:"email";s:14:"andrei@php.net";s:6:"active";s:3:"yes";s:6:"handle";s:6:"andrei";s:4:"role";s:4:"lead";}i:1;a:5:{s:4:"name";s:11:"Stig Bakken";s:5:"email";s:12:"stig@php.net";s:6:"active";s:2:"no";s:6:"handle";s:3:"ssb";s:4:"role";s:9:"developer";}i:2;a:5:{s:4:"name";s:11:"Greg Beaver";s:5:"email";s:14:"cellog@php.net";s:6:"active";s:3:"yes";s:6:"handle";s:6:"cellog";s:4:"role";s:6:"helper";}}}s:10:"xsdversion";s:3:"2.0";s:13:"_lastmodified";i:1234655681;} \ No newline at end of file diff --git a/src/lib/pear/PEAR/.registry/html_template_it.reg b/src/lib/pear/PEAR/.registry/html_template_it.reg new file mode 100644 index 0000000..985a23a --- /dev/null +++ b/src/lib/pear/PEAR/.registry/html_template_it.reg @@ -0,0 +1,60 @@ +a:17:{s:8:"provides";a:44:{s:22:"class;HTML_Template_IT";a:3:{s:4:"type";s:5:"class";s:4:"name";s:16:"HTML_Template_IT";s:8:"explicit";b:1;}s:36:"function;HTML_Template_IT::setOption";a:3:{s:4:"type";s:8:"function";s:4:"name";s:27:"HTML_Template_IT::setOption";s:8:"explicit";b:1;}s:37:"function;HTML_Template_IT::setOptions";a:3:{s:4:"type";s:8:"function";s:4:"name";s:28:"HTML_Template_IT::setOptions";s:8:"explicit";b:1;}s:31:"function;HTML_Template_IT::show";a:3:{s:4:"type";s:8:"function";s:4:"name";s:22:"HTML_Template_IT::show";s:8:"explicit";b:1;}s:30:"function;HTML_Template_IT::get";a:3:{s:4:"type";s:8:"function";s:4:"name";s:21:"HTML_Template_IT::get";s:8:"explicit";b:1;}s:32:"function;HTML_Template_IT::parse";a:3:{s:4:"type";s:8:"function";s:4:"name";s:23:"HTML_Template_IT::parse";s:8:"explicit";b:1;}s:44:"function;HTML_Template_IT::parseCurrentBlock";a:3:{s:4:"type";s:8:"function";s:4:"name";s:35:"HTML_Template_IT::parseCurrentBlock";s:8:"explicit";b:1;}s:38:"function;HTML_Template_IT::setVariable";a:3:{s:4:"type";s:8:"function";s:4:"name";s:29:"HTML_Template_IT::setVariable";s:8:"explicit";b:1;}s:42:"function;HTML_Template_IT::setCurrentBlock";a:3:{s:4:"type";s:8:"function";s:4:"name";s:33:"HTML_Template_IT::setCurrentBlock";s:8:"explicit";b:1;}s:37:"function;HTML_Template_IT::touchBlock";a:3:{s:4:"type";s:8:"function";s:4:"name";s:28:"HTML_Template_IT::touchBlock";s:8:"explicit";b:1;}s:31:"function;HTML_Template_IT::init";a:3:{s:4:"type";s:8:"function";s:4:"name";s:22:"HTML_Template_IT::init";s:8:"explicit";b:1;}s:31:"function;HTML_Template_IT::free";a:3:{s:4:"type";s:8:"function";s:4:"name";s:22:"HTML_Template_IT::free";s:8:"explicit";b:1;}s:38:"function;HTML_Template_IT::setTemplate";a:3:{s:4:"type";s:8:"function";s:4:"name";s:29:"HTML_Template_IT::setTemplate";s:8:"explicit";b:1;}s:43:"function;HTML_Template_IT::loadTemplatefile";a:3:{s:4:"type";s:8:"function";s:4:"name";s:34:"HTML_Template_IT::loadTemplatefile";s:8:"explicit";b:1;}s:34:"function;HTML_Template_IT::setRoot";a:3:{s:4:"type";s:8:"function";s:4:"name";s:25:"HTML_Template_IT::setRoot";s:8:"explicit";b:1;}s:49:"function;HTML_Template_IT::buildBlockvariablelist";a:3:{s:4:"type";s:8:"function";s:4:"name";s:40:"HTML_Template_IT::buildBlockvariablelist";s:8:"explicit";b:1;}s:45:"function;HTML_Template_IT::getGlobalvariables";a:3:{s:4:"type";s:8:"function";s:4:"name";s:36:"HTML_Template_IT::getGlobalvariables";s:8:"explicit";b:1;}s:37:"function;HTML_Template_IT::findBlocks";a:3:{s:4:"type";s:8:"function";s:4:"name";s:28:"HTML_Template_IT::findBlocks";s:8:"explicit";b:1;}s:34:"function;HTML_Template_IT::getFile";a:3:{s:4:"type";s:8:"function";s:4:"name";s:25:"HTML_Template_IT::getFile";s:8:"explicit";b:1;}s:39:"function;HTML_Template_IT::errorMessage";a:3:{s:4:"type";s:8:"function";s:4:"name";s:30:"HTML_Template_IT::errorMessage";s:8:"explicit";b:1;}s:23:"class;HTML_Template_ITX";a:4:{s:4:"type";s:5:"class";s:4:"name";s:17:"HTML_Template_ITX";s:7:"extends";s:16:"HTML_Template_IT";s:8:"explicit";b:1;}s:32:"function;HTML_Template_ITX::init";a:3:{s:4:"type";s:8:"function";s:4:"name";s:23:"HTML_Template_ITX::init";s:8:"explicit";b:1;}s:40:"function;HTML_Template_ITX::replaceBlock";a:3:{s:4:"type";s:8:"function";s:4:"name";s:31:"HTML_Template_ITX::replaceBlock";s:8:"explicit";b:1;}s:44:"function;HTML_Template_ITX::replaceBlockfile";a:3:{s:4:"type";s:8:"function";s:4:"name";s:35:"HTML_Template_ITX::replaceBlockfile";s:8:"explicit";b:1;}s:36:"function;HTML_Template_ITX::addBlock";a:3:{s:4:"type";s:8:"function";s:4:"name";s:27:"HTML_Template_ITX::addBlock";s:8:"explicit";b:1;}s:40:"function;HTML_Template_ITX::addBlockfile";a:3:{s:4:"type";s:8:"function";s:4:"name";s:31:"HTML_Template_ITX::addBlockfile";s:8:"explicit";b:1;}s:45:"function;HTML_Template_ITX::placeholderExists";a:3:{s:4:"type";s:8:"function";s:4:"name";s:36:"HTML_Template_ITX::placeholderExists";s:8:"explicit";b:1;}s:43:"function;HTML_Template_ITX::performCallback";a:3:{s:4:"type";s:8:"function";s:4:"name";s:34:"HTML_Template_ITX::performCallback";s:8:"explicit";b:1;}s:44:"function;HTML_Template_ITX::getFunctioncalls";a:3:{s:4:"type";s:8:"function";s:4:"name";s:35:"HTML_Template_ITX::getFunctioncalls";s:8:"explicit";b:1;}s:46:"function;HTML_Template_ITX::setFunctioncontent";a:3:{s:4:"type";s:8:"function";s:4:"name";s:37:"HTML_Template_ITX::setFunctioncontent";s:8:"explicit";b:1;}s:47:"function;HTML_Template_ITX::setCallbackFunction";a:3:{s:4:"type";s:8:"function";s:4:"name";s:38:"HTML_Template_ITX::setCallbackFunction";s:8:"explicit";b:1;}s:51:"function;HTML_Template_ITX::setCallbackFuntiontable";a:3:{s:4:"type";s:8:"function";s:4:"name";s:42:"HTML_Template_ITX::setCallbackFuntiontable";s:8:"explicit";b:1;}s:43:"function;HTML_Template_ITX::removeBlockData";a:3:{s:4:"type";s:8:"function";s:4:"name";s:34:"HTML_Template_ITX::removeBlockData";s:8:"explicit";b:1;}s:40:"function;HTML_Template_ITX::getBlocklist";a:3:{s:4:"type";s:8:"function";s:4:"name";s:31:"HTML_Template_ITX::getBlocklist";s:8:"explicit";b:1;}s:39:"function;HTML_Template_ITX::blockExists";a:3:{s:4:"type";s:8:"function";s:4:"name";s:30:"HTML_Template_ITX::blockExists";s:8:"explicit";b:1;}s:45:"function;HTML_Template_ITX::getBlockvariables";a:3:{s:4:"type";s:8:"function";s:4:"name";s:36:"HTML_Template_ITX::getBlockvariables";s:8:"explicit";b:1;}s:47:"function;HTML_Template_ITX::BlockvariableExists";a:3:{s:4:"type";s:8:"function";s:4:"name";s:38:"HTML_Template_ITX::BlockvariableExists";s:8:"explicit";b:1;}s:45:"function;HTML_Template_ITX::buildFunctionlist";a:3:{s:4:"type";s:8:"function";s:4:"name";s:36:"HTML_Template_ITX::buildFunctionlist";s:8:"explicit";b:1;}s:36:"function;HTML_Template_ITX::getValue";a:3:{s:4:"type";s:8:"function";s:4:"name";s:27:"HTML_Template_ITX::getValue";s:8:"explicit";b:1;}s:55:"function;HTML_Template_ITX::deleteFromBlockvariablelist";a:3:{s:4:"type";s:8:"function";s:4:"name";s:46:"HTML_Template_ITX::deleteFromBlockvariablelist";s:8:"explicit";b:1;}s:51:"function;HTML_Template_ITX::updateBlockvariablelist";a:3:{s:4:"type";s:8:"function";s:4:"name";s:42:"HTML_Template_ITX::updateBlockvariablelist";s:8:"explicit";b:1;}s:49:"function;HTML_Template_ITX::findPlaceholderBlocks";a:3:{s:4:"type";s:8:"function";s:4:"name";s:40:"HTML_Template_ITX::findPlaceholderBlocks";s:8:"explicit";b:1;}s:35:"function;HTML_Template_ITX::warning";a:3:{s:4:"type";s:8:"function";s:4:"name";s:26:"HTML_Template_ITX::warning";s:8:"explicit";b:1;}s:14:"class;IT_Error";a:4:{s:4:"type";s:5:"class";s:4:"name";s:8:"IT_Error";s:7:"extends";s:10:"PEAR_Error";s:8:"explicit";b:1;}}s:8:"filelist";a:23:{s:6:"IT.php";a:4:{s:4:"role";s:3:"php";s:14:"baseinstalldir";s:13:"HTML/Template";s:6:"md5sum";s:32:"5b034e239aff955692281191318754e4";s:12:"installed_as";s:55:"/www/htdocs/w00acdb0/lib/pear/PEAR/HTML/Template/IT.php";}s:7:"ITX.php";a:4:{s:4:"role";s:3:"php";s:14:"baseinstalldir";s:13:"HTML/Template";s:6:"md5sum";s:32:"3dd802be714a2366531c89933da23a04";s:12:"installed_as";s:56:"/www/htdocs/w00acdb0/lib/pear/PEAR/HTML/Template/ITX.php";}s:12:"IT_Error.php";a:4:{s:4:"role";s:3:"php";s:14:"baseinstalldir";s:13:"HTML/Template";s:6:"md5sum";s:32:"347113315197afdc4ba98815a21f14ab";s:12:"installed_as";s:61:"/www/htdocs/w00acdb0/lib/pear/PEAR/HTML/Template/IT_Error.php";}s:7:"LICENSE";a:4:{s:4:"role";s:3:"doc";s:14:"baseinstalldir";s:13:"HTML/Template";s:6:"md5sum";s:32:"f8790e48b597dff12a643e08e9be3fab";s:12:"installed_as";s:64:"/www/htdocs/w00acdb0/lib/pear/PEAR/docs/HTML_Template_IT/LICENSE";}s:29:"tests/templates/addblock.html";a:4:{s:4:"role";s:4:"test";s:14:"baseinstalldir";s:13:"HTML/Template";s:6:"md5sum";s:32:"e50de49b74a1d96bb77ddae2d0abdfc3";s:12:"installed_as";s:87:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/HTML_Template_IT/tests/templates/addblock.html";}s:35:"tests/templates/blockiteration.html";a:4:{s:4:"role";s:4:"test";s:14:"baseinstalldir";s:13:"HTML/Template";s:6:"md5sum";s:32:"22e56437378e53d08ba07d3dd2aa4b85";s:12:"installed_as";s:93:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/HTML_Template_IT/tests/templates/blockiteration.html";}s:27:"tests/templates/blocks.html";a:4:{s:4:"role";s:4:"test";s:14:"baseinstalldir";s:13:"HTML/Template";s:6:"md5sum";s:32:"4173bf97eec43787532e247ef9b2611a";s:12:"installed_as";s:85:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/HTML_Template_IT/tests/templates/blocks.html";}s:28:"tests/templates/globals.html";a:4:{s:4:"role";s:4:"test";s:14:"baseinstalldir";s:13:"HTML/Template";s:6:"md5sum";s:32:"2611d6ec574a65716f1bc2ca95cb8c63";s:12:"installed_as";s:86:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/HTML_Template_IT/tests/templates/globals.html";}s:30:"tests/templates/__include.html";a:4:{s:4:"role";s:4:"test";s:14:"baseinstalldir";s:13:"HTML/Template";s:6:"md5sum";s:32:"310552db4653b34dbb0f993847572fc5";s:12:"installed_as";s:88:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/HTML_Template_IT/tests/templates/__include.html";}s:28:"tests/templates/include.html";a:4:{s:4:"role";s:4:"test";s:14:"baseinstalldir";s:13:"HTML/Template";s:6:"md5sum";s:32:"db5b226eff0218c831749c07042529f2";s:12:"installed_as";s:86:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/HTML_Template_IT/tests/templates/include.html";}s:37:"tests/templates/loadtemplatefile.html";a:4:{s:4:"role";s:4:"test";s:14:"baseinstalldir";s:13:"HTML/Template";s:6:"md5sum";s:32:"d9a6425eebdfc6981465b4a228dbee51";s:12:"installed_as";s:95:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/HTML_Template_IT/tests/templates/loadtemplatefile.html";}s:33:"tests/templates/replaceblock.html";a:4:{s:4:"role";s:4:"test";s:14:"baseinstalldir";s:13:"HTML/Template";s:6:"md5sum";s:32:"5c7e2e9c32306db4b6667d2b57f1c0ac";s:12:"installed_as";s:91:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/HTML_Template_IT/tests/templates/replaceblock.html";}s:30:"tests/Console_TestListener.php";a:4:{s:4:"role";s:4:"test";s:14:"baseinstalldir";s:13:"HTML/Template";s:6:"md5sum";s:32:"9bd9d964363904b5026972dff0d198da";s:12:"installed_as";s:88:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/HTML_Template_IT/tests/Console_TestListener.php";}s:25:"tests/IT_api_testcase.php";a:4:{s:4:"role";s:4:"test";s:14:"baseinstalldir";s:13:"HTML/Template";s:6:"md5sum";s:32:"e624be47a36948a1e44d231260de808a";s:12:"installed_as";s:83:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/HTML_Template_IT/tests/IT_api_testcase.php";}s:27:"tests/IT_usage_testcase.php";a:4:{s:4:"role";s:4:"test";s:14:"baseinstalldir";s:13:"HTML/Template";s:6:"md5sum";s:32:"3836b3fc1dd5a2a4d09258be575736c9";s:12:"installed_as";s:85:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/HTML_Template_IT/tests/IT_usage_testcase.php";}s:26:"tests/ITX_api_testcase.php";a:4:{s:4:"role";s:4:"test";s:14:"baseinstalldir";s:13:"HTML/Template";s:6:"md5sum";s:32:"8def35e6dae4a5db15ec026bc616a3d3";s:12:"installed_as";s:84:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/HTML_Template_IT/tests/ITX_api_testcase.php";}s:28:"tests/ITX_usage_testcase.php";a:4:{s:4:"role";s:4:"test";s:14:"baseinstalldir";s:13:"HTML/Template";s:6:"md5sum";s:32:"ec630d63df8163f75c4aa3b1e3051d2d";s:12:"installed_as";s:86:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/HTML_Template_IT/tests/ITX_usage_testcase.php";}s:14:"tests/test.php";a:4:{s:4:"role";s:4:"test";s:14:"baseinstalldir";s:13:"HTML/Template";s:6:"md5sum";s:32:"7a2c8eab843daf1cb9acebfd7fa5913d";s:12:"installed_as";s:72:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/HTML_Template_IT/tests/test.php";}s:22:"examples/sample_it.php";a:4:{s:4:"role";s:3:"doc";s:14:"baseinstalldir";s:13:"HTML/Template";s:6:"md5sum";s:32:"ba285cf25750a900690f2388ee31a103";s:12:"installed_as";s:79:"/www/htdocs/w00acdb0/lib/pear/PEAR/docs/HTML_Template_IT/examples/sample_it.php";}s:36:"examples/sample_itx_addblockfile.php";a:4:{s:4:"role";s:3:"doc";s:14:"baseinstalldir";s:13:"HTML/Template";s:6:"md5sum";s:32:"4b2a932053e321a0cf9ced5295113f09";s:12:"installed_as";s:93:"/www/htdocs/w00acdb0/lib/pear/PEAR/docs/HTML_Template_IT/examples/sample_itx_addblockfile.php";}s:31:"examples/templates/main.tpl.htm";a:4:{s:4:"role";s:3:"doc";s:14:"baseinstalldir";s:13:"HTML/Template";s:6:"md5sum";s:32:"834e1e6d40b2f34906aa17f9969bd891";s:12:"installed_as";s:88:"/www/htdocs/w00acdb0/lib/pear/PEAR/docs/HTML_Template_IT/examples/templates/main.tpl.htm";}s:44:"examples/templates/addblockfile_list.tpl.htm";a:4:{s:4:"role";s:3:"doc";s:14:"baseinstalldir";s:13:"HTML/Template";s:6:"md5sum";s:32:"342278cc5fe8ca6c66591cd5ee389402";s:12:"installed_as";s:101:"/www/htdocs/w00acdb0/lib/pear/PEAR/docs/HTML_Template_IT/examples/templates/addblockfile_list.tpl.htm";}s:44:"examples/templates/addblockfile_main.tpl.htm";a:4:{s:4:"role";s:3:"doc";s:14:"baseinstalldir";s:13:"HTML/Template";s:6:"md5sum";s:32:"697f694a67db6b96d247a24bdfd44f9b";s:12:"installed_as";s:101:"/www/htdocs/w00acdb0/lib/pear/PEAR/docs/HTML_Template_IT/examples/templates/addblockfile_main.tpl.htm";}}s:10:"xsdversion";s:3:"1.0";s:15:"packagerversion";s:5:"1.4.9";s:7:"package";s:16:"HTML_Template_IT";s:7:"summary";s:20:"Integrated Templates";s:11:"description";s:1198:"HTML_Template_IT: +Simple template API. +The Isotemplate API is somewhat tricky for a beginner although it is the best +one you can build. template::parse() [phplib template = Isotemplate] requests +you to name a source and a target where the current block gets parsed into. +Source and target can be block names or even handler names. This API gives you +a maximum of fexibility but you always have to know what you do which is +quite unusual for php skripter like me. + +I noticed that I do not any control on which block gets parsed into which one. +If all blocks are within one file, the script knows how they are nested and in +which way you have to parse them. IT knows that inner1 is a child of block2, there's +no need to tell him about this. +Features : + * Nested blocks + * Include external file + * Custom tags format (default {mytag}) + +HTML_Template_ITX : +With this class you get the full power of the phplib template class. +You may have one file with blocks in it but you have as well one main file +and multiple files one for each block. This is quite usefull when you have +user configurable websites. Using blocks not in the main template allows +you to modify some parts of your layout easily. + +";s:11:"maintainers";a:3:{i:0;a:4:{s:6:"handle";s:2:"uw";s:4:"name";s:10:"Ulf Wendel";s:5:"email";s:20:"ulf.wendel@phpdoc.de";s:4:"role";s:9:"developer";}i:1;a:4:{s:6:"handle";s:6:"pajoye";s:4:"name";s:17:"Pierre-Alain Joye";s:5:"email";s:14:"pajoye@php.net";s:4:"role";s:4:"lead";}i:2;a:4:{s:6:"handle";s:3:"dsp";s:4:"name";s:17:"David Soria Parra";s:5:"email";s:11:"dsp@php.net";s:4:"role";s:4:"lead";}}s:7:"version";s:5:"1.2.1";s:12:"release_date";s:10:"2006-08-25";s:15:"release_license";s:20:"Modified BSD license";s:13:"release_state";s:6:"stable";s:13:"release_notes";s:369:"- Deprecate $callbackobject parameter in setCallbackFunction +- Introduce $expandCallbackParameters parameter to setCallbackFunction to support + callbacks that expect to get the parameters in a regular way, not as an array +- #7651, allow dots in placeholder and block names +- #7611, wrong array initialized, the same object cannot be + used for multiple templates + +";s:9:"changelog";a:7:{i:0;a:4:{s:7:"version";s:5:"1.2.0";s:12:"release_date";s:10:"2006-08-17";s:13:"release_state";s:4:"beta";s:13:"release_notes";s:280:"- Deprecate $callbackobject parameter in setCallbackFunction +- Introduce $expandCallbackParameters parameter to setCallbackFunction to support + callbacks that expect to get the parameters in a regular way, not as an array +- #7651, allow dots in placeholder and block names + +";}i:1;a:4:{s:7:"version";s:5:"1.1.5";s:12:"release_date";s:10:"2006-06-13";s:13:"release_state";s:6:"stable";s:13:"release_notes";s:95:"- #7611, wrong array initialized, the same object cannot be + used for multiple templates + +";}i:2;a:4:{s:7:"version";s:5:"1.1.4";s:12:"release_date";s:10:"2006-04-12";s:13:"release_state";s:6:"stable";s:13:"release_notes";s:215:"- #6084, fread raises warning when used with empty files +- #7359, remove notices when a block is not yet defined +- fix a bug introduced with some cleanup commit, in some cases, + callbacks did not work anymore + +";}i:3;a:4:{s:7:"version";s:5:"1.1.3";s:12:"release_date";s:10:"2005-11-01";s:13:"release_state";s:6:"stable";s:13:"release_notes";s:96:"- Change to the new BSD License + (see http://www.opensource.org/licenses/bsd-license.php) + +";}i:4;a:4:{s:7:"version";s:5:"1.1.2";s:12:"release_date";s:10:"2005-10-28";s:13:"release_state";s:6:"stable";s:13:"release_notes";s:254:"- Comply better with the coding standards (dufuz@php.net) +- Fixed Bug #5774 ITX->buildFunctionlist, forced to use {} as delimiters + instead of the user defined once (dufuz@php.net) +- Fixed Bug #5642 Undefined variable: blockname (dufuz@php.net) + +";}i:5;a:4:{s:7:"version";s:5:"1.1.1";s:12:"release_date";s:10:"2003-08-21";s:13:"release_state";s:6:"stable";s:13:"release_notes";s:167:"- fix #4590, case sensitive method name getFile fix +- fix #1453, haltOnWarning fix, wrong property name called +- fix #3952, return IT_OK on success in setOptions + +";}i:6;a:4:{s:7:"version";s:3:"1.1";s:12:"release_date";s:10:"2003-03-11";s:13:"release_state";s:6:"stable";s:13:"release_notes";s:21:"*BETA* release. + +";}}s:12:"_lastversion";N;s:7:"dirtree";a:8:{s:48:"/www/htdocs/w00acdb0/lib/pear/PEAR/HTML/Template";b:1;s:39:"/www/htdocs/w00acdb0/lib/pear/PEAR/HTML";b:1;s:56:"/www/htdocs/w00acdb0/lib/pear/PEAR/docs/HTML_Template_IT";b:1;s:73:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/HTML_Template_IT/tests/templates";b:1;s:63:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/HTML_Template_IT/tests";b:1;s:57:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/HTML_Template_IT";b:1;s:65:"/www/htdocs/w00acdb0/lib/pear/PEAR/docs/HTML_Template_IT/examples";b:1;s:75:"/www/htdocs/w00acdb0/lib/pear/PEAR/docs/HTML_Template_IT/examples/templates";b:1;}s:13:"_lastmodified";i:1234655682;} \ No newline at end of file diff --git a/src/lib/pear/PEAR/.registry/mime_type.reg b/src/lib/pear/PEAR/.registry/mime_type.reg new file mode 100644 index 0000000..a17b50c --- /dev/null +++ b/src/lib/pear/PEAR/.registry/mime_type.reg @@ -0,0 +1,16 @@ +a:23:{s:7:"attribs";a:6:{s:15:"packagerversion";s:11:"1.8.0alpha1";s:7:"version";s:3:"2.0";s:5:"xmlns";s:35:"http://pear.php.net/dtd/package-2.0";s:11:"xmlns:tasks";s:33:"http://pear.php.net/dtd/tasks-1.0";s:9:"xmlns:xsi";s:41:"http://www.w3.org/2001/XMLSchema-instance";s:18:"xsi:schemaLocation";s:147:"http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd";}s:4:"name";s:9:"MIME_Type";s:7:"channel";s:12:"pear.php.net";s:7:"summary";s:41:"Utility class for dealing with MIME types";s:11:"description";s:360:"Provide functionality for dealing with MIME types. +* Parse MIME type. +* Supports full RFC2045 specification. +* Many utility functions for working with and determining info about types. +* Most functions can be called statically. +* Autodetect a files mime-type, either with fileinfo extension, + mime_magic extension, the file command or an in-built mapping list";s:4:"lead";a:4:{s:4:"name";s:8:"Ian Eure";s:4:"user";s:5:"ieure";s:5:"email";s:13:"ieure@php.net";s:6:"active";s:2:"no";}s:9:"developer";a:4:{s:4:"name";s:16:"Christian Weiske";s:4:"user";s:7:"cweiske";s:5:"email";s:15:"cweiske@php.net";s:6:"active";s:3:"yes";}s:4:"date";s:10:"2009-01-16";s:4:"time";s:8:"12:53:27";s:7:"version";a:2:{s:7:"release";s:5:"1.2.0";s:3:"api";s:5:"1.2.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";s:15:"PHP License 3.0";s:5:"notes";s:63:"* Extension-to-MIMEType mapper by Christian Schmidt, bug #13646";s:8:"contents";a:1:{s:3:"dir";a:2:{s:7:"attribs";a:1:{s:4:"name";s:1:"/";}s:4:"file";a:14:{i:0;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d4a7c9a53d3a0c9a293559f7ad8c7937";s:4:"name";s:25:"docs/examples/example.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:9:"@doc_dir@";s:2:"to";s:7:"doc_dir";s:4:"type";s:11:"pear-config";}}}i:1;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7d55b24a7aea73c90136af95ec1d0f61";s:4:"name";s:23:"MIME/Type/Parameter.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:9:"@version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:2;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2070ddcbb72b32da8178e37270b658c5";s:4:"name";s:23:"MIME/Type/Extension.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:9:"@version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:3;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"32e120db9437821b0958ed787920f04c";s:4:"name";s:13:"MIME/Type.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:9:"@version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:4;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e711aa23c64b7aba6fe0eb2514cd892b";s:4:"name";s:23:"tests/files/example.bmp";s:4:"role";s:4:"test";}}i:5;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"288a5568dad31d7e961aa4e0feb53acf";s:4:"name";s:23:"tests/files/example.gif";s:4:"role";s:4:"test";}}i:6;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"07e45f74fa45d72ca3ef3abf6d594974";s:4:"name";s:23:"tests/files/example.jpg";s:4:"role";s:4:"test";}}i:7;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"18891f92b7e1e1b5a480a70226d22a63";s:4:"name";s:23:"tests/files/example.png";s:4:"role";s:4:"test";}}i:8;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7926caaf09e43134fcb571fb1278a678";s:4:"name";s:23:"tests/files/example.txt";s:4:"role";s:4:"test";}}i:9;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1fd5d673c016a26fa5385132a3675ba3";s:4:"name";s:27:"tests/files/example.txt.bz2";s:4:"role";s:4:"test";}}i:10;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"bca061774f382a151df680eb5c2a6d9c";s:4:"name";s:26:"tests/files/example.txt.gz";s:4:"role";s:4:"test";}}i:11;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e37bbe113ba9938069d67ecab300142a";s:4:"name";s:18:"tests/AllTests.php";s:4:"role";s:4:"test";}}i:12;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"bc10846e3755c7729d5f37416c0883d8";s:4:"name";s:18:"tests/TypeTest.php";s:4:"role";s:4:"test";}}i:13;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"cac94e4f71b33607dd4f3a79a670d568";s:4:"name";s:33:"tests/MIME_Type_ExtensionTest.php";s:4:"role";s:4:"test";}}}}}s:12:"dependencies";a:2:{s:8:"required";a:3:{s:3:"php";a:1:{s:3:"min";s:5:"4.3.0";}s:13:"pearinstaller";a:1:{s:3:"min";s:5:"1.4.0";}s:7:"package";a:3:{s:4:"name";s:4:"PEAR";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:5:"1.4.0";}}s:8:"optional";a:1:{s:7:"package";a:2:{s:4:"name";s:14:"System_Command";s:7:"channel";s:12:"pear.php.net";}}}s:10:"phprelease";s:0:"";s:9:"changelog";a:1:{s:7:"release";a:9:{i:0;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.2.0";s:3:"api";s:5:"1.2.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2009-01-16";s:7:"license";s:15:"PHP License 3.0";s:5:"notes";s:63:"* Extension-to-MIMEType mapper by Christian Schmidt, bug #13646";}i:1;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.1.3";s:3:"api";s:5:"1.1.2";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2008-08-03";s:7:"license";s:15:"PHP License 3.0";s:5:"notes";s:83:"- Coding Standards cleanup +- parameters are cleared when parsing again +- more tests";}i:2;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.1.2";s:3:"api";s:5:"1.1.2";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2008-08-01";s:7:"license";s:15:"PHP License 3.0";s:5:"notes";s:81:"- Fix bug #14417: Remove "$comments = null" since that's not supported + in PHP4.";}i:3;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.1.1";s:3:"api";s:5:"1.1.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2008-07-24";s:7:"license";s:15:"PHP License 3.0";s:5:"notes";s:42:"- Fix #14150, notices due to use of = new.";}i:4;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.1.0";s:3:"api";s:5:"1.1.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2007-03-25";s:7:"license";s:15:"PHP License 3.0";s:5:"notes";s:283:"- Implementing request #3719: Use several methods when detecting mime type +- Fixing bug #6095: Parameters and comments parsing buggy +- Fixing bug #8603: function _fileAutoDetect() uses System_Command incorrectly +- Make example.php check for errors when detecting. +- Adding unit tests";}i:5;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.0.0";s:3:"api";s:5:"1.0.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2005-01-26";s:7:"license";s:15:"PHP License 3.0";s:5:"notes";s:30:"- No changes since 1.0.0beta3.";}i:6;a:5:{s:7:"version";a:2:{s:7:"release";s:10:"1.0.0beta3";s:3:"api";s:10:"1.0.0beta3";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:4:"beta";}s:4:"date";s:10:"2004-08-07";s:7:"license";s:15:"PHP License 3.0";s:5:"notes";s:95:"* Add $parameters class var. (Fixes #2083) +* Quote filenames in _fileAutoDetect() (Fixes #2078)";}i:7;a:5:{s:7:"version";a:2:{s:7:"release";s:10:"1.0.0beta2";s:3:"api";s:10:"1.0.0beta2";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:4:"beta";}s:4:"date";s:10:"2004-06-16";s:7:"license";s:15:"PHP License 3.0";s:5:"notes";s:61:"* Make changes as requested during the proposal/vote process.";}i:8;a:5:{s:7:"version";a:2:{s:7:"release";s:10:"1.0.0beta1";s:3:"api";s:10:"1.0.0beta1";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:4:"beta";}s:4:"date";s:10:"2004-04-16";s:7:"license";s:15:"PHP License 3.0";s:5:"notes";s:74:"Initial PEARification +* Split most functionality off from MIME_ContentType";}}}s:8:"filelist";a:14:{s:25:"docs/examples/example.php";a:4:{s:6:"md5sum";s:32:"d4a7c9a53d3a0c9a293559f7ad8c7937";s:4:"name";s:25:"docs/examples/example.php";s:4:"role";s:3:"php";s:12:"installed_as";s:60:"/www/htdocs/w00acdb0/lib/pear/PEAR/docs/examples/example.php";}s:23:"MIME/Type/Parameter.php";a:4:{s:6:"md5sum";s:32:"7d55b24a7aea73c90136af95ec1d0f61";s:4:"name";s:23:"MIME/Type/Parameter.php";s:4:"role";s:3:"php";s:12:"installed_as";s:58:"/www/htdocs/w00acdb0/lib/pear/PEAR/MIME/Type/Parameter.php";}s:23:"MIME/Type/Extension.php";a:4:{s:6:"md5sum";s:32:"2070ddcbb72b32da8178e37270b658c5";s:4:"name";s:23:"MIME/Type/Extension.php";s:4:"role";s:3:"php";s:12:"installed_as";s:58:"/www/htdocs/w00acdb0/lib/pear/PEAR/MIME/Type/Extension.php";}s:13:"MIME/Type.php";a:4:{s:6:"md5sum";s:32:"32e120db9437821b0958ed787920f04c";s:4:"name";s:13:"MIME/Type.php";s:4:"role";s:3:"php";s:12:"installed_as";s:48:"/www/htdocs/w00acdb0/lib/pear/PEAR/MIME/Type.php";}s:23:"tests/files/example.bmp";a:4:{s:6:"md5sum";s:32:"e711aa23c64b7aba6fe0eb2514cd892b";s:4:"name";s:23:"tests/files/example.bmp";s:4:"role";s:4:"test";s:12:"installed_as";s:74:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/MIME_Type/tests/files/example.bmp";}s:23:"tests/files/example.gif";a:4:{s:6:"md5sum";s:32:"288a5568dad31d7e961aa4e0feb53acf";s:4:"name";s:23:"tests/files/example.gif";s:4:"role";s:4:"test";s:12:"installed_as";s:74:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/MIME_Type/tests/files/example.gif";}s:23:"tests/files/example.jpg";a:4:{s:6:"md5sum";s:32:"07e45f74fa45d72ca3ef3abf6d594974";s:4:"name";s:23:"tests/files/example.jpg";s:4:"role";s:4:"test";s:12:"installed_as";s:74:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/MIME_Type/tests/files/example.jpg";}s:23:"tests/files/example.png";a:4:{s:6:"md5sum";s:32:"18891f92b7e1e1b5a480a70226d22a63";s:4:"name";s:23:"tests/files/example.png";s:4:"role";s:4:"test";s:12:"installed_as";s:74:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/MIME_Type/tests/files/example.png";}s:23:"tests/files/example.txt";a:4:{s:6:"md5sum";s:32:"7926caaf09e43134fcb571fb1278a678";s:4:"name";s:23:"tests/files/example.txt";s:4:"role";s:4:"test";s:12:"installed_as";s:74:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/MIME_Type/tests/files/example.txt";}s:27:"tests/files/example.txt.bz2";a:4:{s:6:"md5sum";s:32:"1fd5d673c016a26fa5385132a3675ba3";s:4:"name";s:27:"tests/files/example.txt.bz2";s:4:"role";s:4:"test";s:12:"installed_as";s:78:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/MIME_Type/tests/files/example.txt.bz2";}s:26:"tests/files/example.txt.gz";a:4:{s:6:"md5sum";s:32:"bca061774f382a151df680eb5c2a6d9c";s:4:"name";s:26:"tests/files/example.txt.gz";s:4:"role";s:4:"test";s:12:"installed_as";s:77:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/MIME_Type/tests/files/example.txt.gz";}s:18:"tests/AllTests.php";a:4:{s:6:"md5sum";s:32:"e37bbe113ba9938069d67ecab300142a";s:4:"name";s:18:"tests/AllTests.php";s:4:"role";s:4:"test";s:12:"installed_as";s:69:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/MIME_Type/tests/AllTests.php";}s:18:"tests/TypeTest.php";a:4:{s:6:"md5sum";s:32:"bc10846e3755c7729d5f37416c0883d8";s:4:"name";s:18:"tests/TypeTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:69:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/MIME_Type/tests/TypeTest.php";}s:33:"tests/MIME_Type_ExtensionTest.php";a:4:{s:6:"md5sum";s:32:"cac94e4f71b33607dd4f3a79a670d568";s:4:"name";s:33:"tests/MIME_Type_ExtensionTest.php";s:4:"role";s:4:"test";s:12:"installed_as";s:84:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/MIME_Type/tests/MIME_Type_ExtensionTest.php";}}s:12:"_lastversion";N;s:7:"dirtree";a:7:{s:48:"/www/htdocs/w00acdb0/lib/pear/PEAR/docs/examples";b:1;s:39:"/www/htdocs/w00acdb0/lib/pear/PEAR/docs";b:1;s:44:"/www/htdocs/w00acdb0/lib/pear/PEAR/MIME/Type";b:1;s:39:"/www/htdocs/w00acdb0/lib/pear/PEAR/MIME";b:1;s:62:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/MIME_Type/tests/files";b:1;s:56:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/MIME_Type/tests";b:1;s:50:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/MIME_Type";b:1;}s:3:"old";a:7:{s:7:"version";s:5:"1.2.0";s:12:"release_date";s:10:"2009-01-16";s:13:"release_state";s:6:"stable";s:15:"release_license";s:15:"PHP License 3.0";s:13:"release_notes";s:63:"* Extension-to-MIMEType mapper by Christian Schmidt, bug #13646";s:12:"release_deps";a:4:{i:0;a:4:{s:4:"type";s:3:"php";s:3:"rel";s:2:"ge";s:7:"version";s:5:"4.3.0";s:8:"optional";s:2:"no";}i:1;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:4:"PEAR";s:3:"rel";s:2:"ge";s:7:"version";s:5:"1.4.0";s:8:"optional";s:2:"no";}i:2;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:4:"PEAR";s:3:"rel";s:2:"ge";s:7:"version";s:5:"1.4.0";s:8:"optional";s:2:"no";}i:3;a:5:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:14:"System_Command";s:3:"rel";s:3:"has";s:8:"optional";s:3:"yes";}}s:11:"maintainers";a:2:{i:0;a:5:{s:4:"name";s:8:"Ian Eure";s:5:"email";s:13:"ieure@php.net";s:6:"active";s:2:"no";s:6:"handle";s:5:"ieure";s:4:"role";s:4:"lead";}i:1;a:5:{s:4:"name";s:16:"Christian Weiske";s:5:"email";s:15:"cweiske@php.net";s:6:"active";s:3:"yes";s:6:"handle";s:7:"cweiske";s:4:"role";s:9:"developer";}}}s:10:"xsdversion";s:3:"2.0";s:13:"_lastmodified";i:1234655686;} \ No newline at end of file diff --git a/src/lib/pear/PEAR/.registry/pear.reg b/src/lib/pear/PEAR/.registry/pear.reg new file mode 100644 index 0000000..4ccc7f0 --- /dev/null +++ b/src/lib/pear/PEAR/.registry/pear.reg @@ -0,0 +1,161 @@ +a:24:{s:7:"attribs";a:6:{s:15:"packagerversion";s:5:"1.7.2";s:7:"version";s:3:"2.0";s:5:"xmlns";s:35:"http://pear.php.net/dtd/package-2.0";s:11:"xmlns:tasks";s:33:"http://pear.php.net/dtd/tasks-1.0";s:9:"xmlns:xsi";s:41:"http://www.w3.org/2001/XMLSchema-instance";s:18:"xsi:schemaLocation";s:147:"http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd";}s:4:"name";s:4:"PEAR";s:7:"channel";s:12:"pear.php.net";s:7:"summary";s:16:"PEAR Base System";s:11:"description";s:1101:"The PEAR package contains: + * the PEAR installer, for creating, distributing + and installing packages + * the PEAR_Exception PHP5 error handling mechanism + * the PEAR_ErrorStack advanced error handling mechanism + * the PEAR_Error error handling mechanism + * the OS_Guess class for retrieving info about the OS + where PHP is running on + * the System class for quick handling of common operations + with files and directories + * the PEAR base class + + Features in a nutshell: + * full support for channels + * pre-download dependency validation + * new package.xml 2.0 format allows tremendous flexibility while maintaining BC + * support for optional dependency groups and limited support for sub-packaging + * robust dependency support + * full dependency validation on uninstall + * remote install for hosts with only ftp access - no more problems with + restricted host installation + * full support for mirroring + * support for bundling several packages into a single tarball + * support for static dependencies on a url-based package + * support for custom file roles and installation tasks";s:4:"lead";a:4:{i:0;a:4:{s:4:"name";s:11:"Greg Beaver";s:4:"user";s:6:"cellog";s:5:"email";s:14:"cellog@php.net";s:6:"active";s:3:"yes";}i:1;a:4:{s:4:"name";s:17:"Pierre-Alain Joye";s:4:"user";s:6:"pajoye";s:5:"email";s:14:"pierre@php.net";s:6:"active";s:2:"no";}i:2;a:4:{s:4:"name";s:11:"Stig Bakken";s:4:"user";s:3:"ssb";s:5:"email";s:12:"stig@php.net";s:6:"active";s:2:"no";}i:3;a:4:{s:4:"name";s:13:"Tomas V.V.Cox";s:4:"user";s:3:"cox";s:5:"email";s:15:"cox@idecnet.com";s:6:"active";s:2:"no";}}s:9:"developer";a:2:{i:0;a:4:{s:4:"name";s:13:"Helgi Thormar";s:4:"user";s:5:"dufuz";s:5:"email";s:13:"dufuz@php.net";s:6:"active";s:3:"yes";}i:1;a:4:{s:4:"name";s:9:"Tias Guns";s:4:"user";s:4:"tias";s:5:"email";s:12:"tias@php.net";s:6:"active";s:3:"yes";}}s:6:"helper";a:3:{i:0;a:4:{s:4:"name";s:11:"Tim Jackson";s:4:"user";s:4:"timj";s:5:"email";s:12:"timj@php.net";s:6:"active";s:2:"no";}i:1;a:4:{s:4:"name";s:15:"Bertrand Gugger";s:4:"user";s:5:"toggg";s:5:"email";s:13:"toggg@php.net";s:6:"active";s:2:"no";}i:2;a:4:{s:4:"name";s:13:"Martin Jansen";s:4:"user";s:2:"mj";s:5:"email";s:10:"mj@php.net";s:6:"active";s:2:"no";}}s:4:"date";s:10:"2008-05-17";s:4:"time";s:8:"14:50:14";s:7:"version";a:2:{s:7:"release";s:5:"1.7.2";s:3:"api";s:5:"1.7.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:1625:"* Implement Request #13375: install-pear.php should have option to set cfg_dir [timj] +* Fix Bug #12945 PEAR_Registry::setConfig() does not set install path [cweiske/cellog] +* Fix Bug #12959 PEAR should give warning when doing "special" handling with cfg role [cellog] +* Fix Bug #12960 role=cfg should automatically replace file if it has not been modified [cellog] +* Fix Bug #13031 PEAR fails to authenticate when doing upgrade-all on non-default channel [timj] +* Fix Bug #13033 Signature to PEAR_REST_XX::listAll() changes between REST1.0 and 1.1 [timj] +* Fix Bug #13059 Invalid release type causes Undefined Property notice [gwynne, dufuz] +* Fix Bug #13123 pear config-set works, but pecl config-set does not [cellog] +* Fix Bug #13323 Deprecated errors in many places [hubbitus] +* Fix Bug #13315 Upgrading of package fails if more than one file of role=cfg has changed [timj] +* Fix Bug #13386 "pear install --register-only" fails with cfg role [cellog] +* Fix Bug #13434 Breaks on HPUX - "find () -ls" doesn't work [cellog] +* Fix Bug #13484 pear package brings up warnings [dufuz] +* Fix Bug #13485 pear package-validate brings up ASCII issues [dufuz] +* Fix Bug #13508 undefined index errors when installing a remote bundle [cellog/tswicegood] +* Fix Bug #13525 pear package-validate is not showing warnings even if there are [dufuz] +* Fix Bug #13559 installing package fails via proxy to virtual-hosted server. [hirose] +* Fix Bug #13691 Pear doesn't remove old directories on upgrade [cellog] +* Fix Bug #13870 Notice uninstalling or using bundles [cellog] +* Fix Bug #13883 file permissions not preserved on packaging [cellog]";s:8:"contents";a:1:{s:3:"dir";a:2:{s:7:"attribs";a:1:{s:4:"name";s:1:"/";}s:4:"file";a:105:{i:0;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4fa6b540f217ae9dbab8975f8b93d200";s:4:"name";s:12:"OS/Guess.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:1;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2da630f82eca1531a57fe04696e26a06";s:4:"name";s:27:"PEAR/ChannelFile/Parser.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:2;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"381496e0186e16d613ddb01564fca4a0";s:4:"name";s:21:"PEAR/Command/Auth.xml";s:4:"role";s:3:"php";}}i:3;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2bd9a76a6932fe9fb4fe80d06fd099d4";s:4:"name";s:21:"PEAR/Command/Auth.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:4;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"73602fd7f051eaf8d37452d0e3063bdb";s:4:"name";s:22:"PEAR/Command/Build.xml";s:4:"role";s:3:"php";}}i:5;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2af3d1912b4b6aef6bf17db5e01f257e";s:4:"name";s:22:"PEAR/Command/Build.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:6;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5dfb7898501c43ab655c5f9b7176ea20";s:4:"name";s:25:"PEAR/Command/Channels.xml";s:4:"role";s:3:"php";}}i:7;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5876be616c6e401fd911fb6f5c50b102";s:4:"name";s:25:"PEAR/Command/Channels.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:8;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"22079bbfa5f8ac010683cb0cd84af21f";s:4:"name";s:23:"PEAR/Command/Common.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:9;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"91f189cb9423b5e87ee0abc5ea1a2be3";s:4:"name";s:23:"PEAR/Command/Config.xml";s:4:"role";s:3:"php";}}i:10;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"8d36af1a687b1648a474008e6e2b0239";s:4:"name";s:23:"PEAR/Command/Config.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:11;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e0f361c6ebda100653e550a762a66a06";s:4:"name";s:24:"PEAR/Command/Install.xml";s:4:"role";s:3:"php";}}i:12;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b1954beca05df6a53595112ca12f2cad";s:4:"name";s:24:"PEAR/Command/Install.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:13;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5cb62a04c0a268f4edd64a49a3895c92";s:4:"name";s:23:"PEAR/Command/Mirror.xml";s:4:"role";s:3:"php";}}i:14;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b1c6d624fa98d7f95948e1bca76c46b5";s:4:"name";s:23:"PEAR/Command/Mirror.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:15;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"bbf88f26cd10b1caa76d5eec474f093f";s:4:"name";s:24:"PEAR/Command/Package.xml";s:4:"role";s:3:"php";}}i:16;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"cb6f4b8cf4f297200d1ddb35b768d65f";s:4:"name";s:24:"PEAR/Command/Package.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:2:{i:0;a:1:{s:7:"attribs";a:3:{s:4:"from";s:10:"@DATA-DIR@";s:2:"to";s:8:"data_dir";s:4:"type";s:11:"pear-config";}}i:1;a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}}i:17;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"29c0947f423695818f90759e65376e5c";s:4:"name";s:23:"PEAR/Command/Pickle.xml";s:4:"role";s:3:"php";}}i:18;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b7777e69e2b771a9f691fb4fade4686a";s:4:"name";s:23:"PEAR/Command/Pickle.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:19;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"49b046cfc14747f0365e02e9c3f0e6dc";s:4:"name";s:25:"PEAR/Command/Registry.xml";s:4:"role";s:3:"php";}}i:20;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0e6a7070d8b3bfe5160255b5f5352425";s:4:"name";s:25:"PEAR/Command/Registry.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:21;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"05729e322af29b0ddcdd85559e44cd41";s:4:"name";s:23:"PEAR/Command/Remote.xml";s:4:"role";s:3:"php";}}i:22;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"61cf1731830f4adbb51335a890570b8a";s:4:"name";s:23:"PEAR/Command/Remote.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:23;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"118af6fbf9c37e90957f0bb9d5cf9d82";s:4:"name";s:21:"PEAR/Command/Test.xml";s:4:"role";s:3:"php";}}i:24;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9bd7498ec025144d036a1ca34b0f4365";s:4:"name";s:21:"PEAR/Command/Test.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:25;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4ee3dab326b3f108574d001ca74f1620";s:4:"name";s:27:"PEAR/Downloader/Package.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:10:"@PEAR-VER@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:26;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4d43b606e210a61e003fcea2a46d0fd4";s:4:"name";s:21:"PEAR/Frontend/CLI.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:27;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"82094070511d6369af82529bb8194c8b";s:4:"name";s:30:"PEAR/Installer/Role/Common.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:28;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d8c62e6275e3aaa7784290912406092c";s:4:"name";s:27:"PEAR/Installer/Role/Cfg.xml";s:4:"role";s:3:"php";}}i:29;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3fb2045c4328ba0f0791e6c46aabce8a";s:4:"name";s:27:"PEAR/Installer/Role/Cfg.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:30;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"89a4a2a286e842d45a98974f40a0565c";s:4:"name";s:28:"PEAR/Installer/Role/Data.xml";s:4:"role";s:3:"php";}}i:31;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d505eea75d38763c94f92e639580201a";s:4:"name";s:28:"PEAR/Installer/Role/Data.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:32;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b1ce0fe105251c3b75209d6518ee69ac";s:4:"name";s:27:"PEAR/Installer/Role/Doc.xml";s:4:"role";s:3:"php";}}i:33;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d381e479248b847e1fba152dc95f10d4";s:4:"name";s:27:"PEAR/Installer/Role/Doc.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:34;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"af71c0ad42d16a323afe24a4f884ef15";s:4:"name";s:27:"PEAR/Installer/Role/Ext.xml";s:4:"role";s:3:"php";}}i:35;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"205b68b09e62134f965c16bdac37bcc7";s:4:"name";s:27:"PEAR/Installer/Role/Ext.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:36;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ef88f0321d3e481c2130c95122cf76d8";s:4:"name";s:27:"PEAR/Installer/Role/Php.xml";s:4:"role";s:3:"php";}}i:37;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"284067a202f05fc1b62981d7c0b10419";s:4:"name";s:27:"PEAR/Installer/Role/Php.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:38;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"746461dc3b48af6d24094cb0211608f2";s:4:"name";s:30:"PEAR/Installer/Role/Script.xml";s:4:"role";s:3:"php";}}i:39;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c879348f293100cc0c78220c4de6d711";s:4:"name";s:30:"PEAR/Installer/Role/Script.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:40;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e147d63f168ea156fc2be38caaa63804";s:4:"name";s:27:"PEAR/Installer/Role/Src.xml";s:4:"role";s:3:"php";}}i:41;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e0200455cde8eba003dff160b3657c43";s:4:"name";s:27:"PEAR/Installer/Role/Src.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:42;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a24b596ec987aa5688fc19e8ed4e97ea";s:4:"name";s:28:"PEAR/Installer/Role/Test.xml";s:4:"role";s:3:"php";}}i:43;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"47f59482d09100bc9ad7e137785855e7";s:4:"name";s:28:"PEAR/Installer/Role/Test.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:44;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7641e71c5785bb33a4261ebe25ed0fd7";s:4:"name";s:27:"PEAR/Installer/Role/Www.xml";s:4:"role";s:3:"php";}}i:45;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"0076ccbaa7a6208559df11aa3eb798b5";s:4:"name";s:27:"PEAR/Installer/Role/Www.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:46;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"273540b734ed43343649c416a4f52a99";s:4:"name";s:23:"PEAR/Installer/Role.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:47;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9ff6a4888868c72abf2433f8dfc40be6";s:4:"name";s:33:"PEAR/PackageFile/Generator/v1.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:10:"@PEAR-VER@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:48;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b23f0359cd3306c87bd027eefff38892";s:4:"name";s:33:"PEAR/PackageFile/Generator/v2.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:10:"@PEAR-VER@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:49;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e439d694e4e2c3b4146ee308a2758f5a";s:4:"name";s:30:"PEAR/PackageFile/Parser/v1.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:50;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9fdba40240a1a72820780b5d6184391b";s:4:"name";s:30:"PEAR/PackageFile/Parser/v2.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:51;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c56d70ed9adb2071e530142ed6d296ab";s:4:"name";s:26:"PEAR/PackageFile/v2/rw.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:52;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"85530152fe2098b549ef8e9cbc727f8c";s:4:"name";s:33:"PEAR/PackageFile/v2/Validator.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:53;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"63a79337dfe25c16aee1ce9b136f7044";s:4:"name";s:23:"PEAR/PackageFile/v1.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:54;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1fdb0bd1548aafec891aa6d9580ea59b";s:4:"name";s:23:"PEAR/PackageFile/v2.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:55;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3284fc0ec89030c9d841200beecbf4fa";s:4:"name";s:16:"PEAR/REST/10.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:56;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"71d7072f1cdf9f2065205f4585a2ecc6";s:4:"name";s:16:"PEAR/REST/11.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:57;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"619b085112e10287e66197cc4fc6acaa";s:4:"name";s:16:"PEAR/REST/13.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:58;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9339412e86586c299727121e08adefba";s:4:"name";s:34:"PEAR/Task/Postinstallscript/rw.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:59;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9fe592cd22a83915d796a11af6331606";s:4:"name";s:24:"PEAR/Task/Replace/rw.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:60;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3c7a6eb3a4e207f665f06093cb8bcdf9";s:4:"name";s:24:"PEAR/Task/Unixeol/rw.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:61;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1a390d0f5b489d7f61f9e6682203bcc3";s:4:"name";s:27:"PEAR/Task/Windowseol/rw.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:62;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b5a728f8d59013ab6d5077f27b517a96";s:4:"name";s:20:"PEAR/Task/Common.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:63;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b9e5cc9fed2ebad6d2011ee6a4d592bf";s:4:"name";s:31:"PEAR/Task/Postinstallscript.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:64;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5a3d680bb9c327530f696d830b8b605b";s:4:"name";s:21:"PEAR/Task/Replace.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:65;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f9dc0e5d8d8957ea207d9da8e37dcb26";s:4:"name";s:21:"PEAR/Task/Unixeol.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:66;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2ce493f5d43d7df681a1b45034060904";s:4:"name";s:24:"PEAR/Task/Windowseol.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:67;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2ae06a82c9f955f68c31fdc11bf217c5";s:4:"name";s:23:"PEAR/Validator/PECL.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:68;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9cd95af3af7654b473842723cc7c1bec";s:4:"name";s:19:"PEAR/Autoloader.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:69;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"062dc2dba3349a8f2cadb9e81320cfdb";s:4:"name";s:16:"PEAR/Builder.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:10:"@PEAR-VER@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:70;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"54638616d9fae90609ef027430b86656";s:4:"name";s:20:"PEAR/ChannelFile.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:71;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"7147a5789e7f15c85f3b23d4ffb6b236";s:4:"name";s:16:"PEAR/Command.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:72;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a7ec0f20c252a9cb436968bc9f5635da";s:4:"name";s:15:"PEAR/Common.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:73;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d18ae493cc76570cecff6d6dddc24d3b";s:4:"name";s:15:"PEAR/Config.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:74;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"bcfff6330848fa83118e1ff11b3d7ba0";s:4:"name";s:19:"PEAR/Dependency.php";s:4:"role";s:3:"php";}}i:75;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"f48a05aee6a88319eb2b45a9a649b0f0";s:4:"name";s:21:"PEAR/DependencyDB.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:76;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"893b4e4250ca595dc41c596a60e36de2";s:4:"name";s:20:"PEAR/Dependency2.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:10:"@PEAR-VER@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:77;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c631755222fd7ae155cce369ae46f929";s:4:"name";s:19:"PEAR/Downloader.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:78;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"cf883c744c4be529a3a75b235608eaa4";s:4:"name";s:19:"PEAR/ErrorStack.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:79;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"60040e0928e18981a9ccb036e54db840";s:4:"name";s:18:"PEAR/Exception.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:80;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"e0e4cbcec4a972fbad779d0f9d323120";s:4:"name";s:28:"PEAR/FixPHP5PEARWarnings.php";s:4:"role";s:3:"php";}}i:81;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"d26049bf4358619459eac6bd08e0c61e";s:4:"name";s:17:"PEAR/Frontend.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:82;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"828e42237cd8b0e04a2cf0a5b13099f2";s:4:"name";s:18:"PEAR/Installer.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:83;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4546fbff936d36496c30227f20d5b6a7";s:4:"name";s:20:"PEAR/PackageFile.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:10:"@PEAR-VER@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:84;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"c1708307d9a6037f60ef4cf130b8c1d9";s:4:"name";s:17:"PEAR/Packager.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:85;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"eb579ef0fbff7c72a2f272a90550337e";s:4:"name";s:17:"PEAR/Registry.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:86;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ac90346df7467a1b43b9392069a87750";s:4:"name";s:15:"PEAR/Remote.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:87;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"b8c5c610bcf441261b6101c6ed176e96";s:4:"name";s:13:"PEAR/REST.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:88;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"3345c49c04db53a8424a25985bd69633";s:4:"name";s:16:"PEAR/RunTest.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:89;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2f97edd3496adace0a0e5c9f1b70ae76";s:4:"name";s:17:"PEAR/Validate.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:90;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"dab39738e174b584eebc71bd3ece7a91";s:4:"name";s:18:"PEAR/XMLParser.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:91;a:3:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"bd65b087b7707463525e9f0092337793";s:4:"name";s:16:"scripts/pear.bat";s:4:"role";s:6:"script";}s:13:"tasks:replace";a:3:{i:0;a:1:{s:7:"attribs";a:3:{s:4:"from";s:9:"@bin_dir@";s:2:"to";s:7:"bin_dir";s:4:"type";s:11:"pear-config";}}i:1;a:1:{s:7:"attribs";a:3:{s:4:"from";s:9:"@php_bin@";s:2:"to";s:7:"php_bin";s:4:"type";s:11:"pear-config";}}i:2;a:1:{s:7:"attribs";a:3:{s:4:"from";s:14:"@include_path@";s:2:"to";s:7:"php_dir";s:4:"type";s:11:"pear-config";}}}s:16:"tasks:windowseol";s:0:"";}i:92;a:3:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"f92ee8acc4f00a7ca9ffedc1fe959b69";s:4:"name";s:19:"scripts/peardev.bat";s:4:"role";s:6:"script";}s:13:"tasks:replace";a:3:{i:0;a:1:{s:7:"attribs";a:3:{s:4:"from";s:9:"@bin_dir@";s:2:"to";s:7:"bin_dir";s:4:"type";s:11:"pear-config";}}i:1;a:1:{s:7:"attribs";a:3:{s:4:"from";s:9:"@php_bin@";s:2:"to";s:7:"php_bin";s:4:"type";s:11:"pear-config";}}i:2;a:1:{s:7:"attribs";a:3:{s:4:"from";s:14:"@include_path@";s:2:"to";s:7:"php_dir";s:4:"type";s:11:"pear-config";}}}s:16:"tasks:windowseol";s:0:"";}i:93;a:3:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"34c1cb834dd1c03c9e40998b201d52e0";s:4:"name";s:16:"scripts/pecl.bat";s:4:"role";s:6:"script";}s:13:"tasks:replace";a:3:{i:0;a:1:{s:7:"attribs";a:3:{s:4:"from";s:9:"@bin_dir@";s:2:"to";s:7:"bin_dir";s:4:"type";s:11:"pear-config";}}i:1;a:1:{s:7:"attribs";a:3:{s:4:"from";s:9:"@php_bin@";s:2:"to";s:7:"php_bin";s:4:"type";s:11:"pear-config";}}i:2;a:1:{s:7:"attribs";a:3:{s:4:"from";s:14:"@include_path@";s:2:"to";s:7:"php_dir";s:4:"type";s:11:"pear-config";}}}s:16:"tasks:windowseol";s:0:"";}i:94;a:3:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"5b495a3de3c6092bfbd93806937a0e4e";s:4:"name";s:15:"scripts/pear.sh";s:4:"role";s:6:"script";}s:13:"tasks:replace";a:4:{i:0;a:1:{s:7:"attribs";a:3:{s:4:"from";s:9:"@php_bin@";s:2:"to";s:7:"php_bin";s:4:"type";s:11:"pear-config";}}i:1;a:1:{s:7:"attribs";a:3:{s:4:"from";s:9:"@php_dir@";s:2:"to";s:7:"php_dir";s:4:"type";s:11:"pear-config";}}i:2;a:1:{s:7:"attribs";a:3:{s:4:"from";s:14:"@pear_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}i:3;a:1:{s:7:"attribs";a:3:{s:4:"from";s:14:"@include_path@";s:2:"to";s:7:"php_dir";s:4:"type";s:11:"pear-config";}}}s:13:"tasks:unixeol";s:0:"";}i:95;a:3:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"c69b7eb6cf9198ef8f03a19dcb57ca42";s:4:"name";s:18:"scripts/peardev.sh";s:4:"role";s:6:"script";}s:13:"tasks:replace";a:4:{i:0;a:1:{s:7:"attribs";a:3:{s:4:"from";s:9:"@php_bin@";s:2:"to";s:7:"php_bin";s:4:"type";s:11:"pear-config";}}i:1;a:1:{s:7:"attribs";a:3:{s:4:"from";s:9:"@php_dir@";s:2:"to";s:7:"php_dir";s:4:"type";s:11:"pear-config";}}i:2;a:1:{s:7:"attribs";a:3:{s:4:"from";s:14:"@pear_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}i:3;a:1:{s:7:"attribs";a:3:{s:4:"from";s:14:"@include_path@";s:2:"to";s:7:"php_dir";s:4:"type";s:11:"pear-config";}}}s:13:"tasks:unixeol";s:0:"";}i:96;a:3:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"d00c55f2aa48052c25db271e044e7551";s:4:"name";s:15:"scripts/pecl.sh";s:4:"role";s:6:"script";}s:13:"tasks:replace";a:4:{i:0;a:1:{s:7:"attribs";a:3:{s:4:"from";s:9:"@php_bin@";s:2:"to";s:7:"php_bin";s:4:"type";s:11:"pear-config";}}i:1;a:1:{s:7:"attribs";a:3:{s:4:"from";s:9:"@php_dir@";s:2:"to";s:7:"php_dir";s:4:"type";s:11:"pear-config";}}i:2;a:1:{s:7:"attribs";a:3:{s:4:"from";s:14:"@pear_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}i:3;a:1:{s:7:"attribs";a:3:{s:4:"from";s:14:"@include_path@";s:2:"to";s:7:"php_dir";s:4:"type";s:11:"pear-config";}}}s:13:"tasks:unixeol";s:0:"";}i:97;a:2:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"a398d2c6875a38dc38aa399f3fa12e49";s:4:"name";s:19:"scripts/pearcmd.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:4:{i:0;a:1:{s:7:"attribs";a:3:{s:4:"from";s:9:"@php_bin@";s:2:"to";s:7:"php_bin";s:4:"type";s:11:"pear-config";}}i:1;a:1:{s:7:"attribs";a:3:{s:4:"from";s:9:"@php_dir@";s:2:"to";s:7:"php_dir";s:4:"type";s:11:"pear-config";}}i:2;a:1:{s:7:"attribs";a:3:{s:4:"from";s:14:"@pear_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}i:3;a:1:{s:7:"attribs";a:3:{s:4:"from";s:14:"@include_path@";s:2:"to";s:7:"php_dir";s:4:"type";s:11:"pear-config";}}}}i:98;a:2:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"6356b5beefa80d0bbfd234d222873c7d";s:4:"name";s:19:"scripts/peclcmd.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:4:{i:0;a:1:{s:7:"attribs";a:3:{s:4:"from";s:9:"@php_bin@";s:2:"to";s:7:"php_bin";s:4:"type";s:11:"pear-config";}}i:1;a:1:{s:7:"attribs";a:3:{s:4:"from";s:9:"@php_dir@";s:2:"to";s:7:"php_dir";s:4:"type";s:11:"pear-config";}}i:2;a:1:{s:7:"attribs";a:3:{s:4:"from";s:14:"@pear_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}i:3;a:1:{s:7:"attribs";a:3:{s:4:"from";s:14:"@include_path@";s:2:"to";s:7:"php_dir";s:4:"type";s:11:"pear-config";}}}}i:99;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"671e6690634062ee521d2027a9971f22";s:4:"name";s:7:"INSTALL";s:4:"role";s:3:"doc";}}i:100;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ca444da9174e05f8a0dc71d8ee47900f";s:4:"name";s:11:"package.dtd";s:4:"role";s:4:"data";}}i:101;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"80921dfa70e0699a934c7d21f60b60c7";s:4:"name";s:8:"PEAR.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:102;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"ae70dd96347165e048bd37521d6437f2";s:4:"name";s:6:"README";s:4:"role";s:3:"doc";}}i:103;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"43762dbc126b34e811326bacb76e8609";s:4:"name";s:10:"System.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:104;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"acd010e3bc43c0f72df584acde7b9158";s:4:"name";s:13:"template.spec";s:4:"role";s:4:"data";}}}}}s:12:"dependencies";a:3:{s:8:"required";a:4:{s:3:"php";a:1:{s:3:"min";s:5:"4.3.0";}s:13:"pearinstaller";a:1:{s:3:"min";s:5:"1.4.3";}s:7:"package";a:5:{i:0;a:5:{s:4:"name";s:11:"Archive_Tar";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:3:"1.1";s:11:"recommended";s:5:"1.3.2";s:7:"exclude";s:5:"1.3.0";}i:1;a:4:{s:4:"name";s:16:"Structures_Graph";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:5:"1.0.2";s:11:"recommended";s:5:"1.0.2";}i:2;a:4:{s:4:"name";s:14:"Console_Getopt";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:3:"1.2";s:11:"recommended";s:5:"1.2.3";}i:3;a:4:{s:4:"name";s:17:"PEAR_Frontend_Web";s:7:"channel";s:12:"pear.php.net";s:3:"max";s:3:"0.4";s:9:"conflicts";s:0:"";}i:4;a:5:{s:4:"name";s:17:"PEAR_Frontend_Gtk";s:7:"channel";s:12:"pear.php.net";s:3:"max";s:5:"0.4.0";s:7:"exclude";s:5:"0.4.0";s:9:"conflicts";s:0:"";}}s:9:"extension";a:2:{i:0;a:1:{s:4:"name";s:3:"xml";}i:1;a:1:{s:4:"name";s:4:"pcre";}}}s:8:"optional";a:1:{s:7:"package";a:3:{s:4:"name";s:7:"XML_RPC";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:5:"1.4.0";}}s:5:"group";a:3:{i:0;a:2:{s:7:"attribs";a:2:{s:4:"hint";s:26:"PEAR's web-based installer";s:4:"name";s:12:"webinstaller";}s:7:"package";a:3:{s:4:"name";s:17:"PEAR_Frontend_Web";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:5:"0.5.1";}}i:1;a:2:{s:7:"attribs";a:2:{s:4:"hint";s:30:"PEAR's PHP-GTK-based installer";s:4:"name";s:12:"gtkinstaller";}s:7:"package";a:3:{s:4:"name";s:17:"PEAR_Frontend_Gtk";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:5:"0.4.0";}}i:2;a:2:{s:7:"attribs";a:2:{s:4:"hint";s:31:"PEAR's PHP-GTK2-based installer";s:4:"name";s:13:"gtk2installer";}s:7:"package";a:2:{s:4:"name";s:18:"PEAR_Frontend_Gtk2";s:7:"channel";s:12:"pear.php.net";}}}}s:10:"phprelease";a:2:{i:0;a:2:{s:17:"installconditions";a:1:{s:2:"os";a:1:{s:4:"name";s:7:"windows";}}s:8:"filelist";a:2:{s:7:"install";a:5:{i:0;a:1:{s:7:"attribs";a:2:{s:2:"as";s:8:"pear.bat";s:4:"name";s:16:"scripts/pear.bat";}}i:1;a:1:{s:7:"attribs";a:2:{s:2:"as";s:11:"peardev.bat";s:4:"name";s:19:"scripts/peardev.bat";}}i:2;a:1:{s:7:"attribs";a:2:{s:2:"as";s:8:"pecl.bat";s:4:"name";s:16:"scripts/pecl.bat";}}i:3;a:1:{s:7:"attribs";a:2:{s:2:"as";s:11:"pearcmd.php";s:4:"name";s:19:"scripts/pearcmd.php";}}i:4;a:1:{s:7:"attribs";a:2:{s:2:"as";s:11:"peclcmd.php";s:4:"name";s:19:"scripts/peclcmd.php";}}}s:6:"ignore";a:3:{i:0;a:1:{s:7:"attribs";a:1:{s:4:"name";s:18:"scripts/peardev.sh";}}i:1;a:1:{s:7:"attribs";a:1:{s:4:"name";s:15:"scripts/pear.sh";}}i:2;a:1:{s:7:"attribs";a:1:{s:4:"name";s:15:"scripts/pecl.sh";}}}}}i:1;a:1:{s:8:"filelist";a:2:{s:7:"install";a:5:{i:0;a:1:{s:7:"attribs";a:2:{s:2:"as";s:4:"pear";s:4:"name";s:15:"scripts/pear.sh";}}i:1;a:1:{s:7:"attribs";a:2:{s:2:"as";s:7:"peardev";s:4:"name";s:18:"scripts/peardev.sh";}}i:2;a:1:{s:7:"attribs";a:2:{s:2:"as";s:4:"pecl";s:4:"name";s:15:"scripts/pecl.sh";}}i:3;a:1:{s:7:"attribs";a:2:{s:2:"as";s:11:"pearcmd.php";s:4:"name";s:19:"scripts/pearcmd.php";}}i:4;a:1:{s:7:"attribs";a:2:{s:2:"as";s:11:"peclcmd.php";s:4:"name";s:19:"scripts/peclcmd.php";}}}s:6:"ignore";a:3:{i:0;a:1:{s:7:"attribs";a:1:{s:4:"name";s:16:"scripts/pear.bat";}}i:1;a:1:{s:7:"attribs";a:1:{s:4:"name";s:19:"scripts/peardev.bat";}}i:2;a:1:{s:7:"attribs";a:1:{s:4:"name";s:16:"scripts/pecl.bat";}}}}}}s:9:"changelog";a:1:{s:7:"release";a:6:{i:0;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.6.2";s:3:"api";s:5:"1.6.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2007-09-09";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:1171:"Minor bugfix release +* fix Bug #11420: warning on pecl (un)install with --register-only option [cellog] +* fix Bug #11481: PEAR_PackageFile_Parser_v1 skips single-char directories [pmjones] +* fix Bug #11517: Error : download directory "/var/cache/php-pear" + is not writeable. [remicollet] +* fix Bug #11616: Incorrect equality operator used when comparing md5 check sums [robham] +* fix Bug #11642: PEAR fails to authenticate when downloading deps from non-default + channels [timj] +* fix Bug #11657: Installer generate bad "dirtree" using INSTALL_ROOT [remicollet] +* fix Bug #11678: Registry.php getChannel() deadlocks [cellog] +* fix Bug #11703: pear convert and package.xml with optional dependencies fails [cellog] +* fix Bug #11754: Error at upgrade-all command run [cellog] +* fix Bug #11861: uninstall of package did not delete directory created during install + of package [cellog] +* fix Bug #11862: Notice: Array to string conversion in PEAR/PackageFile.php on line 433 + [cellog] +* fix Bug #11883: run-tests -u -p SomePackage should run the topmost + "AllTests.php" file [cellog] +* fix Bug #11936: run-tests fails to preserve SYSTEMROOT environment variable [cellog]";}i:1;a:5:{s:7:"version";a:2:{s:7:"release";s:8:"1.7.0RC1";s:3:"api";s:5:"1.6.0";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2007-12-10";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:540:"* fix Bug #12116: Accept-Encoding not supported: breaks installer [jldupont] +* fix Bug #12162: config-create doesn't work after installing custom roles [cellog] +* fix Bug #12553: System::find() does not find exact filename matches [cellog/jorrit] +* fix Bug #12554: enableExtension() zeros php.ini in some instances [jlightsey] +* implement Request #11964: introduce www role, www_dir config variable [cellog] +* implement Request #12108: Add "config" (cfg) role [cellog] +* implement Request #12147: Avoid compile-time strict warnings [cellog]";}i:2;a:5:{s:7:"version";a:2:{s:7:"release";s:8:"1.7.0RC2";s:3:"api";s:5:"1.6.0";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2007-01-03";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:1032:"**WARNING** MAJOR BC BREAK IN WWW ROLE** +The www role was installing into packagename/ and now installs into the root directory +of www_dir. This is necessary to allow easy migration from applications already using +Role_Web + + fixed since 1.7.0RC1: +* fix Bug #12662: System::_parseArgs() should be declared statically [cellog] +* fix Bug #12661: System::mktemp needs to be declaired statically [cellog] +* implement PEAR_Error::__toString() as alias to getMessage() [cellog] + fixed since 1.6.2: +* fix Bug #12116: Accept-Encoding not supported: breaks installer [jldupont] +* fix Bug #12162: config-create doesn't work after installing custom roles [cellog] +* fix Bug #12553: System::find() does not find exact filename matches [cellog/jorrit] +* fix Bug #12554: enableExtension() zeros php.ini in some instances [jlightsey] +* implement Request #11964: introduce www role, www_dir config variable [cellog] +* implement Request #12108: Add "config" (cfg) role [cellog] +* implement Request #12147: Avoid compile-time strict warnings [cellog]";}i:3;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.7.0";s:3:"api";s:5:"1.7.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2008-01-31";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:1862:"Minor feature addition release + +Known bugs to be fixed in version 1.7.1: + - Bug #12945 PEAR_Registry::setConfig() does not set install path + - Bug #12959 PEAR should give warning when doing "special" handling with cfg role + - Bug #12960 role=cfg should automatically replace file if it has not been modified + - Bug #13031 PEAR fails to authenticate when doing upgrade-all on non-default channel + - Bug #13033 Signature to PEAR_REST_XX::listAll() changes between REST1.0 and 1.1 + +fixed since 1.7.0RC2 + * fix bug #13030: Port not set for REST HTTP requests [timj] + * fix bug #13029: Duplicate Host headers set when requesting REST data [timj] + * fix Bug #12987: improper calls to class_exists [weirdan] + * fix Bug #12954: Host header missing when using proxy [flint] + * fix Bug #12918: file tasks ignored for role=src [cellog] + * fix Bug #12816: default isn't being parsed [jon] + * fix Bug #12793: run-tests fails when using --ARGS-- in phpt test files [izi] +fixed since 1.7.0RC1: + * fix Bug #12818: package.xml 1.0 parsing can drop lines [cellog] + * fix Bug #12662: System::_parseArgs() should be declared statically [cellog] + * fix Bug #12661: System::mktemp needs to be declaired statically [cellog] + * implement PEAR_Error::__toString() as alias to getMessage() [cellog] +fixed since 1.6.2: + * fix Bug #12116: Accept-Encoding not supported: breaks installer [jldupont] + * fix Bug #12162: config-create doesn't work after installing custom roles [cellog] + * fix Bug #12553: System::find() does not find exact filename matches [cellog/jorrit] + * fix Bug #12554: enableExtension() zeros php.ini in some instances [jlightsey] + * implement Request #11964: introduce www role, www_dir config variable [cellog] + * implement Request #12108: Add "config" (cfg) role [cellog] + * implement Request #12147: Avoid compile-time strict warnings [cellog]";}i:4;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.7.1";s:3:"api";s:5:"1.7.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2008-02-03";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:672:"fixed since 1.7.0 + * fix bug #13030: Port not set for REST HTTP requests [timj] + * fix bug #13029: Duplicate Host headers set when requesting REST data [timj] + * fix bug #13047: PEAR fails to install *any* package [timj] + +Known bugs to be fixed in version 1.7.2: + - Bug #12945 PEAR_Registry::setConfig() does not set install path + - Bug #12959 PEAR should give warning when doing "special" handling with cfg role + - Bug #12960 role=cfg should automatically replace file if it has not been modified + - Bug #13031 PEAR fails to authenticate when doing upgrade-all on non-default channel + - Bug #13033 Signature to PEAR_REST_XX::listAll() changes between REST1.0 and 1.1";}i:5;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.7.2";s:3:"api";s:5:"1.7.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2008-05-17";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:1625:"* Implement Request #13375: install-pear.php should have option to set cfg_dir [timj] +* Fix Bug #12945 PEAR_Registry::setConfig() does not set install path [cweiske/cellog] +* Fix Bug #12959 PEAR should give warning when doing "special" handling with cfg role [cellog] +* Fix Bug #12960 role=cfg should automatically replace file if it has not been modified [cellog] +* Fix Bug #13031 PEAR fails to authenticate when doing upgrade-all on non-default channel [timj] +* Fix Bug #13033 Signature to PEAR_REST_XX::listAll() changes between REST1.0 and 1.1 [timj] +* Fix Bug #13059 Invalid release type causes Undefined Property notice [gwynne, dufuz] +* Fix Bug #13123 pear config-set works, but pecl config-set does not [cellog] +* Fix Bug #13323 Deprecated errors in many places [hubbitus] +* Fix Bug #13315 Upgrading of package fails if more than one file of role=cfg has changed [timj] +* Fix Bug #13386 "pear install --register-only" fails with cfg role [cellog] +* Fix Bug #13434 Breaks on HPUX - "find () -ls" doesn't work [cellog] +* Fix Bug #13484 pear package brings up warnings [dufuz] +* Fix Bug #13485 pear package-validate brings up ASCII issues [dufuz] +* Fix Bug #13508 undefined index errors when installing a remote bundle [cellog/tswicegood] +* Fix Bug #13525 pear package-validate is not showing warnings even if there are [dufuz] +* Fix Bug #13559 installing package fails via proxy to virtual-hosted server. [hirose] +* Fix Bug #13691 Pear doesn't remove old directories on upgrade [cellog] +* Fix Bug #13870 Notice uninstalling or using bundles [cellog] +* Fix Bug #13883 file permissions not preserved on packaging [cellog]";}}}s:8:"filelist";a:102:{s:12:"OS/Guess.php";a:4:{s:6:"md5sum";s:32:"4fa6b540f217ae9dbab8975f8b93d200";s:4:"name";s:12:"OS/Guess.php";s:4:"role";s:3:"php";s:12:"installed_as";s:47:"/www/htdocs/w00acdb0/lib/pear/PEAR/OS/Guess.php";}s:27:"PEAR/ChannelFile/Parser.php";a:4:{s:6:"md5sum";s:32:"2da630f82eca1531a57fe04696e26a06";s:4:"name";s:27:"PEAR/ChannelFile/Parser.php";s:4:"role";s:3:"php";s:12:"installed_as";s:62:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/ChannelFile/Parser.php";}s:21:"PEAR/Command/Auth.xml";a:4:{s:6:"md5sum";s:32:"381496e0186e16d613ddb01564fca4a0";s:4:"name";s:21:"PEAR/Command/Auth.xml";s:4:"role";s:3:"php";s:12:"installed_as";s:56:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Command/Auth.xml";}s:21:"PEAR/Command/Auth.php";a:4:{s:6:"md5sum";s:32:"2bd9a76a6932fe9fb4fe80d06fd099d4";s:4:"name";s:21:"PEAR/Command/Auth.php";s:4:"role";s:3:"php";s:12:"installed_as";s:56:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Command/Auth.php";}s:22:"PEAR/Command/Build.xml";a:4:{s:6:"md5sum";s:32:"73602fd7f051eaf8d37452d0e3063bdb";s:4:"name";s:22:"PEAR/Command/Build.xml";s:4:"role";s:3:"php";s:12:"installed_as";s:57:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Command/Build.xml";}s:22:"PEAR/Command/Build.php";a:4:{s:6:"md5sum";s:32:"2af3d1912b4b6aef6bf17db5e01f257e";s:4:"name";s:22:"PEAR/Command/Build.php";s:4:"role";s:3:"php";s:12:"installed_as";s:57:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Command/Build.php";}s:25:"PEAR/Command/Channels.xml";a:4:{s:6:"md5sum";s:32:"5dfb7898501c43ab655c5f9b7176ea20";s:4:"name";s:25:"PEAR/Command/Channels.xml";s:4:"role";s:3:"php";s:12:"installed_as";s:60:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Command/Channels.xml";}s:25:"PEAR/Command/Channels.php";a:4:{s:6:"md5sum";s:32:"5876be616c6e401fd911fb6f5c50b102";s:4:"name";s:25:"PEAR/Command/Channels.php";s:4:"role";s:3:"php";s:12:"installed_as";s:60:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Command/Channels.php";}s:23:"PEAR/Command/Common.php";a:4:{s:6:"md5sum";s:32:"22079bbfa5f8ac010683cb0cd84af21f";s:4:"name";s:23:"PEAR/Command/Common.php";s:4:"role";s:3:"php";s:12:"installed_as";s:58:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Command/Common.php";}s:23:"PEAR/Command/Config.xml";a:4:{s:6:"md5sum";s:32:"91f189cb9423b5e87ee0abc5ea1a2be3";s:4:"name";s:23:"PEAR/Command/Config.xml";s:4:"role";s:3:"php";s:12:"installed_as";s:58:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Command/Config.xml";}s:23:"PEAR/Command/Config.php";a:4:{s:6:"md5sum";s:32:"8d36af1a687b1648a474008e6e2b0239";s:4:"name";s:23:"PEAR/Command/Config.php";s:4:"role";s:3:"php";s:12:"installed_as";s:58:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Command/Config.php";}s:24:"PEAR/Command/Install.xml";a:4:{s:6:"md5sum";s:32:"e0f361c6ebda100653e550a762a66a06";s:4:"name";s:24:"PEAR/Command/Install.xml";s:4:"role";s:3:"php";s:12:"installed_as";s:59:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Command/Install.xml";}s:24:"PEAR/Command/Install.php";a:4:{s:6:"md5sum";s:32:"b1954beca05df6a53595112ca12f2cad";s:4:"name";s:24:"PEAR/Command/Install.php";s:4:"role";s:3:"php";s:12:"installed_as";s:59:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Command/Install.php";}s:23:"PEAR/Command/Mirror.xml";a:4:{s:6:"md5sum";s:32:"5cb62a04c0a268f4edd64a49a3895c92";s:4:"name";s:23:"PEAR/Command/Mirror.xml";s:4:"role";s:3:"php";s:12:"installed_as";s:58:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Command/Mirror.xml";}s:23:"PEAR/Command/Mirror.php";a:4:{s:6:"md5sum";s:32:"b1c6d624fa98d7f95948e1bca76c46b5";s:4:"name";s:23:"PEAR/Command/Mirror.php";s:4:"role";s:3:"php";s:12:"installed_as";s:58:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Command/Mirror.php";}s:24:"PEAR/Command/Package.xml";a:4:{s:6:"md5sum";s:32:"bbf88f26cd10b1caa76d5eec474f093f";s:4:"name";s:24:"PEAR/Command/Package.xml";s:4:"role";s:3:"php";s:12:"installed_as";s:59:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Command/Package.xml";}s:24:"PEAR/Command/Package.php";a:4:{s:6:"md5sum";s:32:"cb6f4b8cf4f297200d1ddb35b768d65f";s:4:"name";s:24:"PEAR/Command/Package.php";s:4:"role";s:3:"php";s:12:"installed_as";s:59:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Command/Package.php";}s:23:"PEAR/Command/Pickle.xml";a:4:{s:6:"md5sum";s:32:"29c0947f423695818f90759e65376e5c";s:4:"name";s:23:"PEAR/Command/Pickle.xml";s:4:"role";s:3:"php";s:12:"installed_as";s:58:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Command/Pickle.xml";}s:23:"PEAR/Command/Pickle.php";a:4:{s:6:"md5sum";s:32:"b7777e69e2b771a9f691fb4fade4686a";s:4:"name";s:23:"PEAR/Command/Pickle.php";s:4:"role";s:3:"php";s:12:"installed_as";s:58:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Command/Pickle.php";}s:25:"PEAR/Command/Registry.xml";a:4:{s:6:"md5sum";s:32:"49b046cfc14747f0365e02e9c3f0e6dc";s:4:"name";s:25:"PEAR/Command/Registry.xml";s:4:"role";s:3:"php";s:12:"installed_as";s:60:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Command/Registry.xml";}s:25:"PEAR/Command/Registry.php";a:4:{s:6:"md5sum";s:32:"0e6a7070d8b3bfe5160255b5f5352425";s:4:"name";s:25:"PEAR/Command/Registry.php";s:4:"role";s:3:"php";s:12:"installed_as";s:60:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Command/Registry.php";}s:23:"PEAR/Command/Remote.xml";a:4:{s:6:"md5sum";s:32:"05729e322af29b0ddcdd85559e44cd41";s:4:"name";s:23:"PEAR/Command/Remote.xml";s:4:"role";s:3:"php";s:12:"installed_as";s:58:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Command/Remote.xml";}s:23:"PEAR/Command/Remote.php";a:4:{s:6:"md5sum";s:32:"61cf1731830f4adbb51335a890570b8a";s:4:"name";s:23:"PEAR/Command/Remote.php";s:4:"role";s:3:"php";s:12:"installed_as";s:58:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Command/Remote.php";}s:21:"PEAR/Command/Test.xml";a:4:{s:6:"md5sum";s:32:"118af6fbf9c37e90957f0bb9d5cf9d82";s:4:"name";s:21:"PEAR/Command/Test.xml";s:4:"role";s:3:"php";s:12:"installed_as";s:56:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Command/Test.xml";}s:21:"PEAR/Command/Test.php";a:4:{s:6:"md5sum";s:32:"9bd7498ec025144d036a1ca34b0f4365";s:4:"name";s:21:"PEAR/Command/Test.php";s:4:"role";s:3:"php";s:12:"installed_as";s:56:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Command/Test.php";}s:27:"PEAR/Downloader/Package.php";a:4:{s:6:"md5sum";s:32:"4ee3dab326b3f108574d001ca74f1620";s:4:"name";s:27:"PEAR/Downloader/Package.php";s:4:"role";s:3:"php";s:12:"installed_as";s:62:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Downloader/Package.php";}s:21:"PEAR/Frontend/CLI.php";a:4:{s:6:"md5sum";s:32:"4d43b606e210a61e003fcea2a46d0fd4";s:4:"name";s:21:"PEAR/Frontend/CLI.php";s:4:"role";s:3:"php";s:12:"installed_as";s:56:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Frontend/CLI.php";}s:30:"PEAR/Installer/Role/Common.php";a:4:{s:6:"md5sum";s:32:"82094070511d6369af82529bb8194c8b";s:4:"name";s:30:"PEAR/Installer/Role/Common.php";s:4:"role";s:3:"php";s:12:"installed_as";s:65:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Installer/Role/Common.php";}s:27:"PEAR/Installer/Role/Cfg.xml";a:4:{s:6:"md5sum";s:32:"d8c62e6275e3aaa7784290912406092c";s:4:"name";s:27:"PEAR/Installer/Role/Cfg.xml";s:4:"role";s:3:"php";s:12:"installed_as";s:62:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Installer/Role/Cfg.xml";}s:27:"PEAR/Installer/Role/Cfg.php";a:4:{s:6:"md5sum";s:32:"3fb2045c4328ba0f0791e6c46aabce8a";s:4:"name";s:27:"PEAR/Installer/Role/Cfg.php";s:4:"role";s:3:"php";s:12:"installed_as";s:62:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Installer/Role/Cfg.php";}s:28:"PEAR/Installer/Role/Data.xml";a:4:{s:6:"md5sum";s:32:"89a4a2a286e842d45a98974f40a0565c";s:4:"name";s:28:"PEAR/Installer/Role/Data.xml";s:4:"role";s:3:"php";s:12:"installed_as";s:63:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Installer/Role/Data.xml";}s:28:"PEAR/Installer/Role/Data.php";a:4:{s:6:"md5sum";s:32:"d505eea75d38763c94f92e639580201a";s:4:"name";s:28:"PEAR/Installer/Role/Data.php";s:4:"role";s:3:"php";s:12:"installed_as";s:63:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Installer/Role/Data.php";}s:27:"PEAR/Installer/Role/Doc.xml";a:4:{s:6:"md5sum";s:32:"b1ce0fe105251c3b75209d6518ee69ac";s:4:"name";s:27:"PEAR/Installer/Role/Doc.xml";s:4:"role";s:3:"php";s:12:"installed_as";s:62:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Installer/Role/Doc.xml";}s:27:"PEAR/Installer/Role/Doc.php";a:4:{s:6:"md5sum";s:32:"d381e479248b847e1fba152dc95f10d4";s:4:"name";s:27:"PEAR/Installer/Role/Doc.php";s:4:"role";s:3:"php";s:12:"installed_as";s:62:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Installer/Role/Doc.php";}s:27:"PEAR/Installer/Role/Ext.xml";a:4:{s:6:"md5sum";s:32:"af71c0ad42d16a323afe24a4f884ef15";s:4:"name";s:27:"PEAR/Installer/Role/Ext.xml";s:4:"role";s:3:"php";s:12:"installed_as";s:62:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Installer/Role/Ext.xml";}s:27:"PEAR/Installer/Role/Ext.php";a:4:{s:6:"md5sum";s:32:"205b68b09e62134f965c16bdac37bcc7";s:4:"name";s:27:"PEAR/Installer/Role/Ext.php";s:4:"role";s:3:"php";s:12:"installed_as";s:62:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Installer/Role/Ext.php";}s:27:"PEAR/Installer/Role/Php.xml";a:4:{s:6:"md5sum";s:32:"ef88f0321d3e481c2130c95122cf76d8";s:4:"name";s:27:"PEAR/Installer/Role/Php.xml";s:4:"role";s:3:"php";s:12:"installed_as";s:62:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Installer/Role/Php.xml";}s:27:"PEAR/Installer/Role/Php.php";a:4:{s:6:"md5sum";s:32:"284067a202f05fc1b62981d7c0b10419";s:4:"name";s:27:"PEAR/Installer/Role/Php.php";s:4:"role";s:3:"php";s:12:"installed_as";s:62:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Installer/Role/Php.php";}s:30:"PEAR/Installer/Role/Script.xml";a:4:{s:6:"md5sum";s:32:"746461dc3b48af6d24094cb0211608f2";s:4:"name";s:30:"PEAR/Installer/Role/Script.xml";s:4:"role";s:3:"php";s:12:"installed_as";s:65:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Installer/Role/Script.xml";}s:30:"PEAR/Installer/Role/Script.php";a:4:{s:6:"md5sum";s:32:"c879348f293100cc0c78220c4de6d711";s:4:"name";s:30:"PEAR/Installer/Role/Script.php";s:4:"role";s:3:"php";s:12:"installed_as";s:65:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Installer/Role/Script.php";}s:27:"PEAR/Installer/Role/Src.xml";a:4:{s:6:"md5sum";s:32:"e147d63f168ea156fc2be38caaa63804";s:4:"name";s:27:"PEAR/Installer/Role/Src.xml";s:4:"role";s:3:"php";s:12:"installed_as";s:62:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Installer/Role/Src.xml";}s:27:"PEAR/Installer/Role/Src.php";a:4:{s:6:"md5sum";s:32:"e0200455cde8eba003dff160b3657c43";s:4:"name";s:27:"PEAR/Installer/Role/Src.php";s:4:"role";s:3:"php";s:12:"installed_as";s:62:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Installer/Role/Src.php";}s:28:"PEAR/Installer/Role/Test.xml";a:4:{s:6:"md5sum";s:32:"a24b596ec987aa5688fc19e8ed4e97ea";s:4:"name";s:28:"PEAR/Installer/Role/Test.xml";s:4:"role";s:3:"php";s:12:"installed_as";s:63:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Installer/Role/Test.xml";}s:28:"PEAR/Installer/Role/Test.php";a:4:{s:6:"md5sum";s:32:"47f59482d09100bc9ad7e137785855e7";s:4:"name";s:28:"PEAR/Installer/Role/Test.php";s:4:"role";s:3:"php";s:12:"installed_as";s:63:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Installer/Role/Test.php";}s:27:"PEAR/Installer/Role/Www.xml";a:4:{s:6:"md5sum";s:32:"7641e71c5785bb33a4261ebe25ed0fd7";s:4:"name";s:27:"PEAR/Installer/Role/Www.xml";s:4:"role";s:3:"php";s:12:"installed_as";s:62:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Installer/Role/Www.xml";}s:27:"PEAR/Installer/Role/Www.php";a:4:{s:6:"md5sum";s:32:"0076ccbaa7a6208559df11aa3eb798b5";s:4:"name";s:27:"PEAR/Installer/Role/Www.php";s:4:"role";s:3:"php";s:12:"installed_as";s:62:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Installer/Role/Www.php";}s:23:"PEAR/Installer/Role.php";a:4:{s:6:"md5sum";s:32:"273540b734ed43343649c416a4f52a99";s:4:"name";s:23:"PEAR/Installer/Role.php";s:4:"role";s:3:"php";s:12:"installed_as";s:58:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Installer/Role.php";}s:33:"PEAR/PackageFile/Generator/v1.php";a:4:{s:6:"md5sum";s:32:"9ff6a4888868c72abf2433f8dfc40be6";s:4:"name";s:33:"PEAR/PackageFile/Generator/v1.php";s:4:"role";s:3:"php";s:12:"installed_as";s:68:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/PackageFile/Generator/v1.php";}s:33:"PEAR/PackageFile/Generator/v2.php";a:4:{s:6:"md5sum";s:32:"b23f0359cd3306c87bd027eefff38892";s:4:"name";s:33:"PEAR/PackageFile/Generator/v2.php";s:4:"role";s:3:"php";s:12:"installed_as";s:68:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/PackageFile/Generator/v2.php";}s:30:"PEAR/PackageFile/Parser/v1.php";a:4:{s:6:"md5sum";s:32:"e439d694e4e2c3b4146ee308a2758f5a";s:4:"name";s:30:"PEAR/PackageFile/Parser/v1.php";s:4:"role";s:3:"php";s:12:"installed_as";s:65:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/PackageFile/Parser/v1.php";}s:30:"PEAR/PackageFile/Parser/v2.php";a:4:{s:6:"md5sum";s:32:"9fdba40240a1a72820780b5d6184391b";s:4:"name";s:30:"PEAR/PackageFile/Parser/v2.php";s:4:"role";s:3:"php";s:12:"installed_as";s:65:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/PackageFile/Parser/v2.php";}s:26:"PEAR/PackageFile/v2/rw.php";a:4:{s:6:"md5sum";s:32:"c56d70ed9adb2071e530142ed6d296ab";s:4:"name";s:26:"PEAR/PackageFile/v2/rw.php";s:4:"role";s:3:"php";s:12:"installed_as";s:61:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/PackageFile/v2/rw.php";}s:33:"PEAR/PackageFile/v2/Validator.php";a:4:{s:6:"md5sum";s:32:"85530152fe2098b549ef8e9cbc727f8c";s:4:"name";s:33:"PEAR/PackageFile/v2/Validator.php";s:4:"role";s:3:"php";s:12:"installed_as";s:68:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/PackageFile/v2/Validator.php";}s:23:"PEAR/PackageFile/v1.php";a:4:{s:6:"md5sum";s:32:"63a79337dfe25c16aee1ce9b136f7044";s:4:"name";s:23:"PEAR/PackageFile/v1.php";s:4:"role";s:3:"php";s:12:"installed_as";s:58:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/PackageFile/v1.php";}s:23:"PEAR/PackageFile/v2.php";a:4:{s:6:"md5sum";s:32:"1fdb0bd1548aafec891aa6d9580ea59b";s:4:"name";s:23:"PEAR/PackageFile/v2.php";s:4:"role";s:3:"php";s:12:"installed_as";s:58:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/PackageFile/v2.php";}s:16:"PEAR/REST/10.php";a:4:{s:6:"md5sum";s:32:"3284fc0ec89030c9d841200beecbf4fa";s:4:"name";s:16:"PEAR/REST/10.php";s:4:"role";s:3:"php";s:12:"installed_as";s:51:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/REST/10.php";}s:16:"PEAR/REST/11.php";a:4:{s:6:"md5sum";s:32:"71d7072f1cdf9f2065205f4585a2ecc6";s:4:"name";s:16:"PEAR/REST/11.php";s:4:"role";s:3:"php";s:12:"installed_as";s:51:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/REST/11.php";}s:16:"PEAR/REST/13.php";a:4:{s:6:"md5sum";s:32:"619b085112e10287e66197cc4fc6acaa";s:4:"name";s:16:"PEAR/REST/13.php";s:4:"role";s:3:"php";s:12:"installed_as";s:51:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/REST/13.php";}s:34:"PEAR/Task/Postinstallscript/rw.php";a:4:{s:6:"md5sum";s:32:"9339412e86586c299727121e08adefba";s:4:"name";s:34:"PEAR/Task/Postinstallscript/rw.php";s:4:"role";s:3:"php";s:12:"installed_as";s:69:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Task/Postinstallscript/rw.php";}s:24:"PEAR/Task/Replace/rw.php";a:4:{s:6:"md5sum";s:32:"9fe592cd22a83915d796a11af6331606";s:4:"name";s:24:"PEAR/Task/Replace/rw.php";s:4:"role";s:3:"php";s:12:"installed_as";s:59:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Task/Replace/rw.php";}s:24:"PEAR/Task/Unixeol/rw.php";a:4:{s:6:"md5sum";s:32:"3c7a6eb3a4e207f665f06093cb8bcdf9";s:4:"name";s:24:"PEAR/Task/Unixeol/rw.php";s:4:"role";s:3:"php";s:12:"installed_as";s:59:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Task/Unixeol/rw.php";}s:27:"PEAR/Task/Windowseol/rw.php";a:4:{s:6:"md5sum";s:32:"1a390d0f5b489d7f61f9e6682203bcc3";s:4:"name";s:27:"PEAR/Task/Windowseol/rw.php";s:4:"role";s:3:"php";s:12:"installed_as";s:62:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Task/Windowseol/rw.php";}s:20:"PEAR/Task/Common.php";a:4:{s:6:"md5sum";s:32:"b5a728f8d59013ab6d5077f27b517a96";s:4:"name";s:20:"PEAR/Task/Common.php";s:4:"role";s:3:"php";s:12:"installed_as";s:55:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Task/Common.php";}s:31:"PEAR/Task/Postinstallscript.php";a:4:{s:6:"md5sum";s:32:"b9e5cc9fed2ebad6d2011ee6a4d592bf";s:4:"name";s:31:"PEAR/Task/Postinstallscript.php";s:4:"role";s:3:"php";s:12:"installed_as";s:66:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Task/Postinstallscript.php";}s:21:"PEAR/Task/Replace.php";a:4:{s:6:"md5sum";s:32:"5a3d680bb9c327530f696d830b8b605b";s:4:"name";s:21:"PEAR/Task/Replace.php";s:4:"role";s:3:"php";s:12:"installed_as";s:56:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Task/Replace.php";}s:21:"PEAR/Task/Unixeol.php";a:4:{s:6:"md5sum";s:32:"f9dc0e5d8d8957ea207d9da8e37dcb26";s:4:"name";s:21:"PEAR/Task/Unixeol.php";s:4:"role";s:3:"php";s:12:"installed_as";s:56:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Task/Unixeol.php";}s:24:"PEAR/Task/Windowseol.php";a:4:{s:6:"md5sum";s:32:"2ce493f5d43d7df681a1b45034060904";s:4:"name";s:24:"PEAR/Task/Windowseol.php";s:4:"role";s:3:"php";s:12:"installed_as";s:59:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Task/Windowseol.php";}s:23:"PEAR/Validator/PECL.php";a:4:{s:6:"md5sum";s:32:"2ae06a82c9f955f68c31fdc11bf217c5";s:4:"name";s:23:"PEAR/Validator/PECL.php";s:4:"role";s:3:"php";s:12:"installed_as";s:58:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Validator/PECL.php";}s:19:"PEAR/Autoloader.php";a:4:{s:6:"md5sum";s:32:"9cd95af3af7654b473842723cc7c1bec";s:4:"name";s:19:"PEAR/Autoloader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:54:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Autoloader.php";}s:16:"PEAR/Builder.php";a:4:{s:6:"md5sum";s:32:"062dc2dba3349a8f2cadb9e81320cfdb";s:4:"name";s:16:"PEAR/Builder.php";s:4:"role";s:3:"php";s:12:"installed_as";s:51:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Builder.php";}s:20:"PEAR/ChannelFile.php";a:4:{s:6:"md5sum";s:32:"54638616d9fae90609ef027430b86656";s:4:"name";s:20:"PEAR/ChannelFile.php";s:4:"role";s:3:"php";s:12:"installed_as";s:55:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/ChannelFile.php";}s:16:"PEAR/Command.php";a:4:{s:6:"md5sum";s:32:"7147a5789e7f15c85f3b23d4ffb6b236";s:4:"name";s:16:"PEAR/Command.php";s:4:"role";s:3:"php";s:12:"installed_as";s:51:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Command.php";}s:15:"PEAR/Common.php";a:4:{s:6:"md5sum";s:32:"a7ec0f20c252a9cb436968bc9f5635da";s:4:"name";s:15:"PEAR/Common.php";s:4:"role";s:3:"php";s:12:"installed_as";s:50:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Common.php";}s:15:"PEAR/Config.php";a:4:{s:6:"md5sum";s:32:"d18ae493cc76570cecff6d6dddc24d3b";s:4:"name";s:15:"PEAR/Config.php";s:4:"role";s:3:"php";s:12:"installed_as";s:50:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Config.php";}s:19:"PEAR/Dependency.php";a:4:{s:6:"md5sum";s:32:"bcfff6330848fa83118e1ff11b3d7ba0";s:4:"name";s:19:"PEAR/Dependency.php";s:4:"role";s:3:"php";s:12:"installed_as";s:54:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Dependency.php";}s:21:"PEAR/DependencyDB.php";a:4:{s:6:"md5sum";s:32:"f48a05aee6a88319eb2b45a9a649b0f0";s:4:"name";s:21:"PEAR/DependencyDB.php";s:4:"role";s:3:"php";s:12:"installed_as";s:56:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/DependencyDB.php";}s:20:"PEAR/Dependency2.php";a:4:{s:6:"md5sum";s:32:"893b4e4250ca595dc41c596a60e36de2";s:4:"name";s:20:"PEAR/Dependency2.php";s:4:"role";s:3:"php";s:12:"installed_as";s:55:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Dependency2.php";}s:19:"PEAR/Downloader.php";a:4:{s:6:"md5sum";s:32:"c631755222fd7ae155cce369ae46f929";s:4:"name";s:19:"PEAR/Downloader.php";s:4:"role";s:3:"php";s:12:"installed_as";s:54:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Downloader.php";}s:19:"PEAR/ErrorStack.php";a:4:{s:6:"md5sum";s:32:"cf883c744c4be529a3a75b235608eaa4";s:4:"name";s:19:"PEAR/ErrorStack.php";s:4:"role";s:3:"php";s:12:"installed_as";s:54:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/ErrorStack.php";}s:18:"PEAR/Exception.php";a:4:{s:6:"md5sum";s:32:"60040e0928e18981a9ccb036e54db840";s:4:"name";s:18:"PEAR/Exception.php";s:4:"role";s:3:"php";s:12:"installed_as";s:53:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Exception.php";}s:28:"PEAR/FixPHP5PEARWarnings.php";a:4:{s:6:"md5sum";s:32:"e0e4cbcec4a972fbad779d0f9d323120";s:4:"name";s:28:"PEAR/FixPHP5PEARWarnings.php";s:4:"role";s:3:"php";s:12:"installed_as";s:63:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/FixPHP5PEARWarnings.php";}s:17:"PEAR/Frontend.php";a:4:{s:6:"md5sum";s:32:"d26049bf4358619459eac6bd08e0c61e";s:4:"name";s:17:"PEAR/Frontend.php";s:4:"role";s:3:"php";s:12:"installed_as";s:52:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Frontend.php";}s:18:"PEAR/Installer.php";a:4:{s:6:"md5sum";s:32:"828e42237cd8b0e04a2cf0a5b13099f2";s:4:"name";s:18:"PEAR/Installer.php";s:4:"role";s:3:"php";s:12:"installed_as";s:53:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Installer.php";}s:20:"PEAR/PackageFile.php";a:4:{s:6:"md5sum";s:32:"4546fbff936d36496c30227f20d5b6a7";s:4:"name";s:20:"PEAR/PackageFile.php";s:4:"role";s:3:"php";s:12:"installed_as";s:55:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/PackageFile.php";}s:17:"PEAR/Packager.php";a:4:{s:6:"md5sum";s:32:"c1708307d9a6037f60ef4cf130b8c1d9";s:4:"name";s:17:"PEAR/Packager.php";s:4:"role";s:3:"php";s:12:"installed_as";s:52:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Packager.php";}s:17:"PEAR/Registry.php";a:4:{s:6:"md5sum";s:32:"eb579ef0fbff7c72a2f272a90550337e";s:4:"name";s:17:"PEAR/Registry.php";s:4:"role";s:3:"php";s:12:"installed_as";s:52:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Registry.php";}s:15:"PEAR/Remote.php";a:4:{s:6:"md5sum";s:32:"ac90346df7467a1b43b9392069a87750";s:4:"name";s:15:"PEAR/Remote.php";s:4:"role";s:3:"php";s:12:"installed_as";s:50:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Remote.php";}s:13:"PEAR/REST.php";a:4:{s:6:"md5sum";s:32:"b8c5c610bcf441261b6101c6ed176e96";s:4:"name";s:13:"PEAR/REST.php";s:4:"role";s:3:"php";s:12:"installed_as";s:48:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/REST.php";}s:16:"PEAR/RunTest.php";a:4:{s:6:"md5sum";s:32:"3345c49c04db53a8424a25985bd69633";s:4:"name";s:16:"PEAR/RunTest.php";s:4:"role";s:3:"php";s:12:"installed_as";s:51:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/RunTest.php";}s:17:"PEAR/Validate.php";a:4:{s:6:"md5sum";s:32:"2f97edd3496adace0a0e5c9f1b70ae76";s:4:"name";s:17:"PEAR/Validate.php";s:4:"role";s:3:"php";s:12:"installed_as";s:52:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Validate.php";}s:18:"PEAR/XMLParser.php";a:4:{s:6:"md5sum";s:32:"dab39738e174b584eebc71bd3ece7a91";s:4:"name";s:18:"PEAR/XMLParser.php";s:4:"role";s:3:"php";s:12:"installed_as";s:53:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/XMLParser.php";}s:15:"scripts/pear.sh";a:6:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"5b495a3de3c6092bfbd93806937a0e4e";s:4:"name";s:15:"scripts/pear.sh";s:4:"role";s:6:"script";s:10:"install-as";s:4:"pear";s:12:"installed_as";s:38:"/www/htdocs/w00acdb0/lib/pear/bin/pear";}s:18:"scripts/peardev.sh";a:6:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"c69b7eb6cf9198ef8f03a19dcb57ca42";s:4:"name";s:18:"scripts/peardev.sh";s:4:"role";s:6:"script";s:10:"install-as";s:7:"peardev";s:12:"installed_as";s:41:"/www/htdocs/w00acdb0/lib/pear/bin/peardev";}s:15:"scripts/pecl.sh";a:6:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"d00c55f2aa48052c25db271e044e7551";s:4:"name";s:15:"scripts/pecl.sh";s:4:"role";s:6:"script";s:10:"install-as";s:4:"pecl";s:12:"installed_as";s:38:"/www/htdocs/w00acdb0/lib/pear/bin/pecl";}s:19:"scripts/pearcmd.php";a:6:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"a398d2c6875a38dc38aa399f3fa12e49";s:4:"name";s:19:"scripts/pearcmd.php";s:4:"role";s:3:"php";s:10:"install-as";s:11:"pearcmd.php";s:12:"installed_as";s:46:"/www/htdocs/w00acdb0/lib/pear/PEAR/pearcmd.php";}s:19:"scripts/peclcmd.php";a:6:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"6356b5beefa80d0bbfd234d222873c7d";s:4:"name";s:19:"scripts/peclcmd.php";s:4:"role";s:3:"php";s:10:"install-as";s:11:"peclcmd.php";s:12:"installed_as";s:46:"/www/htdocs/w00acdb0/lib/pear/PEAR/peclcmd.php";}s:7:"INSTALL";a:4:{s:6:"md5sum";s:32:"671e6690634062ee521d2027a9971f22";s:4:"name";s:7:"INSTALL";s:4:"role";s:3:"doc";s:12:"installed_as";s:52:"/www/htdocs/w00acdb0/lib/pear/PEAR/docs/PEAR/INSTALL";}s:11:"package.dtd";a:4:{s:6:"md5sum";s:32:"ca444da9174e05f8a0dc71d8ee47900f";s:4:"name";s:11:"package.dtd";s:4:"role";s:4:"data";s:12:"installed_as";s:56:"/www/htdocs/w00acdb0/lib/pear/PEAR/data/PEAR/package.dtd";}s:8:"PEAR.php";a:4:{s:6:"md5sum";s:32:"80921dfa70e0699a934c7d21f60b60c7";s:4:"name";s:8:"PEAR.php";s:4:"role";s:3:"php";s:12:"installed_as";s:43:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR.php";}s:6:"README";a:4:{s:6:"md5sum";s:32:"ae70dd96347165e048bd37521d6437f2";s:4:"name";s:6:"README";s:4:"role";s:3:"doc";s:12:"installed_as";s:51:"/www/htdocs/w00acdb0/lib/pear/PEAR/docs/PEAR/README";}s:10:"System.php";a:4:{s:6:"md5sum";s:32:"43762dbc126b34e811326bacb76e8609";s:4:"name";s:10:"System.php";s:4:"role";s:3:"php";s:12:"installed_as";s:45:"/www/htdocs/w00acdb0/lib/pear/PEAR/System.php";}s:13:"template.spec";a:4:{s:6:"md5sum";s:32:"acd010e3bc43c0f72df584acde7b9158";s:4:"name";s:13:"template.spec";s:4:"role";s:4:"data";s:12:"installed_as";s:58:"/www/htdocs/w00acdb0/lib/pear/PEAR/data/PEAR/template.spec";}}s:12:"_lastversion";N;s:7:"dirtree";a:23:{s:37:"/www/htdocs/w00acdb0/lib/pear/PEAR/OS";b:1;s:51:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/ChannelFile";b:1;s:39:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR";b:1;s:47:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Command";b:1;s:50:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Downloader";b:1;s:48:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Frontend";b:1;s:54:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Installer/Role";b:1;s:49:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Installer";b:1;s:61:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/PackageFile/Generator";b:1;s:51:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/PackageFile";b:1;s:58:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/PackageFile/Parser";b:1;s:54:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/PackageFile/v2";b:1;s:44:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/REST";b:1;s:62:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Task/Postinstallscript";b:1;s:44:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Task";b:1;s:52:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Task/Replace";b:1;s:52:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Task/Unixeol";b:1;s:55:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Task/Windowseol";b:1;s:49:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Validator";b:1;s:33:"/www/htdocs/w00acdb0/lib/pear/bin";b:1;s:34:"/www/htdocs/w00acdb0/lib/pear/PEAR";b:1;s:44:"/www/htdocs/w00acdb0/lib/pear/PEAR/docs/PEAR";b:1;s:44:"/www/htdocs/w00acdb0/lib/pear/PEAR/data/PEAR";b:1;}s:3:"old";a:7:{s:7:"version";s:5:"1.7.2";s:12:"release_date";s:10:"2008-05-17";s:13:"release_state";s:6:"stable";s:15:"release_license";s:11:"PHP License";s:13:"release_notes";s:1625:"* Implement Request #13375: install-pear.php should have option to set cfg_dir [timj] +* Fix Bug #12945 PEAR_Registry::setConfig() does not set install path [cweiske/cellog] +* Fix Bug #12959 PEAR should give warning when doing "special" handling with cfg role [cellog] +* Fix Bug #12960 role=cfg should automatically replace file if it has not been modified [cellog] +* Fix Bug #13031 PEAR fails to authenticate when doing upgrade-all on non-default channel [timj] +* Fix Bug #13033 Signature to PEAR_REST_XX::listAll() changes between REST1.0 and 1.1 [timj] +* Fix Bug #13059 Invalid release type causes Undefined Property notice [gwynne, dufuz] +* Fix Bug #13123 pear config-set works, but pecl config-set does not [cellog] +* Fix Bug #13323 Deprecated errors in many places [hubbitus] +* Fix Bug #13315 Upgrading of package fails if more than one file of role=cfg has changed [timj] +* Fix Bug #13386 "pear install --register-only" fails with cfg role [cellog] +* Fix Bug #13434 Breaks on HPUX - "find () -ls" doesn't work [cellog] +* Fix Bug #13484 pear package brings up warnings [dufuz] +* Fix Bug #13485 pear package-validate brings up ASCII issues [dufuz] +* Fix Bug #13508 undefined index errors when installing a remote bundle [cellog/tswicegood] +* Fix Bug #13525 pear package-validate is not showing warnings even if there are [dufuz] +* Fix Bug #13559 installing package fails via proxy to virtual-hosted server. [hirose] +* Fix Bug #13691 Pear doesn't remove old directories on upgrade [cellog] +* Fix Bug #13870 Notice uninstalling or using bundles [cellog] +* Fix Bug #13883 file permissions not preserved on packaging [cellog]";s:12:"release_deps";a:10:{i:0;a:4:{s:4:"type";s:3:"php";s:3:"rel";s:2:"ge";s:7:"version";s:5:"4.3.0";s:8:"optional";s:2:"no";}i:1;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:4:"PEAR";s:3:"rel";s:2:"ge";s:7:"version";s:5:"1.4.3";s:8:"optional";s:2:"no";}i:2;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:11:"Archive_Tar";s:3:"rel";s:2:"ge";s:7:"version";s:3:"1.1";s:8:"optional";s:2:"no";}i:3;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:16:"Structures_Graph";s:3:"rel";s:2:"ge";s:7:"version";s:5:"1.0.2";s:8:"optional";s:2:"no";}i:4;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:14:"Console_Getopt";s:3:"rel";s:2:"ge";s:7:"version";s:3:"1.2";s:8:"optional";s:2:"no";}i:5;a:4:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:17:"PEAR_Frontend_Web";s:3:"rel";s:3:"not";}i:6;a:4:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:17:"PEAR_Frontend_Gtk";s:3:"rel";s:3:"not";}i:7;a:4:{s:4:"type";s:3:"ext";s:4:"name";s:3:"xml";s:3:"rel";s:3:"has";s:8:"optional";s:2:"no";}i:8;a:4:{s:4:"type";s:3:"ext";s:4:"name";s:4:"pcre";s:3:"rel";s:3:"has";s:8:"optional";s:2:"no";}i:9;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:7:"XML_RPC";s:3:"rel";s:2:"ge";s:7:"version";s:5:"1.4.0";s:8:"optional";s:3:"yes";}}s:11:"maintainers";a:9:{i:0;a:5:{s:4:"name";s:11:"Greg Beaver";s:5:"email";s:14:"cellog@php.net";s:6:"active";s:3:"yes";s:6:"handle";s:6:"cellog";s:4:"role";s:4:"lead";}i:1;a:5:{s:4:"name";s:17:"Pierre-Alain Joye";s:5:"email";s:14:"pierre@php.net";s:6:"active";s:2:"no";s:6:"handle";s:6:"pajoye";s:4:"role";s:4:"lead";}i:2;a:5:{s:4:"name";s:11:"Stig Bakken";s:5:"email";s:12:"stig@php.net";s:6:"active";s:2:"no";s:6:"handle";s:3:"ssb";s:4:"role";s:4:"lead";}i:3;a:5:{s:4:"name";s:13:"Tomas V.V.Cox";s:5:"email";s:15:"cox@idecnet.com";s:6:"active";s:2:"no";s:6:"handle";s:3:"cox";s:4:"role";s:4:"lead";}i:4;a:5:{s:4:"name";s:13:"Helgi Thormar";s:5:"email";s:13:"dufuz@php.net";s:6:"active";s:3:"yes";s:6:"handle";s:5:"dufuz";s:4:"role";s:9:"developer";}i:5;a:5:{s:4:"name";s:9:"Tias Guns";s:5:"email";s:12:"tias@php.net";s:6:"active";s:3:"yes";s:6:"handle";s:4:"tias";s:4:"role";s:9:"developer";}i:6;a:5:{s:4:"name";s:11:"Tim Jackson";s:5:"email";s:12:"timj@php.net";s:6:"active";s:2:"no";s:6:"handle";s:4:"timj";s:4:"role";s:6:"helper";}i:7;a:5:{s:4:"name";s:15:"Bertrand Gugger";s:5:"email";s:13:"toggg@php.net";s:6:"active";s:2:"no";s:6:"handle";s:5:"toggg";s:4:"role";s:6:"helper";}i:8;a:5:{s:4:"name";s:13:"Martin Jansen";s:5:"email";s:10:"mj@php.net";s:6:"active";s:2:"no";s:6:"handle";s:2:"mj";s:4:"role";s:6:"helper";}}}s:10:"xsdversion";s:3:"2.0";s:13:"_lastmodified";i:1234655680;} \ No newline at end of file diff --git a/src/lib/pear/PEAR/.registry/pear_frontend_web.reg b/src/lib/pear/PEAR/.registry/pear_frontend_web.reg new file mode 100644 index 0000000..aa2529f --- /dev/null +++ b/src/lib/pear/PEAR/.registry/pear_frontend_web.reg @@ -0,0 +1,57 @@ +a:23:{s:7:"attribs";a:6:{s:15:"packagerversion";s:5:"1.7.2";s:7:"version";s:3:"2.0";s:5:"xmlns";s:35:"http://pear.php.net/dtd/package-2.0";s:11:"xmlns:tasks";s:33:"http://pear.php.net/dtd/tasks-1.0";s:9:"xmlns:xsi";s:41:"http://www.w3.org/2001/XMLSchema-instance";s:18:"xsi:schemaLocation";s:147:"http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd";}s:4:"name";s:17:"PEAR_Frontend_Web";s:7:"channel";s:12:"pear.php.net";s:7:"summary";s:29:"Webbased PEAR Package Manager";s:11:"description";s:350:"The most accessible way to manage your pear-compatible packages. + +This frontend's most valuable features are: +* Webbased: no remote shell access needed. +* Fully channel aware: no default channel, all channels are managed at the same time +* Unique docviewer: read the installed documentation in your borwser. +* Plus all features of the PEAR Installer.";s:4:"lead";a:4:{i:0;a:4:{s:4:"name";s:9:"Tias Guns";s:4:"user";s:4:"tias";s:5:"email";s:16:"tias@ulyssis.org";s:6:"active";s:3:"yes";}i:1;a:4:{s:4:"name";s:14:"Gregory Beaver";s:4:"user";s:6:"cellog";s:5:"email";s:14:"cellog@php.net";s:6:"active";s:3:"yes";}i:2;a:4:{s:4:"name";s:18:"Christian Dickmann";s:4:"user";s:8:"dickmann";s:5:"email";s:16:"dickmann@php.net";s:6:"active";s:2:"no";}i:3;a:4:{s:4:"name";s:17:"Pierre-Alain Joye";s:4:"user";s:6:"pajoye";s:5:"email";s:17:"pajoye@pearfr.org";s:6:"active";s:2:"no";}}s:6:"helper";a:4:{s:4:"name";s:11:"Stig Bakken";s:4:"user";s:3:"ssb";s:5:"email";s:12:"stig@php.net";s:6:"active";s:2:"no";}s:4:"date";s:10:"2008-08-03";s:4:"time";s:8:"15:59:55";s:7:"version";a:2:{s:7:"release";s:5:"0.7.3";s:3:"api";s:5:"0.7.0";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:4:"beta";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:215:"* Fix bug #13703 no empty channel url +* fix bug #13714 'package information' link on installing local file +* for the open_basedir prisoners, don't allow PEAR to search for a temp dir (would use /tmp), see bug #13167";s:8:"contents";a:1:{s:3:"dir";a:2:{s:7:"attribs";a:2:{s:14:"baseinstalldir";s:4:"PEAR";s:4:"name";s:1:"/";}s:4:"file";a:50:{i:0;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"537b747e123810c7c732a299bba3e380";s:4:"name";s:22:"Command/Categories.php";s:4:"role";s:3:"php";}}i:1;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"3e7a870a30debaeb83a843c41368c581";s:4:"name";s:22:"Command/Categories.xml";s:4:"role";s:3:"php";}}i:2;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"77605580daff87d2ea0855db327aab3c";s:4:"name";s:24:"data/images/category.jpg";s:4:"role";s:4:"data";}}i:3;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"89fbaf12b03630cde8fab8f582a2013e";s:4:"name";s:22:"data/images/config.gif";s:4:"role";s:4:"data";}}i:4;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"917c5480d7887a45fb7ee9e75ffdc90f";s:4:"name";s:24:"data/images/download.gif";s:4:"role";s:4:"data";}}i:5;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"b7910926d28d2174f766edcd5b0203f3";s:4:"name";s:21:"data/images/error.gif";s:4:"role";s:4:"data";}}i:6;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"a9fd915f941d8b2767a86a7b86c1157d";s:4:"name";s:20:"data/images/info.gif";s:4:"role";s:4:"data";}}i:7;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"25ea72ec541af2d75e1c6084bb51c799";s:4:"name";s:24:"data/images/infoplus.gif";s:4:"role";s:4:"data";}}i:8;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"3d5ed1a26b7ba8c9d144d289e40359dd";s:4:"name";s:28:"data/images/install_fail.gif";s:4:"role";s:4:"data";}}i:9;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"bf40b1ad414777f2ec1ffd8f49db8cb8";s:4:"name";s:23:"data/images/install.gif";s:4:"role";s:4:"data";}}i:10;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"b1bd4bab6452562b624834691a2537c6";s:4:"name";s:26:"data/images/install_ok.gif";s:4:"role";s:4:"data";}}i:11;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"7b0098f037a686f02b925333a30161e9";s:4:"name";s:28:"data/images/install_wait.gif";s:4:"role";s:4:"data";}}i:12;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"06f6632208ac488b25c582100d97d03d";s:4:"name";s:21:"data/images/login.gif";s:4:"role";s:4:"data";}}i:13;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"b6ec4b263faa470ff1150637b0d7c63e";s:4:"name";s:22:"data/images/logout.gif";s:4:"role";s:4:"data";}}i:14;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"4c36ad8eaa614f2ce07600789e1193ae";s:4:"name";s:22:"data/images/manual.gif";s:4:"role";s:4:"data";}}i:15;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"3eca2224677c9f266297e4187b0f2db7";s:4:"name";s:26:"data/images/manualplus.gif";s:4:"role";s:4:"data";}}i:16;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"a059eafc2fb95b0ca42977e29d391cff";s:4:"name";s:23:"data/images/package.jpg";s:4:"role";s:4:"data";}}i:17;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"1f0ca8116ffeafac272a3f1a8325e408";s:4:"name";s:25:"data/images/pearsmall.gif";s:4:"role";s:4:"data";}}i:18;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"3bed4b639af3ba0b136c0201ac505a7b";s:4:"name";s:23:"data/images/pkglist.png";s:4:"role";s:4:"data";}}i:19;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"7f8ff108546c678f59f6b8c88ab43c92";s:4:"name";s:25:"data/images/pkgsearch.png";s:4:"role";s:4:"data";}}i:20;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"5c897611197c28498c03da298e5558d7";s:4:"name";s:21:"data/images/trash.gif";s:4:"role";s:4:"data";}}i:21;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"d4e1fcabab3e47008e887626905f1054";s:4:"name";s:34:"data/templates/bottom.inc.tpl.html";s:4:"role";s:4:"data";}}i:22;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"b18981d903ee7fc211d36c01e5b1a305";s:4:"name";s:31:"data/templates/caption.tpl.html";s:4:"role";s:4:"data";}}i:23;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"cedd0f5a97ef9b2115f12524eb94d2ad";s:4:"name";s:39:"data/templates/categories.list.tpl.html";s:4:"role";s:4:"data";}}i:24;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"b86fb131baded66d958b70d6628832b4";s:4:"name";s:36:"data/templates/channel.list.tpl.html";s:4:"role";s:4:"data";}}i:25;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"109ecb0a9cbebe90cb21c92d3c50cf43";s:4:"name";s:29:"data/templates/error.tpl.html";s:4:"role";s:4:"data";}}i:26;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"d8c5490b4d8a34c3aeff56ef6c811eba";s:4:"name";s:34:"data/templates/footer.inc.tpl.html";s:4:"role";s:4:"data";}}i:27;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"01abe0e6ad8d3a37175e94f2bbc035c9";s:4:"name";s:48:"data/templates/generic_table_horizontal.tpl.html";s:4:"role";s:4:"data";}}i:28;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"dda113e0a3881867501ca21bd665ba8b";s:4:"name";s:46:"data/templates/generic_table_vertical.tpl.html";s:4:"role";s:4:"data";}}i:29;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"7e42fdab403903928291024e0a47f333";s:4:"name";s:34:"data/templates/header.inc.tpl.html";s:4:"role";s:4:"data";}}i:30;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"b9353c56426a02f1e3df3c36fa4f6300";s:4:"name";s:28:"data/templates/info.tpl.html";s:4:"role";s:4:"data";}}i:31;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"46c6903f3aeca9de0fcf61605b935cfc";s:4:"name";s:36:"data/templates/package.info.tpl.html";s:4:"role";s:4:"data";}}i:32;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"5c76148ad3ec93ae5fdb806ea61d2966";s:4:"name";s:42:"data/templates/package.list_nocat.tpl.html";s:4:"role";s:4:"data";}}i:33;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"ec801819a4ba1a9d79dac2f449ac68ef";s:4:"name";s:36:"data/templates/package.list.tpl.html";s:4:"role";s:4:"data";}}i:34;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"307a1b0e5e2c599aa54f51a3c5c432d6";s:4:"name";s:40:"data/templates/package.manually.tpl.html";s:4:"role";s:4:"data";}}i:35;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"a217985c9c2c44bccd882aada418eae2";s:4:"name";s:39:"data/templates/package.submenu.tpl.html";s:4:"role";s:4:"data";}}i:36;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"dc79521052deecb9d0eebdf947a3813b";s:4:"name";s:30:"data/templates/search.tpl.html";s:4:"role";s:4:"data";}}i:37;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"10e3d9a24ab736227ec90fffa2b3fe43";s:4:"name";s:39:"data/templates/tableofchannels.tpl.html";s:4:"role";s:4:"data";}}i:38;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"ae3e51f5cf6e3dbfd10240ce1c1863ce";s:4:"name";s:31:"data/templates/top.inc.tpl.html";s:4:"role";s:4:"data";}}i:39;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"0161a5615717519d6b56ecf88ee9b99e";s:4:"name";s:35:"data/templates/upgrade_all.tpl.html";s:4:"role";s:4:"data";}}i:40;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"bdf2a26b1ec194625c9b45fb8ee08ac2";s:4:"name";s:34:"data/templates/userDialog.tpl.html";s:4:"role";s:4:"data";}}i:41;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"5b49b66bae0796bfaa81c6ddcc07c1eb";s:4:"name";s:15:"data/package.js";s:4:"role";s:4:"data";}}i:42;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"943b49e642faf8ce8eff783057719870";s:4:"name";s:14:"data/style.css";s:4:"role";s:4:"data";}}i:43;a:2:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"3aa8d4a2cc7b76c24ecef0eab270b9e5";s:4:"name";s:18:"docs/index.php.txt";s:4:"role";s:3:"doc";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:10:"@pear_dir@";s:2:"to";s:7:"php_dir";s:4:"type";s:11:"pear-config";}}}i:44;a:2:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"69f359fc910291c9d94bbc073ff93720";s:4:"name";s:16:"docs/example.php";s:4:"role";s:3:"doc";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:10:"@pear_dir@";s:2:"to";s:7:"php_dir";s:4:"type";s:11:"pear-config";}}}i:45;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"5db38efed34870b71b5bcb2dce401b59";s:4:"name";s:13:"docs/htaccess";s:4:"role";s:3:"doc";}}i:46;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"124e2f9b362d2339210c6a08d7792178";s:4:"name";s:26:"Frontend/Web/Docviewer.php";s:4:"role";s:3:"php";}}i:47;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"21f77cd6cbfc5931412af40ddefc83a8";s:4:"name";s:16:"Frontend/Web.php";s:4:"role";s:3:"php";}}i:48;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"133856e4d22214c466ead4b6d8d9f4de";s:4:"name";s:19:"pearfrontendweb.php";s:4:"role";s:3:"php";}}i:49;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"adb8c50232c954549a9fa3cfbf116e2e";s:4:"name";s:6:"README";s:4:"role";s:3:"doc";}}}}}s:12:"dependencies";a:1:{s:8:"required";a:3:{s:3:"php";a:1:{s:3:"min";s:5:"4.3.0";}s:13:"pearinstaller";a:1:{s:3:"min";s:5:"1.6.1";}s:7:"package";a:2:{i:0;a:2:{s:4:"name";s:16:"HTML_Template_IT";s:7:"channel";s:12:"pear.php.net";}i:1;a:3:{s:4:"name";s:4:"PEAR";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:5:"1.6.1";}}}}s:10:"phprelease";s:0:"";s:9:"changelog";a:1:{s:7:"release";a:10:{i:0;a:5:{s:4:"date";s:10:"2008-01-20";s:7:"version";a:2:{s:7:"release";s:5:"0.7.2";s:3:"api";s:5:"0.7.0";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:4:"beta";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:196:"* more robust path detection ++ Bug #11485 directory separator ++ Bug #11525 cannot read the template file error ++ Bug #11487 recursive errors ++ Bug #12403 Incorrect path search for config.conf file";}i:1;a:5:{s:4:"date";s:10:"2007-06-26";s:7:"version";a:2:{s:7:"release";s:5:"0.7.1";s:3:"api";s:5:"0.7.0";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:4:"beta";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:334:"* Remove CommandForwardCompatible stuff as it has almost all been merged into PEAR +* Add Command/Categories for the category stuff that was not merged +* Remove a rogue php notice ++ Bug #11300 array_walk_recursive() is a PHP 5 only function +* Colorize and auto-url some output (eg pear install is now much more clear for novice users)";}i:2;a:5:{s:4:"date";s:10:"2007-05-22";s:7:"version";a:2:{s:7:"release";s:5:"0.7.0";s:3:"api";s:5:"0.7.0";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:4:"beta";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:539:"Make more stable: [tias] +* Rewrite launch script [Done] +* Rewrite documentation [Done] +* Make postinstallscripts work [Done] +* Some auto-urling [Done] +* Remove E_Notices and checkcode warnings [Done] +* Unify list of packages output [Done] +* Rename files to standard [Done] +* Add 'Docviewer' [Done] + + * Fix Bug #11028: Post Install shows numerous empty variables errors. [tias] + * Fix Bug #11029: Post Install Error Message - Depreciated Function Call [tias] + * Implement Feature #10887: list-category for channels like pearified.com [tias]";}i:3;a:5:{s:4:"date";s:10:"2007-04-27";s:7:"version";a:2:{s:7:"release";s:5:"0.6.1";s:3:"api";s:5:"0.6.0";}s:9:"stability";a:2:{s:7:"release";s:5:"alpha";s:3:"api";s:5:"alpha";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:277:"Emergency release for go-pear compatibility: +Put docs/example.php back in place: go-pear uses this ! index.php.txt continues to exist because imho docs may not be executable things (so example.php is only there for BC) ++ Bug #10853 "Array" printed when upgrading or installing";}i:4;a:5:{s:4:"date";s:10:"2007-04-26";s:7:"version";a:2:{s:7:"release";s:5:"0.6.0";s:3:"api";s:5:"0.6.0";}s:9:"stability";a:2:{s:7:"release";s:5:"alpha";s:3:"api";s:5:"alpha";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:463:"Reworked webfrontend: [Tias] +* Use 'list' and 'list-upgrades' commands instead of the slow 'list-all' when possible +* Use command 'info' for installed packages +* Add proper documentation +* Make 'search' work over all channels +* Change 'list all packages' too 'list all categories' and list it for _all_ channels (also provide dry list of package names) +* Remove unnecessary DHTML stuff +* Make it easy to set up the frontend for an existing pear installation";}i:5;a:5:{s:4:"date";s:10:"2007-04-03";s:7:"version";a:2:{s:7:"release";s:5:"0.5.2";s:3:"api";s:5:"0.5.1";}s:9:"stability";a:2:{s:7:"release";s:5:"alpha";s:3:"api";s:5:"alpha";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:422:"* Fix Bug #10427: wrong dependencies [tias] +* Fix Bug #10428: install dependencies of package [tias] +* Fix Bug #10429: some small bugfixes [tias] +* Fix Bug #10430: remote-info broken for installed packages [tias] +* Small changes in the templates files, that makes stuff much nicer +* config-show submit: only config-set what has changed (and never the buggy Filename that can not be changed this way), and output it nicely.";}i:6;a:6:{s:4:"date";s:10:"2006-04-18";s:4:"time";s:8:"01:07:41";s:7:"version";a:2:{s:7:"release";s:5:"0.5.1";s:3:"api";s:5:"0.5.1";}s:9:"stability";a:2:{s:7:"release";s:5:"alpha";s:3:"api";s:5:"alpha";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:206:"- #6995 missing require_once in Web.php +- #6993 prevents large response time, create the cache_dir + if it does not exist +- #7319, bad display of errors when the install cmd failed +- remove Pager dependency";}i:7;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"0.5.0";s:3:"api";s:5:"0.5.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2005-03-02";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:111:"Major features addition: channel support +Also, support for post-install scripts on install, and package.xml 2.0";}i:8;a:5:{s:7:"version";a:2:{s:7:"release";s:3:"0.3";s:3:"api";s:3:"0.3";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2003-05-28";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:138:"Bugfixes release: +- Fix a bug while using both CLI and Web installer + (Invalid characters, bug #23516) +- Installs correctly the CLI tools";}i:9;a:5:{s:7:"version";a:2:{s:7:"release";s:3:"0.4";s:3:"api";s:3:"0.4";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2003-06-07";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:179:"Bugfixes release: +- Remove Pager dep +- Should work well on non apache system (ie IIS) +- The 'installed packages' is now the entry page + (no more remote connection during startup)";}}}s:8:"filelist";a:50:{s:22:"Command/Categories.php";a:5:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"537b747e123810c7c732a299bba3e380";s:4:"name";s:22:"Command/Categories.php";s:4:"role";s:3:"php";s:12:"installed_as";s:62:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Command/Categories.php";}s:22:"Command/Categories.xml";a:5:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"3e7a870a30debaeb83a843c41368c581";s:4:"name";s:22:"Command/Categories.xml";s:4:"role";s:3:"php";s:12:"installed_as";s:62:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Command/Categories.xml";}s:24:"data/images/category.jpg";a:5:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"77605580daff87d2ea0855db327aab3c";s:4:"name";s:24:"data/images/category.jpg";s:4:"role";s:4:"data";s:12:"installed_as";s:82:"/www/htdocs/w00acdb0/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/category.jpg";}s:22:"data/images/config.gif";a:5:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"89fbaf12b03630cde8fab8f582a2013e";s:4:"name";s:22:"data/images/config.gif";s:4:"role";s:4:"data";s:12:"installed_as";s:80:"/www/htdocs/w00acdb0/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/config.gif";}s:24:"data/images/download.gif";a:5:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"917c5480d7887a45fb7ee9e75ffdc90f";s:4:"name";s:24:"data/images/download.gif";s:4:"role";s:4:"data";s:12:"installed_as";s:82:"/www/htdocs/w00acdb0/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/download.gif";}s:21:"data/images/error.gif";a:5:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"b7910926d28d2174f766edcd5b0203f3";s:4:"name";s:21:"data/images/error.gif";s:4:"role";s:4:"data";s:12:"installed_as";s:79:"/www/htdocs/w00acdb0/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/error.gif";}s:20:"data/images/info.gif";a:5:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"a9fd915f941d8b2767a86a7b86c1157d";s:4:"name";s:20:"data/images/info.gif";s:4:"role";s:4:"data";s:12:"installed_as";s:78:"/www/htdocs/w00acdb0/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/info.gif";}s:24:"data/images/infoplus.gif";a:5:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"25ea72ec541af2d75e1c6084bb51c799";s:4:"name";s:24:"data/images/infoplus.gif";s:4:"role";s:4:"data";s:12:"installed_as";s:82:"/www/htdocs/w00acdb0/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/infoplus.gif";}s:28:"data/images/install_fail.gif";a:5:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"3d5ed1a26b7ba8c9d144d289e40359dd";s:4:"name";s:28:"data/images/install_fail.gif";s:4:"role";s:4:"data";s:12:"installed_as";s:86:"/www/htdocs/w00acdb0/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/install_fail.gif";}s:23:"data/images/install.gif";a:5:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"bf40b1ad414777f2ec1ffd8f49db8cb8";s:4:"name";s:23:"data/images/install.gif";s:4:"role";s:4:"data";s:12:"installed_as";s:81:"/www/htdocs/w00acdb0/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/install.gif";}s:26:"data/images/install_ok.gif";a:5:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"b1bd4bab6452562b624834691a2537c6";s:4:"name";s:26:"data/images/install_ok.gif";s:4:"role";s:4:"data";s:12:"installed_as";s:84:"/www/htdocs/w00acdb0/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/install_ok.gif";}s:28:"data/images/install_wait.gif";a:5:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"7b0098f037a686f02b925333a30161e9";s:4:"name";s:28:"data/images/install_wait.gif";s:4:"role";s:4:"data";s:12:"installed_as";s:86:"/www/htdocs/w00acdb0/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/install_wait.gif";}s:21:"data/images/login.gif";a:5:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"06f6632208ac488b25c582100d97d03d";s:4:"name";s:21:"data/images/login.gif";s:4:"role";s:4:"data";s:12:"installed_as";s:79:"/www/htdocs/w00acdb0/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/login.gif";}s:22:"data/images/logout.gif";a:5:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"b6ec4b263faa470ff1150637b0d7c63e";s:4:"name";s:22:"data/images/logout.gif";s:4:"role";s:4:"data";s:12:"installed_as";s:80:"/www/htdocs/w00acdb0/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/logout.gif";}s:22:"data/images/manual.gif";a:5:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"4c36ad8eaa614f2ce07600789e1193ae";s:4:"name";s:22:"data/images/manual.gif";s:4:"role";s:4:"data";s:12:"installed_as";s:80:"/www/htdocs/w00acdb0/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/manual.gif";}s:26:"data/images/manualplus.gif";a:5:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"3eca2224677c9f266297e4187b0f2db7";s:4:"name";s:26:"data/images/manualplus.gif";s:4:"role";s:4:"data";s:12:"installed_as";s:84:"/www/htdocs/w00acdb0/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/manualplus.gif";}s:23:"data/images/package.jpg";a:5:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"a059eafc2fb95b0ca42977e29d391cff";s:4:"name";s:23:"data/images/package.jpg";s:4:"role";s:4:"data";s:12:"installed_as";s:81:"/www/htdocs/w00acdb0/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/package.jpg";}s:25:"data/images/pearsmall.gif";a:5:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"1f0ca8116ffeafac272a3f1a8325e408";s:4:"name";s:25:"data/images/pearsmall.gif";s:4:"role";s:4:"data";s:12:"installed_as";s:83:"/www/htdocs/w00acdb0/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/pearsmall.gif";}s:23:"data/images/pkglist.png";a:5:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"3bed4b639af3ba0b136c0201ac505a7b";s:4:"name";s:23:"data/images/pkglist.png";s:4:"role";s:4:"data";s:12:"installed_as";s:81:"/www/htdocs/w00acdb0/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/pkglist.png";}s:25:"data/images/pkgsearch.png";a:5:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"7f8ff108546c678f59f6b8c88ab43c92";s:4:"name";s:25:"data/images/pkgsearch.png";s:4:"role";s:4:"data";s:12:"installed_as";s:83:"/www/htdocs/w00acdb0/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/pkgsearch.png";}s:21:"data/images/trash.gif";a:5:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"5c897611197c28498c03da298e5558d7";s:4:"name";s:21:"data/images/trash.gif";s:4:"role";s:4:"data";s:12:"installed_as";s:79:"/www/htdocs/w00acdb0/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/trash.gif";}s:34:"data/templates/bottom.inc.tpl.html";a:5:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"d4e1fcabab3e47008e887626905f1054";s:4:"name";s:34:"data/templates/bottom.inc.tpl.html";s:4:"role";s:4:"data";s:12:"installed_as";s:92:"/www/htdocs/w00acdb0/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/bottom.inc.tpl.html";}s:31:"data/templates/caption.tpl.html";a:5:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"b18981d903ee7fc211d36c01e5b1a305";s:4:"name";s:31:"data/templates/caption.tpl.html";s:4:"role";s:4:"data";s:12:"installed_as";s:89:"/www/htdocs/w00acdb0/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/caption.tpl.html";}s:39:"data/templates/categories.list.tpl.html";a:5:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"cedd0f5a97ef9b2115f12524eb94d2ad";s:4:"name";s:39:"data/templates/categories.list.tpl.html";s:4:"role";s:4:"data";s:12:"installed_as";s:97:"/www/htdocs/w00acdb0/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/categories.list.tpl.html";}s:36:"data/templates/channel.list.tpl.html";a:5:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"b86fb131baded66d958b70d6628832b4";s:4:"name";s:36:"data/templates/channel.list.tpl.html";s:4:"role";s:4:"data";s:12:"installed_as";s:94:"/www/htdocs/w00acdb0/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/channel.list.tpl.html";}s:29:"data/templates/error.tpl.html";a:5:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"109ecb0a9cbebe90cb21c92d3c50cf43";s:4:"name";s:29:"data/templates/error.tpl.html";s:4:"role";s:4:"data";s:12:"installed_as";s:87:"/www/htdocs/w00acdb0/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/error.tpl.html";}s:34:"data/templates/footer.inc.tpl.html";a:5:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"d8c5490b4d8a34c3aeff56ef6c811eba";s:4:"name";s:34:"data/templates/footer.inc.tpl.html";s:4:"role";s:4:"data";s:12:"installed_as";s:92:"/www/htdocs/w00acdb0/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/footer.inc.tpl.html";}s:48:"data/templates/generic_table_horizontal.tpl.html";a:5:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"01abe0e6ad8d3a37175e94f2bbc035c9";s:4:"name";s:48:"data/templates/generic_table_horizontal.tpl.html";s:4:"role";s:4:"data";s:12:"installed_as";s:106:"/www/htdocs/w00acdb0/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/generic_table_horizontal.tpl.html";}s:46:"data/templates/generic_table_vertical.tpl.html";a:5:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"dda113e0a3881867501ca21bd665ba8b";s:4:"name";s:46:"data/templates/generic_table_vertical.tpl.html";s:4:"role";s:4:"data";s:12:"installed_as";s:104:"/www/htdocs/w00acdb0/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/generic_table_vertical.tpl.html";}s:34:"data/templates/header.inc.tpl.html";a:5:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"7e42fdab403903928291024e0a47f333";s:4:"name";s:34:"data/templates/header.inc.tpl.html";s:4:"role";s:4:"data";s:12:"installed_as";s:92:"/www/htdocs/w00acdb0/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/header.inc.tpl.html";}s:28:"data/templates/info.tpl.html";a:5:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"b9353c56426a02f1e3df3c36fa4f6300";s:4:"name";s:28:"data/templates/info.tpl.html";s:4:"role";s:4:"data";s:12:"installed_as";s:86:"/www/htdocs/w00acdb0/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/info.tpl.html";}s:36:"data/templates/package.info.tpl.html";a:5:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"46c6903f3aeca9de0fcf61605b935cfc";s:4:"name";s:36:"data/templates/package.info.tpl.html";s:4:"role";s:4:"data";s:12:"installed_as";s:94:"/www/htdocs/w00acdb0/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/package.info.tpl.html";}s:42:"data/templates/package.list_nocat.tpl.html";a:5:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"5c76148ad3ec93ae5fdb806ea61d2966";s:4:"name";s:42:"data/templates/package.list_nocat.tpl.html";s:4:"role";s:4:"data";s:12:"installed_as";s:100:"/www/htdocs/w00acdb0/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/package.list_nocat.tpl.html";}s:36:"data/templates/package.list.tpl.html";a:5:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"ec801819a4ba1a9d79dac2f449ac68ef";s:4:"name";s:36:"data/templates/package.list.tpl.html";s:4:"role";s:4:"data";s:12:"installed_as";s:94:"/www/htdocs/w00acdb0/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/package.list.tpl.html";}s:40:"data/templates/package.manually.tpl.html";a:5:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"307a1b0e5e2c599aa54f51a3c5c432d6";s:4:"name";s:40:"data/templates/package.manually.tpl.html";s:4:"role";s:4:"data";s:12:"installed_as";s:98:"/www/htdocs/w00acdb0/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/package.manually.tpl.html";}s:39:"data/templates/package.submenu.tpl.html";a:5:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"a217985c9c2c44bccd882aada418eae2";s:4:"name";s:39:"data/templates/package.submenu.tpl.html";s:4:"role";s:4:"data";s:12:"installed_as";s:97:"/www/htdocs/w00acdb0/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/package.submenu.tpl.html";}s:30:"data/templates/search.tpl.html";a:5:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"dc79521052deecb9d0eebdf947a3813b";s:4:"name";s:30:"data/templates/search.tpl.html";s:4:"role";s:4:"data";s:12:"installed_as";s:88:"/www/htdocs/w00acdb0/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/search.tpl.html";}s:39:"data/templates/tableofchannels.tpl.html";a:5:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"10e3d9a24ab736227ec90fffa2b3fe43";s:4:"name";s:39:"data/templates/tableofchannels.tpl.html";s:4:"role";s:4:"data";s:12:"installed_as";s:97:"/www/htdocs/w00acdb0/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/tableofchannels.tpl.html";}s:31:"data/templates/top.inc.tpl.html";a:5:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"ae3e51f5cf6e3dbfd10240ce1c1863ce";s:4:"name";s:31:"data/templates/top.inc.tpl.html";s:4:"role";s:4:"data";s:12:"installed_as";s:89:"/www/htdocs/w00acdb0/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/top.inc.tpl.html";}s:35:"data/templates/upgrade_all.tpl.html";a:5:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"0161a5615717519d6b56ecf88ee9b99e";s:4:"name";s:35:"data/templates/upgrade_all.tpl.html";s:4:"role";s:4:"data";s:12:"installed_as";s:93:"/www/htdocs/w00acdb0/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/upgrade_all.tpl.html";}s:34:"data/templates/userDialog.tpl.html";a:5:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"bdf2a26b1ec194625c9b45fb8ee08ac2";s:4:"name";s:34:"data/templates/userDialog.tpl.html";s:4:"role";s:4:"data";s:12:"installed_as";s:92:"/www/htdocs/w00acdb0/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/userDialog.tpl.html";}s:15:"data/package.js";a:5:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"5b49b66bae0796bfaa81c6ddcc07c1eb";s:4:"name";s:15:"data/package.js";s:4:"role";s:4:"data";s:12:"installed_as";s:73:"/www/htdocs/w00acdb0/lib/pear/PEAR/data/PEAR_Frontend_Web/data/package.js";}s:14:"data/style.css";a:5:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"943b49e642faf8ce8eff783057719870";s:4:"name";s:14:"data/style.css";s:4:"role";s:4:"data";s:12:"installed_as";s:72:"/www/htdocs/w00acdb0/lib/pear/PEAR/data/PEAR_Frontend_Web/data/style.css";}s:18:"docs/index.php.txt";a:5:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"3aa8d4a2cc7b76c24ecef0eab270b9e5";s:4:"name";s:18:"docs/index.php.txt";s:4:"role";s:3:"doc";s:12:"installed_as";s:76:"/www/htdocs/w00acdb0/lib/pear/PEAR/docs/PEAR_Frontend_Web/docs/index.php.txt";}s:16:"docs/example.php";a:5:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"69f359fc910291c9d94bbc073ff93720";s:4:"name";s:16:"docs/example.php";s:4:"role";s:3:"doc";s:12:"installed_as";s:74:"/www/htdocs/w00acdb0/lib/pear/PEAR/docs/PEAR_Frontend_Web/docs/example.php";}s:13:"docs/htaccess";a:5:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"5db38efed34870b71b5bcb2dce401b59";s:4:"name";s:13:"docs/htaccess";s:4:"role";s:3:"doc";s:12:"installed_as";s:71:"/www/htdocs/w00acdb0/lib/pear/PEAR/docs/PEAR_Frontend_Web/docs/htaccess";}s:26:"Frontend/Web/Docviewer.php";a:5:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"124e2f9b362d2339210c6a08d7792178";s:4:"name";s:26:"Frontend/Web/Docviewer.php";s:4:"role";s:3:"php";s:12:"installed_as";s:66:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Frontend/Web/Docviewer.php";}s:16:"Frontend/Web.php";a:5:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"21f77cd6cbfc5931412af40ddefc83a8";s:4:"name";s:16:"Frontend/Web.php";s:4:"role";s:3:"php";s:12:"installed_as";s:56:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Frontend/Web.php";}s:19:"pearfrontendweb.php";a:5:{s:14:"baseinstalldir";s:1:"/";s:6:"md5sum";s:32:"133856e4d22214c466ead4b6d8d9f4de";s:4:"name";s:19:"pearfrontendweb.php";s:4:"role";s:3:"php";s:12:"installed_as";s:54:"/www/htdocs/w00acdb0/lib/pear/PEAR/pearfrontendweb.php";}s:6:"README";a:5:{s:14:"baseinstalldir";s:4:"PEAR";s:6:"md5sum";s:32:"adb8c50232c954549a9fa3cfbf116e2e";s:4:"name";s:6:"README";s:4:"role";s:3:"doc";s:12:"installed_as";s:64:"/www/htdocs/w00acdb0/lib/pear/PEAR/docs/PEAR_Frontend_Web/README";}}s:12:"_lastversion";N;s:7:"dirtree";a:11:{s:47:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Command";b:1;s:39:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR";b:1;s:69:"/www/htdocs/w00acdb0/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images";b:1;s:62:"/www/htdocs/w00acdb0/lib/pear/PEAR/data/PEAR_Frontend_Web/data";b:1;s:57:"/www/htdocs/w00acdb0/lib/pear/PEAR/data/PEAR_Frontend_Web";b:1;s:72:"/www/htdocs/w00acdb0/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates";b:1;s:62:"/www/htdocs/w00acdb0/lib/pear/PEAR/docs/PEAR_Frontend_Web/docs";b:1;s:57:"/www/htdocs/w00acdb0/lib/pear/PEAR/docs/PEAR_Frontend_Web";b:1;s:52:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Frontend/Web";b:1;s:48:"/www/htdocs/w00acdb0/lib/pear/PEAR/PEAR/Frontend";b:1;s:34:"/www/htdocs/w00acdb0/lib/pear/PEAR";b:1;}s:3:"old";a:7:{s:7:"version";s:5:"0.7.3";s:12:"release_date";s:10:"2008-08-03";s:13:"release_state";s:4:"beta";s:15:"release_license";s:11:"PHP License";s:13:"release_notes";s:215:"* Fix bug #13703 no empty channel url +* fix bug #13714 'package information' link on installing local file +* for the open_basedir prisoners, don't allow PEAR to search for a temp dir (would use /tmp), see bug #13167";s:12:"release_deps";a:4:{i:0;a:4:{s:4:"type";s:3:"php";s:3:"rel";s:2:"ge";s:7:"version";s:5:"4.3.0";s:8:"optional";s:2:"no";}i:1;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:4:"PEAR";s:3:"rel";s:2:"ge";s:7:"version";s:5:"1.6.1";s:8:"optional";s:2:"no";}i:2;a:5:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:16:"HTML_Template_IT";s:3:"rel";s:3:"has";s:8:"optional";s:2:"no";}i:3;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:4:"PEAR";s:3:"rel";s:2:"ge";s:7:"version";s:5:"1.6.1";s:8:"optional";s:2:"no";}}s:11:"maintainers";a:5:{i:0;a:5:{s:4:"name";s:9:"Tias Guns";s:5:"email";s:16:"tias@ulyssis.org";s:6:"active";s:3:"yes";s:6:"handle";s:4:"tias";s:4:"role";s:4:"lead";}i:1;a:5:{s:4:"name";s:14:"Gregory Beaver";s:5:"email";s:14:"cellog@php.net";s:6:"active";s:3:"yes";s:6:"handle";s:6:"cellog";s:4:"role";s:4:"lead";}i:2;a:5:{s:4:"name";s:18:"Christian Dickmann";s:5:"email";s:16:"dickmann@php.net";s:6:"active";s:2:"no";s:6:"handle";s:8:"dickmann";s:4:"role";s:4:"lead";}i:3;a:5:{s:4:"name";s:17:"Pierre-Alain Joye";s:5:"email";s:17:"pajoye@pearfr.org";s:6:"active";s:2:"no";s:6:"handle";s:6:"pajoye";s:4:"role";s:4:"lead";}i:4;a:5:{s:4:"name";s:11:"Stig Bakken";s:5:"email";s:12:"stig@php.net";s:6:"active";s:2:"no";s:6:"handle";s:3:"ssb";s:4:"role";s:6:"helper";}}}s:10:"xsdversion";s:3:"2.0";s:13:"_lastmodified";i:1234655683;} \ No newline at end of file diff --git a/src/lib/pear/PEAR/.registry/structures_graph.reg b/src/lib/pear/PEAR/.registry/structures_graph.reg new file mode 100644 index 0000000..95bb198 --- /dev/null +++ b/src/lib/pear/PEAR/.registry/structures_graph.reg @@ -0,0 +1,6 @@ +a:22:{s:7:"attribs";a:6:{s:15:"packagerversion";s:5:"1.5.0";s:7:"version";s:3:"2.0";s:5:"xmlns";s:35:"http://pear.php.net/dtd/package-2.0";s:11:"xmlns:tasks";s:33:"http://pear.php.net/dtd/tasks-1.0";s:9:"xmlns:xsi";s:41:"http://www.w3.org/2001/XMLSchema-instance";s:18:"xsi:schemaLocation";s:159:"http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd";}s:4:"name";s:16:"Structures_Graph";s:7:"channel";s:12:"pear.php.net";s:7:"summary";s:40:"Graph datastructure manipulation library";s:11:"description";s:293:"Structures_Graph is a package for creating and manipulating graph datastructures. It allows building of directed +and undirected graphs, with data and metadata stored in nodes. The library provides functions for graph traversing +as well as for characteristic extraction from the graph topology.";s:4:"lead";a:4:{s:4:"name";s:16:"Sérgio Carvalho";s:4:"user";s:9:"sergiosgc";s:5:"email";s:32:"sergio.carvalho@portugalmail.com";s:6:"active";s:3:"yes";}s:4:"date";s:10:"2007-02-01";s:4:"time";s:8:"17:45:32";s:7:"version";a:2:{s:7:"release";s:5:"1.0.2";s:3:"api";s:5:"1.0.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:47:"http://opensource.org/licenses/lgpl-license.php";}s:8:"_content";s:4:"LGPL";}s:5:"notes";s:130:"- Bug #9682 only variables can be returned by reference +- fix Bug #9661 notice in Structures_Graph_Manipulator_Topological::sort()";s:8:"contents";a:1:{s:3:"dir";a:2:{s:7:"attribs";a:2:{s:14:"baseinstalldir";s:0:"";s:4:"name";s:1:"/";}s:4:"file";a:32:{i:0;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"039cb8781dae7b5f5661dc2892fb53b5";s:4:"name";s:26:"docs/html/media/banner.css";s:4:"role";s:3:"doc";}}i:1;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"8ff124484e8a009f94a8d0b4d9b8b1cd";s:4:"name";s:30:"docs/html/media/stylesheet.css";s:4:"role";s:3:"doc";}}i:2;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"a17210dd27171316f5cb446a5bef59ab";s:4:"name";s:48:"docs/html/Structures_Graph/Structures_Graph.html";s:4:"role";s:3:"doc";}}i:3;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"1ed0ac55530b7504c00df35f335e7ef3";s:4:"name";s:72:"docs/html/Structures_Graph/Structures_Graph_Manipulator_AcyclicTest.html";s:4:"role";s:3:"doc";}}i:4;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"fefb65755d57a87d2736e058a1095b03";s:4:"name";s:78:"docs/html/Structures_Graph/Structures_Graph_Manipulator_TopologicalSorter.html";s:4:"role";s:3:"doc";}}i:5;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"afb0e3afb91beafd1bc16a07ac31c826";s:4:"name";s:53:"docs/html/Structures_Graph/Structures_Graph_Node.html";s:4:"role";s:3:"doc";}}i:6;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"3fa477998b281061361c4d98fb78c3a8";s:4:"name";s:61:"docs/html/Structures_Graph/tutorial_Structures_Graph.pkg.html";s:4:"role";s:3:"doc";}}i:7;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"c46e6566be5249811667ddc7decf405f";s:4:"name";s:77:"docs/html/Structures_Graph/_Structures_Graph_Manipulator_AcyclicTest_php.html";s:4:"role";s:3:"doc";}}i:8;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"c45890d45dd42dc56adb71988c3a45c1";s:4:"name";s:83:"docs/html/Structures_Graph/_Structures_Graph_Manipulator_TopologicalSorter_php.html";s:4:"role";s:3:"doc";}}i:9;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"09cb6d17f96553bfb66b99c502676844";s:4:"name";s:58:"docs/html/Structures_Graph/_Structures_Graph_Node_php.html";s:4:"role";s:3:"doc";}}i:10;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"78e1e7ec43a6e754cf4d5dace48fe18c";s:4:"name";s:53:"docs/html/Structures_Graph/_Structures_Graph_php.html";s:4:"role";s:3:"doc";}}i:11;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"d0ada99c3b7e95b23461cc3e713f0c3d";s:4:"name";s:42:"docs/html/classtrees_Structures_Graph.html";s:4:"role";s:3:"doc";}}i:12;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"898dd26ccc1c1572d36e9879afcb5d39";s:4:"name";s:27:"docs/html/elementindex.html";s:4:"role";s:3:"doc";}}i:13;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"19dd287d44163d2abde1a1d8d52521f8";s:4:"name";s:44:"docs/html/elementindex_Structures_Graph.html";s:4:"role";s:3:"doc";}}i:14;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"ae809f6ebbf632351648c340d2d6acd4";s:4:"name";s:21:"docs/html/errors.html";s:4:"role";s:3:"doc";}}i:15;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"db3206e7d176ae78fd04f22acead5ffa";s:4:"name";s:20:"docs/html/index.html";s:4:"role";s:3:"doc";}}i:16;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"4ec087627323546610b64d69a6aafca6";s:4:"name";s:34:"docs/html/li_Structures_Graph.html";s:4:"role";s:3:"doc";}}i:17;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"005081a4c5d60afcbabc1f4909ebfcad";s:4:"name";s:23:"docs/html/packages.html";s:4:"role";s:3:"doc";}}i:18;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"a7a1b748bbda6dfa1632bf6078fc8bb6";s:4:"name";s:23:"docs/html/todolist.html";s:4:"role";s:3:"doc";}}i:19;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"628eb6532a8047bf5962fe24c1c245df";s:4:"name";s:52:"docs/tutorials/Structures_Graph/Structures_Graph.pkg";s:4:"role";s:3:"doc";}}i:20;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"ce2da39dbb75e21074eb5e96231a3379";s:4:"name";s:16:"docs/generate.sh";s:4:"role";s:3:"doc";}}i:21;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"f0aff5a1efd188d63b4b8b9e9e840b97";s:4:"name";s:44:"Structures/Graph/Manipulator/AcyclicTest.php";s:4:"role";s:3:"php";}}i:22;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"0492e677436d29228df93dca23629e06";s:4:"name";s:50:"Structures/Graph/Manipulator/TopologicalSorter.php";s:4:"role";s:3:"php";}}i:23;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"7e28e01ebfa273e5df2eb1ef7a356635";s:4:"name";s:25:"Structures/Graph/Node.php";s:4:"role";s:3:"php";}}i:24;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"4f25a6275af156f6f8e7b4309cb9f40d";s:4:"name";s:20:"Structures/Graph.php";s:4:"role";s:3:"php";}}i:25;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"63dfc6f0f14e18c13d8a8415c3fe049d";s:4:"name";s:29:"tests/testCase/BasicGraph.php";s:4:"role";s:4:"test";}}i:26;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"1b9e35896d229b84601e6754cd44e339";s:4:"name";s:19:"tests/all-tests.php";s:4:"role";s:4:"test";}}i:27;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:12:"tests/README";s:4:"role";s:4:"test";}}i:28;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"ab23406ec7bfbb2029ca536378ff57db";s:4:"name";s:17:"genpackage.xml.pl";s:4:"role";s:4:"data";}}i:29;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"7fbc338309ac38fefcd64b04bb903e34";s:4:"name";s:7:"LICENSE";s:4:"role";s:4:"data";}}i:30;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"6e782f281c7d0ce27e54b574247073cb";s:4:"name";s:10:"package.sh";s:4:"role";s:4:"data";}}i:31;a:1:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"b81f67f7b5600231735243be73625e54";s:4:"name";s:10:"publish.sh";s:4:"role";s:4:"data";}}}}}s:12:"dependencies";a:1:{s:8:"required";a:2:{s:3:"php";a:1:{s:3:"min";s:5:"4.2.0";}s:13:"pearinstaller";a:1:{s:3:"min";s:5:"1.4.3";}}}s:10:"phprelease";s:0:"";s:9:"changelog";a:1:{s:7:"release";a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.0.2";s:3:"api";s:5:"1.0.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2007-01-07";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:47:"http://opensource.org/licenses/lgpl-license.php";}s:8:"_content";s:4:"LGPL";}s:5:"notes";s:130:"- Bug #9682 only variables can be returned by reference +- fix Bug #9661 notice in Structures_Graph_Manipulator_Topological::sort()";}}s:8:"filelist";a:32:{s:26:"docs/html/media/banner.css";a:5:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"039cb8781dae7b5f5661dc2892fb53b5";s:4:"name";s:26:"docs/html/media/banner.css";s:4:"role";s:3:"doc";s:12:"installed_as";s:83:"/www/htdocs/w00acdb0/lib/pear/PEAR/docs/Structures_Graph/docs/html/media/banner.css";}s:30:"docs/html/media/stylesheet.css";a:5:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"8ff124484e8a009f94a8d0b4d9b8b1cd";s:4:"name";s:30:"docs/html/media/stylesheet.css";s:4:"role";s:3:"doc";s:12:"installed_as";s:87:"/www/htdocs/w00acdb0/lib/pear/PEAR/docs/Structures_Graph/docs/html/media/stylesheet.css";}s:48:"docs/html/Structures_Graph/Structures_Graph.html";a:5:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"a17210dd27171316f5cb446a5bef59ab";s:4:"name";s:48:"docs/html/Structures_Graph/Structures_Graph.html";s:4:"role";s:3:"doc";s:12:"installed_as";s:105:"/www/htdocs/w00acdb0/lib/pear/PEAR/docs/Structures_Graph/docs/html/Structures_Graph/Structures_Graph.html";}s:72:"docs/html/Structures_Graph/Structures_Graph_Manipulator_AcyclicTest.html";a:5:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"1ed0ac55530b7504c00df35f335e7ef3";s:4:"name";s:72:"docs/html/Structures_Graph/Structures_Graph_Manipulator_AcyclicTest.html";s:4:"role";s:3:"doc";s:12:"installed_as";s:129:"/www/htdocs/w00acdb0/lib/pear/PEAR/docs/Structures_Graph/docs/html/Structures_Graph/Structures_Graph_Manipulator_AcyclicTest.html";}s:78:"docs/html/Structures_Graph/Structures_Graph_Manipulator_TopologicalSorter.html";a:5:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"fefb65755d57a87d2736e058a1095b03";s:4:"name";s:78:"docs/html/Structures_Graph/Structures_Graph_Manipulator_TopologicalSorter.html";s:4:"role";s:3:"doc";s:12:"installed_as";s:135:"/www/htdocs/w00acdb0/lib/pear/PEAR/docs/Structures_Graph/docs/html/Structures_Graph/Structures_Graph_Manipulator_TopologicalSorter.html";}s:53:"docs/html/Structures_Graph/Structures_Graph_Node.html";a:5:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"afb0e3afb91beafd1bc16a07ac31c826";s:4:"name";s:53:"docs/html/Structures_Graph/Structures_Graph_Node.html";s:4:"role";s:3:"doc";s:12:"installed_as";s:110:"/www/htdocs/w00acdb0/lib/pear/PEAR/docs/Structures_Graph/docs/html/Structures_Graph/Structures_Graph_Node.html";}s:61:"docs/html/Structures_Graph/tutorial_Structures_Graph.pkg.html";a:5:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"3fa477998b281061361c4d98fb78c3a8";s:4:"name";s:61:"docs/html/Structures_Graph/tutorial_Structures_Graph.pkg.html";s:4:"role";s:3:"doc";s:12:"installed_as";s:118:"/www/htdocs/w00acdb0/lib/pear/PEAR/docs/Structures_Graph/docs/html/Structures_Graph/tutorial_Structures_Graph.pkg.html";}s:77:"docs/html/Structures_Graph/_Structures_Graph_Manipulator_AcyclicTest_php.html";a:5:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"c46e6566be5249811667ddc7decf405f";s:4:"name";s:77:"docs/html/Structures_Graph/_Structures_Graph_Manipulator_AcyclicTest_php.html";s:4:"role";s:3:"doc";s:12:"installed_as";s:134:"/www/htdocs/w00acdb0/lib/pear/PEAR/docs/Structures_Graph/docs/html/Structures_Graph/_Structures_Graph_Manipulator_AcyclicTest_php.html";}s:83:"docs/html/Structures_Graph/_Structures_Graph_Manipulator_TopologicalSorter_php.html";a:5:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"c45890d45dd42dc56adb71988c3a45c1";s:4:"name";s:83:"docs/html/Structures_Graph/_Structures_Graph_Manipulator_TopologicalSorter_php.html";s:4:"role";s:3:"doc";s:12:"installed_as";s:140:"/www/htdocs/w00acdb0/lib/pear/PEAR/docs/Structures_Graph/docs/html/Structures_Graph/_Structures_Graph_Manipulator_TopologicalSorter_php.html";}s:58:"docs/html/Structures_Graph/_Structures_Graph_Node_php.html";a:5:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"09cb6d17f96553bfb66b99c502676844";s:4:"name";s:58:"docs/html/Structures_Graph/_Structures_Graph_Node_php.html";s:4:"role";s:3:"doc";s:12:"installed_as";s:115:"/www/htdocs/w00acdb0/lib/pear/PEAR/docs/Structures_Graph/docs/html/Structures_Graph/_Structures_Graph_Node_php.html";}s:53:"docs/html/Structures_Graph/_Structures_Graph_php.html";a:5:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"78e1e7ec43a6e754cf4d5dace48fe18c";s:4:"name";s:53:"docs/html/Structures_Graph/_Structures_Graph_php.html";s:4:"role";s:3:"doc";s:12:"installed_as";s:110:"/www/htdocs/w00acdb0/lib/pear/PEAR/docs/Structures_Graph/docs/html/Structures_Graph/_Structures_Graph_php.html";}s:42:"docs/html/classtrees_Structures_Graph.html";a:5:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"d0ada99c3b7e95b23461cc3e713f0c3d";s:4:"name";s:42:"docs/html/classtrees_Structures_Graph.html";s:4:"role";s:3:"doc";s:12:"installed_as";s:99:"/www/htdocs/w00acdb0/lib/pear/PEAR/docs/Structures_Graph/docs/html/classtrees_Structures_Graph.html";}s:27:"docs/html/elementindex.html";a:5:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"898dd26ccc1c1572d36e9879afcb5d39";s:4:"name";s:27:"docs/html/elementindex.html";s:4:"role";s:3:"doc";s:12:"installed_as";s:84:"/www/htdocs/w00acdb0/lib/pear/PEAR/docs/Structures_Graph/docs/html/elementindex.html";}s:44:"docs/html/elementindex_Structures_Graph.html";a:5:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"19dd287d44163d2abde1a1d8d52521f8";s:4:"name";s:44:"docs/html/elementindex_Structures_Graph.html";s:4:"role";s:3:"doc";s:12:"installed_as";s:101:"/www/htdocs/w00acdb0/lib/pear/PEAR/docs/Structures_Graph/docs/html/elementindex_Structures_Graph.html";}s:21:"docs/html/errors.html";a:5:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"ae809f6ebbf632351648c340d2d6acd4";s:4:"name";s:21:"docs/html/errors.html";s:4:"role";s:3:"doc";s:12:"installed_as";s:78:"/www/htdocs/w00acdb0/lib/pear/PEAR/docs/Structures_Graph/docs/html/errors.html";}s:20:"docs/html/index.html";a:5:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"db3206e7d176ae78fd04f22acead5ffa";s:4:"name";s:20:"docs/html/index.html";s:4:"role";s:3:"doc";s:12:"installed_as";s:77:"/www/htdocs/w00acdb0/lib/pear/PEAR/docs/Structures_Graph/docs/html/index.html";}s:34:"docs/html/li_Structures_Graph.html";a:5:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"4ec087627323546610b64d69a6aafca6";s:4:"name";s:34:"docs/html/li_Structures_Graph.html";s:4:"role";s:3:"doc";s:12:"installed_as";s:91:"/www/htdocs/w00acdb0/lib/pear/PEAR/docs/Structures_Graph/docs/html/li_Structures_Graph.html";}s:23:"docs/html/packages.html";a:5:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"005081a4c5d60afcbabc1f4909ebfcad";s:4:"name";s:23:"docs/html/packages.html";s:4:"role";s:3:"doc";s:12:"installed_as";s:80:"/www/htdocs/w00acdb0/lib/pear/PEAR/docs/Structures_Graph/docs/html/packages.html";}s:23:"docs/html/todolist.html";a:5:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"a7a1b748bbda6dfa1632bf6078fc8bb6";s:4:"name";s:23:"docs/html/todolist.html";s:4:"role";s:3:"doc";s:12:"installed_as";s:80:"/www/htdocs/w00acdb0/lib/pear/PEAR/docs/Structures_Graph/docs/html/todolist.html";}s:52:"docs/tutorials/Structures_Graph/Structures_Graph.pkg";a:5:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"628eb6532a8047bf5962fe24c1c245df";s:4:"name";s:52:"docs/tutorials/Structures_Graph/Structures_Graph.pkg";s:4:"role";s:3:"doc";s:12:"installed_as";s:109:"/www/htdocs/w00acdb0/lib/pear/PEAR/docs/Structures_Graph/docs/tutorials/Structures_Graph/Structures_Graph.pkg";}s:16:"docs/generate.sh";a:5:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"ce2da39dbb75e21074eb5e96231a3379";s:4:"name";s:16:"docs/generate.sh";s:4:"role";s:3:"doc";s:12:"installed_as";s:73:"/www/htdocs/w00acdb0/lib/pear/PEAR/docs/Structures_Graph/docs/generate.sh";}s:44:"Structures/Graph/Manipulator/AcyclicTest.php";a:5:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"f0aff5a1efd188d63b4b8b9e9e840b97";s:4:"name";s:44:"Structures/Graph/Manipulator/AcyclicTest.php";s:4:"role";s:3:"php";s:12:"installed_as";s:79:"/www/htdocs/w00acdb0/lib/pear/PEAR/Structures/Graph/Manipulator/AcyclicTest.php";}s:50:"Structures/Graph/Manipulator/TopologicalSorter.php";a:5:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"0492e677436d29228df93dca23629e06";s:4:"name";s:50:"Structures/Graph/Manipulator/TopologicalSorter.php";s:4:"role";s:3:"php";s:12:"installed_as";s:85:"/www/htdocs/w00acdb0/lib/pear/PEAR/Structures/Graph/Manipulator/TopologicalSorter.php";}s:25:"Structures/Graph/Node.php";a:5:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"7e28e01ebfa273e5df2eb1ef7a356635";s:4:"name";s:25:"Structures/Graph/Node.php";s:4:"role";s:3:"php";s:12:"installed_as";s:60:"/www/htdocs/w00acdb0/lib/pear/PEAR/Structures/Graph/Node.php";}s:20:"Structures/Graph.php";a:5:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"4f25a6275af156f6f8e7b4309cb9f40d";s:4:"name";s:20:"Structures/Graph.php";s:4:"role";s:3:"php";s:12:"installed_as";s:55:"/www/htdocs/w00acdb0/lib/pear/PEAR/Structures/Graph.php";}s:29:"tests/testCase/BasicGraph.php";a:5:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"63dfc6f0f14e18c13d8a8415c3fe049d";s:4:"name";s:29:"tests/testCase/BasicGraph.php";s:4:"role";s:4:"test";s:12:"installed_as";s:87:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/Structures_Graph/tests/testCase/BasicGraph.php";}s:19:"tests/all-tests.php";a:5:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"1b9e35896d229b84601e6754cd44e339";s:4:"name";s:19:"tests/all-tests.php";s:4:"role";s:4:"test";s:12:"installed_as";s:77:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/Structures_Graph/tests/all-tests.php";}s:12:"tests/README";a:5:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"d41d8cd98f00b204e9800998ecf8427e";s:4:"name";s:12:"tests/README";s:4:"role";s:4:"test";s:12:"installed_as";s:70:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/Structures_Graph/tests/README";}s:17:"genpackage.xml.pl";a:5:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"ab23406ec7bfbb2029ca536378ff57db";s:4:"name";s:17:"genpackage.xml.pl";s:4:"role";s:4:"data";s:12:"installed_as";s:74:"/www/htdocs/w00acdb0/lib/pear/PEAR/data/Structures_Graph/genpackage.xml.pl";}s:7:"LICENSE";a:5:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"7fbc338309ac38fefcd64b04bb903e34";s:4:"name";s:7:"LICENSE";s:4:"role";s:4:"data";s:12:"installed_as";s:64:"/www/htdocs/w00acdb0/lib/pear/PEAR/data/Structures_Graph/LICENSE";}s:10:"package.sh";a:5:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"6e782f281c7d0ce27e54b574247073cb";s:4:"name";s:10:"package.sh";s:4:"role";s:4:"data";s:12:"installed_as";s:67:"/www/htdocs/w00acdb0/lib/pear/PEAR/data/Structures_Graph/package.sh";}s:10:"publish.sh";a:5:{s:14:"baseinstalldir";s:0:"";s:6:"md5sum";s:32:"b81f67f7b5600231735243be73625e54";s:4:"name";s:10:"publish.sh";s:4:"role";s:4:"data";s:12:"installed_as";s:67:"/www/htdocs/w00acdb0/lib/pear/PEAR/data/Structures_Graph/publish.sh";}}s:12:"_lastversion";N;s:7:"dirtree";a:14:{s:72:"/www/htdocs/w00acdb0/lib/pear/PEAR/docs/Structures_Graph/docs/html/media";b:1;s:66:"/www/htdocs/w00acdb0/lib/pear/PEAR/docs/Structures_Graph/docs/html";b:1;s:61:"/www/htdocs/w00acdb0/lib/pear/PEAR/docs/Structures_Graph/docs";b:1;s:56:"/www/htdocs/w00acdb0/lib/pear/PEAR/docs/Structures_Graph";b:1;s:83:"/www/htdocs/w00acdb0/lib/pear/PEAR/docs/Structures_Graph/docs/html/Structures_Graph";b:1;s:88:"/www/htdocs/w00acdb0/lib/pear/PEAR/docs/Structures_Graph/docs/tutorials/Structures_Graph";b:1;s:71:"/www/htdocs/w00acdb0/lib/pear/PEAR/docs/Structures_Graph/docs/tutorials";b:1;s:63:"/www/htdocs/w00acdb0/lib/pear/PEAR/Structures/Graph/Manipulator";b:1;s:51:"/www/htdocs/w00acdb0/lib/pear/PEAR/Structures/Graph";b:1;s:45:"/www/htdocs/w00acdb0/lib/pear/PEAR/Structures";b:1;s:72:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/Structures_Graph/tests/testCase";b:1;s:63:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/Structures_Graph/tests";b:1;s:57:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/Structures_Graph";b:1;s:56:"/www/htdocs/w00acdb0/lib/pear/PEAR/data/Structures_Graph";b:1;}s:3:"old";a:7:{s:7:"version";s:5:"1.0.2";s:12:"release_date";s:10:"2007-02-01";s:13:"release_state";s:6:"stable";s:15:"release_license";s:4:"LGPL";s:13:"release_notes";s:130:"- Bug #9682 only variables can be returned by reference +- fix Bug #9661 notice in Structures_Graph_Manipulator_Topological::sort()";s:12:"release_deps";a:2:{i:0;a:4:{s:4:"type";s:3:"php";s:3:"rel";s:2:"ge";s:7:"version";s:5:"4.2.0";s:8:"optional";s:2:"no";}i:1;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:4:"PEAR";s:3:"rel";s:2:"ge";s:7:"version";s:5:"1.4.3";s:8:"optional";s:2:"no";}}s:11:"maintainers";a:1:{i:0;a:5:{s:4:"name";s:16:"Sérgio Carvalho";s:5:"email";s:32:"sergio.carvalho@portugalmail.com";s:6:"active";s:3:"yes";s:6:"handle";s:9:"sergiosgc";s:4:"role";s:4:"lead";}}}s:10:"xsdversion";s:3:"2.0";s:13:"_lastmodified";i:1234655680;} \ No newline at end of file diff --git a/src/lib/pear/PEAR/.registry/xml_rpc.reg b/src/lib/pear/PEAR/.registry/xml_rpc.reg new file mode 100644 index 0000000..8bacce8 --- /dev/null +++ b/src/lib/pear/PEAR/.registry/xml_rpc.reg @@ -0,0 +1,73 @@ +a:23:{s:7:"attribs";a:6:{s:15:"packagerversion";s:5:"1.4.9";s:7:"version";s:3:"2.0";s:5:"xmlns";s:35:"http://pear.php.net/dtd/package-2.0";s:11:"xmlns:tasks";s:33:"http://pear.php.net/dtd/tasks-1.0";s:9:"xmlns:xsi";s:41:"http://www.w3.org/2001/XMLSchema-instance";s:18:"xsi:schemaLocation";s:159:"http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd";}s:4:"name";s:7:"XML_RPC";s:7:"channel";s:12:"pear.php.net";s:7:"summary";s:42:"PHP implementation of the XML-RPC protocol";s:11:"description";s:123:"A PEAR-ified version of Useful Inc's XML-RPC for PHP. + +It has support for HTTP/HTTPS transport, proxies and authentication.";s:4:"lead";a:2:{i:0;a:4:{s:4:"name";s:11:"Stig Bakken";s:4:"user";s:3:"ssb";s:5:"email";s:12:"stig@php.net";s:6:"active";s:2:"no";}i:1;a:4:{s:4:"name";s:16:"Daniel Convissor";s:4:"user";s:7:"danielc";s:5:"email";s:15:"danielc@php.net";s:6:"active";s:3:"yes";}}s:4:"date";s:10:"2006-10-28";s:4:"time";s:8:"13:06:09";s:7:"version";a:2:{s:7:"release";s:5:"1.5.1";s:3:"api";s:5:"1.5.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:35:"http://www.php.net/license/3_01.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:280:"* Turn passing payload through mb_convert_encoding() off by default. Use new XML_RPC_Message::setConvertPayloadEncoding() and XML_RPC_Server::setConvertPayloadEncoding() to turn it on. Bug 8632. +* Have XML_RPC_Value::scalarval() return FALSE if value is not a scalar. Bug 8251.";s:8:"contents";a:1:{s:3:"dir";a:2:{s:7:"attribs";a:1:{s:4:"name";s:1:"/";}s:4:"file";a:10:{i:0;a:1:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"12e82943a83395bfdc00505dfe1c4f16";s:4:"name";s:16:"tests/allgot.inc";s:4:"role";s:4:"test";}}i:1;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"4362050edd0f6eb280e93b43c836c711";s:4:"name";s:28:"tests/empty-value-struct.php";s:4:"role";s:4:"test";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:2;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"2d37d500c19606e4ff92364df745e689";s:4:"name";s:21:"tests/empty-value.php";s:4:"role";s:4:"test";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:3;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"a0ab20aef0c7c3af4ed02b5a6b7ef7fc";s:4:"name";s:21:"tests/extra-lines.php";s:4:"role";s:4:"test";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:4;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"5b4852b96c0cd4f1e869effef8003e06";s:4:"name";s:19:"tests/protoport.php";s:4:"role";s:4:"test";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:5;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"9e78b8f4a5cf3a68c6d1b94fb8e621d8";s:4:"name";s:19:"tests/test_Dump.php";s:4:"role";s:4:"test";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:6;a:2:{s:7:"attribs";a:3:{s:6:"md5sum";s:32:"1fdd79c28b047409b327063abd144dd0";s:4:"name";s:15:"tests/types.php";s:4:"role";s:4:"test";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:7;a:2:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:7:"XML/RPC";s:6:"md5sum";s:32:"91b1ae15a18db161b6ebd52a9a4ed6ae";s:4:"name";s:8:"Dump.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:8;a:2:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:3:"XML";s:6:"md5sum";s:32:"c7b9a2b4bff7e860ca3658775672ffa4";s:4:"name";s:7:"RPC.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}i:9;a:2:{s:7:"attribs";a:4:{s:14:"baseinstalldir";s:7:"XML/RPC";s:6:"md5sum";s:32:"46018f4943f7b9a67f4611d242821dab";s:4:"name";s:10:"Server.php";s:4:"role";s:3:"php";}s:13:"tasks:replace";a:1:{s:7:"attribs";a:3:{s:4:"from";s:17:"@package_version@";s:2:"to";s:7:"version";s:4:"type";s:12:"package-info";}}}}}}s:10:"compatible";a:4:{s:4:"name";s:4:"PEAR";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:7:"1.4.0a1";s:3:"max";s:5:"1.4.9";}s:12:"dependencies";a:1:{s:8:"required";a:3:{s:3:"php";a:1:{s:3:"min";s:5:"4.2.0";}s:13:"pearinstaller";a:1:{s:3:"min";s:7:"1.4.0a1";}s:9:"extension";a:1:{s:4:"name";s:3:"xml";}}}s:10:"phprelease";s:0:"";s:9:"changelog";a:1:{s:7:"release";a:34:{i:0;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.5.0";s:3:"api";s:5:"1.5.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2006-07-11";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:35:"http://www.php.net/license/3_01.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:134:"No changes from 1.5.0RC2. + +The primary change from 1.4.8 is improved multi-byte support. See the change log for complete information.";}i:1;a:5:{s:7:"version";a:2:{s:7:"release";s:8:"1.5.0RC2";s:3:"api";s:5:"1.5.0";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:4:"beta";}s:4:"date";s:10:"2006-06-21";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:35:"http://www.php.net/license/3_01.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:127:"* If PHP's mbstring extension is enabled, use mb_convert_encoding() to ensure the server payload matches the intended encoding.";}i:2;a:5:{s:7:"version";a:2:{s:7:"release";s:8:"1.5.0RC1";s:3:"api";s:5:"1.5.0";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:4:"beta";}s:4:"date";s:10:"2006-06-16";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:35:"http://www.php.net/license/3_01.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:749:"* Provide complete multi-byte string support for systems with the mbstring extension enabled. Bug 7837. +* If PHP's mbstring extension is enabled, use mb_convert_encoding() to ensure the client payload matches the intended encoding. This is a better resolution of Bug 7376. +* Turn off the default of automatically base64 encoding strings that can generate fatal errors in PHP's SAX parser. The automatic base64 encoding can be turned on via the new XML_RPC_Client::setAutoBase64() method. The auto-encoding is a workaround for systems that don't have PHP's mbstring extension available. (The automatic base64 encoding was added in the prior release, 1.4.8, and caused problems for users who don't control the receiving end of the requests.) Bug 7837.";}i:3;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.4.8";s:3:"api";s:5:"1.4.6";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2006-04-16";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:34:"http://www.php.net/license/3_0.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:129:"* Characters other than alpha-numeric, punctuation, SP, TAB, LF and CR break the XML parser, encode value via Base 64. Bug 7376.";}i:4;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.4.7";s:3:"api";s:5:"1.4.6";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2006-04-10";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:34:"http://www.php.net/license/3_0.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:132:"* Add include_once for PEAR if need to load xml extension. Bug 7358. +* Add dependency for xml extension in package file. Bug 7358.";}i:5;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.4.6";s:3:"api";s:5:"1.4.6";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2006-04-07";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:34:"http://www.php.net/license/3_0.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:209:"* Add XML_RPC_Message::$remove_extra_lines property. Defaults to true. If set to false, extra lines are left in place. Bug 7088. +* Add XML_RPC_Message::$response_payload property. Makes logging responses easy.";}i:6;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.4.5";s:3:"api";s:5:"1.4.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2006-01-14";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:34:"http://www.php.net/license/3_0.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:114:"* Have server send headers individualy as opposed to sending them all at once. Necessary due to changes PHP 4.4.2.";}i:7;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.4.4";s:3:"api";s:5:"1.4.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2005-10-15";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:34:"http://www.php.net/license/3_0.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:46:"* Properly deal with empty values in struct's.";}i:8;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.4.3";s:3:"api";s:5:"1.4.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2005-09-24";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:34:"http://www.php.net/license/3_0.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:72:"* Make XML_RPC_encode() properly handle dateTime.iso8601. Request 5117.";}i:9;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.4.2";s:3:"api";s:5:"1.4.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2005-09-18";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:34:"http://www.php.net/license/3_0.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:53:"* Allow empty 's without 's. Bug 5315.";}i:10;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.4.1";s:3:"api";s:5:"1.4.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2005-09-07";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:34:"http://www.php.net/license/3_0.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:158:"* Don't add debug info unless debug is on. Bug 5136. +* Use is_a() instead of class_name() so people can use their own XML_RPC_Message objects. Request 5002.";}i:11;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.4.0";s:3:"api";s:5:"1.4.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2005-08-14";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:34:"http://www.php.net/license/3_0.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:171:"* MAJOR SECURITY FIX: eliminate use of eval(). +* Using socket_get_status() because stream_get_meta_data() was introduced in 4.3.0, but we need to support 4.2.0. Bug 4805.";}i:12;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.3.3";s:3:"api";s:5:"1.3.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2005-07-15";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:34:"http://www.php.net/license/3_0.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:220:"* Eliminate memory leak by resetting $XML_RPC_xh each time parseResponse() is called. Bug 4780. +* Using socket_set_timeout() because stream_set_timeout() was introduced in 4.3.0, but we need to support 4.2.0. Bug 4805.";}i:13;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.3.2";s:3:"api";s:5:"1.3.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2005-07-07";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:34:"http://www.php.net/license/3_0.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:584:"* Eliminate path disclosure vulnerabilities by suppressing error messages when eval()'ing. +* Eliminate path disclosure vulnerability by catching bogus parameters submitted to XML_RPC_Value::serializeval(). +* In XML_RPC_Server::service(), only call createServerPayload() and createServerHeaders() if necessary. Fixes compatibility issue introduced in Release 1.3.0RC1 for users who set the $serviceNow parameter of XML_RPC_Server() to 0. Bug 4757. +* Change "var $errstring" to "var $errstr". Bug 4582. Was put into CVS version 1.75 of RPC.php but didn't make it into RELEASE_1_3_1.";}i:14;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.3.1";s:3:"api";s:5:"1.3.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2005-06-29";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:34:"http://www.php.net/license/3_0.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:42:"* Security fix. Update highly recommended!";}i:15;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.3.0";s:3:"api";s:5:"1.3.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2005-06-13";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:34:"http://www.php.net/license/3_0.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:64:"* Stable release. See earlier releases for changes since 1.2.2.";}i:16;a:5:{s:7:"version";a:2:{s:7:"release";s:8:"1.3.0RC3";s:3:"api";s:5:"1.3.0";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2005-05-10";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:34:"http://www.php.net/license/3_0.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:724:"* When verifying requests against function signatures, if the number of parameters don't match, provide an appropriate message. NOTE: this resolves a path disclosure vulnerability. (Refines the changes made in the last commit.) Bug 4231. +* XML_RPC_Message::getParam() now returns an XML_RPC_Response object upon error. Changed from Release 1.3.0RC2. +* Add the XML_RPC_Value::isValue() method. For testing if an item is an XML_RPC_Value object. +* If XML_RPC_Client::send() is given an incorrect $msg parameter, raise an error with the new XML_RPC_ERROR_PROGRAMMING code and return 0. +* Improve cross-platform operation by using PEAR::loadExtension() instead of dl(). +* Use
    instead of
    in XML_RPC_Value::dump().";}i:17;a:5:{s:7:"version";a:2:{s:7:"release";s:8:"1.3.0RC2";s:3:"api";s:5:"1.3.0";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:4:"beta";}s:4:"date";s:10:"2005-05-05";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:34:"http://www.php.net/license/3_0.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:383:"* If XML_RPC_Message::getParam() is given an incorrect parameter, raise an error with the new XML_RPC_ERROR_INCORRECT_PARAMS code and return FALSE. +* Handle improper requests to XML_RPC_Server::verifySignature(). Bug 4231. +* Try to allow HTTP 100 responses if followed by a 200 response. Bug 4116. +* Help Delphi users by making RPCMETHODNAME an alias for METHODNAME. Request 4205.";}i:18;a:5:{s:7:"version";a:2:{s:7:"release";s:8:"1.3.0RC1";s:3:"api";s:5:"1.3.0";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:4:"beta";}s:4:"date";s:10:"2005-04-07";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:34:"http://www.php.net/license/3_0.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:818:"* Improve timeout handling for situations where connection to server is made but no response is not received in time. Accomplished via stream_set_timeout(). Request 3963. +* Add Fault Code 6: "The requested method didn't return an XML_RPC_Response object." Request 4032. +* Add the createServerPayload() and createServerHeaders() methods and the $server_payload and $server_headers properties. Request 3121. +* As in earlier versions, if the $serviceNow parameter to XML_RPC_Server() is 0, no data will be returned, but now the new $server_payload and $server_headers properties will be set. +* Convert the parser handle to an integer before using it as an index for $XML_RPC_xh[$parser]. Reduces E_STRICT notices. Bug 3782. +* Add createHeaders() method and $headers property to XML_RPC_Client to make testing easier.";}i:19;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.2.2";s:3:"api";s:5:"1.2.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2005-03-07";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:34:"http://www.php.net/license/3_0.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:122:"* When using a proxy, add the protocol to the Request-URI, making it an "absoluteURI" as per the HTTP 1.0 spec. Bug 3679.";}i:20;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.2.1";s:3:"api";s:5:"1.2.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2005-03-01";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:34:"http://www.php.net/license/3_0.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:65:"* Add isset() check before examining the dispatch map. Bug 3658.";}i:21;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.2.0";s:3:"api";s:5:"1.2.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2005-02-27";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:34:"http://www.php.net/license/3_0.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:160:"* Provide the "stable" release. +* Add package2.xml for compatibility with PEAR 1.4.0. +* For changes since 1.1.0, see the changelogs for the various RC releases.";}i:22;a:5:{s:7:"version";a:2:{s:7:"release";s:8:"1.2.0RC7";s:3:"api";s:8:"1.2.0RC7";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:4:"beta";}s:4:"date";s:10:"2005-02-22";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:34:"http://www.php.net/license/3_0.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:346:"* Add the setSendEncoding() method and $send_encoding + property to XML_RPC_Message. Request 3537. +* Allow class methods to be mapped using either syntax: + 'function' => 'hello::sayHello', + or + 'function' => array('hello', 'sayhello'), + Bug 3363. +* Use 8192 instead of 32768 for bytes in fread() + in parseResponseFile(). Bug 3340.";}i:23;a:5:{s:7:"version";a:2:{s:7:"release";s:8:"1.2.0RC6";s:3:"api";s:8:"1.2.0RC6";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:4:"beta";}s:4:"date";s:10:"2005-01-25";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:34:"http://www.php.net/license/3_0.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:71:"* Don't put the protocol in the Host field of the POST data. (danielc)";}i:24;a:5:{s:7:"version";a:2:{s:7:"release";s:8:"1.2.0RC5";s:3:"api";s:8:"1.2.0RC5";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:4:"beta";}s:4:"date";s:10:"2005-01-24";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:34:"http://www.php.net/license/3_0.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:91:"* If $port is 443 but a protocol isn't specified in $server, assume ssl:// is the protocol.";}i:25;a:5:{s:7:"version";a:2:{s:7:"release";s:8:"1.2.0RC4";s:3:"api";s:8:"1.2.0RC4";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:4:"beta";}s:4:"date";s:10:"2005-01-24";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:34:"http://www.php.net/license/3_0.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:388:"* When a connection attempt fails, have the method return 0. (danielc) +* Move the protocol/port checking/switching and the property settings from sendPayloadHTTP10() to the XML_RPC_Client constructor. (danielc) +* Add tests for setting the client properties. (danielc) +* Remove $GLOBALS['XML_RPC_twoslash'] since it's not used. (danielc) +* Bundle the tests with the package. (danielc)";}i:26;a:5:{s:7:"version";a:2:{s:7:"release";s:8:"1.2.0RC3";s:3:"api";s:8:"1.2.0RC3";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:4:"beta";}s:4:"date";s:10:"2005-01-19";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:34:"http://www.php.net/license/3_0.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:29:"* ssl uses port 443, not 445.";}i:27;a:5:{s:7:"version";a:2:{s:7:"release";s:8:"1.2.0RC2";s:3:"api";s:8:"1.2.0RC2";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:4:"beta";}s:4:"date";s:10:"2005-01-11";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:34:"http://www.php.net/license/3_0.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:162:"* Handle ssl:// in the $server string. (danielc) +* Also default to port 445 for ssl:// requests as well. (danielc) +* Enhance debugging in the server. (danielc)";}i:28;a:5:{s:7:"version";a:2:{s:7:"release";s:8:"1.2.0RC1";s:3:"api";s:8:"1.2.0RC1";}s:9:"stability";a:2:{s:7:"release";s:4:"beta";s:3:"api";s:4:"beta";}s:4:"date";s:10:"2004-12-30";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:34:"http://www.php.net/license/3_0.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:1187:"* Make things work with SSL. Bug 2489. (nkukard lbsd net) +* Allow array function callbacks (Matt Kane) +* Some minor speed-ups (Matt Kane) +* Add Dump.php to the package (Christian Weiske) +* Replace all line endings with \r\n. Had only done replacements on \n. Bug 2521. (danielc) +* Silence fsockopen() errors. Bug 1714. (danielc) +* Encode empty arrays as an array. Bug 1493. (danielc) +* Eliminate undefined index notice when submitting empty arrays to XML_RPC_Encode(). Bug 1819. (danielc) +* Speed up check for enumerated arrays in XML_RPC_Encode(). (danielc) +* Prepend "XML_RPC_" to ERROR_NON_NUMERIC_FOUND, eliminating problem when eval()'ing error messages. (danielc) +* Use XML_RPC_Base::raiseError() instead of PEAR::raiseError() in XML_RPC_ee() because PEAR.php is lazy loaded. (danielc) +* Allow raiseError() to be called statically. (danielc) +* Stop double escaping of character entities. Bug 987. (danielc) + NOTICE: the following have been removed: + * XML_RPC_dh() + * $GLOBALS['XML_RPC_entities'] + * XML_RPC_entity_decode() + * XML_RPC_lookup_entity() +* Determine the XML's encoding via the encoding attribute in the XML declaration. Bug 52. (danielc)";}i:29;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.1.0";s:3:"api";s:5:"1.1.0";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2004-03-15";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:34:"http://www.php.net/license/3_0.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:517:"* Added support for sequential arrays to XML_RPC_encode() (mroch) +* Cleaned up new XML_RPC_encode() changes a bit (mroch, pierre) +* Remove "require_once 'PEAR.php'", include only when needed to raise an error +* Replace echo and error_log() with raiseError() (mroch) +* Make all classes extend XML_RPC_Base, which will handle common functions (mroch) +* be tolerant of junk after methodResponse (Luca Mariano, mroch) +* Silent notice even in the error log (pierre) +* fix include of shared xml extension on win32 (pierre)";}i:30;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.0.4";s:3:"api";s:5:"1.0.4";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2002-10-02";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:34:"http://www.php.net/license/3_0.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:68:"* added HTTP proxy authorization support (thanks to Arnaud Limbourg)";}i:31;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.0.3";s:3:"api";s:5:"1.0.3";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2002-05-19";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:34:"http://www.php.net/license/3_0.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:51:"* fix bug when parsing responses with boolean types";}i:32;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.0.2";s:3:"api";s:5:"1.0.2";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2002-04-16";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:34:"http://www.php.net/license/3_0.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:48:"* E_ALL fixes +* fix HTTP response header parsing";}i:33;a:5:{s:7:"version";a:2:{s:7:"release";s:5:"1.0.1";s:3:"api";s:5:"1.0.1";}s:9:"stability";a:2:{s:7:"release";s:6:"stable";s:3:"api";s:6:"stable";}s:4:"date";s:10:"2001-09-25";s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:34:"http://www.php.net/license/3_0.txt";}s:8:"_content";s:11:"PHP License";}s:5:"notes";s:132:"This is a PEAR-ified version of Useful Inc's 1.0.1 release. +Includes an urgent security fix identified by Dan Libby .";}}}s:8:"filelist";a:10:{s:16:"tests/allgot.inc";a:4:{s:6:"md5sum";s:32:"12e82943a83395bfdc00505dfe1c4f16";s:4:"name";s:16:"tests/allgot.inc";s:4:"role";s:4:"test";s:12:"installed_as";s:65:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/XML_RPC/tests/allgot.inc";}s:28:"tests/empty-value-struct.php";a:4:{s:6:"md5sum";s:32:"4362050edd0f6eb280e93b43c836c711";s:4:"name";s:28:"tests/empty-value-struct.php";s:4:"role";s:4:"test";s:12:"installed_as";s:77:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/XML_RPC/tests/empty-value-struct.php";}s:21:"tests/empty-value.php";a:4:{s:6:"md5sum";s:32:"2d37d500c19606e4ff92364df745e689";s:4:"name";s:21:"tests/empty-value.php";s:4:"role";s:4:"test";s:12:"installed_as";s:70:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/XML_RPC/tests/empty-value.php";}s:21:"tests/extra-lines.php";a:4:{s:6:"md5sum";s:32:"a0ab20aef0c7c3af4ed02b5a6b7ef7fc";s:4:"name";s:21:"tests/extra-lines.php";s:4:"role";s:4:"test";s:12:"installed_as";s:70:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/XML_RPC/tests/extra-lines.php";}s:19:"tests/protoport.php";a:4:{s:6:"md5sum";s:32:"5b4852b96c0cd4f1e869effef8003e06";s:4:"name";s:19:"tests/protoport.php";s:4:"role";s:4:"test";s:12:"installed_as";s:68:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/XML_RPC/tests/protoport.php";}s:19:"tests/test_Dump.php";a:4:{s:6:"md5sum";s:32:"9e78b8f4a5cf3a68c6d1b94fb8e621d8";s:4:"name";s:19:"tests/test_Dump.php";s:4:"role";s:4:"test";s:12:"installed_as";s:68:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/XML_RPC/tests/test_Dump.php";}s:15:"tests/types.php";a:4:{s:6:"md5sum";s:32:"1fdd79c28b047409b327063abd144dd0";s:4:"name";s:15:"tests/types.php";s:4:"role";s:4:"test";s:12:"installed_as";s:64:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/XML_RPC/tests/types.php";}s:8:"Dump.php";a:5:{s:14:"baseinstalldir";s:7:"XML/RPC";s:6:"md5sum";s:32:"91b1ae15a18db161b6ebd52a9a4ed6ae";s:4:"name";s:8:"Dump.php";s:4:"role";s:3:"php";s:12:"installed_as";s:51:"/www/htdocs/w00acdb0/lib/pear/PEAR/XML/RPC/Dump.php";}s:7:"RPC.php";a:5:{s:14:"baseinstalldir";s:3:"XML";s:6:"md5sum";s:32:"c7b9a2b4bff7e860ca3658775672ffa4";s:4:"name";s:7:"RPC.php";s:4:"role";s:3:"php";s:12:"installed_as";s:46:"/www/htdocs/w00acdb0/lib/pear/PEAR/XML/RPC.php";}s:10:"Server.php";a:5:{s:14:"baseinstalldir";s:7:"XML/RPC";s:6:"md5sum";s:32:"46018f4943f7b9a67f4611d242821dab";s:4:"name";s:10:"Server.php";s:4:"role";s:3:"php";s:12:"installed_as";s:53:"/www/htdocs/w00acdb0/lib/pear/PEAR/XML/RPC/Server.php";}}s:12:"_lastversion";N;s:7:"dirtree";a:4:{s:54:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/XML_RPC/tests";b:1;s:48:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests/XML_RPC";b:1;s:42:"/www/htdocs/w00acdb0/lib/pear/PEAR/XML/RPC";b:1;s:38:"/www/htdocs/w00acdb0/lib/pear/PEAR/XML";b:1;}s:3:"old";a:7:{s:7:"version";s:5:"1.5.1";s:12:"release_date";s:10:"2006-10-28";s:13:"release_state";s:6:"stable";s:15:"release_license";s:11:"PHP License";s:13:"release_notes";s:280:"* Turn passing payload through mb_convert_encoding() off by default. Use new XML_RPC_Message::setConvertPayloadEncoding() and XML_RPC_Server::setConvertPayloadEncoding() to turn it on. Bug 8632. +* Have XML_RPC_Value::scalarval() return FALSE if value is not a scalar. Bug 8251.";s:12:"release_deps";a:3:{i:0;a:4:{s:4:"type";s:3:"php";s:3:"rel";s:2:"ge";s:7:"version";s:5:"4.2.0";s:8:"optional";s:2:"no";}i:1;a:6:{s:4:"type";s:3:"pkg";s:7:"channel";s:12:"pear.php.net";s:4:"name";s:4:"PEAR";s:3:"rel";s:2:"ge";s:7:"version";s:7:"1.4.0a1";s:8:"optional";s:2:"no";}i:2;a:4:{s:4:"type";s:3:"ext";s:4:"name";s:3:"xml";s:3:"rel";s:3:"has";s:8:"optional";s:2:"no";}}s:11:"maintainers";a:2:{i:0;a:5:{s:4:"name";s:11:"Stig Bakken";s:5:"email";s:12:"stig@php.net";s:6:"active";s:2:"no";s:6:"handle";s:3:"ssb";s:4:"role";s:4:"lead";}i:1;a:5:{s:4:"name";s:16:"Daniel Convissor";s:5:"email";s:15:"danielc@php.net";s:6:"active";s:3:"yes";s:6:"handle";s:7:"danielc";s:4:"role";s:4:"lead";}}}s:10:"xsdversion";s:3:"2.0";s:13:"_lastmodified";i:1234656605;} \ No newline at end of file diff --git a/src/lib/pear/PEAR/Archive/Tar.php b/src/lib/pear/PEAR/Archive/Tar.php new file mode 100644 index 0000000..b14e488 --- /dev/null +++ b/src/lib/pear/PEAR/Archive/Tar.php @@ -0,0 +1,1815 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: Tar.php,v 1.39 2006/12/22 19:20:08 cellog Exp $ + +require_once 'PEAR.php'; + + +define ('ARCHIVE_TAR_ATT_SEPARATOR', 90001); +define ('ARCHIVE_TAR_END_BLOCK', pack("a512", '')); + +/** +* Creates a (compressed) Tar archive +* +* @author Vincent Blavet +* @version $Revision: 1.39 $ +* @package Archive +*/ +class Archive_Tar extends PEAR +{ + /** + * @var string Name of the Tar + */ + var $_tarname=''; + + /** + * @var boolean if true, the Tar file will be gzipped + */ + var $_compress=false; + + /** + * @var string Type of compression : 'none', 'gz' or 'bz2' + */ + var $_compress_type='none'; + + /** + * @var string Explode separator + */ + var $_separator=' '; + + /** + * @var file descriptor + */ + var $_file=0; + + /** + * @var string Local Tar name of a remote Tar (http:// or ftp://) + */ + var $_temp_tarname=''; + + // {{{ constructor + /** + * Archive_Tar Class constructor. This flavour of the constructor only + * declare a new Archive_Tar object, identifying it by the name of the + * tar file. + * If the compress argument is set the tar will be read or created as a + * gzip or bz2 compressed TAR file. + * + * @param string $p_tarname The name of the tar archive to create + * @param string $p_compress can be null, 'gz' or 'bz2'. This + * parameter indicates if gzip or bz2 compression + * is required. For compatibility reason the + * boolean value 'true' means 'gz'. + * @access public + */ + function Archive_Tar($p_tarname, $p_compress = null) + { + $this->PEAR(); + $this->_compress = false; + $this->_compress_type = 'none'; + if (($p_compress === null) || ($p_compress == '')) { + if (@file_exists($p_tarname)) { + if ($fp = @fopen($p_tarname, "rb")) { + // look for gzip magic cookie + $data = fread($fp, 2); + fclose($fp); + if ($data == "\37\213") { + $this->_compress = true; + $this->_compress_type = 'gz'; + // No sure it's enought for a magic code .... + } elseif ($data == "BZ") { + $this->_compress = true; + $this->_compress_type = 'bz2'; + } + } + } else { + // probably a remote file or some file accessible + // through a stream interface + if (substr($p_tarname, -2) == 'gz') { + $this->_compress = true; + $this->_compress_type = 'gz'; + } elseif ((substr($p_tarname, -3) == 'bz2') || + (substr($p_tarname, -2) == 'bz')) { + $this->_compress = true; + $this->_compress_type = 'bz2'; + } + } + } else { + if (($p_compress === true) || ($p_compress == 'gz')) { + $this->_compress = true; + $this->_compress_type = 'gz'; + } else if ($p_compress == 'bz2') { + $this->_compress = true; + $this->_compress_type = 'bz2'; + } else { + die("Unsupported compression type '$p_compress'\n". + "Supported types are 'gz' and 'bz2'.\n"); + return false; + } + } + $this->_tarname = $p_tarname; + if ($this->_compress) { // assert zlib or bz2 extension support + if ($this->_compress_type == 'gz') + $extname = 'zlib'; + else if ($this->_compress_type == 'bz2') + $extname = 'bz2'; + + if (!extension_loaded($extname)) { + PEAR::loadExtension($extname); + } + if (!extension_loaded($extname)) { + die("The extension '$extname' couldn't be found.\n". + "Please make sure your version of PHP was built ". + "with '$extname' support.\n"); + return false; + } + } + } + // }}} + + // {{{ destructor + function _Archive_Tar() + { + $this->_close(); + // ----- Look for a local copy to delete + if ($this->_temp_tarname != '') + @unlink($this->_temp_tarname); + $this->_PEAR(); + } + // }}} + + // {{{ create() + /** + * This method creates the archive file and add the files / directories + * that are listed in $p_filelist. + * If a file with the same name exist and is writable, it is replaced + * by the new tar. + * The method return false and a PEAR error text. + * The $p_filelist parameter can be an array of string, each string + * representing a filename or a directory name with their path if + * needed. It can also be a single string with names separated by a + * single blank. + * For each directory added in the archive, the files and + * sub-directories are also added. + * See also createModify() method for more details. + * + * @param array $p_filelist An array of filenames and directory names, or a + * single string with names separated by a single + * blank space. + * @return true on success, false on error. + * @see createModify() + * @access public + */ + function create($p_filelist) + { + return $this->createModify($p_filelist, '', ''); + } + // }}} + + // {{{ add() + /** + * This method add the files / directories that are listed in $p_filelist in + * the archive. If the archive does not exist it is created. + * The method return false and a PEAR error text. + * The files and directories listed are only added at the end of the archive, + * even if a file with the same name is already archived. + * See also createModify() method for more details. + * + * @param array $p_filelist An array of filenames and directory names, or a + * single string with names separated by a single + * blank space. + * @return true on success, false on error. + * @see createModify() + * @access public + */ + function add($p_filelist) + { + return $this->addModify($p_filelist, '', ''); + } + // }}} + + // {{{ extract() + function extract($p_path='') + { + return $this->extractModify($p_path, ''); + } + // }}} + + // {{{ listContent() + function listContent() + { + $v_list_detail = array(); + + if ($this->_openRead()) { + if (!$this->_extractList('', $v_list_detail, "list", '', '')) { + unset($v_list_detail); + $v_list_detail = 0; + } + $this->_close(); + } + + return $v_list_detail; + } + // }}} + + // {{{ createModify() + /** + * This method creates the archive file and add the files / directories + * that are listed in $p_filelist. + * If the file already exists and is writable, it is replaced by the + * new tar. It is a create and not an add. If the file exists and is + * read-only or is a directory it is not replaced. The method return + * false and a PEAR error text. + * The $p_filelist parameter can be an array of string, each string + * representing a filename or a directory name with their path if + * needed. It can also be a single string with names separated by a + * single blank. + * The path indicated in $p_remove_dir will be removed from the + * memorized path of each file / directory listed when this path + * exists. By default nothing is removed (empty path '') + * The path indicated in $p_add_dir will be added at the beginning of + * the memorized path of each file / directory listed. However it can + * be set to empty ''. The adding of a path is done after the removing + * of path. + * The path add/remove ability enables the user to prepare an archive + * for extraction in a different path than the origin files are. + * See also addModify() method for file adding properties. + * + * @param array $p_filelist An array of filenames and directory names, + * or a single string with names separated by + * a single blank space. + * @param string $p_add_dir A string which contains a path to be added + * to the memorized path of each element in + * the list. + * @param string $p_remove_dir A string which contains a path to be + * removed from the memorized path of each + * element in the list, when relevant. + * @return boolean true on success, false on error. + * @access public + * @see addModify() + */ + function createModify($p_filelist, $p_add_dir, $p_remove_dir='') + { + $v_result = true; + + if (!$this->_openWrite()) + return false; + + if ($p_filelist != '') { + if (is_array($p_filelist)) + $v_list = $p_filelist; + elseif (is_string($p_filelist)) + $v_list = explode($this->_separator, $p_filelist); + else { + $this->_cleanFile(); + $this->_error('Invalid file list'); + return false; + } + + $v_result = $this->_addList($v_list, $p_add_dir, $p_remove_dir); + } + + if ($v_result) { + $this->_writeFooter(); + $this->_close(); + } else + $this->_cleanFile(); + + return $v_result; + } + // }}} + + // {{{ addModify() + /** + * This method add the files / directories listed in $p_filelist at the + * end of the existing archive. If the archive does not yet exists it + * is created. + * The $p_filelist parameter can be an array of string, each string + * representing a filename or a directory name with their path if + * needed. It can also be a single string with names separated by a + * single blank. + * The path indicated in $p_remove_dir will be removed from the + * memorized path of each file / directory listed when this path + * exists. By default nothing is removed (empty path '') + * The path indicated in $p_add_dir will be added at the beginning of + * the memorized path of each file / directory listed. However it can + * be set to empty ''. The adding of a path is done after the removing + * of path. + * The path add/remove ability enables the user to prepare an archive + * for extraction in a different path than the origin files are. + * If a file/dir is already in the archive it will only be added at the + * end of the archive. There is no update of the existing archived + * file/dir. However while extracting the archive, the last file will + * replace the first one. This results in a none optimization of the + * archive size. + * If a file/dir does not exist the file/dir is ignored. However an + * error text is send to PEAR error. + * If a file/dir is not readable the file/dir is ignored. However an + * error text is send to PEAR error. + * + * @param array $p_filelist An array of filenames and directory + * names, or a single string with names + * separated by a single blank space. + * @param string $p_add_dir A string which contains a path to be + * added to the memorized path of each + * element in the list. + * @param string $p_remove_dir A string which contains a path to be + * removed from the memorized path of + * each element in the list, when + * relevant. + * @return true on success, false on error. + * @access public + */ + function addModify($p_filelist, $p_add_dir, $p_remove_dir='') + { + $v_result = true; + + if (!$this->_isArchive()) + $v_result = $this->createModify($p_filelist, $p_add_dir, + $p_remove_dir); + else { + if (is_array($p_filelist)) + $v_list = $p_filelist; + elseif (is_string($p_filelist)) + $v_list = explode($this->_separator, $p_filelist); + else { + $this->_error('Invalid file list'); + return false; + } + + $v_result = $this->_append($v_list, $p_add_dir, $p_remove_dir); + } + + return $v_result; + } + // }}} + + // {{{ addString() + /** + * This method add a single string as a file at the + * end of the existing archive. If the archive does not yet exists it + * is created. + * + * @param string $p_filename A string which contains the full + * filename path that will be associated + * with the string. + * @param string $p_string The content of the file added in + * the archive. + * @return true on success, false on error. + * @access public + */ + function addString($p_filename, $p_string) + { + $v_result = true; + + if (!$this->_isArchive()) { + if (!$this->_openWrite()) { + return false; + } + $this->_close(); + } + + if (!$this->_openAppend()) + return false; + + // Need to check the get back to the temporary file ? .... + $v_result = $this->_addString($p_filename, $p_string); + + $this->_writeFooter(); + + $this->_close(); + + return $v_result; + } + // }}} + + // {{{ extractModify() + /** + * This method extract all the content of the archive in the directory + * indicated by $p_path. When relevant the memorized path of the + * files/dir can be modified by removing the $p_remove_path path at the + * beginning of the file/dir path. + * While extracting a file, if the directory path does not exists it is + * created. + * While extracting a file, if the file already exists it is replaced + * without looking for last modification date. + * While extracting a file, if the file already exists and is write + * protected, the extraction is aborted. + * While extracting a file, if a directory with the same name already + * exists, the extraction is aborted. + * While extracting a directory, if a file with the same name already + * exists, the extraction is aborted. + * While extracting a file/directory if the destination directory exist + * and is write protected, or does not exist but can not be created, + * the extraction is aborted. + * If after extraction an extracted file does not show the correct + * stored file size, the extraction is aborted. + * When the extraction is aborted, a PEAR error text is set and false + * is returned. However the result can be a partial extraction that may + * need to be manually cleaned. + * + * @param string $p_path The path of the directory where the + * files/dir need to by extracted. + * @param string $p_remove_path Part of the memorized path that can be + * removed if present at the beginning of + * the file/dir path. + * @return boolean true on success, false on error. + * @access public + * @see extractList() + */ + function extractModify($p_path, $p_remove_path) + { + $v_result = true; + $v_list_detail = array(); + + if ($v_result = $this->_openRead()) { + $v_result = $this->_extractList($p_path, $v_list_detail, + "complete", 0, $p_remove_path); + $this->_close(); + } + + return $v_result; + } + // }}} + + // {{{ extractInString() + /** + * This method extract from the archive one file identified by $p_filename. + * The return value is a string with the file content, or NULL on error. + * @param string $p_filename The path of the file to extract in a string. + * @return a string with the file content or NULL. + * @access public + */ + function extractInString($p_filename) + { + if ($this->_openRead()) { + $v_result = $this->_extractInString($p_filename); + $this->_close(); + } else { + $v_result = NULL; + } + + return $v_result; + } + // }}} + + // {{{ extractList() + /** + * This method extract from the archive only the files indicated in the + * $p_filelist. These files are extracted in the current directory or + * in the directory indicated by the optional $p_path parameter. + * If indicated the $p_remove_path can be used in the same way as it is + * used in extractModify() method. + * @param array $p_filelist An array of filenames and directory names, + * or a single string with names separated + * by a single blank space. + * @param string $p_path The path of the directory where the + * files/dir need to by extracted. + * @param string $p_remove_path Part of the memorized path that can be + * removed if present at the beginning of + * the file/dir path. + * @return true on success, false on error. + * @access public + * @see extractModify() + */ + function extractList($p_filelist, $p_path='', $p_remove_path='') + { + $v_result = true; + $v_list_detail = array(); + + if (is_array($p_filelist)) + $v_list = $p_filelist; + elseif (is_string($p_filelist)) + $v_list = explode($this->_separator, $p_filelist); + else { + $this->_error('Invalid string list'); + return false; + } + + if ($v_result = $this->_openRead()) { + $v_result = $this->_extractList($p_path, $v_list_detail, "partial", + $v_list, $p_remove_path); + $this->_close(); + } + + return $v_result; + } + // }}} + + // {{{ setAttribute() + /** + * This method set specific attributes of the archive. It uses a variable + * list of parameters, in the format attribute code + attribute values : + * $arch->setAttribute(ARCHIVE_TAR_ATT_SEPARATOR, ','); + * @param mixed $argv variable list of attributes and values + * @return true on success, false on error. + * @access public + */ + function setAttribute() + { + $v_result = true; + + // ----- Get the number of variable list of arguments + if (($v_size = func_num_args()) == 0) { + return true; + } + + // ----- Get the arguments + $v_att_list = &func_get_args(); + + // ----- Read the attributes + $i=0; + while ($i<$v_size) { + + // ----- Look for next option + switch ($v_att_list[$i]) { + // ----- Look for options that request a string value + case ARCHIVE_TAR_ATT_SEPARATOR : + // ----- Check the number of parameters + if (($i+1) >= $v_size) { + $this->_error('Invalid number of parameters for ' + .'attribute ARCHIVE_TAR_ATT_SEPARATOR'); + return false; + } + + // ----- Get the value + $this->_separator = $v_att_list[$i+1]; + $i++; + break; + + default : + $this->_error('Unknow attribute code '.$v_att_list[$i].''); + return false; + } + + // ----- Next attribute + $i++; + } + + return $v_result; + } + // }}} + + // {{{ _error() + function _error($p_message) + { + // ----- To be completed + $this->raiseError($p_message); + } + // }}} + + // {{{ _warning() + function _warning($p_message) + { + // ----- To be completed + $this->raiseError($p_message); + } + // }}} + + // {{{ _isArchive() + function _isArchive($p_filename=NULL) + { + if ($p_filename == NULL) { + $p_filename = $this->_tarname; + } + clearstatcache(); + return @is_file($p_filename); + } + // }}} + + // {{{ _openWrite() + function _openWrite() + { + if ($this->_compress_type == 'gz') + $this->_file = @gzopen($this->_tarname, "wb9"); + else if ($this->_compress_type == 'bz2') + $this->_file = @bzopen($this->_tarname, "wb"); + else if ($this->_compress_type == 'none') + $this->_file = @fopen($this->_tarname, "wb"); + else + $this->_error('Unknown or missing compression type (' + .$this->_compress_type.')'); + + if ($this->_file == 0) { + $this->_error('Unable to open in write mode \'' + .$this->_tarname.'\''); + return false; + } + + return true; + } + // }}} + + // {{{ _openRead() + function _openRead() + { + if (strtolower(substr($this->_tarname, 0, 7)) == 'http://') { + + // ----- Look if a local copy need to be done + if ($this->_temp_tarname == '') { + $this->_temp_tarname = uniqid('tar').'.tmp'; + if (!$v_file_from = @fopen($this->_tarname, 'rb')) { + $this->_error('Unable to open in read mode \'' + .$this->_tarname.'\''); + $this->_temp_tarname = ''; + return false; + } + if (!$v_file_to = @fopen($this->_temp_tarname, 'wb')) { + $this->_error('Unable to open in write mode \'' + .$this->_temp_tarname.'\''); + $this->_temp_tarname = ''; + return false; + } + while ($v_data = @fread($v_file_from, 1024)) + @fwrite($v_file_to, $v_data); + @fclose($v_file_from); + @fclose($v_file_to); + } + + // ----- File to open if the local copy + $v_filename = $this->_temp_tarname; + + } else + // ----- File to open if the normal Tar file + $v_filename = $this->_tarname; + + if ($this->_compress_type == 'gz') + $this->_file = @gzopen($v_filename, "rb"); + else if ($this->_compress_type == 'bz2') + $this->_file = @bzopen($v_filename, "rb"); + else if ($this->_compress_type == 'none') + $this->_file = @fopen($v_filename, "rb"); + else + $this->_error('Unknown or missing compression type (' + .$this->_compress_type.')'); + + if ($this->_file == 0) { + $this->_error('Unable to open in read mode \''.$v_filename.'\''); + return false; + } + + return true; + } + // }}} + + // {{{ _openReadWrite() + function _openReadWrite() + { + if ($this->_compress_type == 'gz') + $this->_file = @gzopen($this->_tarname, "r+b"); + else if ($this->_compress_type == 'bz2') + $this->_file = @bzopen($this->_tarname, "r+b"); + else if ($this->_compress_type == 'none') + $this->_file = @fopen($this->_tarname, "r+b"); + else + $this->_error('Unknown or missing compression type (' + .$this->_compress_type.')'); + + if ($this->_file == 0) { + $this->_error('Unable to open in read/write mode \'' + .$this->_tarname.'\''); + return false; + } + + return true; + } + // }}} + + // {{{ _close() + function _close() + { + //if (isset($this->_file)) { + if (is_resource($this->_file)) { + if ($this->_compress_type == 'gz') + @gzclose($this->_file); + else if ($this->_compress_type == 'bz2') + @bzclose($this->_file); + else if ($this->_compress_type == 'none') + @fclose($this->_file); + else + $this->_error('Unknown or missing compression type (' + .$this->_compress_type.')'); + + $this->_file = 0; + } + + // ----- Look if a local copy need to be erase + // Note that it might be interesting to keep the url for a time : ToDo + if ($this->_temp_tarname != '') { + @unlink($this->_temp_tarname); + $this->_temp_tarname = ''; + } + + return true; + } + // }}} + + // {{{ _cleanFile() + function _cleanFile() + { + $this->_close(); + + // ----- Look for a local copy + if ($this->_temp_tarname != '') { + // ----- Remove the local copy but not the remote tarname + @unlink($this->_temp_tarname); + $this->_temp_tarname = ''; + } else { + // ----- Remove the local tarname file + @unlink($this->_tarname); + } + $this->_tarname = ''; + + return true; + } + // }}} + + // {{{ _writeBlock() + function _writeBlock($p_binary_data, $p_len=null) + { + if (is_resource($this->_file)) { + if ($p_len === null) { + if ($this->_compress_type == 'gz') + @gzputs($this->_file, $p_binary_data); + else if ($this->_compress_type == 'bz2') + @bzwrite($this->_file, $p_binary_data); + else if ($this->_compress_type == 'none') + @fputs($this->_file, $p_binary_data); + else + $this->_error('Unknown or missing compression type (' + .$this->_compress_type.')'); + } else { + if ($this->_compress_type == 'gz') + @gzputs($this->_file, $p_binary_data, $p_len); + else if ($this->_compress_type == 'bz2') + @bzwrite($this->_file, $p_binary_data, $p_len); + else if ($this->_compress_type == 'none') + @fputs($this->_file, $p_binary_data, $p_len); + else + $this->_error('Unknown or missing compression type (' + .$this->_compress_type.')'); + + } + } + return true; + } + // }}} + + // {{{ _readBlock() + function _readBlock() + { + $v_block = null; + if (is_resource($this->_file)) { + if ($this->_compress_type == 'gz') + $v_block = @gzread($this->_file, 512); + else if ($this->_compress_type == 'bz2') + $v_block = @bzread($this->_file, 512); + else if ($this->_compress_type == 'none') + $v_block = @fread($this->_file, 512); + else + $this->_error('Unknown or missing compression type (' + .$this->_compress_type.')'); + } + return $v_block; + } + // }}} + + // {{{ _jumpBlock() + function _jumpBlock($p_len=null) + { + if (is_resource($this->_file)) { + if ($p_len === null) + $p_len = 1; + + if ($this->_compress_type == 'gz') { + @gzseek($this->_file, gztell($this->_file)+($p_len*512)); + } + else if ($this->_compress_type == 'bz2') { + // ----- Replace missing bztell() and bzseek() + for ($i=0; $i<$p_len; $i++) + $this->_readBlock(); + } else if ($this->_compress_type == 'none') + @fseek($this->_file, ftell($this->_file)+($p_len*512)); + else + $this->_error('Unknown or missing compression type (' + .$this->_compress_type.')'); + + } + return true; + } + // }}} + + // {{{ _writeFooter() + function _writeFooter() + { + if (is_resource($this->_file)) { + // ----- Write the last 0 filled block for end of archive + $v_binary_data = pack('a1024', ''); + $this->_writeBlock($v_binary_data); + } + return true; + } + // }}} + + // {{{ _addList() + function _addList($p_list, $p_add_dir, $p_remove_dir) + { + $v_result=true; + $v_header = array(); + + // ----- Remove potential windows directory separator + $p_add_dir = $this->_translateWinPath($p_add_dir); + $p_remove_dir = $this->_translateWinPath($p_remove_dir, false); + + if (!$this->_file) { + $this->_error('Invalid file descriptor'); + return false; + } + + if (sizeof($p_list) == 0) + return true; + + foreach ($p_list as $v_filename) { + if (!$v_result) { + break; + } + + // ----- Skip the current tar name + if ($v_filename == $this->_tarname) + continue; + + if ($v_filename == '') + continue; + + if (!file_exists($v_filename)) { + $this->_warning("File '$v_filename' does not exist"); + continue; + } + + // ----- Add the file or directory header + if (!$this->_addFile($v_filename, $v_header, $p_add_dir, $p_remove_dir)) + return false; + + if (@is_dir($v_filename)) { + if (!($p_hdir = opendir($v_filename))) { + $this->_warning("Directory '$v_filename' can not be read"); + continue; + } + while (false !== ($p_hitem = readdir($p_hdir))) { + if (($p_hitem != '.') && ($p_hitem != '..')) { + if ($v_filename != ".") + $p_temp_list[0] = $v_filename.'/'.$p_hitem; + else + $p_temp_list[0] = $p_hitem; + + $v_result = $this->_addList($p_temp_list, + $p_add_dir, + $p_remove_dir); + } + } + + unset($p_temp_list); + unset($p_hdir); + unset($p_hitem); + } + } + + return $v_result; + } + // }}} + + // {{{ _addFile() + function _addFile($p_filename, &$p_header, $p_add_dir, $p_remove_dir) + { + if (!$this->_file) { + $this->_error('Invalid file descriptor'); + return false; + } + + if ($p_filename == '') { + $this->_error('Invalid file name'); + return false; + } + + // ----- Calculate the stored filename + $p_filename = $this->_translateWinPath($p_filename, false);; + $v_stored_filename = $p_filename; + if (strcmp($p_filename, $p_remove_dir) == 0) { + return true; + } + if ($p_remove_dir != '') { + if (substr($p_remove_dir, -1) != '/') + $p_remove_dir .= '/'; + + if (substr($p_filename, 0, strlen($p_remove_dir)) == $p_remove_dir) + $v_stored_filename = substr($p_filename, strlen($p_remove_dir)); + } + $v_stored_filename = $this->_translateWinPath($v_stored_filename); + if ($p_add_dir != '') { + if (substr($p_add_dir, -1) == '/') + $v_stored_filename = $p_add_dir.$v_stored_filename; + else + $v_stored_filename = $p_add_dir.'/'.$v_stored_filename; + } + + $v_stored_filename = $this->_pathReduction($v_stored_filename); + + if ($this->_isArchive($p_filename)) { + if (($v_file = @fopen($p_filename, "rb")) == 0) { + $this->_warning("Unable to open file '".$p_filename + ."' in binary read mode"); + return true; + } + + if (!$this->_writeHeader($p_filename, $v_stored_filename)) + return false; + + while (($v_buffer = fread($v_file, 512)) != '') { + $v_binary_data = pack("a512", "$v_buffer"); + $this->_writeBlock($v_binary_data); + } + + fclose($v_file); + + } else { + // ----- Only header for dir + if (!$this->_writeHeader($p_filename, $v_stored_filename)) + return false; + } + + return true; + } + // }}} + + // {{{ _addString() + function _addString($p_filename, $p_string) + { + if (!$this->_file) { + $this->_error('Invalid file descriptor'); + return false; + } + + if ($p_filename == '') { + $this->_error('Invalid file name'); + return false; + } + + // ----- Calculate the stored filename + $p_filename = $this->_translateWinPath($p_filename, false);; + + if (!$this->_writeHeaderBlock($p_filename, strlen($p_string), + time(), 384, "", 0, 0)) + return false; + + $i=0; + while (($v_buffer = substr($p_string, (($i++)*512), 512)) != '') { + $v_binary_data = pack("a512", $v_buffer); + $this->_writeBlock($v_binary_data); + } + + return true; + } + // }}} + + // {{{ _writeHeader() + function _writeHeader($p_filename, $p_stored_filename) + { + if ($p_stored_filename == '') + $p_stored_filename = $p_filename; + $v_reduce_filename = $this->_pathReduction($p_stored_filename); + + if (strlen($v_reduce_filename) > 99) { + if (!$this->_writeLongHeader($v_reduce_filename)) + return false; + } + + $v_info = stat($p_filename); + $v_uid = sprintf("%6s ", DecOct($v_info[4])); + $v_gid = sprintf("%6s ", DecOct($v_info[5])); + $v_perms = sprintf("%6s ", DecOct(fileperms($p_filename))); + + $v_mtime = sprintf("%11s", DecOct(filemtime($p_filename))); + + if (@is_dir($p_filename)) { + $v_typeflag = "5"; + $v_size = sprintf("%11s ", DecOct(0)); + } else { + $v_typeflag = ''; + clearstatcache(); + $v_size = sprintf("%11s ", DecOct(filesize($p_filename))); + } + + $v_linkname = ''; + + $v_magic = ''; + + $v_version = ''; + + $v_uname = ''; + + $v_gname = ''; + + $v_devmajor = ''; + + $v_devminor = ''; + + $v_prefix = ''; + + $v_binary_data_first = pack("a100a8a8a8a12A12", + $v_reduce_filename, $v_perms, $v_uid, + $v_gid, $v_size, $v_mtime); + $v_binary_data_last = pack("a1a100a6a2a32a32a8a8a155a12", + $v_typeflag, $v_linkname, $v_magic, + $v_version, $v_uname, $v_gname, + $v_devmajor, $v_devminor, $v_prefix, ''); + + // ----- Calculate the checksum + $v_checksum = 0; + // ..... First part of the header + for ($i=0; $i<148; $i++) + $v_checksum += ord(substr($v_binary_data_first,$i,1)); + // ..... Ignore the checksum value and replace it by ' ' (space) + for ($i=148; $i<156; $i++) + $v_checksum += ord(' '); + // ..... Last part of the header + for ($i=156, $j=0; $i<512; $i++, $j++) + $v_checksum += ord(substr($v_binary_data_last,$j,1)); + + // ----- Write the first 148 bytes of the header in the archive + $this->_writeBlock($v_binary_data_first, 148); + + // ----- Write the calculated checksum + $v_checksum = sprintf("%6s ", DecOct($v_checksum)); + $v_binary_data = pack("a8", $v_checksum); + $this->_writeBlock($v_binary_data, 8); + + // ----- Write the last 356 bytes of the header in the archive + $this->_writeBlock($v_binary_data_last, 356); + + return true; + } + // }}} + + // {{{ _writeHeaderBlock() + function _writeHeaderBlock($p_filename, $p_size, $p_mtime=0, $p_perms=0, + $p_type='', $p_uid=0, $p_gid=0) + { + $p_filename = $this->_pathReduction($p_filename); + + if (strlen($p_filename) > 99) { + if (!$this->_writeLongHeader($p_filename)) + return false; + } + + if ($p_type == "5") { + $v_size = sprintf("%11s ", DecOct(0)); + } else { + $v_size = sprintf("%11s ", DecOct($p_size)); + } + + $v_uid = sprintf("%6s ", DecOct($p_uid)); + $v_gid = sprintf("%6s ", DecOct($p_gid)); + $v_perms = sprintf("%6s ", DecOct($p_perms)); + + $v_mtime = sprintf("%11s", DecOct($p_mtime)); + + $v_linkname = ''; + + $v_magic = ''; + + $v_version = ''; + + $v_uname = ''; + + $v_gname = ''; + + $v_devmajor = ''; + + $v_devminor = ''; + + $v_prefix = ''; + + $v_binary_data_first = pack("a100a8a8a8a12A12", + $p_filename, $v_perms, $v_uid, $v_gid, + $v_size, $v_mtime); + $v_binary_data_last = pack("a1a100a6a2a32a32a8a8a155a12", + $p_type, $v_linkname, $v_magic, + $v_version, $v_uname, $v_gname, + $v_devmajor, $v_devminor, $v_prefix, ''); + + // ----- Calculate the checksum + $v_checksum = 0; + // ..... First part of the header + for ($i=0; $i<148; $i++) + $v_checksum += ord(substr($v_binary_data_first,$i,1)); + // ..... Ignore the checksum value and replace it by ' ' (space) + for ($i=148; $i<156; $i++) + $v_checksum += ord(' '); + // ..... Last part of the header + for ($i=156, $j=0; $i<512; $i++, $j++) + $v_checksum += ord(substr($v_binary_data_last,$j,1)); + + // ----- Write the first 148 bytes of the header in the archive + $this->_writeBlock($v_binary_data_first, 148); + + // ----- Write the calculated checksum + $v_checksum = sprintf("%6s ", DecOct($v_checksum)); + $v_binary_data = pack("a8", $v_checksum); + $this->_writeBlock($v_binary_data, 8); + + // ----- Write the last 356 bytes of the header in the archive + $this->_writeBlock($v_binary_data_last, 356); + + return true; + } + // }}} + + // {{{ _writeLongHeader() + function _writeLongHeader($p_filename) + { + $v_size = sprintf("%11s ", DecOct(strlen($p_filename))); + + $v_typeflag = 'L'; + + $v_linkname = ''; + + $v_magic = ''; + + $v_version = ''; + + $v_uname = ''; + + $v_gname = ''; + + $v_devmajor = ''; + + $v_devminor = ''; + + $v_prefix = ''; + + $v_binary_data_first = pack("a100a8a8a8a12A12", + '././@LongLink', 0, 0, 0, $v_size, 0); + $v_binary_data_last = pack("a1a100a6a2a32a32a8a8a155a12", + $v_typeflag, $v_linkname, $v_magic, + $v_version, $v_uname, $v_gname, + $v_devmajor, $v_devminor, $v_prefix, ''); + + // ----- Calculate the checksum + $v_checksum = 0; + // ..... First part of the header + for ($i=0; $i<148; $i++) + $v_checksum += ord(substr($v_binary_data_first,$i,1)); + // ..... Ignore the checksum value and replace it by ' ' (space) + for ($i=148; $i<156; $i++) + $v_checksum += ord(' '); + // ..... Last part of the header + for ($i=156, $j=0; $i<512; $i++, $j++) + $v_checksum += ord(substr($v_binary_data_last,$j,1)); + + // ----- Write the first 148 bytes of the header in the archive + $this->_writeBlock($v_binary_data_first, 148); + + // ----- Write the calculated checksum + $v_checksum = sprintf("%6s ", DecOct($v_checksum)); + $v_binary_data = pack("a8", $v_checksum); + $this->_writeBlock($v_binary_data, 8); + + // ----- Write the last 356 bytes of the header in the archive + $this->_writeBlock($v_binary_data_last, 356); + + // ----- Write the filename as content of the block + $i=0; + while (($v_buffer = substr($p_filename, (($i++)*512), 512)) != '') { + $v_binary_data = pack("a512", "$v_buffer"); + $this->_writeBlock($v_binary_data); + } + + return true; + } + // }}} + + // {{{ _readHeader() + function _readHeader($v_binary_data, &$v_header) + { + if (strlen($v_binary_data)==0) { + $v_header['filename'] = ''; + return true; + } + + if (strlen($v_binary_data) != 512) { + $v_header['filename'] = ''; + $this->_error('Invalid block size : '.strlen($v_binary_data)); + return false; + } + + if (!is_array($v_header)) { + $v_header = array(); + } + // ----- Calculate the checksum + $v_checksum = 0; + // ..... First part of the header + for ($i=0; $i<148; $i++) + $v_checksum+=ord(substr($v_binary_data,$i,1)); + // ..... Ignore the checksum value and replace it by ' ' (space) + for ($i=148; $i<156; $i++) + $v_checksum += ord(' '); + // ..... Last part of the header + for ($i=156; $i<512; $i++) + $v_checksum+=ord(substr($v_binary_data,$i,1)); + + $v_data = unpack("a100filename/a8mode/a8uid/a8gid/a12size/a12mtime/" + ."a8checksum/a1typeflag/a100link/a6magic/a2version/" + ."a32uname/a32gname/a8devmajor/a8devminor", + $v_binary_data); + + // ----- Extract the checksum + $v_header['checksum'] = OctDec(trim($v_data['checksum'])); + if ($v_header['checksum'] != $v_checksum) { + $v_header['filename'] = ''; + + // ----- Look for last block (empty block) + if (($v_checksum == 256) && ($v_header['checksum'] == 0)) + return true; + + $this->_error('Invalid checksum for file "'.$v_data['filename'] + .'" : '.$v_checksum.' calculated, ' + .$v_header['checksum'].' expected'); + return false; + } + + // ----- Extract the properties + $v_header['filename'] = trim($v_data['filename']); + if ($this->_maliciousFilename($v_header['filename'])) { + $this->_error('Malicious .tar detected, file "' . $v_header['filename'] . + '" will not install in desired directory tree'); + return false; + } + $v_header['mode'] = OctDec(trim($v_data['mode'])); + $v_header['uid'] = OctDec(trim($v_data['uid'])); + $v_header['gid'] = OctDec(trim($v_data['gid'])); + $v_header['size'] = OctDec(trim($v_data['size'])); + $v_header['mtime'] = OctDec(trim($v_data['mtime'])); + if (($v_header['typeflag'] = $v_data['typeflag']) == "5") { + $v_header['size'] = 0; + } + $v_header['link'] = trim($v_data['link']); + /* ----- All these fields are removed form the header because + they do not carry interesting info + $v_header[magic] = trim($v_data[magic]); + $v_header[version] = trim($v_data[version]); + $v_header[uname] = trim($v_data[uname]); + $v_header[gname] = trim($v_data[gname]); + $v_header[devmajor] = trim($v_data[devmajor]); + $v_header[devminor] = trim($v_data[devminor]); + */ + + return true; + } + // }}} + + // {{{ _maliciousFilename() + /** + * Detect and report a malicious file name + * + * @param string $file + * @return bool + * @access private + */ + function _maliciousFilename($file) + { + if (strpos($file, '/../') !== false) { + return true; + } + if (strpos($file, '../') === 0) { + return true; + } + return false; + } + // }}} + + // {{{ _readLongHeader() + function _readLongHeader(&$v_header) + { + $v_filename = ''; + $n = floor($v_header['size']/512); + for ($i=0; $i<$n; $i++) { + $v_content = $this->_readBlock(); + $v_filename .= $v_content; + } + if (($v_header['size'] % 512) != 0) { + $v_content = $this->_readBlock(); + $v_filename .= $v_content; + } + + // ----- Read the next header + $v_binary_data = $this->_readBlock(); + + if (!$this->_readHeader($v_binary_data, $v_header)) + return false; + + $v_header['filename'] = $v_filename; + if ($this->_maliciousFilename($v_filename)) { + $this->_error('Malicious .tar detected, file "' . $v_filename . + '" will not install in desired directory tree'); + return false; + } + + return true; + } + // }}} + + // {{{ _extractInString() + /** + * This method extract from the archive one file identified by $p_filename. + * The return value is a string with the file content, or NULL on error. + * @param string $p_filename The path of the file to extract in a string. + * @return a string with the file content or NULL. + * @access private + */ + function _extractInString($p_filename) + { + $v_result_str = ""; + + While (strlen($v_binary_data = $this->_readBlock()) != 0) + { + if (!$this->_readHeader($v_binary_data, $v_header)) + return NULL; + + if ($v_header['filename'] == '') + continue; + + // ----- Look for long filename + if ($v_header['typeflag'] == 'L') { + if (!$this->_readLongHeader($v_header)) + return NULL; + } + + if ($v_header['filename'] == $p_filename) { + if ($v_header['typeflag'] == "5") { + $this->_error('Unable to extract in string a directory ' + .'entry {'.$v_header['filename'].'}'); + return NULL; + } else { + $n = floor($v_header['size']/512); + for ($i=0; $i<$n; $i++) { + $v_result_str .= $this->_readBlock(); + } + if (($v_header['size'] % 512) != 0) { + $v_content = $this->_readBlock(); + $v_result_str .= substr($v_content, 0, + ($v_header['size'] % 512)); + } + return $v_result_str; + } + } else { + $this->_jumpBlock(ceil(($v_header['size']/512))); + } + } + + return NULL; + } + // }}} + + // {{{ _extractList() + function _extractList($p_path, &$p_list_detail, $p_mode, + $p_file_list, $p_remove_path) + { + $v_result=true; + $v_nb = 0; + $v_extract_all = true; + $v_listing = false; + + $p_path = $this->_translateWinPath($p_path, false); + if ($p_path == '' || (substr($p_path, 0, 1) != '/' + && substr($p_path, 0, 3) != "../" && !strpos($p_path, ':'))) { + $p_path = "./".$p_path; + } + $p_remove_path = $this->_translateWinPath($p_remove_path); + + // ----- Look for path to remove format (should end by /) + if (($p_remove_path != '') && (substr($p_remove_path, -1) != '/')) + $p_remove_path .= '/'; + $p_remove_path_size = strlen($p_remove_path); + + switch ($p_mode) { + case "complete" : + $v_extract_all = TRUE; + $v_listing = FALSE; + break; + case "partial" : + $v_extract_all = FALSE; + $v_listing = FALSE; + break; + case "list" : + $v_extract_all = FALSE; + $v_listing = TRUE; + break; + default : + $this->_error('Invalid extract mode ('.$p_mode.')'); + return false; + } + + clearstatcache(); + + while (strlen($v_binary_data = $this->_readBlock()) != 0) + { + $v_extract_file = FALSE; + $v_extraction_stopped = 0; + + if (!$this->_readHeader($v_binary_data, $v_header)) + return false; + + if ($v_header['filename'] == '') { + continue; + } + + // ----- Look for long filename + if ($v_header['typeflag'] == 'L') { + if (!$this->_readLongHeader($v_header)) + return false; + } + + if ((!$v_extract_all) && (is_array($p_file_list))) { + // ----- By default no unzip if the file is not found + $v_extract_file = false; + + for ($i=0; $i strlen($p_file_list[$i])) + && (substr($v_header['filename'], 0, strlen($p_file_list[$i])) + == $p_file_list[$i])) { + $v_extract_file = TRUE; + break; + } + } + + // ----- It is a file, so compare the file names + elseif ($p_file_list[$i] == $v_header['filename']) { + $v_extract_file = TRUE; + break; + } + } + } else { + $v_extract_file = TRUE; + } + + // ----- Look if this file need to be extracted + if (($v_extract_file) && (!$v_listing)) + { + if (($p_remove_path != '') + && (substr($v_header['filename'], 0, $p_remove_path_size) + == $p_remove_path)) + $v_header['filename'] = substr($v_header['filename'], + $p_remove_path_size); + if (($p_path != './') && ($p_path != '/')) { + while (substr($p_path, -1) == '/') + $p_path = substr($p_path, 0, strlen($p_path)-1); + + if (substr($v_header['filename'], 0, 1) == '/') + $v_header['filename'] = $p_path.$v_header['filename']; + else + $v_header['filename'] = $p_path.'/'.$v_header['filename']; + } + if (file_exists($v_header['filename'])) { + if ( (@is_dir($v_header['filename'])) + && ($v_header['typeflag'] == '')) { + $this->_error('File '.$v_header['filename'] + .' already exists as a directory'); + return false; + } + if ( ($this->_isArchive($v_header['filename'])) + && ($v_header['typeflag'] == "5")) { + $this->_error('Directory '.$v_header['filename'] + .' already exists as a file'); + return false; + } + if (!is_writeable($v_header['filename'])) { + $this->_error('File '.$v_header['filename'] + .' already exists and is write protected'); + return false; + } + if (filemtime($v_header['filename']) > $v_header['mtime']) { + // To be completed : An error or silent no replace ? + } + } + + // ----- Check the directory availability and create it if necessary + elseif (($v_result + = $this->_dirCheck(($v_header['typeflag'] == "5" + ?$v_header['filename'] + :dirname($v_header['filename'])))) != 1) { + $this->_error('Unable to create path for '.$v_header['filename']); + return false; + } + + if ($v_extract_file) { + if ($v_header['typeflag'] == "5") { + if (!@file_exists($v_header['filename'])) { + if (!@mkdir($v_header['filename'], 0777)) { + $this->_error('Unable to create directory {' + .$v_header['filename'].'}'); + return false; + } + } + } elseif ($v_header['typeflag'] == "2") { + if (!@symlink($v_header['link'], $v_header['filename'])) { + $this->_error('Unable to extract symbolic link {' + .$v_header['filename'].'}'); + return false; + } + } else { + if (($v_dest_file = @fopen($v_header['filename'], "wb")) == 0) { + $this->_error('Error while opening {'.$v_header['filename'] + .'} in write binary mode'); + return false; + } else { + $n = floor($v_header['size']/512); + for ($i=0; $i<$n; $i++) { + $v_content = $this->_readBlock(); + fwrite($v_dest_file, $v_content, 512); + } + if (($v_header['size'] % 512) != 0) { + $v_content = $this->_readBlock(); + fwrite($v_dest_file, $v_content, ($v_header['size'] % 512)); + } + + @fclose($v_dest_file); + + // ----- Change the file mode, mtime + @touch($v_header['filename'], $v_header['mtime']); + if ($v_header['mode'] & 0111) { + // make file executable, obey umask + $mode = fileperms($v_header['filename']) | (~umask() & 0111); + @chmod($v_header['filename'], $mode); + } + } + + // ----- Check the file size + clearstatcache(); + if (filesize($v_header['filename']) != $v_header['size']) { + $this->_error('Extracted file '.$v_header['filename'] + .' does not have the correct file size \'' + .filesize($v_header['filename']) + .'\' ('.$v_header['size'] + .' expected). Archive may be corrupted.'); + return false; + } + } + } else { + $this->_jumpBlock(ceil(($v_header['size']/512))); + } + } else { + $this->_jumpBlock(ceil(($v_header['size']/512))); + } + + /* TBC : Seems to be unused ... + if ($this->_compress) + $v_end_of_file = @gzeof($this->_file); + else + $v_end_of_file = @feof($this->_file); + */ + + if ($v_listing || $v_extract_file || $v_extraction_stopped) { + // ----- Log extracted files + if (($v_file_dir = dirname($v_header['filename'])) + == $v_header['filename']) + $v_file_dir = ''; + if ((substr($v_header['filename'], 0, 1) == '/') && ($v_file_dir == '')) + $v_file_dir = '/'; + + $p_list_detail[$v_nb++] = $v_header; + if (is_array($p_file_list) && (count($p_list_detail) == count($p_file_list))) { + return true; + } + } + } + + return true; + } + // }}} + + // {{{ _openAppend() + function _openAppend() + { + if (filesize($this->_tarname) == 0) + return $this->_openWrite(); + + if ($this->_compress) { + $this->_close(); + + if (!@rename($this->_tarname, $this->_tarname.".tmp")) { + $this->_error('Error while renaming \''.$this->_tarname + .'\' to temporary file \''.$this->_tarname + .'.tmp\''); + return false; + } + + if ($this->_compress_type == 'gz') + $v_temp_tar = @gzopen($this->_tarname.".tmp", "rb"); + elseif ($this->_compress_type == 'bz2') + $v_temp_tar = @bzopen($this->_tarname.".tmp", "rb"); + + if ($v_temp_tar == 0) { + $this->_error('Unable to open file \''.$this->_tarname + .'.tmp\' in binary read mode'); + @rename($this->_tarname.".tmp", $this->_tarname); + return false; + } + + if (!$this->_openWrite()) { + @rename($this->_tarname.".tmp", $this->_tarname); + return false; + } + + if ($this->_compress_type == 'gz') { + while (!@gzeof($v_temp_tar)) { + $v_buffer = @gzread($v_temp_tar, 512); + if ($v_buffer == ARCHIVE_TAR_END_BLOCK) { + // do not copy end blocks, we will re-make them + // after appending + continue; + } + $v_binary_data = pack("a512", $v_buffer); + $this->_writeBlock($v_binary_data); + } + + @gzclose($v_temp_tar); + } + elseif ($this->_compress_type == 'bz2') { + while (strlen($v_buffer = @bzread($v_temp_tar, 512)) > 0) { + if ($v_buffer == ARCHIVE_TAR_END_BLOCK) { + continue; + } + $v_binary_data = pack("a512", $v_buffer); + $this->_writeBlock($v_binary_data); + } + + @bzclose($v_temp_tar); + } + + if (!@unlink($this->_tarname.".tmp")) { + $this->_error('Error while deleting temporary file \'' + .$this->_tarname.'.tmp\''); + } + + } else { + // ----- For not compressed tar, just add files before the last + // one or two 512 bytes block + if (!$this->_openReadWrite()) + return false; + + clearstatcache(); + $v_size = filesize($this->_tarname); + + // We might have zero, one or two end blocks. + // The standard is two, but we should try to handle + // other cases. + fseek($this->_file, $v_size - 1024); + if (fread($this->_file, 512) == ARCHIVE_TAR_END_BLOCK) { + fseek($this->_file, $v_size - 1024); + } + elseif (fread($this->_file, 512) == ARCHIVE_TAR_END_BLOCK) { + fseek($this->_file, $v_size - 512); + } + } + + return true; + } + // }}} + + // {{{ _append() + function _append($p_filelist, $p_add_dir='', $p_remove_dir='') + { + if (!$this->_openAppend()) + return false; + + if ($this->_addList($p_filelist, $p_add_dir, $p_remove_dir)) + $this->_writeFooter(); + + $this->_close(); + + return true; + } + // }}} + + // {{{ _dirCheck() + + /** + * Check if a directory exists and create it (including parent + * dirs) if not. + * + * @param string $p_dir directory to check + * + * @return bool TRUE if the directory exists or was created + */ + function _dirCheck($p_dir) + { + clearstatcache(); + if ((@is_dir($p_dir)) || ($p_dir == '')) + return true; + + $p_parent_dir = dirname($p_dir); + + if (($p_parent_dir != $p_dir) && + ($p_parent_dir != '') && + (!$this->_dirCheck($p_parent_dir))) + return false; + + if (!@mkdir($p_dir, 0777)) { + $this->_error("Unable to create directory '$p_dir'"); + return false; + } + + return true; + } + + // }}} + + // {{{ _pathReduction() + + /** + * Compress path by changing for example "/dir/foo/../bar" to "/dir/bar", + * rand emove double slashes. + * + * @param string $p_dir path to reduce + * + * @return string reduced path + * + * @access private + * + */ + function _pathReduction($p_dir) + { + $v_result = ''; + + // ----- Look for not empty path + if ($p_dir != '') { + // ----- Explode path by directory names + $v_list = explode('/', $p_dir); + + // ----- Study directories from last to first + for ($i=sizeof($v_list)-1; $i>=0; $i--) { + // ----- Look for current path + if ($v_list[$i] == ".") { + // ----- Ignore this directory + // Should be the first $i=0, but no check is done + } + else if ($v_list[$i] == "..") { + // ----- Ignore it and ignore the $i-1 + $i--; + } + else if ( ($v_list[$i] == '') + && ($i!=(sizeof($v_list)-1)) + && ($i!=0)) { + // ----- Ignore only the double '//' in path, + // but not the first and last / + } else { + $v_result = $v_list[$i].($i!=(sizeof($v_list)-1)?'/' + .$v_result:''); + } + } + } + $v_result = strtr($v_result, '\\', '/'); + return $v_result; + } + + // }}} + + // {{{ _translateWinPath() + function _translateWinPath($p_path, $p_remove_disk_letter=true) + { + if (defined('OS_WINDOWS') && OS_WINDOWS) { + // ----- Look for potential disk letter + if ( ($p_remove_disk_letter) + && (($v_position = strpos($p_path, ':')) != false)) { + $p_path = substr($p_path, $v_position+1); + } + // ----- Change potential windows directory separator + if ((strpos($p_path, '\\') > 0) || (substr($p_path, 0,1) == '\\')) { + $p_path = strtr($p_path, '\\', '/'); + } + } + return $p_path; + } + // }}} + +} +?> diff --git a/src/lib/pear/PEAR/Config.php b/src/lib/pear/PEAR/Config.php new file mode 100644 index 0000000..368f450 --- /dev/null +++ b/src/lib/pear/PEAR/Config.php @@ -0,0 +1,231 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: Config.php,v 1.22 2006/12/22 00:35:34 aashley Exp $ + +require_once('PEAR.php'); +require_once('Config/Container.php'); + +$GLOBALS['CONFIG_TYPES'] = + array( + 'apache' => array('Config/Container/Apache.php', 'Config_Container_Apache'), + 'genericconf' => array('Config/Container/GenericConf.php', 'Config_Container_GenericConf'), + 'inifile' => array('Config/Container/IniFile.php', 'Config_Container_IniFile'), + 'inicommented' => array('Config/Container/IniCommented.php', 'Config_Container_IniCommented'), + 'phparray' => array('Config/Container/PHPArray.php', 'Config_Container_PHPArray'), + 'phpconstants' => array('Config/Container/PHPConstants.php', 'Config_Container_PHPConstants'), + 'xml' => array('Config/Container/XML.php', 'Config_Container_XML') + ); + +/** +* Config +* +* This class allows for parsing and editing of configuration datasources. +* Do not use this class only to read datasources because of the overhead +* it creates to keep track of the configuration structure. +* +* @author Bertrand Mansion +* @package Config +*/ +class Config { + + /** + * Datasource + * Can be a file url, a dsn, an object... + * @var mixed + */ + var $datasrc; + + /** + * Type of datasource for config + * Ex: IniCommented, Apache... + * @var string + */ + var $configType = ''; + + /** + * Options for parser + * @var string + */ + var $parserOptions = array(); + + /** + * Container object + * @var object + */ + var $container; + + /** + * Constructor + * Creates a root container + * + * @access public + */ + function Config() + { + $this->container =& new Config_Container('section', 'root'); + } // end constructor + + /** + * Returns true if container is registered + * + * @param string $configType Type of config + * @access public + * @return bool + */ + function isConfigTypeRegistered($configType) + { + return isset($GLOBALS['CONFIG_TYPES'][strtolower($configType)]); + } // end func isConfigTypeRegistered + + /** + * Register a new container + * + * @param string $configType Type of config + * @param array|false $configInfo Array of format: + * array('path/to/Name.php', + * 'Config_Container_Class_Name'). + * + * If left false, defaults to: + * array('Config/Container/$configType.php', + * 'Config_Container_$configType') + * @access public + * @static + * @author Greg Beaver + * @return true|PEAR_Error true on success + */ + function registerConfigType($configType, $configInfo = false) + { + if (Config::isConfigTypeRegistered($configType)) { + $info = $GLOBALS['CONFIG_TYPES'][strtolower($configType)]; + if ($info[0] == $configInfo[0] && + $info[1] == $configInfo[1]) { + return true; + } else { + return PEAR::raiseError("Config::registerConfigType registration of existing $configType failed.", null, PEAR_ERROR_RETURN); + } + } + if (!is_array($configInfo)) { + // make the normal assumption, that this is a standard config container added in at runtime + $configInfo = array('Config/Container/' . $configType . '.php', + 'Config_Container_'. $configType); + } + $file_exists = @include_once($configInfo[0]); + if ($file_exists) { + if (!class_exists($configInfo[1])) { + return PEAR::raiseError("Config::registerConfigType class '$configInfo[1]' not found in $configInfo[0]", null, PEAR_ERROR_RETURN); + } + } else { + return PEAR::raiseError("Config::registerConfigType file $configInfo[0] not found", null, PEAR_ERROR_RETURN); + } + $GLOBALS['CONFIG_TYPES'][strtolower($configType)] = $configInfo; + return true; + } // end func registerConfigType + + /** + * Returns the root container for this config object + * + * @access public + * @return object reference to config's root container object + */ + function &getRoot() + { + return $this->container; + } // end func getRoot + + /** + * Sets the content of the root Config_container object. + * + * This method will replace the current child of the root + * Config_Container object by the given object. + * + * @param object $rootContainer container to be used as the first child to root + * @access public + * @return mixed true on success or PEAR_Error + */ + function setRoot(&$rootContainer) + { + if (is_object($rootContainer) && strtolower(get_class($rootContainer)) === 'config_container') { + if ($rootContainer->getName() === 'root' && $rootContainer->getType() === 'section') { + $this->container =& $rootContainer; + } else { + $this->container =& new Config_Container('section', 'root'); + $this->container->addItem($rootContainer); + } + return true; + } else { + return PEAR::raiseError("Config::setRoot only accepts object of Config_Container type.", null, PEAR_ERROR_RETURN); + } + } // end func setRoot + + /** + * Parses the datasource contents + * + * This method will parse the datasource given and fill the root + * Config_Container object with other Config_Container objects. + * + * @param mixed $datasrc Datasource to parse + * @param string $configType Type of configuration + * @param array $options Options for the parser + * @access public + * @return mixed PEAR_Error on error or Config_Container object + */ + function &parseConfig($datasrc, $configType, $options = array()) + { + $configType = strtolower($configType); + if (!$this->isConfigTypeRegistered($configType)) { + return PEAR::raiseError("Configuration type '$configType' is not registered in Config::parseConfig.", null, PEAR_ERROR_RETURN); + } + $includeFile = $GLOBALS['CONFIG_TYPES'][$configType][0]; + $className = $GLOBALS['CONFIG_TYPES'][$configType][1]; + include_once($includeFile); + + $parser = new $className($options); + $error = $parser->parseDatasrc($datasrc, $this); + if ($error !== true) { + return $error; + } + $this->parserOptions = $parser->options; + $this->datasrc = $datasrc; + $this->configType = $configType; + return $this->container; + } // end func &parseConfig + + /** + * Writes the container contents to the datasource. + * + * @param mixed $datasrc Datasource to write to + * @param string $configType Type of configuration + * @param array $options Options for config container + * @access public + * @return mixed PEAR_Error on error or true if ok + */ + function writeConfig($datasrc = null, $configType = null, $options = array()) + { + if (empty($datasrc)) { + $datasrc = $this->datasrc; + } + if (empty($configType)) { + $configType = $this->configType; + } + if (empty($options)) { + $options = $this->parserOptions; + } + return $this->container->writeDatasrc($datasrc, $configType, $options); + } // end func writeConfig +} // end class Config +?> diff --git a/src/lib/pear/PEAR/Config/Container.php b/src/lib/pear/PEAR/Config/Container.php new file mode 100644 index 0000000..a143eb6 --- /dev/null +++ b/src/lib/pear/PEAR/Config/Container.php @@ -0,0 +1,776 @@ + | +// +---------------------------------------------------------------------+ +// +// $Id: Container.php,v 1.41 2006/05/30 06:37:28 aashley Exp $ + +require_once 'Config.php'; + +/** +* Interface for Config containers +* +* @author Bertrand Mansion +* @package Config +*/ +class Config_Container { + + /** + * Container object type + * Ex: section, directive, comment, blank + * @var string + */ + var $type; + + /** + * Container object name + * @var string + */ + var $name = ''; + + /** + * Container object content + * @var string + */ + var $content = ''; + + /** + * Container object children + * @var array + */ + var $children = array(); + + /** + * Reference to container object's parent + * @var object + */ + var $parent; + + /** + * Array of attributes for this item + * @var array + */ + var $attributes; + + /** + * Unique id to differenciate nodes + * + * This is used to compare nodes + * Will not be needed anymore when this class will use ZendEngine 2 + * + * @var int + */ + var $_id; + + /** + * Constructor + * + * @param string $type Type of container object + * @param string $name Name of container object + * @param string $content Content of container object + * @param array $attributes Array of attributes for container object + */ + function Config_Container($type = 'section', $name = '', $content = '', $attributes = null) + { + $this->type = $type; + $this->name = $name; + $this->content = $content; + $this->attributes = $attributes; + $this->parent = null; + if (version_compare(PHP_VERSION, '5.0.0', 'gt')) { + $this->_id = uniqid($name.$type, true); + } else { + $this->_id = uniqid(substr($name.$type, 0, 114), true); + } + } // end constructor + + /** + * Create a child for this item. + * @param string $type type of item: directive, section, comment, blank... + * @param mixed $item item name + * @param string $content item content + * @param array $attributes item attributes + * @param string $where choose a position 'bottom', 'top', 'after', 'before' + * @param object $target needed if you choose 'before' or 'after' for where + * @return object reference to new item or Pear_Error + */ + function &createItem($type, $name, $content, $attributes = null, $where = 'bottom', $target = null) + { + $item =& new Config_Container($type, $name, $content, $attributes); + $result =& $this->addItem($item, $where, $target); + return $result; + } // end func &createItem + + /** + * Adds an item to this item. + * @param object $item a container object + * @param string $where choose a position 'bottom', 'top', 'after', 'before' + * @param object $target needed if you choose 'before' or 'after' in $where + * @return mixed reference to added container on success, Pear_Error on error + */ + function &addItem(&$item, $where = 'bottom', $target = null) + { + if ($this->type != 'section') { + return PEAR::raiseError('Config_Container::addItem must be called on a section type object.', null, PEAR_ERROR_RETURN); + } + if (is_null($target)) { + $target =& $this; + } + if (strtolower(get_class($target)) != 'config_container') { + return PEAR::raiseError('Target must be a Config_Container object in Config_Container::addItem.', null, PEAR_ERROR_RETURN); + } + + switch ($where) { + case 'before': + $index = $target->getItemIndex(); + break; + case 'after': + $index = $target->getItemIndex()+1; + break; + case 'top': + $index = 0; + break; + case 'bottom': + $index = -1; + break; + default: + return PEAR::raiseError('Use only top, bottom, before or after in Config_Container::addItem.', null, PEAR_ERROR_RETURN); + } + if (isset($index) && $index >= 0) { + array_splice($this->children, $index, 0, 'tmp'); + } else { + $index = count($this->children); + } + $this->children[$index] =& $item; + $this->children[$index]->parent =& $this; + + return $item; + } // end func addItem + + /** + * Adds a comment to this item. + * This is a helper method that calls createItem + * + * @param string $content Object content + * @param string $where Position : 'top', 'bottom', 'before', 'after' + * @param object $target Needed when $where is 'before' or 'after' + * @return object reference to new item or Pear_Error + */ + function &createComment($content = '', $where = 'bottom', $target = null) + { + return $this->createItem('comment', null, $content, null, $where, $target); + } // end func &createComment + + /** + * Adds a blank line to this item. + * This is a helper method that calls createItem + * + * @return object reference to new item or Pear_Error + */ + function &createBlank($where = 'bottom', $target = null) + { + return $this->createItem('blank', null, null, null, $where, $target); + } // end func &createBlank + + /** + * Adds a directive to this item. + * This is a helper method that calls createItem + * + * @param string $name Name of new directive + * @param string $content Content of new directive + * @param mixed $attributes Directive attributes + * @param string $where Position : 'top', 'bottom', 'before', 'after' + * @param object $target Needed when $where is 'before' or 'after' + * @return object reference to new item or Pear_Error + */ + function &createDirective($name, $content, $attributes = null, $where = 'bottom', $target = null) + { + return $this->createItem('directive', $name, $content, $attributes, $where, $target); + } // end func &createDirective + + /** + * Adds a section to this item. + * + * This is a helper method that calls createItem + * If the section already exists, it won't create a new one. + * It will return reference to existing item. + * + * @param string $name Name of new section + * @param array $attributes Section attributes + * @param string $where Position : 'top', 'bottom', 'before', 'after' + * @param object $target Needed when $where is 'before' or 'after' + * @return object reference to new item or Pear_Error + */ + function &createSection($name, $attributes = null, $where = 'bottom', $target = null) + { + return $this->createItem('section', $name, null, $attributes, $where, $target); + } // end func &createSection + + /** + * Tries to find the specified item(s) and returns the objects. + * + * Examples: + * $directives =& $obj->getItem('directive'); + * $directive_bar_4 =& $obj->getItem('directive', 'bar', null, 4); + * $section_foo =& $obj->getItem('section', 'foo'); + * + * This method can only be called on an object of type 'section'. + * Note that root is a section. + * This method is not recursive and tries to keep the current structure. + * For a deeper search, use searchPath() + * + * @param string $type Type of item: directive, section, comment, blank... + * @param mixed $name Item name + * @param mixed $content Find item with this content + * @param array $attributes Find item with attribute set to the given value + * @param int $index Index of the item in the returned object list. If it is not set, will try to return the last item with this name. + * @return mixed reference to item found or false when not found + * @see &searchPath() + */ + function &getItem($type = null, $name = null, $content = null, $attributes = null, $index = -1) + { + if ($this->type != 'section') { + return PEAR::raiseError('Config_Container::getItem must be called on a section type object.', null, PEAR_ERROR_RETURN); + } + if (!is_null($type)) { + $testFields[] = 'type'; + } + if (!is_null($name)) { + $testFields[] = 'name'; + } + if (!is_null($content)) { + $testFields[] = 'content'; + } + if (!is_null($attributes) && is_array($attributes)) { + $testFields[] = 'attributes'; + } + + $itemsArr = array(); + $fieldsToMatch = count($testFields); + for ($i = 0, $count = count($this->children); $i < $count; $i++) { + $match = 0; + reset($testFields); + foreach ($testFields as $field) { + if ($field != 'attributes') { + if ($this->children[$i]->$field == ${$field}) { + $match++; + } + } else { + // Look for attributes in array + $attrToMatch = count($attributes); + $attrMatch = 0; + foreach ($attributes as $key => $value) { + if (isset($this->children[$i]->attributes[$key]) && + $this->children[$i]->attributes[$key] == $value) { + $attrMatch++; + } + } + if ($attrMatch == $attrToMatch) { + $match++; + } + } + } + if ($match == $fieldsToMatch) { + $itemsArr[] =& $this->children[$i]; + } + } + if ($index >= 0) { + if (isset($itemsArr[$index])) { + return $itemsArr[$index]; + } else { + $return = false; + return $return; + } + } else { + if ($count = count($itemsArr)) { + return $itemsArr[$count-1]; + } else { + $return = false; + return $return; + } + } + } // end func &getItem + + /** + * Finds a node using XPATH like format. + * + * The search format is an array: + * array(item1, item2, item3, ...) + * + * Each item can be defined as the following: + * item = 'string' : will match the container named 'string' + * item = array('string', array('name' => 'xyz')) + * will match the container name 'string' whose attribute name is equal to "xyz" + * For example : + * + * @param mixed Search path and attributes + * + * @return mixed Config_Container object, array of Config_Container objects or false on failure. + * @access public + */ + function &searchPath($args) + { + if ($this->type != 'section') { + return PEAR::raiseError('Config_Container::searchPath must be called on a section type object.', null, PEAR_ERROR_RETURN); + } + + $arg = array_shift($args); + + if (is_array($arg)) { + $name = $arg[0]; + $attributes = $arg[1]; + } else { + $name = $arg; + $attributes = null; + } + // find all the matches for first.. + $match =& $this->getItem(null, $name, null, $attributes); + + if (!$match) { + $return = false; + return $return; + } + if (!empty($args)) { + return $match->searchPath($args); + } + return $match; + } // end func &searchPath + + /** + * Return a child directive's content. + * + * This method can use two different search approach, depending on + * the parameter it is given. If the parameter is an array, it will use + * the {@link Config_Container::searchPath()} method. If it is a string, + * it will use the {@link Config_Container::getItem()} method. + * + * Example: + * + * require_once 'Config.php'; + * $ini = new Config(); + * $conf =& $ini->parseConfig('/path/to/config.ini', 'inicommented'); + * + * // Will return the value found at : + * // [Database] + * // host=localhost + * echo $conf->directiveContent(array('Database', 'host'))); + * + * // Will return the value found at : + * // date="dec-2004" + * echo $conf->directiveContent('date'); + * + * + * + * @param mixed Search path and attributes or a directive name + * @param int Index of the item in the returned directive list. + * Eventually used if args is a string. + * + * @return mixed Content of directive or false if not found. + * @access public + */ + function directiveContent($args, $index = -1) + { + if (is_array($args)) { + $item =& $this->searchPath($args); + } else { + $item =& $this->getItem('directive', $args, null, null, $index); + } + if ($item) { + return $item->getContent(); + } + return false; + } // end func getDirectiveContent + + /** + * Returns how many children this container has + * + * @param string $type type of children counted + * @param string $name name of children counted + * @return int number of children found + */ + function countChildren($type = null, $name = null) + { + if (is_null($type) && is_null($name)) { + return count($this->children); + } + $count = 0; + if (isset($name) && isset($type)) { + for ($i = 0, $children = count($this->children); $i < $children; $i++) { + if ($this->children[$i]->name === $name && + $this->children[$i]->type == $type) { + $count++; + } + } + return $count; + } + if (isset($type)) { + for ($i = 0, $children = count($this->children); $i < $children; $i++) { + if ($this->children[$i]->type == $type) { + $count++; + } + } + return $count; + } + if (isset($name)) { + // Some directives can have the same name + for ($i = 0, $children = count($this->children); $i < $children; $i++) { + if ($this->children[$i]->name === $name) { + $count++; + } + } + return $count; + } + } // end func &countChildren + + /** + * Deletes an item (section, directive, comment...) from the current object + * TODO: recursive remove in sub-sections + * @return mixed true if object was removed, false if not, or PEAR_Error if root + */ + function removeItem() + { + if ($this->isRoot()) { + return PEAR::raiseError('Cannot remove root item in Config_Container::removeItem.', null, PEAR_ERROR_RETURN); + } + $index = $this->getItemIndex(); + if (!is_null($index)) { + array_splice($this->parent->children, $index, 1); + return true; + } + return false; + } // end func removeItem + + /** + * Returns the item index in its parent children array. + * @return int returns int or null if root object + */ + function getItemIndex() + { + if (is_object($this->parent)) { + // This will be optimized with Zend Engine 2 + $pchildren =& $this->parent->children; + for ($i = 0, $count = count($pchildren); $i < $count; $i++) { + if ($pchildren[$i]->_id == $this->_id) { + return $i; + } + } + } + return; + } // end func getItemIndex + + /** + * Returns the item rank in its parent children array + * according to other items with same type and name. + * @param bool count items differently by type + * @return int returns int or null if root object + */ + function getItemPosition($byType = true) + { + if (is_object($this->parent)) { + $pchildren =& $this->parent->children; + for ($i = 0, $count = count($pchildren); $i < $count; $i++) { + if ($pchildren[$i]->name == $this->name) { + if ($byType == true) { + if ($pchildren[$i]->type == $this->type) { + $obj[] =& $pchildren[$i]; + } + } else { + $obj[] =& $pchildren[$i]; + } + } + } + for ($i = 0, $count = count($obj); $i < $count; $i++) { + if ($obj[$i]->_id == $this->_id) { + return $i; + } + } + } + return; + } // end func getItemPosition + + /** + * Returns the item parent object. + * @return object returns reference to parent object or null if root object + */ + function &getParent() + { + return $this->parent; + } // end func &getParent + + /** + * Returns the item parent object. + * @return mixed returns reference to child object or false if child does not exist + */ + function &getChild($index = 0) + { + if (!empty($this->children[$index])) { + return $this->children[$index]; + } else { + return false; + } + } // end func &getChild + + /** + * Set this item's name. + * @return void + */ + function setName($name) + { + $this->name = $name; + } // end func setName + + /** + * Get this item's name. + * @return string item's name + */ + function getName() + { + return $this->name; + } // end func getName + + /** + * Set this item's content. + * @return void + */ + function setContent($content) + { + $this->content = $content; + } // end func setContent + + /** + * Get this item's content. + * @return string item's content + */ + function getContent() + { + return $this->content; + } // end func getContent + + /** + * Set this item's type. + * @return void + */ + function setType($type) + { + $this->type = $type; + } // end func setType + + /** + * Get this item's type. + * @return string item's type + */ + function getType() + { + return $this->type; + } // end func getType + + /** + * Set this item's attributes. + * @param array $attributes Array of attributes + * @return void + */ + function setAttributes($attributes) + { + $this->attributes = $attributes; + } // end func setAttributes + + /** + * Set this item's attributes. + * @param array $attributes Array of attributes + * @return void + */ + function updateAttributes($attributes) + { + if (is_array($attributes)) { + foreach ($attributes as $key => $value) { + $this->attributes[$key] = $value; + } + } + } // end func updateAttributes + + /** + * Get this item's attributes. + * @return array item's attributes + */ + function getAttributes() + { + return $this->attributes; + } // end func getAttributes + + /** + * Get one attribute value of this item + * @param string $attribute Attribute key + * @return mixed item's attribute value + */ + function getAttribute($attribute) + { + if (isset($this->attributes[$attribute])) { + return $this->attributes[$attribute]; + } + return null; + } // end func getAttribute + + /** + * Set a children directive content. + * This is an helper method calling getItem and addItem or setContent for you. + * If the directive does not exist, it will be created at the bottom. + * + * @param string $name Name of the directive to look for + * @param mixed $content New content + * @param int $index Index of the directive to set, + * in case there are more than one directive + * with the same name + * @return object newly set directive + */ + function &setDirective($name, $content, $index = -1) + { + $item =& $this->getItem('directive', $name, null, null, $index); + if ($item === false || PEAR::isError($item)) { + // Directive does not exist, will create one + unset($item); + return $this->createDirective($name, $content, null); + } else { + // Change existing directive value + $item->setContent($content); + return $item; + } + } // end func setDirective + + /** + * Is this item root, in a config container object + * @return bool true if item is root + */ + function isRoot() + { + if (is_null($this->parent)) { + return true; + } + return false; + } // end func isRoot + + /** + * Call the toString methods in the container plugin + * @param string $configType Type of configuration used to generate the string + * @param array $options Specify special options used by the parser + * @return mixed true on success or PEAR_ERROR + */ + function toString($configType, $options = array()) + { + $configType = strtolower($configType); + if (!isset($GLOBALS['CONFIG_TYPES'][$configType])) { + return PEAR::raiseError("Configuration type '$configType' is not registered in Config_Container::toString.", null, PEAR_ERROR_RETURN); + } + $includeFile = $GLOBALS['CONFIG_TYPES'][$configType][0]; + $className = $GLOBALS['CONFIG_TYPES'][$configType][1]; + include_once($includeFile); + $renderer = new $className($options); + return $renderer->toString($this); + } // end func toString + + /** + * Returns a key/value pair array of the container and its children. + * + * Format : section[directive][index] = value + * If the container has attributes, it will use '@' and '#' + * index is here because multiple directives can have the same name. + * + * @param bool $useAttr Whether to return the attributes too + * @return array + */ + function toArray($useAttr = true) + { + $array[$this->name] = array(); + switch ($this->type) { + case 'directive': + if ($useAttr && count($this->attributes) > 0) { + $array[$this->name]['#'] = $this->content; + $array[$this->name]['@'] = $this->attributes; + } else { + $array[$this->name] = $this->content; + } + break; + case 'section': + if ($useAttr && count($this->attributes) > 0) { + $array[$this->name]['@'] = $this->attributes; + } + if ($count = count($this->children)) { + for ($i = 0; $i < $count; $i++) { + $newArr = $this->children[$i]->toArray($useAttr); + if (!is_null($newArr)) { + foreach ($newArr as $key => $value) { + if (isset($array[$this->name][$key])) { + // duplicate name/type + if (!is_array($array[$this->name][$key]) || + !isset($array[$this->name][$key][0])) { + $old = $array[$this->name][$key]; + unset($array[$this->name][$key]); + $array[$this->name][$key][0] = $old; + } + $array[$this->name][$key][] = $value; + } else { + $array[$this->name][$key] = $value; + } + } + } + } + } + break; + default: + return null; + } + return $array; + } // end func toArray + + /** + * Writes the configuration to a file + * + * @param mixed $datasrc Info on datasource such as path to the configuraton file or dsn... + * @param string $configType Type of configuration + * @param array $options Options for writer + * @access public + * @return mixed true on success or PEAR_ERROR + */ + function writeDatasrc($datasrc, $configType, $options = array()) + { + $configType = strtolower($configType); + if (!isset($GLOBALS['CONFIG_TYPES'][$configType])) { + return PEAR::raiseError("Configuration type '$configType' is not registered in Config_Container::writeDatasrc.", null, PEAR_ERROR_RETURN); + } + $includeFile = $GLOBALS['CONFIG_TYPES'][$configType][0]; + $className = $GLOBALS['CONFIG_TYPES'][$configType][1]; + include_once($includeFile); + + $writeMethodName = (version_compare(phpversion(), '5', '<')) ? 'writedatasrc' : 'writeDatasrc'; + if (in_array($writeMethodName, get_class_methods($className))) { + $writer = new $className($options); + return $writer->writeDatasrc($datasrc, $this); + } + + // Default behaviour + $fp = @fopen($datasrc, 'w'); + if ($fp) { + $string = $this->toString($configType, $options); + $len = strlen($string); + @flock($fp, LOCK_EX); + @fwrite($fp, $string, $len); + @flock($fp, LOCK_UN); + @fclose($fp); + return true; + } else { + return PEAR::raiseError('Cannot open datasource for writing.', 1, PEAR_ERROR_RETURN); + } + } // end func writeDatasrc +} // end class Config_Container +?> diff --git a/src/lib/pear/PEAR/Config/Container/Apache.php b/src/lib/pear/PEAR/Config/Container/Apache.php new file mode 100644 index 0000000..fe406ae --- /dev/null +++ b/src/lib/pear/PEAR/Config/Container/Apache.php @@ -0,0 +1,169 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: Apache.php,v 1.11 2005/12/24 02:34:39 aashley Exp $ + +/** +* Simple config parser for apache httpd.conf files +* A more complex version could handle directives as +* associative arrays. +* +* @author Bertrand Mansion +* @package Config +*/ +class Config_Container_Apache { + + /** + * This class options + * Not used at the moment + * + * @var array + */ + var $options = array(); + + /** + * Constructor + * + * @access public + * @param string $options (optional)Options to be used by renderer + */ + function Config_Container_Apache($options = array()) + { + $this->options = $options; + } // end constructor + + /** + * Parses the data of the given configuration file + * + * @access public + * @param string $datasrc path to the configuration file + * @param object $obj reference to a config object + * @return mixed returns a PEAR_ERROR, if error occurs or true if ok + */ + function &parseDatasrc($datasrc, &$obj) + { + $return = true; + if (!is_readable($datasrc)) { + return PEAR::raiseError("Datasource file cannot be read.", null, PEAR_ERROR_RETURN); + } + $lines = file($datasrc); + $n = 0; + $lastline = ''; + $sections[0] =& $obj->container; + foreach ($lines as $line) { + $n++; + if (!preg_match('/^\s*#/', $line) && + preg_match('/^\s*(.*)\s+\\\$/', $line, $match)) { + // directive on more than one line + $lastline .= $match[1].' '; + continue; + } + if ($lastline != '') { + $line = $lastline.trim($line); + $lastline = ''; + } + if (preg_match('/^\s*#+\s*(.*?)\s*$/', $line, $match)) { + // a comment + $currentSection =& $sections[count($sections)-1]; + $currentSection->createComment($match[1]); + } elseif (trim($line) == '') { + // a blank line + $currentSection =& $sections[count($sections)-1]; + $currentSection->createBlank(); + } elseif (preg_match('/^\s*(\w+)(?:\s+(.*?)|)\s*$/', $line, $match)) { + // a directive + $currentSection =& $sections[count($sections)-1]; + $currentSection->createDirective($match[1], $match[2]); + } elseif (preg_match('/^\s*<(\w+)(?:\s+([^>]*)|\s*)>\s*$/', $line, $match)) { + // a section opening + if (!isset($match[2])) + $match[2] = ''; + $currentSection =& $sections[count($sections)-1]; + $attributes = explode(' ', $match[2]); + $sections[] =& $currentSection->createSection($match[1], $attributes); + } elseif (preg_match('/^\s*<\/(\w+)\s*>\s*$/', $line, $match)) { + // a section closing + $currentSection =& $sections[count($sections)-1]; + if ($currentSection->name != $match[1]) { + return PEAR::raiseError("Section not closed in '$datasrc' at line $n.", null, PEAR_ERROR_RETURN); + } + array_pop($sections); + } else { + return PEAR::raiseError("Syntax error in '$datasrc' at line $n.", null, PEAR_ERROR_RETURN); + } + } + return $return; + } // end func parseDatasrc + + /** + * Returns a formatted string of the object + * @param object $obj Container object to be output as string + * @access public + * @return string + */ + function toString(&$obj) + { + static $deep = -1; + $ident = ''; + if (!$obj->isRoot()) { + // no indent for root + $deep++; + $ident = str_repeat(' ', $deep); + } + if (!isset($string)) { + $string = ''; + } + switch ($obj->type) { + case 'blank': + $string = "\n"; + break; + case 'comment': + $string = $ident.'# '.$obj->content."\n"; + break; + case 'directive': + $string = $ident.$obj->name.' '.$obj->content."\n"; + break; + case 'section': + if (!$obj->isRoot()) { + $string = $ident.'<'.$obj->name; + if (is_array($obj->attributes) && count($obj->attributes) > 0) { + foreach ($obj->attributes as $attr => $val) { + $string .= ' '.$val; + } + } + $string .= ">\n"; + } + if (count($obj->children) > 0) { + for ($i = 0; $i < count($obj->children); $i++) { + $string .= $this->toString($obj->getChild($i)); + } + } + if (!$obj->isRoot()) { + // object is not root + $string .= $ident.'name.">\n"; + } + break; + default: + $string = ''; + } + if (!$obj->isRoot()) { + $deep--; + } + return $string; + } // end func toString +} // end class Config_Container_Apache +?> diff --git a/src/lib/pear/PEAR/Config/Container/GenericConf.php b/src/lib/pear/PEAR/Config/Container/GenericConf.php new file mode 100644 index 0000000..a6aef5d --- /dev/null +++ b/src/lib/pear/PEAR/Config/Container/GenericConf.php @@ -0,0 +1,139 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: GenericConf.php,v 1.7 2005/12/24 02:24:30 aashley Exp $ + +/** +* Config parser for generic .conf files like +* htdig.conf... +* +* @author Bertrand Mansion +* @package Config +*/ +class Config_Container_GenericConf { + + /** + * This class options: + * Ex: $options['comment'] = '#'; + * Ex: $options['equals'] = ':'; + * Ex: $options['newline'] = '\\'; + * + * @var array + */ + var $options = array(); + + /** + * Constructor + * + * @access public + * @param string $options (optional)Options to be used by renderer + */ + function Config_Container_GenericConf($options = array()) + { + if (empty($options['comment'])) { + $options['comment'] = '#'; + } + if (empty($options['equals'])) { + $options['equals'] = ':'; + } + if (empty($options['newline'])) { + $options['newline'] = '\\'; + } + $this->options = $options; + } // end constructor + + /** + * Parses the data of the given configuration file + * + * @access public + * @param string $datasrc path to the configuration file + * @param object $obj reference to a config object + * @return mixed returns a PEAR_ERROR, if error occurs or true if ok + */ + function &parseDatasrc($datasrc, &$obj) + { + $return = true; + if (!is_readable($datasrc)) { + return PEAR::raiseError("Datasource file cannot be read.", null, PEAR_ERROR_RETURN); + } + + $lines = file($datasrc); + $n = 0; + $lastline = ''; + $currentSection =& $obj->container; + foreach ($lines as $line) { + $n++; + if (!preg_match('/^\s*'.$this->options['comment'].'/', $line) && + preg_match('/^\s*(.*)\s+'.$this->options['newline'].'\s*$/', $line, $match)) { + // directive on more than one line + $lastline .= $match[1].' '; + continue; + } + if ($lastline != '') { + $line = $lastline.trim($line); + $lastline = ''; + } + if (preg_match('/^\s*'.$this->options['comment'].'+\s*(.*?)\s*$/', $line, $match)) { + // a comment + $currentSection->createComment($match[1]); + } elseif (preg_match('/^\s*$/', $line)) { + // a blank line + $currentSection->createBlank(); + } elseif (preg_match('/^\s*(\w+)'.$this->options['equals'].'\s*((.*?)|)\s*$/', $line, $match)) { + // a directive + $currentSection->createDirective($match[1], $match[2]); + } else { + return PEAR::raiseError("Syntax error in '$datasrc' at line $n.", null, PEAR_ERROR_RETURN); + } + } + return $return; + } // end func parseDatasrc + + /** + * Returns a formatted string of the object + * @param object $obj Container object to be output as string + * @access public + * @return string + */ + function toString(&$obj) + { + $string = ''; + switch ($obj->type) { + case 'blank': + $string = "\n"; + break; + case 'comment': + $string = $this->options['comment'].$obj->content."\n"; + break; + case 'directive': + $string = $obj->name.$this->options['equals'].$obj->content."\n"; + break; + case 'section': + // How to deal with sections ??? + if (count($obj->children) > 0) { + for ($i = 0; $i < count($obj->children); $i++) { + $string .= $this->toString($obj->getChild($i)); + } + } + break; + default: + $string = ''; + } + return $string; + } // end func toString +} // end class Config_Container_GenericConf +?> diff --git a/src/lib/pear/PEAR/Config/Container/IniCommented.php b/src/lib/pear/PEAR/Config/Container/IniCommented.php new file mode 100644 index 0000000..5c2315c --- /dev/null +++ b/src/lib/pear/PEAR/Config/Container/IniCommented.php @@ -0,0 +1,327 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: IniCommented.php,v 1.26 2006/05/30 06:51:05 aashley Exp $ + +/** +* Config parser for PHP .ini files with comments +* +* @author Bertrand Mansion +* @package Config +*/ +class Config_Container_IniCommented { + + /** + * This class options + * Not used at the moment + * + * @var array + */ + var $options = array(); + + /** + * Constructor + * + * @access public + * @param string $options (optional)Options to be used by renderer + */ + function Config_Container_IniCommented($options = array()) + { + $this->options = $options; + } // end constructor + + /** + * Parses the data of the given configuration file + * + * @access public + * @param string $datasrc path to the configuration file + * @param object $obj reference to a config object + * @return mixed returns a PEAR_ERROR, if error occurs or true if ok + */ + function &parseDatasrc($datasrc, &$obj) + { + $return = true; + if (!file_exists($datasrc)) { + return PEAR::raiseError("Datasource file does not exist.", null, PEAR_ERROR_RETURN); + } + $lines = file($datasrc); + $n = 0; + $lastline = ''; + $currentSection =& $obj->container; + foreach ($lines as $line) { + $n++; + if (preg_match('/^\s*;(.*?)\s*$/', $line, $match)) { + // a comment + $currentSection->createComment($match[1]); + } elseif (preg_match('/^\s*$/', $line)) { + // a blank line + $currentSection->createBlank(); + } elseif (preg_match('/^\s*([a-zA-Z0-9_\-\.\s:]*)\s*=\s*(.*)\s*$/', $line, $match)) { + // a directive + + $values = $this->_quoteAndCommaParser($match[2]); + if (PEAR::isError($values)) { + return PEAR::raiseError($values); + } + + if (count($values)) { + foreach($values as $value) { + if ($value[0] == 'normal') { + $currentSection->createDirective(trim($match[1]), $value[1]); + } + if ($value[0] == 'comment') { + $currentSection->createComment(substr($value[1], 1)); + } + } + } + } elseif (preg_match('/^\s*\[\s*(.*)\s*\]\s*$/', $line, $match)) { + // a section + $currentSection =& $obj->container->createSection($match[1]); + } else { + return PEAR::raiseError("Syntax error in '$datasrc' at line $n.", null, PEAR_ERROR_RETURN); + } + } + return $return; + } // end func parseDatasrc + + /** + * Quote and Comma Parser for INI files + * + * This function allows complex values such as: + * + * + * mydirective = "Item, number \"1\"", Item 2 ; "This" is really, really tricky + * + * @param string $text value of a directive to parse for quotes/multiple values + * @return array The array returned contains multiple values, if any (unquoted literals + * to be used as is), and a comment, if any. The format of the array is: + * + *
    +     * array(array('normal', 'first value'),
    +     *       array('normal', 'next value'),...
    +     *       array('comment', '; comment with leading ;'))
    +     * 
    + * @author Greg Beaver + * @access private + */ + function _quoteAndCommaParser($text) + { + $text = trim($text); + if ($text == '') { + $emptyNode = array(); + $emptyNode[0][0] = 'normal'; + $emptyNode[0][1] = ''; + return $emptyNode; + } + + // tokens + $tokens['normal'] = array('"', ';', ','); + $tokens['quote'] = array('"', '\\'); + $tokens['escape'] = false; // cycle + $tokens['after_quote'] = array(',', ';'); + + // events + $events['normal'] = array('"' => 'quote', ';' => 'comment', ',' => 'normal'); + $events['quote'] = array('"' => 'after_quote', '\\' => 'escape'); + $events['after_quote'] = array(',' => 'normal', ';' => 'comment'); + + // state stack + $stack = array(); + + // return information + $return = array(); + $returnpos = 0; + $returntype = 'normal'; + + // initialize + array_push($stack, 'normal'); + $pos = 0; // position in $text + + do { + $char = $text{$pos}; + $state = $this->_getQACEvent($stack); + + if ($tokens[$state]) { + if (in_array($char, $tokens[$state])) { + switch($events[$state][$char]) { + case 'quote' : + if ($state == 'normal' && + isset($return[$returnpos]) && + !empty($return[$returnpos][1])) { + return PEAR::raiseError("invalid ini syntax, quotes cannot follow text '$text'", + null, PEAR_ERROR_RETURN); + } + if ($returnpos >= 0 && isset($return[$returnpos])) { + // trim any unnecessary whitespace in earlier entries + $return[$returnpos][1] = trim($return[$returnpos][1]); + } else { + $returnpos++; + } + $return[$returnpos] = array('normal', ''); + array_push($stack, 'quote'); + continue 2; + break; + case 'comment' : + // comments go to the end of the line, so we are done + $return[++$returnpos] = array('comment', substr($text, $pos)); + return $return; + break; + case 'after_quote' : + array_push($stack, 'after_quote'); + break; + case 'escape' : + // don't save the first slash + array_push($stack, 'escape'); + continue 2; + break; + case 'normal' : + // start a new segment + if ($state == 'normal') { + $returnpos++; + continue 2; + } else { + while ($state != 'normal') { + array_pop($stack); + $state = $this->_getQACEvent($stack); + } + $returnpos++; + } + break; + default : + PEAR::raiseError("::_quoteAndCommaParser oops, state missing", null, PEAR_ERROR_DIE); + break; + } + } else { + if ($state != 'after_quote') { + if (!isset($return[$returnpos])) { + $return[$returnpos] = array('normal', ''); + } + // add this character to the current ini segment if non-empty, or if in a quote + if ($state == 'quote') { + $return[$returnpos][1] .= $char; + } elseif (!empty($return[$returnpos][1]) || + (empty($return[$returnpos][1]) && trim($char) != '')) { + if (!isset($return[$returnpos])) { + $return[$returnpos] = array('normal', ''); + } + $return[$returnpos][1] .= $char; + if (strcasecmp('true', $return[$returnpos][1]) == 0) { + $return[$returnpos][1] = '1'; + } elseif (strcasecmp('false', $return[$returnpos][1]) == 0) { + $return[$returnpos][1] = ''; + } + } + } else { + if (trim($char) != '') { + return PEAR::raiseError("invalid ini syntax, text after a quote not allowed '$text'", + null, PEAR_ERROR_RETURN); + } + } + } + } else { + // no tokens, so add this one and cycle to previous state + $return[$returnpos][1] .= $char; + array_pop($stack); + } + } while (++$pos < strlen($text)); + return $return; + } // end func _quoteAndCommaParser + + /** + * Retrieve the state off of a state stack for the Quote and Comma Parser + * @param array $stack The parser state stack + * @author Greg Beaver + * @access private + */ + function _getQACEvent($stack) + { + return array_pop($stack); + } // end func _getQACEvent + + /** + * Returns a formatted string of the object + * @param object $obj Container object to be output as string + * @access public + * @return string + */ + function toString(&$obj) + { + static $childrenCount, $commaString; + + if (!isset($string)) { + $string = ''; + } + switch ($obj->type) { + case 'blank': + $string = "\n"; + break; + case 'comment': + $string = ';'.$obj->content."\n"; + break; + case 'directive': + $count = $obj->parent->countChildren('directive', $obj->name); + $content = $obj->content; + if ($content === false) { + $content = '0'; + } elseif ($content === true) { + $content = '1'; + } elseif (strlen(trim($content)) < strlen($content) || + strpos($content, ',') !== false || + strpos($content, ';') !== false || + strpos($content, '=') !== false || + strpos($content, '"') !== false || + strpos($content, '%') !== false || + strpos($content, '~') !== false) { + $content = '"'.addslashes($content).'"'; + } + if ($count > 1) { + // multiple values for a directive are separated by a comma + if (isset($childrenCount[$obj->name])) { + $childrenCount[$obj->name]++; + } else { + $childrenCount[$obj->name] = 0; + $commaString[$obj->name] = $obj->name.' = '; + } + if ($childrenCount[$obj->name] == $count-1) { + // Clean the static for future calls to toString + $string .= $commaString[$obj->name].$content."\n"; + unset($childrenCount[$obj->name]); + unset($commaString[$obj->name]); + } else { + $commaString[$obj->name] .= $content.', '; + } + } else { + $string = $obj->name.' = '.$content."\n"; + } + break; + case 'section': + if (!$obj->isRoot()) { + $string = '['.$obj->name."]\n"; + } + if (count($obj->children) > 0) { + for ($i = 0; $i < count($obj->children); $i++) { + $string .= $this->toString($obj->getChild($i)); + } + } + break; + default: + $string = ''; + } + return $string; + } // end func toString +} // end class Config_Container_IniCommented +?> diff --git a/src/lib/pear/PEAR/Config/Container/IniFile.php b/src/lib/pear/PEAR/Config/Container/IniFile.php new file mode 100644 index 0000000..d32bd57 --- /dev/null +++ b/src/lib/pear/PEAR/Config/Container/IniFile.php @@ -0,0 +1,165 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: IniFile.php,v 1.17 2005/12/24 02:36:56 aashley Exp $ + +/** +* Config parser for PHP .ini files +* Faster because it uses parse_ini_file() but get rid of comments, +* quotes, types and converts On, Off, True, False, Yes, No to 0 and 1. +* +* @author Bertrand Mansion +* @package Config +*/ +class Config_Container_IniFile { + + /** + * This class options + * Not used at the moment + * + * @var array + */ + var $options = array(); + + /** + * Constructor + * + * @access public + * @param string $options (optional)Options to be used by renderer + */ + function Config_Container_IniFile($options = array()) + { + $this->options = $options; + } // end constructor + + /** + * Parses the data of the given configuration file + * + * @access public + * @param string $datasrc path to the configuration file + * @param object $obj reference to a config object + * @return mixed returns a PEAR_ERROR, if error occurs or true if ok + */ + function &parseDatasrc($datasrc, &$obj) + { + $return = true; + if (!file_exists($datasrc)) { + return PEAR::raiseError("Datasource file does not exist.", null, PEAR_ERROR_RETURN); + } + $currentSection =& $obj->container; + $confArray = parse_ini_file($datasrc, true); + if (!$confArray) { + return PEAR::raiseError("File '$datasrc' does not contain configuration data.", null, PEAR_ERROR_RETURN); + } + foreach ($confArray as $key => $value) { + if (is_array($value)) { + $currentSection =& $obj->container->createSection($key); + foreach ($value as $directive => $content) { + // try to split the value if comma found + if (strpos($content, '"') === false) { + $values = preg_split('/\s*,\s+/', $content); + if (count($values) > 1) { + foreach ($values as $k => $v) { + $currentSection->createDirective($directive, $v); + } + } else { + $currentSection->createDirective($directive, $content); + } + } else { + $currentSection->createDirective($directive, $content); + } + } + } else { + $currentSection->createDirective($key, $value); + } + } + return $return; + } // end func parseDatasrc + + /** + * Returns a formatted string of the object + * @param object $obj Container object to be output as string + * @access public + * @return string + */ + function toString(&$obj) + { + static $childrenCount, $commaString; + + if (!isset($string)) { + $string = ''; + } + switch ($obj->type) { + case 'blank': + $string = "\n"; + break; + case 'comment': + $string = ';'.$obj->content."\n"; + break; + case 'directive': + $count = $obj->parent->countChildren('directive', $obj->name); + $content = $obj->content; + if ($content === false) { + $content = '0'; + } elseif ($content === true) { + $content = '1'; + } elseif (strlen(trim($content)) < strlen($content) || + strpos($content, ',') !== false || + strpos($content, ';') !== false || + strpos($content, '=') !== false || + strpos($content, '"') !== false || + strpos($content, '%') !== false || + strpos($content, '~') !== false) { + $content = '"'.addslashes($content).'"'; + } + if ($count > 1) { + // multiple values for a directive are separated by a comma + if (isset($childrenCount[$obj->name])) { + $childrenCount[$obj->name]++; + } else { + $childrenCount[$obj->name] = 0; + $commaString[$obj->name] = $obj->name.'='; + } + if ($childrenCount[$obj->name] == $count-1) { + // Clean the static for future calls to toString + $string .= $commaString[$obj->name].$content."\n"; + unset($childrenCount[$obj->name]); + unset($commaString[$obj->name]); + } else { + $commaString[$obj->name] .= $content.', '; + } + } else { + $string = $obj->name.'='.$content."\n"; + } + break; + case 'section': + if (!$obj->isRoot()) { + $string = '['.$obj->name."]\n"; + } + if (count($obj->children) > 0) { + for ($i = 0; $i < count($obj->children); $i++) { + $string .= $this->toString($obj->getChild($i)); + } + } + break; + default: + $string = ''; + } + return $string; + } // end func toString +} // end class Config_Container_IniFile +?> diff --git a/src/lib/pear/PEAR/Config/Container/PHPArray.php b/src/lib/pear/PEAR/Config/Container/PHPArray.php new file mode 100644 index 0000000..68fa317 --- /dev/null +++ b/src/lib/pear/PEAR/Config/Container/PHPArray.php @@ -0,0 +1,251 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: PHPArray.php,v 1.32 2007/06/12 05:24:19 aashley Exp $ + +/** +* Config parser for common PHP configuration array +* such as found in the horde project. +* +* Options expected is: +* 'name' => 'conf' +* Name of the configuration array. +* Default is $conf[]. +* 'useAttr' => true +* Whether we render attributes +* +* @author Bertrand Mansion +* @package Config +*/ +class Config_Container_PHPArray { + + /** + * This class options: + * - name of the config array to parse/output + * Ex: $options['name'] = 'myconf'; + * - Whether to add attributes to the array + * Ex: $options['useAttr'] = false; + * - Whether to treat numbered arrays as duplicates of their parent directive + * or as individual directives + * Ex: $options['duplicateDirectives'] = false; + * + * @var array + */ + var $options = array('name' => 'conf', + 'useAttr' => true, + 'duplicateDirectives' => true); + + /** + * Constructor + * + * @access public + * @param string $options Options to be used by renderer + */ + function Config_Container_PHPArray($options = array()) + { + foreach ($options as $key => $value) { + $this->options[$key] = $value; + } + } // end constructor + + /** + * Parses the data of the given configuration file + * + * @access public + * @param string $datasrc path to the configuration file + * @param object $obj reference to a config object + * @return mixed returns a PEAR_ERROR, if error occurs or true if ok + */ + function &parseDatasrc($datasrc, &$obj) + { + $return = true; + if (empty($datasrc)) { + return PEAR::raiseError("Datasource file path is empty.", null, PEAR_ERROR_RETURN); + } + if (is_array($datasrc)) { + $this->_parseArray($datasrc, $obj->container); + } else { + if (!file_exists($datasrc)) { + return PEAR::raiseError("Datasource file does not exist.", null, PEAR_ERROR_RETURN); + } else { + include($datasrc); + if (!isset(${$this->options['name']}) || !is_array(${$this->options['name']})) { + return PEAR::raiseError("File '$datasrc' does not contain a required '".$this->options['name']."' array.", null, PEAR_ERROR_RETURN); + } + } + $this->_parseArray(${$this->options['name']}, $obj->container); + } + return $return; + } // end func parseDatasrc + + /** + * Parses the PHP array recursively + * @param array $array array values from the config file + * @param object $container reference to the container object + * @access private + * @return void + */ + function _parseArray($array, &$container) + { + foreach ($array as $key => $value) { + switch ((string)$key) { + case '@': + $container->setAttributes($value); + break; + case '#': + $container->setType('directive'); + $container->setContent($value); + break; + default: + if (is_array($value)) { + if ($this->options['duplicateDirectives'] == true && is_integer(key($value))) { + foreach ($value as $nestedValue) { + if (is_array($nestedValue)) { + $section =& $container->createSection($key); + $this->_parseArray($nestedValue, $section); + } else { + $container->createDirective($key, $nestedValue); + } + } + } else { + $section =& $container->createSection($key); + $this->_parseArray($value, $section); + } + } else { + $container->createDirective($key, $value); + } + } + } + } // end func _parseArray + + /** + * Returns a formatted string of the object + * @param object $obj Container object to be output as string + * @access public + * @return string + */ + function toString(&$obj) + { + if (!isset($string)) { + $string = ''; + } + switch ($obj->type) { + case 'blank': + $string .= "\n"; + break; + case 'comment': + $string .= '// '.$obj->content."\n"; + break; + case 'directive': + $attrString = ''; + $parentString = $this->_getParentString($obj); + $attributes = $obj->getAttributes(); + if ($this->options['useAttr'] && is_array($attributes) && count($attributes) > 0) { + // Directive with attributes '@' and value '#' + $string .= $parentString."['#']"; + foreach ($attributes as $attr => $val) { + $attrString .= $parentString."['@']" + ."['".$attr."'] = '".addcslashes($val, "\\'")."';\n"; + } + } else { + $string .= $parentString; + } + $string .= ' = '; + if (is_string($obj->content)) { + $string .= "'".addcslashes($obj->content, "\\'")."'"; + } elseif (is_int($obj->content) || is_float($obj->content)) { + $string .= $obj->content; + } elseif (is_bool($obj->content)) { + $string .= ($obj->content) ? 'true' : 'false'; + } + $string .= ";\n"; + $string .= $attrString; + break; + case 'section': + $attrString = ''; + $attributes = $obj->getAttributes(); + if ($this->options['useAttr'] && is_array($attributes) && count($attributes) > 0) { + $parentString = $this->_getParentString($obj); + foreach ($attributes as $attr => $val) { + $attrString .= $parentString."['@']" + ."['".$attr."'] = '".addcslashes($val, "\\'")."';\n"; + } + } + $string .= $attrString; + if ($count = count($obj->children)) { + for ($i = 0; $i < $count; $i++) { + $string .= $this->toString($obj->getChild($i)); + } + } + break; + default: + $string = ''; + } + return $string; + } // end func toString + + /** + * Returns a formatted string of the object parents + * @access private + * @return string + */ + function _getParentString(&$obj) + { + $string = ''; + if (!$obj->isRoot()) { + $string = is_int($obj->name) ? "[".$obj->name."]" : "['".$obj->name."']"; + $string = $this->_getParentString($obj->parent).$string; + $count = $obj->parent->countChildren(null, $obj->name); + if ($count > 1) { + $string .= '['.$obj->getItemPosition(false).']'; + } + } + else { + if (empty($this->options['name'])) { + $string .= '$'.$obj->name; + } else { + $string .= '$'.$this->options['name']; + } + } + return $string; + } // end func _getParentString + + /** + * Writes the configuration to a file + * + * @param mixed datasrc info on datasource such as path to the configuraton file + * @param string configType (optional)type of configuration + * @access public + * @return string + */ + function writeDatasrc($datasrc, &$obj) + { + $fp = @fopen($datasrc, 'w'); + if ($fp) { + $string = "toString($obj) ."?>"; // diff --git a/src/lib/pear/PEAR/Config/Container/PHPConstants.php b/src/lib/pear/PEAR/Config/Container/PHPConstants.php new file mode 100644 index 0000000..7d5b172 --- /dev/null +++ b/src/lib/pear/PEAR/Config/Container/PHPConstants.php @@ -0,0 +1,199 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: PHPConstants.php,v 1.3 2005/12/24 02:24:30 aashley Exp $ + +/** +* Config parser for PHP constant files +* +* @author Phillip Oertel +* @package Config +* @version 0.1 (not submitted) +*/ + +require_once 'Config/Container.php'; + +class Config_Container_PHPConstants extends Config_Container { + + /** + * This class options + * Not used at the moment + * + * @var array + */ + var $options = array(); + + /** + * Constructor + * + * @access public + * @param string $options (optional)Options to be used by renderer + */ + function Config_Container_PHPConstants($options = array()) + { + $this->options = $options; + } // end constructor + + /** + * Parses the data of the given configuration file + * + * @access public + * @param string $datasrc path to the configuration file + * @param object $obj reference to a config object + * @return mixed returns a PEAR_ERROR, if error occurs or true if ok + */ + function &parseDatasrc($datasrc, &$obj) + { + $return = true; + + if (!file_exists($datasrc)) { + return PEAR::raiseError("Datasource file does not exist.", null, + PEAR_ERROR_RETURN); + } + + $fileContent = file_get_contents($datasrc, true); + + if (!$fileContent) { + return PEAR::raiseError("File '$datasrc' could not be read.", null, + PEAR_ERROR_RETURN); + } + + $rows = explode("\n", $fileContent); + for ($i=0, $max=count($rows); $i<$max; $i++) { + $line = $rows[$i]; + + //blanks? + + // sections + if (preg_match("/^\/\/\s*$/", $line)) { + preg_match("/^\/\/\s*(.+)$/", $rows[$i+1], $matches); + $obj->container->createSection(trim($matches[1])); + $i += 2; + continue; + } + + // comments + if (preg_match("/^\/\/\s*(.+)$/", $line, $matches) || + preg_match("/^#\s*(.+)$/", $line, $matches)) { + $obj->container->createComment(trim($matches[1])); + continue; + } + + // directives + $regex = "/^\s*define\s*\('([A-Z1-9_]+)',\s*'*(.[^\']*)'*\)/"; + preg_match($regex, $line, $matches); + if (!empty($matches)) { + $obj->container->createDirective(trim($matches[1]), + trim($matches[2])); + } + } + + return $return; + + } // end func parseDatasrc + + /** + * Returns a formatted string of the object + * @param object $obj Container object to be output as string + * @access public + * @return string + */ + function toString(&$obj) + { + $string = ''; + + switch ($obj->type) + { + case 'blank': + $string = "\n"; + break; + + case 'comment': + $string = '// '.$obj->content."\n"; + break; + + case 'directive': + $content = $obj->content; + // don't quote numeric values, true/false and constants + if (!is_numeric($content) && !in_array($content, array('false', + 'true')) && !preg_match('/^[A-Z_]+$/', $content)) { + $content = "'".$content."'"; + } + $string = 'define(\''.$obj->name.'\', '.$content.');'.chr(10); + break; + + case 'section': + if (!$obj->isRoot()) { + $string = chr(10); + $string .= '//'.chr(10); + $string .= '// '.$obj->name.chr(10); + $string .= '//'.chr(10); + } + if (count($obj->children) > 0) { + for ($i = 0, $max = count($obj->children); $i < $max; $i++) { + $string .= $this->toString($obj->getChild($i)); + } + } + break; + default: + $string = ''; + } + return $string; + } // end func toString + + /** + * Writes the configuration to a file + * + * @param mixed datasrc info on datasource such as path to the file + * @param string configType (optional)type of configuration + * @access public + * @return string + */ + function writeDatasrc($datasrc, &$obj) + { + $fp = @fopen($datasrc, 'w'); + if ($fp) { + $string = "toString($obj); + $string .= "\n?>"; // diff --git a/src/lib/pear/PEAR/Config/Container/XML.php b/src/lib/pear/PEAR/Config/Container/XML.php new file mode 100644 index 0000000..7cb7636 --- /dev/null +++ b/src/lib/pear/PEAR/Config/Container/XML.php @@ -0,0 +1,249 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: XML.php,v 1.15 2005/12/24 02:24:30 aashley Exp $ + +require_once('XML/Parser.php'); +require_once('XML/Util.php'); + +/** +* Config parser for XML Files +* +* @author Bertrand Mansion +* @package Config +*/ +class Config_Container_XML extends XML_Parser +{ + /** + * Deep level used for indentation + * + * @var int + * @access private + */ + var $_deep = -1; + + /** + * This class options: + * version (1.0) : XML version + * encoding (ISO-8859-1) : XML content encoding + * name : like in phparray, name of your config global entity + * indent : char used for indentation + * linebreak : char used for linebreak + * addDecl : whether to add the xml declaration at beginning or not + * useAttr : whether to use the attributes + * isFile : whether the given content is a file or an XML string + * useCData : whether to surround data with + * + * @var array + */ + var $options = array('version' => '1.0', + 'encoding' => 'ISO-8859-1', + 'name' => '', + 'indent' => ' ', + 'linebreak' => "\n", + 'addDecl' => true, + 'useAttr' => true, + 'isFile' => true, + 'useCData' => false); + + /** + * Container objects + * + * @var array + */ + var $containers = array(); + + /** + * Constructor + * + * @access public + * @param string $options Options to be used by renderer + * version : (1.0) XML version + * encoding : (ISO-8859-1) XML content encoding + * name : like in phparray, name of your config global entity + * indent : char used for indentation + * linebreak : char used for linebreak + * addDecl : whether to add the xml declaration at beginning or not + * useAttr : whether to use the attributes + * isFile : whether the given content is a file or an XML string + */ + function Config_Container_XML($options = array()) + { + foreach ($options as $key => $value) { + $this->options[$key] = $value; + } + } // end constructor + + /** + * Parses the data of the given configuration file + * + * @access public + * @param string $datasrc path to the configuration file + * @param object $obj reference to a config object + * @return mixed returns a PEAR_ERROR, if error occurs or true if ok + */ + function &parseDatasrc($datasrc, &$obj) + { + $err = true; + $this->folding = false; + $this->cdata = null; + $this->XML_Parser($this->options['encoding'], 'event'); + $this->containers[0] =& $obj->container; + if (is_string($datasrc)) { + if ($this->options['isFile']) { + $err = $this->setInputFile($datasrc); + if (PEAR::isError($err)) { + return $err; + } + $err = $this->parse(); + } else { + $err = $this->parseString($datasrc, true); + } + } else { + $this->setInput($datasrc); + $err = $this->parse(); + } + return $err; + } // end func parseDatasrc + + /** + * Handler for the xml-data + * + * @param mixed $xp ignored + * @param string $elem name of the element + * @param array $attribs attributes for the generated node + * + * @access private + */ + function startHandler($xp, $elem, &$attribs) + { + $container =& new Config_Container('section', $elem, null, $attribs); + $this->containers[] =& $container; + return null; + } // end func startHandler + + /** + * Handler for the xml-data + * + * @param mixed $xp ignored + * @param string $elem name of the element + * + * @access private + */ + function endHandler($xp, $elem) + { + $count = count($this->containers); + $container =& $this->containers[$count-1]; + $currentSection =& $this->containers[$count-2]; + if (count($container->children) == 0) { + $container->setType('directive'); + $container->setContent(trim($this->cdata)); + } + $currentSection->addItem($container); + array_pop($this->containers); + $this->cdata = null; + return null; + } // end func endHandler + + /* + * The xml character data handler + * + * @param mixed $xp ignored + * @param string $data PCDATA between tags + * + * @access private + */ + function cdataHandler($xp, $cdata) + { + $this->cdata .= $cdata; + } // end func cdataHandler + + /** + * Returns a formatted string of the object + * @param object $obj Container object to be output as string + * @access public + * @return string + */ + function toString(&$obj) + { + $indent = ''; + if (!$obj->isRoot()) { + // no indent for root + $this->_deep++; + $indent = str_repeat($this->options['indent'], $this->_deep); + } else { + // Initialize string with xml declaration + $string = ''; + if ($this->options['addDecl']) { + $string .= XML_Util::getXMLDeclaration($this->options['version'], $this->options['encoding']); + $string .= $this->options['linebreak']; + } + if (!empty($this->options['name'])) { + $string .= '<'.$this->options['name'].'>'.$this->options['linebreak']; + $this->_deep++; + $indent = str_repeat($this->options['indent'], $this->_deep); + } + } + if (!isset($string)) { + $string = ''; + } + switch ($obj->type) { + case 'directive': + $attributes = ($this->options['useAttr']) ? $obj->attributes : array(); + $string .= $indent.XML_Util::createTag($obj->name, $attributes, $obj->content, null, + ($this->options['useCData'] ? XML_UTIL_CDATA_SECTION : XML_UTIL_REPLACE_ENTITIES)); + $string .= $this->options['linebreak']; + break; + case 'comment': + $string .= $indent.''; + $string .= $this->options['linebreak']; + break; + case 'section': + if (!$obj->isRoot()) { + $string = $indent.'<'.$obj->name; + $string .= ($this->options['useAttr']) ? XML_Util::attributesToString($obj->attributes) : ''; + } + if ($children = count($obj->children)) { + if (!$obj->isRoot()) { + $string .= '>'.$this->options['linebreak']; + } + for ($i = 0; $i < $children; $i++) { + $string .= $this->toString($obj->getChild($i)); + } + } + if (!$obj->isRoot()) { + if ($children) { + $string .= $indent.'name.'>'.$this->options['linebreak']; + } else { + $string .= '/>'.$this->options['linebreak']; + } + } else { + if (!empty($this->options['name'])) { + $string .= 'options['name'].'>'.$this->options['linebreak']; + } + } + break; + default: + $string = ''; + } + if (!$obj->isRoot()) { + $this->_deep--; + } + return $string; + } // end func toString +} // end class Config_Container_XML +?> diff --git a/src/lib/pear/PEAR/Console/Getopt.php b/src/lib/pear/PEAR/Console/Getopt.php new file mode 100644 index 0000000..bb9d69c --- /dev/null +++ b/src/lib/pear/PEAR/Console/Getopt.php @@ -0,0 +1,290 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: Getopt.php,v 1.4 2007/06/12 14:58:56 cellog Exp $ + +require_once 'PEAR.php'; + +/** + * Command-line options parsing class. + * + * @author Andrei Zmievski + * + */ +class Console_Getopt { + /** + * Parses the command-line options. + * + * The first parameter to this function should be the list of command-line + * arguments without the leading reference to the running program. + * + * The second parameter is a string of allowed short options. Each of the + * option letters can be followed by a colon ':' to specify that the option + * requires an argument, or a double colon '::' to specify that the option + * takes an optional argument. + * + * The third argument is an optional array of allowed long options. The + * leading '--' should not be included in the option name. Options that + * require an argument should be followed by '=', and options that take an + * option argument should be followed by '=='. + * + * The return value is an array of two elements: the list of parsed + * options and the list of non-option command-line arguments. Each entry in + * the list of parsed options is a pair of elements - the first one + * specifies the option, and the second one specifies the option argument, + * if there was one. + * + * Long and short options can be mixed. + * + * Most of the semantics of this function are based on GNU getopt_long(). + * + * @param array $args an array of command-line arguments + * @param string $short_options specifies the list of allowed short options + * @param array $long_options specifies the list of allowed long options + * + * @return array two-element array containing the list of parsed options and + * the non-option arguments + * + * @access public + * + */ + function getopt2($args, $short_options, $long_options = null) + { + return Console_Getopt::doGetopt(2, $args, $short_options, $long_options); + } + + /** + * This function expects $args to start with the script name (POSIX-style). + * Preserved for backwards compatibility. + * @see getopt2() + */ + function getopt($args, $short_options, $long_options = null) + { + return Console_Getopt::doGetopt(1, $args, $short_options, $long_options); + } + + /** + * The actual implementation of the argument parsing code. + */ + function doGetopt($version, $args, $short_options, $long_options = null) + { + // in case you pass directly readPHPArgv() as the first arg + if (PEAR::isError($args)) { + return $args; + } + if (empty($args)) { + return array(array(), array()); + } + $opts = array(); + $non_opts = array(); + + settype($args, 'array'); + + if ($long_options) { + sort($long_options); + } + + /* + * Preserve backwards compatibility with callers that relied on + * erroneous POSIX fix. + */ + if ($version < 2) { + if (isset($args[0]{0}) && $args[0]{0} != '-') { + array_shift($args); + } + } + + reset($args); + while (list($i, $arg) = each($args)) { + + /* The special element '--' means explicit end of + options. Treat the rest of the arguments as non-options + and end the loop. */ + if ($arg == '--') { + $non_opts = array_merge($non_opts, array_slice($args, $i + 1)); + break; + } + + if ($arg{0} != '-' || (strlen($arg) > 1 && $arg{1} == '-' && !$long_options)) { + $non_opts = array_merge($non_opts, array_slice($args, $i)); + break; + } elseif (strlen($arg) > 1 && $arg{1} == '-') { + $error = Console_Getopt::_parseLongOption(substr($arg, 2), $long_options, $opts, $args); + if (PEAR::isError($error)) + return $error; + } elseif ($arg == '-') { + // - is stdin + $non_opts = array_merge($non_opts, array_slice($args, $i)); + break; + } else { + $error = Console_Getopt::_parseShortOption(substr($arg, 1), $short_options, $opts, $args); + if (PEAR::isError($error)) + return $error; + } + } + + return array($opts, $non_opts); + } + + /** + * @access private + * + */ + function _parseShortOption($arg, $short_options, &$opts, &$args) + { + for ($i = 0; $i < strlen($arg); $i++) { + $opt = $arg{$i}; + $opt_arg = null; + + /* Try to find the short option in the specifier string. */ + if (($spec = strstr($short_options, $opt)) === false || $arg{$i} == ':') + { + return PEAR::raiseError("Console_Getopt: unrecognized option -- $opt"); + } + + if (strlen($spec) > 1 && $spec{1} == ':') { + if (strlen($spec) > 2 && $spec{2} == ':') { + if ($i + 1 < strlen($arg)) { + /* Option takes an optional argument. Use the remainder of + the arg string if there is anything left. */ + $opts[] = array($opt, substr($arg, $i + 1)); + break; + } + } else { + /* Option requires an argument. Use the remainder of the arg + string if there is anything left. */ + if ($i + 1 < strlen($arg)) { + $opts[] = array($opt, substr($arg, $i + 1)); + break; + } else if (list(, $opt_arg) = each($args)) { + /* Else use the next argument. */; + if (Console_Getopt::_isShortOpt($opt_arg) || Console_Getopt::_isLongOpt($opt_arg)) { + return PEAR::raiseError("Console_Getopt: option requires an argument -- $opt"); + } + } else { + return PEAR::raiseError("Console_Getopt: option requires an argument -- $opt"); + } + } + } + + $opts[] = array($opt, $opt_arg); + } + } + + /** + * @access private + * + */ + function _isShortOpt($arg) + { + return strlen($arg) == 2 && $arg[0] == '-' && preg_match('/[a-zA-Z]/', $arg[1]); + } + + /** + * @access private + * + */ + function _isLongOpt($arg) + { + return strlen($arg) > 2 && $arg[0] == '-' && $arg[1] == '-' && + preg_match('/[a-zA-Z]+$/', substr($arg, 2)); + } + + /** + * @access private + * + */ + function _parseLongOption($arg, $long_options, &$opts, &$args) + { + @list($opt, $opt_arg) = explode('=', $arg, 2); + $opt_len = strlen($opt); + + for ($i = 0; $i < count($long_options); $i++) { + $long_opt = $long_options[$i]; + $opt_start = substr($long_opt, 0, $opt_len); + $long_opt_name = str_replace('=', '', $long_opt); + + /* Option doesn't match. Go on to the next one. */ + if ($long_opt_name != $opt) { + continue; + } + + $opt_rest = substr($long_opt, $opt_len); + + /* Check that the options uniquely matches one of the allowed + options. */ + if ($i + 1 < count($long_options)) { + $next_option_rest = substr($long_options[$i + 1], $opt_len); + } else { + $next_option_rest = ''; + } + if ($opt_rest != '' && $opt{0} != '=' && + $i + 1 < count($long_options) && + $opt == substr($long_options[$i+1], 0, $opt_len) && + $next_option_rest != '' && + $next_option_rest{0} != '=') { + return PEAR::raiseError("Console_Getopt: option --$opt is ambiguous"); + } + + if (substr($long_opt, -1) == '=') { + if (substr($long_opt, -2) != '==') { + /* Long option requires an argument. + Take the next argument if one wasn't specified. */; + if (!strlen($opt_arg) && !(list(, $opt_arg) = each($args))) { + return PEAR::raiseError("Console_Getopt: option --$opt requires an argument"); + } + if (Console_Getopt::_isShortOpt($opt_arg) || Console_Getopt::_isLongOpt($opt_arg)) { + return PEAR::raiseError("Console_Getopt: option requires an argument --$opt"); + } + } + } else if ($opt_arg) { + return PEAR::raiseError("Console_Getopt: option --$opt doesn't allow an argument"); + } + + $opts[] = array('--' . $opt, $opt_arg); + return; + } + + return PEAR::raiseError("Console_Getopt: unrecognized option --$opt"); + } + + /** + * Safely read the $argv PHP array across different PHP configurations. + * Will take care on register_globals and register_argc_argv ini directives + * + * @access public + * @return mixed the $argv PHP array or PEAR error if not registered + */ + function readPHPArgv() + { + global $argv; + if (!is_array($argv)) { + if (!@is_array($_SERVER['argv'])) { + if (!@is_array($GLOBALS['HTTP_SERVER_VARS']['argv'])) { + return PEAR::raiseError("Console_Getopt: Could not read cmd args (register_argc_argv=Off?)"); + } + return $GLOBALS['HTTP_SERVER_VARS']['argv']; + } + return $_SERVER['argv']; + } + return $argv; + } + +} + +?> diff --git a/src/lib/pear/PEAR/FirePHPCore/FirePHP.class.php b/src/lib/pear/PEAR/FirePHPCore/FirePHP.class.php new file mode 100644 index 0000000..733d2b4 --- /dev/null +++ b/src/lib/pear/PEAR/FirePHPCore/FirePHP.class.php @@ -0,0 +1,1375 @@ + + * @license http://www.opensource.org/licenses/bsd-license.php + * @package FirePHP + */ + + +/** + * Sends the given data to the FirePHP Firefox Extension. + * The data can be displayed in the Firebug Console or in the + * "Server" request tab. + * + * For more information see: http://www.firephp.org/ + * + * @copyright Copyright (C) 2007-2008 Christoph Dorn + * @author Christoph Dorn + * @license http://www.opensource.org/licenses/bsd-license.php + * @package FirePHP + */ +class FirePHP { + + /** + * FirePHP version + * + * @var string + */ + const VERSION = '0.2.1'; + + /** + * Firebug LOG level + * + * Logs a message to firebug console. + * + * @var string + */ + const LOG = 'LOG'; + + /** + * Firebug INFO level + * + * Logs a message to firebug console and displays an info icon before the message. + * + * @var string + */ + const INFO = 'INFO'; + + /** + * Firebug WARN level + * + * Logs a message to firebug console, displays an warning icon before the message and colors the line turquoise. + * + * @var string + */ + const WARN = 'WARN'; + + /** + * Firebug ERROR level + * + * Logs a message to firebug console, displays an error icon before the message and colors the line yellow. Also increments the firebug error count. + * + * @var string + */ + const ERROR = 'ERROR'; + + /** + * Dumps a variable to firebug's server panel + * + * @var string + */ + const DUMP = 'DUMP'; + + /** + * Displays a stack trace in firebug console + * + * @var string + */ + const TRACE = 'TRACE'; + + /** + * Displays an exception in firebug console + * + * Increments the firebug error count. + * + * @var string + */ + const EXCEPTION = 'EXCEPTION'; + + /** + * Displays an table in firebug console + * + * @var string + */ + const TABLE = 'TABLE'; + + /** + * Starts a group in firebug console + * + * @var string + */ + const GROUP_START = 'GROUP_START'; + + /** + * Ends a group in firebug console + * + * @var string + */ + const GROUP_END = 'GROUP_END'; + + /** + * Singleton instance of FirePHP + * + * @var FirePHP + */ + protected static $instance = null; + + /** + * Wildfire protocol message index + * + * @var int + */ + protected $messageIndex = 1; + + /** + * Options for the library + * + * @var array + */ + protected $options = array(); + + /** + * Filters used to exclude object members when encoding + * + * @var array + */ + protected $objectFilters = array(); + + /** + * A stack of objects used to detect recursion during object encoding + * + * @var object + */ + protected $objectStack = array(); + + /** + * Flag to enable/disable logging + * + * @var boolean + */ + protected $enabled = true; + + /** + * The object constructor + */ + function __construct() { + $this->options['maxObjectDepth'] = 10; + $this->options['maxArrayDepth'] = 20; + $this->options['useNativeJsonEncode'] = true; + $this->options['includeLineNumbers'] = true; + } + + /** + * When the object gets serialized only include specific object members. + * + * @return array + */ + public function __sleep() { + return array('options','objectFilters','enabled'); + } + + /** + * Gets singleton instance of FirePHP + * + * @param boolean $AutoCreate + * @return FirePHP + */ + public static function getInstance($AutoCreate=false) { + if($AutoCreate===true && !self::$instance) { + self::init(); + } + return self::$instance; + } + + /** + * Creates FirePHP object and stores it for singleton access + * + * @return FirePHP + */ + public static function init() { + return self::$instance = new self(); + } + + /** + * Enable and disable logging to Firebug + * + * @param boolean $Enabled TRUE to enable, FALSE to disable + * @return void + */ + public function setEnabled($Enabled) { + $this->enabled = $Enabled; + } + + /** + * Check if logging is enabled + * + * @return boolean TRUE if enabled + */ + public function getEnabled() { + return $this->enabled; + } + + /** + * Specify a filter to be used when encoding an object + * + * Filters are used to exclude object members. + * + * @param string $Class The class name of the object + * @param array $Filter An array or members to exclude + * @return void + */ + public function setObjectFilter($Class, $Filter) { + $this->objectFilters[$Class] = $Filter; + } + + /** + * Set some options for the library + * + * Options: + * - maxObjectDepth: The maximum depth to traverse objects (default: 10) + * - maxArrayDepth: The maximum depth to traverse arrays (default: 20) + * - useNativeJsonEncode: If true will use json_encode() (default: true) + * - includeLineNumbers: If true will include line numbers and filenames (default: true) + * + * @param array $Options The options to be set + * @return void + */ + public function setOptions($Options) { + $this->options = array_merge($this->options,$Options); + } + + /** + * Register FirePHP as your error handler + * + * Will throw exceptions for each php error. + */ + public function registerErrorHandler() + { + //NOTE: The following errors will not be caught by this error handler: + // E_ERROR, E_PARSE, E_CORE_ERROR, + // E_CORE_WARNING, E_COMPILE_ERROR, + // E_COMPILE_WARNING, E_STRICT + + set_error_handler(array($this,'errorHandler')); + } + + /** + * FirePHP's error handler + * + * Throws exception for each php error that will occur. + * + * @param int $errno + * @param string $errstr + * @param string $errfile + * @param int $errline + * @param array $errcontext + */ + public function errorHandler($errno, $errstr, $errfile, $errline, $errcontext) + { + // Don't throw exception if error reporting is switched off + if (error_reporting() == 0) { + return; + } + // Only throw exceptions for errors we are asking for + if (error_reporting() & $errno) { + throw new ErrorException($errstr, 0, $errno, $errfile, $errline); + } + } + + /** + * Register FirePHP as your exception handler + */ + public function registerExceptionHandler() + { + set_exception_handler(array($this,'exceptionHandler')); + } + + /** + * FirePHP's exception handler + * + * Logs all exceptions to your firebug console and then stops the script. + * + * @param Exception $Exception + * @throws Exception + */ + function exceptionHandler($Exception) { + $this->fb($Exception); + } + + /** + * Set custom processor url for FirePHP + * + * @param string $URL + */ + public function setProcessorUrl($URL) + { + $this->setHeader('X-FirePHP-ProcessorURL', $URL); + } + + /** + * Set custom renderer url for FirePHP + * + * @param string $URL + */ + public function setRendererUrl($URL) + { + $this->setHeader('X-FirePHP-RendererURL', $URL); + } + + /** + * Start a group for following messages + * + * @param string $Name + * @return true + * @throws Exception + */ + public function group($Name) { + return $this->fb(null, $Name, FirePHP::GROUP_START); + } + + /** + * Ends a group you have started before + * + * @return true + * @throws Exception + */ + public function groupEnd() { + return $this->fb(null, null, FirePHP::GROUP_END); + } + + /** + * Log object with label to firebug console + * + * @see FirePHP::LOG + * @param mixes $Object + * @param string $Label + * @return true + * @throws Exception + */ + public function log($Object, $Label=null) { + return $this->fb($Object, $Label, FirePHP::LOG); + } + + /** + * Log object with label to firebug console + * + * @see FirePHP::INFO + * @param mixes $Object + * @param string $Label + * @return true + * @throws Exception + */ + public function info($Object, $Label=null) { + return $this->fb($Object, $Label, FirePHP::INFO); + } + + /** + * Log object with label to firebug console + * + * @see FirePHP::WARN + * @param mixes $Object + * @param string $Label + * @return true + * @throws Exception + */ + public function warn($Object, $Label=null) { + return $this->fb($Object, $Label, FirePHP::WARN); + } + + /** + * Log object with label to firebug console + * + * @see FirePHP::ERROR + * @param mixes $Object + * @param string $Label + * @return true + * @throws Exception + */ + public function error($Object, $Label=null) { + return $this->fb($Object, $Label, FirePHP::ERROR); + } + + /** + * Dumps key and variable to firebug server panel + * + * @see FirePHP::DUMP + * @param string $Key + * @param mixed $Variable + * @return true + * @throws Exception + */ + public function dump($Key, $Variable) { + return $this->fb($Variable, $Key, FirePHP::DUMP); + } + + /** + * Log a trace in the firebug console + * + * @see FirePHP::TRACE + * @param string $Label + * @return true + * @throws Exception + */ + public function trace($Label) { + return $this->fb($Label, FirePHP::TRACE); + } + + /** + * Log a table in the firebug console + * + * @see FirePHP::TABLE + * @param string $Label + * @param string $Table + * @return true + * @throws Exception + */ + public function table($Label, $Table) { + return $this->fb($Table, $Label, FirePHP::TABLE); + } + + /** + * Check if FirePHP is installed on client + * + * @return boolean + */ + public function detectClientExtension() { + /* Check if FirePHP is installed on client */ + if(!@preg_match_all('/\sFirePHP\/([\.|\d]*)\s?/si',$this->getUserAgent(),$m) || + !version_compare($m[1][0],'0.0.6','>=')) { + return false; + } + return true; + } + + /** + * Log varible to Firebug + * + * @see http://www.firephp.org/Wiki/Reference/Fb + * @param mixed $Object The variable to be logged + * @return true Return TRUE if message was added to headers, FALSE otherwise + * @throws Exception + */ + public function fb($Object) { + + if(!$this->enabled) { + return false; + } + + if (headers_sent($filename, $linenum)) { + throw $this->newException('Headers already sent in '.$filename.' on line '.$linenum.'. Cannot send log data to FirePHP. You must have Output Buffering enabled via ob_start() or output_buffering ini directive.'); + } + + $Type = null; + $Label = null; + + if(func_num_args()==1) { + } else + if(func_num_args()==2) { + switch(func_get_arg(1)) { + case self::LOG: + case self::INFO: + case self::WARN: + case self::ERROR: + case self::DUMP: + case self::TRACE: + case self::EXCEPTION: + case self::TABLE: + case self::GROUP_START: + case self::GROUP_END: + $Type = func_get_arg(1); + break; + default: + $Label = func_get_arg(1); + break; + } + } else + if(func_num_args()==3) { + $Type = func_get_arg(2); + $Label = func_get_arg(1); + } else { + throw $this->newException('Wrong number of arguments to fb() function!'); + } + + + if(!$this->detectClientExtension()) { + return false; + } + + $meta = array(); + $skipFinalObjectEncode = false; + + if($Object instanceof Exception) { + + $meta['file'] = $this->_escapeTraceFile($Object->getFile()); + $meta['line'] = $Object->getLine(); + + $trace = $Object->getTrace(); + if($Object instanceof ErrorException + && isset($trace[0]['function']) + && $trace[0]['function']=='errorHandler' + && isset($trace[0]['class']) + && $trace[0]['class']=='FirePHP') { + + $severity = false; + switch($Object->getSeverity()) { + case E_WARNING: $severity = 'E_WARNING'; break; + case E_NOTICE: $severity = 'E_NOTICE'; break; + case E_USER_ERROR: $severity = 'E_USER_ERROR'; break; + case E_USER_WARNING: $severity = 'E_USER_WARNING'; break; + case E_USER_NOTICE: $severity = 'E_USER_NOTICE'; break; + case E_STRICT: $severity = 'E_STRICT'; break; + case E_RECOVERABLE_ERROR: $severity = 'E_RECOVERABLE_ERROR'; break; + case E_DEPRECATED: $severity = 'E_DEPRECATED'; break; + case E_USER_DEPRECATED: $severity = 'E_USER_DEPRECATED'; break; + } + + $Object = array('Class'=>get_class($Object), + 'Message'=>$severity.': '.$Object->getMessage(), + 'File'=>$this->_escapeTraceFile($Object->getFile()), + 'Line'=>$Object->getLine(), + 'Type'=>'trigger', + 'Trace'=>$this->_escapeTrace(array_splice($trace,2))); + $skipFinalObjectEncode = true; + } else { + $Object = array('Class'=>get_class($Object), + 'Message'=>$Object->getMessage(), + 'File'=>$this->_escapeTraceFile($Object->getFile()), + 'Line'=>$Object->getLine(), + 'Type'=>'throw', + 'Trace'=>$this->_escapeTrace($trace)); + $skipFinalObjectEncode = true; + } + $Type = self::EXCEPTION; + + } else + if($Type==self::TRACE) { + + $trace = debug_backtrace(); + if(!$trace) return false; + for( $i=0 ; $i_standardizePath($trace[$i]['file']),-18,18)=='FirePHPCore/fb.php' + || substr($this->_standardizePath($trace[$i]['file']),-29,29)=='FirePHPCore/FirePHP.class.php')) { + /* Skip - FB::trace(), FB::send(), $firephp->trace(), $firephp->fb() */ + } else + if(isset($trace[$i]['class']) + && isset($trace[$i+1]['file']) + && $trace[$i]['class']=='FirePHP' + && substr($this->_standardizePath($trace[$i+1]['file']),-18,18)=='FirePHPCore/fb.php') { + /* Skip fb() */ + } else + if($trace[$i]['function']=='fb' + || $trace[$i]['function']=='trace' + || $trace[$i]['function']=='send') { + $Object = array('Class'=>isset($trace[$i]['class'])?$trace[$i]['class']:'', + 'Type'=>isset($trace[$i]['type'])?$trace[$i]['type']:'', + 'Function'=>isset($trace[$i]['function'])?$trace[$i]['function']:'', + 'Message'=>$trace[$i]['args'][0], + 'File'=>isset($trace[$i]['file'])?$this->_escapeTraceFile($trace[$i]['file']):'', + 'Line'=>isset($trace[$i]['line'])?$trace[$i]['line']:'', + 'Args'=>isset($trace[$i]['args'])?$this->encodeObject($trace[$i]['args']):'', + 'Trace'=>$this->_escapeTrace(array_splice($trace,$i+1))); + + $skipFinalObjectEncode = true; + $meta['file'] = isset($trace[$i]['file'])?$this->_escapeTraceFile($trace[$i]['file']):''; + $meta['line'] = isset($trace[$i]['line'])?$trace[$i]['line']:''; + break; + } + } + + } else + if($Type==self::TABLE) { + + if(isset($Object[0]) && is_string($Object[0])) { + $Object[1] = $this->encodeTable($Object[1]); + } else { + $Object = $this->encodeTable($Object); + } + + $skipFinalObjectEncode = true; + + } else { + if($Type===null) { + $Type = self::LOG; + } + } + + if($this->options['includeLineNumbers']) { + if(!isset($meta['file']) || !isset($meta['line'])) { + + $trace = debug_backtrace(); + for( $i=0 ; $trace && $i_standardizePath($trace[$i]['file']),-18,18)=='FirePHPCore/fb.php' + || substr($this->_standardizePath($trace[$i]['file']),-29,29)=='FirePHPCore/FirePHP.class.php')) { + /* Skip - FB::trace(), FB::send(), $firephp->trace(), $firephp->fb() */ + } else + if(isset($trace[$i]['class']) + && isset($trace[$i+1]['file']) + && $trace[$i]['class']=='FirePHP' + && substr($this->_standardizePath($trace[$i+1]['file']),-18,18)=='FirePHPCore/fb.php') { + /* Skip fb() */ + } else + if(isset($trace[$i]['file']) + && substr($this->_standardizePath($trace[$i]['file']),-18,18)=='FirePHPCore/fb.php') { + /* Skip FB::fb() */ + } else { + $meta['file'] = isset($trace[$i]['file'])?$this->_escapeTraceFile($trace[$i]['file']):''; + $meta['line'] = isset($trace[$i]['line'])?$trace[$i]['line']:''; + break; + } + } + + } + } else { + unset($meta['file']); + unset($meta['line']); + } + + $this->setHeader('X-Wf-Protocol-1','http://meta.wildfirehq.org/Protocol/JsonStream/0.2'); + $this->setHeader('X-Wf-1-Plugin-1','http://meta.firephp.org/Wildfire/Plugin/FirePHP/Library-FirePHPCore/'.self::VERSION); + + $structure_index = 1; + if($Type==self::DUMP) { + $structure_index = 2; + $this->setHeader('X-Wf-1-Structure-2','http://meta.firephp.org/Wildfire/Structure/FirePHP/Dump/0.1'); + } else { + $this->setHeader('X-Wf-1-Structure-1','http://meta.firephp.org/Wildfire/Structure/FirePHP/FirebugConsole/0.1'); + } + + if($Type==self::DUMP) { + $msg = '{"'.$Label.'":'.$this->jsonEncode($Object, $skipFinalObjectEncode).'}'; + } else { + $msg_meta = array('Type'=>$Type); + if($Label!==null) { + $msg_meta['Label'] = $Label; + } + if(isset($meta['file'])) { + $msg_meta['File'] = $meta['file']; + } + if(isset($meta['line'])) { + $msg_meta['Line'] = $meta['line']; + } + $msg = '['.$this->jsonEncode($msg_meta).','.$this->jsonEncode($Object, $skipFinalObjectEncode).']'; + } + + $parts = explode("\n",chunk_split($msg, 5000, "\n")); + + for( $i=0 ; $i2) { + // Message needs to be split into multiple parts + $this->setHeader('X-Wf-1-'.$structure_index.'-'.'1-'.$this->messageIndex, + (($i==0)?strlen($msg):'') + . '|' . $part . '|' + . (($isetHeader('X-Wf-1-'.$structure_index.'-'.'1-'.$this->messageIndex, + strlen($part) . '|' . $part . '|'); + } + + $this->messageIndex++; + + if ($this->messageIndex > 99999) { + throw new Exception('Maximum number (99,999) of messages reached!'); + } + } + } + + $this->setHeader('X-Wf-1-Index',$this->messageIndex-1); + + return true; + } + + /** + * Standardizes path for windows systems. + * + * @param string $Path + * @return string + */ + protected function _standardizePath($Path) { + return preg_replace('/\\\\+/','/',$Path); + } + + /** + * Escape trace path for windows systems + * + * @param array $Trace + * @return array + */ + protected function _escapeTrace($Trace) { + if(!$Trace) return $Trace; + for( $i=0 ; $i_escapeTraceFile($Trace[$i]['file']); + } + if(isset($Trace[$i]['args'])) { + $Trace[$i]['args'] = $this->encodeObject($Trace[$i]['args']); + } + } + return $Trace; + } + + /** + * Escape file information of trace for windows systems + * + * @param string $File + * @return string + */ + protected function _escapeTraceFile($File) { + /* Check if we have a windows filepath */ + if(strpos($File,'\\')) { + /* First strip down to single \ */ + + $file = preg_replace('/\\\\+/','\\',$File); + + return $file; + } + return $File; + } + + /** + * Send header + * + * @param string $Name + * @param string_type $Value + */ + protected function setHeader($Name, $Value) { + return header($Name.': '.$Value); + } + + /** + * Get user agent + * + * @return string|false + */ + protected function getUserAgent() { + if(!isset($_SERVER['HTTP_USER_AGENT'])) return false; + return $_SERVER['HTTP_USER_AGENT']; + } + + /** + * Returns a new exception + * + * @param string $Message + * @return Exception + */ + protected function newException($Message) { + return new Exception($Message); + } + + /** + * Encode an object into a JSON string + * + * Uses PHP's jeson_encode() if available + * + * @param object $Object The object to be encoded + * @return string The JSON string + */ + public function jsonEncode($Object, $skipObjectEncode=false) + { + if(!$skipObjectEncode) { + $Object = $this->encodeObject($Object); + } + + if(function_exists('json_encode') + && $this->options['useNativeJsonEncode']!=false) { + + return json_encode($Object); + } else { + return $this->json_encode($Object); + } + } + + /** + * Encodes a table by encoding each row and column with encodeObject() + * + * @param array $Table The table to be encoded + * @return array + */ + protected function encodeTable($Table) { + if(!$Table) return $Table; + for( $i=0 ; $iencodeObject($Table[$i][$j]); + } + } + } + return $Table; + } + + /** + * Encodes an object including members with + * protected and private visibility + * + * @param Object $Object The object to be encoded + * @param int $Depth The current traversal depth + * @return array All members of the object + */ + protected function encodeObject($Object, $ObjectDepth = 1, $ArrayDepth = 1) + { + $return = array(); + + if (is_resource($Object)) { + + return '** '.(string)$Object.' **'; + + } else + if (is_object($Object)) { + + if ($ObjectDepth > $this->options['maxObjectDepth']) { + return '** Max Object Depth ('.$this->options['maxObjectDepth'].') **'; + } + + foreach ($this->objectStack as $refVal) { + if ($refVal === $Object) { + return '** Recursion ('.get_class($Object).') **'; + } + } + array_push($this->objectStack, $Object); + + $return['__className'] = $class = get_class($Object); + + $reflectionClass = new ReflectionClass($class); + $properties = array(); + foreach( $reflectionClass->getProperties() as $property) { + $properties[$property->getName()] = $property; + } + + $members = (array)$Object; + + foreach( $properties as $raw_name => $property ) { + + $name = $raw_name; + if($property->isStatic()) { + $name = 'static:'.$name; + } + if($property->isPublic()) { + $name = 'public:'.$name; + } else + if($property->isPrivate()) { + $name = 'private:'.$name; + $raw_name = "\0".$class."\0".$raw_name; + } else + if($property->isProtected()) { + $name = 'protected:'.$name; + $raw_name = "\0".'*'."\0".$raw_name; + } + + if(!(isset($this->objectFilters[$class]) + && is_array($this->objectFilters[$class]) + && in_array($raw_name,$this->objectFilters[$class]))) { + + if(array_key_exists($raw_name,$members) + && !$property->isStatic()) { + + $return[$name] = $this->encodeObject($members[$raw_name], $ObjectDepth + 1, 1); + + } else { + if(method_exists($property,'setAccessible')) { + $property->setAccessible(true); + $return[$name] = $this->encodeObject($property->getValue($Object), $ObjectDepth + 1, 1); + } else + if($property->isPublic()) { + $return[$name] = $this->encodeObject($property->getValue($Object), $ObjectDepth + 1, 1); + } else { + $return[$name] = '** Need PHP 5.3 to get value **'; + } + } + } else { + $return[$name] = '** Excluded by Filter **'; + } + } + + // Include all members that are not defined in the class + // but exist in the object + foreach( $members as $raw_name => $value ) { + + $name = $raw_name; + + if ($name{0} == "\0") { + $parts = explode("\0", $name); + $name = $parts[2]; + } + + if(!isset($properties[$name])) { + $name = 'undeclared:'.$name; + + if(!(isset($this->objectFilters[$class]) + && is_array($this->objectFilters[$class]) + && in_array($raw_name,$this->objectFilters[$class]))) { + + $return[$name] = $this->encodeObject($value, $ObjectDepth + 1, 1); + } else { + $return[$name] = '** Excluded by Filter **'; + } + } + } + + array_pop($this->objectStack); + + } elseif (is_array($Object)) { + + if ($ArrayDepth > $this->options['maxArrayDepth']) { + return '** Max Array Depth ('.$this->options['maxArrayDepth'].') **'; + } + + foreach ($Object as $key => $val) { + + // Encoding the $GLOBALS PHP array causes an infinite loop + // if the recursion is not reset here as it contains + // a reference to itself. This is the only way I have come up + // with to stop infinite recursion in this case. + if($key=='GLOBALS' + && is_array($val) + && array_key_exists('GLOBALS',$val)) { + $val['GLOBALS'] = '** Recursion (GLOBALS) **'; + } + + $return[$key] = $this->encodeObject($val, 1, $ArrayDepth + 1); + } + } else { + if(self::is_utf8($Object)) { + return $Object; + } else { + return utf8_encode($Object); + } + } + return $return; + } + + /** + * Returns true if $string is valid UTF-8 and false otherwise. + * + * @param mixed $str String to be tested + * @return boolean + */ + protected static function is_utf8($str) { + $c=0; $b=0; + $bits=0; + $len=strlen($str); + for($i=0; $i<$len; $i++){ + $c=ord($str[$i]); + if($c > 128){ + if(($c >= 254)) return false; + elseif($c >= 252) $bits=6; + elseif($c >= 248) $bits=5; + elseif($c >= 240) $bits=4; + elseif($c >= 224) $bits=3; + elseif($c >= 192) $bits=2; + else return false; + if(($i+$bits) > $len) return false; + while($bits > 1){ + $i++; + $b=ord($str[$i]); + if($b < 128 || $b > 191) return false; + $bits--; + } + } + } + return true; + } + + /** + * Converts to and from JSON format. + * + * JSON (JavaScript Object Notation) is a lightweight data-interchange + * format. It is easy for humans to read and write. It is easy for machines + * to parse and generate. It is based on a subset of the JavaScript + * Programming Language, Standard ECMA-262 3rd Edition - December 1999. + * This feature can also be found in Python. JSON is a text format that is + * completely language independent but uses conventions that are familiar + * to programmers of the C-family of languages, including C, C++, C#, Java, + * JavaScript, Perl, TCL, and many others. These properties make JSON an + * ideal data-interchange language. + * + * This package provides a simple encoder and decoder for JSON notation. It + * is intended for use with client-side Javascript applications that make + * use of HTTPRequest to perform server communication functions - data can + * be encoded into JSON notation for use in a client-side javascript, or + * decoded from incoming Javascript requests. JSON format is native to + * Javascript, and can be directly eval()'ed with no further parsing + * overhead + * + * All strings should be in ASCII or UTF-8 format! + * + * LICENSE: Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: Redistributions of source code must retain the + * above copyright notice, this list of conditions and the following + * disclaimer. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * @category + * @package Services_JSON + * @author Michal Migurski + * @author Matt Knapp + * @author Brett Stimmerman + * @author Christoph Dorn + * @copyright 2005 Michal Migurski + * @version CVS: $Id: JSON.php,v 1.31 2006/06/28 05:54:17 migurski Exp $ + * @license http://www.opensource.org/licenses/bsd-license.php + * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=198 + */ + + + /** + * Keep a list of objects as we descend into the array so we can detect recursion. + */ + private $json_objectStack = array(); + + + /** + * convert a string from one UTF-8 char to one UTF-16 char + * + * Normally should be handled by mb_convert_encoding, but + * provides a slower PHP-only method for installations + * that lack the multibye string extension. + * + * @param string $utf8 UTF-8 character + * @return string UTF-16 character + * @access private + */ + private function json_utf82utf16($utf8) + { + // oh please oh please oh please oh please oh please + if(function_exists('mb_convert_encoding')) { + return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8'); + } + + switch(strlen($utf8)) { + case 1: + // this case should never be reached, because we are in ASCII range + // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + return $utf8; + + case 2: + // return a UTF-16 character from a 2-byte UTF-8 char + // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + return chr(0x07 & (ord($utf8{0}) >> 2)) + . chr((0xC0 & (ord($utf8{0}) << 6)) + | (0x3F & ord($utf8{1}))); + + case 3: + // return a UTF-16 character from a 3-byte UTF-8 char + // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + return chr((0xF0 & (ord($utf8{0}) << 4)) + | (0x0F & (ord($utf8{1}) >> 2))) + . chr((0xC0 & (ord($utf8{1}) << 6)) + | (0x7F & ord($utf8{2}))); + } + + // ignoring UTF-32 for now, sorry + return ''; + } + + /** + * encodes an arbitrary variable into JSON format + * + * @param mixed $var any number, boolean, string, array, or object to be encoded. + * see argument 1 to Services_JSON() above for array-parsing behavior. + * if var is a strng, note that encode() always expects it + * to be in ASCII or UTF-8 format! + * + * @return mixed JSON string representation of input var or an error if a problem occurs + * @access public + */ + private function json_encode($var) + { + + if(is_object($var)) { + if(in_array($var,$this->json_objectStack)) { + return '"** Recursion **"'; + } + } + + switch (gettype($var)) { + case 'boolean': + return $var ? 'true' : 'false'; + + case 'NULL': + return 'null'; + + case 'integer': + return (int) $var; + + case 'double': + case 'float': + return (float) $var; + + case 'string': + // STRINGS ARE EXPECTED TO BE IN ASCII OR UTF-8 FORMAT + $ascii = ''; + $strlen_var = strlen($var); + + /* + * Iterate over every character in the string, + * escaping with a slash or encoding to UTF-8 where necessary + */ + for ($c = 0; $c < $strlen_var; ++$c) { + + $ord_var_c = ord($var{$c}); + + switch (true) { + case $ord_var_c == 0x08: + $ascii .= '\b'; + break; + case $ord_var_c == 0x09: + $ascii .= '\t'; + break; + case $ord_var_c == 0x0A: + $ascii .= '\n'; + break; + case $ord_var_c == 0x0C: + $ascii .= '\f'; + break; + case $ord_var_c == 0x0D: + $ascii .= '\r'; + break; + + case $ord_var_c == 0x22: + case $ord_var_c == 0x2F: + case $ord_var_c == 0x5C: + // double quote, slash, slosh + $ascii .= '\\'.$var{$c}; + break; + + case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)): + // characters U-00000000 - U-0000007F (same as ASCII) + $ascii .= $var{$c}; + break; + + case (($ord_var_c & 0xE0) == 0xC0): + // characters U-00000080 - U-000007FF, mask 110XXXXX + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $char = pack('C*', $ord_var_c, ord($var{$c + 1})); + $c += 1; + $utf16 = $this->json_utf82utf16($char); + $ascii .= sprintf('\u%04s', bin2hex($utf16)); + break; + + case (($ord_var_c & 0xF0) == 0xE0): + // characters U-00000800 - U-0000FFFF, mask 1110XXXX + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $char = pack('C*', $ord_var_c, + ord($var{$c + 1}), + ord($var{$c + 2})); + $c += 2; + $utf16 = $this->json_utf82utf16($char); + $ascii .= sprintf('\u%04s', bin2hex($utf16)); + break; + + case (($ord_var_c & 0xF8) == 0xF0): + // characters U-00010000 - U-001FFFFF, mask 11110XXX + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $char = pack('C*', $ord_var_c, + ord($var{$c + 1}), + ord($var{$c + 2}), + ord($var{$c + 3})); + $c += 3; + $utf16 = $this->json_utf82utf16($char); + $ascii .= sprintf('\u%04s', bin2hex($utf16)); + break; + + case (($ord_var_c & 0xFC) == 0xF8): + // characters U-00200000 - U-03FFFFFF, mask 111110XX + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $char = pack('C*', $ord_var_c, + ord($var{$c + 1}), + ord($var{$c + 2}), + ord($var{$c + 3}), + ord($var{$c + 4})); + $c += 4; + $utf16 = $this->json_utf82utf16($char); + $ascii .= sprintf('\u%04s', bin2hex($utf16)); + break; + + case (($ord_var_c & 0xFE) == 0xFC): + // characters U-04000000 - U-7FFFFFFF, mask 1111110X + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $char = pack('C*', $ord_var_c, + ord($var{$c + 1}), + ord($var{$c + 2}), + ord($var{$c + 3}), + ord($var{$c + 4}), + ord($var{$c + 5})); + $c += 5; + $utf16 = $this->json_utf82utf16($char); + $ascii .= sprintf('\u%04s', bin2hex($utf16)); + break; + } + } + + return '"'.$ascii.'"'; + + case 'array': + /* + * As per JSON spec if any array key is not an integer + * we must treat the the whole array as an object. We + * also try to catch a sparsely populated associative + * array with numeric keys here because some JS engines + * will create an array with empty indexes up to + * max_index which can cause memory issues and because + * the keys, which may be relevant, will be remapped + * otherwise. + * + * As per the ECMA and JSON specification an object may + * have any string as a property. Unfortunately due to + * a hole in the ECMA specification if the key is a + * ECMA reserved word or starts with a digit the + * parameter is only accessible using ECMAScript's + * bracket notation. + */ + + // treat as a JSON object + if (is_array($var) && count($var) && (array_keys($var) !== range(0, sizeof($var) - 1))) { + + $this->json_objectStack[] = $var; + + $properties = array_map(array($this, 'json_name_value'), + array_keys($var), + array_values($var)); + + array_pop($this->json_objectStack); + + foreach($properties as $property) { + if($property instanceof Exception) { + return $property; + } + } + + return '{' . join(',', $properties) . '}'; + } + + $this->json_objectStack[] = $var; + + // treat it like a regular array + $elements = array_map(array($this, 'json_encode'), $var); + + array_pop($this->json_objectStack); + + foreach($elements as $element) { + if($element instanceof Exception) { + return $element; + } + } + + return '[' . join(',', $elements) . ']'; + + case 'object': + $vars = self::encodeObject($var); + + $this->json_objectStack[] = $var; + + $properties = array_map(array($this, 'json_name_value'), + array_keys($vars), + array_values($vars)); + + array_pop($this->json_objectStack); + + foreach($properties as $property) { + if($property instanceof Exception) { + return $property; + } + } + + return '{' . join(',', $properties) . '}'; + + default: + return null; + } + } + + /** + * array-walking function for use in generating JSON-formatted name-value pairs + * + * @param string $name name of key to use + * @param mixed $value reference to an array element to be encoded + * + * @return string JSON-formatted name-value pair, like '"name":value' + * @access private + */ + private function json_name_value($name, $value) + { + // Encoding the $GLOBALS PHP array causes an infinite loop + // if the recursion is not reset here as it contains + // a reference to itself. This is the only way I have come up + // with to stop infinite recursion in this case. + if($name=='GLOBALS' + && is_array($value) + && array_key_exists('GLOBALS',$value)) { + $value['GLOBALS'] = '** Recursion **'; + } + + $encoded_value = $this->json_encode($value); + + if($encoded_value instanceof Exception) { + return $encoded_value; + } + + return $this->json_encode(strval($name)) . ':' . $encoded_value; + } +} diff --git a/src/lib/pear/PEAR/FirePHPCore/fb.php b/src/lib/pear/PEAR/FirePHPCore/fb.php new file mode 100644 index 0000000..96d9719 --- /dev/null +++ b/src/lib/pear/PEAR/FirePHPCore/fb.php @@ -0,0 +1,246 @@ + + * @license http://www.opensource.org/licenses/bsd-license.php + * @package FirePHP + */ + +require_once dirname(__FILE__).'/FirePHP.class.php'; + +/** + * Sends the given data to the FirePHP Firefox Extension. + * The data can be displayed in the Firebug Console or in the + * "Server" request tab. + * + * @see http://www.firephp.org/Wiki/Reference/Fb + * @param mixed $Object + * @return true + * @throws Exception + */ +function fb() +{ + $instance = FirePHP::getInstance(true); + + $args = func_get_args(); + return call_user_func_array(array($instance,'fb'),$args); +} + + +class FB +{ + /** + * Enable and disable logging to Firebug + * + * @see FirePHP->setEnabled() + * @param boolean $Enabled TRUE to enable, FALSE to disable + * @return void + */ + public static function setEnabled($Enabled) { + $instance = FirePHP::getInstance(true); + $instance->setEnabled($Enabled); + } + + /** + * Check if logging is enabled + * + * @see FirePHP->getEnabled() + * @return boolean TRUE if enabled + */ + public static function getEnabled() { + $instance = FirePHP::getInstance(true); + return $instance->getEnabled(); + } + + /** + * Specify a filter to be used when encoding an object + * + * Filters are used to exclude object members. + * + * @see FirePHP->setObjectFilter() + * @param string $Class The class name of the object + * @param array $Filter An array or members to exclude + * @return void + */ + public static function setObjectFilter($Class, $Filter) { + $instance = FirePHP::getInstance(true); + $instance->setObjectFilter($Class, $Filter); + } + + /** + * Set some options for the library + * + * @see FirePHP->setOptions() + * @param array $Options The options to be set + * @return void + */ + public static function setOptions($Options) { + $instance = FirePHP::getInstance(true); + $instance->setOptions($Options); + } + + /** + * Log object to firebug + * + * @see http://www.firephp.org/Wiki/Reference/Fb + * @param mixed $Object + * @return true + * @throws Exception + */ + public static function send() + { + $instance = FirePHP::getInstance(true); + $args = func_get_args(); + return call_user_func_array(array($instance,'fb'),$args); + } + + /** + * Start a group for following messages + * + * @param string $Name + * @return true + * @throws Exception + */ + public static function group($Name) { + return self::send(null, $Name, FirePHP::GROUP_START); + } + + /** + * Ends a group you have started before + * + * @return true + * @throws Exception + */ + public static function groupEnd() { + return self::send(null, null, FirePHP::GROUP_END); + } + + /** + * Log object with label to firebug console + * + * @see FirePHP::LOG + * @param mixes $Object + * @param string $Label + * @return true + * @throws Exception + */ + public static function log($Object, $Label=null) { + return self::send($Object, $Label, FirePHP::LOG); + } + + /** + * Log object with label to firebug console + * + * @see FirePHP::INFO + * @param mixes $Object + * @param string $Label + * @return true + * @throws Exception + */ + public static function info($Object, $Label=null) { + return self::send($Object, $Label, FirePHP::INFO); + } + + /** + * Log object with label to firebug console + * + * @see FirePHP::WARN + * @param mixes $Object + * @param string $Label + * @return true + * @throws Exception + */ + public static function warn($Object, $Label=null) { + return self::send($Object, $Label, FirePHP::WARN); + } + + /** + * Log object with label to firebug console + * + * @see FirePHP::ERROR + * @param mixes $Object + * @param string $Label + * @return true + * @throws Exception + */ + public static function error($Object, $Label=null) { + return self::send($Object, $Label, FirePHP::ERROR); + } + + /** + * Dumps key and variable to firebug server panel + * + * @see FirePHP::DUMP + * @param string $Key + * @param mixed $Variable + * @return true + * @throws Exception + */ + public static function dump($Key, $Variable) { + return self::send($Variable, $Key, FirePHP::DUMP); + } + + /** + * Log a trace in the firebug console + * + * @see FirePHP::TRACE + * @param string $Label + * @return true + * @throws Exception + */ + public static function trace($Label) { + return self::send($Label, FirePHP::TRACE); + } + + /** + * Log a table in the firebug console + * + * @see FirePHP::TABLE + * @param string $Label + * @param string $Table + * @return true + * @throws Exception + */ + public static function table($Label, $Table) { + return self::send($Table, $Label, FirePHP::TABLE); + } + +} + + diff --git a/src/lib/pear/PEAR/HTML/Template/IT.php b/src/lib/pear/PEAR/HTML/Template/IT.php new file mode 100644 index 0000000..ed323fb --- /dev/null +++ b/src/lib/pear/PEAR/HTML/Template/IT.php @@ -0,0 +1,1001 @@ + | +// | Pierre-Alain Joye | +// +----------------------------------------------------------------------+ +// +// $Id: IT.php,v 1.20 2006/08/17 15:47:22 dsp Exp $ +// + +require_once 'PEAR.php'; + +define('IT_OK', 1); +define('IT_ERROR', -1); +define('IT_TPL_NOT_FOUND', -2); +define('IT_BLOCK_NOT_FOUND', -3); +define('IT_BLOCK_DUPLICATE', -4); +define('IT_UNKNOWN_OPTION', -6); +/** + * Integrated Template - IT + * + * Well there's not much to say about it. I needed a template class that + * supports a single template file with multiple (nested) blocks inside and + * a simple block API. + * + * The Isotemplate API is somewhat tricky for a beginner although it is the best + * one you can build. template::parse() [phplib template = Isotemplate] requests + * you to name a source and a target where the current block gets parsed into. + * Source and target can be block names or even handler names. This API gives you + * a maximum of fexibility but you always have to know what you do which is + * quite unusual for php skripter like me. + * + * I noticed that I do not any control on which block gets parsed into which one. + * If all blocks are within one file, the script knows how they are nested and in + * which way you have to parse them. IT knows that inner1 is a child of block2, there's + * no need to tell him about this. + * + * + * + * + * + * + * + * + * + *
    + * __global__ + *

    + * (hidden and automatically added) + *

    block1 + * + * + * + * + * + * + * + * + *
    block2
    inner1inner2
    + *
    + * + * To add content to block1 you simply type: + * $tpl->setCurrentBlock("block1"); + * and repeat this as often as needed: + * + * $tpl->setVariable(...); + * $tpl->parseCurrentBlock(); + * + * + * To add content to block2 you would type something like: + * + * $tpl->setCurrentBlock("inner1"); + * $tpl->setVariable(...); + * $tpl->parseCurrentBlock(); + * + * $tpl->setVariable(...); + * $tpl->parseCurrentBlock(); + * + * $tpl->parse("block1"); + * + * + * This will result in one repition of block1 which contains two repitions + * of inner1. inner2 will be removed if $removeEmptyBlock is set to true which is the default. + * + * Usage: + * + * $tpl = new HTML_Template_IT( [string filerootdir] ); + * + * // load a template or set it with setTemplate() + * $tpl->loadTemplatefile( string filename [, boolean removeUnknownVariables, boolean removeEmptyBlocks] ) + * + * // set "global" Variables meaning variables not beeing within a (inner) block + * $tpl->setVariable( string variablename, mixed value ); + * + * // like with the Isotemplates there's a second way to use setVariable() + * $tpl->setVariable( array ( string varname => mixed value ) ); + * + * // Let's use any block, even a deeply nested one + * $tpl->setCurrentBlock( string blockname ); + * + * // repeat this as often as you need it. + * $tpl->setVariable( array ( string varname => mixed value ) ); + * $tpl->parseCurrentBlock(); + * + * // get the parsed template or print it: $tpl->show() + * $tpl->get(); + * + * + * @author Ulf Wendel + * @version $Id: IT.php,v 1.20 2006/08/17 15:47:22 dsp Exp $ + * @access public + * @package HTML_Template_IT + */ +class HTML_Template_IT +{ + /** + * Contains the error objects + * @var array + * @access public + * @see halt(), $printError, $haltOnError + */ + var $err = array(); + + /** + * Clear cache on get()? + * @var boolean + */ + var $clearCache = false; + + /** + * First character of a variable placeholder ( _{_VARIABLE} ). + * @var string + * @access public + * @see $closingDelimiter, $blocknameRegExp, $variablenameRegExp + */ + var $openingDelimiter = '{'; + + /** + * Last character of a variable placeholder ( {VARIABLE_}_ ). + * @var string + * @access public + * @see $openingDelimiter, $blocknameRegExp, $variablenameRegExp + */ + var $closingDelimiter = '}'; + + /** + * RegExp matching a block in the template. + * Per default "sm" is used as the regexp modifier, "i" is missing. + * That means a case sensitive search is done. + * @var string + * @access public + * @see $variablenameRegExp, $openingDelimiter, $closingDelimiter + */ + var $blocknameRegExp = '[\.0-9A-Za-z_-]+'; + + /** + * RegExp matching a variable placeholder in the template. + * Per default "sm" is used as the regexp modifier, "i" is missing. + * That means a case sensitive search is done. + * @var string + * @access public + * @see $blocknameRegExp, $openingDelimiter, $closingDelimiter + */ + var $variablenameRegExp = '[\.0-9A-Za-z_-]+'; + + /** + * RegExp used to find variable placeholder, filled by the constructor. + * @var string Looks somewhat like @(delimiter varname delimiter)@ + * @access public + * @see IntegratedTemplate() + */ + var $variablesRegExp = ''; + + /** + * RegExp used to strip unused variable placeholder. + * @brother $variablesRegExp + */ + var $removeVariablesRegExp = ''; + + /** + * Controls the handling of unknown variables, default is remove. + * @var boolean + * @access public + */ + var $removeUnknownVariables = true; + + /** + * Controls the handling of empty blocks, default is remove. + * @var boolean + * @access public + */ + var $removeEmptyBlocks = true; + + /** + * RegExp used to find blocks an their content, filled by the constructor. + * @var string + * @see IntegratedTemplate() + */ + var $blockRegExp = ''; + + /** + * Name of the current block. + * @var string + */ + var $currentBlock = '__global__'; + + /** + * Content of the template. + * @var string + */ + var $template = ''; + + /** + * Array of all blocks and their content. + * + * @var array + * @see findBlocks() + */ + var $blocklist = array(); + + /** + * Array with the parsed content of a block. + * + * @var array + */ + var $blockdata = array(); + + /** + * Array of variables in a block. + * @var array + */ + var $blockvariables = array(); + + /** + * Array of inner blocks of a block. + * @var array + */ + var $blockinner = array(); + + /** + * List of blocks to preverse even if they are "empty". + * + * This is something special. Sometimes you have blocks that + * should be preserved although they are empty (no placeholder replaced). + * Think of a shopping basket. If it's empty you have to drop a message to + * the user. If it's filled you have to show the contents of + * the shopping baseket. Now where do you place the message that the basket + * is empty? It's no good idea to place it in you applications as customers + * tend to like unecessary minor text changes. Having another template file + * for an empty basket means that it's very likely that one fine day + * the filled and empty basket templates have different layout. I decided + * to introduce blocks that to not contain any placeholder but only + * text such as the message "Your shopping basked is empty". + * + * Now if there is no replacement done in such a block the block will + * be recognized as "empty" and by default ($removeEmptyBlocks = true) be + * stripped off. To avoid thisyou can now call touchBlock() to avoid this. + * + * The array $touchedBlocks stores a list of touched block which must not + * be removed even if they are empty. + * + * @var array $touchedBlocks + * @see touchBlock(), $removeEmptyBlocks + */ + var $touchedBlocks = array(); + + /** + * List of blocks which should not be shown even if not "empty" + * @var array $_hiddenBlocks + * @see hideBlock(), $removeEmptyBlocks + */ + var $_hiddenBlocks = array(); + + /** + * Variable cache. + * + * Variables get cached before any replacement is done. + * Advantage: empty blocks can be removed automatically. + * Disadvantage: might take some more memory + * + * @var array + * @see setVariable(), $clearCacheOnParse + */ + var $variableCache = array(); + + /** + * Clear the variable cache on parse? + * + * If you're not an expert just leave the default false. + * True reduces memory consumption somewhat if you tend to + * add lots of values for unknown placeholder. + * + * @var boolean + */ + var $clearCacheOnParse = false; + + /** + * Root directory for all file operations. + * The string gets prefixed to all filenames given. + * @var string + * @see HTML_Template_IT(), setRoot() + */ + var $fileRoot = ''; + + /** + * Internal flag indicating that a blockname was used multiple times. + * @var boolean + */ + var $flagBlocktrouble = false; + + /** + * Flag indicating that the global block was parsed. + * @var boolean + */ + var $flagGlobalParsed = false; + + /** + * EXPERIMENTAL! FIXME! + * Flag indication that a template gets cached. + * + * Complex templates require some times to be preparsed + * before the replacement can take place. Often I use + * one template file over and over again but I don't know + * before that I will use the same template file again. + * Now IT could notice this and skip the preparse. + * + * @var boolean + */ + var $flagCacheTemplatefile = true; + + /** + * EXPERIMENTAL! FIXME! + */ + var $lastTemplatefile = ''; + + /** + * $_options['preserve_data'] Whether to substitute variables and remove + * empty placeholders in data passed through setVariable + * (see also bugs #20199, #21951). + * $_options['use_preg'] Whether to use preg_replace instead of + * str_replace in parse() + * (this is a backwards compatibility feature, see also bugs #21951, #20392) + */ + var $_options = array( + 'preserve_data' => false, + 'use_preg' => true + ); + + /** + * Builds some complex regular expressions and optinally sets the + * file root directory. + * + * Make sure that you call this constructor if you derive your template + * class from this one. + * + * @param string File root directory, prefix for all filenames + * given to the object. + * @see setRoot() + */ + function HTML_Template_IT($root = '', $options = null) + { + if (!is_null($options)) { + $this->setOptions($options); + } + $this->variablesRegExp = '@' . $this->openingDelimiter . + '(' . $this->variablenameRegExp . ')' . + $this->closingDelimiter . '@sm'; + $this->removeVariablesRegExp = '@' . $this->openingDelimiter . + "\s*(" . $this->variablenameRegExp . + ")\s*" . $this->closingDelimiter .'@sm'; + + $this->blockRegExp = '@(.*)@sm'; + + $this->setRoot($root); + } // end constructor + + + /** + * Sets the option for the template class + * + * @access public + * @param string option name + * @param mixed option value + * @return mixed IT_OK on success, error object on failure + */ + function setOption($option, $value) + { + if (array_key_exists($option, $this->_options)) { + $this->_options[$option] = $value; + return IT_OK; + } + + return PEAR::raiseError( + $this->errorMessage(IT_UNKNOWN_OPTION) . ": '{$option}'", + IT_UNKNOWN_OPTION + ); + } + + /** + * Sets the options for the template class + * + * @access public + * @param string options array of options + * default value: + * 'preserve_data' => false, + * 'use_preg' => true + * @param mixed option value + * @return mixed IT_OK on success, error object on failure + * @see $options + */ + function setOptions($options) + { + if (is_array($options)) { + foreach ($options as $option => $value) { + $error = $this->setOption($option, $value); + if (PEAR::isError($error)) { + return $error; + } + } + } + + return IT_OK; + } + + /** + * Print a certain block with all replacements done. + * @brother get() + */ + function show($block = '__global__') + { + print $this->get($block); + } // end func show + + /** + * Returns a block with all replacements done. + * + * @param string name of the block + * @return string + * @throws PEAR_Error + * @access public + * @see show() + */ + function get($block = '__global__') + { + if ($block == '__global__' && !$this->flagGlobalParsed) { + $this->parse('__global__'); + } + + if (!isset($this->blocklist[$block])) { + $this->err[] = PEAR::raiseError( + $this->errorMessage(IT_BLOCK_NOT_FOUND) . + '"' . $block . "'", + IT_BLOCK_NOT_FOUND + ); + return ''; + } + + if (isset($this->blockdata[$block])) { + $ret = $this->blockdata[$block]; + if ($this->clearCache) { + unset($this->blockdata[$block]); + } + if ($this->_options['preserve_data']) { + $ret = str_replace( + $this->openingDelimiter . + '%preserved%' . $this->closingDelimiter, + $this->openingDelimiter, + $ret + ); + } + return $ret; + } + + return ''; + } // end func get() + + /** + * Parses the given block. + * + * @param string name of the block to be parsed + * @access public + * @see parseCurrentBlock() + * @throws PEAR_Error + */ + function parse($block = '__global__', $flag_recursion = false) + { + static $regs, $values; + + if (!isset($this->blocklist[$block])) { + return PEAR::raiseError( + $this->errorMessage( IT_BLOCK_NOT_FOUND ) . '"' . $block . "'", + IT_BLOCK_NOT_FOUND + ); + } + + if ($block == '__global__') { + $this->flagGlobalParsed = true; + } + + if (!$flag_recursion) { + $regs = array(); + $values = array(); + } + $outer = $this->blocklist[$block]; + $empty = true; + + if ($this->clearCacheOnParse) { + foreach ($this->variableCache as $name => $value) { + $regs[] = $this->openingDelimiter . + $name . $this->closingDelimiter; + $values[] = $value; + $empty = false; + } + $this->variableCache = array(); + } else { + foreach ($this->blockvariables[$block] as $allowedvar => $v) { + + if (isset($this->variableCache[$allowedvar])) { + $regs[] = $this->openingDelimiter . + $allowedvar . $this->closingDelimiter; + $values[] = $this->variableCache[$allowedvar]; + unset($this->variableCache[$allowedvar]); + $empty = false; + } + } + } + + if (isset($this->blockinner[$block])) { + foreach ($this->blockinner[$block] as $k => $innerblock) { + + $this->parse($innerblock, true); + if ($this->blockdata[$innerblock] != '') { + $empty = false; + } + + $placeholder = $this->openingDelimiter . "__" . + $innerblock . "__" . $this->closingDelimiter; + $outer = str_replace( + $placeholder, + $this->blockdata[$innerblock], $outer + ); + $this->blockdata[$innerblock] = ""; + } + + } + + if (!$flag_recursion && 0 != count($values)) { + if ($this->_options['use_preg']) { + $regs = array_map(array( + &$this, '_addPregDelimiters'), + $regs + ); + $funcReplace = 'preg_replace'; + } else { + $funcReplace = 'str_replace'; + } + + if ($this->_options['preserve_data']) { + $values = array_map( + array(&$this, '_preserveOpeningDelimiter'), $values + ); + } + + $outer = $funcReplace($regs, $values, $outer); + + if ($this->removeUnknownVariables) { + $outer = preg_replace($this->removeVariablesRegExp, "", $outer); + } + } + + if ($empty) { + if (!$this->removeEmptyBlocks) { + $this->blockdata[$block ].= $outer; + } else { + if (isset($this->touchedBlocks[$block])) { + $this->blockdata[$block] .= $outer; + unset($this->touchedBlocks[$block]); + } + } + } else { + if (empty($this->blockdata[$block])) { + $this->blockdata[$block] = $outer; + } else { + $this->blockdata[$block] .= $outer; + } + } + + return $empty; + } // end func parse + + /** + * Parses the current block + * @see parse(), setCurrentBlock(), $currentBlock + * @access public + */ + function parseCurrentBlock() + { + return $this->parse($this->currentBlock); + } // end func parseCurrentBlock + + /** + * Sets a variable value. + * + * The function can be used eighter like setVariable( "varname", "value") + * or with one array $variables["varname"] = "value" + * given setVariable($variables) quite like phplib templates set_var(). + * + * @param mixed string with the variable name or an array + * %variables["varname"] = "value" + * @param string value of the variable or empty if $variable + * is an array. + * @param string prefix for variable names + * @access public + */ + function setVariable($variable, $value = '') + { + if (is_array($variable)) { + $this->variableCache = array_merge( + $this->variableCache, $variable + ); + } else { + $this->variableCache[$variable] = $value; + } + } // end func setVariable + + /** + * Sets the name of the current block that is the block where variables + * are added. + * + * @param string name of the block + * @return boolean false on failure, otherwise true + * @throws PEAR_Error + * @access public + */ + function setCurrentBlock($block = '__global__') + { + + if (!isset($this->blocklist[$block])) { + return PEAR::raiseError( + $this->errorMessage( IT_BLOCK_NOT_FOUND ) . + '"' . $block . "'", IT_BLOCK_NOT_FOUND + ); + } + + $this->currentBlock = $block; + + return true; + } // end func setCurrentBlock + + /** + * Preserves an empty block even if removeEmptyBlocks is true. + * + * @param string name of the block + * @return boolean false on false, otherwise true + * @throws PEAR_Error + * @access public + * @see $removeEmptyBlocks + */ + function touchBlock($block) + { + if (!isset($this->blocklist[$block])) { + return PEAR::raiseError( + $this->errorMessage(IT_BLOCK_NOT_FOUND) . + '"' . $block . "'", IT_BLOCK_NOT_FOUND); + } + + $this->touchedBlocks[$block] = true; + + return true; + } // end func touchBlock + + /** + * Clears all datafields of the object and rebuild the internal blocklist + * + * LoadTemplatefile() and setTemplate() automatically call this function + * when a new template is given. Don't use this function + * unless you know what you're doing. + * + * @access public + * @see free() + */ + function init() + { + $this->free(); + $this->findBlocks($this->template); + // we don't need it any more + $this->template = ''; + $this->buildBlockvariablelist(); + } // end func init + + /** + * Clears all datafields of the object. + * + * Don't use this function unless you know what you're doing. + * + * @access public + * @see init() + */ + function free() + { + $this->err = array(); + + $this->currentBlock = '__global__'; + + $this->variableCache = array(); + $this->blocklist = array(); + $this->touchedBlocks = array(); + + $this->flagBlocktrouble = false; + $this->flagGlobalParsed = false; + } // end func free + + /** + * Sets the template. + * + * You can eighter load a template file from disk with + * LoadTemplatefile() or set the template manually using this function. + * + * @param string template content + * @param boolean remove unknown/unused variables? + * @param boolean remove empty blocks? + * @see LoadTemplatefile(), $template + * @access public + * @return boolean + */ + function setTemplate( $template, $removeUnknownVariables = true, + $removeEmptyBlocks = true) + { + $this->removeUnknownVariables = $removeUnknownVariables; + $this->removeEmptyBlocks = $removeEmptyBlocks; + + if ($template == '' && $this->flagCacheTemplatefile) { + $this->variableCache = array(); + $this->blockdata = array(); + $this->touchedBlocks = array(); + $this->currentBlock = '__global__'; + } else { + $this->template = '' . $template . + ''; + $this->init(); + } + + if ($this->flagBlocktrouble) { + return false; + } + + return true; + } // end func setTemplate + + /** + * Reads a template file from the disk. + * + * @param string name of the template file + * @param bool how to handle unknown variables. + * @param bool how to handle empty blocks. + * @access public + * @return boolean false on failure, otherwise true + * @see $template, setTemplate(), $removeUnknownVariables, + * $removeEmptyBlocks + */ + function loadTemplatefile( $filename, + $removeUnknownVariables = true, + $removeEmptyBlocks = true ) + { + $template = ''; + if (!$this->flagCacheTemplatefile || + $this->lastTemplatefile != $filename + ) { + $template = $this->getFile($filename); + } + $this->lastTemplatefile = $filename; + + return $template != '' ? + $this->setTemplate( + $template,$removeUnknownVariables, $removeEmptyBlocks + ) : false; + } // end func LoadTemplatefile + + /** + * Sets the file root. The file root gets prefixed to all filenames passed + * to the object. + * + * Make sure that you override this function when using the class + * on windows. + * + * @param string + * @see HTML_Template_IT() + * @access public + */ + function setRoot($root) + { + if ($root != '' && substr($root, -1) != '/') { + $root .= '/'; + } + + $this->fileRoot = $root; + } // end func setRoot + + /** + * Build a list of all variables within of a block + */ + function buildBlockvariablelist() + { + foreach ($this->blocklist as $name => $content) { + preg_match_all($this->variablesRegExp, $content, $regs); + + if (count($regs[1]) != 0) { + foreach ($regs[1] as $k => $var) { + $this->blockvariables[$name][$var] = true; + } + } else { + $this->blockvariables[$name] = array(); + } + } + } // end func buildBlockvariablelist + + /** + * Returns a list of all global variables + */ + function getGlobalvariables() + { + $regs = array(); + $values = array(); + + foreach ($this->blockvariables['__global__'] as $allowedvar => $v) { + if (isset($this->variableCache[$allowedvar])) { + $regs[] = '@' . $this->openingDelimiter . + $allowedvar . $this->closingDelimiter . '@'; + $values[] = $this->variableCache[$allowedvar]; + unset($this->variableCache[$allowedvar]); + } + } + + return array($regs, $values); + } // end func getGlobalvariables + + /** + * Recusively builds a list of all blocks within the template. + * + * @param string string that gets scanned + * @see $blocklist + */ + function findBlocks($string) + { + $blocklist = array(); + + if (preg_match_all($this->blockRegExp, $string, $regs, PREG_SET_ORDER)) { + foreach ($regs as $k => $match) { + $blockname = $match[1]; + $blockcontent = $match[2]; + + if (isset($this->blocklist[$blockname])) { + $this->err[] = PEAR::raiseError( + $this->errorMessage( + IT_BLOCK_DUPLICATE, $blockname), + IT_BLOCK_DUPLICATE + ); + $this->flagBlocktrouble = true; + } + + $this->blocklist[$blockname] = $blockcontent; + $this->blockdata[$blockname] = ""; + + $blocklist[] = $blockname; + + $inner = $this->findBlocks($blockcontent); + foreach ($inner as $k => $name) { + $pattern = sprintf( + '@(.*)@sm', + $name, + $name + ); + + $this->blocklist[$blockname] = preg_replace( + $pattern, + $this->openingDelimiter . + '__' . $name . '__' . + $this->closingDelimiter, + $this->blocklist[$blockname] + ); + $this->blockinner[$blockname][] = $name; + $this->blockparents[$name] = $blockname; + } + } + } + + return $blocklist; + } // end func findBlocks + + /** + * Reads a file from disk and returns its content. + * @param string Filename + * @return string Filecontent + */ + function getFile($filename) + { + if ($filename{0} == '/' && substr($this->fileRoot, -1) == '/') { + $filename = substr($filename, 1); + } + + $filename = $this->fileRoot . $filename; + + if (!($fh = @fopen($filename, 'r'))) { + $this->err[] = PEAR::raiseError( + $this->errorMessage(IT_TPL_NOT_FOUND) . + ': "' .$filename .'"', + IT_TPL_NOT_FOUND + ); + return ""; + } + + $fsize = filesize($filename); + if ($fsize < 1) { + fclose($fh); + return ''; + } + + $content = fread($fh, $fsize); + fclose($fh); + + return preg_replace( + "##ime", "\$this->getFile('\\1')", $content + ); + } // end func getFile + + /** + * Adds delimiters to a string, so it can be used as a pattern + * in preg_* functions + * + * @param string + * @return string + */ + function _addPregDelimiters($str) + { + return '@' . $str . '@'; + } + + /** + * Replaces an opening delimiter by a special string + * + * @param string + * @return string + */ + function _preserveOpeningDelimiter($str) + { + return (false === strpos($str, $this->openingDelimiter))? + $str: + str_replace( + $this->openingDelimiter, + $this->openingDelimiter . + '%preserved%' . $this->closingDelimiter, + $str + ); + } + + /** + * Return a textual error message for a IT error code + * + * @param integer $value error code + * + * @return string error message, or false if the error code was + * not recognized + */ + function errorMessage($value, $blockname = '') + { + static $errorMessages; + if (!isset($errorMessages)) { + $errorMessages = array( + IT_OK => '', + IT_ERROR => 'unknown error', + IT_TPL_NOT_FOUND => 'Cannot read the template file', + IT_BLOCK_NOT_FOUND => 'Cannot find this block', + IT_BLOCK_DUPLICATE => 'The name of a block must be'. + ' uniquewithin a template.'. + ' Found "' . $blockname . '" twice.'. + 'Unpredictable results '. + 'may appear.', + IT_UNKNOWN_OPTION => 'Unknown option' + ); + } + + if (PEAR::isError($value)) { + $value = $value->getCode(); + } + + return isset($errorMessages[$value]) ? + $errorMessages[$value] : $errorMessages[IT_ERROR]; + } +} // end class IntegratedTemplate +?> diff --git a/src/lib/pear/PEAR/HTML/Template/ITX.php b/src/lib/pear/PEAR/HTML/Template/ITX.php new file mode 100644 index 0000000..5186472 --- /dev/null +++ b/src/lib/pear/PEAR/HTML/Template/ITX.php @@ -0,0 +1,832 @@ + | +// | Pierre-Alain Joye | +// +----------------------------------------------------------------------+ +// +// $Id: ITX.php,v 1.16 2006/08/17 15:47:22 dsp Exp $ +// + +require_once 'HTML/Template/IT.php'; +require_once 'HTML/Template/IT_Error.php'; + +/** +* Integrated Template Extension - ITX +* +* With this class you get the full power of the phplib template class. +* You may have one file with blocks in it but you have as well one main file +* and multiple files one for each block. This is quite usefull when you have +* user configurable websites. Using blocks not in the main template allows +* you to modify some parts of your layout easily. +* +* Note that you can replace an existing block and add new blocks at runtime. +* Adding new blocks means changing a variable placeholder to a block. +* +* @author Ulf Wendel +* @access public +* @version $Id: ITX.php,v 1.16 2006/08/17 15:47:22 dsp Exp $ +* @package HTML_Template_IT +*/ +class HTML_Template_ITX extends HTML_Template_IT +{ + /** + * Array with all warnings. + * @var array + * @access public + * @see $printWarning, $haltOnWarning, warning() + */ + var $warn = array(); + + /** + * Print warnings? + * @var array + * @access public + * @see $haltOnWarning, $warn, warning() + */ + var $printWarning = false; + + /** + * Call die() on warning? + * @var boolean + * @access public + * @see $warn, $printWarning, warning() + */ + var $haltOnWarning = false; + + /** + * RegExp used to test for a valid blockname. + * @var string + */ + var $checkblocknameRegExp = ''; + + /** + * Functionnameprefix used when searching function calls in the template. + * @var string + */ + var $functionPrefix = 'func_'; + + /** + * Functionname RegExp. + * @var string + */ + var $functionnameRegExp = '[_a-zA-Z]+[A-Za-z_0-9]*'; + + /** + * RegExp used to grep function calls in the template. + * + * The variable gets set by the constructor. + * + * @var string + * @see HTML_Template_IT() + */ + var $functionRegExp = ''; + + /** + * List of functions found in the template. + * + * @var array + */ + var $functions = array(); + + /** + * List of callback functions specified by the user. + * + * @var array + */ + var $callback = array(); + + /** + * Builds some complex regexps and calls the constructor + * of the parent class. + * + * Make sure that you call this constructor if you derive your own + * template class from this one. + * + * @see HTML_Template_IT() + */ + function HTML_Template_ITX($root = '') + { + + $this->checkblocknameRegExp = '@' . $this->blocknameRegExp . '@'; + $this->functionRegExp = '@' . $this->functionPrefix . '(' . + $this->functionnameRegExp . ')\s*\(@sm'; + + $this->HTML_Template_IT($root); + } // end func constructor + + function init() + { + $this->free(); + $this->buildFunctionlist(); + $this->findBlocks($this->template); + // we don't need it any more + $this->template = ''; + $this->buildBlockvariablelist(); + + } // end func init + + /** + * Replaces an existing block with new content. + * + * This function will replace a block of the template and all blocks + * contained in the replaced block and add a new block insted, means + * you can dynamically change your template. + * + * Note that changing the template structure violates one of the IT[X] + * development goals. I've tried to write a simple to use template engine + * supporting blocks. In contrast to other systems IT[X] analyses the way + * you've nested blocks and knows which block belongs into another block. + * The nesting information helps to make the API short and simple. Replacing + * blocks does not only mean that IT[X] has to update the nesting + * information (relatively time consumpting task) but you have to make sure + * that you do not get confused due to the template change itself. + * + * @param string Blockname + * @param string Blockcontent + * @param boolean true if the new block inherits the content + * of the old block + * @return boolean + * @throws IT_Error + * @see replaceBlockfile(), addBlock(), addBlockfile() + * @access public + */ + function replaceBlock($block, $template, $keep_content = false) + { + if (!isset($this->blocklist[$block])) { + return new IT_Error( + "The block "."'$block'". + " does not exist in the template and thus it can't be replaced.", + __FILE__, __LINE__ + ); + } + + if ($template == '') { + return new IT_Error('No block content given.', __FILE__, __LINE__); + } + + if ($keep_content) { + $blockdata = $this->blockdata[$block]; + } + + // remove all kinds of links to the block / data of the block + $this->removeBlockData($block); + + $template = "" . $template . ""; + $parents = $this->blockparents[$block]; + $this->findBlocks($template); + $this->blockparents[$block] = $parents; + + // KLUDGE: rebuild the list for all block - could be done faster + $this->buildBlockvariablelist(); + + if ($keep_content) { + $this->blockdata[$block] = $blockdata; + } + + // old TODO - I'm not sure if we need this + // update caches + + return true; + } // end func replaceBlock + + /** + * Replaces an existing block with new content from a file. + * + * @brother replaceBlock() + * @param string Blockname + * @param string Name of the file that contains the blockcontent + * @param boolean true if the new block inherits the content of the old block + * @access public + */ + function replaceBlockfile($block, $filename, $keep_content = false) + { + return $this->replaceBlock($block, $this->getFile($filename), $keep_content); + } // end func replaceBlockfile + + /** + * Adds a block to the template changing a variable placeholder + * to a block placeholder. + * + * Add means "replace a variable placeholder by a new block". + * This is different to PHPLibs templates. The function loads a + * block, creates a handle for it and assigns it to a certain + * variable placeholder. To to the same with PHPLibs templates you would + * call set_file() to create the handle and parse() to assign the + * parsed block to a variable. By this PHPLibs templates assume + * that you tend to assign a block to more than one one placeholder. + * To assign a parsed block to more than only the placeholder you specify + * in this function you have to use a combination of getBlock() + * and setVariable(). + * + * As no updates to cached data is necessary addBlock() and addBlockfile() + * are rather "cheap" meaning quick operations. + * + * The block content must not start with + * and end with this would cause overhead and + * produce an error. + * + * @param string Name of the variable placeholder, the name must be unique + * within the template. + * @param string Name of the block to be added + * @param string Content of the block + * @return boolean + * @throws IT_Error + * @see addBlockfile() + * @access public + */ + function addBlock($placeholder, $blockname, $template) + { + // Don't trust any user even if it's a programmer or yourself... + if ($placeholder == '') { + return new IT_Error('No variable placeholder given.', + __FILE__, __LINE__ + ); + } elseif ($blockname == '' || + !preg_match($this->checkblocknameRegExp, $blockname) + ) { + return new IT_Error("No or invalid blockname '$blockname' given.", + __FILE__, __LINE__ + ); + } elseif ($template == '') { + return new IT_Error('No block content given.', __FILE__, __LINE__); + } elseif (isset($this->blocklist[$blockname])) { + return new IT_Error('The block already exists.', + __FILE__, __LINE__ + ); + } + + // find out where to insert the new block + $parents = $this->findPlaceholderBlocks($placeholder); + if (count($parents) == 0) { + + return new IT_Error( + "The variable placeholder". + " '$placeholder' was not found in the template.", + __FILE__, __LINE__ + ); + + } elseif (count($parents) > 1) { + + reset($parents); + while (list($k, $parent) = each($parents)) { + $msg .= "$parent, "; + } + $msg = substr($parent, -2); + + return new IT_Error("The variable placeholder "."'$placeholder'". + " must be unique, found in multiple blocks '$msg'.", + __FILE__, __LINE__ + ); + } + + $template = "" . $template . ""; + $this->findBlocks($template); + if ($this->flagBlocktrouble) { + return false; // findBlocks() already throws an exception + } + $this->blockinner[$parents[0]][] = $blockname; + $this->blocklist[$parents[0]] = preg_replace( + '@' . $this->openingDelimiter . $placeholder . + $this->closingDelimiter . '@', + + $this->openingDelimiter . '__' . $blockname . '__' . + $this->closingDelimiter, + + $this->blocklist[$parents[0]] + ); + + $this->deleteFromBlockvariablelist($parents[0], $placeholder); + $this->updateBlockvariablelist($blockname); + + return true; + } // end func addBlock + + /** + * Adds a block taken from a file to the template changing a variable + * placeholder to a block placeholder. + * + * @param string Name of the variable placeholder to be converted + * @param string Name of the block to be added + * @param string File that contains the block + * @brother addBlock() + * @access public + */ + function addBlockfile($placeholder, $blockname, $filename) + { + return $this->addBlock($placeholder, $blockname, $this->getFile($filename)); + } // end func addBlockfile + + /** + * Returns the name of the (first) block that contains + * the specified placeholder. + * + * @param string Name of the placeholder you're searching + * @param string Name of the block to scan. If left out (default) + * all blocks are scanned. + * @return string Name of the (first) block that contains + * the specified placeholder. + * If the placeholder was not found or an error occured + * an empty string is returned. + * @throws IT_Error + * @access public + */ + function placeholderExists($placeholder, $block = '') + { + if ($placeholder == '') { + new IT_Error('No placeholder name given.', __FILE__, __LINE__); + return ''; + } + + if ($block != '' && !isset($this->blocklist[$block])) { + new IT_Error("Unknown block '$block'.", __FILE__, __LINE__); + return ''; + } + + // name of the block where the given placeholder was found + $found = ''; + + if ($block != '') { + if (is_array($variables = $this->blockvariables[$block])) { + // search the value in the list of blockvariables + reset($variables); + while (list($k, $variable) = each($variables)) { + if ($k == $placeholder) { + $found = $block; + break; + } + } + } + } else { + + // search all blocks and return the name of the first block that + // contains the placeholder + reset($this->blockvariables); + while (list($blockname, $variables) = each($this->blockvariables)){ + if (is_array($variables) && isset($variables[$placeholder])) { + $found = $blockname; + break; + } + } + } + + return $found; + } // end func placeholderExists + + /** + * Checks the list of function calls in the template and + * calls their callback function. + * + * @access public + */ + function performCallback() + { + reset($this->functions); + while (list($func_id, $function) = each($this->functions)) { + if (isset($this->callback[$function['name']])) { + if ($this->callback[$function['name']]['expandParameters']) { + $callFunction = 'call_user_func_array'; + } else { + $callFunction = 'call_user_func'; + } + + if ($this->callback[$function['name']]['object'] != '') { + $call = + $callFunction( + array( + &$GLOBALS[$this->callback[$function['name']]['object']], + $this->callback[$function['name']]['function']), + $function['args'] + ); + + } else { + $call = + $callFunction( + $this->callback[$function['name']]['function'], + $function['args'] + ); + } + $this->variableCache['__function' . $func_id . '__'] = $call; + } + } + + } // end func performCallback + + /** + * Returns a list of all function calls in the current template. + * + * @return array + * @access public + */ + function getFunctioncalls() + { + return $this->functions; + } // end func getFunctioncalls + + /** + * Replaces a function call with the given replacement. + * + * @param int Function ID + * @param string Replacement + * @deprecated + */ + function setFunctioncontent($functionID, $replacement) + { + $this->variableCache['__function' . $functionID . '__'] = $replacement; + } // end func setFunctioncontent + + /** + * Sets a callback function. + * + * IT[X] templates (note the X) can contain simple function calls. + * "function call" means that the editor of the template can add + * special placeholder to the template like 'func_h1("embedded in h1")'. + * IT[X] will grab this function calls and allow you to define a callback + * function for them. + * + * This is an absolutely evil feature. If your application makes heavy + * use of such callbacks and you're even implementing if-then etc. on + * the level of a template engine you're reiventing the wheel... - that's + * actually how PHP came into life. Anyway, sometimes it's handy. + * + * Consider also using XML/XSLT or native PHP. And please do not push + * IT[X] any further into this direction of adding logics to the template + * engine. + * + * For those of you ready for the X in IT[X]: + * + * %s', $args[0]); + * } + * + * ... + * $itx = new HTML_Template_ITX( ... ); + * ... + * $itx->setCallbackFunction('h1', 'h_one'); + * $itx->performCallback(); + * ?> + * + * template: + * func_h1('H1 Headline'); + * + * @param string Function name in the template + * @param string Name of the callback function + * @param string Name of the callback object + * @param boolean If the callback is called with a list of parameters or + * with an array holding the parameters + * @return boolean False on failure. + * @throws IT_Error + * @access public + * @deprecated The $callbackobject parameter is depricated since + * version 1.2 and might be dropped in further versions. + */ + function + setCallbackFunction($tplfunction, $callbackfunction, $callbackobject = '', $expandCallbackParameters=false) + { + if ($tplfunction == '' || $callbackfunction == '') { + return new IT_Error( + "No template function "."('$tplfunction')". + " and/or no callback function ('$callback') given.", + __FILE__, __LINE__ + ); + } + $this->callback[$tplfunction] = array( + 'function' => $callbackfunction, + 'object' => $callbackobject, + 'expandParameters' => (boolean) $expandCallbackParameters + ); + + return true; + } // end func setCallbackFunction + + /** + * Sets the Callback function lookup table + * + * @param array function table + * array[templatefunction] = + * array( + * "function" => userfunction, + * "object" => userobject + * ) + * @access public + */ + function setCallbackFuntiontable($functions) + { + $this->callback = $functions; + } // end func setCallbackFunctiontable + + /** + * Recursively removes all data assiciated with a block, including all inner blocks + * + * @param string block to be removed + * @access private + */ + function removeBlockData($block) + { + if (isset($this->blockinner[$block])) { + foreach ($this->blockinner[$block] as $k => $inner) { + $this->removeBlockData($inner); + } + + unset($this->blockinner[$block]); + } + + unset($this->blocklist[$block]); + unset($this->blockdata[$block]); + unset($this->blockvariables[$block]); + unset($this->touchedBlocks[$block]); + + } // end func removeBlockinner + + /** + * Returns a list of blocknames in the template. + * + * @return array [blockname => blockname] + * @access public + * @see blockExists() + */ + function getBlocklist() + { + $blocklist = array(); + foreach ($this->blocklist as $block => $content) { + $blocklist[$block] = $block; + } + + return $blocklist; + } // end func getBlocklist + + /** + * Checks wheter a block exists. + * + * @param string + * @return boolean + * @access public + * @see getBlocklist() + */ + function blockExists($blockname) + { + return isset($this->blocklist[$blockname]); + } // end func blockExists + + /** + * Returns a list of variables of a block. + * + * @param string Blockname + * @return array [varname => varname] + * @access public + * @see BlockvariableExists() + */ + function getBlockvariables($block) + { + if (!isset($this->blockvariables[$block])) { + return array(); + } + + $variables = array(); + foreach ($this->blockvariables[$block] as $variable => $v) { + $variables[$variable] = $variable; + } + + return $variables; + } // end func getBlockvariables + + /** + * Checks wheter a block variable exists. + * + * @param string Blockname + * @param string Variablename + * @return boolean + * @access public + * @see getBlockvariables() + */ + function BlockvariableExists($block, $variable) + { + return isset($this->blockvariables[$block][$variable]); + } // end func BlockvariableExists + + /** + * Builds a functionlist from the template. + * @access private + */ + function buildFunctionlist() + { + $this->functions = array(); + + $template = $this->template; + $num = 0; + + while (preg_match($this->functionRegExp, $template, $regs)) { + + $pos = strpos($template, $regs[0]); + $template = substr($template, $pos + strlen($regs[0])); + + $head = $this->getValue($template, ')'); + $args = array(); + + $search = $regs[0] . $head . ')'; + + $replace = $this->openingDelimiter . + '__function' . $num . '__' . + $this->closingDelimiter; + + $this->template = str_replace($search, $replace, $this->template); + $template = str_replace($search, $replace, $template); + + while ($head != '' && $args2 = $this->getValue($head, ',')) { + $arg2 = trim($args2); + $args[] = ('"' == $arg2{0} || "'" == $arg2{0}) ? + substr($arg2, 1, -1) : $arg2; + if ($arg2 == $head) { + break; + } + $head = substr($head, strlen($arg2) + 1); + } + + $this->functions[$num++] = array( + 'name' => $regs[1], + 'args' => $args + ); + } + + } // end func buildFunctionlist + + /** + * Truncates the given code from the first occurence of + * $delimiter but ignores $delimiter enclosed by " or '. + * + * @access private + * @param string The code which should be parsed + * @param string The delimiter char + * @return string + * @see buildFunctionList() + */ + function getValue($code, $delimiter) { + if ($code == '') { + return ''; + } + + if (!is_array($delimiter)) { + $delimiter = array( $delimiter => true ); + } + + $len = strlen($code); + $enclosed = false; + $enclosed_by = ''; + + if (isset($delimiter[$code[0]])) { + $i = 1; + } else { + for ($i = 0; $i < $len; ++$i) { + $char = $code[$i]; + + if ( + ($char == '"' || $char == "'") && + ($char == $enclosed_by || '' == $enclosed_by) && + (0 == $i || ($i > 0 && '\\' != $code[$i - 1])) + ) { + + if (!$enclosed) { + $enclosed_by = $char; + } else { + $enclosed_by = ""; + } + $enclosed = !$enclosed; + + } + + if (!$enclosed && isset($delimiter[$char])) { + break; + } + } + } + + return substr($code, 0, $i); + } // end func getValue + + /** + * Deletes one or many variables from the block variable list. + * + * @param string Blockname + * @param mixed Name of one variable or array of variables + * ( array ( name => true ) ) to be stripped. + * @access private + */ + function deleteFromBlockvariablelist($block, $variables) + { + if (!is_array($variables)) { + $variables = array($variables => true); + } + + reset($this->blockvariables[$block]); + while (list($varname, $val) = each($this->blockvariables[$block])) { + if (isset($variables[$varname])) { + unset($this->blockvariables[$block][$varname]); + } + } + } // end deleteFromBlockvariablelist + + /** + * Updates the variable list of a block. + * + * @param string Blockname + * @access private + */ + function updateBlockvariablelist($block) + { + preg_match_all( $this->variablesRegExp, + $this->blocklist[$block], $regs + ); + + if (count($regs[1]) != 0) { + foreach ($regs[1] as $k => $var) { + $this->blockvariables[$block][$var] = true; + } + } else { + $this->blockvariables[$block] = array(); + } + + // check if any inner blocks were found + if (isset($this->blockinner[$block]) && + is_array($this->blockinner[$block]) && + count($this->blockinner[$block]) > 0 + ) { + /* + * loop through inner blocks, registering the variable + * placeholders in each + */ + foreach ($this->blockinner[$block] as $childBlock) { + $this->updateBlockvariablelist($childBlock); + } + } + } // end func updateBlockvariablelist + + /** + * Returns an array of blocknames where the given variable + * placeholder is used. + * + * @param string Variable placeholder + * @return array $parents parents[0..n] = blockname + * @access public + */ + function findPlaceholderBlocks($variable) + { + $parents = array(); + reset($this->blocklist); + while (list($blockname, $content) = each($this->blocklist)) { + reset($this->blockvariables[$blockname]); + while ( + list($varname, $val) = each($this->blockvariables[$blockname])) + { + if ($variable == $varname) { + $parents[] = $blockname; + } + } + } + + return $parents; + } // end func findPlaceholderBlocks + + /** + * Handles warnings, saves them to $warn and prints them or + * calls die() depending on the flags + * + * @param string Warning + * @param string File where the warning occured + * @param int Linenumber where the warning occured + * @see $warn, $printWarning, $haltOnWarning + * @access private + */ + function warning($message, $file = '', $line = 0) + { + $message = sprintf( + 'HTML_Template_ITX Warning: %s [File: %s, Line: %d]', + $message, + $file, + $line + ); + + $this->warn[] = $message; + + if ($this->printWarning) { + print $message; + } + + if ($this->haltOnWarning) { + die($message); + } + } // end func warning + +} // end class HTML_Template_ITX +?> diff --git a/src/lib/pear/PEAR/HTML/Template/IT_Error.php b/src/lib/pear/PEAR/HTML/Template/IT_Error.php new file mode 100644 index 0000000..65dae67 --- /dev/null +++ b/src/lib/pear/PEAR/HTML/Template/IT_Error.php @@ -0,0 +1,51 @@ + | +// | Pierre-Alain Joye | +// +----------------------------------------------------------------------+ +// +// $Id: IT_Error.php,v 1.3 2006/08/17 15:44:31 dsp Exp $ + +require_once "PEAR.php"; + +/** +* IT[X] Error class +* +* @package HTML_Template_IT +*/ +class IT_Error extends PEAR_Error { + + + /** + * Prefix of all error messages. + * + * @var string + */ + var $error_message_prefix = "IntegratedTemplate Error: "; + + /** + * Creates an cache error object. + * + * @param string error message + * @param string file where the error occured + * @param string linenumber where the error occured + */ + function IT_Error($msg, $file = __FILE__, $line = __LINE__) { + + $this->PEAR_Error(sprintf("%s [%s on line %d].", $msg, $file, $line)); + + } // end func IT_Error + +} // end class IT_Error +?> diff --git a/src/lib/pear/PEAR/MIME/Type.php b/src/lib/pear/PEAR/MIME/Type.php new file mode 100644 index 0000000..79ab79d --- /dev/null +++ b/src/lib/pear/PEAR/MIME/Type.php @@ -0,0 +1,523 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: Type.php,v 1.6 2009/01/16 11:49:45 cweiske Exp $ + +require_once 'PEAR.php'; + +$_fileCmd = &PEAR::getStaticProperty('MIME_Type', 'fileCmd'); +$_fileCmd = 'file'; + +/** + * Class for working with MIME types + * + * @category MIME + * @package MIME_Type + * @license PHP License 3.0 + * @version 1.2.0 + * @link http://pear.php.net/package/MIME_Type + * @author Ian Eure + */ +class MIME_Type +{ + /** + * The MIME media type + * + * @var string + */ + var $media = ''; + + /** + * The MIME media sub-type + * + * @var string + */ + var $subType = ''; + + /** + * Optional MIME parameters + * + * @var array + */ + var $parameters = array(); + + /** + * List of valid media types. + * A media type is the string in front of the slash. + * The media type of "text/xml" would be "text". + * + * @var array + */ + var $validMediaTypes = array( + 'text', + 'image', + 'audio', + 'video', + 'application', + 'multipart', + 'message' + ); + + + /** + * Constructor. + * + * If $type is set, if will be parsed and the appropriate class vars set. + * If not, you get an empty class. + * This is useful, but not quite as useful as parsing a type. + * + * @param string $type MIME type + * + * @return void + */ + function MIME_Type($type = false) + { + if ($type) { + $this->parse($type); + } + } + + + /** + * Parse a mime-type and set the class variables. + * + * @param string $type MIME type to parse + * + * @return void + */ + function parse($type) + { + $this->media = $this->getMedia($type); + $this->subType = $this->getSubType($type); + $this->parameters = array(); + if (MIME_Type::hasParameters($type)) { + require_once 'MIME/Type/Parameter.php'; + foreach (MIME_Type::getParameters($type) as $param) { + $param = new MIME_Type_Parameter($param); + $this->parameters[$param->name] = $param; + } + } + } + + + /** + * Does this type have any parameters? + * + * @param string $type MIME type to check + * + * @return boolean true if $type has parameters, false otherwise + * @static + */ + function hasParameters($type) + { + if (strstr($type, ';')) { + return true; + } + return false; + } + + + /** + * Get a MIME type's parameters + * + * @param string $type MIME type to get parameters of + * + * @return array $type's parameters + * @static + */ + function getParameters($type) + { + $params = array(); + $tmp = explode(';', $type); + for ($i = 1; $i < count($tmp); $i++) { + $params[] = trim($tmp[$i]); + } + return $params; + } + + + /** + * Strip parameters from a MIME type string. + * + * @param string $type MIME type string + * + * @return string MIME type with parameters removed + * @static + */ + function stripParameters($type) + { + if (strstr($type, ';')) { + return substr($type, 0, strpos($type, ';')); + } + return $type; + } + + + /** + * Removes comments from a media type, subtype or parameter. + * + * @param string $string String to strip comments from + * @param string &$comment Comment is stored in there. + * + * @return string String without comments + * @static + */ + function stripComments($string, &$comment) + { + if (strpos($string, '(') === false) { + return $string; + } + + $inquote = false; + $quoting = false; + $incomment = 0; + $newstring = ''; + + for ($n = 0; $n < strlen($string); $n++) { + if ($quoting) { + if ($incomment == 0) { + $newstring .= $string[$n]; + } else if ($comment !== null) { + $comment .= $string[$n]; + } + $quoting = false; + } else if ($string[$n] == '\\') { + $quoting = true; + } else if (!$inquote && $incomment > 0 && $string[$n] == ')') { + $incomment--; + if ($incomment == 0 && $comment !== null) { + $comment .= ' '; + } + } else if (!$inquote && $string[$n] == '(') { + $incomment++; + } else if ($string[$n] == '"') { + if ($inquote) { + $inquote = false; + } else { + $inquote = true; + } + } else if ($incomment == 0) { + $newstring .= $string[$n]; + } else if ($comment !== null) { + $comment .= $string[$n]; + } + } + + if ($comment !== null) { + $comment = trim($comment); + } + + return $newstring; + } + + + /** + * Get a MIME type's media + * + * @note 'media' refers to the portion before the first slash + * + * @param string $type MIME type to get media of + * + * @return string $type's media + * @static + */ + function getMedia($type) + { + $tmp = explode('/', $type); + return strtolower(trim(MIME_Type::stripComments($tmp[0], $null))); + } + + + /** + * Get a MIME type's subtype + * + * @param string $type MIME type to get subtype of + * + * @return string $type's subtype, null if invalid mime type + * @static + */ + function getSubType($type) + { + $tmp = explode('/', $type); + if (!isset($tmp[1])) { + return null; + } + $tmp = explode(';', $tmp[1]); + return strtolower(trim(MIME_Type::stripComments($tmp[0], $null))); + } + + + /** + * Create a textual MIME type from object values + * + * This function performs the opposite function of parse(). + * + * @return string MIME type string + */ + function get() + { + $type = strtolower($this->media . '/' . $this->subType); + if (count($this->parameters)) { + foreach ($this->parameters as $key => $null) { + $type .= '; ' . $this->parameters[$key]->get(); + } + } + return $type; + } + + + /** + * Is this type experimental? + * + * @note Experimental types are denoted by a leading 'x-' in the media or + * subtype, e.g. text/x-vcard or x-world/x-vrml. + * + * @param string $type MIME type to check + * + * @return boolean true if $type is experimental, false otherwise + * @static + */ + function isExperimental($type) + { + if (substr(MIME_Type::getMedia($type), 0, 2) == 'x-' || + substr(MIME_Type::getSubType($type), 0, 2) == 'x-') { + return true; + } + return false; + } + + + /** + * Is this a vendor MIME type? + * + * @note Vendor types are denoted with a leading 'vnd. in the subtype. + * + * @param string $type MIME type to check + * + * @return boolean true if $type is a vendor type, false otherwise + * @static + */ + function isVendor($type) + { + if (substr(MIME_Type::getSubType($type), 0, 4) == 'vnd.') { + return true; + } + return false; + } + + + /** + * Is this a wildcard type? + * + * @param string $type MIME type to check + * + * @return boolean true if $type is a wildcard, false otherwise + * @static + */ + function isWildcard($type) + { + if ($type == '*/*' || MIME_Type::getSubtype($type) == '*') { + return true; + } + return false; + } + + + /** + * Perform a wildcard match on a MIME type + * + * Example: + * MIME_Type::wildcardMatch('image/*', 'image/png') + * + * @param string $card Wildcard to check against + * @param string $type MIME type to check + * + * @return boolean true if there was a match, false otherwise + * @static + */ + function wildcardMatch($card, $type) + { + if (!MIME_Type::isWildcard($card)) { + return false; + } + + if ($card == '*/*') { + return true; + } + + if (MIME_Type::getMedia($card) == MIME_Type::getMedia($type)) { + return true; + } + + return false; + } + + + /** + * Add a parameter to this type + * + * @param string $name Attribute name + * @param string $value Attribute value + * @param string $comment Comment for this parameter + * + * @return void + */ + function addParameter($name, $value, $comment = false) + { + $tmp = new MIME_Type_Parameter(); + + $tmp->name = $name; + $tmp->value = $value; + $tmp->comment = $comment; + $this->parameters[$name] = $tmp; + } + + + /** + * Remove a parameter from this type + * + * @param string $name Parameter name + * + * @return void + */ + function removeParameter($name) + { + unset($this->parameters[$name]); + } + + + /** + * Autodetect a file's MIME-type + * + * This function may be called staticly. + * + * @internal Tries to use fileinfo extension at first. If that + * does not work, mime_magic is used. If this is also not available + * or does not succeed, "file" command is tried to be executed with + * System_Command. When that fails, too, then we use our in-built + * extension-to-mimetype-mapping list. + * + * @param string $file Path to the file to get the type of + * @param bool $params Append MIME parameters if true + * + * @return string $file's MIME-type on success, PEAR_Error otherwise + * + * @since 1.0.0beta1 + * @static + */ + function autoDetect($file, $params = false) + { + // Sanity checks + if (!file_exists($file)) { + return PEAR::raiseError("File \"$file\" doesn't exist"); + } + + if (!is_readable($file)) { + return PEAR::raiseError("File \"$file\" is not readable"); + } + + if (function_exists('finfo_file')) { + $finfo = finfo_open(FILEINFO_MIME); + $type = finfo_file($finfo, $file); + finfo_close($finfo); + if ($type !== false && $type !== '') { + return MIME_Type::_handleDetection($type, $params); + } + } + + if (function_exists('mime_content_type')) { + $type = mime_content_type($file); + if ($type !== false && $type !== '') { + return MIME_Type::_handleDetection($type, $params); + } + } + + @include_once 'System/Command.php'; + if (class_exists('System_Command')) { + return MIME_Type::_handleDetection( + MIME_Type::_fileAutoDetect($file), + $params + ); + } + + require_once 'MIME/Type/Extension.php'; + $mte = new MIME_Type_Extension(); + return $mte->getMIMEType($file); + } + + + /** + * Handles a detected MIME type and modifies it if necessary. + * + * @param string $type MIME Type of a file + * @param bool $params Append MIME parameters if true + * + * @return string $file's MIME-type on success, PEAR_Error otherwise + */ + function _handleDetection($type, $params) + { + // _fileAutoDetect() may have returned an error. + if (PEAR::isError($type)) { + return $type; + } + + // Don't return an empty string + if (!$type || !strlen($type)) { + return PEAR::raiseError("Sorry, couldn't determine file type."); + } + + // Strip parameters if present & requested + if (MIME_Type::hasParameters($type) && !$params) { + $type = MIME_Type::stripParameters($type); + } + + return $type; + } + + + /** + * Autodetect a file's MIME-type with 'file' and System_Command + * + * This function may be called staticly. + * + * @param string $file Path to the file to get the type of + * + * @return string $file's MIME-type + * + * @since 1.0.0beta1 + * @static + */ + function _fileAutoDetect($file) + { + $cmd = new System_Command(); + + // Make sure we have the 'file' command. + $fileCmd = PEAR::getStaticProperty('MIME_Type', 'fileCmd'); + if (!$cmd->which($fileCmd)) { + unset($cmd); + return PEAR::raiseError("Can't find file command \"{$fileCmd}\""); + } + + $cmd->pushCommand($fileCmd, "-bi " . escapeshellarg($file)); + $res = $cmd->execute(); + unset($cmd); + + return $res; + } + +} \ No newline at end of file diff --git a/src/lib/pear/PEAR/MIME/Type/Extension.php b/src/lib/pear/PEAR/MIME/Type/Extension.php new file mode 100644 index 0000000..1987e2a --- /dev/null +++ b/src/lib/pear/PEAR/MIME/Type/Extension.php @@ -0,0 +1,298 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: Extension.php,v 1.1 2009/01/16 11:49:45 cweiske Exp $ + +require_once 'PEAR.php'; + +/** + * Class for mapping file extensions to MIME types. + * + * @category MIME + * @package MIME_Type + * @author Christian Schmidt + * @license PHP License 3.0 + * @version 1.2.0 + * @link http://pear.php.net/package/MIME_Type + */ +class MIME_Type_Extension +{ + /** + * Mapping between file extension and MIME type. + * + * @internal The array is sorted alphabetically by value and with primary + * extension first. Be careful about not adding duplicate keys - PHP + * silently ignores duplicates. The following command can be used for + * checking for duplicates: + * grep "=> '" Extension.php | cut -d\' -f2 | sort | uniq -d + * application/octet-stream is generally used as fallback when no other + * MIME-type can be found, but the array does not contain a lot of such + * unknown extension. One entry exists, though, to allow detection of + * file extension for this MIME-type. + * + * @var array + */ + var $extensionToType = array ( + 'ez' => 'application/andrew-inset', + 'atom' => 'application/atom+xml', + 'jar' => 'application/java-archive', + 'hqx' => 'application/mac-binhex40', + 'cpt' => 'application/mac-compactpro', + 'mathml' => 'application/mathml+xml', + 'doc' => 'application/msword', + 'dat' => 'application/octet-stream', + 'oda' => 'application/oda', + 'ogg' => 'application/ogg', + 'pdf' => 'application/pdf', + 'ai' => 'application/postscript', + 'eps' => 'application/postscript', + 'ps' => 'application/postscript', + 'rdf' => 'application/rdf+xml', + 'rss' => 'application/rss+xml', + 'smi' => 'application/smil', + 'smil' => 'application/smil', + 'gram' => 'application/srgs', + 'grxml' => 'application/srgs+xml', + 'kml' => 'application/vnd.google-earth.kml+xml', + 'kmz' => 'application/vnd.google-earth.kmz', + 'mif' => 'application/vnd.mif', + 'xul' => 'application/vnd.mozilla.xul+xml', + 'xls' => 'application/vnd.ms-excel', + 'xlb' => 'application/vnd.ms-excel', + 'xlt' => 'application/vnd.ms-excel', + 'xlam' => 'application/vnd.ms-excel.addin.macroEnabled.12', + 'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12', + 'xlsm' => 'application/vnd.ms-excel.sheet.macroEnabled.12', + 'xltm' => 'application/vnd.ms-excel.template.macroEnabled.12', + 'docm' => 'application/vnd.ms-word.document.macroEnabled.12', + 'dotm' => 'application/vnd.ms-word.template.macroEnabled.12', + 'ppam' => 'application/vnd.ms-powerpoint.addin.macroEnabled.12', + 'pptm' => 'application/vnd.ms-powerpoint.presentation.macroEnabled.12', + 'ppsm' => 'application/vnd.ms-powerpoint.slideshow.macroEnabled.12', + 'potm' => 'application/vnd.ms-powerpoint.template.macroEnabled.12', + 'ppt' => 'application/vnd.ms-powerpoint', + 'pps' => 'application/vnd.ms-powerpoint', + 'odc' => 'application/vnd.oasis.opendocument.chart', + 'odb' => 'application/vnd.oasis.opendocument.database', + 'odf' => 'application/vnd.oasis.opendocument.formula', + 'odg' => 'application/vnd.oasis.opendocument.graphics', + 'otg' => 'application/vnd.oasis.opendocument.graphics-template', + 'odi' => 'application/vnd.oasis.opendocument.image', + 'odp' => 'application/vnd.oasis.opendocument.presentation', + 'otp' => 'application/vnd.oasis.opendocument.presentation-template', + 'ods' => 'application/vnd.oasis.opendocument.spreadsheet', + 'ots' => 'application/vnd.oasis.opendocument.spreadsheet-template', + 'odt' => 'application/vnd.oasis.opendocument.text', + 'odm' => 'application/vnd.oasis.opendocument.text-master', + 'ott' => 'application/vnd.oasis.opendocument.text-template', + 'oth' => 'application/vnd.oasis.opendocument.text-web', + 'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template', + 'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow', + 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation', + 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + 'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template', + 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + 'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template', + 'vsd' => 'application/vnd.visio', + 'wbxml' => 'application/vnd.wap.wbxml', + 'wmlc' => 'application/vnd.wap.wmlc', + 'wmlsc' => 'application/vnd.wap.wmlscriptc', + 'vxml' => 'application/voicexml+xml', + 'bcpio' => 'application/x-bcpio', + 'vcd' => 'application/x-cdlink', + 'pgn' => 'application/x-chess-pgn', + 'cpio' => 'application/x-cpio', + 'csh' => 'application/x-csh', + 'dcr' => 'application/x-director', + 'dir' => 'application/x-director', + 'dxr' => 'application/x-director', + 'dvi' => 'application/x-dvi', + 'spl' => 'application/x-futuresplash', + 'tgz' => 'application/x-gtar', + 'gtar' => 'application/x-gtar', + 'hdf' => 'application/x-hdf', + 'js' => 'application/x-javascript', + 'skp' => 'application/x-koan', + 'skd' => 'application/x-koan', + 'skt' => 'application/x-koan', + 'skm' => 'application/x-koan', + 'latex' => 'application/x-latex', + 'nc' => 'application/x-netcdf', + 'cdf' => 'application/x-netcdf', + 'sh' => 'application/x-sh', + 'shar' => 'application/x-shar', + 'swf' => 'application/x-shockwave-flash', + 'sit' => 'application/x-stuffit', + 'sv4cpio' => 'application/x-sv4cpio', + 'sv4crc' => 'application/x-sv4crc', + 'tar' => 'application/x-tar', + 'tcl' => 'application/x-tcl', + 'tex' => 'application/x-tex', + 'texinfo' => 'application/x-texinfo', + 'texi' => 'application/x-texinfo', + 't' => 'application/x-troff', + 'tr' => 'application/x-troff', + 'roff' => 'application/x-troff', + 'man' => 'application/x-troff-man', + 'me' => 'application/x-troff-me', + 'ms' => 'application/x-troff-ms', + 'ustar' => 'application/x-ustar', + 'src' => 'application/x-wais-source', + 'xhtml' => 'application/xhtml+xml', + 'xht' => 'application/xhtml+xml', + 'xslt' => 'application/xslt+xml', + 'xml' => 'application/xml', + 'xsl' => 'application/xml', + 'dtd' => 'application/xml-dtd', + 'zip' => 'application/zip', + 'au' => 'audio/basic', + 'snd' => 'audio/basic', + 'mid' => 'audio/midi', + 'midi' => 'audio/midi', + 'kar' => 'audio/midi', + 'mpga' => 'audio/mpeg', + 'mp2' => 'audio/mpeg', + 'mp3' => 'audio/mpeg', + 'aif' => 'audio/x-aiff', + 'aiff' => 'audio/x-aiff', + 'aifc' => 'audio/x-aiff', + 'm3u' => 'audio/x-mpegurl', + 'wma' => 'audio/x-ms-wma', + 'wax' => 'audio/x-ms-wax', + 'ram' => 'audio/x-pn-realaudio', + 'ra' => 'audio/x-pn-realaudio', + 'rm' => 'application/vnd.rn-realmedia', + 'wav' => 'audio/x-wav', + 'pdb' => 'chemical/x-pdb', + 'xyz' => 'chemical/x-xyz', + 'bmp' => 'image/bmp', + 'cgm' => 'image/cgm', + 'gif' => 'image/gif', + 'ief' => 'image/ief', + 'jpeg' => 'image/jpeg', + 'jpg' => 'image/jpeg', + 'jpe' => 'image/jpeg', + 'png' => 'image/png', + 'svg' => 'image/svg+xml', + 'tiff' => 'image/tiff', + 'tif' => 'image/tiff', + 'djvu' => 'image/vnd.djvu', + 'djv' => 'image/vnd.djvu', + 'wbmp' => 'image/vnd.wap.wbmp', + 'ras' => 'image/x-cmu-raster', + 'ico' => 'image/x-icon', + 'pnm' => 'image/x-portable-anymap', + 'pbm' => 'image/x-portable-bitmap', + 'pgm' => 'image/x-portable-graymap', + 'ppm' => 'image/x-portable-pixmap', + 'rgb' => 'image/x-rgb', + 'xbm' => 'image/x-xbitmap', + 'psd' => 'image/x-photoshop', + 'xpm' => 'image/x-xpixmap', + 'xwd' => 'image/x-xwindowdump', + 'eml' => 'message/rfc822', + 'igs' => 'model/iges', + 'iges' => 'model/iges', + 'msh' => 'model/mesh', + 'mesh' => 'model/mesh', + 'silo' => 'model/mesh', + 'wrl' => 'model/vrml', + 'vrml' => 'model/vrml', + 'ics' => 'text/calendar', + 'ifb' => 'text/calendar', + 'css' => 'text/css', + 'csv' => 'text/csv', + 'html' => 'text/html', + 'htm' => 'text/html', + 'txt' => 'text/plain', + 'asc' => 'text/plain', + 'rtx' => 'text/richtext', + 'rtf' => 'text/rtf', + 'sgml' => 'text/sgml', + 'sgm' => 'text/sgml', + 'tsv' => 'text/tab-separated-values', + 'wml' => 'text/vnd.wap.wml', + 'wmls' => 'text/vnd.wap.wmlscript', + 'etx' => 'text/x-setext', + 'mpeg' => 'video/mpeg', + 'mpg' => 'video/mpeg', + 'mpe' => 'video/mpeg', + 'qt' => 'video/quicktime', + 'mov' => 'video/quicktime', + 'mxu' => 'video/vnd.mpegurl', + 'm4u' => 'video/vnd.mpegurl', + 'flv' => 'video/x-flv', + 'asf' => 'video/x-ms-asf', + 'asx' => 'video/x-ms-asf', + 'wmv' => 'video/x-ms-wmv', + 'wm' => 'video/x-ms-wm', + 'wmx' => 'video/x-ms-wmx', + 'avi' => 'video/x-msvideo', + 'ogv' => 'video/ogg', + 'movie' => 'video/x-sgi-movie', + 'ice' => 'x-conference/x-cooltalk', + ); + + + + /** + * Autodetect a file's MIME-type. + * + * @param string $file Path to the file to get the type of + * + * @return string $file's MIME-type on success, PEAR_Error otherwise + */ + function getMIMEType($file) + { + $extension = substr(strrchr($file, '.'), 1); + if ($extension === false) { + return PEAR::raiseError("File has no extension."); + } + + if (!isset($this->extensionToType[$extension])) { + return PEAR::raiseError("Sorry, couldn't determine file type."); + } + + return $this->extensionToType[$extension]; + } + + + + /** + * Return default MIME-type for the specified extension. + * + * @param string $type MIME-type + * + * @return string A file extension without leading period. + */ + function getExtension($type) + { + require_once 'MIME/Type.php'; + // Strip parameters and comments. + $type = MIME_Type::getMedia($type) . '/' . MIME_Type::getSubType($type); + + $extension = array_search($type, $this->extensionToType); + if ($extension === false) { + return PEAR::raiseError("Sorry, couldn't determine extension."); + } + return $extension; + } + +} + +?> \ No newline at end of file diff --git a/src/lib/pear/PEAR/MIME/Type/Parameter.php b/src/lib/pear/PEAR/MIME/Type/Parameter.php new file mode 100644 index 0000000..399d3dd --- /dev/null +++ b/src/lib/pear/PEAR/MIME/Type/Parameter.php @@ -0,0 +1,163 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: Parameter.php,v 1.1 2007/03/25 10:10:21 cweiske Exp $ + +/** + * Class for working with MIME type parameters + * + * @version 1.2.0 + * @package MIME_Type + * @author Ian Eure + */ +class MIME_Type_Parameter { + /** + * Parameter name + * + * @var string + */ + var $name; + + /** + * Parameter value + * + * @var string + */ + var $value; + + /** + * Parameter comment + * + * @var string + */ + var $comment; + + + /** + * Constructor. + * + * @param string $param MIME parameter to parse, if set. + * @return void + */ + function MIME_Type_Parameter($param = false) + { + if ($param) { + $this->parse($param); + } + } + + + /** + * Parse a MIME type parameter and set object fields + * + * @param string $param MIME type parameter to parse + * @return void + */ + function parse($param) + { + $comment = ''; + $param = MIME_Type::stripComments($param, $comment); + $this->name = $this->getAttribute($param); + $this->value = $this->getValue($param); + $this->comment = $comment; + } + + + /** + * Get a parameter attribute (e.g. name) + * + * @param string MIME type parameter + * @return string Attribute name + * @static + */ + function getAttribute($param) + { + $tmp = explode('=', $param); + return trim($tmp[0]); + } + + + /** + * Get a parameter value + * + * @param string $param MIME type parameter + * @return string Value + * @static + */ + function getValue($param) + { + $tmp = explode('=', $param, 2); + $value = $tmp[1]; + $value = trim($value); + if ($value[0] == '"' && $value[strlen($value)-1] == '"') { + $value = substr($value, 1, -1); + } + $value = str_replace('\\"', '"', $value); + return $value; + } + + + /** + * Get a parameter comment + * + * @param string $param MIME type parameter + * @return string Parameter comment + * @see getComment() + * @static + */ + function getComment($param) + { + $cs = strpos($param, '('); + $comment = substr($param, $cs); + return trim($comment, '() '); + } + + + /** + * Does this parameter have a comment? + * + * @param string $param MIME type parameter + * @return boolean true if $param has a comment, false otherwise + * @static + */ + function hasComment($param) + { + if (strstr($param, '(')) { + return true; + } + return false; + } + + + /** + * Get a string representation of this parameter + * + * This function performs the oppsite of parse() + * + * @return string String representation of parameter + */ + function get() + { + $val = $this->name . '="' . str_replace('"', '\\"', $this->value) . '"'; + if ($this->comment) { + $val .= ' (' . $this->comment . ')'; + } + return $val; + } +} +?> \ No newline at end of file diff --git a/src/lib/pear/PEAR/OS/Guess.php b/src/lib/pear/PEAR/OS/Guess.php new file mode 100644 index 0000000..d266e70 --- /dev/null +++ b/src/lib/pear/PEAR/OS/Guess.php @@ -0,0 +1,344 @@ + + * @author Gregory Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: Guess.php,v 1.26 2008/01/03 20:26:34 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since PEAR 0.1 + */ + +// {{{ uname examples + +// php_uname() without args returns the same as 'uname -a', or a PHP-custom +// string for Windows. +// PHP versions prior to 4.3 return the uname of the host where PHP was built, +// as of 4.3 it returns the uname of the host running the PHP code. +// +// PC RedHat Linux 7.1: +// Linux host.example.com 2.4.2-2 #1 Sun Apr 8 20:41:30 EDT 2001 i686 unknown +// +// PC Debian Potato: +// Linux host 2.4.17 #2 SMP Tue Feb 12 15:10:04 CET 2002 i686 unknown +// +// PC FreeBSD 3.3: +// FreeBSD host.example.com 3.3-STABLE FreeBSD 3.3-STABLE #0: Mon Feb 21 00:42:31 CET 2000 root@example.com:/usr/src/sys/compile/CONFIG i386 +// +// PC FreeBSD 4.3: +// FreeBSD host.example.com 4.3-RELEASE FreeBSD 4.3-RELEASE #1: Mon Jun 25 11:19:43 EDT 2001 root@example.com:/usr/src/sys/compile/CONFIG i386 +// +// PC FreeBSD 4.5: +// FreeBSD host.example.com 4.5-STABLE FreeBSD 4.5-STABLE #0: Wed Feb 6 23:59:23 CET 2002 root@example.com:/usr/src/sys/compile/CONFIG i386 +// +// PC FreeBSD 4.5 w/uname from GNU shellutils: +// FreeBSD host.example.com 4.5-STABLE FreeBSD 4.5-STABLE #0: Wed Feb i386 unknown +// +// HP 9000/712 HP-UX 10: +// HP-UX iq B.10.10 A 9000/712 2008429113 two-user license +// +// HP 9000/712 HP-UX 10 w/uname from GNU shellutils: +// HP-UX host B.10.10 A 9000/712 unknown +// +// IBM RS6000/550 AIX 4.3: +// AIX host 3 4 000003531C00 +// +// AIX 4.3 w/uname from GNU shellutils: +// AIX host 3 4 000003531C00 unknown +// +// SGI Onyx IRIX 6.5 w/uname from GNU shellutils: +// IRIX64 host 6.5 01091820 IP19 mips +// +// SGI Onyx IRIX 6.5: +// IRIX64 host 6.5 01091820 IP19 +// +// SparcStation 20 Solaris 8 w/uname from GNU shellutils: +// SunOS host.example.com 5.8 Generic_108528-12 sun4m sparc +// +// SparcStation 20 Solaris 8: +// SunOS host.example.com 5.8 Generic_108528-12 sun4m sparc SUNW,SPARCstation-20 +// +// Mac OS X (Darwin) +// Darwin home-eden.local 7.5.0 Darwin Kernel Version 7.5.0: Thu Aug 5 19:26:16 PDT 2004; root:xnu/xnu-517.7.21.obj~3/RELEASE_PPC Power Macintosh +// +// Mac OS X early versions +// + +// }}} + +/* TODO: + * - define endianness, to allow matchSignature("bigend") etc. + */ + +/** + * Retrieves information about the current operating system + * + * This class uses php_uname() to grok information about the current OS + * + * @category pear + * @package PEAR + * @author Stig Bakken + * @author Gregory Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 0.1 + */ +class OS_Guess +{ + var $sysname; + var $nodename; + var $cpu; + var $release; + var $extra; + + function OS_Guess($uname = null) + { + list($this->sysname, + $this->release, + $this->cpu, + $this->extra, + $this->nodename) = $this->parseSignature($uname); + } + + function parseSignature($uname = null) + { + static $sysmap = array( + 'HP-UX' => 'hpux', + 'IRIX64' => 'irix', + ); + static $cpumap = array( + 'i586' => 'i386', + 'i686' => 'i386', + 'ppc' => 'powerpc', + ); + if ($uname === null) { + $uname = php_uname(); + } + $parts = split('[[:space:]]+', trim($uname)); + $n = count($parts); + + $release = $machine = $cpu = ''; + $sysname = $parts[0]; + $nodename = $parts[1]; + $cpu = $parts[$n-1]; + $extra = ''; + if ($cpu == 'unknown') { + $cpu = $parts[$n-2]; + } + + switch ($sysname) { + case 'AIX' : + $release = "$parts[3].$parts[2]"; + break; + case 'Windows' : + switch ($parts[1]) { + case '95/98': + $release = '9x'; + break; + default: + $release = $parts[1]; + break; + } + $cpu = 'i386'; + break; + case 'Linux' : + $extra = $this->_detectGlibcVersion(); + // use only the first two digits from the kernel version + $release = ereg_replace('^([[:digit:]]+\.[[:digit:]]+).*', '\1', $parts[2]); + break; + case 'Mac' : + $sysname = 'darwin'; + $nodename = $parts[2]; + $release = $parts[3]; + if ($cpu == 'Macintosh') { + if ($parts[$n - 2] == 'Power') { + $cpu = 'powerpc'; + } + } + break; + case 'Darwin' : + if ($cpu == 'Macintosh') { + if ($parts[$n - 2] == 'Power') { + $cpu = 'powerpc'; + } + } + $release = ereg_replace('^([[:digit:]]+\.[[:digit:]]+).*', '\1', $parts[2]); + break; + default: + $release = ereg_replace('-.*', '', $parts[2]); + break; + } + + + if (isset($sysmap[$sysname])) { + $sysname = $sysmap[$sysname]; + } else { + $sysname = strtolower($sysname); + } + if (isset($cpumap[$cpu])) { + $cpu = $cpumap[$cpu]; + } + return array($sysname, $release, $cpu, $extra, $nodename); + } + + function _detectGlibcVersion() + { + static $glibc = false; + if ($glibc !== false) { + return $glibc; // no need to run this multiple times + } + $major = $minor = 0; + include_once "System.php"; + // Use glibc's header file to + // get major and minor version number: + if (@file_exists('/usr/include/features.h') && + @is_readable('/usr/include/features.h')) { + if (!@file_exists('/usr/bin/cpp') || !@is_executable('/usr/bin/cpp')) { + $features_file = fopen('/usr/include/features.h', 'rb'); + while (!feof($features_file)) { + $line = fgets($features_file, 8192); + if (!$line || (strpos($line, '#define') === false)) { + continue; + } + if (strpos($line, '__GLIBC__')) { + // major version number #define __GLIBC__ version + $line = preg_split('/\s+/', $line); + $glibc_major = trim($line[2]); + if (isset($glibc_minor)) { + break; + } + continue; + } + if (strpos($line, '__GLIBC_MINOR__')) { + // got the minor version number + // #define __GLIBC_MINOR__ version + $line = preg_split('/\s+/', $line); + $glibc_minor = trim($line[2]); + if (isset($glibc_major)) { + break; + } + continue; + } + } + fclose($features_file); + if (!isset($glibc_major) || !isset($glibc_minor)) { + return $glibc = ''; + } + return $glibc = 'glibc' . trim($glibc_major) . "." . trim($glibc_minor) ; + } // no cpp + $tmpfile = System::mktemp("glibctest"); + $fp = fopen($tmpfile, "w"); + fwrite($fp, "#include \n__GLIBC__ __GLIBC_MINOR__\n"); + fclose($fp); + $cpp = popen("/usr/bin/cpp $tmpfile", "r"); + while ($line = fgets($cpp, 1024)) { + if ($line{0} == '#' || trim($line) == '') { + continue; + } + if (list($major, $minor) = explode(' ', trim($line))) { + break; + } + } + pclose($cpp); + unlink($tmpfile); + } // features.h + if (!($major && $minor) && @is_link('/lib/libc.so.6')) { + // Let's try reading the libc.so.6 symlink + if (ereg('^libc-(.*)\.so$', basename(readlink('/lib/libc.so.6')), $matches)) { + list($major, $minor) = explode('.', $matches[1]); + } + } + if (!($major && $minor)) { + return $glibc = ''; + } + return $glibc = "glibc{$major}.{$minor}"; + } + + function getSignature() + { + if (empty($this->extra)) { + return "{$this->sysname}-{$this->release}-{$this->cpu}"; + } + return "{$this->sysname}-{$this->release}-{$this->cpu}-{$this->extra}"; + } + + function getSysname() + { + return $this->sysname; + } + + function getNodename() + { + return $this->nodename; + } + + function getCpu() + { + return $this->cpu; + } + + function getRelease() + { + return $this->release; + } + + function getExtra() + { + return $this->extra; + } + + function matchSignature($match) + { + if (is_array($match)) { + $fragments = $match; + } else { + $fragments = explode('-', $match); + } + $n = count($fragments); + $matches = 0; + if ($n > 0) { + $matches += $this->_matchFragment($fragments[0], $this->sysname); + } + if ($n > 1) { + $matches += $this->_matchFragment($fragments[1], $this->release); + } + if ($n > 2) { + $matches += $this->_matchFragment($fragments[2], $this->cpu); + } + if ($n > 3) { + $matches += $this->_matchFragment($fragments[3], $this->extra); + } + return ($matches == $n); + } + + function _matchFragment($fragment, $value) + { + if (strcspn($fragment, '*?') < strlen($fragment)) { + $reg = '^' . str_replace(array('*', '?', '/'), array('.*', '.', '\\/'), $fragment) . '$'; + return eregi($reg, $value); + } + return ($fragment == '*' || !strcasecmp($fragment, $value)); + } + +} +/* + * Local Variables: + * indent-tabs-mode: nil + * c-basic-offset: 4 + * End: + */ +?> diff --git a/src/lib/pear/PEAR/PEAR.php b/src/lib/pear/PEAR/PEAR.php new file mode 100644 index 0000000..4c24c60 --- /dev/null +++ b/src/lib/pear/PEAR/PEAR.php @@ -0,0 +1,1118 @@ + + * @author Stig Bakken + * @author Tomas V.V.Cox + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: PEAR.php,v 1.104 2008/01/03 20:26:34 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 0.1 + */ + +/**#@+ + * ERROR constants + */ +define('PEAR_ERROR_RETURN', 1); +define('PEAR_ERROR_PRINT', 2); +define('PEAR_ERROR_TRIGGER', 4); +define('PEAR_ERROR_DIE', 8); +define('PEAR_ERROR_CALLBACK', 16); +/** + * WARNING: obsolete + * @deprecated + */ +define('PEAR_ERROR_EXCEPTION', 32); +/**#@-*/ +define('PEAR_ZE2', (function_exists('version_compare') && + version_compare(zend_version(), "2-dev", "ge"))); + +if (substr(PHP_OS, 0, 3) == 'WIN') { + define('OS_WINDOWS', true); + define('OS_UNIX', false); + define('PEAR_OS', 'Windows'); +} else { + define('OS_WINDOWS', false); + define('OS_UNIX', true); + define('PEAR_OS', 'Unix'); // blatant assumption +} + +// instant backwards compatibility +if (!defined('PATH_SEPARATOR')) { + if (OS_WINDOWS) { + define('PATH_SEPARATOR', ';'); + } else { + define('PATH_SEPARATOR', ':'); + } +} + +$GLOBALS['_PEAR_default_error_mode'] = PEAR_ERROR_RETURN; +$GLOBALS['_PEAR_default_error_options'] = E_USER_NOTICE; +$GLOBALS['_PEAR_destructor_object_list'] = array(); +$GLOBALS['_PEAR_shutdown_funcs'] = array(); +$GLOBALS['_PEAR_error_handler_stack'] = array(); + +@ini_set('track_errors', true); + +/** + * Base class for other PEAR classes. Provides rudimentary + * emulation of destructors. + * + * If you want a destructor in your class, inherit PEAR and make a + * destructor method called _yourclassname (same name as the + * constructor, but with a "_" prefix). Also, in your constructor you + * have to call the PEAR constructor: $this->PEAR();. + * The destructor method will be called without parameters. Note that + * at in some SAPI implementations (such as Apache), any output during + * the request shutdown (in which destructors are called) seems to be + * discarded. If you need to get any debug information from your + * destructor, use error_log(), syslog() or something similar. + * + * IMPORTANT! To use the emulated destructors you need to create the + * objects by reference: $obj =& new PEAR_child; + * + * @category pear + * @package PEAR + * @author Stig Bakken + * @author Tomas V.V. Cox + * @author Greg Beaver + * @copyright 1997-2006 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @see PEAR_Error + * @since Class available since PHP 4.0.2 + * @link http://pear.php.net/manual/en/core.pear.php#core.pear.pear + */ +class PEAR +{ + // {{{ properties + + /** + * Whether to enable internal debug messages. + * + * @var bool + * @access private + */ + var $_debug = false; + + /** + * Default error mode for this object. + * + * @var int + * @access private + */ + var $_default_error_mode = null; + + /** + * Default error options used for this object when error mode + * is PEAR_ERROR_TRIGGER. + * + * @var int + * @access private + */ + var $_default_error_options = null; + + /** + * Default error handler (callback) for this object, if error mode is + * PEAR_ERROR_CALLBACK. + * + * @var string + * @access private + */ + var $_default_error_handler = ''; + + /** + * Which class to use for error objects. + * + * @var string + * @access private + */ + var $_error_class = 'PEAR_Error'; + + /** + * An array of expected errors. + * + * @var array + * @access private + */ + var $_expected_errors = array(); + + // }}} + + // {{{ constructor + + /** + * Constructor. Registers this object in + * $_PEAR_destructor_object_list for destructor emulation if a + * destructor object exists. + * + * @param string $error_class (optional) which class to use for + * error objects, defaults to PEAR_Error. + * @access public + * @return void + */ + function PEAR($error_class = null) + { + $classname = strtolower(get_class($this)); + if ($this->_debug) { + print "PEAR constructor called, class=$classname\n"; + } + if ($error_class !== null) { + $this->_error_class = $error_class; + } + while ($classname && strcasecmp($classname, "pear")) { + $destructor = "_$classname"; + if (method_exists($this, $destructor)) { + global $_PEAR_destructor_object_list; + $_PEAR_destructor_object_list[] = &$this; + if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) { + register_shutdown_function("_PEAR_call_destructors"); + $GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true; + } + break; + } else { + $classname = get_parent_class($classname); + } + } + } + + // }}} + // {{{ destructor + + /** + * Destructor (the emulated type of...). Does nothing right now, + * but is included for forward compatibility, so subclass + * destructors should always call it. + * + * See the note in the class desciption about output from + * destructors. + * + * @access public + * @return void + */ + function _PEAR() { + if ($this->_debug) { + printf("PEAR destructor called, class=%s\n", strtolower(get_class($this))); + } + } + + // }}} + // {{{ getStaticProperty() + + /** + * If you have a class that's mostly/entirely static, and you need static + * properties, you can use this method to simulate them. Eg. in your method(s) + * do this: $myVar = &PEAR::getStaticProperty('myclass', 'myVar'); + * You MUST use a reference, or they will not persist! + * + * @access public + * @param string $class The calling classname, to prevent clashes + * @param string $var The variable to retrieve. + * @return mixed A reference to the variable. If not set it will be + * auto initialised to NULL. + */ + function &getStaticProperty($class, $var) + { + static $properties; + if (!isset($properties[$class])) { + $properties[$class] = array(); + } + if (!array_key_exists($var, $properties[$class])) { + $properties[$class][$var] = null; + } + return $properties[$class][$var]; + } + + // }}} + // {{{ registerShutdownFunc() + + /** + * Use this function to register a shutdown method for static + * classes. + * + * @access public + * @param mixed $func The function name (or array of class/method) to call + * @param mixed $args The arguments to pass to the function + * @return void + */ + function registerShutdownFunc($func, $args = array()) + { + // if we are called statically, there is a potential + // that no shutdown func is registered. Bug #6445 + if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) { + register_shutdown_function("_PEAR_call_destructors"); + $GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true; + } + $GLOBALS['_PEAR_shutdown_funcs'][] = array($func, $args); + } + + // }}} + // {{{ isError() + + /** + * Tell whether a value is a PEAR error. + * + * @param mixed $data the value to test + * @param int $code if $data is an error object, return true + * only if $code is a string and + * $obj->getMessage() == $code or + * $code is an integer and $obj->getCode() == $code + * @access public + * @return bool true if parameter is an error + */ + function isError($data, $code = null) + { + if (is_a($data, 'PEAR_Error')) { + if (is_null($code)) { + return true; + } elseif (is_string($code)) { + return $data->getMessage() == $code; + } else { + return $data->getCode() == $code; + } + } + return false; + } + + // }}} + // {{{ setErrorHandling() + + /** + * Sets how errors generated by this object should be handled. + * Can be invoked both in objects and statically. If called + * statically, setErrorHandling sets the default behaviour for all + * PEAR objects. If called in an object, setErrorHandling sets + * the default behaviour for that object. + * + * @param int $mode + * One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT, + * PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE, + * PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION. + * + * @param mixed $options + * When $mode is PEAR_ERROR_TRIGGER, this is the error level (one + * of E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR). + * + * When $mode is PEAR_ERROR_CALLBACK, this parameter is expected + * to be the callback function or method. A callback + * function is a string with the name of the function, a + * callback method is an array of two elements: the element + * at index 0 is the object, and the element at index 1 is + * the name of the method to call in the object. + * + * When $mode is PEAR_ERROR_PRINT or PEAR_ERROR_DIE, this is + * a printf format string used when printing the error + * message. + * + * @access public + * @return void + * @see PEAR_ERROR_RETURN + * @see PEAR_ERROR_PRINT + * @see PEAR_ERROR_TRIGGER + * @see PEAR_ERROR_DIE + * @see PEAR_ERROR_CALLBACK + * @see PEAR_ERROR_EXCEPTION + * + * @since PHP 4.0.5 + */ + + function setErrorHandling($mode = null, $options = null) + { + if (isset($this) && is_a($this, 'PEAR')) { + $setmode = &$this->_default_error_mode; + $setoptions = &$this->_default_error_options; + } else { + $setmode = &$GLOBALS['_PEAR_default_error_mode']; + $setoptions = &$GLOBALS['_PEAR_default_error_options']; + } + + switch ($mode) { + case PEAR_ERROR_EXCEPTION: + case PEAR_ERROR_RETURN: + case PEAR_ERROR_PRINT: + case PEAR_ERROR_TRIGGER: + case PEAR_ERROR_DIE: + case null: + $setmode = $mode; + $setoptions = $options; + break; + + case PEAR_ERROR_CALLBACK: + $setmode = $mode; + // class/object method callback + if (is_callable($options)) { + $setoptions = $options; + } else { + trigger_error("invalid error callback", E_USER_WARNING); + } + break; + + default: + trigger_error("invalid error mode", E_USER_WARNING); + break; + } + } + + // }}} + // {{{ expectError() + + /** + * This method is used to tell which errors you expect to get. + * Expected errors are always returned with error mode + * PEAR_ERROR_RETURN. Expected error codes are stored in a stack, + * and this method pushes a new element onto it. The list of + * expected errors are in effect until they are popped off the + * stack with the popExpect() method. + * + * Note that this method can not be called statically + * + * @param mixed $code a single error code or an array of error codes to expect + * + * @return int the new depth of the "expected errors" stack + * @access public + */ + function expectError($code = '*') + { + if (is_array($code)) { + array_push($this->_expected_errors, $code); + } else { + array_push($this->_expected_errors, array($code)); + } + return sizeof($this->_expected_errors); + } + + // }}} + // {{{ popExpect() + + /** + * This method pops one element off the expected error codes + * stack. + * + * @return array the list of error codes that were popped + */ + function popExpect() + { + return array_pop($this->_expected_errors); + } + + // }}} + // {{{ _checkDelExpect() + + /** + * This method checks unsets an error code if available + * + * @param mixed error code + * @return bool true if the error code was unset, false otherwise + * @access private + * @since PHP 4.3.0 + */ + function _checkDelExpect($error_code) + { + $deleted = false; + + foreach ($this->_expected_errors AS $key => $error_array) { + if (in_array($error_code, $error_array)) { + unset($this->_expected_errors[$key][array_search($error_code, $error_array)]); + $deleted = true; + } + + // clean up empty arrays + if (0 == count($this->_expected_errors[$key])) { + unset($this->_expected_errors[$key]); + } + } + return $deleted; + } + + // }}} + // {{{ delExpect() + + /** + * This method deletes all occurences of the specified element from + * the expected error codes stack. + * + * @param mixed $error_code error code that should be deleted + * @return mixed list of error codes that were deleted or error + * @access public + * @since PHP 4.3.0 + */ + function delExpect($error_code) + { + $deleted = false; + + if ((is_array($error_code) && (0 != count($error_code)))) { + // $error_code is a non-empty array here; + // we walk through it trying to unset all + // values + foreach($error_code as $key => $error) { + if ($this->_checkDelExpect($error)) { + $deleted = true; + } else { + $deleted = false; + } + } + return $deleted ? true : PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME + } elseif (!empty($error_code)) { + // $error_code comes alone, trying to unset it + if ($this->_checkDelExpect($error_code)) { + return true; + } else { + return PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME + } + } else { + // $error_code is empty + return PEAR::raiseError("The expected error you submitted is empty"); // IMPROVE ME + } + } + + // }}} + // {{{ raiseError() + + /** + * This method is a wrapper that returns an instance of the + * configured error class with this object's default error + * handling applied. If the $mode and $options parameters are not + * specified, the object's defaults are used. + * + * @param mixed $message a text error message or a PEAR error object + * + * @param int $code a numeric error code (it is up to your class + * to define these if you want to use codes) + * + * @param int $mode One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT, + * PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE, + * PEAR_ERROR_CALLBACK, PEAR_ERROR_EXCEPTION. + * + * @param mixed $options If $mode is PEAR_ERROR_TRIGGER, this parameter + * specifies the PHP-internal error level (one of + * E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR). + * If $mode is PEAR_ERROR_CALLBACK, this + * parameter specifies the callback function or + * method. In other error modes this parameter + * is ignored. + * + * @param string $userinfo If you need to pass along for example debug + * information, this parameter is meant for that. + * + * @param string $error_class The returned error object will be + * instantiated from this class, if specified. + * + * @param bool $skipmsg If true, raiseError will only pass error codes, + * the error message parameter will be dropped. + * + * @access public + * @return object a PEAR error object + * @see PEAR::setErrorHandling + * @since PHP 4.0.5 + */ + function &raiseError($message = null, + $code = null, + $mode = null, + $options = null, + $userinfo = null, + $error_class = null, + $skipmsg = false) + { + // The error is yet a PEAR error object + if (is_object($message)) { + $code = $message->getCode(); + $userinfo = $message->getUserInfo(); + $error_class = $message->getType(); + $message->error_message_prefix = ''; + $message = $message->getMessage(); + } + + if (isset($this) && isset($this->_expected_errors) && sizeof($this->_expected_errors) > 0 && sizeof($exp = end($this->_expected_errors))) { + if ($exp[0] == "*" || + (is_int(reset($exp)) && in_array($code, $exp)) || + (is_string(reset($exp)) && in_array($message, $exp))) { + $mode = PEAR_ERROR_RETURN; + } + } + // No mode given, try global ones + if ($mode === null) { + // Class error handler + if (isset($this) && isset($this->_default_error_mode)) { + $mode = $this->_default_error_mode; + $options = $this->_default_error_options; + // Global error handler + } elseif (isset($GLOBALS['_PEAR_default_error_mode'])) { + $mode = $GLOBALS['_PEAR_default_error_mode']; + $options = $GLOBALS['_PEAR_default_error_options']; + } + } + + if ($error_class !== null) { + $ec = $error_class; + } elseif (isset($this) && isset($this->_error_class)) { + $ec = $this->_error_class; + } else { + $ec = 'PEAR_Error'; + } + if (intval(PHP_VERSION) < 5) { + // little non-eval hack to fix bug #12147 + include 'PEAR/FixPHP5PEARWarnings.php'; + return $a; + } + if ($skipmsg) { + $a = new $ec($code, $mode, $options, $userinfo); + } else { + $a = new $ec($message, $code, $mode, $options, $userinfo); + } + return $a; + } + + // }}} + // {{{ throwError() + + /** + * Simpler form of raiseError with fewer options. In most cases + * message, code and userinfo are enough. + * + * @param string $message + * + */ + function &throwError($message = null, + $code = null, + $userinfo = null) + { + if (isset($this) && is_a($this, 'PEAR')) { + $a = &$this->raiseError($message, $code, null, null, $userinfo); + return $a; + } else { + $a = &PEAR::raiseError($message, $code, null, null, $userinfo); + return $a; + } + } + + // }}} + function staticPushErrorHandling($mode, $options = null) + { + $stack = &$GLOBALS['_PEAR_error_handler_stack']; + $def_mode = &$GLOBALS['_PEAR_default_error_mode']; + $def_options = &$GLOBALS['_PEAR_default_error_options']; + $stack[] = array($def_mode, $def_options); + switch ($mode) { + case PEAR_ERROR_EXCEPTION: + case PEAR_ERROR_RETURN: + case PEAR_ERROR_PRINT: + case PEAR_ERROR_TRIGGER: + case PEAR_ERROR_DIE: + case null: + $def_mode = $mode; + $def_options = $options; + break; + + case PEAR_ERROR_CALLBACK: + $def_mode = $mode; + // class/object method callback + if (is_callable($options)) { + $def_options = $options; + } else { + trigger_error("invalid error callback", E_USER_WARNING); + } + break; + + default: + trigger_error("invalid error mode", E_USER_WARNING); + break; + } + $stack[] = array($mode, $options); + return true; + } + + function staticPopErrorHandling() + { + $stack = &$GLOBALS['_PEAR_error_handler_stack']; + $setmode = &$GLOBALS['_PEAR_default_error_mode']; + $setoptions = &$GLOBALS['_PEAR_default_error_options']; + array_pop($stack); + list($mode, $options) = $stack[sizeof($stack) - 1]; + array_pop($stack); + switch ($mode) { + case PEAR_ERROR_EXCEPTION: + case PEAR_ERROR_RETURN: + case PEAR_ERROR_PRINT: + case PEAR_ERROR_TRIGGER: + case PEAR_ERROR_DIE: + case null: + $setmode = $mode; + $setoptions = $options; + break; + + case PEAR_ERROR_CALLBACK: + $setmode = $mode; + // class/object method callback + if (is_callable($options)) { + $setoptions = $options; + } else { + trigger_error("invalid error callback", E_USER_WARNING); + } + break; + + default: + trigger_error("invalid error mode", E_USER_WARNING); + break; + } + return true; + } + + // {{{ pushErrorHandling() + + /** + * Push a new error handler on top of the error handler options stack. With this + * you can easily override the actual error handler for some code and restore + * it later with popErrorHandling. + * + * @param mixed $mode (same as setErrorHandling) + * @param mixed $options (same as setErrorHandling) + * + * @return bool Always true + * + * @see PEAR::setErrorHandling + */ + function pushErrorHandling($mode, $options = null) + { + $stack = &$GLOBALS['_PEAR_error_handler_stack']; + if (isset($this) && is_a($this, 'PEAR')) { + $def_mode = &$this->_default_error_mode; + $def_options = &$this->_default_error_options; + } else { + $def_mode = &$GLOBALS['_PEAR_default_error_mode']; + $def_options = &$GLOBALS['_PEAR_default_error_options']; + } + $stack[] = array($def_mode, $def_options); + + if (isset($this) && is_a($this, 'PEAR')) { + $this->setErrorHandling($mode, $options); + } else { + PEAR::setErrorHandling($mode, $options); + } + $stack[] = array($mode, $options); + return true; + } + + // }}} + // {{{ popErrorHandling() + + /** + * Pop the last error handler used + * + * @return bool Always true + * + * @see PEAR::pushErrorHandling + */ + function popErrorHandling() + { + $stack = &$GLOBALS['_PEAR_error_handler_stack']; + array_pop($stack); + list($mode, $options) = $stack[sizeof($stack) - 1]; + array_pop($stack); + if (isset($this) && is_a($this, 'PEAR')) { + $this->setErrorHandling($mode, $options); + } else { + PEAR::setErrorHandling($mode, $options); + } + return true; + } + + // }}} + // {{{ loadExtension() + + /** + * OS independant PHP extension load. Remember to take care + * on the correct extension name for case sensitive OSes. + * + * @param string $ext The extension name + * @return bool Success or not on the dl() call + */ + function loadExtension($ext) + { + if (!extension_loaded($ext)) { + // if either returns true dl() will produce a FATAL error, stop that + if ((ini_get('enable_dl') != 1) || (ini_get('safe_mode') == 1)) { + return false; + } + if (OS_WINDOWS) { + $suffix = '.dll'; + } elseif (PHP_OS == 'HP-UX') { + $suffix = '.sl'; + } elseif (PHP_OS == 'AIX') { + $suffix = '.a'; + } elseif (PHP_OS == 'OSX') { + $suffix = '.bundle'; + } else { + $suffix = '.so'; + } + return @dl('php_'.$ext.$suffix) || @dl($ext.$suffix); + } + return true; + } + + // }}} +} + +// {{{ _PEAR_call_destructors() + +function _PEAR_call_destructors() +{ + global $_PEAR_destructor_object_list; + if (is_array($_PEAR_destructor_object_list) && + sizeof($_PEAR_destructor_object_list)) + { + reset($_PEAR_destructor_object_list); + if (PEAR::getStaticProperty('PEAR', 'destructlifo')) { + $_PEAR_destructor_object_list = array_reverse($_PEAR_destructor_object_list); + } + while (list($k, $objref) = each($_PEAR_destructor_object_list)) { + $classname = get_class($objref); + while ($classname) { + $destructor = "_$classname"; + if (method_exists($objref, $destructor)) { + $objref->$destructor(); + break; + } else { + $classname = get_parent_class($classname); + } + } + } + // Empty the object list to ensure that destructors are + // not called more than once. + $_PEAR_destructor_object_list = array(); + } + + // Now call the shutdown functions + if (is_array($GLOBALS['_PEAR_shutdown_funcs']) AND !empty($GLOBALS['_PEAR_shutdown_funcs'])) { + foreach ($GLOBALS['_PEAR_shutdown_funcs'] as $value) { + call_user_func_array($value[0], $value[1]); + } + } +} + +// }}} +/** + * Standard PEAR error class for PHP 4 + * + * This class is supserseded by {@link PEAR_Exception} in PHP 5 + * + * @category pear + * @package PEAR + * @author Stig Bakken + * @author Tomas V.V. Cox + * @author Gregory Beaver + * @copyright 1997-2006 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/manual/en/core.pear.pear-error.php + * @see PEAR::raiseError(), PEAR::throwError() + * @since Class available since PHP 4.0.2 + */ +class PEAR_Error +{ + // {{{ properties + + var $error_message_prefix = ''; + var $mode = PEAR_ERROR_RETURN; + var $level = E_USER_NOTICE; + var $code = -1; + var $message = ''; + var $userinfo = ''; + var $backtrace = null; + + // }}} + // {{{ constructor + + /** + * PEAR_Error constructor + * + * @param string $message message + * + * @param int $code (optional) error code + * + * @param int $mode (optional) error mode, one of: PEAR_ERROR_RETURN, + * PEAR_ERROR_PRINT, PEAR_ERROR_DIE, PEAR_ERROR_TRIGGER, + * PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION + * + * @param mixed $options (optional) error level, _OR_ in the case of + * PEAR_ERROR_CALLBACK, the callback function or object/method + * tuple. + * + * @param string $userinfo (optional) additional user/debug info + * + * @access public + * + */ + function PEAR_Error($message = 'unknown error', $code = null, + $mode = null, $options = null, $userinfo = null) + { + if ($mode === null) { + $mode = PEAR_ERROR_RETURN; + } + $this->message = $message; + $this->code = $code; + $this->mode = $mode; + $this->userinfo = $userinfo; + if (!PEAR::getStaticProperty('PEAR_Error', 'skiptrace')) { + $this->backtrace = debug_backtrace(); + if (isset($this->backtrace[0]) && isset($this->backtrace[0]['object'])) { + unset($this->backtrace[0]['object']); + } + } + if ($mode & PEAR_ERROR_CALLBACK) { + $this->level = E_USER_NOTICE; + $this->callback = $options; + } else { + if ($options === null) { + $options = E_USER_NOTICE; + } + $this->level = $options; + $this->callback = null; + } + if ($this->mode & PEAR_ERROR_PRINT) { + if (is_null($options) || is_int($options)) { + $format = "%s"; + } else { + $format = $options; + } + printf($format, $this->getMessage()); + } + if ($this->mode & PEAR_ERROR_TRIGGER) { + trigger_error($this->getMessage(), $this->level); + } + if ($this->mode & PEAR_ERROR_DIE) { + $msg = $this->getMessage(); + if (is_null($options) || is_int($options)) { + $format = "%s"; + if (substr($msg, -1) != "\n") { + $msg .= "\n"; + } + } else { + $format = $options; + } + die(sprintf($format, $msg)); + } + if ($this->mode & PEAR_ERROR_CALLBACK) { + if (is_callable($this->callback)) { + call_user_func($this->callback, $this); + } + } + if ($this->mode & PEAR_ERROR_EXCEPTION) { + trigger_error("PEAR_ERROR_EXCEPTION is obsolete, use class PEAR_Exception for exceptions", E_USER_WARNING); + eval('$e = new Exception($this->message, $this->code);throw($e);'); + } + } + + // }}} + // {{{ getMode() + + /** + * Get the error mode from an error object. + * + * @return int error mode + * @access public + */ + function getMode() { + return $this->mode; + } + + // }}} + // {{{ getCallback() + + /** + * Get the callback function/method from an error object. + * + * @return mixed callback function or object/method array + * @access public + */ + function getCallback() { + return $this->callback; + } + + // }}} + // {{{ getMessage() + + + /** + * Get the error message from an error object. + * + * @return string full error message + * @access public + */ + function getMessage() + { + return ($this->error_message_prefix . $this->message); + } + + + // }}} + // {{{ getCode() + + /** + * Get error code from an error object + * + * @return int error code + * @access public + */ + function getCode() + { + return $this->code; + } + + // }}} + // {{{ getType() + + /** + * Get the name of this error/exception. + * + * @return string error/exception name (type) + * @access public + */ + function getType() + { + return get_class($this); + } + + // }}} + // {{{ getUserInfo() + + /** + * Get additional user-supplied information. + * + * @return string user-supplied information + * @access public + */ + function getUserInfo() + { + return $this->userinfo; + } + + // }}} + // {{{ getDebugInfo() + + /** + * Get additional debug information supplied by the application. + * + * @return string debug information + * @access public + */ + function getDebugInfo() + { + return $this->getUserInfo(); + } + + // }}} + // {{{ getBacktrace() + + /** + * Get the call backtrace from where the error was generated. + * Supported with PHP 4.3.0 or newer. + * + * @param int $frame (optional) what frame to fetch + * @return array Backtrace, or NULL if not available. + * @access public + */ + function getBacktrace($frame = null) + { + if (defined('PEAR_IGNORE_BACKTRACE')) { + return null; + } + if ($frame === null) { + return $this->backtrace; + } + return $this->backtrace[$frame]; + } + + // }}} + // {{{ addUserInfo() + + function addUserInfo($info) + { + if (empty($this->userinfo)) { + $this->userinfo = $info; + } else { + $this->userinfo .= " ** $info"; + } + } + + // }}} + // {{{ toString() + function __toString() + { + return $this->getMessage(); + } + // }}} + // {{{ toString() + + /** + * Make a string representation of this object. + * + * @return string a string with an object summary + * @access public + */ + function toString() { + $modes = array(); + $levels = array(E_USER_NOTICE => 'notice', + E_USER_WARNING => 'warning', + E_USER_ERROR => 'error'); + if ($this->mode & PEAR_ERROR_CALLBACK) { + if (is_array($this->callback)) { + $callback = (is_object($this->callback[0]) ? + strtolower(get_class($this->callback[0])) : + $this->callback[0]) . '::' . + $this->callback[1]; + } else { + $callback = $this->callback; + } + return sprintf('[%s: message="%s" code=%d mode=callback '. + 'callback=%s prefix="%s" info="%s"]', + strtolower(get_class($this)), $this->message, $this->code, + $callback, $this->error_message_prefix, + $this->userinfo); + } + if ($this->mode & PEAR_ERROR_PRINT) { + $modes[] = 'print'; + } + if ($this->mode & PEAR_ERROR_TRIGGER) { + $modes[] = 'trigger'; + } + if ($this->mode & PEAR_ERROR_DIE) { + $modes[] = 'die'; + } + if ($this->mode & PEAR_ERROR_RETURN) { + $modes[] = 'return'; + } + return sprintf('[%s: message="%s" code=%d mode=%s level=%s '. + 'prefix="%s" info="%s"]', + strtolower(get_class($this)), $this->message, $this->code, + implode("|", $modes), $levels[$this->level], + $this->error_message_prefix, + $this->userinfo); + } + + // }}} +} + +/* + * Local Variables: + * mode: php + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ +?> diff --git a/src/lib/pear/PEAR/PEAR/Autoloader.php b/src/lib/pear/PEAR/PEAR/Autoloader.php new file mode 100644 index 0000000..07c4de1 --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Autoloader.php @@ -0,0 +1,223 @@ + + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: Autoloader.php,v 1.14 2008/01/03 20:26:34 cellog Exp $ + * @link http://pear.php.net/manual/en/core.ppm.php#core.ppm.pear-autoloader + * @since File available since Release 0.1 + * @deprecated File deprecated in Release 1.4.0a1 + */ + +// /* vim: set expandtab tabstop=4 shiftwidth=4: */ + +if (!extension_loaded("overload")) { + // die hard without ext/overload + die("Rebuild PHP with the `overload' extension to use PEAR_Autoloader"); +} + +/** + * Include for PEAR_Error and PEAR classes + */ +require_once "PEAR.php"; + +/** + * This class is for objects where you want to separate the code for + * some methods into separate classes. This is useful if you have a + * class with not-frequently-used methods that contain lots of code + * that you would like to avoid always parsing. + * + * The PEAR_Autoloader class provides autoloading and aggregation. + * The autoloading lets you set up in which classes the separated + * methods are found. Aggregation is the technique used to import new + * methods, an instance of each class providing separated methods is + * stored and called every time the aggregated method is called. + * + * @category pear + * @package PEAR + * @author Stig Bakken + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/manual/en/core.ppm.php#core.ppm.pear-autoloader + * @since File available since Release 0.1 + * @deprecated File deprecated in Release 1.4.0a1 + */ +class PEAR_Autoloader extends PEAR +{ + // {{{ properties + + /** + * Map of methods and classes where they are defined + * + * @var array + * + * @access private + */ + var $_autoload_map = array(); + + /** + * Map of methods and aggregate objects + * + * @var array + * + * @access private + */ + var $_method_map = array(); + + // }}} + // {{{ addAutoload() + + /** + * Add one or more autoload entries. + * + * @param string $method which method to autoload + * + * @param string $classname (optional) which class to find the method in. + * If the $method parameter is an array, this + * parameter may be omitted (and will be ignored + * if not), and the $method parameter will be + * treated as an associative array with method + * names as keys and class names as values. + * + * @return void + * + * @access public + */ + function addAutoload($method, $classname = null) + { + if (is_array($method)) { + array_walk($method, create_function('$a,&$b', '$b = strtolower($b);')); + $this->_autoload_map = array_merge($this->_autoload_map, $method); + } else { + $this->_autoload_map[strtolower($method)] = $classname; + } + } + + // }}} + // {{{ removeAutoload() + + /** + * Remove an autoload entry. + * + * @param string $method which method to remove the autoload entry for + * + * @return bool TRUE if an entry was removed, FALSE if not + * + * @access public + */ + function removeAutoload($method) + { + $method = strtolower($method); + $ok = isset($this->_autoload_map[$method]); + unset($this->_autoload_map[$method]); + return $ok; + } + + // }}} + // {{{ addAggregateObject() + + /** + * Add an aggregate object to this object. If the specified class + * is not defined, loading it will be attempted following PEAR's + * file naming scheme. All the methods in the class will be + * aggregated, except private ones (name starting with an + * underscore) and constructors. + * + * @param string $classname what class to instantiate for the object. + * + * @return void + * + * @access public + */ + function addAggregateObject($classname) + { + $classname = strtolower($classname); + if (!class_exists($classname)) { + $include_file = preg_replace('/[^a-z0-9]/i', '_', $classname); + include_once $include_file; + } + $obj =& new $classname; + $methods = get_class_methods($classname); + foreach ($methods as $method) { + // don't import priviate methods and constructors + if ($method{0} != '_' && $method != $classname) { + $this->_method_map[$method] = $obj; + } + } + } + + // }}} + // {{{ removeAggregateObject() + + /** + * Remove an aggregate object. + * + * @param string $classname the class of the object to remove + * + * @return bool TRUE if an object was removed, FALSE if not + * + * @access public + */ + function removeAggregateObject($classname) + { + $ok = false; + $classname = strtolower($classname); + reset($this->_method_map); + while (list($method, $obj) = each($this->_method_map)) { + if (is_a($obj, $classname)) { + unset($this->_method_map[$method]); + $ok = true; + } + } + return $ok; + } + + // }}} + // {{{ __call() + + /** + * Overloaded object call handler, called each time an + * undefined/aggregated method is invoked. This method repeats + * the call in the right aggregate object and passes on the return + * value. + * + * @param string $method which method that was called + * + * @param string $args An array of the parameters passed in the + * original call + * + * @return mixed The return value from the aggregated method, or a PEAR + * error if the called method was unknown. + */ + function __call($method, $args, &$retval) + { + $method = strtolower($method); + if (empty($this->_method_map[$method]) && isset($this->_autoload_map[$method])) { + $this->addAggregateObject($this->_autoload_map[$method]); + } + if (isset($this->_method_map[$method])) { + $retval = call_user_func_array(array($this->_method_map[$method], $method), $args); + return true; + } + return false; + } + + // }}} +} + +overload("PEAR_Autoloader"); + +?> diff --git a/src/lib/pear/PEAR/PEAR/Builder.php b/src/lib/pear/PEAR/PEAR/Builder.php new file mode 100644 index 0000000..f7986c0 --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Builder.php @@ -0,0 +1,486 @@ + + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: Builder.php,v 1.34 2008/05/12 23:43:21 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 0.1 + * + * TODO: log output parameters in PECL command line + * TODO: msdev path in configuration + */ + +/** + * Needed for extending PEAR_Builder + */ +require_once 'PEAR/Common.php'; +require_once 'PEAR/PackageFile.php'; +/** + * Class to handle building (compiling) extensions. + * + * @category pear + * @package PEAR + * @author Stig Bakken + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since PHP 4.0.2 + * @see http://pear.php.net/manual/en/core.ppm.pear-builder.php + */ +class PEAR_Builder extends PEAR_Common +{ + // {{{ properties + + var $php_api_version = 0; + var $zend_module_api_no = 0; + var $zend_extension_api_no = 0; + + var $extensions_built = array(); + + /** + * @var string Used for reporting when it is not possible to pass function + * via extra parameter, e.g. log, msdevCallback + */ + var $current_callback = null; + + // used for msdev builds + var $_lastline = null; + var $_firstline = null; + // }}} + // {{{ constructor + + /** + * PEAR_Builder constructor. + * + * @param object $ui user interface object (instance of PEAR_Frontend_*) + * + * @access public + */ + function PEAR_Builder(&$ui) + { + parent::PEAR_Common(); + $this->setFrontendObject($ui); + } + + // }}} + + // {{{ _build_win32() + + /** + * Build an extension from source on windows. + * requires msdev + */ + function _build_win32($descfile, $callback = null) + { + if (is_object($descfile)) { + $pkg = $descfile; + $descfile = $pkg->getPackageFile(); + } else { + $pf = &new PEAR_PackageFile($this->config, $this->debug); + $pkg = &$pf->fromPackageFile($descfile, PEAR_VALIDATE_NORMAL); + if (PEAR::isError($pkg)) { + return $pkg; + } + } + $dir = dirname($descfile); + $old_cwd = getcwd(); + + if (!file_exists($dir) || !is_dir($dir) || !chdir($dir)) { + return $this->raiseError("could not chdir to $dir"); + } + // packages that were in a .tar have the packagefile in this directory + $vdir = $pkg->getPackage() . '-' . $pkg->getVersion(); + if (file_exists($dir) && is_dir($vdir)) { + if (chdir($vdir)) { + $dir = getcwd(); + } else { + return $this->raiseError("could not chdir to " . realpath($vdir)); + } + } + + $this->log(2, "building in $dir"); + + $dsp = $pkg->getPackage().'.dsp'; + if (!file_exists("$dir/$dsp")) { + return $this->raiseError("The DSP $dsp does not exist."); + } + // XXX TODO: make release build type configurable + $command = 'msdev '.$dsp.' /MAKE "'.$pkg->getPackage(). ' - Release"'; + + $err = $this->_runCommand($command, array(&$this, 'msdevCallback')); + if (PEAR::isError($err)) { + return $err; + } + + // figure out the build platform and type + $platform = 'Win32'; + $buildtype = 'Release'; + if (preg_match('/.*?'.$pkg->getPackage().'\s-\s(\w+)\s(.*?)-+/i',$this->_firstline,$matches)) { + $platform = $matches[1]; + $buildtype = $matches[2]; + } + + if (preg_match('/(.*)?\s-\s(\d+).*?(\d+)/',$this->_lastline,$matches)) { + if ($matches[2]) { + // there were errors in the build + return $this->raiseError("There were errors during compilation."); + } + $out = $matches[1]; + } else { + return $this->raiseError("Did not understand the completion status returned from msdev.exe."); + } + + // msdev doesn't tell us the output directory :/ + // open the dsp, find /out and use that directory + $dsptext = join(file($dsp),''); + + // this regex depends on the build platform and type having been + // correctly identified above. + $regex ='/.*?!IF\s+"\$\(CFG\)"\s+==\s+("'. + $pkg->getPackage().'\s-\s'. + $platform.'\s'. + $buildtype.'").*?'. + '\/out:"(.*?)"/is'; + + if ($dsptext && preg_match($regex,$dsptext,$matches)) { + // what we get back is a relative path to the output file itself. + $outfile = realpath($matches[2]); + } else { + return $this->raiseError("Could not retrieve output information from $dsp."); + } + // realpath returns false if the file doesn't exist + if ($outfile && copy($outfile, "$dir/$out")) { + $outfile = "$dir/$out"; + } + + $built_files[] = array( + 'file' => "$outfile", + 'php_api' => $this->php_api_version, + 'zend_mod_api' => $this->zend_module_api_no, + 'zend_ext_api' => $this->zend_extension_api_no, + ); + + return $built_files; + } + // }}} + + // {{{ msdevCallback() + function msdevCallback($what, $data) + { + if (!$this->_firstline) + $this->_firstline = $data; + $this->_lastline = $data; + call_user_func($this->current_callback, $what, $data); + } + // }}} + + // {{{ _harventInstDir + /** + * @param string + * @param string + * @param array + * @access private + */ + function _harvestInstDir($dest_prefix, $dirname, &$built_files) + { + $d = opendir($dirname); + if (!$d) + return false; + + $ret = true; + while (($ent = readdir($d)) !== false) { + if ($ent{0} == '.') + continue; + + $full = $dirname . DIRECTORY_SEPARATOR . $ent; + if (is_dir($full)) { + if (!$this->_harvestInstDir( + $dest_prefix . DIRECTORY_SEPARATOR . $ent, + $full, $built_files)) { + $ret = false; + break; + } + } else { + $dest = $dest_prefix . DIRECTORY_SEPARATOR . $ent; + $built_files[] = array( + 'file' => $full, + 'dest' => $dest, + 'php_api' => $this->php_api_version, + 'zend_mod_api' => $this->zend_module_api_no, + 'zend_ext_api' => $this->zend_extension_api_no, + ); + } + } + closedir($d); + return $ret; + } + + // }}} + + // {{{ build() + + /** + * Build an extension from source. Runs "phpize" in the source + * directory, but compiles in a temporary directory + * (/var/tmp/pear-build-USER/PACKAGE-VERSION). + * + * @param string|PEAR_PackageFile_v* $descfile path to XML package description file, or + * a PEAR_PackageFile object + * + * @param mixed $callback callback function used to report output, + * see PEAR_Builder::_runCommand for details + * + * @return array an array of associative arrays with built files, + * format: + * array( array( 'file' => '/path/to/ext.so', + * 'php_api' => YYYYMMDD, + * 'zend_mod_api' => YYYYMMDD, + * 'zend_ext_api' => YYYYMMDD ), + * ... ) + * + * @access public + * + * @see PEAR_Builder::_runCommand + */ + function build($descfile, $callback = null) + { + $this->current_callback = $callback; + if (PEAR_OS == "Windows") { + return $this->_build_win32($descfile,$callback); + } + if (PEAR_OS != 'Unix') { + return $this->raiseError("building extensions not supported on this platform"); + } + if (is_object($descfile)) { + $pkg = $descfile; + $descfile = $pkg->getPackageFile(); + if (is_a($pkg, 'PEAR_PackageFile_v1')) { + $dir = dirname($descfile); + } else { + $dir = $pkg->_config->get('temp_dir') . '/' . $pkg->getName(); + // automatically delete at session end + $this->addTempFile($dir); + } + } else { + $pf = &new PEAR_PackageFile($this->config); + $pkg = &$pf->fromPackageFile($descfile, PEAR_VALIDATE_NORMAL); + if (PEAR::isError($pkg)) { + return $pkg; + } + $dir = dirname($descfile); + } + $old_cwd = getcwd(); + if (!file_exists($dir) || !is_dir($dir) || !chdir($dir)) { + return $this->raiseError("could not chdir to $dir"); + } + $vdir = $pkg->getPackage() . '-' . $pkg->getVersion(); + if (is_dir($vdir)) { + chdir($vdir); + } + $dir = getcwd(); + $this->log(2, "building in $dir"); + putenv('PATH=' . $this->config->get('bin_dir') . ':' . getenv('PATH')); + $err = $this->_runCommand("phpize", array(&$this, 'phpizeCallback')); + if (PEAR::isError($err)) { + return $err; + } + if (!$err) { + return $this->raiseError("`phpize' failed"); + } + + // {{{ start of interactive part + $configure_command = "$dir/configure"; + $configure_options = $pkg->getConfigureOptions(); + if ($configure_options) { + foreach ($configure_options as $o) { + $default = array_key_exists('default', $o) ? $o['default'] : null; + list($r) = $this->ui->userDialog('build', + array($o['prompt']), + array('text'), + array($default)); + if (substr($o['name'], 0, 5) == 'with-' && + ($r == 'yes' || $r == 'autodetect')) { + $configure_command .= " --$o[name]"; + } else { + $configure_command .= " --$o[name]=".trim($r); + } + } + } + // }}} end of interactive part + + // FIXME make configurable + if(!$user=getenv('USER')){ + $user='defaultuser'; + } + $build_basedir = "/var/tmp/pear-build-$user"; + $build_dir = "$build_basedir/$vdir"; + $inst_dir = "$build_basedir/install-$vdir"; + $this->log(1, "building in $build_dir"); + if (is_dir($build_dir)) { + System::rm(array('-rf', $build_dir)); + } + if (!System::mkDir(array('-p', $build_dir))) { + return $this->raiseError("could not create build dir: $build_dir"); + } + $this->addTempFile($build_dir); + if (!System::mkDir(array('-p', $inst_dir))) { + return $this->raiseError("could not create temporary install dir: $inst_dir"); + } + $this->addTempFile($inst_dir); + + if (getenv('MAKE')) { + $make_command = getenv('MAKE'); + } else { + $make_command = 'make'; + } + $to_run = array( + $configure_command, + $make_command, + "$make_command INSTALL_ROOT=\"$inst_dir\" install", + "find \"$inst_dir\" | xargs ls -dils" + ); + if (!file_exists($build_dir) || !is_dir($build_dir) || !chdir($build_dir)) { + return $this->raiseError("could not chdir to $build_dir"); + } + putenv('PHP_PEAR_VERSION=1.7.2'); + foreach ($to_run as $cmd) { + $err = $this->_runCommand($cmd, $callback); + if (PEAR::isError($err)) { + chdir($old_cwd); + return $err; + } + if (!$err) { + chdir($old_cwd); + return $this->raiseError("`$cmd' failed"); + } + } + if (!($dp = opendir("modules"))) { + chdir($old_cwd); + return $this->raiseError("no `modules' directory found"); + } + $built_files = array(); + $prefix = exec("php-config --prefix"); + $this->_harvestInstDir($prefix, $inst_dir . DIRECTORY_SEPARATOR . $prefix, $built_files); + chdir($old_cwd); + return $built_files; + } + + // }}} + // {{{ phpizeCallback() + + /** + * Message callback function used when running the "phpize" + * program. Extracts the API numbers used. Ignores other message + * types than "cmdoutput". + * + * @param string $what the type of message + * @param mixed $data the message + * + * @return void + * + * @access public + */ + function phpizeCallback($what, $data) + { + if ($what != 'cmdoutput') { + return; + } + $this->log(1, rtrim($data)); + if (preg_match('/You should update your .aclocal.m4/', $data)) { + return; + } + $matches = array(); + if (preg_match('/^\s+(\S[^:]+):\s+(\d{8})/', $data, $matches)) { + $member = preg_replace('/[^a-z]/', '_', strtolower($matches[1])); + $apino = (int)$matches[2]; + if (isset($this->$member)) { + $this->$member = $apino; + //$msg = sprintf("%-22s : %d", $matches[1], $apino); + //$this->log(1, $msg); + } + } + } + + // }}} + // {{{ _runCommand() + + /** + * Run an external command, using a message callback to report + * output. The command will be run through popen and output is + * reported for every line with a "cmdoutput" message with the + * line string, including newlines, as payload. + * + * @param string $command the command to run + * + * @param mixed $callback (optional) function to use as message + * callback + * + * @return bool whether the command was successful (exit code 0 + * means success, any other means failure) + * + * @access private + */ + function _runCommand($command, $callback = null) + { + $this->log(1, "running: $command"); + $pp = popen("$command 2>&1", "r"); + if (!$pp) { + return $this->raiseError("failed to run `$command'"); + } + if ($callback && $callback[0]->debug == 1) { + $olddbg = $callback[0]->debug; + $callback[0]->debug = 2; + } + + while ($line = fgets($pp, 1024)) { + if ($callback) { + call_user_func($callback, 'cmdoutput', $line); + } else { + $this->log(2, rtrim($line)); + } + } + if ($callback && isset($olddbg)) { + $callback[0]->debug = $olddbg; + } + if (is_resource($pp)) { + $exitcode = pclose($pp); + } else { + $exitcode = -1; + } + return ($exitcode == 0); + } + + // }}} + // {{{ log() + + function log($level, $msg) + { + if ($this->current_callback) { + if ($this->debug >= $level) { + call_user_func($this->current_callback, 'output', $msg); + } + return; + } + return PEAR_Common::log($level, $msg); + } + + // }}} +} + +?> diff --git a/src/lib/pear/PEAR/PEAR/ChannelFile.php b/src/lib/pear/PEAR/PEAR/ChannelFile.php new file mode 100644 index 0000000..46dd691 --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/ChannelFile.php @@ -0,0 +1,1615 @@ + + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: ChannelFile.php,v 1.80 2008/01/03 20:26:34 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 1.4.0a1 + */ + +/** + * Needed for error handling + */ +require_once 'PEAR/ErrorStack.php'; +require_once 'PEAR/XMLParser.php'; +require_once 'PEAR/Common.php'; + +/** + * Error code if the channel.xml tag does not contain a valid version + */ +define('PEAR_CHANNELFILE_ERROR_NO_VERSION', 1); +/** + * Error code if the channel.xml tag version is not supported (version 1.0 is the only supported version, + * currently + */ +define('PEAR_CHANNELFILE_ERROR_INVALID_VERSION', 2); + +/** + * Error code if parsing is attempted with no xml extension + */ +define('PEAR_CHANNELFILE_ERROR_NO_XML_EXT', 3); + +/** + * Error code if creating the xml parser resource fails + */ +define('PEAR_CHANNELFILE_ERROR_CANT_MAKE_PARSER', 4); + +/** + * Error code used for all sax xml parsing errors + */ +define('PEAR_CHANNELFILE_ERROR_PARSER_ERROR', 5); + +/**#@+ + * Validation errors + */ +/** + * Error code when channel name is missing + */ +define('PEAR_CHANNELFILE_ERROR_NO_NAME', 6); +/** + * Error code when channel name is invalid + */ +define('PEAR_CHANNELFILE_ERROR_INVALID_NAME', 7); +/** + * Error code when channel summary is missing + */ +define('PEAR_CHANNELFILE_ERROR_NO_SUMMARY', 8); +/** + * Error code when channel summary is multi-line + */ +define('PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY', 9); +/** + * Error code when channel server is missing for xmlrpc or soap protocol + */ +define('PEAR_CHANNELFILE_ERROR_NO_HOST', 10); +/** + * Error code when channel server is invalid for xmlrpc or soap protocol + */ +define('PEAR_CHANNELFILE_ERROR_INVALID_HOST', 11); +/** + * Error code when a mirror name is invalid + */ +define('PEAR_CHANNELFILE_ERROR_INVALID_MIRROR', 21); +/** + * Error code when a mirror type is invalid + */ +define('PEAR_CHANNELFILE_ERROR_INVALID_MIRRORTYPE', 22); +/** + * Error code when an attempt is made to generate xml, but the parsed content is invalid + */ +define('PEAR_CHANNELFILE_ERROR_INVALID', 23); +/** + * Error code when an empty package name validate regex is passed in + */ +define('PEAR_CHANNELFILE_ERROR_EMPTY_REGEX', 24); +/** + * Error code when a tag has no version + */ +define('PEAR_CHANNELFILE_ERROR_NO_FUNCTIONVERSION', 25); +/** + * Error code when a tag has no name + */ +define('PEAR_CHANNELFILE_ERROR_NO_FUNCTIONNAME', 26); +/** + * Error code when a tag has no name + */ +define('PEAR_CHANNELFILE_ERROR_NOVALIDATE_NAME', 27); +/** + * Error code when a tag has no version attribute + */ +define('PEAR_CHANNELFILE_ERROR_NOVALIDATE_VERSION', 28); +/** + * Error code when a mirror does not exist but is called for in one of the set* + * methods. + */ +define('PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND', 32); +/** + * Error code when a server port is not numeric + */ +define('PEAR_CHANNELFILE_ERROR_INVALID_PORT', 33); +/** + * Error code when contains no version attribute + */ +define('PEAR_CHANNELFILE_ERROR_NO_STATICVERSION', 34); +/** + * Error code when contains no type attribute in a protocol definition + */ +define('PEAR_CHANNELFILE_ERROR_NOBASEURLTYPE', 35); +/** + * Error code when a mirror is defined and the channel.xml represents the __uri pseudo-channel + */ +define('PEAR_CHANNELFILE_URI_CANT_MIRROR', 36); +/** + * Error code when ssl attribute is present and is not "yes" + */ +define('PEAR_CHANNELFILE_ERROR_INVALID_SSL', 37); +/**#@-*/ + +/** + * Mirror types allowed. Currently only internet servers are recognized. + */ +$GLOBALS['_PEAR_CHANNELS_MIRROR_TYPES'] = array('server'); + + +/** + * The Channel handling class + * + * @category pear + * @package PEAR + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 1.4.0a1 + */ +class PEAR_ChannelFile { + /** + * @access private + * @var PEAR_ErrorStack + * @access private + */ + var $_stack; + + /** + * Supported channel.xml versions, for parsing + * @var array + * @access private + */ + var $_supportedVersions = array('1.0'); + + /** + * Parsed channel information + * @var array + * @access private + */ + var $_channelInfo; + + /** + * index into the subchannels array, used for parsing xml + * @var int + * @access private + */ + var $_subchannelIndex; + + /** + * index into the mirrors array, used for parsing xml + * @var int + * @access private + */ + var $_mirrorIndex; + + /** + * Flag used to determine the validity of parsed content + * @var boolean + * @access private + */ + var $_isValid = false; + + function PEAR_ChannelFile() + { + $this->_stack = &new PEAR_ErrorStack('PEAR_ChannelFile'); + $this->_stack->setErrorMessageTemplate($this->_getErrorMessage()); + $this->_isValid = false; + } + + /** + * @return array + * @access protected + */ + function _getErrorMessage() + { + return + array( + PEAR_CHANNELFILE_ERROR_INVALID_VERSION => + 'While parsing channel.xml, an invalid version number "%version% was passed in, expecting one of %versions%', + PEAR_CHANNELFILE_ERROR_NO_VERSION => + 'No version number found in tag', + PEAR_CHANNELFILE_ERROR_NO_XML_EXT => + '%error%', + PEAR_CHANNELFILE_ERROR_CANT_MAKE_PARSER => + 'Unable to create XML parser', + PEAR_CHANNELFILE_ERROR_PARSER_ERROR => + '%error%', + PEAR_CHANNELFILE_ERROR_NO_NAME => + 'Missing channel name', + PEAR_CHANNELFILE_ERROR_INVALID_NAME => + 'Invalid channel %tag% "%name%"', + PEAR_CHANNELFILE_ERROR_NO_SUMMARY => + 'Missing channel summary', + PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY => + 'Channel summary should be on one line, but is multi-line', + PEAR_CHANNELFILE_ERROR_NO_HOST => + 'Missing channel server for %type% server', + PEAR_CHANNELFILE_ERROR_INVALID_HOST => + 'Server name "%server%" is invalid for %type% server', + PEAR_CHANNELFILE_ERROR_INVALID_MIRROR => + 'Invalid mirror name "%name%", mirror type %type%', + PEAR_CHANNELFILE_ERROR_INVALID_MIRRORTYPE => + 'Invalid mirror type "%type%"', + PEAR_CHANNELFILE_ERROR_INVALID => + 'Cannot generate xml, contents are invalid', + PEAR_CHANNELFILE_ERROR_EMPTY_REGEX => + 'packagenameregex cannot be empty', + PEAR_CHANNELFILE_ERROR_NO_FUNCTIONVERSION => + '%parent% %protocol% function has no version', + PEAR_CHANNELFILE_ERROR_NO_FUNCTIONNAME => + '%parent% %protocol% function has no name', + PEAR_CHANNELFILE_ERROR_NOBASEURLTYPE => + '%parent% rest baseurl has no type', + PEAR_CHANNELFILE_ERROR_NOVALIDATE_NAME => + 'Validation package has no name in tag', + PEAR_CHANNELFILE_ERROR_NOVALIDATE_VERSION => + 'Validation package "%package%" has no version', + PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND => + 'Mirror "%mirror%" does not exist', + PEAR_CHANNELFILE_ERROR_INVALID_PORT => + 'Port "%port%" must be numeric', + PEAR_CHANNELFILE_ERROR_NO_STATICVERSION => + ' tag must contain version attribute', + PEAR_CHANNELFILE_URI_CANT_MIRROR => + 'The __uri pseudo-channel cannot have mirrors', + PEAR_CHANNELFILE_ERROR_INVALID_SSL => + '%server% has invalid ssl attribute "%ssl%" can only be yes or not present', + ); + } + + /** + * @param string contents of package.xml file + * @return bool success of parsing + */ + function fromXmlString($data) + { + if (preg_match('/_supportedVersions)) { + $this->_stack->push(PEAR_CHANNELFILE_ERROR_INVALID_VERSION, 'error', + array('version' => $channelversion[1])); + return false; + } + $parser = new PEAR_XMLParser; + $result = $parser->parse($data); + if ($result !== true) { + if ($result->getCode() == 1) { + $this->_stack->push(PEAR_CHANNELFILE_ERROR_NO_XML_EXT, 'error', + array('error' => $result->getMessage())); + } else { + $this->_stack->push(PEAR_CHANNELFILE_ERROR_CANT_MAKE_PARSER, 'error'); + } + return false; + } + $this->_channelInfo = $parser->getData(); + return true; + } else { + $this->_stack->push(PEAR_CHANNELFILE_ERROR_NO_VERSION, 'error', array('xml' => $data)); + return false; + } + } + + /** + * @return array + */ + function toArray() + { + if (!$this->_isValid && !$this->validate()) { + return false; + } + return $this->_channelInfo; + } + + /** + * @param array + * @static + * @return PEAR_ChannelFile|false false if invalid + */ + function &fromArray($data, $compatibility = false, $stackClass = 'PEAR_ErrorStack') + { + $a = new PEAR_ChannelFile($compatibility, $stackClass); + $a->_fromArray($data); + if (!$a->validate()) { + $a = false; + return $a; + } + return $a; + } + + /** + * Unlike {@link fromArray()} this does not do any validation + * @param array + * @static + * @return PEAR_ChannelFile + */ + function &fromArrayWithErrors($data, $compatibility = false, + $stackClass = 'PEAR_ErrorStack') + { + $a = new PEAR_ChannelFile($compatibility, $stackClass); + $a->_fromArray($data); + return $a; + } + + /** + * @param array + * @access private + */ + function _fromArray($data) + { + $this->_channelInfo = $data; + } + + /** + * Wrapper to {@link PEAR_ErrorStack::getErrors()} + * @param boolean determines whether to purge the error stack after retrieving + * @return array + */ + function getErrors($purge = false) + { + return $this->_stack->getErrors($purge); + } + + /** + * Unindent given string (?) + * + * @param string $str The string that has to be unindented. + * @return string + * @access private + */ + function _unIndent($str) + { + // remove leading newlines + $str = preg_replace('/^[\r\n]+/', '', $str); + // find whitespace at the beginning of the first line + $indent_len = strspn($str, " \t"); + $indent = substr($str, 0, $indent_len); + $data = ''; + // remove the same amount of whitespace from following lines + foreach (explode("\n", $str) as $line) { + if (substr($line, 0, $indent_len) == $indent) { + $data .= substr($line, $indent_len) . "\n"; + } + } + return $data; + } + + /** + * Parse a channel.xml file. Expects the name of + * a channel xml file as input. + * + * @param string $descfile name of channel xml file + * @return bool success of parsing + */ + function fromXmlFile($descfile) + { + if (!file_exists($descfile) || !is_file($descfile) || !is_readable($descfile) || + (!$fp = fopen($descfile, 'r'))) { + require_once 'PEAR.php'; + return PEAR::raiseError("Unable to open $descfile"); + } + + // read the whole thing so we only get one cdata callback + // for each block of cdata + fclose($fp); + $data = file_get_contents($descfile); + return $this->fromXmlString($data); + } + + /** + * Parse channel information from different sources + * + * This method is able to extract information about a channel + * from an .xml file or a string + * + * @access public + * @param string Filename of the source or the source itself + * @return bool + */ + function fromAny($info) + { + if (is_string($info) && file_exists($info) && strlen($info) < 255) { + $tmp = substr($info, -4); + if ($tmp == '.xml') { + $info = $this->fromXmlFile($info); + } else { + $fp = fopen($info, "r"); + $test = fread($fp, 5); + fclose($fp); + if ($test == "fromXmlFile($info); + } + } + if (PEAR::isError($info)) { + require_once 'PEAR.php'; + return PEAR::raiseError($info); + } + } + if (is_string($info)) { + $info = $this->fromXmlString($info); + } + return $info; + } + + /** + * Return an XML document based on previous parsing and modifications + * + * @return string XML data + * + * @access public + */ + function toXml() + { + if (!$this->_isValid && !$this->validate()) { + $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID); + return false; + } + if (!isset($this->_channelInfo['attribs']['version'])) { + $this->_channelInfo['attribs']['version'] = '1.0'; + } + $channelInfo = $this->_channelInfo; + $ret = "\n"; + $ret .= " + $channelInfo[name] + " . htmlspecialchars($channelInfo['summary'])." +"; + if (isset($channelInfo['suggestedalias'])) { + $ret .= ' ' . $channelInfo['suggestedalias'] . "\n"; + } + if (isset($channelInfo['validatepackage'])) { + $ret .= ' ' . + htmlspecialchars($channelInfo['validatepackage']['_content']) . + "\n"; + } + $ret .= " \n"; + $ret .= ' _makeXmlrpcXml($channelInfo['servers']['primary']['xmlrpc'], ' '); + } + if (isset($channelInfo['servers']['primary']['rest'])) { + $ret .= $this->_makeRestXml($channelInfo['servers']['primary']['rest'], ' '); + } + if (isset($channelInfo['servers']['primary']['soap'])) { + $ret .= $this->_makeSoapXml($channelInfo['servers']['primary']['soap'], ' '); + } + $ret .= " \n"; + if (isset($channelInfo['servers']['mirror'])) { + $ret .= $this->_makeMirrorsXml($channelInfo); + } + $ret .= " \n"; + $ret .= ""; + return str_replace("\r", "\n", str_replace("\r\n", "\n", $ret)); + } + + /** + * Generate the tag + * @access private + */ + function _makeXmlrpcXml($info, $indent) + { + $ret = $indent . "_makeFunctionsXml($info['function'], "$indent "); + $ret .= $indent . "\n"; + return $ret; + } + + /** + * Generate the tag + * @access private + */ + function _makeSoapXml($info, $indent) + { + $ret = $indent . "_makeFunctionsXml($info['function'], "$indent "); + $ret .= $indent . "\n"; + return $ret; + } + + /** + * Generate the tag + * @access private + */ + function _makeRestXml($info, $indent) + { + $ret = $indent . "\n"; + if (!isset($info['baseurl'][0])) { + $info['baseurl'] = array($info['baseurl']); + } + foreach ($info['baseurl'] as $url) { + $ret .= "$indent \n"; + } + $ret .= $indent . "\n"; + return $ret; + } + + /** + * Generate the tag + * @access private + */ + function _makeMirrorsXml($channelInfo) + { + $ret = ""; + if (!isset($channelInfo['servers']['mirror'][0])) { + $channelInfo['servers']['mirror'] = array($channelInfo['servers']['mirror']); + } + foreach ($channelInfo['servers']['mirror'] as $mirror) { + $ret .= ' _makeXmlrpcXml($mirror['xmlrpc'], ' '); + } + if (isset($mirror['rest'])) { + $ret .= $this->_makeRestXml($mirror['rest'], ' '); + } + if (isset($mirror['soap'])) { + $ret .= $this->_makeSoapXml($mirror['soap'], ' '); + } + $ret .= " \n"; + } else { + $ret .= "/>\n"; + } + } + return $ret; + } + + /** + * Generate the tag + * @access private + */ + function _makeFunctionsXml($functions, $indent, $rest = false) + { + $ret = ''; + if (!isset($functions[0])) { + $functions = array($functions); + } + foreach ($functions as $function) { + $ret .= "$indent\n"; + } + return $ret; + } + + /** + * Validation error. Also marks the object contents as invalid + * @param error code + * @param array error information + * @access private + */ + function _validateError($code, $params = array()) + { + $this->_stack->push($code, 'error', $params); + $this->_isValid = false; + } + + /** + * Validation warning. Does not mark the object contents invalid. + * @param error code + * @param array error information + * @access private + */ + function _validateWarning($code, $params = array()) + { + $this->_stack->push($code, 'warning', $params); + } + + /** + * Validate parsed file. + * + * @access public + * @return boolean + */ + function validate() + { + $this->_isValid = true; + $info = $this->_channelInfo; + if (empty($info['name'])) { + $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_NAME); + } elseif (!$this->validChannelServer($info['name'])) { + if ($info['name'] != '__uri') { + $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME, array('tag' => 'name', + 'name' => $info['name'])); + } + } + if (empty($info['summary'])) { + $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_SUMMARY); + } elseif (strpos(trim($info['summary']), "\n") !== false) { + $this->_validateWarning(PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY, + array('summary' => $info['summary'])); + } + if (isset($info['suggestedalias'])) { + if (!$this->validChannelServer($info['suggestedalias'])) { + $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME, + array('tag' => 'suggestedalias', 'name' =>$info['suggestedalias'])); + } + } + if (isset($info['localalias'])) { + if (!$this->validChannelServer($info['localalias'])) { + $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME, + array('tag' => 'localalias', 'name' =>$info['localalias'])); + } + } + if (isset($info['validatepackage'])) { + if (!isset($info['validatepackage']['_content'])) { + $this->_validateError(PEAR_CHANNELFILE_ERROR_NOVALIDATE_NAME); + } + if (!isset($info['validatepackage']['attribs']['version'])) { + $content = isset($info['validatepackage']['_content']) ? + $info['validatepackage']['_content'] : + null; + $this->_validateError(PEAR_CHANNELFILE_ERROR_NOVALIDATE_VERSION, + array('package' => $content)); + } + } + if (isset($info['servers']['primary']['attribs']['port']) && + !is_numeric($info['servers']['primary']['attribs']['port'])) { + $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_PORT, + array('port' => $info['servers']['primary']['attribs']['port'])); + } + if (isset($info['servers']['primary']['attribs']['ssl']) && + $info['servers']['primary']['attribs']['ssl'] != 'yes') { + $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_SSL, + array('ssl' => $info['servers']['primary']['attribs']['ssl'], + 'server' => $info['name'])); + } + + if (isset($info['servers']['primary']['xmlrpc']) && + isset($info['servers']['primary']['xmlrpc']['function'])) { + $this->_validateFunctions('xmlrpc', $info['servers']['primary']['xmlrpc']['function']); + } + if (isset($info['servers']['primary']['soap']) && + isset($info['servers']['primary']['soap']['function'])) { + $this->_validateFunctions('soap', $info['servers']['primary']['soap']['function']); + } + if (isset($info['servers']['primary']['rest']) && + isset($info['servers']['primary']['rest']['baseurl'])) { + $this->_validateFunctions('rest', $info['servers']['primary']['rest']['baseurl']); + } + if (isset($info['servers']['mirror'])) { + if ($this->_channelInfo['name'] == '__uri') { + $this->_validateError(PEAR_CHANNELFILE_URI_CANT_MIRROR); + } + if (!isset($info['servers']['mirror'][0])) { + $info['servers']['mirror'] = array($info['servers']['mirror']); + } + foreach ($info['servers']['mirror'] as $mirror) { + if (!isset($mirror['attribs']['host'])) { + $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_HOST, + array('type' => 'mirror')); + } elseif (!$this->validChannelServer($mirror['attribs']['host'])) { + $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_HOST, + array('server' => $mirror['attribs']['host'], 'type' => 'mirror')); + } + if (isset($mirror['attribs']['ssl']) && $mirror['attribs']['ssl'] != 'yes') { + $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_SSL, + array('ssl' => $info['ssl'], 'server' => $mirror['attribs']['host'])); + } + if (isset($mirror['xmlrpc'])) { + $this->_validateFunctions('xmlrpc', + $mirror['xmlrpc']['function'], $mirror['attribs']['host']); + } + if (isset($mirror['soap'])) { + $this->_validateFunctions('soap', $mirror['soap']['function'], + $mirror['attribs']['host']); + } + if (isset($mirror['rest'])) { + $this->_validateFunctions('rest', $mirror['rest']['baseurl'], + $mirror['attribs']['host']); + } + } + } + return $this->_isValid; + } + + /** + * @param string xmlrpc or soap - protocol name this function applies to + * @param array the functions + * @param string the name of the parent element (mirror name, for instance) + */ + function _validateFunctions($protocol, $functions, $parent = '') + { + if (!isset($functions[0])) { + $functions = array($functions); + } + foreach ($functions as $function) { + if (!isset($function['_content']) || empty($function['_content'])) { + $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_FUNCTIONNAME, + array('parent' => $parent, 'protocol' => $protocol)); + } + if ($protocol == 'rest') { + if (!isset($function['attribs']['type']) || + empty($function['attribs']['type'])) { + $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_BASEURLTYPE, + array('parent' => $parent, 'protocol' => $protocol)); + } + } else { + if (!isset($function['attribs']['version']) || + empty($function['attribs']['version'])) { + $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_FUNCTIONVERSION, + array('parent' => $parent, 'protocol' => $protocol)); + } + } + } + } + + /** + * Test whether a string contains a valid channel server. + * @param string $ver the package version to test + * @return bool + */ + function validChannelServer($server) + { + if ($server == '__uri') { + return true; + } + return (bool) preg_match(PEAR_CHANNELS_SERVER_PREG, $server); + } + + /** + * @return string|false + */ + function getName() + { + if (isset($this->_channelInfo['name'])) { + return $this->_channelInfo['name']; + } else { + return false; + } + } + + /** + * @return string|false + */ + function getServer() + { + if (isset($this->_channelInfo['name'])) { + return $this->_channelInfo['name']; + } else { + return false; + } + } + + /** + * @return int|80 port number to connect to + */ + function getPort($mirror = false) + { + if ($mirror) { + if ($mir = $this->getMirror($mirror)) { + if (isset($mir['attribs']['port'])) { + return $mir['attribs']['port']; + } else { + if ($this->getSSL($mirror)) { + return 443; + } + return 80; + } + } + return false; + } + if (isset($this->_channelInfo['servers']['primary']['attribs']['port'])) { + return $this->_channelInfo['servers']['primary']['attribs']['port']; + } + if ($this->getSSL()) { + return 443; + } + return 80; + } + + /** + * @return bool Determines whether secure sockets layer (SSL) is used to connect to this channel + */ + function getSSL($mirror = false) + { + if ($mirror) { + if ($mir = $this->getMirror($mirror)) { + if (isset($mir['attribs']['ssl'])) { + return true; + } else { + return false; + } + } + return false; + } + if (isset($this->_channelInfo['servers']['primary']['attribs']['ssl'])) { + return true; + } + return false; + } + + /** + * @return string|false + */ + function getSummary() + { + if (isset($this->_channelInfo['summary'])) { + return $this->_channelInfo['summary']; + } else { + return false; + } + } + + /** + * @param string xmlrpc or soap + * @param string|false mirror name or false for primary server + */ + function getPath($protocol, $mirror = false) + { + if (!in_array($protocol, array('xmlrpc', 'soap'))) { + return false; + } + if ($mirror) { + if (!($mir = $this->getMirror($mirror))) { + return false; + } + if (isset($mir[$protocol]['attribs']['path'])) { + return $mir[$protocol]['attribs']['path']; + } else { + return $protocol . '.php'; + } + } elseif (isset($this->_channelInfo['servers']['primary'][$protocol]['attribs']['path'])) { + return $this->_channelInfo['servers']['primary'][$protocol]['attribs']['path']; + } + return $protocol . '.php'; + } + + /** + * @param string protocol type (xmlrpc, soap) + * @param string Mirror name + * @return array|false + */ + function getFunctions($protocol, $mirror = false) + { + if ($this->getName() == '__uri') { + return false; + } + if ($protocol == 'rest') { + $function = 'baseurl'; + } else { + $function = 'function'; + } + if ($mirror) { + if ($mir = $this->getMirror($mirror)) { + if (isset($mir[$protocol][$function])) { + return $mir[$protocol][$function]; + } + } + return false; + } + if (isset($this->_channelInfo['servers']['primary'][$protocol][$function])) { + return $this->_channelInfo['servers']['primary'][$protocol][$function]; + } else { + return false; + } + } + + /** + * @param string Protocol type + * @param string Function name (null to return the + * first protocol of the type requested) + * @param string Mirror name, if any + * @return array + */ + function getFunction($type, $name = null, $mirror = false) + { + $protocols = $this->getFunctions($type, $mirror); + if (!$protocols) { + return false; + } + foreach ($protocols as $protocol) { + if ($name === null) { + return $protocol; + } + if ($protocol['_content'] != $name) { + continue; + } + return $protocol; + } + return false; + } + + /** + * @param string protocol type + * @param string protocol name + * @param string version + * @param string mirror name + * @return boolean + */ + function supports($type, $name = null, $mirror = false, $version = '1.0') + { + $protocols = $this->getFunctions($type, $mirror); + if (!$protocols) { + return false; + } + foreach ($protocols as $protocol) { + if ($protocol['attribs']['version'] != $version) { + continue; + } + if ($name === null) { + return true; + } + if ($protocol['_content'] != $name) { + continue; + } + return true; + } + return false; + } + + /** + * Determines whether a channel supports Representational State Transfer (REST) protocols + * for retrieving channel information + * @param string + * @return bool + */ + function supportsREST($mirror = false) + { + if ($mirror == $this->_channelInfo['name']) { + $mirror = false; + } + if ($mirror) { + if ($mir = $this->getMirror($mirror)) { + return isset($mir['rest']); + } + return false; + } + return isset($this->_channelInfo['servers']['primary']['rest']); + } + + /** + * Get the URL to access a base resource. + * + * Hyperlinks in the returned xml will be used to retrieve the proper information + * needed. This allows extreme extensibility and flexibility in implementation + * @param string Resource Type to retrieve + */ + function getBaseURL($resourceType, $mirror = false) + { + if ($mirror == $this->_channelInfo['name']) { + $mirror = false; + } + if ($mirror) { + if ($mir = $this->getMirror($mirror)) { + $rest = $mir['rest']; + } else { + return false; + } + } else { + $rest = $this->_channelInfo['servers']['primary']['rest']; + } + if (!isset($rest['baseurl'][0])) { + $rest['baseurl'] = array($rest['baseurl']); + } + foreach ($rest['baseurl'] as $baseurl) { + if (strtolower($baseurl['attribs']['type']) == strtolower($resourceType)) { + return $baseurl['_content']; + } + } + return false; + } + + /** + * Since REST does not implement RPC, provide this as a logical wrapper around + * resetFunctions for REST + * @param string|false mirror name, if any + */ + function resetREST($mirror = false) + { + return $this->resetFunctions('rest', $mirror); + } + + /** + * Empty all protocol definitions + * @param string protocol type (xmlrpc, soap) + * @param string|false mirror name, if any + */ + function resetFunctions($type, $mirror = false) + { + if ($mirror) { + if (isset($this->_channelInfo['servers']['mirror'])) { + $mirrors = $this->_channelInfo['servers']['mirror']; + if (!isset($mirrors[0])) { + $mirrors = array($mirrors); + } + foreach ($mirrors as $i => $mir) { + if ($mir['attribs']['host'] == $mirror) { + if (isset($this->_channelInfo['servers']['mirror'][$i][$type])) { + unset($this->_channelInfo['servers']['mirror'][$i][$type]); + } + return true; + } + } + return false; + } else { + return false; + } + } else { + if (isset($this->_channelInfo['servers']['primary'][$type])) { + unset($this->_channelInfo['servers']['primary'][$type]); + } + return true; + } + } + + /** + * Set a channel's protocols to the protocols supported by pearweb + */ + function setDefaultPEARProtocols($version = '1.0', $mirror = false) + { + switch ($version) { + case '1.0' : + $this->resetFunctions('xmlrpc', $mirror); + $this->resetFunctions('soap', $mirror); + $this->resetREST($mirror); + $this->addFunction('xmlrpc', '1.0', 'logintest', $mirror); + $this->addFunction('xmlrpc', '1.0', 'package.listLatestReleases', $mirror); + $this->addFunction('xmlrpc', '1.0', 'package.listAll', $mirror); + $this->addFunction('xmlrpc', '1.0', 'package.info', $mirror); + $this->addFunction('xmlrpc', '1.0', 'package.getDownloadURL', $mirror); + $this->addFunction('xmlrpc', '1.1', 'package.getDownloadURL', $mirror); + $this->addFunction('xmlrpc', '1.0', 'package.getDepDownloadURL', $mirror); + $this->addFunction('xmlrpc', '1.1', 'package.getDepDownloadURL', $mirror); + $this->addFunction('xmlrpc', '1.0', 'package.search', $mirror); + $this->addFunction('xmlrpc', '1.0', 'channel.listAll', $mirror); + return true; + break; + default : + return false; + break; + } + } + + /** + * @return array + */ + function getMirrors() + { + if (isset($this->_channelInfo['servers']['mirror'])) { + $mirrors = $this->_channelInfo['servers']['mirror']; + if (!isset($mirrors[0])) { + $mirrors = array($mirrors); + } + return $mirrors; + } else { + return array(); + } + } + + /** + * Get the unserialized XML representing a mirror + * @return array|false + */ + function getMirror($server) + { + foreach ($this->getMirrors() as $mirror) { + if ($mirror['attribs']['host'] == $server) { + return $mirror; + } + } + return false; + } + + /** + * @param string + * @return string|false + * @error PEAR_CHANNELFILE_ERROR_NO_NAME + * @error PEAR_CHANNELFILE_ERROR_INVALID_NAME + */ + function setName($name) + { + return $this->setServer($name); + } + + /** + * Set the socket number (port) that is used to connect to this channel + * @param integer + * @param string|false name of the mirror server, or false for the primary + */ + function setPort($port, $mirror = false) + { + if ($mirror) { + if (!isset($this->_channelInfo['servers']['mirror'])) { + $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND, + array('mirror' => $mirror)); + return false; + } + if (isset($this->_channelInfo['servers']['mirror'][0])) { + foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) { + if ($mirror == $mir['attribs']['host']) { + $this->_channelInfo['servers']['mirror'][$i]['attribs']['port'] = $port; + return true; + } + } + return false; + } elseif ($this->_channelInfo['servers']['mirror']['attribs']['host'] == $mirror) { + $this->_channelInfo['servers']['mirror']['attribs']['port'] = $port; + $this->_isValid = false; + return true; + } + } + $this->_channelInfo['servers']['primary']['attribs']['port'] = $port; + $this->_isValid = false; + return true; + } + + /** + * Set the socket number (port) that is used to connect to this channel + * @param bool Determines whether to turn on SSL support or turn it off + * @param string|false name of the mirror server, or false for the primary + */ + function setSSL($ssl = true, $mirror = false) + { + if ($mirror) { + if (!isset($this->_channelInfo['servers']['mirror'])) { + $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND, + array('mirror' => $mirror)); + return false; + } + if (isset($this->_channelInfo['servers']['mirror'][0])) { + foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) { + if ($mirror == $mir['attribs']['host']) { + if (!$ssl) { + if (isset($this->_channelInfo['servers']['mirror'][$i] + ['attribs']['ssl'])) { + unset($this->_channelInfo['servers']['mirror'][$i]['attribs']['ssl']); + } + } else { + $this->_channelInfo['servers']['mirror'][$i]['attribs']['ssl'] = 'yes'; + } + return true; + } + } + return false; + } elseif ($this->_channelInfo['servers']['mirror']['attribs']['host'] == $mirror) { + if (!$ssl) { + if (isset($this->_channelInfo['servers']['mirror']['attribs']['ssl'])) { + unset($this->_channelInfo['servers']['mirror']['attribs']['ssl']); + } + } else { + $this->_channelInfo['servers']['mirror']['attribs']['ssl'] = 'yes'; + } + $this->_isValid = false; + return true; + } + } + if ($ssl) { + $this->_channelInfo['servers']['primary']['attribs']['ssl'] = 'yes'; + } else { + if (isset($this->_channelInfo['servers']['primary']['attribs']['ssl'])) { + unset($this->_channelInfo['servers']['primary']['attribs']['ssl']); + } + } + $this->_isValid = false; + return true; + } + + /** + * Set the socket number (port) that is used to connect to this channel + * @param integer + * @param string|false name of the mirror server, or false for the primary + */ + function setPath($protocol, $path, $mirror = false) + { + if (!in_array($protocol, array('xmlrpc', 'soap'))) { + return false; + } + if ($mirror) { + if (!isset($this->_channelInfo['servers']['mirror'])) { + $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND, + array('mirror' => $mirror)); + return false; + } + if (isset($this->_channelInfo['servers']['mirror'][0])) { + foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) { + if ($mirror == $mir['attribs']['host']) { + $this->_channelInfo['servers']['mirror'][$i][$protocol]['attribs']['path'] = + $path; + return true; + } + } + $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND, + array('mirror' => $mirror)); + return false; + } elseif ($this->_channelInfo['servers']['mirror']['attribs']['host'] == $mirror) { + $this->_channelInfo['servers']['mirror'][$protocol]['attribs']['path'] = $path; + $this->_isValid = false; + return true; + } + } + $this->_channelInfo['servers']['primary'][$protocol]['attribs']['path'] = $path; + $this->_isValid = false; + return true; + } + + /** + * @param string + * @return string|false + * @error PEAR_CHANNELFILE_ERROR_NO_SERVER + * @error PEAR_CHANNELFILE_ERROR_INVALID_SERVER + */ + function setServer($server, $mirror = false) + { + if (empty($server)) { + $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_SERVER); + return false; + } elseif (!$this->validChannelServer($server)) { + $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME, + array('tag' => 'name', 'name' => $server)); + return false; + } + if ($mirror) { + $found = false; + foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) { + if ($mirror == $mir['attribs']['host']) { + $found = true; + break; + } + } + if (!$found) { + $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND, + array('mirror' => $mirror)); + return false; + } + $this->_channelInfo['mirror'][$i]['attribs']['host'] = $server; + return true; + } + $this->_channelInfo['name'] = $server; + return true; + } + + /** + * @param string + * @return boolean success + * @error PEAR_CHANNELFILE_ERROR_NO_SUMMARY + * @warning PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY + */ + function setSummary($summary) + { + if (empty($summary)) { + $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_SUMMARY); + return false; + } elseif (strpos(trim($summary), "\n") !== false) { + $this->_validateWarning(PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY, + array('summary' => $summary)); + } + $this->_channelInfo['summary'] = $summary; + return true; + } + + /** + * @param string + * @param boolean determines whether the alias is in channel.xml or local + * @return boolean success + */ + function setAlias($alias, $local = false) + { + if (!$this->validChannelServer($alias)) { + $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME, + array('tag' => 'suggestedalias', 'name' => $alias)); + return false; + } + if ($local) { + $this->_channelInfo['localalias'] = $alias; + } else { + $this->_channelInfo['suggestedalias'] = $alias; + } + return true; + } + + /** + * @return string + */ + function getAlias() + { + if (isset($this->_channelInfo['localalias'])) { + return $this->_channelInfo['localalias']; + } + if (isset($this->_channelInfo['suggestedalias'])) { + return $this->_channelInfo['suggestedalias']; + } + if (isset($this->_channelInfo['name'])) { + return $this->_channelInfo['name']; + } + return ''; + } + + /** + * Set the package validation object if it differs from PEAR's default + * The class must be includeable via changing _ in the classname to path separator, + * but no checking of this is made. + * @param string|false pass in false to reset to the default packagename regex + * @return boolean success + */ + function setValidationPackage($validateclass, $version) + { + if (empty($validateclass)) { + unset($this->_channelInfo['validatepackage']); + } + $this->_channelInfo['validatepackage'] = array('_content' => $validateclass); + $this->_channelInfo['validatepackage']['attribs'] = array('version' => $version); + } + + /** + * Add a protocol to the provides section + * @param string protocol type + * @param string protocol version + * @param string protocol name, if any + * @param string mirror name, if this is a mirror's protocol + * @return bool + */ + function addFunction($type, $version, $name = '', $mirror = false) + { + if ($mirror) { + return $this->addMirrorFunction($mirror, $type, $version, $name); + } + $set = array('attribs' => array('version' => $version), '_content' => $name); + if (!isset($this->_channelInfo['servers']['primary'][$type]['function'])) { + if (!isset($this->_channelInfo['servers'])) { + $this->_channelInfo['servers'] = array('primary' => + array($type => array())); + } elseif (!isset($this->_channelInfo['servers']['primary'])) { + $this->_channelInfo['servers']['primary'] = array($type => array()); + } + $this->_channelInfo['servers']['primary'][$type]['function'] = $set; + $this->_isValid = false; + return true; + } elseif (!isset($this->_channelInfo['servers']['primary'][$type]['function'][0])) { + $this->_channelInfo['servers']['primary'][$type]['function'] = array( + $this->_channelInfo['servers']['primary'][$type]['function']); + } + $this->_channelInfo['servers']['primary'][$type]['function'][] = $set; + return true; + } + /** + * Add a protocol to a mirror's provides section + * @param string mirror name (server) + * @param string protocol type + * @param string protocol version + * @param string protocol name, if any + */ + function addMirrorFunction($mirror, $type, $version, $name = '') + { + if (!isset($this->_channelInfo['servers']['mirror'])) { + $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND, + array('mirror' => $mirror)); + return false; + } + $setmirror = false; + if (isset($this->_channelInfo['servers']['mirror'][0])) { + foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) { + if ($mirror == $mir['attribs']['host']) { + $setmirror = &$this->_channelInfo['servers']['mirror'][$i]; + break; + } + } + } else { + if ($this->_channelInfo['servers']['mirror']['attribs']['host'] == $mirror) { + $setmirror = &$this->_channelInfo['servers']['mirror']; + } + } + if (!$setmirror) { + $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND, + array('mirror' => $mirror)); + return false; + } + $set = array('attribs' => array('version' => $version), '_content' => $name); + if (!isset($setmirror[$type]['function'])) { + $setmirror[$type]['function'] = $set; + $this->_isValid = false; + return true; + } elseif (!isset($setmirror[$type]['function'][0])) { + $setmirror[$type]['function'] = array($setmirror[$type]['function']); + } + $setmirror[$type]['function'][] = $set; + $this->_isValid = false; + return true; + } + + /** + * @param string Resource Type this url links to + * @param string URL + * @param string|false mirror name, if this is not a primary server REST base URL + */ + function setBaseURL($resourceType, $url, $mirror = false) + { + if ($mirror) { + if (!isset($this->_channelInfo['servers']['mirror'])) { + $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND, + array('mirror' => $mirror)); + return false; + } + $setmirror = false; + if (isset($this->_channelInfo['servers']['mirror'][0])) { + foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) { + if ($mirror == $mir['attribs']['host']) { + $setmirror = &$this->_channelInfo['servers']['mirror'][$i]; + break; + } + } + } else { + if ($this->_channelInfo['servers']['mirror']['attribs']['host'] == $mirror) { + $setmirror = &$this->_channelInfo['servers']['mirror']; + } + } + } else { + $setmirror = &$this->_channelInfo['servers']['primary']; + } + $set = array('attribs' => array('type' => $resourceType), '_content' => $url); + if (!isset($setmirror['rest'])) { + $setmirror['rest'] = array(); + } + if (!isset($setmirror['rest']['baseurl'])) { + $setmirror['rest']['baseurl'] = $set; + $this->_isValid = false; + return true; + } elseif (!isset($setmirror['rest']['baseurl'][0])) { + $setmirror['rest']['baseurl'] = array($setmirror['rest']['baseurl']); + } + foreach ($setmirror['rest']['baseurl'] as $i => $url) { + if ($url['attribs']['type'] == $resourceType) { + $this->_isValid = false; + $setmirror['rest']['baseurl'][$i] = $set; + return true; + } + } + $setmirror['rest']['baseurl'][] = $set; + $this->_isValid = false; + return true; + } + + /** + * @param string mirror server + * @param int mirror http port + * @return boolean + */ + function addMirror($server, $port = null) + { + if ($this->_channelInfo['name'] == '__uri') { + return false; // the __uri channel cannot have mirrors by definition + } + $set = array('attribs' => array('host' => $server)); + if (is_numeric($port)) { + $set['attribs']['port'] = $port; + } + if (!isset($this->_channelInfo['servers']['mirror'])) { + $this->_channelInfo['servers']['mirror'] = $set; + return true; + } else { + if (!isset($this->_channelInfo['servers']['mirror'][0])) { + $this->_channelInfo['servers']['mirror'] = + array($this->_channelInfo['servers']['mirror']); + } + } + $this->_channelInfo['servers']['mirror'][] = $set; + return true; + } + + /** + * Retrieve the name of the validation package for this channel + * @return string|false + */ + function getValidationPackage() + { + if (!$this->_isValid && !$this->validate()) { + return false; + } + if (!isset($this->_channelInfo['validatepackage'])) { + return array('attribs' => array('version' => 'default'), + '_content' => 'PEAR_Validate'); + } + return $this->_channelInfo['validatepackage']; + } + + /** + * Retrieve the object that can be used for custom validation + * @param string|false the name of the package to validate. If the package is + * the channel validation package, PEAR_Validate is returned + * @return PEAR_Validate|false false is returned if the validation package + * cannot be located + */ + function &getValidationObject($package = false) + { + if (!class_exists('PEAR_Validate')) { + require_once 'PEAR/Validate.php'; + } + if (!$this->_isValid) { + if (!$this->validate()) { + $a = false; + return $a; + } + } + if (isset($this->_channelInfo['validatepackage'])) { + if ($package == $this->_channelInfo['validatepackage']) { + // channel validation packages are always validated by PEAR_Validate + $val = &new PEAR_Validate; + return $val; + } + if (!class_exists(str_replace('.', '_', + $this->_channelInfo['validatepackage']['_content']))) { + if ($this->isIncludeable(str_replace('_', '/', + $this->_channelInfo['validatepackage']['_content']) . '.php')) { + include_once str_replace('_', '/', + $this->_channelInfo['validatepackage']['_content']) . '.php'; + $vclass = str_replace('.', '_', + $this->_channelInfo['validatepackage']['_content']); + $val = &new $vclass; + } else { + $a = false; + return $a; + } + } else { + $vclass = str_replace('.', '_', + $this->_channelInfo['validatepackage']['_content']); + $val = &new $vclass; + } + } else { + $val = &new PEAR_Validate; + } + return $val; + } + + function isIncludeable($path) + { + $possibilities = explode(PATH_SEPARATOR, ini_get('include_path')); + foreach ($possibilities as $dir) { + if (file_exists($dir . DIRECTORY_SEPARATOR . $path) + && is_readable($dir . DIRECTORY_SEPARATOR . $path)) { + return true; + } + } + return false; + } + + /** + * This function is used by the channel updater and retrieves a value set by + * the registry, or the current time if it has not been set + * @return string + */ + function lastModified() + { + if (isset($this->_channelInfo['_lastmodified'])) { + return $this->_channelInfo['_lastmodified']; + } + return time(); + } +} +?> diff --git a/src/lib/pear/PEAR/PEAR/ChannelFile/Parser.php b/src/lib/pear/PEAR/PEAR/ChannelFile/Parser.php new file mode 100644 index 0000000..8840243 --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/ChannelFile/Parser.php @@ -0,0 +1,73 @@ + + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: Parser.php,v 1.5 2008/01/03 20:26:36 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 1.4.0a1 + */ + +/** + * base xml parser class + */ +require_once 'PEAR/XMLParser.php'; +require_once 'PEAR/ChannelFile.php'; +/** + * Parser for channel.xml + * @category pear + * @package PEAR + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 1.4.0a1 + */ +class PEAR_ChannelFile_Parser extends PEAR_XMLParser +{ + var $_config; + var $_logger; + var $_registry; + + function setConfig(&$c) + { + $this->_config = &$c; + $this->_registry = &$c->getRegistry(); + } + + function setLogger(&$l) + { + $this->_logger = &$l; + } + + function parse($data, $file) + { + if (PEAR::isError($err = parent::parse($data, $file))) { + return $err; + } + $ret = new PEAR_ChannelFile; + $ret->setConfig($this->_config); + if (isset($this->_logger)) { + $ret->setLogger($this->_logger); + } + $ret->fromArray($this->_unserializedData); + // make sure the filelist is in the easy to read format needed + $ret->flattenFilelist(); + $ret->setPackagefile($file, $archive); + return $ret; + } +} +?> \ No newline at end of file diff --git a/src/lib/pear/PEAR/PEAR/Command.php b/src/lib/pear/PEAR/PEAR/Command.php new file mode 100644 index 0000000..38fe69c --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Command.php @@ -0,0 +1,416 @@ + + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: Command.php,v 1.39 2008/01/03 20:26:34 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 0.1 + */ + +/** + * Needed for error handling + */ +require_once 'PEAR.php'; +require_once 'PEAR/Frontend.php'; +require_once 'PEAR/XMLParser.php'; + +/** + * List of commands and what classes they are implemented in. + * @var array command => implementing class + */ +$GLOBALS['_PEAR_Command_commandlist'] = array(); + +/** + * List of commands and their descriptions + * @var array command => description + */ +$GLOBALS['_PEAR_Command_commanddesc'] = array(); + +/** + * List of shortcuts to common commands. + * @var array shortcut => command + */ +$GLOBALS['_PEAR_Command_shortcuts'] = array(); + +/** + * Array of command objects + * @var array class => object + */ +$GLOBALS['_PEAR_Command_objects'] = array(); + +/** + * PEAR command class, a simple factory class for administrative + * commands. + * + * How to implement command classes: + * + * - The class must be called PEAR_Command_Nnn, installed in the + * "PEAR/Common" subdir, with a method called getCommands() that + * returns an array of the commands implemented by the class (see + * PEAR/Command/Install.php for an example). + * + * - The class must implement a run() function that is called with three + * params: + * + * (string) command name + * (array) assoc array with options, freely defined by each + * command, for example: + * array('force' => true) + * (array) list of the other parameters + * + * The run() function returns a PEAR_CommandResponse object. Use + * these methods to get information: + * + * int getStatus() Returns PEAR_COMMAND_(SUCCESS|FAILURE|PARTIAL) + * *_PARTIAL means that you need to issue at least + * one more command to complete the operation + * (used for example for validation steps). + * + * string getMessage() Returns a message for the user. Remember, + * no HTML or other interface-specific markup. + * + * If something unexpected happens, run() returns a PEAR error. + * + * - DON'T OUTPUT ANYTHING! Return text for output instead. + * + * - DON'T USE HTML! The text you return will be used from both Gtk, + * web and command-line interfaces, so for now, keep everything to + * plain text. + * + * - DON'T USE EXIT OR DIE! Always use pear errors. From static + * classes do PEAR::raiseError(), from other classes do + * $this->raiseError(). + * @category pear + * @package PEAR + * @author Stig Bakken + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 0.1 + */ +class PEAR_Command +{ + // {{{ factory() + + /** + * Get the right object for executing a command. + * + * @param string $command The name of the command + * @param object $config Instance of PEAR_Config object + * + * @return object the command object or a PEAR error + * + * @access public + * @static + */ + function &factory($command, &$config) + { + if (empty($GLOBALS['_PEAR_Command_commandlist'])) { + PEAR_Command::registerCommands(); + } + if (isset($GLOBALS['_PEAR_Command_shortcuts'][$command])) { + $command = $GLOBALS['_PEAR_Command_shortcuts'][$command]; + } + if (!isset($GLOBALS['_PEAR_Command_commandlist'][$command])) { + $a = PEAR::raiseError("unknown command `$command'"); + return $a; + } + $class = $GLOBALS['_PEAR_Command_commandlist'][$command]; + if (!class_exists($class)) { + require_once $GLOBALS['_PEAR_Command_objects'][$class]; + } + if (!class_exists($class)) { + $a = PEAR::raiseError("unknown command `$command'"); + return $a; + } + $ui =& PEAR_Command::getFrontendObject(); + $obj = &new $class($ui, $config); + return $obj; + } + + // }}} + // {{{ & getObject() + function &getObject($command) + { + $class = $GLOBALS['_PEAR_Command_commandlist'][$command]; + if (!class_exists($class)) { + require_once $GLOBALS['_PEAR_Command_objects'][$class]; + } + if (!class_exists($class)) { + return PEAR::raiseError("unknown command `$command'"); + } + $ui =& PEAR_Command::getFrontendObject(); + $config = &PEAR_Config::singleton(); + $obj = &new $class($ui, $config); + return $obj; + } + + // }}} + // {{{ & getFrontendObject() + + /** + * Get instance of frontend object. + * + * @return object|PEAR_Error + * @static + */ + function &getFrontendObject() + { + $a = &PEAR_Frontend::singleton(); + return $a; + } + + // }}} + // {{{ & setFrontendClass() + + /** + * Load current frontend class. + * + * @param string $uiclass Name of class implementing the frontend + * + * @return object the frontend object, or a PEAR error + * @static + */ + function &setFrontendClass($uiclass) + { + $a = &PEAR_Frontend::setFrontendClass($uiclass); + return $a; + } + + // }}} + // {{{ setFrontendType() + + /** + * Set current frontend. + * + * @param string $uitype Name of the frontend type (for example "CLI") + * + * @return object the frontend object, or a PEAR error + * @static + */ + function setFrontendType($uitype) + { + $uiclass = 'PEAR_Frontend_' . $uitype; + return PEAR_Command::setFrontendClass($uiclass); + } + + // }}} + // {{{ registerCommands() + + /** + * Scan through the Command directory looking for classes + * and see what commands they implement. + * + * @param bool (optional) if FALSE (default), the new list of + * commands should replace the current one. If TRUE, + * new entries will be merged with old. + * + * @param string (optional) where (what directory) to look for + * classes, defaults to the Command subdirectory of + * the directory from where this file (__FILE__) is + * included. + * + * @return bool TRUE on success, a PEAR error on failure + * + * @access public + * @static + */ + function registerCommands($merge = false, $dir = null) + { + $parser = new PEAR_XMLParser; + if ($dir === null) { + $dir = dirname(__FILE__) . '/Command'; + } + if (!is_dir($dir)) { + return PEAR::raiseError("registerCommands: opendir($dir) '$dir' does not exist or is not a directory"); + } + $dp = @opendir($dir); + if (empty($dp)) { + return PEAR::raiseError("registerCommands: opendir($dir) failed"); + } + if (!$merge) { + $GLOBALS['_PEAR_Command_commandlist'] = array(); + } + while ($entry = readdir($dp)) { + if ($entry{0} == '.' || substr($entry, -4) != '.xml') { + continue; + } + $class = "PEAR_Command_".substr($entry, 0, -4); + $file = "$dir/$entry"; + $parser->parse(file_get_contents($file)); + $implements = $parser->getData(); + // List of commands + if (empty($GLOBALS['_PEAR_Command_objects'][$class])) { + $GLOBALS['_PEAR_Command_objects'][$class] = "$dir/" . substr($entry, 0, -4) . + '.php'; + } + foreach ($implements as $command => $desc) { + if ($command == 'attribs') { + continue; + } + if (isset($GLOBALS['_PEAR_Command_commandlist'][$command])) { + return PEAR::raiseError('Command "' . $command . '" already registered in ' . + 'class "' . $GLOBALS['_PEAR_Command_commandlist'][$command] . '"'); + } + $GLOBALS['_PEAR_Command_commandlist'][$command] = $class; + $GLOBALS['_PEAR_Command_commanddesc'][$command] = $desc['summary']; + if (isset($desc['shortcut'])) { + $shortcut = $desc['shortcut']; + if (isset($GLOBALS['_PEAR_Command_shortcuts'][$shortcut])) { + return PEAR::raiseError('Command shortcut "' . $shortcut . '" already ' . + 'registered to command "' . $command . '" in class "' . + $GLOBALS['_PEAR_Command_commandlist'][$command] . '"'); + } + $GLOBALS['_PEAR_Command_shortcuts'][$shortcut] = $command; + } + if (isset($desc['options']) && $desc['options']) { + foreach ($desc['options'] as $oname => $option) { + if (isset($option['shortopt']) && strlen($option['shortopt']) > 1) { + return PEAR::raiseError('Option "' . $oname . '" short option "' . + $option['shortopt'] . '" must be ' . + 'only 1 character in Command "' . $command . '" in class "' . + $class . '"'); + } + } + } + } + } + ksort($GLOBALS['_PEAR_Command_shortcuts']); + ksort($GLOBALS['_PEAR_Command_commandlist']); + @closedir($dp); + return true; + } + + // }}} + // {{{ getCommands() + + /** + * Get the list of currently supported commands, and what + * classes implement them. + * + * @return array command => implementing class + * + * @access public + * @static + */ + function getCommands() + { + if (empty($GLOBALS['_PEAR_Command_commandlist'])) { + PEAR_Command::registerCommands(); + } + return $GLOBALS['_PEAR_Command_commandlist']; + } + + // }}} + // {{{ getShortcuts() + + /** + * Get the list of command shortcuts. + * + * @return array shortcut => command + * + * @access public + * @static + */ + function getShortcuts() + { + if (empty($GLOBALS['_PEAR_Command_shortcuts'])) { + PEAR_Command::registerCommands(); + } + return $GLOBALS['_PEAR_Command_shortcuts']; + } + + // }}} + // {{{ getGetoptArgs() + + /** + * Compiles arguments for getopt. + * + * @param string $command command to get optstring for + * @param string $short_args (reference) short getopt format + * @param array $long_args (reference) long getopt format + * + * @return void + * + * @access public + * @static + */ + function getGetoptArgs($command, &$short_args, &$long_args) + { + if (empty($GLOBALS['_PEAR_Command_commandlist'])) { + PEAR_Command::registerCommands(); + } + if (isset($GLOBALS['_PEAR_Command_shortcuts'][$command])) { + $command = $GLOBALS['_PEAR_Command_shortcuts'][$command]; + } + if (!isset($GLOBALS['_PEAR_Command_commandlist'][$command])) { + return null; + } + $obj = &PEAR_Command::getObject($command); + return $obj->getGetoptArgs($command, $short_args, $long_args); + } + + // }}} + // {{{ getDescription() + + /** + * Get description for a command. + * + * @param string $command Name of the command + * + * @return string command description + * + * @access public + * @static + */ + function getDescription($command) + { + if (!isset($GLOBALS['_PEAR_Command_commanddesc'][$command])) { + return null; + } + return $GLOBALS['_PEAR_Command_commanddesc'][$command]; + } + + // }}} + // {{{ getHelp() + + /** + * Get help for command. + * + * @param string $command Name of the command to return help for + * + * @access public + * @static + */ + function getHelp($command) + { + $cmds = PEAR_Command::getCommands(); + if (isset($GLOBALS['_PEAR_Command_shortcuts'][$command])) { + $command = $GLOBALS['_PEAR_Command_shortcuts'][$command]; + } + if (isset($cmds[$command])) { + $obj = &PEAR_Command::getObject($command); + return $obj->getHelp($command); + } + return false; + } + // }}} +} + +?> diff --git a/src/lib/pear/PEAR/PEAR/Command/Auth.php b/src/lib/pear/PEAR/PEAR/Command/Auth.php new file mode 100644 index 0000000..005235b --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Command/Auth.php @@ -0,0 +1,203 @@ + + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: Auth.php,v 1.31 2008/01/03 20:26:36 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 0.1 + */ + +/** + * base class + */ +require_once 'PEAR/Command/Common.php'; +require_once 'PEAR/Config.php'; + +/** + * PEAR commands for login/logout + * + * @category pear + * @package PEAR + * @author Stig Bakken + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 0.1 + */ +class PEAR_Command_Auth extends PEAR_Command_Common +{ + // {{{ properties + + var $commands = array( + 'login' => array( + 'summary' => 'Connects and authenticates to remote server', + 'shortcut' => 'li', + 'function' => 'doLogin', + 'options' => array(), + 'doc' => ' +Log in to a remote channel server. If is not supplied, +the default channel is used. To use remote functions in the installer +that require any kind of privileges, you need to log in first. The +username and password you enter here will be stored in your per-user +PEAR configuration (~/.pearrc on Unix-like systems). After logging +in, your username and password will be sent along in subsequent +operations on the remote server.', + ), + 'logout' => array( + 'summary' => 'Logs out from the remote server', + 'shortcut' => 'lo', + 'function' => 'doLogout', + 'options' => array(), + 'doc' => ' +Logs out from the remote server. This command does not actually +connect to the remote server, it only deletes the stored username and +password from your user configuration.', + ) + + ); + + // }}} + + // {{{ constructor + + /** + * PEAR_Command_Auth constructor. + * + * @access public + */ + function PEAR_Command_Auth(&$ui, &$config) + { + parent::PEAR_Command_Common($ui, $config); + } + + // }}} + + // {{{ doLogin() + + /** + * Execute the 'login' command. + * + * @param string $command command name + * + * @param array $options option_name => value + * + * @param array $params list of additional parameters + * + * @return bool TRUE on success or + * a PEAR error on failure + * + * @access public + */ + function doLogin($command, $options, $params) + { + $reg = &$this->config->getRegistry(); + + // If a parameter is supplied, use that as the channel to log in to + if (isset($params[0])) { + $channel = $params[0]; + } else { + $channel = $this->config->get('default_channel'); + } + + $chan = $reg->getChannel($channel); + if (PEAR::isError($chan)) { + return $this->raiseError($chan); + } + $server = $this->config->get('preferred_mirror', null, $channel); + $remote = &$this->config->getRemote(); + $username = $this->config->get('username', null, $channel); + if (empty($username)) { + $username = isset($_ENV['USER']) ? $_ENV['USER'] : null; + } + $this->ui->outputData("Logging in to $server.", $command); + + list($username, $password) = $this->ui->userDialog( + $command, + array('Username', 'Password'), + array('text', 'password'), + array($username, '') + ); + $username = trim($username); + $password = trim($password); + + $ourfile = $this->config->getConfFile('user'); + if (!$ourfile) { + $ourfile = $this->config->getConfFile('system'); + } + + $this->config->set('username', $username, 'user', $channel); + $this->config->set('password', $password, 'user', $channel); + + if ($chan->supportsREST()) { + $ok = true; + } else { + $remote->expectError(401); + $ok = $remote->call('logintest'); + $remote->popExpect(); + } + if ($ok === true) { + $this->ui->outputData("Logged in.", $command); + // avoid changing any temporary settings changed with -d + $ourconfig = new PEAR_Config($ourfile, $ourfile); + $ourconfig->set('username', $username, 'user', $channel); + $ourconfig->set('password', $password, 'user', $channel); + $ourconfig->store(); + } else { + return $this->raiseError("Login failed!"); + } + return true; + } + + // }}} + // {{{ doLogout() + + /** + * Execute the 'logout' command. + * + * @param string $command command name + * + * @param array $options option_name => value + * + * @param array $params list of additional parameters + * + * @return bool TRUE on success or + * a PEAR error on failure + * + * @access public + */ + function doLogout($command, $options, $params) + { + $reg = &$this->config->getRegistry(); + $channel = $this->config->get('default_channel'); + $chan = $reg->getChannel($channel); + if (PEAR::isError($chan)) { + return $this->raiseError($chan); + } + $server = $this->config->get('preferred_mirror'); + $this->ui->outputData("Logging out from $server.", $command); + $this->config->remove('username'); + $this->config->remove('password'); + $this->config->store(); + return true; + } + + // }}} +} + +?> \ No newline at end of file diff --git a/src/lib/pear/PEAR/PEAR/Command/Auth.xml b/src/lib/pear/PEAR/PEAR/Command/Auth.xml new file mode 100644 index 0000000..17e3b34 --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Command/Auth.xml @@ -0,0 +1,26 @@ + + + Connects and authenticates to remote server + li + doLogin + + <channel name> +Log in to a remote channel server. <channel name> is not supplied, +the default channel is used. To use remote functions in the installer +that require any kind of privileges, you need to log in first. The +username and password you enter here will be stored in your per-user +PEAR configuration (~/.pearrc on Unix-like systems). After logging +in, your username and password will be sent along in subsequent +operations on the remote server. + + + Logs out from the remote server + lo + doLogout + + +Logs out from the remote server. This command does not actually +connect to the remote server, it only deletes the stored username and +password from your user configuration. + + \ No newline at end of file diff --git a/src/lib/pear/PEAR/PEAR/Command/Build.php b/src/lib/pear/PEAR/PEAR/Command/Build.php new file mode 100644 index 0000000..d677310 --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Command/Build.php @@ -0,0 +1,104 @@ + + * @author Tomas V.V.Cox + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: Build.php,v 1.14 2008/01/03 20:26:36 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 0.1 + */ + +/** + * base class + */ +require_once 'PEAR/Command/Common.php'; + +/** + * PEAR commands for building extensions. + * + * @category pear + * @package PEAR + * @author Stig Bakken + * @author Tomas V.V.Cox + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 0.1 + */ +class PEAR_Command_Build extends PEAR_Command_Common +{ + // {{{ properties + + var $commands = array( + 'build' => array( + 'summary' => 'Build an Extension From C Source', + 'function' => 'doBuild', + 'shortcut' => 'b', + 'options' => array(), + 'doc' => '[package.xml] +Builds one or more extensions contained in a package.' + ), + ); + + // }}} + + // {{{ constructor + + /** + * PEAR_Command_Build constructor. + * + * @access public + */ + function PEAR_Command_Build(&$ui, &$config) + { + parent::PEAR_Command_Common($ui, $config); + } + + // }}} + + // {{{ doBuild() + + function doBuild($command, $options, $params) + { + require_once 'PEAR/Builder.php'; + if (sizeof($params) < 1) { + $params[0] = 'package.xml'; + } + $builder = &new PEAR_Builder($this->ui); + $this->debug = $this->config->get('verbose'); + $err = $builder->build($params[0], array(&$this, 'buildCallback')); + if (PEAR::isError($err)) { + return $err; + } + return true; + } + + // }}} + // {{{ buildCallback() + + function buildCallback($what, $data) + { + if (($what == 'cmdoutput' && $this->debug > 1) || + ($what == 'output' && $this->debug > 0)) { + $this->ui->outputData(rtrim($data), 'build'); + } + } + + // }}} +} diff --git a/src/lib/pear/PEAR/PEAR/Command/Build.xml b/src/lib/pear/PEAR/PEAR/Command/Build.xml new file mode 100644 index 0000000..ec4e6f5 --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Command/Build.xml @@ -0,0 +1,10 @@ + + + Build an Extension From C Source + doBuild + b + + [package.xml] +Builds one or more extensions contained in a package. + + \ No newline at end of file diff --git a/src/lib/pear/PEAR/PEAR/Command/Categories.php b/src/lib/pear/PEAR/PEAR/Command/Categories.php new file mode 100644 index 0000000..b4c01a3 --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Command/Categories.php @@ -0,0 +1,401 @@ + + * @copyright 1997-2007 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: Categories.php,v 1.1 2007/06/17 14:33:52 tias Exp $ + * @link http://pear.php.net/package/PEAR_Frontend_Web + * @since File available since Release 1.0 + */ + +/** + * base class + */ +require_once 'PEAR/Command/Common.php'; +require_once 'PEAR/REST.php'; + +/** + * PEAR_Frontend_Web command for listing individual category information + * + * @category pear + * @package PEAR_Frontend_Web + * @author Tias Guns + * @copyright 1997-2007 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: TODO + * @link http://pear.php.net/package/PEAR_Frontend_Web + * @since File available since Release 0.6.0 + */ +class PEAR_Command_Categories extends PEAR_Command_Common +{ + // {{{ properties + + var $commands = array( + 'list-packages' => array( + 'summary' => 'List All Packages of a Channel', + 'function' => 'doListPackages', + 'shortcut' => 'lp', + 'options' => array( + 'channel' => array( + 'shortopt' => 'c', + 'doc' => 'specify a channel other than the default channel', + 'arg' => 'CHAN', + ), + 'allchannels' => array( + 'shortopt' => 'a', + 'doc' => 'list available packages from all channels', + ), + ), + 'doc' => ' +Lists all the packages of a channel. For each channel it displays the +channel and package name.', + ), + 'list-categories' => array( + 'summary' => 'List All Categories', + 'function' => 'doListCategories', + 'shortcut' => 'cats', + 'options' => array( + 'channel' => array( + 'shortopt' => 'c', + 'doc' => 'specify a channel other than the default channel', + 'arg' => 'CHAN', + ), + 'allchannels' => array( + 'shortopt' => 'a', + 'doc' => 'list available categories from all channels', + ), + 'packages' => array( + 'shortopt' => 'p', + 'doc' => 'list the packagenames of the categories too', + ), + ), + 'doc' => ' +Lists the categories available on the channel server. For each channel +it displays the channel and categorie name, and optionally the all the +names of the packages in the categories.', + ), + 'list-category' => array( + 'summary' => 'List All Packages of a Category', + 'function' => 'doListCategory', + 'shortcut' => 'cat', + 'options' => array( + 'channel' => array( + 'shortopt' => 'c', + 'doc' => 'specify a channel other than the default channel', + 'arg' => 'CHAN', + ) + ), + 'doc' => ' [...] +Lists all the packages of a category of a channel. For each category +it displays the channel and package name, with local and remote version +information, and the summary.', + ), + ); + + // }}} + // {{{ constructor + + /** + * PEAR_Command_Registry constructor. + * + * @access public + */ + function PEAR_Command_Categories(&$ui, &$config) + { + parent::PEAR_Command_Common($ui, $config); + } + + // }}} + // {{{ doListPackages() + + function doListPackages($command, $options, $params) + { + $reg = &$this->config->getRegistry(); + if (isset($options['allchannels']) && $options['allchannels'] == true) { + // over all channels + unset($options['allchannels']); + $channels = $reg->getChannels(); + $errors = array(); + foreach ($channels as $channel) { + if ($channel->getName() != '__uri') { + $options['channel'] = $channel->getName(); + $ret = $this->doListPackages($command, $options, $params); + if ($ret !== true) { + $errors[] = $ret; + } + } + } + if (count($errors) !== 0) { + // for now, only give first error + return $errors[0]; + } + return true; + } + + $savechannel = $channel = $this->config->get('default_channel'); + if (isset($options['channel'])) { + $channel = $options['channel']; + if ($reg->channelExists($channel)) { + $this->config->set('default_channel', $channel); + } else { + return $this->raiseError("Channel \"$channel\" does not exist"); + } + } + $chan = $reg->getChannel($channel); + // we need Remote::_checkChannelForStatus() + require_once 'PEAR/Command/Remote.php'; + //$cmd = new PEAR_Command_Remote($this->ui, $this->config); + //if (PEAR::isError($e = $cmd->_checkChannelForStatus($channel, $chan))) { + if (PEAR::isError($e = PEAR_Command_Remote::_checkChannelForStatus($channel, $chan))) { + return $e; + } + if ($chan->supportsREST($this->config->get('preferred_mirror')) && + $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) { + $rest = &$this->config->getREST('1.0', array()); + $packages = $rest->listPackages($base); + } else { + return PEAR::raiseError($command.' only works for REST servers'); + } + if (PEAR::isError($packages)) { + $this->config->set('default_channel', $savechannel); + return $this->raiseError('The package list could not be fetched from the remote server. Please try again. (Debug info: "' . $packages->getMessage() . '")'); + } + + $data = array( + 'caption' => 'Channel ' . $channel . ' All packages:', + 'border' => true, + 'headline' => array('Channel', 'Package'), + 'channel' => $channel, + ); + + if (count($packages) === 0) { + unset($data['headline']); + $data['data'] = 'No packages registered'; + } else { + $data['data'] = array(); + foreach($packages as $item) { + $array = array( + $channel, + $item, + ); + $data['data'][] = $array; + } + } + + $this->config->set('default_channel', $savechannel); + $this->ui->outputData($data, $command); + return true; + } + + // }}} + // {{{ doListCategories() + + function doListCategories($command, $options, $params) + { + $reg = &$this->config->getRegistry(); + if (isset($options['allchannels']) && $options['allchannels'] == true) { + // over all channels + unset($options['allchannels']); + $channels = $reg->getChannels(); + $errors = array(); + foreach ($channels as $channel) { + if ($channel->getName() != '__uri') { + $options['channel'] = $channel->getName(); + $ret = $this->doListCategories($command, $options, $params); + if ($ret !== true) { + $errors[] = $ret; + } + } + } + if (count($errors) !== 0) { + // for now, only give first error + return $errors[0]; + } + return true; + } + + $savechannel = $channel = $this->config->get('default_channel'); + if (isset($options['channel'])) { + $channel = $options['channel']; + if ($reg->channelExists($channel)) { + $this->config->set('default_channel', $channel); + } else { + return $this->raiseError("Channel \"$channel\" does not exist"); + } + } + $chan = $reg->getChannel($channel); + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + // we need Remote::_checkChannelForStatus() + require_once 'PEAR/Command/Remote.php'; + //$cmd = new PEAR_Command_Remote($this->ui, $this->config); + //if (PEAR::isError($e = $cmd->_checkChannelForStatus($channel, $chan))) { + if (PEAR::isError($e = PEAR_Command_Remote::_checkChannelForStatus($channel, $chan))) { + return $e; + } + if ($chan->supportsREST($this->config->get('preferred_mirror')) && + $base = $chan->getBaseURL('REST1.1', $this->config->get('preferred_mirror'))) { + $rest = &$this->config->getREST('1.1', array()); + } elseif ($chan->supportsREST($this->config->get('preferred_mirror')) && + $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) { + $rest = &$this->config->getREST('1.0', array()); + } else { + return PEAR::raiseError($command.' only works for REST servers'); + } + $categories = $rest->listCategories($base); + + $data = array( + 'caption' => 'Channel ' . $channel . ' All categories:', + 'border' => true, + 'headline' => array('Channel', 'Category'), + 'channel' => $channel, + ); + if (isset($options['packages']) && $options['packages']) { + $data['headline'][] = 'Packages'; + } + + if (PEAR::isError($categories)) { + unset($data['headline']); + $data['data'] = 'The category list could not be fetched from the remote server. Please try again. (Debug info: "' . $categories->getMessage() . '")'; + } elseif (count($categories) === 0) { + unset($data['headline']); + $data['data'] = 'No categories registered'; + } else { + $data['data'] = array(); + + foreach($categories as $item) { + $category = $item['_content']; + $array = array( + $channel, + $category); + + if (isset($options['packages']) && $options['packages']) { + // get packagenames + $cat_pkgs = $rest->listCategory($base, $category); + if (!PEAR::isError($cat_pkgs)) { + $packages = array(); + foreach($cat_pkgs as $cat_pkg) { + $packages[] = $cat_pkg['_content']; + } + $array[] = $packages; + } + } + $data['data'][] = $array; + } + } + PEAR::staticPopErrorHandling(); + + $this->config->set('default_channel', $savechannel); + $this->ui->outputData($data, $command); + return true; + } + + // }}} + // {{{ doListCategory() + + function doListCategory($command, $options, $params) + { + if (count($params) < 1) { + return PEAR::raiseError('Not enough parameters, use: '.$command.' [...]'); + } + if (count($params) > 1) { + $errors = array(); + foreach($params as $pkg) { + $ret = $this->doListCategory($command, $options, array($pkg)); + if ($ret !== true) { + $errors[] = $ret; + return $ret; + } + } + if (count($errors) !== 0) { + // for now, only give first error + return $errors[0]; + } + return true; + } + $category = $params[0]; + + $savechannel = $channel = $this->config->get('default_channel'); + $reg = &$this->config->getRegistry(); + if (isset($options['channel'])) { + $channel = $options['channel']; + if ($reg->channelExists($channel)) { + $this->config->set('default_channel', $channel); + } else { + return $this->raiseError("Channel \"$channel\" does not exist"); + } + } + $chan = $reg->getChannel($channel); + // we need Remote::_checkChannelForStatus() + require_once 'PEAR/Command/Remote.php'; + //$cmd = new PEAR_Command_Remote($this->ui, $this->config); + //if (PEAR::isError($e = $cmd->_checkChannelForStatus($channel, $chan))) { + if (PEAR::isError($e = PEAR_Command_Remote::_checkChannelForStatus($channel, $chan))) { + return $e; + } + if ($chan->supportsREST($this->config->get('preferred_mirror')) && + $base = $chan->getBaseURL('REST1.1', $this->config->get('preferred_mirror'))) { + $rest = &$this->config->getREST('1.1', array()); + } elseif ($chan->supportsREST($this->config->get('preferred_mirror')) && + $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) { + $rest = &$this->config->getREST('1.0', array()); + } else { + return PEAR::raiseError($command.' only works for REST servers'); + } + $packages = $rest->listCategory($base, $category, true); + if (PEAR::isError($packages)) { + $this->config->set('default_channel', $savechannel); + return $this->raiseError('The package list could not be fetched from the remote server. Please try again. (Debug info: "' . $packages->getMessage() . '")'); + } + + $data = array( + 'caption' => 'Channel '.$channel.' Category '.$category.' All packages:', + 'border' => true, + 'headline' => array('Channel', 'Package', 'Local', 'Remote', 'Summary'), + 'channel' => $channel, + ); + if (count($packages) === 0) { + unset($data['headline']); + $data['data'] = 'No packages registered'; + } else { + $data['data'] = array(); + foreach ($packages as $package_data) { + $package = $package_data['_content']; + $info = $package_data['info']; + if (!isset($info['v'])) { + $remote = '-'; + } else { + $remote = $info['v'].' ('.$info['st'].')'; + } + $summary = $info['s']; + if ($reg->packageExists($package, $channel)) { + $local = sprintf('%s (%s)', + $reg->packageInfo($package, 'version', $channel), + $reg->packageInfo($package, 'release_state', $channel)); + } else { + $local = '-'; + } + $data['data'][] = array($channel, $package, $local, $remote, $summary); + } + } + + $this->config->set('default_channel', $savechannel); + $this->ui->outputData($data, $command); + return true; + } + +} + +?> diff --git a/src/lib/pear/PEAR/PEAR/Command/Categories.xml b/src/lib/pear/PEAR/PEAR/Command/Categories.xml new file mode 100644 index 0000000..045cf7f --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Command/Categories.xml @@ -0,0 +1,61 @@ + + + List All Packages of a Channel + doListPackages + lp + + + c + specify a channel other than the default channel + CHAN + + + a + list available packages from all channels + + + +Lists all the packages of a channel. For each channel it displays the +channel and package name. + + + List All Categories + doListCategories + cats + + + c + specify a channel other than the default channel + CHAN + + + a + list available categories from all channels + + + p + list the packagenames of the categories too + + + +Lists the categories available on the channel server. For each channel +it displays the channel and categorie name, and optionally the all the +names of the packages in the categories. + + + List All Packages of a Category + doListCategory + cat + + + c + specify a channel other than the default channel + CHAN + + + <category> [<category>...] +Lists all the packages of a category of a channel. For each category +it displays the channel and package name, with local and remote version +information, and the summary. + + \ No newline at end of file diff --git a/src/lib/pear/PEAR/PEAR/Command/Channels.php b/src/lib/pear/PEAR/PEAR/Command/Channels.php new file mode 100644 index 0000000..5de0d39 --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Command/Channels.php @@ -0,0 +1,737 @@ + + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: Channels.php,v 1.57 2008/01/03 20:26:36 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 1.4.0a1 + */ + +/** + * base class + */ +require_once 'PEAR/Command/Common.php'; + +/** + * PEAR commands for managing channels. + * + * @category pear + * @package PEAR + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 1.4.0a1 + */ +class PEAR_Command_Channels extends PEAR_Command_Common +{ + // {{{ properties + + var $commands = array( + 'list-channels' => array( + 'summary' => 'List Available Channels', + 'function' => 'doList', + 'shortcut' => 'lc', + 'options' => array(), + 'doc' => ' +List all available channels for installation. +', + ), + 'update-channels' => array( + 'summary' => 'Update the Channel List', + 'function' => 'doUpdateAll', + 'shortcut' => 'uc', + 'options' => array(), + 'doc' => ' +List all installed packages in all channels. +' + ), + 'channel-delete' => array( + 'summary' => 'Remove a Channel From the List', + 'function' => 'doDelete', + 'shortcut' => 'cde', + 'options' => array(), + 'doc' => ' +Delete a channel from the registry. You may not +remove any channel that has installed packages. +' + ), + 'channel-add' => array( + 'summary' => 'Add a Channel', + 'function' => 'doAdd', + 'shortcut' => 'ca', + 'options' => array(), + 'doc' => ' +Add a private channel to the channel list. Note that all +public channels should be synced using "update-channels". +Parameter may be either a local file or remote URL to a +channel.xml. +' + ), + 'channel-update' => array( + 'summary' => 'Update an Existing Channel', + 'function' => 'doUpdate', + 'shortcut' => 'cu', + 'options' => array( + 'force' => array( + 'shortopt' => 'f', + 'doc' => 'will force download of new channel.xml if an existing channel name is used', + ), + 'channel' => array( + 'shortopt' => 'c', + 'arg' => 'CHANNEL', + 'doc' => 'will force download of new channel.xml if an existing channel name is used', + ), +), + 'doc' => '[|] +Update a channel in the channel list directly. Note that all +public channels can be synced using "update-channels". +Parameter may be a local or remote channel.xml, or the name of +an existing channel. +' + ), + 'channel-info' => array( + 'summary' => 'Retrieve Information on a Channel', + 'function' => 'doInfo', + 'shortcut' => 'ci', + 'options' => array(), + 'doc' => ' +List the files in an installed package. +' + ), + 'channel-alias' => array( + 'summary' => 'Specify an alias to a channel name', + 'function' => 'doAlias', + 'shortcut' => 'cha', + 'options' => array(), + 'doc' => ' +Specify a specific alias to use for a channel name. +The alias may not be an existing channel name or +alias. +' + ), + 'channel-discover' => array( + 'summary' => 'Initialize a Channel from its server', + 'function' => 'doDiscover', + 'shortcut' => 'di', + 'options' => array(), + 'doc' => '[|] +Initialize a channel from its server and create a local channel.xml. +If is in the format ":@" then + and will be set as the login username/password for +. Use caution when passing the username/password in this way, as +it may allow other users on your computer to briefly view your username/ +password via the system\'s process list. +' + ), + ); + + // }}} + // {{{ constructor + + /** + * PEAR_Command_Registry constructor. + * + * @access public + */ + function PEAR_Command_Channels(&$ui, &$config) + { + parent::PEAR_Command_Common($ui, $config); + } + + // }}} + + // {{{ doList() + + function _sortChannels($a, $b) + { + return strnatcasecmp($a->getName(), $b->getName()); + } + + function doList($command, $options, $params) + { + $reg = &$this->config->getRegistry(); + $registered = $reg->getChannels(); + usort($registered, array(&$this, '_sortchannels')); + $i = $j = 0; + $data = array( + 'caption' => 'Registered Channels:', + 'border' => true, + 'headline' => array('Channel', 'Summary') + ); + foreach ($registered as $channel) { + $data['data'][] = array($channel->getName(), + $channel->getSummary()); + } + if (count($registered)==0) { + $data = '(no registered channels)'; + } + $this->ui->outputData($data, $command); + return true; + } + + function doUpdateAll($command, $options, $params) + { + $reg = &$this->config->getRegistry(); + $channels = $reg->getChannels(); + + $success = true; + foreach ($channels as $channel) { + if ($channel->getName() != '__uri') { + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + $err = $this->doUpdate('channel-update', + $options, + array($channel->getName())); + if (PEAR::isError($err)) { + $this->ui->outputData($err->getMessage(), $command); + $success = false; + } else { + $success &= $err; + } + } + } + return $success; + } + + function doInfo($command, $options, $params) + { + if (sizeof($params) != 1) { + return $this->raiseError("No channel specified"); + } + $reg = &$this->config->getRegistry(); + $channel = strtolower($params[0]); + if ($reg->channelExists($channel)) { + $chan = $reg->getChannel($channel); + if (PEAR::isError($chan)) { + return $this->raiseError($chan); + } + } else { + if (strpos($channel, '://')) { + $downloader = &$this->getDownloader(); + $tmpdir = $this->config->get('temp_dir'); + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + $loc = $downloader->downloadHttp($channel, $this->ui, $tmpdir); + PEAR::staticPopErrorHandling(); + if (PEAR::isError($loc)) { + return $this->raiseError('Cannot open "' . $channel . + '" (' . $loc->getMessage() . ')'); + } else { + $contents = implode('', file($loc)); + } + } else { + if (file_exists($params[0])) { + $fp = fopen($params[0], 'r'); + if (!$fp) { + return $this->raiseError('Cannot open "' . $params[0] . '"'); + } + } else { + return $this->raiseError('Unknown channel "' . $channel . '"'); + } + $contents = ''; + while (!feof($fp)) { + $contents .= fread($fp, 1024); + } + fclose($fp); + } + if (!class_exists('PEAR_ChannelFile')) { + require_once 'PEAR/ChannelFile.php'; + } + $chan = new PEAR_ChannelFile; + $chan->fromXmlString($contents); + $chan->validate(); + if ($errs = $chan->getErrors(true)) { + foreach ($errs as $err) { + $this->ui->outputData($err['level'] . ': ' . $err['message']); + } + return $this->raiseError('Channel file "' . $params[0] . '" is not valid'); + } + } + if ($chan) { + $channel = $chan->getName(); + $caption = 'Channel ' . $channel . ' Information:'; + $data1 = array( + 'caption' => $caption, + 'border' => true); + $data1['data']['server'] = array('Name and Server', $chan->getName()); + if ($chan->getAlias() != $chan->getName()) { + $data1['data']['alias'] = array('Alias', $chan->getAlias()); + } + $data1['data']['summary'] = array('Summary', $chan->getSummary()); + $validate = $chan->getValidationPackage(); + $data1['data']['vpackage'] = array('Validation Package Name', $validate['_content']); + $data1['data']['vpackageversion'] = + array('Validation Package Version', $validate['attribs']['version']); + $d = array(); + $d['main'] = $data1; + + $data['data'] = array(); + $data['caption'] = 'Server Capabilities'; + $data['headline'] = array('Type', 'Version/REST type', 'Function Name/REST base'); + $capabilities = $chan->getFunctions('xmlrpc'); + $soaps = $chan->getFunctions('soap'); + if ($capabilities || $soaps || $chan->supportsREST()) { + if ($capabilities) { + if (!isset($capabilities[0])) { + $capabilities = array($capabilities); + } + foreach ($capabilities as $protocol) { + $data['data'][] = array('xmlrpc', $protocol['attribs']['version'], + $protocol['_content']); + } + } + if ($soaps) { + if (!isset($soaps[0])) { + $soaps = array($soaps); + } + foreach ($soaps as $protocol) { + $data['data'][] = array('soap', $protocol['attribs']['version'], + $protocol['_content']); + } + } + if ($chan->supportsREST()) { + $funcs = $chan->getFunctions('rest'); + if (!isset($funcs[0])) { + $funcs = array($funcs); + } + foreach ($funcs as $protocol) { + $data['data'][] = array('rest', $protocol['attribs']['type'], + $protocol['_content']); + } + } + } else { + $data['data'][] = array('No supported protocols'); + } + $d['protocols'] = $data; + $data['data'] = array(); + $mirrors = $chan->getMirrors(); + if ($mirrors) { + $data['caption'] = 'Channel ' . $channel . ' Mirrors:'; + unset($data['headline']); + foreach ($mirrors as $mirror) { + $data['data'][] = array($mirror['attribs']['host']); + $d['mirrors'] = $data; + } + foreach ($mirrors as $i => $mirror) { + $data['data'] = array(); + $data['caption'] = 'Mirror ' . $mirror['attribs']['host'] . ' Capabilities'; + $data['headline'] = array('Type', 'Version/REST type', 'Function Name/REST base'); + $capabilities = $chan->getFunctions('xmlrpc', $mirror['attribs']['host']); + $soaps = $chan->getFunctions('soap', $mirror['attribs']['host']); + if ($capabilities || $soaps || $chan->supportsREST($mirror['attribs']['host'])) { + if ($capabilities) { + if (!isset($capabilities[0])) { + $capabilities = array($capabilities); + } + foreach ($capabilities as $protocol) { + $data['data'][] = array('xmlrpc', $protocol['attribs']['version'], + $protocol['_content']); + } + } + if ($soaps) { + if (!isset($soaps[0])) { + $soaps = array($soaps); + } + foreach ($soaps as $protocol) { + $data['data'][] = array('soap', $protocol['attribs']['version'], + $protocol['_content']); + } + } + if ($chan->supportsREST($mirror['attribs']['host'])) { + $funcs = $chan->getFunctions('rest', $mirror['attribs']['host']); + if (!isset($funcs[0])) { + $funcs = array($funcs); + } + foreach ($funcs as $protocol) { + $data['data'][] = array('rest', $protocol['attribs']['type'], + $protocol['_content']); + } + } + } else { + $data['data'][] = array('No supported protocols'); + } + $d['mirrorprotocols' . $i] = $data; + } + } + $this->ui->outputData($d, 'channel-info'); + } else { + return $this->raiseError('Serious error: Channel "' . $params[0] . + '" has a corrupted registry entry'); + } + } + + // }}} + + function doDelete($command, $options, $params) + { + if (sizeof($params) != 1) { + return $this->raiseError('channel-delete: no channel specified'); + } + $reg = &$this->config->getRegistry(); + if (!$reg->channelExists($params[0])) { + return $this->raiseError('channel-delete: channel "' . $params[0] . '" does not exist'); + } + $channel = $reg->channelName($params[0]); + if ($channel == 'pear.php.net') { + return $this->raiseError('Cannot delete the pear.php.net channel'); + } + if ($channel == 'pecl.php.net') { + return $this->raiseError('Cannot delete the pecl.php.net channel'); + } + if ($channel == '__uri') { + return $this->raiseError('Cannot delete the __uri pseudo-channel'); + } + if (PEAR::isError($err = $reg->listPackages($channel))) { + return $err; + } + if (count($err)) { + return $this->raiseError('Channel "' . $channel . + '" has installed packages, cannot delete'); + } + if (!$reg->deleteChannel($channel)) { + return $this->raiseError('Channel "' . $channel . '" deletion failed'); + } else { + $this->config->deleteChannel($channel); + $this->ui->outputData('Channel "' . $channel . '" deleted', $command); + } + } + + function doAdd($command, $options, $params) + { + if (sizeof($params) != 1) { + return $this->raiseError('channel-add: no channel file specified'); + } + if (strpos($params[0], '://')) { + $downloader = &$this->getDownloader(); + $tmpdir = $this->config->get('temp_dir'); + if (!file_exists($tmpdir)) { + require_once 'System.php'; + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + $err = System::mkdir(array('-p', $tmpdir)); + PEAR::staticPopErrorHandling(); + if (PEAR::isError($err)) { + return $this->raiseError('channel-add: temp_dir does not exist: "' . + $tmpdir . + '" - You can change this location with "pear config-set temp_dir"'); + } + } + if (!is_writable($tmpdir)) { + return $this->raiseError('channel-add: temp_dir is not writable: "' . + $tmpdir . + '" - You can change this location with "pear config-set temp_dir"'); + } + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + $loc = $downloader->downloadHttp($params[0], $this->ui, $tmpdir, null, false); + PEAR::staticPopErrorHandling(); + if (PEAR::isError($loc)) { + return $this->raiseError('channel-add: Cannot open "' . $params[0] . + '" (' . $loc->getMessage() . ')'); + } else { + list($loc, $lastmodified) = $loc; + $contents = implode('', file($loc)); + } + } else { + $lastmodified = $fp = false; + if (file_exists($params[0])) { + $fp = fopen($params[0], 'r'); + } + if (!$fp) { + return $this->raiseError('channel-add: cannot open "' . $params[0] . '"'); + } + $contents = ''; + while (!feof($fp)) { + $contents .= fread($fp, 1024); + } + fclose($fp); + } + if (!class_exists('PEAR_ChannelFile')) { + require_once 'PEAR/ChannelFile.php'; + } + $channel = new PEAR_ChannelFile; + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + $result = $channel->fromXmlString($contents); + PEAR::staticPopErrorHandling(); + if (!$result) { + $exit = false; + if (count($errors = $channel->getErrors(true))) { + foreach ($errors as $error) { + $this->ui->outputData(ucfirst($error['level'] . ': ' . $error['message'])); + if (!$exit) { + $exit = $error['level'] == 'error' ? true : false; + } + } + if ($exit) { + return $this->raiseError('channel-add: invalid channel.xml file'); + } + } + } + $reg = &$this->config->getRegistry(); + if ($reg->channelExists($channel->getName())) { + return $this->raiseError('channel-add: Channel "' . $channel->getName() . + '" exists, use channel-update to update entry'); + } + $ret = $reg->addChannel($channel, $lastmodified); + if (PEAR::isError($ret)) { + return $ret; + } + if (!$ret) { + return $this->raiseError('channel-add: adding Channel "' . $channel->getName() . + '" to registry failed'); + } + $this->config->setChannels($reg->listChannels()); + $this->config->writeConfigFile(); + $this->ui->outputData('Adding Channel "' . $channel->getName() . '" succeeded', $command); + } + + function doUpdate($command, $options, $params) + { + $tmpdir = $this->config->get('temp_dir'); + if (!file_exists($tmpdir)) { + require_once 'System.php'; + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + $err = System::mkdir(array('-p', $tmpdir)); + PEAR::staticPopErrorHandling(); + if (PEAR::isError($err)) { + return $this->raiseError('channel-add: temp_dir does not exist: "' . + $tmpdir . + '" - You can change this location with "pear config-set temp_dir"'); + } + } + if (!is_writable($tmpdir)) { + return $this->raiseError('channel-add: temp_dir is not writable: "' . + $tmpdir . + '" - You can change this location with "pear config-set temp_dir"'); + } + $reg = &$this->config->getRegistry(); + if (sizeof($params) != 1) { + return $this->raiseError("No channel file specified"); + } + $lastmodified = false; + if ((!file_exists($params[0]) || is_dir($params[0])) + && $reg->channelExists(strtolower($params[0]))) { + $c = $reg->getChannel(strtolower($params[0])); + if (PEAR::isError($c)) { + return $this->raiseError($c); + } + $this->ui->outputData("Updating channel \"$params[0]\"", $command); + $dl = &$this->getDownloader(array()); + // if force is specified, use a timestamp of "1" to force retrieval + $lastmodified = isset($options['force']) ? false : $c->lastModified(); + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + $contents = $dl->downloadHttp('http://' . $c->getName() . '/channel.xml', + $this->ui, $tmpdir, null, $lastmodified); + PEAR::staticPopErrorHandling(); + if (PEAR::isError($contents)) { + return $this->raiseError('Cannot retrieve channel.xml for channel "' . + $c->getName() . '" (' . $contents->getMessage() . ')'); + } + list($contents, $lastmodified) = $contents; + if (!$contents) { + $this->ui->outputData("Channel \"$params[0]\" is up to date"); + return; + } + $contents = implode('', file($contents)); + if (!class_exists('PEAR_ChannelFile')) { + require_once 'PEAR/ChannelFile.php'; + } + $channel = new PEAR_ChannelFile; + $channel->fromXmlString($contents); + if (!$channel->getErrors()) { + // security check: is the downloaded file for the channel we got it from? + if (strtolower($channel->getName()) != strtolower($c->getName())) { + if (isset($options['force'])) { + $this->ui->log(0, 'WARNING: downloaded channel definition file' . + ' for channel "' . $channel->getName() . '" from channel "' . + strtolower($c->getName()) . '"'); + } else { + return $this->raiseError('ERROR: downloaded channel definition file' . + ' for channel "' . $channel->getName() . '" from channel "' . + strtolower($c->getName()) . '"'); + } + } + } + } else { + if (strpos($params[0], '://')) { + $dl = &$this->getDownloader(); + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + $loc = $dl->downloadHttp($params[0], + $this->ui, $tmpdir, null, $lastmodified); + PEAR::staticPopErrorHandling(); + if (PEAR::isError($loc)) { + return $this->raiseError("Cannot open " . $params[0] . + ' (' . $loc->getMessage() . ')'); + } else { + list($loc, $lastmodified) = $loc; + $contents = implode('', file($loc)); + } + } else { + $fp = false; + if (file_exists($params[0])) { + $fp = fopen($params[0], 'r'); + } + if (!$fp) { + return $this->raiseError("Cannot open " . $params[0]); + } + $contents = ''; + while (!feof($fp)) { + $contents .= fread($fp, 1024); + } + fclose($fp); + } + if (!class_exists('PEAR_ChannelFile')) { + require_once 'PEAR/ChannelFile.php'; + } + $channel = new PEAR_ChannelFile; + $channel->fromXmlString($contents); + } + $exit = false; + if (count($errors = $channel->getErrors(true))) { + foreach ($errors as $error) { + $this->ui->outputData(ucfirst($error['level'] . ': ' . $error['message'])); + if (!$exit) { + $exit = $error['level'] == 'error' ? true : false; + } + } + if ($exit) { + return $this->raiseError('Invalid channel.xml file'); + } + } + if (!$reg->channelExists($channel->getName())) { + return $this->raiseError('Error: Channel "' . $channel->getName() . + '" does not exist, use channel-add to add an entry'); + } + $ret = $reg->updateChannel($channel, $lastmodified); + if (PEAR::isError($ret)) { + return $ret; + } + if (!$ret) { + return $this->raiseError('Updating Channel "' . $channel->getName() . + '" in registry failed'); + } + $this->config->setChannels($reg->listChannels()); + $this->config->writeConfigFile(); + $this->ui->outputData('Update of Channel "' . $channel->getName() . '" succeeded'); + } + + function &getDownloader() + { + if (!class_exists('PEAR_Downloader')) { + require_once 'PEAR/Downloader.php'; + } + $a = new PEAR_Downloader($this->ui, array(), $this->config); + return $a; + } + + function doAlias($command, $options, $params) + { + $reg = &$this->config->getRegistry(); + if (sizeof($params) == 1) { + return $this->raiseError('No channel alias specified'); + } + if (sizeof($params) != 2) { + return $this->raiseError( + 'Invalid format, correct is: channel-alias channel alias'); + } + if (!$reg->channelExists($params[0], true)) { + if ($reg->isAlias($params[0])) { + $extra = ' (use "channel-alias ' . $reg->channelName($params[0]) . ' ' . + strtolower($params[1]) . '")'; + } else { + $extra = ''; + } + return $this->raiseError('"' . $params[0] . '" is not a valid channel' . $extra); + } + if ($reg->isAlias($params[1])) { + return $this->raiseError('Channel "' . $reg->channelName($params[1]) . '" is ' . + 'already aliased to "' . strtolower($params[1]) . '", cannot re-alias'); + } + $chan = &$reg->getChannel($params[0]); + if (PEAR::isError($chan)) { + return $this->raiseError('Corrupt registry? Error retrieving channel "' . $params[0] . + '" information (' . $chan->getMessage() . ')'); + } + // make it a local alias + if (!$chan->setAlias(strtolower($params[1]), true)) { + return $this->raiseError('Alias "' . strtolower($params[1]) . + '" is not a valid channel alias'); + } + $reg->updateChannel($chan); + $this->ui->outputData('Channel "' . $chan->getName() . '" aliased successfully to "' . + strtolower($params[1]) . '"'); + } + + /** + * The channel-discover command + * + * @param string $command command name + * @param array $options option_name => value + * @param array $params list of additional parameters. + * $params[0] should contain a string with either: + * - or + * - :@ + * @return null|PEAR_Error + */ + function doDiscover($command, $options, $params) + { + $reg = &$this->config->getRegistry(); + if (sizeof($params) != 1) { + return $this->raiseError("No channel server specified"); + } + + // Look for the possible input format ":@" + if (preg_match('/^(.+):(.+)@(.+)\\z/', $params[0], $matches)) { + $username = $matches[1]; + $password = $matches[2]; + $channel = $matches[3]; + } else { + $channel = $params[0]; + } + + if ($reg->channelExists($channel)) { + if ($reg->isAlias($channel)) { + return $this->raiseError("A channel alias named \"$channel\" " . + 'already exists, aliasing channel "' . $reg->channelName($channel) + . '"'); + } else { + return $this->raiseError("Channel \"$channel\" is already initialized"); + } + } + $this->pushErrorHandling(PEAR_ERROR_RETURN); + $err = $this->doAdd($command, $options, array('http://' . $channel . '/channel.xml')); + $this->popErrorHandling(); + if (PEAR::isError($err)) { + return $this->raiseError("Discovery of channel \"$channel\" failed (" . + $err->getMessage() . ')'); + } + + // Store username/password if they were given + // Arguably we should do a logintest on the channel here, but since + // that's awkward on a REST-based channel (even "pear login" doesn't + // do it for those), and XML-RPC is deprecated, it's fairly pointless. + if (isset($username)) { + $this->config->set('username', $username, 'user', $channel); + $this->config->set('password', $password, 'user', $channel); + $this->config->store(); + $this->ui->outputData("Stored login for channel \"$channel\" using username \"$username\"", $command); + } + + $this->ui->outputData("Discovery of channel \"$channel\" succeeded", $command); + } +} +?> diff --git a/src/lib/pear/PEAR/PEAR/Command/Channels.xml b/src/lib/pear/PEAR/PEAR/Command/Channels.xml new file mode 100644 index 0000000..e7c7b7f --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Command/Channels.xml @@ -0,0 +1,98 @@ + + + List Available Channels + doList + lc + + +List all available channels for installation. + + + + Update the Channel List + doUpdateAll + uc + + +List all installed packages in all channels. + + + + Remove a Channel From the List + doDelete + cde + + <channel name> +Delete a channel from the registry. You may not +remove any channel that has installed packages. + + + + Add a Channel + doAdd + ca + + <channel.xml> +Add a private channel to the channel list. Note that all +public channels should be synced using "update-channels". +Parameter may be either a local file or remote URL to a +channel.xml. + + + + Update an Existing Channel + doUpdate + cu + + + f + will force download of new channel.xml if an existing channel name is used + + + c + CHANNEL + will force download of new channel.xml if an existing channel name is used + + + [<channel.xml>|<channel name>] +Update a channel in the channel list directly. Note that all +public channels can be synced using "update-channels". +Parameter may be a local or remote channel.xml, or the name of +an existing channel. + + + + Retrieve Information on a Channel + doInfo + ci + + <package> +List the files in an installed package. + + + + Specify an alias to a channel name + doAlias + cha + + <channel> <alias> +Specify a specific alias to use for a channel name. +The alias may not be an existing channel name or +alias. + + + + Initialize a Channel from its server + doDiscover + di + + [<channel.xml>|<channel name>] +Initialize a channel from its server and create a local channel.xml. +If <channel name> is in the format "<username>:<password>@<channel>" then +<username> and <password> will be set as the login username/password for +<channel>. Use caution when passing the username/password in this way, as +it may allow other users on your computer to briefly view your username/ +password via the system's process list. + + + diff --git a/src/lib/pear/PEAR/PEAR/Command/Common.php b/src/lib/pear/PEAR/PEAR/Command/Common.php new file mode 100644 index 0000000..4159540 --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Command/Common.php @@ -0,0 +1,291 @@ + + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: Common.php,v 1.36 2008/01/03 20:26:36 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 0.1 + */ + +/** + * base class + */ +require_once 'PEAR.php'; + +/** + * PEAR commands base class + * + * @category pear + * @package PEAR + * @author Stig Bakken + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 0.1 + */ +class PEAR_Command_Common extends PEAR +{ + // {{{ properties + + /** + * PEAR_Config object used to pass user system and configuration + * on when executing commands + * + * @var PEAR_Config + */ + var $config; + /** + * @var PEAR_Registry + * @access protected + */ + var $_registry; + + /** + * User Interface object, for all interaction with the user. + * @var object + */ + var $ui; + + var $_deps_rel_trans = array( + 'lt' => '<', + 'le' => '<=', + 'eq' => '=', + 'ne' => '!=', + 'gt' => '>', + 'ge' => '>=', + 'has' => '==' + ); + + var $_deps_type_trans = array( + 'pkg' => 'package', + 'ext' => 'extension', + 'php' => 'PHP', + 'prog' => 'external program', + 'ldlib' => 'external library for linking', + 'rtlib' => 'external runtime library', + 'os' => 'operating system', + 'websrv' => 'web server', + 'sapi' => 'SAPI backend' + ); + + // }}} + // {{{ constructor + + /** + * PEAR_Command_Common constructor. + * + * @access public + */ + function PEAR_Command_Common(&$ui, &$config) + { + parent::PEAR(); + $this->config = &$config; + $this->ui = &$ui; + } + + // }}} + + // {{{ getCommands() + + /** + * Return a list of all the commands defined by this class. + * @return array list of commands + * @access public + */ + function getCommands() + { + $ret = array(); + foreach (array_keys($this->commands) as $command) { + $ret[$command] = $this->commands[$command]['summary']; + } + return $ret; + } + + // }}} + // {{{ getShortcuts() + + /** + * Return a list of all the command shortcuts defined by this class. + * @return array shortcut => command + * @access public + */ + function getShortcuts() + { + $ret = array(); + foreach (array_keys($this->commands) as $command) { + if (isset($this->commands[$command]['shortcut'])) { + $ret[$this->commands[$command]['shortcut']] = $command; + } + } + return $ret; + } + + // }}} + // {{{ getOptions() + + function getOptions($command) + { + $shortcuts = $this->getShortcuts(); + if (isset($shortcuts[$command])) { + $command = $shortcuts[$command]; + } + if (isset($this->commands[$command]) && + isset($this->commands[$command]['options'])) { + return $this->commands[$command]['options']; + } else { + return null; + } + } + + // }}} + // {{{ getGetoptArgs() + + function getGetoptArgs($command, &$short_args, &$long_args) + { + $short_args = ""; + $long_args = array(); + if (empty($this->commands[$command]) || empty($this->commands[$command]['options'])) { + return; + } + reset($this->commands[$command]['options']); + while (list($option, $info) = each($this->commands[$command]['options'])) { + $larg = $sarg = ''; + if (isset($info['arg'])) { + if ($info['arg']{0} == '(') { + $larg = '=='; + $sarg = '::'; + $arg = substr($info['arg'], 1, -1); + } else { + $larg = '='; + $sarg = ':'; + $arg = $info['arg']; + } + } + if (isset($info['shortopt'])) { + $short_args .= $info['shortopt'] . $sarg; + } + $long_args[] = $option . $larg; + } + } + + // }}} + // {{{ getHelp() + /** + * Returns the help message for the given command + * + * @param string $command The command + * @return mixed A fail string if the command does not have help or + * a two elements array containing [0]=>help string, + * [1]=> help string for the accepted cmd args + */ + function getHelp($command) + { + $config = &PEAR_Config::singleton(); + if (!isset($this->commands[$command])) { + return "No such command \"$command\""; + } + $help = null; + if (isset($this->commands[$command]['doc'])) { + $help = $this->commands[$command]['doc']; + } + if (empty($help)) { + // XXX (cox) Fallback to summary if there is no doc (show both?) + if (!isset($this->commands[$command]['summary'])) { + return "No help for command \"$command\""; + } + $help = $this->commands[$command]['summary']; + } + if (preg_match_all('/{config\s+([^\}]+)}/e', $help, $matches)) { + foreach($matches[0] as $k => $v) { + $help = preg_replace("/$v/", $config->get($matches[1][$k]), $help); + } + } + return array($help, $this->getHelpArgs($command)); + } + + // }}} + // {{{ getHelpArgs() + /** + * Returns the help for the accepted arguments of a command + * + * @param string $command + * @return string The help string + */ + function getHelpArgs($command) + { + if (isset($this->commands[$command]['options']) && + count($this->commands[$command]['options'])) + { + $help = "Options:\n"; + foreach ($this->commands[$command]['options'] as $k => $v) { + if (isset($v['arg'])) { + if ($v['arg'][0] == '(') { + $arg = substr($v['arg'], 1, -1); + $sapp = " [$arg]"; + $lapp = "[=$arg]"; + } else { + $sapp = " $v[arg]"; + $lapp = "=$v[arg]"; + } + } else { + $sapp = $lapp = ""; + } + if (isset($v['shortopt'])) { + $s = $v['shortopt']; + $help .= " -$s$sapp, --$k$lapp\n"; + } else { + $help .= " --$k$lapp\n"; + } + $p = " "; + $doc = rtrim(str_replace("\n", "\n$p", $v['doc'])); + $help .= " $doc\n"; + } + return $help; + } + return null; + } + + // }}} + // {{{ run() + + function run($command, $options, $params) + { + if (empty($this->commands[$command]['function'])) { + // look for shortcuts + foreach (array_keys($this->commands) as $cmd) { + if (isset($this->commands[$cmd]['shortcut']) && $this->commands[$cmd]['shortcut'] == $command) { + if (empty($this->commands[$cmd]['function'])) { + return $this->raiseError("unknown command `$command'"); + } else { + $func = $this->commands[$cmd]['function']; + } + $command = $cmd; + break; + } + } + } else { + $func = $this->commands[$command]['function']; + } + return $this->$func($command, $options, $params); + } + + // }}} +} + +?> diff --git a/src/lib/pear/PEAR/PEAR/Command/Config.php b/src/lib/pear/PEAR/PEAR/Command/Config.php new file mode 100644 index 0000000..d8179d3 --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Command/Config.php @@ -0,0 +1,422 @@ + + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: Config.php,v 1.56 2008/01/03 20:26:36 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 0.1 + */ + +/** + * base class + */ +require_once 'PEAR/Command/Common.php'; + +/** + * PEAR commands for managing configuration data. + * + * @category pear + * @package PEAR + * @author Stig Bakken + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 0.1 + */ +class PEAR_Command_Config extends PEAR_Command_Common +{ + // {{{ properties + + var $commands = array( + 'config-show' => array( + 'summary' => 'Show All Settings', + 'function' => 'doConfigShow', + 'shortcut' => 'csh', + 'options' => array( + 'channel' => array( + 'shortopt' => 'c', + 'doc' => 'show configuration variables for another channel', + 'arg' => 'CHAN', + ), +), + 'doc' => '[layer] +Displays all configuration values. An optional argument +may be used to tell which configuration layer to display. Valid +configuration layers are "user", "system" and "default". To display +configurations for different channels, set the default_channel +configuration variable and run config-show again. +', + ), + 'config-get' => array( + 'summary' => 'Show One Setting', + 'function' => 'doConfigGet', + 'shortcut' => 'cg', + 'options' => array( + 'channel' => array( + 'shortopt' => 'c', + 'doc' => 'show configuration variables for another channel', + 'arg' => 'CHAN', + ), +), + 'doc' => ' [layer] +Displays the value of one configuration parameter. The +first argument is the name of the parameter, an optional second argument +may be used to tell which configuration layer to look in. Valid configuration +layers are "user", "system" and "default". If no layer is specified, a value +will be picked from the first layer that defines the parameter, in the order +just specified. The configuration value will be retrieved for the channel +specified by the default_channel configuration variable. +', + ), + 'config-set' => array( + 'summary' => 'Change Setting', + 'function' => 'doConfigSet', + 'shortcut' => 'cs', + 'options' => array( + 'channel' => array( + 'shortopt' => 'c', + 'doc' => 'show configuration variables for another channel', + 'arg' => 'CHAN', + ), +), + 'doc' => ' [layer] +Sets the value of one configuration parameter. The first argument is +the name of the parameter, the second argument is the new value. Some +parameters are subject to validation, and the command will fail with +an error message if the new value does not make sense. An optional +third argument may be used to specify in which layer to set the +configuration parameter. The default layer is "user". The +configuration value will be set for the current channel, which +is controlled by the default_channel configuration variable. +', + ), + 'config-help' => array( + 'summary' => 'Show Information About Setting', + 'function' => 'doConfigHelp', + 'shortcut' => 'ch', + 'options' => array(), + 'doc' => '[parameter] +Displays help for a configuration parameter. Without arguments it +displays help for all configuration parameters. +', + ), + 'config-create' => array( + 'summary' => 'Create a Default configuration file', + 'function' => 'doConfigCreate', + 'shortcut' => 'coc', + 'options' => array( + 'windows' => array( + 'shortopt' => 'w', + 'doc' => 'create a config file for a windows install', + ), + ), + 'doc' => ' +Create a default configuration file with all directory configuration +variables set to subdirectories of , and save it as . +This is useful especially for creating a configuration file for a remote +PEAR installation (using the --remoteconfig option of install, upgrade, +and uninstall). +', + ), + ); + + // }}} + // {{{ constructor + + /** + * PEAR_Command_Config constructor. + * + * @access public + */ + function PEAR_Command_Config(&$ui, &$config) + { + parent::PEAR_Command_Common($ui, $config); + } + + // }}} + + // {{{ doConfigShow() + + function doConfigShow($command, $options, $params) + { + if (is_array($params)) { + $layer = isset($params[0]) ? $params[0] : NULL; + } else { + $layer = NULL; + } + + // $params[0] -> the layer + if ($error = $this->_checkLayer($layer)) { + return $this->raiseError("config-show:$error"); + } + $keys = $this->config->getKeys(); + sort($keys); + $channel = isset($options['channel']) ? $options['channel'] : + $this->config->get('default_channel'); + $reg = &$this->config->getRegistry(); + if (!$reg->channelExists($channel)) { + return $this->raiseError('Channel "' . $channel . '" does not exist'); + } + $data = array('caption' => 'Configuration (channel ' . $channel . '):'); + foreach ($keys as $key) { + $type = $this->config->getType($key); + $value = $this->config->get($key, $layer, $channel); + if ($type == 'password' && $value) { + $value = '********'; + } + if ($value === false) { + $value = 'false'; + } elseif ($value === true) { + $value = 'true'; + } + $data['data'][$this->config->getGroup($key)][] = array($this->config->getPrompt($key) , $key, $value); + } + foreach ($this->config->getLayers() as $layer) { + $data['data']['Config Files'][] = array(ucfirst($layer) . ' Configuration File', 'Filename' , $this->config->getConfFile($layer)); + } + + $this->ui->outputData($data, $command); + return true; + } + + // }}} + // {{{ doConfigGet() + + function doConfigGet($command, $options, $params) + { + if (!is_array($params)) { + $args_cnt = 0; + } else { + $args_cnt = count($params); + } + + switch ($args_cnt) { + case 1: + $config_key = $params[0]; + $layer = NULL; + break; + case 2: + $config_key = $params[0]; + $layer = $params[1]; + if ($error = $this->_checkLayer($layer)) { + return $this->raiseError("config-get:$error"); + } + break; + case 0: + default: + return $this->raiseError("config-get expects 1 or 2 parameters"); + } + + $channel = isset($options['channel']) ? $options['channel'] : $this->config->get('default_channel'); + $reg = &$this->config->getRegistry(); + + if (!$reg->channelExists($channel)) { + return $this->raiseError('Channel "' . $channel . '" does not exist'); + } + + $this->ui->outputData($this->config->get($config_key, $layer, $channel), $command); + + return true; + } + + // }}} + // {{{ doConfigSet() + + function doConfigSet($command, $options, $params) + { + // $param[0] -> a parameter to set + // $param[1] -> the value for the parameter + // $param[2] -> the layer + $failmsg = ''; + if (sizeof($params) < 2 || sizeof($params) > 3) { + $failmsg .= "config-set expects 2 or 3 parameters"; + return PEAR::raiseError($failmsg); + } + if (isset($params[2]) && ($error = $this->_checkLayer($params[2]))) { + $failmsg .= $error; + return PEAR::raiseError("config-set:$failmsg"); + } + $channel = isset($options['channel']) ? $options['channel'] : + $this->config->get('default_channel'); + $reg = &$this->config->getRegistry(); + if (!$reg->channelExists($channel)) { + return $this->raiseError('Channel "' . $channel . '" does not exist'); + } + if ($params[0] == 'default_channel') { + if (!$reg->channelExists($params[1])) { + return $this->raiseError('Channel "' . $params[1] . '" does not exist'); + } + } + if (count($params) == 2) { + array_push($params, 'user'); + $layer = 'user'; + } else { + $layer = $params[2]; + } + array_push($params, $channel); + if (!call_user_func_array(array(&$this->config, 'set'), $params)) + { + array_pop($params); + $failmsg = "config-set (" . implode(", ", $params) . ") failed, channel $channel"; + } else { + $this->config->store($layer); + } + if ($failmsg) { + return $this->raiseError($failmsg); + } + $this->ui->outputData('config-set succeeded', $command); + return true; + } + + // }}} + // {{{ doConfigHelp() + + function doConfigHelp($command, $options, $params) + { + if (empty($params)) { + $params = $this->config->getKeys(); + } + $data['caption'] = "Config help" . ((count($params) == 1) ? " for $params[0]" : ''); + $data['headline'] = array('Name', 'Type', 'Description'); + $data['border'] = true; + foreach ($params as $name) { + $type = $this->config->getType($name); + $docs = $this->config->getDocs($name); + if ($type == 'set') { + $docs = rtrim($docs) . "\nValid set: " . + implode(' ', $this->config->getSetValues($name)); + } + $data['data'][] = array($name, $type, $docs); + } + $this->ui->outputData($data, $command); + } + + // }}} + // {{{ doConfigCreate() + + function doConfigCreate($command, $options, $params) + { + if (count($params) != 2) { + return PEAR::raiseError('config-create: must have 2 parameters, root path and ' . + 'filename to save as'); + } + $root = $params[0]; + // Clean up the DIRECTORY_SEPARATOR mess + $ds2 = DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR; + $root = preg_replace(array('!\\\\+!', '!/+!', "!$ds2+!"), + array('/', '/', '/'), + $root); + if ($root{0} != '/') { + if (isset($options['windows'])) { + if (!preg_match('/^[A-Za-z]:/', $root)) { + return PEAR::raiseError('Root directory must be an absolute path beginning ' . + 'with "\\" or "C:\\", was: "' . $root . '"'); + } + } else { + return PEAR::raiseError('Root directory must be an absolute path beginning ' . + 'with "/", was: "' . $root . '"'); + } + } + $windows = isset($options['windows']); + if ($windows) { + $root = str_replace('/', '\\', $root); + } + if (!file_exists($params[1])) { + if (!@touch($params[1])) { + return PEAR::raiseError('Could not create "' . $params[1] . '"'); + } + } + $params[1] = realpath($params[1]); + $config = &new PEAR_Config($params[1], '#no#system#config#', false, false); + if ($root{strlen($root) - 1} == '/') { + $root = substr($root, 0, strlen($root) - 1); + } + $config->noRegistry(); + $config->set('php_dir', $windows ? "$root\\pear\\php" : "$root/pear/php", 'user'); + $config->set('data_dir', $windows ? "$root\\pear\\data" : "$root/pear/data"); + $config->set('www_dir', $windows ? "$root\\pear\\www" : "$root/pear/www"); + $config->set('cfg_dir', $windows ? "$root\\pear\\cfg" : "$root/pear/cfg"); + $config->set('ext_dir', $windows ? "$root\\pear\\ext" : "$root/pear/ext"); + $config->set('doc_dir', $windows ? "$root\\pear\\docs" : "$root/pear/docs"); + $config->set('test_dir', $windows ? "$root\\pear\\tests" : "$root/pear/tests"); + $config->set('cache_dir', $windows ? "$root\\pear\\cache" : "$root/pear/cache"); + $config->set('download_dir', $windows ? "$root\\pear\\download" : "$root/pear/download"); + $config->set('temp_dir', $windows ? "$root\\pear\\temp" : "$root/pear/temp"); + $config->set('bin_dir', $windows ? "$root\\pear" : "$root/pear"); + $config->writeConfigFile(); + $this->_showConfig($config); + $this->ui->outputData('Successfully created default configuration file "' . $params[1] . '"', + $command); + } + + // }}} + + function _showConfig(&$config) + { + $params = array('user'); + $keys = $config->getKeys(); + sort($keys); + $channel = 'pear.php.net'; + $data = array('caption' => 'Configuration (channel ' . $channel . '):'); + foreach ($keys as $key) { + $type = $config->getType($key); + $value = $config->get($key, 'user', $channel); + if ($type == 'password' && $value) { + $value = '********'; + } + if ($value === false) { + $value = 'false'; + } elseif ($value === true) { + $value = 'true'; + } + $data['data'][$config->getGroup($key)][] = + array($config->getPrompt($key) , $key, $value); + } + foreach ($config->getLayers() as $layer) { + $data['data']['Config Files'][] = + array(ucfirst($layer) . ' Configuration File', 'Filename' , + $config->getConfFile($layer)); + } + + $this->ui->outputData($data, 'config-show'); + return true; + } + // {{{ _checkLayer() + + /** + * Checks if a layer is defined or not + * + * @param string $layer The layer to search for + * @return mixed False on no error or the error message + */ + function _checkLayer($layer = null) + { + if (!empty($layer) && $layer != 'default') { + $layers = $this->config->getLayers(); + if (!in_array($layer, $layers)) { + return " only the layers: \"" . implode('" or "', $layers) . "\" are supported"; + } + } + return false; + } + + // }}} +} + +?> diff --git a/src/lib/pear/PEAR/PEAR/Command/Config.xml b/src/lib/pear/PEAR/PEAR/Command/Config.xml new file mode 100644 index 0000000..f64a925 --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Command/Config.xml @@ -0,0 +1,92 @@ + + + Show All Settings + doConfigShow + csh + + + c + show configuration variables for another channel + CHAN + + + [layer] +Displays all configuration values. An optional argument +may be used to tell which configuration layer to display. Valid +configuration layers are "user", "system" and "default". To display +configurations for different channels, set the default_channel +configuration variable and run config-show again. + + + + Show One Setting + doConfigGet + cg + + + c + show configuration variables for another channel + CHAN + + + <parameter> [layer] +Displays the value of one configuration parameter. The +first argument is the name of the parameter, an optional second argument +may be used to tell which configuration layer to look in. Valid configuration +layers are "user", "system" and "default". If no layer is specified, a value +will be picked from the first layer that defines the parameter, in the order +just specified. The configuration value will be retrieved for the channel +specified by the default_channel configuration variable. + + + + Change Setting + doConfigSet + cs + + + c + show configuration variables for another channel + CHAN + + + <parameter> <value> [layer] +Sets the value of one configuration parameter. The first argument is +the name of the parameter, the second argument is the new value. Some +parameters are subject to validation, and the command will fail with +an error message if the new value does not make sense. An optional +third argument may be used to specify in which layer to set the +configuration parameter. The default layer is "user". The +configuration value will be set for the current channel, which +is controlled by the default_channel configuration variable. + + + + Show Information About Setting + doConfigHelp + ch + + [parameter] +Displays help for a configuration parameter. Without arguments it +displays help for all configuration parameters. + + + + Create a Default configuration file + doConfigCreate + coc + + + w + create a config file for a windows install + + + <root path> <filename> +Create a default configuration file with all directory configuration +variables set to subdirectories of <root path>, and save it as <filename>. +This is useful especially for creating a configuration file for a remote +PEAR installation (using the --remoteconfig option of install, upgrade, +and uninstall). + + + \ No newline at end of file diff --git a/src/lib/pear/PEAR/PEAR/Command/Install.php b/src/lib/pear/PEAR/PEAR/Command/Install.php new file mode 100644 index 0000000..fba4382 --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Command/Install.php @@ -0,0 +1,1188 @@ + + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: Install.php,v 1.141 2008/05/13 18:32:29 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 0.1 + */ + +/** + * base class + */ +require_once 'PEAR/Command/Common.php'; + +/** + * PEAR commands for installation or deinstallation/upgrading of + * packages. + * + * @category pear + * @package PEAR + * @author Stig Bakken + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 0.1 + */ +class PEAR_Command_Install extends PEAR_Command_Common +{ + // {{{ properties + + var $commands = array( + 'install' => array( + 'summary' => 'Install Package', + 'function' => 'doInstall', + 'shortcut' => 'i', + 'options' => array( + 'force' => array( + 'shortopt' => 'f', + 'doc' => 'will overwrite newer installed packages', + ), + 'loose' => array( + 'shortopt' => 'l', + 'doc' => 'do not check for recommended dependency version', + ), + 'nodeps' => array( + 'shortopt' => 'n', + 'doc' => 'ignore dependencies, install anyway', + ), + 'register-only' => array( + 'shortopt' => 'r', + 'doc' => 'do not install files, only register the package as installed', + ), + 'soft' => array( + 'shortopt' => 's', + 'doc' => 'soft install, fail silently, or upgrade if already installed', + ), + 'nobuild' => array( + 'shortopt' => 'B', + 'doc' => 'don\'t build C extensions', + ), + 'nocompress' => array( + 'shortopt' => 'Z', + 'doc' => 'request uncompressed files when downloading', + ), + 'installroot' => array( + 'shortopt' => 'R', + 'arg' => 'DIR', + 'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT), use packagingroot for RPM', + ), + 'packagingroot' => array( + 'shortopt' => 'P', + 'arg' => 'DIR', + 'doc' => 'root directory used when packaging files, like RPM packaging', + ), + 'ignore-errors' => array( + 'doc' => 'force install even if there were errors', + ), + 'alldeps' => array( + 'shortopt' => 'a', + 'doc' => 'install all required and optional dependencies', + ), + 'onlyreqdeps' => array( + 'shortopt' => 'o', + 'doc' => 'install all required dependencies', + ), + 'offline' => array( + 'shortopt' => 'O', + 'doc' => 'do not attempt to download any urls or contact channels', + ), + 'pretend' => array( + 'shortopt' => 'p', + 'doc' => 'Only list the packages that would be downloaded', + ), + ), + 'doc' => '[channel/] ... +Installs one or more PEAR packages. You can specify a package to +install in four ways: + +"Package-1.0.tgz" : installs from a local file + +"http://example.com/Package-1.0.tgz" : installs from +anywhere on the net. + +"package.xml" : installs the package described in +package.xml. Useful for testing, or for wrapping a PEAR package in +another package manager such as RPM. + +"Package[-version/state][.tar]" : queries your default channel\'s server +({config master_server}) and downloads the newest package with +the preferred quality/state ({config preferred_state}). + +To retrieve Package version 1.1, use "Package-1.1," to retrieve +Package state beta, use "Package-beta." To retrieve an uncompressed +file, append .tar (make sure there is no file by the same name first) + +To download a package from another channel, prefix with the channel name like +"channel/Package" + +More than one package may be specified at once. It is ok to mix these +four ways of specifying packages. +'), + 'upgrade' => array( + 'summary' => 'Upgrade Package', + 'function' => 'doInstall', + 'shortcut' => 'up', + 'options' => array( + 'force' => array( + 'shortopt' => 'f', + 'doc' => 'overwrite newer installed packages', + ), + 'loose' => array( + 'shortopt' => 'l', + 'doc' => 'do not check for recommended dependency version', + ), + 'nodeps' => array( + 'shortopt' => 'n', + 'doc' => 'ignore dependencies, upgrade anyway', + ), + 'register-only' => array( + 'shortopt' => 'r', + 'doc' => 'do not install files, only register the package as upgraded', + ), + 'nobuild' => array( + 'shortopt' => 'B', + 'doc' => 'don\'t build C extensions', + ), + 'nocompress' => array( + 'shortopt' => 'Z', + 'doc' => 'request uncompressed files when downloading', + ), + 'installroot' => array( + 'shortopt' => 'R', + 'arg' => 'DIR', + 'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT)', + ), + 'ignore-errors' => array( + 'doc' => 'force install even if there were errors', + ), + 'alldeps' => array( + 'shortopt' => 'a', + 'doc' => 'install all required and optional dependencies', + ), + 'onlyreqdeps' => array( + 'shortopt' => 'o', + 'doc' => 'install all required dependencies', + ), + 'offline' => array( + 'shortopt' => 'O', + 'doc' => 'do not attempt to download any urls or contact channels', + ), + 'pretend' => array( + 'shortopt' => 'p', + 'doc' => 'Only list the packages that would be downloaded', + ), + ), + 'doc' => ' ... +Upgrades one or more PEAR packages. See documentation for the +"install" command for ways to specify a package. + +When upgrading, your package will be updated if the provided new +package has a higher version number (use the -f option if you need to +upgrade anyway). + +More than one package may be specified at once. +'), + 'upgrade-all' => array( + 'summary' => 'Upgrade All Packages', + 'function' => 'doUpgradeAll', + 'shortcut' => 'ua', + 'options' => array( + 'nodeps' => array( + 'shortopt' => 'n', + 'doc' => 'ignore dependencies, upgrade anyway', + ), + 'register-only' => array( + 'shortopt' => 'r', + 'doc' => 'do not install files, only register the package as upgraded', + ), + 'nobuild' => array( + 'shortopt' => 'B', + 'doc' => 'don\'t build C extensions', + ), + 'nocompress' => array( + 'shortopt' => 'Z', + 'doc' => 'request uncompressed files when downloading', + ), + 'installroot' => array( + 'shortopt' => 'R', + 'arg' => 'DIR', + 'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT), use packagingroot for RPM', + ), + 'ignore-errors' => array( + 'doc' => 'force install even if there were errors', + ), + 'loose' => array( + 'doc' => 'do not check for recommended dependency version', + ), + ), + 'doc' => ' +Upgrades all packages that have a newer release available. Upgrades are +done only if there is a release available of the state specified in +"preferred_state" (currently {config preferred_state}), or a state considered +more stable. +'), + 'uninstall' => array( + 'summary' => 'Un-install Package', + 'function' => 'doUninstall', + 'shortcut' => 'un', + 'options' => array( + 'nodeps' => array( + 'shortopt' => 'n', + 'doc' => 'ignore dependencies, uninstall anyway', + ), + 'register-only' => array( + 'shortopt' => 'r', + 'doc' => 'do not remove files, only register the packages as not installed', + ), + 'installroot' => array( + 'shortopt' => 'R', + 'arg' => 'DIR', + 'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT)', + ), + 'ignore-errors' => array( + 'doc' => 'force install even if there were errors', + ), + 'offline' => array( + 'shortopt' => 'O', + 'doc' => 'do not attempt to uninstall remotely', + ), + ), + 'doc' => '[channel/] ... +Uninstalls one or more PEAR packages. More than one package may be +specified at once. Prefix with channel name to uninstall from a +channel not in your default channel ({config default_channel}) +'), + 'bundle' => array( + 'summary' => 'Unpacks a Pecl Package', + 'function' => 'doBundle', + 'shortcut' => 'bun', + 'options' => array( + 'destination' => array( + 'shortopt' => 'd', + 'arg' => 'DIR', + 'doc' => 'Optional destination directory for unpacking (defaults to current path or "ext" if exists)', + ), + 'force' => array( + 'shortopt' => 'f', + 'doc' => 'Force the unpacking even if there were errors in the package', + ), + ), + 'doc' => ' +Unpacks a Pecl Package into the selected location. It will download the +package if needed. +'), + 'run-scripts' => array( + 'summary' => 'Run Post-Install Scripts bundled with a package', + 'function' => 'doRunScripts', + 'shortcut' => 'rs', + 'options' => array( + ), + 'doc' => ' +Run post-installation scripts in package , if any exist. +'), + ); + + // }}} + // {{{ constructor + + /** + * PEAR_Command_Install constructor. + * + * @access public + */ + function PEAR_Command_Install(&$ui, &$config) + { + parent::PEAR_Command_Common($ui, $config); + } + + // }}} + + /** + * For unit testing purposes + */ + function &getDownloader(&$ui, $options, &$config) + { + if (!class_exists('PEAR_Downloader')) { + require_once 'PEAR/Downloader.php'; + } + $a = &new PEAR_Downloader($ui, $options, $config); + return $a; + } + + /** + * For unit testing purposes + */ + function &getInstaller(&$ui) + { + if (!class_exists('PEAR_Installer')) { + require_once 'PEAR/Installer.php'; + } + $a = &new PEAR_Installer($ui); + return $a; + } + + function enableExtension($binaries, $type) + { + if (!($phpini = $this->config->get('php_ini', null, 'pear.php.net'))) { + return PEAR::raiseError('configuration option "php_ini" is not set to php.ini location'); + } + $ini = $this->_parseIni($phpini); + if (PEAR::isError($ini)) { + return $ini; + } + $line = 0; + if ($type == 'extsrc' || $type == 'extbin') { + $search = 'extensions'; + $enable = 'extension'; + } else { + $search = 'zend_extensions'; + ob_start(); + phpinfo(INFO_GENERAL); + $info = ob_get_contents(); + ob_end_clean(); + $debug = function_exists('leak') ? '_debug' : ''; + $ts = preg_match('Thread Safety.+enabled', $info) ? '_ts' : ''; + $enable = 'zend_extension' . $debug . $ts; + } + foreach ($ini[$search] as $line => $extension) { + if (in_array($extension, $binaries, true) || in_array( + $ini['extension_dir'] . DIRECTORY_SEPARATOR . $extension, $binaries, true)) { + // already enabled - assume if one is, all are + return true; + } + } + if ($line) { + $newini = array_slice($ini['all'], 0, $line); + } else { + $newini = array(); + } + foreach ($binaries as $binary) { + if ($ini['extension_dir']) { + $binary = basename($binary); + } + $newini[] = $enable . '="' . $binary . '"' . (OS_UNIX ? "\n" : "\r\n"); + } + $newini = array_merge($newini, array_slice($ini['all'], $line)); + $fp = @fopen($phpini, 'wb'); + if (!$fp) { + return PEAR::raiseError('cannot open php.ini "' . $phpini . '" for writing'); + } + foreach ($newini as $line) { + fwrite($fp, $line); + } + fclose($fp); + return true; + } + + function disableExtension($binaries, $type) + { + if (!($phpini = $this->config->get('php_ini', null, 'pear.php.net'))) { + return PEAR::raiseError('configuration option "php_ini" is not set to php.ini location'); + } + $ini = $this->_parseIni($phpini); + if (PEAR::isError($ini)) { + return $ini; + } + $line = 0; + if ($type == 'extsrc' || $type == 'extbin') { + $search = 'extensions'; + $enable = 'extension'; + } else { + $search = 'zend_extensions'; + ob_start(); + phpinfo(INFO_GENERAL); + $info = ob_get_contents(); + ob_end_clean(); + $debug = function_exists('leak') ? '_debug' : ''; + $ts = preg_match('Thread Safety.+enabled', $info) ? '_ts' : ''; + $enable = 'zend_extension' . $debug . $ts; + } + $found = false; + foreach ($ini[$search] as $line => $extension) { + if (in_array($extension, $binaries, true) || in_array( + $ini['extension_dir'] . DIRECTORY_SEPARATOR . $extension, $binaries, true)) { + $found = true; + break; + } + } + if (!$found) { + // not enabled + return true; + } + $fp = @fopen($phpini, 'wb'); + if (!$fp) { + return PEAR::raiseError('cannot open php.ini "' . $phpini . '" for writing'); + } + if ($line) { + $newini = array_slice($ini['all'], 0, $line); + // delete the enable line + $newini = array_merge($newini, array_slice($ini['all'], $line + 1)); + } else { + $newini = array_slice($ini['all'], 1); + } + foreach ($newini as $line) { + fwrite($fp, $line); + } + fclose($fp); + return true; + } + + function _parseIni($filename) + { + if (file_exists($filename)) { + if (filesize($filename) > 300000) { + return PEAR::raiseError('php.ini "' . $filename . '" is too large, aborting'); + } + ob_start(); + phpinfo(INFO_GENERAL); + $info = ob_get_contents(); + ob_end_clean(); + $debug = function_exists('leak') ? '_debug' : ''; + $ts = preg_match('/Thread Safety.+enabled/', $info) ? '_ts' : ''; + $zend_extension_line = 'zend_extension' . $debug . $ts; + $all = @file($filename); + if (!$all) { + return PEAR::raiseError('php.ini "' . $filename .'" could not be read'); + } + $zend_extensions = $extensions = array(); + // assume this is right, but pull from the php.ini if it is found + $extension_dir = ini_get('extension_dir'); + foreach ($all as $linenum => $line) { + $line = trim($line); + if (!$line) { + continue; + } + if ($line[0] == ';') { + continue; + } + if (strtolower(substr($line, 0, 13)) == 'extension_dir') { + $line = trim(substr($line, 13)); + if ($line[0] == '=') { + $x = trim(substr($line, 1)); + $x = explode(';', $x); + $extension_dir = str_replace('"', '', array_shift($x)); + continue; + } + } + if (strtolower(substr($line, 0, 9)) == 'extension') { + $line = trim(substr($line, 9)); + if ($line[0] == '=') { + $x = trim(substr($line, 1)); + $x = explode(';', $x); + $extensions[$linenum] = str_replace('"', '', array_shift($x)); + continue; + } + } + if (strtolower(substr($line, 0, strlen($zend_extension_line))) == + $zend_extension_line) { + $line = trim(substr($line, strlen($zend_extension_line))); + if ($line[0] == '=') { + $x = trim(substr($line, 1)); + $x = explode(';', $x); + $zend_extensions[$linenum] = str_replace('"', '', array_shift($x)); + continue; + } + } + } + return array( + 'extensions' => $extensions, + 'zend_extensions' => $zend_extensions, + 'extension_dir' => $extension_dir, + 'all' => $all, + ); + } else { + return PEAR::raiseError('php.ini "' . $filename . '" does not exist'); + } + } + + // {{{ doInstall() + + function doInstall($command, $options, $params) + { + if (!class_exists('PEAR_PackageFile')) { + require_once 'PEAR/PackageFile.php'; + } + if (empty($this->installer)) { + $this->installer = &$this->getInstaller($this->ui); + } + if ($command == 'upgrade' || $command == 'upgrade-all') { + $options['upgrade'] = true; + } else { + $packages = $params; + } + if (isset($options['installroot']) && isset($options['packagingroot'])) { + return $this->raiseError('ERROR: cannot use both --installroot and --packagingroot'); + } + $reg = &$this->config->getRegistry(); + $instreg = &$reg; // instreg used to check if package is installed + if (isset($options['packagingroot']) && !isset($options['upgrade'])) { + $packrootphp_dir = $this->installer->_prependPath( + $this->config->get('php_dir', null, 'pear.php.net'), + $options['packagingroot']); + $instreg = new PEAR_Registry($packrootphp_dir); // other instreg! + + if ($this->config->get('verbose') > 2) { + $this->ui->outputData('using package root: ' . $options['packagingroot']); + } + } + $abstractpackages = array(); + $otherpackages = array(); + // parse params + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + foreach($params as $param) { + if (strpos($param, 'http://') === 0) { + $otherpackages[] = $param; + continue; + } + if (strpos($param, 'channel://') === false && @file_exists($param)) { + if (isset($options['force'])) { + $otherpackages[] = $param; + continue; + } + $pkg = new PEAR_PackageFile($this->config); + $pf = $pkg->fromAnyFile($param, PEAR_VALIDATE_DOWNLOADING); + if (PEAR::isError($pf)) { + $otherpackages[] = $param; + continue; + } + if ($reg->packageExists($pf->getPackage(), $pf->getChannel()) && + version_compare($pf->getVersion(), + $reg->packageInfo($pf->getPackage(), 'version', $pf->getChannel()), + '<=')) { + if ($this->config->get('verbose')) { + $this->ui->outputData('Ignoring installed package ' . + $reg->parsedPackageNameToString( + array('package' => $pf->getPackage(), + 'channel' => $pf->getChannel()), true)); + } + continue; + } + $otherpackages[] = $param; + continue; + } + $e = $reg->parsePackageName($param, $this->config->get('default_channel')); + if (PEAR::isError($e)) { + $otherpackages[] = $param; + } else { + $abstractpackages[] = $e; + } + } + PEAR::staticPopErrorHandling(); + + // if there are any local package .tgz or remote static url, we can't + // filter. The filter only works for abstract packages + if (count($abstractpackages) && !isset($options['force'])) { + // when not being forced, only do necessary upgrades/installs + if (isset($options['upgrade'])) { + $abstractpackages = $this->_filterUptodatePackages($abstractpackages, + $command); + } else { + foreach ($abstractpackages as $i => $package) { + if (isset($package['group'])) { + // do not filter out install groups + continue; + } + if ($instreg->packageExists($package['package'], $package['channel'])) { + if ($this->config->get('verbose')) { + $this->ui->outputData('Ignoring installed package ' . + $reg->parsedPackageNameToString($package, true)); + } + unset($abstractpackages[$i]); + } + } + } + $abstractpackages = + array_map(array($reg, 'parsedPackageNameToString'), $abstractpackages); + } elseif (count($abstractpackages)) { + $abstractpackages = + array_map(array($reg, 'parsedPackageNameToString'), $abstractpackages); + } + + + $packages = array_merge($abstractpackages, $otherpackages); + if (!count($packages)) { + $this->ui->outputData('Nothing to ' . $command); + return true; + } + + $this->downloader = &$this->getDownloader($this->ui, $options, $this->config); + $errors = array(); + $binaries = array(); + $downloaded = array(); + $downloaded = &$this->downloader->download($packages); + if (PEAR::isError($downloaded)) { + return $this->raiseError($downloaded); + } + $errors = $this->downloader->getErrorMsgs(); + if (count($errors)) { + $err = array(); + $err['data'] = array(); + foreach ($errors as $error) { + $err['data'][] = array($error); + } + $err['headline'] = 'Install Errors'; + $this->ui->outputData($err); + if (!count($downloaded)) { + return $this->raiseError("$command failed"); + } + } + $data = array( + 'headline' => 'Packages that would be Installed' + ); + if (isset($options['pretend'])) { + foreach ($downloaded as $package) { + $data['data'][] = array($reg->parsedPackageNameToString($package->getParsedPackage())); + } + $this->ui->outputData($data, 'pretend'); + return true; + } + $this->installer->setOptions($options); + $this->installer->sortPackagesForInstall($downloaded); + if (PEAR::isError($err = $this->installer->setDownloadedPackages($downloaded))) { + $this->raiseError($err->getMessage()); + return true; + } + $extrainfo = array(); + $binaries = array(); + foreach ($downloaded as $param) { + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + $info = $this->installer->install($param, $options); + PEAR::staticPopErrorHandling(); + if (PEAR::isError($info)) { + $oldinfo = $info; + $pkg = &$param->getPackageFile(); + if ($info->getCode() != PEAR_INSTALLER_NOBINARY) { + if (!($info = $pkg->installBinary($this->installer))) { + $this->ui->outputData('ERROR: ' .$oldinfo->getMessage()); + continue; + } + // we just installed a different package than requested, + // let's change the param and info so that the rest of this works + $param = $info[0]; + $info = $info[1]; + } + } + if (is_array($info)) { + if ($param->getPackageType() == 'extsrc' || + $param->getPackageType() == 'extbin' || + $param->getPackageType() == 'zendextsrc' || + $param->getPackageType() == 'zendextbin') { + $pkg = &$param->getPackageFile(); + if ($instbin = $pkg->getInstalledBinary()) { + $instpkg = &$instreg->getPackage($instbin, $pkg->getChannel()); + } else { + $instpkg = &$instreg->getPackage($pkg->getPackage(), $pkg->getChannel()); + } + + foreach ($instpkg->getFilelist() as $name => $atts) { + $pinfo = pathinfo($atts['installed_as']); + if (!isset($pinfo['extension']) || + in_array($pinfo['extension'], array('c', 'h'))) { + continue; // make sure we don't match php_blah.h + } + if ((strpos($pinfo['basename'], 'php_') === 0 && + $pinfo['extension'] == 'dll') || + // most unices + $pinfo['extension'] == 'so' || + // hp-ux + $pinfo['extension'] == 'sl') { + $binaries[] = array($atts['installed_as'], $pinfo); + break; + } + } + if (count($binaries)) { + foreach ($binaries as $pinfo) { + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + $ret = $this->enableExtension(array($pinfo[0]), $param->getPackageType()); + PEAR::staticPopErrorHandling(); + if (PEAR::isError($ret)) { + $extrainfo[] = $ret->getMessage(); + if ($param->getPackageType() == 'extsrc' || + $param->getPackageType() == 'extbin') { + $exttype = 'extension'; + } else { + ob_start(); + phpinfo(INFO_GENERAL); + $info = ob_get_contents(); + ob_end_clean(); + $debug = function_exists('leak') ? '_debug' : ''; + $ts = preg_match('Thread Safety.+enabled', $info) ? '_ts' : ''; + $exttype = 'zend_extension' . $debug . $ts; + } + $extrainfo[] = 'You should add "' . $exttype . '=' . + $pinfo[1]['basename'] . '" to php.ini'; + } else { + $extrainfo[] = 'Extension ' . $instpkg->getProvidesExtension() . + ' enabled in php.ini'; + } + } + } + } + if ($this->config->get('verbose') > 0) { + $channel = $param->getChannel(); + $label = $reg->parsedPackageNameToString( + array( + 'channel' => $channel, + 'package' => $param->getPackage(), + 'version' => $param->getVersion(), + )); + $out = array('data' => "$command ok: $label"); + if (isset($info['release_warnings'])) { + $out['release_warnings'] = $info['release_warnings']; + } + $this->ui->outputData($out, $command); + if (!isset($options['register-only']) && !isset($options['offline'])) { + if ($this->config->isDefinedLayer('ftp')) { + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + $info = $this->installer->ftpInstall($param); + PEAR::staticPopErrorHandling(); + if (PEAR::isError($info)) { + $this->ui->outputData($info->getMessage()); + $this->ui->outputData("remote install failed: $label"); + } else { + $this->ui->outputData("remote install ok: $label"); + } + } + } + } + $deps = $param->getDeps(); + if ($deps) { + if (isset($deps['group'])) { + $groups = $deps['group']; + if (!isset($groups[0])) { + $groups = array($groups); + } + foreach ($groups as $group) { + if ($group['attribs']['name'] == 'default') { + // default group is always installed, unless the user + // explicitly chooses to install another group + continue; + } + $extrainfo[] = $param->getPackage() . ': Optional feature ' . + $group['attribs']['name'] . ' available (' . + $group['attribs']['hint'] . ')'; + } + $extrainfo[] = $param->getPackage() . + ': To install optional features use "pear install ' . + $reg->parsedPackageNameToString( + array('package' => $param->getPackage(), + 'channel' => $param->getChannel()), true) . + '#featurename"'; + } + } + $pkg = &$instreg->getPackage($param->getPackage(), $param->getChannel()); + // $pkg may be NULL if install is a 'fake' install via --packagingroot + if (is_object($pkg)) { + $pkg->setConfig($this->config); + if ($list = $pkg->listPostinstallScripts()) { + $pn = $reg->parsedPackageNameToString(array('channel' => + $param->getChannel(), 'package' => $param->getPackage()), true); + $extrainfo[] = $pn . ' has post-install scripts:'; + foreach ($list as $file) { + $extrainfo[] = $file; + } + $extrainfo[] = $param->getPackage() . + ': Use "pear run-scripts ' . $pn . '" to finish setup.'; + $extrainfo[] = 'DO NOT RUN SCRIPTS FROM UNTRUSTED SOURCES'; + } + } + } else { + return $this->raiseError("$command failed"); + } + } + if (count($extrainfo)) { + foreach ($extrainfo as $info) { + $this->ui->outputData($info); + } + } + return true; + } + + // }}} + // {{{ doUpgradeAll() + + function doUpgradeAll($command, $options, $params) + { + $reg = &$this->config->getRegistry(); + $toUpgrade = array(); + foreach ($reg->listChannels() as $channel) { + if ($channel == '__uri') { + continue; + } + + // parse name with channel + foreach ($reg->listPackages($channel) as $name) { + $toUpgrade[] = $reg->parsedPackageNameToString(array( + 'channel' => $channel, + 'package' => $name + )); + } + } + + $err = $this->doInstall('upgrade-all', $options, $toUpgrade); + if (PEAR::isError($err)) { + $this->ui->outputData($err->getMessage(), $command); + } + } + + // }}} + // {{{ doUninstall() + + function doUninstall($command, $options, $params) + { + if (empty($this->installer)) { + $this->installer = &$this->getInstaller($this->ui); + } + if (isset($options['remoteconfig'])) { + $e = $this->config->readFTPConfigFile($options['remoteconfig']); + if (!PEAR::isError($e)) { + $this->installer->setConfig($this->config); + } + } + if (sizeof($params) < 1) { + return $this->raiseError("Please supply the package(s) you want to uninstall"); + } + $reg = &$this->config->getRegistry(); + $newparams = array(); + $binaries = array(); + $badparams = array(); + foreach ($params as $pkg) { + $channel = $this->config->get('default_channel'); + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + $parsed = $reg->parsePackageName($pkg, $channel); + PEAR::staticPopErrorHandling(); + if (!$parsed || PEAR::isError($parsed)) { + $badparams[] = $pkg; + continue; + } + $package = $parsed['package']; + $channel = $parsed['channel']; + $info = &$reg->getPackage($package, $channel); + if ($info === null && + ($channel == 'pear.php.net' || $channel == 'pecl.php.net')) { + // make sure this isn't a package that has flipped from pear to pecl but + // used a package.xml 1.0 + $testc = ($channel == 'pear.php.net') ? 'pecl.php.net' : 'pear.php.net'; + $info = &$reg->getPackage($package, $testc); + if ($info !== null) { + $channel = $testc; + } + } + if ($info === null) { + $badparams[] = $pkg; + } else { + $newparams[] = &$info; + // check for binary packages (this is an alias for those packages if so) + if ($installedbinary = $info->getInstalledBinary()) { + $this->ui->log('adding binary package ' . + $reg->parsedPackageNameToString(array('channel' => $channel, + 'package' => $installedbinary), true)); + $newparams[] = &$reg->getPackage($installedbinary, $channel); + } + // add the contents of a dependency group to the list of installed packages + if (isset($parsed['group'])) { + $group = $info->getDependencyGroup($parsed['group']); + if ($group) { + $installed = $reg->getInstalledGroup($group); + if ($installed) { + foreach ($installed as $i => $p) { + $newparams[] = &$installed[$i]; + } + } + } + } + } + } + $err = $this->installer->sortPackagesForUninstall($newparams); + if (PEAR::isError($err)) { + $this->ui->outputData($err->getMessage(), $command); + return true; + } + $params = $newparams; + // twist this to use it to check on whether dependent packages are also being uninstalled + // for circular dependencies like subpackages + $this->installer->setUninstallPackages($newparams); + $params = array_merge($params, $badparams); + $binaries = array(); + foreach ($params as $pkg) { + $this->installer->pushErrorHandling(PEAR_ERROR_RETURN); + if ($err = $this->installer->uninstall($pkg, $options)) { + $this->installer->popErrorHandling(); + if (PEAR::isError($err)) { + $this->ui->outputData($err->getMessage(), $command); + continue; + } + if ($pkg->getPackageType() == 'extsrc' || + $pkg->getPackageType() == 'extbin' || + $pkg->getPackageType() == 'zendextsrc' || + $pkg->getPackageType() == 'zendextbin') { + if ($instbin = $pkg->getInstalledBinary()) { + continue; // this will be uninstalled later + } + + foreach ($pkg->getFilelist() as $name => $atts) { + $pinfo = pathinfo($atts['installed_as']); + if (!isset($pinfo['extension']) || + in_array($pinfo['extension'], array('c', 'h'))) { + continue; // make sure we don't match php_blah.h + } + if ((strpos($pinfo['basename'], 'php_') === 0 && + $pinfo['extension'] == 'dll') || + // most unices + $pinfo['extension'] == 'so' || + // hp-ux + $pinfo['extension'] == 'sl') { + $binaries[] = array($atts['installed_as'], $pinfo); + break; + } + } + if (count($binaries)) { + foreach ($binaries as $pinfo) { + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + $ret = $this->disableExtension(array($pinfo[0]), $pkg->getPackageType()); + PEAR::staticPopErrorHandling(); + if (PEAR::isError($ret)) { + $extrainfo[] = $ret->getMessage(); + if ($pkg->getPackageType() == 'extsrc' || + $pkg->getPackageType() == 'extbin') { + $exttype = 'extension'; + } else { + ob_start(); + phpinfo(INFO_GENERAL); + $info = ob_get_contents(); + ob_end_clean(); + $debug = function_exists('leak') ? '_debug' : ''; + $ts = preg_match('Thread Safety.+enabled', $info) ? '_ts' : ''; + $exttype = 'zend_extension' . $debug . $ts; + } + $this->ui->outputData('Unable to remove "' . $exttype . '=' . + $pinfo[1]['basename'] . '" from php.ini', $command); + } else { + $this->ui->outputData('Extension ' . $pkg->getProvidesExtension() . + ' disabled in php.ini', $command); + } + } + } + } + $savepkg = $pkg; + if ($this->config->get('verbose') > 0) { + if (is_object($pkg)) { + $pkg = $reg->parsedPackageNameToString($pkg); + } + $this->ui->outputData("uninstall ok: $pkg", $command); + } + if (!isset($options['offline']) && is_object($savepkg) && + defined('PEAR_REMOTEINSTALL_OK')) { + if ($this->config->isDefinedLayer('ftp')) { + $this->installer->pushErrorHandling(PEAR_ERROR_RETURN); + $info = $this->installer->ftpUninstall($savepkg); + $this->installer->popErrorHandling(); + if (PEAR::isError($info)) { + $this->ui->outputData($info->getMessage()); + $this->ui->outputData("remote uninstall failed: $pkg"); + } else { + $this->ui->outputData("remote uninstall ok: $pkg"); + } + } + } + } else { + $this->installer->popErrorHandling(); + if (is_object($pkg)) { + $pkg = $reg->parsedPackageNameToString($pkg); + } + return $this->raiseError("uninstall failed: $pkg"); + } + } + return true; + } + + // }}} + + + // }}} + // {{{ doBundle() + /* + (cox) It just downloads and untars the package, does not do + any check that the PEAR_Installer::_installFile() does. + */ + + function doBundle($command, $options, $params) + { + $downloader = &$this->getDownloader($this->ui, array('force' => true, 'nodeps' => true, + 'soft' => true, 'downloadonly' => true), $this->config); + $reg = &$this->config->getRegistry(); + if (sizeof($params) < 1) { + return $this->raiseError("Please supply the package you want to bundle"); + } + + if (isset($options['destination'])) { + if (!is_dir($options['destination'])) { + System::mkdir('-p ' . $options['destination']); + } + $dest = realpath($options['destination']); + } else { + $pwd = getcwd(); + if (is_dir($pwd . DIRECTORY_SEPARATOR . 'ext')) { + $dest = $pwd . DIRECTORY_SEPARATOR . 'ext'; + } else { + $dest = $pwd; + } + } + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + $err = $downloader->setDownloadDir($dest); + PEAR::staticPopErrorHandling(); + if (PEAR::isError($err)) { + return PEAR::raiseError('download directory "' . $dest . + '" is not writeable.'); + } + $result = &$downloader->download(array($params[0])); + if (PEAR::isError($result)) { + return $result; + } + if (!isset($result[0])) { + return $this->raiseError('unable to unpack ' . $params[0]); + } + $pkgfile = &$result[0]->getPackageFile(); + $pkgname = $pkgfile->getName(); + $pkgversion = $pkgfile->getVersion(); + + // Unpacking ------------------------------------------------- + $dest .= DIRECTORY_SEPARATOR . $pkgname; + $orig = $pkgname . '-' . $pkgversion; + + $tar = &new Archive_Tar($pkgfile->getArchiveFile()); + if (!$tar->extractModify($dest, $orig)) { + return $this->raiseError('unable to unpack ' . $pkgfile->getArchiveFile()); + } + $this->ui->outputData("Package ready at '$dest'"); + // }}} + } + + // }}} + + function doRunScripts($command, $options, $params) + { + if (!isset($params[0])) { + return $this->raiseError('run-scripts expects 1 parameter: a package name'); + } + $reg = &$this->config->getRegistry(); + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + $parsed = $reg->parsePackageName($params[0], $this->config->get('default_channel')); + PEAR::staticPopErrorHandling(); + if (PEAR::isError($parsed)) { + return $this->raiseError($parsed); + } + $package = &$reg->getPackage($parsed['package'], $parsed['channel']); + if (is_object($package)) { + $package->setConfig($this->config); + $package->runPostinstallScripts(); + } else { + return $this->raiseError('Could not retrieve package "' . $params[0] . '" from registry'); + } + $this->ui->outputData('Install scripts complete', $command); + return true; + } + + /** + * Given a list of packages, filter out those ones that are already up to date + * + * @param $packages: packages, in parsed array format ! + * @return list of packages that can be upgraded + */ + function _filterUptodatePackages($packages, $command) + { + $reg = &$this->config->getRegistry(); + $latestReleases = array(); + + $ret = array(); + foreach($packages as $package) { + if (isset($package['group'])) { + $ret[] = $package; + continue; + } + $channel = $package['channel']; + $name = $package['package']; + + if (!$reg->packageExists($name, $channel)) { + $ret[] = $package; + continue; + } + if (!isset($latestReleases[$channel])) { + // fill in cache for this channel + $chan = &$reg->getChannel($channel); + if (PEAR::isError($chan)) { + return $this->raiseError($chan); + } + if ($chan->supportsREST($this->config->get('preferred_mirror', + null, $channel)) && + $base = $chan->getBaseURL('REST1.0', + $this->config->get('preferred_mirror', + null, $channel))) + { + $dorest = true; + } else { + $dorest = false; + $remote = &$this->config->getRemote($this->config); + } + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + if ($dorest) { + $rest = &$this->config->getREST('1.0', array()); + $installed = array_flip($reg->listPackages($channel)); + $latest = $rest->listLatestUpgrades($base, + $this->config->get('preferred_state', null, $channel), $installed, + $channel, $reg); + } else { + $latest = $remote->call("package.listLatestReleases", + $this->config->get('preferred_state', null, $channel)); + unset($remote); + } + PEAR::staticPopErrorHandling(); + if (PEAR::isError($latest)) { + $this->ui->outputData('Error getting channel info from ' . $channel . + ': ' . $latest->getMessage()); + continue; + } + + $latestReleases[$channel] = array_change_key_case($latest); + } + + // check package for latest release + if (isset($latestReleases[$channel][strtolower($name)])) { + // if not set, up to date + $inst_version = $reg->packageInfo($name, 'version', $channel); + $channel_version = $latestReleases[$channel][strtolower($name)]['version']; + if (version_compare($channel_version, $inst_version, "le")) { + // installed version is up-to-date + continue; + } + // maintain BC + if ($command == 'upgrade-all') { + $this->ui->outputData(array('data' => 'Will upgrade ' . + $reg->parsedPackageNameToString($package)), $command); + } + $ret[] = $package; + } + } + + return $ret; + } + +} +?> diff --git a/src/lib/pear/PEAR/PEAR/Command/Install.xml b/src/lib/pear/PEAR/PEAR/Command/Install.xml new file mode 100644 index 0000000..94044c2 --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Command/Install.xml @@ -0,0 +1,259 @@ + + + Install Package + doInstall + i + + + f + will overwrite newer installed packages + + + l + do not check for recommended dependency version + + + n + ignore dependencies, install anyway + + + r + do not install files, only register the package as installed + + + s + soft install, fail silently, or upgrade if already installed + + + B + don't build C extensions + + + Z + request uncompressed files when downloading + + + R + DIR + root directory used when installing files (ala PHP's INSTALL_ROOT), use packagingroot for RPM + + + P + DIR + root directory used when packaging files, like RPM packaging + + + force install even if there were errors + + + a + install all required and optional dependencies + + + o + install all required dependencies + + + O + do not attempt to download any urls or contact channels + + + p + Only list the packages that would be downloaded + + + [channel/]<package> ... +Installs one or more PEAR packages. You can specify a package to +install in four ways: + +"Package-1.0.tgz" : installs from a local file + +"http://example.com/Package-1.0.tgz" : installs from +anywhere on the net. + +"package.xml" : installs the package described in +package.xml. Useful for testing, or for wrapping a PEAR package in +another package manager such as RPM. + +"Package[-version/state][.tar]" : queries your default channel's server +({config master_server}) and downloads the newest package with +the preferred quality/state ({config preferred_state}). + +To retrieve Package version 1.1, use "Package-1.1," to retrieve +Package state beta, use "Package-beta." To retrieve an uncompressed +file, append .tar (make sure there is no file by the same name first) + +To download a package from another channel, prefix with the channel name like +"channel/Package" + +More than one package may be specified at once. It is ok to mix these +four ways of specifying packages. + + + + Upgrade Package + doInstall + up + + + f + overwrite newer installed packages + + + l + do not check for recommended dependency version + + + n + ignore dependencies, upgrade anyway + + + r + do not install files, only register the package as upgraded + + + B + don't build C extensions + + + Z + request uncompressed files when downloading + + + R + DIR + root directory used when installing files (ala PHP's INSTALL_ROOT) + + + force install even if there were errors + + + a + install all required and optional dependencies + + + o + install all required dependencies + + + O + do not attempt to download any urls or contact channels + + + p + Only list the packages that would be downloaded + + + <package> ... +Upgrades one or more PEAR packages. See documentation for the +"install" command for ways to specify a package. + +When upgrading, your package will be updated if the provided new +package has a higher version number (use the -f option if you need to +upgrade anyway). + +More than one package may be specified at once. + + + + Upgrade All Packages + doInstall + ua + + + n + ignore dependencies, upgrade anyway + + + r + do not install files, only register the package as upgraded + + + B + don't build C extensions + + + Z + request uncompressed files when downloading + + + R + DIR + root directory used when installing files (ala PHP's INSTALL_ROOT) + + + force install even if there were errors + + + do not check for recommended dependency version + + + +Upgrades all packages that have a newer release available. Upgrades are +done only if there is a release available of the state specified in +"preferred_state" (currently {config preferred_state}), or a state considered +more stable. + + + + Un-install Package + doUninstall + un + + + n + ignore dependencies, uninstall anyway + + + r + do not remove files, only register the packages as not installed + + + R + DIR + root directory used when installing files (ala PHP's INSTALL_ROOT) + + + force install even if there were errors + + + O + do not attempt to uninstall remotely + + + [channel/]<package> ... +Uninstalls one or more PEAR packages. More than one package may be +specified at once. Prefix with channel name to uninstall from a +channel not in your default channel ({config default_channel}) + + + + Unpacks a Pecl Package + doBundle + bun + + + d + DIR + Optional destination directory for unpacking (defaults to current path or "ext" if exists) + + + f + Force the unpacking even if there were errors in the package + + + <package> +Unpacks a Pecl Package into the selected location. It will download the +package if needed. + + + + Run Post-Install Scripts bundled with a package + doRunScripts + rs + + <package> +Run post-installation scripts in package <package>, if any exist. + + + \ No newline at end of file diff --git a/src/lib/pear/PEAR/PEAR/Command/Mirror.php b/src/lib/pear/PEAR/PEAR/Command/Mirror.php new file mode 100644 index 0000000..f1256e0 --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Command/Mirror.php @@ -0,0 +1,153 @@ + + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: Mirror.php,v 1.20 2008/04/11 01:16:40 dufuz Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 1.2.0 + */ + +/** + * base class + */ +require_once 'PEAR/Command/Common.php'; + +/** + * PEAR commands for providing file mirrors + * + * @category pear + * @package PEAR + * @author Alexander Merz + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 1.2.0 + */ +class PEAR_Command_Mirror extends PEAR_Command_Common +{ + // {{{ properties + + var $commands = array( + 'download-all' => array( + 'summary' => 'Downloads each available package from the default channel', + 'function' => 'doDownloadAll', + 'shortcut' => 'da', + 'options' => array( + 'channel' => + array( + 'shortopt' => 'c', + 'doc' => 'specify a channel other than the default channel', + 'arg' => 'CHAN', + ), + ), + 'doc' => ' +Requests a list of available packages from the default channel ({config default_channel}) +and downloads them to current working directory. Note: only +packages within preferred_state ({config preferred_state}) will be downloaded' + ), + ); + + // }}} + + // {{{ constructor + + /** + * PEAR_Command_Mirror constructor. + * + * @access public + * @param object PEAR_Frontend a reference to an frontend + * @param object PEAR_Config a reference to the configuration data + */ + function PEAR_Command_Mirror(&$ui, &$config) + { + parent::PEAR_Command_Common($ui, $config); + } + + // }}} + + /** + * For unit-testing + */ + function &factory($a) + { + $a = &PEAR_Command::factory($a, $this->config); + return $a; + } + + // {{{ doDownloadAll() + /** + * retrieves a list of avaible Packages from master server + * and downloads them + * + * @access public + * @param string $command the command + * @param array $options the command options before the command + * @param array $params the stuff after the command name + * @return bool true if succesful + * @throw PEAR_Error + */ + function doDownloadAll($command, $options, $params) + { + $savechannel = $this->config->get('default_channel'); + $reg = &$this->config->getRegistry(); + $channel = isset($options['channel']) ? $options['channel'] : + $this->config->get('default_channel'); + if (!$reg->channelExists($channel)) { + $this->config->set('default_channel', $savechannel); + return $this->raiseError('Channel "' . $channel . '" does not exist'); + } + $this->config->set('default_channel', $channel); + $this->ui->outputData('Using Channel ' . $this->config->get('default_channel')); + $chan = $reg->getChannel($channel); + if (PEAR::isError($chan)) { + return $this->raiseError($chan); + } + if ($chan->supportsREST($this->config->get('preferred_mirror')) && + $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) { + $rest = &$this->config->getREST('1.0', array()); + $remoteInfo = array_flip($rest->listPackages($base, $channel)); + } else { + $remote = &$this->config->getRemote(); + $stable = ($this->config->get('preferred_state') == 'stable'); + $remoteInfo = $remote->call("package.listAll", true, $stable, false); + } + if (PEAR::isError($remoteInfo)) { + return $remoteInfo; + } + $cmd = &$this->factory("download"); + if (PEAR::isError($cmd)) { + return $cmd; + } + $this->ui->outputData('Using Preferred State of ' . + $this->config->get('preferred_state')); + $this->ui->outputData('Gathering release information, please wait...'); + /** + * Error handling not necessary, because already done by + * the download command + */ + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + $err = $cmd->run('download', array('downloadonly' => true), array_keys($remoteInfo)); + PEAR::staticPopErrorHandling(); + $this->config->set('default_channel', $savechannel); + if (PEAR::isError($err)) { + $this->ui->outputData($err->getMessage()); + } + return true; + } + + // }}} +} diff --git a/src/lib/pear/PEAR/PEAR/Command/Mirror.xml b/src/lib/pear/PEAR/PEAR/Command/Mirror.xml new file mode 100644 index 0000000..fe8be9d --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Command/Mirror.xml @@ -0,0 +1,18 @@ + + + Downloads each available package from the default channel + doDownloadAll + da + + + c + specify a channel other than the default channel + CHAN + + + +Requests a list of available packages from the default channel ({config default_channel}) +and downloads them to current working directory. Note: only +packages within preferred_state ({config preferred_state}) will be downloaded + + \ No newline at end of file diff --git a/src/lib/pear/PEAR/PEAR/Command/Package.php b/src/lib/pear/PEAR/PEAR/Command/Package.php new file mode 100644 index 0000000..8b6e855 --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Command/Package.php @@ -0,0 +1,843 @@ + + * @author Martin Jansen + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: Package.php,v 1.128 2008/03/29 21:06:58 dufuz Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 0.1 + */ + +/** + * base class + */ +require_once 'PEAR/Command/Common.php'; + +/** + * PEAR commands for login/logout + * + * @category pear + * @package PEAR + * @author Stig Bakken + * @author Martin Jansen + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 0.1 + */ + +class PEAR_Command_Package extends PEAR_Command_Common +{ + // {{{ properties + + var $commands = array( + 'package' => array( + 'summary' => 'Build Package', + 'function' => 'doPackage', + 'shortcut' => 'p', + 'options' => array( + 'nocompress' => array( + 'shortopt' => 'Z', + 'doc' => 'Do not gzip the package file' + ), + 'showname' => array( + 'shortopt' => 'n', + 'doc' => 'Print the name of the packaged file.', + ), + ), + 'doc' => '[descfile] [descfile2] +Creates a PEAR package from its description file (usually called +package.xml). If a second packagefile is passed in, then +the packager will check to make sure that one is a package.xml +version 1.0, and the other is a package.xml version 2.0. The +package.xml version 1.0 will be saved as "package.xml" in the archive, +and the other as "package2.xml" in the archive" +' + ), + 'package-validate' => array( + 'summary' => 'Validate Package Consistency', + 'function' => 'doPackageValidate', + 'shortcut' => 'pv', + 'options' => array(), + 'doc' => ' +', + ), + 'cvsdiff' => array( + 'summary' => 'Run a "cvs diff" for all files in a package', + 'function' => 'doCvsDiff', + 'shortcut' => 'cd', + 'options' => array( + 'quiet' => array( + 'shortopt' => 'q', + 'doc' => 'Be quiet', + ), + 'reallyquiet' => array( + 'shortopt' => 'Q', + 'doc' => 'Be really quiet', + ), + 'date' => array( + 'shortopt' => 'D', + 'doc' => 'Diff against revision of DATE', + 'arg' => 'DATE', + ), + 'release' => array( + 'shortopt' => 'R', + 'doc' => 'Diff against tag for package release REL', + 'arg' => 'REL', + ), + 'revision' => array( + 'shortopt' => 'r', + 'doc' => 'Diff against revision REV', + 'arg' => 'REV', + ), + 'context' => array( + 'shortopt' => 'c', + 'doc' => 'Generate context diff', + ), + 'unified' => array( + 'shortopt' => 'u', + 'doc' => 'Generate unified diff', + ), + 'ignore-case' => array( + 'shortopt' => 'i', + 'doc' => 'Ignore case, consider upper- and lower-case letters equivalent', + ), + 'ignore-whitespace' => array( + 'shortopt' => 'b', + 'doc' => 'Ignore changes in amount of white space', + ), + 'ignore-blank-lines' => array( + 'shortopt' => 'B', + 'doc' => 'Ignore changes that insert or delete blank lines', + ), + 'brief' => array( + 'doc' => 'Report only whether the files differ, no details', + ), + 'dry-run' => array( + 'shortopt' => 'n', + 'doc' => 'Don\'t do anything, just pretend', + ), + ), + 'doc' => ' +Compares all the files in a package. Without any options, this +command will compare the current code with the last checked-in code. +Using the -r or -R option you may compare the current code with that +of a specific release. +', + ), + 'cvstag' => array( + 'summary' => 'Set CVS Release Tag', + 'function' => 'doCvsTag', + 'shortcut' => 'ct', + 'options' => array( + 'quiet' => array( + 'shortopt' => 'q', + 'doc' => 'Be quiet', + ), + 'reallyquiet' => array( + 'shortopt' => 'Q', + 'doc' => 'Be really quiet', + ), + 'slide' => array( + 'shortopt' => 'F', + 'doc' => 'Move (slide) tag if it exists', + ), + 'delete' => array( + 'shortopt' => 'd', + 'doc' => 'Remove tag', + ), + 'dry-run' => array( + 'shortopt' => 'n', + 'doc' => 'Don\'t do anything, just pretend', + ), + ), + 'doc' => ' [files...] +Sets a CVS tag on all files in a package. Use this command after you have +packaged a distribution tarball with the "package" command to tag what +revisions of what files were in that release. If need to fix something +after running cvstag once, but before the tarball is released to the public, +use the "slide" option to move the release tag. + +to include files (such as a second package.xml, or tests not included in the +release), pass them as additional parameters. +', + ), + 'package-dependencies' => array( + 'summary' => 'Show package dependencies', + 'function' => 'doPackageDependencies', + 'shortcut' => 'pd', + 'options' => array(), + 'doc' => ' +List all dependencies the package has.' + ), + 'sign' => array( + 'summary' => 'Sign a package distribution file', + 'function' => 'doSign', + 'shortcut' => 'si', + 'options' => array( + 'verbose' => array( + 'shortopt' => 'v', + 'doc' => 'Display GnuPG output', + ), + ), + 'doc' => ' +Signs a package distribution (.tar or .tgz) file with GnuPG.', + ), + 'makerpm' => array( + 'summary' => 'Builds an RPM spec file from a PEAR package', + 'function' => 'doMakeRPM', + 'shortcut' => 'rpm', + 'options' => array( + 'spec-template' => array( + 'shortopt' => 't', + 'arg' => 'FILE', + 'doc' => 'Use FILE as RPM spec file template' + ), + 'rpm-pkgname' => array( + 'shortopt' => 'p', + 'arg' => 'FORMAT', + 'doc' => 'Use FORMAT as format string for RPM package name, %s is replaced +by the PEAR package name, defaults to "PEAR::%s".', + ), + ), + 'doc' => ' + +Creates an RPM .spec file for wrapping a PEAR package inside an RPM +package. Intended to be used from the SPECS directory, with the PEAR +package tarball in the SOURCES directory: + +$ pear makerpm ../SOURCES/Net_Socket-1.0.tgz +Wrote RPM spec file PEAR::Net_Geo-1.0.spec +$ rpm -bb PEAR::Net_Socket-1.0.spec +... +Wrote: /usr/src/redhat/RPMS/i386/PEAR::Net_Socket-1.0-1.i386.rpm +', + ), + 'convert' => array( + 'summary' => 'Convert a package.xml 1.0 to package.xml 2.0 format', + 'function' => 'doConvert', + 'shortcut' => 'c2', + 'options' => array( + 'flat' => array( + 'shortopt' => 'f', + 'doc' => 'do not beautify the filelist.', + ), + ), + 'doc' => '[descfile] [descfile2] +Converts a package.xml in 1.0 format into a package.xml +in 2.0 format. The new file will be named package2.xml by default, +and package.xml will be used as the old file by default. +This is not the most intelligent conversion, and should only be +used for automated conversion or learning the format. +' + ), + ); + + var $output; + + // }}} + // {{{ constructor + + /** + * PEAR_Command_Package constructor. + * + * @access public + */ + function PEAR_Command_Package(&$ui, &$config) + { + parent::PEAR_Command_Common($ui, $config); + } + + // }}} + + // {{{ _displayValidationResults() + + function _displayValidationResults($err, $warn, $strict = false) + { + foreach ($err as $e) { + $this->output .= "Error: $e\n"; + } + foreach ($warn as $w) { + $this->output .= "Warning: $w\n"; + } + $this->output .= sprintf('Validation: %d error(s), %d warning(s)'."\n", + sizeof($err), sizeof($warn)); + if ($strict && sizeof($err) > 0) { + $this->output .= "Fix these errors and try again."; + return false; + } + return true; + } + + // }}} + function &getPackager() + { + if (!class_exists('PEAR_Packager')) { + require_once 'PEAR/Packager.php'; + } + $a = &new PEAR_Packager; + return $a; + } + + function &getPackageFile($config, $debug = false, $tmpdir = null) + { + if (!class_exists('PEAR_Common')) { + require_once 'PEAR/Common.php'; + } + if (!class_exists('PEAR_PackageFile')) { + require_once 'PEAR/PackageFile.php'; + } + $a = &new PEAR_PackageFile($config, $debug, $tmpdir); + $common = new PEAR_Common; + $common->ui = $this->ui; + $a->setLogger($common); + return $a; + } + // {{{ doPackage() + + function doPackage($command, $options, $params) + { + $this->output = ''; + $pkginfofile = isset($params[0]) ? $params[0] : 'package.xml'; + $pkg2 = isset($params[1]) ? $params[1] : null; + if (!$pkg2 && !isset($params[0])) { + if (file_exists('package2.xml')) { + $pkg2 = 'package2.xml'; + } + } + $packager = &$this->getPackager(); + $compress = empty($options['nocompress']) ? true : false; + $result = $packager->package($pkginfofile, $compress, $pkg2); + if (PEAR::isError($result)) { + return $this->raiseError($result); + } + // Don't want output, only the package file name just created + if (isset($options['showname'])) { + $this->output = $result; + } + if ($this->output) { + $this->ui->outputData($this->output, $command); + } + return true; + } + + // }}} + // {{{ doPackageValidate() + + function doPackageValidate($command, $options, $params) + { + $this->output = ''; + if (sizeof($params) < 1) { + $params[0] = "package.xml"; + } + $obj = &$this->getPackageFile($this->config, $this->_debug); + $obj->rawReturn(); + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + $info = $obj->fromTgzFile($params[0], PEAR_VALIDATE_NORMAL); + if (PEAR::isError($info)) { + $info = $obj->fromPackageFile($params[0], PEAR_VALIDATE_NORMAL); + } else { + $archive = $info->getArchiveFile(); + $tar = &new Archive_Tar($archive); + $tar->extract(dirname($info->getPackageFile())); + $info->setPackageFile(dirname($info->getPackageFile()) . DIRECTORY_SEPARATOR . + $info->getPackage() . '-' . $info->getVersion() . DIRECTORY_SEPARATOR . + basename($info->getPackageFile())); + } + PEAR::staticPopErrorHandling(); + if (PEAR::isError($info)) { + return $this->raiseError($info); + } + $valid = false; + if ($info->getPackagexmlVersion() == '2.0') { + if ($valid = $info->validate(PEAR_VALIDATE_NORMAL)) { + $info->flattenFileList(); + $valid = $info->validate(PEAR_VALIDATE_PACKAGING); + } + } else { + $valid = $info->validate(PEAR_VALIDATE_PACKAGING); + } + $err = $warn = array(); + if ($errors = $info->getValidationWarnings()) { + foreach ($errors as $error) { + if ($error['level'] == 'warning') { + $warn[] = $error['message']; + } else { + $err[] = $error['message']; + } + } + } + $this->_displayValidationResults($err, $warn); + $this->ui->outputData($this->output, $command); + return true; + } + + // }}} + // {{{ doCvsTag() + + function doCvsTag($command, $options, $params) + { + $this->output = ''; + $_cmd = $command; + if (sizeof($params) < 1) { + $help = $this->getHelp($command); + return $this->raiseError("$command: missing parameter: $help[0]"); + } + $obj = &$this->getPackageFile($this->config, $this->_debug); + $info = $obj->fromAnyFile($params[0], PEAR_VALIDATE_NORMAL); + if (PEAR::isError($info)) { + return $this->raiseError($info); + } + $err = $warn = array(); + if (!$info->validate()) { + foreach ($info->getValidationWarnings() as $error) { + if ($error['level'] == 'warning') { + $warn[] = $error['message']; + } else { + $err[] = $error['message']; + } + } + } + if (!$this->_displayValidationResults($err, $warn, true)) { + $this->ui->outputData($this->output, $command); + return $this->raiseError('CVS tag failed'); + } + $version = $info->getVersion(); + $cvsversion = preg_replace('/[^a-z0-9]/i', '_', $version); + $cvstag = "RELEASE_$cvsversion"; + $files = array_keys($info->getFilelist()); + $command = "cvs"; + if (isset($options['quiet'])) { + $command .= ' -q'; + } + if (isset($options['reallyquiet'])) { + $command .= ' -Q'; + } + $command .= ' tag'; + if (isset($options['slide'])) { + $command .= ' -F'; + } + if (isset($options['delete'])) { + $command .= ' -d'; + } + $command .= ' ' . $cvstag . ' ' . escapeshellarg($params[0]); + array_shift($params); + if (count($params)) { + // add in additional files to be tagged + $files = array_merge($files, $params); + } + foreach ($files as $file) { + $command .= ' ' . escapeshellarg($file); + } + if ($this->config->get('verbose') > 1) { + $this->output .= "+ $command\n"; + } + $this->output .= "+ $command\n"; + if (empty($options['dry-run'])) { + $fp = popen($command, "r"); + while ($line = fgets($fp, 1024)) { + $this->output .= rtrim($line)."\n"; + } + pclose($fp); + } + $this->ui->outputData($this->output, $_cmd); + return true; + } + + // }}} + // {{{ doCvsDiff() + + function doCvsDiff($command, $options, $params) + { + $this->output = ''; + if (sizeof($params) < 1) { + $help = $this->getHelp($command); + return $this->raiseError("$command: missing parameter: $help[0]"); + } + $obj = &$this->getPackageFile($this->config, $this->_debug); + $info = $obj->fromAnyFile($params[0], PEAR_VALIDATE_NORMAL); + if (PEAR::isError($info)) { + return $this->raiseError($info); + } + $err = $warn = array(); + if (!$info->validate()) { + foreach ($info->getValidationWarnings() as $error) { + if ($error['level'] == 'warning') { + $warn[] = $error['message']; + } else { + $err[] = $error['message']; + } + } + } + if (!$this->_displayValidationResults($err, $warn, true)) { + $this->ui->outputData($this->output, $command); + return $this->raiseError('CVS diff failed'); + } + $info1 = $info->getFilelist(); + $files = $info1; + $cmd = "cvs"; + if (isset($options['quiet'])) { + $cmd .= ' -q'; + unset($options['quiet']); + } + if (isset($options['reallyquiet'])) { + $cmd .= ' -Q'; + unset($options['reallyquiet']); + } + if (isset($options['release'])) { + $cvsversion = preg_replace('/[^a-z0-9]/i', '_', $options['release']); + $cvstag = "RELEASE_$cvsversion"; + $options['revision'] = $cvstag; + unset($options['release']); + } + $execute = true; + if (isset($options['dry-run'])) { + $execute = false; + unset($options['dry-run']); + } + $cmd .= ' diff'; + // the rest of the options are passed right on to "cvs diff" + foreach ($options as $option => $optarg) { + $arg = $short = false; + if (isset($this->commands[$command]['options'][$option])) { + $arg = $this->commands[$command]['options'][$option]['arg']; + $short = $this->commands[$command]['options'][$option]['shortopt']; + } + $cmd .= $short ? " -$short" : " --$option"; + if ($arg && $optarg) { + $cmd .= ($short ? '' : '=') . escapeshellarg($optarg); + } + } + foreach ($files as $file) { + $cmd .= ' ' . escapeshellarg($file['name']); + } + if ($this->config->get('verbose') > 1) { + $this->output .= "+ $cmd\n"; + } + if ($execute) { + $fp = popen($cmd, "r"); + while ($line = fgets($fp, 1024)) { + $this->output .= rtrim($line)."\n"; + } + pclose($fp); + } + $this->ui->outputData($this->output, $command); + return true; + } + + // }}} + // {{{ doPackageDependencies() + + function doPackageDependencies($command, $options, $params) + { + // $params[0] -> the PEAR package to list its information + if (sizeof($params) != 1) { + return $this->raiseError("bad parameter(s), try \"help $command\""); + } + $obj = &$this->getPackageFile($this->config, $this->_debug); + $info = $obj->fromAnyFile($params[0], PEAR_VALIDATE_NORMAL); + if (PEAR::isError($info)) { + return $this->raiseError($info); + } + $deps = $info->getDeps(); + if (is_array($deps)) { + if ($info->getPackagexmlVersion() == '1.0') { + $data = array( + 'caption' => 'Dependencies for pear/' . $info->getPackage(), + 'border' => true, + 'headline' => array("Required?", "Type", "Name", "Relation", "Version"), + ); + + foreach ($deps as $d) { + if (isset($d['optional'])) { + if ($d['optional'] == 'yes') { + $req = 'No'; + } else { + $req = 'Yes'; + } + } else { + $req = 'Yes'; + } + if (isset($this->_deps_rel_trans[$d['rel']])) { + $rel = $this->_deps_rel_trans[$d['rel']]; + } else { + $rel = $d['rel']; + } + + if (isset($this->_deps_type_trans[$d['type']])) { + $type = ucfirst($this->_deps_type_trans[$d['type']]); + } else { + $type = $d['type']; + } + + if (isset($d['name'])) { + $name = $d['name']; + } else { + $name = ''; + } + + if (isset($d['version'])) { + $version = $d['version']; + } else { + $version = ''; + } + + $data['data'][] = array($req, $type, $name, $rel, $version); + } + } else { // package.xml 2.0 dependencies display + require_once 'PEAR/Dependency2.php'; + $deps = $info->getDependencies(); + $reg = &$this->config->getRegistry(); + if (is_array($deps)) { + $d = new PEAR_Dependency2($this->config, array(), ''); + $data = array( + 'caption' => 'Dependencies for ' . $info->getPackage(), + 'border' => true, + 'headline' => array("Required?", "Type", "Name", 'Versioning', 'Group'), + ); + foreach ($deps as $type => $subd) { + $req = ($type == 'required') ? 'Yes' : 'No'; + if ($type == 'group') { + $group = $subd['attribs']['name']; + } else { + $group = ''; + } + if (!isset($subd[0])) { + $subd = array($subd); + } + foreach ($subd as $groupa) { + foreach ($groupa as $deptype => $depinfo) { + if ($deptype == 'attribs') { + continue; + } + if ($deptype == 'pearinstaller') { + $deptype = 'pear Installer'; + } + if (!isset($depinfo[0])) { + $depinfo = array($depinfo); + } + foreach ($depinfo as $inf) { + $name = ''; + if (isset($inf['channel'])) { + $alias = $reg->channelAlias($inf['channel']); + if (!$alias) { + $alias = '(channel?) ' .$inf['channel']; + } + $name = $alias . '/'; + } + if (isset($inf['name'])) { + $name .= $inf['name']; + } elseif (isset($inf['pattern'])) { + $name .= $inf['pattern']; + } else { + $name .= ''; + } + if (isset($inf['uri'])) { + $name .= ' [' . $inf['uri'] . ']'; + } + if (isset($inf['conflicts'])) { + $ver = 'conflicts'; + } else { + $ver = $d->_getExtraString($inf); + } + $data['data'][] = array($req, ucfirst($deptype), $name, + $ver, $group); + } + } + } + } + } + } + + $this->ui->outputData($data, $command); + return true; + } + + // Fallback + $this->ui->outputData("This package does not have any dependencies.", $command); + } + + // }}} + // {{{ doSign() + + function doSign($command, $options, $params) + { + require_once 'System.php'; + require_once 'Archive/Tar.php'; + // should move most of this code into PEAR_Packager + // so it'll be easy to implement "pear package --sign" + if (sizeof($params) != 1) { + return $this->raiseError("bad parameter(s), try \"help $command\""); + } + if (!file_exists($params[0])) { + return $this->raiseError("file does not exist: $params[0]"); + } + $obj = $this->getPackageFile($this->config, $this->_debug); + $info = $obj->fromTgzFile($params[0], PEAR_VALIDATE_NORMAL); + if (PEAR::isError($info)) { + return $this->raiseError($info); + } + $tar = new Archive_Tar($params[0]); + $tmpdir = System::mktemp('-d pearsign'); + if (!$tar->extractList('package2.xml package.xml package.sig', $tmpdir)) { + return $this->raiseError("failed to extract tar file"); + } + if (file_exists("$tmpdir/package.sig")) { + return $this->raiseError("package already signed"); + } + $packagexml = 'package.xml'; + if (file_exists("$tmpdir/package2.xml")) { + $packagexml = 'package2.xml'; + } + if (file_exists("$tmpdir/package.sig")) { + unlink("$tmpdir/package.sig"); + } + if (!file_exists("$tmpdir/$packagexml")) { + return $this->raiseError("Extracted file $tmpdir/$packagexml not found."); + } + $input = $this->ui->userDialog($command, + array('GnuPG Passphrase'), + array('password')); + if (!isset($input[0])) { + //use empty passphrase + $input[0] = ''; + } + + $devnull = (isset($options['verbose'])) ? '' : ' 2>/dev/null'; + $gpg = popen("gpg --batch --passphrase-fd 0 --armor --detach-sign --output $tmpdir/package.sig $tmpdir/$packagexml" . $devnull, "w"); + if (!$gpg) { + return $this->raiseError("gpg command failed"); + } + fwrite($gpg, "$input[0]\n"); + if (pclose($gpg) || !file_exists("$tmpdir/package.sig")) { + return $this->raiseError("gpg sign failed"); + } + if (!$tar->addModify("$tmpdir/package.sig", '', $tmpdir)) { + return $this->raiseError('failed adding signature to file'); + } + + $this->ui->outputData("Package signed.", $command); + return true; + } + + // }}} + + /** + * For unit testing purposes + */ + function &getInstaller(&$ui) + { + if (!class_exists('PEAR_Installer')) { + require_once 'PEAR/Installer.php'; + } + $a = &new PEAR_Installer($ui); + return $a; + } + + /** + * For unit testing purposes + */ + function &getCommandPackaging(&$ui, &$config) + { + if (!class_exists('PEAR_Command_Packaging')) { + if ($fp = @fopen('PEAR/Command/Packaging.php', 'r', true)) { + fclose($fp); + include_once 'PEAR/Command/Packaging.php'; + } + } + + if (class_exists('PEAR_Command_Packaging')) { + $a = &new PEAR_Command_Packaging($ui, $config); + } else { + $a = null; + } + return $a; + } + + // {{{ doMakeRPM() + + function doMakeRPM($command, $options, $params) + { + + // Check to see if PEAR_Command_Packaging is installed, and + // transparently switch to use the "make-rpm-spec" command from it + // instead, if it does. Otherwise, continue to use the old version + // of "makerpm" supplied with this package (PEAR). + $packaging_cmd = $this->getCommandPackaging($this->ui, $this->config); + if ($packaging_cmd !== null) { + $this->ui->outputData('PEAR_Command_Packaging is installed; using '. + 'newer "make-rpm-spec" command instead'); + return $packaging_cmd->run('make-rpm-spec', $options, $params); + } else { + $this->ui->outputData('WARNING: "pear makerpm" is no longer available; an '. + 'improved version is available via "pear make-rpm-spec", which '. + 'is available by installing PEAR_Command_Packaging'); + } + return true; + } + + function doConvert($command, $options, $params) + { + $packagexml = isset($params[0]) ? $params[0] : 'package.xml'; + $newpackagexml = isset($params[1]) ? $params[1] : dirname($packagexml) . + DIRECTORY_SEPARATOR . 'package2.xml'; + $pkg = &$this->getPackageFile($this->config, $this->_debug); + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + $pf = $pkg->fromPackageFile($packagexml, PEAR_VALIDATE_NORMAL); + PEAR::staticPopErrorHandling(); + if (!PEAR::isError($pf)) { + if (is_a($pf, 'PEAR_PackageFile_v2')) { + $this->ui->outputData($packagexml . ' is already a package.xml version 2.0'); + return true; + } + $gen = &$pf->getDefaultGenerator(); + $newpf = &$gen->toV2(); + $newpf->setPackagefile($newpackagexml); + $gen = &$newpf->getDefaultGenerator(); + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + $state = (isset($options['flat']) ? PEAR_VALIDATE_PACKAGING : PEAR_VALIDATE_NORMAL); + $saved = $gen->toPackageFile(dirname($newpackagexml), $state, + basename($newpackagexml)); + PEAR::staticPopErrorHandling(); + if (PEAR::isError($saved)) { + if (is_array($saved->getUserInfo())) { + foreach ($saved->getUserInfo() as $warning) { + $this->ui->outputData($warning['message']); + } + } + $this->ui->outputData($saved->getMessage()); + return true; + } + $this->ui->outputData('Wrote new version 2.0 package.xml to "' . $saved . '"'); + return true; + } else { + if (is_array($pf->getUserInfo())) { + foreach ($pf->getUserInfo() as $warning) { + $this->ui->outputData($warning['message']); + } + } + return $this->raiseError($pf); + } + } + + // }}} +} + +?> diff --git a/src/lib/pear/PEAR/PEAR/Command/Package.xml b/src/lib/pear/PEAR/PEAR/Command/Package.xml new file mode 100644 index 0000000..e3f6a55 --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Command/Package.xml @@ -0,0 +1,194 @@ + + + Build Package + doPackage + p + + + Z + Do not gzip the package file + + + n + Print the name of the packaged file. + + + [descfile] [descfile2] +Creates a PEAR package from its description file (usually called +package.xml). If a second packagefile is passed in, then +the packager will check to make sure that one is a package.xml +version 1.0, and the other is a package.xml version 2.0. The +package.xml version 1.0 will be saved as "package.xml" in the archive, +and the other as "package2.xml" in the archive" + + + + Validate Package Consistency + doPackageValidate + pv + + + + + + Run a "cvs diff" for all files in a package + doCvsDiff + cd + + + q + Be quiet + + + Q + Be really quiet + + + D + Diff against revision of DATE + DATE + + + R + Diff against tag for package release REL + REL + + + r + Diff against revision REV + REV + + + c + Generate context diff + + + u + Generate unified diff + + + i + Ignore case, consider upper- and lower-case letters equivalent + + + b + Ignore changes in amount of white space + + + B + Ignore changes that insert or delete blank lines + + + Report only whether the files differ, no details + + + n + Don't do anything, just pretend + + + <package.xml> +Compares all the files in a package. Without any options, this +command will compare the current code with the last checked-in code. +Using the -r or -R option you may compare the current code with that +of a specific release. + + + + Set CVS Release Tag + doCvsTag + ct + + + q + Be quiet + + + Q + Be really quiet + + + F + Move (slide) tag if it exists + + + d + Remove tag + + + n + Don't do anything, just pretend + + + <package.xml> +Sets a CVS tag on all files in a package. Use this command after you have +packaged a distribution tarball with the "package" command to tag what +revisions of what files were in that release. If need to fix something +after running cvstag once, but before the tarball is released to the public, +use the "slide" option to move the release tag. + + + + Show package dependencies + doPackageDependencies + pd + + +List all dependencies the package has. + + + Sign a package distribution file + doSign + si + + <package-file> +Signs a package distribution (.tar or .tgz) file with GnuPG. + + + Builds an RPM spec file from a PEAR package + doMakeRPM + rpm + + + t + FILE + Use FILE as RPM spec file template + + + p + FORMAT + Use FORMAT as format string for RPM package name, %s is replaced +by the PEAR package name, defaults to "PEAR::%s". + + + <package-file> + +Creates an RPM .spec file for wrapping a PEAR package inside an RPM +package. Intended to be used from the SPECS directory, with the PEAR +package tarball in the SOURCES directory: + +$ pear makerpm ../SOURCES/Net_Socket-1.0.tgz +Wrote RPM spec file PEAR::Net_Geo-1.0.spec +$ rpm -bb PEAR::Net_Socket-1.0.spec +... +Wrote: /usr/src/redhat/RPMS/i386/PEAR::Net_Socket-1.0-1.i386.rpm + + + + Convert a package.xml 1.0 to package.xml 2.0 format + doConvert + c2 + + + f + do not beautify the filelist. + + + [descfile] [descfile2] +Converts a package.xml in 1.0 format into a package.xml +in 2.0 format. The new file will be named package2.xml by default, +and package.xml will be used as the old file by default. +This is not the most intelligent conversion, and should only be +used for automated conversion or learning the format. + + + diff --git a/src/lib/pear/PEAR/PEAR/Command/Pickle.php b/src/lib/pear/PEAR/PEAR/Command/Pickle.php new file mode 100644 index 0000000..d59396a --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Command/Pickle.php @@ -0,0 +1,376 @@ + + * @copyright 2005-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: Pickle.php,v 1.8 2008/01/29 03:21:01 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 1.4.1 + */ + +/** + * base class + */ +require_once 'PEAR/Command/Common.php'; + +/** + * PEAR commands for login/logout + * + * @category pear + * @package PEAR + * @author Greg Beaver + * @copyright 2005-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 1.4.1 + */ + +class PEAR_Command_Pickle extends PEAR_Command_Common +{ + var $commands = array( + 'pickle' => array( + 'summary' => 'Build PECL Package', + 'function' => 'doPackage', + 'shortcut' => 'pi', + 'options' => array( + 'nocompress' => array( + 'shortopt' => 'Z', + 'doc' => 'Do not gzip the package file' + ), + 'showname' => array( + 'shortopt' => 'n', + 'doc' => 'Print the name of the packaged file.', + ), + ), + 'doc' => '[descfile] +Creates a PECL package from its package2.xml file. + +An automatic conversion will be made to a package.xml 1.0 and written out to +disk in the current directory as "package.xml". Note that +only simple package.xml 2.0 will be converted. package.xml 2.0 with: + + - dependency types other than required/optional PECL package/ext/php/pearinstaller + - more than one extsrcrelease or zendextsrcrelease + - zendextbinrelease, extbinrelease, phprelease, or bundle release type + - dependency groups + - ignore tags in release filelist + - tasks other than replace + - custom roles + +will cause pickle to fail, and output an error message. If your package2.xml +uses any of these features, you are best off using PEAR_PackageFileManager to +generate both package.xml. +' + ), + ); + + /** + * PEAR_Command_Package constructor. + * + * @access public + */ + function PEAR_Command_Pickle(&$ui, &$config) + { + parent::PEAR_Command_Common($ui, $config); + } + + + /** + * For unit-testing ease + * + * @return PEAR_Packager + */ + function &getPackager() + { + if (!class_exists('PEAR_Packager')) { + require_once 'PEAR/Packager.php'; + } + $a = &new PEAR_Packager; + return $a; + } + + /** + * For unit-testing ease + * + * @param PEAR_Config $config + * @param bool $debug + * @param string|null $tmpdir + * @return PEAR_PackageFile + */ + function &getPackageFile($config, $debug = false, $tmpdir = null) + { + if (!class_exists('PEAR_Common')) { + require_once 'PEAR/Common.php'; + } + if (!class_exists('PEAR_PackageFile')) { + require_once 'PEAR/PackageFile.php'; + } + $a = &new PEAR_PackageFile($config, $debug, $tmpdir); + $common = new PEAR_Common; + $common->ui = $this->ui; + $a->setLogger($common); + return $a; + } + + function doPackage($command, $options, $params) + { + $this->output = ''; + $pkginfofile = isset($params[0]) ? $params[0] : 'package2.xml'; + $packager = &$this->getPackager(); + if (PEAR::isError($err = $this->_convertPackage($pkginfofile))) { + return $err; + } + $compress = empty($options['nocompress']) ? true : false; + $result = $packager->package($pkginfofile, $compress, 'package.xml'); + if (PEAR::isError($result)) { + return $this->raiseError($result); + } + // Don't want output, only the package file name just created + if (isset($options['showname'])) { + $this->ui->outputData($result, $command); + } + return true; + } + + function _convertPackage($packagexml) + { + $pkg = &$this->getPackageFile($this->config); + $pf2 = &$pkg->fromPackageFile($packagexml, PEAR_VALIDATE_NORMAL); + if (!is_a($pf2, 'PEAR_PackageFile_v2')) { + return $this->raiseError('Cannot process "' . + $packagexml . '", is not a package.xml 2.0'); + } + require_once 'PEAR/PackageFile/v1.php'; + $pf = new PEAR_PackageFile_v1; + $pf->setConfig($this->config); + if ($pf2->getPackageType() != 'extsrc' && $pf2->getPackageType() != 'zendextsrc') { + return $this->raiseError('Cannot safely convert "' . $packagexml . + '", is not an extension source package. Using a PEAR_PackageFileManager-based ' . + 'script is an option'); + } + if (is_array($pf2->getUsesRole())) { + return $this->raiseError('Cannot safely convert "' . $packagexml . + '", contains custom roles. Using a PEAR_PackageFileManager-based script or ' . + 'the convert command is an option'); + } + if (is_array($pf2->getUsesTask())) { + return $this->raiseError('Cannot safely convert "' . $packagexml . + '", contains custom tasks. Using a PEAR_PackageFileManager-based script or ' . + 'the convert command is an option'); + } + $deps = $pf2->getDependencies(); + if (isset($deps['group'])) { + return $this->raiseError('Cannot safely convert "' . $packagexml . + '", contains dependency groups. Using a PEAR_PackageFileManager-based script ' . + 'or the convert command is an option'); + } + if (isset($deps['required']['subpackage']) || + isset($deps['optional']['subpackage'])) { + return $this->raiseError('Cannot safely convert "' . $packagexml . + '", contains subpackage dependencies. Using a PEAR_PackageFileManager-based '. + 'script is an option'); + } + if (isset($deps['required']['os'])) { + return $this->raiseError('Cannot safely convert "' . $packagexml . + '", contains os dependencies. Using a PEAR_PackageFileManager-based '. + 'script is an option'); + } + if (isset($deps['required']['arch'])) { + return $this->raiseError('Cannot safely convert "' . $packagexml . + '", contains arch dependencies. Using a PEAR_PackageFileManager-based '. + 'script is an option'); + } + $pf->setPackage($pf2->getPackage()); + $pf->setSummary($pf2->getSummary()); + $pf->setDescription($pf2->getDescription()); + foreach ($pf2->getMaintainers() as $maintainer) { + $pf->addMaintainer($maintainer['role'], $maintainer['handle'], + $maintainer['name'], $maintainer['email']); + } + $pf->setVersion($pf2->getVersion()); + $pf->setDate($pf2->getDate()); + $pf->setLicense($pf2->getLicense()); + $pf->setState($pf2->getState()); + $pf->setNotes($pf2->getNotes()); + $pf->addPhpDep($deps['required']['php']['min'], 'ge'); + if (isset($deps['required']['php']['max'])) { + $pf->addPhpDep($deps['required']['php']['max'], 'le'); + } + if (isset($deps['required']['package'])) { + if (!isset($deps['required']['package'][0])) { + $deps['required']['package'] = array($deps['required']['package']); + } + foreach ($deps['required']['package'] as $dep) { + if (!isset($dep['channel'])) { + return $this->raiseError('Cannot safely convert "' . $packagexml . '"' . + ' contains uri-based dependency on a package. Using a ' . + 'PEAR_PackageFileManager-based script is an option'); + } + if ($dep['channel'] != 'pear.php.net' && $dep['channel'] != 'pecl.php.net') { + return $this->raiseError('Cannot safely convert "' . $packagexml . '"' . + ' contains dependency on a non-standard channel package. Using a ' . + 'PEAR_PackageFileManager-based script is an option'); + } + if (isset($dep['conflicts'])) { + return $this->raiseError('Cannot safely convert "' . $packagexml . '"' . + ' contains conflicts dependency. Using a ' . + 'PEAR_PackageFileManager-based script is an option'); + } + if (isset($dep['exclude'])) { + $this->ui->outputData('WARNING: exclude tags are ignored in conversion'); + } + if (isset($dep['min'])) { + $pf->addPackageDep($dep['name'], $dep['min'], 'ge'); + } + if (isset($dep['max'])) { + $pf->addPackageDep($dep['name'], $dep['max'], 'le'); + } + } + } + if (isset($deps['required']['extension'])) { + if (!isset($deps['required']['extension'][0])) { + $deps['required']['extension'] = array($deps['required']['extension']); + } + foreach ($deps['required']['extension'] as $dep) { + if (isset($dep['conflicts'])) { + return $this->raiseError('Cannot safely convert "' . $packagexml . '"' . + ' contains conflicts dependency. Using a ' . + 'PEAR_PackageFileManager-based script is an option'); + } + if (isset($dep['exclude'])) { + $this->ui->outputData('WARNING: exclude tags are ignored in conversion'); + } + if (isset($dep['min'])) { + $pf->addExtensionDep($dep['name'], $dep['min'], 'ge'); + } + if (isset($dep['max'])) { + $pf->addExtensionDep($dep['name'], $dep['max'], 'le'); + } + } + } + if (isset($deps['optional']['package'])) { + if (!isset($deps['optional']['package'][0])) { + $deps['optional']['package'] = array($deps['optional']['package']); + } + foreach ($deps['optional']['package'] as $dep) { + if (!isset($dep['channel'])) { + return $this->raiseError('Cannot safely convert "' . $packagexml . '"' . + ' contains uri-based dependency on a package. Using a ' . + 'PEAR_PackageFileManager-based script is an option'); + } + if ($dep['channel'] != 'pear.php.net' && $dep['channel'] != 'pecl.php.net') { + return $this->raiseError('Cannot safely convert "' . $packagexml . '"' . + ' contains dependency on a non-standard channel package. Using a ' . + 'PEAR_PackageFileManager-based script is an option'); + } + if (isset($dep['exclude'])) { + $this->ui->outputData('WARNING: exclude tags are ignored in conversion'); + } + if (isset($dep['min'])) { + $pf->addPackageDep($dep['name'], $dep['min'], 'ge', 'yes'); + } + if (isset($dep['max'])) { + $pf->addPackageDep($dep['name'], $dep['max'], 'le', 'yes'); + } + } + } + if (isset($deps['optional']['extension'])) { + if (!isset($deps['optional']['extension'][0])) { + $deps['optional']['extension'] = array($deps['optional']['extension']); + } + foreach ($deps['optional']['extension'] as $dep) { + if (isset($dep['exclude'])) { + $this->ui->outputData('WARNING: exclude tags are ignored in conversion'); + } + if (isset($dep['min'])) { + $pf->addExtensionDep($dep['name'], $dep['min'], 'ge', 'yes'); + } + if (isset($dep['max'])) { + $pf->addExtensionDep($dep['name'], $dep['max'], 'le', 'yes'); + } + } + } + $contents = $pf2->getContents(); + $release = $pf2->getReleases(); + if (isset($releases[0])) { + return $this->raiseError('Cannot safely process "' . $packagexml . '" contains ' + . 'multiple extsrcrelease/zendextsrcrelease tags. Using a PEAR_PackageFileManager-based script ' . + 'or the convert command is an option'); + } + if ($configoptions = $pf2->getConfigureOptions()) { + foreach ($configoptions as $option) { + $pf->addConfigureOption($option['name'], $option['prompt'], + isset($option['default']) ? $option['default'] : false); + } + } + if (isset($release['filelist']['ignore'])) { + return $this->raiseError('Cannot safely process "' . $packagexml . '" contains ' + . 'ignore tags. Using a PEAR_PackageFileManager-based script or the convert' . + ' command is an option'); + } + if (isset($release['filelist']['install']) && + !isset($release['filelist']['install'][0])) { + $release['filelist']['install'] = array($release['filelist']['install']); + } + if (isset($contents['dir']['attribs']['baseinstalldir'])) { + $baseinstalldir = $contents['dir']['attribs']['baseinstalldir']; + } else { + $baseinstalldir = false; + } + if (!isset($contents['dir']['file'][0])) { + $contents['dir']['file'] = array($contents['dir']['file']); + } + foreach ($contents['dir']['file'] as $file) { + if ($baseinstalldir && !isset($file['attribs']['baseinstalldir'])) { + $file['attribs']['baseinstalldir'] = $baseinstalldir; + } + $processFile = $file; + unset($processFile['attribs']); + if (count($processFile)) { + foreach ($processFile as $name => $task) { + if ($name != $pf2->getTasksNs() . ':replace') { + return $this->raiseError('Cannot safely process "' . $packagexml . + '" contains tasks other than replace. Using a ' . + 'PEAR_PackageFileManager-based script is an option.'); + } + $file['attribs']['replace'][] = $task; + } + } + if (!in_array($file['attribs']['role'], PEAR_Common::getFileRoles())) { + return $this->raiseError('Cannot safely convert "' . $packagexml . + '", contains custom roles. Using a PEAR_PackageFileManager-based script ' . + 'or the convert command is an option'); + } + if (isset($release['filelist']['install'])) { + foreach ($release['filelist']['install'] as $installas) { + if ($installas['attribs']['name'] == $file['attribs']['name']) { + $file['attribs']['install-as'] = $installas['attribs']['as']; + } + } + } + $pf->addFile('/', $file['attribs']['name'], $file['attribs']); + } + if ($pf2->getChangeLog()) { + $this->ui->outputData('WARNING: changelog is not translated to package.xml ' . + '1.0, use PEAR_PackageFileManager-based script if you need changelog-' . + 'translation for package.xml 1.0'); + } + $gen = &$pf->getDefaultGenerator(); + $gen->toPackageFile('.'); + } +} + +?> diff --git a/src/lib/pear/PEAR/PEAR/Command/Pickle.xml b/src/lib/pear/PEAR/PEAR/Command/Pickle.xml new file mode 100644 index 0000000..04c85bc --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Command/Pickle.xml @@ -0,0 +1,40 @@ + + + Build PECL Package + doPackage + pi + + + Z + Do not gzip the package file + + + n + Print the name of the packaged file. + + + [descfile] [descfile2] +Creates a PECL package from its description file (usually called +package.xml). If a second packagefile is passed in, then +the packager will check to make sure that one is a package.xml +version 1.0, and the other is a package.xml version 2.0. The +package.xml version 1.0 will be saved as "package.xml" in the archive, +and the other as "package2.xml" in the archive" + +If no second file is passed in, and [descfile] is a package.xml 2.0, +an automatic conversion will be made to a package.xml 1.0. Note that +only simple package.xml 2.0 will be converted. package.xml 2.0 with: + + - dependency types other than required/optional PECL package/ext/php/pearinstaller + - more than one extsrcrelease/zendextsrcrelease + - zendextbinrelease, extbinrelease, phprelease, or bundle release type + - dependency groups + - ignore tags in release filelist + - tasks other than replace + - custom roles + +will cause pickle to fail, and output an error message. If your package2.xml +uses any of these features, you are best off using PEAR_PackageFileManager to +generate both package.xml. + + \ No newline at end of file diff --git a/src/lib/pear/PEAR/PEAR/Command/Registry.php b/src/lib/pear/PEAR/PEAR/Command/Registry.php new file mode 100644 index 0000000..d2f1dd1 --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Command/Registry.php @@ -0,0 +1,1070 @@ + + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: Registry.php,v 1.81 2008/01/03 20:26:36 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 0.1 + */ + +/** + * base class + */ +require_once 'PEAR/Command/Common.php'; + +/** + * PEAR commands for registry manipulation + * + * @category pear + * @package PEAR + * @author Stig Bakken + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 0.1 + */ +class PEAR_Command_Registry extends PEAR_Command_Common +{ + // {{{ properties + + var $commands = array( + 'list' => array( + 'summary' => 'List Installed Packages In The Default Channel', + 'function' => 'doList', + 'shortcut' => 'l', + 'options' => array( + 'channel' => array( + 'shortopt' => 'c', + 'doc' => 'list installed packages from this channel', + 'arg' => 'CHAN', + ), + 'allchannels' => array( + 'shortopt' => 'a', + 'doc' => 'list installed packages from all channels', + ), + 'channelinfo' => array( + 'shortopt' => 'i', + 'doc' => 'output fully channel-aware data, even on failure', + ), + ), + 'doc' => ' +If invoked without parameters, this command lists the PEAR packages +installed in your php_dir ({config php_dir}). With a parameter, it +lists the files in a package. +', + ), + 'list-files' => array( + 'summary' => 'List Files In Installed Package', + 'function' => 'doFileList', + 'shortcut' => 'fl', + 'options' => array(), + 'doc' => ' +List the files in an installed package. +' + ), + 'shell-test' => array( + 'summary' => 'Shell Script Test', + 'function' => 'doShellTest', + 'shortcut' => 'st', + 'options' => array(), + 'doc' => ' [[relation] version] +Tests if a package is installed in the system. Will exit(1) if it is not. + The version comparison operator. One of: + <, lt, <=, le, >, gt, >=, ge, ==, =, eq, !=, <>, ne + The version to compare with +'), + 'info' => array( + 'summary' => 'Display information about a package', + 'function' => 'doInfo', + 'shortcut' => 'in', + 'options' => array(), + 'doc' => ' +Displays information about a package. The package argument may be a +local package file, an URL to a package file, or the name of an +installed package.' + ) + ); + + // }}} + // {{{ constructor + + /** + * PEAR_Command_Registry constructor. + * + * @access public + */ + function PEAR_Command_Registry(&$ui, &$config) + { + parent::PEAR_Command_Common($ui, $config); + } + + // }}} + + // {{{ doList() + + function _sortinfo($a, $b) + { + $apackage = isset($a['package']) ? $a['package'] : $a['name']; + $bpackage = isset($b['package']) ? $b['package'] : $b['name']; + return strcmp($apackage, $bpackage); + } + + function doList($command, $options, $params) + { + $reg = &$this->config->getRegistry(); + $channelinfo = isset($options['channelinfo']); + if (isset($options['allchannels']) && !$channelinfo) { + return $this->doListAll($command, array(), $params); + } + if (isset($options['allchannels']) && $channelinfo) { + // allchannels with $channelinfo + unset($options['allchannels']); + $channels = $reg->getChannels(); + $errors = array(); + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + foreach ($channels as $channel) { + $options['channel'] = $channel->getName(); + $ret = $this->doList($command, $options, $params); + + if (PEAR::isError($ret)) { + $errors[] = $ret; + } + } + PEAR::staticPopErrorHandling(); + if (count($errors)) { + // for now, only give first error + return PEAR::raiseError($errors[0]); + } + return true; + } + + if (count($params) == 1) { + return $this->doFileList($command, $options, $params); + } + if (isset($options['channel'])) { + if ($reg->channelExists($options['channel'])) { + $channel = $reg->channelName($options['channel']); + } else { + return $this->raiseError('Channel "' . $options['channel'] .'" does not exist'); + } + } else { + $channel = $this->config->get('default_channel'); + } + $installed = $reg->packageInfo(null, null, $channel); + usort($installed, array(&$this, '_sortinfo')); + + $data = array( + 'caption' => 'Installed packages, channel ' . + $channel . ':', + 'border' => true, + 'headline' => array('Package', 'Version', 'State'), + 'channel' => $channel, + ); + if ($channelinfo) { + $data['headline'] = array('Channel', 'Package', 'Version', 'State'); + } + + if (count($installed) && !isset($data['data'])) { + $data['data'] = array(); + } + + foreach ($installed as $package) { + $pobj = $reg->getPackage(isset($package['package']) ? + $package['package'] : $package['name'], $channel); + if ($channelinfo) { + $packageinfo = array($pobj->getChannel(), $pobj->getPackage(), $pobj->getVersion(), + $pobj->getState() ? $pobj->getState() : null); + } else { + $packageinfo = array($pobj->getPackage(), $pobj->getVersion(), + $pobj->getState() ? $pobj->getState() : null); + } + $data['data'][] = $packageinfo; + } + if (count($installed) == 0) { + if (!$channelinfo) { + $data = '(no packages installed from channel ' . $channel . ')'; + } else { + $data = array( + 'caption' => 'Installed packages, channel ' . + $channel . ':', + 'border' => true, + 'channel' => $channel, + 'data' => '(no packages installed)', + ); + } + } + $this->ui->outputData($data, $command); + return true; + } + + function doListAll($command, $options, $params) + { + // This duplicate code is deprecated over + // list --channelinfo, which gives identical + // output for list and list --allchannels. + $reg = &$this->config->getRegistry(); + $installed = $reg->packageInfo(null, null, null); + foreach ($installed as $channel => $packages) { + usort($packages, array($this, '_sortinfo')); + $data = array( + 'caption' => 'Installed packages, channel ' . $channel . ':', + 'border' => true, + 'headline' => array('Package', 'Version', 'State'), + 'channel' => $channel + ); + foreach ($packages as $package) { + $pobj = $reg->getPackage(isset($package['package']) ? + $package['package'] : $package['name'], $channel); + $data['data'][] = array($pobj->getPackage(), $pobj->getVersion(), + $pobj->getState() ? $pobj->getState() : null); + } + if (count($packages)==0) { + $data = array( + 'caption' => 'Installed packages, channel ' . $channel . ':', + 'border' => true, + 'data' => array(array('(no packages installed)')), + 'channel' => $channel + ); + } + $this->ui->outputData($data, $command); + } + return true; + } + + function doFileList($command, $options, $params) + { + if (count($params) != 1) { + return $this->raiseError('list-files expects 1 parameter'); + } + $reg = &$this->config->getRegistry(); + $fp = false; + if (!is_dir($params[0]) && (file_exists($params[0]) || $fp = @fopen($params[0], + 'r'))) { + if ($fp) { + fclose($fp); + } + if (!class_exists('PEAR_PackageFile')) { + require_once 'PEAR/PackageFile.php'; + } + $pkg = &new PEAR_PackageFile($this->config, $this->_debug); + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + $info = &$pkg->fromAnyFile($params[0], PEAR_VALIDATE_NORMAL); + PEAR::staticPopErrorHandling(); + $headings = array('Package File', 'Install Path'); + $installed = false; + } else { + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + $parsed = $reg->parsePackageName($params[0], $this->config->get('default_channel')); + PEAR::staticPopErrorHandling(); + if (PEAR::isError($parsed)) { + return $this->raiseError($parsed); + } + $info = &$reg->getPackage($parsed['package'], $parsed['channel']); + $headings = array('Type', 'Install Path'); + $installed = true; + } + if (PEAR::isError($info)) { + return $this->raiseError($info); + } + if ($info === null) { + return $this->raiseError("`$params[0]' not installed"); + } + $list = ($info->getPackagexmlVersion() == '1.0' || $installed) ? + $info->getFilelist() : $info->getContents(); + if ($installed) { + $caption = 'Installed Files For ' . $params[0]; + } else { + $caption = 'Contents of ' . basename($params[0]); + } + $data = array( + 'caption' => $caption, + 'border' => true, + 'headline' => $headings); + if ($info->getPackagexmlVersion() == '1.0' || $installed) { + foreach ($list as $file => $att) { + if ($installed) { + if (empty($att['installed_as'])) { + continue; + } + $data['data'][] = array($att['role'], $att['installed_as']); + } else { + if (isset($att['baseinstalldir']) && !in_array($att['role'], + array('test', 'data', 'doc'))) { + $dest = $att['baseinstalldir'] . DIRECTORY_SEPARATOR . + $file; + } else { + $dest = $file; + } + switch ($att['role']) { + case 'test': + case 'data': + case 'doc': + $role = $att['role']; + if ($role == 'test') { + $role .= 's'; + } + $dest = $this->config->get($role . '_dir') . DIRECTORY_SEPARATOR . + $info->getPackage() . DIRECTORY_SEPARATOR . $dest; + break; + case 'php': + default: + $dest = $this->config->get('php_dir') . DIRECTORY_SEPARATOR . + $dest; + } + $ds2 = DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR; + $dest = preg_replace(array('!\\\\+!', '!/!', "!$ds2+!"), + array(DIRECTORY_SEPARATOR, + DIRECTORY_SEPARATOR, + DIRECTORY_SEPARATOR), + $dest); + $file = preg_replace('!/+!', '/', $file); + $data['data'][] = array($file, $dest); + } + } + } else { // package.xml 2.0, not installed + if (!isset($list['dir']['file'][0])) { + $list['dir']['file'] = array($list['dir']['file']); + } + foreach ($list['dir']['file'] as $att) { + $att = $att['attribs']; + $file = $att['name']; + $role = &PEAR_Installer_Role::factory($info, $att['role'], $this->config); + $role->setup($this, $info, $att, $file); + if (!$role->isInstallable()) { + $dest = '(not installable)'; + } else { + $dest = $role->processInstallation($info, $att, $file, ''); + if (PEAR::isError($dest)) { + $dest = '(Unknown role "' . $att['role'] . ')'; + } else { + list(,, $dest) = $dest; + } + } + $data['data'][] = array($file, $dest); + } + } + $this->ui->outputData($data, $command); + return true; + } + + // }}} + // {{{ doShellTest() + + function doShellTest($command, $options, $params) + { + if (count($params) < 1) { + return PEAR::raiseError('ERROR, usage: pear shell-test packagename [[relation] version]'); + } + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + $reg = &$this->config->getRegistry(); + $info = $reg->parsePackageName($params[0], $this->config->get('default_channel')); + if (PEAR::isError($info)) { + exit(1); // invalid package name + } + $package = $info['package']; + $channel = $info['channel']; + // "pear shell-test Foo" + if (!$reg->packageExists($package, $channel)) { + if ($channel == 'pecl.php.net') { + if ($reg->packageExists($package, 'pear.php.net')) { + $channel = 'pear.php.net'; // magically change channels for extensions + } + } + } + if (sizeof($params) == 1) { + if (!$reg->packageExists($package, $channel)) { + exit(1); + } + // "pear shell-test Foo 1.0" + } elseif (sizeof($params) == 2) { + $v = $reg->packageInfo($package, 'version', $channel); + if (!$v || !version_compare("$v", "{$params[1]}", "ge")) { + exit(1); + } + // "pear shell-test Foo ge 1.0" + } elseif (sizeof($params) == 3) { + $v = $reg->packageInfo($package, 'version', $channel); + if (!$v || !version_compare("$v", "{$params[2]}", $params[1])) { + exit(1); + } + } else { + PEAR::staticPopErrorHandling(); + $this->raiseError("$command: expects 1 to 3 parameters"); + exit(1); + } + } + + // }}} + // {{{ doInfo + + function doInfo($command, $options, $params) + { + if (count($params) != 1) { + return $this->raiseError('pear info expects 1 parameter'); + } + $info = $fp = false; + $reg = &$this->config->getRegistry(); + if ((file_exists($params[0]) && is_file($params[0]) && !is_dir($params[0])) || $fp = @fopen($params[0], 'r')) { + if ($fp) { + fclose($fp); + } + if (!class_exists('PEAR_PackageFile')) { + require_once 'PEAR/PackageFile.php'; + } + $pkg = &new PEAR_PackageFile($this->config, $this->_debug); + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + $obj = &$pkg->fromAnyFile($params[0], PEAR_VALIDATE_NORMAL); + PEAR::staticPopErrorHandling(); + if (PEAR::isError($obj)) { + $uinfo = $obj->getUserInfo(); + if (is_array($uinfo)) { + foreach ($uinfo as $message) { + if (is_array($message)) { + $message = $message['message']; + } + $this->ui->outputData($message); + } + } + return $this->raiseError($obj); + } + if ($obj->getPackagexmlVersion() == '1.0') { + $info = $obj->toArray(); + } else { + return $this->_doInfo2($command, $options, $params, $obj, false); + } + } else { + $parsed = $reg->parsePackageName($params[0], $this->config->get('default_channel')); + if (PEAR::isError($parsed)) { + return $this->raiseError($parsed); + } + $package = $parsed['package']; + $channel = $parsed['channel']; + $info = $reg->packageInfo($package, null, $channel); + if (isset($info['old'])) { + $obj = $reg->getPackage($package, $channel); + return $this->_doInfo2($command, $options, $params, $obj, true); + } + } + if (PEAR::isError($info)) { + return $info; + } + if (empty($info)) { + $this->raiseError("No information found for `$params[0]'"); + return; + } + unset($info['filelist']); + unset($info['dirtree']); + unset($info['changelog']); + if (isset($info['xsdversion'])) { + $info['package.xml version'] = $info['xsdversion']; + unset($info['xsdversion']); + } + if (isset($info['packagerversion'])) { + $info['packaged with PEAR version'] = $info['packagerversion']; + unset($info['packagerversion']); + } + $keys = array_keys($info); + $longtext = array('description', 'summary'); + foreach ($keys as $key) { + if (is_array($info[$key])) { + switch ($key) { + case 'maintainers': { + $i = 0; + $mstr = ''; + foreach ($info[$key] as $m) { + if ($i++ > 0) { + $mstr .= "\n"; + } + $mstr .= $m['name'] . " <"; + if (isset($m['email'])) { + $mstr .= $m['email']; + } else { + $mstr .= $m['handle'] . '@php.net'; + } + $mstr .= "> ($m[role])"; + } + $info[$key] = $mstr; + break; + } + case 'release_deps': { + $i = 0; + $dstr = ''; + foreach ($info[$key] as $d) { + if (isset($this->_deps_rel_trans[$d['rel']])) { + $rel = $this->_deps_rel_trans[$d['rel']]; + } else { + $rel = $d['rel']; + } + if (isset($this->_deps_type_trans[$d['type']])) { + $type = ucfirst($this->_deps_type_trans[$d['type']]); + } else { + $type = $d['type']; + } + if (isset($d['name'])) { + $name = $d['name'] . ' '; + } else { + $name = ''; + } + if (isset($d['version'])) { + $version = $d['version'] . ' '; + } else { + $version = ''; + } + if (isset($d['optional']) && $d['optional'] == 'yes') { + $optional = ' (optional)'; + } else { + $optional = ''; + } + $dstr .= "$type $name$rel $version$optional\n"; + } + $info[$key] = $dstr; + break; + } + case 'provides' : { + $debug = $this->config->get('verbose'); + if ($debug < 2) { + $pstr = 'Classes: '; + } else { + $pstr = ''; + } + $i = 0; + foreach ($info[$key] as $p) { + if ($debug < 2 && $p['type'] != "class") { + continue; + } + // Only print classes when verbosity mode is < 2 + if ($debug < 2) { + if ($i++ > 0) { + $pstr .= ", "; + } + $pstr .= $p['name']; + } else { + if ($i++ > 0) { + $pstr .= "\n"; + } + $pstr .= ucfirst($p['type']) . " " . $p['name']; + if (isset($p['explicit']) && $p['explicit'] == 1) { + $pstr .= " (explicit)"; + } + } + } + $info[$key] = $pstr; + break; + } + case 'configure_options' : { + foreach ($info[$key] as $i => $p) { + $info[$key][$i] = array_map(null, array_keys($p), array_values($p)); + $info[$key][$i] = array_map(create_function('$a', + 'return join(" = ",$a);'), $info[$key][$i]); + $info[$key][$i] = implode(', ', $info[$key][$i]); + } + $info[$key] = implode("\n", $info[$key]); + break; + } + default: { + $info[$key] = implode(", ", $info[$key]); + break; + } + } + } + if ($key == '_lastmodified') { + $hdate = date('Y-m-d', $info[$key]); + unset($info[$key]); + $info['Last Modified'] = $hdate; + } elseif ($key == '_lastversion') { + $info['Previous Installed Version'] = $info[$key] ? $info[$key] : '- None -'; + unset($info[$key]); + } else { + $info[$key] = trim($info[$key]); + if (in_array($key, $longtext)) { + $info[$key] = preg_replace('/ +/', ' ', $info[$key]); + } + } + } + $caption = 'About ' . $info['package'] . '-' . $info['version']; + $data = array( + 'caption' => $caption, + 'border' => true); + foreach ($info as $key => $value) { + $key = ucwords(trim(str_replace('_', ' ', $key))); + $data['data'][] = array($key, $value); + } + $data['raw'] = $info; + + $this->ui->outputData($data, 'package-info'); + } + + // }}} + + /** + * @access private + */ + function _doInfo2($command, $options, $params, &$obj, $installed) + { + $reg = &$this->config->getRegistry(); + $caption = 'About ' . $obj->getChannel() . '/' .$obj->getPackage() . '-' . + $obj->getVersion(); + $data = array( + 'caption' => $caption, + 'border' => true); + switch ($obj->getPackageType()) { + case 'php' : + $release = 'PEAR-style PHP-based Package'; + break; + case 'extsrc' : + $release = 'PECL-style PHP extension (source code)'; + break; + case 'zendextsrc' : + $release = 'PECL-style Zend extension (source code)'; + break; + case 'extbin' : + $release = 'PECL-style PHP extension (binary)'; + break; + case 'zendextbin' : + $release = 'PECL-style Zend extension (binary)'; + break; + case 'bundle' : + $release = 'Package bundle (collection of packages)'; + break; + } + $extends = $obj->getExtends(); + $extends = $extends ? + $obj->getPackage() . ' (extends ' . $extends . ')' : $obj->getPackage(); + if ($src = $obj->getSourcePackage()) { + $extends .= ' (source package ' . $src['channel'] . '/' . $src['package'] . ')'; + } + $info = array( + 'Release Type' => $release, + 'Name' => $extends, + 'Channel' => $obj->getChannel(), + 'Summary' => preg_replace('/ +/', ' ', $obj->getSummary()), + 'Description' => preg_replace('/ +/', ' ', $obj->getDescription()), + ); + $info['Maintainers'] = ''; + foreach (array('lead', 'developer', 'contributor', 'helper') as $role) { + $leads = $obj->{"get{$role}s"}(); + if (!$leads) { + continue; + } + if (isset($leads['active'])) { + $leads = array($leads); + } + foreach ($leads as $lead) { + if (!empty($info['Maintainers'])) { + $info['Maintainers'] .= "\n"; + } + $info['Maintainers'] .= $lead['name'] . ' <'; + $info['Maintainers'] .= $lead['email'] . "> ($role)"; + } + } + $info['Release Date'] = $obj->getDate(); + if ($time = $obj->getTime()) { + $info['Release Date'] .= ' ' . $time; + } + $info['Release Version'] = $obj->getVersion() . ' (' . $obj->getState() . ')'; + $info['API Version'] = $obj->getVersion('api') . ' (' . $obj->getState('api') . ')'; + $info['License'] = $obj->getLicense(); + $uri = $obj->getLicenseLocation(); + if ($uri) { + if (isset($uri['uri'])) { + $info['License'] .= ' (' . $uri['uri'] . ')'; + } else { + $extra = $obj->getInstalledLocation($info['filesource']); + if ($extra) { + $info['License'] .= ' (' . $uri['filesource'] . ')'; + } + } + } + $info['Release Notes'] = $obj->getNotes(); + if ($compat = $obj->getCompatible()) { + if (!isset($compat[0])) { + $compat = array($compat); + } + $info['Compatible with'] = ''; + foreach ($compat as $package) { + $info['Compatible with'] .= $package['channel'] . '/' . $package['name'] . + "\nVersions >= " . $package['min'] . ', <= ' . $package['max']; + if (isset($package['exclude'])) { + if (is_array($package['exclude'])) { + $package['exclude'] = implode(', ', $package['exclude']); + } + if (!isset($info['Not Compatible with'])) { + $info['Not Compatible with'] = ''; + } else { + $info['Not Compatible with'] .= "\n"; + } + $info['Not Compatible with'] .= $package['channel'] . '/' . + $package['name'] . "\nVersions " . $package['exclude']; + } + } + } + $usesrole = $obj->getUsesrole(); + if ($usesrole) { + if (!isset($usesrole[0])) { + $usesrole = array($usesrole); + } + foreach ($usesrole as $roledata) { + if (isset($info['Uses Custom Roles'])) { + $info['Uses Custom Roles'] .= "\n"; + } else { + $info['Uses Custom Roles'] = ''; + } + if (isset($roledata['package'])) { + $rolepackage = $reg->parsedPackageNameToString($roledata, true); + } else { + $rolepackage = $roledata['uri']; + } + $info['Uses Custom Roles'] .= $roledata['role'] . ' (' . $rolepackage . ')'; + } + } + $usestask = $obj->getUsestask(); + if ($usestask) { + if (!isset($usestask[0])) { + $usestask = array($usestask); + } + foreach ($usestask as $taskdata) { + if (isset($info['Uses Custom Tasks'])) { + $info['Uses Custom Tasks'] .= "\n"; + } else { + $info['Uses Custom Tasks'] = ''; + } + if (isset($taskdata['package'])) { + $taskpackage = $reg->parsedPackageNameToString($taskdata, true); + } else { + $taskpackage = $taskdata['uri']; + } + $info['Uses Custom Tasks'] .= $taskdata['task'] . ' (' . $taskpackage . ')'; + } + } + $deps = $obj->getDependencies(); + $info['Required Dependencies'] = 'PHP version ' . $deps['required']['php']['min']; + if (isset($deps['required']['php']['max'])) { + $info['Required Dependencies'] .= '-' . $deps['required']['php']['max'] . "\n"; + } else { + $info['Required Dependencies'] .= "\n"; + } + if (isset($deps['required']['php']['exclude'])) { + if (!isset($info['Not Compatible with'])) { + $info['Not Compatible with'] = ''; + } else { + $info['Not Compatible with'] .= "\n"; + } + if (is_array($deps['required']['php']['exclude'])) { + $deps['required']['php']['exclude'] = + implode(', ', $deps['required']['php']['exclude']); + } + $info['Not Compatible with'] .= "PHP versions\n " . + $deps['required']['php']['exclude']; + } + $info['Required Dependencies'] .= 'PEAR installer version'; + if (isset($deps['required']['pearinstaller']['max'])) { + $info['Required Dependencies'] .= 's ' . + $deps['required']['pearinstaller']['min'] . '-' . + $deps['required']['pearinstaller']['max']; + } else { + $info['Required Dependencies'] .= ' ' . + $deps['required']['pearinstaller']['min'] . ' or newer'; + } + if (isset($deps['required']['pearinstaller']['exclude'])) { + if (!isset($info['Not Compatible with'])) { + $info['Not Compatible with'] = ''; + } else { + $info['Not Compatible with'] .= "\n"; + } + if (is_array($deps['required']['pearinstaller']['exclude'])) { + $deps['required']['pearinstaller']['exclude'] = + implode(', ', $deps['required']['pearinstaller']['exclude']); + } + $info['Not Compatible with'] .= "PEAR installer\n Versions " . + $deps['required']['pearinstaller']['exclude']; + } + foreach (array('Package', 'Extension') as $type) { + $index = strtolower($type); + if (isset($deps['required'][$index])) { + if (isset($deps['required'][$index]['name'])) { + $deps['required'][$index] = array($deps['required'][$index]); + } + foreach ($deps['required'][$index] as $package) { + if (isset($package['conflicts'])) { + $infoindex = 'Not Compatible with'; + if (!isset($info['Not Compatible with'])) { + $info['Not Compatible with'] = ''; + } else { + $info['Not Compatible with'] .= "\n"; + } + } else { + $infoindex = 'Required Dependencies'; + $info[$infoindex] .= "\n"; + } + if ($index == 'extension') { + $name = $package['name']; + } else { + if (isset($package['channel'])) { + $name = $package['channel'] . '/' . $package['name']; + } else { + $name = '__uri/' . $package['name'] . ' (static URI)'; + } + } + $info[$infoindex] .= "$type $name"; + if (isset($package['uri'])) { + $info[$infoindex] .= "\n Download URI: $package[uri]"; + continue; + } + if (isset($package['max']) && isset($package['min'])) { + $info[$infoindex] .= " \n Versions " . + $package['min'] . '-' . $package['max']; + } elseif (isset($package['min'])) { + $info[$infoindex] .= " \n Version " . + $package['min'] . ' or newer'; + } elseif (isset($package['max'])) { + $info[$infoindex] .= " \n Version " . + $package['max'] . ' or older'; + } + if (isset($package['recommended'])) { + $info[$infoindex] .= "\n Recommended version: $package[recommended]"; + } + if (isset($package['exclude'])) { + if (!isset($info['Not Compatible with'])) { + $info['Not Compatible with'] = ''; + } else { + $info['Not Compatible with'] .= "\n"; + } + if (is_array($package['exclude'])) { + $package['exclude'] = implode(', ', $package['exclude']); + } + $package['package'] = $package['name']; // for parsedPackageNameToString + if (isset($package['conflicts'])) { + $info['Not Compatible with'] .= '=> except '; + } + $info['Not Compatible with'] .= 'Package ' . + $reg->parsedPackageNameToString($package, true); + $info['Not Compatible with'] .= "\n Versions " . $package['exclude']; + } + } + } + } + if (isset($deps['required']['os'])) { + if (isset($deps['required']['os']['name'])) { + $dep['required']['os']['name'] = array($dep['required']['os']['name']); + } + foreach ($dep['required']['os'] as $os) { + if (isset($os['conflicts']) && $os['conflicts'] == 'yes') { + if (!isset($info['Not Compatible with'])) { + $info['Not Compatible with'] = ''; + } else { + $info['Not Compatible with'] .= "\n"; + } + $info['Not Compatible with'] .= "$os[name] Operating System"; + } else { + $info['Required Dependencies'] .= "\n"; + $info['Required Dependencies'] .= "$os[name] Operating System"; + } + } + } + if (isset($deps['required']['arch'])) { + if (isset($deps['required']['arch']['pattern'])) { + $dep['required']['arch']['pattern'] = array($dep['required']['os']['pattern']); + } + foreach ($dep['required']['arch'] as $os) { + if (isset($os['conflicts']) && $os['conflicts'] == 'yes') { + if (!isset($info['Not Compatible with'])) { + $info['Not Compatible with'] = ''; + } else { + $info['Not Compatible with'] .= "\n"; + } + $info['Not Compatible with'] .= "OS/Arch matching pattern '/$os[pattern]/'"; + } else { + $info['Required Dependencies'] .= "\n"; + $info['Required Dependencies'] .= "OS/Arch matching pattern '/$os[pattern]/'"; + } + } + } + if (isset($deps['optional'])) { + foreach (array('Package', 'Extension') as $type) { + $index = strtolower($type); + if (isset($deps['optional'][$index])) { + if (isset($deps['optional'][$index]['name'])) { + $deps['optional'][$index] = array($deps['optional'][$index]); + } + foreach ($deps['optional'][$index] as $package) { + if (isset($package['conflicts']) && $package['conflicts'] == 'yes') { + $infoindex = 'Not Compatible with'; + if (!isset($info['Not Compatible with'])) { + $info['Not Compatible with'] = ''; + } else { + $info['Not Compatible with'] .= "\n"; + } + } else { + $infoindex = 'Optional Dependencies'; + if (!isset($info['Optional Dependencies'])) { + $info['Optional Dependencies'] = ''; + } else { + $info['Optional Dependencies'] .= "\n"; + } + } + if ($index == 'extension') { + $name = $package['name']; + } else { + if (isset($package['channel'])) { + $name = $package['channel'] . '/' . $package['name']; + } else { + $name = '__uri/' . $package['name'] . ' (static URI)'; + } + } + $info[$infoindex] .= "$type $name"; + if (isset($package['uri'])) { + $info[$infoindex] .= "\n Download URI: $package[uri]"; + continue; + } + if ($infoindex == 'Not Compatible with') { + // conflicts is only used to say that all versions conflict + continue; + } + if (isset($package['max']) && isset($package['min'])) { + $info[$infoindex] .= " \n Versions " . + $package['min'] . '-' . $package['max']; + } elseif (isset($package['min'])) { + $info[$infoindex] .= " \n Version " . + $package['min'] . ' or newer'; + } elseif (isset($package['max'])) { + $info[$infoindex] .= " \n Version " . + $package['min'] . ' or older'; + } + if (isset($package['recommended'])) { + $info[$infoindex] .= "\n Recommended version: $package[recommended]"; + } + if (isset($package['exclude'])) { + if (!isset($info['Not Compatible with'])) { + $info['Not Compatible with'] = ''; + } else { + $info['Not Compatible with'] .= "\n"; + } + if (is_array($package['exclude'])) { + $package['exclude'] = implode(', ', $package['exclude']); + } + $info['Not Compatible with'] .= "Package $package\n Versions " . + $package['exclude']; + } + } + } + } + } + if (isset($deps['group'])) { + if (!isset($deps['group'][0])) { + $deps['group'] = array($deps['group']); + } + foreach ($deps['group'] as $group) { + $info['Dependency Group ' . $group['attribs']['name']] = $group['attribs']['hint']; + $groupindex = $group['attribs']['name'] . ' Contents'; + $info[$groupindex] = ''; + foreach (array('Package', 'Extension') as $type) { + $index = strtolower($type); + if (isset($group[$index])) { + if (isset($group[$index]['name'])) { + $group[$index] = array($group[$index]); + } + foreach ($group[$index] as $package) { + if (!empty($info[$groupindex])) { + $info[$groupindex] .= "\n"; + } + if ($index == 'extension') { + $name = $package['name']; + } else { + if (isset($package['channel'])) { + $name = $package['channel'] . '/' . $package['name']; + } else { + $name = '__uri/' . $package['name'] . ' (static URI)'; + } + } + if (isset($package['uri'])) { + if (isset($package['conflicts']) && $package['conflicts'] == 'yes') { + $info[$groupindex] .= "Not Compatible with $type $name"; + } else { + $info[$groupindex] .= "$type $name"; + } + $info[$groupindex] .= "\n Download URI: $package[uri]"; + continue; + } + if (isset($package['conflicts']) && $package['conflicts'] == 'yes') { + $info[$groupindex] .= "Not Compatible with $type $name"; + continue; + } + $info[$groupindex] .= "$type $name"; + if (isset($package['max']) && isset($package['min'])) { + $info[$groupindex] .= " \n Versions " . + $package['min'] . '-' . $package['max']; + } elseif (isset($package['min'])) { + $info[$groupindex] .= " \n Version " . + $package['min'] . ' or newer'; + } elseif (isset($package['max'])) { + $info[$groupindex] .= " \n Version " . + $package['min'] . ' or older'; + } + if (isset($package['recommended'])) { + $info[$groupindex] .= "\n Recommended version: $package[recommended]"; + } + if (isset($package['exclude'])) { + if (!isset($info['Not Compatible with'])) { + $info['Not Compatible with'] = ''; + } else { + $info[$groupindex] .= "Not Compatible with\n"; + } + if (is_array($package['exclude'])) { + $package['exclude'] = implode(', ', $package['exclude']); + } + $info[$groupindex] .= " Package $package\n Versions " . + $package['exclude']; + } + } + } + } + } + } + if ($obj->getPackageType() == 'bundle') { + $info['Bundled Packages'] = ''; + foreach ($obj->getBundledPackages() as $package) { + if (!empty($info['Bundled Packages'])) { + $info['Bundled Packages'] .= "\n"; + } + if (isset($package['uri'])) { + $info['Bundled Packages'] .= '__uri/' . $package['name']; + $info['Bundled Packages'] .= "\n (URI: $package[uri]"; + } else { + $info['Bundled Packages'] .= $package['channel'] . '/' . $package['name']; + } + } + } + $info['package.xml version'] = '2.0'; + if ($installed) { + if ($obj->getLastModified()) { + $info['Last Modified'] = date('Y-m-d H:i', $obj->getLastModified()); + } + $v = $obj->getLastInstalledVersion(); + $info['Previous Installed Version'] = $v ? $v : '- None -'; + } + foreach ($info as $key => $value) { + $data['data'][] = array($key, $value); + } + $data['raw'] = $obj->getArray(); // no validation needed + + $this->ui->outputData($data, 'package-info'); + } +} + +?> diff --git a/src/lib/pear/PEAR/PEAR/Command/Registry.xml b/src/lib/pear/PEAR/PEAR/Command/Registry.xml new file mode 100644 index 0000000..9f4e214 --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Command/Registry.xml @@ -0,0 +1,58 @@ + + + List Installed Packages In The Default Channel + doList + l + + + c + list installed packages from this channel + CHAN + + + a + list installed packages from all channels + + + i + output fully channel-aware data, even on failure + + + <package> +If invoked without parameters, this command lists the PEAR packages +installed in your php_dir ({config php_dir}). With a parameter, it +lists the files in a package. + + + + List Files In Installed Package + doFileList + fl + + <package> +List the files in an installed package. + + + + Shell Script Test + doShellTest + st + + <package> [[relation] version] +Tests if a package is installed in the system. Will exit(1) if it is not. + <relation> The version comparison operator. One of: + <, lt, <=, le, >, gt, >=, ge, ==, =, eq, !=, <>, ne + <version> The version to compare with + + + + Display information about a package + doInfo + in + + <package> +Displays information about a package. The package argument may be a +local package file, an URL to a package file, or the name of an +installed package. + + \ No newline at end of file diff --git a/src/lib/pear/PEAR/PEAR/Command/Remote.php b/src/lib/pear/PEAR/PEAR/Command/Remote.php new file mode 100644 index 0000000..c4fa908 --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Command/Remote.php @@ -0,0 +1,812 @@ + + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: Remote.php,v 1.107 2008/04/11 01:16:40 dufuz Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 0.1 + */ + +/** + * base class + */ +require_once 'PEAR/Command/Common.php'; +require_once 'PEAR/REST.php'; + +/** + * PEAR commands for remote server querying + * + * @category pear + * @package PEAR + * @author Stig Bakken + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 0.1 + */ +class PEAR_Command_Remote extends PEAR_Command_Common +{ + // {{{ command definitions + + var $commands = array( + 'remote-info' => array( + 'summary' => 'Information About Remote Packages', + 'function' => 'doRemoteInfo', + 'shortcut' => 'ri', + 'options' => array(), + 'doc' => ' +Get details on a package from the server.', + ), + 'list-upgrades' => array( + 'summary' => 'List Available Upgrades', + 'function' => 'doListUpgrades', + 'shortcut' => 'lu', + 'options' => array( + 'channelinfo' => array( + 'shortopt' => 'i', + 'doc' => 'output fully channel-aware data, even on failure', + ), + ), + 'doc' => '[preferred_state] +List releases on the server of packages you have installed where +a newer version is available with the same release state (stable etc.) +or the state passed as the second parameter.' + ), + 'remote-list' => array( + 'summary' => 'List Remote Packages', + 'function' => 'doRemoteList', + 'shortcut' => 'rl', + 'options' => array( + 'channel' => + array( + 'shortopt' => 'c', + 'doc' => 'specify a channel other than the default channel', + 'arg' => 'CHAN', + ) + ), + 'doc' => ' +Lists the packages available on the configured server along with the +latest stable release of each package.', + ), + 'search' => array( + 'summary' => 'Search remote package database', + 'function' => 'doSearch', + 'shortcut' => 'sp', + 'options' => array( + 'channel' => + array( + 'shortopt' => 'c', + 'doc' => 'specify a channel other than the default channel', + 'arg' => 'CHAN', + ), + 'allchannels' => array( + 'shortopt' => 'a', + 'doc' => 'search packages from all known channels', + ), + 'channelinfo' => array( + 'shortopt' => 'i', + 'doc' => 'output fully channel-aware data, even on failure', + ), + ), + 'doc' => '[packagename] [packageinfo] +Lists all packages which match the search parameters. The first +parameter is a fragment of a packagename. The default channel +will be used unless explicitly overridden. The second parameter +will be used to match any portion of the summary/description', + ), + 'list-all' => array( + 'summary' => 'List All Packages', + 'function' => 'doListAll', + 'shortcut' => 'la', + 'options' => array( + 'channel' => + array( + 'shortopt' => 'c', + 'doc' => 'specify a channel other than the default channel', + 'arg' => 'CHAN', + ), + 'channelinfo' => array( + 'shortopt' => 'i', + 'doc' => 'output fully channel-aware data, even on failure', + ), + ), + 'doc' => ' +Lists the packages available on the configured server along with the +latest stable release of each package.', + ), + 'download' => array( + 'summary' => 'Download Package', + 'function' => 'doDownload', + 'shortcut' => 'd', + 'options' => array( + 'nocompress' => array( + 'shortopt' => 'Z', + 'doc' => 'download an uncompressed (.tar) file', + ), + ), + 'doc' => '... +Download package tarballs. The files will be named as suggested by the +server, for example if you download the DB package and the latest stable +version of DB is 1.6.5, the downloaded file will be DB-1.6.5.tgz.', + ), + 'clear-cache' => array( + 'summary' => 'Clear Web Services Cache', + 'function' => 'doClearCache', + 'shortcut' => 'cc', + 'options' => array(), + 'doc' => ' +Clear the XML-RPC/REST cache. See also the cache_ttl configuration +parameter. +', + ), + ); + + // }}} + // {{{ constructor + + /** + * PEAR_Command_Remote constructor. + * + * @access public + */ + function PEAR_Command_Remote(&$ui, &$config) + { + parent::PEAR_Command_Common($ui, $config); + } + + // }}} + + function _checkChannelForStatus($channel, $chan) + { + if (PEAR::isError($chan)) { + $this->raiseError($chan); + } + if (!is_a($chan, 'PEAR_ChannelFile')) { + return $this->raiseError('Internal corruption error: invalid channel "' . + $channel . '"'); + } + $rest = new PEAR_REST($this->config); + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + $mirror = $this->config->get('preferred_mirror', null, + $channel); + $a = $rest->downloadHttp('http://' . $channel . + '/channel.xml', $chan->lastModified()); + PEAR::staticPopErrorHandling(); + if (!PEAR::isError($a) && $a) { + $this->ui->outputData('WARNING: channel "' . $channel . '" has ' . + 'updated its protocols, use "channel-update ' . $channel . + '" to update'); + } + } + + // {{{ doRemoteInfo() + + function doRemoteInfo($command, $options, $params) + { + if (sizeof($params) != 1) { + return $this->raiseError("$command expects one param: the remote package name"); + } + $savechannel = $channel = $this->config->get('default_channel'); + $reg = &$this->config->getRegistry(); + $package = $params[0]; + $parsed = $reg->parsePackageName($package, $channel); + if (PEAR::isError($parsed)) { + return $this->raiseError('Invalid package name "' . $package . '"'); + } + + $channel = $parsed['channel']; + $this->config->set('default_channel', $channel); + $chan = $reg->getChannel($channel); + if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) { + return $e; + } + if ($chan->supportsREST($this->config->get('preferred_mirror')) && + $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) { + $rest = &$this->config->getREST('1.0', array()); + $info = $rest->packageInfo($base, $parsed['package'], $channel); + } else { + $r = &$this->config->getRemote(); + $info = $r->call('package.info', $parsed['package']); + } + if (PEAR::isError($info)) { + $this->config->set('default_channel', $savechannel); + return $this->raiseError($info); + } + if (!isset($info['name'])) { + return $this->raiseError('No remote package "' . $package . '" was found'); + } + + $installed = $reg->packageInfo($info['name'], null, $channel); + $info['installed'] = $installed['version'] ? $installed['version'] : '- no -'; + if (is_array($info['installed'])) { + $info['installed'] = $info['installed']['release']; + } + + $this->ui->outputData($info, $command); + $this->config->set('default_channel', $savechannel); + + return true; + } + + // }}} + // {{{ doRemoteList() + + function doRemoteList($command, $options, $params) + { + $savechannel = $channel = $this->config->get('default_channel'); + $reg = &$this->config->getRegistry(); + if (isset($options['channel'])) { + $channel = $options['channel']; + if ($reg->channelExists($channel)) { + $this->config->set('default_channel', $channel); + } else { + return $this->raiseError('Channel "' . $channel . '" does not exist'); + } + } + $chan = $reg->getChannel($channel); + if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) { + return $e; + } + $list_options = false; + if ($this->config->get('preferred_state') == 'stable') { + $list_options = true; + } + if ($chan->supportsREST($this->config->get('preferred_mirror')) && + $base = $chan->getBaseURL('REST1.1', $this->config->get('preferred_mirror'))) { + // use faster list-all if available + $rest = &$this->config->getREST('1.1', array()); + $available = $rest->listAll($base, $list_options, true, false, false, $chan->getName()); + } elseif ($chan->supportsREST($this->config->get('preferred_mirror')) && + $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) { + $rest = &$this->config->getREST('1.0', array()); + $available = $rest->listAll($base, $list_options, true, false, false, $chan->getName()); + } else { + $r = &$this->config->getRemote(); + if ($channel == 'pear.php.net') { + // hack because of poor pearweb design + $available = $r->call('package.listAll', true, $list_options, false); + } else { + $available = $r->call('package.listAll', true, $list_options); + } + } + if (PEAR::isError($available)) { + $this->config->set('default_channel', $savechannel); + return $this->raiseError($available); + } + $i = $j = 0; + $data = array( + 'caption' => 'Channel ' . $channel . ' Available packages:', + 'border' => true, + 'headline' => array('Package', 'Version'), + 'channel' => $channel + ); + if (count($available)==0) { + $data = '(no packages available yet)'; + } else { + foreach ($available as $name => $info) { + $data['data'][] = array($name, (isset($info['stable']) && $info['stable']) + ? $info['stable'] : '-n/a-'); + } + } + $this->ui->outputData($data, $command); + $this->config->set('default_channel', $savechannel); + return true; + } + + // }}} + // {{{ doListAll() + + function doListAll($command, $options, $params) + { + $savechannel = $channel = $this->config->get('default_channel'); + $reg = &$this->config->getRegistry(); + if (isset($options['channel'])) { + $channel = $options['channel']; + if ($reg->channelExists($channel)) { + $this->config->set('default_channel', $channel); + } else { + return $this->raiseError("Channel \"$channel\" does not exist"); + } + } + $list_options = false; + if ($this->config->get('preferred_state') == 'stable') { + $list_options = true; + } + $chan = $reg->getChannel($channel); + if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) { + return $e; + } + if ($chan->supportsREST($this->config->get('preferred_mirror')) && + $base = $chan->getBaseURL('REST1.1', $this->config->get('preferred_mirror'))) { + // use faster list-all if available + $rest = &$this->config->getREST('1.1', array()); + $available = $rest->listAll($base, $list_options, false, false, false, $chan->getName()); + } elseif ($chan->supportsREST($this->config->get('preferred_mirror')) && + $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) { + $rest = &$this->config->getREST('1.0', array()); + $available = $rest->listAll($base, $list_options, false, false, false, $chan->getName()); + } else { + $r = &$this->config->getRemote(); + if ($channel == 'pear.php.net') { + // hack because of poor pearweb design + $available = $r->call('package.listAll', true, $list_options, false); + } else { + $available = $r->call('package.listAll', true, $list_options); + } + } + if (PEAR::isError($available)) { + $this->config->set('default_channel', $savechannel); + return $this->raiseError('The package list could not be fetched from the remote server. Please try again. (Debug info: "' . $available->getMessage() . '")'); + } + $data = array( + 'caption' => 'All packages [Channel ' . $channel . ']:', + 'border' => true, + 'headline' => array('Package', 'Latest', 'Local'), + 'channel' => $channel, + ); + if (isset($options['channelinfo'])) { + // add full channelinfo + $data['caption'] = 'Channel ' . $channel . ' All packages:'; + $data['headline'] = array('Channel', 'Package', 'Latest', 'Local', + 'Description', 'Dependencies'); + } + $local_pkgs = $reg->listPackages($channel); + + foreach ($available as $name => $info) { + $installed = $reg->packageInfo($name, null, $channel); + if (is_array($installed['version'])) { + $installed['version'] = $installed['version']['release']; + } + $desc = $info['summary']; + if (isset($params[$name])) { + $desc .= "\n\n".$info['description']; + } + if (isset($options['mode'])) + { + if ($options['mode'] == 'installed' && !isset($installed['version'])) { + continue; + } + if ($options['mode'] == 'notinstalled' && isset($installed['version'])) { + continue; + } + if ($options['mode'] == 'upgrades' + && (!isset($installed['version']) || version_compare($installed['version'], + $info['stable'], '>='))) { + continue; + } + } + $pos = array_search(strtolower($name), $local_pkgs); + if ($pos !== false) { + unset($local_pkgs[$pos]); + } + + if (isset($info['stable']) && !$info['stable']) { + $info['stable'] = null; + } + + if (isset($options['channelinfo'])) { + // add full channelinfo + if ($info['stable'] === $info['unstable']) { + $state = $info['state']; + } else { + $state = 'stable'; + } + $latest = $info['stable'].' ('.$state.')'; + $local = ''; + if (isset($installed['version'])) { + $inst_state = $reg->packageInfo($name, 'release_state', $channel); + $local = $installed['version'].' ('.$inst_state.')'; + } + + $packageinfo = array( + $channel, + $name, + $latest, + $local, + isset($desc) ? $desc : null, + isset($info['deps']) ? $info['deps'] : null, + ); + } else { + $packageinfo = array( + $reg->channelAlias($channel) . '/' . $name, + isset($info['stable']) ? $info['stable'] : null, + isset($installed['version']) ? $installed['version'] : null, + isset($desc) ? $desc : null, + isset($info['deps']) ? $info['deps'] : null, + ); + } + $data['data'][$info['category']][] = $packageinfo; + } + + if (isset($options['mode']) && in_array($options['mode'], array('notinstalled', 'upgrades'))) { + $this->config->set('default_channel', $savechannel); + $this->ui->outputData($data, $command); + return true; + } + foreach ($local_pkgs as $name) { + $info = &$reg->getPackage($name, $channel); + $data['data']['Local'][] = array( + $reg->channelAlias($channel) . '/' . $info->getPackage(), + '', + $info->getVersion(), + $info->getSummary(), + $info->getDeps() + ); + } + + $this->config->set('default_channel', $savechannel); + $this->ui->outputData($data, $command); + return true; + } + + // }}} + // {{{ doSearch() + + function doSearch($command, $options, $params) + { + if ((!isset($params[0]) || empty($params[0])) + && (!isset($params[1]) || empty($params[1]))) + { + return $this->raiseError('no valid search string supplied'); + }; + + $channelinfo = isset($options['channelinfo']); + $reg = &$this->config->getRegistry(); + if (isset($options['allchannels'])) { + // search all channels + unset($options['allchannels']); + $channels = $reg->getChannels(); + $errors = array(); + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + foreach ($channels as $channel) { + if ($channel->getName() != '__uri') { + $options['channel'] = $channel->getName(); + $ret = $this->doSearch($command, $options, $params); + if (PEAR::isError($ret)) { + $errors[] = $ret; + } + } + } + PEAR::staticPopErrorHandling(); + if (count($errors) !== 0) { + // for now, only give first error + return PEAR::raiseError($errors[0]); + } + + return true; + } + + $savechannel = $channel = $this->config->get('default_channel'); + $package = $params[0]; + $summary = isset($params[1]) ? $params[1] : false; + if (isset($options['channel'])) { + $reg = &$this->config->getRegistry(); + $channel = $options['channel']; + if ($reg->channelExists($channel)) { + $this->config->set('default_channel', $channel); + } else { + return $this->raiseError('Channel "' . $channel . '" does not exist'); + } + } + $chan = $reg->getChannel($channel); + if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) { + return $e; + } + if ($chan->supportsREST($this->config->get('preferred_mirror')) && + $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) { + $rest = &$this->config->getREST('1.0', array()); + $available = $rest->listAll($base, false, false, $package, $summary, $chan->getName()); + } else { + $r = &$this->config->getRemote(); + $available = $r->call('package.search', $package, $summary, true, + $this->config->get('preferred_state') == 'stable', true); + } + if (PEAR::isError($available)) { + $this->config->set('default_channel', $savechannel); + return $this->raiseError($available); + } + if (!$available && !$channelinfo) { + // clean exit when not found, no error ! + $data = 'no packages found that match pattern "' . $package . '", for channel '.$channel.'.'; + $this->ui->outputData($data); + $this->config->set('default_channel', $channel); + return true; + } + if ($channelinfo) { + $data = array( + 'caption' => 'Matched packages, channel ' . $channel . ':', + 'border' => true, + 'headline' => array('Channel', 'Package', 'Stable/(Latest)', 'Local'), + 'channel' => $channel + ); + } else { + $data = array( + 'caption' => 'Matched packages, channel ' . $channel . ':', + 'border' => true, + 'headline' => array('Package', 'Stable/(Latest)', 'Local'), + 'channel' => $channel + ); + } + + if (!$available && $channelinfo) { + unset($data['headline']); + $data['data'] = 'No packages found that match pattern "' . $package . '".'; + $available = array(); + } + foreach ($available as $name => $info) { + $installed = $reg->packageInfo($name, null, $channel); + $desc = $info['summary']; + if (isset($params[$name])) + $desc .= "\n\n".$info['description']; + + if (!isset($info['stable']) || !$info['stable']) { + $version_remote = 'none'; + } else { + if ($info['unstable']) { + $version_remote = $info['unstable']; + } else { + $version_remote = $info['stable']; + } + $version_remote .= ' ('.$info['state'].')'; + } + $version = is_array($installed['version']) ? $installed['version']['release'] : + $installed['version']; + if ($channelinfo) { + $packageinfo = array( + $channel, + $name, + $version_remote, + $version, + $desc, + ); + } else { + $packageinfo = array( + $name, + $version_remote, + $version, + $desc, + ); + } + $data['data'][$info['category']][] = $packageinfo; + } + $this->ui->outputData($data, $command); + $this->config->set('default_channel', $channel); + return true; + } + + // }}} + function &getDownloader($options) + { + if (!class_exists('PEAR_Downloader')) { + require_once 'PEAR/Downloader.php'; + } + $a = &new PEAR_Downloader($this->ui, $options, $this->config); + return $a; + } + // {{{ doDownload() + + function doDownload($command, $options, $params) + { + // make certain that dependencies are ignored + $options['downloadonly'] = 1; + + // eliminate error messages for preferred_state-related errors + /* TODO: Should be an option, but until now download does respect + prefered state */ + /* $options['ignorepreferred_state'] = 1; */ + // eliminate error messages for preferred_state-related errors + + $downloader = &$this->getDownloader($options); + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + $e = $downloader->setDownloadDir(getcwd()); + PEAR::staticPopErrorHandling(); + if (PEAR::isError($e)) { + return $this->raiseError('Current directory is not writeable, cannot download'); + } + $errors = array(); + $downloaded = array(); + $err = $downloader->download($params); + if (PEAR::isError($err)) { + return $err; + } + $errors = $downloader->getErrorMsgs(); + if (count($errors)) { + foreach ($errors as $error) { + $this->ui->outputData($error); + } + return $this->raiseError("$command failed"); + } + $downloaded = $downloader->getDownloadedPackages(); + foreach ($downloaded as $pkg) { + $this->ui->outputData("File $pkg[file] downloaded", $command); + } + return true; + } + + function downloadCallback($msg, $params = null) + { + if ($msg == 'done') { + $this->bytes_downloaded = $params; + } + } + + // }}} + // {{{ doListUpgrades() + + function doListUpgrades($command, $options, $params) + { + require_once 'PEAR/Common.php'; + if (isset($params[0]) && !is_array(PEAR_Common::betterStates($params[0]))) { + return $this->raiseError($params[0] . ' is not a valid state (stable/beta/alpha/devel/etc.) try "pear help list-upgrades"'); + } + $savechannel = $channel = $this->config->get('default_channel'); + $reg = &$this->config->getRegistry(); + foreach ($reg->listChannels() as $channel) { + $inst = array_flip($reg->listPackages($channel)); + if (!count($inst)) { + continue; + } + if ($channel == '__uri') { + continue; + } + $this->config->set('default_channel', $channel); + if (empty($params[0])) { + $state = $this->config->get('preferred_state'); + } else { + $state = $params[0]; + } + $caption = $channel . ' Available Upgrades'; + $chan = $reg->getChannel($channel); + if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) { + return $e; + } + if ($chan->supportsREST($this->config->get('preferred_mirror')) && + $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) { + $rest = &$this->config->getREST('1.0', array()); + if (empty($state) || $state == 'any') { + $state = false; + } else { + $caption .= ' (' . implode(', ', PEAR_Common::betterStates($state, true)) . ')'; + } + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + $latest = $rest->listLatestUpgrades($base, $state, $inst, $channel, $reg); + PEAR::staticPopErrorHandling(); + } else { + $remote = &$this->config->getRemote(); + $remote->pushErrorHandling(PEAR_ERROR_RETURN); + if (empty($state) || $state == 'any') { + $latest = $remote->call("package.listLatestReleases"); + } else { + $latest = $remote->call("package.listLatestReleases", $state); + $caption .= ' (' . implode(', ', PEAR_Common::betterStates($state, true)) . ')'; + } + $remote->popErrorHandling(); + } + if (PEAR::isError($latest)) { + $this->ui->outputData($latest->getMessage()); + continue; + } + $caption .= ':'; + if (PEAR::isError($latest)) { + $this->config->set('default_channel', $savechannel); + return $latest; + } + $data = array( + 'caption' => $caption, + 'border' => 1, + 'headline' => array('Channel', 'Package', 'Local', 'Remote', 'Size'), + 'channel' => $channel + ); + foreach ((array)$latest as $pkg => $info) { + $package = strtolower($pkg); + if (!isset($inst[$package])) { + // skip packages we don't have installed + continue; + } + extract($info); + $inst_version = $reg->packageInfo($package, 'version', $channel); + $inst_state = $reg->packageInfo($package, 'release_state', $channel); + if (version_compare("$version", "$inst_version", "le")) { + // installed version is up-to-date + continue; + } + if ($filesize >= 20480) { + $filesize += 1024 - ($filesize % 1024); + $fs = sprintf("%dkB", $filesize / 1024); + } elseif ($filesize > 0) { + $filesize += 103 - ($filesize % 103); + $fs = sprintf("%.1fkB", $filesize / 1024.0); + } else { + $fs = " -"; // XXX center instead + } + $data['data'][] = array($channel, $pkg, "$inst_version ($inst_state)", "$version ($state)", $fs); + } + if (isset($options['channelinfo'])) { + if (empty($data['data'])) { + unset($data['headline']); + if (count($inst) == 0) { + $data['data'] = '(no packages installed)'; + } else { + $data['data'] = '(no upgrades available)'; + } + } + $this->ui->outputData($data, $command); + } else { + if (empty($data['data'])) { + $this->ui->outputData('Channel ' . $channel . ': No upgrades available'); + } else { + $this->ui->outputData($data, $command); + } + } + } + $this->config->set('default_channel', $savechannel); + return true; + } + + // }}} + // {{{ doClearCache() + + function doClearCache($command, $options, $params) + { + $cache_dir = $this->config->get('cache_dir'); + $verbose = $this->config->get('verbose'); + $output = ''; + if (!file_exists($cache_dir) || !is_dir($cache_dir)) { + return $this->raiseError("$cache_dir does not exist or is not a directory"); + } + if (!($dp = @opendir($cache_dir))) { + return $this->raiseError("opendir($cache_dir) failed: $php_errormsg"); + } + if ($verbose >= 1) { + $output .= "reading directory $cache_dir\n"; + } + $num = 0; + while ($ent = readdir($dp)) { + if (preg_match('/^xmlrpc_cache_[a-z0-9]{32}\\z/', $ent) || + preg_match('/rest.cache(file|id)\\z/', $ent)) { + $path = $cache_dir . DIRECTORY_SEPARATOR . $ent; + if (file_exists($path)) { + $ok = @unlink($path); + } else { + $ok = false; + $php_errormsg = ''; + } + if ($ok) { + if ($verbose >= 2) { + $output .= "deleted $path\n"; + } + $num++; + } elseif ($verbose >= 1) { + $output .= "failed to delete $path $php_errormsg\n"; + } + } + } + closedir($dp); + if ($verbose >= 1) { + $output .= "$num cache entries cleared\n"; + } + $this->ui->outputData(rtrim($output), $command); + return $num; + } + + // }}} +} + +?> diff --git a/src/lib/pear/PEAR/PEAR/Command/Remote.xml b/src/lib/pear/PEAR/PEAR/Command/Remote.xml new file mode 100644 index 0000000..d06f222 --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Command/Remote.xml @@ -0,0 +1,108 @@ + + + Information About Remote Packages + doRemoteInfo + ri + + <package> +Get details on a package from the server. + + + List Available Upgrades + doListUpgrades + lu + + [preferred_state] +List releases on the server of packages you have installed where +a newer version is available with the same release state (stable etc.) +or the state passed as the second parameter. + + + List Remote Packages + doRemoteList + rl + + + c + specify a channel other than the default channel + CHAN + + + i + output fully channel-aware data, even on failure + + + +Lists the packages available on the configured server along with the +latest stable release of each package. + + + Search remote package database + doSearch + sp + + + c + specify a channel other than the default channel + CHAN + + + a + search packages from all known channels + + + i + output fully channel-aware data, even on failure + + + [packagename] [packageinfo] +Lists all packages which match the search parameters. The first +parameter is a fragment of a packagename. The default channel +will be used unless explicitly overridden. The second parameter +will be used to match any portion of the summary/description + + + List All Packages + doListAll + la + + + c + specify a channel other than the default channel + CHAN + + + i + output fully channel-aware data, even on failure + + + +Lists the packages available on the configured server along with the +latest stable release of each package. + + + Download Package + doDownload + d + + + Z + download an uncompressed (.tar) file + + + <package>... +Download package tarballs. The files will be named as suggested by the +server, for example if you download the DB package and the latest stable +version of DB is 1.6.5, the downloaded file will be DB-1.6.5.tgz. + + + Clear Web Services Cache + doClearCache + cc + + +Clear the XML-RPC/REST cache. See also the cache_ttl configuration +parameter. + + + \ No newline at end of file diff --git a/src/lib/pear/PEAR/PEAR/Command/Test.php b/src/lib/pear/PEAR/PEAR/Command/Test.php new file mode 100644 index 0000000..4cf40f6 --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Command/Test.php @@ -0,0 +1,345 @@ + + * @author Martin Jansen + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: Test.php,v 1.27 2008/01/03 20:26:36 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 0.1 + */ + +/** + * base class + */ +require_once 'PEAR/Command/Common.php'; + +/** + * PEAR commands for login/logout + * + * @category pear + * @package PEAR + * @author Stig Bakken + * @author Martin Jansen + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 0.1 + */ + +class PEAR_Command_Test extends PEAR_Command_Common +{ + // {{{ properties + + var $commands = array( + 'run-tests' => array( + 'summary' => 'Run Regression Tests', + 'function' => 'doRunTests', + 'shortcut' => 'rt', + 'options' => array( + 'recur' => array( + 'shortopt' => 'r', + 'doc' => 'Run tests in child directories, recursively. 4 dirs deep maximum', + ), + 'ini' => array( + 'shortopt' => 'i', + 'doc' => 'actual string of settings to pass to php in format " -d setting=blah"', + 'arg' => 'SETTINGS' + ), + 'realtimelog' => array( + 'shortopt' => 'l', + 'doc' => 'Log test runs/results as they are run', + ), + 'quiet' => array( + 'shortopt' => 'q', + 'doc' => 'Only display detail for failed tests', + ), + 'simple' => array( + 'shortopt' => 's', + 'doc' => 'Display simple output for all tests', + ), + 'package' => array( + 'shortopt' => 'p', + 'doc' => 'Treat parameters as installed packages from which to run tests', + ), + 'phpunit' => array( + 'shortopt' => 'u', + 'doc' => 'Search parameters for AllTests.php, and use that to run phpunit-based tests +If none is found, all .phpt tests will be tried instead.', + ), + 'tapoutput' => array( + 'shortopt' => 't', + 'doc' => 'Output run-tests.log in TAP-compliant format', + ), + 'cgi' => array( + 'shortopt' => 'c', + 'doc' => 'CGI php executable (needed for tests with POST/GET section)', + 'arg' => 'PHPCGI', + ), + 'coverage' => array( + 'shortopt' => 'x', + 'doc' => 'Generate a code coverage report (requires Xdebug 2.0.0+)', + ), + ), + 'doc' => '[testfile|dir ...] +Run regression tests with PHP\'s regression testing script (run-tests.php).', + ), + ); + + var $output; + + // }}} + // {{{ constructor + + /** + * PEAR_Command_Test constructor. + * + * @access public + */ + function PEAR_Command_Test(&$ui, &$config) + { + parent::PEAR_Command_Common($ui, $config); + } + + // }}} + // {{{ doRunTests() + + function doRunTests($command, $options, $params) + { + if (isset($options['phpunit']) && isset($options['tapoutput'])) { + return $this->raiseError('ERROR: cannot use both --phpunit and --tapoutput at the same time'); + } + require_once 'PEAR/Common.php'; + require_once 'System.php'; + $log = new PEAR_Common; + $log->ui = &$this->ui; // slightly hacky, but it will work + $tests = array(); + $depth = isset($options['recur']) ? 4 : 1; + + if (!count($params)) { + $params[] = '.'; + } + if (isset($options['package'])) { + $oldparams = $params; + $params = array(); + $reg = &$this->config->getRegistry(); + foreach ($oldparams as $param) { + $pname = $reg->parsePackageName($param, $this->config->get('default_channel')); + if (PEAR::isError($pname)) { + return $this->raiseError($pname); + } + + $package = &$reg->getPackage($pname['package'], $pname['channel']); + if (!$package) { + return PEAR::raiseError('Unknown package "' . + $reg->parsedPackageNameToString($pname) . '"'); + } + + $filelist = $package->getFilelist(); + foreach ($filelist as $name => $atts) { + if (isset($atts['role']) && $atts['role'] != 'test') { + continue; + } + + if (isset($options['phpunit']) && preg_match('/AllTests\.php\\z/i', $name)) { + $params[] = $atts['installed_as']; + continue; + } elseif (!preg_match('/\.phpt\\z/', $name)) { + continue; + } + $params[] = $atts['installed_as']; + } + } + } + + foreach ($params as $p) { + if (is_dir($p)) { + if (isset($options['phpunit'])) { + $dir = System::find(array($p, '-type', 'f', + '-maxdepth', $depth, + '-name', 'AllTests.php')); + if (count($dir)) { + foreach ($dir as $p) { + $p = realpath($p); + if (!count($tests) || + (count($tests) && strlen($p) < strlen($tests[0]))) { + // this is in a higher-level directory, use this one instead. + $tests = array($p); + } + } + } + continue; + } + $dir = System::find(array($p, '-type', 'f', + '-maxdepth', $depth, + '-name', '*.phpt')); + $tests = array_merge($tests, $dir); + } else { + if (isset($options['phpunit'])) { + if (preg_match('/AllTests\.php\\z/i', $p)) { + $p = realpath($p); + if (!count($tests) || + (count($tests) && strlen($p) < strlen($tests[0]))) { + // this is in a higher-level directory, use this one instead. + $tests = array($p); + } + } + continue; + } + + if (file_exists($p) && preg_match('/\.phpt$/', $p)) { + $tests[] = $p; + continue; + } + + if (!preg_match('/\.phpt\\z/', $p)) { + $p .= '.phpt'; + } + $dir = System::find(array(dirname($p), '-type', 'f', + '-maxdepth', $depth, + '-name', $p)); + $tests = array_merge($tests, $dir); + } + } + + $ini_settings = ''; + if (isset($options['ini'])) { + $ini_settings .= $options['ini']; + } + + if (isset($_ENV['TEST_PHP_INCLUDE_PATH'])) { + $ini_settings .= " -d include_path={$_ENV['TEST_PHP_INCLUDE_PATH']}"; + } + + if ($ini_settings) { + $this->ui->outputData('Using INI settings: "' . $ini_settings . '"'); + } + $skipped = $passed = $failed = array(); + $tests_count = count($tests); + $this->ui->outputData('Running ' . $tests_count . ' tests', $command); + $start = time(); + if (isset($options['realtimelog']) && file_exists('run-tests.log')) { + unlink('run-tests.log'); + } + + if (isset($options['tapoutput'])) { + $tap = '1..' . $tests_count . "\n"; + } + + require_once 'PEAR/RunTest.php'; + $run = new PEAR_RunTest($log, $options); + $run->tests_count = $tests_count; + + if (isset($options['coverage']) && extension_loaded('xdebug')){ + $run->xdebug_loaded = true; + } else { + $run->xdebug_loaded = false; + } + + $j = $i = 1; + foreach ($tests as $t) { + if (isset($options['realtimelog'])) { + $fp = @fopen('run-tests.log', 'a'); + if ($fp) { + fwrite($fp, "Running test [$i / $tests_count] $t..."); + fclose($fp); + } + } + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + if (isset($options['phpunit'])) { + $result = $run->runPHPUnit($t, $ini_settings); + } else { + $result = $run->run($t, $ini_settings, $j); + } + PEAR::staticPopErrorHandling(); + if (PEAR::isError($result)) { + $this->ui->log($result->getMessage()); + continue; + } + + if (isset($options['tapoutput'])) { + $tap .= $result[0] . ' ' . $i . $result[1] . "\n"; + continue; + } + + if (isset($options['realtimelog'])) { + $fp = @fopen('run-tests.log', 'a'); + if ($fp) { + fwrite($fp, "$result\n"); + fclose($fp); + } + } + + if ($result == 'FAILED') { + $failed[] = $t; + } + if ($result == 'PASSED') { + $passed[] = $t; + } + if ($result == 'SKIPPED') { + $skipped[] = $t; + } + + $j++; + } + + $total = date('i:s', time() - $start); + if (isset($options['tapoutput'])) { + $fp = @fopen('run-tests.log', 'w'); + if ($fp) { + fwrite($fp, $tap, strlen($tap)); + fclose($fp); + $this->ui->outputData('wrote TAP-format log to "' .realpath('run-tests.log') . + '"', $command); + } + } else { + if (count($failed)) { + $output = "TOTAL TIME: $total\n"; + $output .= count($passed) . " PASSED TESTS\n"; + $output .= count($skipped) . " SKIPPED TESTS\n"; + $output .= count($failed) . " FAILED TESTS:\n"; + foreach ($failed as $failure) { + $output .= $failure . "\n"; + } + + $mode = isset($options['realtimelog']) ? 'a' : 'w'; + $fp = @fopen('run-tests.log', $mode); + + if ($fp) { + fwrite($fp, $output, strlen($output)); + fclose($fp); + $this->ui->outputData('wrote log to "' . realpath('run-tests.log') . '"', $command); + } + } elseif (file_exists('run-tests.log') && !is_dir('run-tests.log')) { + @unlink('run-tests.log'); + } + } + $this->ui->outputData('TOTAL TIME: ' . $total); + $this->ui->outputData(count($passed) . ' PASSED TESTS', $command); + $this->ui->outputData(count($skipped) . ' SKIPPED TESTS', $command); + if (count($failed)) { + $this->ui->outputData(count($failed) . ' FAILED TESTS:', $command); + foreach ($failed as $failure) { + $this->ui->outputData($failure, $command); + } + } + + return true; + } + // }}} +} \ No newline at end of file diff --git a/src/lib/pear/PEAR/PEAR/Command/Test.xml b/src/lib/pear/PEAR/PEAR/Command/Test.xml new file mode 100644 index 0000000..68e8f53 --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Command/Test.xml @@ -0,0 +1,54 @@ + + + Run Regression Tests + doRunTests + rt + + + r + Run tests in child directories, recursively. 4 dirs deep maximum + + + i + actual string of settings to pass to php in format " -d setting=blah" + SETTINGS + + + l + Log test runs/results as they are run + + + q + Only display detail for failed tests + + + s + Display simple output for all tests + + + p + Treat parameters as installed packages from which to run tests + + + u + Search parameters for AllTests.php, and use that to run phpunit-based tests. +If none is found, all .phpt tests will be tried instead. + + + t + Output run-tests.log in TAP-compliant format + + + c + CGI php executable (needed for tests with POST/GET section) + PHPCGI + + + x + Generate a code coverage report (requires Xdebug 2.0.0+) + + + [testfile|dir ...] +Run regression tests with PHP's regression testing script (run-tests.php). + + \ No newline at end of file diff --git a/src/lib/pear/PEAR/PEAR/Common.php b/src/lib/pear/PEAR/PEAR/Common.php new file mode 100644 index 0000000..73ec384 --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Common.php @@ -0,0 +1,1126 @@ + + * @author Tomas V. V. Cox + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: Common.php,v 1.160 2008/01/03 20:26:34 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 0.1.0 + * @deprecated File deprecated since Release 1.4.0a1 + */ + +/** + * Include error handling + */ +require_once 'PEAR.php'; + +// {{{ constants and globals + +/** + * PEAR_Common error when an invalid PHP file is passed to PEAR_Common::analyzeSourceCode() + */ +define('PEAR_COMMON_ERROR_INVALIDPHP', 1); +define('_PEAR_COMMON_PACKAGE_NAME_PREG', '[A-Za-z][a-zA-Z0-9_]+'); +define('PEAR_COMMON_PACKAGE_NAME_PREG', '/^' . _PEAR_COMMON_PACKAGE_NAME_PREG . '\\z/'); + +// this should allow: 1, 1.0, 1.0RC1, 1.0dev, 1.0dev123234234234, 1.0a1, 1.0b1, 1.0pl1 +define('_PEAR_COMMON_PACKAGE_VERSION_PREG', '\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?'); +define('PEAR_COMMON_PACKAGE_VERSION_PREG', '/^' . _PEAR_COMMON_PACKAGE_VERSION_PREG . '\\z/i'); + +// XXX far from perfect :-) +define('_PEAR_COMMON_PACKAGE_DOWNLOAD_PREG', '(' . _PEAR_COMMON_PACKAGE_NAME_PREG . + ')(-([.0-9a-zA-Z]+))?'); +define('PEAR_COMMON_PACKAGE_DOWNLOAD_PREG', '/^' . _PEAR_COMMON_PACKAGE_DOWNLOAD_PREG . + '\\z/'); + +define('_PEAR_CHANNELS_NAME_PREG', '[A-Za-z][a-zA-Z0-9\.]+'); +define('PEAR_CHANNELS_NAME_PREG', '/^' . _PEAR_CHANNELS_NAME_PREG . '\\z/'); + +// this should allow any dns or IP address, plus a path - NO UNDERSCORES ALLOWED +define('_PEAR_CHANNELS_SERVER_PREG', '[a-zA-Z0-9\-]+(?:\.[a-zA-Z0-9\-]+)*(\/[a-zA-Z0-9\-]+)*'); +define('PEAR_CHANNELS_SERVER_PREG', '/^' . _PEAR_CHANNELS_SERVER_PREG . '\\z/i'); + +define('_PEAR_CHANNELS_PACKAGE_PREG', '(' ._PEAR_CHANNELS_SERVER_PREG . ')\/(' + . _PEAR_COMMON_PACKAGE_NAME_PREG . ')'); +define('PEAR_CHANNELS_PACKAGE_PREG', '/^' . _PEAR_CHANNELS_PACKAGE_PREG . '\\z/i'); + +define('_PEAR_COMMON_CHANNEL_DOWNLOAD_PREG', '(' . _PEAR_CHANNELS_NAME_PREG . ')::(' + . _PEAR_COMMON_PACKAGE_NAME_PREG . ')(-([.0-9a-zA-Z]+))?'); +define('PEAR_COMMON_CHANNEL_DOWNLOAD_PREG', '/^' . _PEAR_COMMON_CHANNEL_DOWNLOAD_PREG . '\\z/'); + +/** + * List of temporary files and directories registered by + * PEAR_Common::addTempFile(). + * @var array + */ +$GLOBALS['_PEAR_Common_tempfiles'] = array(); + +/** + * Valid maintainer roles + * @var array + */ +$GLOBALS['_PEAR_Common_maintainer_roles'] = array('lead','developer','contributor','helper'); + +/** + * Valid release states + * @var array + */ +$GLOBALS['_PEAR_Common_release_states'] = array('alpha','beta','stable','snapshot','devel'); + +/** + * Valid dependency types + * @var array + */ +$GLOBALS['_PEAR_Common_dependency_types'] = array('pkg','ext','php','prog','ldlib','rtlib','os','websrv','sapi'); + +/** + * Valid dependency relations + * @var array + */ +$GLOBALS['_PEAR_Common_dependency_relations'] = array('has','eq','lt','le','gt','ge','not', 'ne'); + +/** + * Valid file roles + * @var array + */ +$GLOBALS['_PEAR_Common_file_roles'] = array('php','ext','test','doc','data','src','script'); + +/** + * Valid replacement types + * @var array + */ +$GLOBALS['_PEAR_Common_replacement_types'] = array('php-const', 'pear-config', 'package-info'); + +/** + * Valid "provide" types + * @var array + */ +$GLOBALS['_PEAR_Common_provide_types'] = array('ext', 'prog', 'class', 'function', 'feature', 'api'); + +/** + * Valid "provide" types + * @var array + */ +$GLOBALS['_PEAR_Common_script_phases'] = array('pre-install', 'post-install', 'pre-uninstall', 'post-uninstall', 'pre-build', 'post-build', 'pre-configure', 'post-configure', 'pre-setup', 'post-setup'); + +// }}} + +/** + * Class providing common functionality for PEAR administration classes. + * @category pear + * @package PEAR + * @author Stig Bakken + * @author Tomas V. V. Cox + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 1.4.0a1 + * @deprecated This class will disappear, and its components will be spread + * into smaller classes, like the AT&T breakup, as of Release 1.4.0a1 + */ +class PEAR_Common extends PEAR +{ + // {{{ properties + + /** stack of elements, gives some sort of XML context */ + var $element_stack = array(); + + /** name of currently parsed XML element */ + var $current_element; + + /** array of attributes of the currently parsed XML element */ + var $current_attributes = array(); + + /** assoc with information about a package */ + var $pkginfo = array(); + + /** + * User Interface object (PEAR_Frontend_* class). If null, + * the log() method uses print. + * @var object + */ + var $ui = null; + + /** + * Configuration object (PEAR_Config). + * @var PEAR_Config + */ + var $config = null; + + var $current_path = null; + + /** + * PEAR_SourceAnalyzer instance + * @var object + */ + var $source_analyzer = null; + /** + * Flag variable used to mark a valid package file + * @var boolean + * @access private + */ + var $_validPackageFile; + + // }}} + + // {{{ constructor + + /** + * PEAR_Common constructor + * + * @access public + */ + function PEAR_Common() + { + parent::PEAR(); + $this->config = &PEAR_Config::singleton(); + $this->debug = $this->config->get('verbose'); + } + + // }}} + // {{{ destructor + + /** + * PEAR_Common destructor + * + * @access private + */ + function _PEAR_Common() + { + // doesn't work due to bug #14744 + //$tempfiles = $this->_tempfiles; + $tempfiles =& $GLOBALS['_PEAR_Common_tempfiles']; + while ($file = array_shift($tempfiles)) { + if (@is_dir($file)) { + if (!class_exists('System')) { + require_once 'System.php'; + } + System::rm(array('-rf', $file)); + } elseif (file_exists($file)) { + unlink($file); + } + } + } + + // }}} + // {{{ addTempFile() + + /** + * Register a temporary file or directory. When the destructor is + * executed, all registered temporary files and directories are + * removed. + * + * @param string $file name of file or directory + * + * @return void + * + * @access public + */ + function addTempFile($file) + { + if (!class_exists('PEAR_Frontend')) { + require_once 'PEAR/Frontend.php'; + } + PEAR_Frontend::addTempFile($file); + } + + // }}} + // {{{ mkDirHier() + + /** + * Wrapper to System::mkDir(), creates a directory as well as + * any necessary parent directories. + * + * @param string $dir directory name + * + * @return bool TRUE on success, or a PEAR error + * + * @access public + */ + function mkDirHier($dir) + { + $this->log(2, "+ create dir $dir"); + if (!class_exists('System')) { + require_once 'System.php'; + } + return System::mkDir(array('-p', $dir)); + } + + // }}} + // {{{ log() + + /** + * Logging method. + * + * @param int $level log level (0 is quiet, higher is noisier) + * @param string $msg message to write to the log + * + * @return void + * + * @access public + * @static + */ + function log($level, $msg, $append_crlf = true) + { + if ($this->debug >= $level) { + if (!class_exists('PEAR_Frontend')) { + require_once 'PEAR/Frontend.php'; + } + $ui = &PEAR_Frontend::singleton(); + if (is_a($ui, 'PEAR_Frontend')) { + $ui->log($msg, $append_crlf); + } else { + print "$msg\n"; + } + } + } + + // }}} + // {{{ mkTempDir() + + /** + * Create and register a temporary directory. + * + * @param string $tmpdir (optional) Directory to use as tmpdir. + * Will use system defaults (for example + * /tmp or c:\windows\temp) if not specified + * + * @return string name of created directory + * + * @access public + */ + function mkTempDir($tmpdir = '') + { + if ($tmpdir) { + $topt = array('-t', $tmpdir); + } else { + $topt = array(); + } + $topt = array_merge($topt, array('-d', 'pear')); + if (!class_exists('System')) { + require_once 'System.php'; + } + if (!$tmpdir = System::mktemp($topt)) { + return false; + } + $this->addTempFile($tmpdir); + return $tmpdir; + } + + // }}} + // {{{ setFrontendObject() + + /** + * Set object that represents the frontend to be used. + * + * @param object Reference of the frontend object + * @return void + * @access public + */ + function setFrontendObject(&$ui) + { + $this->ui = &$ui; + } + + // }}} + + // {{{ infoFromTgzFile() + + /** + * Returns information about a package file. Expects the name of + * a gzipped tar file as input. + * + * @param string $file name of .tgz file + * + * @return array array with package information + * + * @access public + * @deprecated use PEAR_PackageFile->fromTgzFile() instead + * + */ + function infoFromTgzFile($file) + { + $packagefile = &new PEAR_PackageFile($this->config); + $pf = &$packagefile->fromTgzFile($file, PEAR_VALIDATE_NORMAL); + if (PEAR::isError($pf)) { + $errs = $pf->getUserinfo(); + if (is_array($errs)) { + foreach ($errs as $error) { + $e = $this->raiseError($error['message'], $error['code'], null, null, $error); + } + } + return $pf; + } + return $this->_postProcessValidPackagexml($pf); + } + + // }}} + // {{{ infoFromDescriptionFile() + + /** + * Returns information about a package file. Expects the name of + * a package xml file as input. + * + * @param string $descfile name of package xml file + * + * @return array array with package information + * + * @access public + * @deprecated use PEAR_PackageFile->fromPackageFile() instead + * + */ + function infoFromDescriptionFile($descfile) + { + $packagefile = &new PEAR_PackageFile($this->config); + $pf = &$packagefile->fromPackageFile($descfile, PEAR_VALIDATE_NORMAL); + if (PEAR::isError($pf)) { + $errs = $pf->getUserinfo(); + if (is_array($errs)) { + foreach ($errs as $error) { + $e = $this->raiseError($error['message'], $error['code'], null, null, $error); + } + } + return $pf; + } + return $this->_postProcessValidPackagexml($pf); + } + + // }}} + // {{{ infoFromString() + + /** + * Returns information about a package file. Expects the contents + * of a package xml file as input. + * + * @param string $data contents of package.xml file + * + * @return array array with package information + * + * @access public + * @deprecated use PEAR_PackageFile->fromXmlstring() instead + * + */ + function infoFromString($data) + { + $packagefile = &new PEAR_PackageFile($this->config); + $pf = &$packagefile->fromXmlString($data, PEAR_VALIDATE_NORMAL, false); + if (PEAR::isError($pf)) { + $errs = $pf->getUserinfo(); + if (is_array($errs)) { + foreach ($errs as $error) { + $e = $this->raiseError($error['message'], $error['code'], null, null, $error); + } + } + return $pf; + } + return $this->_postProcessValidPackagexml($pf); + } + // }}} + + /** + * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2 + * @return array + */ + function _postProcessValidPackagexml(&$pf) + { + if (is_a($pf, 'PEAR_PackageFile_v2')) { + // sort of make this into a package.xml 1.0-style array + // changelog is not converted to old format. + $arr = $pf->toArray(true); + $arr = array_merge($arr, $arr['old']); + unset($arr['old']); + unset($arr['xsdversion']); + unset($arr['contents']); + unset($arr['compatible']); + unset($arr['channel']); + unset($arr['uri']); + unset($arr['dependencies']); + unset($arr['phprelease']); + unset($arr['extsrcrelease']); + unset($arr['zendextsrcrelease']); + unset($arr['extbinrelease']); + unset($arr['zendextbinrelease']); + unset($arr['bundle']); + unset($arr['lead']); + unset($arr['developer']); + unset($arr['helper']); + unset($arr['contributor']); + $arr['filelist'] = $pf->getFilelist(); + $this->pkginfo = $arr; + return $arr; + } else { + $this->pkginfo = $pf->toArray(); + return $this->pkginfo; + } + } + // {{{ infoFromAny() + + /** + * Returns package information from different sources + * + * This method is able to extract information about a package + * from a .tgz archive or from a XML package definition file. + * + * @access public + * @param string Filename of the source ('package.xml', '.tgz') + * @return string + * @deprecated use PEAR_PackageFile->fromAnyFile() instead + */ + function infoFromAny($info) + { + if (is_string($info) && file_exists($info)) { + $packagefile = &new PEAR_PackageFile($this->config); + $pf = &$packagefile->fromAnyFile($info, PEAR_VALIDATE_NORMAL); + if (PEAR::isError($pf)) { + $errs = $pf->getUserinfo(); + if (is_array($errs)) { + foreach ($errs as $error) { + $e = $this->raiseError($error['message'], $error['code'], null, null, $error); + } + } + return $pf; + } + return $this->_postProcessValidPackagexml($pf); + } + return $info; + } + + // }}} + // {{{ xmlFromInfo() + + /** + * Return an XML document based on the package info (as returned + * by the PEAR_Common::infoFrom* methods). + * + * @param array $pkginfo package info + * + * @return string XML data + * + * @access public + * @deprecated use a PEAR_PackageFile_v* object's generator instead + */ + function xmlFromInfo($pkginfo) + { + $config = &PEAR_Config::singleton(); + $packagefile = &new PEAR_PackageFile($config); + $pf = &$packagefile->fromArray($pkginfo); + $gen = &$pf->getDefaultGenerator(); + return $gen->toXml(PEAR_VALIDATE_PACKAGING); + } + + // }}} + // {{{ validatePackageInfo() + + /** + * Validate XML package definition file. + * + * @param string $info Filename of the package archive or of the + * package definition file + * @param array $errors Array that will contain the errors + * @param array $warnings Array that will contain the warnings + * @param string $dir_prefix (optional) directory where source files + * may be found, or empty if they are not available + * @access public + * @return boolean + * @deprecated use the validation of PEAR_PackageFile objects + */ + function validatePackageInfo($info, &$errors, &$warnings, $dir_prefix = '') + { + $config = &PEAR_Config::singleton(); + $packagefile = &new PEAR_PackageFile($config); + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + if (strpos($info, 'fromXmlString($info, PEAR_VALIDATE_NORMAL, ''); + } else { + $pf = &$packagefile->fromAnyFile($info, PEAR_VALIDATE_NORMAL); + } + PEAR::staticPopErrorHandling(); + if (PEAR::isError($pf)) { + $errs = $pf->getUserinfo(); + if (is_array($errs)) { + foreach ($errs as $error) { + if ($error['level'] == 'error') { + $errors[] = $error['message']; + } else { + $warnings[] = $error['message']; + } + } + } + return false; + } + return true; + } + + // }}} + // {{{ buildProvidesArray() + + /** + * Build a "provides" array from data returned by + * analyzeSourceCode(). The format of the built array is like + * this: + * + * array( + * 'class;MyClass' => 'array('type' => 'class', 'name' => 'MyClass'), + * ... + * ) + * + * + * @param array $srcinfo array with information about a source file + * as returned by the analyzeSourceCode() method. + * + * @return void + * + * @access public + * + */ + function buildProvidesArray($srcinfo) + { + $file = basename($srcinfo['source_file']); + $pn = ''; + if (isset($this->_packageName)) { + $pn = $this->_packageName; + } + $pnl = strlen($pn); + foreach ($srcinfo['declared_classes'] as $class) { + $key = "class;$class"; + if (isset($this->pkginfo['provides'][$key])) { + continue; + } + $this->pkginfo['provides'][$key] = + array('file'=> $file, 'type' => 'class', 'name' => $class); + if (isset($srcinfo['inheritance'][$class])) { + $this->pkginfo['provides'][$key]['extends'] = + $srcinfo['inheritance'][$class]; + } + } + foreach ($srcinfo['declared_methods'] as $class => $methods) { + foreach ($methods as $method) { + $function = "$class::$method"; + $key = "function;$function"; + if ($method{0} == '_' || !strcasecmp($method, $class) || + isset($this->pkginfo['provides'][$key])) { + continue; + } + $this->pkginfo['provides'][$key] = + array('file'=> $file, 'type' => 'function', 'name' => $function); + } + } + + foreach ($srcinfo['declared_functions'] as $function) { + $key = "function;$function"; + if ($function{0} == '_' || isset($this->pkginfo['provides'][$key])) { + continue; + } + if (!strstr($function, '::') && strncasecmp($function, $pn, $pnl)) { + $warnings[] = "in1 " . $file . ": function \"$function\" not prefixed with package name \"$pn\""; + } + $this->pkginfo['provides'][$key] = + array('file'=> $file, 'type' => 'function', 'name' => $function); + } + } + + // }}} + // {{{ analyzeSourceCode() + + /** + * Analyze the source code of the given PHP file + * + * @param string Filename of the PHP file + * @return mixed + * @access public + */ + function analyzeSourceCode($file) + { + if (!function_exists("token_get_all")) { + return false; + } + if (!defined('T_DOC_COMMENT')) { + define('T_DOC_COMMENT', T_COMMENT); + } + if (!defined('T_INTERFACE')) { + define('T_INTERFACE', -1); + } + if (!defined('T_IMPLEMENTS')) { + define('T_IMPLEMENTS', -1); + } + if (!$fp = @fopen($file, "r")) { + return false; + } + fclose($fp); + $contents = file_get_contents($file); + $tokens = token_get_all($contents); +/* + for ($i = 0; $i < sizeof($tokens); $i++) { + @list($token, $data) = $tokens[$i]; + if (is_string($token)) { + var_dump($token); + } else { + print token_name($token) . ' '; + var_dump(rtrim($data)); + } + } +*/ + $look_for = 0; + $paren_level = 0; + $bracket_level = 0; + $brace_level = 0; + $lastphpdoc = ''; + $current_class = ''; + $current_interface = ''; + $current_class_level = -1; + $current_function = ''; + $current_function_level = -1; + $declared_classes = array(); + $declared_interfaces = array(); + $declared_functions = array(); + $declared_methods = array(); + $used_classes = array(); + $used_functions = array(); + $extends = array(); + $implements = array(); + $nodeps = array(); + $inquote = false; + $interface = false; + for ($i = 0; $i < sizeof($tokens); $i++) { + if (is_array($tokens[$i])) { + list($token, $data) = $tokens[$i]; + } else { + $token = $tokens[$i]; + $data = ''; + } + if ($inquote) { + if ($token != '"') { + continue; + } else { + $inquote = false; + continue; + } + } + switch ($token) { + case T_WHITESPACE: + continue; + case ';': + if ($interface) { + $current_function = ''; + $current_function_level = -1; + } + break; + case '"': + $inquote = true; + break; + case T_CURLY_OPEN: + case T_DOLLAR_OPEN_CURLY_BRACES: + case '{': $brace_level++; continue 2; + case '}': + $brace_level--; + if ($current_class_level == $brace_level) { + $current_class = ''; + $current_class_level = -1; + } + if ($current_function_level == $brace_level) { + $current_function = ''; + $current_function_level = -1; + } + continue 2; + case '[': $bracket_level++; continue 2; + case ']': $bracket_level--; continue 2; + case '(': $paren_level++; continue 2; + case ')': $paren_level--; continue 2; + case T_INTERFACE: + $interface = true; + case T_CLASS: + if (($current_class_level != -1) || ($current_function_level != -1)) { + PEAR::raiseError("Parser error: invalid PHP found in file \"$file\"", + PEAR_COMMON_ERROR_INVALIDPHP); + return false; + } + case T_FUNCTION: + case T_NEW: + case T_EXTENDS: + case T_IMPLEMENTS: + $look_for = $token; + continue 2; + case T_STRING: + if (version_compare(zend_version(), '2.0', '<')) { + if (in_array(strtolower($data), + array('public', 'private', 'protected', 'abstract', + 'interface', 'implements', 'throw') + )) { + PEAR::raiseError('Error: PHP5 token encountered in ' . $file . + 'packaging should be done in PHP 5'); + return false; + } + } + if ($look_for == T_CLASS) { + $current_class = $data; + $current_class_level = $brace_level; + $declared_classes[] = $current_class; + } elseif ($look_for == T_INTERFACE) { + $current_interface = $data; + $current_class_level = $brace_level; + $declared_interfaces[] = $current_interface; + } elseif ($look_for == T_IMPLEMENTS) { + $implements[$current_class] = $data; + } elseif ($look_for == T_EXTENDS) { + $extends[$current_class] = $data; + } elseif ($look_for == T_FUNCTION) { + if ($current_class) { + $current_function = "$current_class::$data"; + $declared_methods[$current_class][] = $data; + } elseif ($current_interface) { + $current_function = "$current_interface::$data"; + $declared_methods[$current_interface][] = $data; + } else { + $current_function = $data; + $declared_functions[] = $current_function; + } + $current_function_level = $brace_level; + $m = array(); + } elseif ($look_for == T_NEW) { + $used_classes[$data] = true; + } + $look_for = 0; + continue 2; + case T_VARIABLE: + $look_for = 0; + continue 2; + case T_DOC_COMMENT: + case T_COMMENT: + if (preg_match('!^/\*\*\s!', $data)) { + $lastphpdoc = $data; + if (preg_match_all('/@nodep\s+(\S+)/', $lastphpdoc, $m)) { + $nodeps = array_merge($nodeps, $m[1]); + } + } + continue 2; + case T_DOUBLE_COLON: + if (!($tokens[$i - 1][0] == T_WHITESPACE || $tokens[$i - 1][0] == T_STRING)) { + PEAR::raiseError("Parser error: invalid PHP found in file \"$file\"", + PEAR_COMMON_ERROR_INVALIDPHP); + return false; + } + $class = $tokens[$i - 1][1]; + if (strtolower($class) != 'parent') { + $used_classes[$class] = true; + } + continue 2; + } + } + return array( + "source_file" => $file, + "declared_classes" => $declared_classes, + "declared_interfaces" => $declared_interfaces, + "declared_methods" => $declared_methods, + "declared_functions" => $declared_functions, + "used_classes" => array_diff(array_keys($used_classes), $nodeps), + "inheritance" => $extends, + "implements" => $implements, + ); + } + + // }}} + // {{{ betterStates() + + /** + * Return an array containing all of the states that are more stable than + * or equal to the passed in state + * + * @param string Release state + * @param boolean Determines whether to include $state in the list + * @return false|array False if $state is not a valid release state + */ + function betterStates($state, $include = false) + { + static $states = array('snapshot', 'devel', 'alpha', 'beta', 'stable'); + $i = array_search($state, $states); + if ($i === false) { + return false; + } + if ($include) { + $i--; + } + return array_slice($states, $i + 1); + } + + // }}} + // {{{ detectDependencies() + + function detectDependencies($any, $status_callback = null) + { + if (!function_exists("token_get_all")) { + return false; + } + if (PEAR::isError($info = $this->infoFromAny($any))) { + return $this->raiseError($info); + } + if (!is_array($info)) { + return false; + } + $deps = array(); + $used_c = $decl_c = $decl_f = $decl_m = array(); + foreach ($info['filelist'] as $file => $fa) { + $tmp = $this->analyzeSourceCode($file); + $used_c = @array_merge($used_c, $tmp['used_classes']); + $decl_c = @array_merge($decl_c, $tmp['declared_classes']); + $decl_f = @array_merge($decl_f, $tmp['declared_functions']); + $decl_m = @array_merge($decl_m, $tmp['declared_methods']); + $inheri = @array_merge($inheri, $tmp['inheritance']); + } + $used_c = array_unique($used_c); + $decl_c = array_unique($decl_c); + $undecl_c = array_diff($used_c, $decl_c); + return array('used_classes' => $used_c, + 'declared_classes' => $decl_c, + 'declared_methods' => $decl_m, + 'declared_functions' => $decl_f, + 'undeclared_classes' => $undecl_c, + 'inheritance' => $inheri, + ); + } + + // }}} + // {{{ getUserRoles() + + /** + * Get the valid roles for a PEAR package maintainer + * + * @return array + * @static + */ + function getUserRoles() + { + return $GLOBALS['_PEAR_Common_maintainer_roles']; + } + + // }}} + // {{{ getReleaseStates() + + /** + * Get the valid package release states of packages + * + * @return array + * @static + */ + function getReleaseStates() + { + return $GLOBALS['_PEAR_Common_release_states']; + } + + // }}} + // {{{ getDependencyTypes() + + /** + * Get the implemented dependency types (php, ext, pkg etc.) + * + * @return array + * @static + */ + function getDependencyTypes() + { + return $GLOBALS['_PEAR_Common_dependency_types']; + } + + // }}} + // {{{ getDependencyRelations() + + /** + * Get the implemented dependency relations (has, lt, ge etc.) + * + * @return array + * @static + */ + function getDependencyRelations() + { + return $GLOBALS['_PEAR_Common_dependency_relations']; + } + + // }}} + // {{{ getFileRoles() + + /** + * Get the implemented file roles + * + * @return array + * @static + */ + function getFileRoles() + { + return $GLOBALS['_PEAR_Common_file_roles']; + } + + // }}} + // {{{ getReplacementTypes() + + /** + * Get the implemented file replacement types in + * + * @return array + * @static + */ + function getReplacementTypes() + { + return $GLOBALS['_PEAR_Common_replacement_types']; + } + + // }}} + // {{{ getProvideTypes() + + /** + * Get the implemented file replacement types in + * + * @return array + * @static + */ + function getProvideTypes() + { + return $GLOBALS['_PEAR_Common_provide_types']; + } + + // }}} + // {{{ getScriptPhases() + + /** + * Get the implemented file replacement types in + * + * @return array + * @static + */ + function getScriptPhases() + { + return $GLOBALS['_PEAR_Common_script_phases']; + } + + // }}} + // {{{ validPackageName() + + /** + * Test whether a string contains a valid package name. + * + * @param string $name the package name to test + * + * @return bool + * + * @access public + */ + function validPackageName($name) + { + return (bool)preg_match(PEAR_COMMON_PACKAGE_NAME_PREG, $name); + } + + + // }}} + // {{{ validPackageVersion() + + /** + * Test whether a string contains a valid package version. + * + * @param string $ver the package version to test + * + * @return bool + * + * @access public + */ + function validPackageVersion($ver) + { + return (bool)preg_match(PEAR_COMMON_PACKAGE_VERSION_PREG, $ver); + } + + + // }}} + + // {{{ downloadHttp() + + /** + * Download a file through HTTP. Considers suggested file name in + * Content-disposition: header and can run a callback function for + * different events. The callback will be called with two + * parameters: the callback type, and parameters. The implemented + * callback types are: + * + * 'setup' called at the very beginning, parameter is a UI object + * that should be used for all output + * 'message' the parameter is a string with an informational message + * 'saveas' may be used to save with a different file name, the + * parameter is the filename that is about to be used. + * If a 'saveas' callback returns a non-empty string, + * that file name will be used as the filename instead. + * Note that $save_dir will not be affected by this, only + * the basename of the file. + * 'start' download is starting, parameter is number of bytes + * that are expected, or -1 if unknown + * 'bytesread' parameter is the number of bytes read so far + * 'done' download is complete, parameter is the total number + * of bytes read + * 'connfailed' if the TCP connection fails, this callback is called + * with array(host,port,errno,errmsg) + * 'writefailed' if writing to disk fails, this callback is called + * with array(destfile,errmsg) + * + * If an HTTP proxy has been configured (http_proxy PEAR_Config + * setting), the proxy will be used. + * + * @param string $url the URL to download + * @param object $ui PEAR_Frontend_* instance + * @param object $config PEAR_Config instance + * @param string $save_dir (optional) directory to save file in + * @param mixed $callback (optional) function/method to call for status + * updates + * + * @return string Returns the full path of the downloaded file or a PEAR + * error on failure. If the error is caused by + * socket-related errors, the error object will + * have the fsockopen error code available through + * getCode(). + * + * @access public + * @deprecated in favor of PEAR_Downloader::downloadHttp() + */ + function downloadHttp($url, &$ui, $save_dir = '.', $callback = null) + { + if (!class_exists('PEAR_Downloader')) { + require_once 'PEAR/Downloader.php'; + } + return PEAR_Downloader::downloadHttp($url, $ui, $save_dir, $callback); + } + + // }}} + + /** + * @param string $path relative or absolute include path + * @return boolean + * @static + */ + function isIncludeable($path) + { + if (file_exists($path) && is_readable($path)) { + return true; + } + $ipath = explode(PATH_SEPARATOR, ini_get('include_path')); + foreach ($ipath as $include) { + $test = realpath($include . DIRECTORY_SEPARATOR . $path); + if (file_exists($test) && is_readable($test)) { + return true; + } + } + return false; + } +} +require_once 'PEAR/Config.php'; +require_once 'PEAR/PackageFile.php'; +?> \ No newline at end of file diff --git a/src/lib/pear/PEAR/PEAR/Config.php b/src/lib/pear/PEAR/PEAR/Config.php new file mode 100644 index 0000000..25fdd29 --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Config.php @@ -0,0 +1,2164 @@ + + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: Config.php,v 1.146 2008/05/14 04:16:08 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 0.1 + */ + +/** + * Required for error handling + */ +require_once 'PEAR.php'; +require_once 'PEAR/Registry.php'; +require_once 'PEAR/Installer/Role.php'; +require_once 'System.php'; +require_once 'PEAR/Remote.php'; + +/** + * Last created PEAR_Config instance. + * @var object + */ +$GLOBALS['_PEAR_Config_instance'] = null; +if (!defined('PEAR_INSTALL_DIR') || !PEAR_INSTALL_DIR) { + $PEAR_INSTALL_DIR = PHP_LIBDIR . DIRECTORY_SEPARATOR . 'pear'; +} else { + $PEAR_INSTALL_DIR = PEAR_INSTALL_DIR; +} + +// Below we define constants with default values for all configuration +// parameters except username/password. All of them can have their +// defaults set through environment variables. The reason we use the +// PHP_ prefix is for some security, PHP protects environment +// variables starting with PHP_*. + +// default channel and preferred mirror is based on whether we are invoked through +// the "pear" or the "pecl" command + +if (!defined('PEAR_RUNTYPE') || PEAR_RUNTYPE == 'pear') { + define('PEAR_CONFIG_DEFAULT_CHANNEL', 'pear.php.net'); +} else { + define('PEAR_CONFIG_DEFAULT_CHANNEL', 'pecl.php.net'); +} + +if (getenv('PHP_PEAR_SYSCONF_DIR')) { + define('PEAR_CONFIG_SYSCONFDIR', getenv('PHP_PEAR_SYSCONF_DIR')); +} elseif (getenv('SystemRoot')) { + define('PEAR_CONFIG_SYSCONFDIR', getenv('SystemRoot')); +} else { +// define('PEAR_CONFIG_SYSCONFDIR', PHP_SYSCONFDIR); + define('PEAR_CONFIG_SYSCONFDIR', $PEAR_INSTALL_DIR); +} + +// Default for master_server +if (getenv('PHP_PEAR_MASTER_SERVER')) { + define('PEAR_CONFIG_DEFAULT_MASTER_SERVER', getenv('PHP_PEAR_MASTER_SERVER')); +} else { + define('PEAR_CONFIG_DEFAULT_MASTER_SERVER', 'pear.php.net'); +} + +// Default for http_proxy +if (getenv('PHP_PEAR_HTTP_PROXY')) { + define('PEAR_CONFIG_DEFAULT_HTTP_PROXY', getenv('PHP_PEAR_HTTP_PROXY')); +} elseif (getenv('http_proxy')) { + define('PEAR_CONFIG_DEFAULT_HTTP_PROXY', getenv('http_proxy')); +} else { + define('PEAR_CONFIG_DEFAULT_HTTP_PROXY', ''); +} + +// Default for php_dir +if (getenv('PHP_PEAR_INSTALL_DIR')) { + define('PEAR_CONFIG_DEFAULT_PHP_DIR', getenv('PHP_PEAR_INSTALL_DIR')); +} else { + if (file_exists($PEAR_INSTALL_DIR) && is_dir($PEAR_INSTALL_DIR)) { + define('PEAR_CONFIG_DEFAULT_PHP_DIR', + $PEAR_INSTALL_DIR); + } else { + define('PEAR_CONFIG_DEFAULT_PHP_DIR', $PEAR_INSTALL_DIR); + } +} + +// Default for ext_dir +if (getenv('PHP_PEAR_EXTENSION_DIR')) { + define('PEAR_CONFIG_DEFAULT_EXT_DIR', getenv('PHP_PEAR_EXTENSION_DIR')); +} else { + if (ini_get('extension_dir')) { + define('PEAR_CONFIG_DEFAULT_EXT_DIR', ini_get('extension_dir')); + } elseif (defined('PEAR_EXTENSION_DIR') && + file_exists(PEAR_EXTENSION_DIR) && is_dir(PEAR_EXTENSION_DIR)) { + define('PEAR_CONFIG_DEFAULT_EXT_DIR', PEAR_EXTENSION_DIR); + } elseif (defined('PHP_EXTENSION_DIR')) { + define('PEAR_CONFIG_DEFAULT_EXT_DIR', PHP_EXTENSION_DIR); + } else { + define('PEAR_CONFIG_DEFAULT_EXT_DIR', '.'); + } +} + +// Default for doc_dir +if (getenv('PHP_PEAR_DOC_DIR')) { + define('PEAR_CONFIG_DEFAULT_DOC_DIR', getenv('PHP_PEAR_DOC_DIR')); +} else { + define('PEAR_CONFIG_DEFAULT_DOC_DIR', + $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'docs'); +} + +// Default for bin_dir +if (getenv('PHP_PEAR_BIN_DIR')) { + define('PEAR_CONFIG_DEFAULT_BIN_DIR', getenv('PHP_PEAR_BIN_DIR')); +} else { + define('PEAR_CONFIG_DEFAULT_BIN_DIR', PHP_BINDIR); +} + +// Default for data_dir +if (getenv('PHP_PEAR_DATA_DIR')) { + define('PEAR_CONFIG_DEFAULT_DATA_DIR', getenv('PHP_PEAR_DATA_DIR')); +} else { + define('PEAR_CONFIG_DEFAULT_DATA_DIR', + $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'data'); +} + +// Default for cfg_dir +if (getenv('PHP_PEAR_CFG_DIR')) { + define('PEAR_CONFIG_DEFAULT_CFG_DIR', getenv('PHP_PEAR_CFG_DIR')); +} else { + define('PEAR_CONFIG_DEFAULT_CFG_DIR', + $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'cfg'); +} + +// Default for www_dir +if (getenv('PHP_PEAR_WWW_DIR')) { + define('PEAR_CONFIG_DEFAULT_WWW_DIR', getenv('PHP_PEAR_WWW_DIR')); +} else { + define('PEAR_CONFIG_DEFAULT_WWW_DIR', + $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'www'); +} + +// Default for test_dir +if (getenv('PHP_PEAR_TEST_DIR')) { + define('PEAR_CONFIG_DEFAULT_TEST_DIR', getenv('PHP_PEAR_TEST_DIR')); +} else { + define('PEAR_CONFIG_DEFAULT_TEST_DIR', + $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'tests'); +} + +// Default for temp_dir +if (getenv('PHP_PEAR_TEMP_DIR')) { + define('PEAR_CONFIG_DEFAULT_TEMP_DIR', getenv('PHP_PEAR_TEMP_DIR')); +} else { + define('PEAR_CONFIG_DEFAULT_TEMP_DIR', + System::tmpdir() . DIRECTORY_SEPARATOR . 'pear' . + DIRECTORY_SEPARATOR . 'temp'); +} + +// Default for cache_dir +if (getenv('PHP_PEAR_CACHE_DIR')) { + define('PEAR_CONFIG_DEFAULT_CACHE_DIR', getenv('PHP_PEAR_CACHE_DIR')); +} else { + define('PEAR_CONFIG_DEFAULT_CACHE_DIR', + System::tmpdir() . DIRECTORY_SEPARATOR . 'pear' . + DIRECTORY_SEPARATOR . 'cache'); +} + +// Default for download_dir +if (getenv('PHP_PEAR_DOWNLOAD_DIR')) { + define('PEAR_CONFIG_DEFAULT_DOWNLOAD_DIR', getenv('PHP_PEAR_DOWNLOAD_DIR')); +} else { + define('PEAR_CONFIG_DEFAULT_DOWNLOAD_DIR', + System::tmpdir() . DIRECTORY_SEPARATOR . 'pear' . + DIRECTORY_SEPARATOR . 'download'); +} + +// Default for php_bin +if (getenv('PHP_PEAR_PHP_BIN')) { + define('PEAR_CONFIG_DEFAULT_PHP_BIN', getenv('PHP_PEAR_PHP_BIN')); +} else { + define('PEAR_CONFIG_DEFAULT_PHP_BIN', PEAR_CONFIG_DEFAULT_BIN_DIR. + DIRECTORY_SEPARATOR.'php'.(OS_WINDOWS ? '.exe' : '')); +} + +// Default for verbose +if (getenv('PHP_PEAR_VERBOSE')) { + define('PEAR_CONFIG_DEFAULT_VERBOSE', getenv('PHP_PEAR_VERBOSE')); +} else { + define('PEAR_CONFIG_DEFAULT_VERBOSE', 1); +} + +// Default for preferred_state +if (getenv('PHP_PEAR_PREFERRED_STATE')) { + define('PEAR_CONFIG_DEFAULT_PREFERRED_STATE', getenv('PHP_PEAR_PREFERRED_STATE')); +} else { + define('PEAR_CONFIG_DEFAULT_PREFERRED_STATE', 'stable'); +} + +// Default for umask +if (getenv('PHP_PEAR_UMASK')) { + define('PEAR_CONFIG_DEFAULT_UMASK', getenv('PHP_PEAR_UMASK')); +} else { + define('PEAR_CONFIG_DEFAULT_UMASK', decoct(umask())); +} + +// Default for cache_ttl +if (getenv('PHP_PEAR_CACHE_TTL')) { + define('PEAR_CONFIG_DEFAULT_CACHE_TTL', getenv('PHP_PEAR_CACHE_TTL')); +} else { + define('PEAR_CONFIG_DEFAULT_CACHE_TTL', 3600); +} + +// Default for sig_type +if (getenv('PHP_PEAR_SIG_TYPE')) { + define('PEAR_CONFIG_DEFAULT_SIG_TYPE', getenv('PHP_PEAR_SIG_TYPE')); +} else { + define('PEAR_CONFIG_DEFAULT_SIG_TYPE', 'gpg'); +} + +// Default for sig_bin +if (getenv('PHP_PEAR_SIG_BIN')) { + define('PEAR_CONFIG_DEFAULT_SIG_BIN', getenv('PHP_PEAR_SIG_BIN')); +} else { + define('PEAR_CONFIG_DEFAULT_SIG_BIN', + System::which( + 'gpg', OS_WINDOWS ? 'c:\gnupg\gpg.exe' : '/usr/local/bin/gpg')); +} + +// Default for sig_keydir +if (getenv('PHP_PEAR_SIG_KEYDIR')) { + define('PEAR_CONFIG_DEFAULT_SIG_KEYDIR', getenv('PHP_PEAR_SIG_KEYDIR')); +} else { + define('PEAR_CONFIG_DEFAULT_SIG_KEYDIR', + PEAR_CONFIG_SYSCONFDIR . DIRECTORY_SEPARATOR . 'pearkeys'); +} + +/** + * This is a class for storing configuration data, keeping track of + * which are system-defined, user-defined or defaulted. + * @category pear + * @package PEAR + * @author Stig Bakken + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 0.1 + */ +class PEAR_Config extends PEAR +{ + // {{{ properties + + /** + * Array of config files used. + * + * @var array layer => config file + */ + var $files = array( + 'system' => '', + 'user' => '', + ); + + var $layers = array(); + + /** + * Configuration data, two-dimensional array where the first + * dimension is the config layer ('user', 'system' and 'default'), + * and the second dimension is keyname => value. + * + * The order in the first dimension is important! Earlier + * layers will shadow later ones when a config value is + * requested (if a 'user' value exists, it will be returned first, + * then 'system' and finally 'default'). + * + * @var array layer => array(keyname => value, ...) + */ + var $configuration = array( + 'user' => array(), + 'system' => array(), + 'default' => array(), + ); + + /** + * Configuration values that can be set for a channel + * + * All other configuration values can only have a global value + * @var array + * @access private + */ + var $_channelConfigInfo = array( + 'php_dir', 'ext_dir', 'doc_dir', 'bin_dir', 'data_dir', 'cfg_dir', + 'test_dir', 'www_dir', 'php_bin', 'username', 'password', 'verbose', + 'preferred_state', 'umask', 'preferred_mirror', 'php_ini' + ); + + /** + * Channels that can be accessed + * @see setChannels() + * @var array + * @access private + */ + var $_channels = array('pear.php.net', 'pecl.php.net', '__uri'); + + /** + * This variable is used to control the directory values returned + * @see setInstallRoot(); + * @var string|false + * @access private + */ + var $_installRoot = false; + + /** + * If requested, this will always refer to the registry + * contained in php_dir + * @var PEAR_Registry + */ + var $_registry = array(); + + /** + * @var array + * @access private + */ + var $_regInitialized = array(); + + /** + * @var bool + * @access private + */ + var $_noRegistry = false; + + /** + * amount of errors found while parsing config + * @var integer + * @access private + */ + var $_errorsFound = 0; + var $_lastError = null; + + /** + * Information about the configuration data. Stores the type, + * default value and a documentation string for each configuration + * value. + * + * @var array layer => array(infotype => value, ...) + */ + var $configuration_info = array( + // Channels/Internet Access + 'default_channel' => array( + 'type' => 'string', + 'default' => PEAR_CONFIG_DEFAULT_CHANNEL, + 'doc' => 'the default channel to use for all non explicit commands', + 'prompt' => 'Default Channel', + 'group' => 'Internet Access', + ), + 'preferred_mirror' => array( + 'type' => 'string', + 'default' => PEAR_CONFIG_DEFAULT_CHANNEL, + 'doc' => 'the default server or mirror to use for channel actions', + 'prompt' => 'Default Channel Mirror', + 'group' => 'Internet Access', + ), + 'remote_config' => array( + 'type' => 'password', + 'default' => '', + 'doc' => 'ftp url of remote configuration file to use for synchronized install', + 'prompt' => 'Remote Configuration File', + 'group' => 'Internet Access', + ), + 'auto_discover' => array( + 'type' => 'integer', + 'default' => 0, + 'doc' => 'whether to automatically discover new channels', + 'prompt' => 'Auto-discover new Channels', + 'group' => 'Internet Access', + ), + // Internet Access + 'master_server' => array( + 'type' => 'string', + 'default' => 'pear.php.net', + 'doc' => 'name of the main PEAR server [NOT USED IN THIS VERSION]', + 'prompt' => 'PEAR server [DEPRECATED]', + 'group' => 'Internet Access', + ), + 'http_proxy' => array( + 'type' => 'string', + 'default' => PEAR_CONFIG_DEFAULT_HTTP_PROXY, + 'doc' => 'HTTP proxy (host:port) to use when downloading packages', + 'prompt' => 'HTTP Proxy Server Address', + 'group' => 'Internet Access', + ), + // File Locations + 'php_dir' => array( + 'type' => 'directory', + 'default' => PEAR_CONFIG_DEFAULT_PHP_DIR, + 'doc' => 'directory where .php files are installed', + 'prompt' => 'PEAR directory', + 'group' => 'File Locations', + ), + 'ext_dir' => array( + 'type' => 'directory', + 'default' => PEAR_CONFIG_DEFAULT_EXT_DIR, + 'doc' => 'directory where loadable extensions are installed', + 'prompt' => 'PHP extension directory', + 'group' => 'File Locations', + ), + 'doc_dir' => array( + 'type' => 'directory', + 'default' => PEAR_CONFIG_DEFAULT_DOC_DIR, + 'doc' => 'directory where documentation is installed', + 'prompt' => 'PEAR documentation directory', + 'group' => 'File Locations', + ), + 'bin_dir' => array( + 'type' => 'directory', + 'default' => PEAR_CONFIG_DEFAULT_BIN_DIR, + 'doc' => 'directory where executables are installed', + 'prompt' => 'PEAR executables directory', + 'group' => 'File Locations', + ), + 'data_dir' => array( + 'type' => 'directory', + 'default' => PEAR_CONFIG_DEFAULT_DATA_DIR, + 'doc' => 'directory where data files are installed', + 'prompt' => 'PEAR data directory', + 'group' => 'File Locations (Advanced)', + ), + 'cfg_dir' => array( + 'type' => 'directory', + 'default' => PEAR_CONFIG_DEFAULT_CFG_DIR, + 'doc' => 'directory where modifiable configuration files are installed', + 'prompt' => 'PEAR configuration file directory', + 'group' => 'File Locations (Advanced)', + ), + 'www_dir' => array( + 'type' => 'directory', + 'default' => PEAR_CONFIG_DEFAULT_WWW_DIR, + 'doc' => 'directory where www frontend files (html/js) are installed', + 'prompt' => 'PEAR www files directory', + 'group' => 'File Locations (Advanced)', + ), + 'test_dir' => array( + 'type' => 'directory', + 'default' => PEAR_CONFIG_DEFAULT_TEST_DIR, + 'doc' => 'directory where regression tests are installed', + 'prompt' => 'PEAR test directory', + 'group' => 'File Locations (Advanced)', + ), + 'cache_dir' => array( + 'type' => 'directory', + 'default' => PEAR_CONFIG_DEFAULT_CACHE_DIR, + 'doc' => 'directory which is used for XMLRPC cache', + 'prompt' => 'PEAR Installer cache directory', + 'group' => 'File Locations (Advanced)', + ), + 'temp_dir' => array( + 'type' => 'directory', + 'default' => PEAR_CONFIG_DEFAULT_TEMP_DIR, + 'doc' => 'directory which is used for all temp files', + 'prompt' => 'PEAR Installer temp directory', + 'group' => 'File Locations (Advanced)', + ), + 'download_dir' => array( + 'type' => 'directory', + 'default' => PEAR_CONFIG_DEFAULT_DOWNLOAD_DIR, + 'doc' => 'directory which is used for all downloaded files', + 'prompt' => 'PEAR Installer download directory', + 'group' => 'File Locations (Advanced)', + ), + 'php_bin' => array( + 'type' => 'file', + 'default' => PEAR_CONFIG_DEFAULT_PHP_BIN, + 'doc' => 'PHP CLI/CGI binary for executing scripts', + 'prompt' => 'PHP CLI/CGI binary', + 'group' => 'File Locations (Advanced)', + ), + 'php_ini' => array( + 'type' => 'file', + 'default' => '', + 'doc' => 'location of php.ini in which to enable PECL extensions on install', + 'prompt' => 'php.ini location', + 'group' => 'File Locations (Advanced)', + ), + // Maintainers + 'username' => array( + 'type' => 'string', + 'default' => '', + 'doc' => '(maintainers) your PEAR account name', + 'prompt' => 'PEAR username (for maintainers)', + 'group' => 'Maintainers', + ), + 'password' => array( + 'type' => 'password', + 'default' => '', + 'doc' => '(maintainers) your PEAR account password', + 'prompt' => 'PEAR password (for maintainers)', + 'group' => 'Maintainers', + ), + // Advanced + 'verbose' => array( + 'type' => 'integer', + 'default' => PEAR_CONFIG_DEFAULT_VERBOSE, + 'doc' => 'verbosity level +0: really quiet +1: somewhat quiet +2: verbose +3: debug', + 'prompt' => 'Debug Log Level', + 'group' => 'Advanced', + ), + 'preferred_state' => array( + 'type' => 'set', + 'default' => PEAR_CONFIG_DEFAULT_PREFERRED_STATE, + 'doc' => 'the installer will prefer releases with this state when installing packages without a version or state specified', + 'valid_set' => array( + 'stable', 'beta', 'alpha', 'devel', 'snapshot'), + 'prompt' => 'Preferred Package State', + 'group' => 'Advanced', + ), + 'umask' => array( + 'type' => 'mask', + 'default' => PEAR_CONFIG_DEFAULT_UMASK, + 'doc' => 'umask used when creating files (Unix-like systems only)', + 'prompt' => 'Unix file mask', + 'group' => 'Advanced', + ), + 'cache_ttl' => array( + 'type' => 'integer', + 'default' => PEAR_CONFIG_DEFAULT_CACHE_TTL, + 'doc' => 'amount of secs where the local cache is used and not updated', + 'prompt' => 'Cache TimeToLive', + 'group' => 'Advanced', + ), + 'sig_type' => array( + 'type' => 'set', + 'default' => PEAR_CONFIG_DEFAULT_SIG_TYPE, + 'doc' => 'which package signature mechanism to use', + 'valid_set' => array('gpg'), + 'prompt' => 'Package Signature Type', + 'group' => 'Maintainers', + ), + 'sig_bin' => array( + 'type' => 'string', + 'default' => PEAR_CONFIG_DEFAULT_SIG_BIN, + 'doc' => 'which package signature mechanism to use', + 'prompt' => 'Signature Handling Program', + 'group' => 'Maintainers', + ), + 'sig_keyid' => array( + 'type' => 'string', + 'default' => '', + 'doc' => 'which key to use for signing with', + 'prompt' => 'Signature Key Id', + 'group' => 'Maintainers', + ), + 'sig_keydir' => array( + 'type' => 'directory', + 'default' => PEAR_CONFIG_DEFAULT_SIG_KEYDIR, + 'doc' => 'directory where signature keys are located', + 'prompt' => 'Signature Key Directory', + 'group' => 'Maintainers', + ), + // __channels is reserved - used for channel-specific configuration + ); + + // }}} + + // {{{ PEAR_Config([file], [defaults_file]) + + /** + * Constructor. + * + * @param string file to read user-defined options from + * @param string file to read system-wide defaults from + * @param bool determines whether a registry object "follows" + * the value of php_dir (is automatically created + * and moved when php_dir is changed) + * @param bool if true, fails if configuration files cannot be loaded + * + * @access public + * + * @see PEAR_Config::singleton + */ + function PEAR_Config($user_file = '', $system_file = '', $ftp_file = false, + $strict = true) + { + $this->PEAR(); + PEAR_Installer_Role::initializeConfig($this); + $sl = DIRECTORY_SEPARATOR; + if (empty($user_file)) { + if (OS_WINDOWS) { + $user_file = PEAR_CONFIG_SYSCONFDIR . $sl . 'pear.ini'; + } else { + $user_file = getenv('HOME') . $sl . '.pearrc'; + } + } + if (empty($system_file)) { + if (OS_WINDOWS) { + $system_file = PEAR_CONFIG_SYSCONFDIR . $sl . 'pearsys.ini'; + } else { + $system_file = PEAR_CONFIG_SYSCONFDIR . $sl . 'pear.conf'; + } + } + + $this->layers = array_keys($this->configuration); + $this->files['user'] = $user_file; + $this->files['system'] = $system_file; + if ($user_file && file_exists($user_file)) { + $this->pushErrorHandling(PEAR_ERROR_RETURN); + $this->readConfigFile($user_file, 'user', $strict); + $this->popErrorHandling(); + if ($this->_errorsFound > 0) { + return; + } + } + + if ($system_file && file_exists($system_file)) { + $this->mergeConfigFile($system_file, false, 'system', $strict); + if ($this->_errorsFound > 0) { + return; + } + + } + + if (!$ftp_file) { + $ftp_file = $this->get('remote_config'); + } + + if ($ftp_file && defined('PEAR_REMOTEINSTALL_OK')) { + $this->readFTPConfigFile($ftp_file); + } + + foreach ($this->configuration_info as $key => $info) { + $this->configuration['default'][$key] = $info['default']; + } + + $this->_registry['default'] = &new PEAR_Registry($this->configuration['default']['php_dir']); + $this->_registry['default']->setConfig($this, false); + $this->_regInitialized['default'] = false; + //$GLOBALS['_PEAR_Config_instance'] = &$this; + } + + // }}} + /** + * Return the default locations of user and system configuration files + * @static + */ + function getDefaultConfigFiles() + { + $sl = DIRECTORY_SEPARATOR; + if (OS_WINDOWS) { + return array( + 'user' => PEAR_CONFIG_SYSCONFDIR . $sl . 'pear.ini', + 'system' => PEAR_CONFIG_SYSCONFDIR . $sl . 'pearsys.ini' + ); + } else { + return array( + 'user' => getenv('HOME') . $sl . '.pearrc', + 'system' => PEAR_CONFIG_SYSCONFDIR . $sl . 'pear.conf' + ); + } + } + // {{{ singleton([file], [defaults_file]) + + /** + * Static singleton method. If you want to keep only one instance + * of this class in use, this method will give you a reference to + * the last created PEAR_Config object if one exists, or create a + * new object. + * + * @param string (optional) file to read user-defined options from + * @param string (optional) file to read system-wide defaults from + * + * @return object an existing or new PEAR_Config instance + * + * @access public + * + * @see PEAR_Config::PEAR_Config + */ + function &singleton($user_file = '', $system_file = '', $strict = true) + { + if (is_object($GLOBALS['_PEAR_Config_instance'])) { + return $GLOBALS['_PEAR_Config_instance']; + } + + $t_conf = &new PEAR_Config($user_file, $system_file, false, $strict); + if ($t_conf->_errorsFound > 0) { + return $t_conf->lastError; + } + + $GLOBALS['_PEAR_Config_instance'] = &$t_conf; + return $GLOBALS['_PEAR_Config_instance']; + } + + // }}} + // {{{ validConfiguration() + + /** + * Determine whether any configuration files have been detected, and whether a + * registry object can be retrieved from this configuration. + * @return bool + * @since PEAR 1.4.0a1 + */ + function validConfiguration() + { + if ($this->isDefinedLayer('user') || $this->isDefinedLayer('system')) { + return true; + } + return false; + } + + // }}} + // {{{ readConfigFile([file], [layer]) + + /** + * Reads configuration data from a file. All existing values in + * the config layer are discarded and replaced with data from the + * file. + * @param string file to read from, if NULL or not specified, the + * last-used file for the same layer (second param) is used + * @param string config layer to insert data into ('user' or 'system') + * @return bool TRUE on success or a PEAR error on failure + */ + function readConfigFile($file = null, $layer = 'user', $strict = true) + { + if (empty($this->files[$layer])) { + return $this->raiseError("unknown config layer `$layer'"); + } + + if ($file === null) { + $file = $this->files[$layer]; + } + + $data = $this->_readConfigDataFrom($file); + + if (PEAR::isError($data)) { + if ($strict) { + $this->_errorsFound++; + $this->lastError = $data; + + return $data; + } else { + return true; + } + } else { + $this->files[$layer] = $file; + } + + $this->_decodeInput($data); + $this->configuration[$layer] = $data; + $this->_setupChannels(); + if (!$this->_noRegistry && ($phpdir = $this->get('php_dir', $layer, 'pear.php.net'))) { + $this->_registry[$layer] = &new PEAR_Registry($phpdir); + $this->_registry[$layer]->setConfig($this, false); + $this->_regInitialized[$layer] = false; + } else { + unset($this->_registry[$layer]); + } + return true; + } + + // }}} + + /** + * @param string url to the remote config file, like ftp://www.example.com/pear/config.ini + * @return true|PEAR_Error + */ + function readFTPConfigFile($path) + { + do { // poor man's try + if (!class_exists('PEAR_FTP')) { + if (!class_exists('PEAR_Common')) { + require_once 'PEAR/Common.php'; + } + if (PEAR_Common::isIncludeable('PEAR/FTP.php')) { + require_once 'PEAR/FTP.php'; + } + } + if (class_exists('PEAR_FTP')) { + $this->_ftp = &new PEAR_FTP; + $this->_ftp->pushErrorHandling(PEAR_ERROR_RETURN); + $e = $this->_ftp->init($path); + if (PEAR::isError($e)) { + $this->_ftp->popErrorHandling(); + return $e; + } + $tmp = System::mktemp('-d'); + PEAR_Common::addTempFile($tmp); + $e = $this->_ftp->get(basename($path), $tmp . DIRECTORY_SEPARATOR . + 'pear.ini', false, FTP_BINARY); + if (PEAR::isError($e)) { + $this->_ftp->popErrorHandling(); + return $e; + } + PEAR_Common::addTempFile($tmp . DIRECTORY_SEPARATOR . 'pear.ini'); + $this->_ftp->disconnect(); + $this->_ftp->popErrorHandling(); + $this->files['ftp'] = $tmp . DIRECTORY_SEPARATOR . 'pear.ini'; + $e = $this->readConfigFile(null, 'ftp'); + if (PEAR::isError($e)) { + return $e; + } + $fail = array(); + foreach ($this->configuration_info as $key => $val) { + if (in_array($this->getGroup($key), + array('File Locations', 'File Locations (Advanced)')) && + $this->getType($key) == 'directory') { + // any directory configs must be set for this to work + if (!isset($this->configuration['ftp'][$key])) { + $fail[] = $key; + } + } + } + if (count($fail)) { + $fail = '"' . implode('", "', $fail) . '"'; + unset($this->files['ftp']); + unset($this->configuration['ftp']); + return PEAR::raiseError('ERROR: Ftp configuration file must set all ' . + 'directory configuration variables. These variables were not set: ' . + $fail); + } else { + return true; + } + } else { + return PEAR::raiseError('PEAR_RemoteInstaller must be installed to use remote config'); + } + } while (false); // poor man's catch + unset($this->files['ftp']); + return PEAR::raiseError('no remote host specified'); + } + + // {{{ _setupChannels() + + /** + * Reads the existing configurations and creates the _channels array from it + */ + function _setupChannels() + { + $set = array_flip(array_values($this->_channels)); + foreach ($this->configuration as $layer => $data) { + $i = 1000; + if (isset($data['__channels']) && is_array($data['__channels'])) { + foreach ($data['__channels'] as $channel => $info) { + $set[$channel] = $i++; + } + } + } + $this->_channels = array_values(array_flip($set)); + $this->setChannels($this->_channels); + } + + // }}} + // {{{ deleteChannel(channel) + + function deleteChannel($channel) + { + foreach ($this->configuration as $layer => $data) { + if (isset($data['__channels'])) { + if (isset($data['__channels'][strtolower($channel)])) { + unset($this->configuration[$layer]['__channels'][strtolower($channel)]); + } + } + } + $this->_channels = array_flip($this->_channels); + unset($this->_channels[strtolower($channel)]); + $this->_channels = array_flip($this->_channels); + } + + // }}} + // {{{ mergeConfigFile(file, [override], [layer]) + + /** + * Merges data into a config layer from a file. Does the same + * thing as readConfigFile, except it does not replace all + * existing values in the config layer. + * @param string file to read from + * @param bool whether to overwrite existing data (default TRUE) + * @param string config layer to insert data into ('user' or 'system') + * @param string if true, errors are returned if file opening fails + * @return bool TRUE on success or a PEAR error on failure + */ + function mergeConfigFile($file, $override = true, $layer = 'user', $strict = true) + { + if (empty($this->files[$layer])) { + return $this->raiseError("unknown config layer `$layer'"); + } + if ($file === null) { + $file = $this->files[$layer]; + } + $data = $this->_readConfigDataFrom($file); + if (PEAR::isError($data)) { + if ($strict) { + $this->_errorsFound++; + $this->lastError = $data; + + return $data; + } else { + return true; + } + } + $this->_decodeInput($data); + if ($override) { + $this->configuration[$layer] = + PEAR_Config::arrayMergeRecursive($this->configuration[$layer], $data); + } else { + $this->configuration[$layer] = + PEAR_Config::arrayMergeRecursive($data, $this->configuration[$layer]); + } + $this->_setupChannels(); + if (!$this->_noRegistry && ($phpdir = $this->get('php_dir', $layer, 'pear.php.net'))) { + $this->_registry[$layer] = &new PEAR_Registry($phpdir); + $this->_registry[$layer]->setConfig($this, false); + $this->_regInitialized[$layer] = false; + } else { + unset($this->_registry[$layer]); + } + return true; + } + + // }}} + // {{{ arrayMergeRecursive($arr2, $arr1) + /** + * @param array + * @param array + * @return array + * @static + */ + function arrayMergeRecursive($arr2, $arr1) + { + $ret = array(); + foreach ($arr2 as $key => $data) { + if (!isset($arr1[$key])) { + $ret[$key] = $data; + unset($arr1[$key]); + continue; + } + if (is_array($data)) { + if (!is_array($arr1[$key])) { + $ret[$key] = $arr1[$key]; + unset($arr1[$key]); + continue; + } + $ret[$key] = PEAR_Config::arrayMergeRecursive($arr1[$key], $arr2[$key]); + unset($arr1[$key]); + } + } + return array_merge($ret, $arr1); + } + + // }}} + // {{{ writeConfigFile([file], [layer]) + + /** + * Writes data into a config layer from a file. + * + * @param string|null file to read from, or null for default + * @param string config layer to insert data into ('user' or + * 'system') + * @param string|null data to write to config file or null for internal data [DEPRECATED] + * @return bool TRUE on success or a PEAR error on failure + */ + function writeConfigFile($file = null, $layer = 'user', $data = null) + { + $this->_lazyChannelSetup($layer); + if ($layer == 'both' || $layer == 'all') { + foreach ($this->files as $type => $file) { + $err = $this->writeConfigFile($file, $type, $data); + if (PEAR::isError($err)) { + return $err; + } + } + return true; + } + if (empty($this->files[$layer])) { + return $this->raiseError("unknown config file type `$layer'"); + } + if ($file === null) { + $file = $this->files[$layer]; + } + $data = ($data === null) ? $this->configuration[$layer] : $data; + $this->_encodeOutput($data); + $opt = array('-p', dirname($file)); + if (!@System::mkDir($opt)) { + return $this->raiseError("could not create directory: " . dirname($file)); + } + if (file_exists($file) && is_file($file) && !is_writeable($file)) { + return $this->raiseError("no write access to $file!"); + } + $fp = @fopen($file, "w"); + if (!$fp) { + return $this->raiseError("PEAR_Config::writeConfigFile fopen('$file','w') failed ($php_errormsg)"); + } + $contents = "#PEAR_Config 0.9\n" . serialize($data); + if (!@fwrite($fp, $contents)) { + return $this->raiseError("PEAR_Config::writeConfigFile: fwrite failed ($php_errormsg)"); + } + return true; + } + + // }}} + // {{{ _readConfigDataFrom(file) + + /** + * Reads configuration data from a file and returns the parsed data + * in an array. + * + * @param string file to read from + * + * @return array configuration data or a PEAR error on failure + * + * @access private + */ + function _readConfigDataFrom($file) + { + $fp = false; + if (file_exists($file)) { + $fp = @fopen($file, "r"); + } + if (!$fp) { + return $this->raiseError("PEAR_Config::readConfigFile fopen('$file','r') failed"); + } + $size = filesize($file); + $rt = get_magic_quotes_runtime(); + set_magic_quotes_runtime(0); + fclose($fp); + $contents = file_get_contents($file); + if (empty($contents)) { + return $this->raiseError('Configuration file "' . $file . '" is empty'); + } + + set_magic_quotes_runtime($rt); + + $version = false; + if (preg_match('/^#PEAR_Config\s+(\S+)\s+/si', $contents, $matches)) { + $version = $matches[1]; + $contents = substr($contents, strlen($matches[0])); + } else { + // Museum config file + if (substr($contents,0,2) == 'a:') { + $version = '0.1'; + } + } + if ($version && version_compare("$version", '1', '<')) { + + // no '@', it is possible that unserialize + // raises a notice but it seems to block IO to + // STDOUT if a '@' is used and a notice is raise + $data = unserialize($contents); + + if (!is_array($data) && !$data) { + if ($contents == serialize(false)) { + $data = array(); + } else { + $err = $this->raiseError("PEAR_Config: bad data in $file"); + return $err; + } + } + if (!is_array($data)) { + if (strlen(trim($contents)) > 0) { + $error = "PEAR_Config: bad data in $file"; + $err = $this->raiseError($error); + return $err; + } else { + $data = array(); + } + } + // add parsing of newer formats here... + } else { + $err = $this->raiseError("$file: unknown version `$version'"); + return $err; + } + return $data; + } + + // }}} + // {{{ getConfFile(layer) + /** + * Gets the file used for storing the config for a layer + * + * @param string $layer 'user' or 'system' + */ + + function getConfFile($layer) + { + return $this->files[$layer]; + } + + // }}} + + /** + * @param string Configuration class name, used for detecting duplicate calls + * @param array information on a role as parsed from its xml file + * @return true|PEAR_Error + * @access private + */ + function _addConfigVars($class, $vars) + { + static $called = array(); + if (isset($called[$class])) { + return; + } + $called[$class] = 1; + if (count($vars) > 3) { + return $this->raiseError('Roles can only define 3 new config variables or less'); + } + foreach ($vars as $name => $var) { + if (!is_array($var)) { + return $this->raiseError('Configuration information must be an array'); + } + if (!isset($var['type'])) { + return $this->raiseError('Configuration information must contain a type'); + } else { + if (!in_array($var['type'], + array('string', 'mask', 'password', 'directory', 'file', 'set'))) { + return $this->raiseError( + 'Configuration type must be one of directory, file, string, ' . + 'mask, set, or password'); + } + } + if (!isset($var['default'])) { + return $this->raiseError( + 'Configuration information must contain a default value ("default" index)'); + } else { + if (is_array($var['default'])) { + $real_default = ''; + foreach ($var['default'] as $config_var => $val) { + if (strpos($config_var, 'text') === 0) { + $real_default .= $val; + } elseif (strpos($config_var, 'constant') === 0) { + if (defined($val)) { + $real_default .= constant($val); + } else { + return $this->raiseError( + 'Unknown constant "' . $val . '" requested in ' . + 'default value for configuration variable "' . + $name . '"'); + } + } elseif (isset($this->configuration_info[$config_var])) { + $real_default .= + $this->configuration_info[$config_var]['default']; + } else { + return $this->raiseError( + 'Unknown request for "' . $config_var . '" value in ' . + 'default value for configuration variable "' . + $name . '"'); + } + } + $var['default'] = $real_default; + } + if ($var['type'] == 'integer') { + $var['default'] = (integer) $var['default']; + } + } + if (!isset($var['doc'])) { + return $this->raiseError( + 'Configuration information must contain a summary ("doc" index)'); + } + if (!isset($var['prompt'])) { + return $this->raiseError( + 'Configuration information must contain a simple prompt ("prompt" index)'); + } + if (!isset($var['group'])) { + return $this->raiseError( + 'Configuration information must contain a simple group ("group" index)'); + } + if (isset($this->configuration_info[$name])) { + return $this->raiseError('Configuration variable "' . $name . + '" already exists'); + } + $this->configuration_info[$name] = $var; + // fix bug #7351: setting custom config variable in a channel fails + $this->_channelConfigInfo[] = $name; + } + return true; + } + + // {{{ _encodeOutput(&data) + + /** + * Encodes/scrambles configuration data before writing to files. + * Currently, 'password' values will be base64-encoded as to avoid + * that people spot cleartext passwords by accident. + * + * @param array (reference) array to encode values in + * + * @return bool TRUE on success + * + * @access private + */ + function _encodeOutput(&$data) + { + foreach ($data as $key => $value) { + if ($key == '__channels') { + foreach ($data['__channels'] as $channel => $blah) { + $this->_encodeOutput($data['__channels'][$channel]); + } + } + if (!isset($this->configuration_info[$key])) { + continue; + } + $type = $this->configuration_info[$key]['type']; + switch ($type) { + // we base64-encode passwords so they are at least + // not shown in plain by accident + case 'password': { + $data[$key] = base64_encode($data[$key]); + break; + } + case 'mask': { + $data[$key] = octdec($data[$key]); + break; + } + } + } + return true; + } + + // }}} + // {{{ _decodeInput(&data) + + /** + * Decodes/unscrambles configuration data after reading from files. + * + * @param array (reference) array to encode values in + * + * @return bool TRUE on success + * + * @access private + * + * @see PEAR_Config::_encodeOutput + */ + function _decodeInput(&$data) + { + if (!is_array($data)) { + return true; + } + foreach ($data as $key => $value) { + if ($key == '__channels') { + foreach ($data['__channels'] as $channel => $blah) { + $this->_decodeInput($data['__channels'][$channel]); + } + } + if (!isset($this->configuration_info[$key])) { + continue; + } + $type = $this->configuration_info[$key]['type']; + switch ($type) { + case 'password': { + $data[$key] = base64_decode($data[$key]); + break; + } + case 'mask': { + $data[$key] = decoct($data[$key]); + break; + } + } + } + return true; + } + + // }}} + // {{{ getDefaultChannel([layer]) + /** + * Retrieve the default channel. + * + * On startup, channels are not initialized, so if the default channel is not + * pear.php.net, then initialize the config. + * @param string registry layer + * @return string|false + */ + function getDefaultChannel($layer = null) + { + $ret = false; + if ($layer === null) { + foreach ($this->layers as $layer) { + if (isset($this->configuration[$layer]['default_channel'])) { + $ret = $this->configuration[$layer]['default_channel']; + break; + } + } + } elseif (isset($this->configuration[$layer]['default_channel'])) { + $ret = $this->configuration[$layer]['default_channel']; + } + if ($ret == 'pear.php.net' && defined('PEAR_RUNTYPE') && PEAR_RUNTYPE == 'pecl') { + $ret = 'pecl.php.net'; + } + if ($ret) { + if ($ret != 'pear.php.net') { + $this->_lazyChannelSetup(); + } + return $ret; + } + return PEAR_CONFIG_DEFAULT_CHANNEL; + } + + // {{{ get(key, [layer]) + /** + * Returns a configuration value, prioritizing layers as per the + * layers property. + * + * @param string config key + * + * @return mixed the config value, or NULL if not found + * + * @access public + */ + function get($key, $layer = null, $channel = false) + { + if (!isset($this->configuration_info[$key])) { + return null; + } + if ($key == '__channels') { + return null; + } + if ($key == 'default_channel') { + return $this->getDefaultChannel($layer); + } + if (!$channel) { + $channel = $this->getDefaultChannel(); + } elseif ($channel != 'pear.php.net') { + $this->_lazyChannelSetup(); + } + $channel = strtolower($channel); + + $test = (in_array($key, $this->_channelConfigInfo)) ? + $this->_getChannelValue($key, $layer, $channel) : + null; + if ($test !== null) { + if ($this->_installRoot) { + if (in_array($this->getGroup($key), + array('File Locations', 'File Locations (Advanced)')) && + $this->getType($key) == 'directory') { + return $this->_prependPath($test, $this->_installRoot); + } + } + return $test; + } + if ($layer === null) { + foreach ($this->layers as $layer) { + if (isset($this->configuration[$layer][$key])) { + $test = $this->configuration[$layer][$key]; + if ($this->_installRoot) { + if (in_array($this->getGroup($key), + array('File Locations', 'File Locations (Advanced)')) && + $this->getType($key) == 'directory') { + return $this->_prependPath($test, $this->_installRoot); + } + } + if ($key == 'preferred_mirror') { + $reg = &$this->getRegistry(); + if (is_object($reg)) { + $chan = &$reg->getChannel($channel); + if (PEAR::isError($chan)) { + return $channel; + } + if (!$chan->getMirror($test) && $chan->getName() != $test) { + return $channel; // mirror does not exist + } + } + } + return $test; + } + } + } elseif (isset($this->configuration[$layer][$key])) { + $test = $this->configuration[$layer][$key]; + if ($this->_installRoot) { + if (in_array($this->getGroup($key), + array('File Locations', 'File Locations (Advanced)')) && + $this->getType($key) == 'directory') { + return $this->_prependPath($test, $this->_installRoot); + } + } + if ($key == 'preferred_mirror') { + $reg = &$this->getRegistry(); + if (is_object($reg)) { + $chan = &$reg->getChannel($channel); + if (PEAR::isError($chan)) { + return $channel; + } + if (!$chan->getMirror($test) && $chan->getName() != $test) { + return $channel; // mirror does not exist + } + } + } + return $test; + } + return null; + } + + // }}} + // {{{ _getChannelValue(key, value, [layer]) + /** + * Returns a channel-specific configuration value, prioritizing layers as per the + * layers property. + * + * @param string config key + * + * @return mixed the config value, or NULL if not found + * + * @access private + */ + function _getChannelValue($key, $layer, $channel) + { + if ($key == '__channels' || $channel == 'pear.php.net') { + return null; + } + $ret = null; + if ($layer === null) { + foreach ($this->layers as $ilayer) { + if (isset($this->configuration[$ilayer]['__channels'][$channel][$key])) { + $ret = $this->configuration[$ilayer]['__channels'][$channel][$key]; + break; + } + } + } elseif (isset($this->configuration[$layer]['__channels'][$channel][$key])) { + $ret = $this->configuration[$layer]['__channels'][$channel][$key]; + } + if ($key == 'preferred_mirror') { + if ($ret !== null) { + $reg = &$this->getRegistry($layer); + if (is_object($reg)) { + $chan = &$reg->getChannel($channel); + if (PEAR::isError($chan)) { + return $channel; + } + if (!$chan->getMirror($ret) && $chan->getName() != $ret) { + return $channel; // mirror does not exist + } + } + return $ret; + } + if ($channel != $this->getDefaultChannel($layer)) { + return $channel; // we must use the channel name as the preferred mirror + // if the user has not chosen an alternate + } else { + return $this->getDefaultChannel($layer); + } + } + return $ret; + } + + + // }}} + // {{{ set(key, value, [layer]) + + /** + * Set a config value in a specific layer (defaults to 'user'). + * Enforces the types defined in the configuration_info array. An + * integer config variable will be cast to int, and a set config + * variable will be validated against its legal values. + * + * @param string config key + * @param string config value + * @param string (optional) config layer + * @param string channel to set this value for, or null for global value + * @return bool TRUE on success, FALSE on failure + */ + function set($key, $value, $layer = 'user', $channel = false) + { + if ($key == '__channels') { + return false; + } + if (!isset($this->configuration[$layer])) { + return false; + } + if ($key == 'default_channel') { + // can only set this value globally + $channel = 'pear.php.net'; + if ($value != 'pear.php.net') { + $this->_lazyChannelSetup($layer); + } + } + if ($key == 'preferred_mirror') { + if ($channel == '__uri') { + return false; // can't set the __uri pseudo-channel's mirror + } + $reg = &$this->getRegistry($layer); + if (is_object($reg)) { + $chan = &$reg->getChannel($channel ? $channel : 'pear.php.net'); + if (PEAR::isError($chan)) { + return false; + } + if (!$chan->getMirror($value) && $chan->getName() != $value) { + return false; // mirror does not exist + } + } + } + if (!isset($this->configuration_info[$key])) { + return false; + } + extract($this->configuration_info[$key]); + switch ($type) { + case 'integer': + $value = (int)$value; + break; + case 'set': { + // If a valid_set is specified, require the value to + // be in the set. If there is no valid_set, accept + // any value. + if ($valid_set) { + reset($valid_set); + if ((key($valid_set) === 0 && !in_array($value, $valid_set)) || + (key($valid_set) !== 0 && empty($valid_set[$value]))) + { + return false; + } + } + break; + } + } + if (!$channel) { + $channel = $this->get('default_channel', null, 'pear.php.net'); + } + if (!in_array($channel, $this->_channels)) { + $this->_lazyChannelSetup($layer); + $reg = &$this->getRegistry($layer); + if ($reg) { + $channel = $reg->channelName($channel); + } + if (!in_array($channel, $this->_channels)) { + return false; + } + } + if ($channel != 'pear.php.net') { + if (in_array($key, $this->_channelConfigInfo)) { + $this->configuration[$layer]['__channels'][$channel][$key] = $value; + return true; + } else { + return false; + } + } else { + if ($key == 'default_channel') { + if (!isset($reg)) { + $reg = &$this->getRegistry($layer); + if (!$reg) { + $reg = &$this->getRegistry(); + } + } + if ($reg) { + $value = $reg->channelName($value); + } + if (!$value) { + return false; + } + } + } + $this->configuration[$layer][$key] = $value; + if ($key == 'php_dir' && !$this->_noRegistry) { + if (!isset($this->_registry[$layer]) || + $value != $this->_registry[$layer]->install_dir) { + $this->_registry[$layer] = &new PEAR_Registry($value); + $this->_regInitialized[$layer] = false; + $this->_registry[$layer]->setConfig($this, false); + } + } + return true; + } + + // }}} + function _lazyChannelSetup($uselayer = false) + { + if ($this->_noRegistry) { + return; + } + $merge = false; + foreach ($this->_registry as $layer => $p) { + if ($uselayer && $uselayer != $layer) { + continue; + } + if (!$this->_regInitialized[$layer]) { + if ($layer == 'default' && isset($this->_registry['user']) || + isset($this->_registry['system'])) { + // only use the default registry if there are no alternatives + continue; + } + if (!is_object($this->_registry[$layer])) { + if ($phpdir = $this->get('php_dir', $layer, 'pear.php.net')) { + $this->_registry[$layer] = &new PEAR_Registry($phpdir); + $this->_registry[$layer]->setConfig($this, false); + $this->_regInitialized[$layer] = false; + } else { + unset($this->_registry[$layer]); + return; + } + } + $this->setChannels($this->_registry[$layer]->listChannels(), $merge); + $this->_regInitialized[$layer] = true; + $merge = true; + } + } + } + // {{{ setChannels() + + /** + * Set the list of channels. + * + * This should be set via a call to {@link PEAR_Registry::listChannels()} + * @param array + * @param bool + * @return bool success of operation + */ + function setChannels($channels, $merge = false) + { + if (!is_array($channels)) { + return false; + } + if ($merge) { + $this->_channels = array_merge($this->_channels, $channels); + } else { + $this->_channels = $channels; + } + foreach ($channels as $channel) { + $channel = strtolower($channel); + if ($channel == 'pear.php.net') { + continue; + } + foreach ($this->layers as $layer) { + if (!isset($this->configuration[$layer]['__channels'])) { + $this->configuration[$layer]['__channels'] = array(); + } + if (!isset($this->configuration[$layer]['__channels'][$channel]) + || !is_array($this->configuration[$layer]['__channels'][$channel])) { + $this->configuration[$layer]['__channels'][$channel] = array(); + } + } + } + return true; + } + + // }}} + // {{{ getType(key) + + /** + * Get the type of a config value. + * + * @param string config key + * + * @return string type, one of "string", "integer", "file", + * "directory", "set" or "password". + * + * @access public + * + */ + function getType($key) + { + if (isset($this->configuration_info[$key])) { + return $this->configuration_info[$key]['type']; + } + return false; + } + + // }}} + // {{{ getDocs(key) + + /** + * Get the documentation for a config value. + * + * @param string config key + * + * @return string documentation string + * + * @access public + * + */ + function getDocs($key) + { + if (isset($this->configuration_info[$key])) { + return $this->configuration_info[$key]['doc']; + } + return false; + } + // }}} + // {{{ getPrompt(key) + + /** + * Get the short documentation for a config value. + * + * @param string config key + * + * @return string short documentation string + * + * @access public + * + */ + function getPrompt($key) + { + if (isset($this->configuration_info[$key])) { + return $this->configuration_info[$key]['prompt']; + } + return false; + } + // }}} + // {{{ getGroup(key) + + /** + * Get the parameter group for a config key. + * + * @param string config key + * + * @return string parameter group + * + * @access public + * + */ + function getGroup($key) + { + if (isset($this->configuration_info[$key])) { + return $this->configuration_info[$key]['group']; + } + return false; + } + + // }}} + // {{{ getGroups() + + /** + * Get the list of parameter groups. + * + * @return array list of parameter groups + * + * @access public + * + */ + function getGroups() + { + $tmp = array(); + foreach ($this->configuration_info as $key => $info) { + $tmp[$info['group']] = 1; + } + return array_keys($tmp); + } + + // }}} + // {{{ getGroupKeys() + + /** + * Get the list of the parameters in a group. + * + * @param string $group parameter group + * + * @return array list of parameters in $group + * + * @access public + * + */ + function getGroupKeys($group) + { + $keys = array(); + foreach ($this->configuration_info as $key => $info) { + if ($info['group'] == $group) { + $keys[] = $key; + } + } + return $keys; + } + + // }}} + // {{{ getSetValues(key) + + /** + * Get the list of allowed set values for a config value. Returns + * NULL for config values that are not sets. + * + * @param string config key + * + * @return array enumerated array of set values, or NULL if the + * config key is unknown or not a set + * + * @access public + * + */ + function getSetValues($key) + { + if (isset($this->configuration_info[$key]) && + isset($this->configuration_info[$key]['type']) && + $this->configuration_info[$key]['type'] == 'set') + { + $valid_set = $this->configuration_info[$key]['valid_set']; + reset($valid_set); + if (key($valid_set) === 0) { + return $valid_set; + } + return array_keys($valid_set); + } + return null; + } + + // }}} + // {{{ getKeys() + + /** + * Get all the current config keys. + * + * @return array simple array of config keys + * + * @access public + */ + function getKeys() + { + $keys = array(); + foreach ($this->layers as $layer) { + $test = $this->configuration[$layer]; + if (isset($test['__channels'])) { + foreach ($test['__channels'] as $channel => $configs) { + $keys = array_merge($keys, $configs); + } + } + unset($test['__channels']); + $keys = array_merge($keys, $test); + } + return array_keys($keys); + } + + // }}} + // {{{ remove(key, [layer]) + + /** + * Remove the a config key from a specific config layer. + * + * @param string config key + * + * @param string (optional) config layer + * + * @return bool TRUE on success, FALSE on failure + * + * @access public + */ + function remove($key, $layer = 'user') + { + $channel = $this->getDefaultChannel(); + if ($channel !== 'pear.php.net') { + if (isset($this->configuration[$layer]['__channels'][$channel][$key])) { + unset($this->configuration[$layer]['__channels'][$channel][$key]); + return true; + } + } + if (isset($this->configuration[$layer][$key])) { + unset($this->configuration[$layer][$key]); + return true; + } + return false; + } + + // }}} + // {{{ removeLayer(layer) + + /** + * Temporarily remove an entire config layer. USE WITH CARE! + * + * @param string config key + * + * @param string (optional) config layer + * + * @return bool TRUE on success, FALSE on failure + * + * @access public + */ + function removeLayer($layer) + { + if (isset($this->configuration[$layer])) { + $this->configuration[$layer] = array(); + return true; + } + return false; + } + + // }}} + // {{{ store([layer]) + + /** + * Stores configuration data in a layer. + * + * @param string config layer to store + * + * @return bool TRUE on success, or PEAR error on failure + * + * @access public + */ + function store($layer = 'user', $data = null) + { + return $this->writeConfigFile(null, $layer, $data); + } + + // }}} + // {{{ toDefault(key) + + /** + * Unset the user-defined value of a config key, reverting the + * value to the system-defined one. + * + * @param string config key + * + * @return bool TRUE on success, FALSE on failure + * + * @access public + */ + function toDefault($key) + { + trigger_error("PEAR_Config::toDefault() deprecated, use PEAR_Config::remove() instead", E_USER_NOTICE); + return $this->remove($key, 'user'); + } + + // }}} + // {{{ definedBy(key) + + /** + * Tells what config layer that gets to define a key. + * + * @param string config key + * @param boolean return the defining channel + * + * @return string|array the config layer, or an empty string if not found. + * + * if $returnchannel, the return is an array array('layer' => layername, + * 'channel' => channelname), or an empty string if not found + * + * @access public + */ + function definedBy($key, $returnchannel = false) + { + foreach ($this->layers as $layer) { + $channel = $this->getDefaultChannel(); + if ($channel !== 'pear.php.net') { + if (isset($this->configuration[$layer]['__channels'][$channel][$key])) { + if ($returnchannel) { + return array('layer' => $layer, 'channel' => $channel); + } + return $layer; + } + } + if (isset($this->configuration[$layer][$key])) { + if ($returnchannel) { + return array('layer' => $layer, 'channel' => 'pear.php.net'); + } + return $layer; + } + } + return ''; + } + + // }}} + // {{{ isDefaulted(key) + + /** + * Tells whether a config value has a system-defined value. + * + * @param string config key + * + * @return bool + * + * @access public + * + * @deprecated + */ + function isDefaulted($key) + { + trigger_error("PEAR_Config::isDefaulted() deprecated, use PEAR_Config::definedBy() instead", E_USER_NOTICE); + return $this->definedBy($key) == 'system'; + } + + // }}} + // {{{ isDefined(key) + + /** + * Tells whether a given key exists as a config value. + * + * @param string config key + * + * @return bool whether exists in this object + * + * @access public + */ + function isDefined($key) + { + foreach ($this->layers as $layer) { + if (isset($this->configuration[$layer][$key])) { + return true; + } + } + return false; + } + + // }}} + // {{{ isDefinedLayer(key) + + /** + * Tells whether a given config layer exists. + * + * @param string config layer + * + * @return bool whether exists in this object + * + * @access public + */ + function isDefinedLayer($layer) + { + return isset($this->configuration[$layer]); + } + + // }}} + // {{{ getLayers() + + /** + * Returns the layers defined (except the 'default' one) + * + * @return array of the defined layers + */ + function getLayers() + { + $cf = $this->configuration; + unset($cf['default']); + return array_keys($cf); + } + + // }}} + // {{{ apiVersion() + function apiVersion() + { + return '1.1'; + } + // }}} + + /** + * @return PEAR_Registry + */ + function &getRegistry($use = null) + { + if ($use === null) { + $layer = 'user'; + } else { + $layer = $use; + } + if (isset($this->_registry[$layer])) { + return $this->_registry[$layer]; + } elseif ($use === null && isset($this->_registry['system'])) { + return $this->_registry['system']; + } elseif ($use === null && isset($this->_registry['default'])) { + return $this->_registry['default']; + } elseif ($use) { + $a = false; + return $a; + } else { + // only go here if null was passed in + echo "CRITICAL ERROR: Registry could not be initialized from any value"; + exit(1); + } + } + /** + * This is to allow customization like the use of installroot + * @param PEAR_Registry + * @return bool + */ + function setRegistry(&$reg, $layer = 'user') + { + if ($this->_noRegistry) { + return false; + } + if (!in_array($layer, array('user', 'system'))) { + return false; + } + $this->_registry[$layer] = &$reg; + if (is_object($reg)) { + $this->_registry[$layer]->setConfig($this, false); + } + return true; + } + + function noRegistry() + { + $this->_noRegistry = true; + } + + /** + * @return PEAR_Remote + */ + function &getRemote() + { + $remote = &new PEAR_Remote($this); + return $remote; + } + + /** + * @return PEAR_REST + */ + function &getREST($version, $options = array()) + { + $version = str_replace('.', '', $version); + if (!class_exists($class = 'PEAR_REST_' . $version)) { + require_once 'PEAR/REST/' . $version . '.php'; + } + $remote = &new $class($this, $options); + return $remote; + } + + /** + * The ftp server is set in {@link readFTPConfigFile()}. It exists only if a + * remote configuration file has been specified + * @return PEAR_FTP|false + */ + function &getFTP() + { + if (isset($this->_ftp)) { + return $this->_ftp; + } else { + $a = false; + return $a; + } + } + + // {{{ _prependPath($path, $prepend) + + function _prependPath($path, $prepend) + { + if (strlen($prepend) > 0) { + if (OS_WINDOWS && preg_match('/^[a-z]:/i', $path)) { + if (preg_match('/^[a-z]:/i', $prepend)) { + $prepend = substr($prepend, 2); + } elseif ($prepend{0} != '\\') { + $prepend = "\\$prepend"; + } + $path = substr($path, 0, 2) . $prepend . substr($path, 2); + } else { + $path = $prepend . $path; + } + } + return $path; + } + // }}} + + /** + * @param string|false installation directory to prepend to all _dir variables, or false to + * disable + */ + function setInstallRoot($root) + { + if (substr($root, -1) == DIRECTORY_SEPARATOR) { + $root = substr($root, 0, -1); + } + $old = $this->_installRoot; + $this->_installRoot = $root; + if (($old != $root) && !$this->_noRegistry) { + foreach (array_keys($this->_registry) as $layer) { + if ($layer == 'ftp' || !isset($this->_registry[$layer])) { + continue; + } + $this->_registry[$layer] = + &new PEAR_Registry($this->get('php_dir', $layer, 'pear.php.net')); + $this->_registry[$layer]->setConfig($this, false); + $this->_regInitialized[$layer] = false; + } + } + } +} + +?> diff --git a/src/lib/pear/PEAR/PEAR/Dependency.php b/src/lib/pear/PEAR/PEAR/Dependency.php new file mode 100644 index 0000000..0265f6f --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Dependency.php @@ -0,0 +1,498 @@ + + * @author Stig Bakken + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: Dependency.php,v 1.43 2008/01/03 20:26:34 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 1.4.0a1 + */ + +require_once "PEAR.php"; +require_once "OS/Guess.php"; + +define('PEAR_DEPENDENCY_MISSING', -1); +define('PEAR_DEPENDENCY_CONFLICT', -2); +define('PEAR_DEPENDENCY_UPGRADE_MINOR', -3); +define('PEAR_DEPENDENCY_UPGRADE_MAJOR', -4); +define('PEAR_DEPENDENCY_BAD_DEPENDENCY', -5); +define('PEAR_DEPENDENCY_MISSING_OPTIONAL', -6); +define('PEAR_DEPENDENCY_CONFLICT_OPTIONAL', -7); +define('PEAR_DEPENDENCY_UPGRADE_MINOR_OPTIONAL', -8); +define('PEAR_DEPENDENCY_UPGRADE_MAJOR_OPTIONAL', -9); + +/** + * Dependency check for PEAR packages + * + * The class is based on the dependency RFC that can be found at + * http://cvs.php.net/cvs.php/pearweb/rfc. It requires PHP >= 4.1 + * + * @author Tomas V.V.Vox + * @author Stig Bakken + */ +class PEAR_Dependency +{ + // {{{ constructor + /** + * Constructor + * + * @access public + * @param object Registry object + * @return void + */ + function PEAR_Dependency(&$registry) + { + $this->registry = &$registry; + } + + // }}} + // {{{ callCheckMethod() + + /** + * This method maps the XML dependency definition to the + * corresponding one from PEAR_Dependency + * + *
    +    * $opts => Array
    +    *    (
    +    *        [type] => pkg
    +    *        [rel] => ge
    +    *        [version] => 3.4
    +    *        [name] => HTML_Common
    +    *        [optional] => false
    +    *    )
    +    * 
    + * + * @param string Error message + * @param array Options + * @return boolean + */ + function callCheckMethod(&$errmsg, $opts) + { + $rel = isset($opts['rel']) ? $opts['rel'] : 'has'; + $req = isset($opts['version']) ? $opts['version'] : null; + $name = isset($opts['name']) ? $opts['name'] : null; + $channel = isset($opts['channel']) ? $opts['channel'] : 'pear.php.net'; + $opt = (isset($opts['optional']) && $opts['optional'] == 'yes') ? + $opts['optional'] : null; + $errmsg = ''; + switch ($opts['type']) { + case 'pkg': + return $this->checkPackage($errmsg, $name, $req, $rel, $opt, $channel); + break; + case 'ext': + return $this->checkExtension($errmsg, $name, $req, $rel, $opt); + break; + case 'php': + return $this->checkPHP($errmsg, $req, $rel); + break; + case 'prog': + return $this->checkProgram($errmsg, $name); + break; + case 'os': + return $this->checkOS($errmsg, $name); + break; + case 'sapi': + return $this->checkSAPI($errmsg, $name); + break; + case 'zend': + return $this->checkZend($errmsg, $name); + break; + default: + return "'{$opts['type']}' dependency type not supported"; + } + } + + // }}} + // {{{ checkPackage() + + /** + * Package dependencies check method + * + * @param string $errmsg Empty string, it will be populated with an error message, if any + * @param string $name Name of the package to test + * @param string $req The package version required + * @param string $relation How to compare versions with each other + * @param bool $opt Whether the relationship is optional + * @param string $channel Channel name + * + * @return mixed bool false if no error or the error string + */ + function checkPackage(&$errmsg, $name, $req = null, $relation = 'has', + $opt = false, $channel = 'pear.php.net') + { + if (is_string($req) && substr($req, 0, 2) == 'v.') { + $req = substr($req, 2); + } + switch ($relation) { + case 'has': + if (!$this->registry->packageExists($name, $channel)) { + if ($opt) { + $errmsg = "package `$channel/$name' is recommended to utilize some features."; + return PEAR_DEPENDENCY_MISSING_OPTIONAL; + } + $errmsg = "requires package `$channel/$name'"; + return PEAR_DEPENDENCY_MISSING; + } + return false; + case 'not': + if ($this->registry->packageExists($name, $channel)) { + $errmsg = "conflicts with package `$channel/$name'"; + return PEAR_DEPENDENCY_CONFLICT; + } + return false; + case 'lt': + case 'le': + case 'eq': + case 'ne': + case 'ge': + case 'gt': + $version = $this->registry->packageInfo($name, 'version', $channel); + if (!$this->registry->packageExists($name, $channel) + || !version_compare("$version", "$req", $relation)) + { + $code = $this->codeFromRelation($relation, $version, $req, $opt); + if ($opt) { + $errmsg = "package `$channel/$name' version " . $this->signOperator($relation) . + " $req is recommended to utilize some features."; + if ($version) { + $errmsg .= " Installed version is $version"; + } + return $code; + } + $errmsg = "requires package `$channel/$name' " . + $this->signOperator($relation) . " $req"; + return $code; + } + return false; + } + $errmsg = "relation '$relation' with requirement '$req' is not supported (name=$channel/$name)"; + return PEAR_DEPENDENCY_BAD_DEPENDENCY; + } + + // }}} + // {{{ checkPackageUninstall() + + /** + * Check package dependencies on uninstall + * + * @param string $error The resultant error string + * @param string $warning The resultant warning string + * @param string $name Name of the package to test + * @param string $channel Channel name of the package + * + * @return bool true if there were errors + */ + function checkPackageUninstall(&$error, &$warning, $package, $channel = 'pear.php.net') + { + $channel = strtolower($channel); + $error = null; + $channels = $this->registry->listAllPackages(); + foreach ($channels as $channelname => $packages) { + foreach ($packages as $pkg) { + if ($pkg == $package && $channel == $channelname) { + continue; + } + $deps = $this->registry->packageInfo($pkg, 'release_deps', $channel); + if (empty($deps)) { + continue; + } + foreach ($deps as $dep) { + $depchannel = isset($dep['channel']) ? $dep['channel'] : 'pear.php.net'; + if ($dep['type'] == 'pkg' && (strcasecmp($dep['name'], $package) == 0) && + ($depchannel == $channel)) { + if ($dep['rel'] == 'ne') { + continue; + } + if (isset($dep['optional']) && $dep['optional'] == 'yes') { + $warning .= "\nWarning: Package '$depchannel/$pkg' optionally depends on '$channel:/package'"; + } else { + $error .= "Package '$depchannel/$pkg' depends on '$channel/$package'\n"; + } + } + } + } + } + return ($error) ? true : false; + } + + // }}} + // {{{ checkExtension() + + /** + * Extension dependencies check method + * + * @param string $name Name of the extension to test + * @param string $req_ext_ver Required extension version to compare with + * @param string $relation How to compare versions with eachother + * @param bool $opt Whether the relationship is optional + * + * @return mixed bool false if no error or the error string + */ + function checkExtension(&$errmsg, $name, $req = null, $relation = 'has', + $opt = false) + { + if ($relation == 'not') { + if (extension_loaded($name)) { + $errmsg = "conflicts with PHP extension '$name'"; + return PEAR_DEPENDENCY_CONFLICT; + } else { + return false; + } + } + + if (!extension_loaded($name)) { + if ($relation == 'ne') { + return false; + } + if ($opt) { + $errmsg = "'$name' PHP extension is recommended to utilize some features"; + return PEAR_DEPENDENCY_MISSING_OPTIONAL; + } + $errmsg = "'$name' PHP extension is not installed"; + return PEAR_DEPENDENCY_MISSING; + } + if ($relation == 'has') { + return false; + } + $code = false; + if (is_string($req) && substr($req, 0, 2) == 'v.') { + $req = substr($req, 2); + } + $ext_ver = phpversion($name); + $operator = $relation; + // Force params to be strings, otherwise the comparation will fail (ex. 0.9==0.90) + if (!version_compare("$ext_ver", "$req", $operator)) { + $errmsg = "'$name' PHP extension version " . + $this->signOperator($operator) . " $req is required"; + $code = $this->codeFromRelation($relation, $ext_ver, $req, $opt); + if ($opt) { + $errmsg = "'$name' PHP extension version " . $this->signOperator($operator) . + " $req is recommended to utilize some features"; + return $code; + } + } + return $code; + } + + // }}} + // {{{ checkOS() + + /** + * Operating system dependencies check method + * + * @param string $os Name of the operating system + * + * @return mixed bool false if no error or the error string + */ + function checkOS(&$errmsg, $os) + { + // XXX Fixme: Implement a more flexible way, like + // comma separated values or something similar to PEAR_OS + static $myos; + if (empty($myos)) { + $myos = new OS_Guess(); + } + // only 'has' relation is currently supported + if ($myos->matchSignature($os)) { + return false; + } + $errmsg = "'$os' operating system not supported"; + return PEAR_DEPENDENCY_CONFLICT; + } + + // }}} + // {{{ checkPHP() + + /** + * PHP version check method + * + * @param string $req which version to compare + * @param string $relation how to compare the version + * + * @return mixed bool false if no error or the error string + */ + function checkPHP(&$errmsg, $req, $relation = 'ge') + { + // this would be a bit stupid, but oh well :) + if ($relation == 'has') { + return false; + } + if ($relation == 'not') { + $errmsg = "Invalid dependency - 'not' is allowed when specifying PHP, you must run PHP in PHP"; + return PEAR_DEPENDENCY_BAD_DEPENDENCY; + } + if (substr($req, 0, 2) == 'v.') { + $req = substr($req,2, strlen($req) - 2); + } + $php_ver = phpversion(); + $operator = $relation; + if (!version_compare("$php_ver", "$req", $operator)) { + $errmsg = "PHP version " . $this->signOperator($operator) . + " $req is required"; + return PEAR_DEPENDENCY_CONFLICT; + } + return false; + } + + // }}} + // {{{ checkProgram() + + /** + * External program check method. Looks for executable files in + * directories listed in the PATH environment variable. + * + * @param string $program which program to look for + * + * @return mixed bool false if no error or the error string + */ + function checkProgram(&$errmsg, $program) + { + // XXX FIXME honor safe mode + $exe_suffix = OS_WINDOWS ? '.exe' : ''; + $path_elements = explode(PATH_SEPARATOR, getenv('PATH')); + foreach ($path_elements as $dir) { + $file = $dir . DIRECTORY_SEPARATOR . $program . $exe_suffix; + if (file_exists($file) && is_executable($file)) { + return false; + } + } + $errmsg = "'$program' program is not present in the PATH"; + return PEAR_DEPENDENCY_MISSING; + } + + // }}} + // {{{ checkSAPI() + + /** + * SAPI backend check method. Version comparison is not yet + * available here. + * + * @param string $name name of SAPI backend + * @param string $req which version to compare + * @param string $relation how to compare versions (currently + * hardcoded to 'has') + * @return mixed bool false if no error or the error string + */ + function checkSAPI(&$errmsg, $name, $req = null, $relation = 'has') + { + // XXX Fixme: There is no way to know if the user has or + // not other SAPI backends installed than the installer one + + $sapi_backend = php_sapi_name(); + // Version comparisons not supported, sapi backends don't have + // version information yet. + if ($sapi_backend == $name) { + return false; + } + $errmsg = "'$sapi_backend' SAPI backend not supported"; + return PEAR_DEPENDENCY_CONFLICT; + } + + // }}} + // {{{ checkZend() + + /** + * Zend version check method + * + * @param string $req which version to compare + * @param string $relation how to compare the version + * + * @return mixed bool false if no error or the error string + */ + function checkZend(&$errmsg, $req, $relation = 'ge') + { + if (substr($req, 0, 2) == 'v.') { + $req = substr($req,2, strlen($req) - 2); + } + $zend_ver = zend_version(); + $operator = substr($relation,0,2); + if (!version_compare("$zend_ver", "$req", $operator)) { + $errmsg = "Zend version " . $this->signOperator($operator) . + " $req is required"; + return PEAR_DEPENDENCY_CONFLICT; + } + return false; + } + + // }}} + // {{{ signOperator() + + /** + * Converts text comparing operators to them sign equivalents + * + * Example: 'ge' to '>=' + * + * @access public + * @param string Operator + * @return string Sign equivalent + */ + function signOperator($operator) + { + switch($operator) { + case 'lt': return '<'; + case 'le': return '<='; + case 'gt': return '>'; + case 'ge': return '>='; + case 'eq': return '=='; + case 'ne': return '!='; + default: + return $operator; + } + } + + // }}} + // {{{ codeFromRelation() + + /** + * Convert relation into corresponding code + * + * @access public + * @param string Relation + * @param string Version + * @param string Requirement + * @param bool Optional dependency indicator + * @return integer + */ + function codeFromRelation($relation, $version, $req, $opt = false) + { + $code = PEAR_DEPENDENCY_BAD_DEPENDENCY; + switch ($relation) { + case 'gt': case 'ge': case 'eq': + // upgrade + $have_major = preg_replace('/\D.*/', '', $version); + $need_major = preg_replace('/\D.*/', '', $req); + if ($need_major > $have_major) { + $code = $opt ? PEAR_DEPENDENCY_UPGRADE_MAJOR_OPTIONAL : + PEAR_DEPENDENCY_UPGRADE_MAJOR; + } else { + $code = $opt ? PEAR_DEPENDENCY_UPGRADE_MINOR_OPTIONAL : + PEAR_DEPENDENCY_UPGRADE_MINOR; + } + break; + case 'lt': case 'le': case 'ne': + $code = $opt ? PEAR_DEPENDENCY_CONFLICT_OPTIONAL : + PEAR_DEPENDENCY_CONFLICT; + break; + } + return $code; + } + + // }}} +} +?> diff --git a/src/lib/pear/PEAR/PEAR/Dependency2.php b/src/lib/pear/PEAR/PEAR/Dependency2.php new file mode 100644 index 0000000..802e9bf --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Dependency2.php @@ -0,0 +1,1299 @@ + + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: Dependency2.php,v 1.56 2008/01/03 20:26:35 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 1.4.0a1 + */ + +/** + * Required for the PEAR_VALIDATE_* constants + */ +require_once 'PEAR/Validate.php'; + +/** + * Dependency check for PEAR packages + * + * This class handles both version 1.0 and 2.0 dependencies + * WARNING: *any* changes to this class must be duplicated in the + * test_PEAR_Dependency2 class found in tests/PEAR_Dependency2/setup.php.inc, + * or unit tests will not actually validate the changes + * @category pear + * @package PEAR + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 1.4.0a1 + */ +class PEAR_Dependency2 +{ + /** + * One of the PEAR_VALIDATE_* states + * @see PEAR_VALIDATE_NORMAL + * @var integer + */ + var $_state; + /** + * Command-line options to install/upgrade/uninstall commands + * @param array + */ + var $_options; + /** + * @var OS_Guess + */ + var $_os; + /** + * @var PEAR_Registry + */ + var $_registry; + /** + * @var PEAR_Config + */ + var $_config; + /** + * @var PEAR_DependencyDB + */ + var $_dependencydb; + /** + * Output of PEAR_Registry::parsedPackageName() + * @var array + */ + var $_currentPackage; + /** + * @param PEAR_Config + * @param array installation options + * @param array format of PEAR_Registry::parsedPackageName() + * @param int installation state (one of PEAR_VALIDATE_*) + */ + function PEAR_Dependency2(&$config, $installoptions, $package, + $state = PEAR_VALIDATE_INSTALLING) + { + $this->_config = &$config; + if (!class_exists('PEAR_DependencyDB')) { + require_once 'PEAR/DependencyDB.php'; + } + if (isset($installoptions['packagingroot'])) { + // make sure depdb is in the right location + $config->setInstallRoot($installoptions['packagingroot']); + } + $this->_registry = &$config->getRegistry(); + $this->_dependencydb = &PEAR_DependencyDB::singleton($config); + if (isset($installoptions['packagingroot'])) { + $config->setInstallRoot(false); + } + $this->_options = $installoptions; + $this->_state = $state; + if (!class_exists('OS_Guess')) { + require_once 'OS/Guess.php'; + } + $this->_os = new OS_Guess; + $this->_currentPackage = $package; + } + + function _getExtraString($dep) + { + $extra = ' ('; + if (isset($dep['uri'])) { + return ''; + } + if (isset($dep['recommended'])) { + $extra .= 'recommended version ' . $dep['recommended']; + } else { + if (isset($dep['min'])) { + $extra .= 'version >= ' . $dep['min']; + } + if (isset($dep['max'])) { + if ($extra != ' (') { + $extra .= ', '; + } + $extra .= 'version <= ' . $dep['max']; + } + if (isset($dep['exclude'])) { + if (!is_array($dep['exclude'])) { + $dep['exclude'] = array($dep['exclude']); + } + if ($extra != ' (') { + $extra .= ', '; + } + $extra .= 'excluded versions: '; + foreach ($dep['exclude'] as $i => $exclude) { + if ($i) { + $extra .= ', '; + } + $extra .= $exclude; + } + } + } + $extra .= ')'; + if ($extra == ' ()') { + $extra = ''; + } + return $extra; + } + + /** + * This makes unit-testing a heck of a lot easier + */ + function getPHP_OS() + { + return PHP_OS; + } + + /** + * This makes unit-testing a heck of a lot easier + */ + function getsysname() + { + return $this->_os->getSysname(); + } + + /** + * Specify a dependency on an OS. Use arch for detailed os/processor information + * + * There are two generic OS dependencies that will be the most common, unix and windows. + * Other options are linux, freebsd, darwin (OS X), sunos, irix, hpux, aix + */ + function validateOsDependency($dep) + { + if ($this->_state != PEAR_VALIDATE_INSTALLING && + $this->_state != PEAR_VALIDATE_DOWNLOADING) { + return true; + } + if (isset($dep['conflicts'])) { + $not = true; + } else { + $not = false; + } + if ($dep['name'] == '*') { + return true; + } + switch (strtolower($dep['name'])) { + case 'windows' : + if ($not) { + if (strtolower(substr($this->getPHP_OS(), 0, 3)) == 'win') { + if (!isset($this->_options['nodeps']) && + !isset($this->_options['force'])) { + return $this->raiseError("Cannot install %s on Windows"); + } else { + return $this->warning("warning: Cannot install %s on Windows"); + } + } + } else { + if (strtolower(substr($this->getPHP_OS(), 0, 3)) != 'win') { + if (!isset($this->_options['nodeps']) && + !isset($this->_options['force'])) { + return $this->raiseError("Can only install %s on Windows"); + } else { + return $this->warning("warning: Can only install %s on Windows"); + } + } + } + break; + case 'unix' : + $unices = array('linux', 'freebsd', 'darwin', 'sunos', 'irix', 'hpux', 'aix'); + if ($not) { + if (in_array($this->getSysname(), $unices)) { + if (!isset($this->_options['nodeps']) && + !isset($this->_options['force'])) { + return $this->raiseError("Cannot install %s on any Unix system"); + } else { + return $this->warning( + "warning: Cannot install %s on any Unix system"); + } + } + } else { + if (!in_array($this->getSysname(), $unices)) { + if (!isset($this->_options['nodeps']) && + !isset($this->_options['force'])) { + return $this->raiseError("Can only install %s on a Unix system"); + } else { + return $this->warning( + "warning: Can only install %s on a Unix system"); + } + } + } + break; + default : + if ($not) { + if (strtolower($dep['name']) == strtolower($this->getSysname())) { + if (!isset($this->_options['nodeps']) && + !isset($this->_options['force'])) { + return $this->raiseError('Cannot install %s on ' . $dep['name'] . + ' operating system'); + } else { + return $this->warning('warning: Cannot install %s on ' . + $dep['name'] . ' operating system'); + } + } + } else { + if (strtolower($dep['name']) != strtolower($this->getSysname())) { + if (!isset($this->_options['nodeps']) && + !isset($this->_options['force'])) { + return $this->raiseError('Cannot install %s on ' . + $this->getSysname() . + ' operating system, can only install on ' . $dep['name']); + } else { + return $this->warning('warning: Cannot install %s on ' . + $this->getSysname() . + ' operating system, can only install on ' . $dep['name']); + } + } + } + } + return true; + } + + /** + * This makes unit-testing a heck of a lot easier + */ + function matchSignature($pattern) + { + return $this->_os->matchSignature($pattern); + } + + /** + * Specify a complex dependency on an OS/processor/kernel version, + * Use OS for simple operating system dependency. + * + * This is the only dependency that accepts an eregable pattern. The pattern + * will be matched against the php_uname() output parsed by OS_Guess + */ + function validateArchDependency($dep) + { + if ($this->_state != PEAR_VALIDATE_INSTALLING) { + return true; + } + if (isset($dep['conflicts'])) { + $not = true; + } else { + $not = false; + } + if (!$this->matchSignature($dep['pattern'])) { + if (!$not) { + if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { + return $this->raiseError('%s Architecture dependency failed, does not ' . + 'match "' . $dep['pattern'] . '"'); + } else { + return $this->warning('warning: %s Architecture dependency failed, does ' . + 'not match "' . $dep['pattern'] . '"'); + } + } + return true; + } else { + if ($not) { + if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { + return $this->raiseError('%s Architecture dependency failed, required "' . + $dep['pattern'] . '"'); + } else { + return $this->warning('warning: %s Architecture dependency failed, ' . + 'required "' . $dep['pattern'] . '"'); + } + } + return true; + } + } + + /** + * This makes unit-testing a heck of a lot easier + */ + function extension_loaded($name) + { + return extension_loaded($name); + } + + /** + * This makes unit-testing a heck of a lot easier + */ + function phpversion($name = null) + { + if ($name !== null) { + return phpversion($name); + } else { + return phpversion(); + } + } + + function validateExtensionDependency($dep, $required = true) + { + if ($this->_state != PEAR_VALIDATE_INSTALLING && + $this->_state != PEAR_VALIDATE_DOWNLOADING) { + return true; + } + $loaded = $this->extension_loaded($dep['name']); + $extra = $this->_getExtraString($dep); + if (isset($dep['exclude'])) { + if (!is_array($dep['exclude'])) { + $dep['exclude'] = array($dep['exclude']); + } + } + if (!isset($dep['min']) && !isset($dep['max']) && + !isset($dep['recommended']) && !isset($dep['exclude'])) { + if ($loaded) { + if (isset($dep['conflicts'])) { + if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { + return $this->raiseError('%s conflicts with PHP extension "' . + $dep['name'] . '"' . $extra); + } else { + return $this->warning('warning: %s conflicts with PHP extension "' . + $dep['name'] . '"' . $extra); + } + } + return true; + } else { + if (isset($dep['conflicts'])) { + return true; + } + if ($required) { + if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { + return $this->raiseError('%s requires PHP extension "' . + $dep['name'] . '"' . $extra); + } else { + return $this->warning('warning: %s requires PHP extension "' . + $dep['name'] . '"' . $extra); + } + } else { + return $this->warning('%s can optionally use PHP extension "' . + $dep['name'] . '"' . $extra); + } + } + } + if (!$loaded) { + if (isset($dep['conflicts'])) { + return true; + } + if (!$required) { + return $this->warning('%s can optionally use PHP extension "' . + $dep['name'] . '"' . $extra); + } else { + if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { + return $this->raiseError('%s requires PHP extension "' . $dep['name'] . + '"' . $extra); + } + return $this->warning('warning: %s requires PHP extension "' . $dep['name'] . + '"' . $extra); + } + } + $version = (string) $this->phpversion($dep['name']); + if (empty($version)) { + $version = '0'; + } + $fail = false; + if (isset($dep['min'])) { + if (!version_compare($version, $dep['min'], '>=')) { + $fail = true; + } + } + if (isset($dep['max'])) { + if (!version_compare($version, $dep['max'], '<=')) { + $fail = true; + } + } + if ($fail && !isset($dep['conflicts'])) { + if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { + return $this->raiseError('%s requires PHP extension "' . $dep['name'] . + '"' . $extra . ', installed version is ' . $version); + } else { + return $this->warning('warning: %s requires PHP extension "' . $dep['name'] . + '"' . $extra . ', installed version is ' . $version); + } + } elseif ((isset($dep['min']) || isset($dep['max'])) && !$fail && isset($dep['conflicts'])) { + if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { + return $this->raiseError('%s conflicts with PHP extension "' . + $dep['name'] . '"' . $extra . ', installed version is ' . $version); + } else { + return $this->warning('warning: %s conflicts with PHP extension "' . + $dep['name'] . '"' . $extra . ', installed version is ' . $version); + } + } + if (isset($dep['exclude'])) { + foreach ($dep['exclude'] as $exclude) { + if (version_compare($version, $exclude, '==')) { + if (isset($dep['conflicts'])) { + continue; + } + if (!isset($this->_options['nodeps']) && + !isset($this->_options['force'])) { + return $this->raiseError('%s is not compatible with PHP extension "' . + $dep['name'] . '" version ' . + $exclude); + } else { + return $this->warning('warning: %s is not compatible with PHP extension "' . + $dep['name'] . '" version ' . + $exclude); + } + } elseif (version_compare($version, $exclude, '!=') && isset($dep['conflicts'])) { + if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { + return $this->raiseError('%s conflicts with PHP extension "' . + $dep['name'] . '"' . $extra . ', installed version is ' . $version); + } else { + return $this->warning('warning: %s conflicts with PHP extension "' . + $dep['name'] . '"' . $extra . ', installed version is ' . $version); + } + } + } + } + if (isset($dep['recommended'])) { + if (version_compare($version, $dep['recommended'], '==')) { + return true; + } else { + if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { + return $this->raiseError('%s dependency: PHP extension ' . $dep['name'] . + ' version "' . $version . '"' . + ' is not the recommended version "' . $dep['recommended'] . + '", but may be compatible, use --force to install'); + } else { + return $this->warning('warning: %s dependency: PHP extension ' . + $dep['name'] . ' version "' . $version . '"' . + ' is not the recommended version "' . $dep['recommended'].'"'); + } + } + } + return true; + } + + function validatePhpDependency($dep) + { + if ($this->_state != PEAR_VALIDATE_INSTALLING && + $this->_state != PEAR_VALIDATE_DOWNLOADING) { + return true; + } + $version = $this->phpversion(); + $extra = $this->_getExtraString($dep); + if (isset($dep['exclude'])) { + if (!is_array($dep['exclude'])) { + $dep['exclude'] = array($dep['exclude']); + } + } + if (isset($dep['min'])) { + if (!version_compare($version, $dep['min'], '>=')) { + if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { + return $this->raiseError('%s requires PHP' . + $extra . ', installed version is ' . $version); + } else { + return $this->warning('warning: %s requires PHP' . + $extra . ', installed version is ' . $version); + } + } + } + if (isset($dep['max'])) { + if (!version_compare($version, $dep['max'], '<=')) { + if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { + return $this->raiseError('%s requires PHP' . + $extra . ', installed version is ' . $version); + } else { + return $this->warning('warning: %s requires PHP' . + $extra . ', installed version is ' . $version); + } + } + } + if (isset($dep['exclude'])) { + foreach ($dep['exclude'] as $exclude) { + if (version_compare($version, $exclude, '==')) { + if (!isset($this->_options['nodeps']) && + !isset($this->_options['force'])) { + return $this->raiseError('%s is not compatible with PHP version ' . + $exclude); + } else { + return $this->warning( + 'warning: %s is not compatible with PHP version ' . + $exclude); + } + } + } + } + return true; + } + + /** + * This makes unit-testing a heck of a lot easier + */ + function getPEARVersion() + { + return '1.7.2'; + } + + function validatePearinstallerDependency($dep) + { + $pearversion = $this->getPEARVersion(); + $extra = $this->_getExtraString($dep); + if (isset($dep['exclude'])) { + if (!is_array($dep['exclude'])) { + $dep['exclude'] = array($dep['exclude']); + } + } + if (version_compare($pearversion, $dep['min'], '<')) { + if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { + return $this->raiseError('%s requires PEAR Installer' . $extra . + ', installed version is ' . $pearversion); + } else { + return $this->warning('warning: %s requires PEAR Installer' . $extra . + ', installed version is ' . $pearversion); + } + } + if (isset($dep['max'])) { + if (version_compare($pearversion, $dep['max'], '>')) { + if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { + return $this->raiseError('%s requires PEAR Installer' . $extra . + ', installed version is ' . $pearversion); + } else { + return $this->warning('warning: %s requires PEAR Installer' . $extra . + ', installed version is ' . $pearversion); + } + } + } + if (isset($dep['exclude'])) { + if (!isset($dep['exclude'][0])) { + $dep['exclude'] = array($dep['exclude']); + } + foreach ($dep['exclude'] as $exclude) { + if (version_compare($exclude, $pearversion, '==')) { + if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { + return $this->raiseError('%s is not compatible with PEAR Installer ' . + 'version ' . $exclude); + } else { + return $this->warning('warning: %s is not compatible with PEAR ' . + 'Installer version ' . $exclude); + } + } + } + } + return true; + } + + function validateSubpackageDependency($dep, $required, $params) + { + return $this->validatePackageDependency($dep, $required, $params); + } + + /** + * @param array dependency information (2.0 format) + * @param boolean whether this is a required dependency + * @param array a list of downloaded packages to be installed, if any + * @param boolean if true, then deps on pear.php.net that fail will also check + * against pecl.php.net packages to accomodate extensions that have + * moved to pecl.php.net from pear.php.net + */ + function validatePackageDependency($dep, $required, $params, $depv1 = false) + { + if ($this->_state != PEAR_VALIDATE_INSTALLING && + $this->_state != PEAR_VALIDATE_DOWNLOADING) { + return true; + } + if (isset($dep['providesextension'])) { + if ($this->extension_loaded($dep['providesextension'])) { + $save = $dep; + $subdep = $dep; + $subdep['name'] = $subdep['providesextension']; + PEAR::pushErrorHandling(PEAR_ERROR_RETURN); + $ret = $this->validateExtensionDependency($subdep, $required); + PEAR::popErrorHandling(); + if (!PEAR::isError($ret)) { + return true; + } + } + } + if ($this->_state == PEAR_VALIDATE_INSTALLING) { + return $this->_validatePackageInstall($dep, $required, $depv1); + } + if ($this->_state == PEAR_VALIDATE_DOWNLOADING) { + return $this->_validatePackageDownload($dep, $required, $params, $depv1); + } + } + + function _validatePackageDownload($dep, $required, $params, $depv1 = false) + { + $dep['package'] = $dep['name']; + if (isset($dep['uri'])) { + $dep['channel'] = '__uri'; + } + $depname = $this->_registry->parsedPackageNameToString($dep, true); + $found = false; + foreach ($params as $param) { + if ($param->isEqual( + array('package' => $dep['name'], + 'channel' => $dep['channel']))) { + $found = true; + break; + } + if ($depv1 && $dep['channel'] == 'pear.php.net') { + if ($param->isEqual( + array('package' => $dep['name'], + 'channel' => 'pecl.php.net'))) { + $found = true; + break; + } + } + } + if (!$found && isset($dep['providesextension'])) { + foreach ($params as $param) { + if ($param->isExtension($dep['providesextension'])) { + $found = true; + break; + } + } + } + if ($found) { + $version = $param->getVersion(); + $installed = false; + $downloaded = true; + } else { + if ($this->_registry->packageExists($dep['name'], $dep['channel'])) { + $installed = true; + $downloaded = false; + $version = $this->_registry->packageinfo($dep['name'], 'version', + $dep['channel']); + } else { + if ($dep['channel'] == 'pecl.php.net' && $this->_registry->packageExists($dep['name'], + 'pear.php.net')) { + $installed = true; + $downloaded = false; + $version = $this->_registry->packageinfo($dep['name'], 'version', + 'pear.php.net'); + } else { + $version = 'not installed or downloaded'; + $installed = false; + $downloaded = false; + } + } + } + $extra = $this->_getExtraString($dep); + if (isset($dep['exclude'])) { + if (!is_array($dep['exclude'])) { + $dep['exclude'] = array($dep['exclude']); + } + } + if (!isset($dep['min']) && !isset($dep['max']) && + !isset($dep['recommended']) && !isset($dep['exclude'])) { + if ($installed || $downloaded) { + $installed = $installed ? 'installed' : 'downloaded'; + if (isset($dep['conflicts'])) { + if ($version) { + $rest = ", $installed version is " . $version; + } else { + $rest = ''; + } + if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { + return $this->raiseError('%s conflicts with package "' . $depname . '"' . + $extra . $rest); + } else { + return $this->warning('warning: %s conflicts with package "' . $depname . '"' . + $extra . $rest); + } + } + return true; + } else { + if (isset($dep['conflicts'])) { + return true; + } + if ($required) { + if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { + return $this->raiseError('%s requires package "' . $depname . '"' . + $extra); + } else { + return $this->warning('warning: %s requires package "' . $depname . '"' . + $extra); + } + } else { + return $this->warning('%s can optionally use package "' . $depname . '"' . + $extra); + } + } + } + if (!$installed && !$downloaded) { + if (isset($dep['conflicts'])) { + return true; + } + if ($required) { + if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { + return $this->raiseError('%s requires package "' . $depname . '"' . + $extra); + } else { + return $this->warning('warning: %s requires package "' . $depname . '"' . + $extra); + } + } else { + return $this->warning('%s can optionally use package "' . $depname . '"' . + $extra); + } + } + $fail = false; + if (isset($dep['min'])) { + if (version_compare($version, $dep['min'], '<')) { + $fail = true; + } + } + if (isset($dep['max'])) { + if (version_compare($version, $dep['max'], '>')) { + $fail = true; + } + } + if ($fail && !isset($dep['conflicts'])) { + $installed = $installed ? 'installed' : 'downloaded'; + $dep['package'] = $dep['name']; + $dep = $this->_registry->parsedPackageNameToString($dep, true); + if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { + return $this->raiseError('%s requires package "' . $depname . '"' . + $extra . ", $installed version is " . $version); + } else { + return $this->warning('warning: %s requires package "' . $depname . '"' . + $extra . ", $installed version is " . $version); + } + } elseif ((isset($dep['min']) || isset($dep['max'])) && !$fail && + isset($dep['conflicts']) && !isset($dep['exclude'])) { + $installed = $installed ? 'installed' : 'downloaded'; + if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { + return $this->raiseError('%s conflicts with package "' . $depname . '"' . $extra . + ", $installed version is " . $version); + } else { + return $this->warning('warning: %s conflicts with package "' . $depname . '"' . + $extra . ", $installed version is " . $version); + } + } + if (isset($dep['exclude'])) { + $installed = $installed ? 'installed' : 'downloaded'; + foreach ($dep['exclude'] as $exclude) { + if (version_compare($version, $exclude, '==') && !isset($dep['conflicts'])) { + if (!isset($this->_options['nodeps']) && + !isset($this->_options['force'])) { + return $this->raiseError('%s is not compatible with ' . + $installed . ' package "' . + $depname . '" version ' . + $exclude); + } else { + return $this->warning('warning: %s is not compatible with ' . + $installed . ' package "' . + $depname . '" version ' . + $exclude); + } + } elseif (version_compare($version, $exclude, '!=') && isset($dep['conflicts'])) { + $installed = $installed ? 'installed' : 'downloaded'; + if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { + return $this->raiseError('%s conflicts with package "' . $depname . '"' . + $extra . ", $installed version is " . $version); + } else { + return $this->warning('warning: %s conflicts with package "' . $depname . '"' . + $extra . ", $installed version is " . $version); + } + } + } + } + if (isset($dep['recommended'])) { + $installed = $installed ? 'installed' : 'downloaded'; + if (version_compare($version, $dep['recommended'], '==')) { + return true; + } else { + if (!$found && $installed) { + $param = $this->_registry->getPackage($dep['name'], $dep['channel']); + } + if ($param) { + $found = false; + foreach ($params as $parent) { + if ($parent->isEqual($this->_currentPackage)) { + $found = true; + break; + } + } + if ($found) { + if ($param->isCompatible($parent)) { + return true; + } + } else { // this is for validPackage() calls + $parent = $this->_registry->getPackage($this->_currentPackage['package'], + $this->_currentPackage['channel']); + if ($parent !== null) { + if ($param->isCompatible($parent)) { + return true; + } + } + } + } + if (!isset($this->_options['nodeps']) && !isset($this->_options['force']) && + !isset($this->_options['loose'])) { + return $this->raiseError('%s dependency package "' . $depname . + '" ' . $installed . ' version ' . $version . + ' is not the recommended version ' . $dep['recommended'] . + ', but may be compatible, use --force to install'); + } else { + return $this->warning('warning: %s dependency package "' . $depname . + '" ' . $installed . ' version ' . $version . + ' is not the recommended version ' . $dep['recommended']); + } + } + } + return true; + } + + function _validatePackageInstall($dep, $required, $depv1 = false) + { + return $this->_validatePackageDownload($dep, $required, array(), $depv1); + } + + /** + * Verify that uninstalling packages passed in to command line is OK. + * + * @param PEAR_Installer $dl + * @return PEAR_Error|true + */ + function validatePackageUninstall(&$dl) + { + if (PEAR::isError($this->_dependencydb)) { + return $this->_dependencydb; + } + $params = array(); + // construct an array of "downloaded" packages to fool the package dependency checker + // into using these to validate uninstalls of circular dependencies + $downloaded = &$dl->getUninstallPackages(); + foreach ($downloaded as $i => $pf) { + if (!class_exists('PEAR_Downloader_Package')) { + require_once 'PEAR/Downloader/Package.php'; + } + $dp = &new PEAR_Downloader_Package($dl); + $dp->setPackageFile($downloaded[$i]); + $params[$i] = &$dp; + } + // check cache + $memyselfandI = strtolower($this->_currentPackage['channel']) . '/' . + strtolower($this->_currentPackage['package']); + if (isset($dl->___uninstall_package_cache)) { + $badpackages = $dl->___uninstall_package_cache; + if (isset($badpackages[$memyselfandI]['warnings'])) { + foreach ($badpackages[$memyselfandI]['warnings'] as $warning) { + $dl->log(0, $warning[0]); + } + } + if (isset($badpackages[$memyselfandI]['errors'])) { + foreach ($badpackages[$memyselfandI]['errors'] as $error) { + if (is_array($error)) { + $dl->log(0, $error[0]); + } else { + $dl->log(0, $error->getMessage()); + } + } + if (isset($this->_options['nodeps']) || isset($this->_options['force'])) { + return $this->warning( + 'warning: %s should not be uninstalled, other installed packages depend ' . + 'on this package'); + } else { + return $this->raiseError( + '%s cannot be uninstalled, other installed packages depend on this package'); + } + } + return true; + } + // first, list the immediate parents of each package to be uninstalled + $perpackagelist = array(); + $allparents = array(); + foreach ($params as $i => $param) { + $a = array('channel' => strtolower($param->getChannel()), + 'package' => strtolower($param->getPackage())); + $deps = $this->_dependencydb->getDependentPackages($a); + if ($deps) { + foreach ($deps as $d) { + $pardeps = $this->_dependencydb->getDependencies($d); + foreach ($pardeps as $dep) { + if (strtolower($dep['dep']['channel']) == $a['channel'] && + strtolower($dep['dep']['name']) == $a['package']) { + if (!isset($perpackagelist[$a['channel'] . '/' . $a['package']])) { + $perpackagelist[$a['channel'] . '/' . $a['package']] = array(); + } + $perpackagelist[$a['channel'] . '/' . $a['package']][] + = array($d['channel'] . '/' . $d['package'], $dep); + if (!isset($allparents[$d['channel'] . '/' . $d['package']])) { + $allparents[$d['channel'] . '/' . $d['package']] = array(); + } + if (!isset($allparents[$d['channel'] . '/' . $d['package']][$a['channel'] . '/' . $a['package']])) { + $allparents[$d['channel'] . '/' . $d['package']][$a['channel'] . '/' . $a['package']] = array(); + } + $allparents[$d['channel'] . '/' . $d['package']] + [$a['channel'] . '/' . $a['package']][] + = array($d, $dep); + } + } + } + } + } + // next, remove any packages from the parents list that are not installed + $remove = array(); + foreach ($allparents as $parent => $d1) { + foreach ($d1 as $d) { + if ($this->_registry->packageExists($d[0][0]['package'], $d[0][0]['channel'])) { + continue; + } + $remove[$parent] = true; + } + } + // next remove any packages from the parents list that are not passed in for + // uninstallation + foreach ($allparents as $parent => $d1) { + foreach ($d1 as $d) { + foreach ($params as $param) { + if (strtolower($param->getChannel()) == $d[0][0]['channel'] && + strtolower($param->getPackage()) == $d[0][0]['package']) { + // found it + continue 3; + } + } + $remove[$parent] = true; + } + } + // remove all packages whose dependencies fail + // save which ones failed for error reporting + $badchildren = array(); + do { + $fail = false; + foreach ($remove as $package => $unused) { + if (!isset($allparents[$package])) { + continue; + } + foreach ($allparents[$package] as $kid => $d1) { + foreach ($d1 as $depinfo) { + if ($depinfo[1]['type'] != 'optional') { + if (isset($badchildren[$kid])) { + continue; + } + $badchildren[$kid] = true; + $remove[$kid] = true; + $fail = true; + continue 2; + } + } + } + if ($fail) { + // start over, we removed some children + continue 2; + } + } + } while ($fail); + // next, construct the list of packages that can't be uninstalled + $badpackages = array(); + $save = $this->_currentPackage; + foreach ($perpackagelist as $package => $packagedeps) { + foreach ($packagedeps as $parent) { + if (!isset($remove[$parent[0]])) { + continue; + } + $packagename = $this->_registry->parsePackageName($parent[0]); + $packagename['channel'] = $this->_registry->channelAlias($packagename['channel']); + $pa = $this->_registry->getPackage($packagename['package'], $packagename['channel']); + $packagename['package'] = $pa->getPackage(); + $this->_currentPackage = $packagename; + // parent is not present in uninstall list, make sure we can actually + // uninstall it (parent dep is optional) + $parentname['channel'] = $this->_registry->channelAlias($parent[1]['dep']['channel']); + $pa = $this->_registry->getPackage($parent[1]['dep']['name'], $parent[1]['dep']['channel']); + $parentname['package'] = $pa->getPackage(); + $parent[1]['dep']['package'] = $parentname['package']; + $parent[1]['dep']['channel'] = $parentname['channel']; + if ($parent[1]['type'] == 'optional') { + $test = $this->_validatePackageUninstall($parent[1]['dep'], false, $dl); + if ($test !== true) { + $badpackages[$package]['warnings'][] = $test; + } + } else { + $test = $this->_validatePackageUninstall($parent[1]['dep'], true, $dl); + if ($test !== true) { + $badpackages[$package]['errors'][] = $test; + } + } + } + } + $this->_currentPackage = $save; + $dl->___uninstall_package_cache = $badpackages; + if (isset($badpackages[$memyselfandI])) { + if (isset($badpackages[$memyselfandI]['warnings'])) { + foreach ($badpackages[$memyselfandI]['warnings'] as $warning) { + $dl->log(0, $warning[0]); + } + } + if (isset($badpackages[$memyselfandI]['errors'])) { + foreach ($badpackages[$memyselfandI]['errors'] as $error) { + if (is_array($error)) { + $dl->log(0, $error[0]); + } else { + $dl->log(0, $error->getMessage()); + } + } + if (isset($this->_options['nodeps']) || isset($this->_options['force'])) { + return $this->warning( + 'warning: %s should not be uninstalled, other installed packages depend ' . + 'on this package'); + } else { + return $this->raiseError( + '%s cannot be uninstalled, other installed packages depend on this package'); + } + } + } + return true; + } + + function _validatePackageUninstall($dep, $required, $dl) + { + $depname = $this->_registry->parsedPackageNameToString($dep, true); + $version = $this->_registry->packageinfo($dep['package'], 'version', + $dep['channel']); + if (!$version) { + return true; + } + $extra = $this->_getExtraString($dep); + if (isset($dep['exclude'])) { + if (!is_array($dep['exclude'])) { + $dep['exclude'] = array($dep['exclude']); + } + } + if (isset($dep['conflicts'])) { + return true; // uninstall OK - these packages conflict (probably installed with --force) + } + if (!isset($dep['min']) && !isset($dep['max'])) { + if ($required) { + if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { + return $this->raiseError('"' . $depname . '" is required by ' . + 'installed package %s' . $extra); + } else { + return $this->warning('warning: "' . $depname . '" is required by ' . + 'installed package %s' . $extra); + } + } else { + return $this->warning('"' . $depname . '" can be optionally used by ' . + 'installed package %s' . $extra); + } + } + $fail = false; + if (isset($dep['min'])) { + if (version_compare($version, $dep['min'], '>=')) { + $fail = true; + } + } + if (isset($dep['max'])) { + if (version_compare($version, $dep['max'], '<=')) { + $fail = true; + } + } + // we re-use this variable, preserve the original value + $saverequired = $required; + if ($required) { + if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { + return $this->raiseError($depname . $extra . ' is required by installed package' . + ' "%s"'); + } else { + return $this->raiseError('warning: ' . $depname . $extra . + ' is required by installed package "%s"'); + } + } else { + return $this->warning($depname . $extra . ' can be optionally used by installed package' . + ' "%s"'); + } + return true; + } + + /** + * validate a downloaded package against installed packages + * + * As of PEAR 1.4.3, this will only validate + * + * @param array|PEAR_Downloader_Package|PEAR_PackageFile_v1|PEAR_PackageFile_v2 + * $pkg package identifier (either + * array('package' => blah, 'channel' => blah) or an array with + * index 'info' referencing an object) + * @param PEAR_Downloader $dl + * @param array $params full list of packages to install + * @return true|PEAR_Error + */ + function validatePackage($pkg, &$dl, $params = array()) + { + if (is_array($pkg) && isset($pkg['info'])) { + $deps = $this->_dependencydb->getDependentPackageDependencies($pkg['info']); + } else { + $deps = $this->_dependencydb->getDependentPackageDependencies($pkg); + } + $fail = false; + if ($deps) { + if (!class_exists('PEAR_Downloader_Package')) { + require_once 'PEAR/Downloader/Package.php'; + } + $dp = &new PEAR_Downloader_Package($dl); + if (is_object($pkg)) { + $dp->setPackageFile($pkg); + } else { + $dp->setDownloadURL($pkg); + } + PEAR::pushErrorHandling(PEAR_ERROR_RETURN); + foreach ($deps as $channel => $info) { + foreach ($info as $package => $ds) { + foreach ($params as $packd) { + if (strtolower($packd->getPackage()) == strtolower($package) && + $packd->getChannel() == $channel) { + $dl->log(3, 'skipping installed package check of "' . + $this->_registry->parsedPackageNameToString( + array('channel' => $channel, 'package' => $package), + true) . + '", version "' . $packd->getVersion() . '" will be ' . + 'downloaded and installed'); + continue 2; // jump to next package + } + } + foreach ($ds as $d) { + $checker = &new PEAR_Dependency2($this->_config, $this->_options, + array('channel' => $channel, 'package' => $package), $this->_state); + $dep = $d['dep']; + $required = $d['type'] == 'required'; + $ret = $checker->_validatePackageDownload($dep, $required, array(&$dp)); + if (is_array($ret)) { + $dl->log(0, $ret[0]); + } elseif (PEAR::isError($ret)) { + $dl->log(0, $ret->getMessage()); + $fail = true; + } + } + } + } + PEAR::popErrorHandling(); + } + if ($fail) { + return $this->raiseError( + '%s cannot be installed, conflicts with installed packages'); + } + return true; + } + + /** + * validate a package.xml 1.0 dependency + */ + function validateDependency1($dep, $params = array()) + { + if (!isset($dep['optional'])) { + $dep['optional'] = 'no'; + } + list($newdep, $type) = $this->normalizeDep($dep); + if (!$newdep) { + return $this->raiseError("Invalid Dependency"); + } + if (method_exists($this, "validate{$type}Dependency")) { + return $this->{"validate{$type}Dependency"}($newdep, $dep['optional'] == 'no', + $params, true); + } + } + + /** + * Convert a 1.0 dep into a 2.0 dep + */ + function normalizeDep($dep) + { + $types = array( + 'pkg' => 'Package', + 'ext' => 'Extension', + 'os' => 'Os', + 'php' => 'Php' + ); + if (isset($types[$dep['type']])) { + $type = $types[$dep['type']]; + } else { + return array(false, false); + } + $newdep = array(); + switch ($type) { + case 'Package' : + $newdep['channel'] = 'pear.php.net'; + case 'Extension' : + case 'Os' : + $newdep['name'] = $dep['name']; + break; + } + $dep['rel'] = PEAR_Dependency2::signOperator($dep['rel']); + switch ($dep['rel']) { + case 'has' : + return array($newdep, $type); + break; + case 'not' : + $newdep['conflicts'] = true; + break; + case '>=' : + case '>' : + $newdep['min'] = $dep['version']; + if ($dep['rel'] == '>') { + $newdep['exclude'] = $dep['version']; + } + break; + case '<=' : + case '<' : + $newdep['max'] = $dep['version']; + if ($dep['rel'] == '<') { + $newdep['exclude'] = $dep['version']; + } + break; + case 'ne' : + case '!=' : + $newdep['min'] = '0'; + $newdep['max'] = '100000'; + $newdep['exclude'] = $dep['version']; + break; + case '==' : + $newdep['min'] = $dep['version']; + $newdep['max'] = $dep['version']; + break; + } + if ($type == 'Php') { + if (!isset($newdep['min'])) { + $newdep['min'] = '4.2.0'; + } + if (!isset($newdep['max'])) { + $newdep['max'] = '6.0.0'; + } + } + return array($newdep, $type); + } + + /** + * Converts text comparing operators to them sign equivalents + * + * Example: 'ge' to '>=' + * + * @access public + * @param string Operator + * @return string Sign equivalent + */ + function signOperator($operator) + { + switch($operator) { + case 'lt': return '<'; + case 'le': return '<='; + case 'gt': return '>'; + case 'ge': return '>='; + case 'eq': return '=='; + case 'ne': return '!='; + default: + return $operator; + } + } + + function raiseError($msg) + { + if (isset($this->_options['ignore-errors'])) { + return $this->warning($msg); + } + return PEAR::raiseError(sprintf($msg, $this->_registry->parsedPackageNameToString( + $this->_currentPackage, true))); + } + + function warning($msg) + { + return array(sprintf($msg, $this->_registry->parsedPackageNameToString( + $this->_currentPackage, true))); + } +} +?> \ No newline at end of file diff --git a/src/lib/pear/PEAR/PEAR/DependencyDB.php b/src/lib/pear/PEAR/PEAR/DependencyDB.php new file mode 100644 index 0000000..f79ae81 --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/DependencyDB.php @@ -0,0 +1,713 @@ + + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: DependencyDB.php,v 1.37 2008/01/03 20:26:35 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 1.4.0a1 + */ + +/** + * Needed for error handling + */ +require_once 'PEAR.php'; +require_once 'PEAR/Config.php'; + +$GLOBALS['_PEAR_DEPENDENCYDB_INSTANCE'] = array(); +/** + * Track dependency relationships between installed packages + * @category pear + * @package PEAR + * @author Greg Beaver + * @author Tomas V.V.Cox + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 1.4.0a1 + */ +class PEAR_DependencyDB +{ + // {{{ properties + + /** + * This is initialized by {@link setConfig()} + * @var PEAR_Config + * @access private + */ + var $_config; + /** + * This is initialized by {@link setConfig()} + * @var PEAR_Registry + * @access private + */ + var $_registry; + /** + * Filename of the dependency DB (usually .depdb) + * @var string + * @access private + */ + var $_depdb = false; + /** + * File name of the lockfile (usually .depdblock) + * @var string + * @access private + */ + var $_lockfile = false; + /** + * Open file resource for locking the lockfile + * @var resource|false + * @access private + */ + var $_lockFp = false; + /** + * API version of this class, used to validate a file on-disk + * @var string + * @access private + */ + var $_version = '1.0'; + /** + * Cached dependency database file + * @var array|null + * @access private + */ + var $_cache; + + // }}} + // {{{ & singleton() + + /** + * Get a raw dependency database. Calls setConfig() and assertDepsDB() + * @param PEAR_Config + * @param string|false full path to the dependency database, or false to use default + * @return PEAR_DependencyDB|PEAR_Error + * @static + */ + function &singleton(&$config, $depdb = false) + { + if (!isset($GLOBALS['_PEAR_DEPENDENCYDB_INSTANCE'] + [$config->get('php_dir', null, 'pear.php.net')])) { + $a = new PEAR_DependencyDB; + $GLOBALS['_PEAR_DEPENDENCYDB_INSTANCE'] + [$config->get('php_dir', null, 'pear.php.net')] = &$a; + $a->setConfig($config, $depdb); + if (PEAR::isError($e = $a->assertDepsDB())) { + return $e; + } + } + return $GLOBALS['_PEAR_DEPENDENCYDB_INSTANCE'] + [$config->get('php_dir', null, 'pear.php.net')]; + } + + /** + * Set up the registry/location of dependency DB + * @param PEAR_Config|false + * @param string|false full path to the dependency database, or false to use default + */ + function setConfig(&$config, $depdb = false) + { + if (!$config) { + $this->_config = &PEAR_Config::singleton(); + } else { + $this->_config = &$config; + } + $this->_registry = &$this->_config->getRegistry(); + if (!$depdb) { + $this->_depdb = $this->_config->get('php_dir', null, 'pear.php.net') . + DIRECTORY_SEPARATOR . '.depdb'; + } else { + $this->_depdb = $depdb; + } + $this->_lockfile = dirname($this->_depdb) . DIRECTORY_SEPARATOR . '.depdblock'; + } + // }}} + + function hasWriteAccess() + { + if (!file_exists($this->_depdb)) { + $dir = $this->_depdb; + while ($dir && $dir != '.') { + $dir = dirname($dir); // cd .. + if ($dir != '.' && file_exists($dir)) { + if (is_writeable($dir)) { + return true; + } else { + return false; + } + } + } + return false; + } + return is_writeable($this->_depdb); + } + + // {{{ assertDepsDB() + + /** + * Create the dependency database, if it doesn't exist. Error if the database is + * newer than the code reading it. + * @return void|PEAR_Error + */ + function assertDepsDB() + { + if (!is_file($this->_depdb)) { + $this->rebuildDB(); + } else { + $depdb = $this->_getDepDB(); + // Datatype format has been changed, rebuild the Deps DB + if ($depdb['_version'] < $this->_version) { + $this->rebuildDB(); + } + if ($depdb['_version']{0} > $this->_version{0}) { + return PEAR::raiseError('Dependency database is version ' . + $depdb['_version'] . ', and we are version ' . + $this->_version . ', cannot continue'); + } + } + } + + /** + * Get a list of installed packages that depend on this package + * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2|array + * @return array|false + */ + function getDependentPackages(&$pkg) + { + $data = $this->_getDepDB(); + if (is_object($pkg)) { + $channel = strtolower($pkg->getChannel()); + $package = strtolower($pkg->getPackage()); + } else { + $channel = strtolower($pkg['channel']); + $package = strtolower($pkg['package']); + } + if (isset($data['packages'][$channel][$package])) { + return $data['packages'][$channel][$package]; + } + return false; + } + + /** + * Get a list of the actual dependencies of installed packages that depend on + * a package. + * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2|array + * @return array|false + */ + function getDependentPackageDependencies(&$pkg) + { + $data = $this->_getDepDB(); + if (is_object($pkg)) { + $channel = strtolower($pkg->getChannel()); + $package = strtolower($pkg->getPackage()); + } else { + $channel = strtolower($pkg['channel']); + $package = strtolower($pkg['package']); + } + $depend = $this->getDependentPackages($pkg); + if (!$depend) { + return false; + } + $dependencies = array(); + foreach ($depend as $info) { + $temp = $this->getDependencies($info); + foreach ($temp as $dep) { + if (strtolower($dep['dep']['channel']) == strtolower($channel) && + strtolower($dep['dep']['name']) == strtolower($package)) { + if (!isset($dependencies[$info['channel']])) { + $dependencies[$info['channel']] = array(); + } + if (!isset($dependencies[$info['channel']][$info['package']])) { + $dependencies[$info['channel']][$info['package']] = array(); + } + $dependencies[$info['channel']][$info['package']][] = $dep; + } + } + } + return $dependencies; + } + + /** + * Get a list of dependencies of this installed package + * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2|array + * @return array|false + */ + function getDependencies(&$pkg) + { + if (is_object($pkg)) { + $channel = strtolower($pkg->getChannel()); + $package = strtolower($pkg->getPackage()); + } else { + $channel = strtolower($pkg['channel']); + $package = strtolower($pkg['package']); + } + $data = $this->_getDepDB(); + if (isset($data['dependencies'][$channel][$package])) { + return $data['dependencies'][$channel][$package]; + } + return false; + } + + /** + * Determine whether $parent depends on $child, near or deep + * @param array|PEAR_PackageFile_v2|PEAR_PackageFile_v2 + * @param array|PEAR_PackageFile_v2|PEAR_PackageFile_v2 + */ + function dependsOn($parent, $child) + { + $c = array(); + $this->_getDepDB(); + return $this->_dependsOn($parent, $child, $c); + } + + function _dependsOn($parent, $child, &$checked) + { + if (is_object($parent)) { + $channel = strtolower($parent->getChannel()); + $package = strtolower($parent->getPackage()); + } else { + $channel = strtolower($parent['channel']); + $package = strtolower($parent['package']); + } + if (is_object($child)) { + $depchannel = strtolower($child->getChannel()); + $deppackage = strtolower($child->getPackage()); + } else { + $depchannel = strtolower($child['channel']); + $deppackage = strtolower($child['package']); + } + if (isset($checked[$channel][$package][$depchannel][$deppackage])) { + return false; // avoid endless recursion + } + $checked[$channel][$package][$depchannel][$deppackage] = true; + if (!isset($this->_cache['dependencies'][$channel][$package])) { + return false; + } + foreach ($this->_cache['dependencies'][$channel][$package] as $info) { + if (isset($info['dep']['uri'])) { + if (is_object($child)) { + if ($info['dep']['uri'] == $child->getURI()) { + return true; + } + } elseif (isset($child['uri'])) { + if ($info['dep']['uri'] == $child['uri']) { + return true; + } + } + return false; + } + if (strtolower($info['dep']['channel']) == strtolower($depchannel) && + strtolower($info['dep']['name']) == strtolower($deppackage)) { + return true; + } + } + foreach ($this->_cache['dependencies'][$channel][$package] as $info) { + if (isset($info['dep']['uri'])) { + if ($this->_dependsOn(array( + 'uri' => $info['dep']['uri'], + 'package' => $info['dep']['name']), $child, $checked)) { + return true; + } + } else { + if ($this->_dependsOn(array( + 'channel' => $info['dep']['channel'], + 'package' => $info['dep']['name']), $child, $checked)) { + return true; + } + } + } + return false; + } + + /** + * Register dependencies of a package that is being installed or upgraded + * @param PEAR_PackageFile_v2|PEAR_PackageFile_v2 + */ + function installPackage(&$package) + { + $data = $this->_getDepDB(); + unset($this->_cache); + $this->_setPackageDeps($data, $package); + $this->_writeDepDB($data); + } + + /** + * Remove dependencies of a package that is being uninstalled, or upgraded. + * + * Upgraded packages first uninstall, then install + * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2|array If an array, then it must have + * indices 'channel' and 'package' + */ + function uninstallPackage(&$pkg) + { + $data = $this->_getDepDB(); + unset($this->_cache); + if (is_object($pkg)) { + $channel = strtolower($pkg->getChannel()); + $package = strtolower($pkg->getPackage()); + } else { + $channel = strtolower($pkg['channel']); + $package = strtolower($pkg['package']); + } + if (!isset($data['dependencies'][$channel][$package])) { + return true; + } + foreach ($data['dependencies'][$channel][$package] as $dep) { + $found = false; + if (isset($dep['dep']['uri'])) { + $depchannel = '__uri'; + } else { + $depchannel = strtolower($dep['dep']['channel']); + } + if (isset($data['packages'][$depchannel][strtolower($dep['dep']['name'])])) { + foreach ($data['packages'][$depchannel][strtolower($dep['dep']['name'])] as + $i => $info) { + if ($info['channel'] == $channel && + $info['package'] == $package) { + $found = true; + break; + } + } + } + if ($found) { + unset($data['packages'][$depchannel][strtolower($dep['dep']['name'])][$i]); + if (!count($data['packages'][$depchannel][strtolower($dep['dep']['name'])])) { + unset($data['packages'][$depchannel][strtolower($dep['dep']['name'])]); + if (!count($data['packages'][$depchannel])) { + unset($data['packages'][$depchannel]); + } + } else { + $data['packages'][$depchannel][strtolower($dep['dep']['name'])] = + array_values( + $data['packages'][$depchannel][strtolower($dep['dep']['name'])]); + } + } + } + unset($data['dependencies'][$channel][$package]); + if (!count($data['dependencies'][$channel])) { + unset($data['dependencies'][$channel]); + } + if (!count($data['dependencies'])) { + unset($data['dependencies']); + } + if (!count($data['packages'])) { + unset($data['packages']); + } + $this->_writeDepDB($data); + } + + /** + * Rebuild the dependency DB by reading registry entries. + * @return true|PEAR_Error + */ + function rebuildDB() + { + $depdb = array('_version' => $this->_version); + if (!$this->hasWriteAccess()) { + // allow startup for read-only with older Registry + return $depdb; + } + $packages = $this->_registry->listAllPackages(); + if (PEAR::isError($packages)) { + return $packages; + } + foreach ($packages as $channel => $ps) { + foreach ($ps as $package) { + $package = $this->_registry->getPackage($package, $channel); + if (PEAR::isError($package)) { + return $package; + } + $this->_setPackageDeps($depdb, $package); + } + } + $error = $this->_writeDepDB($depdb); + if (PEAR::isError($error)) { + return $error; + } + $this->_cache = $depdb; + return true; + } + + /** + * Register usage of the dependency DB to prevent race conditions + * @param int one of the LOCK_* constants + * @return true|PEAR_Error + * @access private + */ + function _lock($mode = LOCK_EX) + { + if (!eregi('Windows 9', php_uname())) { + if ($mode != LOCK_UN && is_resource($this->_lockFp)) { + // XXX does not check type of lock (LOCK_SH/LOCK_EX) + return true; + } + $open_mode = 'w'; + // XXX People reported problems with LOCK_SH and 'w' + if ($mode === LOCK_SH) { + if (!file_exists($this->_lockfile)) { + touch($this->_lockfile); + } elseif (!is_file($this->_lockfile)) { + return PEAR::raiseError('could not create Dependency lock file, ' . + 'it exists and is not a regular file'); + } + $open_mode = 'r'; + } + + if (!is_resource($this->_lockFp)) { + $this->_lockFp = @fopen($this->_lockfile, $open_mode); + } + if (!is_resource($this->_lockFp)) { + return PEAR::raiseError("could not create Dependency lock file" . + (isset($php_errormsg) ? ": " . $php_errormsg : "")); + } + if (!(int)flock($this->_lockFp, $mode)) { + switch ($mode) { + case LOCK_SH: $str = 'shared'; break; + case LOCK_EX: $str = 'exclusive'; break; + case LOCK_UN: $str = 'unlock'; break; + default: $str = 'unknown'; break; + } + return PEAR::raiseError("could not acquire $str lock ($this->_lockfile)"); + } + } + return true; + } + + /** + * Release usage of dependency DB + * @return true|PEAR_Error + * @access private + */ + function _unlock() + { + $ret = $this->_lock(LOCK_UN); + if (is_resource($this->_lockFp)) { + fclose($this->_lockFp); + } + $this->_lockFp = null; + return $ret; + } + + /** + * Load the dependency database from disk, or return the cache + * @return array|PEAR_Error + */ + function _getDepDB() + { + if (!$this->hasWriteAccess()) { + return array('_version' => $this->_version); + } + if (isset($this->_cache)) { + return $this->_cache; + } + if (!$fp = fopen($this->_depdb, 'r')) { + $err = PEAR::raiseError("Could not open dependencies file `".$this->_depdb."'"); + return $err; + } + $rt = get_magic_quotes_runtime(); + set_magic_quotes_runtime(0); + clearstatcache(); + fclose($fp); + $data = unserialize(file_get_contents($this->_depdb)); + set_magic_quotes_runtime($rt); + $this->_cache = $data; + return $data; + } + + /** + * Write out the dependency database to disk + * @param array the database + * @return true|PEAR_Error + * @access private + */ + function _writeDepDB(&$deps) + { + if (PEAR::isError($e = $this->_lock(LOCK_EX))) { + return $e; + } + if (!$fp = fopen($this->_depdb, 'wb')) { + $this->_unlock(); + return PEAR::raiseError("Could not open dependencies file `".$this->_depdb."' for writing"); + } + $rt = get_magic_quotes_runtime(); + set_magic_quotes_runtime(0); + fwrite($fp, serialize($deps)); + set_magic_quotes_runtime($rt); + fclose($fp); + $this->_unlock(); + $this->_cache = $deps; + return true; + } + + /** + * Register all dependencies from a package in the dependencies database, in essence + * "installing" the package's dependency information + * @param array the database + * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2 + * @access private + */ + function _setPackageDeps(&$data, &$pkg) + { + $pkg->setConfig($this->_config); + if ($pkg->getPackagexmlVersion() == '1.0') { + $gen = &$pkg->getDefaultGenerator(); + $deps = $gen->dependenciesToV2(); + } else { + $deps = $pkg->getDeps(true); + } + if (!$deps) { + return; + } + if (!is_array($data)) { + $data = array(); + } + if (!isset($data['dependencies'])) { + $data['dependencies'] = array(); + } + if (!isset($data['dependencies'][strtolower($pkg->getChannel())])) { + $data['dependencies'][strtolower($pkg->getChannel())] = array(); + } + $data['dependencies'][strtolower($pkg->getChannel())][strtolower($pkg->getPackage())] + = array(); + if (isset($deps['required']['package'])) { + if (!isset($deps['required']['package'][0])) { + $deps['required']['package'] = array($deps['required']['package']); + } + foreach ($deps['required']['package'] as $dep) { + $this->_registerDep($data, $pkg, $dep, 'required'); + } + } + if (isset($deps['optional']['package'])) { + if (!isset($deps['optional']['package'][0])) { + $deps['optional']['package'] = array($deps['optional']['package']); + } + foreach ($deps['optional']['package'] as $dep) { + $this->_registerDep($data, $pkg, $dep, 'optional'); + } + } + if (isset($deps['required']['subpackage'])) { + if (!isset($deps['required']['subpackage'][0])) { + $deps['required']['subpackage'] = array($deps['required']['subpackage']); + } + foreach ($deps['required']['subpackage'] as $dep) { + $this->_registerDep($data, $pkg, $dep, 'required'); + } + } + if (isset($deps['optional']['subpackage'])) { + if (!isset($deps['optional']['subpackage'][0])) { + $deps['optional']['subpackage'] = array($deps['optional']['subpackage']); + } + foreach ($deps['optional']['subpackage'] as $dep) { + $this->_registerDep($data, $pkg, $dep, 'optional'); + } + } + if (isset($deps['group'])) { + if (!isset($deps['group'][0])) { + $deps['group'] = array($deps['group']); + } + foreach ($deps['group'] as $group) { + if (isset($group['package'])) { + if (!isset($group['package'][0])) { + $group['package'] = array($group['package']); + } + foreach ($group['package'] as $dep) { + $this->_registerDep($data, $pkg, $dep, 'optional', + $group['attribs']['name']); + } + } + if (isset($group['subpackage'])) { + if (!isset($group['subpackage'][0])) { + $group['subpackage'] = array($group['subpackage']); + } + foreach ($group['subpackage'] as $dep) { + $this->_registerDep($data, $pkg, $dep, 'optional', + $group['attribs']['name']); + } + } + } + } + if ($data['dependencies'][strtolower($pkg->getChannel())] + [strtolower($pkg->getPackage())] == array()) { + unset($data['dependencies'][strtolower($pkg->getChannel())] + [strtolower($pkg->getPackage())]); + if (!count($data['dependencies'][strtolower($pkg->getChannel())])) { + unset($data['dependencies'][strtolower($pkg->getChannel())]); + } + } + } + + /** + * @param array the database + * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2 + * @param array the specific dependency + * @param required|optional whether this is a required or an optional dep + * @param string|false dependency group this dependency is from, or false for ordinary dep + */ + function _registerDep(&$data, &$pkg, $dep, $type, $group = false) + { + $info = array( + 'dep' => $dep, + 'type' => $type, + 'group' => $group); + + if (isset($dep['channel'])) { + $depchannel = $dep['channel']; + } else { + $depchannel = '__uri'; + } + if (!isset($data['dependencies'])) { + $data['dependencies'] = array(); + } + if (!isset($data['dependencies'][strtolower($pkg->getChannel())])) { + $data['dependencies'][strtolower($pkg->getChannel())] = array(); + } + if (!isset($data['dependencies'][strtolower($pkg->getChannel())][strtolower($pkg->getPackage())])) { + $data['dependencies'][strtolower($pkg->getChannel())][strtolower($pkg->getPackage())] = array(); + } + $data['dependencies'][strtolower($pkg->getChannel())][strtolower($pkg->getPackage())][] + = $info; + if (isset($data['packages'][strtolower($depchannel)][strtolower($dep['name'])])) { + $found = false; + foreach ($data['packages'][strtolower($depchannel)][strtolower($dep['name'])] + as $i => $p) { + if ($p['channel'] == strtolower($pkg->getChannel()) && + $p['package'] == strtolower($pkg->getPackage())) { + $found = true; + break; + } + } + if (!$found) { + $data['packages'][strtolower($depchannel)][strtolower($dep['name'])][] + = array('channel' => strtolower($pkg->getChannel()), + 'package' => strtolower($pkg->getPackage())); + } + } else { + if (!isset($data['packages'])) { + $data['packages'] = array(); + } + if (!isset($data['packages'][strtolower($depchannel)])) { + $data['packages'][strtolower($depchannel)] = array(); + } + if (!isset($data['packages'][strtolower($depchannel)][strtolower($dep['name'])])) { + $data['packages'][strtolower($depchannel)][strtolower($dep['name'])] = array(); + } + $data['packages'][strtolower($depchannel)][strtolower($dep['name'])][] + = array('channel' => strtolower($pkg->getChannel()), + 'package' => strtolower($pkg->getPackage())); + } + } +} +?> \ No newline at end of file diff --git a/src/lib/pear/PEAR/PEAR/Downloader.php b/src/lib/pear/PEAR/PEAR/Downloader.php new file mode 100644 index 0000000..c70a07b --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Downloader.php @@ -0,0 +1,1752 @@ + + * @author Stig Bakken + * @author Tomas V. V. Cox + * @author Martin Jansen + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: Downloader.php,v 1.138 2008/04/11 01:16:40 dufuz Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 1.3.0 + */ + +/** + * Needed for constants, extending + */ +require_once 'PEAR/Common.php'; + +define('PEAR_INSTALLER_OK', 1); +define('PEAR_INSTALLER_FAILED', 0); +define('PEAR_INSTALLER_SKIPPED', -1); +define('PEAR_INSTALLER_ERROR_NO_PREF_STATE', 2); + +/** + * Administration class used to download anything from the internet (PEAR Packages, + * static URLs, xml files) + * + * @category pear + * @package PEAR + * @author Greg Beaver + * @author Stig Bakken + * @author Tomas V. V. Cox + * @author Martin Jansen + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 1.3.0 + */ +class PEAR_Downloader extends PEAR_Common +{ + /** + * @var PEAR_Registry + * @access private + */ + var $_registry; + + /** + * @var PEAR_Remote + * @access private + */ + var $_remote; + + /** + * Preferred Installation State (snapshot, devel, alpha, beta, stable) + * @var string|null + * @access private + */ + var $_preferredState; + + /** + * Options from command-line passed to Install. + * + * Recognized options:
    + * - onlyreqdeps : install all required dependencies as well + * - alldeps : install all dependencies, including optional + * - installroot : base relative path to install files in + * - force : force a download even if warnings would prevent it + * - nocompress : download uncompressed tarballs + * @see PEAR_Command_Install + * @access private + * @var array + */ + var $_options; + + /** + * Downloaded Packages after a call to download(). + * + * Format of each entry: + * + * + * array('pkg' => 'package_name', 'file' => '/path/to/local/file', + * 'info' => array() // parsed package.xml + * ); + * + * @access private + * @var array + */ + var $_downloadedPackages = array(); + + /** + * Packages slated for download. + * + * This is used to prevent downloading a package more than once should it be a dependency + * for two packages to be installed. + * Format of each entry: + * + *
    +     * array('package_name1' => parsed package.xml, 'package_name2' => parsed package.xml,
    +     * );
    +     * 
    + * @access private + * @var array + */ + var $_toDownload = array(); + + /** + * Array of every package installed, with names lower-cased. + * + * Format: + * + * array('package1' => 0, 'package2' => 1, ); + * + * @var array + */ + var $_installed = array(); + + /** + * @var array + * @access private + */ + var $_errorStack = array(); + + /** + * @var boolean + * @access private + */ + var $_internalDownload = false; + + /** + * Temporary variable used in sorting packages by dependency in {@link sortPkgDeps()} + * @var array + * @access private + */ + var $_packageSortTree; + + /** + * Temporary directory, or configuration value where downloads will occur + * @var string + */ + var $_downloadDir; + // {{{ PEAR_Downloader() + + /** + * @param PEAR_Frontend_* + * @param array + * @param PEAR_Config + */ + function PEAR_Downloader(&$ui, $options, &$config) + { + parent::PEAR_Common(); + $this->_options = $options; + $this->config = &$config; + $this->_preferredState = $this->config->get('preferred_state'); + $this->ui = &$ui; + if (!$this->_preferredState) { + // don't inadvertantly use a non-set preferred_state + $this->_preferredState = null; + } + + if (isset($this->_options['installroot'])) { + $this->config->setInstallRoot($this->_options['installroot']); + } + $this->_registry = &$config->getRegistry(); + $this->_remote = &$config->getRemote(); + + if (isset($this->_options['alldeps']) || isset($this->_options['onlyreqdeps'])) { + $this->_installed = $this->_registry->listAllPackages(); + foreach ($this->_installed as $key => $unused) { + if (!count($unused)) { + continue; + } + $strtolower = create_function('$a','return strtolower($a);'); + array_walk($this->_installed[$key], $strtolower); + } + } + } + + /** + * Attempt to discover a channel's remote capabilities from + * its server name + * @param string + * @return boolean + */ + function discover($channel) + { + $this->log(1, 'Attempting to discover channel "' . $channel . '"...'); + PEAR::pushErrorHandling(PEAR_ERROR_RETURN); + $callback = $this->ui ? array(&$this, '_downloadCallback') : null; + if (!class_exists('System')) { + require_once 'System.php'; + } + $a = $this->downloadHttp('http://' . $channel . '/channel.xml', $this->ui, + System::mktemp(array('-d')), $callback, false); + PEAR::popErrorHandling(); + if (PEAR::isError($a)) { + return false; + } + list($a, $lastmodified) = $a; + if (!class_exists('PEAR_ChannelFile')) { + require_once 'PEAR/ChannelFile.php'; + } + $b = new PEAR_ChannelFile; + if ($b->fromXmlFile($a)) { + unlink($a); + if ($this->config->get('auto_discover')) { + $this->_registry->addChannel($b, $lastmodified); + $alias = $b->getName(); + if ($b->getName() == $this->_registry->channelName($b->getAlias())) { + $alias = $b->getAlias(); + } + $this->log(1, 'Auto-discovered channel "' . $channel . + '", alias "' . $alias . '", adding to registry'); + } + return true; + } + unlink($a); + return false; + } + + /** + * For simpler unit-testing + * @param PEAR_Downloader + * @return PEAR_Downloader_Package + */ + function &newDownloaderPackage(&$t) + { + if (!class_exists('PEAR_Downloader_Package')) { + require_once 'PEAR/Downloader/Package.php'; + } + $a = &new PEAR_Downloader_Package($t); + return $a; + } + + /** + * For simpler unit-testing + * @param PEAR_Config + * @param array + * @param array + * @param int + */ + function &getDependency2Object(&$c, $i, $p, $s) + { + if (!class_exists('PEAR_Dependency2')) { + require_once 'PEAR/Dependency2.php'; + } + $z = &new PEAR_Dependency2($c, $i, $p, $s); + return $z; + } + + function &download($params) + { + if (!count($params)) { + $a = array(); + return $a; + } + if (!isset($this->_registry)) { + $this->_registry = &$this->config->getRegistry(); + } + if (!isset($this->_remote)) { + $this->_remote = &$this->config->getRemote(); + } + $channelschecked = array(); + // convert all parameters into PEAR_Downloader_Package objects + foreach ($params as $i => $param) { + $params[$i] = &$this->newDownloaderPackage($this); + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + $err = $params[$i]->initialize($param); + PEAR::staticPopErrorHandling(); + if (!$err) { + // skip parameters that were missed by preferred_state + continue; + } + if (PEAR::isError($err)) { + if (!isset($this->_options['soft'])) { + $this->log(0, $err->getMessage()); + } + $params[$i] = false; + if (is_object($param)) { + $param = $param->getChannel() . '/' . $param->getPackage(); + } + $this->pushError('Package "' . $param . '" is not valid', + PEAR_INSTALLER_SKIPPED); + } else { + do { + if ($params[$i] && $params[$i]->getType() == 'local') { + // bug #7090 + // skip channel.xml check for local packages + break; + } + if ($params[$i] && !isset($channelschecked[$params[$i]->getChannel()]) && + !isset($this->_options['offline'])) { + $channelschecked[$params[$i]->getChannel()] = true; + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + if (!class_exists('System')) { + require_once 'System.php'; + } + $curchannel = &$this->_registry->getChannel($params[$i]->getChannel()); + if (PEAR::isError($curchannel)) { + PEAR::staticPopErrorHandling(); + return $this->raiseError($curchannel); + } + if (PEAR::isError($dir = $this->getDownloadDir())) { + PEAR::staticPopErrorHandling(); + break; + } + $mirror = $this->config->get('preferred_mirror', null, + $params[$i]->getChannel()); + $a = $this->downloadHttp('http://' . $mirror . + '/channel.xml', $this->ui, $dir, null, $curchannel->lastModified()); + + PEAR::staticPopErrorHandling(); + if (PEAR::isError($a) || !$a) { + break; + } + $this->log(0, 'WARNING: channel "' . $params[$i]->getChannel() . '" has ' . + 'updated its protocols, use "channel-update ' . $params[$i]->getChannel() . + '" to update'); + } + } while (false); + if ($params[$i] && !isset($this->_options['downloadonly'])) { + if (isset($this->_options['packagingroot'])) { + $checkdir = $this->_prependPath( + $this->config->get('php_dir', null, $params[$i]->getChannel()), + $this->_options['packagingroot']); + } else { + $checkdir = $this->config->get('php_dir', + null, $params[$i]->getChannel()); + } + while ($checkdir && $checkdir != '/' && !file_exists($checkdir)) { + $checkdir = dirname($checkdir); + } + if ($checkdir == '.') { + $checkdir = '/'; + } + if (!is_writeable($checkdir)) { + return PEAR::raiseError('Cannot install, php_dir for channel "' . + $params[$i]->getChannel() . '" is not writeable by the current user'); + } + } + } + } + unset($channelschecked); + PEAR_Downloader_Package::removeDuplicates($params); + if (!count($params)) { + $a = array(); + return $a; + } + if (!isset($this->_options['nodeps']) && !isset($this->_options['offline'])) { + $reverify = true; + while ($reverify) { + $reverify = false; + foreach ($params as $i => $param) { + //PHP Bug 40768 / PEAR Bug #10944 + //Nested foreaches fail in PHP 5.2.1 + key($params); + $ret = $params[$i]->detectDependencies($params); + if (PEAR::isError($ret)) { + $reverify = true; + $params[$i] = false; + PEAR_Downloader_Package::removeDuplicates($params); + if (!isset($this->_options['soft'])) { + $this->log(0, $ret->getMessage()); + } + continue 2; + } + } + } + } + if (isset($this->_options['offline'])) { + $this->log(3, 'Skipping dependency download check, --offline specified'); + } + if (!count($params)) { + $a = array(); + return $a; + } + while (PEAR_Downloader_Package::mergeDependencies($params)); + PEAR_Downloader_Package::removeDuplicates($params, true); + $errorparams = array(); + if (PEAR_Downloader_Package::detectStupidDuplicates($params, $errorparams)) { + if (count($errorparams)) { + foreach ($errorparams as $param) { + $name = $this->_registry->parsedPackageNameToString($param->getParsedPackage()); + $this->pushError('Duplicate package ' . $name . ' found', PEAR_INSTALLER_FAILED); + } + $a = array(); + return $a; + } + } + PEAR_Downloader_Package::removeInstalled($params); + if (!count($params)) { + $this->pushError('No valid packages found', PEAR_INSTALLER_FAILED); + $a = array(); + return $a; + } + PEAR::pushErrorHandling(PEAR_ERROR_RETURN); + $err = $this->analyzeDependencies($params); + PEAR::popErrorHandling(); + if (!count($params)) { + $this->pushError('No valid packages found', PEAR_INSTALLER_FAILED); + $a = array(); + return $a; + } + $ret = array(); + $newparams = array(); + if (isset($this->_options['pretend'])) { + return $params; + } + $somefailed = false; + foreach ($params as $i => $package) { + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + $pf = &$params[$i]->download(); + PEAR::staticPopErrorHandling(); + if (PEAR::isError($pf)) { + if (!isset($this->_options['soft'])) { + $this->log(1, $pf->getMessage()); + $this->log(0, 'Error: cannot download "' . + $this->_registry->parsedPackageNameToString($package->getParsedPackage(), + true) . + '"'); + } + $somefailed = true; + continue; + } + $newparams[] = &$params[$i]; + $ret[] = array('file' => $pf->getArchiveFile(), + 'info' => &$pf, + 'pkg' => $pf->getPackage()); + } + if ($somefailed) { + // remove params that did not download successfully + PEAR::pushErrorHandling(PEAR_ERROR_RETURN); + $err = $this->analyzeDependencies($newparams, true); + PEAR::popErrorHandling(); + if (!count($newparams)) { + $this->pushError('Download failed', PEAR_INSTALLER_FAILED); + $a = array(); + return $a; + } + } + $this->_downloadedPackages = $ret; + return $newparams; + } + + /** + * @param array all packages to be installed + */ + function analyzeDependencies(&$params, $force = false) + { + $hasfailed = $failed = false; + if (isset($this->_options['downloadonly'])) { + return; + } + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + $redo = true; + $reset = false; + while ($redo) { + $redo = false; + foreach ($params as $i => $param) { + $deps = $param->getDeps(); + if (!$deps) { + $depchecker = &$this->getDependency2Object($this->config, $this->getOptions(), + $param->getParsedPackage(), PEAR_VALIDATE_DOWNLOADING); + if ($param->getType() == 'xmlrpc') { + $send = $param->getDownloadURL(); + } else { + $send = $param->getPackageFile(); + } + $installcheck = $depchecker->validatePackage($send, $this, $params); + if (PEAR::isError($installcheck)) { + if (!isset($this->_options['soft'])) { + $this->log(0, $installcheck->getMessage()); + } + $hasfailed = true; + $params[$i] = false; + $reset = true; + $redo = true; + $failed = false; + PEAR_Downloader_Package::removeDuplicates($params); + continue 2; + } + continue; + } + if (!$reset && $param->alreadyValidated() && !$force) { + continue; + } + if (count($deps)) { + $depchecker = &$this->getDependency2Object($this->config, $this->getOptions(), + $param->getParsedPackage(), PEAR_VALIDATE_DOWNLOADING); + if ($param->getType() == 'xmlrpc') { + $send = $param->getDownloadURL(); + } else { + $send = $param->getPackageFile(); + } + $installcheck = $depchecker->validatePackage($send, $this, $params); + if (PEAR::isError($installcheck)) { + if (!isset($this->_options['soft'])) { + $this->log(0, $installcheck->getMessage()); + } + $hasfailed = true; + $params[$i] = false; + $reset = true; + $redo = true; + $failed = false; + PEAR_Downloader_Package::removeDuplicates($params); + continue 2; + } + $failed = false; + if (isset($deps['required'])) { + foreach ($deps['required'] as $type => $dep) { + // note: Dependency2 will never return a PEAR_Error if ignore-errors + // is specified, so soft is needed to turn off logging + if (!isset($dep[0])) { + if (PEAR::isError($e = $depchecker->{"validate{$type}Dependency"}($dep, + true, $params))) { + $failed = true; + if (!isset($this->_options['soft'])) { + $this->log(0, $e->getMessage()); + } + } elseif (is_array($e) && !$param->alreadyValidated()) { + if (!isset($this->_options['soft'])) { + $this->log(0, $e[0]); + } + } + } else { + foreach ($dep as $d) { + if (PEAR::isError($e = + $depchecker->{"validate{$type}Dependency"}($d, + true, $params))) { + $failed = true; + if (!isset($this->_options['soft'])) { + $this->log(0, $e->getMessage()); + } + } elseif (is_array($e) && !$param->alreadyValidated()) { + if (!isset($this->_options['soft'])) { + $this->log(0, $e[0]); + } + } + } + } + } + if (isset($deps['optional'])) { + foreach ($deps['optional'] as $type => $dep) { + if (!isset($dep[0])) { + if (PEAR::isError($e = + $depchecker->{"validate{$type}Dependency"}($dep, + false, $params))) { + $failed = true; + if (!isset($this->_options['soft'])) { + $this->log(0, $e->getMessage()); + } + } elseif (is_array($e) && !$param->alreadyValidated()) { + if (!isset($this->_options['soft'])) { + $this->log(0, $e[0]); + } + } + } else { + foreach ($dep as $d) { + if (PEAR::isError($e = + $depchecker->{"validate{$type}Dependency"}($d, + false, $params))) { + $failed = true; + if (!isset($this->_options['soft'])) { + $this->log(0, $e->getMessage()); + } + } elseif (is_array($e) && !$param->alreadyValidated()) { + if (!isset($this->_options['soft'])) { + $this->log(0, $e[0]); + } + } + } + } + } + } + $groupname = $param->getGroup(); + if (isset($deps['group']) && $groupname) { + if (!isset($deps['group'][0])) { + $deps['group'] = array($deps['group']); + } + $found = false; + foreach ($deps['group'] as $group) { + if ($group['attribs']['name'] == $groupname) { + $found = true; + break; + } + } + if ($found) { + unset($group['attribs']); + foreach ($group as $type => $dep) { + if (!isset($dep[0])) { + if (PEAR::isError($e = + $depchecker->{"validate{$type}Dependency"}($dep, + false, $params))) { + $failed = true; + if (!isset($this->_options['soft'])) { + $this->log(0, $e->getMessage()); + } + } elseif (is_array($e) && !$param->alreadyValidated()) { + if (!isset($this->_options['soft'])) { + $this->log(0, $e[0]); + } + } + } else { + foreach ($dep as $d) { + if (PEAR::isError($e = + $depchecker->{"validate{$type}Dependency"}($d, + false, $params))) { + $failed = true; + if (!isset($this->_options['soft'])) { + $this->log(0, $e->getMessage()); + } + } elseif (is_array($e) && !$param->alreadyValidated()) { + if (!isset($this->_options['soft'])) { + $this->log(0, $e[0]); + } + } + } + } + } + } + } + } else { + foreach ($deps as $dep) { + if (PEAR::isError($e = $depchecker->validateDependency1($dep, $params))) { + $failed = true; + if (!isset($this->_options['soft'])) { + $this->log(0, $e->getMessage()); + } + } elseif (is_array($e) && !$param->alreadyValidated()) { + if (!isset($this->_options['soft'])) { + $this->log(0, $e[0]); + } + } + } + } + $params[$i]->setValidated(); + } + if ($failed) { + $hasfailed = true; + $params[$i] = false; + $reset = true; + $redo = true; + $failed = false; + PEAR_Downloader_Package::removeDuplicates($params); + continue 2; + } + } + } + PEAR::staticPopErrorHandling(); + if ($hasfailed && (isset($this->_options['ignore-errors']) || + isset($this->_options['nodeps']))) { + // this is probably not needed, but just in case + if (!isset($this->_options['soft'])) { + $this->log(0, 'WARNING: dependencies failed'); + } + } + } + + /** + * Retrieve the directory that downloads will happen in + * @access private + * @return string + */ + function getDownloadDir() + { + if (isset($this->_downloadDir)) { + return $this->_downloadDir; + } + $downloaddir = $this->config->get('download_dir'); + if (empty($downloaddir) || (is_dir($downloaddir) && !is_writable($downloaddir))) { + if (is_dir($downloaddir) && !is_writable($downloaddir)) { + $this->log(0, 'WARNING: configuration download directory "' . $downloaddir . + '" is not writeable. Change download_dir config variable to ' . + 'a writeable dir to avoid this warning'); + } + if (!class_exists('System')) { + require_once 'System.php'; + } + if (PEAR::isError($downloaddir = System::mktemp('-d'))) { + return $downloaddir; + } + $this->log(3, '+ tmp dir created at ' . $downloaddir); + } + if (!is_writable($downloaddir)) { + if (PEAR::isError(System::mkdir(array('-p', $downloaddir))) || + !is_writable($downloaddir)) { + return PEAR::raiseError('download directory "' . $downloaddir . + '" is not writeable. Change download_dir config variable to ' . + 'a writeable dir'); + } + } + return $this->_downloadDir = $downloaddir; + } + + function setDownloadDir($dir) + { + if (!@is_writable($dir)) { + if (PEAR::isError(System::mkdir(array('-p', $dir)))) { + return PEAR::raiseError('download directory "' . $dir . + '" is not writeable. Change download_dir config variable to ' . + 'a writeable dir'); + } + } + $this->_downloadDir = $dir; + } + + // }}} + // {{{ configSet() + function configSet($key, $value, $layer = 'user', $channel = false) + { + $this->config->set($key, $value, $layer, $channel); + $this->_preferredState = $this->config->get('preferred_state', null, $channel); + if (!$this->_preferredState) { + // don't inadvertantly use a non-set preferred_state + $this->_preferredState = null; + } + } + + // }}} + // {{{ setOptions() + function setOptions($options) + { + $this->_options = $options; + } + + // }}} + // {{{ setOptions() + function getOptions() + { + return $this->_options; + } + + // }}} + + /** + * For simpler unit-testing + * @param PEAR_Config + * @param int + * @param string + */ + function &getPackagefileObject(&$c, $d, $t = false) + { + if (!class_exists('PEAR_PackageFile')) { + require_once 'PEAR/PackageFile.php'; + } + $a = &new PEAR_PackageFile($c, $d, $t); + return $a; + } + + // {{{ _getPackageDownloadUrl() + + /** + * @param array output of {@link parsePackageName()} + * @access private + */ + function _getPackageDownloadUrl($parr) + { + $curchannel = $this->config->get('default_channel'); + $this->configSet('default_channel', $parr['channel']); + // getDownloadURL returns an array. On error, it only contains information + // on the latest release as array(version, info). On success it contains + // array(version, info, download url string) + $state = isset($parr['state']) ? $parr['state'] : $this->config->get('preferred_state'); + if (!$this->_registry->channelExists($parr['channel'])) { + do { + if ($this->config->get('auto_discover')) { + if ($this->discover($parr['channel'])) { + break; + } + } + $this->configSet('default_channel', $curchannel); + return PEAR::raiseError('Unknown remote channel: ' . $remotechannel); + } while (false); + } + $chan = &$this->_registry->getChannel($parr['channel']); + if (PEAR::isError($chan)) { + return $chan; + } + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + $version = $this->_registry->packageInfo($parr['package'], 'version', + $parr['channel']); + PEAR::staticPopErrorHandling(); + $base2 = false; + if ($chan->supportsREST($this->config->get('preferred_mirror')) && + (($base2 = $chan->getBaseURL('REST1.3', $this->config->get('preferred_mirror'))) || + ($base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))))) { + if ($base2) { + $rest = &$this->config->getREST('1.3', $this->_options); + $base = $base2; + } else { + $rest = &$this->config->getREST('1.0', $this->_options); + } + if (!isset($parr['version']) && !isset($parr['state']) && $version + && !PEAR::isError($version) + && !isset($this->_options['downloadonly'])) { + $url = $rest->getDownloadURL($base, $parr, $state, $version, $chan->getName()); + } else { + $url = $rest->getDownloadURL($base, $parr, $state, false, $chan->getName()); + } + if (PEAR::isError($url)) { + $this->configSet('default_channel', $curchannel); + return $url; + } + if ($parr['channel'] != $curchannel) { + $this->configSet('default_channel', $curchannel); + } + if (!is_array($url)) { + return $url; + } + $url['raw'] = false; // no checking is necessary for REST + if (!is_array($url['info'])) { + return PEAR::raiseError('Invalid remote dependencies retrieved from REST - ' . + 'this should never happen'); + } + if (!isset($this->_options['force']) && + !isset($this->_options['downloadonly']) && + $version && + !PEAR::isError($version) && + !isset($parr['group'])) { + if (version_compare($version, $url['version'], '>=')) { + return PEAR::raiseError($this->_registry->parsedPackageNameToString( + $parr, true) . ' is already installed and is newer than detected ' . + 'release version ' . $url['version'], -976); + } + } + if (isset($url['info']['required']) || $url['compatible']) { + require_once 'PEAR/PackageFile/v2.php'; + $pf = new PEAR_PackageFile_v2; + $pf->setRawChannel($parr['channel']); + if ($url['compatible']) { + $pf->setRawCompatible($url['compatible']); + } + } else { + require_once 'PEAR/PackageFile/v1.php'; + $pf = new PEAR_PackageFile_v1; + } + $pf->setRawPackage($url['package']); + $pf->setDeps($url['info']); + if ($url['compatible']) { + $pf->setCompatible($url['compatible']); + } + $pf->setRawState($url['stability']); + $url['info'] = &$pf; + if (!extension_loaded("zlib") || isset($this->_options['nocompress'])) { + $ext = '.tar'; + } else { + $ext = '.tgz'; + } + if (is_array($url)) { + if (isset($url['url'])) { + $url['url'] .= $ext; + } + } + return $url; + } elseif ($chan->supports('xmlrpc', 'package.getDownloadURL', false, '1.1')) { + // don't install with the old version information unless we're doing a plain + // vanilla simple installation. If the user says to install a particular + // version or state, ignore the current installed version + if (!isset($parr['version']) && !isset($parr['state']) && $version + && !isset($this->_options['downloadonly'])) { + $url = $this->_remote->call('package.getDownloadURL', $parr, $state, $version); + } else { + $url = $this->_remote->call('package.getDownloadURL', $parr, $state); + } + } else { + $url = $this->_remote->call('package.getDownloadURL', $parr, $state); + } + if (PEAR::isError($url)) { + return $url; + } + if ($parr['channel'] != $curchannel) { + $this->configSet('default_channel', $curchannel); + } + if (isset($url['__PEAR_ERROR_CLASS__'])) { + return PEAR::raiseError($url['message']); + } + if (!is_array($url)) { + return $url; + } + $url['raw'] = $url['info']; + if (isset($this->_options['downloadonly'])) { + $pkg = &$this->getPackagefileObject($this->config, $this->debug); + } else { + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + if (PEAR::isError($dir = $this->getDownloadDir())) { + PEAR::staticPopErrorHandling(); + return $dir; + } + PEAR::staticPopErrorHandling(); + $pkg = &$this->getPackagefileObject($this->config, $this->debug, $dir); + } + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + $pinfo = &$pkg->fromXmlString($url['info'], PEAR_VALIDATE_DOWNLOADING, 'remote'); + PEAR::staticPopErrorHandling(); + if (PEAR::isError($pinfo)) { + if (!isset($this->_options['soft'])) { + $this->log(0, $pinfo->getMessage()); + } + return PEAR::raiseError('Remote package.xml is not valid - this should never happen'); + } + $url['info'] = &$pinfo; + if (!extension_loaded("zlib") || isset($this->_options['nocompress'])) { + $ext = '.tar'; + } else { + $ext = '.tgz'; + } + if (is_array($url)) { + if (isset($url['url'])) { + $url['url'] .= $ext; + } + } + return $url; + } + // }}} + // {{{ getDepPackageDownloadUrl() + + /** + * @param array dependency array + * @access private + */ + function _getDepPackageDownloadUrl($dep, $parr) + { + $xsdversion = isset($dep['rel']) ? '1.0' : '2.0'; + $curchannel = $this->config->get('default_channel'); + if (isset($dep['uri'])) { + $xsdversion = '2.0'; + $chan = &$this->_registry->getChannel('__uri'); + if (PEAR::isError($chan)) { + return $chan; + } + $version = $this->_registry->packageInfo($dep['name'], 'version', '__uri'); + $this->configSet('default_channel', '__uri'); + } else { + if (isset($dep['channel'])) { + $remotechannel = $dep['channel']; + } else { + $remotechannel = 'pear.php.net'; + } + if (!$this->_registry->channelExists($remotechannel)) { + do { + if ($this->config->get('auto_discover')) { + if ($this->discover($remotechannel)) { + break; + } + } + return PEAR::raiseError('Unknown remote channel: ' . $remotechannel); + } while (false); + } + $chan = &$this->_registry->getChannel($remotechannel); + if (PEAR::isError($chan)) { + return $chan; + } + $version = $this->_registry->packageInfo($dep['name'], 'version', + $remotechannel); + $this->configSet('default_channel', $remotechannel); + } + $state = isset($parr['state']) ? $parr['state'] : $this->config->get('preferred_state'); + if (isset($parr['state']) && isset($parr['version'])) { + unset($parr['state']); + } + if (isset($dep['uri'])) { + $info = &$this->newDownloaderPackage($this); + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + $err = $info->initialize($dep); + PEAR::staticPopErrorHandling(); + if (!$err) { + // skip parameters that were missed by preferred_state + return PEAR::raiseError('Cannot initialize dependency'); + } + if (PEAR::isError($err)) { + if (!isset($this->_options['soft'])) { + $this->log(0, $err->getMessage()); + } + if (is_object($info)) { + $param = $info->getChannel() . '/' . $info->getPackage(); + } + return PEAR::raiseError('Package "' . $param . '" is not valid'); + } + return $info; + } elseif ($chan->supportsREST($this->config->get('preferred_mirror')) && + $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) { + $rest = &$this->config->getREST('1.0', $this->_options); + $url = $rest->getDepDownloadURL($base, $xsdversion, $dep, $parr, + $state, $version, $chan->getName()); + if (PEAR::isError($url)) { + return $url; + } + if ($parr['channel'] != $curchannel) { + $this->configSet('default_channel', $curchannel); + } + if (!is_array($url)) { + return $url; + } + $url['raw'] = false; // no checking is necessary for REST + if (!is_array($url['info'])) { + return PEAR::raiseError('Invalid remote dependencies retrieved from REST - ' . + 'this should never happen'); + } + if (isset($url['info']['required'])) { + if (!class_exists('PEAR_PackageFile_v2')) { + require_once 'PEAR/PackageFile/v2.php'; + } + $pf = new PEAR_PackageFile_v2; + $pf->setRawChannel($remotechannel); + } else { + if (!class_exists('PEAR_PackageFile_v1')) { + require_once 'PEAR/PackageFile/v1.php'; + } + $pf = new PEAR_PackageFile_v1; + } + $pf->setRawPackage($url['package']); + $pf->setDeps($url['info']); + if ($url['compatible']) { + $pf->setCompatible($url['compatible']); + } + $pf->setRawState($url['stability']); + $url['info'] = &$pf; + if (!extension_loaded("zlib") || isset($this->_options['nocompress'])) { + $ext = '.tar'; + } else { + $ext = '.tgz'; + } + if (is_array($url)) { + if (isset($url['url'])) { + $url['url'] .= $ext; + } + } + return $url; + } elseif ($chan->supports('xmlrpc', 'package.getDepDownloadURL', false, '1.1')) { + if ($version) { + $url = $this->_remote->call('package.getDepDownloadURL', $xsdversion, $dep, $parr, + $state, $version); + } else { + $url = $this->_remote->call('package.getDepDownloadURL', $xsdversion, $dep, $parr, + $state); + } + } else { + $url = $this->_remote->call('package.getDepDownloadURL', $xsdversion, $dep, $parr, $state); + } + if ($this->config->get('default_channel') != $curchannel) { + $this->configSet('default_channel', $curchannel); + } + if (!is_array($url)) { + return $url; + } + if (isset($url['__PEAR_ERROR_CLASS__'])) { + return PEAR::raiseError($url['message']); + } + $url['raw'] = $url['info']; + $pkg = &$this->getPackagefileObject($this->config, $this->debug); + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + $pinfo = &$pkg->fromXmlString($url['info'], PEAR_VALIDATE_DOWNLOADING, 'remote'); + PEAR::staticPopErrorHandling(); + if (PEAR::isError($pinfo)) { + if (!isset($this->_options['soft'])) { + $this->log(0, $pinfo->getMessage()); + } + return PEAR::raiseError('Remote package.xml is not valid - this should never happen'); + } + $url['info'] = &$pinfo; + if (is_array($url)) { + if (!extension_loaded("zlib") || isset($this->_options['nocompress'])) { + $ext = '.tar'; + } else { + $ext = '.tgz'; + } + if (isset($url['url'])) { + $url['url'] .= $ext; + } + } + return $url; + } + // }}} + // {{{ getPackageDownloadUrl() + + /** + * @deprecated in favor of _getPackageDownloadUrl + */ + function getPackageDownloadUrl($package, $version = null, $channel = false) + { + if ($version) { + $package .= "-$version"; + } + if ($this === null || $this->_registry === null) { + $package = "http://pear.php.net/get/$package"; + } else { + $chan = $this->_registry->getChannel($channel); + if (PEAR::isError($chan)) { + return ''; + } + $package = "http://" . $chan->getServer() . "/get/$package"; + } + if (!extension_loaded("zlib")) { + $package .= '?uncompress=yes'; + } + return $package; + } + + // }}} + // {{{ getDownloadedPackages() + + /** + * Retrieve a list of downloaded packages after a call to {@link download()}. + * + * Also resets the list of downloaded packages. + * @return array + */ + function getDownloadedPackages() + { + $ret = $this->_downloadedPackages; + $this->_downloadedPackages = array(); + $this->_toDownload = array(); + return $ret; + } + + // }}} + // {{{ _downloadCallback() + + function _downloadCallback($msg, $params = null) + { + switch ($msg) { + case 'saveas': + $this->log(1, "downloading $params ..."); + break; + case 'done': + $this->log(1, '...done: ' . number_format($params, 0, '', ',') . ' bytes'); + break; + case 'bytesread': + static $bytes; + if (empty($bytes)) { + $bytes = 0; + } + if (!($bytes % 10240)) { + $this->log(1, '.', false); + } + $bytes += $params; + break; + case 'start': + if($params[1] == -1) { + $length = "Unknown size"; + } else { + $length = number_format($params[1], 0, '', ',')." bytes"; + } + $this->log(1, "Starting to download {$params[0]} ($length)"); + break; + } + if (method_exists($this->ui, '_downloadCallback')) + $this->ui->_downloadCallback($msg, $params); + } + + // }}} + // {{{ _prependPath($path, $prepend) + + function _prependPath($path, $prepend) + { + if (strlen($prepend) > 0) { + if (OS_WINDOWS && preg_match('/^[a-z]:/i', $path)) { + if (preg_match('/^[a-z]:/i', $prepend)) { + $prepend = substr($prepend, 2); + } elseif ($prepend{0} != '\\') { + $prepend = "\\$prepend"; + } + $path = substr($path, 0, 2) . $prepend . substr($path, 2); + } else { + $path = $prepend . $path; + } + } + return $path; + } + // }}} + // {{{ pushError($errmsg, $code) + + /** + * @param string + * @param integer + */ + function pushError($errmsg, $code = -1) + { + array_push($this->_errorStack, array($errmsg, $code)); + } + + // }}} + // {{{ getErrorMsgs() + + function getErrorMsgs() + { + $msgs = array(); + $errs = $this->_errorStack; + foreach ($errs as $err) { + $msgs[] = $err[0]; + } + $this->_errorStack = array(); + return $msgs; + } + + // }}} + + /** + * for BC + */ + function sortPkgDeps(&$packages, $uninstall = false) + { + $uninstall ? + $this->sortPackagesForUninstall($packages) : + $this->sortPackagesForInstall($packages); + } + + /** + * Sort a list of arrays of array(downloaded packagefilename) by dependency. + * + * This uses the topological sort method from graph theory, and the + * Structures_Graph package to properly sort dependencies for installation. + * @param array an array of downloaded PEAR_Downloader_Packages + * @return array array of array(packagefilename, package.xml contents) + */ + function sortPackagesForInstall(&$packages) + { + require_once 'Structures/Graph.php'; + require_once 'Structures/Graph/Node.php'; + require_once 'Structures/Graph/Manipulator/TopologicalSorter.php'; + $depgraph = new Structures_Graph(true); + $nodes = array(); + $reg = &$this->config->getRegistry(); + foreach ($packages as $i => $package) { + $pname = $reg->parsedPackageNameToString( + array( + 'channel' => $package->getChannel(), + 'package' => strtolower($package->getPackage()), + )); + $nodes[$pname] = new Structures_Graph_Node; + $nodes[$pname]->setData($packages[$i]); + $depgraph->addNode($nodes[$pname]); + } + $deplinks = array(); + foreach ($nodes as $package => $node) { + $pf = &$node->getData(); + $pdeps = $pf->getDeps(true); + if (!$pdeps) { + continue; + } + if ($pf->getPackagexmlVersion() == '1.0') { + foreach ($pdeps as $dep) { + if ($dep['type'] != 'pkg' || + (isset($dep['optional']) && $dep['optional'] == 'yes')) { + continue; + } + $dname = $reg->parsedPackageNameToString( + array( + 'channel' => 'pear.php.net', + 'package' => strtolower($dep['name']), + )); + if (isset($nodes[$dname])) + { + if (!isset($deplinks[$dname])) { + $deplinks[$dname] = array(); + } + $deplinks[$dname][$package] = 1; + // dependency is in installed packages + continue; + } + $dname = $reg->parsedPackageNameToString( + array( + 'channel' => 'pecl.php.net', + 'package' => strtolower($dep['name']), + )); + if (isset($nodes[$dname])) + { + if (!isset($deplinks[$dname])) { + $deplinks[$dname] = array(); + } + $deplinks[$dname][$package] = 1; + // dependency is in installed packages + continue; + } + } + } else { + // the only ordering we care about is: + // 1) subpackages must be installed before packages that depend on them + // 2) required deps must be installed before packages that depend on them + if (isset($pdeps['required']['subpackage'])) { + $t = $pdeps['required']['subpackage']; + if (!isset($t[0])) { + $t = array($t); + } + $this->_setupGraph($t, $reg, $deplinks, $nodes, $package); + } + if (isset($pdeps['group'])) { + if (!isset($pdeps['group'][0])) { + $pdeps['group'] = array($pdeps['group']); + } + foreach ($pdeps['group'] as $group) { + if (isset($group['subpackage'])) { + $t = $group['subpackage']; + if (!isset($t[0])) { + $t = array($t); + } + $this->_setupGraph($t, $reg, $deplinks, $nodes, $package); + } + } + } + if (isset($pdeps['optional']['subpackage'])) { + $t = $pdeps['optional']['subpackage']; + if (!isset($t[0])) { + $t = array($t); + } + $this->_setupGraph($t, $reg, $deplinks, $nodes, $package); + } + if (isset($pdeps['required']['package'])) { + $t = $pdeps['required']['package']; + if (!isset($t[0])) { + $t = array($t); + } + $this->_setupGraph($t, $reg, $deplinks, $nodes, $package); + } + if (isset($pdeps['group'])) { + if (!isset($pdeps['group'][0])) { + $pdeps['group'] = array($pdeps['group']); + } + foreach ($pdeps['group'] as $group) { + if (isset($group['package'])) { + $t = $group['package']; + if (!isset($t[0])) { + $t = array($t); + } + $this->_setupGraph($t, $reg, $deplinks, $nodes, $package); + } + } + } + } + } + $this->_detectDepCycle($deplinks); + foreach ($deplinks as $dependent => $parents) { + foreach ($parents as $parent => $unused) { + $nodes[$dependent]->connectTo($nodes[$parent]); + } + } + $installOrder = Structures_Graph_Manipulator_TopologicalSorter::sort($depgraph); + $ret = array(); + for ($i = 0; $i < count($installOrder); $i++) { + foreach ($installOrder[$i] as $index => $sortedpackage) { + $data = &$installOrder[$i][$index]->getData(); + $ret[] = &$nodes[$reg->parsedPackageNameToString( + array( + 'channel' => $data->getChannel(), + 'package' => strtolower($data->getPackage()), + ))]->getData(); + } + } + $packages = $ret; + return; + } + + /** + * Detect recursive links between dependencies and break the cycles + * + * @param array + * @access private + */ + function _detectDepCycle(&$deplinks) + { + do { + $keepgoing = false; + foreach ($deplinks as $dep => $parents) { + foreach ($parents as $parent => $unused) { + // reset the parent cycle detector + $this->_testCycle(null, null, null); + if ($this->_testCycle($dep, $deplinks, $parent)) { + $keepgoing = true; + unset($deplinks[$dep][$parent]); + if (count($deplinks[$dep]) == 0) { + unset($deplinks[$dep]); + } + continue 3; + } + } + } + } while ($keepgoing); + } + + function _testCycle($test, $deplinks, $dep) + { + static $visited = array(); + if ($test === null) { + $visited = array(); + return; + } + // this happens when a parent has a dep cycle on another dependency + // but the child is not part of the cycle + if (isset($visited[$dep])) { + return false; + } + $visited[$dep] = 1; + if ($test == $dep) { + return true; + } + if (isset($deplinks[$dep])) { + if (in_array($test, array_keys($deplinks[$dep]), true)) { + return true; + } + foreach ($deplinks[$dep] as $parent => $unused) { + if ($this->_testCycle($test, $deplinks, $parent)) { + return true; + } + } + } + return false; + } + + /** + * Set up the dependency for installation parsing + * + * @param array $t dependency information + * @param PEAR_Registry $reg + * @param array $deplinks list of dependency links already established + * @param array $nodes all existing package nodes + * @param string $package parent package name + * @access private + */ + function _setupGraph($t, $reg, &$deplinks, &$nodes, $package) + { + foreach ($t as $dep) { + $depchannel = !isset($dep['channel']) ? + '__uri': $dep['channel']; + $dname = $reg->parsedPackageNameToString( + array( + 'channel' => $depchannel, + 'package' => strtolower($dep['name']), + )); + if (isset($nodes[$dname])) + { + if (!isset($deplinks[$dname])) { + $deplinks[$dname] = array(); + } + $deplinks[$dname][$package] = 1; + } + } + } + + function _dependsOn($a, $b) + { + return $this->_checkDepTree(strtolower($a->getChannel()), strtolower($a->getPackage()), + $b); + } + + function _checkDepTree($channel, $package, $b, $checked = array()) + { + $checked[$channel][$package] = true; + if (!isset($this->_depTree[$channel][$package])) { + return false; + } + if (isset($this->_depTree[$channel][$package][strtolower($b->getChannel())] + [strtolower($b->getPackage())])) { + return true; + } + foreach ($this->_depTree[$channel][$package] as $ch => $packages) { + foreach ($packages as $pa => $true) { + if ($this->_checkDepTree($ch, $pa, $b, $checked)) { + return true; + } + } + } + return false; + } + + function _sortInstall($a, $b) + { + if (!$a->getDeps() && !$b->getDeps()) { + return 0; // neither package has dependencies, order is insignificant + } + if ($a->getDeps() && !$b->getDeps()) { + return 1; // $a must be installed after $b because $a has dependencies + } + if (!$a->getDeps() && $b->getDeps()) { + return -1; // $b must be installed after $a because $b has dependencies + } + // both packages have dependencies + if ($this->_dependsOn($a, $b)) { + return 1; + } + if ($this->_dependsOn($b, $a)) { + return -1; + } + return 0; + } + + /** + * Download a file through HTTP. Considers suggested file name in + * Content-disposition: header and can run a callback function for + * different events. The callback will be called with two + * parameters: the callback type, and parameters. The implemented + * callback types are: + * + * 'setup' called at the very beginning, parameter is a UI object + * that should be used for all output + * 'message' the parameter is a string with an informational message + * 'saveas' may be used to save with a different file name, the + * parameter is the filename that is about to be used. + * If a 'saveas' callback returns a non-empty string, + * that file name will be used as the filename instead. + * Note that $save_dir will not be affected by this, only + * the basename of the file. + * 'start' download is starting, parameter is number of bytes + * that are expected, or -1 if unknown + * 'bytesread' parameter is the number of bytes read so far + * 'done' download is complete, parameter is the total number + * of bytes read + * 'connfailed' if the TCP/SSL connection fails, this callback is called + * with array(host,port,errno,errmsg) + * 'writefailed' if writing to disk fails, this callback is called + * with array(destfile,errmsg) + * + * If an HTTP proxy has been configured (http_proxy PEAR_Config + * setting), the proxy will be used. + * + * @param string $url the URL to download + * @param object $ui PEAR_Frontend_* instance + * @param object $config PEAR_Config instance + * @param string $save_dir directory to save file in + * @param mixed $callback function/method to call for status + * updates + * @param false|string|array $lastmodified header values to check against for caching + * use false to return the header values from this download + * @param false|array $accept Accept headers to send + * @param false|string $channel Channel to use for retrieving authentication + * @return string|array Returns the full path of the downloaded file or a PEAR + * error on failure. If the error is caused by + * socket-related errors, the error object will + * have the fsockopen error code available through + * getCode(). If caching is requested, then return the header + * values. + * + * @access public + */ + function downloadHttp($url, &$ui, $save_dir = '.', $callback = null, $lastmodified = null, + $accept = false, $channel = false) + { + static $redirect = 0; + // allways reset , so we are clean case of error + $wasredirect = $redirect; + $redirect = 0; + if ($callback) { + call_user_func($callback, 'setup', array(&$ui)); + } + $info = parse_url($url); + if (!isset($info['scheme']) || !in_array($info['scheme'], array('http', 'https'))) { + return PEAR::raiseError('Cannot download non-http URL "' . $url . '"'); + } + if (!isset($info['host'])) { + return PEAR::raiseError('Cannot download from non-URL "' . $url . '"'); + } else { + $host = isset($info['host']) ? $info['host'] : null; + $port = isset($info['port']) ? $info['port'] : null; + $path = isset($info['path']) ? $info['path'] : null; + } + if (isset($this)) { + $config = &$this->config; + } else { + $config = &PEAR_Config::singleton(); + } + $proxy_host = $proxy_port = $proxy_user = $proxy_pass = ''; + if ($config->get('http_proxy') && + $proxy = parse_url($config->get('http_proxy'))) { + $proxy_host = isset($proxy['host']) ? $proxy['host'] : null; + if (isset($proxy['scheme']) && $proxy['scheme'] == 'https') { + $proxy_host = 'ssl://' . $proxy_host; + } + $proxy_port = isset($proxy['port']) ? $proxy['port'] : 8080; + $proxy_user = isset($proxy['user']) ? urldecode($proxy['user']) : null; + $proxy_pass = isset($proxy['pass']) ? urldecode($proxy['pass']) : null; + + if ($callback) { + call_user_func($callback, 'message', "Using HTTP proxy $host:$port"); + } + } + if (empty($port)) { + if (isset($info['scheme']) && $info['scheme'] == 'https') { + $port = 443; + } else { + $port = 80; + } + } + if ($proxy_host != '') { + $fp = @fsockopen($proxy_host, $proxy_port, $errno, $errstr); + if (!$fp) { + if ($callback) { + call_user_func($callback, 'connfailed', array($proxy_host, $proxy_port, + $errno, $errstr)); + } + return PEAR::raiseError("Connection to `$proxy_host:$proxy_port' failed: $errstr", $errno); + } + if ($lastmodified === false || $lastmodified) { + $request = "GET $url HTTP/1.1\r\n"; + } else { + $request = "GET $url HTTP/1.0\r\n"; + } + } else { + if (isset($info['scheme']) && $info['scheme'] == 'https') { + $host = 'ssl://' . $host; + } + $fp = @fsockopen($host, $port, $errno, $errstr); + if (!$fp) { + if ($callback) { + call_user_func($callback, 'connfailed', array($host, $port, + $errno, $errstr)); + } + return PEAR::raiseError("Connection to `$host:$port' failed: $errstr", $errno); + } + if ($lastmodified === false || $lastmodified) { + $request = "GET $path HTTP/1.1\r\n"; + $request .= "Host: $host:$port\r\n"; + } else { + $request = "GET $path HTTP/1.0\r\n"; + $request .= "Host: $host\r\n"; + } + } + $ifmodifiedsince = ''; + if (is_array($lastmodified)) { + if (isset($lastmodified['Last-Modified'])) { + $ifmodifiedsince = 'If-Modified-Since: ' . $lastmodified['Last-Modified'] . "\r\n"; + } + if (isset($lastmodified['ETag'])) { + $ifmodifiedsince .= "If-None-Match: $lastmodified[ETag]\r\n"; + } + } else { + $ifmodifiedsince = ($lastmodified ? "If-Modified-Since: $lastmodified\r\n" : ''); + } + $request .= $ifmodifiedsince . "User-Agent: PEAR/1.7.2/PHP/" . + PHP_VERSION . "\r\n"; + if (isset($this)) { // only pass in authentication for non-static calls + $username = $config->get('username', null, $channel); + $password = $config->get('password', null, $channel); + if ($username && $password) { + $tmp = base64_encode("$username:$password"); + $request .= "Authorization: Basic $tmp\r\n"; + } + } + if ($proxy_host != '' && $proxy_user != '') { + $request .= 'Proxy-Authorization: Basic ' . + base64_encode($proxy_user . ':' . $proxy_pass) . "\r\n"; + } + if ($accept) { + $request .= 'Accept: ' . implode(', ', $accept) . "\r\n"; + } + $request .= "Connection: close\r\n"; + $request .= "\r\n"; + fwrite($fp, $request); + $headers = array(); + $reply = 0; + while (trim($line = fgets($fp, 1024))) { + if (preg_match('/^([^:]+):\s+(.*)\s*\\z/', $line, $matches)) { + $headers[strtolower($matches[1])] = trim($matches[2]); + } elseif (preg_match('|^HTTP/1.[01] ([0-9]{3}) |', $line, $matches)) { + $reply = (int) $matches[1]; + if ($reply == 304 && ($lastmodified || ($lastmodified === false))) { + return false; + } + if (! in_array($reply, array(200, 301, 302, 303, 305, 307))) { + return PEAR::raiseError("File http://$host:$port$path not valid (received: $line)"); + } + } + } + if ($reply != 200) { + if (isset($headers['location'])) { + if ($wasredirect < 5) { + $redirect = $wasredirect + 1; + return $this->downloadHttp($headers['location'], + $ui, $save_dir, $callback, $lastmodified, $accept); + } else { + return PEAR::raiseError("File http://$host:$port$path not valid (redirection looped more than 5 times)"); + } + } else { + return PEAR::raiseError("File http://$host:$port$path not valid (redirected but no location)"); + } + } + if (isset($headers['content-disposition']) && + preg_match('/\sfilename=\"([^;]*\S)\"\s*(;|\\z)/', $headers['content-disposition'], $matches)) { + $save_as = basename($matches[1]); + } else { + $save_as = basename($url); + } + if ($callback) { + $tmp = call_user_func($callback, 'saveas', $save_as); + if ($tmp) { + $save_as = $tmp; + } + } + $dest_file = $save_dir . DIRECTORY_SEPARATOR . $save_as; + if (!$wp = @fopen($dest_file, 'wb')) { + fclose($fp); + if ($callback) { + call_user_func($callback, 'writefailed', array($dest_file, $php_errormsg)); + } + return PEAR::raiseError("could not open $dest_file for writing"); + } + if (isset($headers['content-length'])) { + $length = $headers['content-length']; + } else { + $length = -1; + } + $bytes = 0; + if ($callback) { + call_user_func($callback, 'start', array(basename($dest_file), $length)); + } + while ($data = fread($fp, 1024)) { + $bytes += strlen($data); + if ($callback) { + call_user_func($callback, 'bytesread', $bytes); + } + if (!@fwrite($wp, $data)) { + fclose($fp); + if ($callback) { + call_user_func($callback, 'writefailed', array($dest_file, $php_errormsg)); + } + return PEAR::raiseError("$dest_file: write failed ($php_errormsg)"); + } + } + fclose($fp); + fclose($wp); + if ($callback) { + call_user_func($callback, 'done', $bytes); + } + if ($lastmodified === false || $lastmodified) { + if (isset($headers['etag'])) { + $lastmodified = array('ETag' => $headers['etag']); + } + if (isset($headers['last-modified'])) { + if (is_array($lastmodified)) { + $lastmodified['Last-Modified'] = $headers['last-modified']; + } else { + $lastmodified = $headers['last-modified']; + } + } + return array($dest_file, $lastmodified, $headers); + } + return $dest_file; + } +} +// }}} + +?> diff --git a/src/lib/pear/PEAR/PEAR/Downloader/Package.php b/src/lib/pear/PEAR/PEAR/Downloader/Package.php new file mode 100644 index 0000000..90eaa2d --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Downloader/Package.php @@ -0,0 +1,1853 @@ + + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: Package.php,v 1.113 2008/03/29 14:18:36 dufuz Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 1.4.0a1 + */ +/** + * Error code when parameter initialization fails because no releases + * exist within preferred_state, but releases do exist + */ +define('PEAR_DOWNLOADER_PACKAGE_STATE', -1003); +/** + * Error code when parameter initialization fails because no releases + * exist that will work with the existing PHP version + */ +define('PEAR_DOWNLOADER_PACKAGE_PHPVERSION', -1004); +/** + * Coordinates download parameters and manages their dependencies + * prior to downloading them. + * + * Input can come from three sources: + * + * - local files (archives or package.xml) + * - remote files (downloadable urls) + * - abstract package names + * + * The first two elements are handled cleanly by PEAR_PackageFile, but the third requires + * accessing pearweb's xml-rpc interface to determine necessary dependencies, and the + * format returned of dependencies is slightly different from that used in package.xml. + * + * This class hides the differences between these elements, and makes automatic + * dependency resolution a piece of cake. It also manages conflicts when + * two classes depend on incompatible dependencies, or differing versions of the same + * package dependency. In addition, download will not be attempted if the php version is + * not supported, PEAR installer version is not supported, or non-PECL extensions are not + * installed. + * @category pear + * @package PEAR + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 1.4.0a1 + */ +class PEAR_Downloader_Package +{ + /** + * @var PEAR_Downloader + */ + var $_downloader; + /** + * @var PEAR_Config + */ + var $_config; + /** + * @var PEAR_Registry + */ + var $_registry; + /** + * Used to implement packagingroot properly + * @var PEAR_Registry + */ + var $_installRegistry; + /** + * @var PEAR_PackageFile_v1|PEAR_PackageFile|v2 + */ + var $_packagefile; + /** + * @var array + */ + var $_parsedname; + /** + * @var array + */ + var $_downloadURL; + /** + * @var array + */ + var $_downloadDeps = array(); + /** + * @var boolean + */ + var $_valid = false; + /** + * @var boolean + */ + var $_analyzed = false; + /** + * if this or a parent package was invoked with Package-state, this is set to the + * state variable. + * + * This allows temporary reassignment of preferred_state for a parent package and all of + * its dependencies. + * @var string|false + */ + var $_explicitState = false; + /** + * If this package is invoked with Package#group, this variable will be true + */ + var $_explicitGroup = false; + /** + * Package type local|url|xmlrpc + * @var string + */ + var $_type; + /** + * Contents of package.xml, if downloaded from a remote channel + * @var string|false + * @access private + */ + var $_rawpackagefile; + /** + * @var boolean + * @access private + */ + var $_validated = false; + + /** + * @param PEAR_Downloader + */ + function PEAR_Downloader_Package(&$downloader) + { + $this->_downloader = &$downloader; + $this->_config = &$this->_downloader->config; + $this->_registry = &$this->_config->getRegistry(); + $options = $downloader->getOptions(); + if (isset($options['packagingroot'])) { + $this->_config->setInstallRoot($options['packagingroot']); + $this->_installRegistry = &$this->_config->getRegistry(); + $this->_config->setInstallRoot(false); + } else { + $this->_installRegistry = &$this->_registry; + } + $this->_valid = $this->_analyzed = false; + } + + /** + * Parse the input and determine whether this is a local file, a remote uri, or an + * abstract package name. + * + * This is the heart of the PEAR_Downloader_Package(), and is used in + * {@link PEAR_Downloader::download()} + * @param string + * @return bool|PEAR_Error + */ + function initialize($param) + { + $origErr = $this->_fromFile($param); + if (!$this->_valid) { + $options = $this->_downloader->getOptions(); + if (isset($options['offline'])) { + if (PEAR::isError($origErr)) { + if (!isset($options['soft'])) { + $this->_downloader->log(0, $origErr->getMessage()); + } + } + return PEAR::raiseError('Cannot download non-local package "' . $param . '"'); + } + $err = $this->_fromUrl($param); + if (PEAR::isError($err) || !$this->_valid) { + if ($this->_type == 'url') { + if (PEAR::isError($err)) { + if (!isset($options['soft'])) { + $this->_downloader->log(0, $err->getMessage()); + } + } + return PEAR::raiseError("Invalid or missing remote package file"); + } + $err = $this->_fromString($param); + if (PEAR::isError($err) || !$this->_valid) { + if (PEAR::isError($err) && + $err->getCode() == PEAR_DOWNLOADER_PACKAGE_STATE) { + return false; // instruct the downloader to silently skip + } + if (isset($this->_type) && $this->_type == 'local' && + PEAR::isError($origErr)) { + if (is_array($origErr->getUserInfo())) { + foreach ($origErr->getUserInfo() as $err) { + if (is_array($err)) { + $err = $err['message']; + } + if (!isset($options['soft'])) { + $this->_downloader->log(0, $err); + } + } + } + if (!isset($options['soft'])) { + $this->_downloader->log(0, $origErr->getMessage()); + } + if (is_array($param)) { + $param = $this->_registry->parsedPackageNameToString($param, + true); + } + return PEAR::raiseError( + "Cannot initialize '$param', invalid or missing package file"); + } + if (PEAR::isError($err)) { + if (!isset($options['soft'])) { + $this->_downloader->log(0, $err->getMessage()); + } + } + if (is_array($param)) { + $param = $this->_registry->parsedPackageNameToString($param, true); + } + return PEAR::raiseError( + "Cannot initialize '$param', invalid or missing package file"); + } + } + } + return true; + } + + /** + * Retrieve any non-local packages + * @return PEAR_PackageFile_v1|PEAR_PackageFile_v2|PEAR_Error + */ + function &download() + { + if (isset($this->_packagefile)) { + return $this->_packagefile; + } + if (isset($this->_downloadURL['url'])) { + $this->_isvalid = false; + $info = $this->getParsedPackage(); + foreach ($info as $i => $p) { + $info[$i] = strtolower($p); + } + $err = $this->_fromUrl($this->_downloadURL['url'], + $this->_registry->parsedPackageNameToString($this->_parsedname, true)); + $newinfo = $this->getParsedPackage(); + foreach ($newinfo as $i => $p) { + $newinfo[$i] = strtolower($p); + } + if ($info != $newinfo) { + do { + if ($info['package'] == 'pecl.php.net' && $newinfo['package'] == 'pear.php.net') { + $info['package'] = 'pear.php.net'; + if ($info == $newinfo) { + // skip the channel check if a pecl package says it's a PEAR package + break; + } + } + return PEAR::raiseError('CRITICAL ERROR: We are ' . + $this->_registry->parsedPackageNameToString($info) . ', but the file ' . + 'downloaded claims to be ' . + $this->_registry->parsedPackageNameToString($this->getParsedPackage())); + } while (false); + } + if (PEAR::isError($err) || !$this->_valid) { + return $err; + } + } + $this->_type = 'local'; + return $this->_packagefile; + } + + function &getPackageFile() + { + return $this->_packagefile; + } + + function &getDownloader() + { + return $this->_downloader; + } + + function getType() + { + return $this->_type; + } + + /** + * Like {@link initialize()}, but operates on a dependency + */ + function fromDepURL($dep) + { + $this->_downloadURL = $dep; + if (isset($dep['uri'])) { + $options = $this->_downloader->getOptions(); + if (!extension_loaded("zlib") || isset($options['nocompress'])) { + $ext = '.tar'; + } else { + $ext = '.tgz'; + } + PEAR::pushErrorHandling(PEAR_ERROR_RETURN); + $err = $this->_fromUrl($dep['uri'] . $ext); + PEAR::popErrorHandling(); + if (PEAR::isError($err)) { + if (!isset($options['soft'])) { + $this->_downloader->log(0, $err->getMessage()); + } + return PEAR::raiseError('Invalid uri dependency "' . $dep['uri'] . $ext . '", ' . + 'cannot download'); + } + } else { + $this->_parsedname = + array( + 'package' => $dep['info']->getPackage(), + 'channel' => $dep['info']->getChannel(), + 'version' => $dep['version'] + ); + if (!isset($dep['nodefault'])) { + $this->_parsedname['group'] = 'default'; // download the default dependency group + $this->_explicitGroup = false; + } + $this->_rawpackagefile = $dep['raw']; + } + } + + function detectDependencies($params) + { + $options = $this->_downloader->getOptions(); + if (isset($options['downloadonly'])) { + return; + } + if (isset($options['offline'])) { + $this->_downloader->log(3, 'Skipping dependency download check, --offline specified'); + return; + } + $pname = $this->getParsedPackage(); + if (!$pname) { + return; + } + $deps = $this->getDeps(); + if (!$deps) { + return; + } + if (isset($deps['required'])) { // package.xml 2.0 + return $this->_detect2($deps, $pname, $options, $params); + } else { + return $this->_detect1($deps, $pname, $options, $params); + } + } + + function setValidated() + { + $this->_validated = true; + } + + function alreadyValidated() + { + return $this->_validated; + } + + /** + * Remove packages to be downloaded that are already installed + * @param array of PEAR_Downloader_Package objects + * @static + */ + function removeInstalled(&$params) + { + if (!isset($params[0])) { + return; + } + $options = $params[0]->_downloader->getOptions(); + if (!isset($options['downloadonly'])) { + foreach ($params as $i => $param) { + // remove self if already installed with this version + // this does not need any pecl magic - we only remove exact matches + if ($param->_installRegistry->packageExists($param->getPackage(), $param->getChannel())) { + if (version_compare($param->_installRegistry->packageInfo($param->getPackage(), 'version', + $param->getChannel()), $param->getVersion(), '==')) { + if (!isset($options['force'])) { + $info = $param->getParsedPackage(); + unset($info['version']); + unset($info['state']); + if (!isset($options['soft'])) { + $param->_downloader->log(1, 'Skipping package "' . + $param->getShortName() . + '", already installed as version ' . + $param->_installRegistry->packageInfo($param->getPackage(), + 'version', $param->getChannel())); + } + $params[$i] = false; + } + } elseif (!isset($options['force']) && !isset($options['upgrade']) && + !isset($options['soft'])) { + $info = $param->getParsedPackage(); + $param->_downloader->log(1, 'Skipping package "' . + $param->getShortName() . + '", already installed as version ' . + $param->_installRegistry->packageInfo($param->getPackage(), 'version', + $param->getChannel())); + $params[$i] = false; + } + } + } + } + PEAR_Downloader_Package::removeDuplicates($params); + } + + function _detect2($deps, $pname, $options, $params) + { + $this->_downloadDeps = array(); + $groupnotfound = false; + foreach (array('package', 'subpackage') as $packagetype) { + // get required dependency group + if (isset($deps['required'][$packagetype])) { + if (isset($deps['required'][$packagetype][0])) { + foreach ($deps['required'][$packagetype] as $dep) { + if (isset($dep['conflicts'])) { + // skip any package that this package conflicts with + continue; + } + $ret = $this->_detect2Dep($dep, $pname, 'required', $params); + if (is_array($ret)) { + $this->_downloadDeps[] = $ret; + } + } + } else { + $dep = $deps['required'][$packagetype]; + if (!isset($dep['conflicts'])) { + // skip any package that this package conflicts with + $ret = $this->_detect2Dep($dep, $pname, 'required', $params); + if (is_array($ret)) { + $this->_downloadDeps[] = $ret; + } + } + } + } + // get optional dependency group, if any + if (isset($deps['optional'][$packagetype])) { + $skipnames = array(); + if (!isset($deps['optional'][$packagetype][0])) { + $deps['optional'][$packagetype] = array($deps['optional'][$packagetype]); + } + foreach ($deps['optional'][$packagetype] as $dep) { + $skip = false; + if (!isset($options['alldeps'])) { + $dep['package'] = $dep['name']; + if (!isset($options['soft'])) { + $this->_downloader->log(3, 'Notice: package "' . + $this->_registry->parsedPackageNameToString($this->getParsedPackage(), + true) . '" optional dependency "' . + $this->_registry->parsedPackageNameToString(array('package' => + $dep['name'], 'channel' => 'pear.php.net'), true) . + '" will not be automatically downloaded'); + } + $skipnames[] = $this->_registry->parsedPackageNameToString($dep, true); + $skip = true; + unset($dep['package']); + } + if (!($ret = $this->_detect2Dep($dep, $pname, 'optional', $params))) { + $dep['package'] = $dep['name']; + $skip = count($skipnames) ? + $skipnames[count($skipnames) - 1] : ''; + if ($skip == + $this->_registry->parsedPackageNameToString($dep, true)) { + array_pop($skipnames); + } + } + if (!$skip && is_array($ret)) { + $this->_downloadDeps[] = $ret; + } + } + if (count($skipnames)) { + if (!isset($options['soft'])) { + $this->_downloader->log(1, 'Did not download optional dependencies: ' . + implode(', ', $skipnames) . + ', use --alldeps to download automatically'); + } + } + } + // get requested dependency group, if any + $groupname = $this->getGroup(); + $explicit = $this->_explicitGroup; + if (!$groupname) { + if ($this->canDefault()) { + $groupname = 'default'; // try the default dependency group + } else { + continue; + } + } + if ($groupnotfound) { + continue; + } + if (isset($deps['group'])) { + if (isset($deps['group']['attribs'])) { + if (strtolower($deps['group']['attribs']['name']) == strtolower($groupname)) { + $group = $deps['group']; + } elseif ($explicit) { + if (!isset($options['soft'])) { + $this->_downloader->log(0, 'Warning: package "' . + $this->_registry->parsedPackageNameToString($pname, true) . + '" has no dependency ' . 'group named "' . $groupname . '"'); + } + $groupnotfound = true; + continue; + } + } else { + $found = false; + foreach ($deps['group'] as $group) { + if (strtolower($group['attribs']['name']) == strtolower($groupname)) { + $found = true; + break; + } + } + if (!$found) { + if ($explicit) { + if (!isset($options['soft'])) { + $this->_downloader->log(0, 'Warning: package "' . + $this->_registry->parsedPackageNameToString($pname, true) . + '" has no dependency ' . 'group named "' . $groupname . '"'); + } + } + $groupnotfound = true; + continue; + } + } + } + if (isset($group)) { + if (isset($group[$packagetype])) { + if (isset($group[$packagetype][0])) { + foreach ($group[$packagetype] as $dep) { + $ret = $this->_detect2Dep($dep, $pname, 'dependency group "' . + $group['attribs']['name'] . '"', $params); + if (is_array($ret)) { + $this->_downloadDeps[] = $ret; + } + } + } else { + $ret = $this->_detect2Dep($group[$packagetype], $pname, + 'dependency group "' . + $group['attribs']['name'] . '"', $params); + if (is_array($ret)) { + $this->_downloadDeps[] = $ret; + } + } + } + } + } + } + + function _detect2Dep($dep, $pname, $group, $params) + { + if (isset($dep['conflicts'])) { + return true; + } + $options = $this->_downloader->getOptions(); + if (isset($dep['uri'])) { + return array('uri' => $dep['uri'], 'dep' => $dep);; + } + $testdep = $dep; + $testdep['package'] = $dep['name']; + if (PEAR_Downloader_Package::willDownload($testdep, $params)) { + $dep['package'] = $dep['name']; + if (!isset($options['soft'])) { + $this->_downloader->log(2, $this->getShortName() . ': Skipping ' . $group . + ' dependency "' . + $this->_registry->parsedPackageNameToString($dep, true) . + '", will be installed'); + } + return false; + } + $options = $this->_downloader->getOptions(); + PEAR::pushErrorHandling(PEAR_ERROR_RETURN); + if ($this->_explicitState) { + $pname['state'] = $this->_explicitState; + } + $url = + $this->_downloader->_getDepPackageDownloadUrl($dep, $pname); + if (PEAR::isError($url)) { + PEAR::popErrorHandling(); + return $url; + } + $dep['package'] = $dep['name']; + $ret = $this->_analyzeDownloadURL($url, 'dependency', $dep, $params, $group == 'optional' && + !isset($options['alldeps']), true); + PEAR::popErrorHandling(); + if (PEAR::isError($ret)) { + if (!isset($options['soft'])) { + $this->_downloader->log(0, $ret->getMessage()); + } + return false; + } else { + // check to see if a dep is already installed and is the same or newer + if (!isset($dep['min']) && !isset($dep['max']) && !isset($dep['recommended'])) { + $oper = 'has'; + } else { + $oper = 'gt'; + } + // do not try to move this before getDepPackageDownloadURL + // we can't determine whether upgrade is necessary until we know what + // version would be downloaded + if (!isset($options['force']) && $this->isInstalled($ret, $oper)) { + $version = $this->_installRegistry->packageInfo($dep['name'], 'version', + $dep['channel']); + $dep['package'] = $dep['name']; + if (!isset($options['soft'])) { + $this->_downloader->log(3, $this->getShortName() . ': Skipping ' . $group . + ' dependency "' . + $this->_registry->parsedPackageNameToString($dep, true) . + '" version ' . $url['version'] . ', already installed as version ' . + $version); + } + return false; + } + } + if (isset($dep['nodefault'])) { + $ret['nodefault'] = true; + } + return $ret; + } + + function _detect1($deps, $pname, $options, $params) + { + $this->_downloadDeps = array(); + $skipnames = array(); + foreach ($deps as $dep) { + $nodownload = false; + if ($dep['type'] == 'pkg') { + $dep['channel'] = 'pear.php.net'; + $dep['package'] = $dep['name']; + switch ($dep['rel']) { + case 'not' : + continue 2; + case 'ge' : + case 'eq' : + case 'gt' : + case 'has' : + $group = (!isset($dep['optional']) || $dep['optional'] == 'no') ? + 'required' : + 'optional'; + if (PEAR_Downloader_Package::willDownload($dep, $params)) { + $this->_downloader->log(2, $this->getShortName() . ': Skipping ' . $group + . ' dependency "' . + $this->_registry->parsedPackageNameToString($dep, true) . + '", will be installed'); + continue 2; + } + $fakedp = new PEAR_PackageFile_v1; + $fakedp->setPackage($dep['name']); + // skip internet check if we are not upgrading (bug #5810) + if (!isset($options['upgrade']) && $this->isInstalled( + $fakedp, $dep['rel'])) { + $this->_downloader->log(2, $this->getShortName() . ': Skipping ' . $group + . ' dependency "' . + $this->_registry->parsedPackageNameToString($dep, true) . + '", is already installed'); + continue 2; + } + } + PEAR::pushErrorHandling(PEAR_ERROR_RETURN); + if ($this->_explicitState) { + $pname['state'] = $this->_explicitState; + } + $url = + $this->_downloader->_getDepPackageDownloadUrl($dep, $pname); + $chan = 'pear.php.net'; + if (PEAR::isError($url)) { + // check to see if this is a pecl package that has jumped + // from pear.php.net to pecl.php.net channel + if (!class_exists('PEAR_Dependency2')) { + require_once 'PEAR/Dependency2.php'; + } + $newdep = PEAR_Dependency2::normalizeDep($dep); + $newdep = $newdep[0]; + $newdep['channel'] = 'pecl.php.net'; + $chan = 'pecl.php.net'; + $url = + $this->_downloader->_getDepPackageDownloadUrl($newdep, $pname); + $obj = &$this->_installRegistry->getPackage($dep['name']); + if (PEAR::isError($url)) { + PEAR::popErrorHandling(); + if ($obj !== null && $this->isInstalled($obj, $dep['rel'])) { + $group = (!isset($dep['optional']) || $dep['optional'] == 'no') ? + 'required' : + 'optional'; + $dep['package'] = $dep['name']; + if (!isset($options['soft'])) { + $this->_downloader->log(3, $this->getShortName() . + ': Skipping ' . $group . ' dependency "' . + $this->_registry->parsedPackageNameToString($dep, true) . + '", already installed as version ' . $obj->getVersion()); + } + $skip = count($skipnames) ? + $skipnames[count($skipnames) - 1] : ''; + if ($skip == + $this->_registry->parsedPackageNameToString($dep, true)) { + array_pop($skipnames); + } + continue; + } else { + if (isset($dep['optional']) && $dep['optional'] == 'yes') { + $this->_downloader->log(2, $this->getShortName() . + ': Skipping optional dependency "' . + $this->_registry->parsedPackageNameToString($dep, true) . + '", no releases exist'); + continue; + } else { + return $url; + } + } + } + } + PEAR::popErrorHandling(); + if (!isset($options['alldeps'])) { + if (isset($dep['optional']) && $dep['optional'] == 'yes') { + if (!isset($options['soft'])) { + $this->_downloader->log(3, 'Notice: package "' . + $this->getShortName() . + '" optional dependency "' . + $this->_registry->parsedPackageNameToString( + array('channel' => $chan, 'package' => + $dep['name']), true) . + '" will not be automatically downloaded'); + } + $skipnames[] = $this->_registry->parsedPackageNameToString( + array('channel' => $chan, 'package' => + $dep['name']), true); + $nodownload = true; + } + } + if (!isset($options['alldeps']) && !isset($options['onlyreqdeps'])) { + if (!isset($dep['optional']) || $dep['optional'] == 'no') { + if (!isset($options['soft'])) { + $this->_downloader->log(3, 'Notice: package "' . + $this->getShortName() . + '" required dependency "' . + $this->_registry->parsedPackageNameToString( + array('channel' => $chan, 'package' => + $dep['name']), true) . + '" will not be automatically downloaded'); + } + $skipnames[] = $this->_registry->parsedPackageNameToString( + array('channel' => $chan, 'package' => + $dep['name']), true); + $nodownload = true; + } + } + // check to see if a dep is already installed + // do not try to move this before getDepPackageDownloadURL + // we can't determine whether upgrade is necessary until we know what + // version would be downloaded + if (!isset($options['force']) && $this->isInstalled( + $url, $dep['rel'])) { + $group = (!isset($dep['optional']) || $dep['optional'] == 'no') ? + 'required' : + 'optional'; + $dep['package'] = $dep['name']; + if (isset($newdep)) { + $version = $this->_installRegistry->packageInfo($newdep['name'], 'version', + $newdep['channel']); + } else { + $version = $this->_installRegistry->packageInfo($dep['name'], 'version'); + } + $dep['version'] = $url['version']; + if (!isset($options['soft'])) { + $this->_downloader->log(3, $this->getShortName() . ': Skipping ' . $group . + ' dependency "' . + $this->_registry->parsedPackageNameToString($dep, true) . + '", already installed as version ' . $version); + } + $skip = count($skipnames) ? + $skipnames[count($skipnames) - 1] : ''; + if ($skip == + $this->_registry->parsedPackageNameToString($dep, true)) { + array_pop($skipnames); + } + continue; + } + if ($nodownload) { + continue; + } + PEAR::pushErrorHandling(PEAR_ERROR_RETURN); + if (isset($newdep)) { + $dep = $newdep; + } + $dep['package'] = $dep['name']; + $ret = $this->_analyzeDownloadURL($url, 'dependency', $dep, $params, + isset($dep['optional']) && $dep['optional'] == 'yes' && + !isset($options['alldeps']), true); + PEAR::popErrorHandling(); + if (PEAR::isError($ret)) { + if (!isset($options['soft'])) { + $this->_downloader->log(0, $ret->getMessage()); + } + continue; + } + $this->_downloadDeps[] = $ret; + } + } + if (count($skipnames)) { + if (!isset($options['soft'])) { + $this->_downloader->log(1, 'Did not download dependencies: ' . + implode(', ', $skipnames) . + ', use --alldeps or --onlyreqdeps to download automatically'); + } + } + } + + function setDownloadURL($pkg) + { + $this->_downloadURL = $pkg; + } + + /** + * Set the package.xml object for this downloaded package + * + * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2 $pkg + */ + function setPackageFile(&$pkg) + { + $this->_packagefile = &$pkg; + } + + function getShortName() + { + return $this->_registry->parsedPackageNameToString(array('channel' => $this->getChannel(), + 'package' => $this->getPackage()), true); + } + + function getParsedPackage() + { + if (isset($this->_packagefile) || isset($this->_parsedname)) { + return array('channel' => $this->getChannel(), + 'package' => $this->getPackage(), + 'version' => $this->getVersion()); + } + return false; + } + + function getDownloadURL() + { + return $this->_downloadURL; + } + + function canDefault() + { + if (isset($this->_downloadURL)) { + if (isset($this->_downloadURL['nodefault'])) { + return false; + } + } + return true; + } + + function getPackage() + { + if (isset($this->_packagefile)) { + return $this->_packagefile->getPackage(); + } elseif (isset($this->_downloadURL['info'])) { + return $this->_downloadURL['info']->getPackage(); + } else { + return false; + } + } + + /** + * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2 + */ + function isSubpackage(&$pf) + { + if (isset($this->_packagefile)) { + return $this->_packagefile->isSubpackage($pf); + } elseif (isset($this->_downloadURL['info'])) { + return $this->_downloadURL['info']->isSubpackage($pf); + } else { + return false; + } + } + + function getPackageType() + { + if (isset($this->_packagefile)) { + return $this->_packagefile->getPackageType(); + } elseif (isset($this->_downloadURL['info'])) { + return $this->_downloadURL['info']->getPackageType(); + } else { + return false; + } + } + + function isBundle() + { + if (isset($this->_packagefile)) { + return $this->_packagefile->getPackageType() == 'bundle'; + } else { + return false; + } + } + + function getPackageXmlVersion() + { + if (isset($this->_packagefile)) { + return $this->_packagefile->getPackagexmlVersion(); + } elseif (isset($this->_downloadURL['info'])) { + return $this->_downloadURL['info']->getPackagexmlVersion(); + } else { + return '1.0'; + } + } + + function getChannel() + { + if (isset($this->_packagefile)) { + return $this->_packagefile->getChannel(); + } elseif (isset($this->_downloadURL['info'])) { + return $this->_downloadURL['info']->getChannel(); + } else { + return false; + } + } + + function getURI() + { + if (isset($this->_packagefile)) { + return $this->_packagefile->getURI(); + } elseif (isset($this->_downloadURL['info'])) { + return $this->_downloadURL['info']->getURI(); + } else { + return false; + } + } + + function getVersion() + { + if (isset($this->_packagefile)) { + return $this->_packagefile->getVersion(); + } elseif (isset($this->_downloadURL['version'])) { + return $this->_downloadURL['version']; + } else { + return false; + } + } + + function isCompatible($pf) + { + if (isset($this->_packagefile)) { + return $this->_packagefile->isCompatible($pf); + } elseif (isset($this->_downloadURL['info'])) { + return $this->_downloadURL['info']->isCompatible($pf); + } else { + return true; + } + } + + function setGroup($group) + { + $this->_parsedname['group'] = $group; + } + + function getGroup() + { + if (isset($this->_parsedname['group'])) { + return $this->_parsedname['group']; + } else { + return ''; + } + } + + function isExtension($name) + { + if (isset($this->_packagefile)) { + return $this->_packagefile->isExtension($name); + } elseif (isset($this->_downloadURL['info'])) { + if ($this->_downloadURL['info']->getPackagexmlVersion() == '2.0') { + return $this->_downloadURL['info']->getProvidesExtension() == $name; + } else { + return false; + } + } else { + return false; + } + } + + function getDeps() + { + if (isset($this->_packagefile)) { + $ver = $this->_packagefile->getPackagexmlVersion(); + if (version_compare($ver, '2.0', '>=')) { + return $this->_packagefile->getDeps(true); + } else { + return $this->_packagefile->getDeps(); + } + } elseif (isset($this->_downloadURL['info'])) { + $ver = $this->_downloadURL['info']->getPackagexmlVersion(); + if (version_compare($ver, '2.0', '>=')) { + return $this->_downloadURL['info']->getDeps(true); + } else { + return $this->_downloadURL['info']->getDeps(); + } + } else { + return array(); + } + } + + /** + * @param array Parsed array from {@link PEAR_Registry::parsePackageName()} or a dependency + * returned from getDepDownloadURL() + */ + function isEqual($param) + { + if (is_object($param)) { + $channel = $param->getChannel(); + $package = $param->getPackage(); + if ($param->getURI()) { + $param = array( + 'channel' => $param->getChannel(), + 'package' => $param->getPackage(), + 'version' => $param->getVersion(), + 'uri' => $param->getURI(), + ); + } else { + $param = array( + 'channel' => $param->getChannel(), + 'package' => $param->getPackage(), + 'version' => $param->getVersion(), + ); + } + } else { + if (isset($param['uri'])) { + if ($this->getChannel() != '__uri') { + return false; + } + return $param['uri'] == $this->getURI(); + } + $package = isset($param['package']) ? $param['package'] : + $param['info']->getPackage(); + $channel = isset($param['channel']) ? $param['channel'] : + $param['info']->getChannel(); + if (isset($param['rel'])) { + if (!class_exists('PEAR_Dependency2')) { + require_once 'PEAR/Dependency2.php'; + } + $newdep = PEAR_Dependency2::normalizeDep($param); + $newdep = $newdep[0]; + } elseif (isset($param['min'])) { + $newdep = $param; + } + } + if (isset($newdep)) { + if (!isset($newdep['min'])) { + $newdep['min'] = '0'; + } + if (!isset($newdep['max'])) { + $newdep['max'] = '100000000000000000000'; + } + // use magic to support pecl packages suddenly jumping to the pecl channel + // we need to support both dependency possibilities + if ($channel == 'pear.php.net' && $this->getChannel() == 'pecl.php.net') { + if ($package == $this->getPackage()) { + $channel = 'pecl.php.net'; + } + } + if ($channel == 'pecl.php.net' && $this->getChannel() == 'pear.php.net') { + if ($package == $this->getPackage()) { + $channel = 'pear.php.net'; + } + } + return (strtolower($package) == strtolower($this->getPackage()) && + $channel == $this->getChannel() && + version_compare($newdep['min'], $this->getVersion(), '<=') && + version_compare($newdep['max'], $this->getVersion(), '>=')); + } + // use magic to support pecl packages suddenly jumping to the pecl channel + if ($channel == 'pecl.php.net' && $this->getChannel() == 'pear.php.net') { + if (strtolower($package) == strtolower($this->getPackage())) { + $channel = 'pear.php.net'; + } + } + if (isset($param['version'])) { + return (strtolower($package) == strtolower($this->getPackage()) && + $channel == $this->getChannel() && + $param['version'] == $this->getVersion()); + } else { + return strtolower($package) == strtolower($this->getPackage()) && + $channel == $this->getChannel(); + } + } + + function isInstalled($dep, $oper = '==') + { + if (!$dep) { + return false; + } + if ($oper != 'ge' && $oper != 'gt' && $oper != 'has' && $oper != '==') { + return false; + } + if (is_object($dep)) { + $package = $dep->getPackage(); + $channel = $dep->getChannel(); + if ($dep->getURI()) { + $dep = array( + 'uri' => $dep->getURI(), + 'version' => $dep->getVersion(), + ); + } else { + $dep = array( + 'version' => $dep->getVersion(), + ); + } + } else { + if (isset($dep['uri'])) { + $channel = '__uri'; + $package = $dep['dep']['name']; + } else { + $channel = $dep['info']->getChannel(); + $package = $dep['info']->getPackage(); + } + } + $options = $this->_downloader->getOptions(); + $test = $this->_installRegistry->packageExists($package, $channel); + if (!$test && $channel == 'pecl.php.net') { + // do magic to allow upgrading from old pecl packages to new ones + $test = $this->_installRegistry->packageExists($package, 'pear.php.net'); + $channel = 'pear.php.net'; + } + if ($test) { + if (isset($dep['uri'])) { + if ($this->_installRegistry->packageInfo($package, 'uri', '__uri') == $dep['uri']) { + return true; + } + } + if (isset($options['upgrade'])) { + if ($oper == 'has') { + if (version_compare($this->_installRegistry->packageInfo( + $package, 'version', $channel), + $dep['version'], '>=')) { + return true; + } else { + return false; + } + } else { + if (version_compare($this->_installRegistry->packageInfo( + $package, 'version', $channel), + $dep['version'], '>=')) { + return true; + } + return false; + } + } + return true; + } + return false; + } + + /** + * Detect duplicate package names with differing versions + * + * If a user requests to install Date 1.4.6 and Date 1.4.7, + * for instance, this is a logic error. This method + * detects this situation. + * + * @param array $params array of PEAR_Downloader_Package objects + * @param array $errorparams empty array + * @return array array of stupid duplicated packages in PEAR_Downloader_Package obejcts + */ + function detectStupidDuplicates($params, &$errorparams) + { + $existing = array(); + foreach ($params as $i => $param) { + $package = $param->getPackage(); + $channel = $param->getChannel(); + $group = $param->getGroup(); + if (!isset($existing[$channel . '/' . $package])) { + $existing[$channel . '/' . $package] = array(); + } + if (!isset($existing[$channel . '/' . $package][$group])) { + $existing[$channel . '/' . $package][$group] = array(); + } + $existing[$channel . '/' . $package][$group][] = $i; + } + + $indices = array(); + foreach ($existing as $package => $groups) { + foreach ($groups as $group => $dupes) { + if (count($dupes) > 1) { + $indices = $indices + $dupes; + } + } + } + + $indices = array_unique($indices); + foreach ($indices as $index) { + $errorparams[] = $params[$index]; + } + return count($errorparams); + } + + /** + * @param array + * @param bool ignore install groups - for final removal of dupe packages + * @static + */ + function removeDuplicates(&$params, $ignoreGroups = false) + { + $pnames = array(); + foreach ($params as $i => $param) { + if (!$param) { + continue; + } + if ($param->getPackage()) { + if ($ignoreGroups) { + $group = ''; + } else { + $group = $param->getGroup(); + } + $pnames[$i] = $param->getChannel() . '/' . + $param->getPackage() . '-' . $param->getVersion() . '#' . $group; + } + } + $pnames = array_unique($pnames); + $unset = array_diff(array_keys($params), array_keys($pnames)); + $testp = array_flip($pnames); + foreach ($params as $i => $param) { + if (!$param) { + $unset[] = $i; + continue; + } + if (!is_a($param, 'PEAR_Downloader_Package')) { + $unset[] = $i; + continue; + } + if ($ignoreGroups) { + $group = ''; + } else { + $group = $param->getGroup(); + } + if (!isset($testp[$param->getChannel() . '/' . $param->getPackage() . '-' . + $param->getVersion() . '#' . $group])) { + $unset[] = $i; + } + } + foreach ($unset as $i) { + unset($params[$i]); + } + $ret = array(); + foreach ($params as $i => $param) { + $ret[] = &$params[$i]; + } + $params = array(); + foreach ($ret as $i => $param) { + $params[] = &$ret[$i]; + } + } + + function explicitState() + { + return $this->_explicitState; + } + + function setExplicitState($s) + { + $this->_explicitState = $s; + } + + /** + * @static + */ + function mergeDependencies(&$params) + { + $newparams = array(); + $bundles = array(); + foreach ($params as $i => $param) { + if (!$param->isBundle()) { + continue; + } + $bundles[] = $i; + $pf = &$param->getPackageFile(); + $newdeps = array(); + $contents = $pf->getBundledPackages(); + if (!is_array($contents)) { + $contents = array($contents); + } + foreach ($contents as $file) { + $filecontents = $pf->getFileContents($file); + $dl = &$param->getDownloader(); + $options = $dl->getOptions(); + if (PEAR::isError($dir = $dl->getDownloadDir())) { + return $dir; + } + $fp = @fopen($dir . DIRECTORY_SEPARATOR . $file, 'wb'); + if (!$fp) { + continue; + } + fwrite($fp, $filecontents, strlen($filecontents)); + fclose($fp); + if ($s = $params[$i]->explicitState()) { + $obj->setExplicitState($s); + } + $obj = &new PEAR_Downloader_Package($params[$i]->getDownloader()); + PEAR::pushErrorHandling(PEAR_ERROR_RETURN); + if (PEAR::isError($dir = $dl->getDownloadDir())) { + PEAR::popErrorHandling(); + return $dir; + } + $e = $obj->_fromFile($a = $dir . DIRECTORY_SEPARATOR . $file); + PEAR::popErrorHandling(); + if (PEAR::isError($e)) { + if (!isset($options['soft'])) { + $dl->log(0, $e->getMessage()); + } + continue; + } + $j = &$obj; + if (!PEAR_Downloader_Package::willDownload($j, + array_merge($params, $newparams)) && !$param->isInstalled($j)) { + $newparams[] = &$j; + } + } + } + foreach ($bundles as $i) { + unset($params[$i]); // remove bundles - only their contents matter for installation + } + PEAR_Downloader_Package::removeDuplicates($params); // strip any unset indices + if (count($newparams)) { // add in bundled packages for install + foreach ($newparams as $i => $unused) { + $params[] = &$newparams[$i]; + } + $newparams = array(); + } + foreach ($params as $i => $param) { + $newdeps = array(); + foreach ($param->_downloadDeps as $dep) { + if (!PEAR_Downloader_Package::willDownload($dep, + array_merge($params, $newparams)) && !$param->isInstalled($dep)) { + $newdeps[] = $dep; + } else { + // detect versioning conflicts here + } + } + // convert the dependencies into PEAR_Downloader_Package objects for the next time + // around + $params[$i]->_downloadDeps = array(); + foreach ($newdeps as $dep) { + $obj = &new PEAR_Downloader_Package($params[$i]->getDownloader()); + if ($s = $params[$i]->explicitState()) { + $obj->setExplicitState($s); + } + PEAR::pushErrorHandling(PEAR_ERROR_RETURN); + $e = $obj->fromDepURL($dep); + PEAR::popErrorHandling(); + if (PEAR::isError($e)) { + if (!isset($options['soft'])) { + $obj->_downloader->log(0, $e->getMessage()); + } + continue; + } + $e = $obj->detectDependencies($params); + if (PEAR::isError($e)) { + if (!isset($options['soft'])) { + $obj->_downloader->log(0, $e->getMessage()); + } + } + $j = &$obj; + $newparams[] = &$j; + } + } + if (count($newparams)) { + foreach ($newparams as $i => $unused) { + $params[] = &$newparams[$i]; + } + return true; + } else { + return false; + } + } + + + /** + * @static + */ + function willDownload($param, $params) + { + if (!is_array($params)) { + return false; + } + foreach ($params as $obj) { + if ($obj->isEqual($param)) { + return true; + } + } + return false; + } + + /** + * For simpler unit-testing + * @param PEAR_Config + * @param int + * @param string + */ + function &getPackagefileObject(&$c, $d, $t = false) + { + $a = &new PEAR_PackageFile($c, $d, $t); + return $a; + } + + + /** + * This will retrieve from a local file if possible, and parse out + * a group name as well. The original parameter will be modified to reflect this. + * @param string|array can be a parsed package name as well + * @access private + */ + function _fromFile(&$param) + { + $saveparam = $param; + if (is_string($param)) { + if (!@file_exists($param)) { + $test = explode('#', $param); + $group = array_pop($test); + if (@file_exists(implode('#', $test))) { + $this->setGroup($group); + $param = implode('#', $test); + $this->_explicitGroup = true; + } + } + if (@is_file($param)) { + $this->_type = 'local'; + $options = $this->_downloader->getOptions(); + if (isset($options['downloadonly'])) { + $pkg = &$this->getPackagefileObject($this->_config, + $this->_downloader->_debug); + } else { + if (PEAR::isError($dir = $this->_downloader->getDownloadDir())) { + return $dir; + } + $pkg = &$this->getPackagefileObject($this->_config, + $this->_downloader->_debug, $dir); + } + PEAR::pushErrorHandling(PEAR_ERROR_RETURN); + $pf = &$pkg->fromAnyFile($param, PEAR_VALIDATE_INSTALLING); + PEAR::popErrorHandling(); + if (PEAR::isError($pf)) { + $this->_valid = false; + $param = $saveparam; + return $pf; + } + $this->_packagefile = &$pf; + if (!$this->getGroup()) { + $this->setGroup('default'); // install the default dependency group + } + return $this->_valid = true; + } + } + $param = $saveparam; + return $this->_valid = false; + } + + function _fromUrl($param, $saveparam = '') + { + if (!is_array($param) && + (preg_match('#^(http|ftp)://#', $param))) { + $options = $this->_downloader->getOptions(); + $this->_type = 'url'; + $callback = $this->_downloader->ui ? + array(&$this->_downloader, '_downloadCallback') : null; + $this->_downloader->pushErrorHandling(PEAR_ERROR_RETURN); + if (PEAR::isError($dir = $this->_downloader->getDownloadDir())) { + $this->_downloader->popErrorHandling(); + return $dir; + } + $this->_downloader->log(3, 'Downloading "' . $param . '"'); + $file = $this->_downloader->downloadHttp($param, $this->_downloader->ui, + $dir, $callback, null, false, $this->getChannel()); + $this->_downloader->popErrorHandling(); + if (PEAR::isError($file)) { + if (!empty($saveparam)) { + $saveparam = ", cannot download \"$saveparam\""; + } + $err = PEAR::raiseError('Could not download from "' . $param . + '"' . $saveparam . ' (' . $file->getMessage() . ')'); + return $err; + } + if ($this->_rawpackagefile) { + require_once 'Archive/Tar.php'; + $tar = &new Archive_Tar($file); + $packagexml = $tar->extractInString('package2.xml'); + if (!$packagexml) { + $packagexml = $tar->extractInString('package.xml'); + } + if (str_replace(array("\n", "\r"), array('',''), $packagexml) != + str_replace(array("\n", "\r"), array('',''), $this->_rawpackagefile)) { + if ($this->getChannel() == 'pear.php.net') { + // be more lax for the existing PEAR packages that have not-ok + // characters in their package.xml + $this->_downloader->log(0, 'CRITICAL WARNING: The "' . + $this->getPackage() . '" package has invalid characters in its ' . + 'package.xml. The next version of PEAR may not be able to install ' . + 'this package for security reasons. Please open a bug report at ' . + 'http://pear.php.net/package/' . $this->getPackage() . '/bugs'); + } else { + return PEAR::raiseError('CRITICAL ERROR: package.xml downloaded does ' . + 'not match value returned from xml-rpc'); + } + } + } + // whew, download worked! + if (isset($options['downloadonly'])) { + $pkg = &$this->getPackagefileObject($this->_config, $this->_downloader->debug); + } else { + if (PEAR::isError($dir = $this->_downloader->getDownloadDir())) { + return $dir; + } + $pkg = &$this->getPackagefileObject($this->_config, $this->_downloader->debug, + $dir); + } + PEAR::pushErrorHandling(PEAR_ERROR_RETURN); + $pf = &$pkg->fromAnyFile($file, PEAR_VALIDATE_INSTALLING); + PEAR::popErrorHandling(); + if (PEAR::isError($pf)) { + if (is_array($pf->getUserInfo())) { + foreach ($pf->getUserInfo() as $err) { + if (is_array($err)) { + $err = $err['message']; + } + if (!isset($options['soft'])) { + $this->_downloader->log(0, "Validation Error: $err"); + } + } + } + if (!isset($options['soft'])) { + $this->_downloader->log(0, $pf->getMessage()); + } + $err = PEAR::raiseError('Download of "' . ($saveparam ? $saveparam : + $param) . '" succeeded, but it is not a valid package archive'); + $this->_valid = false; + return $err; + } + $this->_packagefile = &$pf; + $this->setGroup('default'); // install the default dependency group + return $this->_valid = true; + } + return $this->_valid = false; + } + + /** + * + * @param string|array pass in an array of format + * array( + * 'package' => 'pname', + * ['channel' => 'channame',] + * ['version' => 'version',] + * ['state' => 'state',]) + * or a string of format [channame/]pname[-version|-state] + */ + function _fromString($param) + { + $options = $this->_downloader->getOptions(); + PEAR::pushErrorHandling(PEAR_ERROR_RETURN); + $pname = $this->_registry->parsePackageName($param, + $this->_config->get('default_channel')); + PEAR::popErrorHandling(); + if (PEAR::isError($pname)) { + if ($pname->getCode() == 'invalid') { + $this->_valid = false; + return false; + } + if ($pname->getCode() == 'channel') { + $parsed = $pname->getUserInfo(); + if ($this->_downloader->discover($parsed['channel'])) { + if ($this->_config->get('auto_discover')) { + PEAR::pushErrorHandling(PEAR_ERROR_RETURN); + $pname = $this->_registry->parsePackageName($param, + $this->_config->get('default_channel')); + PEAR::popErrorHandling(); + } else { + if (!isset($options['soft'])) { + $this->_downloader->log(0, 'Channel "' . $parsed['channel'] . + '" is not initialized, use ' . + '"pear channel-discover ' . $parsed['channel'] . '" to initialize' . + 'or pear config-set auto_discover 1'); + } + } + } + if (PEAR::isError($pname)) { + if (!isset($options['soft'])) { + $this->_downloader->log(0, $pname->getMessage()); + } + if (is_array($param)) { + $param = $this->_registry->parsedPackageNameToString($param); + } + $err = PEAR::raiseError('invalid package name/package file "' . + $param . '"'); + $this->_valid = false; + return $err; + } + } else { + if (!isset($options['soft'])) { + $this->_downloader->log(0, $pname->getMessage()); + } + $err = PEAR::raiseError('invalid package name/package file "' . + $param . '"'); + $this->_valid = false; + return $err; + } + } + if (!isset($this->_type)) { + $this->_type = 'xmlrpc'; + } + $this->_parsedname = $pname; + if (isset($pname['state'])) { + $this->_explicitState = $pname['state']; + } else { + $this->_explicitState = false; + } + if (isset($pname['group'])) { + $this->_explicitGroup = true; + } else { + $this->_explicitGroup = false; + } + $info = $this->_downloader->_getPackageDownloadUrl($pname); + if (PEAR::isError($info)) { + if ($info->getCode() != -976 && $pname['channel'] == 'pear.php.net') { + // try pecl + $pname['channel'] = 'pecl.php.net'; + if ($test = $this->_downloader->_getPackageDownloadUrl($pname)) { + if (!PEAR::isError($test)) { + $info = PEAR::raiseError($info->getMessage() . ' - package ' . + $this->_registry->parsedPackageNameToString($pname, true) . + ' can be installed with "pecl install ' . $pname['package'] . + '"'); + } else { + $pname['channel'] = 'pear.php.net'; + } + } else { + $pname['channel'] = 'pear.php.net'; + } + } + return $info; + } + $this->_rawpackagefile = $info['raw']; + $ret = $this->_analyzeDownloadURL($info, $param, $pname); + if (PEAR::isError($ret)) { + return $ret; + } + if ($ret) { + $this->_downloadURL = $ret; + return $this->_valid = (bool) $ret; + } + } + + /** + * @param array output of package.getDownloadURL + * @param string|array|object information for detecting packages to be downloaded, and + * for errors + * @param array name information of the package + * @param array|null packages to be downloaded + * @param bool is this an optional dependency? + * @param bool is this any kind of dependency? + * @access private + */ + function _analyzeDownloadURL($info, $param, $pname, $params = null, $optional = false, + $isdependency = false) + { + if (!is_string($param) && PEAR_Downloader_Package::willDownload($param, $params)) { + return false; + } + if (!$info) { + if (!is_string($param)) { + $saveparam = ", cannot download \"$param\""; + } else { + $saveparam = ''; + } + // no releases exist + return PEAR::raiseError('No releases for package "' . + $this->_registry->parsedPackageNameToString($pname, true) . '" exist' . $saveparam); + } + if (strtolower($info['info']->getChannel()) != strtolower($pname['channel'])) { + $err = false; + if ($pname['channel'] == 'pecl.php.net') { + if ($info['info']->getChannel() != 'pear.php.net') { + $err = true; + } + } elseif ($info['info']->getChannel() == 'pecl.php.net') { + if ($pname['channel'] != 'pear.php.net') { + $err = true; + } + } else { + $err = true; + } + if ($err) { + return PEAR::raiseError('SECURITY ERROR: package in channel "' . $pname['channel'] . + '" retrieved another channel\'s name for download! ("' . + $info['info']->getChannel() . '")'); + } + } + if (!isset($info['url'])) { + if ($this->isInstalled($info)) { + if ($isdependency && version_compare($info['version'], + $this->_registry->packageInfo($info['info']->getPackage(), + 'version', $info['info']->getChannel()), '<=')) { + // ignore bogus errors of "failed to download dependency" + // if it is already installed and the one that would be + // downloaded is older or the same version (Bug #7219) + return false; + } + } + $instead = ', will instead download version ' . $info['version'] . + ', stability "' . $info['info']->getState() . '"'; + // releases exist, but we failed to get any + if (isset($this->_downloader->_options['force'])) { + if (isset($pname['version'])) { + $vs = ', version "' . $pname['version'] . '"'; + } elseif (isset($pname['state'])) { + $vs = ', stability "' . $pname['state'] . '"'; + } elseif ($param == 'dependency') { + if (!class_exists('PEAR_Common')) { + require_once 'PEAR/Common.php'; + } + if (!in_array($info['info']->getState(), + PEAR_Common::betterStates($this->_config->get('preferred_state'), true))) { + if ($optional) { + // don't spit out confusing error message + return $this->_downloader->_getPackageDownloadUrl( + array('package' => $pname['package'], + 'channel' => $pname['channel'], + 'version' => $info['version'])); + } + $vs = ' within preferred state "' . $this->_config->get('preferred_state') . + '"'; + } else { + if (!class_exists('PEAR_Dependency2')) { + require_once 'PEAR/Dependency2.php'; + } + if ($optional) { + // don't spit out confusing error message + return $this->_downloader->_getPackageDownloadUrl( + array('package' => $pname['package'], + 'channel' => $pname['channel'], + 'version' => $info['version'])); + } + $vs = PEAR_Dependency2::_getExtraString($pname); + $instead = ''; + } + } else { + $vs = ' within preferred state "' . $this->_config->get( + 'preferred_state') . '"'; + } + if (!isset($options['soft'])) { + $this->_downloader->log(1, 'WARNING: failed to download ' . $pname['channel'] . + '/' . $pname['package'] . $vs . $instead); + } + // download the latest release + return $this->_downloader->_getPackageDownloadUrl( + array('package' => $pname['package'], + 'channel' => $pname['channel'], + 'version' => $info['version'])); + } else { + if (isset($info['php']) && $info['php']) { + $err = PEAR::raiseError('Failed to download ' . + $this->_registry->parsedPackageNameToString( + array('channel' => $pname['channel'], + 'package' => $pname['package']), + true) . + ', latest release is version ' . $info['php']['v'] . + ', but it requires PHP version "' . + $info['php']['m'] . '", use "' . + $this->_registry->parsedPackageNameToString( + array('channel' => $pname['channel'], 'package' => $pname['package'], + 'version' => $info['php']['v'])) . '" to install', + PEAR_DOWNLOADER_PACKAGE_PHPVERSION); + return $err; + } + // construct helpful error message + if (isset($pname['version'])) { + $vs = ', version "' . $pname['version'] . '"'; + } elseif (isset($pname['state'])) { + $vs = ', stability "' . $pname['state'] . '"'; + } elseif ($param == 'dependency') { + if (!class_exists('PEAR_Common')) { + require_once 'PEAR/Common.php'; + } + if (!in_array($info['info']->getState(), + PEAR_Common::betterStates($this->_config->get('preferred_state'), true))) { + if ($optional) { + // don't spit out confusing error message, and don't die on + // optional dep failure! + return $this->_downloader->_getPackageDownloadUrl( + array('package' => $pname['package'], + 'channel' => $pname['channel'], + 'version' => $info['version'])); + } + $vs = ' within preferred state "' . $this->_config->get('preferred_state') . + '"'; + } else { + if (!class_exists('PEAR_Dependency2')) { + require_once 'PEAR/Dependency2.php'; + } + if ($optional) { + // don't spit out confusing error message, and don't die on + // optional dep failure! + return $this->_downloader->_getPackageDownloadUrl( + array('package' => $pname['package'], + 'channel' => $pname['channel'], + 'version' => $info['version'])); + } + $vs = PEAR_Dependency2::_getExtraString($pname); + } + } else { + $vs = ' within preferred state "' . $this->_downloader->config->get( + 'preferred_state') . '"'; + } + $options = $this->_downloader->getOptions(); + // this is only set by the "download-all" command + if (isset($options['ignorepreferred_state'])) { + $err = PEAR::raiseError( + 'Failed to download ' . $this->_registry->parsedPackageNameToString( + array('channel' => $pname['channel'], 'package' => $pname['package']), + true) + . $vs . + ', latest release is version ' . $info['version'] . + ', stability "' . $info['info']->getState() . '", use "' . + $this->_registry->parsedPackageNameToString( + array('channel' => $pname['channel'], 'package' => $pname['package'], + 'version' => $info['version'])) . '" to install', + PEAR_DOWNLOADER_PACKAGE_STATE); + return $err; + } + $err = PEAR::raiseError( + 'Failed to download ' . $this->_registry->parsedPackageNameToString( + array('channel' => $pname['channel'], 'package' => $pname['package']), + true) + . $vs . + ', latest release is version ' . $info['version'] . + ', stability "' . $info['info']->getState() . '", use "' . + $this->_registry->parsedPackageNameToString( + array('channel' => $pname['channel'], 'package' => $pname['package'], + 'version' => $info['version'])) . '" to install'); + return $err; + } + } + if (isset($info['deprecated']) && $info['deprecated']) { + $this->_downloader->log(0, + 'WARNING: "' . + $this->_registry->parsedPackageNameToString( + array('channel' => $info['info']->getChannel(), + 'package' => $info['info']->getPackage()), true) . + '" is deprecated in favor of "' . + $this->_registry->parsedPackageNameToString($info['deprecated'], true) . + '"'); + } + return $info; + } +} +?> diff --git a/src/lib/pear/PEAR/PEAR/ErrorStack.php b/src/lib/pear/PEAR/PEAR/ErrorStack.php new file mode 100644 index 0000000..ad04901 --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/ErrorStack.php @@ -0,0 +1,985 @@ + + * @copyright 2004-2008 Greg Beaver + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: ErrorStack.php,v 1.28 2008/01/03 20:26:35 cellog Exp $ + * @link http://pear.php.net/package/PEAR_ErrorStack + */ + +/** + * Singleton storage + * + * Format: + *
    + * array(
    + *  'package1' => PEAR_ErrorStack object,
    + *  'package2' => PEAR_ErrorStack object,
    + *  ...
    + * )
    + * 
    + * @access private + * @global array $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] + */ +$GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] = array(); + +/** + * Global error callback (default) + * + * This is only used if set to non-false. * is the default callback for + * all packages, whereas specific packages may set a default callback + * for all instances, regardless of whether they are a singleton or not. + * + * To exclude non-singletons, only set the local callback for the singleton + * @see PEAR_ErrorStack::setDefaultCallback() + * @access private + * @global array $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'] + */ +$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'] = array( + '*' => false, +); + +/** + * Global Log object (default) + * + * This is only used if set to non-false. Use to set a default log object for + * all stacks, regardless of instantiation order or location + * @see PEAR_ErrorStack::setDefaultLogger() + * @access private + * @global array $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] + */ +$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = false; + +/** + * Global Overriding Callback + * + * This callback will override any error callbacks that specific loggers have set. + * Use with EXTREME caution + * @see PEAR_ErrorStack::staticPushCallback() + * @access private + * @global array $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] + */ +$GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'] = array(); + +/**#@+ + * One of four possible return values from the error Callback + * @see PEAR_ErrorStack::_errorCallback() + */ +/** + * If this is returned, then the error will be both pushed onto the stack + * and logged. + */ +define('PEAR_ERRORSTACK_PUSHANDLOG', 1); +/** + * If this is returned, then the error will only be pushed onto the stack, + * and not logged. + */ +define('PEAR_ERRORSTACK_PUSH', 2); +/** + * If this is returned, then the error will only be logged, but not pushed + * onto the error stack. + */ +define('PEAR_ERRORSTACK_LOG', 3); +/** + * If this is returned, then the error is completely ignored. + */ +define('PEAR_ERRORSTACK_IGNORE', 4); +/** + * If this is returned, then the error is logged and die() is called. + */ +define('PEAR_ERRORSTACK_DIE', 5); +/**#@-*/ + +/** + * Error code for an attempt to instantiate a non-class as a PEAR_ErrorStack in + * the singleton method. + */ +define('PEAR_ERRORSTACK_ERR_NONCLASS', 1); + +/** + * Error code for an attempt to pass an object into {@link PEAR_ErrorStack::getMessage()} + * that has no __toString() method + */ +define('PEAR_ERRORSTACK_ERR_OBJTOSTRING', 2); +/** + * Error Stack Implementation + * + * Usage: + * + * // global error stack + * $global_stack = &PEAR_ErrorStack::singleton('MyPackage'); + * // local error stack + * $local_stack = new PEAR_ErrorStack('MyPackage'); + * + * @author Greg Beaver + * @version 1.7.2 + * @package PEAR_ErrorStack + * @category Debugging + * @copyright 2004-2008 Greg Beaver + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: ErrorStack.php,v 1.28 2008/01/03 20:26:35 cellog Exp $ + * @link http://pear.php.net/package/PEAR_ErrorStack + */ +class PEAR_ErrorStack { + /** + * Errors are stored in the order that they are pushed on the stack. + * @since 0.4alpha Errors are no longer organized by error level. + * This renders pop() nearly unusable, and levels could be more easily + * handled in a callback anyway + * @var array + * @access private + */ + var $_errors = array(); + + /** + * Storage of errors by level. + * + * Allows easy retrieval and deletion of only errors from a particular level + * @since PEAR 1.4.0dev + * @var array + * @access private + */ + var $_errorsByLevel = array(); + + /** + * Package name this error stack represents + * @var string + * @access protected + */ + var $_package; + + /** + * Determines whether a PEAR_Error is thrown upon every error addition + * @var boolean + * @access private + */ + var $_compat = false; + + /** + * If set to a valid callback, this will be used to generate the error + * message from the error code, otherwise the message passed in will be + * used + * @var false|string|array + * @access private + */ + var $_msgCallback = false; + + /** + * If set to a valid callback, this will be used to generate the error + * context for an error. For PHP-related errors, this will be a file + * and line number as retrieved from debug_backtrace(), but can be + * customized for other purposes. The error might actually be in a separate + * configuration file, or in a database query. + * @var false|string|array + * @access protected + */ + var $_contextCallback = false; + + /** + * If set to a valid callback, this will be called every time an error + * is pushed onto the stack. The return value will be used to determine + * whether to allow an error to be pushed or logged. + * + * The return value must be one an PEAR_ERRORSTACK_* constant + * @see PEAR_ERRORSTACK_PUSHANDLOG, PEAR_ERRORSTACK_PUSH, PEAR_ERRORSTACK_LOG + * @var false|string|array + * @access protected + */ + var $_errorCallback = array(); + + /** + * PEAR::Log object for logging errors + * @var false|Log + * @access protected + */ + var $_logger = false; + + /** + * Error messages - designed to be overridden + * @var array + * @abstract + */ + var $_errorMsgs = array(); + + /** + * Set up a new error stack + * + * @param string $package name of the package this error stack represents + * @param callback $msgCallback callback used for error message generation + * @param callback $contextCallback callback used for context generation, + * defaults to {@link getFileLine()} + * @param boolean $throwPEAR_Error + */ + function PEAR_ErrorStack($package, $msgCallback = false, $contextCallback = false, + $throwPEAR_Error = false) + { + $this->_package = $package; + $this->setMessageCallback($msgCallback); + $this->setContextCallback($contextCallback); + $this->_compat = $throwPEAR_Error; + } + + /** + * Return a single error stack for this package. + * + * Note that all parameters are ignored if the stack for package $package + * has already been instantiated + * @param string $package name of the package this error stack represents + * @param callback $msgCallback callback used for error message generation + * @param callback $contextCallback callback used for context generation, + * defaults to {@link getFileLine()} + * @param boolean $throwPEAR_Error + * @param string $stackClass class to instantiate + * @static + * @return PEAR_ErrorStack + */ + function &singleton($package, $msgCallback = false, $contextCallback = false, + $throwPEAR_Error = false, $stackClass = 'PEAR_ErrorStack') + { + if (isset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package])) { + return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]; + } + if (!class_exists($stackClass)) { + if (function_exists('debug_backtrace')) { + $trace = debug_backtrace(); + } + PEAR_ErrorStack::staticPush('PEAR_ErrorStack', PEAR_ERRORSTACK_ERR_NONCLASS, + 'exception', array('stackclass' => $stackClass), + 'stack class "%stackclass%" is not a valid class name (should be like PEAR_ErrorStack)', + false, $trace); + } + $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package] = + new $stackClass($package, $msgCallback, $contextCallback, $throwPEAR_Error); + + return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]; + } + + /** + * Internal error handler for PEAR_ErrorStack class + * + * Dies if the error is an exception (and would have died anyway) + * @access private + */ + function _handleError($err) + { + if ($err['level'] == 'exception') { + $message = $err['message']; + if (isset($_SERVER['REQUEST_URI'])) { + echo '
    '; + } else { + echo "\n"; + } + var_dump($err['context']); + die($message); + } + } + + /** + * Set up a PEAR::Log object for all error stacks that don't have one + * @param Log $log + * @static + */ + function setDefaultLogger(&$log) + { + if (is_object($log) && method_exists($log, 'log') ) { + $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = &$log; + } elseif (is_callable($log)) { + $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = &$log; + } + } + + /** + * Set up a PEAR::Log object for this error stack + * @param Log $log + */ + function setLogger(&$log) + { + if (is_object($log) && method_exists($log, 'log') ) { + $this->_logger = &$log; + } elseif (is_callable($log)) { + $this->_logger = &$log; + } + } + + /** + * Set an error code => error message mapping callback + * + * This method sets the callback that can be used to generate error + * messages for any instance + * @param array|string Callback function/method + */ + function setMessageCallback($msgCallback) + { + if (!$msgCallback) { + $this->_msgCallback = array(&$this, 'getErrorMessage'); + } else { + if (is_callable($msgCallback)) { + $this->_msgCallback = $msgCallback; + } + } + } + + /** + * Get an error code => error message mapping callback + * + * This method returns the current callback that can be used to generate error + * messages + * @return array|string|false Callback function/method or false if none + */ + function getMessageCallback() + { + return $this->_msgCallback; + } + + /** + * Sets a default callback to be used by all error stacks + * + * This method sets the callback that can be used to generate error + * messages for a singleton + * @param array|string Callback function/method + * @param string Package name, or false for all packages + * @static + */ + function setDefaultCallback($callback = false, $package = false) + { + if (!is_callable($callback)) { + $callback = false; + } + $package = $package ? $package : '*'; + $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'][$package] = $callback; + } + + /** + * Set a callback that generates context information (location of error) for an error stack + * + * This method sets the callback that can be used to generate context + * information for an error. Passing in NULL will disable context generation + * and remove the expensive call to debug_backtrace() + * @param array|string|null Callback function/method + */ + function setContextCallback($contextCallback) + { + if ($contextCallback === null) { + return $this->_contextCallback = false; + } + if (!$contextCallback) { + $this->_contextCallback = array(&$this, 'getFileLine'); + } else { + if (is_callable($contextCallback)) { + $this->_contextCallback = $contextCallback; + } + } + } + + /** + * Set an error Callback + * If set to a valid callback, this will be called every time an error + * is pushed onto the stack. The return value will be used to determine + * whether to allow an error to be pushed or logged. + * + * The return value must be one of the ERRORSTACK_* constants. + * + * This functionality can be used to emulate PEAR's pushErrorHandling, and + * the PEAR_ERROR_CALLBACK mode, without affecting the integrity of + * the error stack or logging + * @see PEAR_ERRORSTACK_PUSHANDLOG, PEAR_ERRORSTACK_PUSH, PEAR_ERRORSTACK_LOG + * @see popCallback() + * @param string|array $cb + */ + function pushCallback($cb) + { + array_push($this->_errorCallback, $cb); + } + + /** + * Remove a callback from the error callback stack + * @see pushCallback() + * @return array|string|false + */ + function popCallback() + { + if (!count($this->_errorCallback)) { + return false; + } + return array_pop($this->_errorCallback); + } + + /** + * Set a temporary overriding error callback for every package error stack + * + * Use this to temporarily disable all existing callbacks (can be used + * to emulate the @ operator, for instance) + * @see PEAR_ERRORSTACK_PUSHANDLOG, PEAR_ERRORSTACK_PUSH, PEAR_ERRORSTACK_LOG + * @see staticPopCallback(), pushCallback() + * @param string|array $cb + * @static + */ + function staticPushCallback($cb) + { + array_push($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'], $cb); + } + + /** + * Remove a temporary overriding error callback + * @see staticPushCallback() + * @return array|string|false + * @static + */ + function staticPopCallback() + { + $ret = array_pop($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK']); + if (!is_array($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'])) { + $GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'] = array(); + } + return $ret; + } + + /** + * Add an error to the stack + * + * If the message generator exists, it is called with 2 parameters. + * - the current Error Stack object + * - an array that is in the same format as an error. Available indices + * are 'code', 'package', 'time', 'params', 'level', and 'context' + * + * Next, if the error should contain context information, this is + * handled by the context grabbing method. + * Finally, the error is pushed onto the proper error stack + * @param int $code Package-specific error code + * @param string $level Error level. This is NOT spell-checked + * @param array $params associative array of error parameters + * @param string $msg Error message, or a portion of it if the message + * is to be generated + * @param array $repackage If this error re-packages an error pushed by + * another package, place the array returned from + * {@link pop()} in this parameter + * @param array $backtrace Protected parameter: use this to pass in the + * {@link debug_backtrace()} that should be used + * to find error context + * @return PEAR_Error|array if compatibility mode is on, a PEAR_Error is also + * thrown. If a PEAR_Error is returned, the userinfo + * property is set to the following array: + * + * + * array( + * 'code' => $code, + * 'params' => $params, + * 'package' => $this->_package, + * 'level' => $level, + * 'time' => time(), + * 'context' => $context, + * 'message' => $msg, + * //['repackage' => $err] repackaged error array/Exception class + * ); + * + * + * Normally, the previous array is returned. + */ + function push($code, $level = 'error', $params = array(), $msg = false, + $repackage = false, $backtrace = false) + { + $context = false; + // grab error context + if ($this->_contextCallback) { + if (!$backtrace) { + $backtrace = debug_backtrace(); + } + $context = call_user_func($this->_contextCallback, $code, $params, $backtrace); + } + + // save error + $time = explode(' ', microtime()); + $time = $time[1] + $time[0]; + $err = array( + 'code' => $code, + 'params' => $params, + 'package' => $this->_package, + 'level' => $level, + 'time' => $time, + 'context' => $context, + 'message' => $msg, + ); + + if ($repackage) { + $err['repackage'] = $repackage; + } + + // set up the error message, if necessary + if ($this->_msgCallback) { + $msg = call_user_func_array($this->_msgCallback, + array(&$this, $err)); + $err['message'] = $msg; + } + $push = $log = true; + $die = false; + // try the overriding callback first + $callback = $this->staticPopCallback(); + if ($callback) { + $this->staticPushCallback($callback); + } + if (!is_callable($callback)) { + // try the local callback next + $callback = $this->popCallback(); + if (is_callable($callback)) { + $this->pushCallback($callback); + } else { + // try the default callback + $callback = isset($GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'][$this->_package]) ? + $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'][$this->_package] : + $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK']['*']; + } + } + if (is_callable($callback)) { + switch(call_user_func($callback, $err)){ + case PEAR_ERRORSTACK_IGNORE: + return $err; + break; + case PEAR_ERRORSTACK_PUSH: + $log = false; + break; + case PEAR_ERRORSTACK_LOG: + $push = false; + break; + case PEAR_ERRORSTACK_DIE: + $die = true; + break; + // anything else returned has the same effect as pushandlog + } + } + if ($push) { + array_unshift($this->_errors, $err); + if (!isset($this->_errorsByLevel[$err['level']])) { + $this->_errorsByLevel[$err['level']] = array(); + } + $this->_errorsByLevel[$err['level']][] = &$this->_errors[0]; + } + if ($log) { + if ($this->_logger || $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER']) { + $this->_log($err); + } + } + if ($die) { + die(); + } + if ($this->_compat && $push) { + return $this->raiseError($msg, $code, null, null, $err); + } + return $err; + } + + /** + * Static version of {@link push()} + * + * @param string $package Package name this error belongs to + * @param int $code Package-specific error code + * @param string $level Error level. This is NOT spell-checked + * @param array $params associative array of error parameters + * @param string $msg Error message, or a portion of it if the message + * is to be generated + * @param array $repackage If this error re-packages an error pushed by + * another package, place the array returned from + * {@link pop()} in this parameter + * @param array $backtrace Protected parameter: use this to pass in the + * {@link debug_backtrace()} that should be used + * to find error context + * @return PEAR_Error|array if compatibility mode is on, a PEAR_Error is also + * thrown. see docs for {@link push()} + * @static + */ + function staticPush($package, $code, $level = 'error', $params = array(), + $msg = false, $repackage = false, $backtrace = false) + { + $s = &PEAR_ErrorStack::singleton($package); + if ($s->_contextCallback) { + if (!$backtrace) { + if (function_exists('debug_backtrace')) { + $backtrace = debug_backtrace(); + } + } + } + return $s->push($code, $level, $params, $msg, $repackage, $backtrace); + } + + /** + * Log an error using PEAR::Log + * @param array $err Error array + * @param array $levels Error level => Log constant map + * @access protected + */ + function _log($err) + { + if ($this->_logger) { + $logger = &$this->_logger; + } else { + $logger = &$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER']; + } + if (is_a($logger, 'Log')) { + $levels = array( + 'exception' => PEAR_LOG_CRIT, + 'alert' => PEAR_LOG_ALERT, + 'critical' => PEAR_LOG_CRIT, + 'error' => PEAR_LOG_ERR, + 'warning' => PEAR_LOG_WARNING, + 'notice' => PEAR_LOG_NOTICE, + 'info' => PEAR_LOG_INFO, + 'debug' => PEAR_LOG_DEBUG); + if (isset($levels[$err['level']])) { + $level = $levels[$err['level']]; + } else { + $level = PEAR_LOG_INFO; + } + $logger->log($err['message'], $level, $err); + } else { // support non-standard logs + call_user_func($logger, $err); + } + } + + + /** + * Pop an error off of the error stack + * + * @return false|array + * @since 0.4alpha it is no longer possible to specify a specific error + * level to return - the last error pushed will be returned, instead + */ + function pop() + { + $err = @array_shift($this->_errors); + if (!is_null($err)) { + @array_pop($this->_errorsByLevel[$err['level']]); + if (!count($this->_errorsByLevel[$err['level']])) { + unset($this->_errorsByLevel[$err['level']]); + } + } + return $err; + } + + /** + * Pop an error off of the error stack, static method + * + * @param string package name + * @return boolean + * @since PEAR1.5.0a1 + */ + function staticPop($package) + { + if ($package) { + if (!isset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package])) { + return false; + } + return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]->pop(); + } + } + + /** + * Determine whether there are any errors on the stack + * @param string|array Level name. Use to determine if any errors + * of level (string), or levels (array) have been pushed + * @return boolean + */ + function hasErrors($level = false) + { + if ($level) { + return isset($this->_errorsByLevel[$level]); + } + return count($this->_errors); + } + + /** + * Retrieve all errors since last purge + * + * @param boolean set in order to empty the error stack + * @param string level name, to return only errors of a particular severity + * @return array + */ + function getErrors($purge = false, $level = false) + { + if (!$purge) { + if ($level) { + if (!isset($this->_errorsByLevel[$level])) { + return array(); + } else { + return $this->_errorsByLevel[$level]; + } + } else { + return $this->_errors; + } + } + if ($level) { + $ret = $this->_errorsByLevel[$level]; + foreach ($this->_errorsByLevel[$level] as $i => $unused) { + // entries are references to the $_errors array + $this->_errorsByLevel[$level][$i] = false; + } + // array_filter removes all entries === false + $this->_errors = array_filter($this->_errors); + unset($this->_errorsByLevel[$level]); + return $ret; + } + $ret = $this->_errors; + $this->_errors = array(); + $this->_errorsByLevel = array(); + return $ret; + } + + /** + * Determine whether there are any errors on a single error stack, or on any error stack + * + * The optional parameter can be used to test the existence of any errors without the need of + * singleton instantiation + * @param string|false Package name to check for errors + * @param string Level name to check for a particular severity + * @return boolean + * @static + */ + function staticHasErrors($package = false, $level = false) + { + if ($package) { + if (!isset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package])) { + return false; + } + return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]->hasErrors($level); + } + foreach ($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] as $package => $obj) { + if ($obj->hasErrors($level)) { + return true; + } + } + return false; + } + + /** + * Get a list of all errors since last purge, organized by package + * @since PEAR 1.4.0dev BC break! $level is now in the place $merge used to be + * @param boolean $purge Set to purge the error stack of existing errors + * @param string $level Set to a level name in order to retrieve only errors of a particular level + * @param boolean $merge Set to return a flat array, not organized by package + * @param array $sortfunc Function used to sort a merged array - default + * sorts by time, and should be good for most cases + * @static + * @return array + */ + function staticGetErrors($purge = false, $level = false, $merge = false, + $sortfunc = array('PEAR_ErrorStack', '_sortErrors')) + { + $ret = array(); + if (!is_callable($sortfunc)) { + $sortfunc = array('PEAR_ErrorStack', '_sortErrors'); + } + foreach ($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] as $package => $obj) { + $test = $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]->getErrors($purge, $level); + if ($test) { + if ($merge) { + $ret = array_merge($ret, $test); + } else { + $ret[$package] = $test; + } + } + } + if ($merge) { + usort($ret, $sortfunc); + } + return $ret; + } + + /** + * Error sorting function, sorts by time + * @access private + */ + function _sortErrors($a, $b) + { + if ($a['time'] == $b['time']) { + return 0; + } + if ($a['time'] < $b['time']) { + return 1; + } + return -1; + } + + /** + * Standard file/line number/function/class context callback + * + * This function uses a backtrace generated from {@link debug_backtrace()} + * and so will not work at all in PHP < 4.3.0. The frame should + * reference the frame that contains the source of the error. + * @return array|false either array('file' => file, 'line' => line, + * 'function' => function name, 'class' => class name) or + * if this doesn't work, then false + * @param unused + * @param integer backtrace frame. + * @param array Results of debug_backtrace() + * @static + */ + function getFileLine($code, $params, $backtrace = null) + { + if ($backtrace === null) { + return false; + } + $frame = 0; + $functionframe = 1; + if (!isset($backtrace[1])) { + $functionframe = 0; + } else { + while (isset($backtrace[$functionframe]['function']) && + $backtrace[$functionframe]['function'] == 'eval' && + isset($backtrace[$functionframe + 1])) { + $functionframe++; + } + } + if (isset($backtrace[$frame])) { + if (!isset($backtrace[$frame]['file'])) { + $frame++; + } + $funcbacktrace = $backtrace[$functionframe]; + $filebacktrace = $backtrace[$frame]; + $ret = array('file' => $filebacktrace['file'], + 'line' => $filebacktrace['line']); + // rearrange for eval'd code or create function errors + if (strpos($filebacktrace['file'], '(') && + preg_match(';^(.*?)\((\d+)\) : (.*?)\\z;', $filebacktrace['file'], + $matches)) { + $ret['file'] = $matches[1]; + $ret['line'] = $matches[2] + 0; + } + if (isset($funcbacktrace['function']) && isset($backtrace[1])) { + if ($funcbacktrace['function'] != 'eval') { + if ($funcbacktrace['function'] == '__lambda_func') { + $ret['function'] = 'create_function() code'; + } else { + $ret['function'] = $funcbacktrace['function']; + } + } + } + if (isset($funcbacktrace['class']) && isset($backtrace[1])) { + $ret['class'] = $funcbacktrace['class']; + } + return $ret; + } + return false; + } + + /** + * Standard error message generation callback + * + * This method may also be called by a custom error message generator + * to fill in template values from the params array, simply + * set the third parameter to the error message template string to use + * + * The special variable %__msg% is reserved: use it only to specify + * where a message passed in by the user should be placed in the template, + * like so: + * + * Error message: %msg% - internal error + * + * If the message passed like so: + * + * + * $stack->push(ERROR_CODE, 'error', array(), 'server error 500'); + * + * + * The returned error message will be "Error message: server error 500 - + * internal error" + * @param PEAR_ErrorStack + * @param array + * @param string|false Pre-generated error message template + * @static + * @return string + */ + function getErrorMessage(&$stack, $err, $template = false) + { + if ($template) { + $mainmsg = $template; + } else { + $mainmsg = $stack->getErrorMessageTemplate($err['code']); + } + $mainmsg = str_replace('%__msg%', $err['message'], $mainmsg); + if (is_array($err['params']) && count($err['params'])) { + foreach ($err['params'] as $name => $val) { + if (is_array($val)) { + // @ is needed in case $val is a multi-dimensional array + $val = @implode(', ', $val); + } + if (is_object($val)) { + if (method_exists($val, '__toString')) { + $val = $val->__toString(); + } else { + PEAR_ErrorStack::staticPush('PEAR_ErrorStack', PEAR_ERRORSTACK_ERR_OBJTOSTRING, + 'warning', array('obj' => get_class($val)), + 'object %obj% passed into getErrorMessage, but has no __toString() method'); + $val = 'Object'; + } + } + $mainmsg = str_replace('%' . $name . '%', $val, $mainmsg); + } + } + return $mainmsg; + } + + /** + * Standard Error Message Template generator from code + * @return string + */ + function getErrorMessageTemplate($code) + { + if (!isset($this->_errorMsgs[$code])) { + return '%__msg%'; + } + return $this->_errorMsgs[$code]; + } + + /** + * Set the Error Message Template array + * + * The array format must be: + *
    +     * array(error code => 'message template',...)
    +     * 
    + * + * Error message parameters passed into {@link push()} will be used as input + * for the error message. If the template is 'message %foo% was %bar%', and the + * parameters are array('foo' => 'one', 'bar' => 'six'), the error message returned will + * be 'message one was six' + * @return string + */ + function setErrorMessageTemplate($template) + { + $this->_errorMsgs = $template; + } + + + /** + * emulate PEAR::raiseError() + * + * @return PEAR_Error + */ + function raiseError() + { + require_once 'PEAR.php'; + $args = func_get_args(); + return call_user_func_array(array('PEAR', 'raiseError'), $args); + } +} +$stack = &PEAR_ErrorStack::singleton('PEAR_ErrorStack'); +$stack->pushCallback(array('PEAR_ErrorStack', '_handleError')); +?> diff --git a/src/lib/pear/PEAR/PEAR/Exception.php b/src/lib/pear/PEAR/PEAR/Exception.php new file mode 100644 index 0000000..b3d75b2 --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Exception.php @@ -0,0 +1,397 @@ + + * @author Hans Lellelid + * @author Bertrand Mansion + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: Exception.php,v 1.29 2008/01/03 20:26:35 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 1.3.3 + */ + + +/** + * Base PEAR_Exception Class + * + * 1) Features: + * + * - Nestable exceptions (throw new PEAR_Exception($msg, $prev_exception)) + * - Definable triggers, shot when exceptions occur + * - Pretty and informative error messages + * - Added more context info available (like class, method or cause) + * - cause can be a PEAR_Exception or an array of mixed + * PEAR_Exceptions/PEAR_ErrorStack warnings + * - callbacks for specific exception classes and their children + * + * 2) Ideas: + * + * - Maybe a way to define a 'template' for the output + * + * 3) Inherited properties from PHP Exception Class: + * + * protected $message + * protected $code + * protected $line + * protected $file + * private $trace + * + * 4) Inherited methods from PHP Exception Class: + * + * __clone + * __construct + * getMessage + * getCode + * getFile + * getLine + * getTraceSafe + * getTraceSafeAsString + * __toString + * + * 5) Usage example + * + * + * require_once 'PEAR/Exception.php'; + * + * class Test { + * function foo() { + * throw new PEAR_Exception('Error Message', ERROR_CODE); + * } + * } + * + * function myLogger($pear_exception) { + * echo $pear_exception->getMessage(); + * } + * // each time a exception is thrown the 'myLogger' will be called + * // (its use is completely optional) + * PEAR_Exception::addObserver('myLogger'); + * $test = new Test; + * try { + * $test->foo(); + * } catch (PEAR_Exception $e) { + * print $e; + * } + * + * + * @category pear + * @package PEAR + * @author Tomas V.V.Cox + * @author Hans Lellelid + * @author Bertrand Mansion + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 1.3.3 + * + */ +class PEAR_Exception extends Exception +{ + const OBSERVER_PRINT = -2; + const OBSERVER_TRIGGER = -4; + const OBSERVER_DIE = -8; + protected $cause; + private static $_observers = array(); + private static $_uniqueid = 0; + private $_trace; + + /** + * Supported signatures: + * - PEAR_Exception(string $message); + * - PEAR_Exception(string $message, int $code); + * - PEAR_Exception(string $message, Exception $cause); + * - PEAR_Exception(string $message, Exception $cause, int $code); + * - PEAR_Exception(string $message, PEAR_Error $cause); + * - PEAR_Exception(string $message, PEAR_Error $cause, int $code); + * - PEAR_Exception(string $message, array $causes); + * - PEAR_Exception(string $message, array $causes, int $code); + * @param string exception message + * @param int|Exception|PEAR_Error|array|null exception cause + * @param int|null exception code or null + */ + public function __construct($message, $p2 = null, $p3 = null) + { + if (is_int($p2)) { + $code = $p2; + $this->cause = null; + } elseif (is_object($p2) || is_array($p2)) { + // using is_object allows both Exception and PEAR_Error + if (is_object($p2) && !($p2 instanceof Exception)) { + if (!class_exists('PEAR_Error') || !($p2 instanceof PEAR_Error)) { + throw new PEAR_Exception('exception cause must be Exception, ' . + 'array, or PEAR_Error'); + } + } + $code = $p3; + if (is_array($p2) && isset($p2['message'])) { + // fix potential problem of passing in a single warning + $p2 = array($p2); + } + $this->cause = $p2; + } else { + $code = null; + $this->cause = null; + } + parent::__construct($message, $code); + $this->signal(); + } + + /** + * @param mixed $callback - A valid php callback, see php func is_callable() + * - A PEAR_Exception::OBSERVER_* constant + * - An array(const PEAR_Exception::OBSERVER_*, + * mixed $options) + * @param string $label The name of the observer. Use this if you want + * to remove it later with removeObserver() + */ + public static function addObserver($callback, $label = 'default') + { + self::$_observers[$label] = $callback; + } + + public static function removeObserver($label = 'default') + { + unset(self::$_observers[$label]); + } + + /** + * @return int unique identifier for an observer + */ + public static function getUniqueId() + { + return self::$_uniqueid++; + } + + private function signal() + { + foreach (self::$_observers as $func) { + if (is_callable($func)) { + call_user_func($func, $this); + continue; + } + settype($func, 'array'); + switch ($func[0]) { + case self::OBSERVER_PRINT : + $f = (isset($func[1])) ? $func[1] : '%s'; + printf($f, $this->getMessage()); + break; + case self::OBSERVER_TRIGGER : + $f = (isset($func[1])) ? $func[1] : E_USER_NOTICE; + trigger_error($this->getMessage(), $f); + break; + case self::OBSERVER_DIE : + $f = (isset($func[1])) ? $func[1] : '%s'; + die(printf($f, $this->getMessage())); + break; + default: + trigger_error('invalid observer type', E_USER_WARNING); + } + } + } + + /** + * Return specific error information that can be used for more detailed + * error messages or translation. + * + * This method may be overridden in child exception classes in order + * to add functionality not present in PEAR_Exception and is a placeholder + * to define API + * + * The returned array must be an associative array of parameter => value like so: + *
    +     * array('name' => $name, 'context' => array(...))
    +     * 
    + * @return array + */ + public function getErrorData() + { + return array(); + } + + /** + * Returns the exception that caused this exception to be thrown + * @access public + * @return Exception|array The context of the exception + */ + public function getCause() + { + return $this->cause; + } + + /** + * Function must be public to call on caused exceptions + * @param array + */ + public function getCauseMessage(&$causes) + { + $trace = $this->getTraceSafe(); + $cause = array('class' => get_class($this), + 'message' => $this->message, + 'file' => 'unknown', + 'line' => 'unknown'); + if (isset($trace[0])) { + if (isset($trace[0]['file'])) { + $cause['file'] = $trace[0]['file']; + $cause['line'] = $trace[0]['line']; + } + } + $causes[] = $cause; + if ($this->cause instanceof PEAR_Exception) { + $this->cause->getCauseMessage($causes); + } elseif ($this->cause instanceof Exception) { + $causes[] = array('class' => get_class($this->cause), + 'message' => $this->cause->getMessage(), + 'file' => $this->cause->getFile(), + 'line' => $this->cause->getLine()); + } elseif (class_exists('PEAR_Error') && $this->cause instanceof PEAR_Error) { + $causes[] = array('class' => get_class($this->cause), + 'message' => $this->cause->getMessage(), + 'file' => 'unknown', + 'line' => 'unknown'); + } elseif (is_array($this->cause)) { + foreach ($this->cause as $cause) { + if ($cause instanceof PEAR_Exception) { + $cause->getCauseMessage($causes); + } elseif ($cause instanceof Exception) { + $causes[] = array('class' => get_class($cause), + 'message' => $cause->getMessage(), + 'file' => $cause->getFile(), + 'line' => $cause->getLine()); + } elseif (class_exists('PEAR_Error') && $cause instanceof PEAR_Error) { + $causes[] = array('class' => get_class($cause), + 'message' => $cause->getMessage(), + 'file' => 'unknown', + 'line' => 'unknown'); + } elseif (is_array($cause) && isset($cause['message'])) { + // PEAR_ErrorStack warning + $causes[] = array( + 'class' => $cause['package'], + 'message' => $cause['message'], + 'file' => isset($cause['context']['file']) ? + $cause['context']['file'] : + 'unknown', + 'line' => isset($cause['context']['line']) ? + $cause['context']['line'] : + 'unknown', + ); + } + } + } + } + + public function getTraceSafe() + { + if (!isset($this->_trace)) { + $this->_trace = $this->getTrace(); + if (empty($this->_trace)) { + $backtrace = debug_backtrace(); + $this->_trace = array($backtrace[count($backtrace)-1]); + } + } + return $this->_trace; + } + + public function getErrorClass() + { + $trace = $this->getTraceSafe(); + return $trace[0]['class']; + } + + public function getErrorMethod() + { + $trace = $this->getTraceSafe(); + return $trace[0]['function']; + } + + public function __toString() + { + if (isset($_SERVER['REQUEST_URI'])) { + return $this->toHtml(); + } + return $this->toText(); + } + + public function toHtml() + { + $trace = $this->getTraceSafe(); + $causes = array(); + $this->getCauseMessage($causes); + $html = '' . "\n"; + foreach ($causes as $i => $cause) { + $html .= '\n"; + } + $html .= '' . "\n" + . '' + . '' + . '' . "\n"; + + foreach ($trace as $k => $v) { + $html .= '' + . '' + . '' . "\n"; + } + $html .= '' + . '' + . '' . "\n" + . '
    ' + . str_repeat('-', $i) . ' ' . $cause['class'] . ': ' + . htmlspecialchars($cause['message']) . ' in ' . $cause['file'] . ' ' + . 'on line ' . $cause['line'] . '' + . "
    Exception trace
    #FunctionLocation
    ' . $k . ''; + if (!empty($v['class'])) { + $html .= $v['class'] . $v['type']; + } + $html .= $v['function']; + $args = array(); + if (!empty($v['args'])) { + foreach ($v['args'] as $arg) { + if (is_null($arg)) $args[] = 'null'; + elseif (is_array($arg)) $args[] = 'Array'; + elseif (is_object($arg)) $args[] = 'Object('.get_class($arg).')'; + elseif (is_bool($arg)) $args[] = $arg ? 'true' : 'false'; + elseif (is_int($arg) || is_double($arg)) $args[] = $arg; + else { + $arg = (string)$arg; + $str = htmlspecialchars(substr($arg, 0, 16)); + if (strlen($arg) > 16) $str .= '…'; + $args[] = "'" . $str . "'"; + } + } + } + $html .= '(' . implode(', ',$args) . ')' + . '' . (isset($v['file']) ? $v['file'] : 'unknown') + . ':' . (isset($v['line']) ? $v['line'] : 'unknown') + . '
    ' . ($k+1) . '{main} 
    '; + return $html; + } + + public function toText() + { + $causes = array(); + $this->getCauseMessage($causes); + $causeMsg = ''; + foreach ($causes as $i => $cause) { + $causeMsg .= str_repeat(' ', $i) . $cause['class'] . ': ' + . $cause['message'] . ' in ' . $cause['file'] + . ' on line ' . $cause['line'] . "\n"; + } + return $causeMsg . $this->getTraceAsString(); + } +} + +?> \ No newline at end of file diff --git a/src/lib/pear/PEAR/PEAR/FixPHP5PEARWarnings.php b/src/lib/pear/PEAR/PEAR/FixPHP5PEARWarnings.php new file mode 100644 index 0000000..be5dc3c --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/FixPHP5PEARWarnings.php @@ -0,0 +1,7 @@ + \ No newline at end of file diff --git a/src/lib/pear/PEAR/PEAR/Frontend.php b/src/lib/pear/PEAR/PEAR/Frontend.php new file mode 100644 index 0000000..bf7d4ba --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Frontend.php @@ -0,0 +1,223 @@ + + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: Frontend.php,v 1.13 2008/01/03 20:26:35 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 1.4.0a1 + */ + +/** + * Which user interface class is being used. + * @var string class name + */ +$GLOBALS['_PEAR_FRONTEND_CLASS'] = 'PEAR_Frontend_CLI'; + +/** + * Instance of $_PEAR_Command_uiclass. + * @var object + */ +$GLOBALS['_PEAR_FRONTEND_SINGLETON'] = null; + +/** + * Singleton-based frontend for PEAR user input/output + * + * @category pear + * @package PEAR + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 1.4.0a1 + */ +class PEAR_Frontend extends PEAR +{ + /** + * Retrieve the frontend object + * @return PEAR_Frontend_CLI|PEAR_Frontend_Web|PEAR_Frontend_Gtk + * @static + */ + function &singleton($type = null) + { + if ($type === null) { + if (!isset($GLOBALS['_PEAR_FRONTEND_SINGLETON'])) { + $a = false; + return $a; + } + return $GLOBALS['_PEAR_FRONTEND_SINGLETON']; + } else { + $a = PEAR_Frontend::setFrontendClass($type); + return $a; + } + } + + /** + * Set the frontend class that will be used by calls to {@link singleton()} + * + * Frontends are expected to conform to the PEAR naming standard of + * _ => DIRECTORY_SEPARATOR (PEAR_Frontend_CLI is in PEAR/Frontend/CLI.php) + * @param string $uiclass full class name + * @return PEAR_Frontend + * @static + */ + function &setFrontendClass($uiclass) + { + if (is_object($GLOBALS['_PEAR_FRONTEND_SINGLETON']) && + is_a($GLOBALS['_PEAR_FRONTEND_SINGLETON'], $uiclass)) { + return $GLOBALS['_PEAR_FRONTEND_SINGLETON']; + } + if (!class_exists($uiclass)) { + $file = str_replace('_', '/', $uiclass) . '.php'; + if (PEAR_Frontend::isIncludeable($file)) { + include_once $file; + } + } + if (class_exists($uiclass)) { + $obj = &new $uiclass; + // quick test to see if this class implements a few of the most + // important frontend methods + if (is_a($obj, 'PEAR_Frontend')) { + $GLOBALS['_PEAR_FRONTEND_SINGLETON'] = &$obj; + $GLOBALS['_PEAR_FRONTEND_CLASS'] = $uiclass; + return $obj; + } else { + $err = PEAR::raiseError("not a frontend class: $uiclass"); + return $err; + } + } + $err = PEAR::raiseError("no such class: $uiclass"); + return $err; + } + + /** + * Set the frontend class that will be used by calls to {@link singleton()} + * + * Frontends are expected to be a descendant of PEAR_Frontend + * @param PEAR_Frontend + * @return PEAR_Frontend + * @static + */ + function &setFrontendObject($uiobject) + { + if (is_object($GLOBALS['_PEAR_FRONTEND_SINGLETON']) && + is_a($GLOBALS['_PEAR_FRONTEND_SINGLETON'], get_class($uiobject))) { + return $GLOBALS['_PEAR_FRONTEND_SINGLETON']; + } + if (!is_a($uiobject, 'PEAR_Frontend')) { + $err = PEAR::raiseError('not a valid frontend class: (' . + get_class($uiobject) . ')'); + return $err; + } + $GLOBALS['_PEAR_FRONTEND_SINGLETON'] = &$uiobject; + $GLOBALS['_PEAR_FRONTEND_CLASS'] = get_class($uiobject); + return $uiobject; + } + + /** + * @param string $path relative or absolute include path + * @return boolean + * @static + */ + function isIncludeable($path) + { + if (file_exists($path) && is_readable($path)) { + return true; + } + $fp = @fopen($path, 'r', true); + if ($fp) { + fclose($fp); + return true; + } + return false; + } + + /** + * @param PEAR_Config + */ + function setConfig(&$config) + { + } + + /** + * This can be overridden to allow session-based temporary file management + * + * By default, all files are deleted at the end of a session. The web installer + * needs to be able to sustain a list over many sessions in order to support + * user interaction with install scripts + */ + function addTempFile($file) + { + $GLOBALS['_PEAR_Common_tempfiles'][] = $file; + } + + /** + * Log an action + * + * @param string $msg the message to log + * @param boolean $append_crlf + * @return boolean true + * @abstract + */ + function log($msg, $append_crlf = true) + { + } + + /** + * Run a post-installation script + * + * @param array $scripts array of post-install scripts + * @abstract + */ + function runPostinstallScripts(&$scripts) + { + } + + /** + * Display human-friendly output formatted depending on the + * $command parameter. + * + * This should be able to handle basic output data with no command + * @param mixed $data data structure containing the information to display + * @param string $command command from which this method was called + * @abstract + */ + function outputData($data, $command = '_default') + { + } + + /** + * Display a modal form dialog and return the given input + * + * A frontend that requires multiple requests to retrieve and process + * data must take these needs into account, and implement the request + * handling code. + * @param string $command command from which this method was called + * @param array $prompts associative array. keys are the input field names + * and values are the description + * @param array $types array of input field types (text, password, + * etc.) keys have to be the same like in $prompts + * @param array $defaults array of default values. again keys have + * to be the same like in $prompts. Do not depend + * on a default value being set. + * @return array input sent by the user + * @abstract + */ + function userDialog($command, $prompts, $types = array(), $defaults = array()) + { + } +} +?> \ No newline at end of file diff --git a/src/lib/pear/PEAR/PEAR/Frontend/CLI.php b/src/lib/pear/PEAR/PEAR/Frontend/CLI.php new file mode 100644 index 0000000..0655aba --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Frontend/CLI.php @@ -0,0 +1,794 @@ + + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: CLI.php,v 1.68 2008/01/03 20:26:36 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 0.1 + */ +/** + * base class + */ +require_once 'PEAR/Frontend.php'; + +/** + * Command-line Frontend for the PEAR Installer + * @category pear + * @package PEAR + * @author Stig Bakken + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 0.1 + */ +class PEAR_Frontend_CLI extends PEAR_Frontend +{ + // {{{ properties + + /** + * What type of user interface this frontend is for. + * @var string + * @access public + */ + var $type = 'CLI'; + var $lp = ''; // line prefix + + var $params = array(); + var $term = array( + 'bold' => '', + 'normal' => '', + ); + + // }}} + + // {{{ constructor + + function PEAR_Frontend_CLI() + { + parent::PEAR(); + $term = getenv('TERM'); //(cox) $_ENV is empty for me in 4.1.1 + if (function_exists('posix_isatty') && !posix_isatty(1)) { + // output is being redirected to a file or through a pipe + } elseif ($term) { + // XXX can use ncurses extension here, if available + if (preg_match('/^(xterm|vt220|linux)/', $term)) { + $this->term['bold'] = sprintf("%c%c%c%c", 27, 91, 49, 109); + $this->term['normal']=sprintf("%c%c%c", 27, 91, 109); + } elseif (preg_match('/^vt100/', $term)) { + $this->term['bold'] = sprintf("%c%c%c%c%c%c", 27, 91, 49, 109, 0, 0); + $this->term['normal']=sprintf("%c%c%c%c%c", 27, 91, 109, 0, 0); + } + } elseif (OS_WINDOWS) { + // XXX add ANSI codes here + } + } + + // }}} + + // {{{ displayLine(text) + + function displayLine($text) + { + trigger_error("PEAR_Frontend_CLI::displayLine deprecated", E_USER_ERROR); + } + + function _displayLine($text) + { + print "$this->lp$text\n"; + } + + // }}} + // {{{ display(text) + + function display($text) + { + trigger_error("PEAR_Frontend_CLI::display deprecated", E_USER_ERROR); + } + + function _display($text) + { + print $text; + } + + // }}} + // {{{ displayError(eobj) + + /** + * @param object PEAR_Error object + */ + function displayError($eobj) + { + return $this->_displayLine($eobj->getMessage()); + } + + // }}} + // {{{ displayFatalError(eobj) + + /** + * @param object PEAR_Error object + */ + function displayFatalError($eobj) + { + $this->displayError($eobj); + if (class_exists('PEAR_Config')) { + $config = &PEAR_Config::singleton(); + if ($config->get('verbose') > 5) { + if (function_exists('debug_print_backtrace')) { + debug_print_backtrace(); + } elseif (function_exists('debug_backtrace')) { + $trace = debug_backtrace(); + $raised = false; + foreach ($trace as $i => $frame) { + if (!$raised) { + if (isset($frame['class']) && strtolower($frame['class']) == + 'pear' && strtolower($frame['function']) == 'raiseerror') { + $raised = true; + } else { + continue; + } + } + if (!isset($frame['class'])) { + $frame['class'] = ''; + } + if (!isset($frame['type'])) { + $frame['type'] = ''; + } + if (!isset($frame['function'])) { + $frame['function'] = ''; + } + if (!isset($frame['line'])) { + $frame['line'] = ''; + } + $this->_displayLine("#$i: $frame[class]$frame[type]$frame[function] $frame[line]"); + } + } + } + } + exit(1); + } + + // }}} + // {{{ displayHeading(title) + + function displayHeading($title) + { + trigger_error("PEAR_Frontend_CLI::displayHeading deprecated", E_USER_ERROR); + } + + function _displayHeading($title) + { + print $this->lp.$this->bold($title)."\n"; + print $this->lp.str_repeat("=", strlen($title))."\n"; + } + + // }}} + + /** + * Instruct the runInstallScript method to skip a paramgroup that matches the + * id value passed in. + * + * This method is useful for dynamically configuring which sections of a post-install script + * will be run based on the user's setup, which is very useful for making flexible + * post-install scripts without losing the cross-Frontend ability to retrieve user input + * @param string + */ + function skipParamgroup($id) + { + $this->_skipSections[$id] = true; + } + + function runPostinstallScripts(&$scripts) + { + foreach ($scripts as $i => $script) { + $this->runInstallScript($scripts[$i]->_params, $scripts[$i]->_obj); + } + } + + /** + * @param array $xml contents of postinstallscript tag + * @param object $script post-installation script + * @param string install|upgrade + */ + function runInstallScript($xml, &$script) + { + $this->_skipSections = array(); + if (!is_array($xml) || !isset($xml['paramgroup'])) { + $script->run(array(), '_default'); + } else { + $completedPhases = array(); + if (!isset($xml['paramgroup'][0])) { + $xml['paramgroup'] = array($xml['paramgroup']); + } + foreach ($xml['paramgroup'] as $group) { + if (isset($this->_skipSections[$group['id']])) { + // the post-install script chose to skip this section dynamically + continue; + } + if (isset($group['name'])) { + $paramname = explode('::', $group['name']); + if ($lastgroup['id'] != $paramname[0]) { + continue; + } + $group['name'] = $paramname[1]; + if (isset($answers)) { + if (isset($answers[$group['name']])) { + switch ($group['conditiontype']) { + case '=' : + if ($answers[$group['name']] != $group['value']) { + continue 2; + } + break; + case '!=' : + if ($answers[$group['name']] == $group['value']) { + continue 2; + } + break; + case 'preg_match' : + if (!@preg_match('/' . $group['value'] . '/', + $answers[$group['name']])) { + continue 2; + } + break; + default : + return; + } + } + } else { + return; + } + } + $lastgroup = $group; + if (isset($group['instructions'])) { + $this->_display($group['instructions']); + } + if (!isset($group['param'][0])) { + $group['param'] = array($group['param']); + } + if (isset($group['param'])) { + if (method_exists($script, 'postProcessPrompts')) { + $prompts = $script->postProcessPrompts($group['param'], $group['id']); + if (!is_array($prompts) || count($prompts) != count($group['param'])) { + $this->outputData('postinstall', 'Error: post-install script did not ' . + 'return proper post-processed prompts'); + $prompts = $group['param']; + } else { + foreach ($prompts as $i => $var) { + if (!is_array($var) || !isset($var['prompt']) || + !isset($var['name']) || + ($var['name'] != $group['param'][$i]['name']) || + ($var['type'] != $group['param'][$i]['type'])) { + $this->outputData('postinstall', 'Error: post-install script ' . + 'modified the variables or prompts, severe security risk. ' . + 'Will instead use the defaults from the package.xml'); + $prompts = $group['param']; + } + } + } + $answers = $this->confirmDialog($prompts); + } else { + $answers = $this->confirmDialog($group['param']); + } + } + if ((isset($answers) && $answers) || !isset($group['param'])) { + if (!isset($answers)) { + $answers = array(); + } + array_unshift($completedPhases, $group['id']); + if (!$script->run($answers, $group['id'])) { + $script->run($completedPhases, '_undoOnError'); + return; + } + } else { + $script->run($completedPhases, '_undoOnError'); + return; + } + } + } + } + + /** + * Ask for user input, confirm the answers and continue until the user is satisfied + * @param array an array of arrays, format array('name' => 'paramname', 'prompt' => + * 'text to display', 'type' => 'string'[, default => 'default value']) + * @return array + */ + function confirmDialog($params) + { + $answers = array(); + $prompts = $types = array(); + foreach ($params as $param) { + $prompts[$param['name']] = $param['prompt']; + $types[$param['name']] = $param['type']; + if (isset($param['default'])) { + $answers[$param['name']] = $param['default']; + } else { + $answers[$param['name']] = ''; + } + } + $tried = false; + do { + if ($tried) { + $i = 1; + foreach ($answers as $var => $value) { + if (!strlen($value)) { + echo $this->bold("* Enter an answer for #" . $i . ": ({$prompts[$var]})\n"); + } + $i++; + } + } + $answers = $this->userDialog('', $prompts, $types, $answers); + $tried = true; + } while (is_array($answers) && count(array_filter($answers)) != count($prompts)); + return $answers; + } + // {{{ userDialog(prompt, [type], [default]) + + function userDialog($command, $prompts, $types = array(), $defaults = array(), + $screensize = 20) + { + if (!is_array($prompts)) { + return array(); + } + $testprompts = array_keys($prompts); + $result = $defaults; + if (!defined('STDIN')) { + $fp = fopen('php://stdin', 'r'); + } else { + $fp = STDIN; + } + reset($prompts); + if (count($prompts) == 1 && $types[key($prompts)] == 'yesno') { + foreach ($prompts as $key => $prompt) { + $type = $types[$key]; + $default = @$defaults[$key]; + print "$prompt "; + if ($default) { + print "[$default] "; + } + print ": "; + if (version_compare(phpversion(), '5.0.0', '<')) { + $line = fgets($fp, 2048); + } else { + if (!defined('STDIN')) { + define('STDIN', fopen('php://stdin', 'r')); + } + $line = fgets(STDIN, 2048); + } + if ($default && trim($line) == "") { + $result[$key] = $default; + } else { + $result[$key] = trim($line); + } + } + return $result; + } + while (true) { + $descLength = max(array_map('strlen', $prompts)); + $descFormat = "%-{$descLength}s"; + $last = count($prompts); + + $i = 0; + foreach ($prompts as $n => $var) { + printf("%2d. $descFormat : %s\n", ++$i, $prompts[$n], isset($result[$n]) ? + $result[$n] : null); + } + + print "\n1-$last, 'all', 'abort', or Enter to continue: "; + $tmp = trim(fgets($fp, 1024)); + if (empty($tmp)) { + break; + } + if ($tmp == 'abort') { + return false; + } + if (isset($testprompts[(int)$tmp - 1])) { + $var = $testprompts[(int)$tmp - 1]; + $desc = $prompts[$var]; + $current = @$result[$var]; + print "$desc [$current] : "; + $tmp = trim(fgets($fp, 1024)); + if (trim($tmp) !== '') { + $result[$var] = trim($tmp); + } + } elseif ($tmp == 'all') { + foreach ($prompts as $var => $desc) { + $current = $result[$var]; + print "$desc [$current] : "; + $tmp = trim(fgets($fp, 1024)); + if (trim($tmp) !== '') { + $result[$var] = trim($tmp); + } + } + } + } + if (!defined('STDIN')) { + fclose($fp); + } + return $result; + } + + // }}} + // {{{ userConfirm(prompt, [default]) + + function userConfirm($prompt, $default = 'yes') + { + trigger_error("PEAR_Frontend_CLI::userConfirm not yet converted", E_USER_ERROR); + static $positives = array('y', 'yes', 'on', '1'); + static $negatives = array('n', 'no', 'off', '0'); + print "$this->lp$prompt [$default] : "; + $fp = fopen("php://stdin", "r"); + $line = fgets($fp, 2048); + fclose($fp); + $answer = strtolower(trim($line)); + if (empty($answer)) { + $answer = $default; + } + if (in_array($answer, $positives)) { + return true; + } + if (in_array($answer, $negatives)) { + return false; + } + if (in_array($default, $positives)) { + return true; + } + return false; + } + + // }}} + // {{{ startTable([params]) + + function startTable($params = array()) + { + trigger_error("PEAR_Frontend_CLI::startTable deprecated", E_USER_ERROR); + } + + function _startTable($params = array()) + { + $params['table_data'] = array(); + $params['widest'] = array(); // indexed by column + $params['highest'] = array(); // indexed by row + $params['ncols'] = 0; + $this->params = $params; + } + + // }}} + // {{{ tableRow(columns, [rowparams], [colparams]) + + function tableRow($columns, $rowparams = array(), $colparams = array()) + { + trigger_error("PEAR_Frontend_CLI::tableRow deprecated", E_USER_ERROR); + } + + function _tableRow($columns, $rowparams = array(), $colparams = array()) + { + $highest = 1; + for ($i = 0; $i < sizeof($columns); $i++) { + $col = &$columns[$i]; + if (isset($colparams[$i]) && !empty($colparams[$i]['wrap'])) { + $col = wordwrap($col, $colparams[$i]['wrap'], "\n", 0); + } + if (strpos($col, "\n") !== false) { + $multiline = explode("\n", $col); + $w = 0; + foreach ($multiline as $n => $line) { + if (strlen($line) > $w) { + $w = strlen($line); + } + } + $lines = sizeof($multiline); + } else { + $w = strlen($col); + } + + if (isset($this->params['widest'][$i])) { + if ($w > $this->params['widest'][$i]) { + $this->params['widest'][$i] = $w; + } + } else { + $this->params['widest'][$i] = $w; + } + $tmp = count_chars($columns[$i], 1); + // handle unix, mac and windows formats + $lines = (isset($tmp[10]) ? $tmp[10] : (isset($tmp[13]) ? $tmp[13] : 0)) + 1; + if ($lines > $highest) { + $highest = $lines; + } + } + if (sizeof($columns) > $this->params['ncols']) { + $this->params['ncols'] = sizeof($columns); + } + $new_row = array( + 'data' => $columns, + 'height' => $highest, + 'rowparams' => $rowparams, + 'colparams' => $colparams, + ); + $this->params['table_data'][] = $new_row; + } + + // }}} + // {{{ endTable() + + function endTable() + { + trigger_error("PEAR_Frontend_CLI::endTable deprecated", E_USER_ERROR); + } + + function _endTable() + { + extract($this->params); + if (!empty($caption)) { + $this->_displayHeading($caption); + } + if (count($table_data) == 0) { + return; + } + if (!isset($width)) { + $width = $widest; + } else { + for ($i = 0; $i < $ncols; $i++) { + if (!isset($width[$i])) { + $width[$i] = $widest[$i]; + } + } + } + $border = false; + if (empty($border)) { + $cellstart = ''; + $cellend = ' '; + $rowend = ''; + $padrowend = false; + $borderline = ''; + } else { + $cellstart = '| '; + $cellend = ' '; + $rowend = '|'; + $padrowend = true; + $borderline = '+'; + foreach ($width as $w) { + $borderline .= str_repeat('-', $w + strlen($cellstart) + strlen($cellend) - 1); + $borderline .= '+'; + } + } + if ($borderline) { + $this->_displayLine($borderline); + } + for ($i = 0; $i < sizeof($table_data); $i++) { + extract($table_data[$i]); + if (!is_array($rowparams)) { + $rowparams = array(); + } + if (!is_array($colparams)) { + $colparams = array(); + } + $rowlines = array(); + if ($height > 1) { + for ($c = 0; $c < sizeof($data); $c++) { + $rowlines[$c] = preg_split('/(\r?\n|\r)/', $data[$c]); + if (sizeof($rowlines[$c]) < $height) { + $rowlines[$c] = array_pad($rowlines[$c], $height, ''); + } + } + } else { + for ($c = 0; $c < sizeof($data); $c++) { + $rowlines[$c] = array($data[$c]); + } + } + for ($r = 0; $r < $height; $r++) { + $rowtext = ''; + for ($c = 0; $c < sizeof($data); $c++) { + if (isset($colparams[$c])) { + $attribs = array_merge($rowparams, $colparams); + } else { + $attribs = $rowparams; + } + $w = isset($width[$c]) ? $width[$c] : 0; + //$cell = $data[$c]; + $cell = $rowlines[$c][$r]; + $l = strlen($cell); + if ($l > $w) { + $cell = substr($cell, 0, $w); + } + if (isset($attribs['bold'])) { + $cell = $this->bold($cell); + } + if ($l < $w) { + // not using str_pad here because we may + // add bold escape characters to $cell + $cell .= str_repeat(' ', $w - $l); + } + + $rowtext .= $cellstart . $cell . $cellend; + } + if (!$border) { + $rowtext = rtrim($rowtext); + } + $rowtext .= $rowend; + $this->_displayLine($rowtext); + } + } + if ($borderline) { + $this->_displayLine($borderline); + } + } + + // }}} + // {{{ outputData() + + function outputData($data, $command = '_default') + { + switch ($command) { + case 'channel-info': + foreach ($data as $type => $section) { + if ($type == 'main') { + $section['data'] = array_values($section['data']); + } + $this->outputData($section); + } + break; + case 'install': + case 'upgrade': + case 'upgrade-all': + if (isset($data['release_warnings'])) { + $this->_displayLine(''); + $this->_startTable(array( + 'border' => false, + 'caption' => 'Release Warnings' + )); + $this->_tableRow(array($data['release_warnings']), null, array(1 => array('wrap' => 55))); + $this->_endTable(); + $this->_displayLine(''); + } + $this->_displayLine($data['data']); + break; + case 'search': + $this->_startTable($data); + if (isset($data['headline']) && is_array($data['headline'])) { + $this->_tableRow($data['headline'], array('bold' => true), array(1 => array('wrap' => 55))); + } + + foreach($data['data'] as $category) { + foreach($category as $pkg) { + $this->_tableRow($pkg, null, array(1 => array('wrap' => 55))); + } + }; + $this->_endTable(); + break; + case 'list-all': + if (!isset($data['data'])) { + $this->_displayLine('No packages in channel'); + break; + } + $this->_startTable($data); + if (isset($data['headline']) && is_array($data['headline'])) { + $this->_tableRow($data['headline'], array('bold' => true), array(1 => array('wrap' => 55))); + } + + foreach($data['data'] as $category) { + foreach($category as $pkg) { + unset($pkg[4]); + unset($pkg[5]); + $this->_tableRow($pkg, null, array(1 => array('wrap' => 55))); + } + }; + $this->_endTable(); + break; + case 'config-show': + $data['border'] = false; + $opts = array(0 => array('wrap' => 30), + 1 => array('wrap' => 20), + 2 => array('wrap' => 35)); + $this->_startTable($data); + if (isset($data['headline']) && is_array($data['headline'])) { + $this->_tableRow($data['headline'], + array('bold' => true), + $opts); + } + foreach($data['data'] as $group) { + foreach($group as $value) { + if ($value[2] == '') { + $value[2] = ""; + } + $this->_tableRow($value, null, $opts); + } + } + $this->_endTable(); + break; + case 'remote-info': + $d = $data; + $data = array( + 'caption' => 'Package details:', + 'border' => false, + 'data' => array( + array("Latest", $data['stable']), + array("Installed", $data['installed']), + array("Package", $data['name']), + array("License", $data['license']), + array("Category", $data['category']), + array("Summary", $data['summary']), + array("Description", $data['description']), + ), + ); + if (isset($d['deprecated']) && $d['deprecated']) { + $conf = &PEAR_Config::singleton(); + $reg = $conf->getRegistry(); + $name = $reg->parsedPackageNameToString($d['deprecated'], true); + $data['data'][] = array('Deprecated! use', $name); + } + default: { + if (is_array($data)) { + $this->_startTable($data); + $count = count($data['data'][0]); + if ($count == 2) { + $opts = array(0 => array('wrap' => 25), + 1 => array('wrap' => 48) + ); + } elseif ($count == 3) { + $opts = array(0 => array('wrap' => 30), + 1 => array('wrap' => 20), + 2 => array('wrap' => 35) + ); + } else { + $opts = null; + } + if (isset($data['headline']) && is_array($data['headline'])) { + $this->_tableRow($data['headline'], + array('bold' => true), + $opts); + } + foreach($data['data'] as $row) { + $this->_tableRow($row, null, $opts); + } + $this->_endTable(); + } else { + $this->_displayLine($data); + } + } + } + } + + // }}} + // {{{ log(text) + + + function log($text, $append_crlf = true) + { + if ($append_crlf) { + return $this->_displayLine($text); + } + return $this->_display($text); + } + + + // }}} + // {{{ bold($text) + + function bold($text) + { + if (empty($this->term['bold'])) { + return strtoupper($text); + } + return $this->term['bold'] . $text . $this->term['normal']; + } + + // }}} +} + +?> diff --git a/src/lib/pear/PEAR/PEAR/Frontend/Web.php b/src/lib/pear/PEAR/PEAR/Frontend/Web.php new file mode 100644 index 0000000..b4a8e9d --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Frontend/Web.php @@ -0,0 +1,2361 @@ + | + | Tias Guns | + +----------------------------------------------------------------------+ + + * @category pear + * @package PEAR_Frontend_Web + * @author Christian Dickmann + * @author Tias Guns + * @copyright 1997-2007 The PHP Group + * @license http://www.php.net/license/2_02.txt PHP License 2.02 + * @version CVS: $Id: Web.php,v 1.83 2007/08/07 21:01:29 tias Exp $ + * @link http://pear.php.net/package/PEAR_Frontend_Web + * @since File available since Release 0.1 + */ + +/** + * base class + */ +require_once "PEAR/Frontend.php"; +require_once "PEAR/Remote.php"; +require_once "HTML/Template/IT.php"; + +/** + * PEAR_Frontend_Web is a HTML based Webfrontend for the PEAR Installer + * + * The Webfrontend provides basic functionality of the Installer, such as + * a package list grouped by categories, a search mask, the possibility + * to install/upgrade/uninstall packages and some minor things. + * PEAR_Frontend_Web makes use of the PEAR::HTML_IT Template engine which + * provides the possibillity to skin the Installer. + * + * @category pear + * @package PEAR_Frontend_Web + * @author Christian Dickmann + * @author Tias Guns + * @copyright 1997-2007 The PHP Group + * @license http://www.php.net/license/2_02.txt PHP License 2.02 + * @version CVS: $Id: Web.php,v 1.83 2007/08/07 21:01:29 tias Exp $ + * @link http://pear.php.net/package/PEAR_Frontend_Web + * @since File available since Release 0.1 + */ +class PEAR_Frontend_Web extends PEAR_Frontend +{ + // {{{ properties + + /** + * What type of user interface this frontend is for. + * @var string + * @access public + */ + var $type = 'Web'; + + /** + * Container, where values can be saved temporary + * @var array + */ + var $_data = array(); + + /** + * Used to save output, to display it later + */ + var $_savedOutput = array(); + + /** + * The config object + */ + var $config; + + /** + * List of packages that will not be deletable thourgh the webinterface + */ + var $_no_delete_pkgs = array( + 'pear.php.net/Archive_Tar', + 'pear.php.net/Console_Getopt', + 'pear.php.net/HTML_Template_IT', + 'pear.php.net/PEAR', + 'pear.php.net/PEAR_Frontend_Web', + 'pear.php.net/Structures_Graph', + ); + + /** + * List of channels that will not be deletable thourgh the webinterface + */ + var $_no_delete_chans = array( + 'pear.php.net', + '__uri', + ); + + /** + * How many categories to display on one 'list-all' page + */ + var $_paging_cats = 4; + + /** + * Flag to determine whether to treat all output as information from a post-install script + * @var bool + */ + var $_installScript = false; + + // }}} + // {{{ constructor + + function PEAR_Frontend_Web() + { + parent::PEAR(); + $this->config = &$GLOBALS['_PEAR_Frontend_Web_config']; + } + + function setConfig(&$config) + { + $this->config = &$config; + } + + // }}} + // {{{ _initTemplate() + + /** + * Initialize a TemplateObject + * + * @param string $file filename of the template file + * + * @return object Object of HTML/IT - Template - Class + */ + function _initTemplate($file) + { + // Errors here can not be displayed using the UI + PEAR::staticPushErrorHandling(PEAR_ERROR_DIE); + + $tpl_dir = $this->config->get('data_dir').DIRECTORY_SEPARATOR.'PEAR_Frontend_Web'.DIRECTORY_SEPARATOR.'data'.DIRECTORY_SEPARATOR.'templates'; + if (!file_exists($tpl_dir) || !is_readable($tpl_dir)) { + PEAR::raiseError('Error: the template directory ('.$tpl_dir.') is not a directory, or not readable. Make sure the \'data_dir\' of your config file ('.$this->config->get('data_dir').') points to the correct location !'); + } + $tpl = new HTML_Template_IT($tpl_dir); + $tpl->loadTemplateFile($file); + $tpl->setVariable("InstallerURL", $_SERVER["PHP_SELF"]); + + PEAR::staticPopErrorHandling(); // reset error handling + return $tpl; + } + + // }}} + // {{{ displayError() + + /** + * Display an error page + * + * @param mixed $eobj PEAR_Error object or string containing the error message + * @param string $title (optional) title of the page + * @param string $img (optional) iconhandle for this page + * @param boolean $popup (optional) popuperror or normal? + * + * @access public + * + * @return null does not return anything, but exit the script + */ + function displayError($eobj, $title = 'Error', $img = 'error', $popup = false) + { + $msg = ''; + if (PEAR::isError($eobj)) { + $msg .= trim($eobj->getMessage()); + } else { + $msg .= trim($eobj); + } + + $msg = nl2br($msg."\n"); + + $tplfile = ($popup ? "error.popup.tpl.html" : "error.tpl.html"); + $tpl = $this->_initTemplate($tplfile); + + $tpl->setVariable("Error", $msg); + $command_map = array( + "install" => "list", + "uninstall" => "list", + "upgrade" => "list", + ); + if (isset($_GET['command'])) { + if (isset($command_map[$_GET['command']])) { + $_GET['command'] = $command_map[$_GET['command']]; + } + $tpl->setVariable("param", '?command='.$_GET['command']); + } + + $tpl->show(); + exit; + } + + // }}} + // {{{ displayFatalError() + + /** + * Alias for PEAR_Frontend_Web::displayError() + * + * @see PEAR_Frontend_Web::displayError() + */ + function displayFatalError($eobj, $title = 'Error', $img = 'error') + { + $this->displayError($eobj, $title, $img); + } + + // }}} + // {{{ _outputListChannels() + + /** + * Output the list of channels + */ + function _outputListChannels($data) + { + $tpl = $this->_initTemplate('channel.list.tpl.html'); + + $tpl->setVariable("Caption", $data['caption']); + + if (!isset($data['data'])) { + $data['data'] = array(); + } + + $reg = &$this->config->getRegistry(); + foreach($data['data'] as $row) { + list($channel, $summary) = $row; + $url = sprintf('%s?command=channel-info&chan=%s', + $_SERVER['PHP_SELF'], urlencode($channel)); + $channel_info = sprintf('%s', $url, $channel); + + // detect whether any packages from this channel are installed + $anyinstalled = $reg->listPackages($channel); + $id = 'id="'.$channel.'_href"'; + if (in_array($channel, $this->_no_delete_chans) || (is_array($anyinstalled) && count($anyinstalled))) { + // dont delete + $del = ' '; + } else { + $img = 'delete'; + $url = sprintf('%s?command=channel-delete&chan=%s', + $_SERVER["PHP_SELF"], urlencode($channel)); + $del = sprintf('%s', + $url, $channel, $id, $img); + } + + $tpl->setCurrentBlock("Row"); + $tpl->setVariable("ImgPackage", $_SERVER["PHP_SELF"].'?img=package'); + $tpl->setVariable("UpdateChannelsURL", $_SERVER['PHP_SELF']); + $tpl->setVariable("Delete", $del); + $tpl->setVariable("Channel", $channel_info); + $tpl->setVariable("Summary", nl2br($summary)); + $tpl->parseCurrentBlock(); + } + $tpl->show(); + return true; + } + + // }}} + // {{{ _outputListAll() + + /** + * Output a list of packages, grouped by categories. Uses Paging + * + * @param array $data array containing all data to display the list + * @param boolean $paging (optional) use Paging or not + * + * @return boolean true (yep. i am an optimist) + * + * DEPRECATED BY list-categories + */ + function _outputListAll($data, $paging=true) + { + if (!isset($data['data'])) { + return true; + } + + $tpl = $this->_initTemplate('package.list.tpl.html'); + $tpl->setVariable('Caption', $data['caption']); + + if (!is_array($data['data'])) { + $tpl->show(); + print('

     '.$data['data'].'

    '); + return true; + } + + $command = isset($_GET['command']) ? $_GET['command']:'list-all'; + $mode = isset($_GET['mode'])?$_GET['mode']:''; + $links = array('back' => '', + 'next' => '', + 'current' => '&mode='.$mode, + ); + + if ($paging) { + // Generate Linkinformation to redirect to _this_ page after performing an action + $link_str = '%s'; + + $pageId = isset($_GET['from']) ? $_GET['from'] : 0; + $paging_data = $this->__getData($pageId, $this->_paging_cats, count($data['data']), false); + $data['data'] = array_slice($data['data'], $pageId, $this->_paging_cats); + $from = $paging_data['from']; + $to = $paging_data['to']; + + if ($paging_data['from']>1) { + $links['back'] = sprintf($link_str, $command, $paging_data['prev'], $mode, '<<'); + } + + if ( $paging_data['next']) { + $links['next'] = sprintf($link_str, $command, $paging_data['next'], $mode, '>>'); + } + + $links['current'] = '&from=' . $paging_data['from']; + + $blocks = array('Paging_pre', 'Paging_post'); + foreach ($blocks as $block) { + $tpl->setCurrentBlock($block); + $tpl->setVariable('Prev', $links['back']); + $tpl->setVariable('Next', $links['next']); + $tpl->setVariable('PagerFrom', $from); + $tpl->setVariable('PagerTo', $to); + $tpl->setVariable('PagerCount', $paging_data['numrows']); + $tpl->parseCurrentBlock(); + } + } + + $reg = &$this->config->getRegistry(); + foreach($data['data'] as $category => $packages) { + foreach($packages as $row) { + list($pkgChannel, $pkgName, $pkgVersionLatest, $pkgVersionInstalled, $pkgSummary) = $row; + $parsed = $reg->parsePackageName($pkgName, $pkgChannel); + $pkgChannel = $parsed['channel']; + $pkgName = $parsed['package']; + $pkgFull = sprintf('%s/%s-%s', + $pkgChannel, + $pkgName, + substr($pkgVersionLatest, 0, strpos($pkgVersionLatest, ' '))); + $tpl->setCurrentBlock("Row"); + $tpl->setVariable("ImgPackage", $_SERVER["PHP_SELF"].'?img=package'); + $images = array( + 'install' => 'install', + 'uninstall' => 'uninstall', + 'upgrade' => 'upgrade', + 'info' => 'info', + 'infoExt' => 'extended info', + ); + $urls = array( + 'install' => sprintf('%s?command=install&pkg=%s%s', + $_SERVER["PHP_SELF"], $pkgFull, $links['current']), + 'uninstall' => sprintf('%s?command=uninstall&pkg=%s%s', + $_SERVER["PHP_SELF"], $pkgFull, $links['current']), + 'upgrade' => sprintf('%s?command=upgrade&pkg=%s%s', + $_SERVER["PHP_SELF"], $pkgFull, $links['current']), + 'info' => sprintf('%s?command=info&pkg=%s', + $_SERVER["PHP_SELF"], $pkgFull), + 'remote-info' => sprintf('%s?command=remote-info&pkg=%s', + $_SERVER["PHP_SELF"], $pkgFull), + 'infoExt' => 'http://' . $this->config->get('preferred_mirror') + . '/package/' . $row[0], + ); + + $compare = version_compare($pkgVersionLatest, $pkgVersionInstalled); + $id = 'id="'.$pkgName.'_href"'; + if (!$pkgVersionInstalled || $pkgVersionInstalled == "- no -") { + $inst = sprintf('%s', + $urls['install'], $pkgName, $id, $images['install']); + $del = ''; + $info = sprintf('%s', $urls['remote-info'], $images['info']); + } else if ($compare == 1) { + $inst = sprintf('%s', + $urls['upgrade'], $pkgName, $id, $images['upgrade']); + $del = sprintf('%s', + $urls['uninstall'], $pkgName, $id, $images['uninstall']); + $info = sprintf('%s', $urls['info'], $images['info']); + } else { + $inst = ''; + $del = sprintf('%s', + $urls['uninstall'], $pkgName, $id, $images['uninstall']); + $info = sprintf('%s', $urls['info'], $images['info']); + } + $infoExt = sprintf('%s', $urls['infoExt'], $images['infoExt']); + + if (in_array($pkgChannel.'/'.$pkgName, $this->_no_delete_pkgs)) { + $del = ''; + } + + $tpl->setVariable("Latest", $pkgVersionLatest); + $tpl->setVariable("Installed", $pkgVersionInstalled); + $tpl->setVariable("Install", $inst); + $tpl->setVariable("Delete", $del); + $tpl->setVariable("Info", $info); + $tpl->setVariable("InfoExt", $infoExt); + $tpl->setVariable("Package", $pkgName); + $tpl->setVariable("Channel", $pkgChannel); + $tpl->setVariable("Summary", nl2br($pkgSummary)); + $tpl->parseCurrentBlock(); + } + $tpl->setCurrentBlock("Category"); + $tpl->setVariable("categoryName", $category); + $tpl->setVariable("ImgCategory", $_SERVER["PHP_SELF"].'?img=category'); + $tpl->parseCurrentBlock(); + } + $tpl->show(); + + return true; + } + + // }}} + // {{{ _outputListFiles() + + /** + * Output a list of files of a packagename + * + * @param array $data array containing all files of a package + * + * @return boolean true (yep. i am an optimist) + */ + function _outputListFiles($data) + { + sort($data['data']); + return $this->_outputGenericTableVertical($data['caption'], $data['data']); + } + + // }}} + // {{{ _outputListDocs() + + /** + * Output a list of documentation files of a packagename + * + * @param array $data array containing all documentation files of a package + * + * @return boolean true (yep. i am an optimist) + */ + function _outputListDocs($data) + { + $tpl = $this->_initTemplate('caption.tpl.html'); + $tpl->setVariable('Caption', $data['caption']); + $tpl->show(); + + if (is_array($data['data'])) { + print $this->_getListDocsDiv($data['channel'].'/'.$data['package'], $data['data']); + } else { + print $data['data']; + } + return true; + } + + /** + * Get list of the docs of a package in a HTML div + * + * @param string $pkg full package name (channel/package) + * @param array $files array of all files and there location + * @return string HTML + */ + function _getListDocsDiv($pkg, $files) { + $out = '
      '; + foreach($files as $name => $location) { + $out .= sprintf('
    • %s
    • ', + $_SERVER['PHP_SELF'], + $pkg, + urlencode($name), + $location, + $name); + } + $out .= '
    '; + + return $out; + } + + // }}} + // {{{ _outputDocShow() + + /** + * Output a documentation file of a packagename + * + * @param array $data array containing all documentation files of a packages + * + * @return boolean true (yep. i am an optimist) + */ + function _outputDocShow($data) + { + $tpl = $this->_initTemplate('caption.tpl.html'); + $tpl->setVariable('Caption', $data['caption']); + $tpl->show(); + + print '
    '.nl2br(htmlentities($data['data'])).'
    '; + return true; + } + + // }}} + // {{{ _outputListPackages() + + /** + * Output packagenames (of a channel or category) + * + * @param array $data array containing all information about the packages + * + * @return boolean true (yep. i am an optimist) + */ + function _outputListPackages($data) + { + $ROWSPAN=3; + + $caption = sprintf(' %s (%s)', + $data['channel'], + $_SERVER['PHP_SELF'], + $data['caption'], + count($data['data'])); + + $newdata = null; + if (!is_array($data['data'])) { + $newdata = $data['data']; + } else { + $newdata = array(0 => array()); + $row = 0; + $col = 0; + $rows = ceil(count($data['data'])/$ROWSPAN); + foreach ($data['data'] as $package) { + if ($row == $rows) { // row is full + $row = 0; + $col++; + } + if ($col == 0) { // create clean arrays + $newdata[$row] = array(); + } + $newdata[$row][$col] = sprintf(' %s', + $_SERVER['PHP_SELF'], + $_SERVER['PHP_SELF'], + $package[0], + $package[1], + $package[1]); + $row++; + } + while ($row != $rows) { + $newdata[$row][$col] = ' '; + $row++; + } + } + + return $this->_outputGenericTableHorizontal($caption, $newdata); + } + + // }}} + // {{{ _outputListCategories() + + /** + * Prepare output per channel/category + * + * @param array $data array containing caption, channel and headline + * + * @return $tpl Template Object + */ + function _prepareListCategories($data) + { + $channel = $data['channel']; + + if (!is_array($data['data']) && $channel == '__uri') { + // no categories in __uri, don't show this ugly duck ! + return true; + } + + $tpl = $this->_initTemplate('categories.list.tpl.html'); + + $tpl->setVariable('categoryName', $data['caption']); + $tpl->setVariable('channel', $data['channel']); + + // set headlines + if (isset($data['headline']) && is_array($data['headline'])) { + foreach($data['headline'] as $text) { + $tpl->setCurrentBlock('Headline'); + $tpl->setVariable('Text', $text); + $tpl->parseCurrentBlock(); + } + } else { + $tpl->setCurrentBlock('Headline'); + $tpl->setVariable('Text', $data['data']); + $tpl->parseCurrentBlock(); + unset($data['data']); //clear + } + + // set extra title info + $tpl->setCurrentBlock('Title_info'); + $info = sprintf('List all packagenames of this channel.', + $_SERVER['PHP_SELF'], + $channel + ); + $tpl->setVariable('Text', $info); + $tpl->parseCurrentBlock(); + + $tpl->setCurrentBlock('Title_info'); + $info = sprintf('List all packagenames, by category, of this channel.', + $_SERVER['PHP_SELF'], + $channel + ); + $tpl->setVariable('Text', $info); + $tpl->parseCurrentBlock(); + + return $tpl; + } + + /** + * Output the list of categories of a channel + * + * @param array $data array containing all data to display the list + * + * @return boolean true (yep. i am an optimist) + */ + function _outputListCategories($data) + { + $tpl = $this->_prepareListCategories($data); + + if (isset($data['data']) && is_array($data['data'])) { + foreach($data['data'] as $row) { + @list($channel, $category, $packages) = $row; + + $tpl->setCurrentBlock('Data_row'); + $tpl->setVariable('Text', $channel); + $tpl->parseCurrentBlock(); + + $tpl->setCurrentBlock('Data_row'); + $info = sprintf('%s', + $_SERVER['PHP_SELF'], + $channel, + $category, + $category + ); + $tpl->setVariable('Text', $info); + $tpl->parseCurrentBlock(); + + if (is_array($packages)) { + if (count($packages) == 0) { + $info = '(no packages registered)'; + } else { + $info = sprintf(': ', + $_SERVER['PHP_SELF']); + } + foreach($packages as $i => $package) { + $info .= sprintf('%s', + $_SERVER['PHP_SELF'], + $channel, + $package, + $package + ); + + if ($i+1 != count($packages)) { + $info .= ', '; + } + } + $tpl->setCurrentBlock('Data_row'); + $tpl->setVariable('Text', $info); + $tpl->parseCurrentBlock(); + } + + $tpl->setCurrentBlock('Data'); + $tpl->setVariable('Img', 'category'); + $tpl->parseCurrentBlock(); + } + } + + $tpl->show(); + + return true; + } + + /** + * Output the list of packages of a category of a channel + * + * @param array $data array containing all data to display the list + * + * @return boolean true (yep. i am an optimist) + */ + function _outputListCategory($data) + { + if (isset($data['headline'])) { + // create place for install/uninstall icon: + $summary = array_pop($data['headline']); + $data['headline'][] = ' '; // icon + $data['headline'][] = $summary; // restore summary + } + $tpl = $this->_prepareListCategories($data); + $channel = $data['channel']; + + if (isset($data['data']) && is_array($data['data'])) { + foreach($data['data'] as $row) { + // output summary after install icon + $summary = array_pop($row); + + foreach ($row as $i => $col) { + if ($i == 1) { + $package = $col; + // package name, make URL + $col = $this->_prepPkgName($package, $channel); + } + + $tpl->setCurrentBlock('Data_row'); + $tpl->setVariable('Text', $col); + $tpl->parseCurrentBlock(); + } + + // install or uninstall icon + $tpl->setCurrentBlock('Data_row'); + $tpl->setVariable('Text', $this->_prepIcons($package, $channel)); + $tpl->parseCurrentBlock(); + + // now the summary + $tpl->setCurrentBlock('Data_row'); + $tpl->setVariable('Text', $summary); + $tpl->parseCurrentBlock(); + + // and finish. + $tpl->setCurrentBlock('Data'); + $tpl->setVariable('Img', 'package'); + $tpl->parseCurrentBlock(); + } + } + + $tpl->show(); + + return true; + } + + // }}} + // {{{ _outputList() + + /** + * Output the list of installed packages. + * + * @param array $data array containing all data to display the list + * + * @return boolean true (yep. i am an optimist) + */ + function _outputList($data) + { + $channel = $data['channel']; + + if (!is_array($data['data']) && $channel == '__uri') { + // no packages in __uri, don't show this ugly duck ! + return true; + } + + $tpl = $this->_initTemplate('package.list_nocat.tpl.html'); + + $tpl->setVariable('categoryName', $data['caption']); + //$tpl->setVariable('Border', $data['border']); + + // set headlines + if (isset($data['headline']) && is_array($data['headline'])) { + // overwrite + $data['headline'] = array('Channel', 'Package', 'Local', ' ', 'Summary'); + foreach($data['headline'] as $text) { + $tpl->setCurrentBlock('Headline'); + $tpl->setVariable('Text', $text); + $tpl->parseCurrentBlock(); + } + } else { + $tpl->setCurrentBlock('Headline'); + $tpl->setVariable('Text', $data['data']); + $tpl->parseCurrentBlock(); + unset($data['data']); //clear + } + + if (isset($data['data']) && is_array($data['data'])) { + foreach($data['data'] as $row) { + $package = $row[0].'/'.$row[1]; + $package_name = $row[1]; + $local = sprintf('%s (%s)', $row[2], $row[3]); + + // Channel + $tpl->setCurrentBlock('Data_row'); + $tpl->setVariable('Text', $channel); + $tpl->parseCurrentBlock(); + + // Package + $tpl->setCurrentBlock('Data_row'); + $tpl->setVariable('Text', $this->_prepPkgName($package_name, $channel)); + $tpl->parseCurrentBlock(); + + // Local + $tpl->setCurrentBlock('Data_row'); + $tpl->setVariable('Text', $local); + $tpl->parseCurrentBlock(); + + // Icons (uninstall) + $tpl->setCurrentBlock('Data_row'); + $tpl->setVariable('Text', $this->_prepIcons($package_name, $channel, true)); + $tpl->parseCurrentBlock(); + + // Summary + $tpl->setCurrentBlock('Data_row'); + $reg = $this->config->getRegistry(); + $tpl->setVariable('Text', $reg->packageInfo($package_name, 'summary', $channel)); + $tpl->parseCurrentBlock(); + + // and finish. + $tpl->setCurrentBlock('Data'); + $tpl->setVariable("ImgPackage", $_SERVER["PHP_SELF"].'?img=package'); + $tpl->parseCurrentBlock(); + } + } + + $tpl->show(); + + return true; + } + + // }}} + // {{{ _outputListUpgrades() + + /** + * Output the list of available upgrades packages. + * + * @param array $data array containing all data to display the list + * + * @return boolean true (yep. i am an optimist) + */ + function _outputListUpgrades($data) + { + $tpl = $this->_initTemplate('package.list_nocat.tpl.html'); + + $tpl->setVariable('categoryName', $data['caption']); + //$tpl->setVariable('Border', $data['border']); + + + $channel = $data['channel']; + + // set headlines + if (isset($data['headline']) && is_array($data['headline'])) { + $data['headline'][] = ' '; + foreach($data['headline'] as $text) { + $tpl->setCurrentBlock('Headline'); + $tpl->setVariable('Text', $text); + $tpl->parseCurrentBlock(); + } + } else { + $tpl->setCurrentBlock('Headline'); + $tpl->setVariable('Text', $data['data']); + $tpl->parseCurrentBlock(); + unset($data['data']); //clear + } + + if (isset($data['data']) && is_array($data['data'])) { + foreach($data['data'] as $row) { + $package = $channel.'/'.$row[1]; + $package_name = $row[1]; + + foreach($row as $i => $text) { + if ($i == 1) { + // package name + $text = $this->_prepPkgName($text, $channel); + } + $tpl->setCurrentBlock('Data_row'); + $tpl->setVariable('Text', $text); + $tpl->parseCurrentBlock(); + } + // upgrade link + $tpl->setCurrentBlock('Data_row'); + $img = sprintf('upgrade', $_SERVER["PHP_SELF"]); + $url = sprintf('%s?command=upgrade&pkg=%s', $_SERVER["PHP_SELF"], $package); + $text = sprintf('%s', $url, $package, $package.'_href', $img); + $tpl->setVariable('Text', $text); + $tpl->parseCurrentBlock(); + + // and finish. + $tpl->setCurrentBlock('Data'); + $tpl->setVariable("ImgPackage", $_SERVER["PHP_SELF"].'?img=package'); + + $tpl->parseCurrentBlock(); + } + } + + $tpl->show(); + + return true; + } + + // }}} + + function _getPackageDeps($deps) + { + if (count($deps) == 0) { + return "No dependencies registered.\n"; + } else { + $rel_trans = array( + 'lt' => 'older than %s', + 'le' => 'version %s or older', + 'eq' => 'version %s', + 'ne' => 'any version but %s', + 'gt' => 'newer than %s', + 'ge' => '%s or newer', + ); + $dep_type_desc = array( + 'pkg' => 'PEAR Package', + 'ext' => 'PHP Extension', + 'php' => 'PHP Version', + 'prog' => 'Program', + 'ldlib' => 'Development Library', + 'rtlib' => 'Runtime Library', + 'os' => 'Operating System', + 'websrv' => 'Web Server', + 'sapi' => 'SAPI Backend', + ); + $result = "
    \n"; + foreach($deps as $row) { + + // Print link if it's a PEAR package + if ($row['type'] == 'pkg') { + $package = $row['channel'].'/'.$row['name']; + $row['name'] = sprintf('%s', + $_SERVER['PHP_SELF'], $package, $package); + } + + if (isset($rel_trans[$row['rel']])) { + $rel = sprintf($rel_trans[$row['rel']], $row['version']); + $optional = isset($row['optional']) && $row['optional'] == 'yes'; + $result .= sprintf("%s: %s %s" . $optional, + $dep_type_desc[$row['type']], @$row['name'], $rel); + } else { + $result .= sprintf("%s: %s", $dep_type_desc[$row['type']], $row['name']); + } + $result .= '
    '; + } + $result .= "
    \n"; + } + return $result; + } + + /** + * Output details of one package, info (local) + * + * @param array $data array containing all information about the package + * + * @return boolean true (yep. i am an optimist) + */ + function _outputPackageInfo($data) + { + $data['data'] = $this->htmlentities_recursive($data['data']); + if (!isset($data['raw']['channel'])) { + // package1.xml, channel by default pear + $channel = 'pear.php.net'; + $package_name = $data['raw']['package']; + } else { + $channel = $data['raw']['channel']; + $package_name = $data['raw']['name']; + } + $package = $channel.'/'.$package_name; + + // parse extra options + if (!in_array($package, $this->_no_delete_pkgs)) { + $image = sprintf('uninstall', $_SERVER["PHP_SELF"]); + $output = sprintf( + '%s Uninstall package', + $_SERVER["PHP_SELF"], + $package, + 'onClick="return uninstallPkg(\''.$package.'\');"', + $image); + $data['data'][] = array('Options', $output); + } + + $output = ''; + // More: Local Documentation + require_once('PEAR/Frontend/Web/Docviewer.php'); + if (count(PEAR_Frontend_Web_Docviewer::getDocFiles($package_name, $channel)) !== 0) { + $image = sprintf('manual', $_SERVER["PHP_SELF"]); + $output .= sprintf( + '%s Package Documentation', + $_SERVER["PHP_SELF"], + $package, + $image); + $output .= '
    '; + } + $output .= sprintf( + './.. List Files', + $_SERVER["PHP_SELF"], + $package); + $output .= '
    '; + // More: Extended Package Information + $image = sprintf('extra info', $_SERVER["PHP_SELF"]); + if ($channel == 'pear.php.net' || $channel == 'pecl.php.net') { + $url = 'http://%s/package/%s/download/%s'; + } else { + // the normal default + $url = 'http://%s/index.php?package=%s&release=%s'; + } + $output .= sprintf( + '%s Extended Package Information', + $this->config->get('preferred_mirror', null, $channel), + $package_name, + $data['raw']['version']['release'], + $image); + // More: Developer Documentation && Package Manual + if ($channel == 'pear.php.net') { + $output .= '
    '; + $image = sprintf('manual', $_SERVER["PHP_SELF"]); + $output .= sprintf( + '%s pear.php.net Developer Documentation', + $package_name, + $image); + $output .= '
    '; + $image = sprintf('manual', $_SERVER["PHP_SELF"]); + $output .= sprintf( + '%s pear.php.net Package Manual ', + $image); + } + $data['data'][] = array('More', $output); + + return $this->_outputGenericTableVertical($data['caption'], $data['data']); + } + + /** + * Output details of one package, remote-info + * + * @param array $data array containing all information about the package + * + * @return boolean true (yep. i am an optimist) + */ + function _outputPackageRemoteInfo($data) + { + include_once "PEAR/Downloader.php"; + $tpl = $this->_initTemplate('package.info.tpl.html'); + + $tpl->setVariable("PreferredMirror", $this->config->get('preferred_mirror')); + /* + $dl = &new PEAR_Downloader($this, array(), $this->config); + // don't call private functions + // gives error, not gonna fix, but gonna skip + $info = $dl->_getPackageDownloadUrl(array('package' => $data['name'], + 'channel' => $this->config->get('default_channel'), 'version' => $data['stable'])); + if (isset($info['url'])) { + $tpl->setVariable("DownloadURL", $info['url']); + } else { + $tpl->setVariable("DownloadURL", $_SERVER['PHP_SELF']); + } + */ + $channel = $data['channel']; + $package = $data['channel'].'/'.$data['name']; + $package_full = $data['channel'].'/'.$data['name'].'-'.$data['stable']; + + $tpl->setVariable("Latest", $data['stable']); + $tpl->setVariable("Installed", $data['installed']); + $tpl->setVariable("Package", $data['name']); + $tpl->setVariable("License", $data['license']); + $tpl->setVariable("Category", $data['category']); + $tpl->setVariable("Summary", nl2br($data['summary'])); + $tpl->setVariable("Description", nl2br($data['description'])); + $deps = @$data['releases'][$data['stable']]['deps']; + $tpl->setVariable("Dependencies", $this->_getPackageDeps($deps)); + + $compare = version_compare($data['stable'], $data['installed']); + + $images = array( + 'install' => 'install', + 'uninstall' => 'uninstall', + 'upgrade' => 'upgrade', + ); + + $opt_img = array(); + $opt_text = array(); + if (!$data['installed'] || $data['installed'] == "- no -") { + $opt_img[] = sprintf( + '%s', + $_SERVER["PHP_SELF"], $package_full, + 'onClick="return installPkg(\''.$package_full.'\');"', + $images['install']); + $opt_text[] = sprintf( + 'Install package', + $_SERVER["PHP_SELF"], $package_full, + 'onClick="return installPkg(\''.$package_full.'\');"'); + } else if ($compare == 1) { + $opt_img[] = sprintf( + '%s
    ', + $_SERVER["PHP_SELF"], $package, + 'onClick="return installPkg(\''.$package.'\');"', + $images['install']); + $opt_text[] = sprintf( + 'Upgrade package', + $_SERVER["PHP_SELF"], $package, + 'onClick="return installPkg(\''.$package.'\');"'); + if (!in_array($package, $this->_no_delete_pkgs)) { + $opt_img[] = sprintf( + '%s', + $_SERVER["PHP_SELF"], $package, + 'onClick="return uninstallPkg(\''.$package.'\');"', + $images['uninstall']); + $opt_text[] = sprintf( + 'Uninstall package', + $_SERVER["PHP_SELF"], $package, + 'onClick="return uninstallPkg(\''.$package.'\');"'); + } + } else { + if (!in_array($package, $this->_no_delete_pkgs)) { + $opt_img[] = sprintf( + '%s', + $_SERVER["PHP_SELF"], $package, + 'onClick="return uninstallPkg(\''.$package.'\');"', + $images['uninstall']); + $opt_text[] = sprintf( + 'Uninstall package', + $_SERVER["PHP_SELF"], $package, + 'onClick="return uninstallPkg(\''.$package.'\');"'); + } + } + + if (isset($opt_img[0])) + { + $tpl->setVariable('Opt_Img_1', $opt_img[0]); + $tpl->setVariable('Opt_Text_1', $opt_text[0]); + } + if (isset($opt_img[1])) + { + $tpl->setVariable('Opt_Img_2', $opt_img[1]); + $tpl->setVariable('Opt_Text_2', $opt_text[1]); + } + + $tpl->setVariable('More_Title', 'More'); + // More: Extended Package Information + $image = sprintf('extra info', $_SERVER["PHP_SELF"]); + if ($channel == 'pear.php.net' || $channel == 'pecl.php.net') { + $url = 'http://%s/package/%s/download/%s'; + } else { + // the normal default + $url = 'http://%s/index.php?package=%s&release=%s'; + } + $output = sprintf( + '%s Extended Package Information', + $this->config->get('preferred_mirror', null, $channel), + $data['name'], + $data['stable'], + $image); + // More: Developer Documentation && Package Manual + if ($channel == 'pear.php.net') { + $output .= '
    '; + $image = sprintf('manual', $_SERVER["PHP_SELF"]); + $output .= sprintf( + '%s pear.php.net Developer Documentation', + $data['name'], + $image); + $output .= '
    '; + $image = sprintf('manual', $_SERVER["PHP_SELF"]); + $output .= sprintf( + '%s pear.php.net Package Manual ', + $image); + } + $tpl->setVariable('More_Data', $output); + + $tpl->show(); + return true; + } + + /** + * Output given data in a horizontal generic table: + * table headers in the top row. + * Possibly prepend caption + * + * @var string $caption possible caption for table + * @var array $data array of data items + * @return true optimist etc + */ + function _outputGenericTableHorizontal($caption, $data) { + $tpl = $this->_initTemplate('generic_table_horizontal.tpl.html'); + + if (!is_null($caption) && $caption != '') { + $tpl->setVariable('Caption', $caption); + } + + if (!is_array($data)) { + $tpl->setCurrentBlock('Data_row'); + $tpl->setVariable('Text', nl2br($data)); + $tpl->parseCurrentBlock(); + } else { + foreach ($data as $row) { + foreach ($row as $col) { + $tpl->setCurrentBlock('Row_item'); + $tpl->setVariable('Text', nl2br($col)); + $tpl->parseCurrentBlock(); + } + $tpl->setCurrentBlock('Data_row'); + $tpl->parseCurrentBlock(); + } + } + + $tpl->show(); + return true; + } + + /** + * Output given data in a vertical generic table: + * table headers in the left column. + * Possibly prepend caption + * + * @var string $caption possible caption for table + * @var array $data array of data items + * @return true optimist etc + */ + function _outputGenericTableVertical($caption, $data) { + $tpl = $this->_initTemplate('generic_table_vertical.tpl.html'); + + if (!is_null($caption) && $caption != '') { + $tpl->setVariable("Caption", $caption); + } + + if (!is_array($data)) { + $tpl->setCurrentBlock('Data_row'); + $tpl->setVariable('Title', ' '); + $tpl->setVariable('Text', nl2br($data)); + $tpl->parseCurrentBlock(); + } else { + foreach($data as $row) { + $tpl->setCurrentBlock('Data_row'); + $tpl->setVariable('Title', $row[0]); + $tpl->setVariable('Text', nl2br($row[1])); + $tpl->parseCurrentBlock(); + } + } + + $tpl->show(); + return true; + } + + /** + * Output details of one channel + * + * @param array $data array containing all information about the channel + * + * @return boolean true (yep. i am an optimist) + */ + function _outputChannelInfo($data) + { + $data['main']['data'] = $this->htmlentities_recursive($data['main']['data']); + $channel = $data['main']['data']['server'][1]; + $output = ''; + + if ($channel != '__uri') { + // add 'More' options + $image = sprintf('manual', $_SERVER["PHP_SELF"]); + $output .= sprintf( + '%s List all packagenames of this channel', + $_SERVER["PHP_SELF"], + $channel, + $image); + $output .= '
    '; + $image = sprintf('manual', $_SERVER["PHP_SELF"]); + $output .= sprintf( + '%s List all categories of this channel', + $_SERVER["PHP_SELF"], + $channel, + $image); + $output .= '
    '; + $output .= sprintf( + '%s List all categories, with packagenames, of this channel', + $_SERVER["PHP_SELF"], + $channel, + $image); + $data['main']['data']['more'] = array('More', $output); + } + + return $this->_outputGenericTableVertical($data['main']['caption'], $data['main']['data']); + } + + /** + * Output all kinds of data depending on the command which called this method + * + * @param mixed $data datastructure containing the information to display + * @param string $command (optional) command from which this method was called + * + * @access public + * + * @return mixed highly depends on the command + */ + function outputData($data, $command = '_default') + { + switch ($command) { + case 'config-show': + $prompt = array(); + $default = array(); + foreach($data['data'] as $group) { + foreach($group as $row) { + $prompt[$row[1]] = $row[0]; + $default[$row[1]] = $row[2]; + } + } + $title = 'Configuration :: '.$GLOBALS['pear_user_config']; + $GLOBALS['_PEAR_Frontend_Web_Config'] = + $this->userDialog($command, $prompt, array(), $default, $title, 'config'); + return true; + case 'list-files': + return $this->_outputListFiles($data); + case 'list-docs': + return $this->_outputListDocs($data); + case 'doc-show': + return $this->_outputDocShow($data); + case 'list-all': + return $this->_outputListAll($data); + case 'list-packages': + return $this->_outputListPackages($data); + case 'list-categories': + return $this->_outputListCategories($data); + case 'list-category': + return $this->_outputListCategory($data); + case 'list-upgrades': + return $this->_outputListUpgrades($data); + case 'list': + return $this->_outputList($data); + case 'list-channels': + return $this->_outputListChannels($data); + case 'search': + return $this->_outputListAll($data, false); + case 'remote-info': + return $this->_outputPackageRemoteInfo($data); + case 'package-info': // = 'info' command + return $this->_outputPackageInfo($data); + case 'channel-info': + return $this->_outputChannelInfo($data); + case 'login': + if ($_SERVER["REQUEST_METHOD"] != "POST") + $this->_data[$command] = $data; + return true; + case 'logout': + $this->displayError($data, 'Logout', 'logout'); + break; + case 'install': + case 'upgrade': + case 'upgrade-all': + case 'uninstall': + case 'channel-delete': + case 'package': + case 'channel-discover': + case 'update-channels': + case 'channel-update': + if (is_array($data)) { + print($data['data'].'
    '); + } else { + print($data.'
    '); + } + break; + default: + if ($this->_installScript) { + $this->_savedOutput[] = $_SESSION['_PEAR_Frontend_Web_SavedOutput'][] = $data; + break; + } + if (!is_array($data)) { + // WARNING: channel "pear.php.net" has updated its protocols, use "channel-update pear.php.net" to update: auto-URL + if (preg_match('/use "channel-update ([\S]+)" to update$/', $data, $matches)) { + $channel = $matches[1]; + $url = sprintf('channel-update %s', + $_SERVER['PHP_SELF'], + $channel, + $channel); + $data = preg_replace('/channel-update '.$channel.'/', + $url, + $data); + } + + // pearified/Role_Web has post-install scripts: bold + if (strpos($data, 'has post-install scripts:') !== false) { + $data = '
    '.$data.''; + } + // Use "pear run-scripts pearified/Role_Web" to run + if (preg_match('/^Use "pear run-scripts ([\S]+)"$/', $data, $matches)) { + $pkg = $matches[1]; + $url = sprintf('pear run-scripts %s', + $_SERVER['PHP_SELF'], + $pkg, + $pkg); + $pkg = str_replace('/', '\/', $pkg); + $data = preg_replace('/pear run-scripts '.$pkg.'/', + $url, + $data); + $data = 'Attention ! '.$data.' !'; + } + if (strpos($data, 'DO NOT RUN SCRIPTS FROM UNTRUSTED SOURCES') !== false) { + break; + } + + // TODO: div magic, give it a color and a box etc. + print('
    '.$data.'
    '); + } + } + + return true; + } + + /** + * Output a Table Of Channels: + * Table of contents like thing for all channels + * (using _initTemplate('tableofchannels.tpl.html'); + $tpl->setVariable('Caption', 'All available channels:'); + + $reg = $this->config->getRegistry(); + $channels = $reg->getChannels(); + foreach ($channels as $channel) { + if ($channel->getName() != '__uri') { + $tpl->setCurrentBlock('Data_row'); + $tpl->setVariable('Channel', $channel->getName()); + $tpl->parseCurrentBlock(); + } + } + + $tpl->show(); + } + + /** + * Output the 'upgrade-all' page + */ + function outputUpgradeAll() + { + $tpl = $this->_initTemplate('upgrade_all.tpl.html'); + $tpl->setVariable('UpgradeAllURL', $_SERVER['PHP_SELF']); + $tpl->show(); + } + + /** + * Output the 'search' page + */ + function outputSearch() + { + $reg = $this->config->getRegistry(); + $channels = $reg->getChannels(); + $channel_select = array('all' => 'All channels'); + foreach ($channels as $channel) { + if ($channel->getName() != '__uri') { + $channel_select[$channel->getName()] = $channel->getName(); + } + } + + // search-types to display + $arr = array( + 'name' => array('title' => 'Search package by name (fast)', + 'descr' => 'Package name'), + 'description' => array('title' => 'Search package by name and description (slow)', + 'descr' => 'Search:'), + ); + + foreach($arr as $type => $values) { + $tpl = $this->_initTemplate('search.tpl.html'); + $tpl->setCurrentBlock('Search'); + foreach($channel_select as $key => $value) { + $tpl->setCurrentBlock('Search_channel'); + $tpl->setVariable('Key', $key); + $tpl->setVariable('Value', $value); + $tpl->parseCurrentBlock(); + } + $tpl->setVariable('InstallerURL', $_SERVER['PHP_SELF']); + $tpl->setVariable('Search_type', $type); + $tpl->setVariable('Title', $values['title']); + $tpl->setVariable('Description', $values['descr']); + $tpl->parseCurrentBlock(); + $tpl->show(); + } + } + + /** + * Start session: starts saving output temporary + */ + function startSession() + { + if ($this->_installScript) { + if (!isset($_SESSION['_PEAR_Frontend_Web_SavedOutput'])) { + $_SESSION['_PEAR_Frontend_Web_SavedOutput'] = array(); + } + $this->_savedOutput = $_SESSION['_PEAR_Frontend_Web_SavedOutput']; + } else { + $this->_savedOutput = array(); + } + } + + /** + * End session: output all saved output + */ + function finishOutput($command, $redirectLink = false) + { + unset($_SESSION['_PEAR_Frontend_Web_SavedOutput']); + $tpl = $this->_initTemplate('info.tpl.html'); + foreach($this->_savedOutput as $row) { + $tpl->setCurrentBlock('Infoloop'); + $tpl->setVariable("Info", $row); + $tpl->parseCurrentBlock(); + } + if ($redirectLink) { + $tpl->setCurrentBlock('Infoloop'); + $tpl->setVariable("Info", '' . + $redirectLink['text'] . ''); + $tpl->parseCurrentBlock(); + } + $tpl->show(); + } + + /** + * Run postinstall scripts + * + * @param array An array of PEAR_Task_Postinstallscript objects (or related scripts) + * @param PEAR_PackageFile_v2 + */ + function runPostinstallScripts(&$scripts, $pkg) + { + if (!isset($_SESSION['_PEAR_Frontend_Web_Scripts'])) { + $saves = array(); + foreach ($scripts as $i => $task) { + $saves[$i] = (array) $task->_obj; + } + $_SESSION['_PEAR_Frontend_Web_Scripts'] = $saves; + $nonsession = true; + } else { + $nonsession = false; + } + foreach ($scripts as $i => $task) { + if (!isset($_SESSION['_PEAR_Frontend_Web_ScriptIndex'])) { + $_SESSION['_PEAR_Frontend_Web_ScriptIndex'] = $i; + } + if ($i != $_SESSION['_PEAR_Frontend_Web_ScriptIndex']) { + continue; + } + if (!$nonsession) { + // restore values from previous sessions to the install script + foreach ($_SESSION['_PEAR_Frontend_Web_Scripts'][$i] as $name => $val) { + if ($name{0} == '_') { + // only public variables will be restored + continue; + } + $scripts[$i]->_obj->$name = $val; + } + } + $this->_installScript = true; + $this->startSession(); + $this->runInstallScript($scripts[$i]->_params, $scripts[$i]->_obj, $pkg); + $saves = $scripts; + foreach ($saves as $i => $task) { + $saves[$i] = (array) $task->_obj; + } + $_SESSION['_PEAR_Frontend_Web_Scripts'] = $saves; + unset($_SESSION['_PEAR_Frontend_Web_ScriptIndex']); + } + $this->_installScript = false; + unset($_SESSION['_PEAR_Frontend_Web_Scripts']); + $pkg_full = $pkg->getChannel().'/'.$pkg->getPackage(); + $this->finishOutput($pkg_full . ' Install Script', + array('link' => $_SERVER['PHP_SELF'] . + '?command=info&pkg='.$pkg_full, + 'text' => 'Click for ' .$pkg_full. ' Information')); + } + + /** + * Instruct the runInstallScript method to skip a paramgroup that matches the + * id value passed in. + * + * This method is useful for dynamically configuring which sections of a post-install script + * will be run based on the user's setup, which is very useful for making flexible + * post-install scripts without losing the cross-Frontend ability to retrieve user input + * @param string + */ + function skipParamgroup($id) + { + $_SESSION['_PEAR_Frontend_Web_ScriptSkipSections'][$sectionName] = true; + } + + /** + * @param array $xml contents of postinstallscript tag + * example: Array ( + [paramgroup] => Array ( + [id] => webSetup + [param] => Array ( + [name] => webdirpath + [prompt] => Where should... ? + [default] => '/var/www/htdocs/webpear + [type] => string + ) + ) + ) + * @param object $script post-installation script + * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2 $pkg + * @param string $contents contents of the install script + */ + function runInstallScript($xml, &$script, &$pkg) + { + if (!isset($_SESSION['_PEAR_Frontend_Web_ScriptCompletedPhases'])) { + $_SESSION['_PEAR_Frontend_Web_ScriptCompletedPhases'] = array(); + $_SESSION['_PEAR_Frontend_Web_ScriptSkipSections'] = array(); + } + if (isset($_SESSION['_PEAR_Frontend_Web_ScriptObj'])) { + foreach ($_SESSION['_PEAR_Frontend_Web_ScriptObj'] as $name => $val) { + if ($name{0} == '_') { + // only public variables will be restored + continue; + } + $script->$name = $val; + } + } else { + $_SESSION['_PEAR_Frontend_Web_ScriptObj'] = (array) $script; + } + if (!is_array($xml) || !isset($xml['paramgroup'])) { + $script->run(array(), '_default'); + } else { + if (!isset($xml['paramgroup'][0])) { + $xml['paramgroup'] = array($xml['paramgroup']); + } + foreach ($xml['paramgroup'] as $i => $group) { + if (isset($_SESSION['_PEAR_Frontend_Web_ScriptSkipSections'][$group['id']])) { + continue; + } + if (isset($_SESSION['_PEAR_Frontend_Web_ScriptSection'])) { + if ($i < $_SESSION['_PEAR_Frontend_Web_ScriptSection']) { + $lastgroup = $group; + continue; + } + } + if (isset($_SESSION['_PEAR_Frontend_Web_answers'])) { + $answers = $_SESSION['_PEAR_Frontend_Web_answers']; + } + if (isset($group['name'])) { + if (isset($answers)) { + if (isset($answers[$group['name']])) { + switch ($group['conditiontype']) { + case '=' : + if ($answers[$group['name']] != $group['value']) { + continue 2; + } + break; + case '!=' : + if ($answers[$group['name']] == $group['value']) { + continue 2; + } + break; + case 'preg_match' : + if (!@preg_match('/' . $group['value'] . '/', + $answers[$group['name']])) { + continue 2; + } + break; + default : + $this->_clearScriptSession(); + return; + } + } + } else { + $this->_clearScriptSession(); + return; + } + } + if (!isset($group['param'][0])) { + $group['param'] = array($group['param']); + } + $_SESSION['_PEAR_Frontend_Web_ScriptSection'] = $i; + if (!isset($answers)) { + $answers = array(); + } + if (isset($group['param'])) { + if (method_exists($script, 'postProcessPrompts')) { + $prompts = $script->postProcessPrompts($group['param'], $group['name']); + if (!is_array($prompts) || count($prompts) != count($group['param'])) { + $this->outputData('postinstall', 'Error: post-install script did not ' . + 'return proper post-processed prompts'); + $prompts = $group['param']; + } else { + foreach ($prompts as $i => $var) { + if (!is_array($var) || !isset($var['prompt']) || + !isset($var['name']) || + ($var['name'] != $group['param'][$i]['name']) || + ($var['type'] != $group['param'][$i]['type'])) { + $this->outputData('postinstall', 'Error: post-install script ' . + 'modified the variables or prompts, severe security risk. ' . + 'Will instead use the defaults from the package.xml'); + $prompts = $group['param']; + } + } + } + $answers = array_merge($answers, + $this->confirmDialog($prompts, + $pkg->getChannel().'/'.$pkg->getPackage())); + } else { + $answers = array_merge($answers, + $this->confirmDialog($group['param'], + $pkg->getChannel().'/'.$pkg->getPackage())); + } + } + if ($answers) { + array_unshift($_SESSION['_PEAR_Frontend_Web_ScriptCompletedPhases'], + $group['id']); + if (!$script->run($answers, $group['id'])) { + $script->run($_SESSION['_PEAR_Frontend_Web_ScriptCompletedPhases'], + '_undoOnError'); + $this->_clearScriptSession(); + return; + } + } else { + $script->run(array(), '_undoOnError'); + $this->_clearScriptSession(); + return; + } + $lastgroup = $group; + foreach ($group['param'] as $param) { + // rename the current params to save for future tests + $answers[$group['id'] . '::' . $param['name']] = $answers[$param['name']]; + unset($answers[$param['name']]); + } + // save the script's variables and user answers for the next round + $_SESSION['_PEAR_Frontend_Web_ScriptObj'] = (array) $script; + $_SESSION['_PEAR_Frontend_Web_answers'] = $answers; + $_SERVER['REQUEST_METHOD'] = ''; + } + } + $this->_clearScriptSession(); + } + + function _clearScriptSession() + { + unset($_SESSION['_PEAR_Frontend_Web_ScriptObj']); + unset($_SESSION['_PEAR_Frontend_Web_answers']); + unset($_SESSION['_PEAR_Frontend_Web_ScriptSection']); + unset($_SESSION['_PEAR_Frontend_Web_ScriptCompletedPhases']); + unset($_SESSION['_PEAR_Frontend_Web_ScriptSkipSections']); + } + + /** + * Ask for user input, confirm the answers and continue until the user is satisfied + * + * @param array an array of arrays, format array('name' => 'paramname', 'prompt' => + * 'text to display', 'type' => 'string'[, default => 'default value']) + * @param string Package Name + * @return array|false + */ + function confirmDialog($params, $pkg) + { + $answers = array(); + $prompts = $types = array(); + foreach ($params as $param) { + $prompts[$param['name']] = $param['prompt']; + $types[$param['name']] = $param['type']; + if (isset($param['default'])) { + $answers[$param['name']] = $param['default']; + } else { + $answers[$param['name']] = ''; + } + } + $attempt = 0; + do { + if ($attempt) { + $_SERVER['REQUEST_METHOD'] = ''; + } + $title = !$attempt ? $pkg . ' Install Script Input' : 'Please fill in all values'; + $answers = $this->userDialog('run-scripts', $prompts, $types, $answers, $title, '', + array('pkg' => $pkg)); + if ($answers === false) { + return false; + } + $attempt++; + } while (count(array_filter($answers)) != count($prompts)); + $_SERVER['REQUEST_METHOD'] = 'POST'; + return $answers; + } + + /** + * Useless function that needs to exists for Frontend::setFrontendObject() + * Reported in bug #10656 + */ + function userConfirm($prompt, $default = 'yes') + { + trigger_error("PEAR_Frontend_Web::userConfirm not used", E_USER_ERROR); + } + + /** + * Display a formular and return the given input (yes. needs to requests) + * + * @param string $command command from which this method was called + * @param array $prompts associative array. keys are the inputfieldnames + * and values are the description + * @param array $types (optional) array of inputfieldtypes (text, password, + * etc.) keys have to be the same like in $prompts + * @param array $defaults (optional) array of defaultvalues. again keys have + * to be the same like in $prompts + * @param string $title (optional) title of the page + * @param string $icon (optional) iconhandle for this page + * @param array $extra (optional) extra parameters to put in the form action + * + * @access public + * + * @return array input sended by the user + */ + function userDialog($command, $prompts, $types = array(), $defaults = array(), $title = '', + $icon = '', $extra = array()) + { + // If this is an POST Request, we can return the userinput + if (isset($_GET["command"]) && $_GET["command"]==$command + && $_SERVER["REQUEST_METHOD"] == "POST") { + if (isset($_POST['cancel'])) { + return false; + } + $result = array(); + foreach($prompts as $key => $prompt) { + $result[$key] = $_POST[$key]; + } + return $result; + } + + // If this is an Answer GET Request , we can return the userinput + if (isset($_GET["command"]) && $_GET["command"]==$command + && isset($_GET["userDialogResult"]) && $_GET["userDialogResult"]=='get') { + $result = array(); + foreach($prompts as $key => $prompt) { + $result[$key] = $_GET[$key]; + } + return $result; + } + + // Assign title and icon to some commands + if ($command == 'login') { + $title = 'Login'; + } + + $tpl = $this->_initTemplate('userDialog.tpl.html'); + $tpl->setVariable("Command", $command); + $extrap = ''; + if (count($extra)) { + $extrap = '&'; + foreach ($extra as $name => $value) { + $extrap .= urlencode($name) . '=' . urlencode($value); + } + } + $tpl->setVariable("extra", $extrap); + if ($title != '') { + $tpl->setVariable('Caption', $title); + } else { + $tpl->setVariable('Caption', ucfirst($command)); + } + + if (is_array($prompts)) { + $maxlen = 0; + foreach($prompts as $key => $prompt) { + if (strlen($prompt) > $maxlen) { + $maxlen = strlen($prompt); + } + } + + foreach($prompts as $key => $prompt) { + $tpl->setCurrentBlock("InputField"); + $type = (isset($types[$key]) ? $types[$key] : 'text'); + $default = (isset($defaults[$key]) ? $defaults[$key] : ''); + $tpl->setVariable("prompt", $prompt); + $tpl->setVariable("name", $key); + $tpl->setVariable("default", $default); + $tpl->setVariable("type", $type); + if ($maxlen > 25) { + $tpl->setVariable("width", 'width="275"'); + } + $tpl->parseCurrentBlock(); + } + } + if ($command == 'run-scripts') { + $tpl->setVariable("cancel", ''); + } + $tpl->show(); + exit; + } + + /** + * Write message to log + * + * @param string $text message which has to written to log + * + * @access public + * + * @return boolean true + */ + function log($text) + { + if ($text == '.') { + print($text); + } else { + // filter some log output: + // color some things, drop some others + $styled = false; + + // color:error {Failed to download pear/MDB2_Schema within preferred state "stable", latest release is version 0.7.2, stability "beta", use "channel://pear.php.net/MDB2_Schema-0.7.2" to install} + // make hyperlink the 'channel://...' part + $pattern = 'Failed to download'; + if (substr($text, 0, strlen($pattern)) == $pattern) { + // hyperlink + if (preg_match('/use "channel:\/\/([\S]+)" to install/', $text, $matches)) { + $pkg = $matches[1]; + $url = sprintf('channel://%s', + $_SERVER['PHP_SELF'], + urlencode($pkg), + $pkg, + $pkg); + $text = preg_replace('/channel:\/\/'.addcslashes($pkg, '/').'/', + $url, + $text); + } + // color + $text = '
    '.$text.'
    '; + $styled = true; + } + + // color:warning {chiara/Chiara_Bugs requires package "chiara/Chiara_PEAR_Server" (version >= 0.18.4) || chiara/Chiara_Bugs requires package "channel://savant.pearified.com/Savant3" (version >= 3.0.0)} + // make hyperlink the 'ch/pkg || channel://ch/pkg' part + $pattern = ' requires package "'; + if (!$styled && strpos($text, $pattern) !== false) { + // hyperlink + if (preg_match('/ package "([\S]+)" \(version /', $text, $matches)) { + $pkg = $matches[1]; + if (substr($pkg, 0, strlen('channel://')) == 'channel://') { + $pkg = substr($pkg, strlen('channel://')); + } + $url = sprintf('%s', + $_SERVER['PHP_SELF'], + urlencode($pkg), + $matches[1]); + $text = preg_replace('/'.addcslashes($matches[1], '/').'/', + $url, + $text); + } + // color + $text = '
    '.$text.'
    '; + $styled = true; + } + + // color:warning {Could not download from "http://pear.php.net/get/HTML_QuickForm-3.2.9.tgz", cannot download "pear/html_quickform" (could not open /home/tias/WASP/pear/cvs//temp/download/HTML_QuickForm-3.2.9.tgz for writing)} + $pattern = 'Could not download from'; + if (substr($text, 0, strlen($pattern)) == $pattern) { + // color + $text = '
    '.$text.'
    '; + $styled = true; + } + + // color:error {Error: cannot download "pear/HTML_QuickForm"} + $pattern = 'Error:'; + if (substr($text, 0, strlen($pattern)) == $pattern) { + // color + $text = '
    '.$text.'
    '; + $styled = true; + } + + // and output... + if (!$styled) { + $text = '
    '.$text.'
    '; + } + print($text); + } + + return true; + } + + /** + * Totaly deprecated function + * Needed to install pearified's role_web : / + * Don't use this ! + */ + function bold($text) + { + print(''.$text.'
    '); + } + + /** + * Sends the required file along with Headers and exits the script + * + * @param string $handle handle of the requested file + * @param string $group group of the requested file + * + * @access public + * + * @return null nothing, because script exits + */ + function outputFrontendFile($handle, $group) + { + $handles = array( + "css" => array( + "style" => "style.css", + ), + "js" => array( + "package" => "package.js", + ), + "image" => array( + "logout" => array( + "type" => "gif", + "file" => "logout.gif", + ), + "login" => array( + "type" => "gif", + "file" => "login.gif", + ), + "config" => array( + "type" => "gif", + "file" => "config.gif", + ), + "pkglist" => array( + "type" => "png", + "file" => "pkglist.png", + ), + "pkgsearch" => array( + "type" => "png", + "file" => "pkgsearch.png", + ), + "package" => array( + "type" => "jpeg", + "file" => "package.jpg", + ), + "category" => array( + "type" => "jpeg", + "file" => "category.jpg", + ), + "install" => array( + "type" => "gif", + "file" => "install.gif", + ), + "install_wait" => array( + "type" => "gif", + "file" => "install_wait.gif", + ), + "install_ok" => array( + "type" => "gif", + "file" => "install_ok.gif", + ), + "install_fail" => array( + "type" => "gif", + "file" => "install_fail.gif", + ), + "uninstall" => array( + "type" => "gif", + "file" => "trash.gif", + ), + "info" => array( + "type" => "gif", + "file" => "info.gif", + ), + "infoplus" => array( + "type" => "gif", + "file" => "infoplus.gif", + ), + "pear" => array( + "type" => "gif", + "file" => "pearsmall.gif", + ), + "error" => array( + "type" => "gif", + "file" => "error.gif", + ), + "manual" => array( + "type" => "gif", + "file" => "manual.gif", + ), + "manualplus" => array( + "type" => "gif", + "file" => "manualplus.gif", + ), + "download" => array( + "type" => "gif", + "file" => "download.gif", + ), + ), + ); + + $file = $handles[$group][$handle]; + switch ($group) { + case 'css': + header("Content-Type: text/css"); + readfile($this->config->get('data_dir').'/PEAR_Frontend_Web/data/'.$file); + exit; + case 'image': + $filename = $this->config->get('data_dir').'/PEAR_Frontend_Web/data/images/'.$file['file']; + header("Content-Type: image/".$file['type']); + header("Expires: ".gmdate("D, d M Y H:i:s \G\M\T", time() + 60*60*24*100)); + header("Last-Modified: ".gmdate("D, d M Y H:i:s \G\M\T", filemtime($filename))); + header("Cache-Control: public"); + header("Pragma: "); + readfile($filename); + exit; + case 'js': + header("Content-Type: text/javascript"); + readfile($this->config->get('data_dir').'/PEAR_Frontend_Web/data/'.$file); + exit; + } + } + + /* + * From DB::Pager. Removing Pager dependency. + * @private + */ + function __getData($from, $limit, $numrows, $maxpages = false) + { + if (empty($numrows) || ($numrows < 0)) { + return null; + } + $from = (empty($from)) ? 0 : $from; + + if ($limit <= 0) { + return false; + } + + // Total number of pages + $pages = ceil($numrows/$limit); + $data['numpages'] = $pages; + + // first & last page + $data['firstpage'] = 1; + $data['lastpage'] = $pages; + + // Build pages array + $data['pages'] = array(); + for ($i=1; $i <= $pages; $i++) { + $offset = $limit * ($i-1); + $data['pages'][$i] = $offset; + // $from must point to one page + if ($from == $offset) { + // The current page we are + $data['current'] = $i; + } + } + if (!isset($data['current'])) { + return PEAR::raiseError (null, 'wrong "from" param', null, + null, null, 'DB_Error', true); + } + // Limit number of pages (Goole algorithm) + if ($maxpages) { + $radio = floor($maxpages/2); + $minpage = $data['current'] - $radio; + if ($minpage < 1) { + $minpage = 1; + } + $maxpage = $data['current'] + $radio - 1; + if ($maxpage > $data['numpages']) { + $maxpage = $data['numpages']; + } + foreach (range($minpage, $maxpage) as $page) { + $tmp[$page] = $data['pages'][$page]; + } + $data['pages'] = $tmp; + $data['maxpages'] = $maxpages; + } else { + $data['maxpages'] = null; + } + + // Prev link + $prev = $from - $limit; + $data['prev'] = ($prev >= 0) ? $prev : null; + + // Next link + $next = $from + $limit; + $data['next'] = ($next < $numrows) ? $next : null; + + // Results remaining in next page & Last row to fetch + if ($data['current'] == $pages) { + $data['remain'] = 0; + $data['to'] = $numrows; + } else { + if ($data['current'] == ($pages - 1)) { + $data['remain'] = $numrows - ($limit*($pages-1)); + } else { + $data['remain'] = $limit; + } + $data['to'] = $data['current'] * $limit; + } + $data['numrows'] = $numrows; + $data['from'] = $from + 1; + $data['limit'] = $limit; + + return $data; + } + + // }}} + // {{{ outputBegin($command) + + /** + * Start output, HTML header etc + */ + function outputBegin($command) + { + if (is_null($command)) { + // just the header + $tpl = $this->_initTemplate('header.inc.tpl.html'); + } else { + $tpl = $this->_initTemplate('top.inc.tpl.html'); + $tpl->setCurrentBlock('Search'); + $tpl->parseCurrentBlock(); + + if (!$this->_isProtected()) { + $tpl->setCurrentBlock('NotProtected'); + $tpl->setVariable('Filler', ' '); + $tpl->parseCurrentBlock(); + } + } + + // Initialise begin vars + if ($this->config->get('preferred_mirror') != $this->config->get('default_channel')) { + $mirror = ' (mirror ' .$this->config->get('preferred_mirror') . ')'; + } else { + $mirror = ''; + } + $tpl->setVariable('_default_channel', $this->config->get('default_channel') . $mirror); + $tpl->setVariable('ImgPEAR', $_SERVER['PHP_SELF'].'?img=pear'); + $tpl->setVariable('Title', 'PEAR Package Manager, '.$command); + $tpl->setVariable('Headline', 'Webbased PEAR Package Manager on '.$_SERVER['SERVER_NAME']); + + $tpl->setCurrentBlock(); + + $tpl->show(); + + // submenu's for list, list-upgrades and list-all + if ($command == 'list' || + $command == 'list-upgrades' || + $command == 'list-all' || + $command == 'list-categories' || + $command == 'list-category' || + $command == 'list-packages') { + + $tpl = $this->_initTemplate('package.submenu.tpl.html'); + + $menus = array( + 'list' => 'list installed packages', + 'list-upgrades' => 'list available upgrades', + 'list-packages' => 'list all packagenames', + 'list-categories' => 'list all categories', + ); + $highlight_map = array( + 'list' => 'list', + 'list-upgrades' => 'list-upgrades', + 'list-all' => 'list-categories', + 'list-categories' => 'list-categories', + 'list-category' => 'list-category', + 'list-packages' => 'list-packages', + ); + foreach ($menus as $name => $text) { + $tpl->setCurrentBlock('Submenu'); + $tpl->setVariable("href", $_SERVER["PHP_SELF"].'?command='.$name); + $tpl->setVariable("text", $text); + if ($name == $highlight_map[$command]) { + $tpl->setVariable("class", 'red'); + } else { + $tpl->setVariable("class", 'green'); + } + $tpl->parseCurrentBlock(); + } + $tpl->show(); + } + } + + // }}} + // {{{ outputEnd($command) + + /** + * End output, HTML footer etc + */ + function outputEnd($command) + { + if ($command == 'list') { + // show 'install package' footer + $tpl = $this->_initTemplate('package.manually.tpl.html'); + $tpl->show(); + } + + if (is_null($command)) { + // just the header + $tpl = $this->_initTemplate('footer.inc.tpl.html'); + } else { + $tpl = $this->_initTemplate('bottom.inc.tpl.html'); + } + $tpl->setVariable('Filler', ''); + $tpl->show(); + } + + // }}} + + /** + * Checks if this webfrontend is protected: + * - when the client sais so + * - when having .htaccess authentication + * + * @return boolean + */ + function _isProtected() + { + if (isset($GLOBALS['_PEAR_Frontend_Web_protected']) && + $GLOBALS['_PEAR_Frontend_Web_protected'] === true) { + return true; + } + + if (isset($_SERVER['PHP_AUTH_USER'])) { + return true; + } + + if (!empty($_SERVER['PHP_AUTH_DIGEST'])) { + return true; + } + + return false; + } + + /** + * Prepare packagename for HTML output: + * make it a link + * + * @param $package package name (evt 'chan/pkg') + * @param $channel channel name (when pkg not 'chan/pkg') + */ + function _prepPkgName($package, $channel=null) + { + if (is_null($channel)) { + $full = $package; + } else { + $full = $channel.'/'.$package; + } + + return sprintf('%s', + $_SERVER['PHP_SELF'], + $full, + $package); + } + + /** + * Prepare Icons (install/uninstall) for HTML output: + * make img and url + * + * @param $package package name + * @param $channel channel name + * @param $installed optional when we already know the package is installed + */ + function _prepIcons($package_name, $channel, $installed=false) + { + $reg = $this->config->getRegistry(); + $package = $channel.'/'.$package_name; + + if ($installed || $reg->packageExists($package_name, $channel)) { + if (in_array($package, $this->_no_delete_pkgs)) { + // don't allow to uninstall + $out = ' '; + } else { + $img = sprintf('uninstall', $_SERVER["PHP_SELF"]); + $url = sprintf('%s?command=uninstall&pkg=%s', $_SERVER["PHP_SELF"], $package); + $out = sprintf('%s', $url, $package, $package.'_href', $img); + } + } elseif (!$installed) { + $img = sprintf('install', $_SERVER["PHP_SELF"]); + $url = sprintf('%s?command=install&pkg=%s', $_SERVER["PHP_SELF"], $package); + $out = sprintf('%s', $url, $package, $package.'_href', $img); + } + + return $out; + } + + /** + * apply 'htmlentities' to every value of the array + * array_walk_recursive($array, 'htmlentities') in PHP5 + */ + function htmlentities_recursive($data) { + foreach($data as $key => $value) { + if (is_array($value)) { + $data[$key] = $this->htmlentities_recursive($value); + } else { + $data[$key] = htmlentities($value); + } + } + return $data; + } +} + +?> diff --git a/src/lib/pear/PEAR/PEAR/Frontend/Web/Docviewer.php b/src/lib/pear/PEAR/PEAR/Frontend/Web/Docviewer.php new file mode 100644 index 0000000..630ef7f --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Frontend/Web/Docviewer.php @@ -0,0 +1,151 @@ + + * @copyright 1997-2007 The PHP Group + * @license http://www.php.net/license/2_02.txt PHP License 2.02 + * @version CVS: $Id: Docviewer.php,v 1.2 2007/05/19 15:36:40 tias Exp $ + * @link http://pear.php.net/package/PEAR_Frontend_Web + * @since File available since Release 0.6.2 + */ + +/** + * PEAR_Frontend_Web_Docviewer allows you to view the documentation + * of the installed packages, in the webfrontend. + * + * Most packages provide some documentation files, this class allows + * you to find out which ones, and to display there content. + * + * @category Pear + * @package PEAR_Frontend_Web + * @author Tias Guns + * @copyright 1997-2007 The PHP Group + * @license http://www.php.net/license/2_02.txt PHP License 2.02 + * @version CVS: $Id: Docviewer.php,v 1.2 2007/05/19 15:36:40 tias Exp $ + * @link http://pear.php.net/package/PEAR_Frontend_Web + * @since File available since Release 0.6.2 + */ +class PEAR_Frontend_Web_Docviewer +{ + + /** + * The config object + */ + var $config; + + /** + * User Interface object, for all interaction with the user. + * @var object + */ + var $ui; + + /** + * Create instance and set config to global frontweb config + * + * @param $ui User Interface object + */ + function PEAR_Frontend_Web_Docviewer(&$ui) + { + $this->config = &$GLOBALS['_PEAR_Frontend_Web_config']; + $this->ui = &$ui; + } + + /** + * Set the config, manually + * + * @param $config config object + */ + function setConfig(&$config) + { + $this->config = &$config; + } + + /** + * Get the files with role 'doc' of the given package + * + * Can be called as static method + * + * @param string $package package name + * @param string $channel + * @return array('name' => 'installed_as', ... + */ + function getDocFiles($package_name, $channel) + { + $reg = $this->config->getRegistry(); + $files_all = $reg->packageInfo($package_name, 'filelist', $channel); + $files_doc = array(); + foreach($files_all as $name => $file) { + if ($file['role'] == 'doc') { + $files_doc[$name] = $file['installed_as']; + } + } + return $files_doc; + } + + /** + * Output in HTML the list of docs of given package + * + * @param string $package package name + * @param string $channel + * @return true (uses the User Interface object) + */ + function outputListDocs($package_name, $channel) + { + $command = 'list-docs'; + $data = array( + 'caption' => 'Package '.$channel.'/'.$package_name.', Documentation files:', + 'border' => true, + 'headline' => array('File', 'Location'), + 'channel' => $channel, + 'package' => $package_name, + ); + + $files = $this->getDocFiles($package_name, $channel); + if (count($files) == 0) { + $data['data'] = '(no documentation available)'; + } else { + foreach ($files as $name => $location) { + $data['data'][$name] = $location; + } + } + $this->ui->outputData($data, $command); + + return true; + } + + /** + * Output in HTML the documentation file of given package + * + * @param string $package package name + * @param string $channel + * @param string $file + * @return true (uses the User Interface object) + */ + function outputDocShow($package_name, $channel, $file) + { + $this->outputListDocs($package_name, $channel); + + $command = 'doc-show'; + $data = array( + 'caption' => $channel.'/'.$package_name.' :: '.$file.':', + 'border' => true, + 'channel' => $channel, + 'package' => $package_name, + ); + + $files = $this->getDocFiles($package_name, $channel); + if (!isset($files[$file])) { + $data['data'] = 'File '.$file.' is not part of the documentation of this package.'; + } else { + $data['data'] = file_get_contents($files[$file]); + //$data['data'] = $file; + } + $this->ui->outputData($data, $command); + + return true; + } + +} + +?> diff --git a/src/lib/pear/PEAR/PEAR/Installer.php b/src/lib/pear/PEAR/PEAR/Installer.php new file mode 100644 index 0000000..d3f3162 --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Installer.php @@ -0,0 +1,1723 @@ + + * @author Tomas V.V. Cox + * @author Martin Jansen + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: Installer.php,v 1.253 2008/05/13 22:46:07 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 0.1 + */ + +/** + * Used for installation groups in package.xml 2.0 and platform exceptions + */ +require_once 'OS/Guess.php'; +require_once 'PEAR/Downloader.php'; + +define('PEAR_INSTALLER_NOBINARY', -240); +/** + * Administration class used to install PEAR packages and maintain the + * installed package database. + * + * @category pear + * @package PEAR + * @author Stig Bakken + * @author Tomas V.V. Cox + * @author Martin Jansen + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 0.1 + */ +class PEAR_Installer extends PEAR_Downloader +{ + // {{{ properties + + /** name of the package directory, for example Foo-1.0 + * @var string + */ + var $pkgdir; + + /** directory where PHP code files go + * @var string + */ + var $phpdir; + + /** directory where PHP extension files go + * @var string + */ + var $extdir; + + /** directory where documentation goes + * @var string + */ + var $docdir; + + /** installation root directory (ala PHP's INSTALL_ROOT or + * automake's DESTDIR + * @var string + */ + var $installroot = ''; + + /** debug level + * @var int + */ + var $debug = 1; + + /** temporary directory + * @var string + */ + var $tmpdir; + + /** + * PEAR_Registry object used by the installer + * @var PEAR_Registry + */ + var $registry; + + /** + * array of PEAR_Downloader_Packages + * @var array + */ + var $_downloadedPackages; + + /** List of file transactions queued for an install/upgrade/uninstall. + * + * Format: + * array( + * 0 => array("rename => array("from-file", "to-file")), + * 1 => array("delete" => array("file-to-delete")), + * ... + * ) + * + * @var array + */ + var $file_operations = array(); + + // }}} + + // {{{ constructor + + /** + * PEAR_Installer constructor. + * + * @param object $ui user interface object (instance of PEAR_Frontend_*) + * + * @access public + */ + function PEAR_Installer(&$ui) + { + parent::PEAR_Common(); + $this->setFrontendObject($ui); + $this->debug = $this->config->get('verbose'); + } + + function setOptions($options) + { + $this->_options = $options; + } + + function setConfig(&$config) + { + $this->config = &$config; + $this->_registry = &$config->getRegistry(); + } + + // }}} + + function _removeBackups($files) + { + foreach ($files as $path) { + $this->addFileOperation('removebackup', array($path)); + } + } + + // {{{ _deletePackageFiles() + + /** + * Delete a package's installed files, does not remove empty directories. + * + * @param string package name + * @param string channel name + * @param bool if true, then files are backed up first + * @return bool TRUE on success, or a PEAR error on failure + * @access protected + */ + function _deletePackageFiles($package, $channel = false, $backup = false) + { + if (!$channel) { + $channel = 'pear.php.net'; + } + if (!strlen($package)) { + return $this->raiseError("No package to uninstall given"); + } + if (strtolower($package) == 'pear' && $channel == 'pear.php.net') { + // to avoid race conditions, include all possible needed files + require_once 'PEAR/Task/Common.php'; + require_once 'PEAR/Task/Replace.php'; + require_once 'PEAR/Task/Unixeol.php'; + require_once 'PEAR/Task/Windowseol.php'; + require_once 'PEAR/PackageFile/v1.php'; + require_once 'PEAR/PackageFile/v2.php'; + require_once 'PEAR/PackageFile/Generator/v1.php'; + require_once 'PEAR/PackageFile/Generator/v2.php'; + } + $filelist = $this->_registry->packageInfo($package, 'filelist', $channel); + if ($filelist == null) { + return $this->raiseError("$channel/$package not installed"); + } + $ret = array(); + foreach ($filelist as $file => $props) { + if (empty($props['installed_as'])) { + continue; + } + $path = $props['installed_as']; + if ($backup) { + $this->addFileOperation('backup', array($path)); + $ret[] = $path; + } + $this->addFileOperation('delete', array($path)); + } + if ($backup) { + return $ret; + } + return true; + } + + // }}} + // {{{ _installFile() + + /** + * @param string filename + * @param array attributes from tag in package.xml + * @param string path to install the file in + * @param array options from command-line + * @access private + */ + function _installFile($file, $atts, $tmp_path, $options) + { + // {{{ return if this file is meant for another platform + static $os; + if (!isset($this->_registry)) { + $this->_registry = &$this->config->getRegistry(); + } + if (isset($atts['platform'])) { + if (empty($os)) { + $os = new OS_Guess(); + } + if (strlen($atts['platform']) && $atts['platform']{0} == '!') { + $negate = true; + $platform = substr($atts['platform'], 1); + } else { + $negate = false; + $platform = $atts['platform']; + } + if ((bool) $os->matchSignature($platform) === $negate) { + $this->log(3, "skipped $file (meant for $atts[platform], we are ".$os->getSignature().")"); + return PEAR_INSTALLER_SKIPPED; + } + } + // }}} + + $channel = $this->pkginfo->getChannel(); + // {{{ assemble the destination paths + switch ($atts['role']) { + case 'src': + case 'extsrc': + $this->source_files++; + return; + case 'doc': + case 'data': + case 'test': + $dest_dir = $this->config->get($atts['role'] . '_dir', null, $channel) . + DIRECTORY_SEPARATOR . $this->pkginfo->getPackage(); + unset($atts['baseinstalldir']); + break; + case 'ext': + case 'php': + $dest_dir = $this->config->get($atts['role'] . '_dir', null, $channel); + break; + case 'script': + $dest_dir = $this->config->get('bin_dir', null, $channel); + break; + default: + return $this->raiseError("Invalid role `$atts[role]' for file $file"); + } + $save_destdir = $dest_dir; + if (!empty($atts['baseinstalldir'])) { + $dest_dir .= DIRECTORY_SEPARATOR . $atts['baseinstalldir']; + } + if (dirname($file) != '.' && empty($atts['install-as'])) { + $dest_dir .= DIRECTORY_SEPARATOR . dirname($file); + } + if (empty($atts['install-as'])) { + $dest_file = $dest_dir . DIRECTORY_SEPARATOR . basename($file); + } else { + $dest_file = $dest_dir . DIRECTORY_SEPARATOR . $atts['install-as']; + } + $orig_file = $tmp_path . DIRECTORY_SEPARATOR . $file; + + // Clean up the DIRECTORY_SEPARATOR mess + $ds2 = DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR; + list($dest_file, $orig_file) = preg_replace(array('!\\\\+!', '!/!', "!$ds2+!"), + array(DIRECTORY_SEPARATOR, + DIRECTORY_SEPARATOR, + DIRECTORY_SEPARATOR), + array($dest_file, $orig_file)); + $final_dest_file = $installed_as = $dest_file; + if (isset($this->_options['packagingroot'])) { + $installedas_dest_dir = dirname($final_dest_file); + $installedas_dest_file = $dest_dir . DIRECTORY_SEPARATOR . '.tmp' . basename($final_dest_file); + $final_dest_file = $this->_prependPath($final_dest_file, + $this->_options['packagingroot']); + } else { + $installedas_dest_dir = dirname($final_dest_file); + $installedas_dest_file = $installedas_dest_dir . DIRECTORY_SEPARATOR . '.tmp' . basename($final_dest_file); + } + $dest_dir = dirname($final_dest_file); + $dest_file = $dest_dir . DIRECTORY_SEPARATOR . '.tmp' . basename($final_dest_file); + if (preg_match('~/\.\.(/|\\z)|^\.\./~', str_replace('\\', '/', $dest_file))) { + return $this->raiseError("SECURITY ERROR: file $file (installed to $dest_file) contains parent directory reference ..", PEAR_INSTALLER_FAILED); + } + // }}} + + if (empty($this->_options['register-only']) && + (!file_exists($dest_dir) || !is_dir($dest_dir))) { + if (!$this->mkDirHier($dest_dir)) { + return $this->raiseError("failed to mkdir $dest_dir", + PEAR_INSTALLER_FAILED); + } + $this->log(3, "+ mkdir $dest_dir"); + } + // pretty much nothing happens if we are only registering the install + if (empty($this->_options['register-only'])) { + if (empty($atts['replacements'])) { + if (!file_exists($orig_file)) { + return $this->raiseError("file $orig_file does not exist", + PEAR_INSTALLER_FAILED); + } + if (!@copy($orig_file, $dest_file)) { + return $this->raiseError("failed to write $dest_file: $php_errormsg", + PEAR_INSTALLER_FAILED); + } + $this->log(3, "+ cp $orig_file $dest_file"); + if (isset($atts['md5sum'])) { + $md5sum = md5_file($dest_file); + } + } else { + // {{{ file with replacements + if (!file_exists($orig_file)) { + return $this->raiseError("file does not exist", + PEAR_INSTALLER_FAILED); + } + $contents = file_get_contents($orig_file); + if ($contents === false) { + $contents = ''; + } + if (isset($atts['md5sum'])) { + $md5sum = md5($contents); + } + $subst_from = $subst_to = array(); + foreach ($atts['replacements'] as $a) { + $to = ''; + if ($a['type'] == 'php-const') { + if (preg_match('/^[a-z0-9_]+\\z/i', $a['to'])) { + eval("\$to = $a[to];"); + } else { + if (!isset($options['soft'])) { + $this->log(0, "invalid php-const replacement: $a[to]"); + } + continue; + } + } elseif ($a['type'] == 'pear-config') { + if ($a['to'] == 'master_server') { + $chan = $this->_registry->getChannel($channel); + if (!PEAR::isError($chan)) { + $to = $chan->getServer(); + } else { + $to = $this->config->get($a['to'], null, $channel); + } + } else { + $to = $this->config->get($a['to'], null, $channel); + } + if (is_null($to)) { + if (!isset($options['soft'])) { + $this->log(0, "invalid pear-config replacement: $a[to]"); + } + continue; + } + } elseif ($a['type'] == 'package-info') { + if ($t = $this->pkginfo->packageInfo($a['to'])) { + $to = $t; + } else { + if (!isset($options['soft'])) { + $this->log(0, "invalid package-info replacement: $a[to]"); + } + continue; + } + } + if (!is_null($to)) { + $subst_from[] = $a['from']; + $subst_to[] = $to; + } + } + $this->log(3, "doing ".sizeof($subst_from)." substitution(s) for $final_dest_file"); + if (sizeof($subst_from)) { + $contents = str_replace($subst_from, $subst_to, $contents); + } + $wp = @fopen($dest_file, "wb"); + if (!is_resource($wp)) { + return $this->raiseError("failed to create $dest_file: $php_errormsg", + PEAR_INSTALLER_FAILED); + } + if (@fwrite($wp, $contents) === false) { + return $this->raiseError("failed writing to $dest_file: $php_errormsg", + PEAR_INSTALLER_FAILED); + } + fclose($wp); + // }}} + } + // {{{ check the md5 + if (isset($md5sum)) { + if (strtolower($md5sum) === strtolower($atts['md5sum'])) { + $this->log(2, "md5sum ok: $final_dest_file"); + } else { + if (empty($options['force'])) { + // delete the file + if (file_exists($dest_file)) { + unlink($dest_file); + } + if (!isset($options['ignore-errors'])) { + return $this->raiseError("bad md5sum for file $final_dest_file", + PEAR_INSTALLER_FAILED); + } else { + if (!isset($options['soft'])) { + $this->log(0, "warning : bad md5sum for file $final_dest_file"); + } + } + } else { + if (!isset($options['soft'])) { + $this->log(0, "warning : bad md5sum for file $final_dest_file"); + } + } + } + } + // }}} + // {{{ set file permissions + if (!OS_WINDOWS) { + if ($atts['role'] == 'script') { + $mode = 0777 & ~(int)octdec($this->config->get('umask')); + $this->log(3, "+ chmod +x $dest_file"); + } else { + $mode = 0666 & ~(int)octdec($this->config->get('umask')); + } + if ($atts['role'] != 'src') { + $this->addFileOperation("chmod", array($mode, $dest_file)); + if (!@chmod($dest_file, $mode)) { + if (!isset($options['soft'])) { + $this->log(0, "failed to change mode of $dest_file: $php_errormsg"); + } + } + } + } + // }}} + if ($atts['role'] == 'src') { + rename($dest_file, $final_dest_file); + $this->log(2, "renamed source file $dest_file to $final_dest_file"); + } else { + $this->addFileOperation("rename", array($dest_file, $final_dest_file, + $atts['role'] == 'ext')); + } + } + // Store the full path where the file was installed for easy unistall + if ($atts['role'] != 'script') { + $loc = $this->config->get($atts['role'] . '_dir'); + } else { + $loc = $this->config->get('bin_dir'); + } + if ($atts['role'] != 'src') { + $this->addFileOperation("installed_as", array($file, $installed_as, + $loc, + dirname(substr($installedas_dest_file, strlen($loc))))); + } + + //$this->log(2, "installed: $dest_file"); + return PEAR_INSTALLER_OK; + } + + // }}} + // {{{ _installFile2() + + /** + * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2 + * @param string filename + * @param array attributes from tag in package.xml + * @param string path to install the file in + * @param array options from command-line + * @access private + */ + function _installFile2(&$pkg, $file, &$real_atts, $tmp_path, $options) + { + $atts = $real_atts; + if (!isset($this->_registry)) { + $this->_registry = &$this->config->getRegistry(); + } + + $channel = $pkg->getChannel(); + // {{{ assemble the destination paths + if (!in_array($atts['attribs']['role'], + PEAR_Installer_Role::getValidRoles($pkg->getPackageType()))) { + return $this->raiseError('Invalid role `' . $atts['attribs']['role'] . + "' for file $file"); + } + $role = &PEAR_Installer_Role::factory($pkg, $atts['attribs']['role'], $this->config); + $err = $role->setup($this, $pkg, $atts['attribs'], $file); + if (PEAR::isError($err)) { + return $err; + } + if (!$role->isInstallable()) { + return; + } + $info = $role->processInstallation($pkg, $atts['attribs'], $file, $tmp_path); + if (PEAR::isError($info)) { + return $info; + } else { + list($save_destdir, $dest_dir, $dest_file, $orig_file) = $info; + } + if (preg_match('~/\.\.(/|\\z)|^\.\./~', str_replace('\\', '/', $dest_file))) { + return $this->raiseError("SECURITY ERROR: file $file (installed to $dest_file) contains parent directory reference ..", PEAR_INSTALLER_FAILED); + } + $final_dest_file = $installed_as = $dest_file; + if (isset($this->_options['packagingroot'])) { + $final_dest_file = $this->_prependPath($final_dest_file, + $this->_options['packagingroot']); + } + $dest_dir = dirname($final_dest_file); + $dest_file = $dest_dir . DIRECTORY_SEPARATOR . '.tmp' . basename($final_dest_file); + // }}} + + if (empty($this->_options['register-only'])) { + if (!file_exists($dest_dir) || !is_dir($dest_dir)) { + if (!$this->mkDirHier($dest_dir)) { + return $this->raiseError("failed to mkdir $dest_dir", + PEAR_INSTALLER_FAILED); + } + $this->log(3, "+ mkdir $dest_dir"); + } + } + $attribs = $atts['attribs']; + unset($atts['attribs']); + // pretty much nothing happens if we are only registering the install + if (empty($this->_options['register-only'])) { + if (!count($atts)) { // no tasks + if (!file_exists($orig_file)) { + return $this->raiseError("file $orig_file does not exist", + PEAR_INSTALLER_FAILED); + } + if (!@copy($orig_file, $dest_file)) { + return $this->raiseError("failed to write $dest_file: $php_errormsg", + PEAR_INSTALLER_FAILED); + } + $this->log(3, "+ cp $orig_file $dest_file"); + if (isset($attribs['md5sum'])) { + $md5sum = md5_file($dest_file); + } + } else { // file with tasks + if (!file_exists($orig_file)) { + return $this->raiseError("file $orig_file does not exist", + PEAR_INSTALLER_FAILED); + } + $contents = file_get_contents($orig_file); + if ($contents === false) { + $contents = ''; + } + if (isset($attribs['md5sum'])) { + $md5sum = md5($contents); + } + foreach ($atts as $tag => $raw) { + $tag = str_replace(array($pkg->getTasksNs() . ':', '-'), + array('', '_'), $tag); + $task = "PEAR_Task_$tag"; + $task = &new $task($this->config, $this, PEAR_TASK_INSTALL); + if (!$task->isScript()) { // scripts are only handled after installation + $task->init($raw, $attribs, $pkg->getLastInstalledVersion()); + $res = $task->startSession($pkg, $contents, $final_dest_file); + if ($res === false) { + continue; // skip this file + } + if (PEAR::isError($res)) { + return $res; + } + $contents = $res; // save changes + } + $wp = @fopen($dest_file, "wb"); + if (!is_resource($wp)) { + return $this->raiseError("failed to create $dest_file: $php_errormsg", + PEAR_INSTALLER_FAILED); + } + if (fwrite($wp, $contents) === false) { + return $this->raiseError("failed writing to $dest_file: $php_errormsg", + PEAR_INSTALLER_FAILED); + } + fclose($wp); + } + } + // {{{ check the md5 + if (isset($md5sum)) { + if (strtolower($md5sum) === strtolower($attribs['md5sum'])) { + $this->log(2, "md5sum ok: $final_dest_file"); + } else { + if (empty($options['force'])) { + // delete the file + if (file_exists($dest_file)) { + unlink($dest_file); + } + if (!isset($options['ignore-errors'])) { + return $this->raiseError("bad md5sum for file $final_dest_file", + PEAR_INSTALLER_FAILED); + } else { + if (!isset($options['soft'])) { + $this->log(0, "warning : bad md5sum for file $final_dest_file"); + } + } + } else { + if (!isset($options['soft'])) { + $this->log(0, "warning : bad md5sum for file $final_dest_file"); + } + } + } + } else { + $real_atts['attribs']['md5sum'] = md5_file($dest_file); + } + // }}} + // {{{ set file permissions + if (!OS_WINDOWS) { + if ($role->isExecutable()) { + $mode = 0777 & ~(int)octdec($this->config->get('umask')); + $this->log(3, "+ chmod +x $dest_file"); + } else { + $mode = 0666 & ~(int)octdec($this->config->get('umask')); + } + if ($attribs['role'] != 'src') { + $this->addFileOperation("chmod", array($mode, $dest_file)); + if (!@chmod($dest_file, $mode)) { + if (!isset($options['soft'])) { + $this->log(0, "failed to change mode of $dest_file: $php_errormsg"); + } + } + } + } + // }}} + if ($attribs['role'] == 'src') { + rename($dest_file, $final_dest_file); + $this->log(2, "renamed source file $dest_file to $final_dest_file"); + } else { + $this->addFileOperation("rename", array($dest_file, $final_dest_file, $role->isExtension())); + } + } + // Store the full path where the file was installed for easy uninstall + if ($attribs['role'] != 'src') { + $loc = $this->config->get($role->getLocationConfig(), null, $channel); + $this->addFileOperation("installed_as", array($file, $installed_as, + $loc, + dirname(substr($installed_as, strlen($loc))))); + } + + //$this->log(2, "installed: $dest_file"); + return PEAR_INSTALLER_OK; + } + + // }}} + // {{{ addFileOperation() + + /** + * Add a file operation to the current file transaction. + * + * @see startFileTransaction() + * @param string $type This can be one of: + * - rename: rename a file ($data has 3 values) + * - backup: backup an existing file ($data has 1 value) + * - removebackup: clean up backups created during install ($data has 1 value) + * - chmod: change permissions on a file ($data has 2 values) + * - delete: delete a file ($data has 1 value) + * - rmdir: delete a directory if empty ($data has 1 value) + * - installed_as: mark a file as installed ($data has 4 values). + * @param array $data For all file operations, this array must contain the + * full path to the file or directory that is being operated on. For + * the rename command, the first parameter must be the file to rename, + * the second its new name, the third whether this is a PHP extension. + * + * The installed_as operation contains 4 elements in this order: + * 1. Filename as listed in the filelist element from package.xml + * 2. Full path to the installed file + * 3. Full path from the php_dir configuration variable used in this + * installation + * 4. Relative path from the php_dir that this file is installed in + */ + function addFileOperation($type, $data) + { + if (!is_array($data)) { + return $this->raiseError('Internal Error: $data in addFileOperation' + . ' must be an array, was ' . gettype($data)); + } + if ($type == 'chmod') { + $octmode = decoct($data[0]); + $this->log(3, "adding to transaction: $type $octmode $data[1]"); + } else { + $this->log(3, "adding to transaction: $type " . implode(" ", $data)); + } + $this->file_operations[] = array($type, $data); + } + + // }}} + // {{{ startFileTransaction() + + function startFileTransaction($rollback_in_case = false) + { + if (count($this->file_operations) && $rollback_in_case) { + $this->rollbackFileTransaction(); + } + $this->file_operations = array(); + } + + // }}} + // {{{ commitFileTransaction() + + function commitFileTransaction() + { + $n = count($this->file_operations); + $this->log(2, "about to commit $n file operations"); + // {{{ first, check permissions and such manually + $errors = array(); + foreach ($this->file_operations as $tr) { + list($type, $data) = $tr; + switch ($type) { + case 'rename': + if (!file_exists($data[0])) { + $errors[] = "cannot rename file $data[0], doesn't exist"; + } + // check that dest dir. is writable + if (!is_writable(dirname($data[1]))) { + $errors[] = "permission denied ($type): $data[1]"; + } + break; + case 'chmod': + // check that file is writable + if (!is_writable($data[1])) { + $errors[] = "permission denied ($type): $data[1] " . decoct($data[0]); + } + break; + case 'delete': + if (!file_exists($data[0])) { + $this->log(2, "warning: file $data[0] doesn't exist, can't be deleted"); + } + // check that directory is writable + if (file_exists($data[0])) { + if (!is_writable(dirname($data[0]))) { + $errors[] = "permission denied ($type): $data[0]"; + } else { + // make sure the file to be deleted can be opened for writing + $fp = false; + if (!is_dir($data[0]) && + (!is_writable($data[0]) || !($fp = @fopen($data[0], 'a')))) { + $errors[] = "permission denied ($type): $data[0]"; + } elseif ($fp) { + fclose($fp); + } + } + } + break; + } + + } + // }}} + $m = sizeof($errors); + if ($m > 0) { + foreach ($errors as $error) { + if (!isset($this->_options['soft'])) { + $this->log(1, $error); + } + } + if (!isset($this->_options['ignore-errors'])) { + return false; + } + } + $this->_dirtree = array(); + // {{{ really commit the transaction + foreach ($this->file_operations as $i => $tr) { + if (!$tr) { + // support removal of non-existing backups + continue; + } + list($type, $data) = $tr; + switch ($type) { + case 'backup': + if (!file_exists($data[0])) { + $this->file_operations[$i] = false; + break; + } + if (!@copy($data[0], $data[0] . '.bak')) { + $this->log(1, 'Could not copy ' . $data[0] . ' to ' . $data[0] . + '.bak ' . $php_errormsg); + return false; + } + $this->log(3, "+ backup $data[0] to $data[0].bak"); + break; + case 'removebackup': + if (file_exists($data[0] . '.bak') && is_writable($data[0] . '.bak')) { + unlink($data[0] . '.bak'); + $this->log(3, "+ rm backup of $data[0] ($data[0].bak)"); + } + break; + case 'rename': + if (file_exists($data[1])) { + $test = @unlink($data[1]); + } else { + $test = null; + } + if (!$test && file_exists($data[1])) { + if ($data[2]) { + $extra = ', this extension must be installed manually. Rename to "' . + basename($data[1]) . '"'; + } else { + $extra = ''; + } + if (!isset($this->_options['soft'])) { + $this->log(1, 'Could not delete ' . $data[1] . ', cannot rename ' . + $data[0] . $extra); + } + if (!isset($this->_options['ignore-errors'])) { + return false; + } + } + // permissions issues with rename - copy() is far superior + $perms = @fileperms($data[0]); + if (!@copy($data[0], $data[1])) { + $this->log(1, 'Could not rename ' . $data[0] . ' to ' . $data[1] . + ' ' . $php_errormsg); + return false; + } + // copy over permissions, otherwise they are lost + @chmod($data[1], $perms); + @unlink($data[0]); + $this->log(3, "+ mv $data[0] $data[1]"); + break; + case 'chmod': + if (!@chmod($data[1], $data[0])) { + $this->log(1, 'Could not chmod ' . $data[1] . ' to ' . + decoct($data[0]) . ' ' . $php_errormsg); + return false; + } + $octmode = decoct($data[0]); + $this->log(3, "+ chmod $octmode $data[1]"); + break; + case 'delete': + if (file_exists($data[0])) { + if (!@unlink($data[0])) { + $this->log(1, 'Could not delete ' . $data[0] . ' ' . + $php_errormsg); + return false; + } + $this->log(3, "+ rm $data[0]"); + } + break; + case 'rmdir': + if (file_exists($data[0])) { + do { + $testme = opendir($data[0]); + while (false !== ($entry = readdir($testme))) { + if ($entry == '.' || $entry == '..') { + continue; + } + closedir($testme); + break 2; // this directory is not empty and can't be + // deleted + } + closedir($testme); + if (!@rmdir($data[0])) { + $this->log(1, 'Could not rmdir ' . $data[0] . ' ' . + $php_errormsg); + return false; + } + $this->log(3, "+ rmdir $data[0]"); + } while (false); + } + break; + case 'installed_as': + $this->pkginfo->setInstalledAs($data[0], $data[1]); + if (!isset($this->_dirtree[dirname($data[1])])) { + $this->_dirtree[dirname($data[1])] = true; + $this->pkginfo->setDirtree(dirname($data[1])); + + while(!empty($data[3]) && dirname($data[3]) != $data[3] && + $data[3] != '/' && $data[3] != '\\') { + $this->pkginfo->setDirtree($pp = + $this->_prependPath($data[3], $data[2])); + $this->_dirtree[$pp] = true; + $data[3] = dirname($data[3]); + } + } + break; + } + } + // }}} + $this->log(2, "successfully committed $n file operations"); + $this->file_operations = array(); + return true; + } + + // }}} + // {{{ rollbackFileTransaction() + + function rollbackFileTransaction() + { + $n = count($this->file_operations); + $this->log(2, "rolling back $n file operations"); + foreach ($this->file_operations as $tr) { + list($type, $data) = $tr; + switch ($type) { + case 'backup': + if (file_exists($data[0] . '.bak')) { + if (file_exists($data[0] && is_writable($data[0]))) { + unlink($data[0]); + } + @copy($data[0] . '.bak', $data[0]); + $this->log(3, "+ restore $data[0] from $data[0].bak"); + } + break; + case 'removebackup': + if (file_exists($data[0] . '.bak') && is_writable($data[0] . '.bak')) { + unlink($data[0] . '.bak'); + $this->log(3, "+ rm backup of $data[0] ($data[0].bak)"); + } + break; + case 'rename': + @unlink($data[0]); + $this->log(3, "+ rm $data[0]"); + break; + case 'mkdir': + @rmdir($data[0]); + $this->log(3, "+ rmdir $data[0]"); + break; + case 'chmod': + break; + case 'delete': + break; + case 'installed_as': + $this->pkginfo->setInstalledAs($data[0], false); + break; + } + } + $this->pkginfo->resetDirtree(); + $this->file_operations = array(); + } + + // }}} + // {{{ mkDirHier($dir) + + function mkDirHier($dir) + { + $this->addFileOperation('mkdir', array($dir)); + return parent::mkDirHier($dir); + } + + // }}} + // {{{ download() + + /** + * Download any files and their dependencies, if necessary + * + * @param array a mixed list of package names, local files, or package.xml + * @param PEAR_Config + * @param array options from the command line + * @param array this is the array that will be populated with packages to + * install. Format of each entry: + * + * + * array('pkg' => 'package_name', 'file' => '/path/to/local/file', + * 'info' => array() // parsed package.xml + * ); + * + * @param array this will be populated with any error messages + * @param false private recursion variable + * @param false private recursion variable + * @param false private recursion variable + * @deprecated in favor of PEAR_Downloader + */ + function download($packages, $options, &$config, &$installpackages, + &$errors, $installed = false, $willinstall = false, $state = false) + { + // trickiness: initialize here + parent::PEAR_Downloader($this->ui, $options, $config); + $ret = parent::download($packages); + $errors = $this->getErrorMsgs(); + $installpackages = $this->getDownloadedPackages(); + trigger_error("PEAR Warning: PEAR_Installer::download() is deprecated " . + "in favor of PEAR_Downloader class", E_USER_WARNING); + return $ret; + } + + // }}} + // {{{ _parsePackageXml() + + function _parsePackageXml(&$descfile, &$tmpdir) + { + if (substr($descfile, -4) == '.xml') { + $tmpdir = false; + } else { + // {{{ Decompress pack in tmp dir ------------------------------------- + + // To allow relative package file names + $descfile = realpath($descfile); + + if (PEAR::isError($tmpdir = System::mktemp('-d'))) { + return $tmpdir; + } + $this->log(3, '+ tmp dir created at ' . $tmpdir); + // }}} + } + // Parse xml file ----------------------------------------------- + $pkg = new PEAR_PackageFile($this->config, $this->debug, $tmpdir); + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + $p = &$pkg->fromAnyFile($descfile, PEAR_VALIDATE_INSTALLING); + PEAR::staticPopErrorHandling(); + if (PEAR::isError($p)) { + if (is_array($p->getUserInfo())) { + foreach ($p->getUserInfo() as $err) { + $loglevel = $err['level'] == 'error' ? 0 : 1; + if (!isset($this->_options['soft'])) { + $this->log($loglevel, ucfirst($err['level']) . ': ' . $err['message']); + } + } + } + return $this->raiseError('Installation failed: invalid package file'); + } else { + $descfile = $p->getPackageFile(); + } + return $p; + } + + // }}} + /** + * Set the list of PEAR_Downloader_Package objects to allow more sane + * dependency validation + * @param array + */ + function setDownloadedPackages(&$pkgs) + { + PEAR::pushErrorHandling(PEAR_ERROR_RETURN); + $err = $this->analyzeDependencies($pkgs); + PEAR::popErrorHandling(); + if (PEAR::isError($err)) { + return $err; + } + $this->_downloadedPackages = &$pkgs; + } + + /** + * Set the list of PEAR_Downloader_Package objects to allow more sane + * dependency validation + * @param array + */ + function setUninstallPackages(&$pkgs) + { + $this->_downloadedPackages = &$pkgs; + } + + function getInstallPackages() + { + return $this->_downloadedPackages; + } + + // {{{ install() + + /** + * Installs the files within the package file specified. + * + * @param string|PEAR_Downloader_Package $pkgfile path to the package file, + * or a pre-initialized packagefile object + * @param array $options + * recognized options: + * - installroot : optional prefix directory for installation + * - force : force installation + * - register-only : update registry but don't install files + * - upgrade : upgrade existing install + * - soft : fail silently + * - nodeps : ignore dependency conflicts/missing dependencies + * - alldeps : install all dependencies + * - onlyreqdeps : install only required dependencies + * + * @return array|PEAR_Error package info if successful + */ + + function install($pkgfile, $options = array()) + { + $this->_options = $options; + $this->_registry = &$this->config->getRegistry(); + if (is_object($pkgfile)) { + $dlpkg = &$pkgfile; + $pkg = $pkgfile->getPackageFile(); + $pkgfile = $pkg->getArchiveFile(); + $descfile = $pkg->getPackageFile(); + $tmpdir = dirname($descfile); + } else { + $descfile = $pkgfile; + $tmpdir = ''; + if (PEAR::isError($pkg = &$this->_parsePackageXml($descfile, $tmpdir))) { + return $pkg; + } + } + + if (realpath($descfile) != realpath($pkgfile)) { + $tar = new Archive_Tar($pkgfile); + if (!$tar->extract($tmpdir)) { + return $this->raiseError("unable to unpack $pkgfile"); + } + } + + $pkgname = $pkg->getName(); + $channel = $pkg->getChannel(); + if (isset($this->_options['packagingroot'])) { + $regdir = $this->_prependPath( + $this->config->get('php_dir', null, 'pear.php.net'), + $this->_options['packagingroot']); + $packrootphp_dir = $this->_prependPath( + $this->config->get('php_dir', null, $channel), + $this->_options['packagingroot']); + } + + if (isset($options['installroot'])) { + $this->config->setInstallRoot($options['installroot']); + $this->_registry = &$this->config->getRegistry(); + $installregistry = &$this->_registry; + $this->installroot = ''; // all done automagically now + $php_dir = $this->config->get('php_dir', null, $channel); + } else { + $this->config->setInstallRoot(false); + $this->_registry = &$this->config->getRegistry(); + if (isset($this->_options['packagingroot'])) { + $installregistry = &new PEAR_Registry($regdir); + if (!$installregistry->channelExists($channel, true)) { + // we need to fake a channel-discover of this channel + $chanobj = $this->_registry->getChannel($channel, true); + $installregistry->addChannel($chanobj); + } + $php_dir = $packrootphp_dir; + } else { + $installregistry = &$this->_registry; + $php_dir = $this->config->get('php_dir', null, $channel); + } + $this->installroot = ''; + } + + // {{{ checks to do when not in "force" mode + if (empty($options['force']) && + (file_exists($this->config->get('php_dir')) && + is_dir($this->config->get('php_dir')))) { + $testp = $channel == 'pear.php.net' ? $pkgname : array($channel, $pkgname); + $instfilelist = $pkg->getInstallationFileList(true); + if (PEAR::isError($instfilelist)) { + return $instfilelist; + } + // ensure we have the most accurate registry + $installregistry->flushFileMap(); + $test = $installregistry->checkFileMap($instfilelist, $testp, '1.1'); + if (PEAR::isError($test)) { + return $test; + } + if (sizeof($test)) { + $pkgs = $this->getInstallPackages(); + $found = false; + foreach ($pkgs as $param) { + if ($pkg->isSubpackageOf($param)) { + $found = true; + break; + } + } + if ($found) { + // subpackages can conflict with earlier versions of parent packages + $parentreg = $installregistry->packageInfo($param->getPackage(), null, $param->getChannel()); + $tmp = $test; + foreach ($tmp as $file => $info) { + if (is_array($info)) { + if (strtolower($info[1]) == strtolower($param->getPackage()) && + strtolower($info[0]) == strtolower($param->getChannel())) { + unset($test[$file]); + unset($parentreg['filelist'][$file]); + } + } else { + if (strtolower($param->getChannel()) != 'pear.php.net') { + continue; + } + if (strtolower($info) == strtolower($param->getPackage())) { + unset($test[$file]); + unset($parentreg['filelist'][$file]); + } + } + } + $pfk = &new PEAR_PackageFile($this->config); + $parentpkg = &$pfk->fromArray($parentreg); + $installregistry->updatePackage2($parentpkg); + } + if ($param->getChannel() == 'pecl.php.net' && isset($options['upgrade'])) { + $tmp = $test; + foreach ($tmp as $file => $info) { + if (is_string($info)) { + // pear.php.net packages are always stored as strings + if (strtolower($info) == strtolower($param->getPackage())) { + // upgrading existing package + unset($test[$file]); + } + } + } + } + if (sizeof($test)) { + $msg = "$channel/$pkgname: conflicting files found:\n"; + $longest = max(array_map("strlen", array_keys($test))); + $fmt = "%${longest}s (%s)\n"; + foreach ($test as $file => $info) { + if (!is_array($info)) { + $info = array('pear.php.net', $info); + } + $info = $info[0] . '/' . $info[1]; + $msg .= sprintf($fmt, $file, $info); + } + if (!isset($options['ignore-errors'])) { + return $this->raiseError($msg); + } else { + if (!isset($options['soft'])) { + $this->log(0, "WARNING: $msg"); + } + } + } + } + } + // }}} + + $this->startFileTransaction(); + + if (empty($options['upgrade']) && empty($options['soft'])) { + // checks to do only when installing new packages + if ($channel == 'pecl.php.net') { + $test = $installregistry->packageExists($pkgname, $channel); + if (!$test) { + $test = $installregistry->packageExists($pkgname, 'pear.php.net'); + } + } else { + $test = $installregistry->packageExists($pkgname, $channel); + } + if (empty($options['force']) && $test) { + return $this->raiseError("$channel/$pkgname is already installed"); + } + } else { + $usechannel = $channel; + if ($channel == 'pecl.php.net') { + $test = $installregistry->packageExists($pkgname, $channel); + if (!$test) { + $test = $installregistry->packageExists($pkgname, 'pear.php.net'); + $usechannel = 'pear.php.net'; + } + } else { + $test = $installregistry->packageExists($pkgname, $channel); + } + if ($test) { + $v1 = $installregistry->packageInfo($pkgname, 'version', $usechannel); + $v2 = $pkg->getVersion(); + $cmp = version_compare("$v1", "$v2", 'gt'); + if (empty($options['force']) && !version_compare("$v2", "$v1", 'gt')) { + return $this->raiseError("upgrade to a newer version ($v2 is not newer than $v1)"); + } + if (empty($options['register-only'])) { + // when upgrading, remove old release's files first: + if (PEAR::isError($err = $this->_deletePackageFiles($pkgname, $usechannel, + true))) { + if (!isset($options['ignore-errors'])) { + return $this->raiseError($err); + } else { + if (!isset($options['soft'])) { + $this->log(0, 'WARNING: ' . $err->getMessage()); + } + } + } else { + $backedup = $err; + } + } + } + } + + // {{{ Copy files to dest dir --------------------------------------- + + // info from the package it self we want to access from _installFile + $this->pkginfo = &$pkg; + // used to determine whether we should build any C code + $this->source_files = 0; + + $savechannel = $this->config->get('default_channel'); + if (empty($options['register-only']) && !is_dir($php_dir)) { + if (PEAR::isError(System::mkdir(array('-p'), $php_dir))) { + return $this->raiseError("no installation destination directory '$php_dir'\n"); + } + } + + $tmp_path = dirname($descfile); + if (substr($pkgfile, -4) != '.xml') { + $tmp_path .= DIRECTORY_SEPARATOR . $pkgname . '-' . $pkg->getVersion(); + } + + $this->configSet('default_channel', $channel); + // {{{ install files + + $ver = $pkg->getPackagexmlVersion(); + if (version_compare($ver, '2.0', '>=')) { + $filelist = $pkg->getInstallationFilelist(); + } else { + $filelist = $pkg->getFileList(); + } + if (PEAR::isError($filelist)) { + return $filelist; + } + $p = &$installregistry->getPackage($pkgname, $channel); + if (empty($options['register-only']) && $p) { + $dirtree = $p->getDirTree(); + } else { + $dirtree = false; + } + $pkg->resetFilelist(); + $pkg->setLastInstalledVersion($installregistry->packageInfo($pkg->getPackage(), + 'version', $pkg->getChannel())); + foreach ($filelist as $file => $atts) { + if ($pkg->getPackagexmlVersion() == '1.0') { + $this->expectError(PEAR_INSTALLER_FAILED); + $res = $this->_installFile($file, $atts, $tmp_path, $options); + $this->popExpect(); + } else { + $this->expectError(PEAR_INSTALLER_FAILED); + $res = $this->_installFile2($pkg, $file, $atts, $tmp_path, $options); + $this->popExpect(); + } + if (PEAR::isError($res)) { + if (empty($options['ignore-errors'])) { + $this->rollbackFileTransaction(); + if ($res->getMessage() == "file does not exist") { + $this->raiseError("file $file in package.xml does not exist"); + } + return $this->raiseError($res); + } else { + if (!isset($options['soft'])) { + $this->log(0, "Warning: " . $res->getMessage()); + } + } + } + $real = isset($atts['attribs']) ? $atts['attribs'] : $atts; + if ($res == PEAR_INSTALLER_OK && $real['role'] != 'src') { + // Register files that were installed + $pkg->installedFile($file, $atts); + } + } + // }}} + + // {{{ compile and install source files + if ($this->source_files > 0 && empty($options['nobuild'])) { + if (PEAR::isError($err = + $this->_compileSourceFiles($savechannel, $pkg))) { + return $err; + } + } + // }}} + + if (isset($backedup)) { + $this->_removeBackups($backedup); + } + if (!$this->commitFileTransaction()) { + $this->rollbackFileTransaction(); + $this->configSet('default_channel', $savechannel); + return $this->raiseError("commit failed", PEAR_INSTALLER_FAILED); + } + // }}} + + $ret = false; + $installphase = 'install'; + $oldversion = false; + // {{{ Register that the package is installed ----------------------- + if (empty($options['upgrade'])) { + // if 'force' is used, replace the info in registry + $usechannel = $channel; + if ($channel == 'pecl.php.net') { + $test = $installregistry->packageExists($pkgname, $channel); + if (!$test) { + $test = $installregistry->packageExists($pkgname, 'pear.php.net'); + $usechannel = 'pear.php.net'; + } + } else { + $test = $installregistry->packageExists($pkgname, $channel); + } + if (!empty($options['force']) && $test) { + $oldversion = $installregistry->packageInfo($pkgname, 'version', $usechannel); + $installregistry->deletePackage($pkgname, $usechannel); + } + $ret = $installregistry->addPackage2($pkg); + } else { + if ($dirtree) { + $this->startFileTransaction(); + // attempt to delete empty directories + uksort($dirtree, array($this, '_sortDirs')); + foreach($dirtree as $dir => $notused) { + $this->addFileOperation('rmdir', array($dir)); + } + $this->commitFileTransaction(); + } + $usechannel = $channel; + if ($channel == 'pecl.php.net') { + $test = $installregistry->packageExists($pkgname, $channel); + if (!$test) { + $test = $installregistry->packageExists($pkgname, 'pear.php.net'); + $usechannel = 'pear.php.net'; + } + } else { + $test = $installregistry->packageExists($pkgname, $channel); + } + // new: upgrade installs a package if it isn't installed + if (!$test) { + $ret = $installregistry->addPackage2($pkg); + } else { + if ($usechannel != $channel) { + $installregistry->deletePackage($pkgname, $usechannel); + $ret = $installregistry->addPackage2($pkg); + } else { + $ret = $installregistry->updatePackage2($pkg); + } + $installphase = 'upgrade'; + } + } + if (!$ret) { + $this->configSet('default_channel', $savechannel); + return $this->raiseError("Adding package $channel/$pkgname to registry failed"); + } + // }}} + $this->configSet('default_channel', $savechannel); + if (class_exists('PEAR_Task_Common')) { // this is auto-included if any tasks exist + if (PEAR_Task_Common::hasPostinstallTasks()) { + PEAR_Task_Common::runPostinstallTasks($installphase); + } + } + return $pkg->toArray(true); + } + + // }}} + + // {{{ _compileSourceFiles() + /** + * @param string + * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2 + */ + function _compileSourceFiles($savechannel, &$filelist) + { + require_once 'PEAR/Builder.php'; + $this->log(1, "$this->source_files source files, building"); + $bob = &new PEAR_Builder($this->ui); + $bob->debug = $this->debug; + $built = $bob->build($filelist, array(&$this, '_buildCallback')); + if (PEAR::isError($built)) { + $this->rollbackFileTransaction(); + $this->configSet('default_channel', $savechannel); + return $built; + } + $this->log(1, "\nBuild process completed successfully"); + foreach ($built as $ext) { + $bn = basename($ext['file']); + list($_ext_name, $_ext_suff) = explode('.', $bn); + if ($_ext_suff == '.so' || $_ext_suff == '.dll') { + if (extension_loaded($_ext_name)) { + $this->raiseError("Extension '$_ext_name' already loaded. " . + 'Please unload it in your php.ini file ' . + 'prior to install or upgrade'); + } + $role = 'ext'; + } else { + $role = 'src'; + } + $dest = $ext['dest']; + $packagingroot = ''; + if (isset($this->_options['packagingroot'])) { + $packagingroot = $this->_options['packagingroot']; + } + $copyto = $this->_prependPath($dest, $packagingroot); + if ($copyto != $dest) { + $this->log(1, "Installing '$dest' as '$copyto'"); + } else { + $this->log(1, "Installing '$dest'"); + } + $copydir = dirname($copyto); + // pretty much nothing happens if we are only registering the install + if (empty($this->_options['register-only'])) { + if (!file_exists($copydir) || !is_dir($copydir)) { + if (!$this->mkDirHier($copydir)) { + return $this->raiseError("failed to mkdir $copydir", + PEAR_INSTALLER_FAILED); + } + $this->log(3, "+ mkdir $copydir"); + } + if (!@copy($ext['file'], $copyto)) { + return $this->raiseError("failed to write $copyto ($php_errormsg)", PEAR_INSTALLER_FAILED); + } + $this->log(3, "+ cp $ext[file] $copyto"); + $this->addFileOperation('rename', array($ext['file'], $copyto)); + if (!OS_WINDOWS) { + $mode = 0666 & ~(int)octdec($this->config->get('umask')); + $this->addFileOperation('chmod', array($mode, $copyto)); + if (!@chmod($copyto, $mode)) { + $this->log(0, "failed to change mode of $copyto ($php_errormsg)"); + } + } + } + + if ($filelist->getPackageXmlVersion() == '1.0') { + $filelist->installedFile($bn, array( + 'role' => $role, + 'name' => $bn, + 'installed_as' => $dest, + 'php_api' => $ext['php_api'], + 'zend_mod_api' => $ext['zend_mod_api'], + 'zend_ext_api' => $ext['zend_ext_api'], + )); + } else { + $filelist->installedFile($bn, array('attribs' => array( + 'role' => $role, + 'name' => $bn, + 'installed_as' => $dest, + 'php_api' => $ext['php_api'], + 'zend_mod_api' => $ext['zend_mod_api'], + 'zend_ext_api' => $ext['zend_ext_api'], + ))); + } + } + } + + // }}} + function &getUninstallPackages() + { + return $this->_downloadedPackages; + } + // {{{ uninstall() + + /** + * Uninstall a package + * + * This method removes all files installed by the application, and then + * removes any empty directories. + * @param string package name + * @param array Command-line options. Possibilities include: + * + * - installroot: base installation dir, if not the default + * - register-only : update registry but don't remove files + * - nodeps: do not process dependencies of other packages to ensure + * uninstallation does not break things + */ + function uninstall($package, $options = array()) + { + if (isset($options['installroot'])) { + $this->config->setInstallRoot($options['installroot']); + $this->installroot = ''; + } else { + $this->config->setInstallRoot(''); + $this->installroot = ''; + } + $this->_registry = &$this->config->getRegistry(); + if (is_object($package)) { + $channel = $package->getChannel(); + $pkg = $package; + $package = $pkg->getPackage(); + } else { + $pkg = false; + $info = $this->_registry->parsePackageName($package, + $this->config->get('default_channel')); + $channel = $info['channel']; + $package = $info['package']; + } + $savechannel = $this->config->get('default_channel'); + $this->configSet('default_channel', $channel); + if (!is_object($pkg)) { + $pkg = $this->_registry->getPackage($package, $channel); + } + if (!$pkg) { + $this->configSet('default_channel', $savechannel); + return $this->raiseError($this->_registry->parsedPackageNameToString( + array( + 'channel' => $channel, + 'package' => $package + ), true) . ' not installed'); + } + if ($pkg->getInstalledBinary()) { + // this is just an alias for a binary package + return $this->_registry->deletePackage($package, $channel); + } + $filelist = $pkg->getFilelist(); + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + if (!class_exists('PEAR_Dependency2')) { + require_once 'PEAR/Dependency2.php'; + } + $depchecker = &new PEAR_Dependency2($this->config, $options, + array('channel' => $channel, 'package' => $package), + PEAR_VALIDATE_UNINSTALLING); + $e = $depchecker->validatePackageUninstall($this); + PEAR::staticPopErrorHandling(); + if (PEAR::isError($e)) { + if (!isset($options['ignore-errors'])) { + return $this->raiseError($e); + } else { + if (!isset($options['soft'])) { + $this->log(0, 'WARNING: ' . $e->getMessage()); + } + } + } elseif (is_array($e)) { + if (!isset($options['soft'])) { + $this->log(0, $e[0]); + } + } + $this->pkginfo = &$pkg; + // pretty much nothing happens if we are only registering the uninstall + if (empty($options['register-only'])) { + // {{{ Delete the files + $this->startFileTransaction(); + PEAR::pushErrorHandling(PEAR_ERROR_RETURN); + if (PEAR::isError($err = $this->_deletePackageFiles($package, $channel))) { + PEAR::popErrorHandling(); + $this->rollbackFileTransaction(); + $this->configSet('default_channel', $savechannel); + if (!isset($options['ignore-errors'])) { + return $this->raiseError($err); + } else { + if (!isset($options['soft'])) { + $this->log(0, 'WARNING: ' . $err->getMessage()); + } + } + } else { + PEAR::popErrorHandling(); + } + if (!$this->commitFileTransaction()) { + $this->rollbackFileTransaction(); + if (!isset($options['ignore-errors'])) { + return $this->raiseError("uninstall failed"); + } elseif (!isset($options['soft'])) { + $this->log(0, 'WARNING: uninstall failed'); + } + } else { + $this->startFileTransaction(); + if ($dirtree = $pkg->getDirTree()) { + // attempt to delete empty directories + uksort($dirtree, array($this, '_sortDirs')); + foreach($dirtree as $dir => $notused) { + $this->addFileOperation('rmdir', array($dir)); + } + } else { + $this->configSet('default_channel', $savechannel); + return $this->_registry->deletePackage($package, $channel); + } + if (!$this->commitFileTransaction()) { + $this->rollbackFileTransaction(); + if (!isset($options['ignore-errors'])) { + return $this->raiseError("uninstall failed"); + } elseif (!isset($options['soft'])) { + $this->log(0, 'WARNING: uninstall failed'); + } + } + } + // }}} + } + + $this->configSet('default_channel', $savechannel); + // Register that the package is no longer installed + return $this->_registry->deletePackage($package, $channel); + } + + /** + * Sort a list of arrays of array(downloaded packagefilename) by dependency. + * + * It also removes duplicate dependencies + * @param array an array of PEAR_PackageFile_v[1/2] objects + * @return array|PEAR_Error array of array(packagefilename, package.xml contents) + */ + function sortPackagesForUninstall(&$packages) + { + $this->_dependencyDB = &PEAR_DependencyDB::singleton($this->config); + if (PEAR::isError($this->_dependencyDB)) { + return $this->_dependencyDB; + } + usort($packages, array(&$this, '_sortUninstall')); + } + + function _sortUninstall($a, $b) + { + if (!$a->getDeps() && !$b->getDeps()) { + return 0; // neither package has dependencies, order is insignificant + } + if ($a->getDeps() && !$b->getDeps()) { + return -1; // $a must be installed after $b because $a has dependencies + } + if (!$a->getDeps() && $b->getDeps()) { + return 1; // $b must be installed after $a because $b has dependencies + } + // both packages have dependencies + if ($this->_dependencyDB->dependsOn($a, $b)) { + return -1; + } + if ($this->_dependencyDB->dependsOn($b, $a)) { + return 1; + } + return 0; + } + + // }}} + // {{{ _sortDirs() + function _sortDirs($a, $b) + { + if (strnatcmp($a, $b) == -1) return 1; + if (strnatcmp($a, $b) == 1) return -1; + return 0; + } + + // }}} + + // {{{ _buildCallback() + + function _buildCallback($what, $data) + { + if (($what == 'cmdoutput' && $this->debug > 1) || + ($what == 'output' && $this->debug > 0)) { + $this->ui->outputData(rtrim($data), 'build'); + } + } + + // }}} +} + +// {{{ md5_file() utility function +if (!function_exists("md5_file")) { + function md5_file($filename) { + if (!$fd = @fopen($file, 'r')) { + return false; + } + fclose($fd); + return md5(file_get_contents($filename)); + } +} +// }}} + +?> \ No newline at end of file diff --git a/src/lib/pear/PEAR/PEAR/Installer/Role.php b/src/lib/pear/PEAR/PEAR/Installer/Role.php new file mode 100644 index 0000000..3b50db3 --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Installer/Role.php @@ -0,0 +1,253 @@ + + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: Role.php,v 1.20 2008/01/03 20:26:36 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 1.4.0a1 + */ + +/** + * base class for installer roles + */ +require_once 'PEAR/Installer/Role/Common.php'; +require_once 'PEAR/XMLParser.php'; +/** + * @category pear + * @package PEAR + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 1.4.0a1 + */ +class PEAR_Installer_Role +{ + /** + * Set up any additional configuration variables that file roles require + * + * Never call this directly, it is called by the PEAR_Config constructor + * @param PEAR_Config + * @access private + * @static + */ + function initializeConfig(&$config) + { + if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'])) { + PEAR_Installer_Role::registerRoles(); + } + foreach ($GLOBALS['_PEAR_INSTALLER_ROLES'] as $class => $info) { + if (!$info['config_vars']) { + continue; + } + $config->_addConfigVars($class, $info['config_vars']); + } + } + + /** + * @param PEAR_PackageFile_v2 + * @param string role name + * @param PEAR_Config + * @return PEAR_Installer_Role_Common + * @static + */ + function &factory($pkg, $role, &$config) + { + if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'])) { + PEAR_Installer_Role::registerRoles(); + } + if (!in_array($role, PEAR_Installer_Role::getValidRoles($pkg->getPackageType()))) { + $a = false; + return $a; + } + $a = 'PEAR_Installer_Role_' . ucfirst($role); + if (!class_exists($a)) { + require_once str_replace('_', '/', $a) . '.php'; + } + $b = new $a($config); + return $b; + } + + /** + * Get a list of file roles that are valid for the particular release type. + * + * For instance, src files serve no purpose in regular php releases. + * @param string + * @param bool clear cache + * @return array + * @static + */ + function getValidRoles($release, $clear = false) + { + if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'])) { + PEAR_Installer_Role::registerRoles(); + } + static $ret = array(); + if ($clear) { + $ret = array(); + } + if (isset($ret[$release])) { + return $ret[$release]; + } + $ret[$release] = array(); + foreach ($GLOBALS['_PEAR_INSTALLER_ROLES'] as $role => $okreleases) { + if (in_array($release, $okreleases['releasetypes'])) { + $ret[$release][] = strtolower(str_replace('PEAR_Installer_Role_', '', $role)); + } + } + return $ret[$release]; + } + + /** + * Get a list of roles that require their files to be installed + * + * Most roles must be installed, but src and package roles, for instance + * are pseudo-roles. src files are compiled into a new extension. Package + * roles are actually fully bundled releases of a package + * @param bool clear cache + * @return array + * @static + */ + function getInstallableRoles($clear = false) + { + if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'])) { + PEAR_Installer_Role::registerRoles(); + } + static $ret; + if ($clear) { + unset($ret); + } + if (!isset($ret)) { + $ret = array(); + foreach ($GLOBALS['_PEAR_INSTALLER_ROLES'] as $role => $okreleases) { + if ($okreleases['installable']) { + $ret[] = strtolower(str_replace('PEAR_Installer_Role_', '', $role)); + } + } + } + return $ret; + } + + /** + * Return an array of roles that are affected by the baseinstalldir attribute + * + * Most roles ignore this attribute, and instead install directly into: + * PackageName/filepath + * so a tests file tests/file.phpt is installed into PackageName/tests/filepath.php + * @param bool clear cache + * @return array + * @static + */ + function getBaseinstallRoles($clear = false) + { + if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'])) { + PEAR_Installer_Role::registerRoles(); + } + static $ret; + if ($clear) { + unset($ret); + } + if (!isset($ret)) { + $ret = array(); + foreach ($GLOBALS['_PEAR_INSTALLER_ROLES'] as $role => $okreleases) { + if ($okreleases['honorsbaseinstall']) { + $ret[] = strtolower(str_replace('PEAR_Installer_Role_', '', $role)); + } + } + } + return $ret; + } + + /** + * Return an array of file roles that should be analyzed for PHP content at package time, + * like the "php" role. + * @param bool clear cache + * @return array + * @static + */ + function getPhpRoles($clear = false) + { + if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'])) { + PEAR_Installer_Role::registerRoles(); + } + static $ret; + if ($clear) { + unset($ret); + } + if (!isset($ret)) { + $ret = array(); + foreach ($GLOBALS['_PEAR_INSTALLER_ROLES'] as $role => $okreleases) { + if ($okreleases['phpfile']) { + $ret[] = strtolower(str_replace('PEAR_Installer_Role_', '', $role)); + } + } + } + return $ret; + } + + /** + * Scan through the Command directory looking for classes + * and see what commands they implement. + * @param string which directory to look for classes, defaults to + * the Installer/Roles subdirectory of + * the directory from where this file (__FILE__) is + * included. + * + * @return bool TRUE on success, a PEAR error on failure + * @access public + * @static + */ + function registerRoles($dir = null) + { + $GLOBALS['_PEAR_INSTALLER_ROLES'] = array(); + $parser = new PEAR_XMLParser; + if ($dir === null) { + $dir = dirname(__FILE__) . '/Role'; + } + if (!file_exists($dir) || !is_dir($dir)) { + return PEAR::raiseError("registerRoles: opendir($dir) failed: does not exist/is not directory"); + } + $dp = @opendir($dir); + if (empty($dp)) { + return PEAR::raiseError("registerRoles: opendir($dir) failed: $php_errmsg"); + } + while ($entry = readdir($dp)) { + if ($entry{0} == '.' || substr($entry, -4) != '.xml') { + continue; + } + $class = "PEAR_Installer_Role_".substr($entry, 0, -4); + // List of roles + if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'][$class])) { + $file = "$dir/$entry"; + $parser->parse(file_get_contents($file)); + $data = $parser->getData(); + if (!is_array($data['releasetypes'])) { + $data['releasetypes'] = array($data['releasetypes']); + } + $GLOBALS['_PEAR_INSTALLER_ROLES'][$class] = $data; + } + } + closedir($dp); + ksort($GLOBALS['_PEAR_INSTALLER_ROLES']); + PEAR_Installer_Role::getBaseinstallRoles(true); + PEAR_Installer_Role::getInstallableRoles(true); + PEAR_Installer_Role::getPhpRoles(true); + PEAR_Installer_Role::getValidRoles('****', true); + return true; + } +} +?> diff --git a/src/lib/pear/PEAR/PEAR/Installer/Role/Cfg.php b/src/lib/pear/PEAR/PEAR/Installer/Role/Cfg.php new file mode 100644 index 0000000..1928f60 --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Installer/Role/Cfg.php @@ -0,0 +1,108 @@ + + * @copyright 2007-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: Cfg.php,v 1.8 2008/05/14 21:26:30 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 1.7.0 + */ + +/** + * @category pear + * @package PEAR + * @author Greg Beaver + * @copyright 2007-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 1.7.0 + */ +class PEAR_Installer_Role_Cfg extends PEAR_Installer_Role_Common +{ + /** + * @var PEAR_Installer + */ + var $installer; + /** + * the md5 of the original file + * + * @var unknown_type + */ + var $md5 = null; + /** + * Do any unusual setup here + * @param PEAR_Installer + * @param PEAR_PackageFile_v2 + * @param array file attributes + * @param string file name + */ + function setup(&$installer, $pkg, $atts, $file) + { + $this->installer = &$installer; + $reg = &$this->installer->config->getRegistry(); + $package = $reg->getPackage($pkg->getPackage(), $pkg->getChannel()); + if ($package) { + $filelist = $package->getFilelist(); + if (isset($filelist[$file]) && isset($filelist[$file]['md5sum'])) { + $this->md5 = $filelist[$file]['md5sum']; + } + } + } + + function processInstallation($pkg, $atts, $file, $tmp_path, $layer = null) + { + $test = parent::processInstallation($pkg, $atts, $file, $tmp_path, $layer); + if (@file_exists($test[2]) && @file_exists($test[3])) { + $md5 = md5_file($test[2]); + // configuration has already been installed, check for mods + if ($md5 !== $this->md5 && $md5 !== md5_file($test[3])) { + // configuration has been modified, so save our version as + // configfile-version + $old = $test[2]; + $test[2] .= '.new-' . $pkg->getVersion(); + // backup original and re-install it + PEAR::pushErrorHandling(PEAR_ERROR_RETURN); + $tmpcfg = $this->config->get('temp_dir'); + $newloc = System::mkdir(array('-p', $tmpcfg)); + if (!$newloc) { + // try temp_dir + $newloc = System::mktemp(array('-d')); + if (!$newloc || PEAR::isError($newloc)) { + PEAR::popErrorHandling(); + return PEAR::raiseError('Could not save existing configuration file '. + $old . ', unable to install. Please set temp_dir ' . + 'configuration variable to a writeable location and try again'); + } + } else { + $newloc = $tmpcfg; + } + $temp_file = $newloc . DIRECTORY_SEPARATOR . uniqid('savefile'); + if (!@copy($old, $temp_file)) { + PEAR::popErrorHandling(); + return PEAR::raiseError('Could not save existing configuration file '. + $old . ', unable to install. Please set temp_dir ' . + 'configuration variable to a writeable location and try again'); + } + PEAR::popErrorHandling(); + $this->installer->log(0, "WARNING: configuration file $old is being installed as $test[2], you should manually merge in changes to the existing configuration file"); + $this->installer->addFileOperation('rename', array($temp_file, $old, false)); + $this->installer->addFileOperation('delete', array($temp_file)); + } + } + return $test; + } +} +?> diff --git a/src/lib/pear/PEAR/PEAR/Installer/Role/Cfg.xml b/src/lib/pear/PEAR/PEAR/Installer/Role/Cfg.xml new file mode 100644 index 0000000..7a415dc --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Installer/Role/Cfg.xml @@ -0,0 +1,15 @@ + + php + extsrc + extbin + zendextsrc + zendextbin + 1 + cfg_dir + + 1 + + + + + \ No newline at end of file diff --git a/src/lib/pear/PEAR/PEAR/Installer/Role/Common.php b/src/lib/pear/PEAR/PEAR/Installer/Role/Common.php new file mode 100644 index 0000000..32cd821 --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Installer/Role/Common.php @@ -0,0 +1,180 @@ + + * @copyright 1997-2006 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: Common.php,v 1.12 2006/10/19 23:55:32 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 1.4.0a1 + */ +/** + * Base class for all installation roles. + * + * This class allows extensibility of file roles. Packages with complex + * customization can now provide custom file roles along with the possibility of + * adding configuration values to match. + * @category pear + * @package PEAR + * @author Greg Beaver + * @copyright 1997-2006 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 1.4.0a1 + */ +class PEAR_Installer_Role_Common +{ + /** + * @var PEAR_Config + * @access protected + */ + var $config; + + /** + * @param PEAR_Config + */ + function PEAR_Installer_Role_Common(&$config) + { + $this->config = $config; + } + + /** + * Retrieve configuration information about a file role from its XML info + * + * @param string $role Role Classname, as in "PEAR_Installer_Role_Data" + * @return array + */ + function getInfo($role) + { + if (empty($GLOBALS['_PEAR_INSTALLER_ROLES'][$role])) { + return PEAR::raiseError('Unknown Role class: "' . $role . '"'); + } + return $GLOBALS['_PEAR_INSTALLER_ROLES'][$role]; + } + + /** + * This is called for each file to set up the directories and files + * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2 + * @param array attributes from the tag + * @param string file name + * @return array an array consisting of: + * + * 1 the original, pre-baseinstalldir installation directory + * 2 the final installation directory + * 3 the full path to the final location of the file + * 4 the location of the pre-installation file + */ + function processInstallation($pkg, $atts, $file, $tmp_path, $layer = null) + { + $roleInfo = PEAR_Installer_Role_Common::getInfo('PEAR_Installer_Role_' . + ucfirst(str_replace('pear_installer_role_', '', strtolower(get_class($this))))); + if (PEAR::isError($roleInfo)) { + return $roleInfo; + } + if (!$roleInfo['locationconfig']) { + return false; + } + if ($roleInfo['honorsbaseinstall']) { + $dest_dir = $save_destdir = $this->config->get($roleInfo['locationconfig'], $layer, + $pkg->getChannel()); + if (!empty($atts['baseinstalldir'])) { + $dest_dir .= DIRECTORY_SEPARATOR . $atts['baseinstalldir']; + } + } elseif ($roleInfo['unusualbaseinstall']) { + $dest_dir = $save_destdir = $this->config->get($roleInfo['locationconfig'], + $layer, $pkg->getChannel()) . DIRECTORY_SEPARATOR . $pkg->getPackage(); + if (!empty($atts['baseinstalldir'])) { + $dest_dir .= DIRECTORY_SEPARATOR . $atts['baseinstalldir']; + } + } else { + $dest_dir = $save_destdir = $this->config->get($roleInfo['locationconfig'], + $layer, $pkg->getChannel()) . DIRECTORY_SEPARATOR . $pkg->getPackage(); + } + if (dirname($file) != '.' && empty($atts['install-as'])) { + $dest_dir .= DIRECTORY_SEPARATOR . dirname($file); + } + if (empty($atts['install-as'])) { + $dest_file = $dest_dir . DIRECTORY_SEPARATOR . basename($file); + } else { + $dest_file = $dest_dir . DIRECTORY_SEPARATOR . $atts['install-as']; + } + $orig_file = $tmp_path . DIRECTORY_SEPARATOR . $file; + + // Clean up the DIRECTORY_SEPARATOR mess + $ds2 = DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR; + + list($dest_dir, $dest_file, $orig_file) = preg_replace(array('!\\\\+!', '!/!', "!$ds2+!"), + array(DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR, + DIRECTORY_SEPARATOR), + array($dest_dir, $dest_file, $orig_file)); + return array($save_destdir, $dest_dir, $dest_file, $orig_file); + } + + /** + * Get the name of the configuration variable that specifies the location of this file + * @return string|false + */ + function getLocationConfig() + { + $roleInfo = PEAR_Installer_Role_Common::getInfo('PEAR_Installer_Role_' . + ucfirst(str_replace('pear_installer_role_', '', strtolower(get_class($this))))); + if (PEAR::isError($roleInfo)) { + return $roleInfo; + } + return $roleInfo['locationconfig']; + } + + /** + * Do any unusual setup here + * @param PEAR_Installer + * @param PEAR_PackageFile_v2 + * @param array file attributes + * @param string file name + */ + function setup(&$installer, $pkg, $atts, $file) + { + } + + function isExecutable() + { + $roleInfo = PEAR_Installer_Role_Common::getInfo('PEAR_Installer_Role_' . + ucfirst(str_replace('pear_installer_role_', '', strtolower(get_class($this))))); + if (PEAR::isError($roleInfo)) { + return $roleInfo; + } + return $roleInfo['executable']; + } + + function isInstallable() + { + $roleInfo = PEAR_Installer_Role_Common::getInfo('PEAR_Installer_Role_' . + ucfirst(str_replace('pear_installer_role_', '', strtolower(get_class($this))))); + if (PEAR::isError($roleInfo)) { + return $roleInfo; + } + return $roleInfo['installable']; + } + + function isExtension() + { + $roleInfo = PEAR_Installer_Role_Common::getInfo('PEAR_Installer_Role_' . + ucfirst(str_replace('pear_installer_role_', '', strtolower(get_class($this))))); + if (PEAR::isError($roleInfo)) { + return $roleInfo; + } + return $roleInfo['phpextension']; + } +} +?> \ No newline at end of file diff --git a/src/lib/pear/PEAR/PEAR/Installer/Role/Data.php b/src/lib/pear/PEAR/PEAR/Installer/Role/Data.php new file mode 100644 index 0000000..394f68c --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Installer/Role/Data.php @@ -0,0 +1,34 @@ + + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: Data.php,v 1.7 2008/01/03 20:26:36 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 1.4.0a1 + */ + +/** + * @category pear + * @package PEAR + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 1.4.0a1 + */ +class PEAR_Installer_Role_Data extends PEAR_Installer_Role_Common {} +?> \ No newline at end of file diff --git a/src/lib/pear/PEAR/PEAR/Installer/Role/Data.xml b/src/lib/pear/PEAR/PEAR/Installer/Role/Data.xml new file mode 100644 index 0000000..eae6372 --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Installer/Role/Data.xml @@ -0,0 +1,15 @@ + + php + extsrc + extbin + zendextsrc + zendextbin + 1 + data_dir + + + + + + + \ No newline at end of file diff --git a/src/lib/pear/PEAR/PEAR/Installer/Role/Doc.php b/src/lib/pear/PEAR/PEAR/Installer/Role/Doc.php new file mode 100644 index 0000000..b974dc6 --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Installer/Role/Doc.php @@ -0,0 +1,34 @@ + + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: Doc.php,v 1.7 2008/01/03 20:26:36 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 1.4.0a1 + */ + +/** + * @category pear + * @package PEAR + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 1.4.0a1 + */ +class PEAR_Installer_Role_Doc extends PEAR_Installer_Role_Common {} +?> \ No newline at end of file diff --git a/src/lib/pear/PEAR/PEAR/Installer/Role/Doc.xml b/src/lib/pear/PEAR/PEAR/Installer/Role/Doc.xml new file mode 100644 index 0000000..173afba --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Installer/Role/Doc.xml @@ -0,0 +1,15 @@ + + php + extsrc + extbin + zendextsrc + zendextbin + 1 + doc_dir + + + + + + + \ No newline at end of file diff --git a/src/lib/pear/PEAR/PEAR/Installer/Role/Ext.php b/src/lib/pear/PEAR/PEAR/Installer/Role/Ext.php new file mode 100644 index 0000000..38c0e9a --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Installer/Role/Ext.php @@ -0,0 +1,34 @@ + + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: Ext.php,v 1.7 2008/01/03 20:26:36 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 1.4.0a1 + */ + +/** + * @category pear + * @package PEAR + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 1.4.0a1 + */ +class PEAR_Installer_Role_Ext extends PEAR_Installer_Role_Common {} +?> \ No newline at end of file diff --git a/src/lib/pear/PEAR/PEAR/Installer/Role/Ext.xml b/src/lib/pear/PEAR/PEAR/Installer/Role/Ext.xml new file mode 100644 index 0000000..e2940fe --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Installer/Role/Ext.xml @@ -0,0 +1,12 @@ + + extbin + zendextbin + 1 + ext_dir + 1 + + + + 1 + + \ No newline at end of file diff --git a/src/lib/pear/PEAR/PEAR/Installer/Role/Php.php b/src/lib/pear/PEAR/PEAR/Installer/Role/Php.php new file mode 100644 index 0000000..f232b72 --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Installer/Role/Php.php @@ -0,0 +1,34 @@ + + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: Php.php,v 1.8 2008/01/03 20:26:36 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 1.4.0a1 + */ + +/** + * @category pear + * @package PEAR + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 1.4.0a1 + */ +class PEAR_Installer_Role_Php extends PEAR_Installer_Role_Common {} +?> \ No newline at end of file diff --git a/src/lib/pear/PEAR/PEAR/Installer/Role/Php.xml b/src/lib/pear/PEAR/PEAR/Installer/Role/Php.xml new file mode 100644 index 0000000..6b9a0e6 --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Installer/Role/Php.xml @@ -0,0 +1,15 @@ + + php + extsrc + extbin + zendextsrc + zendextbin + 1 + php_dir + 1 + + 1 + + + + \ No newline at end of file diff --git a/src/lib/pear/PEAR/PEAR/Installer/Role/Script.php b/src/lib/pear/PEAR/PEAR/Installer/Role/Script.php new file mode 100644 index 0000000..b8affdb --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Installer/Role/Script.php @@ -0,0 +1,34 @@ + + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: Script.php,v 1.7 2008/01/03 20:26:36 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 1.4.0a1 + */ + +/** + * @category pear + * @package PEAR + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 1.4.0a1 + */ +class PEAR_Installer_Role_Script extends PEAR_Installer_Role_Common {} +?> \ No newline at end of file diff --git a/src/lib/pear/PEAR/PEAR/Installer/Role/Script.xml b/src/lib/pear/PEAR/PEAR/Installer/Role/Script.xml new file mode 100644 index 0000000..e732cf2 --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Installer/Role/Script.xml @@ -0,0 +1,15 @@ + + php + extsrc + extbin + zendextsrc + zendextbin + 1 + bin_dir + 1 + + + 1 + + + \ No newline at end of file diff --git a/src/lib/pear/PEAR/PEAR/Installer/Role/Src.php b/src/lib/pear/PEAR/PEAR/Installer/Role/Src.php new file mode 100644 index 0000000..68d07e4 --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Installer/Role/Src.php @@ -0,0 +1,40 @@ + + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: Src.php,v 1.7 2008/01/03 20:26:36 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 1.4.0a1 + */ + +/** + * @category pear + * @package PEAR + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 1.4.0a1 + */ +class PEAR_Installer_Role_Src extends PEAR_Installer_Role_Common +{ + function setup(&$installer, $pkg, $atts, $file) + { + $installer->source_files++; + } +} +?> \ No newline at end of file diff --git a/src/lib/pear/PEAR/PEAR/Installer/Role/Src.xml b/src/lib/pear/PEAR/PEAR/Installer/Role/Src.xml new file mode 100644 index 0000000..1034834 --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Installer/Role/Src.xml @@ -0,0 +1,12 @@ + + extsrc + zendextsrc + 1 + temp_dir + + + + + + + \ No newline at end of file diff --git a/src/lib/pear/PEAR/PEAR/Installer/Role/Test.php b/src/lib/pear/PEAR/PEAR/Installer/Role/Test.php new file mode 100644 index 0000000..63979b9 --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Installer/Role/Test.php @@ -0,0 +1,34 @@ + + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: Test.php,v 1.7 2008/01/03 20:26:36 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 1.4.0a1 + */ + +/** + * @category pear + * @package PEAR + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 1.4.0a1 + */ +class PEAR_Installer_Role_Test extends PEAR_Installer_Role_Common {} +?> \ No newline at end of file diff --git a/src/lib/pear/PEAR/PEAR/Installer/Role/Test.xml b/src/lib/pear/PEAR/PEAR/Installer/Role/Test.xml new file mode 100644 index 0000000..51d5b89 --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Installer/Role/Test.xml @@ -0,0 +1,15 @@ + + php + extsrc + extbin + zendextsrc + zendextbin + 1 + test_dir + + + + + + + \ No newline at end of file diff --git a/src/lib/pear/PEAR/PEAR/Installer/Role/Www.php b/src/lib/pear/PEAR/PEAR/Installer/Role/Www.php new file mode 100644 index 0000000..801097f --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Installer/Role/Www.php @@ -0,0 +1,34 @@ + + * @copyright 2007-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: Www.php,v 1.2 2008/01/03 20:26:36 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 1.7.0 + */ + +/** + * @category pear + * @package PEAR + * @author Greg Beaver + * @copyright 2007-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 1.7.0 + */ +class PEAR_Installer_Role_Www extends PEAR_Installer_Role_Common {} +?> \ No newline at end of file diff --git a/src/lib/pear/PEAR/PEAR/Installer/Role/Www.xml b/src/lib/pear/PEAR/PEAR/Installer/Role/Www.xml new file mode 100644 index 0000000..7598be3 --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Installer/Role/Www.xml @@ -0,0 +1,15 @@ + + php + extsrc + extbin + zendextsrc + zendextbin + 1 + www_dir + 1 + + + + + + \ No newline at end of file diff --git a/src/lib/pear/PEAR/PEAR/PackageFile.php b/src/lib/pear/PEAR/PEAR/PackageFile.php new file mode 100644 index 0000000..0dc42e9 --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/PackageFile.php @@ -0,0 +1,474 @@ + + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: PackageFile.php,v 1.41 2008/01/03 20:26:36 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 1.4.0a1 + */ + +/** + * needed for PEAR_VALIDATE_* constants + */ +require_once 'PEAR/Validate.php'; +/** + * Error code if the package.xml tag does not contain a valid version + */ +define('PEAR_PACKAGEFILE_ERROR_NO_PACKAGEVERSION', 1); +/** + * Error code if the package.xml tag version is not supported (version 1.0 and 1.1 are the only supported versions, + * currently + */ +define('PEAR_PACKAGEFILE_ERROR_INVALID_PACKAGEVERSION', 2); +/** + * Abstraction for the package.xml package description file + * + * @category pear + * @package PEAR + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 1.4.0a1 + */ +class PEAR_PackageFile +{ + /** + * @var PEAR_Config + */ + var $_config; + var $_debug; + /** + * Temp directory for uncompressing tgz files. + * @var string|false + */ + var $_tmpdir; + var $_logger = false; + /** + * @var boolean + */ + var $_rawReturn = false; + + /** + * + * @param PEAR_Config $config + * @param ? $debug + * @param string @tmpdir Optional temporary directory for uncompressing + * files + */ + function PEAR_PackageFile(&$config, $debug = false, $tmpdir = false) + { + $this->_config = $config; + $this->_debug = $debug; + $this->_tmpdir = $tmpdir; + } + + /** + * Turn off validation - return a parsed package.xml without checking it + * + * This is used by the package-validate command + */ + function rawReturn() + { + $this->_rawReturn = true; + } + + function setLogger(&$l) + { + $this->_logger = &$l; + } + + /** + * Create a PEAR_PackageFile_Parser_v* of a given version. + * @param int $version + * @return PEAR_PackageFile_Parser_v1|PEAR_PackageFile_Parser_v1 + */ + function &parserFactory($version) + { + if (!in_array($version{0}, array('1', '2'))) { + $a = false; + return $a; + } + include_once 'PEAR/PackageFile/Parser/v' . $version{0} . '.php'; + $version = $version{0}; + $class = "PEAR_PackageFile_Parser_v$version"; + $a = new $class; + return $a; + } + + /** + * For simpler unit-testing + * @return string + */ + function getClassPrefix() + { + return 'PEAR_PackageFile_v'; + } + + /** + * Create a PEAR_PackageFile_v* of a given version. + * @param int $version + * @return PEAR_PackageFile_v1|PEAR_PackageFile_v1 + */ + function &factory($version) + { + if (!in_array($version{0}, array('1', '2'))) { + $a = false; + return $a; + } + include_once 'PEAR/PackageFile/v' . $version{0} . '.php'; + $version = $version{0}; + $class = $this->getClassPrefix() . $version; + $a = new $class; + return $a; + } + + /** + * Create a PEAR_PackageFile_v* from its toArray() method + * + * WARNING: no validation is performed, the array is assumed to be valid, + * always parse from xml if you want validation. + * @param array $arr + * @return PEAR_PackageFileManager_v1|PEAR_PackageFileManager_v2 + * @uses factory() to construct the returned object. + */ + function &fromArray($arr) + { + if (isset($arr['xsdversion'])) { + $obj = &$this->factory($arr['xsdversion']); + if ($this->_logger) { + $obj->setLogger($this->_logger); + } + $obj->setConfig($this->_config); + $obj->fromArray($arr); + return $obj; + } else { + if (isset($arr['package']['attribs']['version'])) { + $obj = &$this->factory($arr['package']['attribs']['version']); + } else { + $obj = &$this->factory('1.0'); + } + if ($this->_logger) { + $obj->setLogger($this->_logger); + } + $obj->setConfig($this->_config); + $obj->fromArray($arr); + return $obj; + } + } + + /** + * Create a PEAR_PackageFile_v* from an XML string. + * @access public + * @param string $data contents of package.xml file + * @param int $state package state (one of PEAR_VALIDATE_* constants) + * @param string $file full path to the package.xml file (and the files + * it references) + * @param string $archive optional name of the archive that the XML was + * extracted from, if any + * @return PEAR_PackageFile_v1|PEAR_PackageFile_v2 + * @uses parserFactory() to construct a parser to load the package. + */ + function &fromXmlString($data, $state, $file, $archive = false) + { + if (preg_match('/]+version="([0-9]+\.[0-9]+)"/', $data, $packageversion)) { + if (!in_array($packageversion[1], array('1.0', '2.0', '2.1'))) { + return PEAR::raiseError('package.xml version "' . $packageversion[1] . + '" is not supported, only 1.0, 2.0, and 2.1 are supported.'); + } + $object = &$this->parserFactory($packageversion[1]); + if ($this->_logger) { + $object->setLogger($this->_logger); + } + $object->setConfig($this->_config); + $pf = $object->parse($data, $file, $archive); + if (PEAR::isError($pf)) { + return $pf; + } + if ($this->_rawReturn) { + return $pf; + } + if ($pf->validate($state)) { + if ($this->_logger) { + if ($pf->getValidationWarnings(false)) { + foreach ($pf->getValidationWarnings() as $warning) { + $this->_logger->log(0, 'WARNING: ' . $warning['message']); + } + } + } + if (method_exists($pf, 'flattenFilelist')) { + $pf->flattenFilelist(); // for v2 + } + return $pf; + } else { + if ($this->_config->get('verbose') > 0) { + if ($this->_logger) { + if ($pf->getValidationWarnings(false)) { + foreach ($pf->getValidationWarnings(false) as $warning) { + $this->_logger->log(0, 'ERROR: ' . $warning['message']); + } + } + } + } + $a = PEAR::raiseError('Parsing of package.xml from file "' . $file . '" failed', + 2, null, null, $pf->getValidationWarnings()); + return $a; + } + } elseif (preg_match('/]+version="([^"]+)"/', $data, $packageversion)) { + $a = PEAR::raiseError('package.xml file "' . $file . + '" has unsupported package.xml version "' . $packageversion[1] . '"'); + return $a; + } else { + if (!class_exists('PEAR_ErrorStack')) { + require_once 'PEAR/ErrorStack.php'; + } + PEAR_ErrorStack::staticPush('PEAR_PackageFile', + PEAR_PACKAGEFILE_ERROR_NO_PACKAGEVERSION, + 'warning', array('xml' => $data), 'package.xml "' . $file . + '" has no package.xml version'); + $object = &$this->parserFactory('1.0'); + $object->setConfig($this->_config); + $pf = $object->parse($data, $file, $archive); + if (PEAR::isError($pf)) { + return $pf; + } + if ($this->_rawReturn) { + return $pf; + } + if ($pf->validate($state)) { + if ($this->_logger) { + if ($pf->getValidationWarnings(false)) { + foreach ($pf->getValidationWarnings() as $warning) { + $this->_logger->log(0, 'WARNING: ' . $warning['message']); + } + } + } + if (method_exists($pf, 'flattenFilelist')) { + $pf->flattenFilelist(); // for v2 + } + return $pf; + } else { + $a = PEAR::raiseError('Parsing of package.xml from file "' . $file . '" failed', + 2, null, null, $pf->getValidationWarnings()); + return $a; + } + } + } + + /** + * Register a temporary file or directory. When the destructor is + * executed, all registered temporary files and directories are + * removed. + * + * @param string $file name of file or directory + * @return void + */ + function addTempFile($file) + { + $GLOBALS['_PEAR_Common_tempfiles'][] = $file; + } + + /** + * Create a PEAR_PackageFile_v* from a compresed Tar or Tgz file. + * @access public + * @param string contents of package.xml file + * @param int package state (one of PEAR_VALIDATE_* constants) + * @return PEAR_PackageFile_v1|PEAR_PackageFile_v2 + * @using Archive_Tar to extract the files + * @using fromPackageFile() to load the package after the package.xml + * file is extracted. + */ + function &fromTgzFile($file, $state) + { + if (!class_exists('Archive_Tar')) { + require_once 'Archive/Tar.php'; + } + $tar = new Archive_Tar($file); + if ($this->_debug <= 1) { + $tar->pushErrorHandling(PEAR_ERROR_RETURN); + } + $content = $tar->listContent(); + if ($this->_debug <= 1) { + $tar->popErrorHandling(); + } + if (!is_array($content)) { + if (is_string($file) && strlen($file < 255) && + (!file_exists($file) || !@is_file($file))) { + $ret = PEAR::raiseError("could not open file \"$file\""); + return $ret; + } + $file = realpath($file); + $ret = PEAR::raiseError("Could not get contents of package \"$file\"". + '. Invalid tgz file.'); + return $ret; + } else { + if (!count($content) && !@is_file($file)) { + $ret = PEAR::raiseError("could not open file \"$file\""); + return $ret; + } + } + $xml = null; + $origfile = $file; + foreach ($content as $file) { + $name = $file['filename']; + if ($name == 'package2.xml') { // allow a .tgz to distribute both versions + $xml = $name; + break; + } + if ($name == 'package.xml') { + $xml = $name; + break; + } elseif (ereg('package.xml$', $name, $match)) { + $xml = $name; + break; + } + } + if ($this->_tmpdir) { + $tmpdir = $this->_tmpdir; + } else { + $tmpdir = System::mkTemp(array('-d', 'pear')); + PEAR_PackageFile::addTempFile($tmpdir); + } + $this->_extractErrors(); + PEAR::staticPushErrorHandling(PEAR_ERROR_CALLBACK, array($this, '_extractErrors')); + if (!$xml || !$tar->extractList(array($xml), $tmpdir)) { + $extra = implode("\n", $this->_extractErrors()); + if ($extra) { + $extra = ' ' . $extra; + } + PEAR::staticPopErrorHandling(); + $ret = PEAR::raiseError('could not extract the package.xml file from "' . + $origfile . '"' . $extra); + return $ret; + } + PEAR::staticPopErrorHandling(); + $ret = &PEAR_PackageFile::fromPackageFile("$tmpdir/$xml", $state, $origfile); + return $ret; + } + + /** + * helper for extracting Archive_Tar errors + * @var array + * @access private + */ + var $_extractErrors = array(); + + /** + * helper callback for extracting Archive_Tar errors + * + * @param PEAR_Error|null $err + * @return array + * @access private + */ + function _extractErrors($err = null) + { + static $errors = array(); + if ($err === null) { + $e = $errors; + $errors = array(); + return $e; + } + $errors[] = $err->getMessage(); + } + + /** + * Create a PEAR_PackageFile_v* from a package.xml file. + * + * @access public + * @param string $descfile name of package xml file + * @param int $state package state (one of PEAR_VALIDATE_* constants) + * @param string|false $archive name of the archive this package.xml came + * from, if any + * @return PEAR_PackageFile_v1|PEAR_PackageFile_v2 + * @uses PEAR_PackageFile::fromXmlString to create the oject after the + * XML is loaded from the package.xml file. + */ + function &fromPackageFile($descfile, $state, $archive = false) + { + if (is_string($descfile) && strlen($descfile) < 255 && + (!file_exists($descfile) || !is_file($descfile) || !is_readable($descfile) || + (!$fp = @fopen($descfile, 'r')))) { + $a = PEAR::raiseError("Unable to open $descfile"); + return $a; + } + + // read the whole thing so we only get one cdata callback + // for each block of cdata + fclose($fp); + $data = file_get_contents($descfile); + $ret = &PEAR_PackageFile::fromXmlString($data, $state, $descfile, $archive); + return $ret; + } + + + /** + * Create a PEAR_PackageFile_v* from a .tgz archive or package.xml file. + * + * This method is able to extract information about a package from a .tgz + * archive or from a XML package definition file. + * + * @access public + * @param string $info file name + * @param int $state package state (one of PEAR_VALIDATE_* constants) + * @return PEAR_PackageFile_v1|PEAR_PackageFile_v2 + * @uses fromPackageFile() if the file appears to be XML + * @uses fromTgzFile() to load all non-XML files + */ + function &fromAnyFile($info, $state) + { + if (is_dir($info)) { + $dir_name = realpath($info); + if (file_exists($dir_name . '/package.xml')) { + $info = PEAR_PackageFile::fromPackageFile($dir_name . '/package.xml', $state); + } elseif (file_exists($dir_name . '/package2.xml')) { + $info = PEAR_PackageFile::fromPackageFile($dir_name . '/package2.xml', $state); + } else { + $info = PEAR::raiseError("No package definition found in '$info' directory"); + } + return $info; + } + + $fp = false; + if (is_string($info) && strlen($info) < 255 && + (file_exists($info) || ($fp = @fopen($info, 'r')))) { + if ($fp) { + fclose($fp); + } + $tmp = substr($info, -4); + if ($tmp == '.xml') { + $info = &PEAR_PackageFile::fromPackageFile($info, $state); + } elseif ($tmp == '.tar' || $tmp == '.tgz') { + $info = &PEAR_PackageFile::fromTgzFile($info, $state); + } else { + $fp = fopen($info, "r"); + $test = fread($fp, 5); + fclose($fp); + if ($test == " diff --git a/src/lib/pear/PEAR/PEAR/PackageFile/Generator/v1.php b/src/lib/pear/PEAR/PEAR/PackageFile/Generator/v1.php new file mode 100644 index 0000000..e6c5c94 --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/PackageFile/Generator/v1.php @@ -0,0 +1,1272 @@ + + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: v1.php,v 1.74 2008/01/03 20:26:37 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 1.4.0a1 + */ +/** + * needed for PEAR_VALIDATE_* constants + */ +require_once 'PEAR/Validate.php'; +require_once 'System.php'; +require_once 'PEAR/PackageFile/v2.php'; +/** + * This class converts a PEAR_PackageFile_v1 object into any output format. + * + * Supported output formats include array, XML string, and a PEAR_PackageFile_v2 + * object, for converting package.xml 1.0 into package.xml 2.0 with no sweat. + * @category pear + * @package PEAR + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 1.4.0a1 + */ +class PEAR_PackageFile_Generator_v1 +{ + /** + * @var PEAR_PackageFile_v1 + */ + var $_packagefile; + function PEAR_PackageFile_Generator_v1(&$packagefile) + { + $this->_packagefile = &$packagefile; + } + + function getPackagerVersion() + { + return '1.7.2'; + } + + /** + * @param PEAR_Packager + * @param bool if true, a .tgz is written, otherwise a .tar is written + * @param string|null directory in which to save the .tgz + * @return string|PEAR_Error location of package or error object + */ + function toTgz(&$packager, $compress = true, $where = null) + { + require_once 'Archive/Tar.php'; + if ($where === null) { + if (!($where = System::mktemp(array('-d')))) { + return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: mktemp failed'); + } + } elseif (!@System::mkDir(array('-p', $where))) { + return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: "' . $where . '" could' . + ' not be created'); + } + if (file_exists($where . DIRECTORY_SEPARATOR . 'package.xml') && + !is_file($where . DIRECTORY_SEPARATOR . 'package.xml')) { + return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: unable to save package.xml as' . + ' "' . $where . DIRECTORY_SEPARATOR . 'package.xml"'); + } + if (!$this->_packagefile->validate(PEAR_VALIDATE_PACKAGING)) { + return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: invalid package file'); + } + $pkginfo = $this->_packagefile->getArray(); + $ext = $compress ? '.tgz' : '.tar'; + $pkgver = $pkginfo['package'] . '-' . $pkginfo['version']; + $dest_package = getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext; + if (file_exists(getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext) && + !is_file(getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext)) { + return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: cannot create tgz file "' . + getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext . '"'); + } + if ($pkgfile = $this->_packagefile->getPackageFile()) { + $pkgdir = dirname(realpath($pkgfile)); + $pkgfile = basename($pkgfile); + } else { + return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: package file object must ' . + 'be created from a real file'); + } + // {{{ Create the package file list + $filelist = array(); + $i = 0; + + foreach ($this->_packagefile->getFilelist() as $fname => $atts) { + $file = $pkgdir . DIRECTORY_SEPARATOR . $fname; + if (!file_exists($file)) { + return PEAR::raiseError("File does not exist: $fname"); + } else { + $filelist[$i++] = $file; + if (!isset($atts['md5sum'])) { + $this->_packagefile->setFileAttribute($fname, 'md5sum', md5_file($file)); + } + $packager->log(2, "Adding file $fname"); + } + } + // }}} + $packagexml = $this->toPackageFile($where, PEAR_VALIDATE_PACKAGING, 'package.xml', true); + if ($packagexml) { + $tar =& new Archive_Tar($dest_package, $compress); + $tar->setErrorHandling(PEAR_ERROR_RETURN); // XXX Don't print errors + // ----- Creates with the package.xml file + $ok = $tar->createModify(array($packagexml), '', $where); + if (PEAR::isError($ok)) { + return $ok; + } elseif (!$ok) { + return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: tarball creation failed'); + } + // ----- Add the content of the package + if (!$tar->addModify($filelist, $pkgver, $pkgdir)) { + return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: tarball creation failed'); + } + return $dest_package; + } + } + + /** + * @param string|null directory to place the package.xml in, or null for a temporary dir + * @param int one of the PEAR_VALIDATE_* constants + * @param string name of the generated file + * @param bool if true, then no analysis will be performed on role="php" files + * @return string|PEAR_Error path to the created file on success + */ + function toPackageFile($where = null, $state = PEAR_VALIDATE_NORMAL, $name = 'package.xml', + $nofilechecking = false) + { + if (!$this->_packagefile->validate($state, $nofilechecking)) { + return PEAR::raiseError('PEAR_Packagefile_v1::toPackageFile: invalid package.xml', + null, null, null, $this->_packagefile->getValidationWarnings()); + } + if ($where === null) { + if (!($where = System::mktemp(array('-d')))) { + return PEAR::raiseError('PEAR_Packagefile_v1::toPackageFile: mktemp failed'); + } + } elseif (!@System::mkDir(array('-p', $where))) { + return PEAR::raiseError('PEAR_Packagefile_v1::toPackageFile: "' . $where . '" could' . + ' not be created'); + } + $newpkgfile = $where . DIRECTORY_SEPARATOR . $name; + $np = @fopen($newpkgfile, 'wb'); + if (!$np) { + return PEAR::raiseError('PEAR_Packagefile_v1::toPackageFile: unable to save ' . + "$name as $newpkgfile"); + } + fwrite($np, $this->toXml($state, true)); + fclose($np); + return $newpkgfile; + } + + /** + * fix both XML encoding to be UTF8, and replace standard XML entities < > " & ' + * + * @param string $string + * @return string + * @access private + */ + function _fixXmlEncoding($string) + { + if (version_compare(phpversion(), '5.0.0', 'lt')) { + $string = utf8_encode($string); + } + return strtr($string, array( + '&' => '&', + '>' => '>', + '<' => '<', + '"' => '"', + '\'' => ''' )); + } + + /** + * Return an XML document based on the package info (as returned + * by the PEAR_Common::infoFrom* methods). + * + * @return string XML data + */ + function toXml($state = PEAR_VALIDATE_NORMAL, $nofilevalidation = false) + { + $this->_packagefile->setDate(date('Y-m-d')); + if (!$this->_packagefile->validate($state, $nofilevalidation)) { + return false; + } + $pkginfo = $this->_packagefile->getArray(); + static $maint_map = array( + "handle" => "user", + "name" => "name", + "email" => "email", + "role" => "role", + ); + $ret = "\n"; + $ret .= "\n"; + $ret .= "\n" . +" $pkginfo[package]"; + if (isset($pkginfo['extends'])) { + $ret .= "\n$pkginfo[extends]"; + } + $ret .= + "\n ".$this->_fixXmlEncoding($pkginfo['summary'])."\n" . +" ".trim($this->_fixXmlEncoding($pkginfo['description']))."\n \n" . +" \n"; + foreach ($pkginfo['maintainers'] as $maint) { + $ret .= " \n"; + foreach ($maint_map as $idx => $elm) { + $ret .= " <$elm>"; + $ret .= $this->_fixXmlEncoding($maint[$idx]); + $ret .= "\n"; + } + $ret .= " \n"; + } + $ret .= " \n"; + $ret .= $this->_makeReleaseXml($pkginfo, false, $state); + if (isset($pkginfo['changelog']) && count($pkginfo['changelog']) > 0) { + $ret .= " \n"; + foreach ($pkginfo['changelog'] as $oldrelease) { + $ret .= $this->_makeReleaseXml($oldrelease, true); + } + $ret .= " \n"; + } + $ret .= "\n"; + return $ret; + } + + // }}} + // {{{ _makeReleaseXml() + + /** + * Generate part of an XML description with release information. + * + * @param array $pkginfo array with release information + * @param bool $changelog whether the result will be in a changelog element + * + * @return string XML data + * + * @access private + */ + function _makeReleaseXml($pkginfo, $changelog = false, $state = PEAR_VALIDATE_NORMAL) + { + // XXX QUOTE ENTITIES IN PCDATA, OR EMBED IN CDATA BLOCKS!! + $indent = $changelog ? " " : ""; + $ret = "$indent \n"; + if (!empty($pkginfo['version'])) { + $ret .= "$indent $pkginfo[version]\n"; + } + if (!empty($pkginfo['release_date'])) { + $ret .= "$indent $pkginfo[release_date]\n"; + } + if (!empty($pkginfo['release_license'])) { + $ret .= "$indent $pkginfo[release_license]\n"; + } + if (!empty($pkginfo['release_state'])) { + $ret .= "$indent $pkginfo[release_state]\n"; + } + if (!empty($pkginfo['release_notes'])) { + $ret .= "$indent ".trim($this->_fixXmlEncoding($pkginfo['release_notes'])) + ."\n$indent \n"; + } + if (!empty($pkginfo['release_warnings'])) { + $ret .= "$indent ".$this->_fixXmlEncoding($pkginfo['release_warnings'])."\n"; + } + if (isset($pkginfo['release_deps']) && sizeof($pkginfo['release_deps']) > 0) { + $ret .= "$indent \n"; + foreach ($pkginfo['release_deps'] as $dep) { + $ret .= "$indent _fixXmlEncoding($c['name']) . "\""; + if (isset($c['default'])) { + $ret .= " default=\"" . $this->_fixXmlEncoding($c['default']) . "\""; + } + $ret .= " prompt=\"" . $this->_fixXmlEncoding($c['prompt']) . "\""; + $ret .= "/>\n"; + } + $ret .= "$indent \n"; + } + if (isset($pkginfo['provides'])) { + foreach ($pkginfo['provides'] as $key => $what) { + $ret .= "$indent recursiveXmlFilelist($pkginfo['filelist']); + } else { + foreach ($pkginfo['filelist'] as $file => $fa) { + if (!isset($fa['role'])) { + $fa['role'] = ''; + } + $ret .= "$indent _fixXmlEncoding($fa['baseinstalldir']) . '"'; + } + if (isset($fa['md5sum'])) { + $ret .= " md5sum=\"$fa[md5sum]\""; + } + if (isset($fa['platform'])) { + $ret .= " platform=\"$fa[platform]\""; + } + if (!empty($fa['install-as'])) { + $ret .= ' install-as="' . + $this->_fixXmlEncoding($fa['install-as']) . '"'; + } + $ret .= ' name="' . $this->_fixXmlEncoding($file) . '"'; + if (empty($fa['replacements'])) { + $ret .= "/>\n"; + } else { + $ret .= ">\n"; + foreach ($fa['replacements'] as $r) { + $ret .= "$indent $v) { + $ret .= " $k=\"" . $this->_fixXmlEncoding($v) .'"'; + } + $ret .= "/>\n"; + } + $ret .= "$indent \n"; + } + } + } + $ret .= "$indent \n"; + } + $ret .= "$indent \n"; + return $ret; + } + + /** + * @param array + * @access protected + */ + function recursiveXmlFilelist($list) + { + $this->_dirs = array(); + foreach ($list as $file => $attributes) { + $this->_addDir($this->_dirs, explode('/', dirname($file)), $file, $attributes); + } + return $this->_formatDir($this->_dirs); + } + + /** + * @param array + * @param array + * @param string|null + * @param array|null + * @access private + */ + function _addDir(&$dirs, $dir, $file = null, $attributes = null) + { + if ($dir == array() || $dir == array('.')) { + $dirs['files'][basename($file)] = $attributes; + return; + } + $curdir = array_shift($dir); + if (!isset($dirs['dirs'][$curdir])) { + $dirs['dirs'][$curdir] = array(); + } + $this->_addDir($dirs['dirs'][$curdir], $dir, $file, $attributes); + } + + /** + * @param array + * @param string + * @param string + * @access private + */ + function _formatDir($dirs, $indent = '', $curdir = '') + { + $ret = ''; + if (!count($dirs)) { + return ''; + } + if (isset($dirs['dirs'])) { + uksort($dirs['dirs'], 'strnatcasecmp'); + foreach ($dirs['dirs'] as $dir => $contents) { + $usedir = "$curdir/$dir"; + $ret .= "$indent \n"; + $ret .= $this->_formatDir($contents, "$indent ", $usedir); + $ret .= "$indent \n"; + } + } + if (isset($dirs['files'])) { + uksort($dirs['files'], 'strnatcasecmp'); + foreach ($dirs['files'] as $file => $attribs) { + $ret .= $this->_formatFile($file, $attribs, $indent); + } + } + return $ret; + } + + /** + * @param string + * @param array + * @param string + * @access private + */ + function _formatFile($file, $attributes, $indent) + { + $ret = "$indent _fixXmlEncoding($attributes['baseinstalldir']) . '"'; + } + if (isset($attributes['md5sum'])) { + $ret .= " md5sum=\"$attributes[md5sum]\""; + } + if (isset($attributes['platform'])) { + $ret .= " platform=\"$attributes[platform]\""; + } + if (!empty($attributes['install-as'])) { + $ret .= ' install-as="' . + $this->_fixXmlEncoding($attributes['install-as']) . '"'; + } + $ret .= ' name="' . $this->_fixXmlEncoding($file) . '"'; + if (empty($attributes['replacements'])) { + $ret .= "/>\n"; + } else { + $ret .= ">\n"; + foreach ($attributes['replacements'] as $r) { + $ret .= "$indent $v) { + $ret .= " $k=\"" . $this->_fixXmlEncoding($v) .'"'; + } + $ret .= "/>\n"; + } + $ret .= "$indent \n"; + } + return $ret; + } + + // {{{ _unIndent() + + /** + * Unindent given string (?) + * + * @param string $str The string that has to be unindented. + * @return string + * @access private + */ + function _unIndent($str) + { + // remove leading newlines + $str = preg_replace('/^[\r\n]+/', '', $str); + // find whitespace at the beginning of the first line + $indent_len = strspn($str, " \t"); + $indent = substr($str, 0, $indent_len); + $data = ''; + // remove the same amount of whitespace from following lines + foreach (explode("\n", $str) as $line) { + if (substr($line, 0, $indent_len) == $indent) { + $data .= substr($line, $indent_len) . "\n"; + } + } + return $data; + } + + /** + * @return array + */ + function dependenciesToV2() + { + $arr = array(); + $this->_convertDependencies2_0($arr); + return $arr['dependencies']; + } + + /** + * Convert a package.xml version 1.0 into version 2.0 + * + * Note that this does a basic conversion, to allow more advanced + * features like bundles and multiple releases + * @param string the classname to instantiate and return. This must be + * PEAR_PackageFile_v2 or a descendant + * @param boolean if true, only valid, deterministic package.xml 1.0 as defined by the + * strictest parameters will be converted + * @return PEAR_PackageFile_v2|PEAR_Error + */ + function &toV2($class = 'PEAR_PackageFile_v2', $strict = false) + { + if ($strict) { + if (!$this->_packagefile->validate()) { + $a = PEAR::raiseError('invalid package.xml version 1.0 cannot be converted' . + ' to version 2.0', null, null, null, + $this->_packagefile->getValidationWarnings(true)); + return $a; + } + } + $arr = array( + 'attribs' => array( + 'version' => '2.0', + 'xmlns' => 'http://pear.php.net/dtd/package-2.0', + 'xmlns:tasks' => 'http://pear.php.net/dtd/tasks-1.0', + 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance', + 'xsi:schemaLocation' => "http://pear.php.net/dtd/tasks-1.0\n" . +"http://pear.php.net/dtd/tasks-1.0.xsd\n" . +"http://pear.php.net/dtd/package-2.0\n" . +'http://pear.php.net/dtd/package-2.0.xsd', + ), + 'name' => $this->_packagefile->getPackage(), + 'channel' => 'pear.php.net', + ); + $arr['summary'] = $this->_packagefile->getSummary(); + $arr['description'] = $this->_packagefile->getDescription(); + $maintainers = $this->_packagefile->getMaintainers(); + foreach ($maintainers as $maintainer) { + if ($maintainer['role'] != 'lead') { + continue; + } + $new = array( + 'name' => $maintainer['name'], + 'user' => $maintainer['handle'], + 'email' => $maintainer['email'], + 'active' => 'yes', + ); + $arr['lead'][] = $new; + } + if (!isset($arr['lead'])) { // some people... you know? + $arr['lead'] = array( + 'name' => 'unknown', + 'user' => 'unknown', + 'email' => 'noleadmaintainer@example.com', + 'active' => 'no', + ); + } + if (count($arr['lead']) == 1) { + $arr['lead'] = $arr['lead'][0]; + } + foreach ($maintainers as $maintainer) { + if ($maintainer['role'] == 'lead') { + continue; + } + $new = array( + 'name' => $maintainer['name'], + 'user' => $maintainer['handle'], + 'email' => $maintainer['email'], + 'active' => 'yes', + ); + $arr[$maintainer['role']][] = $new; + } + if (isset($arr['developer']) && count($arr['developer']) == 1) { + $arr['developer'] = $arr['developer'][0]; + } + if (isset($arr['contributor']) && count($arr['contributor']) == 1) { + $arr['contributor'] = $arr['contributor'][0]; + } + if (isset($arr['helper']) && count($arr['helper']) == 1) { + $arr['helper'] = $arr['helper'][0]; + } + $arr['date'] = $this->_packagefile->getDate(); + $arr['version'] = + array( + 'release' => $this->_packagefile->getVersion(), + 'api' => $this->_packagefile->getVersion(), + ); + $arr['stability'] = + array( + 'release' => $this->_packagefile->getState(), + 'api' => $this->_packagefile->getState(), + ); + $licensemap = + array( + 'php' => 'http://www.php.net/license', + 'php license' => 'http://www.php.net/license', + 'lgpl' => 'http://www.gnu.org/copyleft/lesser.html', + 'bsd' => 'http://www.opensource.org/licenses/bsd-license.php', + 'bsd style' => 'http://www.opensource.org/licenses/bsd-license.php', + 'bsd-style' => 'http://www.opensource.org/licenses/bsd-license.php', + 'mit' => 'http://www.opensource.org/licenses/mit-license.php', + 'gpl' => 'http://www.gnu.org/copyleft/gpl.html', + 'apache' => 'http://www.opensource.org/licenses/apache2.0.php' + ); + if (isset($licensemap[strtolower($this->_packagefile->getLicense())])) { + $arr['license'] = array( + 'attribs' => array('uri' => + $licensemap[strtolower($this->_packagefile->getLicense())]), + '_content' => $this->_packagefile->getLicense() + ); + } else { + // don't use bogus uri + $arr['license'] = $this->_packagefile->getLicense(); + } + $arr['notes'] = $this->_packagefile->getNotes(); + $temp = array(); + $arr['contents'] = $this->_convertFilelist2_0($temp); + $this->_convertDependencies2_0($arr); + $release = ($this->_packagefile->getConfigureOptions() || $this->_isExtension) ? + 'extsrcrelease' : 'phprelease'; + if ($release == 'extsrcrelease') { + $arr['channel'] = 'pecl.php.net'; + $arr['providesextension'] = $arr['name']; // assumption + } + $arr[$release] = array(); + if ($this->_packagefile->getConfigureOptions()) { + $arr[$release]['configureoption'] = $this->_packagefile->getConfigureOptions(); + foreach ($arr[$release]['configureoption'] as $i => $opt) { + $arr[$release]['configureoption'][$i] = array('attribs' => $opt); + } + if (count($arr[$release]['configureoption']) == 1) { + $arr[$release]['configureoption'] = $arr[$release]['configureoption'][0]; + } + } + $this->_convertRelease2_0($arr[$release], $temp); + if ($release == 'extsrcrelease' && count($arr[$release]) > 1) { + // multiple extsrcrelease tags added in PEAR 1.4.1 + $arr['dependencies']['required']['pearinstaller']['min'] = '1.4.1'; + } + if ($cl = $this->_packagefile->getChangelog()) { + foreach ($cl as $release) { + $rel = array(); + $rel['version'] = + array( + 'release' => $release['version'], + 'api' => $release['version'], + ); + if (!isset($release['release_state'])) { + $release['release_state'] = 'stable'; + } + $rel['stability'] = + array( + 'release' => $release['release_state'], + 'api' => $release['release_state'], + ); + if (isset($release['release_date'])) { + $rel['date'] = $release['release_date']; + } else { + $rel['date'] = date('Y-m-d'); + } + if (isset($release['release_license'])) { + if (isset($licensemap[strtolower($release['release_license'])])) { + $uri = $licensemap[strtolower($release['release_license'])]; + } else { + $uri = 'http://www.example.com'; + } + $rel['license'] = array( + 'attribs' => array('uri' => $uri), + '_content' => $release['release_license'] + ); + } else { + $rel['license'] = $arr['license']; + } + if (!isset($release['release_notes'])) { + $release['release_notes'] = 'no release notes'; + } + $rel['notes'] = $release['release_notes']; + $arr['changelog']['release'][] = $rel; + } + } + $ret = new $class; + $ret->setConfig($this->_packagefile->_config); + if (isset($this->_packagefile->_logger) && is_object($this->_packagefile->_logger)) { + $ret->setLogger($this->_packagefile->_logger); + } + $ret->fromArray($arr); + return $ret; + } + + /** + * @param array + * @param bool + * @access private + */ + function _convertDependencies2_0(&$release, $internal = false) + { + $peardep = array('pearinstaller' => + array('min' => '1.4.0b1')); // this is a lot safer + $required = $optional = array(); + $release['dependencies'] = array('required' => array()); + if ($this->_packagefile->hasDeps()) { + foreach ($this->_packagefile->getDeps() as $dep) { + if (!isset($dep['optional']) || $dep['optional'] == 'no') { + $required[] = $dep; + } else { + $optional[] = $dep; + } + } + foreach (array('required', 'optional') as $arr) { + $deps = array(); + foreach ($$arr as $dep) { + // organize deps by dependency type and name + if (!isset($deps[$dep['type']])) { + $deps[$dep['type']] = array(); + } + if (isset($dep['name'])) { + $deps[$dep['type']][$dep['name']][] = $dep; + } else { + $deps[$dep['type']][] = $dep; + } + } + do { + if (isset($deps['php'])) { + $php = array(); + if (count($deps['php']) > 1) { + $php = $this->_processPhpDeps($deps['php']); + } else { + if (!isset($deps['php'][0])) { + list($key, $blah) = each ($deps['php']); // stupid buggy versions + $deps['php'] = array($blah[0]); + } + $php = $this->_processDep($deps['php'][0]); + if (!$php) { + break; // poor mans throw + } + } + $release['dependencies'][$arr]['php'] = $php; + } + } while (false); + do { + if (isset($deps['pkg'])) { + $pkg = array(); + $pkg = $this->_processMultipleDepsName($deps['pkg']); + if (!$pkg) { + break; // poor mans throw + } + $release['dependencies'][$arr]['package'] = $pkg; + } + } while (false); + do { + if (isset($deps['ext'])) { + $pkg = array(); + $pkg = $this->_processMultipleDepsName($deps['ext']); + $release['dependencies'][$arr]['extension'] = $pkg; + } + } while (false); + // skip sapi - it's not supported so nobody will have used it + // skip os - it's not supported in 1.0 + } + } + if (isset($release['dependencies']['required'])) { + $release['dependencies']['required'] = + array_merge($peardep, $release['dependencies']['required']); + } else { + $release['dependencies']['required'] = $peardep; + } + if (!isset($release['dependencies']['required']['php'])) { + $release['dependencies']['required']['php'] = + array('min' => '4.0.0'); + } + $order = array(); + $bewm = $release['dependencies']['required']; + $order['php'] = $bewm['php']; + $order['pearinstaller'] = $bewm['pearinstaller']; + isset($bewm['package']) ? $order['package'] = $bewm['package'] :0; + isset($bewm['extension']) ? $order['extension'] = $bewm['extension'] :0; + $release['dependencies']['required'] = $order; + } + + /** + * @param array + * @access private + */ + function _convertFilelist2_0(&$package) + { + $ret = array('dir' => + array( + 'attribs' => array('name' => '/'), + 'file' => array() + ) + ); + $package['platform'] = + $package['install-as'] = array(); + $this->_isExtension = false; + foreach ($this->_packagefile->getFilelist() as $name => $file) { + $file['name'] = $name; + if (isset($file['role']) && $file['role'] == 'src') { + $this->_isExtension = true; + } + if (isset($file['replacements'])) { + $repl = $file['replacements']; + unset($file['replacements']); + } else { + unset($repl); + } + if (isset($file['install-as'])) { + $package['install-as'][$name] = $file['install-as']; + unset($file['install-as']); + } + if (isset($file['platform'])) { + $package['platform'][$name] = $file['platform']; + unset($file['platform']); + } + $file = array('attribs' => $file); + if (isset($repl)) { + foreach ($repl as $replace ) { + $file['tasks:replace'][] = array('attribs' => $replace); + } + if (count($repl) == 1) { + $file['tasks:replace'] = $file['tasks:replace'][0]; + } + } + $ret['dir']['file'][] = $file; + } + return $ret; + } + + /** + * Post-process special files with install-as/platform attributes and + * make the release tag. + * + * This complex method follows this work-flow to create the release tags: + * + *
    +     * - if any install-as/platform exist, create a generic release and fill it with
    +     *   o  tags for 
    +     *   o  tags for 
    +     *   o  tags for 
    +     *   o  tags for 
    +     * - create a release for each platform encountered and fill with
    +     *   o  tags for 
    +     *   o  tags for 
    +     *   o  tags for 
    +     *   o  tags for 
    +     *   o  tags for 
    +     *   o  tags for 
    +     *   o  tags for 
    +     * 
    + * + * It does this by accessing the $package parameter, which contains an array with + * indices: + * + * - platform: mapping of file => OS the file should be installed on + * - install-as: mapping of file => installed name + * - osmap: mapping of OS => list of files that should be installed + * on that OS + * - notosmap: mapping of OS => list of files that should not be + * installed on that OS + * + * @param array + * @param array + * @access private + */ + function _convertRelease2_0(&$release, $package) + { + //- if any install-as/platform exist, create a generic release and fill it with + if (count($package['platform']) || count($package['install-as'])) { + $generic = array(); + $genericIgnore = array(); + foreach ($package['install-as'] as $file => $as) { + //o tags for + if (!isset($package['platform'][$file])) { + $generic[] = $file; + continue; + } + //o tags for + if (isset($package['platform'][$file]) && + $package['platform'][$file]{0} == '!') { + $generic[] = $file; + continue; + } + //o tags for + if (isset($package['platform'][$file]) && + $package['platform'][$file]{0} != '!') { + $genericIgnore[] = $file; + continue; + } + } + foreach ($package['platform'] as $file => $platform) { + if (isset($package['install-as'][$file])) { + continue; + } + if ($platform{0} != '!') { + //o tags for + $genericIgnore[] = $file; + } + } + if (count($package['platform'])) { + $oses = $notplatform = $platform = array(); + foreach ($package['platform'] as $file => $os) { + // get a list of oses + if ($os{0} == '!') { + if (isset($oses[substr($os, 1)])) { + continue; + } + $oses[substr($os, 1)] = count($oses); + } else { + if (isset($oses[$os])) { + continue; + } + $oses[$os] = count($oses); + } + } + //- create a release for each platform encountered and fill with + foreach ($oses as $os => $releaseNum) { + $release[$releaseNum]['installconditions']['os']['name'] = $os; + $release[$releaseNum]['filelist'] = array('install' => array(), + 'ignore' => array()); + foreach ($package['install-as'] as $file => $as) { + //o tags for + if (!isset($package['platform'][$file])) { + $release[$releaseNum]['filelist']['install'][] = + array( + 'attribs' => array( + 'name' => $file, + 'as' => $as, + ), + ); + continue; + } + //o tags for + // + if (isset($package['platform'][$file]) && + $package['platform'][$file] == $os) { + $release[$releaseNum]['filelist']['install'][] = + array( + 'attribs' => array( + 'name' => $file, + 'as' => $as, + ), + ); + continue; + } + //o tags for + // + if (isset($package['platform'][$file]) && + $package['platform'][$file] != "!$os" && + $package['platform'][$file]{0} == '!') { + $release[$releaseNum]['filelist']['install'][] = + array( + 'attribs' => array( + 'name' => $file, + 'as' => $as, + ), + ); + continue; + } + //o tags for + // + if (isset($package['platform'][$file]) && + $package['platform'][$file] == "!$os") { + $release[$releaseNum]['filelist']['ignore'][] = + array( + 'attribs' => array( + 'name' => $file, + ), + ); + continue; + } + //o tags for + // + if (isset($package['platform'][$file]) && + $package['platform'][$file]{0} != '!' && + $package['platform'][$file] != $os) { + $release[$releaseNum]['filelist']['ignore'][] = + array( + 'attribs' => array( + 'name' => $file, + ), + ); + continue; + } + } + foreach ($package['platform'] as $file => $platform) { + if (isset($package['install-as'][$file])) { + continue; + } + //o tags for + if ($platform == "!$os") { + $release[$releaseNum]['filelist']['ignore'][] = + array( + 'attribs' => array( + 'name' => $file, + ), + ); + continue; + } + //o tags for + if ($platform{0} != '!' && $platform != $os) { + $release[$releaseNum]['filelist']['ignore'][] = + array( + 'attribs' => array( + 'name' => $file, + ), + ); + } + } + if (!count($release[$releaseNum]['filelist']['install'])) { + unset($release[$releaseNum]['filelist']['install']); + } + if (!count($release[$releaseNum]['filelist']['ignore'])) { + unset($release[$releaseNum]['filelist']['ignore']); + } + } + if (count($generic) || count($genericIgnore)) { + $release[count($oses)] = array(); + if (count($generic)) { + foreach ($generic as $file) { + if (isset($package['install-as'][$file])) { + $installas = $package['install-as'][$file]; + } else { + $installas = $file; + } + $release[count($oses)]['filelist']['install'][] = + array( + 'attribs' => array( + 'name' => $file, + 'as' => $installas, + ) + ); + } + } + if (count($genericIgnore)) { + foreach ($genericIgnore as $file) { + $release[count($oses)]['filelist']['ignore'][] = + array( + 'attribs' => array( + 'name' => $file, + ) + ); + } + } + } + // cleanup + foreach ($release as $i => $rel) { + if (isset($rel['filelist']['install']) && + count($rel['filelist']['install']) == 1) { + $release[$i]['filelist']['install'] = + $release[$i]['filelist']['install'][0]; + } + if (isset($rel['filelist']['ignore']) && + count($rel['filelist']['ignore']) == 1) { + $release[$i]['filelist']['ignore'] = + $release[$i]['filelist']['ignore'][0]; + } + } + if (count($release) == 1) { + $release = $release[0]; + } + } else { + // no platform atts, but some install-as atts + foreach ($package['install-as'] as $file => $value) { + $release['filelist']['install'][] = + array( + 'attribs' => array( + 'name' => $file, + 'as' => $value + ) + ); + } + if (count($release['filelist']['install']) == 1) { + $release['filelist']['install'] = $release['filelist']['install'][0]; + } + } + } + } + + /** + * @param array + * @return array + * @access private + */ + function _processDep($dep) + { + if ($dep['type'] == 'php') { + if ($dep['rel'] == 'has') { + // come on - everyone has php! + return false; + } + } + $php = array(); + if ($dep['type'] != 'php') { + $php['name'] = $dep['name']; + if ($dep['type'] == 'pkg') { + $php['channel'] = 'pear.php.net'; + } + } + switch ($dep['rel']) { + case 'gt' : + $php['min'] = $dep['version']; + $php['exclude'] = $dep['version']; + break; + case 'ge' : + if (!isset($dep['version'])) { + if ($dep['type'] == 'php') { + if (isset($dep['name'])) { + $dep['version'] = $dep['name']; + } + } + } + $php['min'] = $dep['version']; + break; + case 'lt' : + $php['max'] = $dep['version']; + $php['exclude'] = $dep['version']; + break; + case 'le' : + $php['max'] = $dep['version']; + break; + case 'eq' : + $php['min'] = $dep['version']; + $php['max'] = $dep['version']; + break; + case 'ne' : + $php['exclude'] = $dep['version']; + break; + case 'not' : + $php['conflicts'] = 'yes'; + break; + } + return $php; + } + + /** + * @param array + * @return array + */ + function _processPhpDeps($deps) + { + $test = array(); + foreach ($deps as $dep) { + $test[] = $this->_processDep($dep); + } + $min = array(); + $max = array(); + foreach ($test as $dep) { + if (!$dep) { + continue; + } + if (isset($dep['min'])) { + $min[$dep['min']] = count($min); + } + if (isset($dep['max'])) { + $max[$dep['max']] = count($max); + } + } + if (count($min) > 0) { + uksort($min, 'version_compare'); + } + if (count($max) > 0) { + uksort($max, 'version_compare'); + } + if (count($min)) { + // get the highest minimum + $min = array_pop($a = array_flip($min)); + } else { + $min = false; + } + if (count($max)) { + // get the lowest maximum + $max = array_shift($a = array_flip($max)); + } else { + $max = false; + } + if ($min) { + $php['min'] = $min; + } + if ($max) { + $php['max'] = $max; + } + $exclude = array(); + foreach ($test as $dep) { + if (!isset($dep['exclude'])) { + continue; + } + $exclude[] = $dep['exclude']; + } + if (count($exclude)) { + $php['exclude'] = $exclude; + } + return $php; + } + + /** + * process multiple dependencies that have a name, like package deps + * @param array + * @return array + * @access private + */ + function _processMultipleDepsName($deps) + { + $tests = array(); + foreach ($deps as $name => $dep) { + foreach ($dep as $d) { + $tests[$name][] = $this->_processDep($d); + } + } + foreach ($tests as $name => $test) { + $php = array(); + $min = array(); + $max = array(); + $php['name'] = $name; + foreach ($test as $dep) { + if (!$dep) { + continue; + } + if (isset($dep['channel'])) { + $php['channel'] = 'pear.php.net'; + } + if (isset($dep['conflicts']) && $dep['conflicts'] == 'yes') { + $php['conflicts'] = 'yes'; + } + if (isset($dep['min'])) { + $min[$dep['min']] = count($min); + } + if (isset($dep['max'])) { + $max[$dep['max']] = count($max); + } + } + if (count($min) > 0) { + uksort($min, 'version_compare'); + } + if (count($max) > 0) { + uksort($max, 'version_compare'); + } + if (count($min)) { + // get the highest minimum + $min = array_pop($a = array_flip($min)); + } else { + $min = false; + } + if (count($max)) { + // get the lowest maximum + $max = array_shift($a = array_flip($max)); + } else { + $max = false; + } + if ($min) { + $php['min'] = $min; + } + if ($max) { + $php['max'] = $max; + } + $exclude = array(); + foreach ($test as $dep) { + if (!isset($dep['exclude'])) { + continue; + } + $exclude[] = $dep['exclude']; + } + if (count($exclude)) { + $php['exclude'] = $exclude; + } + $ret[] = $php; + } + return $ret; + } +} +?> \ No newline at end of file diff --git a/src/lib/pear/PEAR/PEAR/PackageFile/Generator/v2.php b/src/lib/pear/PEAR/PEAR/PackageFile/Generator/v2.php new file mode 100644 index 0000000..fb8d2f9 --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/PackageFile/Generator/v2.php @@ -0,0 +1,1531 @@ + + * @author Stephan Schmidt (original XML_Serializer code) + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: v2.php,v 1.39 2008/05/13 05:29:24 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 1.4.0a1 + */ +/** + * file/dir manipulation routines + */ +require_once 'System.php'; +/** + * This class converts a PEAR_PackageFile_v2 object into any output format. + * + * Supported output formats include array, XML string (using S. Schmidt's + * XML_Serializer, slightly customized) + * @category pear + * @package PEAR + * @author Greg Beaver + * @author Stephan Schmidt (original XML_Serializer code) + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 1.4.0a1 + */ +class PEAR_PackageFile_Generator_v2 +{ + /** + * default options for the serialization + * @access private + * @var array $_defaultOptions + */ + var $_defaultOptions = array( + 'indent' => ' ', // string used for indentation + 'linebreak' => "\n", // string used for newlines + 'typeHints' => false, // automatically add type hin attributes + 'addDecl' => true, // add an XML declaration + 'defaultTagName' => 'XML_Serializer_Tag', // tag used for indexed arrays or invalid names + 'classAsTagName' => false, // use classname for objects in indexed arrays + 'keyAttribute' => '_originalKey', // attribute where original key is stored + 'typeAttribute' => '_type', // attribute for type (only if typeHints => true) + 'classAttribute' => '_class', // attribute for class of objects (only if typeHints => true) + 'scalarAsAttributes' => false, // scalar values (strings, ints,..) will be serialized as attribute + 'prependAttributes' => '', // prepend string for attributes + 'indentAttributes' => false, // indent the attributes, if set to '_auto', it will indent attributes so they all start at the same column + 'mode' => 'simplexml', // use 'simplexml' to use parent name as tagname if transforming an indexed array + 'addDoctype' => false, // add a doctype declaration + 'doctype' => null, // supply a string or an array with id and uri ({@see PEAR_PackageFile_Generator_v2_PEAR_PackageFile_Generator_v2_XML_Util::getDoctypeDeclaration()} + 'rootName' => 'package', // name of the root tag + 'rootAttributes' => array( + 'version' => '2.0', + 'xmlns' => 'http://pear.php.net/dtd/package-2.0', + 'xmlns:tasks' => 'http://pear.php.net/dtd/tasks-1.0', + 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance', + 'xsi:schemaLocation' => 'http://pear.php.net/dtd/tasks-1.0 +http://pear.php.net/dtd/tasks-1.0.xsd +http://pear.php.net/dtd/package-2.0 +http://pear.php.net/dtd/package-2.0.xsd', + ), // attributes of the root tag + 'attributesArray' => 'attribs', // all values in this key will be treated as attributes + 'contentName' => '_content', // this value will be used directly as content, instead of creating a new tag, may only be used in conjuction with attributesArray + 'beautifyFilelist' => false, + 'encoding' => 'UTF-8', + ); + + /** + * options for the serialization + * @access private + * @var array $options + */ + var $options = array(); + + /** + * current tag depth + * @var integer $_tagDepth + */ + var $_tagDepth = 0; + + /** + * serilialized representation of the data + * @var string $_serializedData + */ + var $_serializedData = null; + /** + * @var PEAR_PackageFile_v2 + */ + var $_packagefile; + /** + * @param PEAR_PackageFile_v2 + */ + function PEAR_PackageFile_Generator_v2(&$packagefile) + { + $this->_packagefile = &$packagefile; + } + + /** + * @return string + */ + function getPackagerVersion() + { + return '1.7.2'; + } + + /** + * @param PEAR_Packager + * @param bool generate a .tgz or a .tar + * @param string|null temporary directory to package in + */ + function toTgz(&$packager, $compress = true, $where = null) + { + $a = null; + return $this->toTgz2($packager, $a, $compress, $where); + } + + /** + * Package up both a package.xml and package2.xml for the same release + * @param PEAR_Packager + * @param PEAR_PackageFile_v1 + * @param bool generate a .tgz or a .tar + * @param string|null temporary directory to package in + */ + function toTgz2(&$packager, &$pf1, $compress = true, $where = null) + { + require_once 'Archive/Tar.php'; + if (!$this->_packagefile->isEquivalent($pf1)) { + return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: "' . + basename($pf1->getPackageFile()) . + '" is not equivalent to "' . basename($this->_packagefile->getPackageFile()) + . '"'); + } + if ($where === null) { + if (!($where = System::mktemp(array('-d')))) { + return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: mktemp failed'); + } + } elseif (!@System::mkDir(array('-p', $where))) { + return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: "' . $where . '" could' . + ' not be created'); + } + if (file_exists($where . DIRECTORY_SEPARATOR . 'package.xml') && + !is_file($where . DIRECTORY_SEPARATOR . 'package.xml')) { + return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: unable to save package.xml as' . + ' "' . $where . DIRECTORY_SEPARATOR . 'package.xml"'); + } + if (!$this->_packagefile->validate(PEAR_VALIDATE_PACKAGING)) { + return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: invalid package.xml'); + } + $ext = $compress ? '.tgz' : '.tar'; + $pkgver = $this->_packagefile->getPackage() . '-' . $this->_packagefile->getVersion(); + $dest_package = getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext; + if (file_exists(getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext) && + !is_file(getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext)) { + return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: cannot create tgz file "' . + getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext . '"'); + } + if ($pkgfile = $this->_packagefile->getPackageFile()) { + $pkgdir = dirname(realpath($pkgfile)); + $pkgfile = basename($pkgfile); + } else { + return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: package file object must ' . + 'be created from a real file'); + } + // {{{ Create the package file list + $filelist = array(); + $i = 0; + $this->_packagefile->flattenFilelist(); + $contents = $this->_packagefile->getContents(); + if (isset($contents['bundledpackage'])) { // bundles of packages + $contents = $contents['bundledpackage']; + if (!isset($contents[0])) { + $contents = array($contents); + } + $packageDir = $where; + foreach ($contents as $i => $package) { + $fname = $package; + $file = $pkgdir . DIRECTORY_SEPARATOR . $fname; + if (!file_exists($file)) { + return $packager->raiseError("File does not exist: $fname"); + } + $tfile = $packageDir . DIRECTORY_SEPARATOR . $fname; + System::mkdir(array('-p', dirname($tfile))); + copy($file, $tfile); + $filelist[$i++] = $tfile; + $packager->log(2, "Adding package $fname"); + } + } else { // normal packages + $contents = $contents['dir']['file']; + if (!isset($contents[0])) { + $contents = array($contents); + } + + $packageDir = $where; + foreach ($contents as $i => $file) { + $fname = $file['attribs']['name']; + $atts = $file['attribs']; + $orig = $file; + $file = $pkgdir . DIRECTORY_SEPARATOR . $fname; + if (!file_exists($file)) { + return $packager->raiseError("File does not exist: $fname"); + } else { + $origperms = fileperms($file); + $tfile = $packageDir . DIRECTORY_SEPARATOR . $fname; + unset($orig['attribs']); + if (count($orig)) { // file with tasks + // run any package-time tasks + $contents = file_get_contents($file); + foreach ($orig as $tag => $raw) { + $tag = str_replace( + array($this->_packagefile->getTasksNs() . ':', '-'), + array('', '_'), $tag); + $task = "PEAR_Task_$tag"; + $task = &new $task($this->_packagefile->_config, + $this->_packagefile->_logger, + PEAR_TASK_PACKAGE); + $task->init($raw, $atts, null); + $res = $task->startSession($this->_packagefile, $contents, $tfile); + if (!$res) { + continue; // skip this task + } + if (PEAR::isError($res)) { + return $res; + } + $contents = $res; // save changes + System::mkdir(array('-p', dirname($tfile))); + $wp = fopen($tfile, "wb"); + fwrite($wp, $contents); + fclose($wp); + } + } + if (!file_exists($tfile)) { + System::mkdir(array('-p', dirname($tfile))); + copy($file, $tfile); + } + chmod($tfile, $origperms); + $filelist[$i++] = $tfile; + $this->_packagefile->setFileAttribute($fname, 'md5sum', md5_file($tfile), $i - 1); + $packager->log(2, "Adding file $fname"); + } + } + } + // }}} + if ($pf1 !== null) { + $name = 'package2.xml'; + } else { + $name = 'package.xml'; + } + $packagexml = $this->toPackageFile($where, PEAR_VALIDATE_PACKAGING, $name); + if ($packagexml) { + $tar =& new Archive_Tar($dest_package, $compress); + $tar->setErrorHandling(PEAR_ERROR_RETURN); // XXX Don't print errors + // ----- Creates with the package.xml file + $ok = $tar->createModify(array($packagexml), '', $where); + if (PEAR::isError($ok)) { + return $packager->raiseError($ok); + } elseif (!$ok) { + return $packager->raiseError('PEAR_Packagefile_v2::toTgz(): adding ' . $name . + ' failed'); + } + // ----- Add the content of the package + if (!$tar->addModify($filelist, $pkgver, $where)) { + return $packager->raiseError( + 'PEAR_Packagefile_v2::toTgz(): tarball creation failed'); + } + // add the package.xml version 1.0 + if ($pf1 !== null) { + $pfgen = &$pf1->getDefaultGenerator(); + $packagexml1 = $pfgen->toPackageFile($where, PEAR_VALIDATE_PACKAGING, + 'package.xml', true); + if (!$tar->addModify(array($packagexml1), '', $where)) { + return $packager->raiseError( + 'PEAR_Packagefile_v2::toTgz(): adding package.xml failed'); + } + } + return $dest_package; + } + } + + function toPackageFile($where = null, $state = PEAR_VALIDATE_NORMAL, $name = 'package.xml') + { + if (!$this->_packagefile->validate($state)) { + return PEAR::raiseError('PEAR_Packagefile_v2::toPackageFile: invalid package.xml', + null, null, null, $this->_packagefile->getValidationWarnings()); + } + if ($where === null) { + if (!($where = System::mktemp(array('-d')))) { + return PEAR::raiseError('PEAR_Packagefile_v2::toPackageFile: mktemp failed'); + } + } elseif (!@System::mkDir(array('-p', $where))) { + return PEAR::raiseError('PEAR_Packagefile_v2::toPackageFile: "' . $where . '" could' . + ' not be created'); + } + $newpkgfile = $where . DIRECTORY_SEPARATOR . $name; + $np = @fopen($newpkgfile, 'wb'); + if (!$np) { + return PEAR::raiseError('PEAR_Packagefile_v2::toPackageFile: unable to save ' . + "$name as $newpkgfile"); + } + fwrite($np, $this->toXml($state)); + fclose($np); + return $newpkgfile; + } + + function &toV2() + { + return $this->_packagefile; + } + + /** + * Return an XML document based on the package info (as returned + * by the PEAR_Common::infoFrom* methods). + * + * @return string XML data + */ + function toXml($state = PEAR_VALIDATE_NORMAL, $options = array()) + { + $this->_packagefile->setDate(date('Y-m-d')); + $this->_packagefile->setTime(date('H:i:s')); + if (!$this->_packagefile->validate($state)) { + return false; + } + if (is_array($options)) { + $this->options = array_merge($this->_defaultOptions, $options); + } else { + $this->options = $this->_defaultOptions; + } + $arr = $this->_packagefile->getArray(); + if (isset($arr['filelist'])) { + unset($arr['filelist']); + } + if (isset($arr['_lastversion'])) { + unset($arr['_lastversion']); + } + if ($state ^ PEAR_VALIDATE_PACKAGING && !isset($arr['bundle'])) { + $use = $this->_recursiveXmlFilelist($arr['contents']['dir']['file']); + unset($arr['contents']['dir']['file']); + if (isset($use['dir'])) { + $arr['contents']['dir']['dir'] = $use['dir']; + } + if (isset($use['file'])) { + $arr['contents']['dir']['file'] = $use['file']; + } + $this->options['beautifyFilelist'] = true; + } + $arr['attribs']['packagerversion'] = '1.7.2'; + if ($this->serialize($arr, $options)) { + return $this->_serializedData . "\n"; + } + return false; + } + + + function _recursiveXmlFilelist($list) + { + $dirs = array(); + if (isset($list['attribs'])) { + $file = $list['attribs']['name']; + unset($list['attribs']['name']); + $attributes = $list['attribs']; + $this->_addDir($dirs, explode('/', dirname($file)), $file, $attributes); + } else { + foreach ($list as $a) { + $file = $a['attribs']['name']; + $attributes = $a['attribs']; + unset($a['attribs']); + $this->_addDir($dirs, explode('/', dirname($file)), $file, $attributes, $a); + } + } + $this->_formatDir($dirs); + $this->_deFormat($dirs); + return $dirs; + } + + function _addDir(&$dirs, $dir, $file = null, $attributes = null, $tasks = null) + { + if (!$tasks) { + $tasks = array(); + } + if ($dir == array() || $dir == array('.')) { + $dirs['file'][basename($file)] = $tasks; + $attributes['name'] = basename($file); + $dirs['file'][basename($file)]['attribs'] = $attributes; + return; + } + $curdir = array_shift($dir); + if (!isset($dirs['dir'][$curdir])) { + $dirs['dir'][$curdir] = array(); + } + $this->_addDir($dirs['dir'][$curdir], $dir, $file, $attributes, $tasks); + } + + function _formatDir(&$dirs) + { + if (!count($dirs)) { + return array(); + } + $newdirs = array(); + if (isset($dirs['dir'])) { + $newdirs['dir'] = $dirs['dir']; + } + if (isset($dirs['file'])) { + $newdirs['file'] = $dirs['file']; + } + $dirs = $newdirs; + if (isset($dirs['dir'])) { + uksort($dirs['dir'], 'strnatcasecmp'); + foreach ($dirs['dir'] as $dir => $contents) { + $this->_formatDir($dirs['dir'][$dir]); + } + } + if (isset($dirs['file'])) { + uksort($dirs['file'], 'strnatcasecmp'); + }; + } + + function _deFormat(&$dirs) + { + if (!count($dirs)) { + return array(); + } + $newdirs = array(); + if (isset($dirs['dir'])) { + foreach ($dirs['dir'] as $dir => $contents) { + $newdir = array(); + $newdir['attribs']['name'] = $dir; + $this->_deFormat($contents); + foreach ($contents as $tag => $val) { + $newdir[$tag] = $val; + } + $newdirs['dir'][] = $newdir; + } + if (count($newdirs['dir']) == 1) { + $newdirs['dir'] = $newdirs['dir'][0]; + } + } + if (isset($dirs['file'])) { + foreach ($dirs['file'] as $name => $file) { + $newdirs['file'][] = $file; + } + if (count($newdirs['file']) == 1) { + $newdirs['file'] = $newdirs['file'][0]; + } + } + $dirs = $newdirs; + } + + /** + * reset all options to default options + * + * @access public + * @see setOption(), XML_Unserializer() + */ + function resetOptions() + { + $this->options = $this->_defaultOptions; + } + + /** + * set an option + * + * You can use this method if you do not want to set all options in the constructor + * + * @access public + * @see resetOption(), XML_Serializer() + */ + function setOption($name, $value) + { + $this->options[$name] = $value; + } + + /** + * sets several options at once + * + * You can use this method if you do not want to set all options in the constructor + * + * @access public + * @see resetOption(), XML_Unserializer(), setOption() + */ + function setOptions($options) + { + $this->options = array_merge($this->options, $options); + } + + /** + * serialize data + * + * @access public + * @param mixed $data data to serialize + * @return boolean true on success, pear error on failure + */ + function serialize($data, $options = null) + { + // if options have been specified, use them instead + // of the previously defined ones + if (is_array($options)) { + $optionsBak = $this->options; + if (isset($options['overrideOptions']) && $options['overrideOptions'] == true) { + $this->options = array_merge($this->_defaultOptions, $options); + } else { + $this->options = array_merge($this->options, $options); + } + } + else { + $optionsBak = null; + } + + // start depth is zero + $this->_tagDepth = 0; + + $this->_serializedData = ''; + // serialize an array + if (is_array($data)) { + if (isset($this->options['rootName'])) { + $tagName = $this->options['rootName']; + } else { + $tagName = 'array'; + } + + $this->_serializedData .= $this->_serializeArray($data, $tagName, $this->options['rootAttributes']); + } + + // add doctype declaration + if ($this->options['addDoctype'] === true) { + $this->_serializedData = PEAR_PackageFile_Generator_v2_XML_Util::getDoctypeDeclaration($tagName, $this->options['doctype']) + . $this->options['linebreak'] + . $this->_serializedData; + } + + // build xml declaration + if ($this->options['addDecl']) { + $atts = array(); + if (isset($this->options['encoding']) ) { + $encoding = $this->options['encoding']; + } else { + $encoding = null; + } + $this->_serializedData = PEAR_PackageFile_Generator_v2_XML_Util::getXMLDeclaration('1.0', $encoding) + . $this->options['linebreak'] + . $this->_serializedData; + } + + + if ($optionsBak !== null) { + $this->options = $optionsBak; + } + + return true; + } + + /** + * get the result of the serialization + * + * @access public + * @return string serialized XML + */ + function getSerializedData() + { + if ($this->_serializedData == null ) { + return $this->raiseError('No serialized data available. Use XML_Serializer::serialize() first.', XML_SERIALIZER_ERROR_NO_SERIALIZATION); + } + return $this->_serializedData; + } + + /** + * serialize any value + * + * This method checks for the type of the value and calls the appropriate method + * + * @access private + * @param mixed $value + * @param string $tagName + * @param array $attributes + * @return string + */ + function _serializeValue($value, $tagName = null, $attributes = array()) + { + if (is_array($value)) { + $xml = $this->_serializeArray($value, $tagName, $attributes); + } elseif (is_object($value)) { + $xml = $this->_serializeObject($value, $tagName); + } else { + $tag = array( + 'qname' => $tagName, + 'attributes' => $attributes, + 'content' => $value + ); + $xml = $this->_createXMLTag($tag); + } + return $xml; + } + + /** + * serialize an array + * + * @access private + * @param array $array array to serialize + * @param string $tagName name of the root tag + * @param array $attributes attributes for the root tag + * @return string $string serialized data + * @uses PEAR_PackageFile_Generator_v2_XML_Util::isValidName() to check, whether key has to be substituted + */ + function _serializeArray(&$array, $tagName = null, $attributes = array()) + { + $_content = null; + + /** + * check for special attributes + */ + if ($this->options['attributesArray'] !== null) { + if (isset($array[$this->options['attributesArray']])) { + $attributes = $array[$this->options['attributesArray']]; + unset($array[$this->options['attributesArray']]); + } + /** + * check for special content + */ + if ($this->options['contentName'] !== null) { + if (isset($array[$this->options['contentName']])) { + $_content = $array[$this->options['contentName']]; + unset($array[$this->options['contentName']]); + } + } + } + + /* + * if mode is set to simpleXML, check whether + * the array is associative or indexed + */ + if (is_array($array) && $this->options['mode'] == 'simplexml') { + $indexed = true; + if (!count($array)) { + $indexed = false; + } + foreach ($array as $key => $val) { + if (!is_int($key)) { + $indexed = false; + break; + } + } + + if ($indexed && $this->options['mode'] == 'simplexml') { + $string = ''; + foreach ($array as $key => $val) { + if ($this->options['beautifyFilelist'] && $tagName == 'dir') { + if (!isset($this->_curdir)) { + $this->_curdir = ''; + } + $savedir = $this->_curdir; + if (isset($val['attribs'])) { + if ($val['attribs']['name'] == '/') { + $this->_curdir = '/'; + } else { + if ($this->_curdir == '/') { + $this->_curdir = ''; + } + $this->_curdir .= '/' . $val['attribs']['name']; + } + } + } + $string .= $this->_serializeValue( $val, $tagName, $attributes); + if ($this->options['beautifyFilelist'] && $tagName == 'dir') { + $string .= ' '; + if (empty($savedir)) { + unset($this->_curdir); + } else { + $this->_curdir = $savedir; + } + } + + $string .= $this->options['linebreak']; + // do indentation + if ($this->options['indent']!==null && $this->_tagDepth>0) { + $string .= str_repeat($this->options['indent'], $this->_tagDepth); + } + } + return rtrim($string); + } + } + + if ($this->options['scalarAsAttributes'] === true) { + foreach ($array as $key => $value) { + if (is_scalar($value) && (PEAR_PackageFile_Generator_v2_XML_Util::isValidName($key) === true)) { + unset($array[$key]); + $attributes[$this->options['prependAttributes'].$key] = $value; + } + } + } + + // check for empty array => create empty tag + if (empty($array)) { + $tag = array( + 'qname' => $tagName, + 'content' => $_content, + 'attributes' => $attributes + ); + + } else { + $this->_tagDepth++; + $tmp = $this->options['linebreak']; + foreach ($array as $key => $value) { + // do indentation + if ($this->options['indent']!==null && $this->_tagDepth>0) { + $tmp .= str_repeat($this->options['indent'], $this->_tagDepth); + } + + // copy key + $origKey = $key; + // key cannot be used as tagname => use default tag + $valid = PEAR_PackageFile_Generator_v2_XML_Util::isValidName($key); + if (PEAR::isError($valid)) { + if ($this->options['classAsTagName'] && is_object($value)) { + $key = get_class($value); + } else { + $key = $this->options['defaultTagName']; + } + } + $atts = array(); + if ($this->options['typeHints'] === true) { + $atts[$this->options['typeAttribute']] = gettype($value); + if ($key !== $origKey) { + $atts[$this->options['keyAttribute']] = (string)$origKey; + } + + } + if ($this->options['beautifyFilelist'] && $key == 'dir') { + if (!isset($this->_curdir)) { + $this->_curdir = ''; + } + $savedir = $this->_curdir; + if (isset($value['attribs'])) { + if ($value['attribs']['name'] == '/') { + $this->_curdir = '/'; + } else { + $this->_curdir .= '/' . $value['attribs']['name']; + } + } + } + + if (is_string($value) && $value && ($value{strlen($value) - 1} == "\n")) { + $value .= str_repeat($this->options['indent'], $this->_tagDepth); + } + $tmp .= $this->_createXMLTag(array( + 'qname' => $key, + 'attributes' => $atts, + 'content' => $value ) + ); + if ($this->options['beautifyFilelist'] && $key == 'dir') { + if (isset($value['attribs'])) { + $tmp .= ' '; + if (empty($savedir)) { + unset($this->_curdir); + } else { + $this->_curdir = $savedir; + } + } + } + $tmp .= $this->options['linebreak']; + } + + $this->_tagDepth--; + if ($this->options['indent']!==null && $this->_tagDepth>0) { + $tmp .= str_repeat($this->options['indent'], $this->_tagDepth); + } + + if (trim($tmp) === '') { + $tmp = null; + } + + $tag = array( + 'qname' => $tagName, + 'content' => $tmp, + 'attributes' => $attributes + ); + } + if ($this->options['typeHints'] === true) { + if (!isset($tag['attributes'][$this->options['typeAttribute']])) { + $tag['attributes'][$this->options['typeAttribute']] = 'array'; + } + } + + $string = $this->_createXMLTag($tag, false); + return $string; + } + + /** + * create a tag from an array + * this method awaits an array in the following format + * array( + * 'qname' => $tagName, + * 'attributes' => array(), + * 'content' => $content, // optional + * 'namespace' => $namespace // optional + * 'namespaceUri' => $namespaceUri // optional + * ) + * + * @access private + * @param array $tag tag definition + * @param boolean $replaceEntities whether to replace XML entities in content or not + * @return string $string XML tag + */ + function _createXMLTag( $tag, $replaceEntities = true ) + { + if ($this->options['indentAttributes'] !== false) { + $multiline = true; + $indent = str_repeat($this->options['indent'], $this->_tagDepth); + + if ($this->options['indentAttributes'] == '_auto') { + $indent .= str_repeat(' ', (strlen($tag['qname'])+2)); + + } else { + $indent .= $this->options['indentAttributes']; + } + } else { + $multiline = false; + $indent = false; + } + + if (is_array($tag['content'])) { + if (empty($tag['content'])) { + $tag['content'] = ''; + } + } elseif(is_scalar($tag['content']) && (string)$tag['content'] == '') { + $tag['content'] = ''; + } + + if (is_scalar($tag['content']) || is_null($tag['content'])) { + if ($this->options['encoding'] == 'UTF-8' && + version_compare(phpversion(), '5.0.0', 'lt')) { + $encoding = PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_UTF8_XML; + } else { + $encoding = PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_XML; + } + $tag = PEAR_PackageFile_Generator_v2_XML_Util::createTagFromArray($tag, $replaceEntities, $multiline, $indent, $this->options['linebreak'], $encoding); + } elseif (is_array($tag['content'])) { + $tag = $this->_serializeArray($tag['content'], $tag['qname'], $tag['attributes']); + } elseif (is_object($tag['content'])) { + $tag = $this->_serializeObject($tag['content'], $tag['qname'], $tag['attributes']); + } elseif (is_resource($tag['content'])) { + settype($tag['content'], 'string'); + $tag = PEAR_PackageFile_Generator_v2_XML_Util::createTagFromArray($tag, $replaceEntities); + } + return $tag; + } +} + +// well, it's one way to do things without extra deps ... +/* vim: set expandtab tabstop=4 shiftwidth=4: */ +// +----------------------------------------------------------------------+ +// | PHP Version 4 | +// +----------------------------------------------------------------------+ +// | Copyright (c) 1997-2002 The PHP Group | +// +----------------------------------------------------------------------+ +// | This source file is subject to version 2.0 of the PHP license, | +// | that is bundled with this package in the file LICENSE, and is | +// | available at through the world-wide-web at | +// | http://www.php.net/license/2_02.txt. | +// | If you did not receive a copy of the PHP license and are unable to | +// | obtain it through the world-wide-web, please send a note to | +// | license@php.net so we can mail you a copy immediately. | +// +----------------------------------------------------------------------+ +// | Authors: Stephan Schmidt | +// +----------------------------------------------------------------------+ +// +// $Id: v2.php,v 1.39 2008/05/13 05:29:24 cellog Exp $ + +/** + * error code for invalid chars in XML name + */ +define("PEAR_PackageFile_Generator_v2_XML_Util_ERROR_INVALID_CHARS", 51); + +/** + * error code for invalid chars in XML name + */ +define("PEAR_PackageFile_Generator_v2_XML_Util_ERROR_INVALID_START", 52); + +/** + * error code for non-scalar tag content + */ +define("PEAR_PackageFile_Generator_v2_XML_Util_ERROR_NON_SCALAR_CONTENT", 60); + +/** + * error code for missing tag name + */ +define("PEAR_PackageFile_Generator_v2_XML_Util_ERROR_NO_TAG_NAME", 61); + +/** + * replace XML entities + */ +define("PEAR_PackageFile_Generator_v2_XML_Util_REPLACE_ENTITIES", 1); + +/** + * embedd content in a CData Section + */ +define("PEAR_PackageFile_Generator_v2_XML_Util_CDATA_SECTION", 2); + +/** + * do not replace entitites + */ +define("PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_NONE", 0); + +/** + * replace all XML entitites + * This setting will replace <, >, ", ' and & + */ +define("PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_XML", 1); + +/** + * replace only required XML entitites + * This setting will replace <, " and & + */ +define("PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_XML_REQUIRED", 2); + +/** + * replace HTML entitites + * @link http://www.php.net/htmlentities + */ +define("PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_HTML", 3); + +/** + * replace all XML entitites, and encode from ISO-8859-1 to UTF-8 + * This setting will replace <, >, ", ' and & + */ +define("PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_UTF8_XML", 4); + +/** + * utility class for working with XML documents + * + * customized version of XML_Util 0.6.0 + * + * @category XML + * @package PEAR + * @version 0.6.0 + * @author Stephan Schmidt + * @author Gregory Beaver + */ +class PEAR_PackageFile_Generator_v2_XML_Util { + + /** + * return API version + * + * @access public + * @static + * @return string $version API version + */ + function apiVersion() + { + return "0.6"; + } + + /** + * replace XML entities + * + * With the optional second parameter, you may select, which + * entities should be replaced. + * + * + * require_once 'XML/Util.php'; + * + * // replace XML entites: + * $string = PEAR_PackageFile_Generator_v2_XML_Util::replaceEntities("This string contains < & >."); + * + * + * @access public + * @static + * @param string string where XML special chars should be replaced + * @param integer setting for entities in attribute values (one of PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_XML, PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_XML_REQUIRED, PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_HTML) + * @return string string with replaced chars + */ + function replaceEntities($string, $replaceEntities = PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_XML) + { + switch ($replaceEntities) { + case PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_UTF8_XML: + return strtr(utf8_encode($string),array( + '&' => '&', + '>' => '>', + '<' => '<', + '"' => '"', + '\'' => ''' )); + break; + case PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_XML: + return strtr($string,array( + '&' => '&', + '>' => '>', + '<' => '<', + '"' => '"', + '\'' => ''' )); + break; + case PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_XML_REQUIRED: + return strtr($string,array( + '&' => '&', + '<' => '<', + '"' => '"' )); + break; + case PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_HTML: + return htmlspecialchars($string); + break; + } + return $string; + } + + /** + * build an xml declaration + * + * + * require_once 'XML/Util.php'; + * + * // get an XML declaration: + * $xmlDecl = PEAR_PackageFile_Generator_v2_XML_Util::getXMLDeclaration("1.0", "UTF-8", true); + * + * + * @access public + * @static + * @param string $version xml version + * @param string $encoding character encoding + * @param boolean $standAlone document is standalone (or not) + * @return string $decl xml declaration + * @uses PEAR_PackageFile_Generator_v2_XML_Util::attributesToString() to serialize the attributes of the XML declaration + */ + function getXMLDeclaration($version = "1.0", $encoding = null, $standalone = null) + { + $attributes = array( + "version" => $version, + ); + // add encoding + if ($encoding !== null) { + $attributes["encoding"] = $encoding; + } + // add standalone, if specified + if ($standalone !== null) { + $attributes["standalone"] = $standalone ? "yes" : "no"; + } + + return sprintf("", PEAR_PackageFile_Generator_v2_XML_Util::attributesToString($attributes, false)); + } + + /** + * build a document type declaration + * + * + * require_once 'XML/Util.php'; + * + * // get a doctype declaration: + * $xmlDecl = PEAR_PackageFile_Generator_v2_XML_Util::getDocTypeDeclaration("rootTag","myDocType.dtd"); + * + * + * @access public + * @static + * @param string $root name of the root tag + * @param string $uri uri of the doctype definition (or array with uri and public id) + * @param string $internalDtd internal dtd entries + * @return string $decl doctype declaration + * @since 0.2 + */ + function getDocTypeDeclaration($root, $uri = null, $internalDtd = null) + { + if (is_array($uri)) { + $ref = sprintf( ' PUBLIC "%s" "%s"', $uri["id"], $uri["uri"] ); + } elseif (!empty($uri)) { + $ref = sprintf( ' SYSTEM "%s"', $uri ); + } else { + $ref = ""; + } + + if (empty($internalDtd)) { + return sprintf("", $root, $ref); + } else { + return sprintf("", $root, $ref, $internalDtd); + } + } + + /** + * create string representation of an attribute list + * + * + * require_once 'XML/Util.php'; + * + * // build an attribute string + * $att = array( + * "foo" => "bar", + * "argh" => "tomato" + * ); + * + * $attList = PEAR_PackageFile_Generator_v2_XML_Util::attributesToString($att); + * + * + * @access public + * @static + * @param array $attributes attribute array + * @param boolean|array $sort sort attribute list alphabetically, may also be an assoc array containing the keys 'sort', 'multiline', 'indent', 'linebreak' and 'entities' + * @param boolean $multiline use linebreaks, if more than one attribute is given + * @param string $indent string used for indentation of multiline attributes + * @param string $linebreak string used for linebreaks of multiline attributes + * @param integer $entities setting for entities in attribute values (one of PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_NONE, PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_XML, PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_XML_REQUIRED, PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_HTML) + * @return string string representation of the attributes + * @uses PEAR_PackageFile_Generator_v2_XML_Util::replaceEntities() to replace XML entities in attribute values + * @todo allow sort also to be an options array + */ + function attributesToString($attributes, $sort = true, $multiline = false, $indent = ' ', $linebreak = "\n", $entities = PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_XML) + { + /** + * second parameter may be an array + */ + if (is_array($sort)) { + if (isset($sort['multiline'])) { + $multiline = $sort['multiline']; + } + if (isset($sort['indent'])) { + $indent = $sort['indent']; + } + if (isset($sort['linebreak'])) { + $multiline = $sort['linebreak']; + } + if (isset($sort['entities'])) { + $entities = $sort['entities']; + } + if (isset($sort['sort'])) { + $sort = $sort['sort']; + } else { + $sort = true; + } + } + $string = ''; + if (is_array($attributes) && !empty($attributes)) { + if ($sort) { + ksort($attributes); + } + if( !$multiline || count($attributes) == 1) { + foreach ($attributes as $key => $value) { + if ($entities != PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_NONE) { + $value = PEAR_PackageFile_Generator_v2_XML_Util::replaceEntities($value, $entities); + } + $string .= ' '.$key.'="'.$value.'"'; + } + } else { + $first = true; + foreach ($attributes as $key => $value) { + if ($entities != PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_NONE) { + $value = PEAR_PackageFile_Generator_v2_XML_Util::replaceEntities($value, $entities); + } + if ($first) { + $string .= " ".$key.'="'.$value.'"'; + $first = false; + } else { + $string .= $linebreak.$indent.$key.'="'.$value.'"'; + } + } + } + } + return $string; + } + + /** + * create a tag + * + * This method will call PEAR_PackageFile_Generator_v2_XML_Util::createTagFromArray(), which + * is more flexible. + * + * + * require_once 'XML/Util.php'; + * + * // create an XML tag: + * $tag = PEAR_PackageFile_Generator_v2_XML_Util::createTag("myNs:myTag", array("foo" => "bar"), "This is inside the tag", "http://www.w3c.org/myNs#"); + * + * + * @access public + * @static + * @param string $qname qualified tagname (including namespace) + * @param array $attributes array containg attributes + * @param mixed $content + * @param string $namespaceUri URI of the namespace + * @param integer $replaceEntities whether to replace XML special chars in content, embedd it in a CData section or none of both + * @param boolean $multiline whether to create a multiline tag where each attribute gets written to a single line + * @param string $indent string used to indent attributes (_auto indents attributes so they start at the same column) + * @param string $linebreak string used for linebreaks + * @param string $encoding encoding that should be used to translate content + * @return string $string XML tag + * @see PEAR_PackageFile_Generator_v2_XML_Util::createTagFromArray() + * @uses PEAR_PackageFile_Generator_v2_XML_Util::createTagFromArray() to create the tag + */ + function createTag($qname, $attributes = array(), $content = null, $namespaceUri = null, $replaceEntities = PEAR_PackageFile_Generator_v2_XML_Util_REPLACE_ENTITIES, $multiline = false, $indent = "_auto", $linebreak = "\n", $encoding = PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_XML) + { + $tag = array( + "qname" => $qname, + "attributes" => $attributes + ); + + // add tag content + if ($content !== null) { + $tag["content"] = $content; + } + + // add namespace Uri + if ($namespaceUri !== null) { + $tag["namespaceUri"] = $namespaceUri; + } + + return PEAR_PackageFile_Generator_v2_XML_Util::createTagFromArray($tag, $replaceEntities, $multiline, $indent, $linebreak, $encoding); + } + + /** + * create a tag from an array + * this method awaits an array in the following format + *
    +    * array(
    +    *  "qname"        => $qname         // qualified name of the tag
    +    *  "namespace"    => $namespace     // namespace prefix (optional, if qname is specified or no namespace)
    +    *  "localpart"    => $localpart,    // local part of the tagname (optional, if qname is specified)
    +    *  "attributes"   => array(),       // array containing all attributes (optional)
    +    *  "content"      => $content,      // tag content (optional)
    +    *  "namespaceUri" => $namespaceUri  // namespaceUri for the given namespace (optional)
    +    *   )
    +    * 
    + * + * + * require_once 'XML/Util.php'; + * + * $tag = array( + * "qname" => "foo:bar", + * "namespaceUri" => "http://foo.com", + * "attributes" => array( "key" => "value", "argh" => "fruit&vegetable" ), + * "content" => "I'm inside the tag", + * ); + * // creating a tag with qualified name and namespaceUri + * $string = PEAR_PackageFile_Generator_v2_XML_Util::createTagFromArray($tag); + * + * + * @access public + * @static + * @param array $tag tag definition + * @param integer $replaceEntities whether to replace XML special chars in content, embedd it in a CData section or none of both + * @param boolean $multiline whether to create a multiline tag where each attribute gets written to a single line + * @param string $indent string used to indent attributes (_auto indents attributes so they start at the same column) + * @param string $linebreak string used for linebreaks + * @return string $string XML tag + * @see PEAR_PackageFile_Generator_v2_XML_Util::createTag() + * @uses PEAR_PackageFile_Generator_v2_XML_Util::attributesToString() to serialize the attributes of the tag + * @uses PEAR_PackageFile_Generator_v2_XML_Util::splitQualifiedName() to get local part and namespace of a qualified name + */ + function createTagFromArray($tag, $replaceEntities = PEAR_PackageFile_Generator_v2_XML_Util_REPLACE_ENTITIES, $multiline = false, $indent = "_auto", $linebreak = "\n", $encoding = PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_XML) + { + if (isset($tag["content"]) && !is_scalar($tag["content"])) { + return PEAR_PackageFile_Generator_v2_XML_Util::raiseError( "Supplied non-scalar value as tag content", PEAR_PackageFile_Generator_v2_XML_Util_ERROR_NON_SCALAR_CONTENT ); + } + + if (!isset($tag['qname']) && !isset($tag['localPart'])) { + return PEAR_PackageFile_Generator_v2_XML_Util::raiseError( 'You must either supply a qualified name (qname) or local tag name (localPart).', PEAR_PackageFile_Generator_v2_XML_Util_ERROR_NO_TAG_NAME ); + } + + // if no attributes hav been set, use empty attributes + if (!isset($tag["attributes"]) || !is_array($tag["attributes"])) { + $tag["attributes"] = array(); + } + + // qualified name is not given + if (!isset($tag["qname"])) { + // check for namespace + if (isset($tag["namespace"]) && !empty($tag["namespace"])) { + $tag["qname"] = $tag["namespace"].":".$tag["localPart"]; + } else { + $tag["qname"] = $tag["localPart"]; + } + // namespace URI is set, but no namespace + } elseif (isset($tag["namespaceUri"]) && !isset($tag["namespace"])) { + $parts = PEAR_PackageFile_Generator_v2_XML_Util::splitQualifiedName($tag["qname"]); + $tag["localPart"] = $parts["localPart"]; + if (isset($parts["namespace"])) { + $tag["namespace"] = $parts["namespace"]; + } + } + + if (isset($tag["namespaceUri"]) && !empty($tag["namespaceUri"])) { + // is a namespace given + if (isset($tag["namespace"]) && !empty($tag["namespace"])) { + $tag["attributes"]["xmlns:".$tag["namespace"]] = $tag["namespaceUri"]; + } else { + // define this Uri as the default namespace + $tag["attributes"]["xmlns"] = $tag["namespaceUri"]; + } + } + + // check for multiline attributes + if ($multiline === true) { + if ($indent === "_auto") { + $indent = str_repeat(" ", (strlen($tag["qname"])+2)); + } + } + + // create attribute list + $attList = PEAR_PackageFile_Generator_v2_XML_Util::attributesToString($tag["attributes"], true, $multiline, $indent, $linebreak ); + if (!isset($tag["content"]) || (string)$tag["content"] == '') { + $tag = sprintf("<%s%s />", $tag["qname"], $attList); + } else { + if ($replaceEntities == PEAR_PackageFile_Generator_v2_XML_Util_REPLACE_ENTITIES) { + $tag["content"] = PEAR_PackageFile_Generator_v2_XML_Util::replaceEntities($tag["content"], $encoding); + } elseif ($replaceEntities == PEAR_PackageFile_Generator_v2_XML_Util_CDATA_SECTION) { + $tag["content"] = PEAR_PackageFile_Generator_v2_XML_Util::createCDataSection($tag["content"]); + } + $tag = sprintf("<%s%s>%s", $tag["qname"], $attList, $tag["content"], $tag["qname"] ); + } + return $tag; + } + + /** + * create a start element + * + * + * require_once 'XML/Util.php'; + * + * // create an XML start element: + * $tag = PEAR_PackageFile_Generator_v2_XML_Util::createStartElement("myNs:myTag", array("foo" => "bar") ,"http://www.w3c.org/myNs#"); + * + * + * @access public + * @static + * @param string $qname qualified tagname (including namespace) + * @param array $attributes array containg attributes + * @param string $namespaceUri URI of the namespace + * @param boolean $multiline whether to create a multiline tag where each attribute gets written to a single line + * @param string $indent string used to indent attributes (_auto indents attributes so they start at the same column) + * @param string $linebreak string used for linebreaks + * @return string $string XML start element + * @see PEAR_PackageFile_Generator_v2_XML_Util::createEndElement(), PEAR_PackageFile_Generator_v2_XML_Util::createTag() + */ + function createStartElement($qname, $attributes = array(), $namespaceUri = null, $multiline = false, $indent = '_auto', $linebreak = "\n") + { + // if no attributes hav been set, use empty attributes + if (!isset($attributes) || !is_array($attributes)) { + $attributes = array(); + } + + if ($namespaceUri != null) { + $parts = PEAR_PackageFile_Generator_v2_XML_Util::splitQualifiedName($qname); + } + + // check for multiline attributes + if ($multiline === true) { + if ($indent === "_auto") { + $indent = str_repeat(" ", (strlen($qname)+2)); + } + } + + if ($namespaceUri != null) { + // is a namespace given + if (isset($parts["namespace"]) && !empty($parts["namespace"])) { + $attributes["xmlns:".$parts["namespace"]] = $namespaceUri; + } else { + // define this Uri as the default namespace + $attributes["xmlns"] = $namespaceUri; + } + } + + // create attribute list + $attList = PEAR_PackageFile_Generator_v2_XML_Util::attributesToString($attributes, true, $multiline, $indent, $linebreak); + $element = sprintf("<%s%s>", $qname, $attList); + return $element; + } + + /** + * create an end element + * + * + * require_once 'XML/Util.php'; + * + * // create an XML start element: + * $tag = PEAR_PackageFile_Generator_v2_XML_Util::createEndElement("myNs:myTag"); + * + * + * @access public + * @static + * @param string $qname qualified tagname (including namespace) + * @return string $string XML end element + * @see PEAR_PackageFile_Generator_v2_XML_Util::createStartElement(), PEAR_PackageFile_Generator_v2_XML_Util::createTag() + */ + function createEndElement($qname) + { + $element = sprintf("", $qname); + return $element; + } + + /** + * create an XML comment + * + * + * require_once 'XML/Util.php'; + * + * // create an XML start element: + * $tag = PEAR_PackageFile_Generator_v2_XML_Util::createComment("I am a comment"); + * + * + * @access public + * @static + * @param string $content content of the comment + * @return string $comment XML comment + */ + function createComment($content) + { + $comment = sprintf("", $content); + return $comment; + } + + /** + * create a CData section + * + * + * require_once 'XML/Util.php'; + * + * // create a CData section + * $tag = PEAR_PackageFile_Generator_v2_XML_Util::createCDataSection("I am content."); + * + * + * @access public + * @static + * @param string $data data of the CData section + * @return string $string CData section with content + */ + function createCDataSection($data) + { + return sprintf("", $data); + } + + /** + * split qualified name and return namespace and local part + * + * + * require_once 'XML/Util.php'; + * + * // split qualified tag + * $parts = PEAR_PackageFile_Generator_v2_XML_Util::splitQualifiedName("xslt:stylesheet"); + * + * the returned array will contain two elements: + *
    +    * array(
    +    *       "namespace" => "xslt",
    +    *       "localPart" => "stylesheet"
    +    *      );
    +    * 
    + * + * @access public + * @static + * @param string $qname qualified tag name + * @param string $defaultNs default namespace (optional) + * @return array $parts array containing namespace and local part + */ + function splitQualifiedName($qname, $defaultNs = null) + { + if (strstr($qname, ':')) { + $tmp = explode(":", $qname); + return array( + "namespace" => $tmp[0], + "localPart" => $tmp[1] + ); + } + return array( + "namespace" => $defaultNs, + "localPart" => $qname + ); + } + + /** + * check, whether string is valid XML name + * + *

    XML names are used for tagname, attribute names and various + * other, lesser known entities.

    + *

    An XML name may only consist of alphanumeric characters, + * dashes, undescores and periods, and has to start with a letter + * or an underscore. + *

    + * + * + * require_once 'XML/Util.php'; + * + * // verify tag name + * $result = PEAR_PackageFile_Generator_v2_XML_Util::isValidName("invalidTag?"); + * if (PEAR_PackageFile_Generator_v2_XML_Util::isError($result)) { + * print "Invalid XML name: " . $result->getMessage(); + * } + * + * + * @access public + * @static + * @param string $string string that should be checked + * @return mixed $valid true, if string is a valid XML name, PEAR error otherwise + * @todo support for other charsets + */ + function isValidName($string) + { + // check for invalid chars + if (!preg_match("/^[[:alnum:]_\-.]\\z/", $string{0})) { + return PEAR_PackageFile_Generator_v2_XML_Util::raiseError( "XML names may only start with letter or underscore", PEAR_PackageFile_Generator_v2_XML_Util_ERROR_INVALID_START ); + } + + // check for invalid chars + if (!preg_match("/^([a-zA-Z_]([a-zA-Z0-9_\-\.]*)?:)?[a-zA-Z_]([a-zA-Z0-9_\-\.]+)?\\z/", $string)) { + return PEAR_PackageFile_Generator_v2_XML_Util::raiseError( "XML names may only contain alphanumeric chars, period, hyphen, colon and underscores", PEAR_PackageFile_Generator_v2_XML_Util_ERROR_INVALID_CHARS ); + } + // XML name is valid + return true; + } + + /** + * replacement for PEAR_PackageFile_Generator_v2_XML_Util::raiseError + * + * Avoids the necessity to always require + * PEAR.php + * + * @access public + * @param string error message + * @param integer error code + * @return object PEAR_Error + */ + function raiseError($msg, $code) + { + require_once 'PEAR.php'; + return PEAR::raiseError($msg, $code); + } +} +?> \ No newline at end of file diff --git a/src/lib/pear/PEAR/PEAR/PackageFile/Parser/v1.php b/src/lib/pear/PEAR/PEAR/PackageFile/Parser/v1.php new file mode 100644 index 0000000..1134dc6 --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/PackageFile/Parser/v1.php @@ -0,0 +1,465 @@ + + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: v1.php,v 1.27 2008/01/03 20:55:16 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 1.4.0a1 + */ +/** + * package.xml abstraction class + */ +require_once 'PEAR/PackageFile/v1.php'; +/** + * Parser for package.xml version 1.0 + * @category pear + * @package PEAR + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: @PEAR-VER@ + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 1.4.0a1 + */ +class PEAR_PackageFile_Parser_v1 +{ + var $_registry; + var $_config; + var $_logger; + /** + * BC hack to allow PEAR_Common::infoFromString() to sort of + * work with the version 2.0 format - there's no filelist though + * @param PEAR_PackageFile_v2 + */ + function fromV2($packagefile) + { + $info = $packagefile->getArray(true); + $ret = new PEAR_PackageFile_v1; + $ret->fromArray($info['old']); + } + + function setConfig(&$c) + { + $this->_config = &$c; + $this->_registry = &$c->getRegistry(); + } + + function setLogger(&$l) + { + $this->_logger = &$l; + } + + /** + * @param string contents of package.xml file, version 1.0 + * @return bool success of parsing + */ + function &parse($data, $file, $archive = false) + { + if (!extension_loaded('xml')) { + return PEAR::raiseError('Cannot create xml parser for parsing package.xml, no xml extension'); + } + $xp = xml_parser_create(); + if (!$xp) { + $a = &PEAR::raiseError('Cannot create xml parser for parsing package.xml'); + return $a; + } + xml_set_object($xp, $this); + xml_set_element_handler($xp, '_element_start_1_0', '_element_end_1_0'); + xml_set_character_data_handler($xp, '_pkginfo_cdata_1_0'); + xml_parser_set_option($xp, XML_OPTION_CASE_FOLDING, false); + + $this->element_stack = array(); + $this->_packageInfo = array('provides' => array()); + $this->current_element = false; + unset($this->dir_install); + $this->_packageInfo['filelist'] = array(); + $this->filelist =& $this->_packageInfo['filelist']; + $this->dir_names = array(); + $this->in_changelog = false; + $this->d_i = 0; + $this->cdata = ''; + $this->_isValid = true; + + if (!xml_parse($xp, $data, 1)) { + $code = xml_get_error_code($xp); + $line = xml_get_current_line_number($xp); + xml_parser_free($xp); + $a = &PEAR::raiseError(sprintf("XML error: %s at line %d", + $str = xml_error_string($code), $line), 2); + return $a; + } + + xml_parser_free($xp); + + $pf = new PEAR_PackageFile_v1; + $pf->setConfig($this->_config); + if (isset($this->_logger)) { + $pf->setLogger($this->_logger); + } + $pf->setPackagefile($file, $archive); + $pf->fromArray($this->_packageInfo); + return $pf; + } + // {{{ _unIndent() + + /** + * Unindent given string + * + * @param string $str The string that has to be unindented. + * @return string + * @access private + */ + function _unIndent($str) + { + // remove leading newlines + $str = preg_replace('/^[\r\n]+/', '', $str); + // find whitespace at the beginning of the first line + $indent_len = strspn($str, " \t"); + $indent = substr($str, 0, $indent_len); + $data = ''; + // remove the same amount of whitespace from following lines + foreach (explode("\n", $str) as $line) { + if (substr($line, 0, $indent_len) == $indent) { + $data .= substr($line, $indent_len) . "\n"; + } elseif (trim(substr($line, 0, $indent_len))) { + $data .= ltrim($line); + } + } + return $data; + } + + // Support for package DTD v1.0: + // {{{ _element_start_1_0() + + /** + * XML parser callback for ending elements. Used for version 1.0 + * packages. + * + * @param resource $xp XML parser resource + * @param string $name name of ending element + * + * @return void + * + * @access private + */ + function _element_start_1_0($xp, $name, $attribs) + { + array_push($this->element_stack, $name); + $this->current_element = $name; + $spos = sizeof($this->element_stack) - 2; + $this->prev_element = ($spos >= 0) ? $this->element_stack[$spos] : ''; + $this->current_attributes = $attribs; + $this->cdata = ''; + switch ($name) { + case 'dir': + if ($this->in_changelog) { + break; + } + if (array_key_exists('name', $attribs) && $attribs['name'] != '/') { + $attribs['name'] = preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'), + $attribs['name']); + if (strrpos($attribs['name'], '/') === strlen($attribs['name']) - 1) { + $attribs['name'] = substr($attribs['name'], 0, + strlen($attribs['name']) - 1); + } + if (strpos($attribs['name'], '/') === 0) { + $attribs['name'] = substr($attribs['name'], 1); + } + $this->dir_names[] = $attribs['name']; + } + if (isset($attribs['baseinstalldir'])) { + $this->dir_install = $attribs['baseinstalldir']; + } + if (isset($attribs['role'])) { + $this->dir_role = $attribs['role']; + } + break; + case 'file': + if ($this->in_changelog) { + break; + } + if (isset($attribs['name'])) { + $path = ''; + if (count($this->dir_names)) { + foreach ($this->dir_names as $dir) { + $path .= $dir . '/'; + } + } + $path .= preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'), + $attribs['name']); + unset($attribs['name']); + $this->current_path = $path; + $this->filelist[$path] = $attribs; + // Set the baseinstalldir only if the file don't have this attrib + if (!isset($this->filelist[$path]['baseinstalldir']) && + isset($this->dir_install)) + { + $this->filelist[$path]['baseinstalldir'] = $this->dir_install; + } + // Set the Role + if (!isset($this->filelist[$path]['role']) && isset($this->dir_role)) { + $this->filelist[$path]['role'] = $this->dir_role; + } + } + break; + case 'replace': + if (!$this->in_changelog) { + $this->filelist[$this->current_path]['replacements'][] = $attribs; + } + break; + case 'maintainers': + $this->_packageInfo['maintainers'] = array(); + $this->m_i = 0; // maintainers array index + break; + case 'maintainer': + // compatibility check + if (!isset($this->_packageInfo['maintainers'])) { + $this->_packageInfo['maintainers'] = array(); + $this->m_i = 0; + } + $this->_packageInfo['maintainers'][$this->m_i] = array(); + $this->current_maintainer =& $this->_packageInfo['maintainers'][$this->m_i]; + break; + case 'changelog': + $this->_packageInfo['changelog'] = array(); + $this->c_i = 0; // changelog array index + $this->in_changelog = true; + break; + case 'release': + if ($this->in_changelog) { + $this->_packageInfo['changelog'][$this->c_i] = array(); + $this->current_release = &$this->_packageInfo['changelog'][$this->c_i]; + } else { + $this->current_release = &$this->_packageInfo; + } + break; + case 'deps': + if (!$this->in_changelog) { + $this->_packageInfo['release_deps'] = array(); + } + break; + case 'dep': + // dependencies array index + if (!$this->in_changelog) { + $this->d_i++; + isset($attribs['type']) ? ($attribs['type'] = strtolower($attribs['type'])) : false; + $this->_packageInfo['release_deps'][$this->d_i] = $attribs; + } + break; + case 'configureoptions': + if (!$this->in_changelog) { + $this->_packageInfo['configure_options'] = array(); + } + break; + case 'configureoption': + if (!$this->in_changelog) { + $this->_packageInfo['configure_options'][] = $attribs; + } + break; + case 'provides': + if (empty($attribs['type']) || empty($attribs['name'])) { + break; + } + $attribs['explicit'] = true; + $this->_packageInfo['provides']["$attribs[type];$attribs[name]"] = $attribs; + break; + case 'package' : + if (isset($attribs['version'])) { + $this->_packageInfo['xsdversion'] = trim($attribs['version']); + } else { + $this->_packageInfo['xsdversion'] = '1.0'; + } + if (isset($attribs['packagerversion'])) { + $this->_packageInfo['packagerversion'] = $attribs['packagerversion']; + } + break; + } + } + + // }}} + // {{{ _element_end_1_0() + + /** + * XML parser callback for ending elements. Used for version 1.0 + * packages. + * + * @param resource $xp XML parser resource + * @param string $name name of ending element + * + * @return void + * + * @access private + */ + function _element_end_1_0($xp, $name) + { + $data = trim($this->cdata); + switch ($name) { + case 'name': + switch ($this->prev_element) { + case 'package': + $this->_packageInfo['package'] = $data; + break; + case 'maintainer': + $this->current_maintainer['name'] = $data; + break; + } + break; + case 'extends' : + $this->_packageInfo['extends'] = $data; + break; + case 'summary': + $this->_packageInfo['summary'] = $data; + break; + case 'description': + $data = $this->_unIndent($this->cdata); + $this->_packageInfo['description'] = $data; + break; + case 'user': + $this->current_maintainer['handle'] = $data; + break; + case 'email': + $this->current_maintainer['email'] = $data; + break; + case 'role': + $this->current_maintainer['role'] = $data; + break; + case 'version': + //$data = ereg_replace ('[^a-zA-Z0-9._\-]', '_', $data); + if ($this->in_changelog) { + $this->current_release['version'] = $data; + } else { + $this->_packageInfo['version'] = $data; + } + break; + case 'date': + if ($this->in_changelog) { + $this->current_release['release_date'] = $data; + } else { + $this->_packageInfo['release_date'] = $data; + } + break; + case 'notes': + // try to "de-indent" release notes in case someone + // has been over-indenting their xml ;-) + $data = $this->_unIndent($this->cdata); + if ($this->in_changelog) { + $this->current_release['release_notes'] = $data; + } else { + $this->_packageInfo['release_notes'] = $data; + } + break; + case 'warnings': + if ($this->in_changelog) { + $this->current_release['release_warnings'] = $data; + } else { + $this->_packageInfo['release_warnings'] = $data; + } + break; + case 'state': + if ($this->in_changelog) { + $this->current_release['release_state'] = $data; + } else { + $this->_packageInfo['release_state'] = $data; + } + break; + case 'license': + if ($this->in_changelog) { + $this->current_release['release_license'] = $data; + } else { + $this->_packageInfo['release_license'] = $data; + } + break; + case 'dep': + if ($data && !$this->in_changelog) { + $this->_packageInfo['release_deps'][$this->d_i]['name'] = $data; + } + break; + case 'dir': + if ($this->in_changelog) { + break; + } + array_pop($this->dir_names); + break; + case 'file': + if ($this->in_changelog) { + break; + } + if ($data) { + $path = ''; + if (count($this->dir_names)) { + foreach ($this->dir_names as $dir) { + $path .= $dir . '/'; + } + } + $path .= $data; + $this->filelist[$path] = $this->current_attributes; + // Set the baseinstalldir only if the file don't have this attrib + if (!isset($this->filelist[$path]['baseinstalldir']) && + isset($this->dir_install)) + { + $this->filelist[$path]['baseinstalldir'] = $this->dir_install; + } + // Set the Role + if (!isset($this->filelist[$path]['role']) && isset($this->dir_role)) { + $this->filelist[$path]['role'] = $this->dir_role; + } + } + break; + case 'maintainer': + if (empty($this->_packageInfo['maintainers'][$this->m_i]['role'])) { + $this->_packageInfo['maintainers'][$this->m_i]['role'] = 'lead'; + } + $this->m_i++; + break; + case 'release': + if ($this->in_changelog) { + $this->c_i++; + } + break; + case 'changelog': + $this->in_changelog = false; + break; + } + array_pop($this->element_stack); + $spos = sizeof($this->element_stack) - 1; + $this->current_element = ($spos > 0) ? $this->element_stack[$spos] : ''; + $this->cdata = ''; + } + + // }}} + // {{{ _pkginfo_cdata_1_0() + + /** + * XML parser callback for character data. Used for version 1.0 + * packages. + * + * @param resource $xp XML parser resource + * @param string $name character data + * + * @return void + * + * @access private + */ + function _pkginfo_cdata_1_0($xp, $data) + { + if (isset($this->cdata)) { + $this->cdata .= $data; + } + } + + // }}} +} +?> \ No newline at end of file diff --git a/src/lib/pear/PEAR/PEAR/PackageFile/Parser/v2.php b/src/lib/pear/PEAR/PEAR/PackageFile/Parser/v2.php new file mode 100644 index 0000000..7cbc585 --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/PackageFile/Parser/v2.php @@ -0,0 +1,117 @@ + + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: v2.php,v 1.21 2008/01/03 20:26:37 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 1.4.0a1 + */ +/** + * base xml parser class + */ +require_once 'PEAR/XMLParser.php'; +require_once 'PEAR/PackageFile/v2.php'; +/** + * Parser for package.xml version 2.0 + * @category pear + * @package PEAR + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: @PEAR-VER@ + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 1.4.0a1 + */ +class PEAR_PackageFile_Parser_v2 extends PEAR_XMLParser +{ + var $_config; + var $_logger; + var $_registry; + + function setConfig(&$c) + { + $this->_config = &$c; + $this->_registry = &$c->getRegistry(); + } + + function setLogger(&$l) + { + $this->_logger = &$l; + } + /** + * Unindent given string + * + * @param string $str The string that has to be unindented. + * @return string + * @access private + */ + function _unIndent($str) + { + // remove leading newlines + $str = preg_replace('/^[\r\n]+/', '', $str); + // find whitespace at the beginning of the first line + $indent_len = strspn($str, " \t"); + $indent = substr($str, 0, $indent_len); + $data = ''; + // remove the same amount of whitespace from following lines + foreach (explode("\n", $str) as $line) { + if (substr($line, 0, $indent_len) == $indent) { + $data .= substr($line, $indent_len) . "\n"; + } else { + $data .= $line . "\n"; + } + } + return $data; + } + + /** + * post-process data + * + * @param string $data + * @param string $element element name + */ + function postProcess($data, $element) + { + if ($element == 'notes') { + return trim($this->_unIndent($data)); + } + return trim($data); + } + + /** + * @param string + * @param string file name of the package.xml + * @param string|false name of the archive this package.xml came from, if any + * @param string class name to instantiate and return. This must be PEAR_PackageFile_v2 or + * a subclass + * @return PEAR_PackageFile_v2 + */ + function &parse($data, $file, $archive = false, $class = 'PEAR_PackageFile_v2') + { + if (PEAR::isError($err = parent::parse($data, $file))) { + return $err; + } + $ret = new $class; + $ret->setConfig($this->_config); + if (isset($this->_logger)) { + $ret->setLogger($this->_logger); + } + $ret->fromArray($this->_unserializedData); + $ret->setPackagefile($file, $archive); + return $ret; + } +} +?> \ No newline at end of file diff --git a/src/lib/pear/PEAR/PEAR/PackageFile/v1.php b/src/lib/pear/PEAR/PEAR/PackageFile/v1.php new file mode 100644 index 0000000..d289550 --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/PackageFile/v1.php @@ -0,0 +1,1618 @@ + + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: v1.php,v 1.74 2008/01/03 20:26:36 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 1.4.0a1 + */ +/** + * For error handling + */ +require_once 'PEAR/ErrorStack.php'; + +/** + * Error code if parsing is attempted with no xml extension + */ +define('PEAR_PACKAGEFILE_ERROR_NO_XML_EXT', 3); + +/** + * Error code if creating the xml parser resource fails + */ +define('PEAR_PACKAGEFILE_ERROR_CANT_MAKE_PARSER', 4); + +/** + * Error code used for all sax xml parsing errors + */ +define('PEAR_PACKAGEFILE_ERROR_PARSER_ERROR', 5); + +/** + * Error code used when there is no name + */ +define('PEAR_PACKAGEFILE_ERROR_NO_NAME', 6); + +/** + * Error code when a package name is not valid + */ +define('PEAR_PACKAGEFILE_ERROR_INVALID_NAME', 7); + +/** + * Error code used when no summary is parsed + */ +define('PEAR_PACKAGEFILE_ERROR_NO_SUMMARY', 8); + +/** + * Error code for summaries that are more than 1 line + */ +define('PEAR_PACKAGEFILE_ERROR_MULTILINE_SUMMARY', 9); + +/** + * Error code used when no description is present + */ +define('PEAR_PACKAGEFILE_ERROR_NO_DESCRIPTION', 10); + +/** + * Error code used when no license is present + */ +define('PEAR_PACKAGEFILE_ERROR_NO_LICENSE', 11); + +/** + * Error code used when a version number is not present + */ +define('PEAR_PACKAGEFILE_ERROR_NO_VERSION', 12); + +/** + * Error code used when a version number is invalid + */ +define('PEAR_PACKAGEFILE_ERROR_INVALID_VERSION', 13); + +/** + * Error code when release state is missing + */ +define('PEAR_PACKAGEFILE_ERROR_NO_STATE', 14); + +/** + * Error code when release state is invalid + */ +define('PEAR_PACKAGEFILE_ERROR_INVALID_STATE', 15); + +/** + * Error code when release state is missing + */ +define('PEAR_PACKAGEFILE_ERROR_NO_DATE', 16); + +/** + * Error code when release state is invalid + */ +define('PEAR_PACKAGEFILE_ERROR_INVALID_DATE', 17); + +/** + * Error code when no release notes are found + */ +define('PEAR_PACKAGEFILE_ERROR_NO_NOTES', 18); + +/** + * Error code when no maintainers are found + */ +define('PEAR_PACKAGEFILE_ERROR_NO_MAINTAINERS', 19); + +/** + * Error code when a maintainer has no handle + */ +define('PEAR_PACKAGEFILE_ERROR_NO_MAINTHANDLE', 20); + +/** + * Error code when a maintainer has no handle + */ +define('PEAR_PACKAGEFILE_ERROR_NO_MAINTROLE', 21); + +/** + * Error code when a maintainer has no name + */ +define('PEAR_PACKAGEFILE_ERROR_NO_MAINTNAME', 22); + +/** + * Error code when a maintainer has no email + */ +define('PEAR_PACKAGEFILE_ERROR_NO_MAINTEMAIL', 23); + +/** + * Error code when a maintainer has no handle + */ +define('PEAR_PACKAGEFILE_ERROR_INVALID_MAINTROLE', 24); + +/** + * Error code when a dependency is not a PHP dependency, but has no name + */ +define('PEAR_PACKAGEFILE_ERROR_NO_DEPNAME', 25); + +/** + * Error code when a dependency has no type (pkg, php, etc.) + */ +define('PEAR_PACKAGEFILE_ERROR_NO_DEPTYPE', 26); + +/** + * Error code when a dependency has no relation (lt, ge, has, etc.) + */ +define('PEAR_PACKAGEFILE_ERROR_NO_DEPREL', 27); + +/** + * Error code when a dependency is not a 'has' relation, but has no version + */ +define('PEAR_PACKAGEFILE_ERROR_NO_DEPVERSION', 28); + +/** + * Error code when a dependency has an invalid relation + */ +define('PEAR_PACKAGEFILE_ERROR_INVALID_DEPREL', 29); + +/** + * Error code when a dependency has an invalid type + */ +define('PEAR_PACKAGEFILE_ERROR_INVALID_DEPTYPE', 30); + +/** + * Error code when a dependency has an invalid optional option + */ +define('PEAR_PACKAGEFILE_ERROR_INVALID_DEPOPTIONAL', 31); + +/** + * Error code when a dependency is a pkg dependency, and has an invalid package name + */ +define('PEAR_PACKAGEFILE_ERROR_INVALID_DEPNAME', 32); + +/** + * Error code when a dependency has a channel="foo" attribute, and foo is not a registered channel + */ +define('PEAR_PACKAGEFILE_ERROR_UNKNOWN_DEPCHANNEL', 33); + +/** + * Error code when rel="has" and version attribute is present. + */ +define('PEAR_PACKAGEFILE_ERROR_DEPVERSION_IGNORED', 34); + +/** + * Error code when type="php" and dependency name is present + */ +define('PEAR_PACKAGEFILE_ERROR_DEPNAME_IGNORED', 35); + +/** + * Error code when a configure option has no name + */ +define('PEAR_PACKAGEFILE_ERROR_NO_CONFNAME', 36); + +/** + * Error code when a configure option has no name + */ +define('PEAR_PACKAGEFILE_ERROR_NO_CONFPROMPT', 37); + +/** + * Error code when a file in the filelist has an invalid role + */ +define('PEAR_PACKAGEFILE_ERROR_INVALID_FILEROLE', 38); + +/** + * Error code when a file in the filelist has no role + */ +define('PEAR_PACKAGEFILE_ERROR_NO_FILEROLE', 39); + +/** + * Error code when analyzing a php source file that has parse errors + */ +define('PEAR_PACKAGEFILE_ERROR_INVALID_PHPFILE', 40); + +/** + * Error code when analyzing a php source file reveals a source element + * without a package name prefix + */ +define('PEAR_PACKAGEFILE_ERROR_NO_PNAME_PREFIX', 41); + +/** + * Error code when an unknown channel is specified + */ +define('PEAR_PACKAGEFILE_ERROR_UNKNOWN_CHANNEL', 42); + +/** + * Error code when no files are found in the filelist + */ +define('PEAR_PACKAGEFILE_ERROR_NO_FILES', 43); + +/** + * Error code when a file is not valid php according to _analyzeSourceCode() + */ +define('PEAR_PACKAGEFILE_ERROR_INVALID_FILE', 44); + +/** + * Error code when the channel validator returns an error or warning + */ +define('PEAR_PACKAGEFILE_ERROR_CHANNELVAL', 45); + +/** + * Error code when a php5 package is packaged in php4 (analysis doesn't work) + */ +define('PEAR_PACKAGEFILE_ERROR_PHP5', 46); + +/** + * Error code when a file is listed in package.xml but does not exist + */ +define('PEAR_PACKAGEFILE_ERROR_FILE_NOTFOUND', 47); + +/** + * Error code when a + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 1.4.0a1 + */ +class PEAR_PackageFile_v1 +{ + /** + * @access private + * @var PEAR_ErrorStack + * @access private + */ + var $_stack; + + /** + * A registry object, used to access the package name validation regex for non-standard channels + * @var PEAR_Registry + * @access private + */ + var $_registry; + + /** + * An object that contains a log method that matches PEAR_Common::log's signature + * @var object + * @access private + */ + var $_logger; + + /** + * Parsed package information + * @var array + * @access private + */ + var $_packageInfo; + + /** + * path to package.xml + * @var string + * @access private + */ + var $_packageFile; + + /** + * path to package .tgz or false if this is a local/extracted package.xml + * @var string + * @access private + */ + var $_archiveFile; + + /** + * @var int + * @access private + */ + var $_isValid = 0; + + /** + * Determines whether this packagefile was initialized only with partial package info + * + * If this package file was constructed via parsing REST, it will only contain + * + * - package name + * - channel name + * - dependencies + * @var boolean + * @access private + */ + var $_incomplete = true; + + /** + * @param bool determines whether to return a PEAR_Error object, or use the PEAR_ErrorStack + * @param string Name of Error Stack class to use. + */ + function PEAR_PackageFile_v1() + { + $this->_stack = &new PEAR_ErrorStack('PEAR_PackageFile_v1'); + $this->_stack->setErrorMessageTemplate($this->_getErrorMessage()); + $this->_isValid = 0; + } + + function installBinary($installer) + { + return false; + } + + function isExtension($name) + { + return false; + } + + function setConfig(&$config) + { + $this->_config = &$config; + $this->_registry = &$config->getRegistry(); + } + + function setRequestedGroup() + { + // placeholder + } + + /** + * For saving in the registry. + * + * Set the last version that was installed + * @param string + */ + function setLastInstalledVersion($version) + { + $this->_packageInfo['_lastversion'] = $version; + } + + /** + * @return string|false + */ + function getLastInstalledVersion() + { + if (isset($this->_packageInfo['_lastversion'])) { + return $this->_packageInfo['_lastversion']; + } + return false; + } + + function getInstalledBinary() + { + return false; + } + + function listPostinstallScripts() + { + return false; + } + + function initPostinstallScripts() + { + return false; + } + + function setLogger(&$logger) + { + if ($logger && (!is_object($logger) || !method_exists($logger, 'log'))) { + return PEAR::raiseError('Logger must be compatible with PEAR_Common::log'); + } + $this->_logger = &$logger; + } + + function setPackagefile($file, $archive = false) + { + $this->_packageFile = $file; + $this->_archiveFile = $archive ? $archive : $file; + } + + function getPackageFile() + { + return isset($this->_packageFile) ? $this->_packageFile : false; + } + + function getPackageType() + { + return 'php'; + } + + function getArchiveFile() + { + return $this->_archiveFile; + } + + function packageInfo($field) + { + if (!is_string($field) || empty($field) || + !isset($this->_packageInfo[$field])) { + return false; + } + return $this->_packageInfo[$field]; + } + + function setDirtree($path) + { + if (!isset($this->_packageInfo['dirtree'])) { + $this->_packageInfo['dirtree'] = array(); + } + $this->_packageInfo['dirtree'][$path] = true; + } + + function getDirtree() + { + if (isset($this->_packageInfo['dirtree']) && count($this->_packageInfo['dirtree'])) { + return $this->_packageInfo['dirtree']; + } + return false; + } + + function resetDirtree() + { + unset($this->_packageInfo['dirtree']); + } + + function fromArray($pinfo) + { + $this->_incomplete = false; + $this->_packageInfo = $pinfo; + } + + function isIncomplete() + { + return $this->_incomplete; + } + + function getChannel() + { + return 'pear.php.net'; + } + + function getUri() + { + return false; + } + + function getTime() + { + return false; + } + + function getExtends() + { + if (isset($this->_packageInfo['extends'])) { + return $this->_packageInfo['extends']; + } + return false; + } + + /** + * @return array + */ + function toArray() + { + if (!$this->validate(PEAR_VALIDATE_NORMAL)) { + return false; + } + return $this->getArray(); + } + + function getArray() + { + return $this->_packageInfo; + } + + function getName() + { + return $this->getPackage(); + } + + function getPackage() + { + if (isset($this->_packageInfo['package'])) { + return $this->_packageInfo['package']; + } + return false; + } + + /** + * WARNING - don't use this unless you know what you are doing + */ + function setRawPackage($package) + { + $this->_packageInfo['package'] = $package; + } + + function setPackage($package) + { + $this->_packageInfo['package'] = $package; + $this->_isValid = false; + } + + function getVersion() + { + if (isset($this->_packageInfo['version'])) { + return $this->_packageInfo['version']; + } + return false; + } + + function setVersion($version) + { + $this->_packageInfo['version'] = $version; + $this->_isValid = false; + } + + function clearMaintainers() + { + unset($this->_packageInfo['maintainers']); + } + + function getMaintainers() + { + if (isset($this->_packageInfo['maintainers'])) { + return $this->_packageInfo['maintainers']; + } + return false; + } + + /** + * Adds a new maintainer - no checking of duplicates is performed, use + * updatemaintainer for that purpose. + */ + function addMaintainer($role, $handle, $name, $email) + { + $this->_packageInfo['maintainers'][] = + array('handle' => $handle, 'role' => $role, 'email' => $email, 'name' => $name); + $this->_isValid = false; + } + + function updateMaintainer($role, $handle, $name, $email) + { + $found = false; + if (!isset($this->_packageInfo['maintainers']) || + !is_array($this->_packageInfo['maintainers'])) { + return $this->addMaintainer($role, $handle, $name, $email); + } + foreach ($this->_packageInfo['maintainers'] as $i => $maintainer) { + if ($maintainer['handle'] == $handle) { + $found = $i; + break; + } + } + if ($found !== false) { + unset($this->_packageInfo['maintainers'][$found]); + $this->_packageInfo['maintainers'] = + array_values($this->_packageInfo['maintainers']); + } + $this->addMaintainer($role, $handle, $name, $email); + } + + function deleteMaintainer($handle) + { + $found = false; + foreach ($this->_packageInfo['maintainers'] as $i => $maintainer) { + if ($maintainer['handle'] == $handle) { + $found = $i; + break; + } + } + if ($found !== false) { + unset($this->_packageInfo['maintainers'][$found]); + $this->_packageInfo['maintainers'] = + array_values($this->_packageInfo['maintainers']); + return true; + } + return false; + } + + function getState() + { + if (isset($this->_packageInfo['release_state'])) { + return $this->_packageInfo['release_state']; + } + return false; + } + + function setRawState($state) + { + $this->_packageInfo['release_state'] = $state; + } + + function setState($state) + { + $this->_packageInfo['release_state'] = $state; + $this->_isValid = false; + } + + function getDate() + { + if (isset($this->_packageInfo['release_date'])) { + return $this->_packageInfo['release_date']; + } + return false; + } + + function setDate($date) + { + $this->_packageInfo['release_date'] = $date; + $this->_isValid = false; + } + + function getLicense() + { + if (isset($this->_packageInfo['release_license'])) { + return $this->_packageInfo['release_license']; + } + return false; + } + + function setLicense($date) + { + $this->_packageInfo['release_license'] = $date; + $this->_isValid = false; + } + + function getSummary() + { + if (isset($this->_packageInfo['summary'])) { + return $this->_packageInfo['summary']; + } + return false; + } + + function setSummary($summary) + { + $this->_packageInfo['summary'] = $summary; + $this->_isValid = false; + } + + function getDescription() + { + if (isset($this->_packageInfo['description'])) { + return $this->_packageInfo['description']; + } + return false; + } + + function setDescription($desc) + { + $this->_packageInfo['description'] = $desc; + $this->_isValid = false; + } + + function getNotes() + { + if (isset($this->_packageInfo['release_notes'])) { + return $this->_packageInfo['release_notes']; + } + return false; + } + + function setNotes($notes) + { + $this->_packageInfo['release_notes'] = $notes; + $this->_isValid = false; + } + + function getDeps() + { + if (isset($this->_packageInfo['release_deps'])) { + return $this->_packageInfo['release_deps']; + } + return false; + } + + /** + * Reset dependencies prior to adding new ones + */ + function clearDeps() + { + unset($this->_packageInfo['release_deps']); + } + + function addPhpDep($version, $rel) + { + $this->_isValid = false; + $this->_packageInfo['release_deps'][] = + array('type' => 'php', + 'rel' => $rel, + 'version' => $version); + } + + function addPackageDep($name, $version, $rel, $optional = 'no') + { + $this->_isValid = false; + $dep = + array('type' => 'pkg', + 'name' => $name, + 'rel' => $rel, + 'optional' => $optional); + if ($rel != 'has' && $rel != 'not') { + $dep['version'] = $version; + } + $this->_packageInfo['release_deps'][] = $dep; + } + + function addExtensionDep($name, $version, $rel, $optional = 'no') + { + $this->_isValid = false; + $this->_packageInfo['release_deps'][] = + array('type' => 'ext', + 'name' => $name, + 'rel' => $rel, + 'version' => $version, + 'optional' => $optional); + } + + /** + * WARNING - do not use this function directly unless you know what you're doing + */ + function setDeps($deps) + { + $this->_packageInfo['release_deps'] = $deps; + } + + function hasDeps() + { + return isset($this->_packageInfo['release_deps']) && + count($this->_packageInfo['release_deps']); + } + + function getDependencyGroup($group) + { + return false; + } + + function isCompatible($pf) + { + return false; + } + + function isSubpackageOf($p) + { + return $p->isSubpackage($this); + } + + function isSubpackage($p) + { + return false; + } + + function dependsOn($package, $channel) + { + if (strtolower($channel) != 'pear.php.net') { + return false; + } + if (!($deps = $this->getDeps())) { + return false; + } + foreach ($deps as $dep) { + if ($dep['type'] != 'pkg') { + continue; + } + if (strtolower($dep['name']) == strtolower($package)) { + return true; + } + } + return false; + } + + function getConfigureOptions() + { + if (isset($this->_packageInfo['configure_options'])) { + return $this->_packageInfo['configure_options']; + } + return false; + } + + function hasConfigureOptions() + { + return isset($this->_packageInfo['configure_options']) && + count($this->_packageInfo['configure_options']); + } + + function addConfigureOption($name, $prompt, $default = false) + { + $o = array('name' => $name, 'prompt' => $prompt); + if ($default !== false) { + $o['default'] = $default; + } + if (!isset($this->_packageInfo['configure_options'])) { + $this->_packageInfo['configure_options'] = array(); + } + $this->_packageInfo['configure_options'][] = $o; + } + + function clearConfigureOptions() + { + unset($this->_packageInfo['configure_options']); + } + + function getProvides() + { + if (isset($this->_packageInfo['provides'])) { + return $this->_packageInfo['provides']; + } + return false; + } + + function getProvidesExtension() + { + return false; + } + + function addFile($dir, $file, $attrs) + { + $dir = preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'), $dir); + if ($dir == '/' || $dir == '') { + $dir = ''; + } else { + $dir .= '/'; + } + $file = $dir . $file; + $file = preg_replace('![\\/]+!', '/', $file); + $this->_packageInfo['filelist'][$file] = $attrs; + } + + function getInstallationFilelist() + { + return $this->getFilelist(); + } + + function getFilelist() + { + if (isset($this->_packageInfo['filelist'])) { + return $this->_packageInfo['filelist']; + } + return false; + } + + function setFileAttribute($file, $attr, $value) + { + $this->_packageInfo['filelist'][$file][$attr] = $value; + } + + function resetFilelist() + { + $this->_packageInfo['filelist'] = array(); + } + + function setInstalledAs($file, $path) + { + if ($path) { + return $this->_packageInfo['filelist'][$file]['installed_as'] = $path; + } + unset($this->_packageInfo['filelist'][$file]['installed_as']); + } + + function installedFile($file, $atts) + { + if (isset($this->_packageInfo['filelist'][$file])) { + $this->_packageInfo['filelist'][$file] = + array_merge($this->_packageInfo['filelist'][$file], $atts); + } else { + $this->_packageInfo['filelist'][$file] = $atts; + } + } + + function getChangelog() + { + if (isset($this->_packageInfo['changelog'])) { + return $this->_packageInfo['changelog']; + } + return false; + } + + function getPackagexmlVersion() + { + return '1.0'; + } + + /** + * Wrapper to {@link PEAR_ErrorStack::getErrors()} + * @param boolean determines whether to purge the error stack after retrieving + * @return array + */ + function getValidationWarnings($purge = true) + { + return $this->_stack->getErrors($purge); + } + + // }}} + /** + * Validation error. Also marks the object contents as invalid + * @param error code + * @param array error information + * @access private + */ + function _validateError($code, $params = array()) + { + $this->_stack->push($code, 'error', $params, false, false, debug_backtrace()); + $this->_isValid = false; + } + + /** + * Validation warning. Does not mark the object contents invalid. + * @param error code + * @param array error information + * @access private + */ + function _validateWarning($code, $params = array()) + { + $this->_stack->push($code, 'warning', $params, false, false, debug_backtrace()); + } + + /** + * @param integer error code + * @access protected + */ + function _getErrorMessage() + { + return array( + PEAR_PACKAGEFILE_ERROR_NO_NAME => + 'Missing Package Name', + PEAR_PACKAGEFILE_ERROR_NO_SUMMARY => + 'No summary found', + PEAR_PACKAGEFILE_ERROR_MULTILINE_SUMMARY => + 'Summary should be on one line', + PEAR_PACKAGEFILE_ERROR_NO_DESCRIPTION => + 'Missing description', + PEAR_PACKAGEFILE_ERROR_NO_LICENSE => + 'Missing license', + PEAR_PACKAGEFILE_ERROR_NO_VERSION => + 'No release version found', + PEAR_PACKAGEFILE_ERROR_NO_STATE => + 'No release state found', + PEAR_PACKAGEFILE_ERROR_NO_DATE => + 'No release date found', + PEAR_PACKAGEFILE_ERROR_NO_NOTES => + 'No release notes found', + PEAR_PACKAGEFILE_ERROR_NO_LEAD => + 'Package must have at least one lead maintainer', + PEAR_PACKAGEFILE_ERROR_NO_MAINTAINERS => + 'No maintainers found, at least one must be defined', + PEAR_PACKAGEFILE_ERROR_NO_MAINTHANDLE => + 'Maintainer %index% has no handle (user ID at channel server)', + PEAR_PACKAGEFILE_ERROR_NO_MAINTROLE => + 'Maintainer %index% has no role', + PEAR_PACKAGEFILE_ERROR_NO_MAINTNAME => + 'Maintainer %index% has no name', + PEAR_PACKAGEFILE_ERROR_NO_MAINTEMAIL => + 'Maintainer %index% has no email', + PEAR_PACKAGEFILE_ERROR_NO_DEPNAME => + 'Dependency %index% is not a php dependency, and has no name', + PEAR_PACKAGEFILE_ERROR_NO_DEPREL => + 'Dependency %index% has no relation (rel)', + PEAR_PACKAGEFILE_ERROR_NO_DEPTYPE => + 'Dependency %index% has no type', + PEAR_PACKAGEFILE_ERROR_DEPNAME_IGNORED => + 'PHP Dependency %index% has a name attribute of "%name%" which will be' . + ' ignored!', + PEAR_PACKAGEFILE_ERROR_NO_DEPVERSION => + 'Dependency %index% is not a rel="has" or rel="not" dependency, ' . + 'and has no version', + PEAR_PACKAGEFILE_ERROR_NO_DEPPHPVERSION => + 'Dependency %index% is a type="php" dependency, ' . + 'and has no version', + PEAR_PACKAGEFILE_ERROR_DEPVERSION_IGNORED => + 'Dependency %index% is a rel="%rel%" dependency, versioning is ignored', + PEAR_PACKAGEFILE_ERROR_INVALID_DEPOPTIONAL => + 'Dependency %index% has invalid optional value "%opt%", should be yes or no', + PEAR_PACKAGEFILE_PHP_NO_NOT => + 'Dependency %index%: php dependencies cannot use "not" rel, use "ne"' . + ' to exclude specific versions', + PEAR_PACKAGEFILE_ERROR_NO_CONFNAME => + 'Configure Option %index% has no name', + PEAR_PACKAGEFILE_ERROR_NO_CONFPROMPT => + 'Configure Option %index% has no prompt', + PEAR_PACKAGEFILE_ERROR_NO_FILES => + 'No files in section of package.xml', + PEAR_PACKAGEFILE_ERROR_NO_FILEROLE => + 'File "%file%" has no role, expecting one of "%roles%"', + PEAR_PACKAGEFILE_ERROR_INVALID_FILEROLE => + 'File "%file%" has invalid role "%role%", expecting one of "%roles%"', + PEAR_PACKAGEFILE_ERROR_INVALID_FILENAME => + 'File "%file%" cannot start with ".", cannot package or install', + PEAR_PACKAGEFILE_ERROR_INVALID_PHPFILE => + 'Parser error: invalid PHP found in file "%file%"', + PEAR_PACKAGEFILE_ERROR_NO_PNAME_PREFIX => + 'in %file%: %type% "%name%" not prefixed with package name "%package%"', + PEAR_PACKAGEFILE_ERROR_INVALID_FILE => + 'Parser error: invalid PHP file "%file%"', + PEAR_PACKAGEFILE_ERROR_CHANNELVAL => + 'Channel validator error: field "%field%" - %reason%', + PEAR_PACKAGEFILE_ERROR_PHP5 => + 'Error, PHP5 token encountered in %file%, analysis should be in PHP5', + PEAR_PACKAGEFILE_ERROR_FILE_NOTFOUND => + 'File "%file%" in package.xml does not exist', + PEAR_PACKAGEFILE_ERROR_NON_ISO_CHARS => + 'Package.xml contains non-ISO-8859-1 characters, and may not validate', + ); + } + + /** + * Validate XML package definition file. + * + * @access public + * @return boolean + */ + function validate($state = PEAR_VALIDATE_NORMAL, $nofilechecking = false) + { + if (($this->_isValid & $state) == $state) { + return true; + } + $this->_isValid = true; + $info = $this->_packageInfo; + if (empty($info['package'])) { + $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_NAME); + $this->_packageName = $pn = 'unknown'; + } else { + $this->_packageName = $pn = $info['package']; + } + + if (empty($info['summary'])) { + $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_SUMMARY); + } elseif (strpos(trim($info['summary']), "\n") !== false) { + $this->_validateWarning(PEAR_PACKAGEFILE_ERROR_MULTILINE_SUMMARY, + array('summary' => $info['summary'])); + } + if (empty($info['description'])) { + $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DESCRIPTION); + } + if (empty($info['release_license'])) { + $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_LICENSE); + } + if (empty($info['version'])) { + $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_VERSION); + } + if (empty($info['release_state'])) { + $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_STATE); + } + if (empty($info['release_date'])) { + $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DATE); + } + if (empty($info['release_notes'])) { + $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_NOTES); + } + if (empty($info['maintainers'])) { + $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_MAINTAINERS); + } else { + $haslead = false; + $i = 1; + foreach ($info['maintainers'] as $m) { + if (empty($m['handle'])) { + $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_MAINTHANDLE, + array('index' => $i)); + } + if (empty($m['role'])) { + $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_MAINTROLE, + array('index' => $i, 'roles' => PEAR_Common::getUserRoles())); + } elseif ($m['role'] == 'lead') { + $haslead = true; + } + if (empty($m['name'])) { + $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_MAINTNAME, + array('index' => $i)); + } + if (empty($m['email'])) { + $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_MAINTEMAIL, + array('index' => $i)); + } + $i++; + } + if (!$haslead) { + $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_LEAD); + } + } + if (!empty($info['release_deps'])) { + $i = 1; + foreach ($info['release_deps'] as $d) { + if (!isset($d['type']) || empty($d['type'])) { + $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DEPTYPE, + array('index' => $i, 'types' => PEAR_Common::getDependencyTypes())); + continue; + } + if (!isset($d['rel']) || empty($d['rel'])) { + $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DEPREL, + array('index' => $i, 'rels' => PEAR_Common::getDependencyRelations())); + continue; + } + if (!empty($d['optional'])) { + if (!in_array($d['optional'], array('yes', 'no'))) { + $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_DEPOPTIONAL, + array('index' => $i, 'opt' => $d['optional'])); + } + } + if ($d['rel'] != 'has' && $d['rel'] != 'not' && empty($d['version'])) { + $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DEPVERSION, + array('index' => $i)); + } elseif (($d['rel'] == 'has' || $d['rel'] == 'not') && !empty($d['version'])) { + $this->_validateWarning(PEAR_PACKAGEFILE_ERROR_DEPVERSION_IGNORED, + array('index' => $i, 'rel' => $d['rel'])); + } + if ($d['type'] == 'php' && !empty($d['name'])) { + $this->_validateWarning(PEAR_PACKAGEFILE_ERROR_DEPNAME_IGNORED, + array('index' => $i, 'name' => $d['name'])); + } elseif ($d['type'] != 'php' && empty($d['name'])) { + $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DEPNAME, + array('index' => $i)); + } + if ($d['type'] == 'php' && empty($d['version'])) { + $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DEPPHPVERSION, + array('index' => $i)); + } + if (($d['rel'] == 'not') && ($d['type'] == 'php')) { + $this->_validateError(PEAR_PACKAGEFILE_PHP_NO_NOT, + array('index' => $i)); + } + $i++; + } + } + if (!empty($info['configure_options'])) { + $i = 1; + foreach ($info['configure_options'] as $c) { + if (empty($c['name'])) { + $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_CONFNAME, + array('index' => $i)); + } + if (empty($c['prompt'])) { + $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_CONFPROMPT, + array('index' => $i)); + } + $i++; + } + } + if (empty($info['filelist'])) { + $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_FILES); + $errors[] = 'no files'; + } else { + foreach ($info['filelist'] as $file => $fa) { + if (empty($fa['role'])) { + $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_FILEROLE, + array('file' => $file, 'roles' => PEAR_Common::getFileRoles())); + continue; + } elseif (!in_array($fa['role'], PEAR_Common::getFileRoles())) { + $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_FILEROLE, + array('file' => $file, 'role' => $fa['role'], 'roles' => PEAR_Common::getFileRoles())); + } + if (preg_match('~/\.\.?(/|\\z)|^\.\.?/~', str_replace('\\', '/', $file))) { + // file contains .. parent directory or . cur directory references + $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_FILENAME, + array('file' => $file)); + } + if (isset($fa['install-as']) && + preg_match('~/\.\.?(/|\\z)|^\.\.?/~', + str_replace('\\', '/', $fa['install-as']))) { + // install-as contains .. parent directory or . cur directory references + $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_FILENAME, + array('file' => $file . ' [installed as ' . $fa['install-as'] . ']')); + } + if (isset($fa['baseinstalldir']) && + preg_match('~/\.\.?(/|\\z)|^\.\.?/~', + str_replace('\\', '/', $fa['baseinstalldir']))) { + // install-as contains .. parent directory or . cur directory references + $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_FILENAME, + array('file' => $file . ' [baseinstalldir ' . $fa['baseinstalldir'] . ']')); + } + } + } + if (isset($this->_registry) && $this->_isValid) { + $chan = $this->_registry->getChannel('pear.php.net'); + if (PEAR::isError($chan)) { + $this->_validateError(PEAR_PACKAGEFILE_ERROR_CHANNELVAL, $chan->getMessage()); + return $this->_isValid = 0; + } + $validator = $chan->getValidationObject(); + $validator->setPackageFile($this); + $validator->validate($state); + $failures = $validator->getFailures(); + foreach ($failures['errors'] as $error) { + $this->_validateError(PEAR_PACKAGEFILE_ERROR_CHANNELVAL, $error); + } + foreach ($failures['warnings'] as $warning) { + $this->_validateWarning(PEAR_PACKAGEFILE_ERROR_CHANNELVAL, $warning); + } + } + if ($this->_isValid && $state == PEAR_VALIDATE_PACKAGING && !$nofilechecking) { + if ($this->_analyzePhpFiles()) { + $this->_isValid = true; + } + } + if ($this->_isValid) { + return $this->_isValid = $state; + } + return $this->_isValid = 0; + } + + function _analyzePhpFiles() + { + if (!$this->_isValid) { + return false; + } + if (!isset($this->_packageFile)) { + return false; + } + $dir_prefix = dirname($this->_packageFile); + $common = new PEAR_Common; + $log = isset($this->_logger) ? array(&$this->_logger, 'log') : + array($common, 'log'); + $info = $this->getFilelist(); + foreach ($info as $file => $fa) { + if (!file_exists($dir_prefix . DIRECTORY_SEPARATOR . $file)) { + $this->_validateError(PEAR_PACKAGEFILE_ERROR_FILE_NOTFOUND, + array('file' => realpath($dir_prefix) . DIRECTORY_SEPARATOR . $file)); + continue; + } + if ($fa['role'] == 'php' && $dir_prefix) { + call_user_func_array($log, array(1, "Analyzing $file")); + $srcinfo = $this->_analyzeSourceCode($dir_prefix . DIRECTORY_SEPARATOR . $file); + if ($srcinfo) { + $this->_buildProvidesArray($srcinfo); + } + } + } + $this->_packageName = $pn = $this->getPackage(); + $pnl = strlen($pn); + if (isset($this->_packageInfo['provides'])) { + foreach ((array) $this->_packageInfo['provides'] as $key => $what) { + if (isset($what['explicit'])) { + // skip conformance checks if the provides entry is + // specified in the package.xml file + continue; + } + extract($what); + if ($type == 'class') { + if (!strncasecmp($name, $pn, $pnl)) { + continue; + } + $this->_validateWarning(PEAR_PACKAGEFILE_ERROR_NO_PNAME_PREFIX, + array('file' => $file, 'type' => $type, 'name' => $name, 'package' => $pn)); + } elseif ($type == 'function') { + if (strstr($name, '::') || !strncasecmp($name, $pn, $pnl)) { + continue; + } + $this->_validateWarning(PEAR_PACKAGEFILE_ERROR_NO_PNAME_PREFIX, + array('file' => $file, 'type' => $type, 'name' => $name, 'package' => $pn)); + } + } + } + return $this->_isValid; + } + + /** + * Get the default xml generator object + * + * @return PEAR_PackageFile_Generator_v1 + */ + function &getDefaultGenerator() + { + if (!class_exists('PEAR_PackageFile_Generator_v1')) { + require_once 'PEAR/PackageFile/Generator/v1.php'; + } + $a = &new PEAR_PackageFile_Generator_v1($this); + return $a; + } + + /** + * Get the contents of a file listed within the package.xml + * @param string + * @return string + */ + function getFileContents($file) + { + if ($this->_archiveFile == $this->_packageFile) { // unpacked + $dir = dirname($this->_packageFile); + $file = $dir . DIRECTORY_SEPARATOR . $file; + $file = str_replace(array('/', '\\'), + array(DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR), $file); + if (file_exists($file) && is_readable($file)) { + return implode('', file($file)); + } + } else { // tgz + if (!class_exists('Archive_Tar')) { + require_once 'Archive/Tar.php'; + } + $tar = &new Archive_Tar($this->_archiveFile); + $tar->pushErrorHandling(PEAR_ERROR_RETURN); + if ($file != 'package.xml' && $file != 'package2.xml') { + $file = $this->getPackage() . '-' . $this->getVersion() . '/' . $file; + } + $file = $tar->extractInString($file); + $tar->popErrorHandling(); + if (PEAR::isError($file)) { + return PEAR::raiseError("Cannot locate file '$file' in archive"); + } + return $file; + } + } + + // {{{ analyzeSourceCode() + /** + * Analyze the source code of the given PHP file + * + * @param string Filename of the PHP file + * @return mixed + * @access private + */ + function _analyzeSourceCode($file) + { + if (!function_exists("token_get_all")) { + return false; + } + if (!defined('T_DOC_COMMENT')) { + define('T_DOC_COMMENT', T_COMMENT); + } + if (!defined('T_INTERFACE')) { + define('T_INTERFACE', -1); + } + if (!defined('T_IMPLEMENTS')) { + define('T_IMPLEMENTS', -1); + } + if (!$fp = @fopen($file, "r")) { + return false; + } + fclose($fp); + $contents = file_get_contents($file); + $tokens = token_get_all($contents); +/* + for ($i = 0; $i < sizeof($tokens); $i++) { + @list($token, $data) = $tokens[$i]; + if (is_string($token)) { + var_dump($token); + } else { + print token_name($token) . ' '; + var_dump(rtrim($data)); + } + } +*/ + $look_for = 0; + $paren_level = 0; + $bracket_level = 0; + $brace_level = 0; + $lastphpdoc = ''; + $current_class = ''; + $current_interface = ''; + $current_class_level = -1; + $current_function = ''; + $current_function_level = -1; + $declared_classes = array(); + $declared_interfaces = array(); + $declared_functions = array(); + $declared_methods = array(); + $used_classes = array(); + $used_functions = array(); + $extends = array(); + $implements = array(); + $nodeps = array(); + $inquote = false; + $interface = false; + for ($i = 0; $i < sizeof($tokens); $i++) { + if (is_array($tokens[$i])) { + list($token, $data) = $tokens[$i]; + } else { + $token = $tokens[$i]; + $data = ''; + } + if ($inquote) { + if ($token != '"' && $token != T_END_HEREDOC) { + continue; + } else { + $inquote = false; + continue; + } + } + switch ($token) { + case T_WHITESPACE : + continue; + case ';': + if ($interface) { + $current_function = ''; + $current_function_level = -1; + } + break; + case '"': + case T_START_HEREDOC: + $inquote = true; + break; + case T_CURLY_OPEN: + case T_DOLLAR_OPEN_CURLY_BRACES: + case '{': $brace_level++; continue 2; + case '}': + $brace_level--; + if ($current_class_level == $brace_level) { + $current_class = ''; + $current_class_level = -1; + } + if ($current_function_level == $brace_level) { + $current_function = ''; + $current_function_level = -1; + } + continue 2; + case '[': $bracket_level++; continue 2; + case ']': $bracket_level--; continue 2; + case '(': $paren_level++; continue 2; + case ')': $paren_level--; continue 2; + case T_INTERFACE: + $interface = true; + case T_CLASS: + if (($current_class_level != -1) || ($current_function_level != -1)) { + $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_PHPFILE, + array('file' => $file)); + return false; + } + case T_FUNCTION: + case T_NEW: + case T_EXTENDS: + case T_IMPLEMENTS: + $look_for = $token; + continue 2; + case T_STRING: + if (version_compare(zend_version(), '2.0', '<')) { + if (in_array(strtolower($data), + array('public', 'private', 'protected', 'abstract', + 'interface', 'implements', 'throw') + )) { + $this->_validateWarning(PEAR_PACKAGEFILE_ERROR_PHP5, + array($file)); + } + } + if ($look_for == T_CLASS) { + $current_class = $data; + $current_class_level = $brace_level; + $declared_classes[] = $current_class; + } elseif ($look_for == T_INTERFACE) { + $current_interface = $data; + $current_class_level = $brace_level; + $declared_interfaces[] = $current_interface; + } elseif ($look_for == T_IMPLEMENTS) { + $implements[$current_class] = $data; + } elseif ($look_for == T_EXTENDS) { + $extends[$current_class] = $data; + } elseif ($look_for == T_FUNCTION) { + if ($current_class) { + $current_function = "$current_class::$data"; + $declared_methods[$current_class][] = $data; + } elseif ($current_interface) { + $current_function = "$current_interface::$data"; + $declared_methods[$current_interface][] = $data; + } else { + $current_function = $data; + $declared_functions[] = $current_function; + } + $current_function_level = $brace_level; + $m = array(); + } elseif ($look_for == T_NEW) { + $used_classes[$data] = true; + } + $look_for = 0; + continue 2; + case T_VARIABLE: + $look_for = 0; + continue 2; + case T_DOC_COMMENT: + case T_COMMENT: + if (preg_match('!^/\*\*\s!', $data)) { + $lastphpdoc = $data; + if (preg_match_all('/@nodep\s+(\S+)/', $lastphpdoc, $m)) { + $nodeps = array_merge($nodeps, $m[1]); + } + } + continue 2; + case T_DOUBLE_COLON: + if (!($tokens[$i - 1][0] == T_WHITESPACE || $tokens[$i - 1][0] == T_STRING)) { + $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_PHPFILE, + array('file' => $file)); + return false; + } + $class = $tokens[$i - 1][1]; + if (strtolower($class) != 'parent') { + $used_classes[$class] = true; + } + continue 2; + } + } + return array( + "source_file" => $file, + "declared_classes" => $declared_classes, + "declared_interfaces" => $declared_interfaces, + "declared_methods" => $declared_methods, + "declared_functions" => $declared_functions, + "used_classes" => array_diff(array_keys($used_classes), $nodeps), + "inheritance" => $extends, + "implements" => $implements, + ); + } + + /** + * Build a "provides" array from data returned by + * analyzeSourceCode(). The format of the built array is like + * this: + * + * array( + * 'class;MyClass' => 'array('type' => 'class', 'name' => 'MyClass'), + * ... + * ) + * + * + * @param array $srcinfo array with information about a source file + * as returned by the analyzeSourceCode() method. + * + * @return void + * + * @access private + * + */ + function _buildProvidesArray($srcinfo) + { + if (!$this->_isValid) { + return false; + } + $file = basename($srcinfo['source_file']); + $pn = $this->getPackage(); + $pnl = strlen($pn); + foreach ($srcinfo['declared_classes'] as $class) { + $key = "class;$class"; + if (isset($this->_packageInfo['provides'][$key])) { + continue; + } + $this->_packageInfo['provides'][$key] = + array('file'=> $file, 'type' => 'class', 'name' => $class); + if (isset($srcinfo['inheritance'][$class])) { + $this->_packageInfo['provides'][$key]['extends'] = + $srcinfo['inheritance'][$class]; + } + } + foreach ($srcinfo['declared_methods'] as $class => $methods) { + foreach ($methods as $method) { + $function = "$class::$method"; + $key = "function;$function"; + if ($method{0} == '_' || !strcasecmp($method, $class) || + isset($this->_packageInfo['provides'][$key])) { + continue; + } + $this->_packageInfo['provides'][$key] = + array('file'=> $file, 'type' => 'function', 'name' => $function); + } + } + + foreach ($srcinfo['declared_functions'] as $function) { + $key = "function;$function"; + if ($function{0} == '_' || isset($this->_packageInfo['provides'][$key])) { + continue; + } + if (!strstr($function, '::') && strncasecmp($function, $pn, $pnl)) { + $warnings[] = "in1 " . $file . ": function \"$function\" not prefixed with package name \"$pn\""; + } + $this->_packageInfo['provides'][$key] = + array('file'=> $file, 'type' => 'function', 'name' => $function); + } + } + + // }}} +} +?> diff --git a/src/lib/pear/PEAR/PEAR/PackageFile/v2.php b/src/lib/pear/PEAR/PEAR/PackageFile/v2.php new file mode 100644 index 0000000..4638a77 --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/PackageFile/v2.php @@ -0,0 +1,2046 @@ + + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: v2.php,v 1.143 2008/05/13 05:28:51 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 1.4.0a1 + */ +/** + * For error handling + */ +require_once 'PEAR/ErrorStack.php'; +/** + * @category pear + * @package PEAR + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 1.4.0a1 + */ +class PEAR_PackageFile_v2 +{ + + /** + * Parsed package information + * @var array + * @access private + */ + var $_packageInfo = array(); + + /** + * path to package .tgz or false if this is a local/extracted package.xml + * @var string|false + * @access private + */ + var $_archiveFile; + + /** + * path to package .xml or false if this is an abstract parsed-from-string xml + * @var string|false + * @access private + */ + var $_packageFile; + + /** + * This is used by file analysis routines to log progress information + * @var PEAR_Common + * @access protected + */ + var $_logger; + + /** + * This is set to the highest validation level that has been validated + * + * If the package.xml is invalid or unknown, this is set to 0. If + * normal validation has occurred, this is set to PEAR_VALIDATE_NORMAL. If + * downloading/installation validation has occurred it is set to PEAR_VALIDATE_DOWNLOADING + * or INSTALLING, and so on up to PEAR_VALIDATE_PACKAGING. This allows validation + * "caching" to occur, which is particularly important for package validation, so + * that PHP files are not validated twice + * @var int + * @access private + */ + var $_isValid = 0; + + /** + * True if the filelist has been validated + * @param bool + */ + var $_filesValid = false; + + /** + * @var PEAR_Registry + * @access protected + */ + var $_registry; + + /** + * @var PEAR_Config + * @access protected + */ + var $_config; + + /** + * Optional Dependency group requested for installation + * @var string + * @access private + */ + var $_requestedGroup = false; + + /** + * @var PEAR_ErrorStack + * @access protected + */ + var $_stack; + + /** + * Namespace prefix used for tasks in this package.xml - use tasks: whenever possible + */ + var $_tasksNs; + + /** + * Determines whether this packagefile was initialized only with partial package info + * + * If this package file was constructed via parsing REST, it will only contain + * + * - package name + * - channel name + * - dependencies + * @var boolean + * @access private + */ + var $_incomplete = true; + + /** + * @var PEAR_PackageFile_v2_Validator + */ + var $_v2Validator; + + /** + * The constructor merely sets up the private error stack + */ + function PEAR_PackageFile_v2() + { + $this->_stack = new PEAR_ErrorStack('PEAR_PackageFile_v2', false, null); + $this->_isValid = false; + } + + /** + * To make unit-testing easier + * @param PEAR_Frontend_* + * @param array options + * @param PEAR_Config + * @return PEAR_Downloader + * @access protected + */ + function &getPEARDownloader(&$i, $o, &$c) + { + $z = &new PEAR_Downloader($i, $o, $c); + return $z; + } + + /** + * To make unit-testing easier + * @param PEAR_Config + * @param array options + * @param array package name as returned from {@link PEAR_Registry::parsePackageName()} + * @param int PEAR_VALIDATE_* constant + * @return PEAR_Dependency2 + * @access protected + */ + function &getPEARDependency2(&$c, $o, $p, $s = PEAR_VALIDATE_INSTALLING) + { + if (!class_exists('PEAR_Dependency2')) { + require_once 'PEAR/Dependency2.php'; + } + $z = &new PEAR_Dependency2($c, $o, $p, $s); + return $z; + } + + function getInstalledBinary() + { + return isset($this->_packageInfo['#binarypackage']) ? $this->_packageInfo['#binarypackage'] : + false; + } + + /** + * Installation of source package has failed, attempt to download and install the + * binary version of this package. + * @param PEAR_Installer + * @return array|false + */ + function installBinary(&$installer) + { + if (!OS_WINDOWS) { + $a = false; + return $a; + } + if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') { + $releasetype = $this->getPackageType() . 'release'; + if (!is_array($installer->getInstallPackages())) { + $a = false; + return $a; + } + foreach ($installer->getInstallPackages() as $p) { + if ($p->isExtension($this->_packageInfo['providesextension'])) { + if ($p->getPackageType() != 'extsrc' && $p->getPackageType() != 'zendextsrc') { + $a = false; + return $a; // the user probably downloaded it separately + } + } + } + if (isset($this->_packageInfo[$releasetype]['binarypackage'])) { + $installer->log(0, 'Attempting to download binary version of extension "' . + $this->_packageInfo['providesextension'] . '"'); + $params = $this->_packageInfo[$releasetype]['binarypackage']; + if (!is_array($params) || !isset($params[0])) { + $params = array($params); + } + if (isset($this->_packageInfo['channel'])) { + foreach ($params as $i => $param) { + $params[$i] = array('channel' => $this->_packageInfo['channel'], + 'package' => $param, 'version' => $this->getVersion()); + } + } + $dl = &$this->getPEARDownloader($installer->ui, $installer->getOptions(), + $installer->config); + $verbose = $dl->config->get('verbose'); + $dl->config->set('verbose', -1); + foreach ($params as $param) { + PEAR::pushErrorHandling(PEAR_ERROR_RETURN); + $ret = $dl->download(array($param)); + PEAR::popErrorHandling(); + if (is_array($ret) && count($ret)) { + break; + } + } + $dl->config->set('verbose', $verbose); + if (is_array($ret)) { + if (count($ret) == 1) { + $pf = $ret[0]->getPackageFile(); + PEAR::pushErrorHandling(PEAR_ERROR_RETURN); + $err = $installer->install($ret[0]); + PEAR::popErrorHandling(); + if (is_array($err)) { + $this->_packageInfo['#binarypackage'] = $ret[0]->getPackage(); + // "install" self, so all dependencies will work transparently + $this->_registry->addPackage2($this); + $installer->log(0, 'Download and install of binary extension "' . + $this->_registry->parsedPackageNameToString( + array('channel' => $pf->getChannel(), + 'package' => $pf->getPackage()), true) . '" successful'); + $a = array($ret[0], $err); + return $a; + } + $installer->log(0, 'Download and install of binary extension "' . + $this->_registry->parsedPackageNameToString( + array('channel' => $pf->getChannel(), + 'package' => $pf->getPackage()), true) . '" failed'); + } + } + } + } + $a = false; + return $a; + } + + /** + * @return string|false Extension name + */ + function getProvidesExtension() + { + if (in_array($this->getPackageType(), + array('extsrc', 'extbin', 'zendextsrc', 'zendextbin'))) { + if (isset($this->_packageInfo['providesextension'])) { + return $this->_packageInfo['providesextension']; + } + } + return false; + } + + /** + * @param string Extension name + * @return bool + */ + function isExtension($extension) + { + if (in_array($this->getPackageType(), + array('extsrc', 'extbin', 'zendextsrc', 'zendextbin'))) { + return $this->_packageInfo['providesextension'] == $extension; + } + return false; + } + + /** + * Tests whether every part of the package.xml 1.0 is represented in + * this package.xml 2.0 + * @param PEAR_PackageFile_v1 + * @return bool + */ + function isEquivalent($pf1) + { + if (!$pf1) { + return true; + } + if ($this->getPackageType() == 'bundle') { + return false; + } + $this->_stack->getErrors(true); + if (!$pf1->validate(PEAR_VALIDATE_NORMAL)) { + return false; + } + $pass = true; + if ($pf1->getPackage() != $this->getPackage()) { + $this->_differentPackage($pf1->getPackage()); + $pass = false; + } + if ($pf1->getVersion() != $this->getVersion()) { + $this->_differentVersion($pf1->getVersion()); + $pass = false; + } + if (trim($pf1->getSummary()) != $this->getSummary()) { + $this->_differentSummary($pf1->getSummary()); + $pass = false; + } + if (preg_replace('/\s+/', '', $pf1->getDescription()) != + preg_replace('/\s+/', '', $this->getDescription())) { + $this->_differentDescription($pf1->getDescription()); + $pass = false; + } + if ($pf1->getState() != $this->getState()) { + $this->_differentState($pf1->getState()); + $pass = false; + } + if (!strstr(preg_replace('/\s+/', '', $this->getNotes()), + preg_replace('/\s+/', '', $pf1->getNotes()))) { + $this->_differentNotes($pf1->getNotes()); + $pass = false; + } + $mymaintainers = $this->getMaintainers(); + $yourmaintainers = $pf1->getMaintainers(); + for ($i1 = 0; $i1 < count($yourmaintainers); $i1++) { + $reset = false; + for ($i2 = 0; $i2 < count($mymaintainers); $i2++) { + if ($mymaintainers[$i2]['handle'] == $yourmaintainers[$i1]['handle']) { + if ($mymaintainers[$i2]['role'] != $yourmaintainers[$i1]['role']) { + $this->_differentRole($mymaintainers[$i2]['handle'], + $yourmaintainers[$i1]['role'], $mymaintainers[$i2]['role']); + $pass = false; + } + if ($mymaintainers[$i2]['email'] != $yourmaintainers[$i1]['email']) { + $this->_differentEmail($mymaintainers[$i2]['handle'], + $yourmaintainers[$i1]['email'], $mymaintainers[$i2]['email']); + $pass = false; + } + if ($mymaintainers[$i2]['name'] != $yourmaintainers[$i1]['name']) { + $this->_differentName($mymaintainers[$i2]['handle'], + $yourmaintainers[$i1]['name'], $mymaintainers[$i2]['name']); + $pass = false; + } + unset($mymaintainers[$i2]); + $mymaintainers = array_values($mymaintainers); + unset($yourmaintainers[$i1]); + $yourmaintainers = array_values($yourmaintainers); + $reset = true; + break; + } + } + if ($reset) { + $i1 = -1; + } + } + $this->_unmatchedMaintainers($mymaintainers, $yourmaintainers); + $filelist = $this->getFilelist(); + foreach ($pf1->getFilelist() as $file => $atts) { + if (!isset($filelist[$file])) { + $this->_missingFile($file); + $pass = false; + } + } + return $pass; + } + + function _differentPackage($package) + { + $this->_stack->push(__FUNCTION__, 'error', array('package' => $package, + 'self' => $this->getPackage()), + 'package.xml 1.0 package "%package%" does not match "%self%"'); + } + + function _differentVersion($version) + { + $this->_stack->push(__FUNCTION__, 'error', array('version' => $version, + 'self' => $this->getVersion()), + 'package.xml 1.0 version "%version%" does not match "%self%"'); + } + + function _differentState($state) + { + $this->_stack->push(__FUNCTION__, 'error', array('state' => $state, + 'self' => $this->getState()), + 'package.xml 1.0 state "%state%" does not match "%self%"'); + } + + function _differentRole($handle, $role, $selfrole) + { + $this->_stack->push(__FUNCTION__, 'error', array('handle' => $handle, + 'role' => $role, 'self' => $selfrole), + 'package.xml 1.0 maintainer "%handle%" role "%role%" does not match "%self%"'); + } + + function _differentEmail($handle, $email, $selfemail) + { + $this->_stack->push(__FUNCTION__, 'error', array('handle' => $handle, + 'email' => $email, 'self' => $selfemail), + 'package.xml 1.0 maintainer "%handle%" email "%email%" does not match "%self%"'); + } + + function _differentName($handle, $name, $selfname) + { + $this->_stack->push(__FUNCTION__, 'error', array('handle' => $handle, + 'name' => $name, 'self' => $selfname), + 'package.xml 1.0 maintainer "%handle%" name "%name%" does not match "%self%"'); + } + + function _unmatchedMaintainers($my, $yours) + { + if ($my) { + array_walk($my, create_function('&$i, $k', '$i = $i["handle"];')); + $this->_stack->push(__FUNCTION__, 'error', array('handles' => $my), + 'package.xml 2.0 has unmatched extra maintainers "%handles%"'); + } + if ($yours) { + array_walk($yours, create_function('&$i, $k', '$i = $i["handle"];')); + $this->_stack->push(__FUNCTION__, 'error', array('handles' => $yours), + 'package.xml 1.0 has unmatched extra maintainers "%handles%"'); + } + } + + function _differentNotes($notes) + { + $truncnotes = strlen($notes) < 25 ? $notes : substr($notes, 0, 24) . '...'; + $truncmynotes = strlen($this->getNotes()) < 25 ? $this->getNotes() : + substr($this->getNotes(), 0, 24) . '...'; + $this->_stack->push(__FUNCTION__, 'error', array('notes' => $truncnotes, + 'self' => $truncmynotes), + 'package.xml 1.0 release notes "%notes%" do not match "%self%"'); + } + + function _differentSummary($summary) + { + $truncsummary = strlen($summary) < 25 ? $summary : substr($summary, 0, 24) . '...'; + $truncmysummary = strlen($this->getsummary()) < 25 ? $this->getSummary() : + substr($this->getsummary(), 0, 24) . '...'; + $this->_stack->push(__FUNCTION__, 'error', array('summary' => $truncsummary, + 'self' => $truncmysummary), + 'package.xml 1.0 summary "%summary%" does not match "%self%"'); + } + + function _differentDescription($description) + { + $truncdescription = trim(strlen($description) < 25 ? $description : substr($description, 0, 24) . '...'); + $truncmydescription = trim(strlen($this->getDescription()) < 25 ? $this->getDescription() : + substr($this->getdescription(), 0, 24) . '...'); + $this->_stack->push(__FUNCTION__, 'error', array('description' => $truncdescription, + 'self' => $truncmydescription), + 'package.xml 1.0 description "%description%" does not match "%self%"'); + } + + function _missingFile($file) + { + $this->_stack->push(__FUNCTION__, 'error', array('file' => $file), + 'package.xml 1.0 file "%file%" is not present in '); + } + + /** + * WARNING - do not use this function unless you know what you're doing + */ + function setRawState($state) + { + if (!isset($this->_packageInfo['stability'])) { + $this->_packageInfo['stability'] = array(); + } + $this->_packageInfo['stability']['release'] = $state; + } + + /** + * WARNING - do not use this function unless you know what you're doing + */ + function setRawCompatible($compatible) + { + $this->_packageInfo['compatible'] = $compatible; + } + + /** + * WARNING - do not use this function unless you know what you're doing + */ + function setRawPackage($package) + { + $this->_packageInfo['name'] = $package; + } + + /** + * WARNING - do not use this function unless you know what you're doing + */ + function setRawChannel($channel) + { + $this->_packageInfo['channel'] = $channel; + } + + function setRequestedGroup($group) + { + $this->_requestedGroup = $group; + } + + function getRequestedGroup() + { + if (isset($this->_requestedGroup)) { + return $this->_requestedGroup; + } + return false; + } + + /** + * For saving in the registry. + * + * Set the last version that was installed + * @param string + */ + function setLastInstalledVersion($version) + { + $this->_packageInfo['_lastversion'] = $version; + } + + /** + * @return string|false + */ + function getLastInstalledVersion() + { + if (isset($this->_packageInfo['_lastversion'])) { + return $this->_packageInfo['_lastversion']; + } + return false; + } + + /** + * Determines whether this package.xml has post-install scripts or not + * @return array|false + */ + function listPostinstallScripts() + { + $filelist = $this->getFilelist(); + $contents = $this->getContents(); + $contents = $contents['dir']['file']; + if (!is_array($contents) || !isset($contents[0])) { + $contents = array($contents); + } + $taskfiles = array(); + foreach ($contents as $file) { + $atts = $file['attribs']; + unset($file['attribs']); + if (count($file)) { + $taskfiles[$atts['name']] = $file; + } + } + $common = new PEAR_Common; + $common->debug = $this->_config->get('verbose'); + $this->_scripts = array(); + $ret = array(); + foreach ($taskfiles as $name => $tasks) { + if (!isset($filelist[$name])) { + // ignored files will not be in the filelist + continue; + } + $atts = $filelist[$name]; + foreach ($tasks as $tag => $raw) { + $task = $this->getTask($tag); + $task = &new $task($this->_config, $common, PEAR_TASK_INSTALL); + if ($task->isScript()) { + $ret[] = $filelist[$name]['installed_as']; + } + } + } + if (count($ret)) { + return $ret; + } + return false; + } + + /** + * Initialize post-install scripts for running + * + * This method can be used to detect post-install scripts, as the return value + * indicates whether any exist + * @return bool + */ + function initPostinstallScripts() + { + $filelist = $this->getFilelist(); + $contents = $this->getContents(); + $contents = $contents['dir']['file']; + if (!is_array($contents) || !isset($contents[0])) { + $contents = array($contents); + } + $taskfiles = array(); + foreach ($contents as $file) { + $atts = $file['attribs']; + unset($file['attribs']); + if (count($file)) { + $taskfiles[$atts['name']] = $file; + } + } + $common = new PEAR_Common; + $common->debug = $this->_config->get('verbose'); + $this->_scripts = array(); + foreach ($taskfiles as $name => $tasks) { + if (!isset($filelist[$name])) { + // file was not installed due to installconditions + continue; + } + $atts = $filelist[$name]; + foreach ($tasks as $tag => $raw) { + $taskname = $this->getTask($tag); + $task = &new $taskname($this->_config, $common, PEAR_TASK_INSTALL); + if (!$task->isScript()) { + continue; // scripts are only handled after installation + } + $lastversion = isset($this->_packageInfo['_lastversion']) ? + $this->_packageInfo['_lastversion'] : null; + $task->init($raw, $atts, $lastversion); + $res = $task->startSession($this, $atts['installed_as']); + if (!$res) { + continue; // skip this file + } + if (PEAR::isError($res)) { + return $res; + } + $assign = &$task; + $this->_scripts[] = &$assign; + } + } + if (count($this->_scripts)) { + return true; + } + return false; + } + + function runPostinstallScripts() + { + if ($this->initPostinstallScripts()) { + $ui = &PEAR_Frontend::singleton(); + if ($ui) { + $ui->runPostinstallScripts($this->_scripts, $this); + } + } + } + + + /** + * Convert a recursive set of and tags into a single tag with + * tags. + */ + function flattenFilelist() + { + if (isset($this->_packageInfo['bundle'])) { + return; + } + $filelist = array(); + if (isset($this->_packageInfo['contents']['dir']['dir'])) { + $this->_getFlattenedFilelist($filelist, $this->_packageInfo['contents']['dir']); + if (!isset($filelist[1])) { + $filelist = $filelist[0]; + } + $this->_packageInfo['contents']['dir']['file'] = $filelist; + unset($this->_packageInfo['contents']['dir']['dir']); + } else { + // else already flattened but check for baseinstalldir propagation + if (isset($this->_packageInfo['contents']['dir']['attribs']['baseinstalldir'])) { + if (isset($this->_packageInfo['contents']['dir']['file'][0])) { + foreach ($this->_packageInfo['contents']['dir']['file'] as $i => $file) { + if (isset($file['attribs']['baseinstalldir'])) { + continue; + } + $this->_packageInfo['contents']['dir']['file'][$i]['attribs']['baseinstalldir'] + = $this->_packageInfo['contents']['dir']['attribs']['baseinstalldir']; + } + } else { + if (!isset($this->_packageInfo['contents']['dir']['file']['attribs']['baseinstalldir'])) { + $this->_packageInfo['contents']['dir']['file']['attribs']['baseinstalldir'] + = $this->_packageInfo['contents']['dir']['attribs']['baseinstalldir']; + } + } + } + } + } + + /** + * @param array the final flattened file list + * @param array the current directory being processed + * @param string|false any recursively inherited baeinstalldir attribute + * @param string private recursion variable + * @return array + * @access protected + */ + function _getFlattenedFilelist(&$files, $dir, $baseinstall = false, $path = '') + { + if (isset($dir['attribs']) && isset($dir['attribs']['baseinstalldir'])) { + $baseinstall = $dir['attribs']['baseinstalldir']; + } + if (isset($dir['dir'])) { + if (!isset($dir['dir'][0])) { + $dir['dir'] = array($dir['dir']); + } + foreach ($dir['dir'] as $subdir) { + if (!isset($subdir['attribs']) || !isset($subdir['attribs']['name'])) { + $name = '*unknown*'; + } else { + $name = $subdir['attribs']['name']; + } + $newpath = empty($path) ? $name : + $path . '/' . $name; + $this->_getFlattenedFilelist($files, $subdir, + $baseinstall, $newpath); + } + } + if (isset($dir['file'])) { + if (!isset($dir['file'][0])) { + $dir['file'] = array($dir['file']); + } + foreach ($dir['file'] as $file) { + $attrs = $file['attribs']; + $name = $attrs['name']; + if ($baseinstall && !isset($attrs['baseinstalldir'])) { + $attrs['baseinstalldir'] = $baseinstall; + } + $attrs['name'] = empty($path) ? $name : $path . '/' . $name; + $attrs['name'] = preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'), + $attrs['name']); + $file['attribs'] = $attrs; + $files[] = $file; + } + } + } + + function setConfig(&$config) + { + $this->_config = &$config; + $this->_registry = &$config->getRegistry(); + } + + function setLogger(&$logger) + { + if (!is_object($logger) || !method_exists($logger, 'log')) { + return PEAR::raiseError('Logger must be compatible with PEAR_Common::log'); + } + $this->_logger = &$logger; + } + + /** + * WARNING - do not use this function directly unless you know what you're doing + */ + function setDeps($deps) + { + $this->_packageInfo['dependencies'] = $deps; + } + + /** + * WARNING - do not use this function directly unless you know what you're doing + */ + function setCompatible($compat) + { + $this->_packageInfo['compatible'] = $compat; + } + + function setPackagefile($file, $archive = false) + { + $this->_packageFile = $file; + $this->_archiveFile = $archive ? $archive : $file; + } + + /** + * Wrapper to {@link PEAR_ErrorStack::getErrors()} + * @param boolean determines whether to purge the error stack after retrieving + * @return array + */ + function getValidationWarnings($purge = true) + { + return $this->_stack->getErrors($purge); + } + + function getPackageFile() + { + return $this->_packageFile; + } + + function getArchiveFile() + { + return $this->_archiveFile; + } + + + /** + * Directly set the array that defines this packagefile + * + * WARNING: no validation. This should only be performed by internal methods + * inside PEAR or by inputting an array saved from an existing PEAR_PackageFile_v2 + * @param array + */ + function fromArray($pinfo) + { + unset($pinfo['old']); + unset($pinfo['xsdversion']); + $this->_incomplete = false; + $this->_packageInfo = $pinfo; + } + + function isIncomplete() + { + return $this->_incomplete; + } + + /** + * @return array + */ + function toArray($forreg = false) + { + if (!$this->validate(PEAR_VALIDATE_NORMAL)) { + return false; + } + return $this->getArray($forreg); + } + + function getArray($forReg = false) + { + if ($forReg) { + $arr = $this->_packageInfo; + $arr['old'] = array(); + $arr['old']['version'] = $this->getVersion(); + $arr['old']['release_date'] = $this->getDate(); + $arr['old']['release_state'] = $this->getState(); + $arr['old']['release_license'] = $this->getLicense(); + $arr['old']['release_notes'] = $this->getNotes(); + $arr['old']['release_deps'] = $this->getDeps(); + $arr['old']['maintainers'] = $this->getMaintainers(); + $arr['xsdversion'] = '2.0'; + return $arr; + } else { + $info = $this->_packageInfo; + unset($info['dirtree']); + if (isset($info['_lastversion'])) { + unset($info['_lastversion']); + } + if (isset($info['#binarypackage'])) { + unset($info['#binarypackage']); + } + return $info; + } + } + + function packageInfo($field) + { + $arr = $this->getArray(true); + if ($field == 'state') { + return $arr['stability']['release']; + } + if ($field == 'api-version') { + return $arr['version']['api']; + } + if ($field == 'api-state') { + return $arr['stability']['api']; + } + if (isset($arr['old'][$field])) { + if (!is_string($arr['old'][$field])) { + return null; + } + return $arr['old'][$field]; + } + if (isset($arr[$field])) { + if (!is_string($arr[$field])) { + return null; + } + return $arr[$field]; + } + return null; + } + + function getName() + { + return $this->getPackage(); + } + + function getPackage() + { + if (isset($this->_packageInfo['name'])) { + return $this->_packageInfo['name']; + } + return false; + } + + function getChannel() + { + if (isset($this->_packageInfo['uri'])) { + return '__uri'; + } + if (isset($this->_packageInfo['channel'])) { + return strtolower($this->_packageInfo['channel']); + } + return false; + } + + function getUri() + { + if (isset($this->_packageInfo['uri'])) { + return $this->_packageInfo['uri']; + } + return false; + } + + function getExtends() + { + if (isset($this->_packageInfo['extends'])) { + return $this->_packageInfo['extends']; + } + return false; + } + + function getSummary() + { + if (isset($this->_packageInfo['summary'])) { + return $this->_packageInfo['summary']; + } + return false; + } + + function getDescription() + { + if (isset($this->_packageInfo['description'])) { + return $this->_packageInfo['description']; + } + return false; + } + + function getMaintainers($raw = false) + { + if (!isset($this->_packageInfo['lead'])) { + return false; + } + if ($raw) { + $ret = array('lead' => $this->_packageInfo['lead']); + (isset($this->_packageInfo['developer'])) ? + $ret['developer'] = $this->_packageInfo['developer'] :null; + (isset($this->_packageInfo['contributor'])) ? + $ret['contributor'] = $this->_packageInfo['contributor'] :null; + (isset($this->_packageInfo['helper'])) ? + $ret['helper'] = $this->_packageInfo['helper'] :null; + return $ret; + } else { + $ret = array(); + $leads = isset($this->_packageInfo['lead'][0]) ? $this->_packageInfo['lead'] : + array($this->_packageInfo['lead']); + foreach ($leads as $lead) { + $s = $lead; + $s['handle'] = $s['user']; + unset($s['user']); + $s['role'] = 'lead'; + $ret[] = $s; + } + if (isset($this->_packageInfo['developer'])) { + $leads = isset($this->_packageInfo['developer'][0]) ? + $this->_packageInfo['developer'] : + array($this->_packageInfo['developer']); + foreach ($leads as $maintainer) { + $s = $maintainer; + $s['handle'] = $s['user']; + unset($s['user']); + $s['role'] = 'developer'; + $ret[] = $s; + } + } + if (isset($this->_packageInfo['contributor'])) { + $leads = isset($this->_packageInfo['contributor'][0]) ? + $this->_packageInfo['contributor'] : + array($this->_packageInfo['contributor']); + foreach ($leads as $maintainer) { + $s = $maintainer; + $s['handle'] = $s['user']; + unset($s['user']); + $s['role'] = 'contributor'; + $ret[] = $s; + } + } + if (isset($this->_packageInfo['helper'])) { + $leads = isset($this->_packageInfo['helper'][0]) ? + $this->_packageInfo['helper'] : + array($this->_packageInfo['helper']); + foreach ($leads as $maintainer) { + $s = $maintainer; + $s['handle'] = $s['user']; + unset($s['user']); + $s['role'] = 'helper'; + $ret[] = $s; + } + } + return $ret; + } + return false; + } + + function getLeads() + { + if (isset($this->_packageInfo['lead'])) { + return $this->_packageInfo['lead']; + } + return false; + } + + function getDevelopers() + { + if (isset($this->_packageInfo['developer'])) { + return $this->_packageInfo['developer']; + } + return false; + } + + function getContributors() + { + if (isset($this->_packageInfo['contributor'])) { + return $this->_packageInfo['contributor']; + } + return false; + } + + function getHelpers() + { + if (isset($this->_packageInfo['helper'])) { + return $this->_packageInfo['helper']; + } + return false; + } + + function setDate($date) + { + if (!isset($this->_packageInfo['date'])) { + // ensure that the extends tag is set up in the right location + $this->_packageInfo = $this->_insertBefore($this->_packageInfo, + array('time', 'version', + 'stability', 'license', 'notes', 'contents', 'compatible', + 'dependencies', 'providesextension', 'srcpackage', 'srcuri', + 'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', + 'zendextbinrelease', 'bundle', 'changelog'), array(), 'date'); + } + $this->_packageInfo['date'] = $date; + $this->_isValid = 0; + } + + function setTime($time) + { + $this->_isValid = 0; + if (!isset($this->_packageInfo['time'])) { + // ensure that the time tag is set up in the right location + $this->_packageInfo = $this->_insertBefore($this->_packageInfo, + array('version', + 'stability', 'license', 'notes', 'contents', 'compatible', + 'dependencies', 'providesextension', 'srcpackage', 'srcuri', + 'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', + 'zendextbinrelease', 'bundle', 'changelog'), $time, 'time'); + } + $this->_packageInfo['time'] = $time; + } + + function getDate() + { + if (isset($this->_packageInfo['date'])) { + return $this->_packageInfo['date']; + } + return false; + } + + function getTime() + { + if (isset($this->_packageInfo['time'])) { + return $this->_packageInfo['time']; + } + return false; + } + + /** + * @param package|api version category to return + */ + function getVersion($key = 'release') + { + if (isset($this->_packageInfo['version'][$key])) { + return $this->_packageInfo['version'][$key]; + } + return false; + } + + function getStability() + { + if (isset($this->_packageInfo['stability'])) { + return $this->_packageInfo['stability']; + } + return false; + } + + function getState($key = 'release') + { + if (isset($this->_packageInfo['stability'][$key])) { + return $this->_packageInfo['stability'][$key]; + } + return false; + } + + function getLicense($raw = false) + { + if (isset($this->_packageInfo['license'])) { + if ($raw) { + return $this->_packageInfo['license']; + } + if (is_array($this->_packageInfo['license'])) { + return $this->_packageInfo['license']['_content']; + } else { + return $this->_packageInfo['license']; + } + } + return false; + } + + function getLicenseLocation() + { + if (!isset($this->_packageInfo['license']) || !is_array($this->_packageInfo['license'])) { + return false; + } + return $this->_packageInfo['license']['attribs']; + } + + function getNotes() + { + if (isset($this->_packageInfo['notes'])) { + return $this->_packageInfo['notes']; + } + return false; + } + + /** + * Return the tag contents, if any + * @return array|false + */ + function getUsesrole() + { + if (isset($this->_packageInfo['usesrole'])) { + return $this->_packageInfo['usesrole']; + } + return false; + } + + /** + * Return the tag contents, if any + * @return array|false + */ + function getUsestask() + { + if (isset($this->_packageInfo['usestask'])) { + return $this->_packageInfo['usestask']; + } + return false; + } + + /** + * This should only be used to retrieve filenames and install attributes + */ + function getFilelist($preserve = false) + { + if (isset($this->_packageInfo['filelist']) && !$preserve) { + return $this->_packageInfo['filelist']; + } + $this->flattenFilelist(); + if ($contents = $this->getContents()) { + $ret = array(); + if (!isset($contents['dir'])) { + return false; + } + if (!isset($contents['dir']['file'][0])) { + $contents['dir']['file'] = array($contents['dir']['file']); + } + foreach ($contents['dir']['file'] as $file) { + $name = $file['attribs']['name']; + if (!$preserve) { + $file = $file['attribs']; + } + $ret[$name] = $file; + } + if (!$preserve) { + $this->_packageInfo['filelist'] = $ret; + } + return $ret; + } + return false; + } + + /** + * Return configure options array, if any + * + * @return array|false + */ + function getConfigureOptions() + { + if ($this->getPackageType() != 'extsrc' && $this->getPackageType() != 'zendextsrc') { + return false; + } + $releases = $this->getReleases(); + if (isset($releases[0])) { + $releases = $releases[0]; + } + if (isset($releases['configureoption'])) { + if (!isset($releases['configureoption'][0])) { + $releases['configureoption'] = array($releases['configureoption']); + } + for ($i = 0; $i < count($releases['configureoption']); $i++) { + $releases['configureoption'][$i] = $releases['configureoption'][$i]['attribs']; + } + return $releases['configureoption']; + } + return false; + } + + /** + * This is only used at install-time, after all serialization + * is over. + */ + function resetFilelist() + { + $this->_packageInfo['filelist'] = array(); + } + + /** + * Retrieve a list of files that should be installed on this computer + * @return array + */ + function getInstallationFilelist($forfilecheck = false) + { + $contents = $this->getFilelist(true); + if (isset($contents['dir']['attribs']['baseinstalldir'])) { + $base = $contents['dir']['attribs']['baseinstalldir']; + } + if (isset($this->_packageInfo['bundle'])) { + return PEAR::raiseError( + 'Exception: bundles should be handled in download code only'); + } + $release = $this->getReleases(); + if ($release) { + if (!isset($release[0])) { + if (!isset($release['installconditions']) && !isset($release['filelist'])) { + if ($forfilecheck) { + return $this->getFilelist(); + } + return $contents; + } + $release = array($release); + } + $depchecker = &$this->getPEARDependency2($this->_config, array(), + array('channel' => $this->getChannel(), 'package' => $this->getPackage()), + PEAR_VALIDATE_INSTALLING); + foreach ($release as $instance) { + if (isset($instance['installconditions'])) { + $installconditions = $instance['installconditions']; + if (is_array($installconditions)) { + PEAR::pushErrorHandling(PEAR_ERROR_RETURN); + foreach ($installconditions as $type => $conditions) { + if (!isset($conditions[0])) { + $conditions = array($conditions); + } + foreach ($conditions as $condition) { + $ret = $depchecker->{"validate{$type}Dependency"}($condition); + if (PEAR::isError($ret)) { + PEAR::popErrorHandling(); + continue 3; // skip this release + } + } + } + PEAR::popErrorHandling(); + } + } + // this is the release to use + if (isset($instance['filelist'])) { + // ignore files + if (isset($instance['filelist']['ignore'])) { + $ignore = isset($instance['filelist']['ignore'][0]) ? + $instance['filelist']['ignore'] : + array($instance['filelist']['ignore']); + foreach ($ignore as $ig) { + unset ($contents[$ig['attribs']['name']]); + } + } + // install files as this name + if (isset($instance['filelist']['install'])) { + $installas = isset($instance['filelist']['install'][0]) ? + $instance['filelist']['install'] : + array($instance['filelist']['install']); + foreach ($installas as $as) { + $contents[$as['attribs']['name']]['attribs']['install-as'] = + $as['attribs']['as']; + } + } + } + if ($forfilecheck) { + foreach ($contents as $file => $attrs) { + $contents[$file] = $attrs['attribs']; + } + } + return $contents; + } + } else { // simple release - no installconditions or install-as + if ($forfilecheck) { + return $this->getFilelist(); + } + return $contents; + } + // no releases matched + return PEAR::raiseError('No releases in package.xml matched the existing operating ' . + 'system, extensions installed, or architecture, cannot install'); + } + + /** + * This is only used at install-time, after all serialization + * is over. + * @param string file name + * @param string installed path + */ + function setInstalledAs($file, $path) + { + if ($path) { + return $this->_packageInfo['filelist'][$file]['installed_as'] = $path; + } + unset($this->_packageInfo['filelist'][$file]['installed_as']); + } + + function getInstalledLocation($file) + { + if (isset($this->_packageInfo['filelist'][$file]['installed_as'])) { + return $this->_packageInfo['filelist'][$file]['installed_as']; + } + return false; + } + + /** + * This is only used at install-time, after all serialization + * is over. + */ + function installedFile($file, $atts) + { + if (isset($this->_packageInfo['filelist'][$file])) { + $this->_packageInfo['filelist'][$file] = + array_merge($this->_packageInfo['filelist'][$file], $atts['attribs']); + } else { + $this->_packageInfo['filelist'][$file] = $atts['attribs']; + } + } + + /** + * Retrieve the contents tag + */ + function getContents() + { + if (isset($this->_packageInfo['contents'])) { + return $this->_packageInfo['contents']; + } + return false; + } + + /** + * @param string full path to file + * @param string attribute name + * @param string attribute value + * @param int risky but fast - use this to choose a file based on its position in the list + * of files. Index is zero-based like PHP arrays. + * @return bool success of operation + */ + function setFileAttribute($filename, $attr, $value, $index = false) + { + $this->_isValid = 0; + if (in_array($attr, array('role', 'name', 'baseinstalldir'))) { + $this->_filesValid = false; + } + if ($index !== false && + isset($this->_packageInfo['contents']['dir']['file'][$index]['attribs'])) { + $this->_packageInfo['contents']['dir']['file'][$index]['attribs'][$attr] = $value; + return true; + } + if (!isset($this->_packageInfo['contents']['dir']['file'])) { + return false; + } + $files = $this->_packageInfo['contents']['dir']['file']; + if (!isset($files[0])) { + $files = array($files); + $ind = false; + } else { + $ind = true; + } + foreach ($files as $i => $file) { + if (isset($file['attribs'])) { + if ($file['attribs']['name'] == $filename) { + if ($ind) { + $this->_packageInfo['contents']['dir']['file'][$i]['attribs'][$attr] = $value; + } else { + $this->_packageInfo['contents']['dir']['file']['attribs'][$attr] = $value; + } + return true; + } + } + } + return false; + } + + function setDirtree($path) + { + if (!isset($this->_packageInfo['dirtree'])) { + $this->_packageInfo['dirtree'] = array(); + } + $this->_packageInfo['dirtree'][$path] = true; + } + + function getDirtree() + { + if (isset($this->_packageInfo['dirtree']) && count($this->_packageInfo['dirtree'])) { + return $this->_packageInfo['dirtree']; + } + return false; + } + + function resetDirtree() + { + unset($this->_packageInfo['dirtree']); + } + + /** + * Determines whether this package claims it is compatible with the version of + * the package that has a recommended version dependency + * @param PEAR_PackageFile_v2|PEAR_PackageFile_v1|PEAR_Downloader_Package + * @return boolean + */ + function isCompatible($pf) + { + if (!isset($this->_packageInfo['compatible'])) { + return false; + } + if (!isset($this->_packageInfo['channel'])) { + return false; + } + $me = $pf->getVersion(); + $compatible = $this->_packageInfo['compatible']; + if (!isset($compatible[0])) { + $compatible = array($compatible); + } + $found = false; + foreach ($compatible as $info) { + if (strtolower($info['name']) == strtolower($pf->getPackage())) { + if (strtolower($info['channel']) == strtolower($pf->getChannel())) { + $found = true; + break; + } + } + } + if (!$found) { + return false; + } + if (isset($info['exclude'])) { + if (!isset($info['exclude'][0])) { + $info['exclude'] = array($info['exclude']); + } + foreach ($info['exclude'] as $exclude) { + if (version_compare($me, $exclude, '==')) { + return false; + } + } + } + if (version_compare($me, $info['min'], '>=') && version_compare($me, $info['max'], '<=')) { + return true; + } + return false; + } + + /** + * @return array|false + */ + function getCompatible() + { + if (isset($this->_packageInfo['compatible'])) { + return $this->_packageInfo['compatible']; + } + return false; + } + + function getDependencies() + { + if (isset($this->_packageInfo['dependencies'])) { + return $this->_packageInfo['dependencies']; + } + return false; + } + + function isSubpackageOf($p) + { + return $p->isSubpackage($this); + } + + /** + * Determines whether the passed in package is a subpackage of this package. + * + * No version checking is done, only name verification. + * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2 + * @return bool + */ + function isSubpackage($p) + { + $sub = array(); + if (isset($this->_packageInfo['dependencies']['required']['subpackage'])) { + $sub = $this->_packageInfo['dependencies']['required']['subpackage']; + if (!isset($sub[0])) { + $sub = array($sub); + } + } + if (isset($this->_packageInfo['dependencies']['optional']['subpackage'])) { + $sub1 = $this->_packageInfo['dependencies']['optional']['subpackage']; + if (!isset($sub1[0])) { + $sub1 = array($sub1); + } + $sub = array_merge($sub, $sub1); + } + if (isset($this->_packageInfo['dependencies']['group'])) { + $group = $this->_packageInfo['dependencies']['group']; + if (!isset($group[0])) { + $group = array($group); + } + foreach ($group as $deps) { + if (isset($deps['subpackage'])) { + $sub2 = $deps['subpackage']; + if (!isset($sub2[0])) { + $sub2 = array($sub2); + } + $sub = array_merge($sub, $sub2); + } + } + } + foreach ($sub as $dep) { + if (strtolower($dep['name']) == strtolower($p->getPackage())) { + if (isset($dep['channel'])) { + if (strtolower($dep['channel']) == strtolower($p->getChannel())) { + return true; + } + } else { + if ($dep['uri'] == $p->getURI()) { + return true; + } + } + } + } + return false; + } + + function dependsOn($package, $channel) + { + if (!($deps = $this->getDependencies())) { + return false; + } + foreach (array('package', 'subpackage') as $type) { + foreach (array('required', 'optional') as $needed) { + if (isset($deps[$needed][$type])) { + if (!isset($deps[$needed][$type][0])) { + $deps[$needed][$type] = array($deps[$needed][$type]); + } + foreach ($deps[$needed][$type] as $dep) { + $depchannel = isset($dep['channel']) ? $dep['channel'] : '__uri'; + if (strtolower($dep['name']) == strtolower($package) && + $depchannel == $channel) { + return true; + } + } + } + } + if (isset($deps['group'])) { + if (!isset($deps['group'][0])) { + $dep['group'] = array($deps['group']); + } + foreach ($deps['group'] as $group) { + if (isset($group[$type])) { + if (!is_array($group[$type])) { + $group[$type] = array($group[$type]); + } + foreach ($group[$type] as $dep) { + $depchannel = isset($dep['channel']) ? $dep['channel'] : '__uri'; + if (strtolower($dep['name']) == strtolower($package) && + $depchannel == $channel) { + return true; + } + } + } + } + } + } + return false; + } + + /** + * Get the contents of a dependency group + * @param string + * @return array|false + */ + function getDependencyGroup($name) + { + $name = strtolower($name); + if (!isset($this->_packageInfo['dependencies']['group'])) { + return false; + } + $groups = $this->_packageInfo['dependencies']['group']; + if (!isset($groups[0])) { + $groups = array($groups); + } + foreach ($groups as $group) { + if (strtolower($group['attribs']['name']) == $name) { + return $group; + } + } + return false; + } + + /** + * Retrieve a partial package.xml 1.0 representation of dependencies + * + * a very limited representation of dependencies is returned by this method. + * The tag for excluding certain versions of a dependency is + * completely ignored. In addition, dependency groups are ignored, with the + * assumption that all dependencies in dependency groups are also listed in + * the optional group that work with all dependency groups + * @param boolean return package.xml 2.0 tag + * @return array|false + */ + function getDeps($raw = false, $nopearinstaller = false) + { + if (isset($this->_packageInfo['dependencies'])) { + if ($raw) { + return $this->_packageInfo['dependencies']; + } + $ret = array(); + $map = array( + 'php' => 'php', + 'package' => 'pkg', + 'subpackage' => 'pkg', + 'extension' => 'ext', + 'os' => 'os', + 'pearinstaller' => 'pkg', + ); + foreach (array('required', 'optional') as $type) { + $optional = ($type == 'optional') ? 'yes' : 'no'; + if (!isset($this->_packageInfo['dependencies'][$type]) + || empty($this->_packageInfo['dependencies'][$type])) { + continue; + } + foreach ($this->_packageInfo['dependencies'][$type] as $dtype => $deps) { + if ($dtype == 'pearinstaller' && $nopearinstaller) { + continue; + } + if (!isset($deps[0])) { + $deps = array($deps); + } + foreach ($deps as $dep) { + if (!isset($map[$dtype])) { + // no support for arch type + continue; + } + if ($dtype == 'pearinstaller') { + $dep['name'] = 'PEAR'; + $dep['channel'] = 'pear.php.net'; + } + $s = array('type' => $map[$dtype]); + if (isset($dep['channel'])) { + $s['channel'] = $dep['channel']; + } + if (isset($dep['uri'])) { + $s['uri'] = $dep['uri']; + } + if (isset($dep['name'])) { + $s['name'] = $dep['name']; + } + if (isset($dep['conflicts'])) { + $s['rel'] = 'not'; + } else { + if (!isset($dep['min']) && + !isset($dep['max'])) { + $s['rel'] = 'has'; + $s['optional'] = $optional; + } elseif (isset($dep['min']) && + isset($dep['max'])) { + $s['rel'] = 'ge'; + $s1 = $s; + $s1['rel'] = 'le'; + $s['version'] = $dep['min']; + $s1['version'] = $dep['max']; + if (isset($dep['channel'])) { + $s1['channel'] = $dep['channel']; + } + if ($dtype != 'php') { + $s['name'] = $dep['name']; + $s1['name'] = $dep['name']; + } + $s['optional'] = $optional; + $s1['optional'] = $optional; + $ret[] = $s1; + } elseif (isset($dep['min'])) { + if (isset($dep['exclude']) && + $dep['exclude'] == $dep['min']) { + $s['rel'] = 'gt'; + } else { + $s['rel'] = 'ge'; + } + $s['version'] = $dep['min']; + $s['optional'] = $optional; + if ($dtype != 'php') { + $s['name'] = $dep['name']; + } + } elseif (isset($dep['max'])) { + if (isset($dep['exclude']) && + $dep['exclude'] == $dep['max']) { + $s['rel'] = 'lt'; + } else { + $s['rel'] = 'le'; + } + $s['version'] = $dep['max']; + $s['optional'] = $optional; + if ($dtype != 'php') { + $s['name'] = $dep['name']; + } + } + } + $ret[] = $s; + } + } + } + if (count($ret)) { + return $ret; + } + } + return false; + } + + /** + * @return php|extsrc|extbin|zendextsrc|zendextbin|bundle|false + */ + function getPackageType() + { + if (isset($this->_packageInfo['phprelease'])) { + return 'php'; + } + if (isset($this->_packageInfo['extsrcrelease'])) { + return 'extsrc'; + } + if (isset($this->_packageInfo['extbinrelease'])) { + return 'extbin'; + } + if (isset($this->_packageInfo['zendextsrcrelease'])) { + return 'zendextsrc'; + } + if (isset($this->_packageInfo['zendextbinrelease'])) { + return 'zendextbin'; + } + if (isset($this->_packageInfo['bundle'])) { + return 'bundle'; + } + return false; + } + + /** + * @return array|false + */ + function getReleases() + { + $type = $this->getPackageType(); + if ($type != 'bundle') { + $type .= 'release'; + } + if ($this->getPackageType() && isset($this->_packageInfo[$type])) { + return $this->_packageInfo[$type]; + } + return false; + } + + /** + * @return array + */ + function getChangelog() + { + if (isset($this->_packageInfo['changelog'])) { + return $this->_packageInfo['changelog']; + } + return false; + } + + function hasDeps() + { + return isset($this->_packageInfo['dependencies']); + } + + function getPackagexmlVersion() + { + if (isset($this->_packageInfo['zendextsrcrelease'])) { + return '2.1'; + } + if (isset($this->_packageInfo['zendextbinrelease'])) { + return '2.1'; + } + return '2.0'; + } + + /** + * @return array|false + */ + function getSourcePackage() + { + if (isset($this->_packageInfo['extbinrelease']) || + isset($this->_packageInfo['zendextbinrelease'])) { + return array('channel' => $this->_packageInfo['srcchannel'], + 'package' => $this->_packageInfo['srcpackage']); + } + return false; + } + + function getBundledPackages() + { + if (isset($this->_packageInfo['bundle'])) { + return $this->_packageInfo['contents']['bundledpackage']; + } + return false; + } + + function getLastModified() + { + if (isset($this->_packageInfo['_lastmodified'])) { + return $this->_packageInfo['_lastmodified']; + } + return false; + } + + /** + * Get the contents of a file listed within the package.xml + * @param string + * @return string + */ + function getFileContents($file) + { + if ($this->_archiveFile == $this->_packageFile) { // unpacked + $dir = dirname($this->_packageFile); + $file = $dir . DIRECTORY_SEPARATOR . $file; + $file = str_replace(array('/', '\\'), + array(DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR), $file); + if (file_exists($file) && is_readable($file)) { + return implode('', file($file)); + } + } else { // tgz + $tar = &new Archive_Tar($this->_archiveFile); + $tar->pushErrorHandling(PEAR_ERROR_RETURN); + if ($file != 'package.xml' && $file != 'package2.xml') { + $file = $this->getPackage() . '-' . $this->getVersion() . '/' . $file; + } + $file = $tar->extractInString($file); + $tar->popErrorHandling(); + if (PEAR::isError($file)) { + return PEAR::raiseError("Cannot locate file '$file' in archive"); + } + return $file; + } + } + + function &getRW() + { + if (!class_exists('PEAR_PackageFile_v2_rw')) { + require_once 'PEAR/PackageFile/v2/rw.php'; + } + $a = new PEAR_PackageFile_v2_rw; + foreach (get_object_vars($this) as $name => $unused) { + if (!isset($this->$name)) { + continue; + } + if ($name == '_config' || $name == '_logger'|| $name == '_registry' || + $name == '_stack') { + $a->$name = &$this->$name; + } else { + $a->$name = $this->$name; + } + } + return $a; + } + + function &getDefaultGenerator() + { + if (!class_exists('PEAR_PackageFile_Generator_v2')) { + require_once 'PEAR/PackageFile/Generator/v2.php'; + } + $a = &new PEAR_PackageFile_Generator_v2($this); + return $a; + } + + function analyzeSourceCode($file, $string = false) + { + if (!isset($this->_v2Validator) || + !is_a($this->_v2Validator, 'PEAR_PackageFile_v2_Validator')) { + if (!class_exists('PEAR_PackageFile_v2_Validator')) { + require_once 'PEAR/PackageFile/v2/Validator.php'; + } + $this->_v2Validator = new PEAR_PackageFile_v2_Validator; + } + return $this->_v2Validator->analyzeSourceCode($file, $string); + } + + function validate($state = PEAR_VALIDATE_NORMAL) + { + if (!isset($this->_packageInfo) || !is_array($this->_packageInfo)) { + return false; + } + if (!isset($this->_v2Validator) || + !is_a($this->_v2Validator, 'PEAR_PackageFile_v2_Validator')) { + if (!class_exists('PEAR_PackageFile_v2_Validator')) { + require_once 'PEAR/PackageFile/v2/Validator.php'; + } + $this->_v2Validator = new PEAR_PackageFile_v2_Validator; + } + if (isset($this->_packageInfo['xsdversion'])) { + unset($this->_packageInfo['xsdversion']); + } + return $this->_v2Validator->validate($this, $state); + } + + function getTasksNs() + { + if (!isset($this->_tasksNs)) { + if (isset($this->_packageInfo['attribs'])) { + foreach ($this->_packageInfo['attribs'] as $name => $value) { + if ($value == 'http://pear.php.net/dtd/tasks-1.0') { + $this->_tasksNs = str_replace('xmlns:', '', $name); + break; + } + } + } + } + return $this->_tasksNs; + } + + /** + * Determine whether a task name is a valid task. Custom tasks may be defined + * using subdirectories by putting a "-" in the name, as in + * + * Note that this method will auto-load the task class file and test for the existence + * of the name with "-" replaced by "_" as in PEAR/Task/mycustom/task.php makes class + * PEAR_Task_mycustom_task + * @param string + * @return boolean + */ + function getTask($task) + { + $this->getTasksNs(); + // transform all '-' to '/' and 'tasks:' to '' so tasks:replace becomes replace + $task = str_replace(array($this->_tasksNs . ':', '-'), array('', ' '), $task); + $taskfile = str_replace(' ', '/', ucwords($task)); + $task = str_replace(array(' ', '/'), '_', ucwords($task)); + if (class_exists("PEAR_Task_$task")) { + return "PEAR_Task_$task"; + } + $fp = @fopen("PEAR/Task/$taskfile.php", 'r', true); + if ($fp) { + fclose($fp); + require_once "PEAR/Task/$taskfile.php"; + return "PEAR_Task_$task"; + } + return false; + } + + /** + * Key-friendly array_splice + * @param tagname to splice a value in before + * @param mixed the value to splice in + * @param string the new tag name + */ + function _ksplice($array, $key, $value, $newkey) + { + $offset = array_search($key, array_keys($array)); + $after = array_slice($array, $offset); + $before = array_slice($array, 0, $offset); + $before[$newkey] = $value; + return array_merge($before, $after); + } + + /** + * @param array a list of possible keys, in the order they may occur + * @param mixed contents of the new package.xml tag + * @param string tag name + * @access private + */ + function _insertBefore($array, $keys, $contents, $newkey) + { + foreach ($keys as $key) { + if (isset($array[$key])) { + return $array = $this->_ksplice($array, $key, $contents, $newkey); + } + } + $array[$newkey] = $contents; + return $array; + } + + /** + * @param subsection of {@link $_packageInfo} + * @param array|string tag contents + * @param array format: + *
    +     * array(
    +     *   tagname => array(list of tag names that follow this one),
    +     *   childtagname => array(list of child tag names that follow this one),
    +     * )
    +     * 
    + * + * This allows construction of nested tags + * @access private + */ + function _mergeTag($manip, $contents, $order) + { + if (count($order)) { + foreach ($order as $tag => $curorder) { + if (!isset($manip[$tag])) { + // ensure that the tag is set up + $manip = $this->_insertBefore($manip, $curorder, array(), $tag); + } + if (count($order) > 1) { + $manip[$tag] = $this->_mergeTag($manip[$tag], $contents, array_slice($order, 1)); + return $manip; + } + } + } else { + return $manip; + } + if (is_array($manip[$tag]) && !empty($manip[$tag]) && isset($manip[$tag][0])) { + $manip[$tag][] = $contents; + } else { + if (!count($manip[$tag])) { + $manip[$tag] = $contents; + } else { + $manip[$tag] = array($manip[$tag]); + $manip[$tag][] = $contents; + } + } + return $manip; + } +} +?> diff --git a/src/lib/pear/PEAR/PEAR/PackageFile/v2/Validator.php b/src/lib/pear/PEAR/PEAR/PackageFile/v2/Validator.php new file mode 100644 index 0000000..10efbbb --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/PackageFile/v2/Validator.php @@ -0,0 +1,2116 @@ + + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: Validator.php,v 1.106 2008/03/28 22:23:41 dufuz Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 1.4.0a8 + */ +/** + * Private validation class used by PEAR_PackageFile_v2 - do not use directly, its + * sole purpose is to split up the PEAR/PackageFile/v2.php file to make it smaller + * @category pear + * @package PEAR + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 1.4.0a8 + * @access private + */ +class PEAR_PackageFile_v2_Validator +{ + /** + * @var array + */ + var $_packageInfo; + /** + * @var PEAR_PackageFile_v2 + */ + var $_pf; + /** + * @var PEAR_ErrorStack + */ + var $_stack; + /** + * @var int + */ + var $_isValid = 0; + /** + * @var int + */ + var $_filesValid = 0; + /** + * @var int + */ + var $_curState = 0; + /** + * @param PEAR_PackageFile_v2 + * @param int + */ + function validate(&$pf, $state = PEAR_VALIDATE_NORMAL) + { + $this->_pf = &$pf; + $this->_curState = $state; + $this->_packageInfo = $this->_pf->getArray(); + $this->_isValid = $this->_pf->_isValid; + $this->_filesValid = $this->_pf->_filesValid; + $this->_stack = &$pf->_stack; + $this->_stack->getErrors(true); + if (($this->_isValid & $state) == $state) { + return true; + } + if (!isset($this->_packageInfo) || !is_array($this->_packageInfo)) { + return false; + } + if (!isset($this->_packageInfo['attribs']['version']) || + ($this->_packageInfo['attribs']['version'] != '2.0' && + $this->_packageInfo['attribs']['version'] != '2.1') + ) { + $this->_noPackageVersion(); + } + $structure = + array( + 'name', + 'channel|uri', + '*extends', // can't be multiple, but this works fine + 'summary', + 'description', + '+lead', // these all need content checks + '*developer', + '*contributor', + '*helper', + 'date', + '*time', + 'version', + 'stability', + 'license->?uri->?filesource', + 'notes', + 'contents', //special validation needed + '*compatible', + 'dependencies', //special validation needed + '*usesrole', + '*usestask', // reserve these for 1.4.0a1 to implement + // this will allow a package.xml to gracefully say it + // needs a certain package installed in order to implement a role or task + '*providesextension', + '*srcpackage|*srcuri', + '+phprelease|+extsrcrelease|+extbinrelease|' . + '+zendextsrcrelease|+zendextbinrelease|bundle', //special validation needed + '*changelog', + ); + $test = $this->_packageInfo; + if (isset($test['dependencies']) && + isset($test['dependencies']['required']) && + isset($test['dependencies']['required']['pearinstaller']) && + isset($test['dependencies']['required']['pearinstaller']['min']) && + version_compare('1.7.2', + $test['dependencies']['required']['pearinstaller']['min'], '<') + ) { + $this->_pearVersionTooLow($test['dependencies']['required']['pearinstaller']['min']); + return false; + } + // ignore post-installation array fields + if (array_key_exists('filelist', $test)) { + unset($test['filelist']); + } + if (array_key_exists('_lastmodified', $test)) { + unset($test['_lastmodified']); + } + if (array_key_exists('#binarypackage', $test)) { + unset($test['#binarypackage']); + } + if (array_key_exists('old', $test)) { + unset($test['old']); + } + if (array_key_exists('_lastversion', $test)) { + unset($test['_lastversion']); + } + if (!$this->_stupidSchemaValidate($structure, $test, '')) { + return false; + } + if (empty($this->_packageInfo['name'])) { + $this->_tagCannotBeEmpty('name'); + } + $test = isset($this->_packageInfo['uri']) ? 'uri' :'channel'; + if (empty($this->_packageInfo[$test])) { + $this->_tagCannotBeEmpty($test); + } + if (is_array($this->_packageInfo['license']) && + (!isset($this->_packageInfo['license']['_content']) || + empty($this->_packageInfo['license']['_content']))) { + $this->_tagCannotBeEmpty('license'); + } elseif (empty($this->_packageInfo['license'])) { + $this->_tagCannotBeEmpty('license'); + } + if (empty($this->_packageInfo['summary'])) { + $this->_tagCannotBeEmpty('summary'); + } + if (empty($this->_packageInfo['description'])) { + $this->_tagCannotBeEmpty('description'); + } + if (empty($this->_packageInfo['date'])) { + $this->_tagCannotBeEmpty('date'); + } + if (empty($this->_packageInfo['notes'])) { + $this->_tagCannotBeEmpty('notes'); + } + if (isset($this->_packageInfo['time']) && empty($this->_packageInfo['time'])) { + $this->_tagCannotBeEmpty('time'); + } + if (isset($this->_packageInfo['dependencies'])) { + $this->_validateDependencies(); + } + if (isset($this->_packageInfo['compatible'])) { + $this->_validateCompatible(); + } + if (!isset($this->_packageInfo['bundle'])) { + if (empty($this->_packageInfo['contents'])) { + $this->_tagCannotBeEmpty('contents'); + } + if (!isset($this->_packageInfo['contents']['dir'])) { + $this->_filelistMustContainDir('contents'); + return false; + } + if (isset($this->_packageInfo['contents']['file'])) { + $this->_filelistCannotContainFile('contents'); + return false; + } + } + $this->_validateMaintainers(); + $this->_validateStabilityVersion(); + $fail = false; + if (array_key_exists('usesrole', $this->_packageInfo)) { + $roles = $this->_packageInfo['usesrole']; + if (!is_array($roles) || !isset($roles[0])) { + $roles = array($roles); + } + foreach ($roles as $role) { + if (!isset($role['role'])) { + $this->_usesroletaskMustHaveRoleTask('usesrole', 'role'); + $fail = true; + } else { + if (!isset($role['channel'])) { + if (!isset($role['uri'])) { + $this->_usesroletaskMustHaveChannelOrUri($role['role'], 'usesrole'); + $fail = true; + } + } elseif (!isset($role['package'])) { + $this->_usesroletaskMustHavePackage($role['role'], 'usesrole'); + $fail = true; + } + } + } + } + if (array_key_exists('usestask', $this->_packageInfo)) { + $roles = $this->_packageInfo['usestask']; + if (!is_array($roles) || !isset($roles[0])) { + $roles = array($roles); + } + foreach ($roles as $role) { + if (!isset($role['task'])) { + $this->_usesroletaskMustHaveRoleTask('usestask', 'task'); + $fail = true; + } else { + if (!isset($role['channel'])) { + if (!isset($role['uri'])) { + $this->_usesroletaskMustHaveChannelOrUri($role['task'], 'usestask'); + $fail = true; + } + } elseif (!isset($role['package'])) { + $this->_usesroletaskMustHavePackage($role['task'], 'usestask'); + $fail = true; + } + } + } + } + if ($fail) { + return false; + } + $list = $this->_packageInfo['contents']; + if (isset($list['dir']) && is_array($list['dir']) && isset($list['dir'][0])) { + $this->_multipleToplevelDirNotAllowed(); + return $this->_isValid = 0; + } + $this->_validateFilelist(); + $this->_validateRelease(); + if (!$this->_stack->hasErrors()) { + $chan = $this->_pf->_registry->getChannel($this->_pf->getChannel(), true); + if (PEAR::isError($chan)) { + $this->_unknownChannel($this->_pf->getChannel()); + } else { + $valpack = $chan->getValidationPackage(); + // for channel validator packages, always use the default PEAR validator. + // otherwise, they can't be installed or packaged + $validator = $chan->getValidationObject($this->_pf->getPackage()); + if (!$validator) { + $this->_stack->push(__FUNCTION__, 'error', + array_merge( + array('channel' => $chan->getName(), + 'package' => $this->_pf->getPackage()), + $valpack + ), + 'package "%channel%/%package%" cannot be properly validated without ' . + 'validation package "%channel%/%name%-%version%"'); + return $this->_isValid = 0; + } + $validator->setPackageFile($this->_pf); + $validator->validate($state); + $failures = $validator->getFailures(); + foreach ($failures['errors'] as $error) { + $this->_stack->push(__FUNCTION__, 'error', $error, + 'Channel validator error: field "%field%" - %reason%'); + } + foreach ($failures['warnings'] as $warning) { + $this->_stack->push(__FUNCTION__, 'warning', $warning, + 'Channel validator warning: field "%field%" - %reason%'); + } + } + } + $this->_pf->_isValid = $this->_isValid = !$this->_stack->hasErrors('error'); + if ($this->_isValid && $state == PEAR_VALIDATE_PACKAGING && !$this->_filesValid) { + if ($this->_pf->getPackageType() == 'bundle') { + if ($this->_analyzeBundledPackages()) { + $this->_filesValid = $this->_pf->_filesValid = true; + } else { + $this->_pf->_isValid = $this->_isValid = 0; + } + } else { + if (!$this->_analyzePhpFiles()) { + $this->_pf->_isValid = $this->_isValid = 0; + } else { + $this->_filesValid = $this->_pf->_filesValid = true; + } + } + } + if ($this->_isValid) { + return $this->_pf->_isValid = $this->_isValid = $state; + } + return $this->_pf->_isValid = $this->_isValid = 0; + } + + function _stupidSchemaValidate($structure, $xml, $root) + { + if (!is_array($xml)) { + $xml = array(); + } + $keys = array_keys($xml); + reset($keys); + $key = current($keys); + while ($key == 'attribs' || $key == '_contents') { + $key = next($keys); + } + $unfoundtags = $optionaltags = array(); + $ret = true; + $mismatch = false; + foreach ($structure as $struc) { + if ($key) { + $tag = $xml[$key]; + } + $test = $this->_processStructure($struc); + if (isset($test['choices'])) { + $loose = true; + foreach ($test['choices'] as $choice) { + if ($key == $choice['tag']) { + $key = next($keys); + while ($key == 'attribs' || $key == '_contents') { + $key = next($keys); + } + $unfoundtags = $optionaltags = array(); + $mismatch = false; + if ($key && $key != $choice['tag'] && isset($choice['multiple'])) { + $unfoundtags[] = $choice['tag']; + $optionaltags[] = $choice['tag']; + if ($key) { + $mismatch = true; + } + } + $ret &= $this->_processAttribs($choice, $tag, $root); + continue 2; + } else { + $unfoundtags[] = $choice['tag']; + $mismatch = true; + } + if (!isset($choice['multiple']) || $choice['multiple'] != '*') { + $loose = false; + } else { + $optionaltags[] = $choice['tag']; + } + } + if (!$loose) { + $this->_invalidTagOrder($unfoundtags, $key, $root); + return false; + } + } else { + if ($key != $test['tag']) { + if (isset($test['multiple']) && $test['multiple'] != '*') { + $unfoundtags[] = $test['tag']; + $this->_invalidTagOrder($unfoundtags, $key, $root); + return false; + } else { + if ($key) { + $mismatch = true; + } + $unfoundtags[] = $test['tag']; + $optionaltags[] = $test['tag']; + } + if (!isset($test['multiple'])) { + $this->_invalidTagOrder($unfoundtags, $key, $root); + return false; + } + continue; + } else { + $unfoundtags = $optionaltags = array(); + $mismatch = false; + } + $key = next($keys); + while ($key == 'attribs' || $key == '_contents') { + $key = next($keys); + } + if ($key && $key != $test['tag'] && isset($test['multiple'])) { + $unfoundtags[] = $test['tag']; + $optionaltags[] = $test['tag']; + $mismatch = true; + } + $ret &= $this->_processAttribs($test, $tag, $root); + continue; + } + } + if (!$mismatch && count($optionaltags)) { + // don't error out on any optional tags + $unfoundtags = array_diff($unfoundtags, $optionaltags); + } + if (count($unfoundtags)) { + $this->_invalidTagOrder($unfoundtags, $key, $root); + } elseif ($key) { + // unknown tags + $this->_invalidTagOrder('*no tags allowed here*', $key, $root); + while ($key = next($keys)) { + $this->_invalidTagOrder('*no tags allowed here*', $key, $root); + } + } + return $ret; + } + + function _processAttribs($choice, $tag, $context) + { + if (isset($choice['attribs'])) { + if (!is_array($tag)) { + $tag = array($tag); + } + $tags = $tag; + if (!isset($tags[0])) { + $tags = array($tags); + } + $ret = true; + foreach ($tags as $i => $tag) { + if (!is_array($tag) || !isset($tag['attribs'])) { + foreach ($choice['attribs'] as $attrib) { + if ($attrib{0} != '?') { + $ret &= $this->_tagHasNoAttribs($choice['tag'], + $context); + continue 2; + } + } + } + foreach ($choice['attribs'] as $attrib) { + if ($attrib{0} != '?') { + if (!isset($tag['attribs'][$attrib])) { + $ret &= $this->_tagMissingAttribute($choice['tag'], + $attrib, $context); + } + } + } + } + return $ret; + } + return true; + } + + function _processStructure($key) + { + $ret = array(); + if (count($pieces = explode('|', $key)) > 1) { + $ret['choices'] = array(); + foreach ($pieces as $piece) { + $ret['choices'][] = $this->_processStructure($piece); + } + return $ret; + } + $multi = $key{0}; + if ($multi == '+' || $multi == '*') { + $ret['multiple'] = $key{0}; + $key = substr($key, 1); + } + if (count($attrs = explode('->', $key)) > 1) { + $ret['tag'] = array_shift($attrs); + $ret['attribs'] = $attrs; + } else { + $ret['tag'] = $key; + } + return $ret; + } + + function _validateStabilityVersion() + { + $structure = array('release', 'api'); + $a = $this->_stupidSchemaValidate($structure, $this->_packageInfo['version'], ''); + $a &= $this->_stupidSchemaValidate($structure, $this->_packageInfo['stability'], ''); + if ($a) { + if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/', + $this->_packageInfo['version']['release'])) { + $this->_invalidVersion('release', $this->_packageInfo['version']['release']); + } + if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/', + $this->_packageInfo['version']['api'])) { + $this->_invalidVersion('api', $this->_packageInfo['version']['api']); + } + if (!in_array($this->_packageInfo['stability']['release'], + array('snapshot', 'devel', 'alpha', 'beta', 'stable'))) { + $this->_invalidState('release', $this->_packageInfo['stability']['release']); + } + if (!in_array($this->_packageInfo['stability']['api'], + array('devel', 'alpha', 'beta', 'stable'))) { + $this->_invalidState('api', $this->_packageInfo['stability']['api']); + } + } + } + + function _validateMaintainers() + { + $structure = + array( + 'name', + 'user', + 'email', + 'active', + ); + foreach (array('lead', 'developer', 'contributor', 'helper') as $type) { + if (!isset($this->_packageInfo[$type])) { + continue; + } + if (isset($this->_packageInfo[$type][0])) { + foreach ($this->_packageInfo[$type] as $lead) { + $this->_stupidSchemaValidate($structure, $lead, '<' . $type . '>'); + } + } else { + $this->_stupidSchemaValidate($structure, $this->_packageInfo[$type], + '<' . $type . '>'); + } + } + } + + function _validatePhpDep($dep, $installcondition = false) + { + $structure = array( + 'min', + '*max', + '*exclude', + ); + $type = $installcondition ? '' : ''; + $this->_stupidSchemaValidate($structure, $dep, $type); + if (isset($dep['min'])) { + if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?(?:-[a-zA-Z0-9]+)?\\z/', + $dep['min'])) { + $this->_invalidVersion($type . '', $dep['min']); + } + } + if (isset($dep['max'])) { + if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?(?:-[a-zA-Z0-9]+)?\\z/', + $dep['max'])) { + $this->_invalidVersion($type . '', $dep['max']); + } + } + if (isset($dep['exclude'])) { + if (!is_array($dep['exclude'])) { + $dep['exclude'] = array($dep['exclude']); + } + foreach ($dep['exclude'] as $exclude) { + if (!preg_match( + '/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?(?:-[a-zA-Z0-9]+)?\\z/', + $exclude)) { + $this->_invalidVersion($type . '', $exclude); + } + } + } + } + + function _validatePearinstallerDep($dep) + { + $structure = array( + 'min', + '*max', + '*recommended', + '*exclude', + ); + $this->_stupidSchemaValidate($structure, $dep, ''); + if (isset($dep['min'])) { + if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/', + $dep['min'])) { + $this->_invalidVersion('', + $dep['min']); + } + } + if (isset($dep['max'])) { + if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/', + $dep['max'])) { + $this->_invalidVersion('', + $dep['max']); + } + } + if (isset($dep['recommended'])) { + if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/', + $dep['recommended'])) { + $this->_invalidVersion('', + $dep['recommended']); + } + } + if (isset($dep['exclude'])) { + if (!is_array($dep['exclude'])) { + $dep['exclude'] = array($dep['exclude']); + } + foreach ($dep['exclude'] as $exclude) { + if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/', + $exclude)) { + $this->_invalidVersion('', + $exclude); + } + } + } + } + + function _validatePackageDep($dep, $group, $type = '') + { + if (isset($dep['uri'])) { + if (isset($dep['conflicts'])) { + $structure = array( + 'name', + 'uri', + 'conflicts', + '*providesextension', + ); + } else { + $structure = array( + 'name', + 'uri', + '*providesextension', + ); + } + } else { + if (isset($dep['conflicts'])) { + $structure = array( + 'name', + 'channel', + '*min', + '*max', + '*exclude', + 'conflicts', + '*providesextension', + ); + } else { + $structure = array( + 'name', + 'channel', + '*min', + '*max', + '*recommended', + '*exclude', + '*nodefault', + '*providesextension', + ); + } + } + if (isset($dep['name'])) { + $type .= '' . $dep['name'] . ''; + } + $this->_stupidSchemaValidate($structure, $dep, '' . $group . $type); + if (isset($dep['uri']) && (isset($dep['min']) || isset($dep['max']) || + isset($dep['recommended']) || isset($dep['exclude']))) { + $this->_uriDepsCannotHaveVersioning('' . $group . $type); + } + if (isset($dep['channel']) && strtolower($dep['channel']) == '__uri') { + $this->_DepchannelCannotBeUri('' . $group . $type); + } + if (isset($dep['min'])) { + if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/', + $dep['min'])) { + $this->_invalidVersion('' . $group . $type . '', $dep['min']); + } + } + if (isset($dep['max'])) { + if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/', + $dep['max'])) { + $this->_invalidVersion('' . $group . $type . '', $dep['max']); + } + } + if (isset($dep['recommended'])) { + if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/', + $dep['recommended'])) { + $this->_invalidVersion('' . $group . $type . '', + $dep['recommended']); + } + } + if (isset($dep['exclude'])) { + if (!is_array($dep['exclude'])) { + $dep['exclude'] = array($dep['exclude']); + } + foreach ($dep['exclude'] as $exclude) { + if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/', + $exclude)) { + $this->_invalidVersion('' . $group . $type . '', + $exclude); + } + } + } + } + + function _validateSubpackageDep($dep, $group) + { + $this->_validatePackageDep($dep, $group, ''); + if (isset($dep['providesextension'])) { + $this->_subpackageCannotProvideExtension(isset($dep['name']) ? $dep['name'] : ''); + } + if (isset($dep['conflicts'])) { + $this->_subpackagesCannotConflict(isset($dep['name']) ? $dep['name'] : ''); + } + } + + function _validateExtensionDep($dep, $group = false, $installcondition = false) + { + if (isset($dep['conflicts'])) { + $structure = array( + 'name', + '*min', + '*max', + '*exclude', + 'conflicts', + ); + } else { + $structure = array( + 'name', + '*min', + '*max', + '*recommended', + '*exclude', + ); + } + if ($installcondition) { + $type = ''; + } else { + $type = '' . $group . ''; + } + if (isset($dep['name'])) { + $type .= '' . $dep['name'] . ''; + } + $this->_stupidSchemaValidate($structure, $dep, $type); + if (isset($dep['min'])) { + if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/', + $dep['min'])) { + $this->_invalidVersion(substr($type, 1) . '_invalidVersion(substr($type, 1) . '_invalidVersion(substr($type, 1) . '_invalidVersion(substr($type, 1) . '' : ''; + if ($this->_stupidSchemaValidate($structure, $dep, $type)) { + if ($dep['name'] == '*') { + if (array_key_exists('conflicts', $dep)) { + $this->_cannotConflictWithAllOs($type); + } + } + } + } + + function _validateArchDep($dep, $installcondition = false) + { + $structure = array( + 'pattern', + '*conflicts', + ); + $type = $installcondition ? '' : ''; + $this->_stupidSchemaValidate($structure, $dep, $type); + } + + function _validateInstallConditions($cond, $release) + { + $structure = array( + '*php', + '*extension', + '*os', + '*arch', + ); + if (!$this->_stupidSchemaValidate($structure, + $cond, $release)) { + return false; + } + foreach (array('php', 'extension', 'os', 'arch') as $type) { + if (isset($cond[$type])) { + $iter = $cond[$type]; + if (!is_array($iter) || !isset($iter[0])) { + $iter = array($iter); + } + foreach ($iter as $package) { + if ($type == 'extension') { + $this->{"_validate{$type}Dep"}($package, false, true); + } else { + $this->{"_validate{$type}Dep"}($package, true); + } + } + } + } + } + + function _validateDependencies() + { + $structure = array( + 'required', + '*optional', + '*group->name->hint' + ); + if (!$this->_stupidSchemaValidate($structure, + $this->_packageInfo['dependencies'], '')) { + return false; + } + foreach (array('required', 'optional') as $simpledep) { + if (isset($this->_packageInfo['dependencies'][$simpledep])) { + if ($simpledep == 'optional') { + $structure = array( + '*package', + '*subpackage', + '*extension', + ); + } else { + $structure = array( + 'php', + 'pearinstaller', + '*package', + '*subpackage', + '*extension', + '*os', + '*arch', + ); + } + if ($this->_stupidSchemaValidate($structure, + $this->_packageInfo['dependencies'][$simpledep], + "<$simpledep>")) { + foreach (array('package', 'subpackage', 'extension') as $type) { + if (isset($this->_packageInfo['dependencies'][$simpledep][$type])) { + $iter = $this->_packageInfo['dependencies'][$simpledep][$type]; + if (!isset($iter[0])) { + $iter = array($iter); + } + foreach ($iter as $package) { + if ($type != 'extension') { + if (isset($package['uri'])) { + if (isset($package['channel'])) { + $this->_UrlOrChannel($type, + $package['name']); + } + } else { + if (!isset($package['channel'])) { + $this->_NoChannel($type, $package['name']); + } + } + } + $this->{"_validate{$type}Dep"}($package, "<$simpledep>"); + } + } + } + if ($simpledep == 'optional') { + continue; + } + foreach (array('php', 'pearinstaller', 'os', 'arch') as $type) { + if (isset($this->_packageInfo['dependencies'][$simpledep][$type])) { + $iter = $this->_packageInfo['dependencies'][$simpledep][$type]; + if (!isset($iter[0])) { + $iter = array($iter); + } + foreach ($iter as $package) { + $this->{"_validate{$type}Dep"}($package); + } + } + } + } + } + } + if (isset($this->_packageInfo['dependencies']['group'])) { + $groups = $this->_packageInfo['dependencies']['group']; + if (!isset($groups[0])) { + $groups = array($groups); + } + $structure = array( + '*package', + '*subpackage', + '*extension', + ); + foreach ($groups as $group) { + if ($this->_stupidSchemaValidate($structure, $group, '')) { + if (!PEAR_Validate::validGroupName($group['attribs']['name'])) { + $this->_invalidDepGroupName($group['attribs']['name']); + } + foreach (array('package', 'subpackage', 'extension') as $type) { + if (isset($group[$type])) { + $iter = $group[$type]; + if (!isset($iter[0])) { + $iter = array($iter); + } + foreach ($iter as $package) { + if ($type != 'extension') { + if (isset($package['uri'])) { + if (isset($package['channel'])) { + $this->_UrlOrChannelGroup($type, + $package['name'], + $group['name']); + } + } else { + if (!isset($package['channel'])) { + $this->_NoChannelGroup($type, + $package['name'], + $group['name']); + } + } + } + $this->{"_validate{$type}Dep"}($package, ''); + } + } + } + } + } + } + } + + function _validateCompatible() + { + $compat = $this->_packageInfo['compatible']; + if (!isset($compat[0])) { + $compat = array($compat); + } + $required = array('name', 'channel', 'min', 'max', '*exclude'); + foreach ($compat as $package) { + $type = ''; + if (is_array($package) && array_key_exists('name', $package)) { + $type .= '' . $package['name'] . ''; + } + $this->_stupidSchemaValidate($required, $package, $type); + if (is_array($package) && array_key_exists('min', $package)) { + if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/', + $package['min'])) { + $this->_invalidVersion(substr($type, 1) . '_invalidVersion(substr($type, 1) . '_invalidVersion(substr($type, 1) . '_NoBundledPackages(); + } + if (!is_array($list['bundledpackage']) || !isset($list['bundledpackage'][0])) { + return $this->_AtLeast2BundledPackages(); + } + foreach ($list['bundledpackage'] as $package) { + if (!is_string($package)) { + $this->_bundledPackagesMustBeFilename(); + } + } + } + + function _validateFilelist($list = false, $allowignore = false, $dirs = '') + { + $iscontents = false; + if (!$list) { + $iscontents = true; + $list = $this->_packageInfo['contents']; + if (isset($this->_packageInfo['bundle'])) { + return $this->_validateBundle($list); + } + } + if ($allowignore) { + $struc = array( + '*install->name->as', + '*ignore->name' + ); + } else { + $struc = array( + '*dir->name->?baseinstalldir', + '*file->name->role->?baseinstalldir->?md5sum' + ); + if (isset($list['dir']) && isset($list['file'])) { + // stave off validation errors without requiring a set order. + $_old = $list; + if (isset($list['attribs'])) { + $list = array('attribs' => $_old['attribs']); + } + $list['dir'] = $_old['dir']; + $list['file'] = $_old['file']; + } + } + if (!isset($list['attribs']) || !isset($list['attribs']['name'])) { + $unknown = $allowignore ? '' : ''; + $dirname = $iscontents ? '' : $unknown; + } else { + $dirname = ''; + if (preg_match('~/\.\.?(/|\\z)|^\.\.?/~', + str_replace('\\', '/', $list['attribs']['name']))) { + // file contains .. parent directory or . cur directory + $this->_invalidDirName($list['attribs']['name']); + } + } + $res = $this->_stupidSchemaValidate($struc, $list, $dirname); + if ($allowignore && $res) { + $ignored_or_installed = array(); + $this->_pf->getFilelist(); + $fcontents = $this->_pf->getContents(); + $filelist = array(); + if (!isset($fcontents['dir']['file'][0])) { + $fcontents['dir']['file'] = array($fcontents['dir']['file']); + } + foreach ($fcontents['dir']['file'] as $file) { + $filelist[$file['attribs']['name']] = true; + } + if (isset($list['install'])) { + if (!isset($list['install'][0])) { + $list['install'] = array($list['install']); + } + foreach ($list['install'] as $file) { + if (!isset($filelist[$file['attribs']['name']])) { + $this->_notInContents($file['attribs']['name'], 'install'); + continue; + } + if (array_key_exists($file['attribs']['name'], $ignored_or_installed)) { + $this->_multipleInstallAs($file['attribs']['name']); + } + if (!isset($ignored_or_installed[$file['attribs']['name']])) { + $ignored_or_installed[$file['attribs']['name']] = array(); + } + $ignored_or_installed[$file['attribs']['name']][] = 1; + if (preg_match('~/\.\.?(/|\\z)|^\.\.?/~', + str_replace('\\', '/', $file['attribs']['as']))) { + // file contains .. parent directory or . cur directory references + $this->_invalidFileInstallAs($file['attribs']['name'], + $file['attribs']['as']); + } + } + } + if (isset($list['ignore'])) { + if (!isset($list['ignore'][0])) { + $list['ignore'] = array($list['ignore']); + } + foreach ($list['ignore'] as $file) { + if (!isset($filelist[$file['attribs']['name']])) { + $this->_notInContents($file['attribs']['name'], 'ignore'); + continue; + } + if (array_key_exists($file['attribs']['name'], $ignored_or_installed)) { + $this->_ignoreAndInstallAs($file['attribs']['name']); + } + } + } + } + if (!$allowignore && isset($list['file'])) { + if (is_string($list['file'])) { + $this->_oldStyleFileNotAllowed(); + return false; + } + if (!isset($list['file'][0])) { + // single file + $list['file'] = array($list['file']); + } + foreach ($list['file'] as $i => $file) + { + if (isset($file['attribs']) && isset($file['attribs']['name'])) { + if ($file['attribs']['name']{0} == '.' && + $file['attribs']['name']{1} == '/') { + // name is something like "./doc/whatever.txt" + $this->_invalidFileName($file['attribs']['name'], $dirname); + } + if (preg_match('~/\.\.?(/|\\z)|^\.\.?/~', + str_replace('\\', '/', $file['attribs']['name']))) { + // file contains .. parent directory or . cur directory + $this->_invalidFileName($file['attribs']['name'], $dirname); + } + } + if (isset($file['attribs']) && isset($file['attribs']['role'])) { + if (!$this->_validateRole($file['attribs']['role'])) { + if (isset($this->_packageInfo['usesrole'])) { + $roles = $this->_packageInfo['usesrole']; + if (!isset($roles[0])) { + $roles = array($roles); + } + foreach ($roles as $role) { + if ($role['role'] = $file['attribs']['role']) { + $msg = 'This package contains role "%role%" and requires ' . + 'package "%package%" to be used'; + if (isset($role['uri'])) { + $params = array('role' => $role['role'], + 'package' => $role['uri']); + } else { + $params = array('role' => $role['role'], + 'package' => $this->_pf->_registry-> + parsedPackageNameToString(array('package' => + $role['package'], 'channel' => $role['channel']), + true)); + } + $this->_stack->push('_mustInstallRole', 'error', $params, $msg); + } + } + } + $this->_invalidFileRole($file['attribs']['name'], + $dirname, $file['attribs']['role']); + } + } + if (!isset($file['attribs'])) { + continue; + } + $save = $file['attribs']; + if ($dirs) { + $save['name'] = $dirs . '/' . $save['name']; + } + unset($file['attribs']); + if (count($file) && $this->_curState != PEAR_VALIDATE_DOWNLOADING) { // has tasks + foreach ($file as $task => $value) { + if ($tagClass = $this->_pf->getTask($task)) { + if (!is_array($value) || !isset($value[0])) { + $value = array($value); + } + foreach ($value as $v) { + $ret = call_user_func(array($tagClass, 'validateXml'), + $this->_pf, $v, $this->_pf->_config, $save); + if (is_array($ret)) { + $this->_invalidTask($task, $ret, isset($save['name']) ? + $save['name'] : ''); + } + } + } else { + if (isset($this->_packageInfo['usestask'])) { + $roles = $this->_packageInfo['usestask']; + if (!isset($roles[0])) { + $roles = array($roles); + } + foreach ($roles as $role) { + if ($role['task'] = $task) { + $msg = 'This package contains task "%task%" and requires ' . + 'package "%package%" to be used'; + if (isset($role['uri'])) { + $params = array('task' => $role['task'], + 'package' => $role['uri']); + } else { + $params = array('task' => $role['task'], + 'package' => $this->_pf->_registry-> + parsedPackageNameToString(array('package' => + $role['package'], 'channel' => $role['channel']), + true)); + } + $this->_stack->push('_mustInstallTask', 'error', + $params, $msg); + } + } + } + $this->_unknownTask($task, $save['name']); + } + } + } + } + } + if (isset($list['ignore'])) { + if (!$allowignore) { + $this->_ignoreNotAllowed('ignore'); + } + } + if (isset($list['install'])) { + if (!$allowignore) { + $this->_ignoreNotAllowed('install'); + } + } + if (isset($list['file'])) { + if ($allowignore) { + $this->_fileNotAllowed('file'); + } + } + if (isset($list['dir'])) { + if ($allowignore) { + $this->_fileNotAllowed('dir'); + } else { + if (!isset($list['dir'][0])) { + $list['dir'] = array($list['dir']); + } + foreach ($list['dir'] as $dir) { + if (isset($dir['attribs']) && isset($dir['attribs']['name'])) { + if ($dir['attribs']['name'] == '/' || + !isset($this->_packageInfo['contents']['dir']['dir'])) { + // always use nothing if the filelist has already been flattened + $newdirs = ''; + } elseif ($dirs == '') { + $newdirs = $dir['attribs']['name']; + } else { + $newdirs = $dirs . '/' . $dir['attribs']['name']; + } + } else { + $newdirs = $dirs; + } + $this->_validateFilelist($dir, $allowignore, $newdirs); + } + } + } + } + + function _validateRelease() + { + if (isset($this->_packageInfo['phprelease'])) { + $release = 'phprelease'; + if (isset($this->_packageInfo['providesextension'])) { + $this->_cannotProvideExtension($release); + } + if (isset($this->_packageInfo['srcpackage']) || isset($this->_packageInfo['srcuri'])) { + $this->_cannotHaveSrcpackage($release); + } + $releases = $this->_packageInfo['phprelease']; + if (!is_array($releases)) { + return true; + } + if (!isset($releases[0])) { + $releases = array($releases); + } + foreach ($releases as $rel) { + $this->_stupidSchemaValidate(array( + '*installconditions', + '*filelist', + ), $rel, ''); + } + } + foreach (array('', 'zend') as $prefix) { + $releasetype = $prefix . 'extsrcrelease'; + if (isset($this->_packageInfo[$releasetype])) { + $release = $releasetype; + if (!isset($this->_packageInfo['providesextension'])) { + $this->_mustProvideExtension($release); + } + if (isset($this->_packageInfo['srcpackage']) || isset($this->_packageInfo['srcuri'])) { + $this->_cannotHaveSrcpackage($release); + } + $releases = $this->_packageInfo[$releasetype]; + if (!is_array($releases)) { + return true; + } + if (!isset($releases[0])) { + $releases = array($releases); + } + foreach ($releases as $rel) { + $this->_stupidSchemaValidate(array( + '*installconditions', + '*configureoption->name->prompt->?default', + '*binarypackage', + '*filelist', + ), $rel, '<' . $releasetype . '>'); + if (isset($rel['binarypackage'])) { + if (!is_array($rel['binarypackage']) || !isset($rel['binarypackage'][0])) { + $rel['binarypackage'] = array($rel['binarypackage']); + } + foreach ($rel['binarypackage'] as $bin) { + if (!is_string($bin)) { + $this->_binaryPackageMustBePackagename(); + } + } + } + } + } + $releasetype = 'extbinrelease'; + if (isset($this->_packageInfo[$releasetype])) { + $release = $releasetype; + if (!isset($this->_packageInfo['providesextension'])) { + $this->_mustProvideExtension($release); + } + if (isset($this->_packageInfo['channel']) && + !isset($this->_packageInfo['srcpackage'])) { + $this->_mustSrcPackage($release); + } + if (isset($this->_packageInfo['uri']) && !isset($this->_packageInfo['srcuri'])) { + $this->_mustSrcuri($release); + } + $releases = $this->_packageInfo[$releasetype]; + if (!is_array($releases)) { + return true; + } + if (!isset($releases[0])) { + $releases = array($releases); + } + foreach ($releases as $rel) { + $this->_stupidSchemaValidate(array( + '*installconditions', + '*filelist', + ), $rel, '<' . $releasetype . '>'); + } + } + } + if (isset($this->_packageInfo['bundle'])) { + $release = 'bundle'; + if (isset($this->_packageInfo['providesextension'])) { + $this->_cannotProvideExtension($release); + } + if (isset($this->_packageInfo['srcpackage']) || isset($this->_packageInfo['srcuri'])) { + $this->_cannotHaveSrcpackage($release); + } + $releases = $this->_packageInfo['bundle']; + if (!is_array($releases) || !isset($releases[0])) { + $releases = array($releases); + } + foreach ($releases as $rel) { + $this->_stupidSchemaValidate(array( + '*installconditions', + '*filelist', + ), $rel, ''); + } + } + foreach ($releases as $rel) { + if (is_array($rel) && array_key_exists('installconditions', $rel)) { + $this->_validateInstallConditions($rel['installconditions'], + "<$release>"); + } + if (is_array($rel) && array_key_exists('filelist', $rel)) { + if ($rel['filelist']) { + + $this->_validateFilelist($rel['filelist'], true); + } + } + } + } + + /** + * This is here to allow role extension through plugins + * @param string + */ + function _validateRole($role) + { + return in_array($role, PEAR_Installer_Role::getValidRoles($this->_pf->getPackageType())); + } + + function _pearVersionTooLow($version) + { + $this->_stack->push(__FUNCTION__, 'error', + array('version' => $version), + 'This package.xml requires PEAR version %version% to parse properly, we are ' . + 'version 1.7.2'); + } + + function _invalidTagOrder($oktags, $actual, $root) + { + $this->_stack->push(__FUNCTION__, 'error', + array('oktags' => $oktags, 'actual' => $actual, 'root' => $root), + 'Invalid tag order in %root%, found <%actual%> expected one of "%oktags%"'); + } + + function _ignoreNotAllowed($type) + { + $this->_stack->push(__FUNCTION__, 'error', array('type' => $type), + '<%type%> is not allowed inside global , only inside ' . + '//, use and only'); + } + + function _fileNotAllowed($type) + { + $this->_stack->push(__FUNCTION__, 'error', array('type' => $type), + '<%type%> is not allowed inside release , only inside ' . + ', use and only'); + } + + function _oldStyleFileNotAllowed() + { + $this->_stack->push(__FUNCTION__, 'error', array(), + 'Old-style name is not allowed. Use' . + ''); + } + + function _tagMissingAttribute($tag, $attr, $context) + { + $this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag, + 'attribute' => $attr, 'context' => $context), + 'tag <%tag%> in context "%context%" has no attribute "%attribute%"'); + } + + function _tagHasNoAttribs($tag, $context) + { + $this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag, + 'context' => $context), + 'tag <%tag%> has no attributes in context "%context%"'); + } + + function _invalidInternalStructure() + { + $this->_stack->push(__FUNCTION__, 'exception', array(), + 'internal array was not generated by compatible parser, or extreme parser error, cannot continue'); + } + + function _invalidFileRole($file, $dir, $role) + { + $this->_stack->push(__FUNCTION__, 'error', array( + 'file' => $file, 'dir' => $dir, 'role' => $role, + 'roles' => PEAR_Installer_Role::getValidRoles($this->_pf->getPackageType())), + 'File "%file%" in directory "%dir%" has invalid role "%role%", should be one of %roles%'); + } + + function _invalidFileName($file, $dir) + { + $this->_stack->push(__FUNCTION__, 'error', array( + 'file' => $file), + 'File "%file%" in directory "%dir%" cannot begin with "./" or contain ".."'); + } + + function _invalidFileInstallAs($file, $as) + { + $this->_stack->push(__FUNCTION__, 'error', array( + 'file' => $file, 'as' => $as), + 'File "%file%" cannot contain "./" or contain ".."'); + } + + function _invalidDirName($dir) + { + $this->_stack->push(__FUNCTION__, 'error', array( + 'dir' => $file), + 'Directory "%dir%" cannot begin with "./" or contain ".."'); + } + + function _filelistCannotContainFile($filelist) + { + $this->_stack->push(__FUNCTION__, 'error', array('tag' => $filelist), + '<%tag%> can only contain , contains . Use ' . + ' as the first dir element'); + } + + function _filelistMustContainDir($filelist) + { + $this->_stack->push(__FUNCTION__, 'error', array('tag' => $filelist), + '<%tag%> must contain . Use as the ' . + 'first dir element'); + } + + function _tagCannotBeEmpty($tag) + { + $this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag), + '<%tag%> cannot be empty (<%tag%/>)'); + } + + function _UrlOrChannel($type, $name) + { + $this->_stack->push(__FUNCTION__, 'error', array('type' => $type, + 'name' => $name), + 'Required dependency <%type%> "%name%" can have either url OR ' . + 'channel attributes, and not both'); + } + + function _NoChannel($type, $name) + { + $this->_stack->push(__FUNCTION__, 'error', array('type' => $type, + 'name' => $name), + 'Required dependency <%type%> "%name%" must have either url OR ' . + 'channel attributes'); + } + + function _UrlOrChannelGroup($type, $name, $group) + { + $this->_stack->push(__FUNCTION__, 'error', array('type' => $type, + 'name' => $name, 'group' => $group), + 'Group "%group%" dependency <%type%> "%name%" can have either url OR ' . + 'channel attributes, and not both'); + } + + function _NoChannelGroup($type, $name, $group) + { + $this->_stack->push(__FUNCTION__, 'error', array('type' => $type, + 'name' => $name, 'group' => $group), + 'Group "%group%" dependency <%type%> "%name%" must have either url OR ' . + 'channel attributes'); + } + + function _unknownChannel($channel) + { + $this->_stack->push(__FUNCTION__, 'error', array('channel' => $channel), + 'Unknown channel "%channel%"'); + } + + function _noPackageVersion() + { + $this->_stack->push(__FUNCTION__, 'error', array(), + 'package.xml tag has no version attribute, or version is not 2.0'); + } + + function _NoBundledPackages() + { + $this->_stack->push(__FUNCTION__, 'error', array(), + 'No tag was found in , required for bundle packages'); + } + + function _AtLeast2BundledPackages() + { + $this->_stack->push(__FUNCTION__, 'error', array(), + 'At least 2 packages must be bundled in a bundle package'); + } + + function _ChannelOrUri($name) + { + $this->_stack->push(__FUNCTION__, 'error', array('name' => $name), + 'Bundled package "%name%" can have either a uri or a channel, not both'); + } + + function _noChildTag($child, $tag) + { + $this->_stack->push(__FUNCTION__, 'error', array('child' => $child, 'tag' => $tag), + 'Tag <%tag%> is missing child tag <%child%>'); + } + + function _invalidVersion($type, $value) + { + $this->_stack->push(__FUNCTION__, 'error', array('type' => $type, 'value' => $value), + 'Version type <%type%> is not a valid version (%value%)'); + } + + function _invalidState($type, $value) + { + $states = array('stable', 'beta', 'alpha', 'devel'); + if ($type != 'api') { + $states[] = 'snapshot'; + } + if (strtolower($value) == 'rc') { + $this->_stack->push(__FUNCTION__, 'error', + array('version' => $this->_packageInfo['version']['release']), + 'RC is not a state, it is a version postfix, try %version%RC1, stability beta'); + } + $this->_stack->push(__FUNCTION__, 'error', array('type' => $type, 'value' => $value, + 'types' => $states), + 'Stability type <%type%> is not a valid stability (%value%), must be one of ' . + '%types%'); + } + + function _invalidTask($task, $ret, $file) + { + switch ($ret[0]) { + case PEAR_TASK_ERROR_MISSING_ATTRIB : + $info = array('attrib' => $ret[1], 'task' => $task, 'file' => $file); + $msg = 'task <%task%> is missing attribute "%attrib%" in file %file%'; + break; + case PEAR_TASK_ERROR_NOATTRIBS : + $info = array('task' => $task, 'file' => $file); + $msg = 'task <%task%> has no attributes in file %file%'; + break; + case PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE : + $info = array('attrib' => $ret[1], 'values' => $ret[3], + 'was' => $ret[2], 'task' => $task, 'file' => $file); + $msg = 'task <%task%> attribute "%attrib%" has the wrong value "%was%" '. + 'in file %file%, expecting one of "%values%"'; + break; + case PEAR_TASK_ERROR_INVALID : + $info = array('reason' => $ret[1], 'task' => $task, 'file' => $file); + $msg = 'task <%task%> in file %file% is invalid because of "%reason%"'; + break; + } + $this->_stack->push(__FUNCTION__, 'error', $info, $msg); + } + + function _unknownTask($task, $file) + { + $this->_stack->push(__FUNCTION__, 'error', array('task' => $task, 'file' => $file), + 'Unknown task "%task%" passed in file '); + } + + function _subpackageCannotProvideExtension($name) + { + $this->_stack->push(__FUNCTION__, 'error', array('name' => $name), + 'Subpackage dependency "%name%" cannot use , ' . + 'only package dependencies can use this tag'); + } + + function _subpackagesCannotConflict($name) + { + $this->_stack->push(__FUNCTION__, 'error', array('name' => $name), + 'Subpackage dependency "%name%" cannot use , ' . + 'only package dependencies can use this tag'); + } + + function _cannotProvideExtension($release) + { + $this->_stack->push(__FUNCTION__, 'error', array('release' => $release), + '<%release%> packages cannot use , only extbinrelease, extsrcrelease, zendextsrcrelease, and zendextbinrelease can provide a PHP extension'); + } + + function _mustProvideExtension($release) + { + $this->_stack->push(__FUNCTION__, 'error', array('release' => $release), + '<%release%> packages must use to indicate which PHP extension is provided'); + } + + function _cannotHaveSrcpackage($release) + { + $this->_stack->push(__FUNCTION__, 'error', array('release' => $release), + '<%release%> packages cannot specify a source code package, only extension binaries may use the tag'); + } + + function _mustSrcPackage($release) + { + $this->_stack->push(__FUNCTION__, 'error', array('release' => $release), + '/ packages must specify a source code package with '); + } + + function _mustSrcuri($release) + { + $this->_stack->push(__FUNCTION__, 'error', array('release' => $release), + '/ packages must specify a source code package with '); + } + + function _uriDepsCannotHaveVersioning($type) + { + $this->_stack->push(__FUNCTION__, 'error', array('type' => $type), + '%type%: dependencies with a tag cannot have any versioning information'); + } + + function _conflictingDepsCannotHaveVersioning($type) + { + $this->_stack->push(__FUNCTION__, 'error', array('type' => $type), + '%type%: conflicting dependencies cannot have versioning info, use to ' . + 'exclude specific versions of a dependency'); + } + + function _DepchannelCannotBeUri($type) + { + $this->_stack->push(__FUNCTION__, 'error', array('type' => $type), + '%type%: channel cannot be __uri, this is a pseudo-channel reserved for uri ' . + 'dependencies only'); + } + + function _bundledPackagesMustBeFilename() + { + $this->_stack->push(__FUNCTION__, 'error', array(), + ' tags must contain only the filename of a package release ' . + 'in the bundle'); + } + + function _binaryPackageMustBePackagename() + { + $this->_stack->push(__FUNCTION__, 'error', array(), + ' tags must contain the name of a package that is ' . + 'a compiled version of this extsrc/zendextsrc package'); + } + + function _fileNotFound($file) + { + $this->_stack->push(__FUNCTION__, 'error', array('file' => $file), + 'File "%file%" in package.xml does not exist'); + } + + function _notInContents($file, $tag) + { + $this->_stack->push(__FUNCTION__, 'error', array('file' => $file, 'tag' => $tag), + '<%tag% name="%file%"> is invalid, file is not in '); + } + + function _cannotValidateNoPathSet() + { + $this->_stack->push(__FUNCTION__, 'error', array(), + 'Cannot validate files, no path to package file is set (use setPackageFile())'); + } + + function _usesroletaskMustHaveChannelOrUri($role, $tag) + { + $this->_stack->push(__FUNCTION__, 'error', array('role' => $role, 'tag' => $tag), + '<%tag%> for role "%role%" must contain either , or and '); + } + + function _usesroletaskMustHavePackage($role, $tag) + { + $this->_stack->push(__FUNCTION__, 'error', array('role' => $role, 'tag' => $tag), + '<%tag%> for role "%role%" must contain '); + } + + function _usesroletaskMustHaveRoleTask($tag, $type) + { + $this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag, 'type' => $type), + '<%tag%> must contain <%type%> defining the %type% to be used'); + } + + function _cannotConflictWithAllOs($type) + { + $this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag), + '%tag% cannot conflict with all OSes'); + } + + function _invalidDepGroupName($name) + { + $this->_stack->push(__FUNCTION__, 'error', array('name' => $name), + 'Invalid dependency group name "%name%"'); + } + + function _multipleToplevelDirNotAllowed() + { + $this->_stack->push(__FUNCTION__, 'error', array(), + 'Multiple top-level tags are not allowed. Enclose them ' . + 'in a '); + } + + function _multipleInstallAs($file) + { + $this->_stack->push(__FUNCTION__, 'error', array('file' => $file), + 'Only one tag is allowed for file "%file%"'); + } + + function _ignoreAndInstallAs($file) + { + $this->_stack->push(__FUNCTION__, 'error', array('file' => $file), + 'Cannot have both and tags for file "%file%"'); + } + + function _analyzeBundledPackages() + { + if (!$this->_isValid) { + return false; + } + if (!$this->_pf->getPackageType() == 'bundle') { + return false; + } + if (!isset($this->_pf->_packageFile)) { + return false; + } + $dir_prefix = dirname($this->_pf->_packageFile); + $common = new PEAR_Common; + $log = isset($this->_pf->_logger) ? array(&$this->_pf->_logger, 'log') : + array($common, 'log'); + $info = $this->_pf->getContents(); + $info = $info['bundledpackage']; + if (!is_array($info)) { + $info = array($info); + } + $pkg = &new PEAR_PackageFile($this->_pf->_config); + foreach ($info as $package) { + if (!file_exists($dir_prefix . DIRECTORY_SEPARATOR . $package)) { + $this->_fileNotFound($dir_prefix . DIRECTORY_SEPARATOR . $package); + $this->_isValid = 0; + continue; + } + call_user_func_array($log, array(1, "Analyzing bundled package $package")); + PEAR::pushErrorHandling(PEAR_ERROR_RETURN); + $ret = $pkg->fromAnyFile($dir_prefix . DIRECTORY_SEPARATOR . $package, + PEAR_VALIDATE_NORMAL); + PEAR::popErrorHandling(); + if (PEAR::isError($ret)) { + call_user_func_array($log, array(0, "ERROR: package $package is not a valid " . + 'package')); + $inf = $ret->getUserInfo(); + if (is_array($inf)) { + foreach ($inf as $err) { + call_user_func_array($log, array(1, $err['message'])); + } + } + return false; + } + } + return true; + } + + function _analyzePhpFiles() + { + if (!$this->_isValid) { + return false; + } + if (!isset($this->_pf->_packageFile)) { + $this->_cannotValidateNoPathSet(); + return false; + } + $dir_prefix = dirname($this->_pf->_packageFile); + $common = new PEAR_Common; + $log = isset($this->_pf->_logger) ? array(&$this->_pf->_logger, 'log') : + array(&$common, 'log'); + $info = $this->_pf->getContents(); + if (!$info || !isset($info['dir']['file'])) { + $this->_tagCannotBeEmpty('contents>_fileNotFound($dir_prefix . DIRECTORY_SEPARATOR . $file); + $this->_isValid = 0; + continue; + } + if (in_array($fa['role'], PEAR_Installer_Role::getPhpRoles()) && $dir_prefix) { + call_user_func_array($log, array(1, "Analyzing $file")); + $srcinfo = $this->analyzeSourceCode($dir_prefix . DIRECTORY_SEPARATOR . $file); + if ($srcinfo) { + $provides = array_merge($provides, $this->_buildProvidesArray($srcinfo)); + } + } + } + $this->_packageName = $pn = $this->_pf->getPackage(); + $pnl = strlen($pn); + foreach ($provides as $key => $what) { + if (isset($what['explicit']) || !$what) { + // skip conformance checks if the provides entry is + // specified in the package.xml file + continue; + } + extract($what); + if ($type == 'class') { + if (!strncasecmp($name, $pn, $pnl)) { + continue; + } + $this->_stack->push(__FUNCTION__, 'warning', + array('file' => $file, 'type' => $type, 'name' => $name, 'package' => $pn), + 'in %file%: %type% "%name%" not prefixed with package name "%package%"'); + } elseif ($type == 'function') { + if (strstr($name, '::') || !strncasecmp($name, $pn, $pnl)) { + continue; + } + $this->_stack->push(__FUNCTION__, 'warning', + array('file' => $file, 'type' => $type, 'name' => $name, 'package' => $pn), + 'in %file%: %type% "%name%" not prefixed with package name "%package%"'); + } + } + return $this->_isValid; + } + + /** + * Analyze the source code of the given PHP file + * + * @param string Filename of the PHP file + * @param boolean whether to analyze $file as the file contents + * @return mixed + */ + function analyzeSourceCode($file, $string = false) + { + if (!function_exists("token_get_all")) { + $this->_stack->push(__FUNCTION__, 'error', array('file' => $file), + 'Parser error: token_get_all() function must exist to analyze source code, PHP may have been compiled with --disable-tokenizer'); + return false; + } + if (!defined('T_DOC_COMMENT')) { + define('T_DOC_COMMENT', T_COMMENT); + } + if (!defined('T_INTERFACE')) { + define('T_INTERFACE', -1); + } + if (!defined('T_IMPLEMENTS')) { + define('T_IMPLEMENTS', -1); + } + if ($string) { + $contents = $file; + } else { + if (!$fp = @fopen($file, "r")) { + return false; + } + fclose($fp); + $contents = file_get_contents($file); + } + + // Silence this function so we can catch PHP Warnings and show our own custom message + $tokens = @token_get_all($contents); + if (isset($php_errormsg)) { + $pn = $this->_pf->getPackage(); + $this->_stack->push(__FUNCTION__, 'warning', + array('file' => $file, 'package' => $pn), + 'in %file%: Could not process file for unkown reasons,' . + ' possibly a PHP parse error in %file% from %package%'); + + } +/* + for ($i = 0; $i < sizeof($tokens); $i++) { + @list($token, $data) = $tokens[$i]; + if (is_string($token)) { + var_dump($token); + } else { + print token_name($token) . ' '; + var_dump(rtrim($data)); + } + } +*/ + $look_for = 0; + $paren_level = 0; + $bracket_level = 0; + $brace_level = 0; + $lastphpdoc = ''; + $current_class = ''; + $current_interface = ''; + $current_class_level = -1; + $current_function = ''; + $current_function_level = -1; + $declared_classes = array(); + $declared_interfaces = array(); + $declared_functions = array(); + $declared_methods = array(); + $used_classes = array(); + $used_functions = array(); + $extends = array(); + $implements = array(); + $nodeps = array(); + $inquote = false; + $interface = false; + for ($i = 0; $i < sizeof($tokens); $i++) { + if (is_array($tokens[$i])) { + list($token, $data) = $tokens[$i]; + } else { + $token = $tokens[$i]; + $data = ''; + } + if ($inquote) { + if ($token != '"' && $token != T_END_HEREDOC) { + continue; + } else { + $inquote = false; + continue; + } + } + switch ($token) { + case T_WHITESPACE : + continue; + case ';': + if ($interface) { + $current_function = ''; + $current_function_level = -1; + } + break; + case '"': + case T_START_HEREDOC: + $inquote = true; + break; + case T_CURLY_OPEN: + case T_DOLLAR_OPEN_CURLY_BRACES: + case '{': $brace_level++; continue 2; + case '}': + $brace_level--; + if ($current_class_level == $brace_level) { + $current_class = ''; + $current_class_level = -1; + } + if ($current_function_level == $brace_level) { + $current_function = ''; + $current_function_level = -1; + } + continue 2; + case '[': $bracket_level++; continue 2; + case ']': $bracket_level--; continue 2; + case '(': $paren_level++; continue 2; + case ')': $paren_level--; continue 2; + case T_INTERFACE: + $interface = true; + case T_CLASS: + if (($current_class_level != -1) || ($current_function_level != -1)) { + $this->_stack->push(__FUNCTION__, 'error', array('file' => $file), + 'Parser error: invalid PHP found in file "%file%"'); + return false; + } + case T_FUNCTION: + case T_NEW: + case T_EXTENDS: + case T_IMPLEMENTS: + $look_for = $token; + continue 2; + case T_STRING: + if (version_compare(zend_version(), '2.0', '<')) { + if (in_array(strtolower($data), + array('public', 'private', 'protected', 'abstract', + 'interface', 'implements', 'throw') + )) { + $this->_stack->push(__FUNCTION__, 'warning', array( + 'file' => $file), + 'Error, PHP5 token encountered in %file%,' . + ' analysis should be in PHP5'); + } + } + if ($look_for == T_CLASS) { + $current_class = $data; + $current_class_level = $brace_level; + $declared_classes[] = $current_class; + } elseif ($look_for == T_INTERFACE) { + $current_interface = $data; + $current_class_level = $brace_level; + $declared_interfaces[] = $current_interface; + } elseif ($look_for == T_IMPLEMENTS) { + $implements[$current_class] = $data; + } elseif ($look_for == T_EXTENDS) { + $extends[$current_class] = $data; + } elseif ($look_for == T_FUNCTION) { + if ($current_class) { + $current_function = "$current_class::$data"; + $declared_methods[$current_class][] = $data; + } elseif ($current_interface) { + $current_function = "$current_interface::$data"; + $declared_methods[$current_interface][] = $data; + } else { + $current_function = $data; + $declared_functions[] = $current_function; + } + $current_function_level = $brace_level; + $m = array(); + } elseif ($look_for == T_NEW) { + $used_classes[$data] = true; + } + $look_for = 0; + continue 2; + case T_VARIABLE: + $look_for = 0; + continue 2; + case T_DOC_COMMENT: + case T_COMMENT: + if (preg_match('!^/\*\*\s!', $data)) { + $lastphpdoc = $data; + if (preg_match_all('/@nodep\s+(\S+)/', $lastphpdoc, $m)) { + $nodeps = array_merge($nodeps, $m[1]); + } + } + continue 2; + case T_DOUBLE_COLON: + if (!($tokens[$i - 1][0] == T_WHITESPACE || $tokens[$i - 1][0] == T_STRING)) { + $this->_stack->push(__FUNCTION__, 'warning', array('file' => $file), + 'Parser error: invalid PHP found in file "%file%"'); + return false; + } + $class = $tokens[$i - 1][1]; + if (strtolower($class) != 'parent') { + $used_classes[$class] = true; + } + continue 2; + } + } + return array( + "source_file" => $file, + "declared_classes" => $declared_classes, + "declared_interfaces" => $declared_interfaces, + "declared_methods" => $declared_methods, + "declared_functions" => $declared_functions, + "used_classes" => array_diff(array_keys($used_classes), $nodeps), + "inheritance" => $extends, + "implements" => $implements, + ); + } + + /** + * Build a "provides" array from data returned by + * analyzeSourceCode(). The format of the built array is like + * this: + * + * array( + * 'class;MyClass' => 'array('type' => 'class', 'name' => 'MyClass'), + * ... + * ) + * + * + * @param array $srcinfo array with information about a source file + * as returned by the analyzeSourceCode() method. + * + * @return void + * + * @access private + * + */ + function _buildProvidesArray($srcinfo) + { + if (!$this->_isValid) { + return array(); + } + $providesret = array(); + $file = basename($srcinfo['source_file']); + $pn = $this->_pf->getPackage(); + $pnl = strlen($pn); + foreach ($srcinfo['declared_classes'] as $class) { + $key = "class;$class"; + if (isset($providesret[$key])) { + continue; + } + $providesret[$key] = + array('file'=> $file, 'type' => 'class', 'name' => $class); + if (isset($srcinfo['inheritance'][$class])) { + $providesret[$key]['extends'] = + $srcinfo['inheritance'][$class]; + } + } + foreach ($srcinfo['declared_methods'] as $class => $methods) { + foreach ($methods as $method) { + $function = "$class::$method"; + $key = "function;$function"; + if ($method{0} == '_' || !strcasecmp($method, $class) || + isset($providesret[$key])) { + continue; + } + $providesret[$key] = + array('file'=> $file, 'type' => 'function', 'name' => $function); + } + } + + foreach ($srcinfo['declared_functions'] as $function) { + $key = "function;$function"; + if ($function{0} == '_' || isset($providesret[$key])) { + continue; + } + if (!strstr($function, '::') && strncasecmp($function, $pn, $pnl)) { + $warnings[] = "in1 " . $file . ": function \"$function\" not prefixed with package name \"$pn\""; + } + $providesret[$key] = + array('file'=> $file, 'type' => 'function', 'name' => $function); + } + return $providesret; + } +} +?> \ No newline at end of file diff --git a/src/lib/pear/PEAR/PEAR/PackageFile/v2/rw.php b/src/lib/pear/PEAR/PEAR/PackageFile/v2/rw.php new file mode 100644 index 0000000..383042b --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/PackageFile/v2/rw.php @@ -0,0 +1,1603 @@ + + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: rw.php,v 1.22 2008/01/18 22:47:49 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 1.4.0a8 + */ +/** + * For base class + */ +require_once 'PEAR/PackageFile/v2.php'; +/** + * @category pear + * @package PEAR + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 1.4.0a8 + */ +class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2 +{ + /** + * @param string Extension name + * @return bool success of operation + */ + function setProvidesExtension($extension) + { + if (in_array($this->getPackageType(), + array('extsrc', 'extbin', 'zendextsrc', 'zendextbin'))) { + if (!isset($this->_packageInfo['providesextension'])) { + // ensure that the channel tag is set up in the right location + $this->_packageInfo = $this->_insertBefore($this->_packageInfo, + array('usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', + 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', + 'bundle', 'changelog'), + $extension, 'providesextension'); + } + $this->_packageInfo['providesextension'] = $extension; + return true; + } + return false; + } + + function setPackage($package) + { + $this->_isValid = 0; + if (!isset($this->_packageInfo['attribs'])) { + $this->_packageInfo = array_merge(array('attribs' => array( + 'version' => '2.0', + 'xmlns' => 'http://pear.php.net/dtd/package-2.0', + 'xmlns:tasks' => 'http://pear.php.net/dtd/tasks-1.0', + 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance', + 'xsi:schemaLocation' => 'http://pear.php.net/dtd/tasks-1.0 + http://pear.php.net/dtd/tasks-1.0.xsd + http://pear.php.net/dtd/package-2.0 + http://pear.php.net/dtd/package-2.0.xsd', + )), $this->_packageInfo); + } + if (!isset($this->_packageInfo['name'])) { + return $this->_packageInfo = array_merge(array('name' => $package), + $this->_packageInfo); + } + $this->_packageInfo['name'] = $package; + } + + /** + * set this as a package.xml version 2.1 + * @access private + */ + function _setPackageVersion2_1() + { + $info = array( + 'version' => '2.1', + 'xmlns' => 'http://pear.php.net/dtd/package-2.1', + 'xmlns:tasks' => 'http://pear.php.net/dtd/tasks-1.0', + 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance', + 'xsi:schemaLocation' => 'http://pear.php.net/dtd/tasks-1.0 + http://pear.php.net/dtd/tasks-1.0.xsd + http://pear.php.net/dtd/package-2.1 + http://pear.php.net/dtd/package-2.1.xsd', + ); + if (!isset($this->_packageInfo['attribs'])) { + $this->_packageInfo = array_merge(array('attribs' => $info), $this->_packageInfo); + } else { + $this->_packageInfo['attribs'] = $info; + } + } + + function setUri($uri) + { + unset($this->_packageInfo['channel']); + $this->_isValid = 0; + if (!isset($this->_packageInfo['uri'])) { + // ensure that the uri tag is set up in the right location + $this->_packageInfo = $this->_insertBefore($this->_packageInfo, + array('extends', 'summary', 'description', 'lead', + 'developer', 'contributor', 'helper', 'date', 'time', 'version', + 'stability', 'license', 'notes', 'contents', 'compatible', + 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', + 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease', + 'extbinrelease', 'bundle', 'changelog'), $uri, 'uri'); + } + $this->_packageInfo['uri'] = $uri; + } + + function setChannel($channel) + { + unset($this->_packageInfo['uri']); + $this->_isValid = 0; + if (!isset($this->_packageInfo['channel'])) { + // ensure that the channel tag is set up in the right location + $this->_packageInfo = $this->_insertBefore($this->_packageInfo, + array('extends', 'summary', 'description', 'lead', + 'developer', 'contributor', 'helper', 'date', 'time', 'version', + 'stability', 'license', 'notes', 'contents', 'compatible', + 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', + 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease', + 'extbinrelease', 'bundle', 'changelog'), $channel, 'channel'); + } + $this->_packageInfo['channel'] = $channel; + } + + function setExtends($extends) + { + $this->_isValid = 0; + if (!isset($this->_packageInfo['extends'])) { + // ensure that the extends tag is set up in the right location + $this->_packageInfo = $this->_insertBefore($this->_packageInfo, + array('summary', 'description', 'lead', + 'developer', 'contributor', 'helper', 'date', 'time', 'version', + 'stability', 'license', 'notes', 'contents', 'compatible', + 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', + 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease', + 'extbinrelease', 'bundle', 'changelog'), $extends, 'extends'); + } + $this->_packageInfo['extends'] = $extends; + } + + function setSummary($summary) + { + $this->_isValid = 0; + if (!isset($this->_packageInfo['summary'])) { + // ensure that the summary tag is set up in the right location + $this->_packageInfo = $this->_insertBefore($this->_packageInfo, + array('description', 'lead', + 'developer', 'contributor', 'helper', 'date', 'time', 'version', + 'stability', 'license', 'notes', 'contents', 'compatible', + 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', + 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease', + 'extbinrelease', 'bundle', 'changelog'), $summary, 'summary'); + } + $this->_packageInfo['summary'] = $summary; + } + + function setDescription($desc) + { + $this->_isValid = 0; + if (!isset($this->_packageInfo['description'])) { + // ensure that the description tag is set up in the right location + $this->_packageInfo = $this->_insertBefore($this->_packageInfo, + array('lead', + 'developer', 'contributor', 'helper', 'date', 'time', 'version', + 'stability', 'license', 'notes', 'contents', 'compatible', + 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', + 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease', + 'extbinrelease', 'bundle', 'changelog'), $desc, 'description'); + } + $this->_packageInfo['description'] = $desc; + } + + /** + * Adds a new maintainer - no checking of duplicates is performed, use + * updatemaintainer for that purpose. + */ + function addMaintainer($role, $handle, $name, $email, $active = 'yes') + { + if (!in_array($role, array('lead', 'developer', 'contributor', 'helper'))) { + return false; + } + if (isset($this->_packageInfo[$role])) { + if (!isset($this->_packageInfo[$role][0])) { + $this->_packageInfo[$role] = array($this->_packageInfo[$role]); + } + $this->_packageInfo[$role][] = + array( + 'name' => $name, + 'user' => $handle, + 'email' => $email, + 'active' => $active, + ); + } else { + $testarr = array('lead', + 'developer', 'contributor', 'helper', 'date', 'time', 'version', + 'stability', 'license', 'notes', 'contents', 'compatible', + 'dependencies', 'providesextension', 'usesrole', 'usestask', + 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', + 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'); + foreach (array('lead', 'developer', 'contributor', 'helper') as $testrole) { + array_shift($testarr); + if ($role == $testrole) { + break; + } + } + if (!isset($this->_packageInfo[$role])) { + // ensure that the extends tag is set up in the right location + $this->_packageInfo = $this->_insertBefore($this->_packageInfo, $testarr, + array(), $role); + } + $this->_packageInfo[$role] = + array( + 'name' => $name, + 'user' => $handle, + 'email' => $email, + 'active' => $active, + ); + } + $this->_isValid = 0; + } + + function updateMaintainer($newrole, $handle, $name, $email, $active = 'yes') + { + $found = false; + foreach (array('lead', 'developer', 'contributor', 'helper') as $role) { + if (!isset($this->_packageInfo[$role])) { + continue; + } + $info = $this->_packageInfo[$role]; + if (!isset($info[0])) { + if ($info['user'] == $handle) { + $found = true; + break; + } + } + foreach ($info as $i => $maintainer) { + if ($maintainer['user'] == $handle) { + $found = $i; + break 2; + } + } + } + if ($found === false) { + return $this->addMaintainer($newrole, $handle, $name, $email, $active); + } + if ($found !== false) { + if ($found === true) { + unset($this->_packageInfo[$role]); + } else { + unset($this->_packageInfo[$role][$found]); + $this->_packageInfo[$role] = array_values($this->_packageInfo[$role]); + } + } + $this->addMaintainer($newrole, $handle, $name, $email, $active); + $this->_isValid = 0; + } + + function deleteMaintainer($handle) + { + $found = false; + foreach (array('lead', 'developer', 'contributor', 'helper') as $role) { + if (!isset($this->_packageInfo[$role])) { + continue; + } + if (!isset($this->_packageInfo[$role][0])) { + $this->_packageInfo[$role] = array($this->_packageInfo[$role]); + } + foreach ($this->_packageInfo[$role] as $i => $maintainer) { + if ($maintainer['user'] == $handle) { + $found = $i; + break; + } + } + if ($found !== false) { + unset($this->_packageInfo[$role][$found]); + if (!count($this->_packageInfo[$role]) && $role == 'lead') { + $this->_isValid = 0; + } + if (!count($this->_packageInfo[$role])) { + unset($this->_packageInfo[$role]); + return true; + } + $this->_packageInfo[$role] = + array_values($this->_packageInfo[$role]); + if (count($this->_packageInfo[$role]) == 1) { + $this->_packageInfo[$role] = $this->_packageInfo[$role][0]; + } + return true; + } + if (count($this->_packageInfo[$role]) == 1) { + $this->_packageInfo[$role] = $this->_packageInfo[$role][0]; + } + } + return false; + } + + function setReleaseVersion($version) + { + if (isset($this->_packageInfo['version']) && + isset($this->_packageInfo['version']['release'])) { + unset($this->_packageInfo['version']['release']); + } + $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $version, array( + 'version' => array('stability', 'license', 'notes', 'contents', 'compatible', + 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', + 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease', + 'extbinrelease', 'bundle', 'changelog'), + 'release' => array('api'))); + $this->_isValid = 0; + } + + function setAPIVersion($version) + { + if (isset($this->_packageInfo['version']) && + isset($this->_packageInfo['version']['api'])) { + unset($this->_packageInfo['version']['api']); + } + $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $version, array( + 'version' => array('stability', 'license', 'notes', 'contents', 'compatible', + 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', + 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease', + 'extbinrelease', 'bundle', 'changelog'), + 'api' => array())); + $this->_isValid = 0; + } + + /** + * snapshot|devel|alpha|beta|stable + */ + function setReleaseStability($state) + { + if (isset($this->_packageInfo['stability']) && + isset($this->_packageInfo['stability']['release'])) { + unset($this->_packageInfo['stability']['release']); + } + $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $state, array( + 'stability' => array('license', 'notes', 'contents', 'compatible', + 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', + 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease', + 'extbinrelease', 'bundle', 'changelog'), + 'release' => array('api'))); + $this->_isValid = 0; + } + + /** + * @param devel|alpha|beta|stable + */ + function setAPIStability($state) + { + if (isset($this->_packageInfo['stability']) && + isset($this->_packageInfo['stability']['api'])) { + unset($this->_packageInfo['stability']['api']); + } + $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $state, array( + 'stability' => array('license', 'notes', 'contents', 'compatible', + 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', + 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease', + 'extbinrelease', 'bundle', 'changelog'), + 'api' => array())); + $this->_isValid = 0; + } + + function setLicense($license, $uri = false, $filesource = false) + { + if (!isset($this->_packageInfo['license'])) { + // ensure that the license tag is set up in the right location + $this->_packageInfo = $this->_insertBefore($this->_packageInfo, + array('notes', 'contents', 'compatible', + 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', + 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease', + 'extbinrelease', 'bundle', 'changelog'), 0, 'license'); + } + if ($uri || $filesource) { + $attribs = array(); + if ($uri) { + $attribs['uri'] = $uri; + } + $uri = true; // for test below + if ($filesource) { + $attribs['filesource'] = $filesource; + } + } + $license = $uri ? array('attribs' => $attribs, '_content' => $license) : $license; + $this->_packageInfo['license'] = $license; + $this->_isValid = 0; + } + + function setNotes($notes) + { + $this->_isValid = 0; + if (!isset($this->_packageInfo['notes'])) { + // ensure that the notes tag is set up in the right location + $this->_packageInfo = $this->_insertBefore($this->_packageInfo, + array('contents', 'compatible', + 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri', + 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease', + 'extbinrelease', 'bundle', 'changelog'), $notes, 'notes'); + } + $this->_packageInfo['notes'] = $notes; + } + + /** + * This is only used at install-time, after all serialization + * is over. + * @param string file name + * @param string installed path + */ + function setInstalledAs($file, $path) + { + if ($path) { + return $this->_packageInfo['filelist'][$file]['installed_as'] = $path; + } + unset($this->_packageInfo['filelist'][$file]['installed_as']); + } + + /** + * This is only used at install-time, after all serialization + * is over. + */ + function installedFile($file, $atts) + { + if (isset($this->_packageInfo['filelist'][$file])) { + $this->_packageInfo['filelist'][$file] = + array_merge($this->_packageInfo['filelist'][$file], $atts['attribs']); + } else { + $this->_packageInfo['filelist'][$file] = $atts['attribs']; + } + } + + /** + * Reset the listing of package contents + * @param string base installation dir for the whole package, if any + */ + function clearContents($baseinstall = false) + { + $this->_filesValid = false; + $this->_isValid = 0; + if (!isset($this->_packageInfo['contents'])) { + $this->_packageInfo = $this->_insertBefore($this->_packageInfo, + array('compatible', + 'dependencies', 'providesextension', 'usesrole', 'usestask', + 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', + 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', + 'bundle', 'changelog'), array(), 'contents'); + } + if ($this->getPackageType() != 'bundle') { + $this->_packageInfo['contents'] = + array('dir' => array('attribs' => array('name' => '/'))); + if ($baseinstall) { + $this->_packageInfo['contents']['dir']['attribs']['baseinstalldir'] = $baseinstall; + } + } else { + $this->_packageInfo['contents'] = array('bundledpackage' => array()); + } + } + + /** + * @param string relative path of the bundled package. + */ + function addBundledPackage($path) + { + if ($this->getPackageType() != 'bundle') { + return false; + } + $this->_filesValid = false; + $this->_isValid = 0; + $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $path, array( + 'contents' => array('compatible', 'dependencies', 'providesextension', + 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease', + 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', + 'bundle', 'changelog'), + 'bundledpackage' => array())); + } + + /** + * @param string file name + * @param PEAR_Task_Common a read/write task + */ + function addTaskToFile($filename, $task) + { + if (!method_exists($task, 'getXml')) { + return false; + } + if (!method_exists($task, 'getName')) { + return false; + } + if (!method_exists($task, 'validate')) { + return false; + } + if (!$task->validate()) { + return false; + } + if (!isset($this->_packageInfo['contents']['dir']['file'])) { + return false; + } + $this->getTasksNs(); // discover the tasks namespace if not done already + $files = $this->_packageInfo['contents']['dir']['file']; + if (!isset($files[0])) { + $files = array($files); + $ind = false; + } else { + $ind = true; + } + foreach ($files as $i => $file) { + if (isset($file['attribs'])) { + if ($file['attribs']['name'] == $filename) { + if ($ind) { + $t = isset($this->_packageInfo['contents']['dir']['file'][$i] + ['attribs'][$this->_tasksNs . + ':' . $task->getName()]) ? + $this->_packageInfo['contents']['dir']['file'][$i] + ['attribs'][$this->_tasksNs . + ':' . $task->getName()] : false; + if ($t && !isset($t[0])) { + $this->_packageInfo['contents']['dir']['file'][$i] + [$this->_tasksNs . ':' . $task->getName()] = array($t); + } + $this->_packageInfo['contents']['dir']['file'][$i][$this->_tasksNs . + ':' . $task->getName()][] = $task->getXml(); + } else { + $t = isset($this->_packageInfo['contents']['dir']['file'] + ['attribs'][$this->_tasksNs . + ':' . $task->getName()]) ? $this->_packageInfo['contents']['dir']['file'] + ['attribs'][$this->_tasksNs . + ':' . $task->getName()] : false; + if ($t && !isset($t[0])) { + $this->_packageInfo['contents']['dir']['file'] + [$this->_tasksNs . ':' . $task->getName()] = array($t); + } + $this->_packageInfo['contents']['dir']['file'][$this->_tasksNs . + ':' . $task->getName()][] = $task->getXml(); + } + return true; + } + } + } + return false; + } + + /** + * @param string path to the file + * @param string filename + * @param array extra attributes + */ + function addFile($dir, $file, $attrs) + { + if ($this->getPackageType() == 'bundle') { + return false; + } + $this->_filesValid = false; + $this->_isValid = 0; + $dir = preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'), $dir); + if ($dir == '/' || $dir == '') { + $dir = ''; + } else { + $dir .= '/'; + } + $attrs['name'] = $dir . $file; + if (!isset($this->_packageInfo['contents'])) { + // ensure that the contents tag is set up + $this->_packageInfo = $this->_insertBefore($this->_packageInfo, + array('compatible', 'dependencies', 'providesextension', 'usesrole', 'usestask', + 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', + 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', + 'bundle', 'changelog'), array(), 'contents'); + } + if (isset($this->_packageInfo['contents']['dir']['file'])) { + if (!isset($this->_packageInfo['contents']['dir']['file'][0])) { + $this->_packageInfo['contents']['dir']['file'] = + array($this->_packageInfo['contents']['dir']['file']); + } + $this->_packageInfo['contents']['dir']['file'][]['attribs'] = $attrs; + } else { + $this->_packageInfo['contents']['dir']['file']['attribs'] = $attrs; + } + } + + /** + * @param string Dependent package name + * @param string Dependent package's channel name + * @param string minimum version of specified package that this release is guaranteed to be + * compatible with + * @param string maximum version of specified package that this release is guaranteed to be + * compatible with + * @param string versions of specified package that this release is not compatible with + */ + function addCompatiblePackage($name, $channel, $min, $max, $exclude = false) + { + $this->_isValid = 0; + $set = array( + 'name' => $name, + 'channel' => $channel, + 'min' => $min, + 'max' => $max, + ); + if ($exclude) { + $set['exclude'] = $exclude; + } + $this->_isValid = 0; + $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $set, array( + 'compatible' => array('dependencies', 'providesextension', 'usesrole', 'usestask', + 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', + 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog') + )); + } + + /** + * Removes the tag entirely + */ + function resetUsesrole() + { + if (isset($this->_packageInfo['usesrole'])) { + unset($this->_packageInfo['usesrole']); + } + } + + /** + * @param string + * @param string package name or uri + * @param string channel name if non-uri + */ + function addUsesrole($role, $packageOrUri, $channel = false) { + $set = array('role' => $role); + if ($channel) { + $set['package'] = $packageOrUri; + $set['channel'] = $channel; + } else { + $set['uri'] = $packageOrUri; + } + $this->_isValid = 0; + $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $set, array( + 'usesrole' => array('usestask', 'srcpackage', 'srcuri', + 'phprelease', 'extsrcrelease', 'extbinrelease', + 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog') + )); + } + + /** + * Removes the tag entirely + */ + function resetUsestask() + { + if (isset($this->_packageInfo['usestask'])) { + unset($this->_packageInfo['usestask']); + } + } + + + /** + * @param string + * @param string package name or uri + * @param string channel name if non-uri + */ + function addUsestask($task, $packageOrUri, $channel = false) { + $set = array('task' => $task); + if ($channel) { + $set['package'] = $packageOrUri; + $set['channel'] = $channel; + } else { + $set['uri'] = $packageOrUri; + } + $this->_isValid = 0; + $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $set, array( + 'usestask' => array('srcpackage', 'srcuri', + 'phprelease', 'extsrcrelease', 'extbinrelease', + 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog') + )); + } + + /** + * Remove all compatible tags + */ + function clearCompatible() + { + unset($this->_packageInfo['compatible']); + } + + /** + * Reset dependencies prior to adding new ones + */ + function clearDeps() + { + if (!isset($this->_packageInfo['dependencies'])) { + $this->_packageInfo = $this->_mergeTag($this->_packageInfo, array(), + array( + 'dependencies' => array('providesextension', 'usesrole', 'usestask', + 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', + 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'))); + } + $this->_packageInfo['dependencies'] = array(); + } + + /** + * @param string minimum PHP version allowed + * @param string maximum PHP version allowed + * @param array $exclude incompatible PHP versions + */ + function setPhpDep($min, $max = false, $exclude = false) + { + $this->_isValid = 0; + $dep = + array( + 'min' => $min, + ); + if ($max) { + $dep['max'] = $max; + } + if ($exclude) { + if (count($exclude) == 1) { + $exclude = $exclude[0]; + } + $dep['exclude'] = $exclude; + } + if (isset($this->_packageInfo['dependencies']['required']['php'])) { + $this->_stack->push(__FUNCTION__, 'warning', array('dep' => + $this->_packageInfo['dependencies']['required']['php']), + 'warning: PHP dependency already exists, overwriting'); + unset($this->_packageInfo['dependencies']['required']['php']); + } + $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep, + array( + 'dependencies' => array('providesextension', 'usesrole', 'usestask', + 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', + 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), + 'required' => array('optional', 'group'), + 'php' => array('pearinstaller', 'package', 'subpackage', 'extension', 'os', 'arch') + )); + return true; + } + + /** + * @param string minimum allowed PEAR installer version + * @param string maximum allowed PEAR installer version + * @param string recommended PEAR installer version + * @param array incompatible version of the PEAR installer + */ + function setPearinstallerDep($min, $max = false, $recommended = false, $exclude = false) + { + $this->_isValid = 0; + $dep = + array( + 'min' => $min, + ); + if ($max) { + $dep['max'] = $max; + } + if ($recommended) { + $dep['recommended'] = $recommended; + } + if ($exclude) { + if (count($exclude) == 1) { + $exclude = $exclude[0]; + } + $dep['exclude'] = $exclude; + } + if (isset($this->_packageInfo['dependencies']['required']['pearinstaller'])) { + $this->_stack->push(__FUNCTION__, 'warning', array('dep' => + $this->_packageInfo['dependencies']['required']['pearinstaller']), + 'warning: PEAR Installer dependency already exists, overwriting'); + unset($this->_packageInfo['dependencies']['required']['pearinstaller']); + } + $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep, + array( + 'dependencies' => array('providesextension', 'usesrole', 'usestask', + 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', + 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), + 'required' => array('optional', 'group'), + 'pearinstaller' => array('package', 'subpackage', 'extension', 'os', 'arch') + )); + } + + /** + * Mark a package as conflicting with this package + * @param string package name + * @param string package channel + * @param string extension this package provides, if any + * @param string|false minimum version required + * @param string|false maximum version allowed + * @param array|false versions to exclude from installation + */ + function addConflictingPackageDepWithChannel($name, $channel, + $providesextension = false, $min = false, $max = false, $exclude = false) + { + $this->_isValid = 0; + $dep = $this->_constructDep($name, $channel, false, $min, $max, false, + $exclude, $providesextension, false, true); + $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep, + array( + 'dependencies' => array('providesextension', 'usesrole', 'usestask', + 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', + 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), + 'required' => array('optional', 'group'), + 'package' => array('subpackage', 'extension', 'os', 'arch') + )); + } + + /** + * Mark a package as conflicting with this package + * @param string package name + * @param string package channel + * @param string extension this package provides, if any + */ + function addConflictingPackageDepWithUri($name, $uri, $providesextension = false) + { + $this->_isValid = 0; + $dep = + array( + 'name' => $name, + 'uri' => $uri, + 'conflicts' => '', + ); + if ($providesextension) { + $dep['providesextension'] = $providesextension; + } + $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep, + array( + 'dependencies' => array('providesextension', 'usesrole', 'usestask', + 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', + 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), + 'required' => array('optional', 'group'), + 'package' => array('subpackage', 'extension', 'os', 'arch') + )); + } + + function addDependencyGroup($name, $hint) + { + $this->_isValid = 0; + $this->_packageInfo = $this->_mergeTag($this->_packageInfo, + array('attribs' => array('name' => $name, 'hint' => $hint)), + array( + 'dependencies' => array('providesextension', 'usesrole', 'usestask', + 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', + 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), + 'group' => array(), + )); + } + + /** + * @param string package name + * @param string|false channel name, false if this is a uri + * @param string|false uri name, false if this is a channel + * @param string|false minimum version required + * @param string|false maximum version allowed + * @param string|false recommended installation version + * @param array|false versions to exclude from installation + * @param string extension this package provides, if any + * @param bool if true, tells the installer to ignore the default optional dependency group + * when installing this package + * @param bool if true, tells the installer to negate this dependency (conflicts) + * @return array + * @access private + */ + function _constructDep($name, $channel, $uri, $min, $max, $recommended, $exclude, + $providesextension = false, $nodefault = false, + $conflicts = false) + { + $dep = + array( + 'name' => $name, + ); + if ($channel) { + $dep['channel'] = $channel; + } elseif ($uri) { + $dep['uri'] = $uri; + } + if ($min) { + $dep['min'] = $min; + } + if ($max) { + $dep['max'] = $max; + } + if ($recommended) { + $dep['recommended'] = $recommended; + } + if ($exclude) { + if (is_array($exclude) && count($exclude) == 1) { + $exclude = $exclude[0]; + } + $dep['exclude'] = $exclude; + } + if ($conflicts) { + $dep['conflicts'] = ''; + } + if ($nodefault) { + $dep['nodefault'] = ''; + } + if ($providesextension) { + $dep['providesextension'] = $providesextension; + } + return $dep; + } + + /** + * @param package|subpackage + * @param string group name + * @param string package name + * @param string package channel + * @param string minimum version + * @param string maximum version + * @param string recommended version + * @param array|false optional excluded versions + * @param string extension this package provides, if any + * @param bool if true, tells the installer to ignore the default optional dependency group + * when installing this package + * @return bool false if the dependency group has not been initialized with + * {@link addDependencyGroup()}, or a subpackage is added with + * a providesextension + */ + function addGroupPackageDepWithChannel($type, $groupname, $name, $channel, $min = false, + $max = false, $recommended = false, $exclude = false, + $providesextension = false, $nodefault = false) + { + if ($type == 'subpackage' && $providesextension) { + return false; // subpackages must be php packages + } + $dep = $this->_constructDep($name, $channel, false, $min, $max, $recommended, $exclude, + $providesextension, $nodefault); + return $this->_addGroupDependency($type, $dep, $groupname); + } + + /** + * @param package|subpackage + * @param string group name + * @param string package name + * @param string package uri + * @param string extension this package provides, if any + * @param bool if true, tells the installer to ignore the default optional dependency group + * when installing this package + * @return bool false if the dependency group has not been initialized with + * {@link addDependencyGroup()} + */ + function addGroupPackageDepWithURI($type, $groupname, $name, $uri, $providesextension = false, + $nodefault = false) + { + if ($type == 'subpackage' && $providesextension) { + return false; // subpackages must be php packages + } + $dep = $this->_constructDep($name, false, $uri, false, false, false, false, + $providesextension, $nodefault); + return $this->_addGroupDependency($type, $dep, $groupname); + } + + /** + * @param string group name (must be pre-existing) + * @param string extension name + * @param string minimum version allowed + * @param string maximum version allowed + * @param string recommended version + * @param array incompatible versions + */ + function addGroupExtensionDep($groupname, $name, $min = false, $max = false, + $recommended = false, $exclude = false) + { + $this->_isValid = 0; + $dep = $this->_constructDep($name, false, false, $min, $max, $recommended, $exclude); + return $this->_addGroupDependency('extension', $dep, $groupname); + } + + /** + * @param package|subpackage|extension + * @param array dependency contents + * @param string name of the dependency group to add this to + * @return boolean + * @access private + */ + function _addGroupDependency($type, $dep, $groupname) + { + $arr = array('subpackage', 'extension'); + if ($type != 'package') { + array_shift($arr); + } + if ($type == 'extension') { + array_shift($arr); + } + if (!isset($this->_packageInfo['dependencies']['group'])) { + return false; + } else { + if (!isset($this->_packageInfo['dependencies']['group'][0])) { + if ($this->_packageInfo['dependencies']['group']['attribs']['name'] == $groupname) { + $this->_packageInfo['dependencies']['group'] = $this->_mergeTag( + $this->_packageInfo['dependencies']['group'], $dep, + array( + $type => $arr + )); + $this->_isValid = 0; + return true; + } else { + return false; + } + } else { + foreach ($this->_packageInfo['dependencies']['group'] as $i => $group) { + if ($group['attribs']['name'] == $groupname) { + $this->_packageInfo['dependencies']['group'][$i] = $this->_mergeTag( + $this->_packageInfo['dependencies']['group'][$i], $dep, + array( + $type => $arr + )); + $this->_isValid = 0; + return true; + } + } + return false; + } + } + } + + /** + * @param optional|required + * @param string package name + * @param string package channel + * @param string minimum version + * @param string maximum version + * @param string recommended version + * @param string extension this package provides, if any + * @param bool if true, tells the installer to ignore the default optional dependency group + * when installing this package + * @param array|false optional excluded versions + */ + function addPackageDepWithChannel($type, $name, $channel, $min = false, $max = false, + $recommended = false, $exclude = false, + $providesextension = false, $nodefault = false) + { + if (!in_array($type, array('optional', 'required'), true)) { + $type = 'required'; + } + $this->_isValid = 0; + $arr = array('optional', 'group'); + if ($type != 'required') { + array_shift($arr); + } + $dep = $this->_constructDep($name, $channel, false, $min, $max, $recommended, $exclude, + $providesextension, $nodefault); + $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep, + array( + 'dependencies' => array('providesextension', 'usesrole', 'usestask', + 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', + 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), + $type => $arr, + 'package' => array('subpackage', 'extension', 'os', 'arch') + )); + } + + /** + * @param optional|required + * @param string name of the package + * @param string uri of the package + * @param string extension this package provides, if any + * @param bool if true, tells the installer to ignore the default optional dependency group + * when installing this package + */ + function addPackageDepWithUri($type, $name, $uri, $providesextension = false, + $nodefault = false) + { + $this->_isValid = 0; + $arr = array('optional', 'group'); + if ($type != 'required') { + array_shift($arr); + } + $dep = $this->_constructDep($name, false, $uri, false, false, false, false, + $providesextension, $nodefault); + $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep, + array( + 'dependencies' => array('providesextension', 'usesrole', 'usestask', + 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', + 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), + $type => $arr, + 'package' => array('subpackage', 'extension', 'os', 'arch') + )); + } + + /** + * @param optional|required optional, required + * @param string package name + * @param string package channel + * @param string minimum version + * @param string maximum version + * @param string recommended version + * @param array incompatible versions + * @param bool if true, tells the installer to ignore the default optional dependency group + * when installing this package + */ + function addSubpackageDepWithChannel($type, $name, $channel, $min = false, $max = false, + $recommended = false, $exclude = false, + $nodefault = false) + { + $this->_isValid = 0; + $arr = array('optional', 'group'); + if ($type != 'required') { + array_shift($arr); + } + $dep = $this->_constructDep($name, $channel, false, $min, $max, $recommended, $exclude, + $nodefault); + $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep, + array( + 'dependencies' => array('providesextension', 'usesrole', 'usestask', + 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', + 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), + $type => $arr, + 'subpackage' => array('extension', 'os', 'arch') + )); + } + + /** + * @param optional|required optional, required + * @param string package name + * @param string package uri for download + * @param bool if true, tells the installer to ignore the default optional dependency group + * when installing this package + */ + function addSubpackageDepWithUri($type, $name, $uri, $nodefault = false) + { + $this->_isValid = 0; + $arr = array('optional', 'group'); + if ($type != 'required') { + array_shift($arr); + } + $dep = $this->_constructDep($name, false, $uri, false, false, false, false, $nodefault); + $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep, + array( + 'dependencies' => array('providesextension', 'usesrole', 'usestask', + 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', + 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), + $type => $arr, + 'subpackage' => array('extension', 'os', 'arch') + )); + } + + /** + * @param optional|required optional, required + * @param string extension name + * @param string minimum version + * @param string maximum version + * @param string recommended version + * @param array incompatible versions + */ + function addExtensionDep($type, $name, $min = false, $max = false, $recommended = false, + $exclude = false) + { + $this->_isValid = 0; + $arr = array('optional', 'group'); + if ($type != 'required') { + array_shift($arr); + } + $dep = $this->_constructDep($name, false, false, $min, $max, $recommended, $exclude); + $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep, + array( + 'dependencies' => array('providesextension', 'usesrole', 'usestask', + 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', + 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), + $type => $arr, + 'extension' => array('os', 'arch') + )); + } + + /** + * @param string Operating system name + * @param boolean true if this package cannot be installed on this OS + */ + function addOsDep($name, $conflicts = false) + { + $this->_isValid = 0; + $dep = array('name' => $name); + if ($conflicts) { + $dep['conflicts'] = ''; + } + $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep, + array( + 'dependencies' => array('providesextension', 'usesrole', 'usestask', + 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', + 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), + 'required' => array('optional', 'group'), + 'os' => array('arch') + )); + } + + /** + * @param string Architecture matching pattern + * @param boolean true if this package cannot be installed on this architecture + */ + function addArchDep($pattern, $conflicts = false) + { + $this->_isValid = 0; + $dep = array('pattern' => $pattern); + if ($conflicts) { + $dep['conflicts'] = ''; + } + $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep, + array( + 'dependencies' => array('providesextension', 'usesrole', 'usestask', + 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease', + 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'), + 'required' => array('optional', 'group'), + 'arch' => array() + )); + } + + /** + * Set the kind of package, and erase all release tags + * + * - a php package is a PEAR-style package + * - an extbin package is a PECL-style extension binary + * - an extsrc package is a PECL-style source for a binary + * - an zendextbin package is a PECL-style zend extension binary + * - an zendextsrc package is a PECL-style source for a zend extension binary + * - a bundle package is a collection of other pre-packaged packages + * @param php|extbin|extsrc|zendextsrc|zendextbin|bundle + * @return bool success + */ + function setPackageType($type) + { + $this->_isValid = 0; + if (!in_array($type, array('php', 'extbin', 'extsrc', 'zendextsrc', + 'zendextbin', 'bundle'))) { + return false; + } + if (in_array($type, array('zendextsrc', 'zendextbin'))) { + $this->_setPackageVersion2_1(); + } + if ($type != 'bundle') { + $type .= 'release'; + } + foreach (array('phprelease', 'extbinrelease', 'extsrcrelease', + 'zendextsrcrelease', 'zendextbinrelease', 'bundle') as $test) { + unset($this->_packageInfo[$test]); + } + if (!isset($this->_packageInfo[$type])) { + // ensure that the release tag is set up + $this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('changelog'), + array(), $type); + } + $this->_packageInfo[$type] = array(); + return true; + } + + /** + * @return bool true if package type is set up + */ + function addRelease() + { + if ($type = $this->getPackageType()) { + if ($type != 'bundle') { + $type .= 'release'; + } + $this->_packageInfo = $this->_mergeTag($this->_packageInfo, array(), + array($type => array('changelog'))); + return true; + } + return false; + } + + /** + * Get the current release tag in order to add to it + * @param bool returns only releases that have installcondition if true + * @return array|null + */ + function &_getCurrentRelease($strict = true) + { + if ($p = $this->getPackageType()) { + if ($strict) { + if ($p == 'extsrc' || $p == 'zendextsrc') { + $a = null; + return $a; + } + } + if ($p != 'bundle') { + $p .= 'release'; + } + if (isset($this->_packageInfo[$p][0])) { + return $this->_packageInfo[$p][count($this->_packageInfo[$p]) - 1]; + } else { + return $this->_packageInfo[$p]; + } + } else { + $a = null; + return $a; + } + } + + /** + * Add a file to the current release that should be installed under a different name + * @param string path to file + * @param string name the file should be installed as + */ + function addInstallAs($path, $as) + { + $r = &$this->_getCurrentRelease(); + if ($r === null) { + return false; + } + $this->_isValid = 0; + $r = $this->_mergeTag($r, array('attribs' => array('name' => $path, 'as' => $as)), + array( + 'filelist' => array(), + 'install' => array('ignore') + )); + } + + /** + * Add a file to the current release that should be ignored + * @param string path to file + * @return bool success of operation + */ + function addIgnore($path) + { + $r = &$this->_getCurrentRelease(); + if ($r === null) { + return false; + } + $this->_isValid = 0; + $r = $this->_mergeTag($r, array('attribs' => array('name' => $path)), + array( + 'filelist' => array(), + 'ignore' => array() + )); + } + + /** + * Add an extension binary package for this extension source code release + * + * Note that the package must be from the same channel as the extension source package + * @param string + */ + function addBinarypackage($package) + { + if ($this->getPackageType() != 'extsrc' && $this->getPackageType() != 'zendextsrc') { + return false; + } + $r = &$this->_getCurrentRelease(false); + if ($r === null) { + return false; + } + $this->_isValid = 0; + $r = $this->_mergeTag($r, $package, + array( + 'binarypackage' => array('filelist'), + )); + } + + /** + * Add a configureoption to an extension source package + * @param string + * @param string + * @param string + */ + function addConfigureOption($name, $prompt, $default = null) + { + if ($this->getPackageType() != 'extsrc' && $this->getPackageType() != 'zendextsrc') { + return false; + } + $r = &$this->_getCurrentRelease(false); + if ($r === null) { + return false; + } + $opt = array('attribs' => array('name' => $name, 'prompt' => $prompt)); + if ($default !== null) { + $opt['attribs']['default'] = $default; + } + $this->_isValid = 0; + $r = $this->_mergeTag($r, $opt, + array( + 'configureoption' => array('binarypackage', 'filelist'), + )); + } + + /** + * Set an installation condition based on php version for the current release set + * @param string minimum version + * @param string maximum version + * @param false|array incompatible versions of PHP + */ + function setPhpInstallCondition($min, $max, $exclude = false) + { + $r = &$this->_getCurrentRelease(); + if ($r === null) { + return false; + } + $this->_isValid = 0; + if (isset($r['installconditions']['php'])) { + unset($r['installconditions']['php']); + } + $dep = array('min' => $min, 'max' => $max); + if ($exclude) { + if (is_array($exclude) && count($exclude) == 1) { + $exclude = $exclude[0]; + } + $dep['exclude'] = $exclude; + } + if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') { + $r = $this->_mergeTag($r, $dep, + array( + 'installconditions' => array('configureoption', 'binarypackage', + 'filelist'), + 'php' => array('extension', 'os', 'arch') + )); + } else { + $r = $this->_mergeTag($r, $dep, + array( + 'installconditions' => array('filelist'), + 'php' => array('extension', 'os', 'arch') + )); + } + } + + /** + * @param optional|required optional, required + * @param string extension name + * @param string minimum version + * @param string maximum version + * @param string recommended version + * @param array incompatible versions + */ + function addExtensionInstallCondition($name, $min = false, $max = false, $recommended = false, + $exclude = false) + { + $r = &$this->_getCurrentRelease(); + if ($r === null) { + return false; + } + $this->_isValid = 0; + $dep = $this->_constructDep($name, false, false, $min, $max, $recommended, $exclude); + if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') { + $r = $this->_mergeTag($r, $dep, + array( + 'installconditions' => array('configureoption', 'binarypackage', + 'filelist'), + 'extension' => array('os', 'arch') + )); + } else { + $r = $this->_mergeTag($r, $dep, + array( + 'installconditions' => array('filelist'), + 'extension' => array('os', 'arch') + )); + } + } + + /** + * Set an installation condition based on operating system for the current release set + * @param string OS name + * @param bool whether this OS is incompatible with the current release + */ + function setOsInstallCondition($name, $conflicts = false) + { + $r = &$this->_getCurrentRelease(); + if ($r === null) { + return false; + } + $this->_isValid = 0; + if (isset($r['installconditions']['os'])) { + unset($r['installconditions']['os']); + } + $dep = array('name' => $name); + if ($conflicts) { + $dep['conflicts'] = ''; + } + if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') { + $r = $this->_mergeTag($r, $dep, + array( + 'installconditions' => array('configureoption', 'binarypackage', + 'filelist'), + 'os' => array('arch') + )); + } else { + $r = $this->_mergeTag($r, $dep, + array( + 'installconditions' => array('filelist'), + 'os' => array('arch') + )); + } + } + + /** + * Set an installation condition based on architecture for the current release set + * @param string architecture pattern + * @param bool whether this arch is incompatible with the current release + */ + function setArchInstallCondition($pattern, $conflicts = false) + { + $r = &$this->_getCurrentRelease(); + if ($r === null) { + return false; + } + $this->_isValid = 0; + if (isset($r['installconditions']['arch'])) { + unset($r['installconditions']['arch']); + } + $dep = array('pattern' => $pattern); + if ($conflicts) { + $dep['conflicts'] = ''; + } + if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') { + $r = $this->_mergeTag($r, $dep, + array( + 'installconditions' => array('configureoption', 'binarypackage', + 'filelist'), + 'arch' => array() + )); + } else { + $r = $this->_mergeTag($r, $dep, + array( + 'installconditions' => array('filelist'), + 'arch' => array() + )); + } + } + + /** + * For extension binary releases, this is used to specify either the + * static URI to a source package, or the package name and channel of the extsrc/zendextsrc + * package it is based on. + * @param string Package name, or full URI to source package (extsrc/zendextsrc type) + */ + function setSourcePackage($packageOrUri) + { + $this->_isValid = 0; + if (isset($this->_packageInfo['channel'])) { + $this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('phprelease', + 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', + 'bundle', 'changelog'), + $packageOrUri, 'srcpackage'); + } else { + $this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('phprelease', + 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', + 'bundle', 'changelog'), $packageOrUri, 'srcuri'); + } + } + + /** + * Generate a valid change log entry from the current package.xml + * @param string|false + */ + function generateChangeLogEntry($notes = false) + { + return array( + 'version' => + array( + 'release' => $this->getVersion('release'), + 'api' => $this->getVersion('api'), + ), + 'stability' => + $this->getStability(), + 'date' => $this->getDate(), + 'license' => $this->getLicense(true), + 'notes' => $notes ? $notes : $this->getNotes() + ); + } + + /** + * @param string release version to set change log notes for + * @param array output of {@link generateChangeLogEntry()} + */ + function setChangelogEntry($releaseversion, $contents) + { + if (!isset($this->_packageInfo['changelog'])) { + $this->_packageInfo['changelog']['release'] = $contents; + return; + } + if (!isset($this->_packageInfo['changelog']['release'][0])) { + if ($this->_packageInfo['changelog']['release']['version']['release'] == $releaseversion) { + $this->_packageInfo['changelog']['release'] = array( + $this->_packageInfo['changelog']['release']); + } else { + $this->_packageInfo['changelog']['release'] = array( + $this->_packageInfo['changelog']['release']); + return $this->_packageInfo['changelog']['release'][] = $contents; + } + } + foreach($this->_packageInfo['changelog']['release'] as $index => $changelog) { + if (isset($changelog['version']) && + strnatcasecmp($changelog['version']['release'], $releaseversion) == 0) { + $curlog = $index; + } + } + if (isset($curlog)) { + $this->_packageInfo['changelog']['release'][$curlog] = $contents; + } else { + $this->_packageInfo['changelog']['release'][] = $contents; + } + } + + /** + * Remove the changelog entirely + */ + function clearChangeLog() + { + unset($this->_packageInfo['changelog']); + } +} +?> \ No newline at end of file diff --git a/src/lib/pear/PEAR/PEAR/Packager.php b/src/lib/pear/PEAR/PEAR/Packager.php new file mode 100644 index 0000000..bae9282 --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Packager.php @@ -0,0 +1,199 @@ + + * @author Tomas V. V. Cox + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: Packager.php,v 1.71 2008/01/03 20:26:36 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 0.1 + */ + +/** + * base class + */ +require_once 'PEAR/Common.php'; +require_once 'PEAR/PackageFile.php'; +require_once 'System.php'; + +/** + * Administration class used to make a PEAR release tarball. + * + * @category pear + * @package PEAR + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 0.1 + */ +class PEAR_Packager extends PEAR_Common +{ + /** + * @var PEAR_Registry + */ + var $_registry; + // {{{ package() + + function package($pkgfile = null, $compress = true, $pkg2 = null) + { + // {{{ validate supplied package.xml file + if (empty($pkgfile)) { + $pkgfile = 'package.xml'; + } + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + $pkg = &new PEAR_PackageFile($this->config, $this->debug); + $pf = &$pkg->fromPackageFile($pkgfile, PEAR_VALIDATE_NORMAL); + $main = &$pf; + PEAR::staticPopErrorHandling(); + if (PEAR::isError($pf)) { + if (is_array($pf->getUserInfo())) { + foreach ($pf->getUserInfo() as $error) { + $this->log(0, 'Error: ' . $error['message']); + } + } + $this->log(0, $pf->getMessage()); + return $this->raiseError("Cannot package, errors in package file"); + } else { + foreach ($pf->getValidationWarnings() as $warning) { + $this->log(1, 'Warning: ' . $warning['message']); + } + } + + // }}} + if ($pkg2) { + $this->log(0, 'Attempting to process the second package file'); + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + $pf2 = &$pkg->fromPackageFile($pkg2, PEAR_VALIDATE_NORMAL); + PEAR::staticPopErrorHandling(); + if (PEAR::isError($pf2)) { + if (is_array($pf2->getUserInfo())) { + foreach ($pf2->getUserInfo() as $error) { + $this->log(0, 'Error: ' . $error['message']); + } + } + $this->log(0, $pf2->getMessage()); + return $this->raiseError("Cannot package, errors in second package file"); + } else { + foreach ($pf2->getValidationWarnings() as $warning) { + $this->log(1, 'Warning: ' . $warning['message']); + } + } + if ($pf2->getPackagexmlVersion() == '2.0' || + $pf2->getPackagexmlVersion() == '2.1') { + $main = &$pf2; + $other = &$pf; + } else { + $main = &$pf; + $other = &$pf2; + } + if ($main->getPackagexmlVersion() != '2.0' && + $main->getPackagexmlVersion() != '2.1') { + return PEAR::raiseError('Error: cannot package two package.xml version 1.0, can ' . + 'only package together a package.xml 1.0 and package.xml 2.0'); + } + if ($other->getPackagexmlVersion() != '1.0') { + return PEAR::raiseError('Error: cannot package two package.xml version 2.0, can ' . + 'only package together a package.xml 1.0 and package.xml 2.0'); + } + } + $main->setLogger($this); + if (!$main->validate(PEAR_VALIDATE_PACKAGING)) { + foreach ($main->getValidationWarnings() as $warning) { + $this->log(0, 'Error: ' . $warning['message']); + } + return $this->raiseError("Cannot package, errors in package"); + } else { + foreach ($main->getValidationWarnings() as $warning) { + $this->log(1, 'Warning: ' . $warning['message']); + } + } + if ($pkg2) { + $other->setLogger($this); + $a = false; + if (!$other->validate(PEAR_VALIDATE_NORMAL) || $a = !$main->isEquivalent($other)) { + foreach ($other->getValidationWarnings() as $warning) { + $this->log(0, 'Error: ' . $warning['message']); + } + foreach ($main->getValidationWarnings() as $warning) { + $this->log(0, 'Error: ' . $warning['message']); + } + if ($a) { + return $this->raiseError('The two package.xml files are not equivalent!'); + } + return $this->raiseError("Cannot package, errors in package"); + } else { + foreach ($other->getValidationWarnings() as $warning) { + $this->log(1, 'Warning: ' . $warning['message']); + } + } + $gen = &$main->getDefaultGenerator(); + $tgzfile = $gen->toTgz2($this, $other, $compress); + if (PEAR::isError($tgzfile)) { + return $tgzfile; + } + $dest_package = basename($tgzfile); + $pkgdir = dirname($pkgfile); + + // TAR the Package ------------------------------------------- + $this->log(1, "Package $dest_package done"); + if (file_exists("$pkgdir/CVS/Root")) { + $cvsversion = preg_replace('/[^a-z0-9]/i', '_', $pf->getVersion()); + $cvstag = "RELEASE_$cvsversion"; + $this->log(1, 'Tag the released code with "pear cvstag ' . + $main->getPackageFile() . '"'); + $this->log(1, "(or set the CVS tag $cvstag by hand)"); + } + } else { // this branch is executed for single packagefile packaging + $gen = &$pf->getDefaultGenerator(); + $tgzfile = $gen->toTgz($this, $compress); + if (PEAR::isError($tgzfile)) { + $this->log(0, $tgzfile->getMessage()); + return $this->raiseError("Cannot package, errors in package"); + } + $dest_package = basename($tgzfile); + $pkgdir = dirname($pkgfile); + + // TAR the Package ------------------------------------------- + $this->log(1, "Package $dest_package done"); + if (file_exists("$pkgdir/CVS/Root")) { + $cvsversion = preg_replace('/[^a-z0-9]/i', '_', $pf->getVersion()); + $cvstag = "RELEASE_$cvsversion"; + $this->log(1, "Tag the released code with `pear cvstag $pkgfile'"); + $this->log(1, "(or set the CVS tag $cvstag by hand)"); + } + } + return $dest_package; + } + + // }}} +} + +// {{{ md5_file() utility function +if (!function_exists('md5_file')) { + function md5_file($file) { + if (!$fd = @fopen($file, 'r')) { + return false; + } + fclose($fd); + $md5 = md5(file_get_contents($file)); + return $md5; + } +} +// }}} + +?> diff --git a/src/lib/pear/PEAR/PEAR/REST.php b/src/lib/pear/PEAR/PEAR/REST.php new file mode 100644 index 0000000..143654e --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/REST.php @@ -0,0 +1,397 @@ + + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: REST.php,v 1.31 2008/05/13 18:03:36 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 1.4.0a1 + */ + +/** + * For downloading xml files + */ +require_once 'PEAR.php'; +require_once 'PEAR/XMLParser.php'; + +/** + * Intelligently retrieve data, following hyperlinks if necessary, and re-directing + * as well + * @category pear + * @package PEAR + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 1.4.0a1 + */ +class PEAR_REST +{ + var $config; + var $_options; + function PEAR_REST(&$config, $options = array()) + { + $this->config = &$config; + $this->_options = $options; + } + + /** + * Retrieve REST data, but always retrieve the local cache if it is available. + * + * This is useful for elements that should never change, such as information on a particular + * release + * @param string full URL to this resource + * @param array|false contents of the accept-encoding header + * @param boolean if true, xml will be returned as a string, otherwise, xml will be + * parsed using PEAR_XMLParser + * @return string|array + */ + function retrieveCacheFirst($url, $accept = false, $forcestring = false, $channel = false) + { + $cachefile = $this->config->get('cache_dir') . DIRECTORY_SEPARATOR . + md5($url) . 'rest.cachefile'; + if (file_exists($cachefile)) { + return unserialize(implode('', file($cachefile))); + } + return $this->retrieveData($url, $accept, $forcestring, $channel); + } + + /** + * Retrieve a remote REST resource + * @param string full URL to this resource + * @param array|false contents of the accept-encoding header + * @param boolean if true, xml will be returned as a string, otherwise, xml will be + * parsed using PEAR_XMLParser + * @return string|array + */ + function retrieveData($url, $accept = false, $forcestring = false, $channel = false) + { + $cacheId = $this->getCacheId($url); + if ($ret = $this->useLocalCache($url, $cacheId)) { + return $ret; + } + if (!isset($this->_options['offline'])) { + $trieddownload = true; + $file = $this->downloadHttp($url, $cacheId ? $cacheId['lastChange'] : false, $accept, $channel); + } else { + $trieddownload = false; + $file = false; + } + if (PEAR::isError($file)) { + if ($file->getCode() == -9276) { + $trieddownload = false; + $file = false; // use local copy if available on socket connect error + } else { + return $file; + } + } + if (!$file) { + $ret = $this->getCache($url); + if (!PEAR::isError($ret) && $trieddownload) { + // reset the age of the cache if the server says it was unmodified + $this->saveCache($url, $ret, null, true, $cacheId); + } + return $ret; + } + if (is_array($file)) { + $headers = $file[2]; + $lastmodified = $file[1]; + $content = $file[0]; + } else { + $content = $file; + $lastmodified = false; + $headers = array(); + } + if ($forcestring) { + $this->saveCache($url, $content, $lastmodified, false, $cacheId); + return $content; + } + if (isset($headers['content-type'])) { + switch ($headers['content-type']) { + case 'text/xml' : + case 'application/xml' : + $parser = new PEAR_XMLParser; + PEAR::pushErrorHandling(PEAR_ERROR_RETURN); + $err = $parser->parse($content); + PEAR::popErrorHandling(); + if (PEAR::isError($err)) { + return PEAR::raiseError('Invalid xml downloaded from "' . $url . '": ' . + $err->getMessage()); + } + $content = $parser->getData(); + case 'text/html' : + default : + // use it as a string + } + } else { + // assume XML + $parser = new PEAR_XMLParser; + $parser->parse($content); + $content = $parser->getData(); + } + $this->saveCache($url, $content, $lastmodified, false, $cacheId); + return $content; + } + + function useLocalCache($url, $cacheid = null) + { + if ($cacheid === null) { + $cacheidfile = $this->config->get('cache_dir') . DIRECTORY_SEPARATOR . + md5($url) . 'rest.cacheid'; + if (file_exists($cacheidfile)) { + $cacheid = unserialize(implode('', file($cacheidfile))); + } else { + return false; + } + } + $cachettl = $this->config->get('cache_ttl'); + // If cache is newer than $cachettl seconds, we use the cache! + if (time() - $cacheid['age'] < $cachettl) { + return $this->getCache($url); + } + return false; + } + + function getCacheId($url) + { + $cacheidfile = $this->config->get('cache_dir') . DIRECTORY_SEPARATOR . + md5($url) . 'rest.cacheid'; + if (file_exists($cacheidfile)) { + $ret = unserialize(implode('', file($cacheidfile))); + return $ret; + } else { + return false; + } + } + + function getCache($url) + { + $cachefile = $this->config->get('cache_dir') . DIRECTORY_SEPARATOR . + md5($url) . 'rest.cachefile'; + if (file_exists($cachefile)) { + return unserialize(implode('', file($cachefile))); + } else { + return PEAR::raiseError('No cached content available for "' . $url . '"'); + } + } + + /** + * @param string full URL to REST resource + * @param string original contents of the REST resource + * @param array HTTP Last-Modified and ETag headers + * @param bool if true, then the cache id file should be regenerated to + * trigger a new time-to-live value + */ + function saveCache($url, $contents, $lastmodified, $nochange = false, $cacheid = null) + { + $cacheidfile = $this->config->get('cache_dir') . DIRECTORY_SEPARATOR . + md5($url) . 'rest.cacheid'; + $cachefile = $this->config->get('cache_dir') . DIRECTORY_SEPARATOR . + md5($url) . 'rest.cachefile'; + if ($cacheid === null && $nochange) { + $cacheid = unserialize(implode('', file($cacheidfile))); + } + + $fp = @fopen($cacheidfile, 'wb'); + if (!$fp) { + $cache_dir = $this->config->get('cache_dir'); + if (!is_dir($cache_dir)) { + System::mkdir(array('-p', $cache_dir)); + $fp = @fopen($cacheidfile, 'wb'); + if (!$fp) { + return false; + } + } else { + return false; + } + } + + if ($nochange) { + fwrite($fp, serialize(array( + 'age' => time(), + 'lastChange' => $cacheid['lastChange'], + ))); + fclose($fp); + return true; + } else { + fwrite($fp, serialize(array( + 'age' => time(), + 'lastChange' => $lastmodified, + ))); + } + fclose($fp); + $fp = @fopen($cachefile, 'wb'); + if (!$fp) { + if (file_exists($cacheidfile)) { + @unlink($cacheidfile); + } + return false; + } + fwrite($fp, serialize($contents)); + fclose($fp); + return true; + } + + /** + * Efficiently Download a file through HTTP. Returns downloaded file as a string in-memory + * This is best used for small files + * + * If an HTTP proxy has been configured (http_proxy PEAR_Config + * setting), the proxy will be used. + * + * @param string $url the URL to download + * @param string $save_dir directory to save file in + * @param false|string|array $lastmodified header values to check against for caching + * use false to return the header values from this download + * @param false|array $accept Accept headers to send + * @return string|array Returns the contents of the downloaded file or a PEAR + * error on failure. If the error is caused by + * socket-related errors, the error object will + * have the fsockopen error code available through + * getCode(). If caching is requested, then return the header + * values. + * + * @access public + */ + function downloadHttp($url, $lastmodified = null, $accept = false, $channel = false) + { + $info = parse_url($url); + if (!isset($info['scheme']) || !in_array($info['scheme'], array('http', 'https'))) { + return PEAR::raiseError('Cannot download non-http URL "' . $url . '"'); + } + if (!isset($info['host'])) { + return PEAR::raiseError('Cannot download from non-URL "' . $url . '"'); + } else { + $host = $info['host']; + if (!array_key_exists('port', $info)) { + $info['port'] = null; + } + if (!array_key_exists('path', $info)) { + $info['path'] = null; + } + $port = $info['port']; + $path = $info['path']; + } + $proxy_host = $proxy_port = $proxy_user = $proxy_pass = ''; + if ($this->config->get('http_proxy')&& + $proxy = parse_url($this->config->get('http_proxy'))) { + $proxy_host = isset($proxy['host']) ? $proxy['host'] : null; + if (isset($proxy['scheme']) && $proxy['scheme'] == 'https') { + $proxy_host = 'ssl://' . $proxy_host; + } + $proxy_port = isset($proxy['port']) ? $proxy['port'] : 8080; + $proxy_user = isset($proxy['user']) ? urldecode($proxy['user']) : null; + $proxy_pass = isset($proxy['pass']) ? urldecode($proxy['pass']) : null; + } + if (empty($port)) { + if (isset($info['scheme']) && $info['scheme'] == 'https') { + $port = 443; + } else { + $port = 80; + } + } + If (isset($proxy['host'])) { + $request = "GET $url HTTP/1.1\r\n"; + } else { + $request = "GET $path HTTP/1.1\r\n"; + } + $request .= "Host: $host:$port\r\n"; + + $ifmodifiedsince = ''; + if (is_array($lastmodified)) { + if (isset($lastmodified['Last-Modified'])) { + $ifmodifiedsince = 'If-Modified-Since: ' . $lastmodified['Last-Modified'] . "\r\n"; + } + if (isset($lastmodified['ETag'])) { + $ifmodifiedsince .= "If-None-Match: $lastmodified[ETag]\r\n"; + } + } else { + $ifmodifiedsince = ($lastmodified ? "If-Modified-Since: $lastmodified\r\n" : ''); + } + $request .= $ifmodifiedsince . + "User-Agent: PEAR/1.7.2/PHP/" . PHP_VERSION . "\r\n"; + $username = $this->config->get('username', null, $channel); + $password = $this->config->get('password', null, $channel); + if ($username && $password) { + $tmp = base64_encode("$username:$password"); + $request .= "Authorization: Basic $tmp\r\n"; + } + if ($proxy_host != '' && $proxy_user != '') { + $request .= 'Proxy-Authorization: Basic ' . + base64_encode($proxy_user . ':' . $proxy_pass) . "\r\n"; + } + if ($accept) { + $request .= 'Accept: ' . implode(', ', $accept) . "\r\n"; + } + $request .= "Accept-Encoding:\r\n"; + $request .= "Connection: close\r\n"; + $request .= "\r\n"; + if ($proxy_host != '') { + $fp = @fsockopen($proxy_host, $proxy_port, $errno, $errstr, 15); + if (!$fp) { + return PEAR::raiseError("Connection to `$proxy_host:$proxy_port' failed: $errstr", + -9276); + } + } else { + if (isset($info['scheme']) && $info['scheme'] == 'https') { + $host = 'ssl://' . $host; + } + $fp = @fsockopen($host, $port, $errno, $errstr); + if (!$fp) { + return PEAR::raiseError("Connection to `$host:$port' failed: $errstr", $errno); + } + } + fwrite($fp, $request); + $headers = array(); + while (trim($line = fgets($fp, 1024))) { + if (preg_match('/^([^:]+):\s+(.*)\s*\\z/', $line, $matches)) { + $headers[strtolower($matches[1])] = trim($matches[2]); + } elseif (preg_match('|^HTTP/1.[01] ([0-9]{3}) |', $line, $matches)) { + if ($matches[1] == 304 && ($lastmodified || ($lastmodified === false))) { + return false; + } + if ($matches[1] != 200) { + return PEAR::raiseError("File http://$host:$port$path not valid (received: $line)", (int) $matches[1]); + } + } + } + if (isset($headers['content-length'])) { + $length = $headers['content-length']; + } else { + $length = -1; + } + $data = ''; + while ($chunk = @fread($fp, 8192)) { + $data .= $chunk; + } + fclose($fp); + if ($lastmodified === false || $lastmodified) { + if (isset($headers['etag'])) { + $lastmodified = array('ETag' => $headers['etag']); + } + if (isset($headers['last-modified'])) { + if (is_array($lastmodified)) { + $lastmodified['Last-Modified'] = $headers['last-modified']; + } else { + $lastmodified = $headers['last-modified']; + } + } + return array($data, $lastmodified, $headers); + } + return $data; + } +} +?> diff --git a/src/lib/pear/PEAR/PEAR/REST/10.php b/src/lib/pear/PEAR/PEAR/REST/10.php new file mode 100644 index 0000000..9359031 --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/REST/10.php @@ -0,0 +1,797 @@ + + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: 10.php,v 1.53 2008/04/11 01:16:40 dufuz Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 1.4.0a12 + */ + +/** + * For downloading REST xml/txt files + */ +require_once 'PEAR/REST.php'; + +/** + * Implement REST 1.0 + * + * @category pear + * @package PEAR + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 1.4.0a12 + */ +class PEAR_REST_10 +{ + /** + * @var PEAR_REST + */ + var $_rest; + function PEAR_REST_10($config, $options = array()) + { + $this->_rest = &new PEAR_REST($config, $options); + } + + /** + * Retrieve information about a remote package to be downloaded from a REST server + * + * @param string $base The uri to prepend to all REST calls + * @param array $packageinfo an array of format: + *
    +     *  array(
    +     *   'package' => 'packagename',
    +     *   'channel' => 'channelname',
    +     *  ['state' => 'alpha' (or valid state),]
    +     *  -or-
    +     *  ['version' => '1.whatever']
    +     * 
    + * @param string $prefstate Current preferred_state config variable value + * @param bool $installed the installed version of this package to compare against + * @return array|false|PEAR_Error see {@link _returnDownloadURL()} + */ + function getDownloadURL($base, $packageinfo, $prefstate, $installed, $channel = false) + { + $channel = $packageinfo['channel']; + $package = $packageinfo['package']; + $states = $this->betterStates($prefstate, true); + if (!$states) { + return PEAR::raiseError('"' . $prefstate . '" is not a valid state'); + } + $state = isset($packageinfo['state']) ? $packageinfo['state'] : null; + $version = isset($packageinfo['version']) ? $packageinfo['version'] : null; + $info = $this->_rest->retrieveData($base . 'r/' . strtolower($package) . '/allreleases.xml', false, false, $channel); + if (PEAR::isError($info)) { + return PEAR::raiseError('No releases available for package "' . + $channel . '/' . $package . '"'); + } + if (!isset($info['r'])) { + return false; + } + $release = $found = false; + if (!is_array($info['r']) || !isset($info['r'][0])) { + $info['r'] = array($info['r']); + } + foreach ($info['r'] as $release) { + if (!isset($this->_rest->_options['force']) && ($installed && + version_compare($release['v'], $installed, '<'))) { + continue; + } + if (isset($state)) { + // try our preferred state first + if ($release['s'] == $state) { + $found = true; + break; + } + // see if there is something newer and more stable + // bug #7221 + if (in_array($release['s'], $this->betterStates($state), true)) { + $found = true; + break; + } + } elseif (isset($version)) { + if ($release['v'] == $version) { + $found = true; + break; + } + } else { + if (in_array($release['s'], $states)) { + $found = true; + break; + } + } + } + return $this->_returnDownloadURL($base, $package, $release, $info, $found, false, $channel); + } + + function getDepDownloadURL($base, $xsdversion, $dependency, $deppackage, + $prefstate = 'stable', $installed = false, $channel = false) + { + $channel = $dependency['channel']; + $package = $dependency['name']; + $states = $this->betterStates($prefstate, true); + if (!$states) { + return PEAR::raiseError('"' . $prefstate . '" is not a valid state'); + } + $state = isset($dependency['state']) ? $dependency['state'] : null; + $version = isset($dependency['version']) ? $dependency['version'] : null; + $info = $this->_rest->retrieveData($base . 'r/' . strtolower($package) . '/allreleases.xml', false, false, $channel); + if (PEAR::isError($info)) { + return PEAR::raiseError('Package "' . $deppackage['channel'] . '/' . $deppackage['package'] + . '" dependency "' . $channel . '/' . $package . '" has no releases'); + } + if (!is_array($info) || !isset($info['r'])) { + return false; + } + $exclude = array(); + $min = $max = $recommended = false; + if ($xsdversion == '1.0') { + switch ($dependency['rel']) { + case 'ge' : + $min = $dependency['version']; + break; + case 'gt' : + $min = $dependency['version']; + $exclude = array($dependency['version']); + break; + case 'eq' : + $recommended = $dependency['version']; + break; + case 'lt' : + $max = $dependency['version']; + $exclude = array($dependency['version']); + break; + case 'le' : + $max = $dependency['version']; + break; + case 'ne' : + $exclude = array($dependency['version']); + break; + } + } else { + $min = isset($dependency['min']) ? $dependency['min'] : false; + $max = isset($dependency['max']) ? $dependency['max'] : false; + $recommended = isset($dependency['recommended']) ? + $dependency['recommended'] : false; + if (isset($dependency['exclude'])) { + if (!isset($dependency['exclude'][0])) { + $exclude = array($dependency['exclude']); + } + } + } + $release = $found = false; + if (!is_array($info['r']) || !isset($info['r'][0])) { + $info['r'] = array($info['r']); + } + foreach ($info['r'] as $release) { + if (!isset($this->_rest->_options['force']) && ($installed && + version_compare($release['v'], $installed, '<'))) { + continue; + } + if (in_array($release['v'], $exclude)) { // skip excluded versions + continue; + } + // allow newer releases to say "I'm OK with the dependent package" + if ($xsdversion == '2.0' && isset($release['co'])) { + if (!is_array($release['co']) || !isset($release['co'][0])) { + $release['co'] = array($release['co']); + } + foreach ($release['co'] as $entry) { + if (isset($entry['x']) && !is_array($entry['x'])) { + $entry['x'] = array($entry['x']); + } elseif (!isset($entry['x'])) { + $entry['x'] = array(); + } + if ($entry['c'] == $deppackage['channel'] && + strtolower($entry['p']) == strtolower($deppackage['package']) && + version_compare($deppackage['version'], $entry['min'], '>=') && + version_compare($deppackage['version'], $entry['max'], '<=') && + !in_array($release['v'], $entry['x'])) { + $recommended = $release['v']; + break; + } + } + } + if ($recommended) { + if ($release['v'] != $recommended) { // if we want a specific + // version, then skip all others + continue; + } else { + if (!in_array($release['s'], $states)) { + // the stability is too low, but we must return the + // recommended version if possible + return $this->_returnDownloadURL($base, $package, $release, $info, true, false, $channel); + } + } + } + if ($min && version_compare($release['v'], $min, 'lt')) { // skip too old versions + continue; + } + if ($max && version_compare($release['v'], $max, 'gt')) { // skip too new versions + continue; + } + if ($installed && version_compare($release['v'], $installed, '<')) { + continue; + } + if (in_array($release['s'], $states)) { // if in the preferred state... + $found = true; // ... then use it + break; + } + } + return $this->_returnDownloadURL($base, $package, $release, $info, $found, false, $channel); + } + + /** + * Take raw data and return the array needed for processing a download URL + * + * @param string $base REST base uri + * @param string $package Package name + * @param array $release an array of format array('v' => version, 's' => state) + * describing the release to download + * @param array $info list of all releases as defined by allreleases.xml + * @param bool|null $found determines whether the release was found or this is the next + * best alternative. If null, then versions were skipped because + * of PHP dependency + * @return array|PEAR_Error + * @access private + */ + function _returnDownloadURL($base, $package, $release, $info, $found, $phpversion = false, $channel = false) + { + if (!$found) { + $release = $info['r'][0]; + } + $pinfo = $this->_rest->retrieveCacheFirst($base . 'p/' . strtolower($package) . '/' . + 'info.xml', false, false, $channel); + if (PEAR::isError($pinfo)) { + return PEAR::raiseError('Package "' . $package . + '" does not have REST info xml available'); + } + $releaseinfo = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package) . '/' . + $release['v'] . '.xml', false, false, $channel); + if (PEAR::isError($releaseinfo)) { + return PEAR::raiseError('Package "' . $package . '" Version "' . $release['v'] . + '" does not have REST xml available'); + } + $packagexml = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package) . '/' . + 'deps.' . $release['v'] . '.txt', false, true, $channel); + if (PEAR::isError($packagexml)) { + return PEAR::raiseError('Package "' . $package . '" Version "' . $release['v'] . + '" does not have REST dependency information available'); + } + $packagexml = unserialize($packagexml); + if (!$packagexml) { + $packagexml = array(); + } + $allinfo = $this->_rest->retrieveData($base . 'r/' . strtolower($package) . + '/allreleases.xml', false, false, $channel); + if (!is_array($allinfo['r']) || !isset($allinfo['r'][0])) { + $allinfo['r'] = array($allinfo['r']); + } + $compatible = false; + foreach ($allinfo['r'] as $release) { + if ($release['v'] != $releaseinfo['v']) { + continue; + } + if (!isset($release['co'])) { + break; + } + $compatible = array(); + if (!is_array($release['co']) || !isset($release['co'][0])) { + $release['co'] = array($release['co']); + } + foreach ($release['co'] as $entry) { + $comp = array(); + $comp['name'] = $entry['p']; + $comp['channel'] = $entry['c']; + $comp['min'] = $entry['min']; + $comp['max'] = $entry['max']; + if (isset($entry['x']) && !is_array($entry['x'])) { + $comp['exclude'] = $entry['x']; + } + $compatible[] = $comp; + } + if (count($compatible) == 1) { + $compatible = $compatible[0]; + } + break; + } + if (isset($pinfo['dc']) && isset($pinfo['dp'])) { + if (is_array($pinfo['dp'])) { + $deprecated = array('channel' => (string) $pinfo['dc'], + 'package' => trim($pinfo['dp']['_content'])); + } else { + $deprecated = array('channel' => (string) $pinfo['dc'], + 'package' => trim($pinfo['dp'])); + } + } else { + $deprecated = false; + } + if ($found) { + return + array('version' => $releaseinfo['v'], + 'info' => $packagexml, + 'package' => $releaseinfo['p']['_content'], + 'stability' => $releaseinfo['st'], + 'url' => $releaseinfo['g'], + 'compatible' => $compatible, + 'deprecated' => $deprecated, + ); + } else { + return + array('version' => $releaseinfo['v'], + 'package' => $releaseinfo['p']['_content'], + 'stability' => $releaseinfo['st'], + 'info' => $packagexml, + 'compatible' => $compatible, + 'deprecated' => $deprecated, + 'php' => $phpversion + ); + } + } + + function listPackages($base, $channel = false) + { + $packagelist = $this->_rest->retrieveData($base . 'p/packages.xml', false, false, $channel); + if (PEAR::isError($packagelist)) { + return $packagelist; + } + if (!is_array($packagelist) || !isset($packagelist['p'])) { + return array(); + } + if (!is_array($packagelist['p'])) { + $packagelist['p'] = array($packagelist['p']); + } + return $packagelist['p']; + } + + /** + * List all categories of a REST server + * + * @param string $base base URL of the server + * @return array of categorynames + */ + function listCategories($base, $channel = false) + { + $categories = array(); + + // c/categories.xml does not exist; + // check for every package its category manually + // This is SLOOOWWWW : /// + $packagelist = $this->_rest->retrieveData($base . 'p/packages.xml', false, false, $channel); + if (PEAR::isError($packagelist)) { + return $packagelist; + } + if (!is_array($packagelist) || !isset($packagelist['p'])) { + $ret = array(); + return $ret; + } + if (!is_array($packagelist['p'])) { + $packagelist['p'] = array($packagelist['p']); + } + + PEAR::pushErrorHandling(PEAR_ERROR_RETURN); + foreach ($packagelist['p'] as $package) { + $inf = $this->_rest->retrieveData($base . 'p/' . strtolower($package) . '/info.xml', false, false, $channel); + if (PEAR::isError($inf)) { + PEAR::popErrorHandling(); + return $inf; + } + $cat = $inf['ca']['_content']; + if (!isset($categories[$cat])) { + $categories[$cat] = $inf['ca']; + } + } + return array_values($categories); + } + + /** + * List a category of a REST server + * + * @param string $base base URL of the server + * @param string $category name of the category + * @param boolean $info also download full package info + * @return array of packagenames + */ + function listCategory($base, $category, $info = false, $channel = false) + { + // gives '404 Not Found' error when category doesn't exist + $packagelist = $this->_rest->retrieveData($base.'c/'.urlencode($category).'/packages.xml', false, false, $channel); + if (PEAR::isError($packagelist)) { + return $packagelist; + } + if (!is_array($packagelist) || !isset($packagelist['p'])) { + return array(); + } + if (!is_array($packagelist['p']) || + !isset($packagelist['p'][0])) { // only 1 pkg + $packagelist = array($packagelist['p']); + } else { + $packagelist = $packagelist['p']; + } + + if ($info == true) { + // get individual package info + PEAR::pushErrorHandling(PEAR_ERROR_RETURN); + foreach ($packagelist as $i => $packageitem) { + $url = sprintf('%s'.'r/%s/latest.txt', + $base, + strtolower($packageitem['_content'])); + $version = $this->_rest->retrieveData($url, false, false, $channel); + if (PEAR::isError($version)) { + break; // skipit + } + $url = sprintf('%s'.'r/%s/%s.xml', + $base, + strtolower($packageitem['_content']), + $version); + $info = $this->_rest->retrieveData($url, false, false, $channel); + if (PEAR::isError($info)) { + break; // skipit + } + $packagelist[$i]['info'] = $info; + } + PEAR::popErrorHandling(); + } + + return $packagelist; + } + + + function listAll($base, $dostable, $basic = true, $searchpackage = false, $searchsummary = false, $channel = false) + { + $packagelist = $this->_rest->retrieveData($base . 'p/packages.xml', false, false, $channel); + if (PEAR::isError($packagelist)) { + return $packagelist; + } + if ($this->_rest->config->get('verbose') > 0) { + $ui = &PEAR_Frontend::singleton(); + $ui->log('Retrieving data...0%', false); + } + $ret = array(); + if (!is_array($packagelist) || !isset($packagelist['p'])) { + return $ret; + } + if (!is_array($packagelist['p'])) { + $packagelist['p'] = array($packagelist['p']); + } + + // only search-packagename = quicksearch ! + if ($searchpackage && (!$searchsummary || empty($searchpackage))) { + $newpackagelist = array(); + foreach ($packagelist['p'] as $package) { + if (!empty($searchpackage) && stristr($package, $searchpackage) !== false) { + $newpackagelist[] = $package; + } + } + $packagelist['p'] = $newpackagelist; + } + PEAR::pushErrorHandling(PEAR_ERROR_RETURN); + $next = .1; + foreach ($packagelist['p'] as $progress => $package) { + if ($this->_rest->config->get('verbose') > 0) { + if ($progress / count($packagelist['p']) >= $next) { + if ($next == .5) { + $ui->log('50%', false); + } else { + $ui->log('.', false); + } + $next += .1; + } + } + if ($basic) { // remote-list command + if ($dostable) { + $latest = $this->_rest->retrieveData($base . 'r/' . strtolower($package) . + '/stable.txt', false, false, $channel); + } else { + $latest = $this->_rest->retrieveData($base . 'r/' . strtolower($package) . + '/latest.txt', false, false, $channel); + } + if (PEAR::isError($latest)) { + $latest = false; + } + $info = array('stable' => $latest); + } else { // list-all command + $inf = $this->_rest->retrieveData($base . 'p/' . strtolower($package) . '/info.xml', false, false, $channel); + if (PEAR::isError($inf)) { + PEAR::popErrorHandling(); + return $inf; + } + if ($searchpackage) { + $found = (!empty($searchpackage) && stristr($package, $searchpackage) !== false); + if (!$found && !(isset($searchsummary) && !empty($searchsummary) + && (stristr($inf['s'], $searchsummary) !== false + || stristr($inf['d'], $searchsummary) !== false))) + { + continue; + }; + } + $releases = $this->_rest->retrieveData($base . 'r/' . strtolower($package) . + '/allreleases.xml', false, false, $channel); + if (PEAR::isError($releases)) { + continue; + } + if (!isset($releases['r'][0])) { + $releases['r'] = array($releases['r']); + } + unset($latest); + unset($unstable); + unset($stable); + unset($state); + foreach ($releases['r'] as $release) { + if (!isset($latest)) { + if ($dostable && $release['s'] == 'stable') { + $latest = $release['v']; + $state = 'stable'; + } + if (!$dostable) { + $latest = $release['v']; + $state = $release['s']; + } + } + if (!isset($stable) && $release['s'] == 'stable') { + $stable = $release['v']; + if (!isset($unstable)) { + $unstable = $stable; + } + } + if (!isset($unstable) && $release['s'] != 'stable') { + $latest = $unstable = $release['v']; + $state = $release['s']; + } + if (isset($latest) && !isset($state)) { + $state = $release['s']; + } + if (isset($latest) && isset($stable) && isset($unstable)) { + break; + } + } + $deps = array(); + if (!isset($unstable)) { + $unstable = false; + $state = 'stable'; + if (isset($stable)) { + $latest = $unstable = $stable; + } + } else { + $latest = $unstable; + } + if (!isset($latest)) { + $latest = false; + } + if ($latest) { + $d = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package) . '/deps.' . + $latest . '.txt', false, false, $channel); + if (!PEAR::isError($d)) { + $d = unserialize($d); + if ($d) { + if (isset($d['required'])) { + if (!class_exists('PEAR_PackageFile_v2')) { + require_once 'PEAR/PackageFile/v2.php'; + } + if (!isset($pf)) { + $pf = new PEAR_PackageFile_v2; + } + $pf->setDeps($d); + $tdeps = $pf->getDeps(); + } else { + $tdeps = $d; + } + foreach ($tdeps as $dep) { + if ($dep['type'] !== 'pkg') { + continue; + } + $deps[] = $dep; + } + } + } + } + if (!isset($stable)) { + $stable = '-n/a-'; + } + if (!$searchpackage) { + $info = array('stable' => $latest, 'summary' => $inf['s'], 'description' => + $inf['d'], 'deps' => $deps, 'category' => $inf['ca']['_content'], + 'unstable' => $unstable, 'state' => $state); + } else { + $info = array('stable' => $stable, 'summary' => $inf['s'], 'description' => + $inf['d'], 'deps' => $deps, 'category' => $inf['ca']['_content'], + 'unstable' => $unstable, 'state' => $state); + } + } + $ret[$package] = $info; + } + PEAR::popErrorHandling(); + return $ret; + } + + function listLatestUpgrades($base, $pref_state, $installed, $channel, &$reg) + { + $packagelist = $this->_rest->retrieveData($base . 'p/packages.xml', false, false, $channel); + if (PEAR::isError($packagelist)) { + return $packagelist; + } + $ret = array(); + if (!is_array($packagelist) || !isset($packagelist['p'])) { + return $ret; + } + if (!is_array($packagelist['p'])) { + $packagelist['p'] = array($packagelist['p']); + } + foreach ($packagelist['p'] as $package) { + if (!isset($installed[strtolower($package)])) { + continue; + } + $inst_version = $reg->packageInfo($package, 'version', $channel); + $inst_state = $reg->packageInfo($package, 'release_state', $channel); + PEAR::pushErrorHandling(PEAR_ERROR_RETURN); + $info = $this->_rest->retrieveData($base . 'r/' . strtolower($package) . + '/allreleases.xml', false, false, $channel); + PEAR::popErrorHandling(); + if (PEAR::isError($info)) { + continue; // no remote releases + } + if (!isset($info['r'])) { + continue; + } + $found = false; + $release = false; + if (!is_array($info['r']) || !isset($info['r'][0])) { + $info['r'] = array($info['r']); + } + // $info['r'] is sorted by version number + foreach ($info['r'] as $release) { + if ($inst_version && version_compare($release['v'], $inst_version, '<=')) { + // not newer than the one installed + break; + } + + // new version > installed version + if (!$pref_state) { + // every state is a good state + $found = true; + break; + } else { + $new_state = $release['s']; + // if new state >= installed state: go + if (in_array($new_state, $this->betterStates($inst_state, true))) { + $found = true; + break; + } else { + // only allow to lower the state of package, + // if new state >= preferred state: go + if (in_array($new_state, $this->betterStates($pref_state, true))) { + $found = true; + break; + } + } + } + } + if (!$found) { + continue; + } + $relinfo = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package) . '/' . + $release['v'] . '.xml', false, false, $channel); + if (PEAR::isError($relinfo)) { + return $relinfo; + } + $ret[$package] = array( + 'version' => $release['v'], + 'state' => $release['s'], + 'filesize' => $relinfo['f'], + ); + } + return $ret; + } + + function packageInfo($base, $package, $channel = false) + { + PEAR::pushErrorHandling(PEAR_ERROR_RETURN); + $pinfo = $this->_rest->retrieveData($base . 'p/' . strtolower($package) . '/info.xml', false, false, $channel); + if (PEAR::isError($pinfo)) { + PEAR::popErrorHandling(); + return PEAR::raiseError('Unknown package: "' . $package . '" (Debug: ' . + $pinfo->getMessage() . ')'); + } + $releases = array(); + $allreleases = $this->_rest->retrieveData($base . 'r/' . strtolower($package) . + '/allreleases.xml', false, false, $channel); + if (!PEAR::isError($allreleases)) { + if (!class_exists('PEAR_PackageFile_v2')) { + require_once 'PEAR/PackageFile/v2.php'; + } + if (!is_array($allreleases['r']) || !isset($allreleases['r'][0])) { + $allreleases['r'] = array($allreleases['r']); + } + $pf = new PEAR_PackageFile_v2; + foreach ($allreleases['r'] as $release) { + $ds = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package) . '/deps.' . + $release['v'] . '.txt', false, false, $channel); + if (PEAR::isError($ds)) { + continue; + } + if (!isset($latest)) { + $latest = $release['v']; + } + $pf->setDeps(unserialize($ds)); + $ds = $pf->getDeps(); + $info = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package) + . '/' . $release['v'] . '.xml', false, false, $channel); + if (PEAR::isError($info)) { + continue; + } + $releases[$release['v']] = array( + 'doneby' => $info['m'], + 'license' => $info['l'], + 'summary' => $info['s'], + 'description' => $info['d'], + 'releasedate' => $info['da'], + 'releasenotes' => $info['n'], + 'state' => $release['s'], + 'deps' => $ds ? $ds : array(), + ); + } + } else { + $latest = ''; + } + PEAR::popErrorHandling(); + if (isset($pinfo['dc']) && isset($pinfo['dp'])) { + if (is_array($pinfo['dp'])) { + $deprecated = array('channel' => (string) $pinfo['dc'], + 'package' => trim($pinfo['dp']['_content'])); + } else { + $deprecated = array('channel' => (string) $pinfo['dc'], + 'package' => trim($pinfo['dp'])); + } + } else { + $deprecated = false; + } + return array( + 'name' => $pinfo['n'], + 'channel' => $pinfo['c'], + 'category' => $pinfo['ca']['_content'], + 'stable' => $latest, + 'license' => $pinfo['l'], + 'summary' => $pinfo['s'], + 'description' => $pinfo['d'], + 'releases' => $releases, + 'deprecated' => $deprecated, + ); + } + + /** + * Return an array containing all of the states that are more stable than + * or equal to the passed in state + * + * @param string Release state + * @param boolean Determines whether to include $state in the list + * @return false|array False if $state is not a valid release state + */ + function betterStates($state, $include = false) + { + static $states = array('snapshot', 'devel', 'alpha', 'beta', 'stable'); + $i = array_search($state, $states); + if ($i === false) { + return false; + } + if ($include) { + $i--; + } + return array_slice($states, $i + 1); + } +} +?> \ No newline at end of file diff --git a/src/lib/pear/PEAR/PEAR/REST/11.php b/src/lib/pear/PEAR/PEAR/REST/11.php new file mode 100644 index 0000000..3dafb4c --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/REST/11.php @@ -0,0 +1,317 @@ + + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: 11.php,v 1.14 2008/04/11 01:16:40 dufuz Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 1.4.3 + */ + +/** + * For downloading REST xml/txt files + */ +require_once 'PEAR/REST.php'; + +/** + * Implement REST 1.1 + * + * @category pear + * @package PEAR + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 1.4.3 + */ +class PEAR_REST_11 +{ + /** + * @var PEAR_REST + */ + var $_rest; + + function PEAR_REST_11($config, $options = array()) + { + $this->_rest = &new PEAR_REST($config, $options); + } + + function listAll($base, $dostable, $basic = true, $searchpackage = false, $searchsummary = false, $channel = false) + { + $categorylist = $this->_rest->retrieveData($base . 'c/categories.xml', false, false, $channel); + if (PEAR::isError($categorylist)) { + return $categorylist; + } + $ret = array(); + if (!is_array($categorylist['c']) || !isset($categorylist['c'][0])) { + $categorylist['c'] = array($categorylist['c']); + } + PEAR::pushErrorHandling(PEAR_ERROR_RETURN); + + foreach ($categorylist['c'] as $progress => $category) { + $category = $category['_content']; + $packagesinfo = $this->_rest->retrieveData($base . + 'c/' . urlencode($category) . '/packagesinfo.xml', false, false, $channel); + + if (PEAR::isError($packagesinfo)) { + continue; + } + + if (!is_array($packagesinfo) || !isset($packagesinfo['pi'])) { + continue; + } + + if (!is_array($packagesinfo['pi']) || !isset($packagesinfo['pi'][0])) { + $packagesinfo['pi'] = array($packagesinfo['pi']); + } + + foreach ($packagesinfo['pi'] as $packageinfo) { + $info = $packageinfo['p']; + $package = $info['n']; + $releases = isset($packageinfo['a']) ? $packageinfo['a'] : false; + unset($latest); + unset($unstable); + unset($stable); + unset($state); + + if ($releases) { + if (!isset($releases['r'][0])) { + $releases['r'] = array($releases['r']); + } + foreach ($releases['r'] as $release) { + if (!isset($latest)) { + if ($dostable && $release['s'] == 'stable') { + $latest = $release['v']; + $state = 'stable'; + } + if (!$dostable) { + $latest = $release['v']; + $state = $release['s']; + } + } + if (!isset($stable) && $release['s'] == 'stable') { + $stable = $release['v']; + if (!isset($unstable)) { + $unstable = $stable; + } + } + if (!isset($unstable) && $release['s'] != 'stable') { + $unstable = $release['v']; + $state = $release['s']; + } + if (isset($latest) && !isset($state)) { + $state = $release['s']; + } + if (isset($latest) && isset($stable) && isset($unstable)) { + break; + } + } + } + + if ($basic) { // remote-list command + if (!isset($latest)) { + $latest = false; + } + if ($dostable) { + // $state is not set if there are no releases + if (isset($state) && $state == 'stable') { + $ret[$package] = array('stable' => $latest); + } else { + $ret[$package] = array('stable' => '-n/a-'); + } + } else { + $ret[$package] = array('stable' => $latest); + } + continue; + } + + // list-all command + $deps = array(); + if (!isset($unstable)) { + $unstable = false; + $state = 'stable'; + if (isset($stable)) { + $latest = $unstable = $stable; + } + } else { + $latest = $unstable; + } + + if (!isset($latest)) { + $latest = false; + } + + if ($latest && isset($packageinfo['deps'])) { + if (!is_array($packageinfo['deps']) || + !isset($packageinfo['deps'][0])) { + $packageinfo['deps'] = array($packageinfo['deps']); + } + $d = false; + foreach ($packageinfo['deps'] as $dep) { + if ($dep['v'] == $latest) { + $d = unserialize($dep['d']); + } + } + if ($d) { + if (isset($d['required'])) { + if (!class_exists('PEAR_PackageFile_v2')) { + require_once 'PEAR/PackageFile/v2.php'; + } + if (!isset($pf)) { + $pf = new PEAR_PackageFile_v2; + } + $pf->setDeps($d); + $tdeps = $pf->getDeps(); + } else { + $tdeps = $d; + } + foreach ($tdeps as $dep) { + if ($dep['type'] !== 'pkg') { + continue; + } + $deps[] = $dep; + } + } + } + + $info = array('stable' => $latest, 'summary' => $info['s'], + 'description' => + $info['d'], 'deps' => $deps, 'category' => $info['ca']['_content'], + 'unstable' => $unstable, 'state' => $state); + $ret[$package] = $info; + } + } + PEAR::popErrorHandling(); + return $ret; + } + + /** + * List all categories of a REST server + * + * @param string $base base URL of the server + * @return array of categorynames + */ + function listCategories($base, $channel = false) + { + $categorylist = $this->_rest->retrieveData($base . 'c/categories.xml', false, false, $channel); + if (PEAR::isError($categorylist)) { + return $categorylist; + } + if (!is_array($categorylist) || !isset($categorylist['c'])) { + return array(); + } + if (isset($categorylist['c']['_content'])) { + // only 1 category + $categorylist['c'] = array($categorylist['c']); + } + return $categorylist['c']; + } + + /** + * List packages in a category of a REST server + * + * @param string $base base URL of the server + * @param string $category name of the category + * @param boolean $info also download full package info + * @return array of packagenames + */ + function listCategory($base, $category, $info = false, $channel = false) + { + if ($info == false) { + $url = '%s'.'c/%s/packages.xml'; + } else { + $url = '%s'.'c/%s/packagesinfo.xml'; + } + $url = sprintf($url, + $base, + urlencode($category)); + + // gives '404 Not Found' error when category doesn't exist + $packagelist = $this->_rest->retrieveData($url, false, false, $channel); + if (PEAR::isError($packagelist)) { + return $packagelist; + } + if (!is_array($packagelist)) { + return array(); + } + + if ($info == false) { + if (!isset($packagelist['p'])) { + return array(); + } + if (!is_array($packagelist['p']) || + !isset($packagelist['p'][0])) { // only 1 pkg + $packagelist = array($packagelist['p']); + } else { + $packagelist = $packagelist['p']; + } + return $packagelist; + } else { + // info == true + if (!isset($packagelist['pi'])) { + return array(); + } + if (!is_array($packagelist['pi']) || + !isset($packagelist['pi'][0])) { // only 1 pkg + $packagelist_pre = array($packagelist['pi']); + } else { + $packagelist_pre = $packagelist['pi']; + } + + $packagelist = array(); + foreach ($packagelist_pre as $i => $item) { + // compatibility with r/.xml + if (isset($item['a']['r'][0])) { + // multiple releases + $item['p']['v'] = $item['a']['r'][0]['v']; + $item['p']['st'] = $item['a']['r'][0]['s']; + } elseif (isset($item['a'])) { + // first and only release + $item['p']['v'] = $item['a']['r']['v']; + $item['p']['st'] = $item['a']['r']['s']; + } + + $packagelist[$i] = array('attribs' => $item['p']['r'], + '_content' => $item['p']['n'], + 'info' => $item['p']); + } + } + + return $packagelist; + } + + /** + * Return an array containing all of the states that are more stable than + * or equal to the passed in state + * + * @param string Release state + * @param boolean Determines whether to include $state in the list + * @return false|array False if $state is not a valid release state + */ + function betterStates($state, $include = false) + { + static $states = array('snapshot', 'devel', 'alpha', 'beta', 'stable'); + $i = array_search($state, $states); + if ($i === false) { + return false; + } + if ($include) { + $i--; + } + return array_slice($states, $i + 1); + } +} +?> \ No newline at end of file diff --git a/src/lib/pear/PEAR/PEAR/REST/13.php b/src/lib/pear/PEAR/PEAR/REST/13.php new file mode 100644 index 0000000..17cea45 --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/REST/13.php @@ -0,0 +1,280 @@ + + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: 13.php,v 1.6 2008/04/11 01:16:40 dufuz Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 1.4.0a12 + */ + +/** + * For downloading REST xml/txt files + */ +require_once 'PEAR/REST.php'; +require_once 'PEAR/REST/10.php'; + +/** + * Implement REST 1.3 + * + * @category pear + * @package PEAR + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 1.4.0a12 + */ +class PEAR_REST_13 extends PEAR_REST_10 +{ + /** + * Retrieve information about a remote package to be downloaded from a REST server + * + * This is smart enough to resolve the minimum PHP version dependency prior to download + * @param string $base The uri to prepend to all REST calls + * @param array $packageinfo an array of format: + *
    +     *  array(
    +     *   'package' => 'packagename',
    +     *   'channel' => 'channelname',
    +     *  ['state' => 'alpha' (or valid state),]
    +     *  -or-
    +     *  ['version' => '1.whatever']
    +     * 
    + * @param string $prefstate Current preferred_state config variable value + * @param bool $installed the installed version of this package to compare against + * @return array|false|PEAR_Error see {@link _returnDownloadURL()} + */ + function getDownloadURL($base, $packageinfo, $prefstate, $installed, $channel = false) + { + $channel = $packageinfo['channel']; + $package = $packageinfo['package']; + $states = $this->betterStates($prefstate, true); + if (!$states) { + return PEAR::raiseError('"' . $prefstate . '" is not a valid state'); + } + $state = isset($packageinfo['state']) ? $packageinfo['state'] : null; + $version = isset($packageinfo['version']) ? $packageinfo['version'] : null; + $info = $this->_rest->retrieveData($base . 'r/' . strtolower($package) . + '/allreleases2.xml'); + if (PEAR::isError($info)) { + return PEAR::raiseError('No releases available for package "' . + $channel . '/' . $package . '"'); + } + if (!isset($info['r'])) { + return false; + } + $release = $found = false; + if (!is_array($info['r']) || !isset($info['r'][0])) { + $info['r'] = array($info['r']); + } + $skippedphp = false; + foreach ($info['r'] as $release) { + if (!isset($this->_rest->_options['force']) && ($installed && + version_compare($release['v'], $installed, '<'))) { + continue; + } + if (isset($state)) { + // try our preferred state first + if ($release['s'] == $state) { + if (!isset($version) && version_compare($release['m'], phpversion(), '>')) { + // skip releases that require a PHP version newer than our PHP version + $skippedphp = $release; + continue; + } + $found = true; + break; + } + // see if there is something newer and more stable + // bug #7221 + if (in_array($release['s'], $this->betterStates($state), true)) { + if (!isset($version) && version_compare($release['m'], phpversion(), '>')) { + // skip releases that require a PHP version newer than our PHP version + $skippedphp = $release; + continue; + } + $found = true; + break; + } + } elseif (isset($version)) { + if ($release['v'] == $version) { + if (!isset($this->_rest->_options['force']) && + !isset($version) && + version_compare($release['m'], phpversion(), '>')) { + // skip releases that require a PHP version newer than our PHP version + $skippedphp = $release; + continue; + } + $found = true; + break; + } + } else { + if (in_array($release['s'], $states)) { + if (version_compare($release['m'], phpversion(), '>')) { + // skip releases that require a PHP version newer than our PHP version + $skippedphp = $release; + continue; + } + $found = true; + break; + } + } + } + if (!$found && $skippedphp) { + $found = null; + } + return $this->_returnDownloadURL($base, $package, $release, $info, $found, $skippedphp, $channel); + } + + function getDepDownloadURL($base, $xsdversion, $dependency, $deppackage, + $prefstate = 'stable', $installed = false, $channel = false) + { + $channel = $dependency['channel']; + $package = $dependency['name']; + $states = $this->betterStates($prefstate, true); + if (!$states) { + return PEAR::raiseError('"' . $prefstate . '" is not a valid state'); + } + $state = isset($dependency['state']) ? $dependency['state'] : null; + $version = isset($dependency['version']) ? $dependency['version'] : null; + $info = $this->_rest->retrieveData($base . 'r/' . strtolower($package) . + '/allreleases2.xml'); + if (PEAR::isError($info)) { + return PEAR::raiseError('Package "' . $deppackage['channel'] . '/' . $deppackage['package'] + . '" dependency "' . $channel . '/' . $package . '" has no releases'); + } + if (!is_array($info) || !isset($info['r'])) { + return false; + } + $exclude = array(); + $min = $max = $recommended = false; + if ($xsdversion == '1.0') { + $pinfo['package'] = $dependency['name']; + $pinfo['channel'] = 'pear.php.net'; // this is always true - don't change this + switch ($dependency['rel']) { + case 'ge' : + $min = $dependency['version']; + break; + case 'gt' : + $min = $dependency['version']; + $exclude = array($dependency['version']); + break; + case 'eq' : + $recommended = $dependency['version']; + break; + case 'lt' : + $max = $dependency['version']; + $exclude = array($dependency['version']); + break; + case 'le' : + $max = $dependency['version']; + break; + case 'ne' : + $exclude = array($dependency['version']); + break; + } + } else { + $pinfo['package'] = $dependency['name']; + $min = isset($dependency['min']) ? $dependency['min'] : false; + $max = isset($dependency['max']) ? $dependency['max'] : false; + $recommended = isset($dependency['recommended']) ? + $dependency['recommended'] : false; + if (isset($dependency['exclude'])) { + if (!isset($dependency['exclude'][0])) { + $exclude = array($dependency['exclude']); + } + } + } + $found = false; + $release = false; + $skippedphp = false; + if (!is_array($info['r']) || !isset($info['r'][0])) { + $info['r'] = array($info['r']); + } + foreach ($info['r'] as $release) { + if (!isset($this->_rest->_options['force']) && ($installed && + version_compare($release['v'], $installed, '<'))) { + continue; + } + if (in_array($release['v'], $exclude)) { // skip excluded versions + continue; + } + // allow newer releases to say "I'm OK with the dependent package" + if ($xsdversion == '2.0' && isset($release['co'])) { + if (!is_array($release['co']) || !isset($release['co'][0])) { + $release['co'] = array($release['co']); + } + foreach ($release['co'] as $entry) { + if (isset($entry['x']) && !is_array($entry['x'])) { + $entry['x'] = array($entry['x']); + } elseif (!isset($entry['x'])) { + $entry['x'] = array(); + } + if ($entry['c'] == $deppackage['channel'] && + strtolower($entry['p']) == strtolower($deppackage['package']) && + version_compare($deppackage['version'], $entry['min'], '>=') && + version_compare($deppackage['version'], $entry['max'], '<=') && + !in_array($release['v'], $entry['x'])) { + if (version_compare($release['m'], phpversion(), '>')) { + // skip dependency releases that require a PHP version + // newer than our PHP version + $skippedphp = $release; + continue; + } + $recommended = $release['v']; + break; + } + } + } + if ($recommended) { + if ($release['v'] != $recommended) { // if we want a specific + // version, then skip all others + continue; + } else { + if (!in_array($release['s'], $states)) { + // the stability is too low, but we must return the + // recommended version if possible + return $this->_returnDownloadURL($base, $package, $release, $info, true, false, $channel); + } + } + } + if ($min && version_compare($release['v'], $min, 'lt')) { // skip too old versions + continue; + } + if ($max && version_compare($release['v'], $max, 'gt')) { // skip too new versions + continue; + } + if ($installed && version_compare($release['v'], $installed, '<')) { + continue; + } + if (in_array($release['s'], $states)) { // if in the preferred state... + if (version_compare($release['m'], phpversion(), '>')) { + // skip dependency releases that require a PHP version + // newer than our PHP version + $skippedphp = $release; + continue; + } + $found = true; // ... then use it + break; + } + } + if (!$found && $skippedphp) { + $found = null; + } + return $this->_returnDownloadURL($base, $package, $release, $info, $found, $skippedphp, $channel); + } +} +?> \ No newline at end of file diff --git a/src/lib/pear/PEAR/PEAR/Registry.php b/src/lib/pear/PEAR/PEAR/Registry.php new file mode 100644 index 0000000..556366d --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Registry.php @@ -0,0 +1,2236 @@ + + * @author Tomas V. V. Cox + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: Registry.php,v 1.171 2008/05/14 04:16:08 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 0.1 + */ + +/** + * for PEAR_Error + */ +require_once 'PEAR.php'; +require_once 'PEAR/DependencyDB.php'; + +define('PEAR_REGISTRY_ERROR_LOCK', -2); +define('PEAR_REGISTRY_ERROR_FORMAT', -3); +define('PEAR_REGISTRY_ERROR_FILE', -4); +define('PEAR_REGISTRY_ERROR_CONFLICT', -5); +define('PEAR_REGISTRY_ERROR_CHANNEL_FILE', -6); + +/** + * Administration class used to maintain the installed package database. + * @category pear + * @package PEAR + * @author Stig Bakken + * @author Tomas V. V. Cox + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 1.4.0a1 + */ +class PEAR_Registry extends PEAR +{ + // {{{ properties + + /** + * File containing all channel information. + * @var string + */ + var $channels = ''; + + /** Directory where registry files are stored. + * @var string + */ + var $statedir = ''; + + /** File where the file map is stored + * @var string + */ + var $filemap = ''; + + /** Directory where registry files for channels are stored. + * @var string + */ + var $channelsdir = ''; + + /** Name of file used for locking the registry + * @var string + */ + var $lockfile = ''; + + /** File descriptor used during locking + * @var resource + */ + var $lock_fp = null; + + /** Mode used during locking + * @var int + */ + var $lock_mode = 0; // XXX UNUSED + + /** Cache of package information. Structure: + * array( + * 'package' => array('id' => ... ), + * ... ) + * @var array + */ + var $pkginfo_cache = array(); + + /** Cache of file map. Structure: + * array( '/path/to/file' => 'package', ... ) + * @var array + */ + var $filemap_cache = array(); + + /** + * @var false|PEAR_ChannelFile + */ + var $_pearChannel; + + /** + * @var false|PEAR_ChannelFile + */ + var $_peclChannel; + + /** + * @var PEAR_DependencyDB + */ + var $_dependencyDB; + + /** + * @var PEAR_Config + */ + var $_config; + // }}} + + // {{{ constructor + + /** + * PEAR_Registry constructor. + * + * @param string (optional) PEAR install directory (for .php files) + * @param PEAR_ChannelFile PEAR_ChannelFile object representing the PEAR channel, if + * default values are not desired. Only used the very first time a PEAR + * repository is initialized + * @param PEAR_ChannelFile PEAR_ChannelFile object representing the PECL channel, if + * default values are not desired. Only used the very first time a PEAR + * repository is initialized + * + * @access public + */ + function PEAR_Registry($pear_install_dir = PEAR_INSTALL_DIR, $pear_channel = false, + $pecl_channel = false) + { + parent::PEAR(); + $this->setInstallDir($pear_install_dir); + $this->_pearChannel = $pear_channel; + $this->_peclChannel = $pecl_channel; + $this->_config = false; + } + + function setInstallDir($pear_install_dir = PEAR_INSTALL_DIR) + { + $ds = DIRECTORY_SEPARATOR; + $this->install_dir = $pear_install_dir; + $this->channelsdir = $pear_install_dir.$ds.'.channels'; + $this->statedir = $pear_install_dir.$ds.'.registry'; + $this->filemap = $pear_install_dir.$ds.'.filemap'; + $this->lockfile = $pear_install_dir.$ds.'.lock'; + } + + function hasWriteAccess() + { + if (!file_exists($this->install_dir)) { + $dir = $this->install_dir; + while ($dir && $dir != '.') { + $olddir = $dir; + $dir = dirname($dir); // cd .. + if ($dir != '.' && file_exists($dir)) { + if (is_writeable($dir)) { + return true; + } else { + return false; + } + } + if ($dir == $olddir) { // this can happen in safe mode + return @is_writable($dir); + } + } + return false; + } + return is_writeable($this->install_dir); + } + + function setConfig(&$config, $resetInstallDir = true) + { + $this->_config = &$config; + if ($resetInstallDir) { + $this->setInstallDir($config->get('php_dir')); + } + } + + function _initializeChannelDirs() + { + static $running = false; + if (!$running) { + $running = true; + $ds = DIRECTORY_SEPARATOR; + if (!is_dir($this->channelsdir) || + !file_exists($this->channelsdir . $ds . 'pear.php.net.reg') || + !file_exists($this->channelsdir . $ds . 'pecl.php.net.reg') || + !file_exists($this->channelsdir . $ds . '__uri.reg')) { + if (!file_exists($this->channelsdir . $ds . 'pear.php.net.reg')) { + $pear_channel = $this->_pearChannel; + if (!is_a($pear_channel, 'PEAR_ChannelFile') || !$pear_channel->validate()) { + if (!class_exists('PEAR_ChannelFile')) { + require_once 'PEAR/ChannelFile.php'; + } + $pear_channel = new PEAR_ChannelFile; + $pear_channel->setName('pear.php.net'); + $pear_channel->setAlias('pear'); + $pear_channel->setServer('pear.php.net'); + $pear_channel->setSummary('PHP Extension and Application Repository'); + $pear_channel->setDefaultPEARProtocols(); + $pear_channel->setBaseURL('REST1.0', 'http://pear.php.net/rest/'); + $pear_channel->setBaseURL('REST1.1', 'http://pear.php.net/rest/'); + } else { + $pear_channel->setName('pear.php.net'); + $pear_channel->setAlias('pear'); + } + $pear_channel->validate(); + $this->_addChannel($pear_channel); + } + if (!file_exists($this->channelsdir . $ds . 'pecl.php.net.reg')) { + $pecl_channel = $this->_peclChannel; + if (!is_a($pecl_channel, 'PEAR_ChannelFile') || !$pecl_channel->validate()) { + if (!class_exists('PEAR_ChannelFile')) { + require_once 'PEAR/ChannelFile.php'; + } + $pecl_channel = new PEAR_ChannelFile; + $pecl_channel->setName('pecl.php.net'); + $pecl_channel->setAlias('pecl'); + $pecl_channel->setServer('pecl.php.net'); + $pecl_channel->setSummary('PHP Extension Community Library'); + $pecl_channel->setDefaultPEARProtocols(); + $pecl_channel->setBaseURL('REST1.0', 'http://pecl.php.net/rest/'); + $pecl_channel->setBaseURL('REST1.1', 'http://pecl.php.net/rest/'); + $pecl_channel->setValidationPackage('PEAR_Validator_PECL', '1.0'); + } else { + $pecl_channel->setName('pecl.php.net'); + $pecl_channel->setAlias('pecl'); + } + $pecl_channel->validate(); + $this->_addChannel($pecl_channel); + } + if (!file_exists($this->channelsdir . $ds . '__uri.reg')) { + if (!class_exists('PEAR_ChannelFile')) { + require_once 'PEAR/ChannelFile.php'; + } + $private = new PEAR_ChannelFile; + $private->setName('__uri'); + $private->addFunction('xmlrpc', '1.0', '****'); + $private->setSummary('Pseudo-channel for static packages'); + $this->_addChannel($private); + } + $this->_rebuildFileMap(); + } + $running = false; + } + } + + function _initializeDirs() + { + $ds = DIRECTORY_SEPARATOR; + // XXX Compatibility code should be removed in the future + // rename all registry files if any to lowercase + if (!OS_WINDOWS && file_exists($this->statedir) && is_dir($this->statedir) && + $handle = opendir($this->statedir)) { + $dest = $this->statedir . $ds; + while (false !== ($file = readdir($handle))) { + if (preg_match('/^.*[A-Z].*\.reg\\z/', $file)) { + rename($dest . $file, $dest . strtolower($file)); + } + } + closedir($handle); + } + $this->_initializeChannelDirs(); + if (!file_exists($this->filemap)) { + $this->_rebuildFileMap(); + } + $this->_initializeDepDB(); + } + + function _initializeDepDB() + { + if (!isset($this->_dependencyDB)) { + static $initializing = false; + if (!$initializing) { + $initializing = true; + if (!$this->_config) { // never used? + if (OS_WINDOWS) { + $file = 'pear.ini'; + } else { + $file = '.pearrc'; + } + $this->_config = &new PEAR_Config($this->statedir . DIRECTORY_SEPARATOR . + $file); + $this->_config->setRegistry($this); + $this->_config->set('php_dir', $this->install_dir); + } + $this->_dependencyDB = &PEAR_DependencyDB::singleton($this->_config); + if (PEAR::isError($this->_dependencyDB)) { + // attempt to recover by removing the dep db + if (file_exists($this->_config->get('php_dir', null, 'pear.php.net') . + DIRECTORY_SEPARATOR . '.depdb')) { + @unlink($this->_config->get('php_dir', null, 'pear.php.net') . + DIRECTORY_SEPARATOR . '.depdb'); + } + $this->_dependencyDB = &PEAR_DependencyDB::singleton($this->_config); + if (PEAR::isError($this->_dependencyDB)) { + echo $this->_dependencyDB->getMessage(); + echo 'Unrecoverable error'; + exit(1); + } + } + $initializing = false; + } + } + } + // }}} + // {{{ destructor + + /** + * PEAR_Registry destructor. Makes sure no locks are forgotten. + * + * @access private + */ + function _PEAR_Registry() + { + parent::_PEAR(); + if (is_resource($this->lock_fp)) { + $this->_unlock(); + } + } + + // }}} + + // {{{ _assertStateDir() + + /** + * Make sure the directory where we keep registry files exists. + * + * @return bool TRUE if directory exists, FALSE if it could not be + * created + * + * @access private + */ + function _assertStateDir($channel = false) + { + if ($channel && $this->_getChannelFromAlias($channel) != 'pear.php.net') { + return $this->_assertChannelStateDir($channel); + } + static $init = false; + if (!file_exists($this->statedir)) { + if (!$this->hasWriteAccess()) { + return false; + } + require_once 'System.php'; + if (!System::mkdir(array('-p', $this->statedir))) { + return $this->raiseError("could not create directory '{$this->statedir}'"); + } + $init = true; + } elseif (!is_dir($this->statedir)) { + return $this->raiseError('Cannot create directory ' . $this->statedir . ', ' . + 'it already exists and is not a directory'); + } + $ds = DIRECTORY_SEPARATOR; + if (!file_exists($this->channelsdir)) { + if (!file_exists($this->channelsdir . $ds . 'pear.php.net.reg') || + !file_exists($this->channelsdir . $ds . 'pecl.php.net.reg') || + !file_exists($this->channelsdir . $ds . '__uri.reg')) { + $init = true; + } + } elseif (!is_dir($this->channelsdir)) { + return $this->raiseError('Cannot create directory ' . $this->channelsdir . ', ' . + 'it already exists and is not a directory'); + } + if ($init) { + static $running = false; + if (!$running) { + $running = true; + $this->_initializeDirs(); + $running = false; + $init = false; + } + } else { + $this->_initializeDepDB(); + } + return true; + } + + // }}} + // {{{ _assertChannelStateDir() + + /** + * Make sure the directory where we keep registry files exists for a non-standard channel. + * + * @param string channel name + * @return bool TRUE if directory exists, FALSE if it could not be + * created + * + * @access private + */ + function _assertChannelStateDir($channel) + { + $ds = DIRECTORY_SEPARATOR; + if (!$channel || $this->_getChannelFromAlias($channel) == 'pear.php.net') { + if (!file_exists($this->channelsdir . $ds . 'pear.php.net.reg')) { + $this->_initializeChannelDirs(); + } + return $this->_assertStateDir($channel); + } + $channelDir = $this->_channelDirectoryName($channel); + if (!is_dir($this->channelsdir) || + !file_exists($this->channelsdir . $ds . 'pear.php.net.reg')) { + $this->_initializeChannelDirs(); + } + if (!file_exists($channelDir)) { + if (!$this->hasWriteAccess()) { + return false; + } + require_once 'System.php'; + if (!System::mkdir(array('-p', $channelDir))) { + return $this->raiseError("could not create directory '" . $channelDir . + "'"); + } + } elseif (!is_dir($channelDir)) { + return $this->raiseError("could not create directory '" . $channelDir . + "', already exists and is not a directory"); + } + return true; + } + + // }}} + // {{{ _assertChannelDir() + + /** + * Make sure the directory where we keep registry files for channels exists + * + * @return bool TRUE if directory exists, FALSE if it could not be + * created + * + * @access private + */ + function _assertChannelDir() + { + if (!file_exists($this->channelsdir)) { + if (!$this->hasWriteAccess()) { + return false; + } + require_once 'System.php'; + if (!System::mkdir(array('-p', $this->channelsdir))) { + return $this->raiseError("could not create directory '{$this->channelsdir}'"); + } + } elseif (!is_dir($this->channelsdir)) { + return $this->raiseError("could not create directory '{$this->channelsdir}" . + "', it already exists and is not a directory"); + + } + if (!file_exists($this->channelsdir . DIRECTORY_SEPARATOR . '.alias')) { + if (!$this->hasWriteAccess()) { + return false; + } + require_once 'System.php'; + if (!System::mkdir(array('-p', $this->channelsdir . DIRECTORY_SEPARATOR . '.alias'))) { + return $this->raiseError("could not create directory '{$this->channelsdir}/.alias'"); + } + } elseif (!is_dir($this->channelsdir . DIRECTORY_SEPARATOR . '.alias')) { + return $this->raiseError("could not create directory '{$this->channelsdir}" . + "/.alias', it already exists and is not a directory"); + + } + return true; + } + + // }}} + // {{{ _packageFileName() + + /** + * Get the name of the file where data for a given package is stored. + * + * @param string channel name, or false if this is a PEAR package + * @param string package name + * + * @return string registry file name + * + * @access public + */ + function _packageFileName($package, $channel = false) + { + if ($channel && $this->_getChannelFromAlias($channel) != 'pear.php.net') { + return $this->_channelDirectoryName($channel) . DIRECTORY_SEPARATOR . + strtolower($package) . '.reg'; + } + return $this->statedir . DIRECTORY_SEPARATOR . strtolower($package) . '.reg'; + } + + // }}} + // {{{ _channelFileName() + + /** + * Get the name of the file where data for a given channel is stored. + * @param string channel name + * @return string registry file name + */ + function _channelFileName($channel, $noaliases = false) + { + if (!$noaliases) { + if (file_exists($this->_getChannelAliasFileName($channel))) { + $channel = implode('', file($this->_getChannelAliasFileName($channel))); + } + } + return $this->channelsdir . DIRECTORY_SEPARATOR . str_replace('/', '_', + strtolower($channel)) . '.reg'; + } + + // }}} + // {{{ getChannelAliasFileName() + + /** + * @param string + * @return string + */ + function _getChannelAliasFileName($alias) + { + return $this->channelsdir . DIRECTORY_SEPARATOR . '.alias' . + DIRECTORY_SEPARATOR . str_replace('/', '_', strtolower($alias)) . '.txt'; + } + + // }}} + // {{{ _getChannelFromAlias() + + /** + * Get the name of a channel from its alias + */ + function _getChannelFromAlias($channel) + { + if (!$this->_channelExists($channel)) { + if ($channel == 'pear.php.net') { + return 'pear.php.net'; + } + if ($channel == 'pecl.php.net') { + return 'pecl.php.net'; + } + if ($channel == '__uri') { + return '__uri'; + } + return false; + } + $channel = strtolower($channel); + if (file_exists($this->_getChannelAliasFileName($channel))) { + // translate an alias to an actual channel + return implode('', file($this->_getChannelAliasFileName($channel))); + } else { + return $channel; + } + } + // }}} + // {{{ _getChannelFromAlias() + + /** + * Get the alias of a channel from its alias or its name + */ + function _getAlias($channel) + { + if (!$this->_channelExists($channel)) { + if ($channel == 'pear.php.net') { + return 'pear'; + } + if ($channel == 'pecl.php.net') { + return 'pecl'; + } + return false; + } + $channel = $this->_getChannel($channel); + if (PEAR::isError($channel)) { + return $channel; + } + return $channel->getAlias(); + } + // }}} + // {{{ _channelDirectoryName() + + /** + * Get the name of the file where data for a given package is stored. + * + * @param string channel name, or false if this is a PEAR package + * @param string package name + * + * @return string registry file name + * + * @access public + */ + function _channelDirectoryName($channel) + { + if (!$channel || $this->_getChannelFromAlias($channel) == 'pear.php.net') { + return $this->statedir; + } else { + $ch = $this->_getChannelFromAlias($channel); + if (!$ch) { + $ch = $channel; + } + return $this->statedir . DIRECTORY_SEPARATOR . strtolower('.channel.' . + str_replace('/', '_', $ch)); + } + } + + // }}} + // {{{ _openPackageFile() + + function _openPackageFile($package, $mode, $channel = false) + { + if (!$this->_assertStateDir($channel)) { + return null; + } + if (!in_array($mode, array('r', 'rb')) && !$this->hasWriteAccess()) { + return null; + } + $file = $this->_packageFileName($package, $channel); + if (!file_exists($file) && $mode == 'r' || $mode == 'rb') { + return null; + } + $fp = @fopen($file, $mode); + if (!$fp) { + return null; + } + return $fp; + } + + // }}} + // {{{ _closePackageFile() + + function _closePackageFile($fp) + { + fclose($fp); + } + + // }}} + // {{{ _openChannelFile() + + function _openChannelFile($channel, $mode) + { + if (!$this->_assertChannelDir()) { + return null; + } + if (!in_array($mode, array('r', 'rb')) && !$this->hasWriteAccess()) { + return null; + } + $file = $this->_channelFileName($channel); + if (!file_exists($file) && $mode == 'r' || $mode == 'rb') { + return null; + } + $fp = @fopen($file, $mode); + if (!$fp) { + return null; + } + return $fp; + } + + // }}} + // {{{ _closePackageFile() + + function _closeChannelFile($fp) + { + fclose($fp); + } + + // }}} + // {{{ _rebuildFileMap() + + function _rebuildFileMap() + { + if (!class_exists('PEAR_Installer_Role')) { + require_once 'PEAR/Installer/Role.php'; + } + $channels = $this->_listAllPackages(); + $files = array(); + foreach ($channels as $channel => $packages) { + foreach ($packages as $package) { + $version = $this->_packageInfo($package, 'version', $channel); + $filelist = $this->_packageInfo($package, 'filelist', $channel); + if (!is_array($filelist)) { + continue; + } + foreach ($filelist as $name => $attrs) { + if (isset($attrs['attribs'])) { + $attrs = $attrs['attribs']; + } + // it is possible for conflicting packages in different channels to + // conflict with data files/doc files + if ($name == 'dirtree') { + continue; + } + if (isset($attrs['role']) && !in_array($attrs['role'], + PEAR_Installer_Role::getInstallableRoles())) { + // these are not installed + continue; + } + if (isset($attrs['role']) && !in_array($attrs['role'], + PEAR_Installer_Role::getBaseinstallRoles())) { + $attrs['baseinstalldir'] = $package; + } + if (isset($attrs['baseinstalldir'])) { + $file = $attrs['baseinstalldir'].DIRECTORY_SEPARATOR.$name; + } else { + $file = $name; + } + $file = preg_replace(',^/+,', '', $file); + if ($channel != 'pear.php.net') { + if (!isset($files[$attrs['role']])) { + $files[$attrs['role']] = array(); + } + $files[$attrs['role']][$file] = array(strtolower($channel), + strtolower($package)); + } else { + if (!isset($files[$attrs['role']])) { + $files[$attrs['role']] = array(); + } + $files[$attrs['role']][$file] = strtolower($package); + } + } + } + } + $this->_assertStateDir(); + if (!$this->hasWriteAccess()) { + return false; + } + $fp = @fopen($this->filemap, 'wb'); + if (!$fp) { + return false; + } + $this->filemap_cache = $files; + fwrite($fp, serialize($files)); + fclose($fp); + return true; + } + + // }}} + // {{{ _readFileMap() + + function _readFileMap() + { + if (!file_exists($this->filemap)) { + return array(); + } + $fp = @fopen($this->filemap, 'r'); + if (!$fp) { + return $this->raiseError('PEAR_Registry: could not open filemap "' . $this->filemap . '"', PEAR_REGISTRY_ERROR_FILE, null, null, $php_errormsg); + } + clearstatcache(); + $rt = get_magic_quotes_runtime(); + set_magic_quotes_runtime(0); + $fsize = filesize($this->filemap); + fclose($fp); + $data = file_get_contents($this->filemap); + set_magic_quotes_runtime($rt); + $tmp = unserialize($data); + if (!$tmp && $fsize > 7) { + return $this->raiseError('PEAR_Registry: invalid filemap data', PEAR_REGISTRY_ERROR_FORMAT, null, null, $data); + } + $this->filemap_cache = $tmp; + return true; + } + + // }}} + // {{{ _lock() + + /** + * Lock the registry. + * + * @param integer lock mode, one of LOCK_EX, LOCK_SH or LOCK_UN. + * See flock manual for more information. + * + * @return bool TRUE on success, FALSE if locking failed, or a + * PEAR error if some other error occurs (such as the + * lock file not being writable). + * + * @access private + */ + function _lock($mode = LOCK_EX) + { + if (!eregi('Windows 9', php_uname())) { + if ($mode != LOCK_UN && is_resource($this->lock_fp)) { + // XXX does not check type of lock (LOCK_SH/LOCK_EX) + return true; + } + if (!$this->_assertStateDir()) { + if ($mode == LOCK_EX) { + return $this->raiseError('Registry directory is not writeable by the current user'); + } else { + return true; + } + } + $open_mode = 'w'; + // XXX People reported problems with LOCK_SH and 'w' + if ($mode === LOCK_SH || $mode === LOCK_UN) { + if (!file_exists($this->lockfile)) { + touch($this->lockfile); + } + $open_mode = 'r'; + } + + if (!is_resource($this->lock_fp)) { + $this->lock_fp = @fopen($this->lockfile, $open_mode); + } + + if (!is_resource($this->lock_fp)) { + $this->lock_fp = null; + return $this->raiseError("could not create lock file" . + (isset($php_errormsg) ? ": " . $php_errormsg : "")); + } + if (!(int)flock($this->lock_fp, $mode)) { + switch ($mode) { + case LOCK_SH: $str = 'shared'; break; + case LOCK_EX: $str = 'exclusive'; break; + case LOCK_UN: $str = 'unlock'; break; + default: $str = 'unknown'; break; + } + //is resource at this point, close it on error. + fclose($this->lock_fp); + $this->lock_fp = null; + return $this->raiseError("could not acquire $str lock ($this->lockfile)", + PEAR_REGISTRY_ERROR_LOCK); + } + } + return true; + } + + // }}} + // {{{ _unlock() + + function _unlock() + { + $ret = $this->_lock(LOCK_UN); + if (is_resource($this->lock_fp)) { + fclose($this->lock_fp); + } + $this->lock_fp = null; + return $ret; + } + + // }}} + // {{{ _packageExists() + + function _packageExists($package, $channel = false) + { + return file_exists($this->_packageFileName($package, $channel)); + } + + // }}} + // {{{ _channelExists() + + /** + * Determine whether a channel exists in the registry + * @param string Channel name + * @param bool if true, then aliases will be ignored + * @return boolean + */ + function _channelExists($channel, $noaliases = false) + { + $a = file_exists($this->_channelFileName($channel, $noaliases)); + if (!$a && $channel == 'pear.php.net') { + return true; + } + if (!$a && $channel == 'pecl.php.net') { + return true; + } + return $a; + } + + // }}} + // {{{ _addChannel() + + /** + * @param PEAR_ChannelFile Channel object + * @param donotuse + * @param string Last-Modified HTTP tag from remote request + * @return boolean|PEAR_Error True on creation, false if it already exists + */ + function _addChannel($channel, $update = false, $lastmodified = false) + { + if (!is_a($channel, 'PEAR_ChannelFile')) { + return false; + } + if (!$channel->validate()) { + return false; + } + if (file_exists($this->_channelFileName($channel->getName()))) { + if (!$update) { + return false; + } + $checker = $this->_getChannel($channel->getName()); + if (PEAR::isError($checker)) { + return $checker; + } + if ($channel->getAlias() != $checker->getAlias()) { + if (file_exists($this->_getChannelAliasFileName($checker->getAlias()))) { + @unlink($this->_getChannelAliasFileName($checker->getAlias())); + } + } + } else { + if ($update && !in_array($channel->getName(), array('pear.php.net', 'pecl.php.net'))) { + return false; + } + } + $ret = $this->_assertChannelDir(); + if (PEAR::isError($ret)) { + return $ret; + } + $ret = $this->_assertChannelStateDir($channel->getName()); + if (PEAR::isError($ret)) { + return $ret; + } + if ($channel->getAlias() != $channel->getName()) { + if (file_exists($this->_getChannelAliasFileName($channel->getAlias())) && + $this->_getChannelFromAlias($channel->getAlias()) != $channel->getName()) { + $channel->setAlias($channel->getName()); + } + if (!$this->hasWriteAccess()) { + return false; + } + $fp = @fopen($this->_getChannelAliasFileName($channel->getAlias()), 'w'); + if (!$fp) { + return false; + } + fwrite($fp, $channel->getName()); + fclose($fp); + } + if (!$this->hasWriteAccess()) { + return false; + } + $fp = @fopen($this->_channelFileName($channel->getName()), 'wb'); + if (!$fp) { + return false; + } + $info = $channel->toArray(); + if ($lastmodified) { + $info['_lastmodified'] = $lastmodified; + } else { + $info['_lastmodified'] = date('r'); + } + fwrite($fp, serialize($info)); + fclose($fp); + return true; + } + + // }}} + // {{{ _deleteChannel() + + /** + * Deletion fails if there are any packages installed from the channel + * @param string|PEAR_ChannelFile channel name + * @return boolean|PEAR_Error True on deletion, false if it doesn't exist + */ + function _deleteChannel($channel) + { + if (!is_string($channel)) { + if (is_a($channel, 'PEAR_ChannelFile')) { + if (!$channel->validate()) { + return false; + } + $channel = $channel->getName(); + } else { + return false; + } + } + if ($this->_getChannelFromAlias($channel) == '__uri') { + return false; + } + if ($this->_getChannelFromAlias($channel) == 'pecl.php.net') { + return false; + } + if (!$this->_channelExists($channel)) { + return false; + } + if (!$channel || $this->_getChannelFromAlias($channel) == 'pear.php.net') { + return false; + } + $channel = $this->_getChannelFromAlias($channel); + if ($channel == 'pear.php.net') { + return false; + } + $test = $this->_listChannelPackages($channel); + if (count($test)) { + return false; + } + $test = @rmdir($this->_channelDirectoryName($channel)); + if (!$test) { + return false; + } + $file = $this->_getChannelAliasFileName($this->_getAlias($channel)); + if (file_exists($file)) { + $test = @unlink($file); + if (!$test) { + return false; + } + } + $file = $this->_channelFileName($channel); + $ret = true; + if (file_exists($file)) { + $ret = @unlink($file); + } + return $ret; + } + + // }}} + // {{{ _isChannelAlias() + + /** + * Determine whether a channel exists in the registry + * @param string Channel Alias + * @return boolean + */ + function _isChannelAlias($alias) + { + return file_exists($this->_getChannelAliasFileName($alias)); + } + + // }}} + // {{{ _packageInfo() + + /** + * @param string|null + * @param string|null + * @param string|null + * @return array|null + * @access private + */ + function _packageInfo($package = null, $key = null, $channel = 'pear.php.net') + { + if ($package === null) { + if ($channel === null) { + $channels = $this->_listChannels(); + $ret = array(); + foreach ($channels as $channel) { + $channel = strtolower($channel); + $ret[$channel] = array(); + $packages = $this->_listPackages($channel); + foreach ($packages as $package) { + $ret[$channel][] = $this->_packageInfo($package, null, $channel); + } + } + return $ret; + } + $ps = $this->_listPackages($channel); + if (!count($ps)) { + return array(); + } + return array_map(array(&$this, '_packageInfo'), + $ps, array_fill(0, count($ps), null), + array_fill(0, count($ps), $channel)); + } + $fp = $this->_openPackageFile($package, 'r', $channel); + if ($fp === null) { + return null; + } + $rt = get_magic_quotes_runtime(); + set_magic_quotes_runtime(0); + clearstatcache(); + $this->_closePackageFile($fp); + $data = file_get_contents($this->_packageFileName($package, $channel)); + set_magic_quotes_runtime($rt); + $data = unserialize($data); + if ($key === null) { + return $data; + } + // compatibility for package.xml version 2.0 + if (isset($data['old'][$key])) { + return $data['old'][$key]; + } + if (isset($data[$key])) { + return $data[$key]; + } + return null; + } + + // }}} + // {{{ _channelInfo() + + /** + * @param string Channel name + * @param bool whether to strictly retrieve info of channels, not just aliases + * @return array|null + */ + function _channelInfo($channel, $noaliases = false) + { + if (!$this->_channelExists($channel, $noaliases)) { + return null; + } + $fp = $this->_openChannelFile($channel, 'r'); + if ($fp === null) { + return null; + } + $rt = get_magic_quotes_runtime(); + set_magic_quotes_runtime(0); + clearstatcache(); + $this->_closeChannelFile($fp); + $data = file_get_contents($this->_channelFileName($channel)); + set_magic_quotes_runtime($rt); + $data = unserialize($data); + return $data; + } + + // }}} + // {{{ _listChannels() + + function _listChannels() + { + $channellist = array(); + if (!file_exists($this->channelsdir) || !is_dir($this->channelsdir)) { + return array('pear.php.net', 'pecl.php.net', '__uri'); + } + $dp = opendir($this->channelsdir); + while ($ent = readdir($dp)) { + if ($ent{0} == '.' || substr($ent, -4) != '.reg') { + continue; + } + if ($ent == '__uri.reg') { + $channellist[] = '__uri'; + continue; + } + $channellist[] = str_replace('_', '/', substr($ent, 0, -4)); + } + closedir($dp); + if (!in_array('pear.php.net', $channellist)) { + $channellist[] = 'pear.php.net'; + } + if (!in_array('pecl.php.net', $channellist)) { + $channellist[] = 'pecl.php.net'; + } + if (!in_array('__uri', $channellist)) { + $channellist[] = '__uri'; + } + + natsort($channellist); + return $channellist; + } + + // }}} + // {{{ _listPackages() + + function _listPackages($channel = false) + { + if ($channel && $this->_getChannelFromAlias($channel) != 'pear.php.net') { + return $this->_listChannelPackages($channel); + } + if (!file_exists($this->statedir) || !is_dir($this->statedir)) { + return array(); + } + $pkglist = array(); + $dp = opendir($this->statedir); + if (!$dp) { + return $pkglist; + } + while ($ent = readdir($dp)) { + if ($ent{0} == '.' || substr($ent, -4) != '.reg') { + continue; + } + $pkglist[] = substr($ent, 0, -4); + } + closedir($dp); + return $pkglist; + } + + // }}} + // {{{ _listChannelPackages() + + function _listChannelPackages($channel) + { + $pkglist = array(); + if (!file_exists($this->_channelDirectoryName($channel)) || + !is_dir($this->_channelDirectoryName($channel))) { + return array(); + } + $dp = opendir($this->_channelDirectoryName($channel)); + if (!$dp) { + return $pkglist; + } + while ($ent = readdir($dp)) { + if ($ent{0} == '.' || substr($ent, -4) != '.reg') { + continue; + } + $pkglist[] = substr($ent, 0, -4); + } + closedir($dp); + return $pkglist; + } + + // }}} + + function _listAllPackages() + { + $ret = array(); + foreach ($this->_listChannels() as $channel) { + $ret[$channel] = $this->_listPackages($channel); + } + return $ret; + } + + /** + * Add an installed package to the registry + * @param string package name + * @param array package info (parsed by PEAR_Common::infoFrom*() methods) + * @return bool success of saving + * @access private + */ + function _addPackage($package, $info) + { + if ($this->_packageExists($package)) { + return false; + } + $fp = $this->_openPackageFile($package, 'wb'); + if ($fp === null) { + return false; + } + $info['_lastmodified'] = time(); + fwrite($fp, serialize($info)); + $this->_closePackageFile($fp); + if (isset($info['filelist'])) { + $this->_rebuildFileMap(); + } + return true; + } + + /** + * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2 + * @return bool + * @access private + */ + function _addPackage2($info) + { + if (!is_a($info, 'PEAR_PackageFile_v1') && !is_a($info, 'PEAR_PackageFile_v2')) { + return false; + } + + if (!$info->validate()) { + if (class_exists('PEAR_Common')) { + $ui = PEAR_Frontend::singleton(); + if ($ui) { + foreach ($info->getValidationWarnings() as $err) { + $ui->log($err['message'], true); + } + } + } + return false; + } + $channel = $info->getChannel(); + $package = $info->getPackage(); + $save = $info; + if ($this->_packageExists($package, $channel)) { + return false; + } + if (!$this->_channelExists($channel, true)) { + return false; + } + $info = $info->toArray(true); + if (!$info) { + return false; + } + $fp = $this->_openPackageFile($package, 'wb', $channel); + if ($fp === null) { + return false; + } + $info['_lastmodified'] = time(); + fwrite($fp, serialize($info)); + $this->_closePackageFile($fp); + $this->_rebuildFileMap(); + return true; + } + + /** + * @param string Package name + * @param array parsed package.xml 1.0 + * @param bool this parameter is only here for BC. Don't use it. + * @access private + */ + function _updatePackage($package, $info, $merge = true) + { + $oldinfo = $this->_packageInfo($package); + if (empty($oldinfo)) { + return false; + } + $fp = $this->_openPackageFile($package, 'w'); + if ($fp === null) { + return false; + } + if (is_object($info)) { + $info = $info->toArray(); + } + $info['_lastmodified'] = time(); + $newinfo = $info; + if ($merge) { + $info = array_merge($oldinfo, $info); + } else { + $diff = $info; + } + fwrite($fp, serialize($info)); + $this->_closePackageFile($fp); + if (isset($newinfo['filelist'])) { + $this->_rebuildFileMap(); + } + return true; + } + + /** + * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2 + * @return bool + * @access private + */ + function _updatePackage2($info) + { + if (!$this->_packageExists($info->getPackage(), $info->getChannel())) { + return false; + } + $fp = $this->_openPackageFile($info->getPackage(), 'w', $info->getChannel()); + if ($fp === null) { + return false; + } + $save = $info; + $info = $save->getArray(true); + $info['_lastmodified'] = time(); + fwrite($fp, serialize($info)); + $this->_closePackageFile($fp); + $this->_rebuildFileMap(); + return true; + } + + /** + * @param string Package name + * @param string Channel name + * @return PEAR_PackageFile_v1|PEAR_PackageFile_v2|null + * @access private + */ + function &_getPackage($package, $channel = 'pear.php.net') + { + $info = $this->_packageInfo($package, null, $channel); + if ($info === null) { + return $info; + } + $a = $this->_config; + if (!$a) { + $this->_config = &new PEAR_Config; + $this->_config->set('php_dir', $this->statedir); + } + if (!class_exists('PEAR_PackageFile')) { + require_once 'PEAR/PackageFile.php'; + } + $pkg = &new PEAR_PackageFile($this->_config); + $pf = &$pkg->fromArray($info); + return $pf; + } + + /** + * @param string channel name + * @param bool whether to strictly retrieve channel names + * @return PEAR_ChannelFile|PEAR_Error + * @access private + */ + function &_getChannel($channel, $noaliases = false) + { + $ch = false; + if ($this->_channelExists($channel, $noaliases)) { + $chinfo = $this->_channelInfo($channel, $noaliases); + if ($chinfo) { + if (!class_exists('PEAR_ChannelFile')) { + require_once 'PEAR/ChannelFile.php'; + } + $ch = &PEAR_ChannelFile::fromArrayWithErrors($chinfo); + } + } + if ($ch) { + if ($ch->validate()) { + return $ch; + } + foreach ($ch->getErrors(true) as $err) { + $message = $err['message'] . "\n"; + } + $ch = PEAR::raiseError($message); + return $ch; + } + if ($this->_getChannelFromAlias($channel) == 'pear.php.net') { + // the registry is not properly set up, so use defaults + if (!class_exists('PEAR_ChannelFile')) { + require_once 'PEAR/ChannelFile.php'; + } + $pear_channel = new PEAR_ChannelFile; + $pear_channel->setName('pear.php.net'); + $pear_channel->setAlias('pear'); + $pear_channel->setSummary('PHP Extension and Application Repository'); + $pear_channel->setDefaultPEARProtocols(); + $pear_channel->setBaseURL('REST1.0', 'http://pear.php.net/rest/'); + $pear_channel->setBaseURL('REST1.1', 'http://pear.php.net/rest/'); + return $pear_channel; + } + if ($this->_getChannelFromAlias($channel) == 'pecl.php.net') { + // the registry is not properly set up, so use defaults + if (!class_exists('PEAR_ChannelFile')) { + require_once 'PEAR/ChannelFile.php'; + } + $pear_channel = new PEAR_ChannelFile; + $pear_channel->setName('pecl.php.net'); + $pear_channel->setAlias('pecl'); + $pear_channel->setSummary('PHP Extension Community Library'); + $pear_channel->setDefaultPEARProtocols(); + $pear_channel->setBaseURL('REST1.0', 'http://pecl.php.net/rest/'); + $pear_channel->setBaseURL('REST1.1', 'http://pecl.php.net/rest/'); + $pear_channel->setValidationPackage('PEAR_Validator_PECL', '1.0'); + return $pear_channel; + } + if ($this->_getChannelFromAlias($channel) == '__uri') { + // the registry is not properly set up, so use defaults + if (!class_exists('PEAR_ChannelFile')) { + require_once 'PEAR/ChannelFile.php'; + } + $private = new PEAR_ChannelFile; + $private->setName('__uri'); + $private->addFunction('xmlrpc', '1.0', '****'); + $private->setSummary('Pseudo-channel for static packages'); + return $private; + } + return $ch; + } + + // {{{ packageExists() + + /** + * @param string Package name + * @param string Channel name + * @return bool + */ + function packageExists($package, $channel = 'pear.php.net') + { + if (PEAR::isError($e = $this->_lock(LOCK_SH))) { + return $e; + } + $ret = $this->_packageExists($package, $channel); + $this->_unlock(); + return $ret; + } + + // }}} + + // {{{ channelExists() + + /** + * @param string channel name + * @param bool if true, then aliases will be ignored + * @return bool + */ + function channelExists($channel, $noaliases = false) + { + if (PEAR::isError($e = $this->_lock(LOCK_SH))) { + return $e; + } + $ret = $this->_channelExists($channel, $noaliases); + $this->_unlock(); + return $ret; + } + + // }}} + + // {{{ isAlias() + + /** + * Determines whether the parameter is an alias of a channel + * @param string + * @return bool + */ + function isAlias($alias) + { + if (PEAR::isError($e = $this->_lock(LOCK_SH))) { + return $e; + } + $ret = $this->_isChannelAlias($alias); + $this->_unlock(); + return $ret; + } + + // }}} + // {{{ packageInfo() + + /** + * @param string|null + * @param string|null + * @param string + * @return array|null + */ + function packageInfo($package = null, $key = null, $channel = 'pear.php.net') + { + if (PEAR::isError($e = $this->_lock(LOCK_SH))) { + return $e; + } + $ret = $this->_packageInfo($package, $key, $channel); + $this->_unlock(); + return $ret; + } + + // }}} + // {{{ channelInfo() + + /** + * Retrieve a raw array of channel data. + * + * Do not use this, instead use {@link getChannel()} for normal + * operations. Array structure is undefined in this method + * @param string channel name + * @param bool whether to strictly retrieve information only on non-aliases + * @return array|null|PEAR_Error + */ + function channelInfo($channel = null, $noaliases = false) + { + if (PEAR::isError($e = $this->_lock(LOCK_SH))) { + return $e; + } + $ret = $this->_channelInfo($channel, $noaliases); + $this->_unlock(); + return $ret; + } + + // }}} + + /** + * @param string + */ + function channelName($channel) + { + if (PEAR::isError($e = $this->_lock(LOCK_SH))) { + return $e; + } + $ret = $this->_getChannelFromAlias($channel); + $this->_unlock(); + return $ret; + } + + /** + * @param string + */ + function channelAlias($channel) + { + if (PEAR::isError($e = $this->_lock(LOCK_SH))) { + return $e; + } + $ret = $this->_getAlias($channel); + $this->_unlock(); + return $ret; + } + // {{{ listPackages() + + function listPackages($channel = false) + { + if (PEAR::isError($e = $this->_lock(LOCK_SH))) { + return $e; + } + $ret = $this->_listPackages($channel); + $this->_unlock(); + return $ret; + } + + // }}} + // {{{ listAllPackages() + + function listAllPackages() + { + if (PEAR::isError($e = $this->_lock(LOCK_SH))) { + return $e; + } + $ret = $this->_listAllPackages(); + $this->_unlock(); + return $ret; + } + + // }}} + // {{{ listChannel() + + function listChannels() + { + if (PEAR::isError($e = $this->_lock(LOCK_SH))) { + return $e; + } + $ret = $this->_listChannels(); + $this->_unlock(); + return $ret; + } + + // }}} + // {{{ addPackage() + + /** + * Add an installed package to the registry + * @param string|PEAR_PackageFile_v1|PEAR_PackageFile_v2 package name or object + * that will be passed to {@link addPackage2()} + * @param array package info (parsed by PEAR_Common::infoFrom*() methods) + * @return bool success of saving + */ + function addPackage($package, $info) + { + if (is_object($info)) { + return $this->addPackage2($info); + } + if (PEAR::isError($e = $this->_lock(LOCK_EX))) { + return $e; + } + $ret = $this->_addPackage($package, $info); + $this->_unlock(); + if ($ret) { + if (!class_exists('PEAR_PackageFile_v1')) { + require_once 'PEAR/PackageFile/v1.php'; + } + $pf = new PEAR_PackageFile_v1; + $pf->setConfig($this->_config); + $pf->fromArray($info); + $this->_dependencyDB->uninstallPackage($pf); + $this->_dependencyDB->installPackage($pf); + } + return $ret; + } + + // }}} + // {{{ addPackage2() + + function addPackage2($info) + { + if (!is_object($info)) { + return $this->addPackage($info['package'], $info); + } + if (PEAR::isError($e = $this->_lock(LOCK_EX))) { + return $e; + } + $ret = $this->_addPackage2($info); + $this->_unlock(); + if ($ret) { + $this->_dependencyDB->uninstallPackage($info); + $this->_dependencyDB->installPackage($info); + } + return $ret; + } + + // }}} + // {{{ updateChannel() + + /** + * For future expandibility purposes, separate this + * @param PEAR_ChannelFile + */ + function updateChannel($channel, $lastmodified = null) + { + if ($channel->getName() == '__uri') { + return false; + } + return $this->addChannel($channel, $lastmodified, true); + } + + // }}} + // {{{ deleteChannel() + + /** + * Deletion fails if there are any packages installed from the channel + * @param string|PEAR_ChannelFile channel name + * @return boolean|PEAR_Error True on deletion, false if it doesn't exist + */ + function deleteChannel($channel) + { + if (PEAR::isError($e = $this->_lock(LOCK_EX))) { + return $e; + } + $ret = $this->_deleteChannel($channel); + $this->_unlock(); + if ($ret && is_a($this->_config, 'PEAR_Config')) { + $this->_config->setChannels($this->listChannels()); + } + return $ret; + } + + // }}} + // {{{ addChannel() + + /** + * @param PEAR_ChannelFile Channel object + * @param string Last-Modified header from HTTP for caching + * @return boolean|PEAR_Error True on creation, false if it already exists + */ + function addChannel($channel, $lastmodified = false, $update = false) + { + if (!is_a($channel, 'PEAR_ChannelFile')) { + return false; + } + if (!$channel->validate()) { + return false; + } + if (PEAR::isError($e = $this->_lock(LOCK_EX))) { + return $e; + } + $ret = $this->_addChannel($channel, $update, $lastmodified); + $this->_unlock(); + if (!$update && $ret && is_a($this->_config, 'PEAR_Config')) { + $this->_config->setChannels($this->listChannels()); + } + return $ret; + } + + // }}} + // {{{ deletePackage() + + function deletePackage($package, $channel = 'pear.php.net') + { + if (PEAR::isError($e = $this->_lock(LOCK_EX))) { + return $e; + } + $file = $this->_packageFileName($package, $channel); + if (file_exists($file)) { + $ret = @unlink($file); + } else { + $ret = false; + } + $this->_rebuildFileMap(); + $this->_unlock(); + $p = array('channel' => $channel, 'package' => $package); + $this->_dependencyDB->uninstallPackage($p); + return $ret; + } + + // }}} + // {{{ updatePackage() + + function updatePackage($package, $info, $merge = true) + { + if (is_object($info)) { + return $this->updatePackage2($info, $merge); + } + if (PEAR::isError($e = $this->_lock(LOCK_EX))) { + return $e; + } + $ret = $this->_updatePackage($package, $info, $merge); + $this->_unlock(); + if ($ret) { + if (!class_exists('PEAR_PackageFile_v1')) { + require_once 'PEAR/PackageFile/v1.php'; + } + $pf = new PEAR_PackageFile_v1; + $pf->setConfig($this->_config); + $pf->fromArray($this->packageInfo($package)); + $this->_dependencyDB->uninstallPackage($pf); + $this->_dependencyDB->installPackage($pf); + } + return $ret; + } + + // }}} + // {{{ updatePackage2() + + function updatePackage2($info) + { + if (!is_object($info)) { + return $this->updatePackage($info['package'], $info, $merge); + } + if (!$info->validate(PEAR_VALIDATE_DOWNLOADING)) { + return false; + } + if (PEAR::isError($e = $this->_lock(LOCK_EX))) { + return $e; + } + $ret = $this->_updatePackage2($info); + $this->_unlock(); + if ($ret) { + $this->_dependencyDB->uninstallPackage($info); + $this->_dependencyDB->installPackage($info); + } + return $ret; + } + + // }}} + // {{{ getChannel() + /** + * @param string channel name + * @param bool whether to strictly return raw channels (no aliases) + * @return PEAR_ChannelFile|PEAR_Error + */ + function &getChannel($channel, $noaliases = false) + { + if (PEAR::isError($e = $this->_lock(LOCK_SH))) { + return $e; + } + $ret = &$this->_getChannel($channel, $noaliases); + $this->_unlock(); + if (!$ret) { + return PEAR::raiseError('Unknown channel: ' . $channel); + } + return $ret; + } + + // }}} + // {{{ getPackage() + /** + * @param string package name + * @param string channel name + * @return PEAR_PackageFile_v1|PEAR_PackageFile_v2|null + */ + function &getPackage($package, $channel = 'pear.php.net') + { + if (PEAR::isError($e = $this->_lock(LOCK_SH))) { + return $e; + } + $pf = &$this->_getPackage($package, $channel); + $this->_unlock(); + return $pf; + } + + // }}} + + /** + * Get PEAR_PackageFile_v[1/2] objects representing the contents of + * a dependency group that are installed. + * + * This is used at uninstall-time + * @param array + * @return array|false + */ + function getInstalledGroup($group) + { + $ret = array(); + if (isset($group['package'])) { + if (!isset($group['package'][0])) { + $group['package'] = array($group['package']); + } + foreach ($group['package'] as $package) { + $depchannel = isset($package['channel']) ? $package['channel'] : '__uri'; + $p = &$this->getPackage($package['name'], $depchannel); + if ($p) { + $save = &$p; + $ret[] = &$save; + } + } + } + if (isset($group['subpackage'])) { + if (!isset($group['subpackage'][0])) { + $group['subpackage'] = array($group['subpackage']); + } + foreach ($group['subpackage'] as $package) { + $depchannel = isset($package['channel']) ? $package['channel'] : '__uri'; + $p = &$this->getPackage($package['name'], $depchannel); + if ($p) { + $save = &$p; + $ret[] = &$save; + } + } + } + if (!count($ret)) { + return false; + } + return $ret; + } + + // {{{ getChannelValidator() + /** + * @param string channel name + * @return PEAR_Validate|false + */ + function &getChannelValidator($channel) + { + $chan = $this->getChannel($channel); + if (PEAR::isError($chan)) { + return $chan; + } + $val = $chan->getValidationObject(); + return $val; + } + // }}} + // {{{ getChannels() + /** + * @param string channel name + * @return array an array of PEAR_ChannelFile objects representing every installed channel + */ + function &getChannels() + { + $ret = array(); + if (PEAR::isError($e = $this->_lock(LOCK_SH))) { + return $e; + } + foreach ($this->_listChannels() as $channel) { + $e = &$this->_getChannel($channel); + if (!$e || PEAR::isError($e)) { + continue; + } + $ret[] = $e; + } + $this->_unlock(); + return $ret; + } + + // }}} + // {{{ checkFileMap() + + /** + * Test whether a file or set of files belongs to a package. + * + * If an array is passed in + * @param string|array file path, absolute or relative to the pear + * install dir + * @param string|array name of PEAR package or array('package' => name, 'channel' => + * channel) of a package that will be ignored + * @param string API version - 1.1 will exclude any files belonging to a package + * @param array private recursion variable + * @return array|false which package and channel the file belongs to, or an empty + * string if the file does not belong to an installed package, + * or belongs to the second parameter's package + */ + function checkFileMap($path, $package = false, $api = '1.0', $attrs = false) + { + if (is_array($path)) { + static $notempty; + if (empty($notempty)) { + if (!class_exists('PEAR_Installer_Role')) { + require_once 'PEAR/Installer/Role.php'; + } + $notempty = create_function('$a','return !empty($a);'); + } + $package = is_array($package) ? array(strtolower($package[0]), strtolower($package[1])) + : strtolower($package); + $pkgs = array(); + foreach ($path as $name => $attrs) { + if (is_array($attrs)) { + if (isset($attrs['install-as'])) { + $name = $attrs['install-as']; + } + if (!in_array($attrs['role'], PEAR_Installer_Role::getInstallableRoles())) { + // these are not installed + continue; + } + if (!in_array($attrs['role'], PEAR_Installer_Role::getBaseinstallRoles())) { + $attrs['baseinstalldir'] = is_array($package) ? $package[1] : $package; + } + if (isset($attrs['baseinstalldir'])) { + $name = $attrs['baseinstalldir'] . DIRECTORY_SEPARATOR . $name; + } + } + $pkgs[$name] = $this->checkFileMap($name, $package, $api, $attrs); + if (PEAR::isError($pkgs[$name])) { + return $pkgs[$name]; + } + } + return array_filter($pkgs, $notempty); + } + if (empty($this->filemap_cache)) { + if (PEAR::isError($e = $this->_lock(LOCK_SH))) { + return $e; + } + $err = $this->_readFileMap(); + $this->_unlock(); + if (PEAR::isError($err)) { + return $err; + } + } + if (!$attrs) { + $attrs = array('role' => 'php'); // any old call would be for PHP role only + } + if (isset($this->filemap_cache[$attrs['role']][$path])) { + if ($api >= '1.1' && $this->filemap_cache[$attrs['role']][$path] == $package) { + return false; + } + return $this->filemap_cache[$attrs['role']][$path]; + } + $l = strlen($this->install_dir); + if (substr($path, 0, $l) == $this->install_dir) { + $path = preg_replace('!^'.DIRECTORY_SEPARATOR.'+!', '', substr($path, $l)); + } + if (isset($this->filemap_cache[$attrs['role']][$path])) { + if ($api >= '1.1' && $this->filemap_cache[$attrs['role']][$path] == $package) { + return false; + } + return $this->filemap_cache[$attrs['role']][$path]; + } + return false; + } + + // }}} + // {{{ flush() + /** + * Force a reload of the filemap + * @since 1.5.0RC3 + */ + function flushFileMap() + { + $this->filemap_cache = null; + clearstatcache(); // ensure that the next read gets the full, current filemap + } + + // }}} + // {{{ apiVersion() + /** + * Get the expected API version. Channels API is version 1.1, as it is backwards + * compatible with 1.0 + * @return string + */ + function apiVersion() + { + return '1.1'; + } + // }}} + + + /** + * Parse a package name, or validate a parsed package name array + * @param string|array pass in an array of format + * array( + * 'package' => 'pname', + * ['channel' => 'channame',] + * ['version' => 'version',] + * ['state' => 'state',] + * ['group' => 'groupname']) + * or a string of format + * [channel://][channame/]pname[-version|-state][/group=groupname] + * @return array|PEAR_Error + */ + function parsePackageName($param, $defaultchannel = 'pear.php.net') + { + $saveparam = $param; + if (is_array($param)) { + // convert to string for error messages + $saveparam = $this->parsedPackageNameToString($param); + // process the array + if (!isset($param['package'])) { + return PEAR::raiseError('parsePackageName(): array $param ' . + 'must contain a valid package name in index "param"', + 'package', null, null, $param); + } + if (!isset($param['uri'])) { + if (!isset($param['channel'])) { + $param['channel'] = $defaultchannel; + } + } else { + $param['channel'] = '__uri'; + } + } else { + $components = @parse_url((string) $param); + if (isset($components['scheme'])) { + if ($components['scheme'] == 'http') { + // uri package + $param = array('uri' => $param, 'channel' => '__uri'); + } elseif($components['scheme'] != 'channel') { + return PEAR::raiseError('parsePackageName(): only channel:// uris may ' . + 'be downloaded, not "' . $param . '"', 'invalid', null, null, $param); + } + } + if (!isset($components['path'])) { + return PEAR::raiseError('parsePackageName(): array $param ' . + 'must contain a valid package name in "' . $param . '"', + 'package', null, null, $param); + } + if (isset($components['host'])) { + // remove the leading "/" + $components['path'] = substr($components['path'], 1); + } + if (!isset($components['scheme'])) { + if (strpos($components['path'], '/') !== false) { + if ($components['path']{0} == '/') { + return PEAR::raiseError('parsePackageName(): this is not ' . + 'a package name, it begins with "/" in "' . $param . '"', + 'invalid', null, null, $param); + } + $parts = explode('/', $components['path']); + $components['host'] = array_shift($parts); + if (count($parts) > 1) { + $components['path'] = array_pop($parts); + $components['host'] .= '/' . implode('/', $parts); + } else { + $components['path'] = implode('/', $parts); + } + } else { + $components['host'] = $defaultchannel; + } + } else { + if (strpos($components['path'], '/')) { + $parts = explode('/', $components['path']); + $components['path'] = array_pop($parts); + $components['host'] .= '/' . implode('/', $parts); + } + } + + if (is_array($param)) { + $param['package'] = $components['path']; + } else { + $param = array( + 'package' => $components['path'] + ); + if (isset($components['host'])) { + $param['channel'] = $components['host']; + } + } + if (isset($components['fragment'])) { + $param['group'] = $components['fragment']; + } + if (isset($components['user'])) { + $param['user'] = $components['user']; + } + if (isset($components['pass'])) { + $param['pass'] = $components['pass']; + } + if (isset($components['query'])) { + parse_str($components['query'], $param['opts']); + } + // check for extension + $pathinfo = pathinfo($param['package']); + if (isset($pathinfo['extension']) && + in_array(strtolower($pathinfo['extension']), array('tgz', 'tar'))) { + $param['extension'] = $pathinfo['extension']; + $param['package'] = substr($pathinfo['basename'], 0, + strlen($pathinfo['basename']) - 4); + } + // check for version + if (strpos($param['package'], '-')) { + $test = explode('-', $param['package']); + if (count($test) != 2) { + return PEAR::raiseError('parsePackageName(): only one version/state ' . + 'delimiter "-" is allowed in "' . $saveparam . '"', + 'version', null, null, $param); + } + list($param['package'], $param['version']) = $test; + } + } + // validation + $info = $this->channelExists($param['channel']); + if (PEAR::isError($info)) { + return $info; + } + if (!$info) { + return PEAR::raiseError('unknown channel "' . $param['channel'] . + '" in "' . $saveparam . '"', 'channel', null, null, $param); + } + $chan = $this->getChannel($param['channel']); + if (PEAR::isError($chan)) { + return $chan; + } + if (!$chan) { + return PEAR::raiseError("Exception: corrupt registry, could not " . + "retrieve channel " . $param['channel'] . " information", + 'registry', null, null, $param); + } + $param['channel'] = $chan->getName(); + $validate = $chan->getValidationObject(); + $vpackage = $chan->getValidationPackage(); + // validate package name + if (!$validate->validPackageName($param['package'], $vpackage['_content'])) { + return PEAR::raiseError('parsePackageName(): invalid package name "' . + $param['package'] . '" in "' . $saveparam . '"', + 'package', null, null, $param); + } + if (isset($param['group'])) { + if (!PEAR_Validate::validGroupName($param['group'])) { + return PEAR::raiseError('parsePackageName(): dependency group "' . $param['group'] . + '" is not a valid group name in "' . $saveparam . '"', 'group', null, null, + $param); + } + } + if (isset($param['state'])) { + if (!in_array(strtolower($param['state']), $validate->getValidStates())) { + return PEAR::raiseError('parsePackageName(): state "' . $param['state'] + . '" is not a valid state in "' . $saveparam . '"', + 'state', null, null, $param); + } + } + if (isset($param['version'])) { + if (isset($param['state'])) { + return PEAR::raiseError('parsePackageName(): cannot contain both ' . + 'a version and a stability (state) in "' . $saveparam . '"', + 'version/state', null, null, $param); + } + // check whether version is actually a state + if (in_array(strtolower($param['version']), $validate->getValidStates())) { + $param['state'] = strtolower($param['version']); + unset($param['version']); + } else { + if (!$validate->validVersion($param['version'])) { + return PEAR::raiseError('parsePackageName(): "' . $param['version'] . + '" is neither a valid version nor a valid state in "' . + $saveparam . '"', 'version/state', null, null, $param); + } + } + } + return $param; + } + + /** + * @param array + * @return string + */ + function parsedPackageNameToString($parsed, $brief = false) + { + if (is_string($parsed)) { + return $parsed; + } + if (is_object($parsed)) { + $p = $parsed; + $parsed = array( + 'package' => $p->getPackage(), + 'channel' => $p->getChannel(), + 'version' => $p->getVersion(), + ); + } + if (isset($parsed['uri'])) { + return $parsed['uri']; + } + if ($brief) { + if ($channel = $this->channelAlias($parsed['channel'])) { + return $channel . '/' . $parsed['package']; + } + } + $upass = ''; + if (isset($parsed['user'])) { + $upass = $parsed['user']; + if (isset($parsed['pass'])) { + $upass .= ':' . $parsed['pass']; + } + $upass = "$upass@"; + } + $ret = 'channel://' . $upass . $parsed['channel'] . '/' . $parsed['package']; + if (isset($parsed['version']) || isset($parsed['state'])) { + $ver = isset($parsed['version']) ? $parsed['version'] : ''; + $ver .= isset($parsed['state']) ? $parsed['state'] : ''; + $ret .= '-' . $ver; + } + if (isset($parsed['extension'])) { + $ret .= '.' . $parsed['extension']; + } + if (isset($parsed['opts'])) { + $ret .= '?'; + foreach ($parsed['opts'] as $name => $value) { + $parsed['opts'][$name] = "$name=$value"; + } + $ret .= implode('&', $parsed['opts']); + } + if (isset($parsed['group'])) { + $ret .= '#' . $parsed['group']; + } + return $ret; + } +} + +?> diff --git a/src/lib/pear/PEAR/PEAR/Remote.php b/src/lib/pear/PEAR/PEAR/Remote.php new file mode 100644 index 0000000..09ddb99 --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Remote.php @@ -0,0 +1,498 @@ + + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: Remote.php,v 1.80 2008/01/03 20:26:36 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 0.1 + */ + +/** + * needed for PEAR_Error + */ +require_once 'PEAR.php'; +require_once 'PEAR/Config.php'; + +/** + * This is a class for doing remote operations against the central + * PEAR database. + * + * @nodep XML_RPC_Value + * @nodep XML_RPC_Message + * @nodep XML_RPC_Client + * @category pear + * @package PEAR + * @author Stig Bakken + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 0.1 + */ +class PEAR_Remote extends PEAR +{ + // {{{ properties + + var $config = null; + var $cache = null; + /** + * @var PEAR_Registry + * @access private + */ + var $_registry; + + // }}} + + // {{{ PEAR_Remote(config_object) + + function PEAR_Remote(&$config) + { + $this->PEAR(); + $this->config = &$config; + $this->_registry = &$this->config->getRegistry(); + } + + // }}} + // {{{ setRegistry() + + function setRegistry(&$reg) + { + $this->_registry = &$reg; + } + // }}} + // {{{ getCache() + + + function getCache($args) + { + $id = md5(serialize($args)); + $cachedir = $this->config->get('cache_dir'); + $filename = $cachedir . DIRECTORY_SEPARATOR . 'xmlrpc_cache_' . $id; + if (!file_exists($filename)) { + return null; + } + + $fp = fopen($filename, 'rb'); + if (!$fp) { + return null; + } + fclose($fp); + $content = file_get_contents($filename); + $result = array( + 'age' => time() - filemtime($filename), + 'lastChange' => filemtime($filename), + 'content' => unserialize($content), + ); + return $result; + } + + // }}} + + // {{{ saveCache() + + function saveCache($args, $data) + { + $id = md5(serialize($args)); + $cachedir = $this->config->get('cache_dir'); + if (!file_exists($cachedir)) { + System::mkdir(array('-p', $cachedir)); + } + $filename = $cachedir.'/xmlrpc_cache_'.$id; + + $fp = @fopen($filename, "wb"); + if ($fp) { + fwrite($fp, serialize($data)); + fclose($fp); + } + } + + // }}} + + // {{{ clearCache() + + function clearCache($method, $args) + { + array_unshift($args, $method); + array_unshift($args, $this->config->get('default_channel')); // cache by channel + $id = md5(serialize($args)); + $cachedir = $this->config->get('cache_dir'); + $filename = $cachedir.'/xmlrpc_cache_'.$id; + if (file_exists($filename)) { + @unlink($filename); + } + } + + // }}} + // {{{ call(method, [args...]) + + function call($method) + { + $_args = $args = func_get_args(); + + $server_channel = $this->config->get('default_channel'); + $channel = $this->_registry->getChannel($server_channel); + if (!PEAR::isError($channel)) { + $mirror = $this->config->get('preferred_mirror'); + if ($channel->getMirror($mirror)) { + if ($channel->supports('xmlrpc', $method, $mirror)) { + $server_channel = $server_host = $mirror; // use the preferred mirror + $server_port = $channel->getPort($mirror); + } elseif (!$channel->supports('xmlrpc', $method)) { + return $this->raiseError("Channel $server_channel does not " . + "support xml-rpc method $method"); + } + } + if (!isset($server_host)) { + if (!$channel->supports('xmlrpc', $method)) { + return $this->raiseError("Channel $server_channel does not support " . + "xml-rpc method $method"); + } else { + $server_host = $server_channel; + $server_port = $channel->getPort(); + } + } + } else { + return $this->raiseError("Unknown channel '$server_channel'"); + } + + array_unshift($_args, $server_channel); // cache by channel + $this->cache = $this->getCache($_args); + $cachettl = $this->config->get('cache_ttl'); + // If cache is newer than $cachettl seconds, we use the cache! + if ($this->cache !== null && $this->cache['age'] < $cachettl) { + return $this->cache['content']; + } + $fp = false; + if (extension_loaded("xmlrpc")) { + $result = call_user_func_array(array(&$this, 'call_epi'), $args); + if (!PEAR::isError($result)) { + $this->saveCache($_args, $result); + } + return $result; + } elseif (!($fp = fopen('XML/RPC.php', 'r', true))) { + return $this->raiseError("For this remote PEAR operation you need to load the xmlrpc extension or install XML_RPC"); + } + include_once 'XML/RPC.php'; + if ($fp) { + fclose($fp); + } + + array_shift($args); + $username = $this->config->get('username'); + $password = $this->config->get('password'); + $eargs = array(); + foreach($args as $arg) { + $eargs[] = $this->_encode($arg); + } + $f = new XML_RPC_Message($method, $eargs); + if ($this->cache !== null) { + $maxAge = '?maxAge='.$this->cache['lastChange']; + } else { + $maxAge = ''; + } + $proxy_host = $proxy_port = $proxy_user = $proxy_pass = ''; + if ($proxy = parse_url($this->config->get('http_proxy'))) { + $proxy_host = isset($proxy['host']) ? $proxy['host'] : null; + if (isset($proxy['scheme']) && $proxy['scheme'] == 'https') { + $proxy_host = 'https://' . $proxy_host; + } + $proxy_port = isset($proxy['port']) ? $proxy['port'] : 8080; + $proxy_user = isset($proxy['user']) ? urldecode($proxy['user']) : null; + $proxy_pass = isset($proxy['pass']) ? urldecode($proxy['pass']) : null; + } + $shost = $server_host; + if ($channel->getSSL()) { + $shost = "https://$shost"; + } + $c = new XML_RPC_Client('/' . $channel->getPath('xmlrpc') + . $maxAge, $shost, $server_port, $proxy_host, $proxy_port, + $proxy_user, $proxy_pass); + if ($username && $password) { + $c->setCredentials($username, $password); + } + if ($this->config->get('verbose') >= 3) { + $c->setDebug(1); + } + $r = $c->send($f); + if (!$r) { + return $this->raiseError("XML_RPC send failed"); + } + $v = $r->value(); + if ($e = $r->faultCode()) { + if ($e == $GLOBALS['XML_RPC_err']['http_error'] && strstr($r->faultString(), '304 Not Modified') !== false) { + return $this->cache['content']; + } + return $this->raiseError($r->faultString(), $e); + } + + $result = XML_RPC_decode($v); + $this->saveCache($_args, $result); + return $result; + } + + // }}} + + // {{{ call_epi(method, [args...]) + + function call_epi($method) + { + if (!extension_loaded("xmlrpc")) { + return $this->raiseError("xmlrpc extension is not loaded"); + } + $server_channel = $this->config->get('default_channel'); + $channel = $this->_registry->getChannel($server_channel); + if (!PEAR::isError($channel)) { + $mirror = $this->config->get('preferred_mirror'); + if ($channel->getMirror($mirror)) { + if ($channel->supports('xmlrpc', $method, $mirror)) { + $server_channel = $server_host = $mirror; // use the preferred mirror + $server_port = $channel->getPort($mirror); + } elseif (!$channel->supports('xmlrpc', $method)) { + return $this->raiseError("Channel $server_channel does not " . + "support xml-rpc method $method"); + } + } + if (!isset($server_host)) { + if (!$channel->supports('xmlrpc', $method)) { + return $this->raiseError("Channel $server_channel does not support " . + "xml-rpc method $method"); + } else { + $server_host = $server_channel; + $server_port = $channel->getPort(); + } + } + } else { + return $this->raiseError("Unknown channel '$server_channel'"); + } + $params = func_get_args(); + array_shift($params); + $method = str_replace("_", ".", $method); + $request = xmlrpc_encode_request($method, $params); + if ($http_proxy = $this->config->get('http_proxy')) { + $proxy = parse_url($http_proxy); + $proxy_host = $proxy_port = $proxy_user = $proxy_pass = ''; + $proxy_host = isset($proxy['host']) ? $proxy['host'] : null; + if (isset($proxy['scheme']) && $proxy['scheme'] == 'https') { + $proxy_host = 'https://' . $proxy_host; + } + $proxy_port = isset($proxy['port']) ? $proxy['port'] : null; + $proxy_user = isset($proxy['user']) ? urldecode($proxy['user']) : null; + $proxy_pass = isset($proxy['pass']) ? urldecode($proxy['pass']) : null; + $fp = @fsockopen($proxy_host, $proxy_port); + $use_proxy = true; + if ($channel->getSSL()) { + $server_host = "https://$server_host"; + } + } else { + $use_proxy = false; + $ssl = $channel->getSSL(); + $fp = @fsockopen(($ssl ? 'ssl://' : '') . $server_host, $server_port); + if (!$fp) { + $server_host = "$ssl$server_host"; // for error-reporting + } + } + if (!$fp && $http_proxy) { + return $this->raiseError("PEAR_Remote::call: fsockopen(`$proxy_host', $proxy_port) failed"); + } elseif (!$fp) { + return $this->raiseError("PEAR_Remote::call: fsockopen(`$server_host', $server_port) failed"); + } + $len = strlen($request); + $req_headers = "Host: $server_host:$server_port\r\n" . + "Content-type: text/xml\r\n" . + "Content-length: $len\r\n"; + $username = $this->config->get('username'); + $password = $this->config->get('password'); + if ($username && $password) { + $req_headers .= "Cookie: PEAR_USER=$username; PEAR_PW=$password\r\n"; + $tmp = base64_encode("$username:$password"); + $req_headers .= "Authorization: Basic $tmp\r\n"; + } + if ($this->cache !== null) { + $maxAge = '?maxAge='.$this->cache['lastChange']; + } else { + $maxAge = ''; + } + + if ($use_proxy && $proxy_host != '' && $proxy_user != '') { + $req_headers .= 'Proxy-Authorization: Basic ' + .base64_encode($proxy_user.':'.$proxy_pass) + ."\r\n"; + } + + if ($this->config->get('verbose') > 3) { + print "XMLRPC REQUEST HEADERS:\n"; + var_dump($req_headers); + print "XMLRPC REQUEST BODY:\n"; + var_dump($request); + } + + if ($use_proxy && $proxy_host != '') { + $post_string = "POST http://".$server_host; + if ($proxy_port > '') { + $post_string .= ':'.$server_port; + } + } else { + $post_string = "POST "; + } + + $path = '/' . $channel->getPath('xmlrpc'); + fwrite($fp, ($post_string . $path . "$maxAge HTTP/1.0\r\n$req_headers\r\n$request")); + $response = ''; + $line1 = fgets($fp, 2048); + if (!preg_match('!^HTTP/[0-9\.]+ (\d+) (.*)!', $line1, $matches)) { + return $this->raiseError("PEAR_Remote: invalid HTTP response from XML-RPC server"); + } + switch ($matches[1]) { + case "200": // OK + break; + case "304": // Not Modified + return $this->cache['content']; + case "401": // Unauthorized + if ($username && $password) { + return $this->raiseError("PEAR_Remote ($server_host:$server_port) " . + ": authorization failed", 401); + } else { + return $this->raiseError("PEAR_Remote ($server_host:$server_port) " . + ": authorization required, please log in first", 401); + } + default: + return $this->raiseError("PEAR_Remote ($server_host:$server_port) : " . + "unexpected HTTP response", (int)$matches[1], null, null, + "$matches[1] $matches[2]"); + } + while (trim(fgets($fp, 2048)) != ''); // skip rest of headers + while ($chunk = fread($fp, 10240)) { + $response .= $chunk; + } + fclose($fp); + if ($this->config->get('verbose') > 3) { + print "XMLRPC RESPONSE:\n"; + var_dump($response); + } + $ret = xmlrpc_decode($response); + if (is_array($ret) && isset($ret['__PEAR_TYPE__'])) { + if ($ret['__PEAR_TYPE__'] == 'error') { + if (isset($ret['__PEAR_CLASS__'])) { + $class = $ret['__PEAR_CLASS__']; + } else { + $class = "PEAR_Error"; + } + if ($ret['code'] === '') $ret['code'] = null; + if ($ret['message'] === '') $ret['message'] = null; + if ($ret['userinfo'] === '') $ret['userinfo'] = null; + if (strtolower($class) == 'db_error') { + $ret = $this->raiseError(PEAR::errorMessage($ret['code']), + $ret['code'], null, null, + $ret['userinfo']); + } else { + $ret = $this->raiseError($ret['message'], $ret['code'], + null, null, $ret['userinfo']); + } + } + } elseif (is_array($ret) && sizeof($ret) == 1 && isset($ret[0]) + && is_array($ret[0]) && + !empty($ret[0]['faultString']) && + !empty($ret[0]['faultCode'])) { + extract($ret[0]); + $faultString = "XML-RPC Server Fault: " . + str_replace("\n", " ", $faultString); + return $this->raiseError($faultString, $faultCode); + } elseif (is_array($ret) && sizeof($ret) == 2 && !empty($ret['faultString']) && + !empty($ret['faultCode'])) { + extract($ret); + $faultString = "XML-RPC Server Fault: " . + str_replace("\n", " ", $faultString); + return $this->raiseError($faultString, $faultCode); + } + return $ret; + } + + // }}} + + // {{{ _encode + + // a slightly extended version of XML_RPC_encode + function _encode($php_val) + { + global $XML_RPC_Boolean, $XML_RPC_Int, $XML_RPC_Double; + global $XML_RPC_String, $XML_RPC_Array, $XML_RPC_Struct; + + $type = gettype($php_val); + $xmlrpcval = new XML_RPC_Value; + + switch($type) { + case "array": + reset($php_val); + $firstkey = key($php_val); + end($php_val); + $lastkey = key($php_val); + reset($php_val); + if ($firstkey === 0 && is_int($lastkey) && + ($lastkey + 1) == count($php_val)) { + $is_continuous = true; + reset($php_val); + $size = count($php_val); + for ($expect = 0; $expect < $size; $expect++, next($php_val)) { + if (key($php_val) !== $expect) { + $is_continuous = false; + break; + } + } + if ($is_continuous) { + reset($php_val); + $arr = array(); + while (list($k, $v) = each($php_val)) { + $arr[$k] = $this->_encode($v); + } + $xmlrpcval->addArray($arr); + break; + } + } + // fall though if not numerical and continuous + case "object": + $arr = array(); + while (list($k, $v) = each($php_val)) { + $arr[$k] = $this->_encode($v); + } + $xmlrpcval->addStruct($arr); + break; + case "integer": + $xmlrpcval->addScalar($php_val, $XML_RPC_Int); + break; + case "double": + $xmlrpcval->addScalar($php_val, $XML_RPC_Double); + break; + case "string": + case "NULL": + $xmlrpcval->addScalar($php_val, $XML_RPC_String); + break; + case "boolean": + $xmlrpcval->addScalar($php_val, $XML_RPC_Boolean); + break; + case "unknown type": + default: + return null; + } + return $xmlrpcval; + } + + // }}} + +} + +?> diff --git a/src/lib/pear/PEAR/PEAR/RunTest.php b/src/lib/pear/PEAR/PEAR/RunTest.php new file mode 100644 index 0000000..85f49d9 --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/RunTest.php @@ -0,0 +1,927 @@ + + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: RunTest.php,v 1.67 2008/05/14 02:30:16 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 1.3.3 + */ + +/** + * for error handling + */ +require_once 'PEAR.php'; +require_once 'PEAR/Config.php'; + +define('DETAILED', 1); +putenv("PHP_PEAR_RUNTESTS=1"); + +/** + * Simplified version of PHP's test suite + * + * Try it with: + * + * $ php -r 'include "../PEAR/RunTest.php"; $t=new PEAR_RunTest; $o=$t->run("./pear_system.phpt");print_r($o);' + * + * + * @category pear + * @package PEAR + * @author Tomas V.V.Cox + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 1.3.3 + */ +class PEAR_RunTest +{ + var $_headers = array(); + var $_logger; + var $_options; + var $_php; + var $tests_count; + var $xdebug_loaded; + /** + * Saved value of php executable, used to reset $_php when we + * have a test that uses cgi + * + * @var unknown_type + */ + var $_savephp; + var $ini_overwrites = array( + 'output_handler=', + 'open_basedir=', + 'safe_mode=0', + 'disable_functions=', + 'output_buffering=Off', + 'display_errors=1', + 'log_errors=0', + 'html_errors=0', + 'track_errors=1', + 'report_memleaks=0', + 'report_zend_debug=0', + 'docref_root=', + 'docref_ext=.html', + 'error_prepend_string=', + 'error_append_string=', + 'auto_prepend_file=', + 'auto_append_file=', + 'magic_quotes_runtime=0', + 'xdebug.default_enable=0', + 'allow_url_fopen=1', + ); + + /** + * An object that supports the PEAR_Common->log() signature, or null + * @param PEAR_Common|null + */ + function PEAR_RunTest($logger = null, $options = array()) + { + if (!defined('E_DEPRECATED')) { + define('E_DEPRECATED', 0); + } + if (!defined('E_STRICT')) { + define('E_STRICT', 0); + } + $this->ini_overwrites[] = 'error_reporting=' . (E_ALL & ~(E_DEPRECATED | E_STRICT)); + if (is_null($logger)) { + require_once 'PEAR/Common.php'; + $logger = new PEAR_Common; + } + $this->_logger = $logger; + $this->_options = $options; + + $conf = &PEAR_Config::singleton(); + $this->_php = $conf->get('php_bin'); + } + + /** + * Taken from php-src/run-tests.php + * + * @param string $commandline command name + * @param array $env + * @param string $stdin standard input to pass to the command + * @return unknown + */ + function system_with_timeout($commandline, $env = null, $stdin = null) + { + $data = ''; + if (version_compare(phpversion(), '5.0.0', '<')) { + $proc = proc_open($commandline, array( + 0 => array('pipe', 'r'), + 1 => array('pipe', 'w'), + 2 => array('pipe', 'w') + ), $pipes); + } else { + $proc = proc_open($commandline, array( + 0 => array('pipe', 'r'), + 1 => array('pipe', 'w'), + 2 => array('pipe', 'w') + ), $pipes, null, $env, array('suppress_errors' => true)); + } + + if (!$proc) { + return false; + } + + if (is_string($stdin)) { + fwrite($pipes[0], $stdin); + } + fclose($pipes[0]); + + while (true) { + /* hide errors from interrupted syscalls */ + $r = $pipes; + $e = $w = null; + $n = @stream_select($r, $w, $e, 60); + + if ($n === 0) { + /* timed out */ + $data .= "\n ** ERROR: process timed out **\n"; + proc_terminate($proc); + return array(1234567890, $data); + } else if ($n > 0) { + $line = fread($pipes[1], 8192); + if (strlen($line) == 0) { + /* EOF */ + break; + } + $data .= $line; + } + } + if (function_exists('proc_get_status')) { + $stat = proc_get_status($proc); + if ($stat['signaled']) { + $data .= "\nTermsig=".$stat['stopsig']; + } + } + $code = proc_close($proc); + if (function_exists('proc_get_status')) { + $code = $stat['exitcode']; + } + return array($code, $data); + } + + /** + * Turns a PHP INI string into an array + * + * Turns -d "include_path=/foo/bar" into this: + * array( + * 'include_path' => array( + * 'operator' => '-d', + * 'value' => '/foo/bar', + * ) + * ) + * Works both with quotes and without + * + * @param string an PHP INI string, -d "include_path=/foo/bar" + * @return array + */ + function iniString2array($ini_string) + { + if (!$ini_string) { + return array(); + } + $split = preg_split('/[\s]|=/', $ini_string, -1, PREG_SPLIT_NO_EMPTY); + $key = $split[1][0] == '"' ? substr($split[1], 1) : $split[1]; + $value = $split[2][strlen($split[2]) - 1] == '"' ? substr($split[2], 0, -1) : $split[2]; + // FIXME review if this is really the struct to go with + $array = array($key => array('operator' => $split[0], 'value' => $value)); + return $array; + } + + function settings2array($settings, $ini_settings) + { + foreach ($settings as $setting) { + if (strpos($setting, '=') !== false) { + $setting = explode('=', $setting, 2); + $name = trim(strtolower($setting[0])); + $value = trim($setting[1]); + $ini_settings[$name] = $value; + } + } + return $ini_settings; + } + + function settings2params($ini_settings) + { + $settings = ''; + foreach ($ini_settings as $name => $value) { + if (is_array($value)) { + $operator = $value['operator']; + $value = $value['value']; + } else { + $operator = '-d'; + } + $value = addslashes($value); + $settings .= " $operator \"$name=$value\""; + } + return $settings; + } + + function runPHPUnit($file, $ini_settings = '') + { + if (!file_exists($file) && file_exists(getcwd() . DIRECTORY_SEPARATOR . $file)) { + $file = realpath(getcwd() . DIRECTORY_SEPARATOR . $file); + break; + } elseif (file_exists($file)) { + $file = realpath($file); + } + $cmd = "$this->_php$ini_settings -f $file"; + if (isset($this->_logger)) { + $this->_logger->log(2, 'Running command "' . $cmd . '"'); + } + + $savedir = getcwd(); // in case the test moves us around + chdir(dirname($file)); + echo `$cmd`; + chdir($savedir); + return 'PASSED'; // we have no way of knowing this information so assume passing + } + + /** + * Runs an individual test case. + * + * @param string The filename of the test + * @param array|string INI settings to be applied to the test run + * @param integer Number what the current running test is of the + * whole test suite being runned. + * + * @return string|object Returns PASSED, WARNED, FAILED depending on how the + * test came out. + * PEAR Error when the tester it self fails + */ + function run($file, $ini_settings = array(), $test_number = 1) + { + if (isset($this->_savephp)) { + $this->_php = $this->_savephp; + unset($this->_savephp); + } + if (empty($this->_options['cgi'])) { + // try to see if php-cgi is in the path + $res = $this->system_with_timeout('php-cgi -v'); + if (false !== $res && !(is_array($res) && $res === array(127, ''))) { + $this->_options['cgi'] = 'php-cgi'; + } + } + if (1 < $len = strlen($this->tests_count)) { + $test_number = str_pad($test_number, $len, ' ', STR_PAD_LEFT); + $test_nr = "[$test_number/$this->tests_count] "; + } else { + $test_nr = ''; + } + + $file = realpath($file); + $section_text = $this->_readFile($file); + if (PEAR::isError($section_text)) { + return $section_text; + } + + if (isset($section_text['POST_RAW']) && isset($section_text['UPLOAD'])) { + return PEAR::raiseError("Cannot contain both POST_RAW and UPLOAD in test file: $file"); + } + + $cwd = getcwd(); + + $pass_options = ''; + if (!empty($this->_options['ini'])) { + $pass_options = $this->_options['ini']; + } + + if (is_string($ini_settings)) { + $ini_settings = $this->iniString2array($ini_settings); + } + + $ini_settings = $this->settings2array($this->ini_overwrites, $ini_settings); + if ($section_text['INI']) { + if (strpos($section_text['INI'], '{PWD}') !== false) { + $section_text['INI'] = str_replace('{PWD}', dirname($file), $section_text['INI']); + } + $ini = preg_split( "/[\n\r]+/", $section_text['INI']); + $ini_settings = $this->settings2array($ini, $ini_settings); + } + $ini_settings = $this->settings2params($ini_settings); + $shortname = str_replace($cwd . DIRECTORY_SEPARATOR, '', $file); + + $tested = trim($section_text['TEST']); + $tested.= !isset($this->_options['simple']) ? "[$shortname]" : ' '; + + if (!empty($section_text['POST']) || !empty($section_text['POST_RAW']) || + !empty($section_text['UPLOAD']) || !empty($section_text['GET']) || + !empty($section_text['COOKIE']) || !empty($section_text['EXPECTHEADERS'])) { + if (empty($this->_options['cgi'])) { + if (!isset($this->_options['quiet'])) { + $this->_logger->log(0, "SKIP $test_nr$tested (reason: --cgi option needed for this test, type 'pear help run-tests')"); + } + if (isset($this->_options['tapoutput'])) { + return array('ok', ' # skip --cgi option needed for this test, "pear help run-tests" for info'); + } + return 'SKIPPED'; + } + $this->_savephp = $this->_php; + $this->_php = $this->_options['cgi']; + } + + $temp_dir = realpath(dirname($file)); + $main_file_name = basename($file, 'phpt'); + $diff_filename = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'diff'; + $log_filename = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'log'; + $exp_filename = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'exp'; + $output_filename = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'out'; + $memcheck_filename = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'mem'; + $temp_file = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'php'; + $temp_skipif = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'skip.php'; + $temp_clean = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'clean.php'; + $tmp_post = $temp_dir . DIRECTORY_SEPARATOR . uniqid('phpt.'); + + // unlink old test results + $this->_cleanupOldFiles($file); + + // Check if test should be skipped. + $res = $this->_runSkipIf($section_text, $temp_skipif, $tested, $ini_settings); + if (count($res) != 2) { + return $res; + } + $info = $res['info']; + $warn = $res['warn']; + + // We've satisfied the preconditions - run the test! + if (isset($this->_options['coverage']) && $this->xdebug_loaded) { + $len_f = 5; + if (substr($section_text['FILE'], 0, 5) != '')); + $xdebug_file = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name . 'xdebug'; + $text .= "\n" . + "\n" . '$xdebug = var_export(xdebug_get_code_coverage(), true);'; + if (!function_exists('file_put_contents')) { + $text .= "\n" . '$fh = fopen(\'' . $xdebug_file . '\', "wb");' . + "\n" . 'if ($fh !== false) {' . + "\n" . ' fwrite($fh, $xdebug);' . + "\n" . ' fclose($fh);' . + "\n" . '}'; + } else { + $text .= "\n" . 'file_put_contents(\'' . $xdebug_file . '\', $xdebug);'; + } + $text .= "\n" . 'xdebug_stop_code_coverage();' . "\n" . '?>'; + + $this->save_text($temp_file, $text); + } else { + $this->save_text($temp_file, $section_text['FILE']); + } + + $args = $section_text['ARGS'] ? ' -- '.$section_text['ARGS'] : ''; + $cmd = "$this->_php$ini_settings -f \"$temp_file\" $args 2>&1"; + if (isset($this->_logger)) { + $this->_logger->log(2, 'Running command "' . $cmd . '"'); + } + + // Reset environment from any previous test. + $env = $this->_resetEnv($section_text, $temp_file); + + $section_text = $this->_processUpload($section_text, $file); + if (PEAR::isError($section_text)) { + return $section_text; + } + + if (array_key_exists('POST_RAW', $section_text) && !empty($section_text['POST_RAW'])) { + $post = trim($section_text['POST_RAW']); + $raw_lines = explode("\n", $post); + + $request = ''; + $started = false; + foreach ($raw_lines as $i => $line) { + if (empty($env['CONTENT_TYPE']) && + preg_match('/^Content-Type:(.*)/i', $line, $res)) { + $env['CONTENT_TYPE'] = trim(str_replace("\r", '', $res[1])); + continue; + } + if ($started) { + $request .= "\n"; + } + $started = true; + $request .= $line; + } + + $env['CONTENT_LENGTH'] = strlen($request); + $env['REQUEST_METHOD'] = 'POST'; + + $this->save_text($tmp_post, $request); + $cmd = "$this->_php$pass_options$ini_settings \"$temp_file\" 2>&1 < $tmp_post"; + } elseif (array_key_exists('POST', $section_text) && !empty($section_text['POST'])) { + $post = trim($section_text['POST']); + $this->save_text($tmp_post, $post); + $content_length = strlen($post); + + $env['REQUEST_METHOD'] = 'POST'; + $env['CONTENT_TYPE'] = 'application/x-www-form-urlencoded'; + $env['CONTENT_LENGTH'] = $content_length; + + $cmd = "$this->_php$pass_options$ini_settings \"$temp_file\" 2>&1 < $tmp_post"; + } else { + $env['REQUEST_METHOD'] = 'GET'; + $env['CONTENT_TYPE'] = ''; + $env['CONTENT_LENGTH'] = ''; + } + + if (OS_WINDOWS && isset($section_text['RETURNS'])) { + ob_start(); + system($cmd, $return_value); + $out = ob_get_contents(); + ob_end_clean(); + $section_text['RETURNS'] = (int) trim($section_text['RETURNS']); + $returnfail = ($return_value != $section_text['RETURNS']); + } else { + $returnfail = false; + $stdin = isset($section_text['STDIN']) ? $section_text['STDIN'] : null; + $out = $this->system_with_timeout($cmd, $env, $stdin); + $return_value = $out[0]; + $out = $out[1]; + } + + $output = preg_replace('/\r\n/', "\n", trim($out)); + + if (isset($tmp_post) && realpath($tmp_post) && file_exists($tmp_post)) { + @unlink(realpath($tmp_post)); + } + chdir($cwd); // in case the test moves us around + + $this->_testCleanup($section_text, $temp_clean); + + /* when using CGI, strip the headers from the output */ + $output = $this->_stripHeadersCGI($output); + + if (isset($section_text['EXPECTHEADERS'])) { + $testheaders = $this->_processHeaders($section_text['EXPECTHEADERS']); + $missing = array_diff_assoc($testheaders, $this->_headers); + $changed = ''; + foreach ($missing as $header => $value) { + if (isset($this->_headers[$header])) { + $changed .= "-$header: $value\n+$header: "; + $changed .= $this->_headers[$header]; + } else { + $changed .= "-$header: $value\n"; + } + } + if ($missing) { + // tack on failed headers to output: + $output .= "\n====EXPECTHEADERS FAILURE====:\n$changed"; + } + } + // Does the output match what is expected? + do { + if (isset($section_text['EXPECTF']) || isset($section_text['EXPECTREGEX'])) { + if (isset($section_text['EXPECTF'])) { + $wanted = trim($section_text['EXPECTF']); + } else { + $wanted = trim($section_text['EXPECTREGEX']); + } + $wanted_re = preg_replace('/\r\n/', "\n", $wanted); + if (isset($section_text['EXPECTF'])) { + $wanted_re = preg_quote($wanted_re, '/'); + // Stick to basics + $wanted_re = str_replace("%s", ".+?", $wanted_re); //not greedy + $wanted_re = str_replace("%i", "[+\-]?[0-9]+", $wanted_re); + $wanted_re = str_replace("%d", "[0-9]+", $wanted_re); + $wanted_re = str_replace("%x", "[0-9a-fA-F]+", $wanted_re); + $wanted_re = str_replace("%f", "[+\-]?\.?[0-9]+\.?[0-9]*(E-?[0-9]+)?", $wanted_re); + $wanted_re = str_replace("%c", ".", $wanted_re); + // %f allows two points "-.0.0" but that is the best *simple* expression + } + /* DEBUG YOUR REGEX HERE + var_dump($wanted_re); + print(str_repeat('=', 80) . "\n"); + var_dump($output); + */ + if (!$returnfail && preg_match("/^$wanted_re\$/s", $output)) { + if (file_exists($temp_file)) { + unlink($temp_file); + } + if (array_key_exists('FAIL', $section_text)) { + break; + } + if (!isset($this->_options['quiet'])) { + $this->_logger->log(0, "PASS $test_nr$tested$info"); + } + if (isset($this->_options['tapoutput'])) { + return array('ok', ' - ' . $tested); + } + return 'PASSED'; + } + } else { + if (isset($section_text['EXPECTFILE'])) { + $f = $temp_dir . '/' . trim($section_text['EXPECTFILE']); + if (!($fp = @fopen($f, 'rb'))) { + return PEAR::raiseError('--EXPECTFILE-- section file ' . + $f . ' not found'); + } + fclose($fp); + $section_text['EXPECT'] = file_get_contents($f); + } + $wanted = preg_replace('/\r\n/', "\n", trim($section_text['EXPECT'])); + // compare and leave on success + if (!$returnfail && 0 == strcmp($output, $wanted)) { + if (file_exists($temp_file)) { + unlink($temp_file); + } + if (array_key_exists('FAIL', $section_text)) { + break; + } + if (!isset($this->_options['quiet'])) { + $this->_logger->log(0, "PASS $test_nr$tested$info"); + } + if (isset($this->_options['tapoutput'])) { + return array('ok', ' - ' . $tested); + } + return 'PASSED'; + } + } + } while (false); + + if (array_key_exists('FAIL', $section_text)) { + // we expect a particular failure + // this is only used for testing PEAR_RunTest + $expectf = isset($section_text['EXPECTF']) ? $wanted_re : null; + $faildiff = $this->generate_diff($wanted, $output, null, $expectf); + $faildiff = preg_replace('/\r/', '', $faildiff); + $wanted = preg_replace('/\r/', '', trim($section_text['FAIL'])); + if ($faildiff == $wanted) { + if (!isset($this->_options['quiet'])) { + $this->_logger->log(0, "PASS $test_nr$tested$info"); + } + if (isset($this->_options['tapoutput'])) { + return array('ok', ' - ' . $tested); + } + return 'PASSED'; + } + unset($section_text['EXPECTF']); + $output = $faildiff; + if (isset($section_text['RETURNS'])) { + return PEAR::raiseError('Cannot have both RETURNS and FAIL in the same test: ' . + $file); + } + } + + // Test failed so we need to report details. + $txt = $warn ? 'WARN ' : 'FAIL '; + $this->_logger->log(0, $txt . $test_nr . $tested . $info); + + // write .exp + $res = $this->_writeLog($exp_filename, $wanted); + if (PEAR::isError($res)) { + return $res; + } + + // write .out + $res = $this->_writeLog($output_filename, $output); + if (PEAR::isError($res)) { + return $res; + } + + // write .diff + $returns = isset($section_text['RETURNS']) ? + array(trim($section_text['RETURNS']), $return_value) : null; + $expectf = isset($section_text['EXPECTF']) ? $wanted_re : null; + $data = $this->generate_diff($wanted, $output, $returns, $expectf); + $res = $this->_writeLog($diff_filename, $data); + if (PEAR::isError($res)) { + return $res; + } + + // write .log + $data = " +---- EXPECTED OUTPUT +$wanted +---- ACTUAL OUTPUT +$output +---- FAILED +"; + + if ($returnfail) { + $data .= " +---- EXPECTED RETURN +$section_text[RETURNS] +---- ACTUAL RETURN +$return_value +"; + } + + $res = $this->_writeLog($log_filename, $data); + if (PEAR::isError($res)) { + return $res; + } + + if (isset($this->_options['tapoutput'])) { + $wanted = explode("\n", $wanted); + $wanted = "# Expected output:\n#\n#" . implode("\n#", $wanted); + $output = explode("\n", $output); + $output = "#\n#\n# Actual output:\n#\n#" . implode("\n#", $output); + return array($wanted . $output . 'not ok', ' - ' . $tested); + } + return $warn ? 'WARNED' : 'FAILED'; + } + + function generate_diff($wanted, $output, $rvalue, $wanted_re) + { + $w = explode("\n", $wanted); + $o = explode("\n", $output); + $wr = explode("\n", $wanted_re); + $w1 = array_diff_assoc($w, $o); + $o1 = array_diff_assoc($o, $w); + $o2 = $w2 = array(); + foreach ($w1 as $idx => $val) { + if (!$wanted_re || !isset($wr[$idx]) || !isset($o1[$idx]) || + !preg_match('/^' . $wr[$idx] . '\\z/', $o1[$idx])) { + $w2[sprintf("%03d<", $idx)] = sprintf("%03d- ", $idx + 1) . $val; + } + } + foreach ($o1 as $idx => $val) { + if (!$wanted_re || !isset($wr[$idx]) || + !preg_match('/^' . $wr[$idx] . '\\z/', $val)) { + $o2[sprintf("%03d>", $idx)] = sprintf("%03d+ ", $idx + 1) . $val; + } + } + $diff = array_merge($w2, $o2); + ksort($diff); + $extra = $rvalue ? "##EXPECTED: $rvalue[0]\r\n##RETURNED: $rvalue[1]" : ''; + return implode("\r\n", $diff) . $extra; + } + + // Write the given text to a temporary file, and return the filename. + function save_text($filename, $text) + { + if (!$fp = fopen($filename, 'w')) { + return PEAR::raiseError("Cannot open file '" . $filename . "' (save_text)"); + } + fwrite($fp, $text); + fclose($fp); + if (1 < DETAILED) echo " +FILE $filename {{{ +$text +}}} +"; + } + + function _cleanupOldFiles($file) + { + $temp_dir = realpath(dirname($file)); + $mainFileName = basename($file, 'phpt'); + $diff_filename = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'diff'; + $log_filename = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'log'; + $exp_filename = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'exp'; + $output_filename = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'out'; + $memcheck_filename = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'mem'; + $temp_file = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'php'; + $temp_skipif = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'skip.php'; + $temp_clean = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'clean.php'; + $tmp_post = $temp_dir . DIRECTORY_SEPARATOR . uniqid('phpt.'); + + // unlink old test results + @unlink($diff_filename); + @unlink($log_filename); + @unlink($exp_filename); + @unlink($output_filename); + @unlink($memcheck_filename); + @unlink($temp_file); + @unlink($temp_skipif); + @unlink($tmp_post); + @unlink($temp_clean); + } + + function _runSkipIf($section_text, $temp_skipif, $tested, $ini_settings) + { + $info = ''; + $warn = false; + if (array_key_exists('SKIPIF', $section_text) && trim($section_text['SKIPIF'])) { + $this->save_text($temp_skipif, $section_text['SKIPIF']); + $output = $this->system_with_timeout("$this->_php$ini_settings -f \"$temp_skipif\""); + $output = $output[1]; + $loutput = ltrim($output); + unlink($temp_skipif); + if (!strncasecmp('skip', $loutput, 4)) { + $skipreason = "SKIP $tested"; + if (preg_match('/^\s*skip\s*(.+)\s*/i', $output, $m)) { + $skipreason .= '(reason: ' . $m[1] . ')'; + } + if (!isset($this->_options['quiet'])) { + $this->_logger->log(0, $skipreason); + } + if (isset($this->_options['tapoutput'])) { + return array('ok', ' # skip ' . $reason); + } + return 'SKIPPED'; + } + + if (!strncasecmp('info', $loutput, 4) + && preg_match('/^\s*info\s*(.+)\s*/i', $output, $m)) { + $info = " (info: $m[1])"; + } + + if (!strncasecmp('warn', $loutput, 4) + && preg_match('/^\s*warn\s*(.+)\s*/i', $output, $m)) { + $warn = true; /* only if there is a reason */ + $info = " (warn: $m[1])"; + } + } + + return array('warn' => $warn, 'info' => $info); + } + + function _stripHeadersCGI($output) + { + $this->headers = array(); + if (!empty($this->_options['cgi']) && + $this->_php == $this->_options['cgi'] && + preg_match("/^(.*?)(?:\n\n(.*)|\\z)/s", $output, $match)) { + $output = isset($match[2]) ? trim($match[2]) : ''; + $this->_headers = $this->_processHeaders($match[1]); + } + + return $output; + } + + /** + * Return an array that can be used with array_diff() to compare headers + * + * @param string $text + */ + function _processHeaders($text) + { + $headers = array(); + $rh = preg_split("/[\n\r]+/", $text); + foreach ($rh as $line) { + if (strpos($line, ':')!== false) { + $line = explode(':', $line, 2); + $headers[trim($line[0])] = trim($line[1]); + } + } + return $headers; + } + + function _readFile($file) + { + // Load the sections of the test file. + $section_text = array( + 'TEST' => '(unnamed test)', + 'SKIPIF' => '', + 'GET' => '', + 'COOKIE' => '', + 'POST' => '', + 'ARGS' => '', + 'INI' => '', + 'CLEAN' => '', + ); + + if (!is_file($file) || !$fp = fopen($file, "r")) { + return PEAR::raiseError("Cannot open test file: $file"); + } + + $section = ''; + while (!feof($fp)) { + $line = fgets($fp); + + // Match the beginning of a section. + if (preg_match('/^--([_A-Z]+)--/', $line, $r)) { + $section = $r[1]; + $section_text[$section] = ''; + continue; + } elseif (empty($section)) { + fclose($fp); + return PEAR::raiseError("Invalid sections formats in test file: $file"); + } + + // Add to the section text. + $section_text[$section] .= $line; + } + fclose($fp); + + return $section_text; + } + + function _writeLog($logname, $data) + { + if (!$log = fopen($logname, 'w')) { + return PEAR::raiseError("Cannot create test log - $logname"); + } + fwrite($log, $data); + fclose($log); + } + + function _resetEnv($section_text, $temp_file) + { + $env = $_ENV; + $env['REDIRECT_STATUS'] = ''; + $env['QUERY_STRING'] = ''; + $env['PATH_TRANSLATED'] = ''; + $env['SCRIPT_FILENAME'] = ''; + $env['REQUEST_METHOD'] = ''; + $env['CONTENT_TYPE'] = ''; + $env['CONTENT_LENGTH'] = ''; + if (!empty($section_text['ENV'])) { + foreach (explode("\n", trim($section_text['ENV'])) as $e) { + $e = explode('=', trim($e), 2); + if (!empty($e[0]) && isset($e[1])) { + $env[$e[0]] = $e[1]; + } + } + } + if (array_key_exists('GET', $section_text)) { + $env['QUERY_STRING'] = trim($section_text['GET']); + } else { + $env['QUERY_STRING'] = ''; + } + if (array_key_exists('COOKIE', $section_text)) { + $env['HTTP_COOKIE'] = trim($section_text['COOKIE']); + } else { + $env['HTTP_COOKIE'] = ''; + } + $env['REDIRECT_STATUS'] = '1'; + $env['PATH_TRANSLATED'] = $temp_file; + $env['SCRIPT_FILENAME'] = $temp_file; + + return $env; + } + + function _processUpload($section_text, $file) + { + if (array_key_exists('UPLOAD', $section_text) && !empty($section_text['UPLOAD'])) { + $upload_files = trim($section_text['UPLOAD']); + $upload_files = explode("\n", $upload_files); + + $request = "Content-Type: multipart/form-data; boundary=---------------------------20896060251896012921717172737\n" . + "-----------------------------20896060251896012921717172737\n"; + foreach ($upload_files as $fileinfo) { + $fileinfo = explode('=', $fileinfo); + if (count($fileinfo) != 2) { + return PEAR::raiseError("Invalid UPLOAD section in test file: $file"); + } + if (!realpath(dirname($file) . '/' . $fileinfo[1])) { + return PEAR::raiseError("File for upload does not exist: $fileinfo[1] " . + "in test file: $file"); + } + $file_contents = file_get_contents(dirname($file) . '/' . $fileinfo[1]); + $fileinfo[1] = basename($fileinfo[1]); + $request .= "Content-Disposition: form-data; name=\"$fileinfo[0]\"; filename=\"$fileinfo[1]\"\n"; + $request .= "Content-Type: text/plain\n\n"; + $request .= $file_contents . "\n" . + "-----------------------------20896060251896012921717172737\n"; + } + + if (array_key_exists('POST', $section_text) && !empty($section_text['POST'])) { + // encode POST raw + $post = trim($section_text['POST']); + $post = explode('&', $post); + foreach ($post as $i => $post_info) { + $post_info = explode('=', $post_info); + if (count($post_info) != 2) { + return PEAR::raiseError("Invalid POST data in test file: $file"); + } + $post_info[0] = rawurldecode($post_info[0]); + $post_info[1] = rawurldecode($post_info[1]); + $post[$i] = $post_info; + } + foreach ($post as $post_info) { + $request .= "Content-Disposition: form-data; name=\"$post_info[0]\"\n\n"; + $request .= $post_info[1] . "\n" . + "-----------------------------20896060251896012921717172737\n"; + } + unset($section_text['POST']); + } + $section_text['POST_RAW'] = $request; + } + + return $section_text; + } + + function _testCleanup($section_text, $temp_clean) + { + if ($section_text['CLEAN']) { + // perform test cleanup + $this->save_text($temp_clean, $section_text['CLEAN']); + $this->system_with_timeout("$this->_php $temp_clean"); + if (file_exists($temp_clean)) { + unlink($temp_clean); + } + } + } +} \ No newline at end of file diff --git a/src/lib/pear/PEAR/PEAR/Task/Common.php b/src/lib/pear/PEAR/PEAR/Task/Common.php new file mode 100644 index 0000000..5841f28 --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Task/Common.php @@ -0,0 +1,208 @@ + + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: Common.php,v 1.18 2008/05/13 21:28:20 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 1.4.0a1 + */ +/**#@+ + * Error codes for task validation routines + */ +define('PEAR_TASK_ERROR_NOATTRIBS', 1); +define('PEAR_TASK_ERROR_MISSING_ATTRIB', 2); +define('PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE', 3); +define('PEAR_TASK_ERROR_INVALID', 4); +/**#@-*/ +define('PEAR_TASK_PACKAGE', 1); +define('PEAR_TASK_INSTALL', 2); +define('PEAR_TASK_PACKAGEANDINSTALL', 3); +/** + * A task is an operation that manipulates the contents of a file. + * + * Simple tasks operate on 1 file. Multiple tasks are executed after all files have been + * processed and installed, and are designed to operate on all files containing the task. + * The Post-install script task simply takes advantage of the fact that it will be run + * after installation, replace is a simple task. + * + * Combining tasks is possible, but ordering is significant. + * + * + * + * + * + * + * This will first replace any instance of @data-dir@ in the test.php file + * with the path to the current data directory. Then, it will include the + * test.php file and run the script it contains to configure the package post-installation. + * @category pear + * @package PEAR + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 1.4.0a1 + * @abstract + */ +class PEAR_Task_Common +{ + /** + * Valid types for this version are 'simple' and 'multiple' + * + * - simple tasks operate on the contents of a file and write out changes to disk + * - multiple tasks operate on the contents of many files and write out the + * changes directly to disk + * + * Child task classes must override this property. + * @access protected + */ + var $type = 'simple'; + /** + * Determines which install phase this task is executed under + */ + var $phase = PEAR_TASK_INSTALL; + /** + * @access protected + */ + var $config; + /** + * @access protected + */ + var $registry; + /** + * @access protected + */ + var $logger; + /** + * @access protected + */ + var $installphase; + /** + * @param PEAR_Config + * @param PEAR_Common + */ + function PEAR_Task_Common(&$config, &$logger, $phase) + { + $this->config = &$config; + $this->registry = &$config->getRegistry(); + $this->logger = &$logger; + $this->installphase = $phase; + if ($this->type == 'multiple') { + $GLOBALS['_PEAR_TASK_POSTINSTANCES'][get_class($this)][] = &$this; + } + } + + /** + * Validate the basic contents of a task tag. + * @param PEAR_PackageFile_v2 + * @param array + * @param PEAR_Config + * @param array the entire parsed tag + * @return true|array On error, return an array in format: + * array(PEAR_TASK_ERROR_???[, param1][, param2][, ...]) + * + * For PEAR_TASK_ERROR_MISSING_ATTRIB, pass the attribute name in + * For PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE, pass the attribute name and an array + * of legal values in + * @static + * @abstract + */ + function validateXml($pkg, $xml, $config, $fileXml) + { + } + + /** + * Initialize a task instance with the parameters + * @param array raw, parsed xml + * @param array attributes from the tag containing this task + * @param string|null last installed version of this package + * @abstract + */ + function init($xml, $fileAttributes, $lastVersion) + { + } + + /** + * Begin a task processing session. All multiple tasks will be processed after each file + * has been successfully installed, all simple tasks should perform their task here and + * return any errors using the custom throwError() method to allow forward compatibility + * + * This method MUST NOT write out any changes to disk + * @param PEAR_PackageFile_v2 + * @param string file contents + * @param string the eventual final file location (informational only) + * @return string|false|PEAR_Error false to skip this file, PEAR_Error to fail + * (use $this->throwError), otherwise return the new contents + * @abstract + */ + function startSession($pkg, $contents, $dest) + { + } + + /** + * This method is used to process each of the tasks for a particular multiple class + * type. Simple tasks need not implement this method. + * @param array an array of tasks + * @access protected + * @static + * @abstract + */ + function run($tasks) + { + } + + /** + * @static + * @final + */ + function hasPostinstallTasks() + { + return isset($GLOBALS['_PEAR_TASK_POSTINSTANCES']); + } + + /** + * @static + * @final + */ + function runPostinstallTasks() + { + foreach ($GLOBALS['_PEAR_TASK_POSTINSTANCES'] as $class => $tasks) { + $err = call_user_func(array($class, 'run'), + $GLOBALS['_PEAR_TASK_POSTINSTANCES'][$class]); + if ($err) { + return PEAR_Task_Common::throwError($err); + } + } + unset($GLOBALS['_PEAR_TASK_POSTINSTANCES']); + } + + /** + * Determines whether a role is a script + * @return bool + */ + function isScript() + { + return $this->type == 'script'; + } + + function throwError($msg, $code = -1) + { + include_once 'PEAR.php'; + return PEAR::raiseError($msg, $code); + } +} +?> \ No newline at end of file diff --git a/src/lib/pear/PEAR/PEAR/Task/Postinstallscript.php b/src/lib/pear/PEAR/PEAR/Task/Postinstallscript.php new file mode 100644 index 0000000..024c058 --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Task/Postinstallscript.php @@ -0,0 +1,329 @@ + + * + * PHP versions 4 and 5 + * + * LICENSE: This source file is subject to version 3.0 of the PHP license + * that is available through the world-wide-web at the following URI: + * http://www.php.net/license/3_0.txt. If you did not receive a copy of + * the PHP License and are unable to obtain it through the web, please + * send a note to license@php.net so we can mail you a copy immediately. + * + * @category pear + * @package PEAR + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: Postinstallscript.php,v 1.20 2008/05/13 21:28:20 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 1.4.0a1 + */ +/** + * Base class + */ +require_once 'PEAR/Task/Common.php'; +/** + * Implements the postinstallscript file task. + * + * Note that post-install scripts are handled separately from installation, by the + * "pear run-scripts" command + * @category pear + * @package PEAR + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 1.4.0a1 + */ +class PEAR_Task_Postinstallscript extends PEAR_Task_Common +{ + var $type = 'script'; + var $_class; + var $_params; + var $_obj; + /** + * + * @var PEAR_PackageFile_v2 + */ + var $_pkg; + var $_contents; + var $phase = PEAR_TASK_INSTALL; + + /** + * Validate the raw xml at parsing-time. + * + * This also attempts to validate the script to make sure it meets the criteria + * for a post-install script + * @param PEAR_PackageFile_v2 + * @param array The XML contents of the tag + * @param PEAR_Config + * @param array the entire parsed tag + * @static + */ + function validateXml($pkg, $xml, $config, $fileXml) + { + if ($fileXml['role'] != 'php') { + return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' . + $fileXml['name'] . '" must be role="php"'); + } + PEAR::pushErrorHandling(PEAR_ERROR_RETURN); + $file = $pkg->getFileContents($fileXml['name']); + if (PEAR::isError($file)) { + PEAR::popErrorHandling(); + return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' . + $fileXml['name'] . '" is not valid: ' . + $file->getMessage()); + } elseif ($file === null) { + return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' . + $fileXml['name'] . '" could not be retrieved for processing!'); + } else { + $analysis = $pkg->analyzeSourceCode($file, true); + if (!$analysis) { + PEAR::popErrorHandling(); + $warnings = ''; + foreach ($pkg->getValidationWarnings() as $warn) { + $warnings .= $warn['message'] . "\n"; + } + return array(PEAR_TASK_ERROR_INVALID, 'Analysis of post-install script "' . + $fileXml['name'] . '" failed: ' . $warnings); + } + if (count($analysis['declared_classes']) != 1) { + PEAR::popErrorHandling(); + return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' . + $fileXml['name'] . '" must declare exactly 1 class'); + } + $class = $analysis['declared_classes'][0]; + if ($class != str_replace(array('/', '.php'), array('_', ''), + $fileXml['name']) . '_postinstall') { + PEAR::popErrorHandling(); + return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' . + $fileXml['name'] . '" class "' . $class . '" must be named "' . + str_replace(array('/', '.php'), array('_', ''), + $fileXml['name']) . '_postinstall"'); + } + if (!isset($analysis['declared_methods'][$class])) { + PEAR::popErrorHandling(); + return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' . + $fileXml['name'] . '" must declare methods init() and run()'); + } + $methods = array('init' => 0, 'run' => 1); + foreach ($analysis['declared_methods'][$class] as $method) { + if (isset($methods[$method])) { + unset($methods[$method]); + } + } + if (count($methods)) { + PEAR::popErrorHandling(); + return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' . + $fileXml['name'] . '" must declare methods init() and run()'); + } + } + PEAR::popErrorHandling(); + $definedparams = array(); + $tasksNamespace = $pkg->getTasksNs() . ':'; + if (!isset($xml[$tasksNamespace . 'paramgroup']) && isset($xml['paramgroup'])) { + // in order to support the older betas, which did not expect internal tags + // to also use the namespace + $tasksNamespace = ''; + } + if (isset($xml[$tasksNamespace . 'paramgroup'])) { + $params = $xml[$tasksNamespace . 'paramgroup']; + if (!is_array($params) || !isset($params[0])) { + $params = array($params); + } + foreach ($params as $param) { + if (!isset($param[$tasksNamespace . 'id'])) { + return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' . + $fileXml['name'] . '" must have ' . + 'an ' . $tasksNamespace . 'id> tag'); + } + if (isset($param[$tasksNamespace . 'name'])) { + if (!in_array($param[$tasksNamespace . 'name'], $definedparams)) { + return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' . + $fileXml['name'] . '" ' . $tasksNamespace . + 'paramgroup> id "' . $param[$tasksNamespace . 'id'] . + '" parameter "' . $param[$tasksNamespace . 'name'] . + '" has not been previously defined'); + } + if (!isset($param[$tasksNamespace . 'conditiontype'])) { + return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' . + $fileXml['name'] . '" ' . $tasksNamespace . + 'paramgroup> id "' . $param[$tasksNamespace . 'id'] . + '" must have a ' . $tasksNamespace . + 'conditiontype> tag containing either "=", ' . + '"!=", or "preg_match"'); + } + if (!in_array($param[$tasksNamespace . 'conditiontype'], + array('=', '!=', 'preg_match'))) { + return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' . + $fileXml['name'] . '" ' . $tasksNamespace . + 'paramgroup> id "' . $param[$tasksNamespace . 'id'] . + '" must have a ' . $tasksNamespace . + 'conditiontype> tag containing either "=", ' . + '"!=", or "preg_match"'); + } + if (!isset($param[$tasksNamespace . 'value'])) { + return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' . + $fileXml['name'] . '" ' . $tasksNamespace . + 'paramgroup> id "' . $param[$tasksNamespace . 'id'] . + '" must have a ' . $tasksNamespace . + 'value> tag containing expected parameter value'); + } + } + if (isset($param[$tasksNamespace . 'instructions'])) { + if (!is_string($param[$tasksNamespace . 'instructions'])) { + return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' . + $fileXml['name'] . '" ' . $tasksNamespace . + 'paramgroup> id "' . $param[$tasksNamespace . 'id'] . + '" ' . $tasksNamespace . 'instructions> must be simple text'); + } + } + if (!isset($param[$tasksNamespace . 'param'])) { + continue; // is no longer required + } + $subparams = $param[$tasksNamespace . 'param']; + if (!is_array($subparams) || !isset($subparams[0])) { + $subparams = array($subparams); + } + foreach ($subparams as $subparam) { + if (!isset($subparam[$tasksNamespace . 'name'])) { + return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' . + $fileXml['name'] . '" parameter for ' . + $tasksNamespace . 'paramgroup> id "' . + $param[$tasksNamespace . 'id'] . '" must have ' . + 'a ' . $tasksNamespace . 'name> tag'); + } + if (!preg_match('/[a-zA-Z0-9]+/', + $subparam[$tasksNamespace . 'name'])) { + return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' . + $fileXml['name'] . '" parameter "' . + $subparam[$tasksNamespace . 'name'] . + '" for ' . $tasksNamespace . 'paramgroup> id "' . + $param[$tasksNamespace . 'id'] . + '" is not a valid name. Must contain only alphanumeric characters'); + } + if (!isset($subparam[$tasksNamespace . 'prompt'])) { + return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' . + $fileXml['name'] . '" parameter "' . + $subparam[$tasksNamespace . 'name'] . + '" for ' . $tasksNamespace . 'paramgroup> id "' . + $param[$tasksNamespace . 'id'] . + '" must have a ' . $tasksNamespace . 'prompt> tag'); + } + if (!isset($subparam[$tasksNamespace . 'type'])) { + return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' . + $fileXml['name'] . '" parameter "' . + $subparam[$tasksNamespace . 'name'] . + '" for ' . $tasksNamespace . 'paramgroup> id "' . + $param[$tasksNamespace . 'id'] . + '" must have a ' . $tasksNamespace . 'type> tag'); + } + $definedparams[] = $param[$tasksNamespace . 'id'] . '::' . + $subparam[$tasksNamespace . 'name']; + } + } + } + return true; + } + + /** + * Initialize a task instance with the parameters + * @param array raw, parsed xml + * @param array attributes from the tag containing this task + * @param string|null last installed version of this package, if any (useful for upgrades) + */ + function init($xml, $fileattribs, $lastversion) + { + $this->_class = str_replace('/', '_', $fileattribs['name']); + $this->_filename = $fileattribs['name']; + $this->_class = str_replace ('.php', '', $this->_class) . '_postinstall'; + $this->_params = $xml; + $this->_lastversion = $lastversion; + } + + /** + * Strip the tasks: namespace from internal params + * + * @access private + */ + function _stripNamespace($params = null) + { + if ($params === null) { + $params = array(); + if (!is_array($this->_params)) { + return; + } + foreach ($this->_params as $i => $param) { + if (is_array($param)) { + $param = $this->_stripNamespace($param); + } + $params[str_replace($this->_pkg->getTasksNs() . ':', '', $i)] = $param; + } + $this->_params = $params; + } else { + $newparams = array(); + foreach ($params as $i => $param) { + if (is_array($param)) { + $param = $this->_stripNamespace($param); + } + $newparams[str_replace($this->_pkg->getTasksNs() . ':', '', $i)] = $param; + } + return $newparams; + } + } + + /** + * Unlike other tasks, the installed file name is passed in instead of the file contents, + * because this task is handled post-installation + * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2 + * @param string file name + * @return bool|PEAR_Error false to skip this file, PEAR_Error to fail + * (use $this->throwError) + */ + function startSession($pkg, $contents) + { + if ($this->installphase != PEAR_TASK_INSTALL) { + return false; + } + // remove the tasks: namespace if present + $this->_pkg = $pkg; + $this->_stripNamespace(); + $this->logger->log(0, 'Including external post-installation script "' . + $contents . '" - any errors are in this script'); + include_once $contents; + if (class_exists($this->_class)) { + $this->logger->log(0, 'Inclusion succeeded'); + } else { + return $this->throwError('init of post-install script class "' . $this->_class + . '" failed'); + } + $this->_obj = new $this->_class; + $this->logger->log(1, 'running post-install script "' . $this->_class . '->init()"'); + PEAR::pushErrorHandling(PEAR_ERROR_RETURN); + $res = $this->_obj->init($this->config, $pkg, $this->_lastversion); + PEAR::popErrorHandling(); + if ($res) { + $this->logger->log(0, 'init succeeded'); + } else { + return $this->throwError('init of post-install script "' . $this->_class . + '->init()" failed'); + } + $this->_contents = $contents; + return true; + } + + /** + * No longer used + * @see PEAR_PackageFile_v2::runPostinstallScripts() + * @param array an array of tasks + * @param string install or upgrade + * @access protected + * @static + */ + function run() + { + } +} +?> \ No newline at end of file diff --git a/src/lib/pear/PEAR/PEAR/Task/Postinstallscript/rw.php b/src/lib/pear/PEAR/PEAR/Task/Postinstallscript/rw.php new file mode 100644 index 0000000..3f2a97c --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Task/Postinstallscript/rw.php @@ -0,0 +1,176 @@ + - read/write version + * + * PHP versions 4 and 5 + * + * LICENSE: This source file is subject to version 3.0 of the PHP license + * that is available through the world-wide-web at the following URI: + * http://www.php.net/license/3_0.txt. If you did not receive a copy of + * the PHP License and are unable to obtain it through the web, please + * send a note to license@php.net so we can mail you a copy immediately. + * + * @category pear + * @package PEAR + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: rw.php,v 1.12 2008/01/03 20:26:37 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 1.4.0a10 + */ +/** + * Base class + */ +require_once 'PEAR/Task/Postinstallscript.php'; +/** + * Abstracts the postinstallscript file task xml. + * @category pear + * @package PEAR + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 1.4.0a10 + */ +class PEAR_Task_Postinstallscript_rw extends PEAR_Task_Postinstallscript +{ + /** + * parent package file object + * + * @var PEAR_PackageFile_v2_rw + */ + var $_pkg; + /** + * Enter description here... + * + * @param PEAR_PackageFile_v2_rw $pkg + * @param PEAR_Config $config + * @param PEAR_Frontend $logger + * @param array $fileXml + * @return PEAR_Task_Postinstallscript_rw + */ + function PEAR_Task_Postinstallscript_rw(&$pkg, &$config, &$logger, $fileXml) + { + parent::PEAR_Task_Common($config, $logger, PEAR_TASK_PACKAGE); + $this->_contents = $fileXml; + $this->_pkg = &$pkg; + $this->_params = array(); + } + + function validate() + { + return $this->validateXml($this->_pkg, $this->_params, $this->config, $this->_contents); + } + + function getName() + { + return 'postinstallscript'; + } + + /** + * add a simple to the post-install script + * + * Order is significant, so call this method in the same + * sequence the users should see the paramgroups. The $params + * parameter should either be the result of a call to {@link getParam()} + * or an array of calls to getParam(). + * + * Use {@link addConditionTypeGroup()} to add a containing + * a tag + * @param string $id id as seen by the script + * @param array|false $params array of getParam() calls, or false for no params + * @param string|false $instructions + */ + function addParamGroup($id, $params = false, $instructions = false) + { + if ($params && isset($params[0]) && !isset($params[1])) { + $params = $params[0]; + } + $stuff = + array( + $this->_pkg->getTasksNs() . ':id' => $id, + ); + if ($instructions) { + $stuff[$this->_pkg->getTasksNs() . ':instructions'] = $instructions; + } + if ($params) { + $stuff[$this->_pkg->getTasksNs() . ':param'] = $params; + } + $this->_params[$this->_pkg->getTasksNs() . ':paramgroup'][] = $stuff; + } + + /** + * add a complex to the post-install script with conditions + * + * This inserts a with + * + * Order is significant, so call this method in the same + * sequence the users should see the paramgroups. The $params + * parameter should either be the result of a call to {@link getParam()} + * or an array of calls to getParam(). + * + * Use {@link addParamGroup()} to add a simple + * + * @param string $id id as seen by the script + * @param string $oldgroup id of the section referenced by + * + * @param string $param name of the from the older section referenced + * by + * @param string $value value to match of the parameter + * @param string $conditiontype one of '=', '!=', 'preg_match' + * @param array|false $params array of getParam() calls, or false for no params + * @param string|false $instructions + */ + function addConditionTypeGroup($id, $oldgroup, $param, $value, $conditiontype = '=', + $params = false, $instructions = false) + { + if ($params && isset($params[0]) && !isset($params[1])) { + $params = $params[0]; + } + $stuff = + array( + $this->_pkg->getTasksNs() . ':id' => $id, + ); + if ($instructions) { + $stuff[$this->_pkg->getTasksNs() . ':instructions'] = $instructions; + } + $stuff[$this->_pkg->getTasksNs() . ':name'] = $oldgroup . '::' . $param; + $stuff[$this->_pkg->getTasksNs() . ':conditiontype'] = $conditiontype; + $stuff[$this->_pkg->getTasksNs() . ':value'] = $value; + if ($params) { + $stuff[$this->_pkg->getTasksNs() . ':param'] = $params; + } + $this->_params[$this->_pkg->getTasksNs() . ':paramgroup'][] = $stuff; + } + + function getXml() + { + return $this->_params; + } + + /** + * Use to set up a param tag for use in creating a paramgroup + * @static + */ + function getParam($name, $prompt, $type = 'string', $default = null) + { + if ($default !== null) { + return + array( + $this->_pkg->getTasksNs() . ':name' => $name, + $this->_pkg->getTasksNs() . ':prompt' => $prompt, + $this->_pkg->getTasksNs() . ':type' => $type, + $this->_pkg->getTasksNs() . ':default' => $default + ); + } + return + array( + $this->_pkg->getTasksNs() . ':name' => $name, + $this->_pkg->getTasksNs() . ':prompt' => $prompt, + $this->_pkg->getTasksNs() . ':type' => $type, + ); + } +} +?> \ No newline at end of file diff --git a/src/lib/pear/PEAR/PEAR/Task/Replace.php b/src/lib/pear/PEAR/PEAR/Task/Replace.php new file mode 100644 index 0000000..9a94181 --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Task/Replace.php @@ -0,0 +1,182 @@ + + * + * PHP versions 4 and 5 + * + * LICENSE: This source file is subject to version 3.0 of the PHP license + * that is available through the world-wide-web at the following URI: + * http://www.php.net/license/3_0.txt. If you did not receive a copy of + * the PHP License and are unable to obtain it through the web, please + * send a note to license@php.net so we can mail you a copy immediately. + * + * @category pear + * @package PEAR + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: Replace.php,v 1.17 2008/05/13 21:28:20 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 1.4.0a1 + */ +/** + * Base class + */ +require_once 'PEAR/Task/Common.php'; +/** + * Implements the replace file task. + * @category pear + * @package PEAR + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 1.4.0a1 + */ +class PEAR_Task_Replace extends PEAR_Task_Common +{ + var $type = 'simple'; + var $phase = PEAR_TASK_PACKAGEANDINSTALL; + var $_replacements; + + /** + * Validate the raw xml at parsing-time. + * @param PEAR_PackageFile_v2 + * @param array raw, parsed xml + * @param PEAR_Config + * @static + */ + function validateXml($pkg, $xml, $config, $fileXml) + { + if (!isset($xml['attribs'])) { + return array(PEAR_TASK_ERROR_NOATTRIBS); + } + if (!isset($xml['attribs']['type'])) { + return array(PEAR_TASK_ERROR_MISSING_ATTRIB, 'type'); + } + if (!isset($xml['attribs']['to'])) { + return array(PEAR_TASK_ERROR_MISSING_ATTRIB, 'to'); + } + if (!isset($xml['attribs']['from'])) { + return array(PEAR_TASK_ERROR_MISSING_ATTRIB, 'from'); + } + if ($xml['attribs']['type'] == 'pear-config') { + if (!in_array($xml['attribs']['to'], $config->getKeys())) { + return array(PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE, 'to', $xml['attribs']['to'], + $config->getKeys()); + } + } elseif ($xml['attribs']['type'] == 'php-const') { + if (defined($xml['attribs']['to'])) { + return true; + } else { + return array(PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE, 'to', $xml['attribs']['to'], + array('valid PHP constant')); + } + } elseif ($xml['attribs']['type'] == 'package-info') { + if (in_array($xml['attribs']['to'], + array('name', 'summary', 'channel', 'notes', 'extends', 'description', + 'release_notes', 'license', 'release-license', 'license-uri', + 'version', 'api-version', 'state', 'api-state', 'release_date', + 'date', 'time'))) { + return true; + } else { + return array(PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE, 'to', $xml['attribs']['to'], + array('name', 'summary', 'channel', 'notes', 'extends', 'description', + 'release_notes', 'license', 'release-license', 'license-uri', + 'version', 'api-version', 'state', 'api-state', 'release_date', + 'date', 'time')); + } + } else { + return array(PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE, 'type', $xml['attribs']['type'], + array('pear-config', 'package-info', 'php-const')); + } + return true; + } + + /** + * Initialize a task instance with the parameters + * @param array raw, parsed xml + * @param unused + */ + function init($xml, $attribs) + { + $this->_replacements = isset($xml['attribs']) ? array($xml) : $xml; + } + + /** + * Do a package.xml 1.0 replacement, with additional package-info fields available + * + * See validateXml() source for the complete list of allowed fields + * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2 + * @param string file contents + * @param string the eventual final file location (informational only) + * @return string|false|PEAR_Error false to skip this file, PEAR_Error to fail + * (use $this->throwError), otherwise return the new contents + */ + function startSession($pkg, $contents, $dest) + { + $subst_from = $subst_to = array(); + foreach ($this->_replacements as $a) { + $a = $a['attribs']; + $to = ''; + if ($a['type'] == 'pear-config') { + if ($this->installphase == PEAR_TASK_PACKAGE) { + return false; + } + if ($a['to'] == 'master_server') { + $chan = $this->registry->getChannel($pkg->getChannel()); + if (!PEAR::isError($chan)) { + $to = $chan->getServer(); + } else { + $this->logger->log(0, "$dest: invalid pear-config replacement: $a[to]"); + return false; + } + } else { + if ($this->config->isDefinedLayer('ftp')) { + // try the remote config file first + $to = $this->config->get($a['to'], 'ftp', $pkg->getChannel()); + if (is_null($to)) { + // then default to local + $to = $this->config->get($a['to'], null, $pkg->getChannel()); + } + } else { + $to = $this->config->get($a['to'], null, $pkg->getChannel()); + } + } + if (is_null($to)) { + $this->logger->log(0, "$dest: invalid pear-config replacement: $a[to]"); + return false; + } + } elseif ($a['type'] == 'php-const') { + if ($this->installphase == PEAR_TASK_PACKAGE) { + return false; + } + if (defined($a['to'])) { + $to = constant($a['to']); + } else { + $this->logger->log(0, "$dest: invalid php-const replacement: $a[to]"); + return false; + } + } else { + if ($t = $pkg->packageInfo($a['to'])) { + $to = $t; + } else { + $this->logger->log(0, "$dest: invalid package-info replacement: $a[to]"); + return false; + } + } + if (!is_null($to)) { + $subst_from[] = $a['from']; + $subst_to[] = $to; + } + } + $this->logger->log(3, "doing " . sizeof($subst_from) . + " substitution(s) for $dest"); + if (sizeof($subst_from)) { + $contents = str_replace($subst_from, $subst_to, $contents); + } + return $contents; + } +} +?> \ No newline at end of file diff --git a/src/lib/pear/PEAR/PEAR/Task/Replace/rw.php b/src/lib/pear/PEAR/PEAR/Task/Replace/rw.php new file mode 100644 index 0000000..fe03d2e --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Task/Replace/rw.php @@ -0,0 +1,67 @@ + - read/write version + * + * PHP versions 4 and 5 + * + * LICENSE: This source file is subject to version 3.0 of the PHP license + * that is available through the world-wide-web at the following URI: + * http://www.php.net/license/3_0.txt. If you did not receive a copy of + * the PHP License and are unable to obtain it through the web, please + * send a note to license@php.net so we can mail you a copy immediately. + * + * @category pear + * @package PEAR + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: rw.php,v 1.4 2008/01/03 20:26:37 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 1.4.0a10 + */ +/** + * Base class + */ +require_once 'PEAR/Task/Replace.php'; +/** + * Abstracts the replace task xml. + * @category pear + * @package PEAR + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 1.4.0a10 + */ +class PEAR_Task_Replace_rw extends PEAR_Task_Replace +{ + function PEAR_Task_Replace_rw(&$pkg, &$config, &$logger, $fileXml) + { + parent::PEAR_Task_Common($config, $logger, PEAR_TASK_PACKAGE); + $this->_contents = $fileXml; + $this->_pkg = &$pkg; + $this->_params = array(); + } + + function validate() + { + return $this->validateXml($this->_pkg, $this->_params, $this->config, $this->_contents); + } + + function setInfo($from, $to, $type) + { + $this->_params = array('attribs' => array('from' => $from, 'to' => $to, 'type' => $type)); + } + + function getName() + { + return 'replace'; + } + + function getXml() + { + return $this->_params; + } +} +?> \ No newline at end of file diff --git a/src/lib/pear/PEAR/PEAR/Task/Unixeol.php b/src/lib/pear/PEAR/PEAR/Task/Unixeol.php new file mode 100644 index 0000000..bfd3f11 --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Task/Unixeol.php @@ -0,0 +1,83 @@ + + * + * PHP versions 4 and 5 + * + * LICENSE: This source file is subject to version 3.0 of the PHP license + * that is available through the world-wide-web at the following URI: + * http://www.php.net/license/3_0.txt. If you did not receive a copy of + * the PHP License and are unable to obtain it through the web, please + * send a note to license@php.net so we can mail you a copy immediately. + * + * @category pear + * @package PEAR + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: Unixeol.php,v 1.10 2008/05/13 21:28:20 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 1.4.0a1 + */ +/** + * Base class + */ +require_once 'PEAR/Task/Common.php'; +/** + * Implements the unix line endings file task. + * @category pear + * @package PEAR + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 1.4.0a1 + */ +class PEAR_Task_Unixeol extends PEAR_Task_Common +{ + var $type = 'simple'; + var $phase = PEAR_TASK_PACKAGE; + var $_replacements; + + /** + * Validate the raw xml at parsing-time. + * @param PEAR_PackageFile_v2 + * @param array raw, parsed xml + * @param PEAR_Config + * @static + */ + function validateXml($pkg, $xml, $config, $fileXml) + { + if ($xml != '') { + return array(PEAR_TASK_ERROR_INVALID, 'no attributes allowed'); + } + return true; + } + + /** + * Initialize a task instance with the parameters + * @param array raw, parsed xml + * @param unused + */ + function init($xml, $attribs) + { + } + + /** + * Replace all line endings with line endings customized for the current OS + * + * See validateXml() source for the complete list of allowed fields + * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2 + * @param string file contents + * @param string the eventual final file location (informational only) + * @return string|false|PEAR_Error false to skip this file, PEAR_Error to fail + * (use $this->throwError), otherwise return the new contents + */ + function startSession($pkg, $contents, $dest) + { + $this->logger->log(3, "replacing all line endings with \\n in $dest"); + return preg_replace("/\r\n|\n\r|\r|\n/", "\n", $contents); + } +} +?> \ No newline at end of file diff --git a/src/lib/pear/PEAR/PEAR/Task/Unixeol/rw.php b/src/lib/pear/PEAR/PEAR/Task/Unixeol/rw.php new file mode 100644 index 0000000..f04f0f0 --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Task/Unixeol/rw.php @@ -0,0 +1,62 @@ + - read/write version + * + * PHP versions 4 and 5 + * + * LICENSE: This source file is subject to version 3.0 of the PHP license + * that is available through the world-wide-web at the following URI: + * http://www.php.net/license/3_0.txt. If you did not receive a copy of + * the PHP License and are unable to obtain it through the web, please + * send a note to license@php.net so we can mail you a copy immediately. + * + * @category pear + * @package PEAR + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: rw.php,v 1.5 2008/01/03 20:26:37 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 1.4.0a10 + */ +/** + * Base class + */ +require_once 'PEAR/Task/Unixeol.php'; +/** + * Abstracts the unixeol task xml. + * @category pear + * @package PEAR + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 1.4.0a10 + */ +class PEAR_Task_Unixeol_rw extends PEAR_Task_Unixeol +{ + function PEAR_Task_Unixeol_rw(&$pkg, &$config, &$logger, $fileXml) + { + parent::PEAR_Task_Common($config, $logger, PEAR_TASK_PACKAGE); + $this->_contents = $fileXml; + $this->_pkg = &$pkg; + $this->_params = array(); + } + + function validate() + { + return true; + } + + function getName() + { + return 'unixeol'; + } + + function getXml() + { + return ''; + } +} +?> \ No newline at end of file diff --git a/src/lib/pear/PEAR/PEAR/Task/Windowseol.php b/src/lib/pear/PEAR/PEAR/Task/Windowseol.php new file mode 100644 index 0000000..1a1be1e --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Task/Windowseol.php @@ -0,0 +1,83 @@ + + * + * PHP versions 4 and 5 + * + * LICENSE: This source file is subject to version 3.0 of the PHP license + * that is available through the world-wide-web at the following URI: + * http://www.php.net/license/3_0.txt. If you did not receive a copy of + * the PHP License and are unable to obtain it through the web, please + * send a note to license@php.net so we can mail you a copy immediately. + * + * @category pear + * @package PEAR + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: Windowseol.php,v 1.9 2008/05/13 21:28:20 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 1.4.0a1 + */ +/** + * Base class + */ +require_once 'PEAR/Task/Common.php'; +/** + * Implements the windows line endsings file task. + * @category pear + * @package PEAR + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 1.4.0a1 + */ +class PEAR_Task_Windowseol extends PEAR_Task_Common +{ + var $type = 'simple'; + var $phase = PEAR_TASK_PACKAGE; + var $_replacements; + + /** + * Validate the raw xml at parsing-time. + * @param PEAR_PackageFile_v2 + * @param array raw, parsed xml + * @param PEAR_Config + * @static + */ + function validateXml($pkg, $xml, $config, $fileXml) + { + if ($xml != '') { + return array(PEAR_TASK_ERROR_INVALID, 'no attributes allowed'); + } + return true; + } + + /** + * Initialize a task instance with the parameters + * @param array raw, parsed xml + * @param unused + */ + function init($xml, $attribs) + { + } + + /** + * Replace all line endings with windows line endings + * + * See validateXml() source for the complete list of allowed fields + * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2 + * @param string file contents + * @param string the eventual final file location (informational only) + * @return string|false|PEAR_Error false to skip this file, PEAR_Error to fail + * (use $this->throwError), otherwise return the new contents + */ + function startSession($pkg, $contents, $dest) + { + $this->logger->log(3, "replacing all line endings with \\r\\n in $dest"); + return preg_replace("/\r\n|\n\r|\r|\n/", "\r\n", $contents); + } +} +?> \ No newline at end of file diff --git a/src/lib/pear/PEAR/PEAR/Task/Windowseol/rw.php b/src/lib/pear/PEAR/PEAR/Task/Windowseol/rw.php new file mode 100644 index 0000000..c61a15d --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Task/Windowseol/rw.php @@ -0,0 +1,62 @@ + - read/write version + * + * PHP versions 4 and 5 + * + * LICENSE: This source file is subject to version 3.0 of the PHP license + * that is available through the world-wide-web at the following URI: + * http://www.php.net/license/3_0.txt. If you did not receive a copy of + * the PHP License and are unable to obtain it through the web, please + * send a note to license@php.net so we can mail you a copy immediately. + * + * @category pear + * @package PEAR + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: rw.php,v 1.5 2008/01/03 20:26:37 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 1.4.0a10 + */ +/** + * Base class + */ +require_once 'PEAR/Task/Windowseol.php'; +/** + * Abstracts the windowseol task xml. + * @category pear + * @package PEAR + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 1.4.0a10 + */ +class PEAR_Task_Windowseol_rw extends PEAR_Task_Windowseol +{ + function PEAR_Task_Windowseol_rw(&$pkg, &$config, &$logger, $fileXml) + { + parent::PEAR_Task_Common($config, $logger, PEAR_TASK_PACKAGE); + $this->_contents = $fileXml; + $this->_pkg = &$pkg; + $this->_params = array(); + } + + function validate() + { + return true; + } + + function getName() + { + return 'windowseol'; + } + + function getXml() + { + return ''; + } +} +?> \ No newline at end of file diff --git a/src/lib/pear/PEAR/PEAR/Validate.php b/src/lib/pear/PEAR/PEAR/Validate.php new file mode 100644 index 0000000..34796b7 --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Validate.php @@ -0,0 +1,634 @@ + + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: Validate.php,v 1.52 2008/01/03 20:26:36 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 1.4.0a1 + */ +/**#@+ + * Constants for install stage + */ +define('PEAR_VALIDATE_INSTALLING', 1); +define('PEAR_VALIDATE_UNINSTALLING', 2); // this is not bit-mapped like the others +define('PEAR_VALIDATE_NORMAL', 3); +define('PEAR_VALIDATE_DOWNLOADING', 4); // this is not bit-mapped like the others +define('PEAR_VALIDATE_PACKAGING', 7); +/**#@-*/ +require_once 'PEAR/Common.php'; +require_once 'PEAR/Validator/PECL.php'; + +/** + * Validation class for package.xml - channel-level advanced validation + * @category pear + * @package PEAR + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 1.4.0a1 + */ +class PEAR_Validate +{ + var $packageregex = _PEAR_COMMON_PACKAGE_NAME_PREG; + /** + * @var PEAR_PackageFile_v1|PEAR_PackageFile_v2 + */ + var $_packagexml; + /** + * @var int one of the PEAR_VALIDATE_* constants + */ + var $_state = PEAR_VALIDATE_NORMAL; + /** + * Format: ('error' => array('field' => name, 'reason' => reason), 'warning' => same) + * @var array + * @access private + */ + var $_failures = array('error' => array(), 'warning' => array()); + + /** + * Override this method to handle validation of normal package names + * @param string + * @return bool + * @access protected + */ + function _validPackageName($name) + { + return (bool) preg_match('/^' . $this->packageregex . '\\z/', $name); + } + + /** + * @param string package name to validate + * @param string name of channel-specific validation package + * @final + */ + function validPackageName($name, $validatepackagename = false) + { + if ($validatepackagename) { + if (strtolower($name) == strtolower($validatepackagename)) { + return (bool) preg_match('/^[a-zA-Z0-9_]+(?:\.[a-zA-Z0-9_]+)*\\z/', $name); + } + } + return $this->_validPackageName($name); + } + + /** + * This validates a bundle name, and bundle names must conform + * to the PEAR naming convention, so the method is final and static. + * @param string + * @final + * @static + */ + function validGroupName($name) + { + return (bool) preg_match('/^' . _PEAR_COMMON_PACKAGE_NAME_PREG . '\\z/', $name); + } + + /** + * Determine whether $state represents a valid stability level + * @param string + * @return bool + * @static + * @final + */ + function validState($state) + { + return in_array($state, array('snapshot', 'devel', 'alpha', 'beta', 'stable')); + } + + /** + * Get a list of valid stability levels + * @return array + * @static + * @final + */ + function getValidStates() + { + return array('snapshot', 'devel', 'alpha', 'beta', 'stable'); + } + + /** + * Determine whether a version is a properly formatted version number that can be used + * by version_compare + * @param string + * @return bool + * @static + * @final + */ + function validVersion($ver) + { + return (bool) preg_match(PEAR_COMMON_PACKAGE_VERSION_PREG, $ver); + } + + /** + * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2 + */ + function setPackageFile(&$pf) + { + $this->_packagexml = &$pf; + } + + /** + * @access private + */ + function _addFailure($field, $reason) + { + $this->_failures['errors'][] = array('field' => $field, 'reason' => $reason); + } + + /** + * @access private + */ + function _addWarning($field, $reason) + { + $this->_failures['warnings'][] = array('field' => $field, 'reason' => $reason); + } + + function getFailures() + { + $failures = $this->_failures; + $this->_failures = array('warnings' => array(), 'errors' => array()); + return $failures; + } + + /** + * @param int one of the PEAR_VALIDATE_* constants + */ + function validate($state = null) + { + if (!isset($this->_packagexml)) { + return false; + } + if ($state !== null) { + $this->_state = $state; + } + $this->_failures = array('warnings' => array(), 'errors' => array()); + $this->validatePackageName(); + $this->validateVersion(); + $this->validateMaintainers(); + $this->validateDate(); + $this->validateSummary(); + $this->validateDescription(); + $this->validateLicense(); + $this->validateNotes(); + if ($this->_packagexml->getPackagexmlVersion() == '1.0') { + $this->validateState(); + $this->validateFilelist(); + } elseif ($this->_packagexml->getPackagexmlVersion() == '2.0' || + $this->_packagexml->getPackagexmlVersion() == '2.1') { + $this->validateTime(); + $this->validateStability(); + $this->validateDeps(); + $this->validateMainFilelist(); + $this->validateReleaseFilelist(); + //$this->validateGlobalTasks(); + $this->validateChangelog(); + } + return !((bool) count($this->_failures['errors'])); + } + + /** + * @access protected + */ + function validatePackageName() + { + if ($this->_state == PEAR_VALIDATE_PACKAGING || + $this->_state == PEAR_VALIDATE_NORMAL) { + if (($this->_packagexml->getPackagexmlVersion() == '2.0' || + $this->_packagexml->getPackagexmlVersion() == '2.1') && + $this->_packagexml->getExtends()) { + $version = $this->_packagexml->getVersion() . ''; + $name = $this->_packagexml->getPackage(); + $test = array_shift($a = explode('.', $version)); + if ($test == '0') { + return true; + } + $vlen = strlen($test); + $majver = substr($name, strlen($name) - $vlen); + while ($majver && !is_numeric($majver{0})) { + $majver = substr($majver, 1); + } + if ($majver != $test) { + $this->_addWarning('package', "package $name extends package " . + $this->_packagexml->getExtends() . ' and so the name should ' . + 'have a postfix equal to the major version like "' . + $this->_packagexml->getExtends() . $test . '"'); + return true; + } elseif (substr($name, 0, strlen($name) - $vlen) != + $this->_packagexml->getExtends()) { + $this->_addWarning('package', "package $name extends package " . + $this->_packagexml->getExtends() . ' and so the name must ' . + 'be an extension like "' . $this->_packagexml->getExtends() . + $test . '"'); + return true; + } + } + } + if (!$this->validPackageName($this->_packagexml->getPackage())) { + $this->_addFailure('name', 'package name "' . + $this->_packagexml->getPackage() . '" is invalid'); + return false; + } + } + + /** + * @access protected + */ + function validateVersion() + { + if ($this->_state != PEAR_VALIDATE_PACKAGING) { + if (!$this->validVersion($this->_packagexml->getVersion())) { + $this->_addFailure('version', + 'Invalid version number "' . $this->_packagexml->getVersion() . '"'); + } + return false; + } + $version = $this->_packagexml->getVersion(); + $versioncomponents = explode('.', $version); + if (count($versioncomponents) != 3) { + $this->_addWarning('version', + 'A version number should have 3 decimals (x.y.z)'); + return true; + } + $name = $this->_packagexml->getPackage(); + // version must be based upon state + switch ($this->_packagexml->getState()) { + case 'snapshot' : + return true; + case 'devel' : + if ($versioncomponents[0] . 'a' == '0a') { + return true; + } + if ($versioncomponents[0] == 0) { + $versioncomponents[0] = '0'; + $this->_addWarning('version', + 'version "' . $version . '" should be "' . + implode('.' ,$versioncomponents) . '"'); + } else { + $this->_addWarning('version', + 'packages with devel stability must be < version 1.0.0'); + } + return true; + break; + case 'alpha' : + case 'beta' : + // check for a package that extends a package, + // like Foo and Foo2 + if ($this->_state == PEAR_VALIDATE_PACKAGING) { + if (substr($versioncomponents[2], 1, 2) == 'rc') { + $this->_addFailure('version', 'Release Candidate versions ' . + 'must have capital RC, not lower-case rc'); + return false; + } + } + if (!$this->_packagexml->getExtends()) { + if ($versioncomponents[0] == '1') { + if ($versioncomponents[2]{0} == '0') { + if ($versioncomponents[2] == '0') { + // version 1.*.0000 + $this->_addWarning('version', + 'version 1.' . $versioncomponents[1] . + '.0 probably should not be alpha or beta'); + return true; + } elseif (strlen($versioncomponents[2]) > 1) { + // version 1.*.0RC1 or 1.*.0beta24 etc. + return true; + } else { + // version 1.*.0 + $this->_addWarning('version', + 'version 1.' . $versioncomponents[1] . + '.0 probably should not be alpha or beta'); + return true; + } + } else { + $this->_addWarning('version', + 'bugfix versions (1.3.x where x > 0) probably should ' . + 'not be alpha or beta'); + return true; + } + } elseif ($versioncomponents[0] != '0') { + $this->_addWarning('version', + 'major versions greater than 1 are not allowed for packages ' . + 'without an tag or an identical postfix (foo2 v2.0.0)'); + return true; + } + if ($versioncomponents[0] . 'a' == '0a') { + return true; + } + if ($versioncomponents[0] == 0) { + $versioncomponents[0] = '0'; + $this->_addWarning('version', + 'version "' . $version . '" should be "' . + implode('.' ,$versioncomponents) . '"'); + } + } else { + $vlen = strlen($versioncomponents[0] . ''); + $majver = substr($name, strlen($name) - $vlen); + while ($majver && !is_numeric($majver{0})) { + $majver = substr($majver, 1); + } + if (($versioncomponents[0] != 0) && $majver != $versioncomponents[0]) { + $this->_addWarning('version', 'first version number "' . + $versioncomponents[0] . '" must match the postfix of ' . + 'package name "' . $name . '" (' . + $majver . ')'); + return true; + } + if ($versioncomponents[0] == $majver) { + if ($versioncomponents[2]{0} == '0') { + if ($versioncomponents[2] == '0') { + // version 2.*.0000 + $this->_addWarning('version', + "version $majver." . $versioncomponents[1] . + '.0 probably should not be alpha or beta'); + return false; + } elseif (strlen($versioncomponents[2]) > 1) { + // version 2.*.0RC1 or 2.*.0beta24 etc. + return true; + } else { + // version 2.*.0 + $this->_addWarning('version', + "version $majver." . $versioncomponents[1] . + '.0 cannot be alpha or beta'); + return true; + } + } else { + $this->_addWarning('version', + "bugfix versions ($majver.x.y where y > 0) should " . + 'not be alpha or beta'); + return true; + } + } elseif ($versioncomponents[0] != '0') { + $this->_addWarning('version', + "only versions 0.x.y and $majver.x.y are allowed for alpha/beta releases"); + return true; + } + if ($versioncomponents[0] . 'a' == '0a') { + return true; + } + if ($versioncomponents[0] == 0) { + $versioncomponents[0] = '0'; + $this->_addWarning('version', + 'version "' . $version . '" should be "' . + implode('.' ,$versioncomponents) . '"'); + } + } + return true; + break; + case 'stable' : + if ($versioncomponents[0] == '0') { + $this->_addWarning('version', 'versions less than 1.0.0 cannot ' . + 'be stable'); + return true; + } + if (!is_numeric($versioncomponents[2])) { + if (preg_match('/\d+(rc|a|alpha|b|beta)\d*/i', + $versioncomponents[2])) { + $this->_addWarning('version', 'version "' . $version . '" or any ' . + 'RC/beta/alpha version cannot be stable'); + return true; + } + } + // check for a package that extends a package, + // like Foo and Foo2 + if ($this->_packagexml->getExtends()) { + $vlen = strlen($versioncomponents[0] . ''); + $majver = substr($name, strlen($name) - $vlen); + while ($majver && !is_numeric($majver{0})) { + $majver = substr($majver, 1); + } + if (($versioncomponents[0] != 0) && $majver != $versioncomponents[0]) { + $this->_addWarning('version', 'first version number "' . + $versioncomponents[0] . '" must match the postfix of ' . + 'package name "' . $name . '" (' . + $majver . ')'); + return true; + } + } elseif ($versioncomponents[0] > 1) { + $this->_addWarning('version', 'major version x in x.y.z may not be greater than ' . + '1 for any package that does not have an tag'); + } + return true; + break; + default : + return false; + break; + } + } + + /** + * @access protected + */ + function validateMaintainers() + { + // maintainers can only be truly validated server-side for most channels + // but allow this customization for those who wish it + return true; + } + + /** + * @access protected + */ + function validateDate() + { + if ($this->_state == PEAR_VALIDATE_NORMAL || + $this->_state == PEAR_VALIDATE_PACKAGING) { + + if (!preg_match('/(\d\d\d\d)\-(\d\d)\-(\d\d)/', + $this->_packagexml->getDate(), $res) || + count($res) < 4 + || !checkdate($res[2], $res[3], $res[1]) + ) { + $this->_addFailure('date', 'invalid release date "' . + $this->_packagexml->getDate() . '"'); + return false; + } + + + if ($this->_state == PEAR_VALIDATE_PACKAGING && + $this->_packagexml->getDate() != date('Y-m-d')) { + $this->_addWarning('date', 'Release Date "' . + $this->_packagexml->getDate() . '" is not today'); + } + } + return true; + } + + /** + * @access protected + */ + function validateTime() + { + if (!$this->_packagexml->getTime()) { + // default of no time value set + return true; + } + // packager automatically sets time, so only validate if + // pear validate is called + if ($this->_state = PEAR_VALIDATE_NORMAL) { + if (!preg_match('/\d\d:\d\d:\d\d/', + $this->_packagexml->getTime())) { + $this->_addFailure('time', 'invalid release time "' . + $this->_packagexml->getTime() . '"'); + return false; + } + if (strtotime($this->_packagexml->getTime()) == -1) { + $this->_addFailure('time', 'invalid release time "' . + $this->_packagexml->getTime() . '"'); + return false; + } + } + return true; + } + + /** + * @access protected + */ + function validateState() + { + // this is the closest to "final" php4 can get + if (!PEAR_Validate::validState($this->_packagexml->getState())) { + if (strtolower($this->_packagexml->getState() == 'rc')) { + $this->_addFailure('state', 'RC is not a state, it is a version ' . + 'postfix, use ' . $this->_packagexml->getVersion() . 'RC1, state beta'); + } + $this->_addFailure('state', 'invalid release state "' . + $this->_packagexml->getState() . '", must be one of: ' . + implode(', ', PEAR_Validate::getValidStates())); + return false; + } + return true; + } + + /** + * @access protected + */ + function validateStability() + { + $ret = true; + $packagestability = $this->_packagexml->getState(); + $apistability = $this->_packagexml->getState('api'); + if (!PEAR_Validate::validState($packagestability)) { + $this->_addFailure('state', 'invalid release stability "' . + $this->_packagexml->getState() . '", must be one of: ' . + implode(', ', PEAR_Validate::getValidStates())); + $ret = false; + } + $apistates = PEAR_Validate::getValidStates(); + array_shift($apistates); // snapshot is not allowed + if (!in_array($apistability, $apistates)) { + $this->_addFailure('state', 'invalid API stability "' . + $this->_packagexml->getState('api') . '", must be one of: ' . + implode(', ', $apistates)); + $ret = false; + } + return $ret; + } + + /** + * @access protected + */ + function validateSummary() + { + return true; + } + + /** + * @access protected + */ + function validateDescription() + { + return true; + } + + /** + * @access protected + */ + function validateLicense() + { + return true; + } + + /** + * @access protected + */ + function validateNotes() + { + return true; + } + + /** + * for package.xml 2.0 only - channels can't use package.xml 1.0 + * @access protected + */ + function validateDependencies() + { + return true; + } + + /** + * for package.xml 1.0 only + * @access private + */ + function _validateFilelist() + { + return true; // placeholder for now + } + + /** + * for package.xml 2.0 only + * @access protected + */ + function validateMainFilelist() + { + return true; // placeholder for now + } + + /** + * for package.xml 2.0 only + * @access protected + */ + function validateReleaseFilelist() + { + return true; // placeholder for now + } + + /** + * @access protected + */ + function validateChangelog() + { + return true; + } + + /** + * @access protected + */ + function validateFilelist() + { + return true; + } + + /** + * @access protected + */ + function validateDeps() + { + return true; + } +} +?> diff --git a/src/lib/pear/PEAR/PEAR/Validator/PECL.php b/src/lib/pear/PEAR/PEAR/Validator/PECL.php new file mode 100644 index 0000000..354a5be --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/Validator/PECL.php @@ -0,0 +1,63 @@ + + * @copyright 1997-2006 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: PECL.php,v 1.9 2008/01/03 20:26:37 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 1.4.0a5 + */ +/** + * This is the parent class for all validators + */ +require_once 'PEAR/Validate.php'; +/** + * Channel Validator for the pecl.php.net channel + * @category pear + * @package PEAR + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 1.4.0a5 + */ +class PEAR_Validator_PECL extends PEAR_Validate +{ + function validateVersion() + { + if ($this->_state == PEAR_VALIDATE_PACKAGING) { + $version = $this->_packagexml->getVersion(); + $versioncomponents = explode('.', $version); + $last = array_pop($versioncomponents); + if (substr($last, 1, 2) == 'rc') { + $this->_addFailure('version', 'Release Candidate versions must have ' . + 'upper-case RC, not lower-case rc'); + return false; + } + } + return true; + } + + function validatePackageName() + { + $ret = parent::validatePackageName(); + if ($this->_packagexml->getPackageType() == 'extsrc' || + $this->_packagexml->getPackageType() == 'zendextsrc') { + if (strtolower($this->_packagexml->getPackage()) != + strtolower($this->_packagexml->getProvidesExtension())) { + $this->_addWarning('providesextension', 'package name "' . + $this->_packagexml->getPackage() . '" is different from extension name "' . + $this->_packagexml->getProvidesExtension() . '"'); + } + } + return $ret; + } +} +?> \ No newline at end of file diff --git a/src/lib/pear/PEAR/PEAR/XMLParser.php b/src/lib/pear/PEAR/PEAR/XMLParser.php new file mode 100644 index 0000000..faabc07 --- /dev/null +++ b/src/lib/pear/PEAR/PEAR/XMLParser.php @@ -0,0 +1,261 @@ + + * @author Stephan Schmidt (original XML_Unserializer code) + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: XMLParser.php,v 1.13 2008/01/03 20:26:36 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 1.4.0a1 + */ + +/** + * Parser for any xml file + * @category pear + * @package PEAR + * @author Greg Beaver + * @author Stephan Schmidt (original XML_Unserializer code) + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 1.4.0a1 + */ +class PEAR_XMLParser +{ + /** + * unserilialized data + * @var string $_serializedData + */ + var $_unserializedData = null; + + /** + * name of the root tag + * @var string $_root + */ + var $_root = null; + + /** + * stack for all data that is found + * @var array $_dataStack + */ + var $_dataStack = array(); + + /** + * stack for all values that are generated + * @var array $_valStack + */ + var $_valStack = array(); + + /** + * current tag depth + * @var int $_depth + */ + var $_depth = 0; + + /** + * @return array + */ + function getData() + { + return $this->_unserializedData; + } + + /** + * @param string xml content + * @return true|PEAR_Error + */ + function parse($data) + { + if (!extension_loaded('xml')) { + include_once 'PEAR.php'; + return PEAR::raiseError("XML Extension not found", 1); + } + $this->_valStack = array(); + $this->_dataStack = array(); + $this->_depth = 0; + + if (version_compare(phpversion(), '5.0.0', 'lt')) { + if (strpos($data, 'encoding="UTF-8"')) { + $data = utf8_decode($data); + } + $xp = xml_parser_create('ISO-8859-1'); + } else { + if (strpos($data, 'encoding="UTF-8"')) { + $xp = xml_parser_create('UTF-8'); + } else { + $xp = xml_parser_create('ISO-8859-1'); + } + } + xml_parser_set_option($xp, XML_OPTION_CASE_FOLDING, 0); + xml_set_object($xp, $this); + xml_set_element_handler($xp, 'startHandler', 'endHandler'); + xml_set_character_data_handler($xp, 'cdataHandler'); + if (!xml_parse($xp, $data)) { + $msg = xml_error_string(xml_get_error_code($xp)); + $line = xml_get_current_line_number($xp); + xml_parser_free($xp); + include_once 'PEAR.php'; + return PEAR::raiseError("XML Error: '$msg' on line '$line'", 2); + } + xml_parser_free($xp); + return true; + } + + /** + * Start element handler for XML parser + * + * @access private + * @param object $parser XML parser object + * @param string $element XML element + * @param array $attribs attributes of XML tag + * @return void + */ + function startHandler($parser, $element, $attribs) + { + $type = 'string'; + + $this->_depth++; + $this->_dataStack[$this->_depth] = null; + + $val = array( + 'name' => $element, + 'value' => null, + 'type' => $type, + 'childrenKeys' => array(), + 'aggregKeys' => array() + ); + + if (count($attribs) > 0) { + $val['children'] = array(); + $val['type'] = 'array'; + + $val['children']['attribs'] = $attribs; + + } + + array_push($this->_valStack, $val); + } + + /** + * post-process data + * + * @param string $data + * @param string $element element name + */ + function postProcess($data, $element) + { + return trim($data); + } + + /** + * End element handler for XML parser + * + * @access private + * @param object XML parser object + * @param string + * @return void + */ + function endHandler($parser, $element) + { + $value = array_pop($this->_valStack); + $data = $this->postProcess($this->_dataStack[$this->_depth], $element); + + // adjust type of the value + switch(strtolower($value['type'])) { + + /* + * unserialize an array + */ + case 'array': + if ($data !== '') { + $value['children']['_content'] = $data; + } + if (isset($value['children'])) { + $value['value'] = $value['children']; + } else { + $value['value'] = array(); + } + break; + + /* + * unserialize a null value + */ + case 'null': + $data = null; + break; + + /* + * unserialize any scalar value + */ + default: + settype($data, $value['type']); + $value['value'] = $data; + break; + } + $parent = array_pop($this->_valStack); + if ($parent === null) { + $this->_unserializedData = &$value['value']; + $this->_root = &$value['name']; + return true; + } else { + // parent has to be an array + if (!isset($parent['children']) || !is_array($parent['children'])) { + $parent['children'] = array(); + if ($parent['type'] != 'array') { + $parent['type'] = 'array'; + } + } + + if (!empty($value['name'])) { + // there already has been a tag with this name + if (in_array($value['name'], $parent['childrenKeys'])) { + // no aggregate has been created for this tag + if (!in_array($value['name'], $parent['aggregKeys'])) { + if (isset($parent['children'][$value['name']])) { + $parent['children'][$value['name']] = array($parent['children'][$value['name']]); + } else { + $parent['children'][$value['name']] = array(); + } + array_push($parent['aggregKeys'], $value['name']); + } + array_push($parent['children'][$value['name']], $value['value']); + } else { + $parent['children'][$value['name']] = &$value['value']; + array_push($parent['childrenKeys'], $value['name']); + } + } else { + array_push($parent['children'],$value['value']); + } + array_push($this->_valStack, $parent); + } + + $this->_depth--; + } + + /** + * Handler for character data + * + * @access private + * @param object XML parser object + * @param string CDATA + * @return void + */ + function cdataHandler($parser, $cdata) + { + $this->_dataStack[$this->_depth] .= $cdata; + } +} +?> \ No newline at end of file diff --git a/src/lib/pear/PEAR/Structures/Graph.php b/src/lib/pear/PEAR/Structures/Graph.php new file mode 100644 index 0000000..3757f15 --- /dev/null +++ b/src/lib/pear/PEAR/Structures/Graph.php @@ -0,0 +1,154 @@ + | +// +-----------------------------------------------------------------------------+ +// +/** + * The Graph.php file contains the definition of the Structures_Graph class + * + * @see Structures_Graph + * @package Structures_Graph + */ + +/* dependencies {{{ */ +/** PEAR base classes */ +require_once 'PEAR.php'; +/** Graph Node */ +require_once 'Structures/Graph/Node.php'; +/* }}} */ + +define('STRUCTURES_GRAPH_ERROR_GENERIC', 100); + +/* class Structures_Graph {{{ */ +/** + * The Structures_Graph class represents a graph data structure. + * + * A Graph is a data structure composed by a set of nodes, connected by arcs. + * Graphs may either be directed or undirected. In a directed graph, arcs are + * directional, and can be traveled only one way. In an undirected graph, arcs + * are bidirectional, and can be traveled both ways. + * + * @author Sérgio Carvalho + * @copyright (c) 2004 by Sérgio Carvalho + * @package Structures_Graph + */ +/* }}} */ +class Structures_Graph { + /* fields {{{ */ + /** + * @access private + */ + var $_nodes = array(); + /** + * @access private + */ + var $_directed = false; + /* }}} */ + + /* Constructor {{{ */ + /** + * + * Constructor + * + * @param boolean Set to true if the graph is directed. Set to false if it is not directed. (Optional, defaults to true) + * @access public + */ + function Structures_Graph($directed = true) { + $this->_directed = $directed; + } + /* }}} */ + + /* isDirected {{{ */ + /** + * + * Return true if a graph is directed + * + * @return boolean true if the graph is directed + * @access public + */ + function isDirected() { + return (boolean) $this->_directed; + } + /* }}} */ + + /* addNode {{{ */ + /** + * + * Add a Node to the Graph + * + * @param Structures_Graph_Node The node to be added. + * @access public + */ + function addNode(&$newNode) { + // We only add nodes + if (!is_a($newNode, 'Structures_Graph_Node')) return Pear::raiseError('Structures_Graph::addNode received an object that is not a Structures_Graph_Node', STRUCTURES_GRAPH_ERROR_GENERIC); + // Graphs are node *sets*, so duplicates are forbidden. We allow nodes that are exactly equal, but disallow equal references. + foreach($this->_nodes as $key => $node) { + /* + ZE1 equality operators choke on the recursive cycle introduced by the _graph field in the Node object. + So, we'll check references the hard way (change $this->_nodes[$key] and check if the change reflects in + $node) + */ + $savedData = $this->_nodes[$key]; + $referenceIsEqualFlag = false; + $this->_nodes[$key] = true; + if ($node === true) { + $this->_nodes[$key] = false; + if ($node === false) $referenceIsEqualFlag = true; + } + $this->_nodes[$key] = $savedData; + if ($referenceIsEqualFlag) return Pear::raiseError('Structures_Graph::addNode received an object that is a duplicate for this dataset', STRUCTURES_GRAPH_ERROR_GENERIC); + } + $this->_nodes[] =& $newNode; + $newNode->setGraph($this); + } + /* }}} */ + + /* removeNode (unimplemented) {{{ */ + /** + * + * Remove a Node from the Graph + * + * @todo This is unimplemented + * @param Structures_Graph_Node The node to be removed from the graph + * @access public + */ + function removeNode(&$node) { + } + /* }}} */ + + /* getNodes {{{ */ + /** + * + * Return the node set, in no particular order. For ordered node sets, use a Graph Manipulator insted. + * + * @access public + * @see Structures_Graph_Manipulator_TopologicalSorter + * @return array The set of nodes in this graph + */ + function &getNodes() { + return $this->_nodes; + } + /* }}} */ +} +?> diff --git a/src/lib/pear/PEAR/Structures/Graph/Manipulator/AcyclicTest.php b/src/lib/pear/PEAR/Structures/Graph/Manipulator/AcyclicTest.php new file mode 100644 index 0000000..fc1ba92 --- /dev/null +++ b/src/lib/pear/PEAR/Structures/Graph/Manipulator/AcyclicTest.php @@ -0,0 +1,136 @@ + | +// +-----------------------------------------------------------------------------+ +// +/** + * This file contains the definition of the Structures_Graph_Manipulator_AcyclicTest graph manipulator. + * + * @see Structures_Graph_Manipulator_AcyclicTest + * @package Structures_Graph + */ + +/* dependencies {{{ */ +/** */ +require_once 'PEAR.php'; +/** */ +require_once 'Structures/Graph.php'; +/** */ +require_once 'Structures/Graph/Node.php'; +/* }}} */ + +/* class Structures_Graph_Manipulator_AcyclicTest {{{ */ +/** + * The Structures_Graph_Manipulator_AcyclicTest is a graph manipulator + * which tests whether a graph contains a cycle. + * + * The definition of an acyclic graph used in this manipulator is that of a + * DAG. The graph must be directed, or else it is considered cyclic, even when + * there are no arcs. + * + * @author Sérgio Carvalho + * @copyright (c) 2004 by Sérgio Carvalho + * @package Structures_Graph + */ +class Structures_Graph_Manipulator_AcyclicTest { + /* _nonVisitedInDegree {{{ */ + /** + * + * This is a variant of Structures_Graph::inDegree which does + * not count nodes marked as visited. + * + * @access private + * @return integer Number of non-visited nodes that link to this one + */ + function _nonVisitedInDegree(&$node) { + $result = 0; + $graphNodes =& $node->_graph->getNodes(); + foreach (array_keys($graphNodes) as $key) { + if ((!$graphNodes[$key]->getMetadata('acyclic-test-visited')) && $graphNodes[$key]->connectsTo($node)) $result++; + } + return $result; + + } + /* }}} */ + + /* _isAcyclic {{{ */ + /** + * @access private + */ + function _isAcyclic(&$graph) { + // Mark every node as not visited + $nodes =& $graph->getNodes(); + $nodeKeys = array_keys($nodes); + $refGenerator = array(); + foreach($nodeKeys as $key) { + $refGenerator[] = false; + $nodes[$key]->setMetadata('acyclic-test-visited', $refGenerator[sizeof($refGenerator) - 1]); + } + + // Iteratively peel off leaf nodes + do { + // Find out which nodes are leafs (excluding visited nodes) + $leafNodes = array(); + foreach($nodeKeys as $key) { + if ((!$nodes[$key]->getMetadata('acyclic-test-visited')) && Structures_Graph_Manipulator_AcyclicTest::_nonVisitedInDegree($nodes[$key]) == 0) { + $leafNodes[] =& $nodes[$key]; + } + } + // Mark leafs as visited + for ($i=sizeof($leafNodes) - 1; $i>=0; $i--) { + $visited =& $leafNodes[$i]->getMetadata('acyclic-test-visited'); + $visited = true; + $leafNodes[$i]->setMetadata('acyclic-test-visited', $visited); + } + } while (sizeof($leafNodes) > 0); + + // If graph is a DAG, there should be no non-visited nodes. Let's try to prove otherwise + $result = true; + foreach($nodeKeys as $key) if (!$nodes[$key]->getMetadata('acyclic-test-visited')) $result = false; + + // Cleanup visited marks + foreach($nodeKeys as $key) $nodes[$key]->unsetMetadata('acyclic-test-visited'); + + return $result; + } + /* }}} */ + + /* isAcyclic {{{ */ + /** + * + * isAcyclic returns true if a graph contains no cycles, false otherwise. + * + * @return boolean true iff graph is acyclic + * @access public + */ + function isAcyclic(&$graph) { + // We only test graphs + if (!is_a($graph, 'Structures_Graph')) return Pear::raiseError('Structures_Graph_Manipulator_AcyclicTest::isAcyclic received an object that is not a Structures_Graph', STRUCTURES_GRAPH_ERROR_GENERIC); + if (!$graph->isDirected()) return false; // Only directed graphs may be acyclic + + return Structures_Graph_Manipulator_AcyclicTest::_isAcyclic($graph); + } + /* }}} */ +} +/* }}} */ +?> diff --git a/src/lib/pear/PEAR/Structures/Graph/Manipulator/TopologicalSorter.php b/src/lib/pear/PEAR/Structures/Graph/Manipulator/TopologicalSorter.php new file mode 100644 index 0000000..98a9fa0 --- /dev/null +++ b/src/lib/pear/PEAR/Structures/Graph/Manipulator/TopologicalSorter.php @@ -0,0 +1,153 @@ + | +// +-----------------------------------------------------------------------------+ +// +/** + * This file contains the definition of the Structures_Graph_Manipulator_TopologicalSorter class. + * + * @see Structures_Graph_Manipulator_TopologicalSorter + * @package Structures_Graph + */ + +/* dependencies {{{ */ +/** */ +require_once 'PEAR.php'; +/** */ +require_once 'Structures/Graph.php'; +/** */ +require_once 'Structures/Graph/Node.php'; +/** */ +require_once 'Structures/Graph/Manipulator/AcyclicTest.php'; +/* }}} */ + +/* class Structures_Graph_Manipulator_TopologicalSorter {{{ */ +/** + * The Structures_Graph_Manipulator_TopologicalSorter is a manipulator + * which is able to return the set of nodes in a graph, sorted by topological + * order. + * + * A graph may only be sorted topologically iff it's a DAG. You can test it + * with the Structures_Graph_Manipulator_AcyclicTest. + * + * @author Sérgio Carvalho + * @copyright (c) 2004 by Sérgio Carvalho + * @see Structures_Graph_Manipulator_AcyclicTest + * @package Structures_Graph + */ +class Structures_Graph_Manipulator_TopologicalSorter { + /* _nonVisitedInDegree {{{ */ + /** + * + * This is a variant of Structures_Graph::inDegree which does + * not count nodes marked as visited. + * + * @access private + * @return integer Number of non-visited nodes that link to this one + */ + function _nonVisitedInDegree(&$node) { + $result = 0; + $graphNodes =& $node->_graph->getNodes(); + foreach (array_keys($graphNodes) as $key) { + if ((!$graphNodes[$key]->getMetadata('topological-sort-visited')) && $graphNodes[$key]->connectsTo($node)) $result++; + } + return $result; + + } + /* }}} */ + + /* _sort {{{ */ + /** + * @access private + */ + function _sort(&$graph) { + // Mark every node as not visited + $nodes =& $graph->getNodes(); + $nodeKeys = array_keys($nodes); + $refGenerator = array(); + foreach($nodeKeys as $key) { + $refGenerator[] = false; + $nodes[$key]->setMetadata('topological-sort-visited', $refGenerator[sizeof($refGenerator) - 1]); + } + + // Iteratively peel off leaf nodes + $topologicalLevel = 0; + do { + // Find out which nodes are leafs (excluding visited nodes) + $leafNodes = array(); + foreach($nodeKeys as $key) { + if ((!$nodes[$key]->getMetadata('topological-sort-visited')) && Structures_Graph_Manipulator_TopologicalSorter::_nonVisitedInDegree($nodes[$key]) == 0) { + $leafNodes[] =& $nodes[$key]; + } + } + // Mark leafs as visited + $refGenerator[] = $topologicalLevel; + for ($i=sizeof($leafNodes) - 1; $i>=0; $i--) { + $visited =& $leafNodes[$i]->getMetadata('topological-sort-visited'); + $visited = true; + $leafNodes[$i]->setMetadata('topological-sort-visited', $visited); + $leafNodes[$i]->setMetadata('topological-sort-level', $refGenerator[sizeof($refGenerator) - 1]); + } + $topologicalLevel++; + } while (sizeof($leafNodes) > 0); + + // Cleanup visited marks + foreach($nodeKeys as $key) $nodes[$key]->unsetMetadata('topological-sort-visited'); + } + /* }}} */ + + /* sort {{{ */ + /** + * + * sort returns the graph's nodes, sorted by topological order. + * + * The result is an array with + * as many entries as topological levels. Each entry in this array is an array of nodes within + * the given topological level. + * + * @return array The graph's nodes, sorted by topological order. + * @access public + */ + function sort(&$graph) { + // We only sort graphs + if (!is_a($graph, 'Structures_Graph')) return Pear::raiseError('Structures_Graph_Manipulator_TopologicalSorter::sort received an object that is not a Structures_Graph', STRUCTURES_GRAPH_ERROR_GENERIC); + if (!Structures_Graph_Manipulator_AcyclicTest::isAcyclic($graph)) return Pear::raiseError('Structures_Graph_Manipulator_TopologicalSorter::sort received an graph that has cycles', STRUCTURES_GRAPH_ERROR_GENERIC); + + Structures_Graph_Manipulator_TopologicalSorter::_sort($graph); + $result = array(); + + // Fill out result array + $nodes =& $graph->getNodes(); + $nodeKeys = array_keys($nodes); + foreach($nodeKeys as $key) { + if (!array_key_exists($nodes[$key]->getMetadata('topological-sort-level'), $result)) $result[$nodes[$key]->getMetadata('topological-sort-level')] = array(); + $result[$nodes[$key]->getMetadata('topological-sort-level')][] =& $nodes[$key]; + $nodes[$key]->unsetMetadata('topological-sort-level'); + } + + return $result; + } + /* }}} */ +} +/* }}} */ +?> diff --git a/src/lib/pear/PEAR/Structures/Graph/Node.php b/src/lib/pear/PEAR/Structures/Graph/Node.php new file mode 100644 index 0000000..a2ea415 --- /dev/null +++ b/src/lib/pear/PEAR/Structures/Graph/Node.php @@ -0,0 +1,338 @@ + | +// +-----------------------------------------------------------------------------+ +// +/** + * This file contains the definition of the Structures_Graph_Node class + * + * @see Structures_Graph_Node + * @package Structures_Graph + */ + +/* dependencies {{{ */ +/** */ +require_once 'PEAR.php'; +/** */ +require_once 'Structures/Graph.php'; +/* }}} */ + +/* class Structures_Graph_Node {{{ */ +/** + * The Structures_Graph_Node class represents a Node that can be member of a + * graph node set. + * + * A graph node can contain data. Under this API, the node contains default data, + * and key index data. It behaves, thus, both as a regular data node, and as a + * dictionary (or associative array) node. + * + * Regular data is accessed via getData and setData. Key indexed data is accessed + * via getMetadata and setMetadata. + * + * @author Sérgio Carvalho + * @copyright (c) 2004 by Sérgio Carvalho + * @package Structures_Graph + */ +/* }}} */ +class Structures_Graph_Node { + /* fields {{{ */ + /** + * @access private + */ + var $_data = null; + /** @access private */ + var $_metadata = array(); + /** @access private */ + var $_arcs = array(); + /** @access private */ + var $_graph = null; + /* }}} */ + + /* Constructor {{{ */ + /** + * + * Constructor + * + * @access public + */ + function Structures_Graph_Node() { + } + /* }}} */ + + /* getGraph {{{ */ + /** + * + * Node graph getter + * + * @return Structures_Graph Graph where node is stored + * @access public + */ + function &getGraph() { + return $this->_graph; + } + /* }}} */ + + /* setGraph {{{ */ + /** + * + * Node graph setter. This method should not be called directly. Use Graph::addNode instead. + * + * @param Structures_Graph Set the graph for this node. + * @see Structures_Graph::addNode() + * @access public + */ + function setGraph(&$graph) { + $this->_graph =& $graph; + } + /* }}} */ + + /* getData {{{ */ + /** + * + * Node data getter. + * + * Each graph node can contain a reference to one variable. This is the getter for that reference. + * + * @return mixed Data stored in node + * @access public + */ + function &getData() { + return $this->_data; + } + /* }}} */ + + /* setData {{{ */ + /** + * + * Node data setter + * + * Each graph node can contain a reference to one variable. This is the setter for that reference. + * + * @return mixed Data to store in node + * @access public + */ + function setData($data) { + $this->_data =& $data; + } + /* }}} */ + + /* metadataKeyExists {{{ */ + /** + * + * Test for existence of metadata under a given key. + * + * Each graph node can contain multiple 'metadata' entries, each stored under a different key, as in an + * associative array or in a dictionary. This method tests whether a given metadata key exists for this node. + * + * @param string Key to test + * @return boolean + * @access public + */ + function metadataKeyExists($key) { + return array_key_exists($key, $this->_metadata); + } + /* }}} */ + + /* getMetadata {{{ */ + /** + * + * Node metadata getter + * + * Each graph node can contain multiple 'metadata' entries, each stored under a different key, as in an + * associative array or in a dictionary. This method gets the data under the given key. If the key does + * not exist, an error will be thrown, so testing using metadataKeyExists might be needed. + * + * @param string Key + * @param boolean nullIfNonexistent (defaults to false). + * @return mixed Metadata Data stored in node under given key + * @see metadataKeyExists + * @access public + */ + function &getMetadata($key, $nullIfNonexistent = false) { + if (array_key_exists($key, $this->_metadata)) { + return $this->_metadata[$key]; + } else { + if ($nullIfNonexistent) { + $a = null; + return $a; + } else { + $a = Pear::raiseError('Structures_Graph_Node::getMetadata: Requested key does not exist', STRUCTURES_GRAPH_ERROR_GENERIC); + return $a; + } + } + } + /* }}} */ + + /* unsetMetadata {{{ */ + /** + * + * Delete metadata by key + * + * Each graph node can contain multiple 'metadata' entries, each stored under a different key, as in an + * associative array or in a dictionary. This method removes any data that might be stored under the provided key. + * If the key does not exist, no error is thrown, so it is safe using this method without testing for key existence. + * + * @param string Key + * @access public + */ + function unsetMetadata($key) { + if (array_key_exists($key, $this->_metadata)) unset($this->_metadata[$key]); + } + /* }}} */ + + /* setMetadata {{{ */ + /** + * + * Node metadata setter + * + * Each graph node can contain multiple 'metadata' entries, each stored under a different key, as in an + * associative array or in a dictionary. This method stores data under the given key. If the key already exists, + * previously stored data is discarded. + * + * @param string Key + * @param mixed Data + * @access public + */ + function setMetadata($key, $data) { + $this->_metadata[$key] =& $data; + } + /* }}} */ + + /* _connectTo {{{ */ + /** @access private */ + function _connectTo(&$destinationNode) { + $this->_arcs[] =& $destinationNode; + } + /* }}} */ + + /* connectTo {{{ */ + /** + * + * Connect this node to another one. + * + * If the graph is not directed, the reverse arc, connecting $destinationNode to $this is also created. + * + * @param Structures_Graph Node to connect to + * @access public + */ + function connectTo(&$destinationNode) { + // We only connect to nodes + if (!is_a($destinationNode, 'Structures_Graph_Node')) return Pear::raiseError('Structures_Graph_Node::connectTo received an object that is not a Structures_Graph_Node', STRUCTURES_GRAPH_ERROR_GENERIC); + // Nodes must already be in graphs to be connected + if ($this->_graph == null) return Pear::raiseError('Structures_Graph_Node::connectTo Tried to connect a node that is not in a graph', STRUCTURES_GRAPH_ERROR_GENERIC); + if ($destinationNode->getGraph() == null) return Pear::raiseError('Structures_Graph_Node::connectTo Tried to connect to a node that is not in a graph', STRUCTURES_GRAPH_ERROR_GENERIC); + // Connect here + $this->_connectTo($destinationNode); + // If graph is undirected, connect back + if (!$this->_graph->isDirected()) { + $destinationNode->_connectTo($this); + } + } + /* }}} */ + + /* getNeighbours {{{ */ + /** + * + * Return nodes connected to this one. + * + * @return array Array of nodes + * @access public + */ + function getNeighbours() { + return $this->_arcs; + } + /* }}} */ + + /* connectsTo {{{ */ + /** + * + * Test wether this node has an arc to the target node + * + * @return boolean True if the two nodes are connected + * @access public + */ + function connectsTo(&$target) { + $copy = $target; + $arcKeys = array_keys($this->_arcs); + foreach($arcKeys as $key) { + /* ZE1 chokes on this expression: + if ($target === $arc) return true; + so, we'll use more convoluted stuff + */ + $arc =& $this->_arcs[$key]; + $target = true; + if ($arc === true) { + $target = false; + if ($arc === false) { + $target = $copy; + return true; + } + } + } + $target = $copy; + return false; + } + /* }}} */ + + /* inDegree {{{ */ + /** + * + * Calculate the in degree of the node. + * + * The indegree for a node is the number of arcs entering the node. For non directed graphs, + * the indegree is equal to the outdegree. + * + * @return integer In degree of the node + * @access public + */ + function inDegree() { + if ($this->_graph == null) return 0; + if (!$this->_graph->isDirected()) return $this->outDegree(); + $result = 0; + $graphNodes =& $this->_graph->getNodes(); + foreach (array_keys($graphNodes) as $key) { + if ($graphNodes[$key]->connectsTo($this)) $result++; + } + return $result; + + } + /* }}} */ + + /* outDegree {{{ */ + /** + * + * Calculate the out degree of the node. + * + * The outdegree for a node is the number of arcs exiting the node. For non directed graphs, + * the outdegree is always equal to the indegree. + * + * @return integer Out degree of the node + * @access public + */ + function outDegree() { + if ($this->_graph == null) return 0; + return sizeof($this->_arcs); + } + /* }}} */ +} +?> diff --git a/src/lib/pear/PEAR/System.php b/src/lib/pear/PEAR/System.php new file mode 100644 index 0000000..534f0a9 --- /dev/null +++ b/src/lib/pear/PEAR/System.php @@ -0,0 +1,606 @@ + + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: System.php,v 1.62 2008/01/03 20:26:34 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 0.1 + */ + +/** + * base class + */ +require_once 'PEAR.php'; +require_once 'Console/Getopt.php'; + +$GLOBALS['_System_temp_files'] = array(); + +/** +* System offers cross plattform compatible system functions +* +* Static functions for different operations. Should work under +* Unix and Windows. The names and usage has been taken from its respectively +* GNU commands. The functions will return (bool) false on error and will +* trigger the error with the PHP trigger_error() function (you can silence +* the error by prefixing a '@' sign after the function call, but this +* is not recommended practice. Instead use an error handler with +* {@link set_error_handler()}). +* +* Documentation on this class you can find in: +* http://pear.php.net/manual/ +* +* Example usage: +* if (!@System::rm('-r file1 dir1')) { +* print "could not delete file1 or dir1"; +* } +* +* In case you need to to pass file names with spaces, +* pass the params as an array: +* +* System::rm(array('-r', $file1, $dir1)); +* +* @category pear +* @package System +* @author Tomas V.V. Cox +* @copyright 1997-2006 The PHP Group +* @license http://www.php.net/license/3_0.txt PHP License 3.0 +* @version Release: 1.7.2 +* @link http://pear.php.net/package/PEAR +* @since Class available since Release 0.1 +* @static +*/ +class System +{ + /** + * returns the commandline arguments of a function + * + * @param string $argv the commandline + * @param string $short_options the allowed option short-tags + * @param string $long_options the allowed option long-tags + * @return array the given options and there values + * @static + * @access private + */ + function _parseArgs($argv, $short_options, $long_options = null) + { + if (!is_array($argv) && $argv !== null) { + $argv = preg_split('/\s+/', $argv, -1, PREG_SPLIT_NO_EMPTY); + } + return Console_Getopt::getopt2($argv, $short_options); + } + + /** + * Output errors with PHP trigger_error(). You can silence the errors + * with prefixing a "@" sign to the function call: @System::mkdir(..); + * + * @param mixed $error a PEAR error or a string with the error message + * @return bool false + * @static + * @access private + */ + function raiseError($error) + { + if (PEAR::isError($error)) { + $error = $error->getMessage(); + } + trigger_error($error, E_USER_WARNING); + return false; + } + + /** + * Creates a nested array representing the structure of a directory + * + * System::_dirToStruct('dir1', 0) => + * Array + * ( + * [dirs] => Array + * ( + * [0] => dir1 + * ) + * + * [files] => Array + * ( + * [0] => dir1/file2 + * [1] => dir1/file3 + * ) + * ) + * @param string $sPath Name of the directory + * @param integer $maxinst max. deep of the lookup + * @param integer $aktinst starting deep of the lookup + * @param bool $silent if true, do not emit errors. + * @return array the structure of the dir + * @static + * @access private + */ + + function _dirToStruct($sPath, $maxinst, $aktinst = 0, $silent = false) + { + $struct = array('dirs' => array(), 'files' => array()); + if (($dir = @opendir($sPath)) === false) { + if (!$silent) { + System::raiseError("Could not open dir $sPath"); + } + return $struct; // XXX could not open error + } + $struct['dirs'][] = $sPath = realpath($sPath); // XXX don't add if '.' or '..' ? + $list = array(); + while (false !== ($file = readdir($dir))) { + if ($file != '.' && $file != '..') { + $list[] = $file; + } + } + closedir($dir); + sort($list); + if ($aktinst < $maxinst || $maxinst == 0) { + foreach ($list as $val) { + $path = $sPath . DIRECTORY_SEPARATOR . $val; + if (is_dir($path) && !is_link($path)) { + $tmp = System::_dirToStruct($path, $maxinst, $aktinst+1, $silent); + $struct = array_merge_recursive($tmp, $struct); + } else { + $struct['files'][] = $path; + } + } + } + return $struct; + } + + /** + * Creates a nested array representing the structure of a directory and files + * + * @param array $files Array listing files and dirs + * @return array + * @static + * @see System::_dirToStruct() + */ + function _multipleToStruct($files) + { + $struct = array('dirs' => array(), 'files' => array()); + settype($files, 'array'); + foreach ($files as $file) { + if (is_dir($file) && !is_link($file)) { + $tmp = System::_dirToStruct($file, 0); + $struct = array_merge_recursive($tmp, $struct); + } else { + $struct['files'][] = $file; + } + } + return $struct; + } + + /** + * The rm command for removing files. + * Supports multiple files and dirs and also recursive deletes + * + * @param string $args the arguments for rm + * @return mixed PEAR_Error or true for success + * @static + * @access public + */ + function rm($args) + { + $opts = System::_parseArgs($args, 'rf'); // "f" does nothing but I like it :-) + if (PEAR::isError($opts)) { + return System::raiseError($opts); + } + foreach ($opts[0] as $opt) { + if ($opt[0] == 'r') { + $do_recursive = true; + } + } + $ret = true; + if (isset($do_recursive)) { + $struct = System::_multipleToStruct($opts[1]); + foreach ($struct['files'] as $file) { + if (!@unlink($file)) { + $ret = false; + } + } + foreach ($struct['dirs'] as $dir) { + if (!@rmdir($dir)) { + $ret = false; + } + } + } else { + foreach ($opts[1] as $file) { + $delete = (is_dir($file)) ? 'rmdir' : 'unlink'; + if (!@$delete($file)) { + $ret = false; + } + } + } + return $ret; + } + + /** + * Make directories. + * + * The -p option will create parent directories + * @param string $args the name of the director(y|ies) to create + * @return bool True for success + * @static + * @access public + */ + function mkDir($args) + { + $opts = System::_parseArgs($args, 'pm:'); + if (PEAR::isError($opts)) { + return System::raiseError($opts); + } + $mode = 0777; // default mode + foreach ($opts[0] as $opt) { + if ($opt[0] == 'p') { + $create_parents = true; + } elseif ($opt[0] == 'm') { + // if the mode is clearly an octal number (starts with 0) + // convert it to decimal + if (strlen($opt[1]) && $opt[1]{0} == '0') { + $opt[1] = octdec($opt[1]); + } else { + // convert to int + $opt[1] += 0; + } + $mode = $opt[1]; + } + } + $ret = true; + if (isset($create_parents)) { + foreach ($opts[1] as $dir) { + $dirstack = array(); + while ((!file_exists($dir) || !is_dir($dir)) && + $dir != DIRECTORY_SEPARATOR) { + array_unshift($dirstack, $dir); + $dir = dirname($dir); + } + while ($newdir = array_shift($dirstack)) { + if (!is_writeable(dirname($newdir))) { + $ret = false; + break; + } + if (!mkdir($newdir, $mode)) { + $ret = false; + } + } + } + } else { + foreach($opts[1] as $dir) { + if ((@file_exists($dir) || !is_dir($dir)) && !mkdir($dir, $mode)) { + $ret = false; + } + } + } + return $ret; + } + + /** + * Concatenate files + * + * Usage: + * 1) $var = System::cat('sample.txt test.txt'); + * 2) System::cat('sample.txt test.txt > final.txt'); + * 3) System::cat('sample.txt test.txt >> final.txt'); + * + * Note: as the class use fopen, urls should work also (test that) + * + * @param string $args the arguments + * @return boolean true on success + * @static + * @access public + */ + function &cat($args) + { + $ret = null; + $files = array(); + if (!is_array($args)) { + $args = preg_split('/\s+/', $args, -1, PREG_SPLIT_NO_EMPTY); + } + + $count_args = count($args); + for ($i = 0; $i < $count_args; $i++) { + if ($args[$i] == '>') { + $mode = 'wb'; + $outputfile = $args[$i+1]; + break; + } elseif ($args[$i] == '>>') { + $mode = 'ab+'; + $outputfile = $args[$i+1]; + break; + } else { + $files[] = $args[$i]; + } + } + $outputfd = false; + if (isset($mode)) { + if (!$outputfd = fopen($outputfile, $mode)) { + $err = System::raiseError("Could not open $outputfile"); + return $err; + } + $ret = true; + } + foreach ($files as $file) { + if (!$fd = fopen($file, 'r')) { + System::raiseError("Could not open $file"); + continue; + } + while ($cont = fread($fd, 2048)) { + if (is_resource($outputfd)) { + fwrite($outputfd, $cont); + } else { + $ret .= $cont; + } + } + fclose($fd); + } + if (is_resource($outputfd)) { + fclose($outputfd); + } + return $ret; + } + + /** + * Creates temporary files or directories. This function will remove + * the created files when the scripts finish its execution. + * + * Usage: + * 1) $tempfile = System::mktemp("prefix"); + * 2) $tempdir = System::mktemp("-d prefix"); + * 3) $tempfile = System::mktemp(); + * 4) $tempfile = System::mktemp("-t /var/tmp prefix"); + * + * prefix -> The string that will be prepended to the temp name + * (defaults to "tmp"). + * -d -> A temporary dir will be created instead of a file. + * -t -> The target dir where the temporary (file|dir) will be created. If + * this param is missing by default the env vars TMP on Windows or + * TMPDIR in Unix will be used. If these vars are also missing + * c:\windows\temp or /tmp will be used. + * + * @param string $args The arguments + * @return mixed the full path of the created (file|dir) or false + * @see System::tmpdir() + * @static + * @access public + */ + function mktemp($args = null) + { + static $first_time = true; + $opts = System::_parseArgs($args, 't:d'); + if (PEAR::isError($opts)) { + return System::raiseError($opts); + } + foreach ($opts[0] as $opt) { + if ($opt[0] == 'd') { + $tmp_is_dir = true; + } elseif ($opt[0] == 't') { + $tmpdir = $opt[1]; + } + } + $prefix = (isset($opts[1][0])) ? $opts[1][0] : 'tmp'; + if (!isset($tmpdir)) { + $tmpdir = System::tmpdir(); + } + if (!System::mkDir(array('-p', $tmpdir))) { + return false; + } + $tmp = tempnam($tmpdir, $prefix); + if (isset($tmp_is_dir)) { + unlink($tmp); // be careful possible race condition here + if (!mkdir($tmp, 0700)) { + return System::raiseError("Unable to create temporary directory $tmpdir"); + } + } + $GLOBALS['_System_temp_files'][] = $tmp; + if ($first_time) { + PEAR::registerShutdownFunc(array('System', '_removeTmpFiles')); + $first_time = false; + } + return $tmp; + } + + /** + * Remove temporary files created my mkTemp. This function is executed + * at script shutdown time + * + * @static + * @access private + */ + function _removeTmpFiles() + { + if (count($GLOBALS['_System_temp_files'])) { + $delete = $GLOBALS['_System_temp_files']; + array_unshift($delete, '-r'); + System::rm($delete); + $GLOBALS['_System_temp_files'] = array(); + } + } + + /** + * Get the path of the temporal directory set in the system + * by looking in its environments variables. + * Note: php.ini-recommended removes the "E" from the variables_order setting, + * making unavaible the $_ENV array, that s why we do tests with _ENV + * + * @static + * @return string The temporary directory on the system + */ + function tmpdir() + { + if (OS_WINDOWS) { + if ($var = isset($_ENV['TMP']) ? $_ENV['TMP'] : getenv('TMP')) { + return $var; + } + if ($var = isset($_ENV['TEMP']) ? $_ENV['TEMP'] : getenv('TEMP')) { + return $var; + } + if ($var = isset($_ENV['USERPROFILE']) ? $_ENV['USERPROFILE'] : getenv('USERPROFILE')) { + return $var; + } + if ($var = isset($_ENV['windir']) ? $_ENV['windir'] : getenv('windir')) { + return $var; + } + return getenv('SystemRoot') . '\temp'; + } + if ($var = isset($_ENV['TMPDIR']) ? $_ENV['TMPDIR'] : getenv('TMPDIR')) { + return $var; + } + return realpath('/tmp'); + } + + /** + * The "which" command (show the full path of a command) + * + * @param string $program The command to search for + * @param mixed $fallback Value to return if $program is not found + * + * @return mixed A string with the full path or false if not found + * @static + * @author Stig Bakken + */ + function which($program, $fallback = false) + { + // enforce API + if (!is_string($program) || '' == $program) { + return $fallback; + } + + // full path given + if (basename($program) != $program) { + $path_elements[] = dirname($program); + $program = basename($program); + } else { + // Honor safe mode + if (!ini_get('safe_mode') || !$path = ini_get('safe_mode_exec_dir')) { + $path = getenv('PATH'); + if (!$path) { + $path = getenv('Path'); // some OSes are just stupid enough to do this + } + } + $path_elements = explode(PATH_SEPARATOR, $path); + } + + if (OS_WINDOWS) { + $exe_suffixes = getenv('PATHEXT') + ? explode(PATH_SEPARATOR, getenv('PATHEXT')) + : array('.exe','.bat','.cmd','.com'); + // allow passing a command.exe param + if (strpos($program, '.') !== false) { + array_unshift($exe_suffixes, ''); + } + // is_executable() is not available on windows for PHP4 + $pear_is_executable = (function_exists('is_executable')) ? 'is_executable' : 'is_file'; + } else { + $exe_suffixes = array(''); + $pear_is_executable = 'is_executable'; + } + + foreach ($exe_suffixes as $suff) { + foreach ($path_elements as $dir) { + $file = $dir . DIRECTORY_SEPARATOR . $program . $suff; + if (@$pear_is_executable($file)) { + return $file; + } + } + } + return $fallback; + } + + /** + * The "find" command + * + * Usage: + * + * System::find($dir); + * System::find("$dir -type d"); + * System::find("$dir -type f"); + * System::find("$dir -name *.php"); + * System::find("$dir -name *.php -name *.htm*"); + * System::find("$dir -maxdepth 1"); + * + * Params implmented: + * $dir -> Start the search at this directory + * -type d -> return only directories + * -type f -> return only files + * -maxdepth -> max depth of recursion + * -name -> search pattern (bash style). Multiple -name param allowed + * + * @param mixed Either array or string with the command line + * @return array Array of found files + * @static + * + */ + function find($args) + { + if (!is_array($args)) { + $args = preg_split('/\s+/', $args, -1, PREG_SPLIT_NO_EMPTY); + } + $dir = realpath(array_shift($args)); + if (!$dir) { + return array(); + } + $patterns = array(); + $depth = 0; + $do_files = $do_dirs = true; + $args_count = count($args); + for ($i = 0; $i < $args_count; $i++) { + switch ($args[$i]) { + case '-type': + if (in_array($args[$i+1], array('d', 'f'))) { + if ($args[$i+1] == 'd') { + $do_files = false; + } else { + $do_dirs = false; + } + } + $i++; + break; + case '-name': + $name = preg_quote($args[$i+1], '#'); + // our magic characters ? and * have just been escaped, + // so now we change the escaped versions to PCRE operators + $name = strtr($name, array('\?' => '.', '\*' => '.*')); + $patterns[] = '('.$name.')'; + $i++; + break; + case '-maxdepth': + $depth = $args[$i+1]; + break; + } + } + $path = System::_dirToStruct($dir, $depth, 0, true); + if ($do_files && $do_dirs) { + $files = array_merge($path['files'], $path['dirs']); + } elseif ($do_dirs) { + $files = $path['dirs']; + } else { + $files = $path['files']; + } + if (count($patterns)) { + $dsq = preg_quote(DIRECTORY_SEPARATOR, '#'); + $pattern = '#(^|'.$dsq.')'.implode('|', $patterns).'($|'.$dsq.')#'; + $ret = array(); + $files_count = count($files); + for ($i = 0; $i < $files_count; $i++) { + // only search in the part of the file below the current directory + $filepart = basename($files[$i]); + if (preg_match($pattern, $filepart)) { + $ret[] = $files[$i]; + } + } + return $ret; + } + return $files; + } +} \ No newline at end of file diff --git a/src/lib/pear/PEAR/XML/RPC.php b/src/lib/pear/PEAR/XML/RPC.php new file mode 100644 index 0000000..f3baec2 --- /dev/null +++ b/src/lib/pear/PEAR/XML/RPC.php @@ -0,0 +1,2077 @@ + + * @author Stig Bakken + * @author Martin Jansen + * @author Daniel Convissor + * @copyright 1999-2001 Edd Dumbill, 2001-2006 The PHP Group + * @version CVS: $Id: RPC.php,v 1.101 2006/10/28 16:42:34 danielc Exp $ + * @link http://pear.php.net/package/XML_RPC + */ + + +if (!function_exists('xml_parser_create')) { + include_once 'PEAR.php'; + PEAR::loadExtension('xml'); +} + +/**#@+ + * Error constants + */ +/** + * Parameter values don't match parameter types + */ +define('XML_RPC_ERROR_INVALID_TYPE', 101); +/** + * Parameter declared to be numeric but the values are not + */ +define('XML_RPC_ERROR_NON_NUMERIC_FOUND', 102); +/** + * Communication error + */ +define('XML_RPC_ERROR_CONNECTION_FAILED', 103); +/** + * The array or struct has already been started + */ +define('XML_RPC_ERROR_ALREADY_INITIALIZED', 104); +/** + * Incorrect parameters submitted + */ +define('XML_RPC_ERROR_INCORRECT_PARAMS', 105); +/** + * Programming error by developer + */ +define('XML_RPC_ERROR_PROGRAMMING', 106); +/**#@-*/ + + +/** + * Data types + * @global string $GLOBALS['XML_RPC_I4'] + */ +$GLOBALS['XML_RPC_I4'] = 'i4'; + +/** + * Data types + * @global string $GLOBALS['XML_RPC_Int'] + */ +$GLOBALS['XML_RPC_Int'] = 'int'; + +/** + * Data types + * @global string $GLOBALS['XML_RPC_Boolean'] + */ +$GLOBALS['XML_RPC_Boolean'] = 'boolean'; + +/** + * Data types + * @global string $GLOBALS['XML_RPC_Double'] + */ +$GLOBALS['XML_RPC_Double'] = 'double'; + +/** + * Data types + * @global string $GLOBALS['XML_RPC_String'] + */ +$GLOBALS['XML_RPC_String'] = 'string'; + +/** + * Data types + * @global string $GLOBALS['XML_RPC_DateTime'] + */ +$GLOBALS['XML_RPC_DateTime'] = 'dateTime.iso8601'; + +/** + * Data types + * @global string $GLOBALS['XML_RPC_Base64'] + */ +$GLOBALS['XML_RPC_Base64'] = 'base64'; + +/** + * Data types + * @global string $GLOBALS['XML_RPC_Array'] + */ +$GLOBALS['XML_RPC_Array'] = 'array'; + +/** + * Data types + * @global string $GLOBALS['XML_RPC_Struct'] + */ +$GLOBALS['XML_RPC_Struct'] = 'struct'; + + +/** + * Data type meta-types + * @global array $GLOBALS['XML_RPC_Types'] + */ +$GLOBALS['XML_RPC_Types'] = array( + $GLOBALS['XML_RPC_I4'] => 1, + $GLOBALS['XML_RPC_Int'] => 1, + $GLOBALS['XML_RPC_Boolean'] => 1, + $GLOBALS['XML_RPC_String'] => 1, + $GLOBALS['XML_RPC_Double'] => 1, + $GLOBALS['XML_RPC_DateTime'] => 1, + $GLOBALS['XML_RPC_Base64'] => 1, + $GLOBALS['XML_RPC_Array'] => 2, + $GLOBALS['XML_RPC_Struct'] => 3, +); + + +/** + * Error message numbers + * @global array $GLOBALS['XML_RPC_err'] + */ +$GLOBALS['XML_RPC_err'] = array( + 'unknown_method' => 1, + 'invalid_return' => 2, + 'incorrect_params' => 3, + 'introspect_unknown' => 4, + 'http_error' => 5, + 'not_response_object' => 6, + 'invalid_request' => 7, +); + +/** + * Error message strings + * @global array $GLOBALS['XML_RPC_str'] + */ +$GLOBALS['XML_RPC_str'] = array( + 'unknown_method' => 'Unknown method', + 'invalid_return' => 'Invalid return payload: enable debugging to examine incoming payload', + 'incorrect_params' => 'Incorrect parameters passed to method', + 'introspect_unknown' => 'Can\'t introspect: method unknown', + 'http_error' => 'Didn\'t receive 200 OK from remote server.', + 'not_response_object' => 'The requested method didn\'t return an XML_RPC_Response object.', + 'invalid_request' => 'Invalid request payload', +); + + +/** + * Default XML encoding (ISO-8859-1, UTF-8 or US-ASCII) + * @global string $GLOBALS['XML_RPC_defencoding'] + */ +$GLOBALS['XML_RPC_defencoding'] = 'UTF-8'; + +/** + * User error codes start at 800 + * @global int $GLOBALS['XML_RPC_erruser'] + */ +$GLOBALS['XML_RPC_erruser'] = 800; + +/** + * XML parse error codes start at 100 + * @global int $GLOBALS['XML_RPC_errxml'] + */ +$GLOBALS['XML_RPC_errxml'] = 100; + + +/** + * Compose backslashes for escaping regexp + * @global string $GLOBALS['XML_RPC_backslash'] + */ +$GLOBALS['XML_RPC_backslash'] = chr(92) . chr(92); + + +/**#@+ + * Which functions to use, depending on whether mbstring is enabled or not. + */ +if (function_exists('mb_ereg')) { + /** @global string $GLOBALS['XML_RPC_func_ereg'] */ + $GLOBALS['XML_RPC_func_ereg'] = 'mb_eregi'; + /** @global string $GLOBALS['XML_RPC_func_ereg_replace'] */ + $GLOBALS['XML_RPC_func_ereg_replace'] = 'mb_eregi_replace'; + /** @global string $GLOBALS['XML_RPC_func_split'] */ + $GLOBALS['XML_RPC_func_split'] = 'mb_split'; +} else { + /** @ignore */ + $GLOBALS['XML_RPC_func_ereg'] = 'eregi'; + /** @ignore */ + $GLOBALS['XML_RPC_func_ereg_replace'] = 'eregi_replace'; + /** @ignore */ + $GLOBALS['XML_RPC_func_split'] = 'split'; +} +/**#@-*/ + + +/** + * Should we automatically base64 encode strings that contain characters + * which can cause PHP's SAX-based XML parser to break? + * @global boolean $GLOBALS['XML_RPC_auto_base64'] + */ +$GLOBALS['XML_RPC_auto_base64'] = false; + + +/** + * Valid parents of XML elements + * @global array $GLOBALS['XML_RPC_valid_parents'] + */ +$GLOBALS['XML_RPC_valid_parents'] = array( + 'BOOLEAN' => array('VALUE'), + 'I4' => array('VALUE'), + 'INT' => array('VALUE'), + 'STRING' => array('VALUE'), + 'DOUBLE' => array('VALUE'), + 'DATETIME.ISO8601' => array('VALUE'), + 'BASE64' => array('VALUE'), + 'ARRAY' => array('VALUE'), + 'STRUCT' => array('VALUE'), + 'PARAM' => array('PARAMS'), + 'METHODNAME' => array('METHODCALL'), + 'PARAMS' => array('METHODCALL', 'METHODRESPONSE'), + 'MEMBER' => array('STRUCT'), + 'NAME' => array('MEMBER'), + 'DATA' => array('ARRAY'), + 'FAULT' => array('METHODRESPONSE'), + 'VALUE' => array('MEMBER', 'DATA', 'PARAM', 'FAULT'), +); + + +/** + * Stores state during parsing + * + * quick explanation of components: + * + ac = accumulates values + * + qt = decides if quotes are needed for evaluation + * + cm = denotes struct or array (comma needed) + * + isf = indicates a fault + * + lv = indicates "looking for a value": implements the logic + * to allow values with no types to be strings + * + params = stores parameters in method calls + * + method = stores method name + * + * @global array $GLOBALS['XML_RPC_xh'] + */ +$GLOBALS['XML_RPC_xh'] = array(); + + +/** + * Start element handler for the XML parser + * + * @return void + */ +function XML_RPC_se($parser_resource, $name, $attrs) +{ + global $XML_RPC_xh, $XML_RPC_valid_parents; + + $parser = (int) $parser_resource; + + // if invalid xmlrpc already detected, skip all processing + if ($XML_RPC_xh[$parser]['isf'] >= 2) { + return; + } + + // check for correct element nesting + // top level element can only be of 2 types + if (count($XML_RPC_xh[$parser]['stack']) == 0) { + if ($name != 'METHODRESPONSE' && $name != 'METHODCALL') { + $XML_RPC_xh[$parser]['isf'] = 2; + $XML_RPC_xh[$parser]['isf_reason'] = 'missing top level xmlrpc element'; + return; + } + } else { + // not top level element: see if parent is OK + if (!in_array($XML_RPC_xh[$parser]['stack'][0], $XML_RPC_valid_parents[$name])) { + $name = $GLOBALS['XML_RPC_func_ereg_replace']('[^a-zA-Z0-9._-]', '', $name); + $XML_RPC_xh[$parser]['isf'] = 2; + $XML_RPC_xh[$parser]['isf_reason'] = "xmlrpc element $name cannot be child of {$XML_RPC_xh[$parser]['stack'][0]}"; + return; + } + } + + switch ($name) { + case 'STRUCT': + $XML_RPC_xh[$parser]['cm']++; + + // turn quoting off + $XML_RPC_xh[$parser]['qt'] = 0; + + $cur_val = array(); + $cur_val['value'] = array(); + $cur_val['members'] = 1; + array_unshift($XML_RPC_xh[$parser]['valuestack'], $cur_val); + break; + + case 'ARRAY': + $XML_RPC_xh[$parser]['cm']++; + + // turn quoting off + $XML_RPC_xh[$parser]['qt'] = 0; + + $cur_val = array(); + $cur_val['value'] = array(); + $cur_val['members'] = 0; + array_unshift($XML_RPC_xh[$parser]['valuestack'], $cur_val); + break; + + case 'NAME': + $XML_RPC_xh[$parser]['ac'] = ''; + break; + + case 'FAULT': + $XML_RPC_xh[$parser]['isf'] = 1; + break; + + case 'PARAM': + $XML_RPC_xh[$parser]['valuestack'] = array(); + break; + + case 'VALUE': + $XML_RPC_xh[$parser]['lv'] = 1; + $XML_RPC_xh[$parser]['vt'] = $GLOBALS['XML_RPC_String']; + $XML_RPC_xh[$parser]['ac'] = ''; + $XML_RPC_xh[$parser]['qt'] = 0; + // look for a value: if this is still 1 by the + // time we reach the first data segment then the type is string + // by implication and we need to add in a quote + break; + + case 'I4': + case 'INT': + case 'STRING': + case 'BOOLEAN': + case 'DOUBLE': + case 'DATETIME.ISO8601': + case 'BASE64': + $XML_RPC_xh[$parser]['ac'] = ''; // reset the accumulator + + if ($name == 'DATETIME.ISO8601' || $name == 'STRING') { + $XML_RPC_xh[$parser]['qt'] = 1; + + if ($name == 'DATETIME.ISO8601') { + $XML_RPC_xh[$parser]['vt'] = $GLOBALS['XML_RPC_DateTime']; + } + + } elseif ($name == 'BASE64') { + $XML_RPC_xh[$parser]['qt'] = 2; + } else { + // No quoting is required here -- but + // at the end of the element we must check + // for data format errors. + $XML_RPC_xh[$parser]['qt'] = 0; + } + break; + + case 'MEMBER': + $XML_RPC_xh[$parser]['ac'] = ''; + break; + + case 'DATA': + case 'METHODCALL': + case 'METHODNAME': + case 'METHODRESPONSE': + case 'PARAMS': + // valid elements that add little to processing + break; + } + + + // Save current element to stack + array_unshift($XML_RPC_xh[$parser]['stack'], $name); + + if ($name != 'VALUE') { + $XML_RPC_xh[$parser]['lv'] = 0; + } +} + +/** + * End element handler for the XML parser + * + * @return void + */ +function XML_RPC_ee($parser_resource, $name) +{ + global $XML_RPC_xh; + + $parser = (int) $parser_resource; + + if ($XML_RPC_xh[$parser]['isf'] >= 2) { + return; + } + + // push this element from stack + // NB: if XML validates, correct opening/closing is guaranteed and + // we do not have to check for $name == $curr_elem. + // we also checked for proper nesting at start of elements... + $curr_elem = array_shift($XML_RPC_xh[$parser]['stack']); + + switch ($name) { + case 'STRUCT': + case 'ARRAY': + $cur_val = array_shift($XML_RPC_xh[$parser]['valuestack']); + $XML_RPC_xh[$parser]['value'] = $cur_val['value']; + $XML_RPC_xh[$parser]['vt'] = strtolower($name); + $XML_RPC_xh[$parser]['cm']--; + break; + + case 'NAME': + $XML_RPC_xh[$parser]['valuestack'][0]['name'] = $XML_RPC_xh[$parser]['ac']; + break; + + case 'BOOLEAN': + // special case here: we translate boolean 1 or 0 into PHP + // constants true or false + if ($XML_RPC_xh[$parser]['ac'] == '1') { + $XML_RPC_xh[$parser]['ac'] = 'true'; + } else { + $XML_RPC_xh[$parser]['ac'] = 'false'; + } + + $XML_RPC_xh[$parser]['vt'] = strtolower($name); + // Drop through intentionally. + + case 'I4': + case 'INT': + case 'STRING': + case 'DOUBLE': + case 'DATETIME.ISO8601': + case 'BASE64': + if ($XML_RPC_xh[$parser]['qt'] == 1) { + // we use double quotes rather than single so backslashification works OK + $XML_RPC_xh[$parser]['value'] = $XML_RPC_xh[$parser]['ac']; + } elseif ($XML_RPC_xh[$parser]['qt'] == 2) { + $XML_RPC_xh[$parser]['value'] = base64_decode($XML_RPC_xh[$parser]['ac']); + } elseif ($name == 'BOOLEAN') { + $XML_RPC_xh[$parser]['value'] = $XML_RPC_xh[$parser]['ac']; + } else { + // we have an I4, INT or a DOUBLE + // we must check that only 0123456789-. are characters here + if (!$GLOBALS['XML_RPC_func_ereg']("^[+-]?[0123456789 \t\.]+$", $XML_RPC_xh[$parser]['ac'])) { + XML_RPC_Base::raiseError('Non-numeric value received in INT or DOUBLE', + XML_RPC_ERROR_NON_NUMERIC_FOUND); + $XML_RPC_xh[$parser]['value'] = XML_RPC_ERROR_NON_NUMERIC_FOUND; + } else { + // it's ok, add it on + $XML_RPC_xh[$parser]['value'] = $XML_RPC_xh[$parser]['ac']; + } + } + + $XML_RPC_xh[$parser]['ac'] = ''; + $XML_RPC_xh[$parser]['qt'] = 0; + $XML_RPC_xh[$parser]['lv'] = 3; // indicate we've found a value + break; + + case 'VALUE': + if ($XML_RPC_xh[$parser]['vt'] == $GLOBALS['XML_RPC_String']) { + if (strlen($XML_RPC_xh[$parser]['ac']) > 0) { + $XML_RPC_xh[$parser]['value'] = $XML_RPC_xh[$parser]['ac']; + } elseif ($XML_RPC_xh[$parser]['lv'] == 1) { + // The element was empty. + $XML_RPC_xh[$parser]['value'] = ''; + } + } + + $temp = new XML_RPC_Value($XML_RPC_xh[$parser]['value'], $XML_RPC_xh[$parser]['vt']); + + $cur_val = array_shift($XML_RPC_xh[$parser]['valuestack']); + if (is_array($cur_val)) { + if ($cur_val['members']==0) { + $cur_val['value'][] = $temp; + } else { + $XML_RPC_xh[$parser]['value'] = $temp; + } + array_unshift($XML_RPC_xh[$parser]['valuestack'], $cur_val); + } else { + $XML_RPC_xh[$parser]['value'] = $temp; + } + break; + + case 'MEMBER': + $XML_RPC_xh[$parser]['ac'] = ''; + $XML_RPC_xh[$parser]['qt'] = 0; + + $cur_val = array_shift($XML_RPC_xh[$parser]['valuestack']); + if (is_array($cur_val)) { + if ($cur_val['members']==1) { + $cur_val['value'][$cur_val['name']] = $XML_RPC_xh[$parser]['value']; + } + array_unshift($XML_RPC_xh[$parser]['valuestack'], $cur_val); + } + break; + + case 'DATA': + $XML_RPC_xh[$parser]['ac'] = ''; + $XML_RPC_xh[$parser]['qt'] = 0; + break; + + case 'PARAM': + $XML_RPC_xh[$parser]['params'][] = $XML_RPC_xh[$parser]['value']; + break; + + case 'METHODNAME': + case 'RPCMETHODNAME': + $XML_RPC_xh[$parser]['method'] = $GLOBALS['XML_RPC_func_ereg_replace']("^[\n\r\t ]+", '', + $XML_RPC_xh[$parser]['ac']); + break; + } + + // if it's a valid type name, set the type + if (isset($GLOBALS['XML_RPC_Types'][strtolower($name)])) { + $XML_RPC_xh[$parser]['vt'] = strtolower($name); + } +} + +/** + * Character data handler for the XML parser + * + * @return void + */ +function XML_RPC_cd($parser_resource, $data) +{ + global $XML_RPC_xh, $XML_RPC_backslash; + + $parser = (int) $parser_resource; + + if ($XML_RPC_xh[$parser]['lv'] != 3) { + // "lookforvalue==3" means that we've found an entire value + // and should discard any further character data + + if ($XML_RPC_xh[$parser]['lv'] == 1) { + // if we've found text and we're just in a then + // turn quoting on, as this will be a string + $XML_RPC_xh[$parser]['qt'] = 1; + // and say we've found a value + $XML_RPC_xh[$parser]['lv'] = 2; + } + + // replace characters that eval would + // do special things with + if (!isset($XML_RPC_xh[$parser]['ac'])) { + $XML_RPC_xh[$parser]['ac'] = ''; + } + $XML_RPC_xh[$parser]['ac'] .= $data; + } +} + +/** + * The common methods and properties for all of the XML_RPC classes + * + * @category Web Services + * @package XML_RPC + * @author Edd Dumbill + * @author Stig Bakken + * @author Martin Jansen + * @author Daniel Convissor + * @copyright 1999-2001 Edd Dumbill, 2001-2006 The PHP Group + * @version Release: 1.5.1 + * @link http://pear.php.net/package/XML_RPC + */ +class XML_RPC_Base { + + /** + * PEAR Error handling + * + * @return object PEAR_Error object + */ + function raiseError($msg, $code) + { + include_once 'PEAR.php'; + if (is_object(@$this)) { + return PEAR::raiseError(get_class($this) . ': ' . $msg, $code); + } else { + return PEAR::raiseError('XML_RPC: ' . $msg, $code); + } + } + + /** + * Tell whether something is a PEAR_Error object + * + * @param mixed $value the item to check + * + * @return bool whether $value is a PEAR_Error object or not + * + * @access public + */ + function isError($value) + { + return is_a($value, 'PEAR_Error'); + } +} + +/** + * The methods and properties for submitting XML RPC requests + * + * @category Web Services + * @package XML_RPC + * @author Edd Dumbill + * @author Stig Bakken + * @author Martin Jansen + * @author Daniel Convissor + * @copyright 1999-2001 Edd Dumbill, 2001-2006 The PHP Group + * @version Release: 1.5.1 + * @link http://pear.php.net/package/XML_RPC + */ +class XML_RPC_Client extends XML_RPC_Base { + + /** + * The path and name of the RPC server script you want the request to go to + * @var string + */ + var $path = ''; + + /** + * The name of the remote server to connect to + * @var string + */ + var $server = ''; + + /** + * The protocol to use in contacting the remote server + * @var string + */ + var $protocol = 'http://'; + + /** + * The port for connecting to the remote server + * + * The default is 80 for http:// connections + * and 443 for https:// and ssl:// connections. + * + * @var integer + */ + var $port = 80; + + /** + * A user name for accessing the RPC server + * @var string + * @see XML_RPC_Client::setCredentials() + */ + var $username = ''; + + /** + * A password for accessing the RPC server + * @var string + * @see XML_RPC_Client::setCredentials() + */ + var $password = ''; + + /** + * The name of the proxy server to use, if any + * @var string + */ + var $proxy = ''; + + /** + * The protocol to use in contacting the proxy server, if any + * @var string + */ + var $proxy_protocol = 'http://'; + + /** + * The port for connecting to the proxy server + * + * The default is 8080 for http:// connections + * and 443 for https:// and ssl:// connections. + * + * @var integer + */ + var $proxy_port = 8080; + + /** + * A user name for accessing the proxy server + * @var string + */ + var $proxy_user = ''; + + /** + * A password for accessing the proxy server + * @var string + */ + var $proxy_pass = ''; + + /** + * The error number, if any + * @var integer + */ + var $errno = 0; + + /** + * The error message, if any + * @var string + */ + var $errstr = ''; + + /** + * The current debug mode (1 = on, 0 = off) + * @var integer + */ + var $debug = 0; + + /** + * The HTTP headers for the current request. + * @var string + */ + var $headers = ''; + + + /** + * Sets the object's properties + * + * @param string $path the path and name of the RPC server script + * you want the request to go to + * @param string $server the URL of the remote server to connect to. + * If this parameter doesn't specify a + * protocol and $port is 443, ssl:// is + * assumed. + * @param integer $port a port for connecting to the remote server. + * Defaults to 80 for http:// connections and + * 443 for https:// and ssl:// connections. + * @param string $proxy the URL of the proxy server to use, if any. + * If this parameter doesn't specify a + * protocol and $port is 443, ssl:// is + * assumed. + * @param integer $proxy_port a port for connecting to the remote server. + * Defaults to 8080 for http:// connections and + * 443 for https:// and ssl:// connections. + * @param string $proxy_user a user name for accessing the proxy server + * @param string $proxy_pass a password for accessing the proxy server + * + * @return void + */ + function XML_RPC_Client($path, $server, $port = 0, + $proxy = '', $proxy_port = 0, + $proxy_user = '', $proxy_pass = '') + { + $this->path = $path; + $this->proxy_user = $proxy_user; + $this->proxy_pass = $proxy_pass; + + $GLOBALS['XML_RPC_func_ereg']('^(http://|https://|ssl://)?(.*)$', $server, $match); + if ($match[1] == '') { + if ($port == 443) { + $this->server = $match[2]; + $this->protocol = 'ssl://'; + $this->port = 443; + } else { + $this->server = $match[2]; + if ($port) { + $this->port = $port; + } + } + } elseif ($match[1] == 'http://') { + $this->server = $match[2]; + if ($port) { + $this->port = $port; + } + } else { + $this->server = $match[2]; + $this->protocol = 'ssl://'; + if ($port) { + $this->port = $port; + } else { + $this->port = 443; + } + } + + if ($proxy) { + $GLOBALS['XML_RPC_func_ereg']('^(http://|https://|ssl://)?(.*)$', $proxy, $match); + if ($match[1] == '') { + if ($proxy_port == 443) { + $this->proxy = $match[2]; + $this->proxy_protocol = 'ssl://'; + $this->proxy_port = 443; + } else { + $this->proxy = $match[2]; + if ($proxy_port) { + $this->proxy_port = $proxy_port; + } + } + } elseif ($match[1] == 'http://') { + $this->proxy = $match[2]; + if ($proxy_port) { + $this->proxy_port = $proxy_port; + } + } else { + $this->proxy = $match[2]; + $this->proxy_protocol = 'ssl://'; + if ($proxy_port) { + $this->proxy_port = $proxy_port; + } else { + $this->proxy_port = 443; + } + } + } + } + + /** + * Change the current debug mode + * + * @param int $in where 1 = on, 0 = off + * + * @return void + */ + function setDebug($in) + { + if ($in) { + $this->debug = 1; + } else { + $this->debug = 0; + } + } + + /** + * Sets whether strings that contain characters which may cause PHP's + * SAX-based XML parser to break should be automatically base64 encoded + * + * This is is a workaround for systems that don't have PHP's mbstring + * extension available. + * + * @param int $in where 1 = on, 0 = off + * + * @return void + */ + function setAutoBase64($in) + { + if ($in) { + $GLOBALS['XML_RPC_auto_base64'] = true; + } else { + $GLOBALS['XML_RPC_auto_base64'] = false; + } + } + + /** + * Set username and password properties for connecting to the RPC server + * + * @param string $u the user name + * @param string $p the password + * + * @return void + * + * @see XML_RPC_Client::$username, XML_RPC_Client::$password + */ + function setCredentials($u, $p) + { + $this->username = $u; + $this->password = $p; + } + + /** + * Transmit the RPC request via HTTP 1.0 protocol + * + * @param object $msg the XML_RPC_Message object + * @param int $timeout how many seconds to wait for the request + * + * @return object an XML_RPC_Response object. 0 is returned if any + * problems happen. + * + * @see XML_RPC_Message, XML_RPC_Client::XML_RPC_Client(), + * XML_RPC_Client::setCredentials() + */ + function send($msg, $timeout = 0) + { + if (!is_a($msg, 'XML_RPC_Message')) { + $this->errstr = 'send()\'s $msg parameter must be an' + . ' XML_RPC_Message object.'; + $this->raiseError($this->errstr, XML_RPC_ERROR_PROGRAMMING); + return 0; + } + $msg->debug = $this->debug; + return $this->sendPayloadHTTP10($msg, $this->server, $this->port, + $timeout, $this->username, + $this->password); + } + + /** + * Transmit the RPC request via HTTP 1.0 protocol + * + * Requests should be sent using XML_RPC_Client send() rather than + * calling this method directly. + * + * @param object $msg the XML_RPC_Message object + * @param string $server the server to send the request to + * @param int $port the server port send the request to + * @param int $timeout how many seconds to wait for the request + * before giving up + * @param string $username a user name for accessing the RPC server + * @param string $password a password for accessing the RPC server + * + * @return object an XML_RPC_Response object. 0 is returned if any + * problems happen. + * + * @access protected + * @see XML_RPC_Client::send() + */ + function sendPayloadHTTP10($msg, $server, $port, $timeout = 0, + $username = '', $password = '') + { + /* + * If we're using a proxy open a socket to the proxy server + * instead to the xml-rpc server + */ + if ($this->proxy) { + if ($this->proxy_protocol == 'http://') { + $protocol = ''; + } else { + $protocol = $this->proxy_protocol; + } + if ($timeout > 0) { + $fp = @fsockopen($protocol . $this->proxy, $this->proxy_port, + $this->errno, $this->errstr, $timeout); + } else { + $fp = @fsockopen($protocol . $this->proxy, $this->proxy_port, + $this->errno, $this->errstr); + } + } else { + if ($this->protocol == 'http://') { + $protocol = ''; + } else { + $protocol = $this->protocol; + } + if ($timeout > 0) { + $fp = @fsockopen($protocol . $server, $port, + $this->errno, $this->errstr, $timeout); + } else { + $fp = @fsockopen($protocol . $server, $port, + $this->errno, $this->errstr); + } + } + + /* + * Just raising the error without returning it is strange, + * but keep it here for backwards compatibility. + */ + if (!$fp && $this->proxy) { + $this->raiseError('Connection to proxy server ' + . $this->proxy . ':' . $this->proxy_port + . ' failed. ' . $this->errstr, + XML_RPC_ERROR_CONNECTION_FAILED); + return 0; + } elseif (!$fp) { + $this->raiseError('Connection to RPC server ' + . $server . ':' . $port + . ' failed. ' . $this->errstr, + XML_RPC_ERROR_CONNECTION_FAILED); + return 0; + } + + if ($timeout) { + /* + * Using socket_set_timeout() because stream_set_timeout() + * was introduced in 4.3.0, but we need to support 4.2.0. + */ + socket_set_timeout($fp, $timeout); + } + + // Pre-emptive BC hacks for fools calling sendPayloadHTTP10() directly + if ($username != $this->username) { + $this->setCredentials($username, $password); + } + + // Only create the payload if it was not created previously + if (empty($msg->payload)) { + $msg->createPayload(); + } + $this->createHeaders($msg); + + $op = $this->headers . "\r\n\r\n"; + $op .= $msg->payload; + + if (!fputs($fp, $op, strlen($op))) { + $this->errstr = 'Write error'; + return 0; + } + $resp = $msg->parseResponseFile($fp); + + $meta = socket_get_status($fp); + if ($meta['timed_out']) { + fclose($fp); + $this->errstr = 'RPC server did not send response before timeout.'; + $this->raiseError($this->errstr, XML_RPC_ERROR_CONNECTION_FAILED); + return 0; + } + + fclose($fp); + return $resp; + } + + /** + * Determines the HTTP headers and puts it in the $headers property + * + * @param object $msg the XML_RPC_Message object + * + * @return boolean TRUE if okay, FALSE if the message payload isn't set. + * + * @access protected + */ + function createHeaders($msg) + { + if (empty($msg->payload)) { + return false; + } + if ($this->proxy) { + $this->headers = 'POST ' . $this->protocol . $this->server; + if ($this->proxy_port) { + $this->headers .= ':' . $this->port; + } + } else { + $this->headers = 'POST '; + } + $this->headers .= $this->path. " HTTP/1.0\r\n"; + + $this->headers .= "User-Agent: PEAR XML_RPC\r\n"; + $this->headers .= 'Host: ' . $this->server . "\r\n"; + + if ($this->proxy && $this->proxy_user) { + $this->headers .= 'Proxy-Authorization: Basic ' + . base64_encode("$this->proxy_user:$this->proxy_pass") + . "\r\n"; + } + + // thanks to Grant Rauscher for this + if ($this->username) { + $this->headers .= 'Authorization: Basic ' + . base64_encode("$this->username:$this->password") + . "\r\n"; + } + + $this->headers .= "Content-Type: text/xml\r\n"; + $this->headers .= 'Content-Length: ' . strlen($msg->payload); + return true; + } +} + +/** + * The methods and properties for interpreting responses to XML RPC requests + * + * @category Web Services + * @package XML_RPC + * @author Edd Dumbill + * @author Stig Bakken + * @author Martin Jansen + * @author Daniel Convissor + * @copyright 1999-2001 Edd Dumbill, 2001-2006 The PHP Group + * @version Release: 1.5.1 + * @link http://pear.php.net/package/XML_RPC + */ +class XML_RPC_Response extends XML_RPC_Base +{ + var $xv; + var $fn; + var $fs; + var $hdrs; + + /** + * @return void + */ + function XML_RPC_Response($val, $fcode = 0, $fstr = '') + { + if ($fcode != 0) { + $this->fn = $fcode; + $this->fs = htmlspecialchars($fstr); + } else { + $this->xv = $val; + } + } + + /** + * @return int the error code + */ + function faultCode() + { + if (isset($this->fn)) { + return $this->fn; + } else { + return 0; + } + } + + /** + * @return string the error string + */ + function faultString() + { + return $this->fs; + } + + /** + * @return mixed the value + */ + function value() + { + return $this->xv; + } + + /** + * @return string the error message in XML format + */ + function serialize() + { + $rs = "\n"; + if ($this->fn) { + $rs .= " + + + + faultCode + " . $this->fn . " + + + faultString + " . $this->fs . " + + + +"; + } else { + $rs .= "\n\n" . $this->xv->serialize() . + "\n"; + } + $rs .= "\n"; + return $rs; + } +} + +/** + * The methods and properties for composing XML RPC messages + * + * @category Web Services + * @package XML_RPC + * @author Edd Dumbill + * @author Stig Bakken + * @author Martin Jansen + * @author Daniel Convissor + * @copyright 1999-2001 Edd Dumbill, 2001-2006 The PHP Group + * @version Release: 1.5.1 + * @link http://pear.php.net/package/XML_RPC + */ +class XML_RPC_Message extends XML_RPC_Base +{ + /** + * Should the payload's content be passed through mb_convert_encoding()? + * + * @see XML_RPC_Message::setConvertPayloadEncoding() + * @since Property available since Release 1.5.1 + * @var boolean + */ + var $convert_payload_encoding = false; + + /** + * The current debug mode (1 = on, 0 = off) + * @var integer + */ + var $debug = 0; + + /** + * The encoding to be used for outgoing messages + * + * Defaults to the value of $GLOBALS['XML_RPC_defencoding'] + * + * @var string + * @see XML_RPC_Message::setSendEncoding(), + * $GLOBALS['XML_RPC_defencoding'], XML_RPC_Message::xml_header() + */ + var $send_encoding = ''; + + /** + * The method presently being evaluated + * @var string + */ + var $methodname = ''; + + /** + * @var array + */ + var $params = array(); + + /** + * The XML message being generated + * @var string + */ + var $payload = ''; + + /** + * Should extra line breaks be removed from the payload? + * @since Property available since Release 1.4.6 + * @var boolean + */ + var $remove_extra_lines = true; + + /** + * The XML response from the remote server + * @since Property available since Release 1.4.6 + * @var string + */ + var $response_payload = ''; + + + /** + * @return void + */ + function XML_RPC_Message($meth, $pars = 0) + { + $this->methodname = $meth; + if (is_array($pars) && sizeof($pars) > 0) { + for ($i = 0; $i < sizeof($pars); $i++) { + $this->addParam($pars[$i]); + } + } + } + + /** + * Produces the XML declaration including the encoding attribute + * + * The encoding is determined by this class' $send_encoding + * property. If the $send_encoding property is not set, use + * $GLOBALS['XML_RPC_defencoding']. + * + * @return string the XML declaration and element + * + * @see XML_RPC_Message::setSendEncoding(), + * XML_RPC_Message::$send_encoding, $GLOBALS['XML_RPC_defencoding'] + */ + function xml_header() + { + global $XML_RPC_defencoding; + + if (!$this->send_encoding) { + $this->send_encoding = $XML_RPC_defencoding; + } + return 'send_encoding . '"?>' + . "\n\n"; + } + + /** + * @return string the closing tag + */ + function xml_footer() + { + return "\n"; + } + + /** + * Fills the XML_RPC_Message::$payload property + * + * Part of the process makes sure all line endings are in DOS format + * (CRLF), which is probably required by specifications. + * + * If XML_RPC_Message::setConvertPayloadEncoding() was set to true, + * the payload gets passed through mb_convert_encoding() + * to ensure the payload matches the encoding set in the + * XML declaration. The encoding type can be manually set via + * XML_RPC_Message::setSendEncoding(). + * + * @return void + * + * @uses XML_RPC_Message::xml_header(), XML_RPC_Message::xml_footer() + * @see XML_RPC_Message::setSendEncoding(), $GLOBALS['XML_RPC_defencoding'], + * XML_RPC_Message::setConvertPayloadEncoding() + */ + function createPayload() + { + $this->payload = $this->xml_header(); + $this->payload .= '' . $this->methodname . "\n"; + $this->payload .= "\n"; + for ($i = 0; $i < sizeof($this->params); $i++) { + $p = $this->params[$i]; + $this->payload .= "\n" . $p->serialize() . "\n"; + } + $this->payload .= "\n"; + $this->payload .= $this->xml_footer(); + if ($this->remove_extra_lines) { + $this->payload = $GLOBALS['XML_RPC_func_ereg_replace']("[\r\n]+", "\r\n", $this->payload); + } else { + $this->payload = $GLOBALS['XML_RPC_func_ereg_replace']("\r\n|\n|\r|\n\r", "\r\n", $this->payload); + } + if ($this->convert_payload_encoding) { + $this->payload = mb_convert_encoding($this->payload, $this->send_encoding); + } + } + + /** + * @return string the name of the method + */ + function method($meth = '') + { + if ($meth != '') { + $this->methodname = $meth; + } + return $this->methodname; + } + + /** + * @return string the payload + */ + function serialize() + { + $this->createPayload(); + return $this->payload; + } + + /** + * @return void + */ + function addParam($par) + { + $this->params[] = $par; + } + + /** + * Obtains an XML_RPC_Value object for the given parameter + * + * @param int $i the index number of the parameter to obtain + * + * @return object the XML_RPC_Value object. + * If the parameter doesn't exist, an XML_RPC_Response object. + * + * @since Returns XML_RPC_Response object on error since Release 1.3.0 + */ + function getParam($i) + { + global $XML_RPC_err, $XML_RPC_str; + + if (isset($this->params[$i])) { + return $this->params[$i]; + } else { + $this->raiseError('The submitted request did not contain this parameter', + XML_RPC_ERROR_INCORRECT_PARAMS); + return new XML_RPC_Response(0, $XML_RPC_err['incorrect_params'], + $XML_RPC_str['incorrect_params']); + } + } + + /** + * @return int the number of parameters + */ + function getNumParams() + { + return sizeof($this->params); + } + + /** + * Sets whether the payload's content gets passed through + * mb_convert_encoding() + * + * Returns PEAR_ERROR object if mb_convert_encoding() isn't available. + * + * @param int $in where 1 = on, 0 = off + * + * @return void + * + * @see XML_RPC_Message::setSendEncoding() + * @since Method available since Release 1.5.1 + */ + function setConvertPayloadEncoding($in) + { + if ($in && !function_exists('mb_convert_encoding')) { + return $this->raiseError('mb_convert_encoding() is not available', + XML_RPC_ERROR_PROGRAMMING); + } + $this->convert_payload_encoding = $in; + } + + /** + * Sets the XML declaration's encoding attribute + * + * @param string $type the encoding type (ISO-8859-1, UTF-8 or US-ASCII) + * + * @return void + * + * @see XML_RPC_Message::setConvertPayloadEncoding(), XML_RPC_Message::xml_header() + * @since Method available since Release 1.2.0 + */ + function setSendEncoding($type) + { + $this->send_encoding = $type; + } + + /** + * Determine the XML's encoding via the encoding attribute + * in the XML declaration + * + * If the encoding parameter is not set or is not ISO-8859-1, UTF-8 + * or US-ASCII, $XML_RPC_defencoding will be returned. + * + * @param string $data the XML that will be parsed + * + * @return string the encoding to be used + * + * @link http://php.net/xml_parser_create + * @since Method available since Release 1.2.0 + */ + function getEncoding($data) + { + global $XML_RPC_defencoding; + + if ($GLOBALS['XML_RPC_func_ereg']('<\?xml[^>]*[:space:]*encoding[:space:]*=[:space:]*[\'"]([^"\']*)[\'"]', + $data, $match)) + { + $match[1] = trim(strtoupper($match[1])); + switch ($match[1]) { + case 'ISO-8859-1': + case 'UTF-8': + case 'US-ASCII': + return $match[1]; + break; + + default: + return $XML_RPC_defencoding; + } + } else { + return $XML_RPC_defencoding; + } + } + + /** + * @return object a new XML_RPC_Response object + */ + function parseResponseFile($fp) + { + $ipd = ''; + while ($data = @fread($fp, 8192)) { + $ipd .= $data; + } + return $this->parseResponse($ipd); + } + + /** + * @return object a new XML_RPC_Response object + */ + function parseResponse($data = '') + { + global $XML_RPC_xh, $XML_RPC_err, $XML_RPC_str, $XML_RPC_defencoding; + + $encoding = $this->getEncoding($data); + $parser_resource = xml_parser_create($encoding); + $parser = (int) $parser_resource; + + $XML_RPC_xh = array(); + $XML_RPC_xh[$parser] = array(); + + $XML_RPC_xh[$parser]['cm'] = 0; + $XML_RPC_xh[$parser]['isf'] = 0; + $XML_RPC_xh[$parser]['ac'] = ''; + $XML_RPC_xh[$parser]['qt'] = ''; + $XML_RPC_xh[$parser]['stack'] = array(); + $XML_RPC_xh[$parser]['valuestack'] = array(); + + xml_parser_set_option($parser_resource, XML_OPTION_CASE_FOLDING, true); + xml_set_element_handler($parser_resource, 'XML_RPC_se', 'XML_RPC_ee'); + xml_set_character_data_handler($parser_resource, 'XML_RPC_cd'); + + $hdrfnd = 0; + if ($this->debug) { + print "\n
    ---GOT---\n";
    +            print isset($_SERVER['SERVER_PROTOCOL']) ? htmlspecialchars($data) : $data;
    +            print "\n---END---
    \n"; + } + + // See if response is a 200 or a 100 then a 200, else raise error. + // But only do this if we're using the HTTP protocol. + if ($GLOBALS['XML_RPC_func_ereg']('^HTTP', $data) && + !$GLOBALS['XML_RPC_func_ereg']('^HTTP/[0-9\.]+ 200 ', $data) && + !$GLOBALS['XML_RPC_func_ereg']('^HTTP/[0-9\.]+ 10[0-9]([A-Z ]+)?[\r\n]+HTTP/[0-9\.]+ 200', $data)) + { + $errstr = substr($data, 0, strpos($data, "\n") - 1); + error_log('HTTP error, got response: ' . $errstr); + $r = new XML_RPC_Response(0, $XML_RPC_err['http_error'], + $XML_RPC_str['http_error'] . ' (' . + $errstr . ')'); + xml_parser_free($parser_resource); + return $r; + } + + // gotta get rid of headers here + if (!$hdrfnd && ($brpos = strpos($data,"\r\n\r\n"))) { + $XML_RPC_xh[$parser]['ha'] = substr($data, 0, $brpos); + $data = substr($data, $brpos + 4); + $hdrfnd = 1; + } + + /* + * be tolerant of junk after methodResponse + * (e.g. javascript automatically inserted by free hosts) + * thanks to Luca Mariano + */ + $data = substr($data, 0, strpos($data, "") + 17); + $this->response_payload = $data; + + if (!xml_parse($parser_resource, $data, sizeof($data))) { + // thanks to Peter Kocks + if (xml_get_current_line_number($parser_resource) == 1) { + $errstr = 'XML error at line 1, check URL'; + } else { + $errstr = sprintf('XML error: %s at line %d', + xml_error_string(xml_get_error_code($parser_resource)), + xml_get_current_line_number($parser_resource)); + } + error_log($errstr); + $r = new XML_RPC_Response(0, $XML_RPC_err['invalid_return'], + $XML_RPC_str['invalid_return']); + xml_parser_free($parser_resource); + return $r; + } + + xml_parser_free($parser_resource); + + if ($this->debug) { + print "\n
    ---PARSED---\n";
    +            var_dump($XML_RPC_xh[$parser]['value']);
    +            print "---END---
    \n"; + } + + if ($XML_RPC_xh[$parser]['isf'] > 1) { + $r = new XML_RPC_Response(0, $XML_RPC_err['invalid_return'], + $XML_RPC_str['invalid_return'].' '.$XML_RPC_xh[$parser]['isf_reason']); + } elseif (!is_object($XML_RPC_xh[$parser]['value'])) { + // then something odd has happened + // and it's time to generate a client side error + // indicating something odd went on + $r = new XML_RPC_Response(0, $XML_RPC_err['invalid_return'], + $XML_RPC_str['invalid_return']); + } else { + $v = $XML_RPC_xh[$parser]['value']; + if ($XML_RPC_xh[$parser]['isf']) { + $f = $v->structmem('faultCode'); + $fs = $v->structmem('faultString'); + $r = new XML_RPC_Response($v, $f->scalarval(), + $fs->scalarval()); + } else { + $r = new XML_RPC_Response($v); + } + } + $r->hdrs = split("\r?\n", $XML_RPC_xh[$parser]['ha'][1]); + return $r; + } +} + +/** + * The methods and properties that represent data in XML RPC format + * + * @category Web Services + * @package XML_RPC + * @author Edd Dumbill + * @author Stig Bakken + * @author Martin Jansen + * @author Daniel Convissor + * @copyright 1999-2001 Edd Dumbill, 2001-2006 The PHP Group + * @version Release: 1.5.1 + * @link http://pear.php.net/package/XML_RPC + */ +class XML_RPC_Value extends XML_RPC_Base +{ + var $me = array(); + var $mytype = 0; + + /** + * @return void + */ + function XML_RPC_Value($val = -1, $type = '') + { + $this->me = array(); + $this->mytype = 0; + if ($val != -1 || $type != '') { + if ($type == '') { + $type = 'string'; + } + if (!array_key_exists($type, $GLOBALS['XML_RPC_Types'])) { + // XXX + // need some way to report this error + } elseif ($GLOBALS['XML_RPC_Types'][$type] == 1) { + $this->addScalar($val, $type); + } elseif ($GLOBALS['XML_RPC_Types'][$type] == 2) { + $this->addArray($val); + } elseif ($GLOBALS['XML_RPC_Types'][$type] == 3) { + $this->addStruct($val); + } + } + } + + /** + * @return int returns 1 if successful or 0 if there are problems + */ + function addScalar($val, $type = 'string') + { + if ($this->mytype == 1) { + $this->raiseError('Scalar can have only one value', + XML_RPC_ERROR_INVALID_TYPE); + return 0; + } + $typeof = $GLOBALS['XML_RPC_Types'][$type]; + if ($typeof != 1) { + $this->raiseError("Not a scalar type (${typeof})", + XML_RPC_ERROR_INVALID_TYPE); + return 0; + } + + if ($type == $GLOBALS['XML_RPC_Boolean']) { + if (strcasecmp($val, 'true') == 0 + || $val == 1 + || ($val == true && strcasecmp($val, 'false'))) + { + $val = 1; + } else { + $val = 0; + } + } + + if ($this->mytype == 2) { + // we're adding to an array here + $ar = $this->me['array']; + $ar[] = new XML_RPC_Value($val, $type); + $this->me['array'] = $ar; + } else { + // a scalar, so set the value and remember we're scalar + $this->me[$type] = $val; + $this->mytype = $typeof; + } + return 1; + } + + /** + * @return int returns 1 if successful or 0 if there are problems + */ + function addArray($vals) + { + if ($this->mytype != 0) { + $this->raiseError( + 'Already initialized as a [' . $this->kindOf() . ']', + XML_RPC_ERROR_ALREADY_INITIALIZED); + return 0; + } + $this->mytype = $GLOBALS['XML_RPC_Types']['array']; + $this->me['array'] = $vals; + return 1; + } + + /** + * @return int returns 1 if successful or 0 if there are problems + */ + function addStruct($vals) + { + if ($this->mytype != 0) { + $this->raiseError( + 'Already initialized as a [' . $this->kindOf() . ']', + XML_RPC_ERROR_ALREADY_INITIALIZED); + return 0; + } + $this->mytype = $GLOBALS['XML_RPC_Types']['struct']; + $this->me['struct'] = $vals; + return 1; + } + + /** + * @return void + */ + function dump($ar) + { + reset($ar); + foreach ($ar as $key => $val) { + echo "$key => $val
    "; + if ($key == 'array') { + foreach ($val as $key2 => $val2) { + echo "-- $key2 => $val2
    "; + } + } + } + } + + /** + * @return string the data type of the current value + */ + function kindOf() + { + switch ($this->mytype) { + case 3: + return 'struct'; + + case 2: + return 'array'; + + case 1: + return 'scalar'; + + default: + return 'undef'; + } + } + + /** + * @return string the data in XML format + */ + function serializedata($typ, $val) + { + $rs = ''; + if (!array_key_exists($typ, $GLOBALS['XML_RPC_Types'])) { + // XXX + // need some way to report this error + return; + } + switch ($GLOBALS['XML_RPC_Types'][$typ]) { + case 3: + // struct + $rs .= "\n"; + reset($val); + foreach ($val as $key2 => $val2) { + $rs .= "${key2}\n"; + $rs .= $this->serializeval($val2); + $rs .= "\n"; + } + $rs .= ''; + break; + + case 2: + // array + $rs .= "\n\n"; + for ($i = 0; $i < sizeof($val); $i++) { + $rs .= $this->serializeval($val[$i]); + } + $rs .= "\n"; + break; + + case 1: + switch ($typ) { + case $GLOBALS['XML_RPC_Base64']: + $rs .= "<${typ}>" . base64_encode($val) . ""; + break; + case $GLOBALS['XML_RPC_Boolean']: + $rs .= "<${typ}>" . ($val ? '1' : '0') . ""; + break; + case $GLOBALS['XML_RPC_String']: + $rs .= "<${typ}>" . htmlspecialchars($val). ""; + break; + default: + $rs .= "<${typ}>${val}"; + } + } + return $rs; + } + + /** + * @return string the data in XML format + */ + function serialize() + { + return $this->serializeval($this); + } + + /** + * @return string the data in XML format + */ + function serializeval($o) + { + if (!is_object($o) || empty($o->me) || !is_array($o->me)) { + return ''; + } + $ar = $o->me; + reset($ar); + list($typ, $val) = each($ar); + return '' . $this->serializedata($typ, $val) . "\n"; + } + + /** + * @return mixed the contents of the element requested + */ + function structmem($m) + { + return $this->me['struct'][$m]; + } + + /** + * @return void + */ + function structreset() + { + reset($this->me['struct']); + } + + /** + * @return the key/value pair of the struct's current element + */ + function structeach() + { + return each($this->me['struct']); + } + + /** + * @return mixed the current value + */ + function getval() + { + // UNSTABLE + + reset($this->me); + $b = current($this->me); + + // contributed by I Sofer, 2001-03-24 + // add support for nested arrays to scalarval + // i've created a new method here, so as to + // preserve back compatibility + + if (is_array($b)) { + foreach ($b as $id => $cont) { + $b[$id] = $cont->scalarval(); + } + } + + // add support for structures directly encoding php objects + if (is_object($b)) { + $t = get_object_vars($b); + foreach ($t as $id => $cont) { + $t[$id] = $cont->scalarval(); + } + foreach ($t as $id => $cont) { + $b->$id = $cont; + } + } + + // end contrib + return $b; + } + + /** + * @return mixed the current element's scalar value. If the value is + * not scalar, FALSE is returned. + */ + function scalarval() + { + reset($this->me); + $v = current($this->me); + if (!is_scalar($v)) { + $v = false; + } + return $v; + } + + /** + * @return string + */ + function scalartyp() + { + reset($this->me); + $a = key($this->me); + if ($a == $GLOBALS['XML_RPC_I4']) { + $a = $GLOBALS['XML_RPC_Int']; + } + return $a; + } + + /** + * @return mixed the struct's current element + */ + function arraymem($m) + { + return $this->me['array'][$m]; + } + + /** + * @return int the number of elements in the array + */ + function arraysize() + { + reset($this->me); + list($a, $b) = each($this->me); + return sizeof($b); + } + + /** + * Determines if the item submitted is an XML_RPC_Value object + * + * @param mixed $val the variable to be evaluated + * + * @return bool TRUE if the item is an XML_RPC_Value object + * + * @static + * @since Method available since Release 1.3.0 + */ + function isValue($val) + { + return (strtolower(get_class($val)) == 'xml_rpc_value'); + } +} + +/** + * Return an ISO8601 encoded string + * + * While timezones ought to be supported, the XML-RPC spec says: + * + * "Don't assume a timezone. It should be specified by the server in its + * documentation what assumptions it makes about timezones." + * + * This routine always assumes localtime unless $utc is set to 1, in which + * case UTC is assumed and an adjustment for locale is made when encoding. + * + * @return string the formatted date + */ +function XML_RPC_iso8601_encode($timet, $utc = 0) +{ + if (!$utc) { + $t = strftime('%Y%m%dT%H:%M:%S', $timet); + } else { + if (function_exists('gmstrftime')) { + // gmstrftime doesn't exist in some versions + // of PHP + $t = gmstrftime('%Y%m%dT%H:%M:%S', $timet); + } else { + $t = strftime('%Y%m%dT%H:%M:%S', $timet - date('Z')); + } + } + return $t; +} + +/** + * Convert a datetime string into a Unix timestamp + * + * While timezones ought to be supported, the XML-RPC spec says: + * + * "Don't assume a timezone. It should be specified by the server in its + * documentation what assumptions it makes about timezones." + * + * This routine always assumes localtime unless $utc is set to 1, in which + * case UTC is assumed and an adjustment for locale is made when encoding. + * + * @return int the unix timestamp of the date submitted + */ +function XML_RPC_iso8601_decode($idate, $utc = 0) +{ + $t = 0; + if ($GLOBALS['XML_RPC_func_ereg']('([0-9]{4})([0-9]{2})([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})', $idate, $regs)) { + if ($utc) { + $t = gmmktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]); + } else { + $t = mktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]); + } + } + return $t; +} + +/** + * Converts an XML_RPC_Value object into native PHP types + * + * @param object $XML_RPC_val the XML_RPC_Value object to decode + * + * @return mixed the PHP values + */ +function XML_RPC_decode($XML_RPC_val) +{ + $kind = $XML_RPC_val->kindOf(); + + if ($kind == 'scalar') { + return $XML_RPC_val->scalarval(); + + } elseif ($kind == 'array') { + $size = $XML_RPC_val->arraysize(); + $arr = array(); + for ($i = 0; $i < $size; $i++) { + $arr[] = XML_RPC_decode($XML_RPC_val->arraymem($i)); + } + return $arr; + + } elseif ($kind == 'struct') { + $XML_RPC_val->structreset(); + $arr = array(); + while (list($key, $value) = $XML_RPC_val->structeach()) { + $arr[$key] = XML_RPC_decode($value); + } + return $arr; + } +} + +/** + * Converts native PHP types into an XML_RPC_Value object + * + * @param mixed $php_val the PHP value or variable you want encoded + * + * @return object the XML_RPC_Value object + */ +function XML_RPC_encode($php_val) +{ + $type = gettype($php_val); + $XML_RPC_val = new XML_RPC_Value; + + switch ($type) { + case 'array': + if (empty($php_val)) { + $XML_RPC_val->addArray($php_val); + break; + } + $tmp = array_diff(array_keys($php_val), range(0, count($php_val)-1)); + if (empty($tmp)) { + $arr = array(); + foreach ($php_val as $k => $v) { + $arr[$k] = XML_RPC_encode($v); + } + $XML_RPC_val->addArray($arr); + break; + } + // fall though if it's not an enumerated array + + case 'object': + $arr = array(); + foreach ($php_val as $k => $v) { + $arr[$k] = XML_RPC_encode($v); + } + $XML_RPC_val->addStruct($arr); + break; + + case 'integer': + $XML_RPC_val->addScalar($php_val, $GLOBALS['XML_RPC_Int']); + break; + + case 'double': + $XML_RPC_val->addScalar($php_val, $GLOBALS['XML_RPC_Double']); + break; + + case 'string': + case 'NULL': + if ($GLOBALS['XML_RPC_func_ereg']('^[0-9]{8}\T{1}[0-9]{2}\:[0-9]{2}\:[0-9]{2}$', $php_val)) { + $XML_RPC_val->addScalar($php_val, $GLOBALS['XML_RPC_DateTime']); + } elseif ($GLOBALS['XML_RPC_auto_base64'] + && $GLOBALS['XML_RPC_func_ereg']("[^ -~\t\r\n]", $php_val)) + { + // Characters other than alpha-numeric, punctuation, SP, TAB, + // LF and CR break the XML parser, encode value via Base 64. + $XML_RPC_val->addScalar($php_val, $GLOBALS['XML_RPC_Base64']); + } else { + $XML_RPC_val->addScalar($php_val, $GLOBALS['XML_RPC_String']); + } + break; + + case 'boolean': + // Add support for encoding/decoding of booleans, since they + // are supported in PHP + // by + $XML_RPC_val->addScalar($php_val, $GLOBALS['XML_RPC_Boolean']); + break; + + case 'unknown type': + default: + $XML_RPC_val = false; + } + return $XML_RPC_val; +} + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * c-hanging-comment-ender-p: nil + * End: + */ + +?> diff --git a/src/lib/pear/PEAR/XML/RPC/Dump.php b/src/lib/pear/PEAR/XML/RPC/Dump.php new file mode 100644 index 0000000..97c30e2 --- /dev/null +++ b/src/lib/pear/PEAR/XML/RPC/Dump.php @@ -0,0 +1,187 @@ + + * @version CVS: $Id: Dump.php,v 1.7 2005/01/24 03:47:55 danielc Exp $ + * @link http://pear.php.net/package/XML_RPC + */ + + +/** + * Pull in the XML_RPC class + */ +require_once 'XML/RPC.php'; + + +/** + * Generates the dump of the XML_RPC_Value and echoes it + * + * @param object $value the XML_RPC_Value object to dump + * + * @return void + */ +function XML_RPC_Dump($value) +{ + $dumper = new XML_RPC_Dump(); + echo $dumper->generateDump($value); +} + + +/** + * Class which generates a dump of a XML_RPC_Value object + * + * @category Web Services + * @package XML_RPC + * @author Christian Weiske + * @version Release: 1.5.1 + * @link http://pear.php.net/package/XML_RPC + */ +class XML_RPC_Dump +{ + /** + * The indentation array cache + * @var array + */ + var $arIndent = array(); + + /** + * The spaces used for indenting the XML + * @var string + */ + var $strBaseIndent = ' '; + + /** + * Returns the dump in XML format without printing it out + * + * @param object $value the XML_RPC_Value object to dump + * @param int $nLevel the level of indentation + * + * @return string the dump + */ + function generateDump($value, $nLevel = 0) + { + if (!is_object($value) && get_class($value) != 'xml_rpc_value') { + require_once 'PEAR.php'; + PEAR::raiseError('Tried to dump non-XML_RPC_Value variable' . "\r\n", + 0, PEAR_ERROR_PRINT); + if (is_object($value)) { + $strType = get_class($value); + } else { + $strType = gettype($value); + } + return $this->getIndent($nLevel) . 'NOT A XML_RPC_Value: ' + . $strType . "\r\n"; + } + + switch ($value->kindOf()) { + case 'struct': + $ret = $this->genStruct($value, $nLevel); + break; + case 'array': + $ret = $this->genArray($value, $nLevel); + break; + case 'scalar': + $ret = $this->genScalar($value->scalarval(), $nLevel); + break; + default: + require_once 'PEAR.php'; + PEAR::raiseError('Illegal type "' . $value->kindOf() + . '" in XML_RPC_Value' . "\r\n", 0, + PEAR_ERROR_PRINT); + } + + return $ret; + } + + /** + * Returns the scalar value dump + * + * @param object $value the scalar XML_RPC_Value object to dump + * @param int $nLevel the level of indentation + * + * @return string Dumped version of the scalar value + */ + function genScalar($value, $nLevel) + { + if (gettype($value) == 'object') { + $strClass = ' ' . get_class($value); + } else { + $strClass = ''; + } + return $this->getIndent($nLevel) . gettype($value) . $strClass + . ' ' . $value . "\r\n"; + } + + /** + * Returns the dump of a struct + * + * @param object $value the struct XML_RPC_Value object to dump + * @param int $nLevel the level of indentation + * + * @return string Dumped version of the scalar value + */ + function genStruct($value, $nLevel) + { + $value->structreset(); + $strOutput = $this->getIndent($nLevel) . 'struct' . "\r\n"; + while (list($key, $keyval) = $value->structeach()) { + $strOutput .= $this->getIndent($nLevel + 1) . $key . "\r\n"; + $strOutput .= $this->generateDump($keyval, $nLevel + 2); + } + return $strOutput; + } + + /** + * Returns the dump of an array + * + * @param object $value the array XML_RPC_Value object to dump + * @param int $nLevel the level of indentation + * + * @return string Dumped version of the scalar value + */ + function genArray($value, $nLevel) + { + $nSize = $value->arraysize(); + $strOutput = $this->getIndent($nLevel) . 'array' . "\r\n"; + for($nA = 0; $nA < $nSize; $nA++) { + $strOutput .= $this->getIndent($nLevel + 1) . $nA . "\r\n"; + $strOutput .= $this->generateDump($value->arraymem($nA), + $nLevel + 2); + } + return $strOutput; + } + + /** + * Returns the indent for a specific level and caches it for faster use + * + * @param int $nLevel the level + * + * @return string the indented string + */ + function getIndent($nLevel) + { + if (!isset($this->arIndent[$nLevel])) { + $this->arIndent[$nLevel] = str_repeat($this->strBaseIndent, $nLevel); + } + return $this->arIndent[$nLevel]; + } +} + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * c-hanging-comment-ender-p: nil + * End: + */ + +?> diff --git a/src/lib/pear/PEAR/XML/RPC/Server.php b/src/lib/pear/PEAR/XML/RPC/Server.php new file mode 100644 index 0000000..ab1c55d --- /dev/null +++ b/src/lib/pear/PEAR/XML/RPC/Server.php @@ -0,0 +1,685 @@ + + * @author Stig Bakken + * @author Martin Jansen + * @author Daniel Convissor + * @copyright 1999-2001 Edd Dumbill, 2001-2006 The PHP Group + * @version CVS: $Id: Server.php,v 1.37 2006/10/28 16:42:34 danielc Exp $ + * @link http://pear.php.net/package/XML_RPC + */ + + +/** + * Pull in the XML_RPC class + */ +require_once 'XML/RPC.php'; + + +/** + * signature for system.listMethods: return = array, + * parameters = a string or nothing + * @global array $GLOBALS['XML_RPC_Server_listMethods_sig'] + */ +$GLOBALS['XML_RPC_Server_listMethods_sig'] = array( + array($GLOBALS['XML_RPC_Array'], + $GLOBALS['XML_RPC_String'] + ), + array($GLOBALS['XML_RPC_Array']) +); + +/** + * docstring for system.listMethods + * @global string $GLOBALS['XML_RPC_Server_listMethods_doc'] + */ +$GLOBALS['XML_RPC_Server_listMethods_doc'] = 'This method lists all the' + . ' methods that the XML-RPC server knows how to dispatch'; + +/** + * signature for system.methodSignature: return = array, + * parameters = string + * @global array $GLOBALS['XML_RPC_Server_methodSignature_sig'] + */ +$GLOBALS['XML_RPC_Server_methodSignature_sig'] = array( + array($GLOBALS['XML_RPC_Array'], + $GLOBALS['XML_RPC_String'] + ) +); + +/** + * docstring for system.methodSignature + * @global string $GLOBALS['XML_RPC_Server_methodSignature_doc'] + */ +$GLOBALS['XML_RPC_Server_methodSignature_doc'] = 'Returns an array of known' + . ' signatures (an array of arrays) for the method name passed. If' + . ' no signatures are known, returns a none-array (test for type !=' + . ' array to detect missing signature)'; + +/** + * signature for system.methodHelp: return = string, + * parameters = string + * @global array $GLOBALS['XML_RPC_Server_methodHelp_sig'] + */ +$GLOBALS['XML_RPC_Server_methodHelp_sig'] = array( + array($GLOBALS['XML_RPC_String'], + $GLOBALS['XML_RPC_String'] + ) +); + +/** + * docstring for methodHelp + * @global string $GLOBALS['XML_RPC_Server_methodHelp_doc'] + */ +$GLOBALS['XML_RPC_Server_methodHelp_doc'] = 'Returns help text if defined' + . ' for the method passed, otherwise returns an empty string'; + +/** + * dispatch map for the automatically declared XML-RPC methods. + * @global array $GLOBALS['XML_RPC_Server_dmap'] + */ +$GLOBALS['XML_RPC_Server_dmap'] = array( + 'system.listMethods' => array( + 'function' => 'XML_RPC_Server_listMethods', + 'signature' => $GLOBALS['XML_RPC_Server_listMethods_sig'], + 'docstring' => $GLOBALS['XML_RPC_Server_listMethods_doc'] + ), + 'system.methodHelp' => array( + 'function' => 'XML_RPC_Server_methodHelp', + 'signature' => $GLOBALS['XML_RPC_Server_methodHelp_sig'], + 'docstring' => $GLOBALS['XML_RPC_Server_methodHelp_doc'] + ), + 'system.methodSignature' => array( + 'function' => 'XML_RPC_Server_methodSignature', + 'signature' => $GLOBALS['XML_RPC_Server_methodSignature_sig'], + 'docstring' => $GLOBALS['XML_RPC_Server_methodSignature_doc'] + ) +); + +/** + * @global string $GLOBALS['XML_RPC_Server_debuginfo'] + */ +$GLOBALS['XML_RPC_Server_debuginfo'] = ''; + + +/** + * Lists all the methods that the XML-RPC server knows how to dispatch + * + * @return object a new XML_RPC_Response object + */ +function XML_RPC_Server_listMethods($server, $m) +{ + global $XML_RPC_err, $XML_RPC_str, $XML_RPC_Server_dmap; + + $v = new XML_RPC_Value(); + $outAr = array(); + foreach ($server->dmap as $key => $val) { + $outAr[] = new XML_RPC_Value($key, 'string'); + } + foreach ($XML_RPC_Server_dmap as $key => $val) { + $outAr[] = new XML_RPC_Value($key, 'string'); + } + $v->addArray($outAr); + return new XML_RPC_Response($v); +} + +/** + * Returns an array of known signatures (an array of arrays) + * for the given method + * + * If no signatures are known, returns a none-array + * (test for type != array to detect missing signature) + * + * @return object a new XML_RPC_Response object + */ +function XML_RPC_Server_methodSignature($server, $m) +{ + global $XML_RPC_err, $XML_RPC_str, $XML_RPC_Server_dmap; + + $methName = $m->getParam(0); + $methName = $methName->scalarval(); + if (strpos($methName, 'system.') === 0) { + $dmap = $XML_RPC_Server_dmap; + $sysCall = 1; + } else { + $dmap = $server->dmap; + $sysCall = 0; + } + // print "\n"; + if (isset($dmap[$methName])) { + if ($dmap[$methName]['signature']) { + $sigs = array(); + $thesigs = $dmap[$methName]['signature']; + for ($i = 0; $i < sizeof($thesigs); $i++) { + $cursig = array(); + $inSig = $thesigs[$i]; + for ($j = 0; $j < sizeof($inSig); $j++) { + $cursig[] = new XML_RPC_Value($inSig[$j], 'string'); + } + $sigs[] = new XML_RPC_Value($cursig, 'array'); + } + $r = new XML_RPC_Response(new XML_RPC_Value($sigs, 'array')); + } else { + $r = new XML_RPC_Response(new XML_RPC_Value('undef', 'string')); + } + } else { + $r = new XML_RPC_Response(0, $XML_RPC_err['introspect_unknown'], + $XML_RPC_str['introspect_unknown']); + } + return $r; +} + +/** + * Returns help text if defined for the method passed, otherwise returns + * an empty string + * + * @return object a new XML_RPC_Response object + */ +function XML_RPC_Server_methodHelp($server, $m) +{ + global $XML_RPC_err, $XML_RPC_str, $XML_RPC_Server_dmap; + + $methName = $m->getParam(0); + $methName = $methName->scalarval(); + if (strpos($methName, 'system.') === 0) { + $dmap = $XML_RPC_Server_dmap; + $sysCall = 1; + } else { + $dmap = $server->dmap; + $sysCall = 0; + } + + if (isset($dmap[$methName])) { + if ($dmap[$methName]['docstring']) { + $r = new XML_RPC_Response(new XML_RPC_Value($dmap[$methName]['docstring']), + 'string'); + } else { + $r = new XML_RPC_Response(new XML_RPC_Value('', 'string')); + } + } else { + $r = new XML_RPC_Response(0, $XML_RPC_err['introspect_unknown'], + $XML_RPC_str['introspect_unknown']); + } + return $r; +} + +/** + * @return void + */ +function XML_RPC_Server_debugmsg($m) +{ + global $XML_RPC_Server_debuginfo; + $XML_RPC_Server_debuginfo = $XML_RPC_Server_debuginfo . $m . "\n"; +} + + +/** + * A server for receiving and replying to XML RPC requests + * + * + * $server = new XML_RPC_Server( + * array( + * 'isan8' => + * array( + * 'function' => 'is_8', + * 'signature' => + * array( + * array('boolean', 'int'), + * array('boolean', 'int', 'boolean'), + * array('boolean', 'string'), + * array('boolean', 'string', 'boolean'), + * ), + * 'docstring' => 'Is the value an 8?' + * ), + * ), + * 1, + * 0 + * ); + * + * + * @category Web Services + * @package XML_RPC + * @author Edd Dumbill + * @author Stig Bakken + * @author Martin Jansen + * @author Daniel Convissor + * @copyright 1999-2001 Edd Dumbill, 2001-2006 The PHP Group + * @version Release: 1.5.1 + * @link http://pear.php.net/package/XML_RPC + */ +class XML_RPC_Server +{ + /** + * Should the payload's content be passed through mb_convert_encoding()? + * + * @see XML_RPC_Server::setConvertPayloadEncoding() + * @since Property available since Release 1.5.1 + * @var boolean + */ + var $convert_payload_encoding = false; + + /** + * The dispatch map, listing the methods this server provides. + * @var array + */ + var $dmap = array(); + + /** + * The present response's encoding + * @var string + * @see XML_RPC_Message::getEncoding() + */ + var $encoding = ''; + + /** + * Debug mode (0 = off, 1 = on) + * @var integer + */ + var $debug = 0; + + /** + * The response's HTTP headers + * @var string + */ + var $server_headers = ''; + + /** + * The response's XML payload + * @var string + */ + var $server_payload = ''; + + + /** + * Constructor for the XML_RPC_Server class + * + * @param array $dispMap the dispatch map. An associative array + * explaining each function. The keys of the main + * array are the procedure names used by the + * clients. The value is another associative array + * that contains up to three elements: + * + The 'function' element's value is the name + * of the function or method that gets called. + * To define a class' method: 'class::method'. + * + The 'signature' element (optional) is an + * array describing the return values and + * parameters + * + The 'docstring' element (optional) is a + * string describing what the method does + * @param int $serviceNow should the HTTP response be sent now? + * (1 = yes, 0 = no) + * @param int $debug should debug output be displayed? + * (1 = yes, 0 = no) + * + * @return void + */ + function XML_RPC_Server($dispMap, $serviceNow = 1, $debug = 0) + { + global $HTTP_RAW_POST_DATA; + + if ($debug) { + $this->debug = 1; + } else { + $this->debug = 0; + } + + $this->dmap = $dispMap; + + if ($serviceNow) { + $this->service(); + } else { + $this->createServerPayload(); + $this->createServerHeaders(); + } + } + + /** + * @return string the debug information if debug debug mode is on + */ + function serializeDebug() + { + global $XML_RPC_Server_debuginfo, $HTTP_RAW_POST_DATA; + + if ($this->debug) { + XML_RPC_Server_debugmsg('vvv POST DATA RECEIVED BY SERVER vvv' . "\n" + . $HTTP_RAW_POST_DATA + . "\n" . '^^^ END POST DATA ^^^'); + } + + if ($XML_RPC_Server_debuginfo != '') { + return "\n"; + } else { + return ''; + } + } + + /** + * Sets whether the payload's content gets passed through + * mb_convert_encoding() + * + * Returns PEAR_ERROR object if mb_convert_encoding() isn't available. + * + * @param int $in where 1 = on, 0 = off + * + * @return void + * + * @see XML_RPC_Message::getEncoding() + * @since Method available since Release 1.5.1 + */ + function setConvertPayloadEncoding($in) + { + if ($in && !function_exists('mb_convert_encoding')) { + return $this->raiseError('mb_convert_encoding() is not available', + XML_RPC_ERROR_PROGRAMMING); + } + $this->convert_payload_encoding = $in; + } + + /** + * Sends the response + * + * The encoding and content-type are determined by + * XML_RPC_Message::getEncoding() + * + * @return void + * + * @uses XML_RPC_Server::createServerPayload(), + * XML_RPC_Server::createServerHeaders() + */ + function service() + { + if (!$this->server_payload) { + $this->createServerPayload(); + } + if (!$this->server_headers) { + $this->createServerHeaders(); + } + + /* + * $server_headers needs to remain a string for compatibility with + * old scripts using this package, but PHP 4.4.2 no longer allows + * line breaks in header() calls. So, we split each header into + * an individual call. The initial replace handles the off chance + * that someone composed a single header with multiple lines, which + * the RFCs allow. + */ + $this->server_headers = $GLOBALS['XML_RPC_func_ereg_replace']("[\r\n]+[ \t]+", + ' ', trim($this->server_headers)); + $headers = $GLOBALS['XML_RPC_func_split']("[\r\n]+", $this->server_headers); + foreach ($headers as $header) + { + header($header); + } + + print $this->server_payload; + } + + /** + * Generates the payload and puts it in the $server_payload property + * + * If XML_RPC_Server::setConvertPayloadEncoding() was set to true, + * the payload gets passed through mb_convert_encoding() + * to ensure the payload matches the encoding set in the + * XML declaration. The encoding type can be manually set via + * XML_RPC_Message::setSendEncoding(). + * + * @return void + * + * @uses XML_RPC_Server::parseRequest(), XML_RPC_Server::$encoding, + * XML_RPC_Response::serialize(), XML_RPC_Server::serializeDebug() + * @see XML_RPC_Server::setConvertPayloadEncoding() + */ + function createServerPayload() + { + $r = $this->parseRequest(); + $this->server_payload = 'encoding . '"?>' . "\n" + . $this->serializeDebug() + . $r->serialize(); + if ($this->convert_payload_encoding) { + $this->server_payload = mb_convert_encoding($this->server_payload, + $this->encoding); + } + } + + /** + * Determines the HTTP headers and puts them in the $server_headers + * property + * + * @return boolean TRUE if okay, FALSE if $server_payload isn't set. + * + * @uses XML_RPC_Server::createServerPayload(), + * XML_RPC_Server::$server_headers + */ + function createServerHeaders() + { + if (!$this->server_payload) { + return false; + } + $this->server_headers = 'Content-Length: ' + . strlen($this->server_payload) . "\r\n" + . 'Content-Type: text/xml;' + . ' charset=' . $this->encoding; + return true; + } + + /** + * @return array + */ + function verifySignature($in, $sig) + { + for ($i = 0; $i < sizeof($sig); $i++) { + // check each possible signature in turn + $cursig = $sig[$i]; + if (sizeof($cursig) == $in->getNumParams() + 1) { + $itsOK = 1; + for ($n = 0; $n < $in->getNumParams(); $n++) { + $p = $in->getParam($n); + // print "\n"; + if ($p->kindOf() == 'scalar') { + $pt = $p->scalartyp(); + } else { + $pt = $p->kindOf(); + } + // $n+1 as first type of sig is return type + if ($pt != $cursig[$n+1]) { + $itsOK = 0; + $pno = $n+1; + $wanted = $cursig[$n+1]; + $got = $pt; + break; + } + } + if ($itsOK) { + return array(1); + } + } + } + if (isset($wanted)) { + return array(0, "Wanted ${wanted}, got ${got} at param ${pno}"); + } else { + $allowed = array(); + foreach ($sig as $val) { + end($val); + $allowed[] = key($val); + } + $allowed = array_unique($allowed); + $last = count($allowed) - 1; + if ($last > 0) { + $allowed[$last] = 'or ' . $allowed[$last]; + } + return array(0, + 'Signature permits ' . implode(', ', $allowed) + . ' parameters but the request had ' + . $in->getNumParams()); + } + } + + /** + * @return object a new XML_RPC_Response object + * + * @uses XML_RPC_Message::getEncoding(), XML_RPC_Server::$encoding + */ + function parseRequest($data = '') + { + global $XML_RPC_xh, $HTTP_RAW_POST_DATA, + $XML_RPC_err, $XML_RPC_str, $XML_RPC_errxml, + $XML_RPC_defencoding, $XML_RPC_Server_dmap; + + if ($data == '') { + $data = $HTTP_RAW_POST_DATA; + } + + $this->encoding = XML_RPC_Message::getEncoding($data); + $parser_resource = xml_parser_create($this->encoding); + $parser = (int) $parser_resource; + + $XML_RPC_xh[$parser] = array(); + $XML_RPC_xh[$parser]['cm'] = 0; + $XML_RPC_xh[$parser]['isf'] = 0; + $XML_RPC_xh[$parser]['params'] = array(); + $XML_RPC_xh[$parser]['method'] = ''; + $XML_RPC_xh[$parser]['stack'] = array(); + $XML_RPC_xh[$parser]['valuestack'] = array(); + + $plist = ''; + + // decompose incoming XML into request structure + + xml_parser_set_option($parser_resource, XML_OPTION_CASE_FOLDING, true); + xml_set_element_handler($parser_resource, 'XML_RPC_se', 'XML_RPC_ee'); + xml_set_character_data_handler($parser_resource, 'XML_RPC_cd'); + if (!xml_parse($parser_resource, $data, 1)) { + // return XML error as a faultCode + $r = new XML_RPC_Response(0, + $XML_RPC_errxml+xml_get_error_code($parser_resource), + sprintf('XML error: %s at line %d', + xml_error_string(xml_get_error_code($parser_resource)), + xml_get_current_line_number($parser_resource))); + xml_parser_free($parser_resource); + } elseif ($XML_RPC_xh[$parser]['isf']>1) { + $r = new XML_RPC_Response(0, + $XML_RPC_err['invalid_request'], + $XML_RPC_str['invalid_request'] + . ': ' + . $XML_RPC_xh[$parser]['isf_reason']); + xml_parser_free($parser_resource); + } else { + xml_parser_free($parser_resource); + $m = new XML_RPC_Message($XML_RPC_xh[$parser]['method']); + // now add parameters in + for ($i = 0; $i < sizeof($XML_RPC_xh[$parser]['params']); $i++) { + // print '\n"; + $plist .= "$i - " . var_export($XML_RPC_xh[$parser]['params'][$i], true) . " \n"; + $m->addParam($XML_RPC_xh[$parser]['params'][$i]); + } + + if ($this->debug) { + XML_RPC_Server_debugmsg($plist); + } + + // now to deal with the method + $methName = $XML_RPC_xh[$parser]['method']; + if (strpos($methName, 'system.') === 0) { + $dmap = $XML_RPC_Server_dmap; + $sysCall = 1; + } else { + $dmap = $this->dmap; + $sysCall = 0; + } + + if (isset($dmap[$methName]['function']) + && is_string($dmap[$methName]['function']) + && strpos($dmap[$methName]['function'], '::') !== false) + { + $dmap[$methName]['function'] = + explode('::', $dmap[$methName]['function']); + } + + if (isset($dmap[$methName]['function']) + && is_callable($dmap[$methName]['function'])) + { + // dispatch if exists + if (isset($dmap[$methName]['signature'])) { + $sr = $this->verifySignature($m, + $dmap[$methName]['signature'] ); + } + if (!isset($dmap[$methName]['signature']) || $sr[0]) { + // if no signature or correct signature + if ($sysCall) { + $r = call_user_func($dmap[$methName]['function'], $this, $m); + } else { + $r = call_user_func($dmap[$methName]['function'], $m); + } + if (!is_a($r, 'XML_RPC_Response')) { + $r = new XML_RPC_Response(0, $XML_RPC_err['not_response_object'], + $XML_RPC_str['not_response_object']); + } + } else { + $r = new XML_RPC_Response(0, $XML_RPC_err['incorrect_params'], + $XML_RPC_str['incorrect_params'] + . ': ' . $sr[1]); + } + } else { + // else prepare error response + $r = new XML_RPC_Response(0, $XML_RPC_err['unknown_method'], + $XML_RPC_str['unknown_method']); + } + } + return $r; + } + + /** + * Echos back the input packet as a string value + * + * @return void + * + * Useful for debugging. + */ + function echoInput() + { + global $HTTP_RAW_POST_DATA; + + $r = new XML_RPC_Response(0); + $r->xv = new XML_RPC_Value("'Aha said I: '" . $HTTP_RAW_POST_DATA, 'string'); + print $r->serialize(); + } +} + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * c-hanging-comment-ender-p: nil + * End: + */ + +?> diff --git a/src/lib/pear/PEAR/data/PEAR/package.dtd b/src/lib/pear/PEAR/data/PEAR/package.dtd new file mode 100644 index 0000000..5bc04dd --- /dev/null +++ b/src/lib/pear/PEAR/data/PEAR/package.dtd @@ -0,0 +1,103 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/lib/pear/PEAR/data/PEAR/template.spec b/src/lib/pear/PEAR/data/PEAR/template.spec new file mode 100644 index 0000000..37b477f --- /dev/null +++ b/src/lib/pear/PEAR/data/PEAR/template.spec @@ -0,0 +1,72 @@ +Summary: PEAR: @summary@ +Name: @rpm_package@ +Version: @version@ +Release: 1 +License: @release_license@ +Group: Development/Libraries +Source: http://@master_server@/get/@package@-%{version}.tgz +BuildRoot: %{_tmppath}/%{name}-root +URL: http://@master_server@/package/@package@ +Prefix: %{_prefix} +BuildArchitectures: @arch@ +@extra_headers@ + +%description +@description@ + +%prep +rm -rf %{buildroot}/* +%setup -c -T +# XXX Source files location is missing here in pear cmd +pear -v -c %{buildroot}/pearrc \ + -d php_dir=%{_libdir}/php/pear \ + -d doc_dir=/docs \ + -d bin_dir=%{_bindir} \ + -d data_dir=%{_libdir}/php/pear/data \ + -d test_dir=%{_libdir}/php/pear/tests \ + -d ext_dir=%{_libdir} \@extra_config@ + -s + +%build +echo BuildRoot=%{buildroot} + +%postun +# if refcount = 0 then package has been removed (not upgraded) +if [ "$1" -eq "0" ]; then + pear uninstall --nodeps -r @possible_channel@@package@ + rm @rpm_xml_dir@/@package@.xml +fi + + +%post +# if refcount = 2 then package has been upgraded +if [ "$1" -ge "2" ]; then + pear upgrade --nodeps -r @rpm_xml_dir@/@package@.xml +else + pear install --nodeps -r @rpm_xml_dir@/@package@.xml +fi + +%install +pear -c %{buildroot}/pearrc install --nodeps -R %{buildroot} \ + $RPM_SOURCE_DIR/@package@-%{version}.tgz +rm %{buildroot}/pearrc +rm %{buildroot}/%{_libdir}/php/pear/.filemap +rm %{buildroot}/%{_libdir}/php/pear/.lock +rm -rf %{buildroot}/%{_libdir}/php/pear/.registry +if [ "@doc_files@" != "" ]; then + mv %{buildroot}/docs/@package@/* . + rm -rf %{buildroot}/docs +fi +mkdir -p %{buildroot}@rpm_xml_dir@ +tar -xzf $RPM_SOURCE_DIR/@package@-%{version}.tgz package@package2xml@.xml +cp -p package@package2xml@.xml %{buildroot}@rpm_xml_dir@/@package@.xml + +#rm -rf %{buildroot}/* +#pear -q install -R %{buildroot} -n package@package2xml@.xml +#mkdir -p %{buildroot}@rpm_xml_dir@ +#cp -p package@package2xml@.xml %{buildroot}@rpm_xml_dir@/@package@.xml + +%files + %defattr(-,root,root) + %doc @doc_files@ + / diff --git a/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/category.jpg b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/category.jpg new file mode 100644 index 0000000..12d287c Binary files /dev/null and b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/category.jpg differ diff --git a/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/config.gif b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/config.gif new file mode 100644 index 0000000..fbdc0a6 Binary files /dev/null and b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/config.gif differ diff --git a/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/download.gif b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/download.gif new file mode 100644 index 0000000..82cc07b Binary files /dev/null and b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/download.gif differ diff --git a/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/error.gif b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/error.gif new file mode 100644 index 0000000..e43fe32 Binary files /dev/null and b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/error.gif differ diff --git a/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/info.gif b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/info.gif new file mode 100644 index 0000000..73db409 Binary files /dev/null and b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/info.gif differ diff --git a/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/infoplus.gif b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/infoplus.gif new file mode 100644 index 0000000..4fdd503 Binary files /dev/null and b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/infoplus.gif differ diff --git a/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/install.gif b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/install.gif new file mode 100644 index 0000000..7bf7379 Binary files /dev/null and b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/install.gif differ diff --git a/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/install_fail.gif b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/install_fail.gif new file mode 100644 index 0000000..5b066a1 Binary files /dev/null and b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/install_fail.gif differ diff --git a/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/install_ok.gif b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/install_ok.gif new file mode 100644 index 0000000..4304b9e Binary files /dev/null and b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/install_ok.gif differ diff --git a/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/install_wait.gif b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/install_wait.gif new file mode 100644 index 0000000..111dae9 Binary files /dev/null and b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/install_wait.gif differ diff --git a/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/login.gif b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/login.gif new file mode 100644 index 0000000..44d2c76 Binary files /dev/null and b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/login.gif differ diff --git a/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/logout.gif b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/logout.gif new file mode 100644 index 0000000..2410e92 Binary files /dev/null and b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/logout.gif differ diff --git a/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/manual.gif b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/manual.gif new file mode 100644 index 0000000..8af8a40 Binary files /dev/null and b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/manual.gif differ diff --git a/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/manualplus.gif b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/manualplus.gif new file mode 100644 index 0000000..2a1ff96 Binary files /dev/null and b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/manualplus.gif differ diff --git a/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/package.jpg b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/package.jpg new file mode 100644 index 0000000..a96b8ad Binary files /dev/null and b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/package.jpg differ diff --git a/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/pearsmall.gif b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/pearsmall.gif new file mode 100644 index 0000000..8ab9a26 Binary files /dev/null and b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/pearsmall.gif differ diff --git a/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/pkglist.png b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/pkglist.png new file mode 100644 index 0000000..9fbf252 Binary files /dev/null and b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/pkglist.png differ diff --git a/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/pkgsearch.png b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/pkgsearch.png new file mode 100644 index 0000000..319035b Binary files /dev/null and b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/pkgsearch.png differ diff --git a/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/trash.gif b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/trash.gif new file mode 100644 index 0000000..31d9775 Binary files /dev/null and b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/images/trash.gif differ diff --git a/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/package.js b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/package.js new file mode 100644 index 0000000..b4783a8 --- /dev/null +++ b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/package.js @@ -0,0 +1,10 @@ +function uninstallPkg(pkg) { + if (!confirm('Do you really want to uninstall "'+pkg+'"?')) + return false; + return true; +} +function installPkg(pkg) { + if (!confirm('Please be patient while downloading "'+pkg+'".')) + return false; + return true; +} diff --git a/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/style.css b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/style.css new file mode 100644 index 0000000..a6de910 --- /dev/null +++ b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/style.css @@ -0,0 +1,234 @@ +a { + color:#000000; + text-decoration: none; +} +a:visited { + color:#000000; + text-decoration: none; +} +a:active { + color:#000000; + text-decoration: none; +} +a:hover { + color:#000000; + text-decoration: underline; +} + +a.green { + color:#006600; + text-decoration: none; +} +a.green:visited { + color:#006600; + text-decoration: none; +} +a.green:active { + color:#006600; + text-decoration: none; +} +a.green:hover { + color:#006600; + text-decoration: underline; +} + +a.blue { + color:#0022cc; + text-decoration: none; +} +a.blue:visited { + color:#0022cc; + text-decoration: none; +} +a.blue:active { + color:#0022cc; + text-decoration: none; +} +a.blue:hover { + color:#0022cc; + text-decoration: underline; +} + +body, td, th { + font-family: verdana,arial,helvetica,sans-serif; + font-size: 90%; +} + +p { + font-family: verdana,arial,helvetica,sans-serif; +} + +th.pack { + color: #FFFFFF; + background: #009933; + text-align: right; +} + +td.package_info_title { + color: #006600; + font-weight: bold; +} + +td.channel_info_title { + color: #006600; + font-weight: bold; +} + +th.others { + color: #006600; + text-align: left; +} + +em { + font-weight: bold; + font-style: italic; +} + +span.green { + color: #006600; +} + +span.headline { + font-family: verdana,arial,helvetica,sans-serif; + font-size: 125%; + font-weight: bold; + color: #ffffff; +} + +span.title { + font-family: verdana,arial,helvetica,sans-serif; + font-size: 110%; + font-weight: bold; + color: #006600; +} + +.newsDate { + font-size: 85%; + font-style: italic; + color: #66cc66; +} + +.compact { + font-family: arial, helvetica, sans-serif; + font-size: 90%; +} + +.menuWhite { + font-family: verdana,arial,helvetica,sans-serif; + font-size: 75%; + color: #ffffff; +} +.menuBlack { + font-family: verdana,arial,helvetica,sans-serif; + text-decoration: none; + font-weight: bold; + font-size: 75%; + color: #000000; +} + +.sidebar { + font-size: 85%; +} + +code, pre, tt { + font-family: Courier, "Courier New", monospace; + font-size: 90%; +} + +pre.php { + border-color: black; + border-style: dashed; + border-width: 1px; + background-color: #eeeeee; + padding: 5px; +} + +h1 { + font-family: verdana,arial,helvetica,sans-serif; + font-size: 140%; + font-weight: bold; + color: #006600; +} + +h2 { + font-family: verdana,arial,helvetica,sans-serif; + font-size: 125%; + font-weight: bold; + color: #006600; +} + +h3 { + font-family: verdana,arial,helvetica,sans-serif; + font-size: 110%; + font-weight: bold; + color: #006600; +} + +small { + font-family: verdana,arial,helvetica,sans-serif; + font-size: 75%; +} + +a.small { + font-family: verdana,arial,helvetica,sans-serif; + font-size: 75%; + text-decoration: none; +} + +.tableTitle { + font-family: verdana,arial,helvetica,sans-serif; + font-weight: bold; +} + +.tableExtras { + font-family: verdana,arial,helvetica,sans-serif; + font-size: 85%; + color: #FFFFFF; +} + +input { + font-family: verdana,arial,helvetica,sans-serif; +} + +textarea { + font-family: verdana,arial,helvetica,sans-serif; +} + +input.small, select.small { + font-family: verdana,arial,helvetica,sans-serif; + font-size: 75%; +} + +textarea.small { + font-family: verdana,arial,helvetica,sans-serif; + font-size: 75%; +} + +form { + margin-bottom : 0; +} + +table.DHTML_Category_Expand { + cursor: hand; +} + +#docshow { + padding: 0.5em 0.5em 0.5em 0.5em; + border-style: double; +} + +#error { + padding: 0.5em 0em 0.5em 0.5em; + margin: 1em 2em 1em 2em; + border-style: solid; + border-color: #ff0000; + background-color: #ffbaba; +} + +#warning { + color: #ff0000; +} + +#log { + color: gray; +} diff --git a/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/bottom.inc.tpl.html b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/bottom.inc.tpl.html new file mode 100644 index 0000000..8028b6d --- /dev/null +++ b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/bottom.inc.tpl.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/caption.tpl.html b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/caption.tpl.html new file mode 100644 index 0000000..d141244 --- /dev/null +++ b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/caption.tpl.html @@ -0,0 +1,10 @@ + + + + + +
    +   + + {Caption} +
    diff --git a/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/categories.list.tpl.html b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/categories.list.tpl.html new file mode 100644 index 0000000..0928c06 --- /dev/null +++ b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/categories.list.tpl.html @@ -0,0 +1,43 @@ +

    + + + + + + + + + + + + +
    + {categoryName} + + {categoryName} +
      {Text}
    + + + + + + + + + + + + + + + +
    +   + + {Text} +
    + + + {Text} +
    +

    diff --git a/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/channel.list.tpl.html b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/channel.list.tpl.html new file mode 100644 index 0000000..aef9700 --- /dev/null +++ b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/channel.list.tpl.html @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + +
    +   + +   + + Channel Server + +   + + Description +
    +   + + + + {Channel} + + {Delete} + + {Summary} +
    +   + +
    + + +
    +
    +

    + + + + + + + +
    + Add a new channel server: +
    +
    + + package +
    +
    +

    diff --git a/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/error.tpl.html b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/error.tpl.html new file mode 100644 index 0000000..f3d1ea2 --- /dev/null +++ b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/error.tpl.html @@ -0,0 +1,10 @@ + + + + + +
      + {Error} +
    + Back +
    diff --git a/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/footer.inc.tpl.html b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/footer.inc.tpl.html new file mode 100644 index 0000000..c1e3439 --- /dev/null +++ b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/footer.inc.tpl.html @@ -0,0 +1,3 @@ +{Filler} + + diff --git a/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/generic_table_horizontal.tpl.html b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/generic_table_horizontal.tpl.html new file mode 100644 index 0000000..0fea7b1 --- /dev/null +++ b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/generic_table_horizontal.tpl.html @@ -0,0 +1,14 @@ + + + + + + + + + + + +
    + {Text} +
    diff --git a/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/generic_table_vertical.tpl.html b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/generic_table_vertical.tpl.html new file mode 100644 index 0000000..cbb0b9b --- /dev/null +++ b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/generic_table_vertical.tpl.html @@ -0,0 +1,15 @@ + + + + + + + + + + +
    + {Title} + + {Text} +
    diff --git a/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/header.inc.tpl.html b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/header.inc.tpl.html new file mode 100644 index 0000000..ff6dd0f --- /dev/null +++ b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/header.inc.tpl.html @@ -0,0 +1,52 @@ + + + + {Title} + + + + + + + + + + + + + + + + + + + + + + + +
    + PEAR + +   + + {Headline} +
    + +
    + + Search package by name + + + +
    +
    +
    + diff --git a/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/info.tpl.html b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/info.tpl.html new file mode 100644 index 0000000..4d0e327 --- /dev/null +++ b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/info.tpl.html @@ -0,0 +1,12 @@ +

    + + + + + +
      + + {Info}
    + +
    +

    diff --git a/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/package.info.tpl.html b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/package.info.tpl.html new file mode 100644 index 0000000..aada9b0 --- /dev/null +++ b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/package.info.tpl.html @@ -0,0 +1,100 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + Package + + {Package} +
    + Installed + + {Installed} +
    + Latest + + {Latest} +
    + License + + {License} +
    + Summary + + {Summary} +
    + Description + + {Description} +
    + Dependencies + + {Dependencies} +
    + Options + + + + + + + + + + + + + + + +
    + {Opt_Img_1} + + + {Opt_Text_1} +
    + {Opt_Img_2} + + + {Opt_Text_2} +
    +
    + {More_Title} + + {More_Data} +
    diff --git a/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/package.list.tpl.html b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/package.list.tpl.html new file mode 100644 index 0000000..e0392b4 --- /dev/null +++ b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/package.list.tpl.html @@ -0,0 +1,127 @@ + + + + + + + + + +
    + + {Prev} + + Displaying {PagerFrom} to {PagerTo} of {PagerCount} Categories + + {Next} +
    +
    + + + + + + + + +
    + + {categoryName} + + {categoryName} +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + Channel + + Package + + Local version + + Latest version + + + + + + + + + + Description +
    + + + + + + + {Channel} + + {Package} + +
    {Installed}
    +
    +
    {Latest}
    +
    +
    {Install}
    +
    +
    {Delete}
    +
    + {Info} + + {InfoExt} + + {Summary} +
    + + +
    + + + + + + + +
    + + {Prev} + + Displaying {PagerFrom} to {PagerTo} of {PagerCount} Categories + + {Next} +
    + diff --git a/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/package.list_nocat.tpl.html b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/package.list_nocat.tpl.html new file mode 100644 index 0000000..b3c0c27 --- /dev/null +++ b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/package.list_nocat.tpl.html @@ -0,0 +1,37 @@ +

    + + + + + +
    + {categoryName} + + {categoryName} +
    + + + + + + + + + + + + + + + +
    +   + + {Text} +
    + + + + {Text} +
    +

    diff --git a/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/package.manually.tpl.html b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/package.manually.tpl.html new file mode 100644 index 0000000..6911da8 --- /dev/null +++ b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/package.manually.tpl.html @@ -0,0 +1,21 @@ +

    + + + + + + + +
    + Quick-install a package +
    +
    + + + package + + force? + +
    +
    +

    diff --git a/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/package.submenu.tpl.html b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/package.submenu.tpl.html new file mode 100644 index 0000000..78878b2 --- /dev/null +++ b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/package.submenu.tpl.html @@ -0,0 +1,10 @@ + + + + + + +
    + [ {text} ] +
    +
    diff --git a/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/search.tpl.html b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/search.tpl.html new file mode 100644 index 0000000..349bd02 --- /dev/null +++ b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/search.tpl.html @@ -0,0 +1,38 @@ + +

    +

    + + + + + + + + + + + + + + + + + + + + + + + +
    +   + + {Title} +
      {Description}
      Channel
      
    +
    +

    + diff --git a/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/tableofchannels.tpl.html b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/tableofchannels.tpl.html new file mode 100644 index 0000000..85022d8 --- /dev/null +++ b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/tableofchannels.tpl.html @@ -0,0 +1,19 @@ + + + + + + + + +
    +   + + {Caption} +
      + +
    diff --git a/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/top.inc.tpl.html b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/top.inc.tpl.html new file mode 100644 index 0000000..b3c29dc --- /dev/null +++ b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/top.inc.tpl.html @@ -0,0 +1,61 @@ + + + + + + + + + + + diff --git a/src/templates/attplan_content_scans.html b/src/templates/attplan_content_scans.html new file mode 100644 index 0000000..e722985 --- /dev/null +++ b/src/templates/attplan_content_scans.html @@ -0,0 +1,325 @@ + + + + {cycle print=false values="#EFEFEF"} + {foreach item=scan from=$scanlist} {cycle print=false assign="color"} + + + + + + + + + + {foreachelse} + + + + {/foreach} diff --git a/src/templates/attplan_content_search.html b/src/templates/attplan_content_search.html new file mode 100644 index 0000000..311a8f6 --- /dev/null +++ b/src/templates/attplan_content_search.html @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/templates/attplan_content_tactic.html b/src/templates/attplan_content_tactic.html new file mode 100644 index 0000000..5e1e4b1 --- /dev/null +++ b/src/templates/attplan_content_tactic.html @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/templates/attplan_edit.html b/src/templates/attplan_edit.html new file mode 100644 index 0000000..cc6f463 --- /dev/null +++ b/src/templates/attplan_edit.html @@ -0,0 +1,132 @@ + + + + + +
    + + + + +
    +   +

    + Package Management
    + Package Management +

    +   +

    + Package Search
    + Package Search +

    +   +

    + Channel Management
    + Channel Management +

    +   +

    + Configuration
    + Configuration +

    +   +
    +
    + + + ", $strInfo ); + $cli = false; + } else { + $arrayInfo = explode("\n",$strInfo); + $cli = true; + } + + foreach($arrayInfo as $val){ + if ( strpos($val,"php.ini") ) { + if($cli){ + list(,$pathIni) = explode('=>',$val); + } else { + $pathIni = strip_tags(trim($val) ); + } + $pathIni = trim($pathIni); + if(is_file($pathIni)){ + return $pathIni; + } + } + } + + return false; +} + +// }}} +// {{{ alterPhpIni + +/* + * Not optimized, but seems to work, if some nice + * peardev will test it? :) + * + * @Author Pierre-Alain Joye + */ +function alterPhpIni($pathIni='') +{ + global $php_dir, $prefix; + + $iniSep = WINDOWS?';':':'; + + if( $pathIni=='' ){ + $pathIni = getphpinipath(); + } + + $arrayIni = file($pathIni); + $i=0; + $found=0; + + // Looks for each active include_path directives + foreach ( $arrayIni as $iniLine ) { + $iniLine = trim($iniLine); + $iniLine = str_replace(array("\n","\r"),array(),$iniLine); + if( preg_match("/^include_path/",$iniLine) ){ + $foundAt[] = $i; + $found++; + } + $i++; + } + + if ( $found ) { + $includeLine = $arrayIni[$foundAt[0]]; + list(,$currentPath)=explode('=',$includeLine); + + $currentPath = trim($currentPath); + if(substr($currentPath,0,1)=='"'){ + $currentPath = substr($currentPath,1,strlen($currentPath)-2); + } + + $arrayPath = explode($iniSep, $currentPath); + if( $arrayPath[0]=='.' ){ + $newPath[0] = '.'; + $newPath[1] = $php_dir; + array_shift($arrayPath); + } else { + $newPath[0] = $php_dir; + } + + foreach( $arrayPath as $path ){ + $newPath[]= $path; + } + } else { + $newPath[0] = '.'; + $newPath[1] = $php_dir; + + } + $nl = WINDOWS?"\r\n":"\n"; + $includepath = 'include_path="'.implode($iniSep,$newPath).'"'; + $newInclude = "$nl$nl;***** Added by go-pear$nl". + $includepath. + $nl.";*****". + $nl.$nl; + + $arrayIni[$foundAt[0]] = $newInclude; + + for( $i=1; $i<$found; $i++){ + $arrayIni[$foundAt[$i]]=';'.trim($arrayIni[$foundAt[$i]]); + } + + $newIni = implode("",$arrayIni); + if ( !($fh = @fopen($pathIni, "wb+")) ){ + $prefixIni = $prefix.DIRECTORY_SEPARATOR."php.ini-gopear"; + $fh = fopen($prefixIni, "wb+"); + if ( !$fh ) { + echo +" +****************************************************************************** +WARNING! I cannot write to $pathIni nor in $prefix/php.ini-gopear. Please +modify manually your php.ini by adding: + +$includepath + +"; + return false; + } else { + fwrite($fh, $newIni, strlen($newIni)); + fclose($fh); + echo +" +****************************************************************************** +WARNING! I cannot write to $pathIni, but I succesfully created a php.ini +under <$prefix/php.ini-gopear>. Please replace the file <$pathIni> with +<$prefixIni> or modify your php.ini by adding: + +$includepath + +"; + + } + } else { + fwrite($fh, $newIni, strlen($newIni)); + fclose($fh); + echo " +php.ini <$pathIni> include_path updated. +"; + } + return true; +} + +?> diff --git a/src/lib/pear/index.php b/src/lib/pear/index.php new file mode 100644 index 0000000..c87ab8f --- /dev/null +++ b/src/lib/pear/index.php @@ -0,0 +1,32 @@ + diff --git a/src/lib/pear/pear.conf b/src/lib/pear/pear.conf new file mode 100644 index 0000000..d90c58d --- /dev/null +++ b/src/lib/pear/pear.conf @@ -0,0 +1,2 @@ +#PEAR_Config 0.9 +a:12:{s:15:"preferred_state";s:6:"stable";s:8:"temp_dir";s:34:"/www/htdocs/w00acdb0/lib/pear/temp";s:7:"bin_dir";s:33:"/www/htdocs/w00acdb0/lib/pear/bin";s:7:"php_dir";s:34:"/www/htdocs/w00acdb0/lib/pear/PEAR";s:7:"doc_dir";s:39:"/www/htdocs/w00acdb0/lib/pear/PEAR/docs";s:8:"data_dir";s:39:"/www/htdocs/w00acdb0/lib/pear/PEAR/data";s:8:"test_dir";s:40:"/www/htdocs/w00acdb0/lib/pear/PEAR/tests";s:9:"cache_dir";s:40:"/www/htdocs/w00acdb0/lib/pear/PEAR/cache";s:9:"cache_ttl";i:300;s:12:"download_dir";s:43:"/www/htdocs/w00acdb0/lib/pear/temp/download";s:10:"http_proxy";s:0:"";s:10:"__channels";a:3:{s:5:"__uri";a:0:{}s:12:"pecl.php.net";a:0:{}s:16:"pear.firephp.org";a:0:{}}} \ No newline at end of file diff --git a/src/lib/pear/temp/channel.xml b/src/lib/pear/temp/channel.xml new file mode 100644 index 0000000..e38f4e6 --- /dev/null +++ b/src/lib/pear/temp/channel.xml @@ -0,0 +1,16 @@ + + + pear.firephp.org + Server code for FirePHP Firefox Extension (http://www.firephp.org/) + firephp + + + + http://pear.firephp.org/Chiara_PEAR_Server_REST/ + http://pear.firephp.org/Chiara_PEAR_Server_REST/ + + + + \ No newline at end of file diff --git a/src/lib/pear/temp/download/FirePHPCore-0.2.1.tgz b/src/lib/pear/temp/download/FirePHPCore-0.2.1.tgz new file mode 100644 index 0000000..3a632d5 Binary files /dev/null and b/src/lib/pear/temp/download/FirePHPCore-0.2.1.tgz differ diff --git a/src/lib/pear/temp/download/FirePHPCore-0.2.1/FirePHP.class.php b/src/lib/pear/temp/download/FirePHPCore-0.2.1/FirePHP.class.php new file mode 100644 index 0000000..733d2b4 --- /dev/null +++ b/src/lib/pear/temp/download/FirePHPCore-0.2.1/FirePHP.class.php @@ -0,0 +1,1375 @@ + + * @license http://www.opensource.org/licenses/bsd-license.php + * @package FirePHP + */ + + +/** + * Sends the given data to the FirePHP Firefox Extension. + * The data can be displayed in the Firebug Console or in the + * "Server" request tab. + * + * For more information see: http://www.firephp.org/ + * + * @copyright Copyright (C) 2007-2008 Christoph Dorn + * @author Christoph Dorn + * @license http://www.opensource.org/licenses/bsd-license.php + * @package FirePHP + */ +class FirePHP { + + /** + * FirePHP version + * + * @var string + */ + const VERSION = '0.2.1'; + + /** + * Firebug LOG level + * + * Logs a message to firebug console. + * + * @var string + */ + const LOG = 'LOG'; + + /** + * Firebug INFO level + * + * Logs a message to firebug console and displays an info icon before the message. + * + * @var string + */ + const INFO = 'INFO'; + + /** + * Firebug WARN level + * + * Logs a message to firebug console, displays an warning icon before the message and colors the line turquoise. + * + * @var string + */ + const WARN = 'WARN'; + + /** + * Firebug ERROR level + * + * Logs a message to firebug console, displays an error icon before the message and colors the line yellow. Also increments the firebug error count. + * + * @var string + */ + const ERROR = 'ERROR'; + + /** + * Dumps a variable to firebug's server panel + * + * @var string + */ + const DUMP = 'DUMP'; + + /** + * Displays a stack trace in firebug console + * + * @var string + */ + const TRACE = 'TRACE'; + + /** + * Displays an exception in firebug console + * + * Increments the firebug error count. + * + * @var string + */ + const EXCEPTION = 'EXCEPTION'; + + /** + * Displays an table in firebug console + * + * @var string + */ + const TABLE = 'TABLE'; + + /** + * Starts a group in firebug console + * + * @var string + */ + const GROUP_START = 'GROUP_START'; + + /** + * Ends a group in firebug console + * + * @var string + */ + const GROUP_END = 'GROUP_END'; + + /** + * Singleton instance of FirePHP + * + * @var FirePHP + */ + protected static $instance = null; + + /** + * Wildfire protocol message index + * + * @var int + */ + protected $messageIndex = 1; + + /** + * Options for the library + * + * @var array + */ + protected $options = array(); + + /** + * Filters used to exclude object members when encoding + * + * @var array + */ + protected $objectFilters = array(); + + /** + * A stack of objects used to detect recursion during object encoding + * + * @var object + */ + protected $objectStack = array(); + + /** + * Flag to enable/disable logging + * + * @var boolean + */ + protected $enabled = true; + + /** + * The object constructor + */ + function __construct() { + $this->options['maxObjectDepth'] = 10; + $this->options['maxArrayDepth'] = 20; + $this->options['useNativeJsonEncode'] = true; + $this->options['includeLineNumbers'] = true; + } + + /** + * When the object gets serialized only include specific object members. + * + * @return array + */ + public function __sleep() { + return array('options','objectFilters','enabled'); + } + + /** + * Gets singleton instance of FirePHP + * + * @param boolean $AutoCreate + * @return FirePHP + */ + public static function getInstance($AutoCreate=false) { + if($AutoCreate===true && !self::$instance) { + self::init(); + } + return self::$instance; + } + + /** + * Creates FirePHP object and stores it for singleton access + * + * @return FirePHP + */ + public static function init() { + return self::$instance = new self(); + } + + /** + * Enable and disable logging to Firebug + * + * @param boolean $Enabled TRUE to enable, FALSE to disable + * @return void + */ + public function setEnabled($Enabled) { + $this->enabled = $Enabled; + } + + /** + * Check if logging is enabled + * + * @return boolean TRUE if enabled + */ + public function getEnabled() { + return $this->enabled; + } + + /** + * Specify a filter to be used when encoding an object + * + * Filters are used to exclude object members. + * + * @param string $Class The class name of the object + * @param array $Filter An array or members to exclude + * @return void + */ + public function setObjectFilter($Class, $Filter) { + $this->objectFilters[$Class] = $Filter; + } + + /** + * Set some options for the library + * + * Options: + * - maxObjectDepth: The maximum depth to traverse objects (default: 10) + * - maxArrayDepth: The maximum depth to traverse arrays (default: 20) + * - useNativeJsonEncode: If true will use json_encode() (default: true) + * - includeLineNumbers: If true will include line numbers and filenames (default: true) + * + * @param array $Options The options to be set + * @return void + */ + public function setOptions($Options) { + $this->options = array_merge($this->options,$Options); + } + + /** + * Register FirePHP as your error handler + * + * Will throw exceptions for each php error. + */ + public function registerErrorHandler() + { + //NOTE: The following errors will not be caught by this error handler: + // E_ERROR, E_PARSE, E_CORE_ERROR, + // E_CORE_WARNING, E_COMPILE_ERROR, + // E_COMPILE_WARNING, E_STRICT + + set_error_handler(array($this,'errorHandler')); + } + + /** + * FirePHP's error handler + * + * Throws exception for each php error that will occur. + * + * @param int $errno + * @param string $errstr + * @param string $errfile + * @param int $errline + * @param array $errcontext + */ + public function errorHandler($errno, $errstr, $errfile, $errline, $errcontext) + { + // Don't throw exception if error reporting is switched off + if (error_reporting() == 0) { + return; + } + // Only throw exceptions for errors we are asking for + if (error_reporting() & $errno) { + throw new ErrorException($errstr, 0, $errno, $errfile, $errline); + } + } + + /** + * Register FirePHP as your exception handler + */ + public function registerExceptionHandler() + { + set_exception_handler(array($this,'exceptionHandler')); + } + + /** + * FirePHP's exception handler + * + * Logs all exceptions to your firebug console and then stops the script. + * + * @param Exception $Exception + * @throws Exception + */ + function exceptionHandler($Exception) { + $this->fb($Exception); + } + + /** + * Set custom processor url for FirePHP + * + * @param string $URL + */ + public function setProcessorUrl($URL) + { + $this->setHeader('X-FirePHP-ProcessorURL', $URL); + } + + /** + * Set custom renderer url for FirePHP + * + * @param string $URL + */ + public function setRendererUrl($URL) + { + $this->setHeader('X-FirePHP-RendererURL', $URL); + } + + /** + * Start a group for following messages + * + * @param string $Name + * @return true + * @throws Exception + */ + public function group($Name) { + return $this->fb(null, $Name, FirePHP::GROUP_START); + } + + /** + * Ends a group you have started before + * + * @return true + * @throws Exception + */ + public function groupEnd() { + return $this->fb(null, null, FirePHP::GROUP_END); + } + + /** + * Log object with label to firebug console + * + * @see FirePHP::LOG + * @param mixes $Object + * @param string $Label + * @return true + * @throws Exception + */ + public function log($Object, $Label=null) { + return $this->fb($Object, $Label, FirePHP::LOG); + } + + /** + * Log object with label to firebug console + * + * @see FirePHP::INFO + * @param mixes $Object + * @param string $Label + * @return true + * @throws Exception + */ + public function info($Object, $Label=null) { + return $this->fb($Object, $Label, FirePHP::INFO); + } + + /** + * Log object with label to firebug console + * + * @see FirePHP::WARN + * @param mixes $Object + * @param string $Label + * @return true + * @throws Exception + */ + public function warn($Object, $Label=null) { + return $this->fb($Object, $Label, FirePHP::WARN); + } + + /** + * Log object with label to firebug console + * + * @see FirePHP::ERROR + * @param mixes $Object + * @param string $Label + * @return true + * @throws Exception + */ + public function error($Object, $Label=null) { + return $this->fb($Object, $Label, FirePHP::ERROR); + } + + /** + * Dumps key and variable to firebug server panel + * + * @see FirePHP::DUMP + * @param string $Key + * @param mixed $Variable + * @return true + * @throws Exception + */ + public function dump($Key, $Variable) { + return $this->fb($Variable, $Key, FirePHP::DUMP); + } + + /** + * Log a trace in the firebug console + * + * @see FirePHP::TRACE + * @param string $Label + * @return true + * @throws Exception + */ + public function trace($Label) { + return $this->fb($Label, FirePHP::TRACE); + } + + /** + * Log a table in the firebug console + * + * @see FirePHP::TABLE + * @param string $Label + * @param string $Table + * @return true + * @throws Exception + */ + public function table($Label, $Table) { + return $this->fb($Table, $Label, FirePHP::TABLE); + } + + /** + * Check if FirePHP is installed on client + * + * @return boolean + */ + public function detectClientExtension() { + /* Check if FirePHP is installed on client */ + if(!@preg_match_all('/\sFirePHP\/([\.|\d]*)\s?/si',$this->getUserAgent(),$m) || + !version_compare($m[1][0],'0.0.6','>=')) { + return false; + } + return true; + } + + /** + * Log varible to Firebug + * + * @see http://www.firephp.org/Wiki/Reference/Fb + * @param mixed $Object The variable to be logged + * @return true Return TRUE if message was added to headers, FALSE otherwise + * @throws Exception + */ + public function fb($Object) { + + if(!$this->enabled) { + return false; + } + + if (headers_sent($filename, $linenum)) { + throw $this->newException('Headers already sent in '.$filename.' on line '.$linenum.'. Cannot send log data to FirePHP. You must have Output Buffering enabled via ob_start() or output_buffering ini directive.'); + } + + $Type = null; + $Label = null; + + if(func_num_args()==1) { + } else + if(func_num_args()==2) { + switch(func_get_arg(1)) { + case self::LOG: + case self::INFO: + case self::WARN: + case self::ERROR: + case self::DUMP: + case self::TRACE: + case self::EXCEPTION: + case self::TABLE: + case self::GROUP_START: + case self::GROUP_END: + $Type = func_get_arg(1); + break; + default: + $Label = func_get_arg(1); + break; + } + } else + if(func_num_args()==3) { + $Type = func_get_arg(2); + $Label = func_get_arg(1); + } else { + throw $this->newException('Wrong number of arguments to fb() function!'); + } + + + if(!$this->detectClientExtension()) { + return false; + } + + $meta = array(); + $skipFinalObjectEncode = false; + + if($Object instanceof Exception) { + + $meta['file'] = $this->_escapeTraceFile($Object->getFile()); + $meta['line'] = $Object->getLine(); + + $trace = $Object->getTrace(); + if($Object instanceof ErrorException + && isset($trace[0]['function']) + && $trace[0]['function']=='errorHandler' + && isset($trace[0]['class']) + && $trace[0]['class']=='FirePHP') { + + $severity = false; + switch($Object->getSeverity()) { + case E_WARNING: $severity = 'E_WARNING'; break; + case E_NOTICE: $severity = 'E_NOTICE'; break; + case E_USER_ERROR: $severity = 'E_USER_ERROR'; break; + case E_USER_WARNING: $severity = 'E_USER_WARNING'; break; + case E_USER_NOTICE: $severity = 'E_USER_NOTICE'; break; + case E_STRICT: $severity = 'E_STRICT'; break; + case E_RECOVERABLE_ERROR: $severity = 'E_RECOVERABLE_ERROR'; break; + case E_DEPRECATED: $severity = 'E_DEPRECATED'; break; + case E_USER_DEPRECATED: $severity = 'E_USER_DEPRECATED'; break; + } + + $Object = array('Class'=>get_class($Object), + 'Message'=>$severity.': '.$Object->getMessage(), + 'File'=>$this->_escapeTraceFile($Object->getFile()), + 'Line'=>$Object->getLine(), + 'Type'=>'trigger', + 'Trace'=>$this->_escapeTrace(array_splice($trace,2))); + $skipFinalObjectEncode = true; + } else { + $Object = array('Class'=>get_class($Object), + 'Message'=>$Object->getMessage(), + 'File'=>$this->_escapeTraceFile($Object->getFile()), + 'Line'=>$Object->getLine(), + 'Type'=>'throw', + 'Trace'=>$this->_escapeTrace($trace)); + $skipFinalObjectEncode = true; + } + $Type = self::EXCEPTION; + + } else + if($Type==self::TRACE) { + + $trace = debug_backtrace(); + if(!$trace) return false; + for( $i=0 ; $i_standardizePath($trace[$i]['file']),-18,18)=='FirePHPCore/fb.php' + || substr($this->_standardizePath($trace[$i]['file']),-29,29)=='FirePHPCore/FirePHP.class.php')) { + /* Skip - FB::trace(), FB::send(), $firephp->trace(), $firephp->fb() */ + } else + if(isset($trace[$i]['class']) + && isset($trace[$i+1]['file']) + && $trace[$i]['class']=='FirePHP' + && substr($this->_standardizePath($trace[$i+1]['file']),-18,18)=='FirePHPCore/fb.php') { + /* Skip fb() */ + } else + if($trace[$i]['function']=='fb' + || $trace[$i]['function']=='trace' + || $trace[$i]['function']=='send') { + $Object = array('Class'=>isset($trace[$i]['class'])?$trace[$i]['class']:'', + 'Type'=>isset($trace[$i]['type'])?$trace[$i]['type']:'', + 'Function'=>isset($trace[$i]['function'])?$trace[$i]['function']:'', + 'Message'=>$trace[$i]['args'][0], + 'File'=>isset($trace[$i]['file'])?$this->_escapeTraceFile($trace[$i]['file']):'', + 'Line'=>isset($trace[$i]['line'])?$trace[$i]['line']:'', + 'Args'=>isset($trace[$i]['args'])?$this->encodeObject($trace[$i]['args']):'', + 'Trace'=>$this->_escapeTrace(array_splice($trace,$i+1))); + + $skipFinalObjectEncode = true; + $meta['file'] = isset($trace[$i]['file'])?$this->_escapeTraceFile($trace[$i]['file']):''; + $meta['line'] = isset($trace[$i]['line'])?$trace[$i]['line']:''; + break; + } + } + + } else + if($Type==self::TABLE) { + + if(isset($Object[0]) && is_string($Object[0])) { + $Object[1] = $this->encodeTable($Object[1]); + } else { + $Object = $this->encodeTable($Object); + } + + $skipFinalObjectEncode = true; + + } else { + if($Type===null) { + $Type = self::LOG; + } + } + + if($this->options['includeLineNumbers']) { + if(!isset($meta['file']) || !isset($meta['line'])) { + + $trace = debug_backtrace(); + for( $i=0 ; $trace && $i_standardizePath($trace[$i]['file']),-18,18)=='FirePHPCore/fb.php' + || substr($this->_standardizePath($trace[$i]['file']),-29,29)=='FirePHPCore/FirePHP.class.php')) { + /* Skip - FB::trace(), FB::send(), $firephp->trace(), $firephp->fb() */ + } else + if(isset($trace[$i]['class']) + && isset($trace[$i+1]['file']) + && $trace[$i]['class']=='FirePHP' + && substr($this->_standardizePath($trace[$i+1]['file']),-18,18)=='FirePHPCore/fb.php') { + /* Skip fb() */ + } else + if(isset($trace[$i]['file']) + && substr($this->_standardizePath($trace[$i]['file']),-18,18)=='FirePHPCore/fb.php') { + /* Skip FB::fb() */ + } else { + $meta['file'] = isset($trace[$i]['file'])?$this->_escapeTraceFile($trace[$i]['file']):''; + $meta['line'] = isset($trace[$i]['line'])?$trace[$i]['line']:''; + break; + } + } + + } + } else { + unset($meta['file']); + unset($meta['line']); + } + + $this->setHeader('X-Wf-Protocol-1','http://meta.wildfirehq.org/Protocol/JsonStream/0.2'); + $this->setHeader('X-Wf-1-Plugin-1','http://meta.firephp.org/Wildfire/Plugin/FirePHP/Library-FirePHPCore/'.self::VERSION); + + $structure_index = 1; + if($Type==self::DUMP) { + $structure_index = 2; + $this->setHeader('X-Wf-1-Structure-2','http://meta.firephp.org/Wildfire/Structure/FirePHP/Dump/0.1'); + } else { + $this->setHeader('X-Wf-1-Structure-1','http://meta.firephp.org/Wildfire/Structure/FirePHP/FirebugConsole/0.1'); + } + + if($Type==self::DUMP) { + $msg = '{"'.$Label.'":'.$this->jsonEncode($Object, $skipFinalObjectEncode).'}'; + } else { + $msg_meta = array('Type'=>$Type); + if($Label!==null) { + $msg_meta['Label'] = $Label; + } + if(isset($meta['file'])) { + $msg_meta['File'] = $meta['file']; + } + if(isset($meta['line'])) { + $msg_meta['Line'] = $meta['line']; + } + $msg = '['.$this->jsonEncode($msg_meta).','.$this->jsonEncode($Object, $skipFinalObjectEncode).']'; + } + + $parts = explode("\n",chunk_split($msg, 5000, "\n")); + + for( $i=0 ; $i2) { + // Message needs to be split into multiple parts + $this->setHeader('X-Wf-1-'.$structure_index.'-'.'1-'.$this->messageIndex, + (($i==0)?strlen($msg):'') + . '|' . $part . '|' + . (($isetHeader('X-Wf-1-'.$structure_index.'-'.'1-'.$this->messageIndex, + strlen($part) . '|' . $part . '|'); + } + + $this->messageIndex++; + + if ($this->messageIndex > 99999) { + throw new Exception('Maximum number (99,999) of messages reached!'); + } + } + } + + $this->setHeader('X-Wf-1-Index',$this->messageIndex-1); + + return true; + } + + /** + * Standardizes path for windows systems. + * + * @param string $Path + * @return string + */ + protected function _standardizePath($Path) { + return preg_replace('/\\\\+/','/',$Path); + } + + /** + * Escape trace path for windows systems + * + * @param array $Trace + * @return array + */ + protected function _escapeTrace($Trace) { + if(!$Trace) return $Trace; + for( $i=0 ; $i_escapeTraceFile($Trace[$i]['file']); + } + if(isset($Trace[$i]['args'])) { + $Trace[$i]['args'] = $this->encodeObject($Trace[$i]['args']); + } + } + return $Trace; + } + + /** + * Escape file information of trace for windows systems + * + * @param string $File + * @return string + */ + protected function _escapeTraceFile($File) { + /* Check if we have a windows filepath */ + if(strpos($File,'\\')) { + /* First strip down to single \ */ + + $file = preg_replace('/\\\\+/','\\',$File); + + return $file; + } + return $File; + } + + /** + * Send header + * + * @param string $Name + * @param string_type $Value + */ + protected function setHeader($Name, $Value) { + return header($Name.': '.$Value); + } + + /** + * Get user agent + * + * @return string|false + */ + protected function getUserAgent() { + if(!isset($_SERVER['HTTP_USER_AGENT'])) return false; + return $_SERVER['HTTP_USER_AGENT']; + } + + /** + * Returns a new exception + * + * @param string $Message + * @return Exception + */ + protected function newException($Message) { + return new Exception($Message); + } + + /** + * Encode an object into a JSON string + * + * Uses PHP's jeson_encode() if available + * + * @param object $Object The object to be encoded + * @return string The JSON string + */ + public function jsonEncode($Object, $skipObjectEncode=false) + { + if(!$skipObjectEncode) { + $Object = $this->encodeObject($Object); + } + + if(function_exists('json_encode') + && $this->options['useNativeJsonEncode']!=false) { + + return json_encode($Object); + } else { + return $this->json_encode($Object); + } + } + + /** + * Encodes a table by encoding each row and column with encodeObject() + * + * @param array $Table The table to be encoded + * @return array + */ + protected function encodeTable($Table) { + if(!$Table) return $Table; + for( $i=0 ; $iencodeObject($Table[$i][$j]); + } + } + } + return $Table; + } + + /** + * Encodes an object including members with + * protected and private visibility + * + * @param Object $Object The object to be encoded + * @param int $Depth The current traversal depth + * @return array All members of the object + */ + protected function encodeObject($Object, $ObjectDepth = 1, $ArrayDepth = 1) + { + $return = array(); + + if (is_resource($Object)) { + + return '** '.(string)$Object.' **'; + + } else + if (is_object($Object)) { + + if ($ObjectDepth > $this->options['maxObjectDepth']) { + return '** Max Object Depth ('.$this->options['maxObjectDepth'].') **'; + } + + foreach ($this->objectStack as $refVal) { + if ($refVal === $Object) { + return '** Recursion ('.get_class($Object).') **'; + } + } + array_push($this->objectStack, $Object); + + $return['__className'] = $class = get_class($Object); + + $reflectionClass = new ReflectionClass($class); + $properties = array(); + foreach( $reflectionClass->getProperties() as $property) { + $properties[$property->getName()] = $property; + } + + $members = (array)$Object; + + foreach( $properties as $raw_name => $property ) { + + $name = $raw_name; + if($property->isStatic()) { + $name = 'static:'.$name; + } + if($property->isPublic()) { + $name = 'public:'.$name; + } else + if($property->isPrivate()) { + $name = 'private:'.$name; + $raw_name = "\0".$class."\0".$raw_name; + } else + if($property->isProtected()) { + $name = 'protected:'.$name; + $raw_name = "\0".'*'."\0".$raw_name; + } + + if(!(isset($this->objectFilters[$class]) + && is_array($this->objectFilters[$class]) + && in_array($raw_name,$this->objectFilters[$class]))) { + + if(array_key_exists($raw_name,$members) + && !$property->isStatic()) { + + $return[$name] = $this->encodeObject($members[$raw_name], $ObjectDepth + 1, 1); + + } else { + if(method_exists($property,'setAccessible')) { + $property->setAccessible(true); + $return[$name] = $this->encodeObject($property->getValue($Object), $ObjectDepth + 1, 1); + } else + if($property->isPublic()) { + $return[$name] = $this->encodeObject($property->getValue($Object), $ObjectDepth + 1, 1); + } else { + $return[$name] = '** Need PHP 5.3 to get value **'; + } + } + } else { + $return[$name] = '** Excluded by Filter **'; + } + } + + // Include all members that are not defined in the class + // but exist in the object + foreach( $members as $raw_name => $value ) { + + $name = $raw_name; + + if ($name{0} == "\0") { + $parts = explode("\0", $name); + $name = $parts[2]; + } + + if(!isset($properties[$name])) { + $name = 'undeclared:'.$name; + + if(!(isset($this->objectFilters[$class]) + && is_array($this->objectFilters[$class]) + && in_array($raw_name,$this->objectFilters[$class]))) { + + $return[$name] = $this->encodeObject($value, $ObjectDepth + 1, 1); + } else { + $return[$name] = '** Excluded by Filter **'; + } + } + } + + array_pop($this->objectStack); + + } elseif (is_array($Object)) { + + if ($ArrayDepth > $this->options['maxArrayDepth']) { + return '** Max Array Depth ('.$this->options['maxArrayDepth'].') **'; + } + + foreach ($Object as $key => $val) { + + // Encoding the $GLOBALS PHP array causes an infinite loop + // if the recursion is not reset here as it contains + // a reference to itself. This is the only way I have come up + // with to stop infinite recursion in this case. + if($key=='GLOBALS' + && is_array($val) + && array_key_exists('GLOBALS',$val)) { + $val['GLOBALS'] = '** Recursion (GLOBALS) **'; + } + + $return[$key] = $this->encodeObject($val, 1, $ArrayDepth + 1); + } + } else { + if(self::is_utf8($Object)) { + return $Object; + } else { + return utf8_encode($Object); + } + } + return $return; + } + + /** + * Returns true if $string is valid UTF-8 and false otherwise. + * + * @param mixed $str String to be tested + * @return boolean + */ + protected static function is_utf8($str) { + $c=0; $b=0; + $bits=0; + $len=strlen($str); + for($i=0; $i<$len; $i++){ + $c=ord($str[$i]); + if($c > 128){ + if(($c >= 254)) return false; + elseif($c >= 252) $bits=6; + elseif($c >= 248) $bits=5; + elseif($c >= 240) $bits=4; + elseif($c >= 224) $bits=3; + elseif($c >= 192) $bits=2; + else return false; + if(($i+$bits) > $len) return false; + while($bits > 1){ + $i++; + $b=ord($str[$i]); + if($b < 128 || $b > 191) return false; + $bits--; + } + } + } + return true; + } + + /** + * Converts to and from JSON format. + * + * JSON (JavaScript Object Notation) is a lightweight data-interchange + * format. It is easy for humans to read and write. It is easy for machines + * to parse and generate. It is based on a subset of the JavaScript + * Programming Language, Standard ECMA-262 3rd Edition - December 1999. + * This feature can also be found in Python. JSON is a text format that is + * completely language independent but uses conventions that are familiar + * to programmers of the C-family of languages, including C, C++, C#, Java, + * JavaScript, Perl, TCL, and many others. These properties make JSON an + * ideal data-interchange language. + * + * This package provides a simple encoder and decoder for JSON notation. It + * is intended for use with client-side Javascript applications that make + * use of HTTPRequest to perform server communication functions - data can + * be encoded into JSON notation for use in a client-side javascript, or + * decoded from incoming Javascript requests. JSON format is native to + * Javascript, and can be directly eval()'ed with no further parsing + * overhead + * + * All strings should be in ASCII or UTF-8 format! + * + * LICENSE: Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: Redistributions of source code must retain the + * above copyright notice, this list of conditions and the following + * disclaimer. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * @category + * @package Services_JSON + * @author Michal Migurski + * @author Matt Knapp + * @author Brett Stimmerman + * @author Christoph Dorn + * @copyright 2005 Michal Migurski + * @version CVS: $Id: JSON.php,v 1.31 2006/06/28 05:54:17 migurski Exp $ + * @license http://www.opensource.org/licenses/bsd-license.php + * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=198 + */ + + + /** + * Keep a list of objects as we descend into the array so we can detect recursion. + */ + private $json_objectStack = array(); + + + /** + * convert a string from one UTF-8 char to one UTF-16 char + * + * Normally should be handled by mb_convert_encoding, but + * provides a slower PHP-only method for installations + * that lack the multibye string extension. + * + * @param string $utf8 UTF-8 character + * @return string UTF-16 character + * @access private + */ + private function json_utf82utf16($utf8) + { + // oh please oh please oh please oh please oh please + if(function_exists('mb_convert_encoding')) { + return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8'); + } + + switch(strlen($utf8)) { + case 1: + // this case should never be reached, because we are in ASCII range + // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + return $utf8; + + case 2: + // return a UTF-16 character from a 2-byte UTF-8 char + // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + return chr(0x07 & (ord($utf8{0}) >> 2)) + . chr((0xC0 & (ord($utf8{0}) << 6)) + | (0x3F & ord($utf8{1}))); + + case 3: + // return a UTF-16 character from a 3-byte UTF-8 char + // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + return chr((0xF0 & (ord($utf8{0}) << 4)) + | (0x0F & (ord($utf8{1}) >> 2))) + . chr((0xC0 & (ord($utf8{1}) << 6)) + | (0x7F & ord($utf8{2}))); + } + + // ignoring UTF-32 for now, sorry + return ''; + } + + /** + * encodes an arbitrary variable into JSON format + * + * @param mixed $var any number, boolean, string, array, or object to be encoded. + * see argument 1 to Services_JSON() above for array-parsing behavior. + * if var is a strng, note that encode() always expects it + * to be in ASCII or UTF-8 format! + * + * @return mixed JSON string representation of input var or an error if a problem occurs + * @access public + */ + private function json_encode($var) + { + + if(is_object($var)) { + if(in_array($var,$this->json_objectStack)) { + return '"** Recursion **"'; + } + } + + switch (gettype($var)) { + case 'boolean': + return $var ? 'true' : 'false'; + + case 'NULL': + return 'null'; + + case 'integer': + return (int) $var; + + case 'double': + case 'float': + return (float) $var; + + case 'string': + // STRINGS ARE EXPECTED TO BE IN ASCII OR UTF-8 FORMAT + $ascii = ''; + $strlen_var = strlen($var); + + /* + * Iterate over every character in the string, + * escaping with a slash or encoding to UTF-8 where necessary + */ + for ($c = 0; $c < $strlen_var; ++$c) { + + $ord_var_c = ord($var{$c}); + + switch (true) { + case $ord_var_c == 0x08: + $ascii .= '\b'; + break; + case $ord_var_c == 0x09: + $ascii .= '\t'; + break; + case $ord_var_c == 0x0A: + $ascii .= '\n'; + break; + case $ord_var_c == 0x0C: + $ascii .= '\f'; + break; + case $ord_var_c == 0x0D: + $ascii .= '\r'; + break; + + case $ord_var_c == 0x22: + case $ord_var_c == 0x2F: + case $ord_var_c == 0x5C: + // double quote, slash, slosh + $ascii .= '\\'.$var{$c}; + break; + + case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)): + // characters U-00000000 - U-0000007F (same as ASCII) + $ascii .= $var{$c}; + break; + + case (($ord_var_c & 0xE0) == 0xC0): + // characters U-00000080 - U-000007FF, mask 110XXXXX + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $char = pack('C*', $ord_var_c, ord($var{$c + 1})); + $c += 1; + $utf16 = $this->json_utf82utf16($char); + $ascii .= sprintf('\u%04s', bin2hex($utf16)); + break; + + case (($ord_var_c & 0xF0) == 0xE0): + // characters U-00000800 - U-0000FFFF, mask 1110XXXX + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $char = pack('C*', $ord_var_c, + ord($var{$c + 1}), + ord($var{$c + 2})); + $c += 2; + $utf16 = $this->json_utf82utf16($char); + $ascii .= sprintf('\u%04s', bin2hex($utf16)); + break; + + case (($ord_var_c & 0xF8) == 0xF0): + // characters U-00010000 - U-001FFFFF, mask 11110XXX + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $char = pack('C*', $ord_var_c, + ord($var{$c + 1}), + ord($var{$c + 2}), + ord($var{$c + 3})); + $c += 3; + $utf16 = $this->json_utf82utf16($char); + $ascii .= sprintf('\u%04s', bin2hex($utf16)); + break; + + case (($ord_var_c & 0xFC) == 0xF8): + // characters U-00200000 - U-03FFFFFF, mask 111110XX + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $char = pack('C*', $ord_var_c, + ord($var{$c + 1}), + ord($var{$c + 2}), + ord($var{$c + 3}), + ord($var{$c + 4})); + $c += 4; + $utf16 = $this->json_utf82utf16($char); + $ascii .= sprintf('\u%04s', bin2hex($utf16)); + break; + + case (($ord_var_c & 0xFE) == 0xFC): + // characters U-04000000 - U-7FFFFFFF, mask 1111110X + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $char = pack('C*', $ord_var_c, + ord($var{$c + 1}), + ord($var{$c + 2}), + ord($var{$c + 3}), + ord($var{$c + 4}), + ord($var{$c + 5})); + $c += 5; + $utf16 = $this->json_utf82utf16($char); + $ascii .= sprintf('\u%04s', bin2hex($utf16)); + break; + } + } + + return '"'.$ascii.'"'; + + case 'array': + /* + * As per JSON spec if any array key is not an integer + * we must treat the the whole array as an object. We + * also try to catch a sparsely populated associative + * array with numeric keys here because some JS engines + * will create an array with empty indexes up to + * max_index which can cause memory issues and because + * the keys, which may be relevant, will be remapped + * otherwise. + * + * As per the ECMA and JSON specification an object may + * have any string as a property. Unfortunately due to + * a hole in the ECMA specification if the key is a + * ECMA reserved word or starts with a digit the + * parameter is only accessible using ECMAScript's + * bracket notation. + */ + + // treat as a JSON object + if (is_array($var) && count($var) && (array_keys($var) !== range(0, sizeof($var) - 1))) { + + $this->json_objectStack[] = $var; + + $properties = array_map(array($this, 'json_name_value'), + array_keys($var), + array_values($var)); + + array_pop($this->json_objectStack); + + foreach($properties as $property) { + if($property instanceof Exception) { + return $property; + } + } + + return '{' . join(',', $properties) . '}'; + } + + $this->json_objectStack[] = $var; + + // treat it like a regular array + $elements = array_map(array($this, 'json_encode'), $var); + + array_pop($this->json_objectStack); + + foreach($elements as $element) { + if($element instanceof Exception) { + return $element; + } + } + + return '[' . join(',', $elements) . ']'; + + case 'object': + $vars = self::encodeObject($var); + + $this->json_objectStack[] = $var; + + $properties = array_map(array($this, 'json_name_value'), + array_keys($vars), + array_values($vars)); + + array_pop($this->json_objectStack); + + foreach($properties as $property) { + if($property instanceof Exception) { + return $property; + } + } + + return '{' . join(',', $properties) . '}'; + + default: + return null; + } + } + + /** + * array-walking function for use in generating JSON-formatted name-value pairs + * + * @param string $name name of key to use + * @param mixed $value reference to an array element to be encoded + * + * @return string JSON-formatted name-value pair, like '"name":value' + * @access private + */ + private function json_name_value($name, $value) + { + // Encoding the $GLOBALS PHP array causes an infinite loop + // if the recursion is not reset here as it contains + // a reference to itself. This is the only way I have come up + // with to stop infinite recursion in this case. + if($name=='GLOBALS' + && is_array($value) + && array_key_exists('GLOBALS',$value)) { + $value['GLOBALS'] = '** Recursion **'; + } + + $encoded_value = $this->json_encode($value); + + if($encoded_value instanceof Exception) { + return $encoded_value; + } + + return $this->json_encode(strval($name)) . ':' . $encoded_value; + } +} diff --git a/src/lib/pear/temp/download/FirePHPCore-0.2.1/fb.php b/src/lib/pear/temp/download/FirePHPCore-0.2.1/fb.php new file mode 100644 index 0000000..96d9719 --- /dev/null +++ b/src/lib/pear/temp/download/FirePHPCore-0.2.1/fb.php @@ -0,0 +1,246 @@ + + * @license http://www.opensource.org/licenses/bsd-license.php + * @package FirePHP + */ + +require_once dirname(__FILE__).'/FirePHP.class.php'; + +/** + * Sends the given data to the FirePHP Firefox Extension. + * The data can be displayed in the Firebug Console or in the + * "Server" request tab. + * + * @see http://www.firephp.org/Wiki/Reference/Fb + * @param mixed $Object + * @return true + * @throws Exception + */ +function fb() +{ + $instance = FirePHP::getInstance(true); + + $args = func_get_args(); + return call_user_func_array(array($instance,'fb'),$args); +} + + +class FB +{ + /** + * Enable and disable logging to Firebug + * + * @see FirePHP->setEnabled() + * @param boolean $Enabled TRUE to enable, FALSE to disable + * @return void + */ + public static function setEnabled($Enabled) { + $instance = FirePHP::getInstance(true); + $instance->setEnabled($Enabled); + } + + /** + * Check if logging is enabled + * + * @see FirePHP->getEnabled() + * @return boolean TRUE if enabled + */ + public static function getEnabled() { + $instance = FirePHP::getInstance(true); + return $instance->getEnabled(); + } + + /** + * Specify a filter to be used when encoding an object + * + * Filters are used to exclude object members. + * + * @see FirePHP->setObjectFilter() + * @param string $Class The class name of the object + * @param array $Filter An array or members to exclude + * @return void + */ + public static function setObjectFilter($Class, $Filter) { + $instance = FirePHP::getInstance(true); + $instance->setObjectFilter($Class, $Filter); + } + + /** + * Set some options for the library + * + * @see FirePHP->setOptions() + * @param array $Options The options to be set + * @return void + */ + public static function setOptions($Options) { + $instance = FirePHP::getInstance(true); + $instance->setOptions($Options); + } + + /** + * Log object to firebug + * + * @see http://www.firephp.org/Wiki/Reference/Fb + * @param mixed $Object + * @return true + * @throws Exception + */ + public static function send() + { + $instance = FirePHP::getInstance(true); + $args = func_get_args(); + return call_user_func_array(array($instance,'fb'),$args); + } + + /** + * Start a group for following messages + * + * @param string $Name + * @return true + * @throws Exception + */ + public static function group($Name) { + return self::send(null, $Name, FirePHP::GROUP_START); + } + + /** + * Ends a group you have started before + * + * @return true + * @throws Exception + */ + public static function groupEnd() { + return self::send(null, null, FirePHP::GROUP_END); + } + + /** + * Log object with label to firebug console + * + * @see FirePHP::LOG + * @param mixes $Object + * @param string $Label + * @return true + * @throws Exception + */ + public static function log($Object, $Label=null) { + return self::send($Object, $Label, FirePHP::LOG); + } + + /** + * Log object with label to firebug console + * + * @see FirePHP::INFO + * @param mixes $Object + * @param string $Label + * @return true + * @throws Exception + */ + public static function info($Object, $Label=null) { + return self::send($Object, $Label, FirePHP::INFO); + } + + /** + * Log object with label to firebug console + * + * @see FirePHP::WARN + * @param mixes $Object + * @param string $Label + * @return true + * @throws Exception + */ + public static function warn($Object, $Label=null) { + return self::send($Object, $Label, FirePHP::WARN); + } + + /** + * Log object with label to firebug console + * + * @see FirePHP::ERROR + * @param mixes $Object + * @param string $Label + * @return true + * @throws Exception + */ + public static function error($Object, $Label=null) { + return self::send($Object, $Label, FirePHP::ERROR); + } + + /** + * Dumps key and variable to firebug server panel + * + * @see FirePHP::DUMP + * @param string $Key + * @param mixed $Variable + * @return true + * @throws Exception + */ + public static function dump($Key, $Variable) { + return self::send($Variable, $Key, FirePHP::DUMP); + } + + /** + * Log a trace in the firebug console + * + * @see FirePHP::TRACE + * @param string $Label + * @return true + * @throws Exception + */ + public static function trace($Label) { + return self::send($Label, FirePHP::TRACE); + } + + /** + * Log a table in the firebug console + * + * @see FirePHP::TABLE + * @param string $Label + * @param string $Table + * @return true + * @throws Exception + */ + public static function table($Label, $Table) { + return self::send($Table, $Label, FirePHP::TABLE); + } + +} + + diff --git a/src/lib/pear/temp/download/XML_RPC-1.5.1.tgz b/src/lib/pear/temp/download/XML_RPC-1.5.1.tgz new file mode 100644 index 0000000..37da034 Binary files /dev/null and b/src/lib/pear/temp/download/XML_RPC-1.5.1.tgz differ diff --git a/src/lib/pear/temp/download/XML_RPC-1.5.1/Dump.php b/src/lib/pear/temp/download/XML_RPC-1.5.1/Dump.php new file mode 100644 index 0000000..97c30e2 --- /dev/null +++ b/src/lib/pear/temp/download/XML_RPC-1.5.1/Dump.php @@ -0,0 +1,187 @@ + + * @version CVS: $Id: Dump.php,v 1.7 2005/01/24 03:47:55 danielc Exp $ + * @link http://pear.php.net/package/XML_RPC + */ + + +/** + * Pull in the XML_RPC class + */ +require_once 'XML/RPC.php'; + + +/** + * Generates the dump of the XML_RPC_Value and echoes it + * + * @param object $value the XML_RPC_Value object to dump + * + * @return void + */ +function XML_RPC_Dump($value) +{ + $dumper = new XML_RPC_Dump(); + echo $dumper->generateDump($value); +} + + +/** + * Class which generates a dump of a XML_RPC_Value object + * + * @category Web Services + * @package XML_RPC + * @author Christian Weiske + * @version Release: 1.5.1 + * @link http://pear.php.net/package/XML_RPC + */ +class XML_RPC_Dump +{ + /** + * The indentation array cache + * @var array + */ + var $arIndent = array(); + + /** + * The spaces used for indenting the XML + * @var string + */ + var $strBaseIndent = ' '; + + /** + * Returns the dump in XML format without printing it out + * + * @param object $value the XML_RPC_Value object to dump + * @param int $nLevel the level of indentation + * + * @return string the dump + */ + function generateDump($value, $nLevel = 0) + { + if (!is_object($value) && get_class($value) != 'xml_rpc_value') { + require_once 'PEAR.php'; + PEAR::raiseError('Tried to dump non-XML_RPC_Value variable' . "\r\n", + 0, PEAR_ERROR_PRINT); + if (is_object($value)) { + $strType = get_class($value); + } else { + $strType = gettype($value); + } + return $this->getIndent($nLevel) . 'NOT A XML_RPC_Value: ' + . $strType . "\r\n"; + } + + switch ($value->kindOf()) { + case 'struct': + $ret = $this->genStruct($value, $nLevel); + break; + case 'array': + $ret = $this->genArray($value, $nLevel); + break; + case 'scalar': + $ret = $this->genScalar($value->scalarval(), $nLevel); + break; + default: + require_once 'PEAR.php'; + PEAR::raiseError('Illegal type "' . $value->kindOf() + . '" in XML_RPC_Value' . "\r\n", 0, + PEAR_ERROR_PRINT); + } + + return $ret; + } + + /** + * Returns the scalar value dump + * + * @param object $value the scalar XML_RPC_Value object to dump + * @param int $nLevel the level of indentation + * + * @return string Dumped version of the scalar value + */ + function genScalar($value, $nLevel) + { + if (gettype($value) == 'object') { + $strClass = ' ' . get_class($value); + } else { + $strClass = ''; + } + return $this->getIndent($nLevel) . gettype($value) . $strClass + . ' ' . $value . "\r\n"; + } + + /** + * Returns the dump of a struct + * + * @param object $value the struct XML_RPC_Value object to dump + * @param int $nLevel the level of indentation + * + * @return string Dumped version of the scalar value + */ + function genStruct($value, $nLevel) + { + $value->structreset(); + $strOutput = $this->getIndent($nLevel) . 'struct' . "\r\n"; + while (list($key, $keyval) = $value->structeach()) { + $strOutput .= $this->getIndent($nLevel + 1) . $key . "\r\n"; + $strOutput .= $this->generateDump($keyval, $nLevel + 2); + } + return $strOutput; + } + + /** + * Returns the dump of an array + * + * @param object $value the array XML_RPC_Value object to dump + * @param int $nLevel the level of indentation + * + * @return string Dumped version of the scalar value + */ + function genArray($value, $nLevel) + { + $nSize = $value->arraysize(); + $strOutput = $this->getIndent($nLevel) . 'array' . "\r\n"; + for($nA = 0; $nA < $nSize; $nA++) { + $strOutput .= $this->getIndent($nLevel + 1) . $nA . "\r\n"; + $strOutput .= $this->generateDump($value->arraymem($nA), + $nLevel + 2); + } + return $strOutput; + } + + /** + * Returns the indent for a specific level and caches it for faster use + * + * @param int $nLevel the level + * + * @return string the indented string + */ + function getIndent($nLevel) + { + if (!isset($this->arIndent[$nLevel])) { + $this->arIndent[$nLevel] = str_repeat($this->strBaseIndent, $nLevel); + } + return $this->arIndent[$nLevel]; + } +} + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * c-hanging-comment-ender-p: nil + * End: + */ + +?> diff --git a/src/lib/pear/temp/download/XML_RPC-1.5.1/RPC.php b/src/lib/pear/temp/download/XML_RPC-1.5.1/RPC.php new file mode 100644 index 0000000..f3baec2 --- /dev/null +++ b/src/lib/pear/temp/download/XML_RPC-1.5.1/RPC.php @@ -0,0 +1,2077 @@ + + * @author Stig Bakken + * @author Martin Jansen + * @author Daniel Convissor + * @copyright 1999-2001 Edd Dumbill, 2001-2006 The PHP Group + * @version CVS: $Id: RPC.php,v 1.101 2006/10/28 16:42:34 danielc Exp $ + * @link http://pear.php.net/package/XML_RPC + */ + + +if (!function_exists('xml_parser_create')) { + include_once 'PEAR.php'; + PEAR::loadExtension('xml'); +} + +/**#@+ + * Error constants + */ +/** + * Parameter values don't match parameter types + */ +define('XML_RPC_ERROR_INVALID_TYPE', 101); +/** + * Parameter declared to be numeric but the values are not + */ +define('XML_RPC_ERROR_NON_NUMERIC_FOUND', 102); +/** + * Communication error + */ +define('XML_RPC_ERROR_CONNECTION_FAILED', 103); +/** + * The array or struct has already been started + */ +define('XML_RPC_ERROR_ALREADY_INITIALIZED', 104); +/** + * Incorrect parameters submitted + */ +define('XML_RPC_ERROR_INCORRECT_PARAMS', 105); +/** + * Programming error by developer + */ +define('XML_RPC_ERROR_PROGRAMMING', 106); +/**#@-*/ + + +/** + * Data types + * @global string $GLOBALS['XML_RPC_I4'] + */ +$GLOBALS['XML_RPC_I4'] = 'i4'; + +/** + * Data types + * @global string $GLOBALS['XML_RPC_Int'] + */ +$GLOBALS['XML_RPC_Int'] = 'int'; + +/** + * Data types + * @global string $GLOBALS['XML_RPC_Boolean'] + */ +$GLOBALS['XML_RPC_Boolean'] = 'boolean'; + +/** + * Data types + * @global string $GLOBALS['XML_RPC_Double'] + */ +$GLOBALS['XML_RPC_Double'] = 'double'; + +/** + * Data types + * @global string $GLOBALS['XML_RPC_String'] + */ +$GLOBALS['XML_RPC_String'] = 'string'; + +/** + * Data types + * @global string $GLOBALS['XML_RPC_DateTime'] + */ +$GLOBALS['XML_RPC_DateTime'] = 'dateTime.iso8601'; + +/** + * Data types + * @global string $GLOBALS['XML_RPC_Base64'] + */ +$GLOBALS['XML_RPC_Base64'] = 'base64'; + +/** + * Data types + * @global string $GLOBALS['XML_RPC_Array'] + */ +$GLOBALS['XML_RPC_Array'] = 'array'; + +/** + * Data types + * @global string $GLOBALS['XML_RPC_Struct'] + */ +$GLOBALS['XML_RPC_Struct'] = 'struct'; + + +/** + * Data type meta-types + * @global array $GLOBALS['XML_RPC_Types'] + */ +$GLOBALS['XML_RPC_Types'] = array( + $GLOBALS['XML_RPC_I4'] => 1, + $GLOBALS['XML_RPC_Int'] => 1, + $GLOBALS['XML_RPC_Boolean'] => 1, + $GLOBALS['XML_RPC_String'] => 1, + $GLOBALS['XML_RPC_Double'] => 1, + $GLOBALS['XML_RPC_DateTime'] => 1, + $GLOBALS['XML_RPC_Base64'] => 1, + $GLOBALS['XML_RPC_Array'] => 2, + $GLOBALS['XML_RPC_Struct'] => 3, +); + + +/** + * Error message numbers + * @global array $GLOBALS['XML_RPC_err'] + */ +$GLOBALS['XML_RPC_err'] = array( + 'unknown_method' => 1, + 'invalid_return' => 2, + 'incorrect_params' => 3, + 'introspect_unknown' => 4, + 'http_error' => 5, + 'not_response_object' => 6, + 'invalid_request' => 7, +); + +/** + * Error message strings + * @global array $GLOBALS['XML_RPC_str'] + */ +$GLOBALS['XML_RPC_str'] = array( + 'unknown_method' => 'Unknown method', + 'invalid_return' => 'Invalid return payload: enable debugging to examine incoming payload', + 'incorrect_params' => 'Incorrect parameters passed to method', + 'introspect_unknown' => 'Can\'t introspect: method unknown', + 'http_error' => 'Didn\'t receive 200 OK from remote server.', + 'not_response_object' => 'The requested method didn\'t return an XML_RPC_Response object.', + 'invalid_request' => 'Invalid request payload', +); + + +/** + * Default XML encoding (ISO-8859-1, UTF-8 or US-ASCII) + * @global string $GLOBALS['XML_RPC_defencoding'] + */ +$GLOBALS['XML_RPC_defencoding'] = 'UTF-8'; + +/** + * User error codes start at 800 + * @global int $GLOBALS['XML_RPC_erruser'] + */ +$GLOBALS['XML_RPC_erruser'] = 800; + +/** + * XML parse error codes start at 100 + * @global int $GLOBALS['XML_RPC_errxml'] + */ +$GLOBALS['XML_RPC_errxml'] = 100; + + +/** + * Compose backslashes for escaping regexp + * @global string $GLOBALS['XML_RPC_backslash'] + */ +$GLOBALS['XML_RPC_backslash'] = chr(92) . chr(92); + + +/**#@+ + * Which functions to use, depending on whether mbstring is enabled or not. + */ +if (function_exists('mb_ereg')) { + /** @global string $GLOBALS['XML_RPC_func_ereg'] */ + $GLOBALS['XML_RPC_func_ereg'] = 'mb_eregi'; + /** @global string $GLOBALS['XML_RPC_func_ereg_replace'] */ + $GLOBALS['XML_RPC_func_ereg_replace'] = 'mb_eregi_replace'; + /** @global string $GLOBALS['XML_RPC_func_split'] */ + $GLOBALS['XML_RPC_func_split'] = 'mb_split'; +} else { + /** @ignore */ + $GLOBALS['XML_RPC_func_ereg'] = 'eregi'; + /** @ignore */ + $GLOBALS['XML_RPC_func_ereg_replace'] = 'eregi_replace'; + /** @ignore */ + $GLOBALS['XML_RPC_func_split'] = 'split'; +} +/**#@-*/ + + +/** + * Should we automatically base64 encode strings that contain characters + * which can cause PHP's SAX-based XML parser to break? + * @global boolean $GLOBALS['XML_RPC_auto_base64'] + */ +$GLOBALS['XML_RPC_auto_base64'] = false; + + +/** + * Valid parents of XML elements + * @global array $GLOBALS['XML_RPC_valid_parents'] + */ +$GLOBALS['XML_RPC_valid_parents'] = array( + 'BOOLEAN' => array('VALUE'), + 'I4' => array('VALUE'), + 'INT' => array('VALUE'), + 'STRING' => array('VALUE'), + 'DOUBLE' => array('VALUE'), + 'DATETIME.ISO8601' => array('VALUE'), + 'BASE64' => array('VALUE'), + 'ARRAY' => array('VALUE'), + 'STRUCT' => array('VALUE'), + 'PARAM' => array('PARAMS'), + 'METHODNAME' => array('METHODCALL'), + 'PARAMS' => array('METHODCALL', 'METHODRESPONSE'), + 'MEMBER' => array('STRUCT'), + 'NAME' => array('MEMBER'), + 'DATA' => array('ARRAY'), + 'FAULT' => array('METHODRESPONSE'), + 'VALUE' => array('MEMBER', 'DATA', 'PARAM', 'FAULT'), +); + + +/** + * Stores state during parsing + * + * quick explanation of components: + * + ac = accumulates values + * + qt = decides if quotes are needed for evaluation + * + cm = denotes struct or array (comma needed) + * + isf = indicates a fault + * + lv = indicates "looking for a value": implements the logic + * to allow values with no types to be strings + * + params = stores parameters in method calls + * + method = stores method name + * + * @global array $GLOBALS['XML_RPC_xh'] + */ +$GLOBALS['XML_RPC_xh'] = array(); + + +/** + * Start element handler for the XML parser + * + * @return void + */ +function XML_RPC_se($parser_resource, $name, $attrs) +{ + global $XML_RPC_xh, $XML_RPC_valid_parents; + + $parser = (int) $parser_resource; + + // if invalid xmlrpc already detected, skip all processing + if ($XML_RPC_xh[$parser]['isf'] >= 2) { + return; + } + + // check for correct element nesting + // top level element can only be of 2 types + if (count($XML_RPC_xh[$parser]['stack']) == 0) { + if ($name != 'METHODRESPONSE' && $name != 'METHODCALL') { + $XML_RPC_xh[$parser]['isf'] = 2; + $XML_RPC_xh[$parser]['isf_reason'] = 'missing top level xmlrpc element'; + return; + } + } else { + // not top level element: see if parent is OK + if (!in_array($XML_RPC_xh[$parser]['stack'][0], $XML_RPC_valid_parents[$name])) { + $name = $GLOBALS['XML_RPC_func_ereg_replace']('[^a-zA-Z0-9._-]', '', $name); + $XML_RPC_xh[$parser]['isf'] = 2; + $XML_RPC_xh[$parser]['isf_reason'] = "xmlrpc element $name cannot be child of {$XML_RPC_xh[$parser]['stack'][0]}"; + return; + } + } + + switch ($name) { + case 'STRUCT': + $XML_RPC_xh[$parser]['cm']++; + + // turn quoting off + $XML_RPC_xh[$parser]['qt'] = 0; + + $cur_val = array(); + $cur_val['value'] = array(); + $cur_val['members'] = 1; + array_unshift($XML_RPC_xh[$parser]['valuestack'], $cur_val); + break; + + case 'ARRAY': + $XML_RPC_xh[$parser]['cm']++; + + // turn quoting off + $XML_RPC_xh[$parser]['qt'] = 0; + + $cur_val = array(); + $cur_val['value'] = array(); + $cur_val['members'] = 0; + array_unshift($XML_RPC_xh[$parser]['valuestack'], $cur_val); + break; + + case 'NAME': + $XML_RPC_xh[$parser]['ac'] = ''; + break; + + case 'FAULT': + $XML_RPC_xh[$parser]['isf'] = 1; + break; + + case 'PARAM': + $XML_RPC_xh[$parser]['valuestack'] = array(); + break; + + case 'VALUE': + $XML_RPC_xh[$parser]['lv'] = 1; + $XML_RPC_xh[$parser]['vt'] = $GLOBALS['XML_RPC_String']; + $XML_RPC_xh[$parser]['ac'] = ''; + $XML_RPC_xh[$parser]['qt'] = 0; + // look for a value: if this is still 1 by the + // time we reach the first data segment then the type is string + // by implication and we need to add in a quote + break; + + case 'I4': + case 'INT': + case 'STRING': + case 'BOOLEAN': + case 'DOUBLE': + case 'DATETIME.ISO8601': + case 'BASE64': + $XML_RPC_xh[$parser]['ac'] = ''; // reset the accumulator + + if ($name == 'DATETIME.ISO8601' || $name == 'STRING') { + $XML_RPC_xh[$parser]['qt'] = 1; + + if ($name == 'DATETIME.ISO8601') { + $XML_RPC_xh[$parser]['vt'] = $GLOBALS['XML_RPC_DateTime']; + } + + } elseif ($name == 'BASE64') { + $XML_RPC_xh[$parser]['qt'] = 2; + } else { + // No quoting is required here -- but + // at the end of the element we must check + // for data format errors. + $XML_RPC_xh[$parser]['qt'] = 0; + } + break; + + case 'MEMBER': + $XML_RPC_xh[$parser]['ac'] = ''; + break; + + case 'DATA': + case 'METHODCALL': + case 'METHODNAME': + case 'METHODRESPONSE': + case 'PARAMS': + // valid elements that add little to processing + break; + } + + + // Save current element to stack + array_unshift($XML_RPC_xh[$parser]['stack'], $name); + + if ($name != 'VALUE') { + $XML_RPC_xh[$parser]['lv'] = 0; + } +} + +/** + * End element handler for the XML parser + * + * @return void + */ +function XML_RPC_ee($parser_resource, $name) +{ + global $XML_RPC_xh; + + $parser = (int) $parser_resource; + + if ($XML_RPC_xh[$parser]['isf'] >= 2) { + return; + } + + // push this element from stack + // NB: if XML validates, correct opening/closing is guaranteed and + // we do not have to check for $name == $curr_elem. + // we also checked for proper nesting at start of elements... + $curr_elem = array_shift($XML_RPC_xh[$parser]['stack']); + + switch ($name) { + case 'STRUCT': + case 'ARRAY': + $cur_val = array_shift($XML_RPC_xh[$parser]['valuestack']); + $XML_RPC_xh[$parser]['value'] = $cur_val['value']; + $XML_RPC_xh[$parser]['vt'] = strtolower($name); + $XML_RPC_xh[$parser]['cm']--; + break; + + case 'NAME': + $XML_RPC_xh[$parser]['valuestack'][0]['name'] = $XML_RPC_xh[$parser]['ac']; + break; + + case 'BOOLEAN': + // special case here: we translate boolean 1 or 0 into PHP + // constants true or false + if ($XML_RPC_xh[$parser]['ac'] == '1') { + $XML_RPC_xh[$parser]['ac'] = 'true'; + } else { + $XML_RPC_xh[$parser]['ac'] = 'false'; + } + + $XML_RPC_xh[$parser]['vt'] = strtolower($name); + // Drop through intentionally. + + case 'I4': + case 'INT': + case 'STRING': + case 'DOUBLE': + case 'DATETIME.ISO8601': + case 'BASE64': + if ($XML_RPC_xh[$parser]['qt'] == 1) { + // we use double quotes rather than single so backslashification works OK + $XML_RPC_xh[$parser]['value'] = $XML_RPC_xh[$parser]['ac']; + } elseif ($XML_RPC_xh[$parser]['qt'] == 2) { + $XML_RPC_xh[$parser]['value'] = base64_decode($XML_RPC_xh[$parser]['ac']); + } elseif ($name == 'BOOLEAN') { + $XML_RPC_xh[$parser]['value'] = $XML_RPC_xh[$parser]['ac']; + } else { + // we have an I4, INT or a DOUBLE + // we must check that only 0123456789-. are characters here + if (!$GLOBALS['XML_RPC_func_ereg']("^[+-]?[0123456789 \t\.]+$", $XML_RPC_xh[$parser]['ac'])) { + XML_RPC_Base::raiseError('Non-numeric value received in INT or DOUBLE', + XML_RPC_ERROR_NON_NUMERIC_FOUND); + $XML_RPC_xh[$parser]['value'] = XML_RPC_ERROR_NON_NUMERIC_FOUND; + } else { + // it's ok, add it on + $XML_RPC_xh[$parser]['value'] = $XML_RPC_xh[$parser]['ac']; + } + } + + $XML_RPC_xh[$parser]['ac'] = ''; + $XML_RPC_xh[$parser]['qt'] = 0; + $XML_RPC_xh[$parser]['lv'] = 3; // indicate we've found a value + break; + + case 'VALUE': + if ($XML_RPC_xh[$parser]['vt'] == $GLOBALS['XML_RPC_String']) { + if (strlen($XML_RPC_xh[$parser]['ac']) > 0) { + $XML_RPC_xh[$parser]['value'] = $XML_RPC_xh[$parser]['ac']; + } elseif ($XML_RPC_xh[$parser]['lv'] == 1) { + // The element was empty. + $XML_RPC_xh[$parser]['value'] = ''; + } + } + + $temp = new XML_RPC_Value($XML_RPC_xh[$parser]['value'], $XML_RPC_xh[$parser]['vt']); + + $cur_val = array_shift($XML_RPC_xh[$parser]['valuestack']); + if (is_array($cur_val)) { + if ($cur_val['members']==0) { + $cur_val['value'][] = $temp; + } else { + $XML_RPC_xh[$parser]['value'] = $temp; + } + array_unshift($XML_RPC_xh[$parser]['valuestack'], $cur_val); + } else { + $XML_RPC_xh[$parser]['value'] = $temp; + } + break; + + case 'MEMBER': + $XML_RPC_xh[$parser]['ac'] = ''; + $XML_RPC_xh[$parser]['qt'] = 0; + + $cur_val = array_shift($XML_RPC_xh[$parser]['valuestack']); + if (is_array($cur_val)) { + if ($cur_val['members']==1) { + $cur_val['value'][$cur_val['name']] = $XML_RPC_xh[$parser]['value']; + } + array_unshift($XML_RPC_xh[$parser]['valuestack'], $cur_val); + } + break; + + case 'DATA': + $XML_RPC_xh[$parser]['ac'] = ''; + $XML_RPC_xh[$parser]['qt'] = 0; + break; + + case 'PARAM': + $XML_RPC_xh[$parser]['params'][] = $XML_RPC_xh[$parser]['value']; + break; + + case 'METHODNAME': + case 'RPCMETHODNAME': + $XML_RPC_xh[$parser]['method'] = $GLOBALS['XML_RPC_func_ereg_replace']("^[\n\r\t ]+", '', + $XML_RPC_xh[$parser]['ac']); + break; + } + + // if it's a valid type name, set the type + if (isset($GLOBALS['XML_RPC_Types'][strtolower($name)])) { + $XML_RPC_xh[$parser]['vt'] = strtolower($name); + } +} + +/** + * Character data handler for the XML parser + * + * @return void + */ +function XML_RPC_cd($parser_resource, $data) +{ + global $XML_RPC_xh, $XML_RPC_backslash; + + $parser = (int) $parser_resource; + + if ($XML_RPC_xh[$parser]['lv'] != 3) { + // "lookforvalue==3" means that we've found an entire value + // and should discard any further character data + + if ($XML_RPC_xh[$parser]['lv'] == 1) { + // if we've found text and we're just in a then + // turn quoting on, as this will be a string + $XML_RPC_xh[$parser]['qt'] = 1; + // and say we've found a value + $XML_RPC_xh[$parser]['lv'] = 2; + } + + // replace characters that eval would + // do special things with + if (!isset($XML_RPC_xh[$parser]['ac'])) { + $XML_RPC_xh[$parser]['ac'] = ''; + } + $XML_RPC_xh[$parser]['ac'] .= $data; + } +} + +/** + * The common methods and properties for all of the XML_RPC classes + * + * @category Web Services + * @package XML_RPC + * @author Edd Dumbill + * @author Stig Bakken + * @author Martin Jansen + * @author Daniel Convissor + * @copyright 1999-2001 Edd Dumbill, 2001-2006 The PHP Group + * @version Release: 1.5.1 + * @link http://pear.php.net/package/XML_RPC + */ +class XML_RPC_Base { + + /** + * PEAR Error handling + * + * @return object PEAR_Error object + */ + function raiseError($msg, $code) + { + include_once 'PEAR.php'; + if (is_object(@$this)) { + return PEAR::raiseError(get_class($this) . ': ' . $msg, $code); + } else { + return PEAR::raiseError('XML_RPC: ' . $msg, $code); + } + } + + /** + * Tell whether something is a PEAR_Error object + * + * @param mixed $value the item to check + * + * @return bool whether $value is a PEAR_Error object or not + * + * @access public + */ + function isError($value) + { + return is_a($value, 'PEAR_Error'); + } +} + +/** + * The methods and properties for submitting XML RPC requests + * + * @category Web Services + * @package XML_RPC + * @author Edd Dumbill + * @author Stig Bakken + * @author Martin Jansen + * @author Daniel Convissor + * @copyright 1999-2001 Edd Dumbill, 2001-2006 The PHP Group + * @version Release: 1.5.1 + * @link http://pear.php.net/package/XML_RPC + */ +class XML_RPC_Client extends XML_RPC_Base { + + /** + * The path and name of the RPC server script you want the request to go to + * @var string + */ + var $path = ''; + + /** + * The name of the remote server to connect to + * @var string + */ + var $server = ''; + + /** + * The protocol to use in contacting the remote server + * @var string + */ + var $protocol = 'http://'; + + /** + * The port for connecting to the remote server + * + * The default is 80 for http:// connections + * and 443 for https:// and ssl:// connections. + * + * @var integer + */ + var $port = 80; + + /** + * A user name for accessing the RPC server + * @var string + * @see XML_RPC_Client::setCredentials() + */ + var $username = ''; + + /** + * A password for accessing the RPC server + * @var string + * @see XML_RPC_Client::setCredentials() + */ + var $password = ''; + + /** + * The name of the proxy server to use, if any + * @var string + */ + var $proxy = ''; + + /** + * The protocol to use in contacting the proxy server, if any + * @var string + */ + var $proxy_protocol = 'http://'; + + /** + * The port for connecting to the proxy server + * + * The default is 8080 for http:// connections + * and 443 for https:// and ssl:// connections. + * + * @var integer + */ + var $proxy_port = 8080; + + /** + * A user name for accessing the proxy server + * @var string + */ + var $proxy_user = ''; + + /** + * A password for accessing the proxy server + * @var string + */ + var $proxy_pass = ''; + + /** + * The error number, if any + * @var integer + */ + var $errno = 0; + + /** + * The error message, if any + * @var string + */ + var $errstr = ''; + + /** + * The current debug mode (1 = on, 0 = off) + * @var integer + */ + var $debug = 0; + + /** + * The HTTP headers for the current request. + * @var string + */ + var $headers = ''; + + + /** + * Sets the object's properties + * + * @param string $path the path and name of the RPC server script + * you want the request to go to + * @param string $server the URL of the remote server to connect to. + * If this parameter doesn't specify a + * protocol and $port is 443, ssl:// is + * assumed. + * @param integer $port a port for connecting to the remote server. + * Defaults to 80 for http:// connections and + * 443 for https:// and ssl:// connections. + * @param string $proxy the URL of the proxy server to use, if any. + * If this parameter doesn't specify a + * protocol and $port is 443, ssl:// is + * assumed. + * @param integer $proxy_port a port for connecting to the remote server. + * Defaults to 8080 for http:// connections and + * 443 for https:// and ssl:// connections. + * @param string $proxy_user a user name for accessing the proxy server + * @param string $proxy_pass a password for accessing the proxy server + * + * @return void + */ + function XML_RPC_Client($path, $server, $port = 0, + $proxy = '', $proxy_port = 0, + $proxy_user = '', $proxy_pass = '') + { + $this->path = $path; + $this->proxy_user = $proxy_user; + $this->proxy_pass = $proxy_pass; + + $GLOBALS['XML_RPC_func_ereg']('^(http://|https://|ssl://)?(.*)$', $server, $match); + if ($match[1] == '') { + if ($port == 443) { + $this->server = $match[2]; + $this->protocol = 'ssl://'; + $this->port = 443; + } else { + $this->server = $match[2]; + if ($port) { + $this->port = $port; + } + } + } elseif ($match[1] == 'http://') { + $this->server = $match[2]; + if ($port) { + $this->port = $port; + } + } else { + $this->server = $match[2]; + $this->protocol = 'ssl://'; + if ($port) { + $this->port = $port; + } else { + $this->port = 443; + } + } + + if ($proxy) { + $GLOBALS['XML_RPC_func_ereg']('^(http://|https://|ssl://)?(.*)$', $proxy, $match); + if ($match[1] == '') { + if ($proxy_port == 443) { + $this->proxy = $match[2]; + $this->proxy_protocol = 'ssl://'; + $this->proxy_port = 443; + } else { + $this->proxy = $match[2]; + if ($proxy_port) { + $this->proxy_port = $proxy_port; + } + } + } elseif ($match[1] == 'http://') { + $this->proxy = $match[2]; + if ($proxy_port) { + $this->proxy_port = $proxy_port; + } + } else { + $this->proxy = $match[2]; + $this->proxy_protocol = 'ssl://'; + if ($proxy_port) { + $this->proxy_port = $proxy_port; + } else { + $this->proxy_port = 443; + } + } + } + } + + /** + * Change the current debug mode + * + * @param int $in where 1 = on, 0 = off + * + * @return void + */ + function setDebug($in) + { + if ($in) { + $this->debug = 1; + } else { + $this->debug = 0; + } + } + + /** + * Sets whether strings that contain characters which may cause PHP's + * SAX-based XML parser to break should be automatically base64 encoded + * + * This is is a workaround for systems that don't have PHP's mbstring + * extension available. + * + * @param int $in where 1 = on, 0 = off + * + * @return void + */ + function setAutoBase64($in) + { + if ($in) { + $GLOBALS['XML_RPC_auto_base64'] = true; + } else { + $GLOBALS['XML_RPC_auto_base64'] = false; + } + } + + /** + * Set username and password properties for connecting to the RPC server + * + * @param string $u the user name + * @param string $p the password + * + * @return void + * + * @see XML_RPC_Client::$username, XML_RPC_Client::$password + */ + function setCredentials($u, $p) + { + $this->username = $u; + $this->password = $p; + } + + /** + * Transmit the RPC request via HTTP 1.0 protocol + * + * @param object $msg the XML_RPC_Message object + * @param int $timeout how many seconds to wait for the request + * + * @return object an XML_RPC_Response object. 0 is returned if any + * problems happen. + * + * @see XML_RPC_Message, XML_RPC_Client::XML_RPC_Client(), + * XML_RPC_Client::setCredentials() + */ + function send($msg, $timeout = 0) + { + if (!is_a($msg, 'XML_RPC_Message')) { + $this->errstr = 'send()\'s $msg parameter must be an' + . ' XML_RPC_Message object.'; + $this->raiseError($this->errstr, XML_RPC_ERROR_PROGRAMMING); + return 0; + } + $msg->debug = $this->debug; + return $this->sendPayloadHTTP10($msg, $this->server, $this->port, + $timeout, $this->username, + $this->password); + } + + /** + * Transmit the RPC request via HTTP 1.0 protocol + * + * Requests should be sent using XML_RPC_Client send() rather than + * calling this method directly. + * + * @param object $msg the XML_RPC_Message object + * @param string $server the server to send the request to + * @param int $port the server port send the request to + * @param int $timeout how many seconds to wait for the request + * before giving up + * @param string $username a user name for accessing the RPC server + * @param string $password a password for accessing the RPC server + * + * @return object an XML_RPC_Response object. 0 is returned if any + * problems happen. + * + * @access protected + * @see XML_RPC_Client::send() + */ + function sendPayloadHTTP10($msg, $server, $port, $timeout = 0, + $username = '', $password = '') + { + /* + * If we're using a proxy open a socket to the proxy server + * instead to the xml-rpc server + */ + if ($this->proxy) { + if ($this->proxy_protocol == 'http://') { + $protocol = ''; + } else { + $protocol = $this->proxy_protocol; + } + if ($timeout > 0) { + $fp = @fsockopen($protocol . $this->proxy, $this->proxy_port, + $this->errno, $this->errstr, $timeout); + } else { + $fp = @fsockopen($protocol . $this->proxy, $this->proxy_port, + $this->errno, $this->errstr); + } + } else { + if ($this->protocol == 'http://') { + $protocol = ''; + } else { + $protocol = $this->protocol; + } + if ($timeout > 0) { + $fp = @fsockopen($protocol . $server, $port, + $this->errno, $this->errstr, $timeout); + } else { + $fp = @fsockopen($protocol . $server, $port, + $this->errno, $this->errstr); + } + } + + /* + * Just raising the error without returning it is strange, + * but keep it here for backwards compatibility. + */ + if (!$fp && $this->proxy) { + $this->raiseError('Connection to proxy server ' + . $this->proxy . ':' . $this->proxy_port + . ' failed. ' . $this->errstr, + XML_RPC_ERROR_CONNECTION_FAILED); + return 0; + } elseif (!$fp) { + $this->raiseError('Connection to RPC server ' + . $server . ':' . $port + . ' failed. ' . $this->errstr, + XML_RPC_ERROR_CONNECTION_FAILED); + return 0; + } + + if ($timeout) { + /* + * Using socket_set_timeout() because stream_set_timeout() + * was introduced in 4.3.0, but we need to support 4.2.0. + */ + socket_set_timeout($fp, $timeout); + } + + // Pre-emptive BC hacks for fools calling sendPayloadHTTP10() directly + if ($username != $this->username) { + $this->setCredentials($username, $password); + } + + // Only create the payload if it was not created previously + if (empty($msg->payload)) { + $msg->createPayload(); + } + $this->createHeaders($msg); + + $op = $this->headers . "\r\n\r\n"; + $op .= $msg->payload; + + if (!fputs($fp, $op, strlen($op))) { + $this->errstr = 'Write error'; + return 0; + } + $resp = $msg->parseResponseFile($fp); + + $meta = socket_get_status($fp); + if ($meta['timed_out']) { + fclose($fp); + $this->errstr = 'RPC server did not send response before timeout.'; + $this->raiseError($this->errstr, XML_RPC_ERROR_CONNECTION_FAILED); + return 0; + } + + fclose($fp); + return $resp; + } + + /** + * Determines the HTTP headers and puts it in the $headers property + * + * @param object $msg the XML_RPC_Message object + * + * @return boolean TRUE if okay, FALSE if the message payload isn't set. + * + * @access protected + */ + function createHeaders($msg) + { + if (empty($msg->payload)) { + return false; + } + if ($this->proxy) { + $this->headers = 'POST ' . $this->protocol . $this->server; + if ($this->proxy_port) { + $this->headers .= ':' . $this->port; + } + } else { + $this->headers = 'POST '; + } + $this->headers .= $this->path. " HTTP/1.0\r\n"; + + $this->headers .= "User-Agent: PEAR XML_RPC\r\n"; + $this->headers .= 'Host: ' . $this->server . "\r\n"; + + if ($this->proxy && $this->proxy_user) { + $this->headers .= 'Proxy-Authorization: Basic ' + . base64_encode("$this->proxy_user:$this->proxy_pass") + . "\r\n"; + } + + // thanks to Grant Rauscher for this + if ($this->username) { + $this->headers .= 'Authorization: Basic ' + . base64_encode("$this->username:$this->password") + . "\r\n"; + } + + $this->headers .= "Content-Type: text/xml\r\n"; + $this->headers .= 'Content-Length: ' . strlen($msg->payload); + return true; + } +} + +/** + * The methods and properties for interpreting responses to XML RPC requests + * + * @category Web Services + * @package XML_RPC + * @author Edd Dumbill + * @author Stig Bakken + * @author Martin Jansen + * @author Daniel Convissor + * @copyright 1999-2001 Edd Dumbill, 2001-2006 The PHP Group + * @version Release: 1.5.1 + * @link http://pear.php.net/package/XML_RPC + */ +class XML_RPC_Response extends XML_RPC_Base +{ + var $xv; + var $fn; + var $fs; + var $hdrs; + + /** + * @return void + */ + function XML_RPC_Response($val, $fcode = 0, $fstr = '') + { + if ($fcode != 0) { + $this->fn = $fcode; + $this->fs = htmlspecialchars($fstr); + } else { + $this->xv = $val; + } + } + + /** + * @return int the error code + */ + function faultCode() + { + if (isset($this->fn)) { + return $this->fn; + } else { + return 0; + } + } + + /** + * @return string the error string + */ + function faultString() + { + return $this->fs; + } + + /** + * @return mixed the value + */ + function value() + { + return $this->xv; + } + + /** + * @return string the error message in XML format + */ + function serialize() + { + $rs = "\n"; + if ($this->fn) { + $rs .= " + + + + faultCode + " . $this->fn . " + + + faultString + " . $this->fs . " + + + +"; + } else { + $rs .= "\n\n" . $this->xv->serialize() . + "\n"; + } + $rs .= "\n"; + return $rs; + } +} + +/** + * The methods and properties for composing XML RPC messages + * + * @category Web Services + * @package XML_RPC + * @author Edd Dumbill + * @author Stig Bakken + * @author Martin Jansen + * @author Daniel Convissor + * @copyright 1999-2001 Edd Dumbill, 2001-2006 The PHP Group + * @version Release: 1.5.1 + * @link http://pear.php.net/package/XML_RPC + */ +class XML_RPC_Message extends XML_RPC_Base +{ + /** + * Should the payload's content be passed through mb_convert_encoding()? + * + * @see XML_RPC_Message::setConvertPayloadEncoding() + * @since Property available since Release 1.5.1 + * @var boolean + */ + var $convert_payload_encoding = false; + + /** + * The current debug mode (1 = on, 0 = off) + * @var integer + */ + var $debug = 0; + + /** + * The encoding to be used for outgoing messages + * + * Defaults to the value of $GLOBALS['XML_RPC_defencoding'] + * + * @var string + * @see XML_RPC_Message::setSendEncoding(), + * $GLOBALS['XML_RPC_defencoding'], XML_RPC_Message::xml_header() + */ + var $send_encoding = ''; + + /** + * The method presently being evaluated + * @var string + */ + var $methodname = ''; + + /** + * @var array + */ + var $params = array(); + + /** + * The XML message being generated + * @var string + */ + var $payload = ''; + + /** + * Should extra line breaks be removed from the payload? + * @since Property available since Release 1.4.6 + * @var boolean + */ + var $remove_extra_lines = true; + + /** + * The XML response from the remote server + * @since Property available since Release 1.4.6 + * @var string + */ + var $response_payload = ''; + + + /** + * @return void + */ + function XML_RPC_Message($meth, $pars = 0) + { + $this->methodname = $meth; + if (is_array($pars) && sizeof($pars) > 0) { + for ($i = 0; $i < sizeof($pars); $i++) { + $this->addParam($pars[$i]); + } + } + } + + /** + * Produces the XML declaration including the encoding attribute + * + * The encoding is determined by this class' $send_encoding + * property. If the $send_encoding property is not set, use + * $GLOBALS['XML_RPC_defencoding']. + * + * @return string the XML declaration and element + * + * @see XML_RPC_Message::setSendEncoding(), + * XML_RPC_Message::$send_encoding, $GLOBALS['XML_RPC_defencoding'] + */ + function xml_header() + { + global $XML_RPC_defencoding; + + if (!$this->send_encoding) { + $this->send_encoding = $XML_RPC_defencoding; + } + return 'send_encoding . '"?>' + . "\n\n"; + } + + /** + * @return string the closing tag + */ + function xml_footer() + { + return "\n"; + } + + /** + * Fills the XML_RPC_Message::$payload property + * + * Part of the process makes sure all line endings are in DOS format + * (CRLF), which is probably required by specifications. + * + * If XML_RPC_Message::setConvertPayloadEncoding() was set to true, + * the payload gets passed through mb_convert_encoding() + * to ensure the payload matches the encoding set in the + * XML declaration. The encoding type can be manually set via + * XML_RPC_Message::setSendEncoding(). + * + * @return void + * + * @uses XML_RPC_Message::xml_header(), XML_RPC_Message::xml_footer() + * @see XML_RPC_Message::setSendEncoding(), $GLOBALS['XML_RPC_defencoding'], + * XML_RPC_Message::setConvertPayloadEncoding() + */ + function createPayload() + { + $this->payload = $this->xml_header(); + $this->payload .= '' . $this->methodname . "\n"; + $this->payload .= "\n"; + for ($i = 0; $i < sizeof($this->params); $i++) { + $p = $this->params[$i]; + $this->payload .= "\n" . $p->serialize() . "\n"; + } + $this->payload .= "\n"; + $this->payload .= $this->xml_footer(); + if ($this->remove_extra_lines) { + $this->payload = $GLOBALS['XML_RPC_func_ereg_replace']("[\r\n]+", "\r\n", $this->payload); + } else { + $this->payload = $GLOBALS['XML_RPC_func_ereg_replace']("\r\n|\n|\r|\n\r", "\r\n", $this->payload); + } + if ($this->convert_payload_encoding) { + $this->payload = mb_convert_encoding($this->payload, $this->send_encoding); + } + } + + /** + * @return string the name of the method + */ + function method($meth = '') + { + if ($meth != '') { + $this->methodname = $meth; + } + return $this->methodname; + } + + /** + * @return string the payload + */ + function serialize() + { + $this->createPayload(); + return $this->payload; + } + + /** + * @return void + */ + function addParam($par) + { + $this->params[] = $par; + } + + /** + * Obtains an XML_RPC_Value object for the given parameter + * + * @param int $i the index number of the parameter to obtain + * + * @return object the XML_RPC_Value object. + * If the parameter doesn't exist, an XML_RPC_Response object. + * + * @since Returns XML_RPC_Response object on error since Release 1.3.0 + */ + function getParam($i) + { + global $XML_RPC_err, $XML_RPC_str; + + if (isset($this->params[$i])) { + return $this->params[$i]; + } else { + $this->raiseError('The submitted request did not contain this parameter', + XML_RPC_ERROR_INCORRECT_PARAMS); + return new XML_RPC_Response(0, $XML_RPC_err['incorrect_params'], + $XML_RPC_str['incorrect_params']); + } + } + + /** + * @return int the number of parameters + */ + function getNumParams() + { + return sizeof($this->params); + } + + /** + * Sets whether the payload's content gets passed through + * mb_convert_encoding() + * + * Returns PEAR_ERROR object if mb_convert_encoding() isn't available. + * + * @param int $in where 1 = on, 0 = off + * + * @return void + * + * @see XML_RPC_Message::setSendEncoding() + * @since Method available since Release 1.5.1 + */ + function setConvertPayloadEncoding($in) + { + if ($in && !function_exists('mb_convert_encoding')) { + return $this->raiseError('mb_convert_encoding() is not available', + XML_RPC_ERROR_PROGRAMMING); + } + $this->convert_payload_encoding = $in; + } + + /** + * Sets the XML declaration's encoding attribute + * + * @param string $type the encoding type (ISO-8859-1, UTF-8 or US-ASCII) + * + * @return void + * + * @see XML_RPC_Message::setConvertPayloadEncoding(), XML_RPC_Message::xml_header() + * @since Method available since Release 1.2.0 + */ + function setSendEncoding($type) + { + $this->send_encoding = $type; + } + + /** + * Determine the XML's encoding via the encoding attribute + * in the XML declaration + * + * If the encoding parameter is not set or is not ISO-8859-1, UTF-8 + * or US-ASCII, $XML_RPC_defencoding will be returned. + * + * @param string $data the XML that will be parsed + * + * @return string the encoding to be used + * + * @link http://php.net/xml_parser_create + * @since Method available since Release 1.2.0 + */ + function getEncoding($data) + { + global $XML_RPC_defencoding; + + if ($GLOBALS['XML_RPC_func_ereg']('<\?xml[^>]*[:space:]*encoding[:space:]*=[:space:]*[\'"]([^"\']*)[\'"]', + $data, $match)) + { + $match[1] = trim(strtoupper($match[1])); + switch ($match[1]) { + case 'ISO-8859-1': + case 'UTF-8': + case 'US-ASCII': + return $match[1]; + break; + + default: + return $XML_RPC_defencoding; + } + } else { + return $XML_RPC_defencoding; + } + } + + /** + * @return object a new XML_RPC_Response object + */ + function parseResponseFile($fp) + { + $ipd = ''; + while ($data = @fread($fp, 8192)) { + $ipd .= $data; + } + return $this->parseResponse($ipd); + } + + /** + * @return object a new XML_RPC_Response object + */ + function parseResponse($data = '') + { + global $XML_RPC_xh, $XML_RPC_err, $XML_RPC_str, $XML_RPC_defencoding; + + $encoding = $this->getEncoding($data); + $parser_resource = xml_parser_create($encoding); + $parser = (int) $parser_resource; + + $XML_RPC_xh = array(); + $XML_RPC_xh[$parser] = array(); + + $XML_RPC_xh[$parser]['cm'] = 0; + $XML_RPC_xh[$parser]['isf'] = 0; + $XML_RPC_xh[$parser]['ac'] = ''; + $XML_RPC_xh[$parser]['qt'] = ''; + $XML_RPC_xh[$parser]['stack'] = array(); + $XML_RPC_xh[$parser]['valuestack'] = array(); + + xml_parser_set_option($parser_resource, XML_OPTION_CASE_FOLDING, true); + xml_set_element_handler($parser_resource, 'XML_RPC_se', 'XML_RPC_ee'); + xml_set_character_data_handler($parser_resource, 'XML_RPC_cd'); + + $hdrfnd = 0; + if ($this->debug) { + print "\n
    ---GOT---\n";
    +            print isset($_SERVER['SERVER_PROTOCOL']) ? htmlspecialchars($data) : $data;
    +            print "\n---END---
    \n"; + } + + // See if response is a 200 or a 100 then a 200, else raise error. + // But only do this if we're using the HTTP protocol. + if ($GLOBALS['XML_RPC_func_ereg']('^HTTP', $data) && + !$GLOBALS['XML_RPC_func_ereg']('^HTTP/[0-9\.]+ 200 ', $data) && + !$GLOBALS['XML_RPC_func_ereg']('^HTTP/[0-9\.]+ 10[0-9]([A-Z ]+)?[\r\n]+HTTP/[0-9\.]+ 200', $data)) + { + $errstr = substr($data, 0, strpos($data, "\n") - 1); + error_log('HTTP error, got response: ' . $errstr); + $r = new XML_RPC_Response(0, $XML_RPC_err['http_error'], + $XML_RPC_str['http_error'] . ' (' . + $errstr . ')'); + xml_parser_free($parser_resource); + return $r; + } + + // gotta get rid of headers here + if (!$hdrfnd && ($brpos = strpos($data,"\r\n\r\n"))) { + $XML_RPC_xh[$parser]['ha'] = substr($data, 0, $brpos); + $data = substr($data, $brpos + 4); + $hdrfnd = 1; + } + + /* + * be tolerant of junk after methodResponse + * (e.g. javascript automatically inserted by free hosts) + * thanks to Luca Mariano + */ + $data = substr($data, 0, strpos($data, "") + 17); + $this->response_payload = $data; + + if (!xml_parse($parser_resource, $data, sizeof($data))) { + // thanks to Peter Kocks + if (xml_get_current_line_number($parser_resource) == 1) { + $errstr = 'XML error at line 1, check URL'; + } else { + $errstr = sprintf('XML error: %s at line %d', + xml_error_string(xml_get_error_code($parser_resource)), + xml_get_current_line_number($parser_resource)); + } + error_log($errstr); + $r = new XML_RPC_Response(0, $XML_RPC_err['invalid_return'], + $XML_RPC_str['invalid_return']); + xml_parser_free($parser_resource); + return $r; + } + + xml_parser_free($parser_resource); + + if ($this->debug) { + print "\n
    ---PARSED---\n";
    +            var_dump($XML_RPC_xh[$parser]['value']);
    +            print "---END---
    \n"; + } + + if ($XML_RPC_xh[$parser]['isf'] > 1) { + $r = new XML_RPC_Response(0, $XML_RPC_err['invalid_return'], + $XML_RPC_str['invalid_return'].' '.$XML_RPC_xh[$parser]['isf_reason']); + } elseif (!is_object($XML_RPC_xh[$parser]['value'])) { + // then something odd has happened + // and it's time to generate a client side error + // indicating something odd went on + $r = new XML_RPC_Response(0, $XML_RPC_err['invalid_return'], + $XML_RPC_str['invalid_return']); + } else { + $v = $XML_RPC_xh[$parser]['value']; + if ($XML_RPC_xh[$parser]['isf']) { + $f = $v->structmem('faultCode'); + $fs = $v->structmem('faultString'); + $r = new XML_RPC_Response($v, $f->scalarval(), + $fs->scalarval()); + } else { + $r = new XML_RPC_Response($v); + } + } + $r->hdrs = split("\r?\n", $XML_RPC_xh[$parser]['ha'][1]); + return $r; + } +} + +/** + * The methods and properties that represent data in XML RPC format + * + * @category Web Services + * @package XML_RPC + * @author Edd Dumbill + * @author Stig Bakken + * @author Martin Jansen + * @author Daniel Convissor + * @copyright 1999-2001 Edd Dumbill, 2001-2006 The PHP Group + * @version Release: 1.5.1 + * @link http://pear.php.net/package/XML_RPC + */ +class XML_RPC_Value extends XML_RPC_Base +{ + var $me = array(); + var $mytype = 0; + + /** + * @return void + */ + function XML_RPC_Value($val = -1, $type = '') + { + $this->me = array(); + $this->mytype = 0; + if ($val != -1 || $type != '') { + if ($type == '') { + $type = 'string'; + } + if (!array_key_exists($type, $GLOBALS['XML_RPC_Types'])) { + // XXX + // need some way to report this error + } elseif ($GLOBALS['XML_RPC_Types'][$type] == 1) { + $this->addScalar($val, $type); + } elseif ($GLOBALS['XML_RPC_Types'][$type] == 2) { + $this->addArray($val); + } elseif ($GLOBALS['XML_RPC_Types'][$type] == 3) { + $this->addStruct($val); + } + } + } + + /** + * @return int returns 1 if successful or 0 if there are problems + */ + function addScalar($val, $type = 'string') + { + if ($this->mytype == 1) { + $this->raiseError('Scalar can have only one value', + XML_RPC_ERROR_INVALID_TYPE); + return 0; + } + $typeof = $GLOBALS['XML_RPC_Types'][$type]; + if ($typeof != 1) { + $this->raiseError("Not a scalar type (${typeof})", + XML_RPC_ERROR_INVALID_TYPE); + return 0; + } + + if ($type == $GLOBALS['XML_RPC_Boolean']) { + if (strcasecmp($val, 'true') == 0 + || $val == 1 + || ($val == true && strcasecmp($val, 'false'))) + { + $val = 1; + } else { + $val = 0; + } + } + + if ($this->mytype == 2) { + // we're adding to an array here + $ar = $this->me['array']; + $ar[] = new XML_RPC_Value($val, $type); + $this->me['array'] = $ar; + } else { + // a scalar, so set the value and remember we're scalar + $this->me[$type] = $val; + $this->mytype = $typeof; + } + return 1; + } + + /** + * @return int returns 1 if successful or 0 if there are problems + */ + function addArray($vals) + { + if ($this->mytype != 0) { + $this->raiseError( + 'Already initialized as a [' . $this->kindOf() . ']', + XML_RPC_ERROR_ALREADY_INITIALIZED); + return 0; + } + $this->mytype = $GLOBALS['XML_RPC_Types']['array']; + $this->me['array'] = $vals; + return 1; + } + + /** + * @return int returns 1 if successful or 0 if there are problems + */ + function addStruct($vals) + { + if ($this->mytype != 0) { + $this->raiseError( + 'Already initialized as a [' . $this->kindOf() . ']', + XML_RPC_ERROR_ALREADY_INITIALIZED); + return 0; + } + $this->mytype = $GLOBALS['XML_RPC_Types']['struct']; + $this->me['struct'] = $vals; + return 1; + } + + /** + * @return void + */ + function dump($ar) + { + reset($ar); + foreach ($ar as $key => $val) { + echo "$key => $val
    "; + if ($key == 'array') { + foreach ($val as $key2 => $val2) { + echo "-- $key2 => $val2
    "; + } + } + } + } + + /** + * @return string the data type of the current value + */ + function kindOf() + { + switch ($this->mytype) { + case 3: + return 'struct'; + + case 2: + return 'array'; + + case 1: + return 'scalar'; + + default: + return 'undef'; + } + } + + /** + * @return string the data in XML format + */ + function serializedata($typ, $val) + { + $rs = ''; + if (!array_key_exists($typ, $GLOBALS['XML_RPC_Types'])) { + // XXX + // need some way to report this error + return; + } + switch ($GLOBALS['XML_RPC_Types'][$typ]) { + case 3: + // struct + $rs .= "\n"; + reset($val); + foreach ($val as $key2 => $val2) { + $rs .= "${key2}\n"; + $rs .= $this->serializeval($val2); + $rs .= "\n"; + } + $rs .= ''; + break; + + case 2: + // array + $rs .= "\n\n"; + for ($i = 0; $i < sizeof($val); $i++) { + $rs .= $this->serializeval($val[$i]); + } + $rs .= "\n"; + break; + + case 1: + switch ($typ) { + case $GLOBALS['XML_RPC_Base64']: + $rs .= "<${typ}>" . base64_encode($val) . ""; + break; + case $GLOBALS['XML_RPC_Boolean']: + $rs .= "<${typ}>" . ($val ? '1' : '0') . ""; + break; + case $GLOBALS['XML_RPC_String']: + $rs .= "<${typ}>" . htmlspecialchars($val). ""; + break; + default: + $rs .= "<${typ}>${val}"; + } + } + return $rs; + } + + /** + * @return string the data in XML format + */ + function serialize() + { + return $this->serializeval($this); + } + + /** + * @return string the data in XML format + */ + function serializeval($o) + { + if (!is_object($o) || empty($o->me) || !is_array($o->me)) { + return ''; + } + $ar = $o->me; + reset($ar); + list($typ, $val) = each($ar); + return '' . $this->serializedata($typ, $val) . "\n"; + } + + /** + * @return mixed the contents of the element requested + */ + function structmem($m) + { + return $this->me['struct'][$m]; + } + + /** + * @return void + */ + function structreset() + { + reset($this->me['struct']); + } + + /** + * @return the key/value pair of the struct's current element + */ + function structeach() + { + return each($this->me['struct']); + } + + /** + * @return mixed the current value + */ + function getval() + { + // UNSTABLE + + reset($this->me); + $b = current($this->me); + + // contributed by I Sofer, 2001-03-24 + // add support for nested arrays to scalarval + // i've created a new method here, so as to + // preserve back compatibility + + if (is_array($b)) { + foreach ($b as $id => $cont) { + $b[$id] = $cont->scalarval(); + } + } + + // add support for structures directly encoding php objects + if (is_object($b)) { + $t = get_object_vars($b); + foreach ($t as $id => $cont) { + $t[$id] = $cont->scalarval(); + } + foreach ($t as $id => $cont) { + $b->$id = $cont; + } + } + + // end contrib + return $b; + } + + /** + * @return mixed the current element's scalar value. If the value is + * not scalar, FALSE is returned. + */ + function scalarval() + { + reset($this->me); + $v = current($this->me); + if (!is_scalar($v)) { + $v = false; + } + return $v; + } + + /** + * @return string + */ + function scalartyp() + { + reset($this->me); + $a = key($this->me); + if ($a == $GLOBALS['XML_RPC_I4']) { + $a = $GLOBALS['XML_RPC_Int']; + } + return $a; + } + + /** + * @return mixed the struct's current element + */ + function arraymem($m) + { + return $this->me['array'][$m]; + } + + /** + * @return int the number of elements in the array + */ + function arraysize() + { + reset($this->me); + list($a, $b) = each($this->me); + return sizeof($b); + } + + /** + * Determines if the item submitted is an XML_RPC_Value object + * + * @param mixed $val the variable to be evaluated + * + * @return bool TRUE if the item is an XML_RPC_Value object + * + * @static + * @since Method available since Release 1.3.0 + */ + function isValue($val) + { + return (strtolower(get_class($val)) == 'xml_rpc_value'); + } +} + +/** + * Return an ISO8601 encoded string + * + * While timezones ought to be supported, the XML-RPC spec says: + * + * "Don't assume a timezone. It should be specified by the server in its + * documentation what assumptions it makes about timezones." + * + * This routine always assumes localtime unless $utc is set to 1, in which + * case UTC is assumed and an adjustment for locale is made when encoding. + * + * @return string the formatted date + */ +function XML_RPC_iso8601_encode($timet, $utc = 0) +{ + if (!$utc) { + $t = strftime('%Y%m%dT%H:%M:%S', $timet); + } else { + if (function_exists('gmstrftime')) { + // gmstrftime doesn't exist in some versions + // of PHP + $t = gmstrftime('%Y%m%dT%H:%M:%S', $timet); + } else { + $t = strftime('%Y%m%dT%H:%M:%S', $timet - date('Z')); + } + } + return $t; +} + +/** + * Convert a datetime string into a Unix timestamp + * + * While timezones ought to be supported, the XML-RPC spec says: + * + * "Don't assume a timezone. It should be specified by the server in its + * documentation what assumptions it makes about timezones." + * + * This routine always assumes localtime unless $utc is set to 1, in which + * case UTC is assumed and an adjustment for locale is made when encoding. + * + * @return int the unix timestamp of the date submitted + */ +function XML_RPC_iso8601_decode($idate, $utc = 0) +{ + $t = 0; + if ($GLOBALS['XML_RPC_func_ereg']('([0-9]{4})([0-9]{2})([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})', $idate, $regs)) { + if ($utc) { + $t = gmmktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]); + } else { + $t = mktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]); + } + } + return $t; +} + +/** + * Converts an XML_RPC_Value object into native PHP types + * + * @param object $XML_RPC_val the XML_RPC_Value object to decode + * + * @return mixed the PHP values + */ +function XML_RPC_decode($XML_RPC_val) +{ + $kind = $XML_RPC_val->kindOf(); + + if ($kind == 'scalar') { + return $XML_RPC_val->scalarval(); + + } elseif ($kind == 'array') { + $size = $XML_RPC_val->arraysize(); + $arr = array(); + for ($i = 0; $i < $size; $i++) { + $arr[] = XML_RPC_decode($XML_RPC_val->arraymem($i)); + } + return $arr; + + } elseif ($kind == 'struct') { + $XML_RPC_val->structreset(); + $arr = array(); + while (list($key, $value) = $XML_RPC_val->structeach()) { + $arr[$key] = XML_RPC_decode($value); + } + return $arr; + } +} + +/** + * Converts native PHP types into an XML_RPC_Value object + * + * @param mixed $php_val the PHP value or variable you want encoded + * + * @return object the XML_RPC_Value object + */ +function XML_RPC_encode($php_val) +{ + $type = gettype($php_val); + $XML_RPC_val = new XML_RPC_Value; + + switch ($type) { + case 'array': + if (empty($php_val)) { + $XML_RPC_val->addArray($php_val); + break; + } + $tmp = array_diff(array_keys($php_val), range(0, count($php_val)-1)); + if (empty($tmp)) { + $arr = array(); + foreach ($php_val as $k => $v) { + $arr[$k] = XML_RPC_encode($v); + } + $XML_RPC_val->addArray($arr); + break; + } + // fall though if it's not an enumerated array + + case 'object': + $arr = array(); + foreach ($php_val as $k => $v) { + $arr[$k] = XML_RPC_encode($v); + } + $XML_RPC_val->addStruct($arr); + break; + + case 'integer': + $XML_RPC_val->addScalar($php_val, $GLOBALS['XML_RPC_Int']); + break; + + case 'double': + $XML_RPC_val->addScalar($php_val, $GLOBALS['XML_RPC_Double']); + break; + + case 'string': + case 'NULL': + if ($GLOBALS['XML_RPC_func_ereg']('^[0-9]{8}\T{1}[0-9]{2}\:[0-9]{2}\:[0-9]{2}$', $php_val)) { + $XML_RPC_val->addScalar($php_val, $GLOBALS['XML_RPC_DateTime']); + } elseif ($GLOBALS['XML_RPC_auto_base64'] + && $GLOBALS['XML_RPC_func_ereg']("[^ -~\t\r\n]", $php_val)) + { + // Characters other than alpha-numeric, punctuation, SP, TAB, + // LF and CR break the XML parser, encode value via Base 64. + $XML_RPC_val->addScalar($php_val, $GLOBALS['XML_RPC_Base64']); + } else { + $XML_RPC_val->addScalar($php_val, $GLOBALS['XML_RPC_String']); + } + break; + + case 'boolean': + // Add support for encoding/decoding of booleans, since they + // are supported in PHP + // by + $XML_RPC_val->addScalar($php_val, $GLOBALS['XML_RPC_Boolean']); + break; + + case 'unknown type': + default: + $XML_RPC_val = false; + } + return $XML_RPC_val; +} + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * c-hanging-comment-ender-p: nil + * End: + */ + +?> diff --git a/src/lib/pear/temp/download/XML_RPC-1.5.1/Server.php b/src/lib/pear/temp/download/XML_RPC-1.5.1/Server.php new file mode 100644 index 0000000..ab1c55d --- /dev/null +++ b/src/lib/pear/temp/download/XML_RPC-1.5.1/Server.php @@ -0,0 +1,685 @@ + + * @author Stig Bakken + * @author Martin Jansen + * @author Daniel Convissor + * @copyright 1999-2001 Edd Dumbill, 2001-2006 The PHP Group + * @version CVS: $Id: Server.php,v 1.37 2006/10/28 16:42:34 danielc Exp $ + * @link http://pear.php.net/package/XML_RPC + */ + + +/** + * Pull in the XML_RPC class + */ +require_once 'XML/RPC.php'; + + +/** + * signature for system.listMethods: return = array, + * parameters = a string or nothing + * @global array $GLOBALS['XML_RPC_Server_listMethods_sig'] + */ +$GLOBALS['XML_RPC_Server_listMethods_sig'] = array( + array($GLOBALS['XML_RPC_Array'], + $GLOBALS['XML_RPC_String'] + ), + array($GLOBALS['XML_RPC_Array']) +); + +/** + * docstring for system.listMethods + * @global string $GLOBALS['XML_RPC_Server_listMethods_doc'] + */ +$GLOBALS['XML_RPC_Server_listMethods_doc'] = 'This method lists all the' + . ' methods that the XML-RPC server knows how to dispatch'; + +/** + * signature for system.methodSignature: return = array, + * parameters = string + * @global array $GLOBALS['XML_RPC_Server_methodSignature_sig'] + */ +$GLOBALS['XML_RPC_Server_methodSignature_sig'] = array( + array($GLOBALS['XML_RPC_Array'], + $GLOBALS['XML_RPC_String'] + ) +); + +/** + * docstring for system.methodSignature + * @global string $GLOBALS['XML_RPC_Server_methodSignature_doc'] + */ +$GLOBALS['XML_RPC_Server_methodSignature_doc'] = 'Returns an array of known' + . ' signatures (an array of arrays) for the method name passed. If' + . ' no signatures are known, returns a none-array (test for type !=' + . ' array to detect missing signature)'; + +/** + * signature for system.methodHelp: return = string, + * parameters = string + * @global array $GLOBALS['XML_RPC_Server_methodHelp_sig'] + */ +$GLOBALS['XML_RPC_Server_methodHelp_sig'] = array( + array($GLOBALS['XML_RPC_String'], + $GLOBALS['XML_RPC_String'] + ) +); + +/** + * docstring for methodHelp + * @global string $GLOBALS['XML_RPC_Server_methodHelp_doc'] + */ +$GLOBALS['XML_RPC_Server_methodHelp_doc'] = 'Returns help text if defined' + . ' for the method passed, otherwise returns an empty string'; + +/** + * dispatch map for the automatically declared XML-RPC methods. + * @global array $GLOBALS['XML_RPC_Server_dmap'] + */ +$GLOBALS['XML_RPC_Server_dmap'] = array( + 'system.listMethods' => array( + 'function' => 'XML_RPC_Server_listMethods', + 'signature' => $GLOBALS['XML_RPC_Server_listMethods_sig'], + 'docstring' => $GLOBALS['XML_RPC_Server_listMethods_doc'] + ), + 'system.methodHelp' => array( + 'function' => 'XML_RPC_Server_methodHelp', + 'signature' => $GLOBALS['XML_RPC_Server_methodHelp_sig'], + 'docstring' => $GLOBALS['XML_RPC_Server_methodHelp_doc'] + ), + 'system.methodSignature' => array( + 'function' => 'XML_RPC_Server_methodSignature', + 'signature' => $GLOBALS['XML_RPC_Server_methodSignature_sig'], + 'docstring' => $GLOBALS['XML_RPC_Server_methodSignature_doc'] + ) +); + +/** + * @global string $GLOBALS['XML_RPC_Server_debuginfo'] + */ +$GLOBALS['XML_RPC_Server_debuginfo'] = ''; + + +/** + * Lists all the methods that the XML-RPC server knows how to dispatch + * + * @return object a new XML_RPC_Response object + */ +function XML_RPC_Server_listMethods($server, $m) +{ + global $XML_RPC_err, $XML_RPC_str, $XML_RPC_Server_dmap; + + $v = new XML_RPC_Value(); + $outAr = array(); + foreach ($server->dmap as $key => $val) { + $outAr[] = new XML_RPC_Value($key, 'string'); + } + foreach ($XML_RPC_Server_dmap as $key => $val) { + $outAr[] = new XML_RPC_Value($key, 'string'); + } + $v->addArray($outAr); + return new XML_RPC_Response($v); +} + +/** + * Returns an array of known signatures (an array of arrays) + * for the given method + * + * If no signatures are known, returns a none-array + * (test for type != array to detect missing signature) + * + * @return object a new XML_RPC_Response object + */ +function XML_RPC_Server_methodSignature($server, $m) +{ + global $XML_RPC_err, $XML_RPC_str, $XML_RPC_Server_dmap; + + $methName = $m->getParam(0); + $methName = $methName->scalarval(); + if (strpos($methName, 'system.') === 0) { + $dmap = $XML_RPC_Server_dmap; + $sysCall = 1; + } else { + $dmap = $server->dmap; + $sysCall = 0; + } + // print "\n"; + if (isset($dmap[$methName])) { + if ($dmap[$methName]['signature']) { + $sigs = array(); + $thesigs = $dmap[$methName]['signature']; + for ($i = 0; $i < sizeof($thesigs); $i++) { + $cursig = array(); + $inSig = $thesigs[$i]; + for ($j = 0; $j < sizeof($inSig); $j++) { + $cursig[] = new XML_RPC_Value($inSig[$j], 'string'); + } + $sigs[] = new XML_RPC_Value($cursig, 'array'); + } + $r = new XML_RPC_Response(new XML_RPC_Value($sigs, 'array')); + } else { + $r = new XML_RPC_Response(new XML_RPC_Value('undef', 'string')); + } + } else { + $r = new XML_RPC_Response(0, $XML_RPC_err['introspect_unknown'], + $XML_RPC_str['introspect_unknown']); + } + return $r; +} + +/** + * Returns help text if defined for the method passed, otherwise returns + * an empty string + * + * @return object a new XML_RPC_Response object + */ +function XML_RPC_Server_methodHelp($server, $m) +{ + global $XML_RPC_err, $XML_RPC_str, $XML_RPC_Server_dmap; + + $methName = $m->getParam(0); + $methName = $methName->scalarval(); + if (strpos($methName, 'system.') === 0) { + $dmap = $XML_RPC_Server_dmap; + $sysCall = 1; + } else { + $dmap = $server->dmap; + $sysCall = 0; + } + + if (isset($dmap[$methName])) { + if ($dmap[$methName]['docstring']) { + $r = new XML_RPC_Response(new XML_RPC_Value($dmap[$methName]['docstring']), + 'string'); + } else { + $r = new XML_RPC_Response(new XML_RPC_Value('', 'string')); + } + } else { + $r = new XML_RPC_Response(0, $XML_RPC_err['introspect_unknown'], + $XML_RPC_str['introspect_unknown']); + } + return $r; +} + +/** + * @return void + */ +function XML_RPC_Server_debugmsg($m) +{ + global $XML_RPC_Server_debuginfo; + $XML_RPC_Server_debuginfo = $XML_RPC_Server_debuginfo . $m . "\n"; +} + + +/** + * A server for receiving and replying to XML RPC requests + * + * + * $server = new XML_RPC_Server( + * array( + * 'isan8' => + * array( + * 'function' => 'is_8', + * 'signature' => + * array( + * array('boolean', 'int'), + * array('boolean', 'int', 'boolean'), + * array('boolean', 'string'), + * array('boolean', 'string', 'boolean'), + * ), + * 'docstring' => 'Is the value an 8?' + * ), + * ), + * 1, + * 0 + * ); + * + * + * @category Web Services + * @package XML_RPC + * @author Edd Dumbill + * @author Stig Bakken + * @author Martin Jansen + * @author Daniel Convissor + * @copyright 1999-2001 Edd Dumbill, 2001-2006 The PHP Group + * @version Release: 1.5.1 + * @link http://pear.php.net/package/XML_RPC + */ +class XML_RPC_Server +{ + /** + * Should the payload's content be passed through mb_convert_encoding()? + * + * @see XML_RPC_Server::setConvertPayloadEncoding() + * @since Property available since Release 1.5.1 + * @var boolean + */ + var $convert_payload_encoding = false; + + /** + * The dispatch map, listing the methods this server provides. + * @var array + */ + var $dmap = array(); + + /** + * The present response's encoding + * @var string + * @see XML_RPC_Message::getEncoding() + */ + var $encoding = ''; + + /** + * Debug mode (0 = off, 1 = on) + * @var integer + */ + var $debug = 0; + + /** + * The response's HTTP headers + * @var string + */ + var $server_headers = ''; + + /** + * The response's XML payload + * @var string + */ + var $server_payload = ''; + + + /** + * Constructor for the XML_RPC_Server class + * + * @param array $dispMap the dispatch map. An associative array + * explaining each function. The keys of the main + * array are the procedure names used by the + * clients. The value is another associative array + * that contains up to three elements: + * + The 'function' element's value is the name + * of the function or method that gets called. + * To define a class' method: 'class::method'. + * + The 'signature' element (optional) is an + * array describing the return values and + * parameters + * + The 'docstring' element (optional) is a + * string describing what the method does + * @param int $serviceNow should the HTTP response be sent now? + * (1 = yes, 0 = no) + * @param int $debug should debug output be displayed? + * (1 = yes, 0 = no) + * + * @return void + */ + function XML_RPC_Server($dispMap, $serviceNow = 1, $debug = 0) + { + global $HTTP_RAW_POST_DATA; + + if ($debug) { + $this->debug = 1; + } else { + $this->debug = 0; + } + + $this->dmap = $dispMap; + + if ($serviceNow) { + $this->service(); + } else { + $this->createServerPayload(); + $this->createServerHeaders(); + } + } + + /** + * @return string the debug information if debug debug mode is on + */ + function serializeDebug() + { + global $XML_RPC_Server_debuginfo, $HTTP_RAW_POST_DATA; + + if ($this->debug) { + XML_RPC_Server_debugmsg('vvv POST DATA RECEIVED BY SERVER vvv' . "\n" + . $HTTP_RAW_POST_DATA + . "\n" . '^^^ END POST DATA ^^^'); + } + + if ($XML_RPC_Server_debuginfo != '') { + return "\n"; + } else { + return ''; + } + } + + /** + * Sets whether the payload's content gets passed through + * mb_convert_encoding() + * + * Returns PEAR_ERROR object if mb_convert_encoding() isn't available. + * + * @param int $in where 1 = on, 0 = off + * + * @return void + * + * @see XML_RPC_Message::getEncoding() + * @since Method available since Release 1.5.1 + */ + function setConvertPayloadEncoding($in) + { + if ($in && !function_exists('mb_convert_encoding')) { + return $this->raiseError('mb_convert_encoding() is not available', + XML_RPC_ERROR_PROGRAMMING); + } + $this->convert_payload_encoding = $in; + } + + /** + * Sends the response + * + * The encoding and content-type are determined by + * XML_RPC_Message::getEncoding() + * + * @return void + * + * @uses XML_RPC_Server::createServerPayload(), + * XML_RPC_Server::createServerHeaders() + */ + function service() + { + if (!$this->server_payload) { + $this->createServerPayload(); + } + if (!$this->server_headers) { + $this->createServerHeaders(); + } + + /* + * $server_headers needs to remain a string for compatibility with + * old scripts using this package, but PHP 4.4.2 no longer allows + * line breaks in header() calls. So, we split each header into + * an individual call. The initial replace handles the off chance + * that someone composed a single header with multiple lines, which + * the RFCs allow. + */ + $this->server_headers = $GLOBALS['XML_RPC_func_ereg_replace']("[\r\n]+[ \t]+", + ' ', trim($this->server_headers)); + $headers = $GLOBALS['XML_RPC_func_split']("[\r\n]+", $this->server_headers); + foreach ($headers as $header) + { + header($header); + } + + print $this->server_payload; + } + + /** + * Generates the payload and puts it in the $server_payload property + * + * If XML_RPC_Server::setConvertPayloadEncoding() was set to true, + * the payload gets passed through mb_convert_encoding() + * to ensure the payload matches the encoding set in the + * XML declaration. The encoding type can be manually set via + * XML_RPC_Message::setSendEncoding(). + * + * @return void + * + * @uses XML_RPC_Server::parseRequest(), XML_RPC_Server::$encoding, + * XML_RPC_Response::serialize(), XML_RPC_Server::serializeDebug() + * @see XML_RPC_Server::setConvertPayloadEncoding() + */ + function createServerPayload() + { + $r = $this->parseRequest(); + $this->server_payload = 'encoding . '"?>' . "\n" + . $this->serializeDebug() + . $r->serialize(); + if ($this->convert_payload_encoding) { + $this->server_payload = mb_convert_encoding($this->server_payload, + $this->encoding); + } + } + + /** + * Determines the HTTP headers and puts them in the $server_headers + * property + * + * @return boolean TRUE if okay, FALSE if $server_payload isn't set. + * + * @uses XML_RPC_Server::createServerPayload(), + * XML_RPC_Server::$server_headers + */ + function createServerHeaders() + { + if (!$this->server_payload) { + return false; + } + $this->server_headers = 'Content-Length: ' + . strlen($this->server_payload) . "\r\n" + . 'Content-Type: text/xml;' + . ' charset=' . $this->encoding; + return true; + } + + /** + * @return array + */ + function verifySignature($in, $sig) + { + for ($i = 0; $i < sizeof($sig); $i++) { + // check each possible signature in turn + $cursig = $sig[$i]; + if (sizeof($cursig) == $in->getNumParams() + 1) { + $itsOK = 1; + for ($n = 0; $n < $in->getNumParams(); $n++) { + $p = $in->getParam($n); + // print "\n"; + if ($p->kindOf() == 'scalar') { + $pt = $p->scalartyp(); + } else { + $pt = $p->kindOf(); + } + // $n+1 as first type of sig is return type + if ($pt != $cursig[$n+1]) { + $itsOK = 0; + $pno = $n+1; + $wanted = $cursig[$n+1]; + $got = $pt; + break; + } + } + if ($itsOK) { + return array(1); + } + } + } + if (isset($wanted)) { + return array(0, "Wanted ${wanted}, got ${got} at param ${pno}"); + } else { + $allowed = array(); + foreach ($sig as $val) { + end($val); + $allowed[] = key($val); + } + $allowed = array_unique($allowed); + $last = count($allowed) - 1; + if ($last > 0) { + $allowed[$last] = 'or ' . $allowed[$last]; + } + return array(0, + 'Signature permits ' . implode(', ', $allowed) + . ' parameters but the request had ' + . $in->getNumParams()); + } + } + + /** + * @return object a new XML_RPC_Response object + * + * @uses XML_RPC_Message::getEncoding(), XML_RPC_Server::$encoding + */ + function parseRequest($data = '') + { + global $XML_RPC_xh, $HTTP_RAW_POST_DATA, + $XML_RPC_err, $XML_RPC_str, $XML_RPC_errxml, + $XML_RPC_defencoding, $XML_RPC_Server_dmap; + + if ($data == '') { + $data = $HTTP_RAW_POST_DATA; + } + + $this->encoding = XML_RPC_Message::getEncoding($data); + $parser_resource = xml_parser_create($this->encoding); + $parser = (int) $parser_resource; + + $XML_RPC_xh[$parser] = array(); + $XML_RPC_xh[$parser]['cm'] = 0; + $XML_RPC_xh[$parser]['isf'] = 0; + $XML_RPC_xh[$parser]['params'] = array(); + $XML_RPC_xh[$parser]['method'] = ''; + $XML_RPC_xh[$parser]['stack'] = array(); + $XML_RPC_xh[$parser]['valuestack'] = array(); + + $plist = ''; + + // decompose incoming XML into request structure + + xml_parser_set_option($parser_resource, XML_OPTION_CASE_FOLDING, true); + xml_set_element_handler($parser_resource, 'XML_RPC_se', 'XML_RPC_ee'); + xml_set_character_data_handler($parser_resource, 'XML_RPC_cd'); + if (!xml_parse($parser_resource, $data, 1)) { + // return XML error as a faultCode + $r = new XML_RPC_Response(0, + $XML_RPC_errxml+xml_get_error_code($parser_resource), + sprintf('XML error: %s at line %d', + xml_error_string(xml_get_error_code($parser_resource)), + xml_get_current_line_number($parser_resource))); + xml_parser_free($parser_resource); + } elseif ($XML_RPC_xh[$parser]['isf']>1) { + $r = new XML_RPC_Response(0, + $XML_RPC_err['invalid_request'], + $XML_RPC_str['invalid_request'] + . ': ' + . $XML_RPC_xh[$parser]['isf_reason']); + xml_parser_free($parser_resource); + } else { + xml_parser_free($parser_resource); + $m = new XML_RPC_Message($XML_RPC_xh[$parser]['method']); + // now add parameters in + for ($i = 0; $i < sizeof($XML_RPC_xh[$parser]['params']); $i++) { + // print '\n"; + $plist .= "$i - " . var_export($XML_RPC_xh[$parser]['params'][$i], true) . " \n"; + $m->addParam($XML_RPC_xh[$parser]['params'][$i]); + } + + if ($this->debug) { + XML_RPC_Server_debugmsg($plist); + } + + // now to deal with the method + $methName = $XML_RPC_xh[$parser]['method']; + if (strpos($methName, 'system.') === 0) { + $dmap = $XML_RPC_Server_dmap; + $sysCall = 1; + } else { + $dmap = $this->dmap; + $sysCall = 0; + } + + if (isset($dmap[$methName]['function']) + && is_string($dmap[$methName]['function']) + && strpos($dmap[$methName]['function'], '::') !== false) + { + $dmap[$methName]['function'] = + explode('::', $dmap[$methName]['function']); + } + + if (isset($dmap[$methName]['function']) + && is_callable($dmap[$methName]['function'])) + { + // dispatch if exists + if (isset($dmap[$methName]['signature'])) { + $sr = $this->verifySignature($m, + $dmap[$methName]['signature'] ); + } + if (!isset($dmap[$methName]['signature']) || $sr[0]) { + // if no signature or correct signature + if ($sysCall) { + $r = call_user_func($dmap[$methName]['function'], $this, $m); + } else { + $r = call_user_func($dmap[$methName]['function'], $m); + } + if (!is_a($r, 'XML_RPC_Response')) { + $r = new XML_RPC_Response(0, $XML_RPC_err['not_response_object'], + $XML_RPC_str['not_response_object']); + } + } else { + $r = new XML_RPC_Response(0, $XML_RPC_err['incorrect_params'], + $XML_RPC_str['incorrect_params'] + . ': ' . $sr[1]); + } + } else { + // else prepare error response + $r = new XML_RPC_Response(0, $XML_RPC_err['unknown_method'], + $XML_RPC_str['unknown_method']); + } + } + return $r; + } + + /** + * Echos back the input packet as a string value + * + * @return void + * + * Useful for debugging. + */ + function echoInput() + { + global $HTTP_RAW_POST_DATA; + + $r = new XML_RPC_Response(0); + $r->xv = new XML_RPC_Value("'Aha said I: '" . $HTTP_RAW_POST_DATA, 'string'); + print $r->serialize(); + } +} + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * c-hanging-comment-ender-p: nil + * End: + */ + +?> diff --git a/src/lib/pear/temp/download/XML_RPC-1.5.1/tests/allgot.inc b/src/lib/pear/temp/download/XML_RPC-1.5.1/tests/allgot.inc new file mode 100644 index 0000000..3a74d53 --- /dev/null +++ b/src/lib/pear/temp/download/XML_RPC-1.5.1/tests/allgot.inc @@ -0,0 +1,58 @@ + + * @copyright 2005-2006 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License + * @version CVS: $Id: allgot.inc,v 1.2 2006/06/11 00:25:17 danielc Exp $ + * @link http://pear.php.net/package/XML_RPC + * @since File available since Release 1.4.4 + */ + +ob_start(); + +function returnAllGot($params) { + $out = ''; + $count = count($params->params); + for ($i = 0; $i < $count; $i++) { + $param = $params->getParam($i); + if (!XML_RPC_Value::isValue($param)) { + $out .= "parameter $i was error: $param\n"; + continue; + } + $got = XML_RPC_Decode($param); + $out .= "param $i: " . var_export($got, true) . "\n"; + } + $val = new XML_RPC_Value($out, 'string'); + return new XML_RPC_Response($val); +} + +$server = new XML_RPC_Server( + array( + 'allgot' => array( + 'function' => 'returnAllGot', + ), + ) +); + +$got = ob_get_clean(); + +if ($got == $expect) { + echo "passed\n"; +} else { + echo "FAILED\n"; + echo "Expected:\n$expect\n"; + echo "Got:\n$got\n"; +} diff --git a/src/lib/pear/temp/download/XML_RPC-1.5.1/tests/empty-value-struct.php b/src/lib/pear/temp/download/XML_RPC-1.5.1/tests/empty-value-struct.php new file mode 100644 index 0000000..7ef9d48 --- /dev/null +++ b/src/lib/pear/temp/download/XML_RPC-1.5.1/tests/empty-value-struct.php @@ -0,0 +1,90 @@ + + * @copyright 2005-2006 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License + * @version CVS: $Id: empty-value-struct.php,v 1.2 2006/06/11 00:25:17 danielc Exp $ + * @link http://pear.php.net/package/XML_RPC + * @since File available since Release 1.4.4 + */ + +/* + * If the package version number is found in the left hand + * portion of the if() expression below, that means this file has + * come from the PEAR installer. Therefore, let's test the + * installed version of XML_RPC which should be in the include path. + * + * If the version has not been substituted in the if() expression, + * this file has likely come from a CVS checkout or a .tar file. + * Therefore, we'll assume the tests should use the version of + * XML_RPC that has come from there as well. + */ +if ('1.5.1' != '@'.'package_version'.'@') { + /** + * Get the needed class from the PEAR installation + */ + require_once 'XML/RPC/Server.php'; +} else { + if (substr(dirname(__FILE__), -9, -6) != 'XML') { + echo "The parent directory must be named 'XML'.\n"; + exit; + } + + ini_set('include_path', '../../' + . PATH_SEPARATOR . '.' . PATH_SEPARATOR + . ini_get('include_path') + ); + + /** + * Get the needed class from the parent directory + */ + require_once '../Server.php'; +} + +$GLOBALS['HTTP_RAW_POST_DATA'] = << + + allgot + + + + + + fld1 + + + +EOPOST; + +$expect = << + + + +param 0: array ( + 'fld1' => '', +) + + + + +EOEXP; + +include './allgot.inc'; diff --git a/src/lib/pear/temp/download/XML_RPC-1.5.1/tests/empty-value.php b/src/lib/pear/temp/download/XML_RPC-1.5.1/tests/empty-value.php new file mode 100644 index 0000000..50de789 --- /dev/null +++ b/src/lib/pear/temp/download/XML_RPC-1.5.1/tests/empty-value.php @@ -0,0 +1,88 @@ + + * @copyright 2005-2006 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License + * @version CVS: $Id: empty-value.php,v 1.2 2006/06/11 00:25:17 danielc Exp $ + * @link http://pear.php.net/package/XML_RPC + * @since File available since Release 1.4.4 + */ + +/* + * If the package version number is found in the left hand + * portion of the if() expression below, that means this file has + * come from the PEAR installer. Therefore, let's test the + * installed version of XML_RPC which should be in the include path. + * + * If the version has not been substituted in the if() expression, + * this file has likely come from a CVS checkout or a .tar file. + * Therefore, we'll assume the tests should use the version of + * XML_RPC that has come from there as well. + */ +if ('1.5.1' != '@'.'package_version'.'@') { + /** + * Get the needed class from the PEAR installation + */ + require_once 'XML/RPC/Server.php'; +} else { + if (substr(dirname(__FILE__), -9, -6) != 'XML') { + echo "The parent directory must be named 'XML'.\n"; + exit; + } + + ini_set('include_path', '../../' + . PATH_SEPARATOR . '.' . PATH_SEPARATOR + . ini_get('include_path') + ); + + /** + * Get the needed class from the parent directory + */ + require_once '../Server.php'; +} + +$GLOBALS['HTTP_RAW_POST_DATA'] = << + + allgot + + + first + + + + +EOPOST; + +$expect = << + + + +param 0: '' +param 1: 'first' +param 2: ' ' +param 3: '' + + + + +EOEXP; + +include './allgot.inc'; diff --git a/src/lib/pear/temp/download/XML_RPC-1.5.1/tests/extra-lines.php b/src/lib/pear/temp/download/XML_RPC-1.5.1/tests/extra-lines.php new file mode 100644 index 0000000..e5edfb8 --- /dev/null +++ b/src/lib/pear/temp/download/XML_RPC-1.5.1/tests/extra-lines.php @@ -0,0 +1,109 @@ + + * @copyright 2005-2006 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License + * @version CVS: $Id: extra-lines.php,v 1.2 2006/06/11 00:25:17 danielc Exp $ + * @link http://pear.php.net/package/XML_RPC + * @since File available since Release 1.4.4 + */ + +/* + * If the package version number is found in the left hand + * portion of the if() expression below, that means this file has + * come from the PEAR installer. Therefore, let's test the + * installed version of XML_RPC which should be in the include path. + * + * If the version has not been substituted in the if() expression, + * this file has likely come from a CVS checkout or a .tar file. + * Therefore, we'll assume the tests should use the version of + * XML_RPC that has come from there as well. + */ +if ('1.5.1' != '@'.'package_version'.'@') { + /** + * Get the needed class from the PEAR installation + */ + require_once 'XML/RPC.php'; +} else { + if (substr(dirname(__FILE__), -9, -6) != 'XML') { + echo "The parent directory must be named 'XML'.\n"; + exit; + } + + ini_set('include_path', '../../' + . PATH_SEPARATOR . '.' . PATH_SEPARATOR + . ini_get('include_path') + ); + + /** + * Get the needed class from the parent directory + */ + require_once '../RPC.php'; +} + +$input = "First lfs\n\nSecond crlfs\r\n\r\nThird crs\r\rFourth line"; + +$expect_removed = " + +nada + + +First lfs +Second crlfs +Third crs +Fourth line + + + +"; + +$expect_not_removed = " + +nada + + +First lfs + +Second crlfs + +Third crs + +Fourth line + + + +"; + + +$msg = new XML_RPC_Message('nada', array(XML_RPC_encode($input))); +$msg->createPayload(); +if ($msg->payload == $expect_removed) { + echo "passed\n"; +} else { + echo "PROBLEM\n"; +} + +$msg = new XML_RPC_Message('nada', array(XML_RPC_encode($input))); +$msg->remove_extra_lines = false; +$msg->createPayload(); +if ($msg->payload == $expect_not_removed) { + echo "passed\n"; +} else { + echo "PROBLEM\n"; +} diff --git a/src/lib/pear/temp/download/XML_RPC-1.5.1/tests/protoport.php b/src/lib/pear/temp/download/XML_RPC-1.5.1/tests/protoport.php new file mode 100644 index 0000000..fea5b56 --- /dev/null +++ b/src/lib/pear/temp/download/XML_RPC-1.5.1/tests/protoport.php @@ -0,0 +1,437 @@ + + * @copyright 2005-2006 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License + * @version CVS: $Id: protoport.php,v 1.6 2006/06/11 00:25:17 danielc Exp $ + * @link http://pear.php.net/package/XML_RPC + * @since File available since Release 1.2 + */ + +/* + * If the package version number is found in the left hand + * portion of the if() expression below, that means this file has + * come from the PEAR installer. Therefore, let's test the + * installed version of XML_RPC which should be in the include path. + * + * If the version has not been substituted in the if() expression, + * this file has likely come from a CVS checkout or a .tar file. + * Therefore, we'll assume the tests should use the version of + * XML_RPC that has come from there as well. + */ +if ('1.5.1' != '@'.'package_version'.'@') { + /** + * Get the needed class from the PEAR installation + */ + require_once 'XML/RPC.php'; +} else { + /** + * Get the needed class from the parent directory + */ + require_once '../RPC.php'; +} + +/** + * Compare the test result to the expected result + * + * If the test fails, echo out the results. + * + * @param array $expect the array of object properties you expect + * from the test + * @param object $actual the object results from the test + * @param string $test_name the name of the test + * + * @return void + */ +function compare($expect, $actual, $test_name) { + $actual = get_object_vars($actual); + if (count(array_diff($actual, $expect))) { + echo "$test_name failed.\nExpect: "; + print_r($expect); + echo "Actual: "; + print_r($actual); + echo "\n"; + } +} + +if (php_sapi_name() != 'cli') { + echo "
    \n";
    +}
    +
    +
    +$x = array(
    +    'path' => 'thepath',
    +    'server' => 'theserver',
    +    'protocol' => 'http://',
    +    'port' => 80,
    +    'proxy' => '',
    +    'proxy_protocol' => 'http://',
    +    'proxy_port' => 8080,
    +    'proxy_user' => '',
    +    'proxy_pass' => '',
    +    'errno' => 0,
    +    'errstring' => '',
    +    'debug' => 0,
    +    'username' => '',
    +    'password' => '',
    +);
    +$c = new XML_RPC_Client('thepath', 'theserver');
    +compare($x, $c, 'defaults');
    +
    +$x = array(
    +    'path' => 'thepath',
    +    'server' => 'theserver',
    +    'protocol' => 'http://',
    +    'port' => 80,
    +    'proxy' => '',
    +    'proxy_protocol' => 'http://',
    +    'proxy_port' => 8080,
    +    'proxy_user' => '',
    +    'proxy_pass' => '',
    +    'errno' => 0,
    +    'errstring' => '',
    +    'debug' => 0,
    +    'username' => '',
    +    'password' => '',
    +);
    +$c = new XML_RPC_Client('thepath', 'http://theserver');
    +compare($x, $c, 'defaults with http');
    +
    +$x = array(
    +    'path' => 'thepath',
    +    'server' => 'theserver',
    +    'protocol' => 'ssl://',
    +    'port' => 443,
    +    'proxy' => '',
    +    'proxy_protocol' => 'http://',
    +    'proxy_port' => 8080,
    +    'proxy_user' => '',
    +    'proxy_pass' => '',
    +    'errno' => 0,
    +    'errstring' => '',
    +    'debug' => 0,
    +    'username' => '',
    +    'password' => '',
    +);
    +$c = new XML_RPC_Client('thepath', 'https://theserver');
    +compare($x, $c, 'defaults with https');
    +
    +$x = array(
    +    'path' => 'thepath',
    +    'server' => 'theserver',
    +    'protocol' => 'ssl://',
    +    'port' => 443,
    +    'proxy' => '',
    +    'proxy_protocol' => 'http://',
    +    'proxy_port' => 8080,
    +    'proxy_user' => '',
    +    'proxy_pass' => '',
    +    'errno' => 0,
    +    'errstring' => '',
    +    'debug' => 0,
    +    'username' => '',
    +    'password' => '',
    +);
    +$c = new XML_RPC_Client('thepath', 'ssl://theserver');
    +compare($x, $c, 'defaults with ssl');
    +
    +
    +$x = array(
    +    'path' => 'thepath',
    +    'server' => 'theserver',
    +    'protocol' => 'http://',
    +    'port' => 65,
    +    'proxy' => '',
    +    'proxy_protocol' => 'http://',
    +    'proxy_port' => 8080,
    +    'proxy_user' => '',
    +    'proxy_pass' => '',
    +    'errno' => 0,
    +    'errstring' => '',
    +    'debug' => 0,
    +    'username' => '',
    +    'password' => '',
    +);
    +$c = new XML_RPC_Client('thepath', 'theserver', 65);
    +compare($x, $c, 'port 65');
    +
    +$x = array(
    +    'path' => 'thepath',
    +    'server' => 'theserver',
    +    'protocol' => 'http://',
    +    'port' => 65,
    +    'proxy' => '',
    +    'proxy_protocol' => 'http://',
    +    'proxy_port' => 8080,
    +    'proxy_user' => '',
    +    'proxy_pass' => '',
    +    'errno' => 0,
    +    'errstring' => '',
    +    'debug' => 0,
    +    'username' => '',
    +    'password' => '',
    +);
    +$c = new XML_RPC_Client('thepath', 'http://theserver', 65);
    +compare($x, $c, 'port 65 with http');
    +
    +$x = array(
    +    'path' => 'thepath',
    +    'server' => 'theserver',
    +    'protocol' => 'ssl://',
    +    'port' => 65,
    +    'proxy' => '',
    +    'proxy_protocol' => 'http://',
    +    'proxy_port' => 8080,
    +    'proxy_user' => '',
    +    'proxy_pass' => '',
    +    'errno' => 0,
    +    'errstring' => '',
    +    'debug' => 0,
    +    'username' => '',
    +    'password' => '',
    +);
    +$c = new XML_RPC_Client('thepath', 'https://theserver', 65);
    +compare($x, $c, 'port 65 with https');
    +
    +$x = array(
    +    'path' => 'thepath',
    +    'server' => 'theserver',
    +    'protocol' => 'ssl://',
    +    'port' => 65,
    +    'proxy' => '',
    +    'proxy_protocol' => 'http://',
    +    'proxy_port' => 8080,
    +    'proxy_user' => '',
    +    'proxy_pass' => '',
    +    'errno' => 0,
    +    'errstring' => '',
    +    'debug' => 0,
    +    'username' => '',
    +    'password' => '',
    +);
    +$c = new XML_RPC_Client('thepath', 'ssl://theserver', 65);
    +compare($x, $c, 'port 65 with ssl');
    +
    +
    +$x = array(
    +    'path' => 'thepath',
    +    'server' => 'theserver',
    +    'protocol' => 'http://',
    +    'port' => 80,
    +    'proxy' => 'theproxy',
    +    'proxy_protocol' => 'http://',
    +    'proxy_port' => 8080,
    +    'proxy_user' => '',
    +    'proxy_pass' => '',
    +    'errno' => 0,
    +    'errstring' => '',
    +    'debug' => 0,
    +    'username' => '',
    +    'password' => '',
    +);
    +$c = new XML_RPC_Client('thepath', 'theserver', 0,
    +                        'theproxy');
    +compare($x, $c, 'defaults proxy');
    +
    +$x = array(
    +    'path' => 'thepath',
    +    'server' => 'theserver',
    +    'protocol' => 'http://',
    +    'port' => 80,
    +    'proxy' => 'theproxy',
    +    'proxy_protocol' => 'http://',
    +    'proxy_port' => 8080,
    +    'proxy_user' => '',
    +    'proxy_pass' => '',
    +    'errno' => 0,
    +    'errstring' => '',
    +    'debug' => 0,
    +    'username' => '',
    +    'password' => '',
    +);
    +$c = new XML_RPC_Client('thepath', 'http://theserver', 0,
    +                        'http://theproxy');
    +compare($x, $c, 'defaults with http proxy');
    +
    +$x = array(
    +    'path' => 'thepath',
    +    'server' => 'theserver',
    +    'protocol' => 'ssl://',
    +    'port' => 443,
    +    'proxy' => 'theproxy',
    +    'proxy_protocol' => 'ssl://',
    +    'proxy_port' => 443,
    +    'proxy_user' => '',
    +    'proxy_pass' => '',
    +    'errno' => 0,
    +    'errstring' => '',
    +    'debug' => 0,
    +    'username' => '',
    +    'password' => '',
    +);
    +$c = new XML_RPC_Client('thepath', 'https://theserver', 0,
    +                        'https://theproxy');
    +compare($x, $c, 'defaults with https proxy');
    +
    +$x = array(
    +    'path' => 'thepath',
    +    'server' => 'theserver',
    +    'protocol' => 'ssl://',
    +    'port' => 443,
    +    'proxy' => 'theproxy',
    +    'proxy_protocol' => 'ssl://',
    +    'proxy_port' => 443,
    +    'proxy_user' => '',
    +    'proxy_pass' => '',
    +    'errno' => 0,
    +    'errstring' => '',
    +    'debug' => 0,
    +    'username' => '',
    +    'password' => '',
    +);
    +$c = new XML_RPC_Client('thepath', 'ssl://theserver', 0,
    +                        'ssl://theproxy');
    +compare($x, $c, 'defaults with ssl proxy');
    +
    +
    +$x = array(
    +    'path' => 'thepath',
    +    'server' => 'theserver',
    +    'protocol' => 'http://',
    +    'port' => 65,
    +    'proxy' => 'theproxy',
    +    'proxy_protocol' => 'http://',
    +    'proxy_port' => 6565,
    +    'proxy_user' => '',
    +    'proxy_pass' => '',
    +    'errno' => 0,
    +    'errstring' => '',
    +    'debug' => 0,
    +    'username' => '',
    +    'password' => '',
    +);
    +$c = new XML_RPC_Client('thepath', 'theserver', 65,
    +                        'theproxy', 6565);
    +compare($x, $c, 'port 65 proxy 6565');
    +
    +$x = array(
    +    'path' => 'thepath',
    +    'server' => 'theserver',
    +    'protocol' => 'http://',
    +    'port' => 65,
    +    'proxy' => 'theproxy',
    +    'proxy_protocol' => 'http://',
    +    'proxy_port' => 6565,
    +    'proxy_user' => '',
    +    'proxy_pass' => '',
    +    'errno' => 0,
    +    'errstring' => '',
    +    'debug' => 0,
    +    'username' => '',
    +    'password' => '',
    +);
    +$c = new XML_RPC_Client('thepath', 'http://theserver', 65,
    +                        'http://theproxy', 6565);
    +compare($x, $c, 'port 65 with http proxy 6565');
    +
    +$x = array(
    +    'path' => 'thepath',
    +    'server' => 'theserver',
    +    'protocol' => 'ssl://',
    +    'port' => 65,
    +    'proxy' => 'theproxy',
    +    'proxy_protocol' => 'ssl://',
    +    'proxy_port' => 6565,
    +    'proxy_user' => '',
    +    'proxy_pass' => '',
    +    'errno' => 0,
    +    'errstring' => '',
    +    'debug' => 0,
    +    'username' => '',
    +    'password' => '',
    +);
    +$c = new XML_RPC_Client('thepath', 'https://theserver', 65,
    +                        'https://theproxy', 6565);
    +compare($x, $c, 'port 65 with https proxy 6565');
    +
    +$x = array(
    +    'path' => 'thepath',
    +    'server' => 'theserver',
    +    'protocol' => 'ssl://',
    +    'port' => 65,
    +    'proxy' => 'theproxy',
    +    'proxy_protocol' => 'ssl://',
    +    'proxy_port' => 6565,
    +    'proxy_user' => '',
    +    'proxy_pass' => '',
    +    'errno' => 0,
    +    'errstring' => '',
    +    'debug' => 0,
    +    'username' => '',
    +    'password' => '',
    +);
    +$c = new XML_RPC_Client('thepath', 'ssl://theserver', 65,
    +                        'ssl://theproxy', 6565);
    +compare($x, $c, 'port 65 with ssl proxy 6565');
    +
    +
    +$x = array(
    +    'path' => 'thepath',
    +    'server' => 'theserver',
    +    'protocol' => 'ssl://',
    +    'port' => 443,
    +    'proxy' => 'theproxy',
    +    'proxy_protocol' => 'ssl://',
    +    'proxy_port' => 443,
    +    'proxy_user' => '',
    +    'proxy_pass' => '',
    +    'errno' => 0,
    +    'errstring' => '',
    +    'debug' => 0,
    +    'username' => '',
    +    'password' => '',
    +);
    +$c = new XML_RPC_Client('thepath', 'theserver', 443,
    +                        'theproxy', 443);
    +compare($x, $c, 'port 443 no protocol and proxy port 443 no protocol');
    +
    +$x = array(
    +    'path' => 'thepath',
    +    'server' => 'theserver',
    +    'protocol' => 'http://',
    +    'port' => 80,
    +    'proxy' => 'theproxy',
    +    'proxy_protocol' => 'ssl://',
    +    'proxy_port' => 6565,
    +    'proxy_user' => '',
    +    'proxy_pass' => '',
    +    'errno' => 0,
    +    'errstring' => '',
    +    'debug' => 0,
    +    'username' => '',
    +    'password' => '',
    +);
    +$c = new XML_RPC_Client('thepath', 'theserver', 0,
    +                        'ssl://theproxy', 6565);
    +compare($x, $c, 'port 443 no protocol and proxy port 443 no protocol');
    +
    +echo "\nIf no other output was produced, these tests passed.\n";
    diff --git a/src/lib/pear/temp/download/XML_RPC-1.5.1/tests/test_Dump.php b/src/lib/pear/temp/download/XML_RPC-1.5.1/tests/test_Dump.php
    new file mode 100644
    index 0000000..0b2739e
    --- /dev/null
    +++ b/src/lib/pear/temp/download/XML_RPC-1.5.1/tests/test_Dump.php
    @@ -0,0 +1,50 @@
    +new XML_RPC_Value('das ist der Titel', 'string'),
    +    'startDate'=>new XML_RPC_Value(mktime(0,0,0,13,11,2004), 'dateTime.iso8601'),
    +    'endDate'  =>new XML_RPC_Value(mktime(0,0,0,15,11,2004), 'dateTime.iso8601'),
    +    'error'    =>'string',
    +    'arkey'    => new XML_RPC_Value( array(
    +        new XML_RPC_Value('simple string'),
    +        new XML_RPC_Value(12345, 'int')
    +        ), 'array')
    +    )
    +    ,'struct');
    +
    +XML_RPC_Dump($val);
    +
    +echo '==============' . "\r\n";
    +$val2 = new XML_RPC_Value(44353, 'int');
    +XML_RPC_Dump($val2);
    +
    +echo '==============' . "\r\n";
    +$val3 = new XML_RPC_Value('this should be a string', 'string');
    +XML_RPC_Dump($val3);
    +
    +echo '==============' . "\r\n";
    +$val4 = new XML_RPC_Value(true, 'boolean');
    +XML_RPC_Dump($val4);
    diff --git a/src/lib/pear/temp/download/XML_RPC-1.5.1/tests/types.php b/src/lib/pear/temp/download/XML_RPC-1.5.1/tests/types.php
    new file mode 100644
    index 0000000..2ed8678
    --- /dev/null
    +++ b/src/lib/pear/temp/download/XML_RPC-1.5.1/tests/types.php
    @@ -0,0 +1,132 @@
    +
    + * @copyright  2005-2006 The PHP Group
    + * @license    http://www.php.net/license/3_01.txt  PHP License
    + * @version    CVS: $Id: types.php,v 1.2 2006/06/11 00:25:17 danielc Exp $
    + * @link       http://pear.php.net/package/XML_RPC
    + * @since      File available since Release 1.4.4
    + */
    +
    +/*
    + * If the package version number is found in the left hand
    + * portion of the if() expression below, that means this file has
    + * come from the PEAR installer.  Therefore, let's test the
    + * installed version of XML_RPC which should be in the include path.
    + * 
    + * If the version has not been substituted in the if() expression,
    + * this file has likely come from a CVS checkout or a .tar file.
    + * Therefore, we'll assume the tests should use the version of
    + * XML_RPC that has come from there as well.
    + */
    +if ('1.5.1' != '@'.'package_version'.'@') {
    +    /**
    +     * Get the needed class from the PEAR installation
    +     */
    +    require_once 'XML/RPC/Server.php';
    +} else {
    +    if (substr(dirname(__FILE__), -9, -6) != 'XML') {
    +        echo "The parent directory must be named 'XML'.\n";
    +        exit;
    +    }
    +
    +    ini_set('include_path', '../../'
    +            . PATH_SEPARATOR . '.' . PATH_SEPARATOR
    +            . ini_get('include_path')
    +    );
    +
    +    /**
    +     * Get the needed class from the parent directory
    +     */
    +    require_once '../Server.php';
    +}
    +
    +$GLOBALS['HTTP_RAW_POST_DATA'] = <<
    +
    + allgot
    +  
    +   default to string
    +   inside string
    +   8
    +   20050809T01:33:44
    +
    +   
    +    
    +     
    +      
    +       
    +        a
    +       
    +       
    +        b
    +       
    +      
    +     
    +    
    +   
    +
    +   
    +    
    +     
    +      
    +       a
    +       
    +        ay
    +       
    +      
    +      
    +       b
    +       
    +        be
    +       
    +      
    +     
    +    
    +   
    +
    +  
    + 
    +EOPOST;
    +
    +$expect = <<
    +
    +
    +
    +param 0: 'default to string'
    +param 1: 'inside string'
    +param 2: '8'
    +param 3: '20050809T01:33:44'
    +param 4: array (
    +  0 => 'a',
    +  1 => 'b',
    +)
    +param 5: array (
    +  'a' => 'ay',
    +  'b' => 'be',
    +)
    +
    +
    +
    +
    +EOEXP;
    +
    +include './allgot.inc';
    diff --git a/src/lib/pear/temp/download/package.xml b/src/lib/pear/temp/download/package.xml
    new file mode 100644
    index 0000000..92e76bb
    --- /dev/null
    +++ b/src/lib/pear/temp/download/package.xml
    @@ -0,0 +1,375 @@
    +
    +
    +
    + XML_RPC
    + PHP implementation of the XML-RPC protocol
    + A PEAR-ified version of Useful Inc's XML-RPC for PHP.
    +
    +It has support for HTTP/HTTPS transport, proxies and authentication.
    + 
    + 
    +  
    +   ssb
    +   Stig Bakken
    +   stig@php.net
    +   lead
    +  
    +  
    +   danielc
    +   Daniel Convissor
    +   danielc@php.net
    +   lead
    +  
    +  
    + 
    +  1.5.1
    +  2006-10-28
    +  PHP License
    +  stable
    +  * Turn passing payload through mb_convert_encoding() off by default.  Use new XML_RPC_Message::setConvertPayloadEncoding() and XML_RPC_Server::setConvertPayloadEncoding() to turn it on.  Bug 8632.
    +* Have XML_RPC_Value::scalarval() return FALSE if value is not a scalar.  Bug 8251.
    +  
    +  
    +   
    +   xml
    +  
    +  
    +   
    +    
    +   
    +   
    +    
    +   
    +   
    +    
    +   
    +   
    +   
    +    
    +   
    +   
    +    
    +   
    +   
    +    
    +   
    +   
    +    
    +   
    +   
    +    
    +   
    +   
    +    
    +   
    +  
    + 
    + 
    +   
    +    1.5.0
    +    2006-07-11
    +    stable
    +    No changes from 1.5.0RC2.
    +
    +The primary change from 1.4.8 is improved multi-byte support.  See the change log for complete information.
    +    
    +   
    +   
    +    1.5.0RC2
    +    2006-06-21
    +    beta
    +    * If PHP's mbstring extension is enabled, use mb_convert_encoding() to ensure the server payload matches the intended encoding.
    +    
    +   
    +   
    +    1.5.0RC1
    +    2006-06-16
    +    beta
    +    * Provide complete multi-byte string support for systems with the mbstring extension enabled. Bug 7837.
    +* If PHP's mbstring extension is enabled, use mb_convert_encoding() to ensure the client payload matches the intended encoding. This is a better resolution of Bug 7376.
    +* Turn off the default of automatically base64 encoding strings that can generate fatal errors in PHP's SAX parser. The automatic base64 encoding can be turned on via the new XML_RPC_Client::setAutoBase64() method. The auto-encoding is a workaround for systems that don't have PHP's mbstring extension available. (The automatic base64 encoding was added in the prior release, 1.4.8, and caused problems for users who don't control the receiving end of the requests.) Bug 7837.
    +    
    +   
    +   
    +    1.4.8
    +    2006-04-16
    +    stable
    +    * Characters other than alpha-numeric, punctuation, SP, TAB, LF and CR break the XML parser, encode value via Base 64.  Bug 7376.
    +    
    +   
    +   
    +    1.4.7
    +    2006-04-10
    +    stable
    +    * Add include_once for PEAR if need to load xml extension.  Bug 7358.
    +* Add dependency for xml extension in package file.  Bug 7358.
    +    
    +   
    +   
    +    1.4.6
    +    2006-04-07
    +    stable
    +    * Add XML_RPC_Message::$remove_extra_lines property. Defaults to true. If set to false, extra lines are left in place. Bug 7088.
    +* Add XML_RPC_Message::$response_payload property. Makes logging responses easy.
    +    
    +   
    +   
    +    1.4.5
    +    2006-01-14
    +    stable
    +    * Have server send headers individualy as opposed to sending them all at once. Necessary due to changes PHP 4.4.2.
    +    
    +   
    +   
    +    1.4.4
    +    2005-10-15
    +    stable
    +    * Properly deal with empty values in struct's.
    +    
    +   
    +   
    +    1.4.3
    +    2005-09-24
    +    stable
    +    * Make XML_RPC_encode() properly handle dateTime.iso8601.  Request 5117.
    +    
    +   
    +   
    +    1.4.2
    +    2005-09-18
    +    stable
    +    * Allow empty <value>'s without <types>'s.  Bug 5315.
    +    
    +   
    +   
    +    1.4.1
    +    2005-09-07
    +    stable
    +    * Don't add debug info unless debug is on.  Bug 5136.
    +* Use is_a() instead of class_name() so people can use their own XML_RPC_Message objects.  Request 5002.
    +    
    +   
    +   
    +    1.4.0
    +    2005-08-14
    +    stable
    +    * MAJOR SECURITY FIX: eliminate use of eval().
    +* Using socket_get_status() because stream_get_meta_data() was introduced in 4.3.0, but we need to support 4.2.0.  Bug 4805.
    +    
    +   
    +   
    +    1.3.3
    +    2005-07-15
    +    stable
    +    * Eliminate memory leak by resetting $XML_RPC_xh each time parseResponse() is called.  Bug 4780.
    +* Using socket_set_timeout() because stream_set_timeout() was introduced in 4.3.0, but we need to support 4.2.0.  Bug 4805.
    +    
    +   
    +   
    +    1.3.2
    +    2005-07-07
    +    stable
    +    * Eliminate path disclosure vulnerabilities by suppressing error messages when eval()'ing.
    +* Eliminate path disclosure vulnerability by catching bogus parameters submitted to XML_RPC_Value::serializeval().
    +* In XML_RPC_Server::service(), only call createServerPayload() and createServerHeaders() if necessary.  Fixes compatibility issue introduced in Release 1.3.0RC1 for users who set the $serviceNow parameter of XML_RPC_Server() to 0.  Bug 4757.
    +* Change "var $errstring" to "var $errstr".  Bug 4582.  Was put into CVS version 1.75 of RPC.php but didn't make it into RELEASE_1_3_1.
    +    
    +   
    +   
    +    1.3.1
    +    2005-06-29
    +    stable
    +    * Security fix. Update highly recommended!
    +    
    +   
    +   
    +    1.3.0
    +    2005-06-13
    +    stable
    +    * Stable release.  See earlier releases for changes since 1.2.2.
    +    
    +   
    +   
    +    1.3.0RC3
    +    2005-05-10
    +    beta
    +    * When verifying requests against function signatures, if the number of parameters don't match, provide an appropriate message.  NOTE: this resolves a path disclosure vulnerability.  (Refines the changes made in the last commit.)  Bug 4231.
    +* XML_RPC_Message::getParam() now returns an XML_RPC_Response object upon error.  Changed from Release 1.3.0RC2.
    +* Add the XML_RPC_Value::isValue() method. For testing if an item is an XML_RPC_Value object.
    +* If XML_RPC_Client::send() is given an incorrect $msg parameter, raise an error with the new XML_RPC_ERROR_PROGRAMMING code and return 0.
    +* Improve cross-platform operation by using PEAR::loadExtension() instead of dl().
    +* Use <br /> instead of <br> in XML_RPC_Value::dump().
    +    
    +   
    +   
    +    1.3.0RC2
    +    2005-05-05
    +    beta
    +    * If XML_RPC_Message::getParam() is given an incorrect parameter, raise an error with the new XML_RPC_ERROR_INCORRECT_PARAMS code and return FALSE.
    +* Handle improper requests to XML_RPC_Server::verifySignature().  Bug 4231.
    +* Try to allow HTTP 100 responses if followed by a 200 response.  Bug 4116.
    +* Help Delphi users by making RPCMETHODNAME an alias for METHODNAME.  Request 4205.
    +    
    +   
    +   
    +    1.3.0RC1
    +    2005-04-07
    +    beta
    +    * Improve timeout handling for situations where connection to server is made but no response is not received in time. Accomplished via stream_set_timeout().  Request 3963.
    +* Add Fault Code 6: "The requested method didn't return an XML_RPC_Response object."  Request 4032.
    +* Add the createServerPayload() and createServerHeaders() methods and the $server_payload and $server_headers properties.  Request 3121.
    +* As in earlier versions, if the $serviceNow parameter to XML_RPC_Server() is 0, no data will be returned, but now the new $server_payload and $server_headers properties will be set.
    +* Convert the parser handle to an integer before using it as an index for $XML_RPC_xh[$parser].  Reduces E_STRICT notices.  Bug 3782.
    +* Add createHeaders() method and $headers property to XML_RPC_Client to make testing easier.
    +    
    +   
    +   
    +    1.2.2
    +    2005-03-07
    +    stable
    +    * When using a proxy, add the protocol to the Request-URI, making it an "absoluteURI" as per the HTTP 1.0 spec.  Bug 3679.
    +    
    +   
    +   
    +    1.2.1
    +    2005-03-01
    +    stable
    +    * Add isset() check before examining the dispatch map.  Bug 3658.
    +    
    +   
    +   
    +    1.2.0
    +    2005-02-27
    +    stable
    +    * Provide the "stable" release.
    +* Add package2.xml for compatibility with PEAR 1.4.0.
    +* For changes since 1.1.0, see the changelogs for the various RC releases.
    +    
    +   
    +   
    +    1.2.0RC7
    +    2005-02-22
    +    beta
    +    * Add the setSendEncoding() method and $send_encoding
    +  property to XML_RPC_Message.  Request 3537.
    +* Allow class methods to be mapped using either syntax:
    +     'function' => 'hello::sayHello',
    +     or
    +     'function' => array('hello', 'sayhello'),
    +  Bug 3363.
    +* Use 8192 instead of 32768 for bytes in fread()
    +  in parseResponseFile().  Bug 3340.
    +    
    +   
    +   
    +    1.2.0RC6
    +    2005-01-25
    +    beta
    +    * Don't put the protocol in the Host field of the POST data.  (danielc)
    +    
    +   
    +   
    +    1.2.0RC5
    +    2005-01-24
    +    beta
    +    * If $port is 443 but a protocol isn't specified in $server, assume ssl:// is the protocol.
    +    
    +   
    +   
    +    1.2.0RC4
    +    2005-01-24
    +    beta
    +    * When a connection attempt fails, have the method return 0.  (danielc)
    +* Move the protocol/port checking/switching and the property settings from sendPayloadHTTP10() to the XML_RPC_Client constructor.  (danielc)
    +* Add tests for setting the client properties.  (danielc)
    +* Remove $GLOBALS['XML_RPC_twoslash'] since it's not used.  (danielc)
    +* Bundle the tests with the package.  (danielc)
    +    
    +   
    +   
    +    1.2.0RC3
    +    2005-01-19
    +    beta
    +    * ssl uses port 443, not 445.
    +    
    +   
    +   
    +    1.2.0RC2
    +    2005-01-11
    +    beta
    +    * Handle ssl:// in the $server string.  (danielc)
    +* Also default to port 445 for ssl:// requests as well.  (danielc)
    +* Enhance debugging in the server.  (danielc)
    +    
    +   
    +   
    +    1.2.0RC1
    +    2004-12-30
    +    beta
    +    * Make things work with SSL.  Bug 2489.  (nkukard lbsd net)
    +* Allow array function callbacks (Matt Kane)
    +* Some minor speed-ups (Matt Kane)
    +* Add Dump.php to the package (Christian Weiske)
    +* Replace all line endings with \r\n.  Had only done replacements on \n.  Bug 2521.  (danielc)
    +* Silence fsockopen() errors.  Bug 1714.  (danielc)
    +* Encode empty arrays as an array. Bug 1493.  (danielc)
    +* Eliminate undefined index notice when submitting empty arrays to XML_RPC_Encode().  Bug 1819.  (danielc)
    +* Speed up check for enumerated arrays in XML_RPC_Encode().  (danielc)
    +* Prepend "XML_RPC_" to ERROR_NON_NUMERIC_FOUND, eliminating problem when eval()'ing error messages.  (danielc)
    +* Use XML_RPC_Base::raiseError() instead of PEAR::raiseError() in XML_RPC_ee() because PEAR.php is lazy loaded.  (danielc)
    +* Allow raiseError() to be called statically.  (danielc)
    +* Stop double escaping of character entities.  Bug 987.  (danielc)
    +  NOTICE: the following have been removed:
    +    * XML_RPC_dh()
    +    * $GLOBALS['XML_RPC_entities']
    +    * XML_RPC_entity_decode()
    +    * XML_RPC_lookup_entity()
    +* Determine the XML's encoding via the encoding attribute in the XML declaration.  Bug 52.  (danielc)
    +    
    +   
    +   
    +    1.1.0
    +    2004-03-15
    +    stable
    +    * Added support for sequential arrays to XML_RPC_encode() (mroch)
    +* Cleaned up new XML_RPC_encode() changes a bit (mroch, pierre)
    +* Remove "require_once 'PEAR.php'", include only when needed to raise an error
    +* Replace echo and error_log() with raiseError() (mroch)
    +* Make all classes extend XML_RPC_Base, which will handle common functions  (mroch)
    +* be tolerant of junk after methodResponse (Luca Mariano, mroch)
    +* Silent notice even in the error log (pierre)
    +* fix include of shared xml extension on win32 (pierre)
    +    
    +   
    +   
    +    1.0.4
    +    2002-10-02
    +    stable
    +    * added HTTP proxy authorization support (thanks to Arnaud Limbourg)
    +    
    +   
    +   
    +    1.0.3
    +    2002-05-19
    +    stable
    +    * fix bug when parsing responses with boolean types
    +    
    +   
    +   
    +    1.0.2
    +    2002-04-16
    +    stable
    +    * E_ALL fixes
    +* fix HTTP response header parsing
    +    
    +   
    +   
    +    1.0.1
    +    2001-09-25
    +    stable
    +    This is a PEAR-ified version of Useful Inc's 1.0.1 release.
    +Includes an urgent security fix identified by Dan Libby <dan@libby.com>.
    +    
    +   
    + 
    +
    diff --git a/src/lib/pear/temp/download/package2.xml b/src/lib/pear/temp/download/package2.xml
    new file mode 100644
    index 0000000..857d45f
    --- /dev/null
    +++ b/src/lib/pear/temp/download/package2.xml
    @@ -0,0 +1,598 @@
    +
    +
    + XML_RPC
    + pear.php.net
    + PHP implementation of the XML-RPC protocol
    + A PEAR-ified version of Useful Inc's XML-RPC for PHP.
    +
    +It has support for HTTP/HTTPS transport, proxies and authentication.
    + 
    +  Stig Bakken
    +  ssb
    +  stig@php.net
    +  no
    + 
    + 
    +  Daniel Convissor
    +  danielc
    +  danielc@php.net
    +  yes
    + 
    + 2006-10-28
    + 
    + 
    +  1.5.1
    +  1.5.0
    + 
    + 
    +  stable
    +  stable
    + 
    + PHP License
    + * Turn passing payload through mb_convert_encoding() off by default.  Use new XML_RPC_Message::setConvertPayloadEncoding() and XML_RPC_Server::setConvertPayloadEncoding() to turn it on.  Bug 8632.
    +* Have XML_RPC_Value::scalarval() return FALSE if value is not a scalar.  Bug 8251.
    + 
    +  
    +   
    +   
    +    
    +   
    +   
    +    
    +   
    +   
    +    
    +   
    +   
    +    
    +   
    +   
    +    
    +   
    +   
    +    
    +   
    +   
    +    
    +   
    +   
    +    
    +   
    +   
    +    
    +   
    +  
    + 
    + 
    +  PEAR
    +  pear.php.net
    +  1.4.0a1
    +  1.4.9
    + 
    + 
    +  
    +   
    +    4.2.0
    +   
    +   
    +    1.4.0a1
    +   
    +   
    +    xml
    +   
    +  
    + 
    + 
    + 
    +  
    +   
    +    1.5.0
    +    1.5.0
    +   
    +   
    +    stable
    +    stable
    +   
    +   2006-07-11
    +   PHP License
    +   No changes from 1.5.0RC2.
    +
    +The primary change from 1.4.8 is improved multi-byte support.  See the change log for complete information.
    +  
    +  
    +   
    +    1.5.0RC2
    +    1.5.0
    +   
    +   
    +    beta
    +    beta
    +   
    +   2006-06-21
    +   PHP License
    +   * If PHP's mbstring extension is enabled, use mb_convert_encoding() to ensure the server payload matches the intended encoding.
    +  
    +  
    +   
    +    1.5.0RC1
    +    1.5.0
    +   
    +   
    +    beta
    +    beta
    +   
    +   2006-06-16
    +   PHP License
    +   * Provide complete multi-byte string support for systems with the mbstring extension enabled. Bug 7837.
    +* If PHP's mbstring extension is enabled, use mb_convert_encoding() to ensure the client payload matches the intended encoding. This is a better resolution of Bug 7376.
    +* Turn off the default of automatically base64 encoding strings that can generate fatal errors in PHP's SAX parser. The automatic base64 encoding can be turned on via the new XML_RPC_Client::setAutoBase64() method. The auto-encoding is a workaround for systems that don't have PHP's mbstring extension available. (The automatic base64 encoding was added in the prior release, 1.4.8, and caused problems for users who don't control the receiving end of the requests.) Bug 7837.
    +  
    +  
    +   
    +    1.4.8
    +    1.4.6
    +   
    +   
    +    stable
    +    stable
    +   
    +   2006-04-16
    +   PHP License
    +   * Characters other than alpha-numeric, punctuation, SP, TAB, LF and CR break the XML parser, encode value via Base 64.  Bug 7376.
    +  
    +  
    +   
    +    1.4.7
    +    1.4.6
    +   
    +   
    +    stable
    +    stable
    +   
    +   2006-04-10
    +   PHP License
    +   * Add include_once for PEAR if need to load xml extension.  Bug 7358.
    +* Add dependency for xml extension in package file.  Bug 7358.
    +  
    +  
    +   
    +    1.4.6
    +    1.4.6
    +   
    +   
    +    stable
    +    stable
    +   
    +   2006-04-07
    +   PHP License
    +   * Add XML_RPC_Message::$remove_extra_lines property. Defaults to true. If set to false, extra lines are left in place. Bug 7088.
    +* Add XML_RPC_Message::$response_payload property. Makes logging responses easy.
    +  
    +  
    +   
    +    1.4.5
    +    1.4.0
    +   
    +   
    +    stable
    +    stable
    +   
    +   2006-01-14
    +   PHP License
    +   * Have server send headers individualy as opposed to sending them all at once. Necessary due to changes PHP 4.4.2.
    +  
    +  
    +   
    +    1.4.4
    +    1.4.0
    +   
    +   
    +    stable
    +    stable
    +   
    +   2005-10-15
    +   PHP License
    +   * Properly deal with empty values in struct's.
    +  
    +  
    +   
    +    1.4.3
    +    1.4.0
    +   
    +   
    +    stable
    +    stable
    +   
    +   2005-09-24
    +   PHP License
    +   * Make XML_RPC_encode() properly handle dateTime.iso8601.  Request 5117.
    +  
    +  
    +   
    +    1.4.2
    +    1.4.0
    +   
    +   
    +    stable
    +    stable
    +   
    +   2005-09-18
    +   PHP License
    +   * Allow empty <value>'s without <types>'s.  Bug 5315.
    +  
    +  
    +   
    +    1.4.1
    +    1.4.0
    +   
    +   
    +    stable
    +    stable
    +   
    +   2005-09-07
    +   PHP License
    +   * Don't add debug info unless debug is on.  Bug 5136.
    +* Use is_a() instead of class_name() so people can use their own XML_RPC_Message objects.  Request 5002.
    +  
    +  
    +   
    +    1.4.0
    +    1.4.0
    +   
    +   
    +    stable
    +    stable
    +   
    +   2005-08-14
    +   PHP License
    +   * MAJOR SECURITY FIX: eliminate use of eval().
    +* Using socket_get_status() because stream_get_meta_data() was introduced in 4.3.0, but we need to support 4.2.0.  Bug 4805.
    +  
    +  
    +   
    +    1.3.3
    +    1.3.0
    +   
    +   
    +    stable
    +    stable
    +   
    +   2005-07-15
    +   PHP License
    +   * Eliminate memory leak by resetting $XML_RPC_xh each time parseResponse() is called.  Bug 4780.
    +* Using socket_set_timeout() because stream_set_timeout() was introduced in 4.3.0, but we need to support 4.2.0.  Bug 4805.
    +  
    +  
    +   
    +    1.3.2
    +    1.3.0
    +   
    +   
    +    stable
    +    stable
    +   
    +   2005-07-07
    +   PHP License
    +   * Eliminate path disclosure vulnerabilities by suppressing error messages when eval()'ing.
    +* Eliminate path disclosure vulnerability by catching bogus parameters submitted to XML_RPC_Value::serializeval().
    +* In XML_RPC_Server::service(), only call createServerPayload() and createServerHeaders() if necessary.  Fixes compatibility issue introduced in Release 1.3.0RC1 for users who set the $serviceNow parameter of XML_RPC_Server() to 0.  Bug 4757.
    +* Change "var $errstring" to "var $errstr".  Bug 4582.  Was put into CVS version 1.75 of RPC.php but didn't make it into RELEASE_1_3_1.
    +  
    +  
    +   
    +    1.3.1
    +    1.3.0
    +   
    +   
    +    stable
    +    stable
    +   
    +   2005-06-29
    +   PHP License
    +   * Security fix. Update highly recommended!
    +  
    +  
    +   
    +    1.3.0
    +    1.3.0
    +   
    +   
    +    stable
    +    stable
    +   
    +   2005-06-13
    +   PHP License
    +   * Stable release.  See earlier releases for changes since 1.2.2.
    +  
    +  
    +   
    +    1.3.0RC3
    +    1.3.0
    +   
    +   
    +    beta
    +    stable
    +   
    +   2005-05-10
    +   PHP License
    +   * When verifying requests against function signatures, if the number of parameters don't match, provide an appropriate message.  NOTE: this resolves a path disclosure vulnerability.  (Refines the changes made in the last commit.)  Bug 4231.
    +* XML_RPC_Message::getParam() now returns an XML_RPC_Response object upon error.  Changed from Release 1.3.0RC2.
    +* Add the XML_RPC_Value::isValue() method. For testing if an item is an XML_RPC_Value object.
    +* If XML_RPC_Client::send() is given an incorrect $msg parameter, raise an error with the new XML_RPC_ERROR_PROGRAMMING code and return 0.
    +* Improve cross-platform operation by using PEAR::loadExtension() instead of dl().
    +* Use <br /> instead of <br> in XML_RPC_Value::dump().
    +  
    +  
    +   
    +    1.3.0RC2
    +    1.3.0
    +   
    +   
    +    beta
    +    beta
    +   
    +   2005-05-05
    +   PHP License
    +   * If XML_RPC_Message::getParam() is given an incorrect parameter, raise an error with the new XML_RPC_ERROR_INCORRECT_PARAMS code and return FALSE.
    +* Handle improper requests to XML_RPC_Server::verifySignature().  Bug 4231.
    +* Try to allow HTTP 100 responses if followed by a 200 response.  Bug 4116.
    +* Help Delphi users by making RPCMETHODNAME an alias for METHODNAME.  Request 4205.
    +  
    +  
    +   
    +    1.3.0RC1
    +    1.3.0
    +   
    +   
    +    beta
    +    beta
    +   
    +   2005-04-07
    +   PHP License
    +   * Improve timeout handling for situations where connection to server is made but no response is not received in time. Accomplished via stream_set_timeout().  Request 3963.
    +* Add Fault Code 6: "The requested method didn't return an XML_RPC_Response object."  Request 4032.
    +* Add the createServerPayload() and createServerHeaders() methods and the $server_payload and $server_headers properties.  Request 3121.
    +* As in earlier versions, if the $serviceNow parameter to XML_RPC_Server() is 0, no data will be returned, but now the new $server_payload and $server_headers properties will be set.
    +* Convert the parser handle to an integer before using it as an index for $XML_RPC_xh[$parser].  Reduces E_STRICT notices.  Bug 3782.
    +* Add createHeaders() method and $headers property to XML_RPC_Client to make testing easier.
    +  
    +  
    +   
    +    1.2.2
    +    1.2.0
    +   
    +   
    +    stable
    +    stable
    +   
    +   2005-03-07
    +   PHP License
    +   * When using a proxy, add the protocol to the Request-URI, making it an "absoluteURI" as per the HTTP 1.0 spec.  Bug 3679.
    +  
    +  
    +   
    +    1.2.1
    +    1.2.0
    +   
    +   
    +    stable
    +    stable
    +   
    +   2005-03-01
    +   PHP License
    +   * Add isset() check before examining the dispatch map.  Bug 3658.
    +  
    +  
    +   
    +    1.2.0
    +    1.2.0
    +   
    +   
    +    stable
    +    stable
    +   
    +   2005-02-27
    +   PHP License
    +   * Provide the "stable" release.
    +* Add package2.xml for compatibility with PEAR 1.4.0.
    +* For changes since 1.1.0, see the changelogs for the various RC releases.
    +  
    +  
    +   
    +    1.2.0RC7
    +    1.2.0RC7
    +   
    +   
    +    beta
    +    beta
    +   
    +   2005-02-22
    +   PHP License
    +   * Add the setSendEncoding() method and $send_encoding
    +  property to XML_RPC_Message.  Request 3537.
    +* Allow class methods to be mapped using either syntax:
    +     'function' => 'hello::sayHello',
    +     or
    +     'function' => array('hello', 'sayhello'),
    +  Bug 3363.
    +* Use 8192 instead of 32768 for bytes in fread()
    +  in parseResponseFile().  Bug 3340.
    +  
    +  
    +   
    +    1.2.0RC6
    +    1.2.0RC6
    +   
    +   
    +    beta
    +    beta
    +   
    +   2005-01-25
    +   PHP License
    +   * Don't put the protocol in the Host field of the POST data.  (danielc)
    +  
    +  
    +   
    +    1.2.0RC5
    +    1.2.0RC5
    +   
    +   
    +    beta
    +    beta
    +   
    +   2005-01-24
    +   PHP License
    +   * If $port is 443 but a protocol isn't specified in $server, assume ssl:// is the protocol.
    +  
    +  
    +   
    +    1.2.0RC4
    +    1.2.0RC4
    +   
    +   
    +    beta
    +    beta
    +   
    +   2005-01-24
    +   PHP License
    +   * When a connection attempt fails, have the method return 0.  (danielc)
    +* Move the protocol/port checking/switching and the property settings from sendPayloadHTTP10() to the XML_RPC_Client constructor.  (danielc)
    +* Add tests for setting the client properties.  (danielc)
    +* Remove $GLOBALS['XML_RPC_twoslash'] since it's not used.  (danielc)
    +* Bundle the tests with the package.  (danielc)
    +  
    +  
    +   
    +    1.2.0RC3
    +    1.2.0RC3
    +   
    +   
    +    beta
    +    beta
    +   
    +   2005-01-19
    +   PHP License
    +   * ssl uses port 443, not 445.
    +  
    +  
    +   
    +    1.2.0RC2
    +    1.2.0RC2
    +   
    +   
    +    beta
    +    beta
    +   
    +   2005-01-11
    +   PHP License
    +   * Handle ssl:// in the $server string.  (danielc)
    +* Also default to port 445 for ssl:// requests as well.  (danielc)
    +* Enhance debugging in the server.  (danielc)
    +  
    +  
    +   
    +    1.2.0RC1
    +    1.2.0RC1
    +   
    +   
    +    beta
    +    beta
    +   
    +   2004-12-30
    +   PHP License
    +   * Make things work with SSL.  Bug 2489.  (nkukard lbsd net)
    +* Allow array function callbacks (Matt Kane)
    +* Some minor speed-ups (Matt Kane)
    +* Add Dump.php to the package (Christian Weiske)
    +* Replace all line endings with \r\n.  Had only done replacements on \n.  Bug 2521.  (danielc)
    +* Silence fsockopen() errors.  Bug 1714.  (danielc)
    +* Encode empty arrays as an array. Bug 1493.  (danielc)
    +* Eliminate undefined index notice when submitting empty arrays to XML_RPC_Encode().  Bug 1819.  (danielc)
    +* Speed up check for enumerated arrays in XML_RPC_Encode().  (danielc)
    +* Prepend "XML_RPC_" to ERROR_NON_NUMERIC_FOUND, eliminating problem when eval()'ing error messages.  (danielc)
    +* Use XML_RPC_Base::raiseError() instead of PEAR::raiseError() in XML_RPC_ee() because PEAR.php is lazy loaded.  (danielc)
    +* Allow raiseError() to be called statically.  (danielc)
    +* Stop double escaping of character entities.  Bug 987.  (danielc)
    +  NOTICE: the following have been removed:
    +    * XML_RPC_dh()
    +    * $GLOBALS['XML_RPC_entities']
    +    * XML_RPC_entity_decode()
    +    * XML_RPC_lookup_entity()
    +* Determine the XML's encoding via the encoding attribute in the XML declaration.  Bug 52.  (danielc)
    +  
    +  
    +   
    +    1.1.0
    +    1.1.0
    +   
    +   
    +    stable
    +    stable
    +   
    +   2004-03-15
    +   PHP License
    +   * Added support for sequential arrays to XML_RPC_encode() (mroch)
    +* Cleaned up new XML_RPC_encode() changes a bit (mroch, pierre)
    +* Remove "require_once 'PEAR.php'", include only when needed to raise an error
    +* Replace echo and error_log() with raiseError() (mroch)
    +* Make all classes extend XML_RPC_Base, which will handle common functions  (mroch)
    +* be tolerant of junk after methodResponse (Luca Mariano, mroch)
    +* Silent notice even in the error log (pierre)
    +* fix include of shared xml extension on win32 (pierre)
    +  
    +  
    +   
    +    1.0.4
    +    1.0.4
    +   
    +   
    +    stable
    +    stable
    +   
    +   2002-10-02
    +   PHP License
    +   * added HTTP proxy authorization support (thanks to Arnaud Limbourg)
    +  
    +  
    +   
    +    1.0.3
    +    1.0.3
    +   
    +   
    +    stable
    +    stable
    +   
    +   2002-05-19
    +   PHP License
    +   * fix bug when parsing responses with boolean types
    +  
    +  
    +   
    +    1.0.2
    +    1.0.2
    +   
    +   
    +    stable
    +    stable
    +   
    +   2002-04-16
    +   PHP License
    +   * E_ALL fixes
    +* fix HTTP response header parsing
    +  
    +  
    +   
    +    1.0.1
    +    1.0.1
    +   
    +   
    +    stable
    +    stable
    +   
    +   2001-09-25
    +   PHP License
    +   This is a PEAR-ified version of Useful Inc's 1.0.1 release.
    +Includes an urgent security fix identified by Dan Libby <dan@libby.com>.
    +  
    + 
    +
    diff --git a/src/popup.php b/src/popup.php
    new file mode 100644
    index 0000000..42d4705
    --- /dev/null
    +++ b/src/popup.php
    @@ -0,0 +1,16 @@
    +
    +
    +
    +Galaxy-Network Scan + +
    + +
    +/i","\n",$scan);
    +echo $scan;
    +?>
    +
    + + \ No newline at end of file diff --git a/src/reset.php b/src/reset.php new file mode 100644 index 0000000..e3b656c --- /dev/null +++ b/src/reset.php @@ -0,0 +1,35 @@ +reset templates_c:
    "; +$dir = "./templates_c/"; +$fh = opendir($dir); +while($entry = readdir($fh)) { + if($entry == ".." || $entry == ".") + continue; + if(is_dir($dir . $entry)) { + echo "delete dir ".$dir . $entry . "/
    "; + deltree($dir . $entry . "/"); + } else { + echo "delete file ".$dir . $entry . "/
    "; + unlink($dir . $entry); + } +} +closedir($fh); + +?> \ No newline at end of file diff --git a/src/scans.php b/src/scans.php new file mode 100644 index 0000000..1c922b9 --- /dev/null +++ b/src/scans.php @@ -0,0 +1,7 @@ +run(); +?> \ No newline at end of file diff --git a/src/sessions/.htaccess b/src/sessions/.htaccess new file mode 100644 index 0000000..cffd5d4 --- /dev/null +++ b/src/sessions/.htaccess @@ -0,0 +1,8 @@ + +AuthUserFile /www/htdocs/w00acdb0//sessions//.htpasswd +AuthGroupFile /dev/null +AuthName ByPassword +AuthType Basic + +require user w00acdb0 + diff --git a/src/sessions/.htpasswd b/src/sessions/.htpasswd new file mode 100644 index 0000000..ede8113 --- /dev/null +++ b/src/sessions/.htpasswd @@ -0,0 +1 @@ +w00acdb0:$1$roy.SttY$5EIDRe/ip5oZ5QlKRGb2E0 diff --git a/src/simulator.php b/src/simulator.php new file mode 100644 index 0000000..e677c60 --- /dev/null +++ b/src/simulator.php @@ -0,0 +1,7 @@ +run(); +?> \ No newline at end of file diff --git a/src/takscreen.php b/src/takscreen.php new file mode 100644 index 0000000..eeec61e --- /dev/null +++ b/src/takscreen.php @@ -0,0 +1,6 @@ +run(); +?> \ No newline at end of file diff --git a/src/templates/.#index.html.1.10 b/src/templates/.#index.html.1.10 new file mode 100644 index 0000000..e69de29 diff --git a/src/templates/admin_fleetupdate_form.html b/src/templates/admin_fleetupdate_form.html new file mode 100644 index 0000000..836d23b --- /dev/null +++ b/src/templates/admin_fleetupdate_form.html @@ -0,0 +1,87 @@ +
    + + + + + +
    + + + + + + + + +
    + + {_Icon} + + + {_Title} +
    +
    + + + +
    {Filler} + Warning: This package management website is not protected with a password, this is a MAJOR security risk. Please read the README. +
    + + diff --git a/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/upgrade_all.tpl.html b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/upgrade_all.tpl.html new file mode 100644 index 0000000..b30f24a --- /dev/null +++ b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/upgrade_all.tpl.html @@ -0,0 +1,13 @@ + + + + + +
    +   + +
    + + +
    +
    diff --git a/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/userDialog.tpl.html b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/userDialog.tpl.html new file mode 100644 index 0000000..f9fec84 --- /dev/null +++ b/src/lib/pear/PEAR/data/PEAR_Frontend_Web/data/templates/userDialog.tpl.html @@ -0,0 +1,16 @@ + +
    + + + + + + + +
    + {prompt}: + + +
    + {cancel} +
    diff --git a/src/lib/pear/PEAR/data/Structures_Graph/LICENSE b/src/lib/pear/PEAR/data/Structures_Graph/LICENSE new file mode 100644 index 0000000..b1e3f5a --- /dev/null +++ b/src/lib/pear/PEAR/data/Structures_Graph/LICENSE @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/src/lib/pear/PEAR/data/Structures_Graph/genpackage.xml.pl b/src/lib/pear/PEAR/data/Structures_Graph/genpackage.xml.pl new file mode 100644 index 0000000..3b54fe7 --- /dev/null +++ b/src/lib/pear/PEAR/data/Structures_Graph/genpackage.xml.pl @@ -0,0 +1,16 @@ +#!/usr/bin/perl +while (<>) { + if (!/FILESGOHERE/) { + print $_; + } else { + open FILELIST,'find Structures -type f | grep -v .arch-ids |'; + while () { + $md5sum = `md5sum $_`; + chomp($md5sum); + $md5sum = substr $md5sum, 0, 32; +# $_ =~ s/\//\\\//g; + chomp($_); + print " \n"; + } + } +} diff --git a/src/lib/pear/PEAR/data/Structures_Graph/package.sh b/src/lib/pear/PEAR/data/Structures_Graph/package.sh new file mode 100644 index 0000000..11c36c2 --- /dev/null +++ b/src/lib/pear/PEAR/data/Structures_Graph/package.sh @@ -0,0 +1,51 @@ +#!/bin/bash +VERSION=`tla tree-version 2>&1 | sed "s/^.*\([0-9][0-9]*\.[0-9][0-9]*\)$/\1/g"` +TARGET_DIR=BUILD/ +TARGET_DIRS=`find Structures -type d | grep -v .arch-ids` +mkdir -p $TARGET_DIR +./genpackage.xml.pl > BUILD/package.xml << EOF + + + Structures_Graph + Graph datastructure manipulation library + LGPL + + Structures_Graph is a package for creating and manipulating graph datastructures. It allows building of directed + and undirected graphs, with data and metadata stored in nodes. The library provides functions for graph traversing + as well as for characteristic extraction from the graph topology. + + + + sergiosgc + Sérgio Carvalho + sergio.carvalho@portugalmail.com + lead + + + + + 1.0.3 + 2007-01-30 + stable + + Version 1.0.3 is functionally equivalent to 1.0.2, but released with a v1.0 package.xml to deal with bug #9965:installation problem + + +FILESGOHERE + + + + PEAR + + +EOF +for dir in $TARGET_DIRS +do + mkdir -p $TARGET_DIR/$dir + cp `find $dir -maxdepth 1 -type f | grep -v .arch-ids` $TARGET_DIR/$dir +done +cp LICENSE BUILD +(cd BUILD; pear package) +rm -Rf BUILD/package.xml BUILD/LICENSE BUILD/Structures + + diff --git a/src/lib/pear/PEAR/data/Structures_Graph/publish.sh b/src/lib/pear/PEAR/data/Structures_Graph/publish.sh new file mode 100644 index 0000000..1632e23 --- /dev/null +++ b/src/lib/pear/PEAR/data/Structures_Graph/publish.sh @@ -0,0 +1,5 @@ +#!/bin/sh +./package.sh +scp BUILD/*.tgz root@sergiocarvalho.com:/home/httpd/vhosts/com/sergiocarvalho/pear-base/pear +(cd docs; ./generate.sh) +scp -r docs/html/* root@iluvatar.portugalmail.pt:/home/httpd/vhosts/com/sergiocarvalho/pear-base/pear/docs/Structures_Graph diff --git a/src/lib/pear/PEAR/docs/Archive_Tar/docs/Archive_Tar.txt b/src/lib/pear/PEAR/docs/Archive_Tar/docs/Archive_Tar.txt new file mode 100644 index 0000000..623cafe --- /dev/null +++ b/src/lib/pear/PEAR/docs/Archive_Tar/docs/Archive_Tar.txt @@ -0,0 +1,461 @@ +Documentation for class Archive_Tar +=================================== +Last update : 2001-08-15 + + + +Overview : +---------- + + The Archive_Tar class helps in creating and managing GNU TAR format + files compressed by GNU ZIP or not. + The class offers basic functions like creating an archive, adding + files in the archive, extracting files from the archive and listing + the archive content. + It also provide advanced functions that allow the adding and + extraction of files with path manipulation. + + +Sample : +-------- + + // ----- Creating the object (uncompressed archive) + $tar_object = new Archive_Tar("tarname.tar"); + $tar_object->setErrorHandling(PEAR_ERROR_PRINT); + + // ----- Creating the archive + $v_list[0]="file.txt"; + $v_list[1]="data/"; + $v_list[2]="file.log"; + $tar_object->create($v_list); + + // ----- Adding files + $v_list[0]="dev/file.txt"; + $v_list[1]="dev/data/"; + $v_list[2]="log/file.log"; + $tar_object->add($v_list); + + // ----- Adding more files + $tar_object->add("release/newfile.log release/readme.txt"); + + // ----- Listing the content + if (($v_list = $tar_object->listContent()) != 0) + for ($i=0; $i"; + echo " .size :'".$v_list[$i][size]."'
    "; + echo " .mtime :'".$v_list[$i][mtime]."' (".date("l dS of F Y h:i:s A", $v_list[$i][mtime]).")
    "; + echo " .mode :'".$v_list[$i][mode]."'
    "; + echo " .uid :'".$v_list[$i][uid]."'
    "; + echo " .gid :'".$v_list[$i][gid]."'
    "; + echo " .typeflag :'".$v_list[$i][typeflag]."'
    "; + } + + // ----- Extracting the archive in directory "install" + $tar_object->extract("install"); + + +Public arguments : +------------------ + +None + + +Public Methods : +---------------- + +Method : Archive_Tar($p_tarname, $compress = null) +Description : + Archive_Tar Class constructor. This flavour of the constructor only + declare a new Archive_Tar object, identifying it by the name of the + tar file. + If the compress argument is set the tar will be read or created as a + gzip or bz2 compressed TAR file. +Arguments : + $p_tarname : A valid filename for the tar archive file. + $p_compress : can be null, 'gz' or 'bz2'. For + compatibility reason it can also be true. This + parameter indicates if gzip or bz2 compression + is required. +Return value : + The Archive_Tar object. +Sample : + $tar_object = new Archive_Tar("tarname.tar"); + $tar_object_compressed = new Archive_Tar("tarname.tgz", true); +How it works : + Initialize the object. + +Method : create($p_filelist) +Description : + This method creates the archive file and add the files / directories + that are listed in $p_filelist. + If the file already exists and is writable, it is replaced by the + new tar. It is a create and not an add. If the file exists and is + read-only or is a directory it is not replaced. The method return + false and a PEAR error text. + The $p_filelist parameter can be an array of string, each string + representing a filename or a directory name with their path if + needed. It can also be a single string with names separated by a + single blank. + See also createModify() method for more details. +Arguments : + $p_filelist : An array of filenames and directory names, or a single + string with names separated by a single blank space. +Return value : + true on success, false on error. +Sample 1 : + $tar_object = new Archive_Tar("tarname.tar"); + $tar_object->setErrorHandling(PEAR_ERROR_PRINT); // Optional error handling + $v_list[0]="file.txt"; + $v_list[1]="data/"; (Optional '/' at the end) + $v_list[2]="file.log"; + $tar_object->create($v_list); +Sample 2 : + $tar_object = new Archive_Tar("tarname.tar"); + $tar_object->setErrorHandling(PEAR_ERROR_PRINT); // Optional error handling + $tar_object->create("file.txt data/ file.log"); +How it works : + Just calling the createModify() method with the right parameters. + +Method : createModify($p_filelist, $p_add_dir, $p_remove_dir = "") +Description : + This method creates the archive file and add the files / directories + that are listed in $p_filelist. + If the file already exists and is writable, it is replaced by the + new tar. It is a create and not an add. If the file exists and is + read-only or is a directory it is not replaced. The method return + false and a PEAR error text. + The $p_filelist parameter can be an array of string, each string + representing a filename or a directory name with their path if + needed. It can also be a single string with names separated by a + single blank. + The path indicated in $p_remove_dir will be removed from the + memorized path of each file / directory listed when this path + exists. By default nothing is removed (empty path "") + The path indicated in $p_add_dir will be added at the beginning of + the memorized path of each file / directory listed. However it can + be set to empty "". The adding of a path is done after the removing + of path. + The path add/remove ability enables the user to prepare an archive + for extraction in a different path than the origin files are. + See also addModify() method for file adding properties. +Arguments : + $p_filelist : An array of filenames and directory names, or a single + string with names separated by a single blank space. + $p_add_dir : A string which contains a path to be added to the + memorized path of each element in the list. + $p_remove_dir : A string which contains a path to be removed from + the memorized path of each element in the list, when + relevant. +Return value : + true on success, false on error. +Sample 1 : + $tar_object = new Archive_Tar("tarname.tar"); + $tar_object->setErrorHandling(PEAR_ERROR_PRINT); // Optional error handling + $v_list[0]="file.txt"; + $v_list[1]="data/"; (Optional '/' at the end) + $v_list[2]="file.log"; + $tar_object->createModify($v_list, "install"); + // files are stored in the archive as : + // install/file.txt + // install/data + // install/data/file1.txt + // install/data/... all the files and sub-dirs of data/ + // install/file.log +Sample 2 : + $tar_object = new Archive_Tar("tarname.tar"); + $tar_object->setErrorHandling(PEAR_ERROR_PRINT); // Optional error handling + $v_list[0]="dev/file.txt"; + $v_list[1]="dev/data/"; (Optional '/' at the end) + $v_list[2]="log/file.log"; + $tar_object->createModify($v_list, "install", "dev"); + // files are stored in the archive as : + // install/file.txt + // install/data + // install/data/file1.txt + // install/data/... all the files and sub-dirs of data/ + // install/log/file.log +How it works : + Open the file in write mode (erasing the existing one if one), + call the _addList() method for adding the files in an empty archive, + add the tar footer (512 bytes block), close the tar file. + + +Method : addModify($p_filelist, $p_add_dir, $p_remove_dir="") +Description : + This method add the files / directories listed in $p_filelist at the + end of the existing archive. If the archive does not yet exists it + is created. + The $p_filelist parameter can be an array of string, each string + representing a filename or a directory name with their path if + needed. It can also be a single string with names separated by a + single blank. + The path indicated in $p_remove_dir will be removed from the + memorized path of each file / directory listed when this path + exists. By default nothing is removed (empty path "") + The path indicated in $p_add_dir will be added at the beginning of + the memorized path of each file / directory listed. However it can + be set to empty "". The adding of a path is done after the removing + of path. + The path add/remove ability enables the user to prepare an archive + for extraction in a different path than the origin files are. + If a file/dir is already in the archive it will only be added at the + end of the archive. There is no update of the existing archived + file/dir. However while extracting the archive, the last file will + replace the first one. This results in a none optimization of the + archive size. + If a file/dir does not exist the file/dir is ignored. However an + error text is send to PEAR error. + If a file/dir is not readable the file/dir is ignored. However an + error text is send to PEAR error. + If the resulting filename/dirname (after the add/remove option or + not) string is greater than 99 char, the file/dir is + ignored. However an error text is send to PEAR error. +Arguments : + $p_filelist : An array of filenames and directory names, or a single + string with names separated by a single blank space. + $p_add_dir : A string which contains a path to be added to the + memorized path of each element in the list. + $p_remove_dir : A string which contains a path to be removed from + the memorized path of each element in the list, when + relevant. +Return value : + true on success, false on error. +Sample 1 : + $tar_object = new Archive_Tar("tarname.tar"); + [...] + $v_list[0]="dev/file.txt"; + $v_list[1]="dev/data/"; (Optional '/' at the end) + $v_list[2]="log/file.log"; + $tar_object->addModify($v_list, "install"); + // files are stored in the archive as : + // install/file.txt + // install/data + // install/data/file1.txt + // install/data/... all the files and sub-dirs of data/ + // install/file.log +Sample 2 : + $tar_object = new Archive_Tar("tarname.tar"); + [...] + $v_list[0]="dev/file.txt"; + $v_list[1]="dev/data/"; (Optional '/' at the end) + $v_list[2]="log/file.log"; + $tar_object->addModify($v_list, "install", "dev"); + // files are stored in the archive as : + // install/file.txt + // install/data + // install/data/file1.txt + // install/data/... all the files and sub-dirs of data/ + // install/log/file.log +How it works : + If the archive does not exists it create it and add the files. + If the archive does exists and is not compressed, it open it, jump + before the last empty 512 bytes block (tar footer) and add the files + at this point. + If the archive does exists and is compressed, a temporary copy file + is created. This temporary file is then 'gzip' read block by block + until the last empty block. The new files are then added in the + compressed file. + The adding of files is done by going through the file/dir list, + adding files per files, in a recursive way through the + directory. Each time a path need to be added/removed it is done + before writing the file header in the archive. + +Method : add($p_filelist) +Description : + This method add the files / directories listed in $p_filelist at the + end of the existing archive. If the archive does not yet exists it + is created. + The $p_filelist parameter can be an array of string, each string + representing a filename or a directory name with their path if + needed. It can also be a single string with names separated by a + single blank. + See addModify() method for details and limitations. +Arguments : + $p_filelist : An array of filenames and directory names, or a single + string with names separated by a single blank space. +Return value : + true on success, false on error. +Sample 1 : + $tar_object = new Archive_Tar("tarname.tar"); + [...] + $v_list[0]="dev/file.txt"; + $v_list[1]="dev/data/"; (Optional '/' at the end) + $v_list[2]="log/file.log"; + $tar_object->add($v_list); +Sample 2 : + $tar_object = new Archive_Tar("tarname.tgz", true); + [...] + $v_list[0]="dev/file.txt"; + $v_list[1]="dev/data/"; (Optional '/' at the end) + $v_list[2]="log/file.log"; + $tar_object->add($v_list); +How it works : + Simply call the addModify() method with the right parameters. + +Method : addString($p_filename, $p_string) +Description : + This method add a single string as a file at the + end of the existing archive. If the archive does not yet exists it + is created. +Arguments : + $p_filename : A string which contains the full filename path + that will be associated with the string. + $p_string : The content of the file added in the archive. +Return value : + true on success, false on error. +Sample 1 : + $v_archive = & new Archive_Tar($p_filename); + $v_archive->setErrorHandling(PEAR_ERROR_PRINT); + $v_result = $v_archive->addString('data/test.txt', 'This is the text of the string'); + + +Method : extract($p_path = "") +Description : + This method extract all the content of the archive in the directory + indicated by $p_path.If $p_path is optional, if not set the archive + is extracted in the current directory. + While extracting a file, if the directory path does not exists it is + created. + See extractModify() for details and limitations. +Arguments : + $p_path : Optional path where the files/dir need to by extracted. +Return value : + true on success, false on error. +Sample : + $tar_object = new Archive_Tar("tarname.tar"); + $tar_object->extract(); +How it works : + Simply call the extractModify() method with appropriate parameters. + +Method : extractModify($p_path, $p_remove_path) +Description : + This method extract all the content of the archive in the directory + indicated by $p_path. When relevant the memorized path of the + files/dir can be modified by removing the $p_remove_path path at the + beginning of the file/dir path. + While extracting a file, if the directory path does not exists it is + created. + While extracting a file, if the file already exists it is replaced + without looking for last modification date. + While extracting a file, if the file already exists and is write + protected, the extraction is aborted. + While extracting a file, if a directory with the same name already + exists, the extraction is aborted. + While extracting a directory, if a file with the same name already + exists, the extraction is aborted. + While extracting a file/directory if the destination directory exist + and is write protected, or does not exist but can not be created, + the extraction is aborted. + If after extraction an extracted file does not show the correct + stored file size, the extraction is aborted. + When the extraction is aborted, a PEAR error text is set and false + is returned. However the result can be a partial extraction that may + need to be manually cleaned. +Arguments : + $p_path : The path of the directory where the files/dir need to by + extracted. + $p_remove_path : Part of the memorized path that can be removed if + present at the beginning of the file/dir path. +Return value : + true on success, false on error. +Sample : + // Imagine tarname.tar with files : + // dev/data/file.txt + // dev/data/log.txt + // readme.txt + $tar_object = new Archive_Tar("tarname.tar"); + $tar_object->extractModify("install", "dev"); + // Files will be extracted there : + // install/data/file.txt + // install/data/log.txt + // install/readme.txt +How it works : + Open the archive and call a more generic function that can extract + only a part of the archive or all the archive. + See extractList() method for more details. + +Method : extractInString($p_filename) +Description : + This method extract from the archive one file identified by $p_filename. + The return value is a string with the file content, or NULL on error. +Arguments : + $p_filename : The path of the file to extract in a string. +Return value : + a string with the file content or NULL. +Sample : + // Imagine tarname.tar with files : + // dev/data/file.txt + // dev/data/log.txt + // dev/readme.txt + $v_archive = & new Archive_Tar('tarname.tar'); + $v_archive->setErrorHandling(PEAR_ERROR_PRINT); + $v_string = $v_archive->extractInString('dev/readme.txt'); + echo $v_string; + +Method : listContent() +Description : + This method returns an array of arrays that describe each + file/directory present in the archive. + The array is not sorted, so it show the position of the file in the + archive. + The file informations are : + $file[filename] : Name and path of the file/dir. + $file[mode] : File permissions (result of fileperms()) + $file[uid] : user id + $file[gid] : group id + $file[size] : filesize + $file[mtime] : Last modification time (result of filemtime()) + $file[typeflag] : "" for file, "5" for directory +Arguments : +Return value : + An array of arrays or 0 on error. +Sample : + $tar_object = new Archive_Tar("tarname.tar"); + if (($v_list = $tar_object->listContent()) != 0) + for ($i=0; $i"; + echo " .size :'".$v_list[$i][size]."'
    "; + echo " .mtime :'".$v_list[$i][mtime]."' (". + date("l dS of F Y h:i:s A", $v_list[$i][mtime]).")
    "; + echo " .mode :'".$v_list[$i][mode]."'
    "; + echo " .uid :'".$v_list[$i][uid]."'
    "; + echo " .gid :'".$v_list[$i][gid]."'
    "; + echo " .typeflag :'".$v_list[$i][typeflag]."'
    "; + } +How it works : + Call the same function as an extract however with a flag to only go + through the archive without extracting the files. + +Method : extractList($p_filelist, $p_path = "", $p_remove_path = "") +Description : + This method extract from the archive only the files indicated in the + $p_filelist. These files are extracted in the current directory or + in the directory indicated by the optional $p_path parameter. + If indicated the $p_remove_path can be used in the same way as it is + used in extractModify() method. +Arguments : + $p_filelist : An array of filenames and directory names, or a single + string with names separated by a single blank space. + $p_path : The path of the directory where the files/dir need to by + extracted. + $p_remove_path : Part of the memorized path that can be removed if + present at the beginning of the file/dir path. +Return value : + true on success, false on error. +Sample : + // Imagine tarname.tar with files : + // dev/data/file.txt + // dev/data/log.txt + // readme.txt + $tar_object = new Archive_Tar("tarname.tar"); + $tar_object->extractList("dev/data/file.txt readme.txt", "install", + "dev"); + // Files will be extracted there : + // install/data/file.txt + // install/readme.txt +How it works : + Go through the archive and extract only the files present in the + list. + diff --git a/src/lib/pear/PEAR/docs/Config/docs/Apache.php b/src/lib/pear/PEAR/docs/Config/docs/Apache.php new file mode 100644 index 0000000..5987ed1 --- /dev/null +++ b/src/lib/pear/PEAR/docs/Config/docs/Apache.php @@ -0,0 +1,57 @@ + +* @package Config +*/ +// $Id: Apache.php,v 1.2 2003/03/22 17:44:12 mansion Exp $ + +require_once('Config.php'); + +$datasrc = '/path/to/httpd.conf'; +$conf = new Config(); +$content =& $conf->parseConfig($datasrc, 'apache'); +if (PEAR::isError($content)) { + die($content->getMessage()); +} + +// adding a new virtual-host + +$content->createBlank(); +$content->createComment('My virtual host'); +$content->createBlank(); + +$vhost =& $content->createSection('VirtualHost', array('127.0.0.1:82')); +$vhost->createDirective('DocumentRoot', '/usr/share/www'); +$vhost->createDirective('ServerName', 'www.mamasam.com'); +$location =& $vhost->createSection('Location', array('/admin')); +$location->createDirective('AuthType', 'basic'); +$location->createDirective('Require', 'group admin'); + +// adding some directives Listen + +if ($listen =& $content->getItem('directive', 'Listen')) { + $res =& $content->createDirective('Listen', '82', null, 'after', $listen); +} else { + $listen =& $content->createDirective('Listen', '81', null, 'bottom'); + if (PEAR::isError($listen)) { + die($listen->getMessage()); + } + $content->createDirective('Listen', '82', null, 'after', $listen); +} + +echo '
    '.htmlspecialchars($content->toString('apache')).'
    '; + +// Writing the files +/* +if (!PEAR::isError($write = $conf->writeConfig('/tmp/httpd.conf', 'apache'))) { + echo 'done writing config
    '; +} else { + die($write->getMessage()); +} + +if ($vhost->writeDatasrc('/tmp/vhost.conf', 'apache')) { + echo 'done writing vhost
    '; +} +*/ +?> \ No newline at end of file diff --git a/src/lib/pear/PEAR/docs/Config/docs/IniCommented.php b/src/lib/pear/PEAR/docs/Config/docs/IniCommented.php new file mode 100644 index 0000000..a155616 --- /dev/null +++ b/src/lib/pear/PEAR/docs/Config/docs/IniCommented.php @@ -0,0 +1,25 @@ + +* @package Config +*/ +// $Id: IniCommented.php,v 1.4 2005/12/24 02:16:57 aashley Exp $ + +require_once('Config.php'); + +$datasrc = '/usr/local/php5/lib/php.ini'; + +$phpIni = new Config(); +$root =& $phpIni->parseConfig($datasrc, 'inicommented'); +if (PEAR::isError($root)) { + die($root->getMessage()); +} + +// Convert your ini file to a php array config + +echo '
    '.$root->toString('phparray', array('name' => 'php_ini')).'
    '; +?> diff --git a/src/lib/pear/PEAR/docs/Config/docs/IniFromScratch.php b/src/lib/pear/PEAR/docs/Config/docs/IniFromScratch.php new file mode 100644 index 0000000..0dff589 --- /dev/null +++ b/src/lib/pear/PEAR/docs/Config/docs/IniFromScratch.php @@ -0,0 +1,80 @@ + +* @package Config +*/ +// $Id: IniFromScratch.php,v 1.2 2003/03/21 18:04:21 mansion Exp $ + +require_once('Config.php'); + +// Creates a PHPArray config with attributes, from scratch + +$dsn = array('type' => 'mysql', + 'host' => 'localhost', + 'user' => 'mamasam', + 'pass' => 'foobar'); + +$c = new Config_Container('section', 'root'); + $c->createComment('DB Config'); + $db =& $c->createSection('DB', $dsn); + $fields =& $db->createSection('fields'); + $fields->createDirective('username', 'USERNAME', array('type' => 'varchar', 'size' => 32)); + $fields->createDirective('password', 'PASSWD', array('type' => 'varchar', 'size' => 32)); + $c->createBlank(); + $c->createComment('Support config'); + $c->createDirective('support', 'See my wishlist...'); + +echo '
    '. $c->toString('phparray') .'
    '; +unset($c); + +// Parses and writes an existing php array $conf + +$conf['storage']['driver'] = 'sql'; +$conf['storage']['params']['phptype'] = 'mysql'; +$conf['storage']['params']['hostspec'] = 'localhost'; +$conf['storage']['params']['username'] = 'mamasam'; +$conf['storage']['params']['password'] = 'foobar'; +$conf['menu']['apps'] = array('imp', 'turba'); +$conf['stdcontent']['para'][0] = 'This is really cool !'; +$conf['stdcontent']['para'][1] = 'It just rocks...'; + +$c = new Config(); +$root =& $c->parseConfig($conf, 'phparray'); + +$storage =& $root->getItem('section', 'storage'); +$storage->removeItem(); +$root->addItem($storage); + +echo '
    '. $root->toString('phparray', array('name' => 'test')) .'
    '; + +if ($c->writeConfig('/tmp/Config_Test.php', 'phparray', array('name' => 'test')) === true) { + echo 'Config written into /tmp/Config_Test.php'; +} + +// Making a php ini file with $storage only + +$ini = new Config(); +$iniRoot =& $ini->getRoot(); +$iniRoot->addItem($storage); + +$comment =& new Config_Container('comment', null, 'This is the php ini version of storage'); +$iniRoot->addItem($comment, 'top'); +$iniRoot->createBlank('after', $comment); +echo '
    '. $iniRoot->toString('inicommented') .'
    '; + +// Gonna make an array with it + +echo '
    '; var_dump($iniRoot->toArray()); echo '
    '; + +// Now, I'll parse you php.ini file and make it a php array + +$phpIni = new Config(); +$phpIni->parseConfig('/usr/local/lib/php.ini', 'inifile'); +$root =& $phpIni->getRoot(); +echo '
    '.$root->toString('phparray', array('name' => 'php_ini')).'
    '; + +?> \ No newline at end of file diff --git a/src/lib/pear/PEAR/docs/HTML_Template_IT/LICENSE b/src/lib/pear/PEAR/docs/HTML_Template_IT/LICENSE new file mode 100644 index 0000000..0857cce --- /dev/null +++ b/src/lib/pear/PEAR/docs/HTML_Template_IT/LICENSE @@ -0,0 +1,22 @@ +Redistribution and use in source and binary forms, with or without modification +, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, th + is list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/ + or other materials provided with the distribution. + +3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WA +RRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABIL +ITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR C +ONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOW +EVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILI +TY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE U +SE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/src/lib/pear/PEAR/docs/HTML_Template_IT/examples/sample_it.php b/src/lib/pear/PEAR/docs/HTML_Template_IT/examples/sample_it.php new file mode 100644 index 0000000..1fe2ac2 --- /dev/null +++ b/src/lib/pear/PEAR/docs/HTML_Template_IT/examples/sample_it.php @@ -0,0 +1,27 @@ + array('Stig', 'Bakken'), + '1' => array('Martin', 'Jansen'), + '2' => array('Alexander', 'Merz') +); + +$tpl = new HTML_Template_IT('./templates'); +$tpl->loadTemplatefile('main.tpl.htm', true, true); + +foreach ($data as $name) { + foreach ($name as $cell) { + // Assign data to the inner block + $tpl->setCurrentBlock('cell'); + $tpl->setVariable('DATA', $cell); + $tpl->parseCurrentBlock(); + } + // Assign data and the inner block to the + // outer block + $tpl->setCurrentBlock('row'); + $tpl->parseCurrentBlock(); +} +// print the output +$tpl->show(); +?> diff --git a/src/lib/pear/PEAR/docs/HTML_Template_IT/examples/sample_itx_addblockfile.php b/src/lib/pear/PEAR/docs/HTML_Template_IT/examples/sample_itx_addblockfile.php new file mode 100644 index 0000000..aed3f58 --- /dev/null +++ b/src/lib/pear/PEAR/docs/HTML_Template_IT/examples/sample_itx_addblockfile.php @@ -0,0 +1,58 @@ +'mypackage', + 'version' =>'1.0', + 'changelog' => array ('fix bug #002', + 'add author FOO to AUTHORS') + ), + array ('packagename'=>'mypackage', + 'version' =>'1.0 RC 1', + 'changelog' => array ('fix bug #002', + 'added method foo()') + ) + ); + +$tpl = new HTML_Template_ITX('./templates'); +$tpl->loadTemplatefile('addblockfile_main.tpl.htm', true, true); + +// The complete content of "addblockfile_main.tpl.htm" will be loaded into a block +// called "list_template". The placeholder {DESCRIPTION} will be replaced +// with the added block "list_template". +$tpl->addBlockfile('DESCRIPTION', 'list_template', 'addblockfile_list.tpl.htm'); + + +// we now have the following blocks loaded: +// __global__, row, list_template and listelement +// lets assign the data. +foreach ($data as $entry) { + // assign data to the inner block (listelement) of list_template. + $tpl->setCurrentBlock('listelement'); + foreach ($entry['changelog'] as $changelogentry) { + $tpl->setVariable('ENTRY', $changelogentry); + $tpl->parseCurrentBlock(); + } + + // assign data to the added list_template block + $tpl->setCurrentBlock('list_template'); + $tpl->setVariable('LISTNAME', $entry['version']); + $tpl->parseCurrentBlock(); + + // back in the original templatefile we assign data to the row block + // notice: + // {DESCRIPTION} is not longer available, because it was replaced by the + // list_template block + $tpl->setCurrentBlock('row'); + $tpl->setVariable('NAME', $entry['packagename']); + $tpl->parseCurrentBlock(); +} + +$tpl->show(); +?> diff --git a/src/lib/pear/PEAR/docs/HTML_Template_IT/examples/templates/addblockfile_list.tpl.htm b/src/lib/pear/PEAR/docs/HTML_Template_IT/examples/templates/addblockfile_list.tpl.htm new file mode 100644 index 0000000..69e470b --- /dev/null +++ b/src/lib/pear/PEAR/docs/HTML_Template_IT/examples/templates/addblockfile_list.tpl.htm @@ -0,0 +1,6 @@ +{LISTNAME} +
      + +
    • {ENTRY}
    • + +
    \ No newline at end of file diff --git a/src/lib/pear/PEAR/docs/HTML_Template_IT/examples/templates/addblockfile_main.tpl.htm b/src/lib/pear/PEAR/docs/HTML_Template_IT/examples/templates/addblockfile_main.tpl.htm new file mode 100644 index 0000000..db9e239 --- /dev/null +++ b/src/lib/pear/PEAR/docs/HTML_Template_IT/examples/templates/addblockfile_main.tpl.htm @@ -0,0 +1,12 @@ + + + + + + + + + +
    {NAME}{DESCRIPTION}
    + + \ No newline at end of file diff --git a/src/lib/pear/PEAR/docs/HTML_Template_IT/examples/templates/main.tpl.htm b/src/lib/pear/PEAR/docs/HTML_Template_IT/examples/templates/main.tpl.htm new file mode 100644 index 0000000..271feca --- /dev/null +++ b/src/lib/pear/PEAR/docs/HTML_Template_IT/examples/templates/main.tpl.htm @@ -0,0 +1,13 @@ + + + + + + + + + +
    + {DATA} +
    + diff --git a/src/lib/pear/PEAR/docs/PEAR/INSTALL b/src/lib/pear/PEAR/docs/PEAR/INSTALL new file mode 100644 index 0000000..2e15a6c --- /dev/null +++ b/src/lib/pear/PEAR/docs/PEAR/INSTALL @@ -0,0 +1,53 @@ +PEAR - The PEAR Installer +========================= +Installing the PEAR Installer. + +You should install PEAR on a local development machine first. Installing +PEAR on a remote production machine should only be done after you are +familiar with PEAR and have tested code using PEAR on your development +machine. + +There are two methods of installing PEAR + - PEAR bundled in PHP + - go-pear + +We will first examine how to install PEAR that is bundled with PHP. + +Microsoft Windows +================= +If you are running PHP 5.2.0 or newer, simply download and +run the windows installer (.msi) and PEAR can be automatically +installed. + +Otherwise, for older PHP versions, download the .zip of windows, +there is a script included with your PHP distribution that is called +"go-pear". You must open a command box in order to run it. Click +"start" then click "Run..." and type "cmd.exe" to open a command box. +Use "cd" to change directory to the location of PHP where you unzipped it, +and run the go-pear command. + +Unix +==== +make sure you have enabled default extensions, and if you want faster +downloads, enable the zlib extension. You must also enable the CLI +SAPI with the --enable-cli extension directive. After this, simply run: + +make install-pear + +and PEAR will be automatically configured for you. + +go-pear +======= +For users who cannot perform the above steps, or who wish to obtain the +latest PEAR with a slightly higher risk of failure, use go-pear. go-pear +is obtained by downloading http://go-pear.org and saving it as go-pear.php. +After downloading, simply run "php go-pear.php" or open it in a web browser +(windows only) to download and install PEAR. + +You can always ask general installation questions on pear-general@lists.php.net, +a public mailing list devoted to support for PEAR packages and installation- +related issues. + +Happy PHPing, we hope PEAR will be a great tool for your development work! + +$Id: INSTALL,v 1.1 2006/09/22 03:31:36 cellog Exp $ \ No newline at end of file diff --git a/src/lib/pear/PEAR/docs/PEAR/README b/src/lib/pear/PEAR/docs/PEAR/README new file mode 100644 index 0000000..cb5dea4 --- /dev/null +++ b/src/lib/pear/PEAR/docs/PEAR/README @@ -0,0 +1,32 @@ +PEAR - The PEAR Installer +========================= + +What is the PEAR Installer? What is PEAR? + +PEAR is the PHP Extension and Application Repository, found at +http://pear.php.net. The PEAR Installer is this software, which +contains executable files and PHP code that is used to download +and install PEAR code from pear.php.net. + +PEAR contains useful software libraries and applications such as +MDB2 (database abstraction), HTML_QuickForm (HTML forms management), +PhpDocumentor (auto-documentation generator), DB_DataObject +(Data Access Abstraction), and many hundreds more. Browse all +available packages at http://pear.php.net, the list is constantly +growing and updating to reflect improvements in the PHP language. + +DOCUMENTATION +============= + +Documentation for PEAR can be found at http://pear.php.net/manual/. +Installation documentation can be found in the INSTALL file included +in this tarball. + +WARNING: DO NOT RUN PEAR WITHOUT INSTALLING IT - if you downloaded this +tarball manually, you MUST install it. Read the instructions in INSTALL +prior to use. + + +Happy PHPing, we hope PEAR will be a great tool for your development work! + +$Id: README,v 1.11 2006/09/22 03:31:36 cellog Exp $ \ No newline at end of file diff --git a/src/lib/pear/PEAR/docs/PEAR_Frontend_Web/README b/src/lib/pear/PEAR/docs/PEAR_Frontend_Web/README new file mode 100644 index 0000000..e2a6c88 --- /dev/null +++ b/src/lib/pear/PEAR/docs/PEAR_Frontend_Web/README @@ -0,0 +1,35 @@ +PEAR_Frontend_Web +================= +Webbased PEAR Package Manager, the best way to manage your pear-compatible packages. + +Installation: +------------- +1) Install this package (pear install PEAR_Frontend_Web) +2) copy docs/index.php.txt to /index.php where is a web-accessible directory +3) Open, in your browser, the URL to that freshly copied file. +4) You are using the webfrontend : ) + +!BC Warning: If you get a require_once error on PEAR/WebInstaller.php then copy docs/index.php.txt over the erroneous file (eg. index.php) ! + +Permissions: +------------ +Your entire PEAR directory has to be writable by the webserver ! +This webfrontend is a frontend, it calls the PEAR installer functions so it must be able to change all PEAR-managed files, through the webserver. + +Security: +--------- +The webfrontend manages all packages, be sure to protect it ! +The easiest way is to protect it with a .htaccess file, in the webdir: +$ echo " +AuthUserFile $(pwd)/.htpasswd +AuthType Basic +AuthName \"Web-based PEAR Frontend\" +Require valid-user" > .htaccess && htpasswd -c .htpasswd admin + +This command (everything after the $) creates a .htaccess file, like the one supplied with this documentation, and creates a .htpasswd with user 'admin'. +(your apache config must have the directive: AllowOverride AuthConfig) + + +Please report any problems through the bugtracker at http://pear.php.net/package/PEAR_Frontend_Web/bugs +Have Fun, +Tias diff --git a/src/lib/pear/PEAR/docs/PEAR_Frontend_Web/docs/example.php b/src/lib/pear/PEAR/docs/PEAR_Frontend_Web/docs/example.php new file mode 100644 index 0000000..29db917 --- /dev/null +++ b/src/lib/pear/PEAR/docs/PEAR_Frontend_Web/docs/example.php @@ -0,0 +1,37 @@ + diff --git a/src/lib/pear/PEAR/docs/PEAR_Frontend_Web/docs/htaccess b/src/lib/pear/PEAR/docs/PEAR_Frontend_Web/docs/htaccess new file mode 100644 index 0000000..a477292 --- /dev/null +++ b/src/lib/pear/PEAR/docs/PEAR_Frontend_Web/docs/htaccess @@ -0,0 +1,6 @@ +# replace with +# the correct and full path to the .htpasswd file +AuthUserFile /.htpasswd +AuthType Basic +AuthName "Web-based PEAR Frontend" +Require valid-user diff --git a/src/lib/pear/PEAR/docs/PEAR_Frontend_Web/docs/index.php.txt b/src/lib/pear/PEAR/docs/PEAR_Frontend_Web/docs/index.php.txt new file mode 100644 index 0000000..c87ab8f --- /dev/null +++ b/src/lib/pear/PEAR/docs/PEAR_Frontend_Web/docs/index.php.txt @@ -0,0 +1,32 @@ + diff --git a/src/lib/pear/PEAR/docs/Structures_Graph/docs/generate.sh b/src/lib/pear/PEAR/docs/Structures_Graph/docs/generate.sh new file mode 100644 index 0000000..173d87c --- /dev/null +++ b/src/lib/pear/PEAR/docs/Structures_Graph/docs/generate.sh @@ -0,0 +1,8 @@ +#!/bin/sh +(cd ..; tar czf docs/arch.tgz "{arch}") +rm -Rf "../{arch}" +rm -Rf ./html +mkdir -p ./html +phpdoc --directory ../Structures,./tutorials --target ./html --title "Structures_Graph Documentation" --output "HTML:frames" --defaultpackagename structures_graph --defaultcategoryname structures --pear +(cd ..; tar --absolute-names -xzf docs/arch.tgz) +#rm arch.tgz diff --git a/src/lib/pear/PEAR/docs/Structures_Graph/docs/html/Structures_Graph/Structures_Graph.html b/src/lib/pear/PEAR/docs/Structures_Graph/docs/html/Structures_Graph/Structures_Graph.html new file mode 100644 index 0000000..00ec0bc --- /dev/null +++ b/src/lib/pear/PEAR/docs/Structures_Graph/docs/html/Structures_Graph/Structures_Graph.html @@ -0,0 +1,243 @@ + + + + + + Docs For Class Structures_Graph + + + + +
    +

    Class Structures_Graph

    + + +
    +
    Description
    + +
    + +

    The Structures_Graph class represents a graph data structure.

    +

    A Graph is a data structure composed by a set of nodes, connected by arcs. Graphs may either be directed or undirected. In a directed graph, arcs are directional, and can be traveled only one way. In an undirected graph, arcs are bidirectional, and can be traveled both ways.

    + +

    + Located in /Structures/Graph.php (line 56) +

    + + +
    
    +	
    +			
    +
    + + + + +
    +
    Method Summary
    + +
    +
    + +
    + Structures_Graph + Structures_Graph + ([boolean $directed = true]) +
    + +
    + void + addNode + (Structures_Graph_Node &$newNode) +
    + +
    + array + &getNodes + () +
    + +
    + boolean + isDirected + () +
    + +
    + void + removeNode + (Structures_Graph_Node &$node) +
    +
    +
    +
    + + + +
    +
    Methods
    + +
    + + +
    + +
    + Constructor Structures_Graph (line 76) +
    + + +

    Constructor

    +
      +
    • access: public
    • +
    + +
    + Structures_Graph + + Structures_Graph + + ([boolean $directed = true]) +
    + +
      +
    • + boolean + $directed: Set to true if the graph is directed. Set to false if it is not directed. (Optional, defaults to true)
    • +
    + + +
    + +
    + +
    + addNode (line 102) +
    + + +

    Add a Node to the Graph

    +
      +
    • access: public
    • +
    + +
    + void + + addNode + + (Structures_Graph_Node &$newNode) +
    + + + + +
    + +
    + +
    + getNodes (line 151) +
    + + +

    Return the node set, in no particular order. For ordered node sets, use a Graph Manipulator insted.

    + + +
    + array + + &getNodes + + () +
    + + + +
    + +
    + +
    + isDirected (line 89) +
    + + +

    Return true if a graph is directed

    +
      +
    • return: true if the graph is directed
    • +
    • access: public
    • +
    + +
    + boolean + + isDirected + + () +
    + + + +
    + +
    + +
    + removeNode (line 138) +
    + + +

    Remove a Node from the Graph

    +
      +
    • access: public
    • +
    • todo: This is unimplemented
    • +
    + +
    + void + + removeNode + + (Structures_Graph_Node &$node) +
    + + + + +
    + +
    +
    + +

    + Documentation generated on Fri, 30 Jan 2004 16:37:28 +0000 by phpDocumentor 1.2.3 +

    +
    + \ No newline at end of file diff --git a/src/lib/pear/PEAR/docs/Structures_Graph/docs/html/Structures_Graph/Structures_Graph_Manipulator_AcyclicTest.html b/src/lib/pear/PEAR/docs/Structures_Graph/docs/html/Structures_Graph/Structures_Graph_Manipulator_AcyclicTest.html new file mode 100644 index 0000000..0197946 --- /dev/null +++ b/src/lib/pear/PEAR/docs/Structures_Graph/docs/html/Structures_Graph/Structures_Graph_Manipulator_AcyclicTest.html @@ -0,0 +1,105 @@ + + + + + + Docs For Class Structures_Graph_Manipulator_AcyclicTest + + + + +
    +

    Class Structures_Graph_Manipulator_AcyclicTest

    + + +
    +
    Description
    + +
    + +

    The Structures_Graph_Manipulator_AcyclicTest is a graph manipulator which tests whether a graph contains a cycle.

    +

    The definition of an acyclic graph used in this manipulator is that of a DAG. The graph must be directed, or else it is considered cyclic, even when there are no arcs.

    + +

    + Located in /Structures/Graph/Manipulator/AcyclicTest.php (line 55) +

    + + +
    
    +	
    +			
    +
    + + + + +
    +
    Method Summary
    + +
    +
    + +
    + boolean + isAcyclic + (mixed &$graph) +
    +
    +
    +
    + + + +
    +
    Methods
    + +
    + + +
    + +
    + isAcyclic (line 126) +
    + + +

    isAcyclic returns true if a graph contains no cycles, false otherwise.

    +
      +
    • return: true iff graph is acyclic
    • +
    • access: public
    • +
    + +
    + boolean + + isAcyclic + + (mixed &$graph) +
    + + + +
    + +
    +
    + +

    + Documentation generated on Fri, 30 Jan 2004 16:37:28 +0000 by phpDocumentor 1.2.3 +

    +
    + \ No newline at end of file diff --git a/src/lib/pear/PEAR/docs/Structures_Graph/docs/html/Structures_Graph/Structures_Graph_Manipulator_TopologicalSorter.html b/src/lib/pear/PEAR/docs/Structures_Graph/docs/html/Structures_Graph/Structures_Graph_Manipulator_TopologicalSorter.html new file mode 100644 index 0000000..6db747b --- /dev/null +++ b/src/lib/pear/PEAR/docs/Structures_Graph/docs/html/Structures_Graph/Structures_Graph_Manipulator_TopologicalSorter.html @@ -0,0 +1,107 @@ + + + + + + Docs For Class Structures_Graph_Manipulator_TopologicalSorter + + + + +
    +

    Class Structures_Graph_Manipulator_TopologicalSorter

    + + +
    +
    Description
    + +
    + +

    The Structures_Graph_Manipulator_TopologicalSorter is a manipulator which is able to return the set of nodes in a graph, sorted by topological order.

    +

    A graph may only be sorted topologically iff it's a DAG. You can test it with the Structures_Graph_Manipulator_AcyclicTest.

    + +

    + Located in /Structures/Graph/Manipulator/TopologicalSorter.php (line 58) +

    + + +
    
    +	
    +			
    +
    + + + + +
    +
    Method Summary
    + +
    +
    + +
    + array + sort + (mixed &$graph) +
    +
    +
    +
    + + + +
    +
    Methods
    + +
    + + +
    + +
    + sort (line 133) +
    + + +

    sort returns the graph's nodes, sorted by topological order.

    +

    The result is an array with as many entries as topological levels. Each entry in this array is an array of nodes within the given topological level.

    +
      +
    • return: The graph's nodes, sorted by topological order.
    • +
    • access: public
    • +
    + +
    + array + + sort + + (mixed &$graph) +
    + + + +
    + +
    +
    + +

    + Documentation generated on Fri, 30 Jan 2004 16:37:29 +0000 by phpDocumentor 1.2.3 +

    +
    + \ No newline at end of file diff --git a/src/lib/pear/PEAR/docs/Structures_Graph/docs/html/Structures_Graph/Structures_Graph_Node.html b/src/lib/pear/PEAR/docs/Structures_Graph/docs/html/Structures_Graph/Structures_Graph_Node.html new file mode 100644 index 0000000..43922b3 --- /dev/null +++ b/src/lib/pear/PEAR/docs/Structures_Graph/docs/html/Structures_Graph/Structures_Graph_Node.html @@ -0,0 +1,549 @@ + + + + + + Docs For Class Structures_Graph_Node + + + + +
    +

    Class Structures_Graph_Node

    + + +
    +
    Description
    + +
    + +

    The Structures_Graph_Node class represents a Node that can be member of a graph node set.

    +

    A graph node can contain data. Under this API, the node contains default data, and key index data. It behaves, thus, both as a regular data node, and as a dictionary (or associative array) node.

    Regular data is accessed via getData and setData. Key indexed data is accessed via getMetadata and setMetadata.

    + +

    + Located in /Structures/Graph/Node.php (line 57) +

    + + +
    
    +	
    +			
    +
    + + + + +
    +
    Method Summary
    + +
    +
    + +
    + Structures_Graph_Node + Structures_Graph_Node + () +
    + +
    + boolean + connectsTo + (mixed &$target) +
    + +
    + void + connectTo + (Structures_Graph &$destinationNode) +
    + +
    + mixed + &getData + () +
    + + + +
    + mixed + &getMetadata + (string $key, [boolean $nullIfNonexistent = false]) +
    + +
    + array + getNeighbours + () +
    + +
    + integer + inDegree + () +
    + +
    + boolean + metadataKeyExists + (string $key) +
    + +
    + integer + outDegree + () +
    + +
    + mixed + setData + (mixed $data) +
    + +
    + void + setGraph + (Structures_Graph &$graph) +
    + +
    + void + setMetadata + (string $key, mixed $data) +
    + +
    + void + unsetMetadata + (string $key) +
    +
    +
    +
    + + + +
    +
    Methods
    + +
    + + +
    + +
    + Constructor Structures_Graph_Node (line 78) +
    + + +

    Constructor

    +
      +
    • access: public
    • +
    + +
    + Structures_Graph_Node + + Structures_Graph_Node + + () +
    + + + +
    + +
    + +
    + connectsTo (line 275) +
    + + +

    Test wether this node has an arc to the target node

    +
      +
    • return: True if the two nodes are connected
    • +
    • access: public
    • +
    + +
    + boolean + + connectsTo + + (mixed &$target) +
    + + + +
    + +
    + +
    + connectTo (line 236) +
    + + +

    Connect this node to another one.

    +

    If the graph is not directed, the reverse arc, connecting $destinationNode to $this is also created.

    +
      +
    • access: public
    • +
    + +
    + void + + connectTo + + (Structures_Graph &$destinationNode) +
    + + + + +
    + +
    + +
    + getData (line 119) +
    + + +

    Node data getter.

    +

    Each graph node can contain a reference to one variable. This is the getter for that reference.

    +
      +
    • return: Data stored in node
    • +
    • access: public
    • +
    + +
    + mixed + + &getData + + () +
    + + + +
    + +
    + +
    + getGraph (line 90) +
    + + +

    Node graph getter

    +
      +
    • return: Graph where node is stored
    • +
    • access: public
    • +
    + +
    + Structures_Graph + + &getGraph + + () +
    + + + +
    + +
    + +
    + getMetadata (line 171) +
    + + +

    Node metadata getter

    +

    Each graph node can contain multiple 'metadata' entries, each stored under a different key, as in an associative array or in a dictionary. This method gets the data under the given key. If the key does not exist, an error will be thrown, so testing using metadataKeyExists might be needed.

    + + +
    + mixed + + &getMetadata + + (string $key, [boolean $nullIfNonexistent = false]) +
    + +
      +
    • + string + $key: Key
    • +
    • + boolean + $nullIfNonexistent: nullIfNonexistent (defaults to false).
    • +
    + + +
    + +
    + +
    + getNeighbours (line 262) +
    + + +

    Return nodes connected to this one.

    +
      +
    • return: Array of nodes
    • +
    • access: public
    • +
    + +
    + array + + getNeighbours + + () +
    + + + +
    + +
    + +
    + inDegree (line 309) +
    + + +

    Calculate the in degree of the node.

    +

    The indegree for a node is the number of arcs entering the node. For non directed graphs, the indegree is equal to the outdegree.

    +
      +
    • return: In degree of the node
    • +
    • access: public
    • +
    + +
    + integer + + inDegree + + () +
    + + + +
    + +
    + +
    + metadataKeyExists (line 151) +
    + + +

    Test for existence of metadata under a given key.

    +

    Each graph node can contain multiple 'metadata' entries, each stored under a different key, as in an associative array or in a dictionary. This method tests whether a given metadata key exists for this node.

    +
      +
    • access: public
    • +
    + +
    + boolean + + metadataKeyExists + + (string $key) +
    + +
      +
    • + string + $key: Key to test
    • +
    + + +
    + +
    + +
    + outDegree (line 333) +
    + + +

    Calculate the out degree of the node.

    +

    The outdegree for a node is the number of arcs exiting the node. For non directed graphs, the outdegree is always equal to the indegree.

    +
      +
    • return: Out degree of the node
    • +
    • access: public
    • +
    + +
    + integer + + outDegree + + () +
    + + + +
    + +
    + +
    + setData (line 134) +
    + + +

    Node data setter

    +

    Each graph node can contain a reference to one variable. This is the setter for that reference.

    +
      +
    • return: Data to store in node
    • +
    • access: public
    • +
    + +
    + mixed + + setData + + (mixed $data) +
    + + + +
    + +
    + +
    + setGraph (line 104) +
    + + +

    Node graph setter. This method should not be called directly. Use Graph::addNode instead.

    + + +
    + void + + setGraph + + (Structures_Graph &$graph) +
    + + + + +
    + +
    + +
    + setMetadata (line 214) +
    + + +

    Node metadata setter

    +

    Each graph node can contain multiple 'metadata' entries, each stored under a different key, as in an associative array or in a dictionary. This method stores data under the given key. If the key already exists, previously stored data is discarded.

    +
      +
    • access: public
    • +
    + +
    + void + + setMetadata + + (string $key, mixed $data) +
    + +
      +
    • + string + $key: Key
    • +
    • + mixed + $data: Data
    • +
    + + +
    + +
    + +
    + unsetMetadata (line 196) +
    + + +

    Delete metadata by key

    +

    Each graph node can contain multiple 'metadata' entries, each stored under a different key, as in an associative array or in a dictionary. This method removes any data that might be stored under the provided key. If the key does not exist, no error is thrown, so it is safe using this method without testing for key existence.

    +
      +
    • access: public
    • +
    + +
    + void + + unsetMetadata + + (string $key) +
    + +
      +
    • + string + $key: Key
    • +
    + + +
    + +
    +
    + +

    + Documentation generated on Fri, 30 Jan 2004 16:37:29 +0000 by phpDocumentor 1.2.3 +

    +
    + \ No newline at end of file diff --git a/src/lib/pear/PEAR/docs/Structures_Graph/docs/html/Structures_Graph/_Structures_Graph_Manipulator_AcyclicTest_php.html b/src/lib/pear/PEAR/docs/Structures_Graph/docs/html/Structures_Graph/_Structures_Graph_Manipulator_AcyclicTest_php.html new file mode 100644 index 0000000..6834ae0 --- /dev/null +++ b/src/lib/pear/PEAR/docs/Structures_Graph/docs/html/Structures_Graph/_Structures_Graph_Manipulator_AcyclicTest_php.html @@ -0,0 +1,119 @@ + + + + + + Docs for page AcyclicTest.php + + + + +
    +

    /Structures/Graph/Manipulator/AcyclicTest.php

    + + +
    +
    Description
    + +
    + +

    This file contains the definition of the Structures_Graph_Manipulator_AcyclicTest graph manipulator.

    + + +
    +
    + + +
    +
    Classes
    + +
    + + + + + + + + + +
    ClassDescription
    + Structures_Graph_Manipulator_AcyclicTest + + The Structures_Graph_Manipulator_AcyclicTest is a graph manipulator which tests whether a graph contains a cycle. +
    +
    +
    + + +
    +
    Includes
    + +
    + +
    + +
    + + require_once + ('PEAR.php') + (line 35) + +
    + + + +
    + +
    + +
    + + require_once + ('Structures/Graph.php') + (line 37) + +
    + + + +
    + +
    + +
    + + require_once + ('Structures/Graph/Node.php') + (line 39) + +
    + + + +
    +
    +
    + + + + +

    + Documentation generated on Fri, 30 Jan 2004 16:37:28 +0000 by phpDocumentor 1.2.3 +

    +
    + \ No newline at end of file diff --git a/src/lib/pear/PEAR/docs/Structures_Graph/docs/html/Structures_Graph/_Structures_Graph_Manipulator_TopologicalSorter_php.html b/src/lib/pear/PEAR/docs/Structures_Graph/docs/html/Structures_Graph/_Structures_Graph_Manipulator_TopologicalSorter_php.html new file mode 100644 index 0000000..d8cde62 --- /dev/null +++ b/src/lib/pear/PEAR/docs/Structures_Graph/docs/html/Structures_Graph/_Structures_Graph_Manipulator_TopologicalSorter_php.html @@ -0,0 +1,133 @@ + + + + + + Docs for page TopologicalSorter.php + + + + +
    +

    /Structures/Graph/Manipulator/TopologicalSorter.php

    + + +
    +
    Description
    + +
    + +

    This file contains the definition of the Structures_Graph_Manipulator_TopologicalSorter class.

    + + +
    +
    + + +
    +
    Classes
    + +
    + + + + + + + + + +
    ClassDescription
    + Structures_Graph_Manipulator_TopologicalSorter + + The Structures_Graph_Manipulator_TopologicalSorter is a manipulator which is able to return the set of nodes in a graph, sorted by topological order. +
    +
    +
    + + +
    +
    Includes
    + +
    + +
    + +
    + + require_once + ('PEAR.php') + (line 35) + +
    + + + +
    + +
    + +
    + + require_once + ('Structures/Graph.php') + (line 37) + +
    + + + +
    + +
    + +
    + + require_once + ('Structures/Graph/Node.php') + (line 39) + +
    + + + +
    + +
    + +
    + + require_once + ('Structures/Graph/Manipulator/AcyclicTest.php') + (line 41) + +
    + + + +
    +
    +
    + + + + +

    + Documentation generated on Fri, 30 Jan 2004 16:37:29 +0000 by phpDocumentor 1.2.3 +

    +
    + \ No newline at end of file diff --git a/src/lib/pear/PEAR/docs/Structures_Graph/docs/html/Structures_Graph/_Structures_Graph_Node_php.html b/src/lib/pear/PEAR/docs/Structures_Graph/docs/html/Structures_Graph/_Structures_Graph_Node_php.html new file mode 100644 index 0000000..528a021 --- /dev/null +++ b/src/lib/pear/PEAR/docs/Structures_Graph/docs/html/Structures_Graph/_Structures_Graph_Node_php.html @@ -0,0 +1,105 @@ + + + + + + Docs for page Node.php + + + + +
    +

    /Structures/Graph/Node.php

    + + +
    +
    Description
    + +
    + +

    This file contains the definition of the Structures_Graph_Node class

    + + +
    +
    + + +
    +
    Classes
    + +
    + + + + + + + + + +
    ClassDescription
    + Structures_Graph_Node + + The Structures_Graph_Node class represents a Node that can be member of a graph node set. +
    +
    +
    + + +
    +
    Includes
    + +
    + +
    + +
    + + require_once + ('PEAR.php') + (line 35) + +
    + + + +
    + +
    + +
    + + require_once + ('Structures/Graph.php') + (line 37) + +
    + + + +
    +
    +
    + + + + +

    + Documentation generated on Fri, 30 Jan 2004 16:37:29 +0000 by phpDocumentor 1.2.3 +

    +
    + \ No newline at end of file diff --git a/src/lib/pear/PEAR/docs/Structures_Graph/docs/html/Structures_Graph/_Structures_Graph_php.html b/src/lib/pear/PEAR/docs/Structures_Graph/docs/html/Structures_Graph/_Structures_Graph_php.html new file mode 100644 index 0000000..b00220b --- /dev/null +++ b/src/lib/pear/PEAR/docs/Structures_Graph/docs/html/Structures_Graph/_Structures_Graph_php.html @@ -0,0 +1,136 @@ + + + + + + Docs for page Graph.php + + + + +
    +

    /Structures/Graph.php

    + + +
    +
    Description
    + +
    + +

    The Graph.php file contains the definition of the Structures_Graph class

    + + +
    +
    + + +
    +
    Classes
    + +
    + + + + + + + + + +
    ClassDescription
    + Structures_Graph + + The Structures_Graph class represents a graph data structure. +
    +
    +
    + + +
    +
    Includes
    + +
    + +
    + +
    + + require_once + ('Structures/Graph/Node.php') + (line 37) + +
    + + +

    Graph Node

    + +
    + +
    + +
    + + require_once + ('PEAR.php') + (line 35) + +
    + + +

    PEAR base classes

    + +
    +
    +
    + + +
    +
    Constants
    + +
    + +
    + +
    + + STRUCTURES_GRAPH_ERROR_GENERIC = 100 + (line 40) + +
    + + + + +
    +
    +
    + + + +

    + Documentation generated on Fri, 30 Jan 2004 16:37:28 +0000 by phpDocumentor 1.2.3 +

    +
    + \ No newline at end of file diff --git a/src/lib/pear/PEAR/docs/Structures_Graph/docs/html/Structures_Graph/tutorial_Structures_Graph.pkg.html b/src/lib/pear/PEAR/docs/Structures_Graph/docs/html/Structures_Graph/tutorial_Structures_Graph.pkg.html new file mode 100644 index 0000000..fd9f790 --- /dev/null +++ b/src/lib/pear/PEAR/docs/Structures_Graph/docs/html/Structures_Graph/tutorial_Structures_Graph.pkg.html @@ -0,0 +1,75 @@ + + + + + + Structures_Graph Tutorial + + + + +
    + +

    Structures_Graph Tutorial

    +

    A first tour of graph datastructure manipulation

    +

    Introduction

    Structures_Graph is a package for creating and manipulating graph datastructures. A graph is a set of objects, called nodes, connected by arcs. When used as a datastructure, usually nodes contain data, and arcs represent relationships between nodes. When arcs have a direction, and can be travelled only one way, graphs are said to be directed. When arcs have no direction, and can always be travelled both ways, graphs are said to be non directed.

    +

    Structures_Graph provides an object oriented API to create and directly query a graph, as well as a set of Manipulator classes to extract information from the graph.

    +

    Creating a Graph

    Creating a graph is done using the simple constructor: +

    +require_once 'Structures/Graph.php';
    +
    +$directedGraph =& new Structures_Graph(true);
    +$nonDirectedGraph =& new Structures_Graph(false);
    +    
    + and passing the constructor a flag telling it whether the graph should be directed. A directed graph will always be directed during its lifetime. It's a permanent characteristic.

    +

    To fill out the graph, we'll need to create some nodes, and then call Graph::addNode. +

    +require_once 'Structures/Graph/Node.php';
    +
    +$nodeOne =& new Structures_Graph_Node();
    +$nodeTwo =& new Structures_Graph_Node();
    +$nodeThree =& new Structures_Graph_Node();
    +
    +$directedGraph->addNode(&$nodeOne);
    +$directedGraph->addNode(&$nodeTwo);
    +$directedGraph->addNode(&$nodeThree);
    +    
    + and then setup the arcs: +
    +$nodeOne->connectTo($nodeTwo);
    +$nodeOne->connectTo($nodeThree);
    +    
    + Note that arcs can only be created after the nodes have been inserted into the graph.

    +

    Associating Data

    Graphs are only useful as datastructures if they can hold data. Structure_Graph stores data in nodes. Each node contains a setter and a getter for its data. +

    +$nodeOne->setData("Node One's Data is a String");
    +$nodeTwo->setData(1976);
    +$nodeThree->setData('Some other string');
    +
    +print("NodeTwo's Data is an integer: " . $nodeTwo->getData());
    +    

    +

    Structure_Graph nodes can also store metadata, alongside with the main data. Metadata differs from regular data just because it is stored under a key, making it possible to store more than one data reference per node. The metadata getter and setter need the key to perform the operation: +

    +$nodeOne->setMetadata('example key', "Node One's Sample Metadata");
    +print("Metadata stored under key 'example key' in node one: " . $nodeOne->getMetadata('example key'));
    +$nodeOne->unsetMetadata('example key');
    +    

    +

    Querying a Graph

    Structures_Graph provides for basic querying of the graph: +

    +// Nodes are able to calculate their indegree and outdegree
    +print("NodeOne's inDegree: " . $nodeOne->inDegree());
    +print("NodeOne's outDegree: " . $nodeOne->outDegree());
    +
    +// and naturally, nodes can report on their arcs
    +$arcs = $nodeOne->getNeighbours();
    +for ($i=0;$i<sizeof($arcs);$i++) {
    +    print("NodeOne has an arc to " . $arcs[$i]->getData());
    +}
    +    

    + + +

    + Documentation generated on Fri, 30 Jan 2004 16:37:28 +0000 by phpDocumentor 1.2.3 +

    +
    + \ No newline at end of file diff --git a/src/lib/pear/PEAR/docs/Structures_Graph/docs/html/classtrees_Structures_Graph.html b/src/lib/pear/PEAR/docs/Structures_Graph/docs/html/classtrees_Structures_Graph.html new file mode 100644 index 0000000..d3b0c91 --- /dev/null +++ b/src/lib/pear/PEAR/docs/Structures_Graph/docs/html/classtrees_Structures_Graph.html @@ -0,0 +1,36 @@ + + + + + + + + + + + + +

    + +

    +

    Root class Structures_Graph

    + + +

    Root class Structures_Graph_Manipulator_AcyclicTest

    + + +

    Root class Structures_Graph_Manipulator_TopologicalSorter

    + + +

    Root class Structures_Graph_Node

    + + +

    + Documentation generated on Fri, 30 Jan 2004 16:37:28 +0000 by phpDocumentor 1.2.3 +

    + + \ No newline at end of file diff --git a/src/lib/pear/PEAR/docs/Structures_Graph/docs/html/elementindex.html b/src/lib/pear/PEAR/docs/Structures_Graph/docs/html/elementindex.html new file mode 100644 index 0000000..882faeb --- /dev/null +++ b/src/lib/pear/PEAR/docs/Structures_Graph/docs/html/elementindex.html @@ -0,0 +1,339 @@ + + + + + + + + + + + +

    Full index

    +

    Package indexes

    + +
    +
    + a + c + g + i + m + n + o + r + s + t + u +
    + + +
    +
    a
    + +
    +
    +
    +
    + addNode +
    +
    + +
    Add a Node to the Graph
    +
    +
    + AcyclicTest.php +
    +
    +
    AcyclicTest.php in AcyclicTest.php
    +
    +
    + +
    +
    c
    + +
    +
    +
    +
    + connectsTo +
    +
    + +
    Test wether this node has an arc to the target node
    +
    +
    + connectTo +
    +
    + +
    Connect this node to another one.
    +
    +
    + +
    +
    g
    + +
    +
    +
    +
    + getData +
    +
    + +
    Node data getter.
    +
    +
    + getGraph +
    +
    + +
    Node graph getter
    +
    +
    + getMetadata +
    +
    + +
    Node metadata getter
    +
    +
    + getNeighbours +
    +
    + +
    Return nodes connected to this one.
    +
    +
    + getNodes +
    +
    + +
    Return the node set, in no particular order. For ordered node sets, use a Graph Manipulator insted.
    +
    +
    + Graph.php +
    +
    +
    Graph.php in Graph.php
    +
    +
    + +
    +
    i
    + +
    +
    +
    +
    + inDegree +
    +
    + +
    Calculate the in degree of the node.
    +
    +
    + isAcyclic +
    +
    + +
    isAcyclic returns true if a graph contains no cycles, false otherwise.
    +
    +
    + isDirected +
    +
    + +
    Return true if a graph is directed
    +
    +
    + +
    +
    m
    + +
    +
    +
    +
    + metadataKeyExists +
    +
    + +
    Test for existence of metadata under a given key.
    +
    +
    + +
    +
    n
    + +
    +
    +
    +
    + Node.php +
    +
    +
    Node.php in Node.php
    +
    +
    + +
    +
    o
    + +
    +
    +
    +
    + outDegree +
    +
    + +
    Calculate the out degree of the node.
    +
    +
    + +
    +
    r
    + +
    +
    +
    +
    + removeNode +
    +
    + +
    Remove a Node from the Graph
    +
    +
    + +
    +
    s
    + +
    +
    +
    +
    + setData +
    +
    + +
    Node data setter
    +
    +
    + setGraph +
    +
    + +
    Node graph setter. This method should not be called directly. Use Graph::addNode instead.
    +
    +
    + setMetadata +
    +
    + +
    Node metadata setter
    +
    +
    + sort +
    +
    + +
    sort returns the graph's nodes, sorted by topological order.
    +
    +
    + Structures_Graph +
    +
    +
    Structures_Graph in Graph.php
    +
    The Structures_Graph class represents a graph data structure.
    +
    +
    + Structures_Graph +
    +
    + +
    Constructor
    +
    +
    + STRUCTURES_GRAPH_ERROR_GENERIC +
    +
    + +
    +
    + Structures_Graph_Manipulator_AcyclicTest +
    +
    + +
    The Structures_Graph_Manipulator_AcyclicTest is a graph manipulator which tests whether a graph contains a cycle.
    +
    +
    + Structures_Graph_Manipulator_TopologicalSorter +
    +
    + +
    The Structures_Graph_Manipulator_TopologicalSorter is a manipulator which is able to return the set of nodes in a graph, sorted by topological order.
    +
    +
    + Structures_Graph_Node +
    +
    + +
    Constructor
    +
    +
    + Structures_Graph_Node +
    +
    + +
    The Structures_Graph_Node class represents a Node that can be member of a graph node set.
    +
    +
    + +
    +
    t
    + +
    +
    +
    +
    + TopologicalSorter.php +
    +
    +
    TopologicalSorter.php in TopologicalSorter.php
    +
    +
    + +
    +
    u
    + +
    +
    +
    +
    + unsetMetadata +
    +
    + +
    Delete metadata by key
    +
    +
    + +
    + a + c + g + i + m + n + o + r + s + t + u +
    + \ No newline at end of file diff --git a/src/lib/pear/PEAR/docs/Structures_Graph/docs/html/elementindex_Structures_Graph.html b/src/lib/pear/PEAR/docs/Structures_Graph/docs/html/elementindex_Structures_Graph.html new file mode 100644 index 0000000..373d3a5 --- /dev/null +++ b/src/lib/pear/PEAR/docs/Structures_Graph/docs/html/elementindex_Structures_Graph.html @@ -0,0 +1,336 @@ + + + + + + + + + + + +

    [Structures_Graph] element index

    +All elements +
    +
    + a + c + g + i + m + n + o + r + s + t + u +
    + + +
    +
    a
    + +
    +
    +
    +
    + addNode +
    +
    + +
    Add a Node to the Graph
    +
    +
    + AcyclicTest.php +
    +
    +
    AcyclicTest.php in AcyclicTest.php
    +
    +
    + +
    +
    c
    + +
    +
    +
    +
    + connectsTo +
    +
    + +
    Test wether this node has an arc to the target node
    +
    +
    + connectTo +
    +
    + +
    Connect this node to another one.
    +
    +
    + +
    +
    g
    + +
    +
    +
    +
    + getData +
    +
    + +
    Node data getter.
    +
    +
    + getGraph +
    +
    + +
    Node graph getter
    +
    +
    + getMetadata +
    +
    + +
    Node metadata getter
    +
    +
    + getNeighbours +
    +
    + +
    Return nodes connected to this one.
    +
    +
    + getNodes +
    +
    + +
    Return the node set, in no particular order. For ordered node sets, use a Graph Manipulator insted.
    +
    +
    + Graph.php +
    +
    +
    Graph.php in Graph.php
    +
    +
    + +
    +
    i
    + +
    +
    +
    +
    + inDegree +
    +
    + +
    Calculate the in degree of the node.
    +
    +
    + isAcyclic +
    +
    + +
    isAcyclic returns true if a graph contains no cycles, false otherwise.
    +
    +
    + isDirected +
    +
    + +
    Return true if a graph is directed
    +
    +
    + +
    +
    m
    + +
    +
    +
    +
    + metadataKeyExists +
    +
    + +
    Test for existence of metadata under a given key.
    +
    +
    + +
    +
    n
    + +
    +
    +
    +
    + Node.php +
    +
    +
    Node.php in Node.php
    +
    +
    + +
    +
    o
    + +
    +
    +
    +
    + outDegree +
    +
    + +
    Calculate the out degree of the node.
    +
    +
    + +
    +
    r
    + +
    +
    +
    +
    + removeNode +
    +
    + +
    Remove a Node from the Graph
    +
    +
    + +
    +
    s
    + +
    +
    +
    +
    + setData +
    +
    + +
    Node data setter
    +
    +
    + setGraph +
    +
    + +
    Node graph setter. This method should not be called directly. Use Graph::addNode instead.
    +
    +
    + setMetadata +
    +
    + +
    Node metadata setter
    +
    +
    + sort +
    +
    + +
    sort returns the graph's nodes, sorted by topological order.
    +
    +
    + Structures_Graph +
    +
    +
    Structures_Graph in Graph.php
    +
    The Structures_Graph class represents a graph data structure.
    +
    +
    + Structures_Graph +
    +
    + +
    Constructor
    +
    +
    + STRUCTURES_GRAPH_ERROR_GENERIC +
    +
    + +
    +
    + Structures_Graph_Manipulator_AcyclicTest +
    +
    + +
    The Structures_Graph_Manipulator_AcyclicTest is a graph manipulator which tests whether a graph contains a cycle.
    +
    +
    + Structures_Graph_Manipulator_TopologicalSorter +
    +
    + +
    The Structures_Graph_Manipulator_TopologicalSorter is a manipulator which is able to return the set of nodes in a graph, sorted by topological order.
    +
    +
    + Structures_Graph_Node +
    +
    + +
    Constructor
    +
    +
    + Structures_Graph_Node +
    +
    + +
    The Structures_Graph_Node class represents a Node that can be member of a graph node set.
    +
    +
    + +
    +
    t
    + +
    +
    +
    +
    + TopologicalSorter.php +
    +
    +
    TopologicalSorter.php in TopologicalSorter.php
    +
    +
    + +
    +
    u
    + +
    +
    +
    +
    + unsetMetadata +
    +
    + +
    Delete metadata by key
    +
    +
    + +
    + a + c + g + i + m + n + o + r + s + t + u +
    + \ No newline at end of file diff --git a/src/lib/pear/PEAR/docs/Structures_Graph/docs/html/errors.html b/src/lib/pear/PEAR/docs/Structures_Graph/docs/html/errors.html new file mode 100644 index 0000000..c9b3c93 --- /dev/null +++ b/src/lib/pear/PEAR/docs/Structures_Graph/docs/html/errors.html @@ -0,0 +1,16 @@ + + + + + + phpDocumentor Parser Errors and Warnings + + + + + Post-parsing
    +

    + Documentation generated on Fri, 30 Jan 2004 16:37:29 +0000 by phpDocumentor 1.2.3 +

    + + \ No newline at end of file diff --git a/src/lib/pear/PEAR/docs/Structures_Graph/docs/html/index.html b/src/lib/pear/PEAR/docs/Structures_Graph/docs/html/index.html new file mode 100644 index 0000000..f4d550e --- /dev/null +++ b/src/lib/pear/PEAR/docs/Structures_Graph/docs/html/index.html @@ -0,0 +1,24 @@ + + + + + + Structures_Graph Documentation + + + + + + + + + + + <H2>Frame Alert</H2> + <P>This document is designed to be viewed using the frames feature. + If you see this message, you are using a non-frame-capable web client.</P> + + + \ No newline at end of file diff --git a/src/lib/pear/PEAR/docs/Structures_Graph/docs/html/li_Structures_Graph.html b/src/lib/pear/PEAR/docs/Structures_Graph/docs/html/li_Structures_Graph.html new file mode 100644 index 0000000..f1f8296 --- /dev/null +++ b/src/lib/pear/PEAR/docs/Structures_Graph/docs/html/li_Structures_Graph.html @@ -0,0 +1,53 @@ + + + + + + + + + + +
    Structures_Graph
    + +

    phpDocumentor v 1.2.3

    + + \ No newline at end of file diff --git a/src/lib/pear/PEAR/docs/Structures_Graph/docs/html/media/banner.css b/src/lib/pear/PEAR/docs/Structures_Graph/docs/html/media/banner.css new file mode 100644 index 0000000..f2149eb --- /dev/null +++ b/src/lib/pear/PEAR/docs/Structures_Graph/docs/html/media/banner.css @@ -0,0 +1,32 @@ +body +{ + background-color: #CCCCFF; + margin: 0px; + padding: 0px; +} + +/* Banner (top bar) classes */ + +.banner { } + +.banner-menu +{ + clear: both; + padding: .5em; + border-top: 2px solid #6666AA; +} + +.banner-title +{ + text-align: right; + font-size: 20pt; + font-weight: bold; + margin: .2em; +} + +.package-selector +{ + background-color: #AAAADD; + border: 1px solid black; + color: yellow; +} diff --git a/src/lib/pear/PEAR/docs/Structures_Graph/docs/html/media/stylesheet.css b/src/lib/pear/PEAR/docs/Structures_Graph/docs/html/media/stylesheet.css new file mode 100644 index 0000000..380dcee --- /dev/null +++ b/src/lib/pear/PEAR/docs/Structures_Graph/docs/html/media/stylesheet.css @@ -0,0 +1,134 @@ +a { color: #336699; text-decoration: none; } +a:hover { color: #6699CC; text-decoration: underline; } +a:active { color: #6699CC; text-decoration: underline; } + +body { background : #FFFFFF; } +body, table { font-family: Georgia, Times New Roman, Times, serif; font-size: 10pt } +p, li { line-height: 140% } +a img { border: 0px; } +dd { margin-left: 0px; padding-left: 1em; } + +/* Page layout/boxes */ + +.info-box {} +.info-box-title { margin: 1em 0em 0em 0em; padding: .25em; font-weight: normal; font-size: 14pt; border: 2px solid #999999; background-color: #CCCCFF } +.info-box-body { border: 1px solid #999999; padding: .5em; } +.nav-bar { font-size: 8pt; white-space: nowrap; text-align: right; padding: .2em; margin: 0em 0em 1em 0em; } + +.oddrow { background-color: #F8F8F8; border: 1px solid #AAAAAA; padding: .5em; margin-bottom: 1em} +.evenrow { border: 1px solid #AAAAAA; padding: .5em; margin-bottom: 1em} + +.page-body { max-width: 800px; margin: auto; } +.tree dl { margin: 0px } + +/* Index formatting classes */ + +.index-item-body { margin-top: .5em; margin-bottom: .5em} +.index-item-description { margin-top: .25em } +.index-item-details { font-weight: normal; font-style: italic; font-size: 8pt } +.index-letter-section { background-color: #EEEEEE; border: 1px dotted #999999; padding: .5em; margin-bottom: 1em} +.index-letter-title { font-size: 12pt; font-weight: bold } +.index-letter-menu { text-align: center; margin: 1em } +.index-letter { font-size: 12pt } + +/* Docbook classes */ + +.description {} +.short-description { font-weight: bold; color: #666666; } +.tags { padding-left: 0em; margin-left: 3em; color: #666666; list-style-type: square; } +.parameters { padding-left: 0em; margin-left: 3em; font-style: italic; list-style-type: square; } +.redefinitions { font-size: 8pt; padding-left: 0em; margin-left: 2em; } +.package { } +.package-title { font-weight: bold; font-size: 14pt; border-bottom: 1px solid black } +.package-details { font-size: 85%; } +.sub-package { font-weight: bold; font-size: 120% } +.tutorial { border-width: thin; border-color: #0066ff } +.tutorial-nav-box { width: 100%; border: 1px solid #999999; background-color: #F8F8F8; } +.nav-button-disabled { color: #999999; } +.nav-button:active, +.nav-button:focus, +.nav-button:hover { background-color: #DDDDDD; outline: 1px solid #999999; text-decoration: none } +.folder-title { font-style: italic } + +/* Generic formatting */ + +.field { font-weight: bold; } +.detail { font-size: 8pt; } +.notes { font-style: italic; font-size: 8pt; } +.separator { background-color: #999999; height: 2px; } +.warning { color: #FF6600; } +.disabled { font-style: italic; color: #999999; } + +/* Code elements */ + +.line-number { } + +.class-table { width: 100%; } +.class-table-header { border-bottom: 1px dotted #666666; text-align: left} +.class-name { color: #000000; font-weight: bold; } + +.method-summary { padding-left: 1em; font-size: 8pt } +.method-header { } +.method-definition { margin-bottom: .3em } +.method-title { font-weight: bold; } +.method-name { font-weight: bold; } +.method-signature { font-size: 85%; color: #666666; margin: .5em 0em } +.method-result { font-style: italic; } + +.var-summary { padding-left: 1em; font-size: 8pt; } +.var-header { } +.var-title { margin-bottom: .3em } +.var-type { font-style: italic; } +.var-name { font-weight: bold; } +.var-default {} +.var-description { font-weight: normal; color: #000000; } + +.include-title { } +.include-type { font-style: italic; } +.include-name { font-weight: bold; } + +.const-title { } +.const-name { font-weight: bold; } + +/* Syntax highlighting */ + +.src-code { border: 1px solid #336699; padding: 1em; background-color: #EEEEEE; } + +.src-comm { color: green; } +.src-id { } +.src-inc { color: #0000FF; } +.src-key { color: #0000FF; } +.src-num { color: #CC0000; } +.src-str { color: #66cccc; } +.src-sym { font-weight: bold; } +.src-var { } + +.src-php { font-weight: bold; } + +.src-doc { color: #009999 } +.src-doc-close-template { color: #0000FF } +.src-doc-coretag { color: #0099FF; font-weight: bold } +.src-doc-inlinetag { color: #0099FF } +.src-doc-internal { color: #6699cc } +.src-doc-tag { color: #0080CC } +.src-doc-template { color: #0000FF } +.src-doc-type { font-style: italic } +.src-doc-var { font-style: italic } + +/* tutorial */ + +.authors { } +.author { font-style: italic; font-weight: bold } +.author-blurb { margin: .5em 0em .5em 2em; font-size: 85%; font-weight: normal; font-style: normal } +.example { border: 1px dashed #999999; background-color: #EEEEEE; padding: .5em } +.listing { border: 1px dashed #999999; background-color: #EEEEEE; padding: .5em; white-space: nowrap } +.release-info { font-size: 85%; font-style: italic; margin: 1em 0em } +.ref-title-box { } +.ref-title { } +.ref-purpose { font-style: italic; color: #666666 } +.ref-synopsis { } +.title { font-weight: bold; margin: 1em 0em 0em 0em; padding: .25em; border: 2px solid #999999; background-color: #CCCCFF } +.cmd-synopsis { margin: 1em 0em } +.cmd-title { font-weight: bold } +.toc { margin-left: 2em; padding-left: 0em } + diff --git a/src/lib/pear/PEAR/docs/Structures_Graph/docs/html/packages.html b/src/lib/pear/PEAR/docs/Structures_Graph/docs/html/packages.html new file mode 100644 index 0000000..01d657f --- /dev/null +++ b/src/lib/pear/PEAR/docs/Structures_Graph/docs/html/packages.html @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/lib/pear/PEAR/docs/Structures_Graph/docs/html/todolist.html b/src/lib/pear/PEAR/docs/Structures_Graph/docs/html/todolist.html new file mode 100644 index 0000000..5a55ee8 --- /dev/null +++ b/src/lib/pear/PEAR/docs/Structures_Graph/docs/html/todolist.html @@ -0,0 +1,21 @@ + + + + + + Todo List + + + + +

    Todo List

    +

    Structures_Graph

    +

    Structures_Graph::removeNode()

    +
      +
    • This is unimplemented
    • +
    +

    + Documentation generated on Fri, 30 Jan 2004 16:37:29 +0000 by phpDocumentor 1.2.3 +

    + + \ No newline at end of file diff --git a/src/lib/pear/PEAR/docs/Structures_Graph/docs/tutorials/Structures_Graph/Structures_Graph.pkg b/src/lib/pear/PEAR/docs/Structures_Graph/docs/tutorials/Structures_Graph/Structures_Graph.pkg new file mode 100644 index 0000000..23def41 --- /dev/null +++ b/src/lib/pear/PEAR/docs/Structures_Graph/docs/tutorials/Structures_Graph/Structures_Graph.pkg @@ -0,0 +1,98 @@ + + + Structures_Graph Tutorial + A first tour of graph datastructure manipulation + + + Introduction + + Structures_Graph is a package for creating and manipulating graph datastructures. A graph is a set of objects, called nodes, connected by arcs. When used as a datastructure, usually nodes contain data, and arcs represent relationships between nodes. When arcs have a direction, and can be travelled only one way, graphs are said to be directed. When arcs have no direction, and can always be travelled both ways, graphs are said to be non directed. + + + Structures_Graph provides an object oriented API to create and directly query a graph, as well as a set of Manipulator classes to extract information from the graph. + + + + Creating a Graph + + Creating a graph is done using the simple constructor: + + + + and passing the constructor a flag telling it whether the graph should be directed. A directed graph will always be directed during its lifetime. It's a permanent characteristic. + + + To fill out the graph, we'll need to create some nodes, and then call Graph::addNode. + + addNode(&$nodeOne); +$directedGraph->addNode(&$nodeTwo); +$directedGraph->addNode(&$nodeThree); + ]]> + + and then setup the arcs: + + connectTo($nodeTwo); +$nodeOne->connectTo($nodeThree); + ]]> + + Note that arcs can only be created after the nodes have been inserted into the graph. + + + + Associating Data + + Graphs are only useful as datastructures if they can hold data. Structure_Graph stores data in nodes. Each node contains a setter and a getter for its data. + + setData("Node One's Data is a String"); +$nodeTwo->setData(1976); +$nodeThree->setData('Some other string'); + +print("NodeTwo's Data is an integer: " . $nodeTwo->getData()); + ]]> + + + + Structure_Graph nodes can also store metadata, alongside with the main data. Metadata differs from regular data just because it is stored under a key, making it possible to store more than one data reference per node. The metadata getter and setter need the key to perform the operation: + + setMetadata('example key', "Node One's Sample Metadata"); +print("Metadata stored under key 'example key' in node one: " . $nodeOne->getMetadata('example key')); +$nodeOne->unsetMetadata('example key'); + ]]> + + + + + Querying a Graph + + Structures_Graph provides for basic querying of the graph: + + inDegree()); +print("NodeOne's outDegree: " . $nodeOne->outDegree()); + +// and naturally, nodes can report on their arcs +$arcs = $nodeOne->getNeighbours(); +for ($i=0;$igetData()); +} + ]]> + + + + diff --git a/src/lib/pear/PEAR/docs/examples/example.php b/src/lib/pear/PEAR/docs/examples/example.php new file mode 100644 index 0000000..8a9b122 --- /dev/null +++ b/src/lib/pear/PEAR/docs/examples/example.php @@ -0,0 +1,32 @@ +getMessage() . "\n"; +} else { + print $type . "\n"; +} + +?> diff --git a/src/lib/pear/PEAR/pearcmd.php b/src/lib/pear/PEAR/pearcmd.php new file mode 100644 index 0000000..9bfea98 --- /dev/null +++ b/src/lib/pear/PEAR/pearcmd.php @@ -0,0 +1,450 @@ + | +// | Tomas V.V.Cox | +// | | +// +----------------------------------------------------------------------+ +// +// $Id: pearcmd.php,v 1.39 2008/03/25 04:58:42 cellog Exp $ + +ob_end_clean(); +if (!defined('PEAR_RUNTYPE')) { + // this is defined in peclcmd.php as 'pecl' + define('PEAR_RUNTYPE', 'pear'); +} +define('PEAR_IGNORE_BACKTRACE', 1); +/** + * @nodep Gtk + */ +if ('/www/htdocs/w00acdb0/lib/pear/PEAR' != '@'.'include_path'.'@') { + ini_set('include_path', '/www/htdocs/w00acdb0/lib/pear/PEAR'); + $raw = false; +} else { + // this is a raw, uninstalled pear, either a cvs checkout, or php distro + $raw = true; +} +@ini_set('allow_url_fopen', true); +if (!ini_get('safe_mode')) { + @set_time_limit(0); +} +ob_implicit_flush(true); +@ini_set('track_errors', true); +@ini_set('html_errors', false); +@ini_set('magic_quotes_runtime', false); +$_PEAR_PHPDIR = '#$%^&*'; +set_error_handler('error_handler'); + +$pear_package_version = "1.7.2"; + +require_once 'PEAR.php'; +require_once 'PEAR/Frontend.php'; +require_once 'PEAR/Config.php'; +require_once 'PEAR/Command.php'; +require_once 'Console/Getopt.php'; + + +PEAR_Command::setFrontendType('CLI'); +$all_commands = PEAR_Command::getCommands(); + +// remove this next part when we stop supporting that crap-ass PHP 4.2 +if (!isset($_SERVER['argv']) && !isset($argv) && !isset($HTTP_SERVER_VARS['argv'])) { + echo 'ERROR: either use the CLI php executable, or set register_argc_argv=On in php.ini'; + exit(1); +} +$argv = Console_Getopt::readPHPArgv(); +// fix CGI sapi oddity - the -- in pear.bat/pear is not removed +if (php_sapi_name() != 'cli' && isset($argv[1]) && $argv[1] == '--') { + unset($argv[1]); + $argv = array_values($argv); +} +$progname = PEAR_RUNTYPE; +if (in_array('getopt2', get_class_methods('Console_Getopt'))) { + array_shift($argv); + $options = Console_Getopt::getopt2($argv, "c:C:d:D:Gh?sSqu:vV"); +} else { + $options = Console_Getopt::getopt($argv, "c:C:d:D:Gh?sSqu:vV"); +} +if (PEAR::isError($options)) { + usage($options); +} + +$opts = $options[0]; + +$fetype = 'CLI'; +if ($progname == 'gpear' || $progname == 'pear-gtk') { + $fetype = 'Gtk'; +} else { + foreach ($opts as $opt) { + if ($opt[0] == 'G') { + $fetype = 'Gtk'; + } + } +} +//Check if Gtk and PHP >= 5.1.0 +if ($fetype == 'Gtk' && version_compare(phpversion(), '5.1.0', '>=')) { + $fetype = 'Gtk2'; +} + +$pear_user_config = ''; +$pear_system_config = ''; +$store_user_config = false; +$store_system_config = false; +$verbose = 1; + +foreach ($opts as $opt) { + switch ($opt[0]) { + case 'c': + $pear_user_config = $opt[1]; + break; + case 'C': + $pear_system_config = $opt[1]; + break; + } +} + +PEAR_Command::setFrontendType($fetype); +$ui = &PEAR_Command::getFrontendObject(); +$config = &PEAR_Config::singleton($pear_user_config, $pear_system_config); + +if (PEAR::isError($config)) { + $_file = ''; + if ($pear_user_config !== false) { + $_file .= $pear_user_config; + } + if ($pear_system_config !== false) { + $_file .= '/' . $pear_system_config; + } + if ($_file == '/') { + $_file = 'The default config file'; + } + $config->getMessage(); + $ui->outputData("ERROR: $_file is not a valid config file or is corrupted."); + // We stop, we have no idea where we are :) + exit(1); +} + +// this is used in the error handler to retrieve a relative path +$_PEAR_PHPDIR = $config->get('php_dir'); +$ui->setConfig($config); +PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, array($ui, "displayFatalError")); +if (ini_get('safe_mode')) { + $ui->outputData('WARNING: running in safe mode requires that all files created ' . + 'be the same uid as the current script. PHP reports this script is uid: ' . + @getmyuid() . ', and current user is: ' . @get_current_user()); +} + +$verbose = $config->get("verbose"); +$cmdopts = array(); + +if ($raw) { + if (!$config->isDefinedLayer('user') && !$config->isDefinedLayer('system')) { + $found = false; + foreach ($opts as $opt) { + if ($opt[0] == 'd' || $opt[0] == 'D') { + $found = true; // the user knows what they are doing, and are setting config values + } + } + if (!$found) { + // no prior runs, try to install PEAR + if (strpos(dirname(__FILE__), 'scripts')) { + $packagexml = dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'package2.xml'; + $pearbase = dirname(dirname(__FILE__)); + } else { + $packagexml = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'package2.xml'; + $pearbase = dirname(__FILE__); + } + if (file_exists($packagexml)) { + $options[1] = array( + 'install', + $packagexml + ); + $config->set('php_dir', $pearbase . DIRECTORY_SEPARATOR . 'php'); + $config->set('data_dir', $pearbase . DIRECTORY_SEPARATOR . 'data'); + $config->set('doc_dir', $pearbase . DIRECTORY_SEPARATOR . 'docs'); + $config->set('test_dir', $pearbase . DIRECTORY_SEPARATOR . 'tests'); + $config->set('ext_dir', $pearbase . DIRECTORY_SEPARATOR . 'extensions'); + $config->set('bin_dir', $pearbase); + $config->mergeConfigFile($pearbase . 'pear.ini', false); + $config->store(); + $config->set('auto_discover', 1); + } + } + } +} +foreach ($opts as $opt) { + $param = !empty($opt[1]) ? $opt[1] : true; + switch ($opt[0]) { + case 'd': + if ($param === true) { + die('Invalid usage of "-d" option, expected -d config_value=value, ' . + 'received "-d"' . "\n"); + } + $possible = explode('=', $param); + if (count($possible) != 2) { + die('Invalid usage of "-d" option, expected -d config_value=value, received "' . + $param . '"' . "\n"); + } + list($key, $value) = explode('=', $param); + $config->set($key, $value, 'user'); + break; + case 'D': + if ($param === true) { + die('Invalid usage of "-d" option, expected -d config_value=value, ' . + 'received "-d"' . "\n"); + } + $possible = explode('=', $param); + if (count($possible) != 2) { + die('Invalid usage of "-d" option, expected -d config_value=value, received "' . + $param . '"' . "\n"); + } + list($key, $value) = explode('=', $param); + $config->set($key, $value, 'system'); + break; + case 's': + $store_user_config = true; + break; + case 'S': + $store_system_config = true; + break; + case 'u': + $config->remove($param, 'user'); + break; + case 'v': + $config->set('verbose', $config->get('verbose') + 1); + break; + case 'q': + $config->set('verbose', $config->get('verbose') - 1); + break; + case 'V': + usage(null, 'version'); + case 'c': + case 'C': + break; + default: + // all non pear params goes to the command + $cmdopts[$opt[0]] = $param; + break; + } +} + +if ($store_system_config) { + $config->store('system'); +} + +if ($store_user_config) { + $config->store('user'); +} + +$command = (isset($options[1][0])) ? $options[1][0] : null; + +if (empty($command) && ($store_user_config || $store_system_config)) { + exit; +} + +if ($fetype == 'Gtk' || $fetype == 'Gtk2') { + if (!$config->validConfiguration()) { + PEAR::raiseError('CRITICAL ERROR: no existing valid configuration files found in files ' . + "'$pear_user_config' or '$pear_system_config', please copy an existing configuration" . + 'file to one of these locations, or use the -c and -s options to create one'); + } + Gtk::main(); +} else do { + if ($command == 'help') { + usage(null, @$options[1][1]); + } + if (!$config->validConfiguration()) { + PEAR::raiseError('CRITICAL ERROR: no existing valid configuration files found in files ' . + "'$pear_user_config' or '$pear_system_config', please copy an existing configuration" . + 'file to one of these locations, or use the -c and -s options to create one'); + } + + PEAR::pushErrorHandling(PEAR_ERROR_RETURN); + $cmd = PEAR_Command::factory($command, $config); + PEAR::popErrorHandling(); + if (PEAR::isError($cmd)) { + usage(null, @$options[1][0]); + } + + $short_args = $long_args = null; + PEAR_Command::getGetoptArgs($command, $short_args, $long_args); + if (in_array('getopt2', get_class_methods('Console_Getopt'))) { + array_shift($options[1]); + $tmp = Console_Getopt::getopt2($options[1], $short_args, $long_args); + } else { + $tmp = Console_Getopt::getopt($options[1], $short_args, $long_args); + } + if (PEAR::isError($tmp)) { + break; + } + list($tmpopt, $params) = $tmp; + $opts = array(); + foreach ($tmpopt as $foo => $tmp2) { + list($opt, $value) = $tmp2; + if ($value === null) { + $value = true; // options without args + } + if (strlen($opt) == 1) { + $cmdoptions = $cmd->getOptions($command); + foreach ($cmdoptions as $o => $d) { + if (@$d['shortopt'] == $opt) { + $opts[$o] = $value; + } + } + } else { + if (substr($opt, 0, 2) == '--') { + $opts[substr($opt, 2)] = $value; + } + } + } + $ok = $cmd->run($command, $opts, $params); + if ($ok === false) { + PEAR::raiseError("unknown command `$command'"); + } + if (PEAR::isError($ok)) { + PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, array($ui, "displayFatalError")); + PEAR::raiseError($ok); + } +} while (false); + +// {{{ usage() + +function usage($error = null, $helpsubject = null) +{ + global $progname, $all_commands; + $stderr = fopen('php://stderr', 'w'); + if (PEAR::isError($error)) { + fputs($stderr, $error->getMessage() . "\n"); + } elseif ($error !== null) { + fputs($stderr, "$error\n"); + } + if ($helpsubject != null) { + $put = cmdHelp($helpsubject); + } else { + $put = + "Commands:\n"; + $maxlen = max(array_map("strlen", $all_commands)); + $formatstr = "%-{$maxlen}s %s\n"; + ksort($all_commands); + foreach ($all_commands as $cmd => $class) { + $put .= sprintf($formatstr, $cmd, PEAR_Command::getDescription($cmd)); + } + $put .= + "Usage: $progname [options] command [command-options] \n". + "Type \"$progname help options\" to list all options.\n". + "Type \"$progname help shortcuts\" to list all command shortcuts.\n". + "Type \"$progname help \" to get the help for the specified command."; + } + fputs($stderr, "$put\n"); + fclose($stderr); + exit(1); +} + +function cmdHelp($command) +{ + global $progname, $all_commands, $config; + if ($command == "options") { + return + "Options:\n". + " -v increase verbosity level (default 1)\n". + " -q be quiet, decrease verbosity level\n". + " -c file find user configuration in `file'\n". + " -C file find system configuration in `file'\n". + " -d foo=bar set user config variable `foo' to `bar'\n". + " -D foo=bar set system config variable `foo' to `bar'\n". + " -G start in graphical (Gtk) mode\n". + " -s store user configuration\n". + " -S store system configuration\n". + " -u foo unset `foo' in the user configuration\n". + " -h, -? display help/usage (this message)\n". + " -V version information\n"; + } elseif ($command == "shortcuts") { + $sc = PEAR_Command::getShortcuts(); + $ret = "Shortcuts:\n"; + foreach ($sc as $s => $c) { + $ret .= sprintf(" %-8s %s\n", $s, $c); + } + return $ret; + + } elseif ($command == "version") { + return "PEAR Version: ".$GLOBALS['pear_package_version']. + "\nPHP Version: ".phpversion(). + "\nZend Engine Version: ".zend_version(). + "\nRunning on: ".php_uname(); + + } elseif ($help = PEAR_Command::getHelp($command)) { + if (is_string($help)) { + return "$progname $command [options] $help\n"; + } + if ($help[1] === null) { + return "$progname $command $help[0]"; + } else { + return "$progname $command [options] $help[0]\n$help[1]"; + } + } + return "Command '$command' is not valid, try '$progname help'"; +} + +// }}} + +function error_handler($errno, $errmsg, $file, $line, $vars) { + if ((defined('E_STRICT') && $errno & E_STRICT) || (defined('E_DEPRECATED') && + $errno & E_DEPRECATED) || !error_reporting()) { + if (defined('E_STRICT') && $errno & E_STRICT) { + return; // E_STRICT + } + if (defined('E_DEPRECATED') && $errno & E_DEPRECATED) { + return; // E_DEPRECATED + } + if ($GLOBALS['config']->get('verbose') < 4) { + return false; // @silenced error, show all if debug is high enough + } + } + $errortype = array ( + E_ERROR => "Error", + E_WARNING => "Warning", + E_PARSE => "Parsing Error", + E_NOTICE => "Notice", + E_CORE_ERROR => "Core Error", + E_CORE_WARNING => "Core Warning", + E_COMPILE_ERROR => "Compile Error", + E_COMPILE_WARNING => "Compile Warning", + E_USER_ERROR => "User Error", + E_USER_WARNING => "User Warning", + E_USER_NOTICE => "User Notice" + ); + $prefix = $errortype[$errno]; + global $_PEAR_PHPDIR; + if (stristr($file, $_PEAR_PHPDIR)) { + $file = substr($file, strlen($_PEAR_PHPDIR) + 1); + } else { + $file = basename($file); + } + print "\n$prefix: $errmsg in $file on line $line\n"; + return false; +} + + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: nil + * mode: php + * End: + */ +// vim600:syn=php + +?> diff --git a/src/lib/pear/PEAR/pearfrontendweb.php b/src/lib/pear/PEAR/pearfrontendweb.php new file mode 100644 index 0000000..aa9fce2 --- /dev/null +++ b/src/lib/pear/PEAR/pearfrontendweb.php @@ -0,0 +1,491 @@ + | + | Pierre-Alain Joye | + | Tias Guns | + +----------------------------------------------------------------------+ + + * Web-based PEAR Frontend, include this file to display the fontend. + * This file does the basic configuration, handles all requests and calls + * the needed commands. + * + * @category pear + * @package PEAR_Frontend_Web + * @author Christian Dickmann + * @author Pierre-Alain Joye + * @author Tias Guns + * @copyright 1997-2007 The PHP Group + * @license http://www.php.net/license/2_02.txt PHP License 2.02 + * @version CVS: $Id: pearfrontendweb.php,v 1.69 2008/08/02 16:22:35 tias Exp $ + * @link http://pear.php.net/package/PEAR_Frontend_Web + * @since File available since Release 0.1 + */ + +/** + * This is PEAR_Frontend_Web + */ +define('PEAR_Frontend_Web',1); +@session_start(); + +/** + * base frontend class + */ +require_once 'PEAR/Frontend.php'; +require_once 'PEAR/Command.php'; + +// for the open_basedir prisoners, don't allow PEAR to search for a temp dir (would use /tmp), see bug #13167 +putenv('TMPDIR='.dirname(__FILE__).'/temp'); + +// set $pear_user_config if it isn't set yet +// finds an existing file, or proposes the default location +if (!isset($pear_user_config) || $pear_user_config == '') { + if (OS_WINDOWS) { + $conf_name = 'pear.ini'; + } else { + $conf_name = 'pear.conf'; + } + + // default backup config: the one from the installer (if available). + $install_config = '@pear_install_config@'; // filled in on install + // TODO: doesn't work yet ! There is no way to find the system config + if (file_exists($install_config)) { + $pear_user_config = $install_config; + } else { + + // find other config file location + $default_config_dirs = array( + substr(dirname(__FILE__), 0, strrpos(dirname(__FILE__), DIRECTORY_SEPARATOR)), // strip eg PEAR from .../example/PEAR(/pearfrontendweb.php) + dirname($_SERVER['SCRIPT_FILENAME']), + PEAR_CONFIG_SYSCONFDIR, + ); + // set the default: __FILE__ without PEAR/ + $pear_user_config = $default_config_dirs[0].DIRECTORY_SEPARATOR.$conf_name; + + $found = false; + foreach ($default_config_dirs as $confdir) { + if (file_exists($confdir.DIRECTORY_SEPARATOR.$conf_name)) { + $pear_user_config = $confdir.DIRECTORY_SEPARATOR.$conf_name; + $found = true; + break; + } + } + + if (!$found) { + print('

    Warning: Can not find config file, please specify the $pear_user_config variable in '.$_SERVER['PHP_SELF'].'

    '); + } + } + unset($conf_name, $default_config_dirs, $confdir); +} + +require_once 'PEAR/Registry.php'; +require_once 'PEAR/Config.php'; + +// moving this here allows startup messages and errors to work properly +PEAR_Frontend::setFrontendClass('PEAR_Frontend_Web'); +// Init PEAR Installer Code and WebFrontend +$GLOBALS['_PEAR_Frontend_Web_config'] = &PEAR_Config::singleton($pear_user_config, ''); +$config = &$GLOBALS['_PEAR_Frontend_Web_config']; +if (PEAR::isError($config)) { + die('Error: '.$config->getMessage()); +} + +$ui = &PEAR_Command::getFrontendObject(); +if (PEAR::isError($ui)) { + die('Error: '.$ui->getMessage()); +} +$ui->setConfig($config); + +PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, array($ui, "displayFatalError")); + +// Cient requests an Image/Stylesheet/Javascript +// outputFrontendFile() does exit() +if (isset($_GET["css"])) { + $ui->outputFrontendFile($_GET["css"], 'css'); +} +if (isset($_GET["js"])) { + $ui->outputFrontendFile($_GET["js"], 'js'); +} +if (isset($_GET["img"])) { + $ui->outputFrontendFile($_GET["img"], 'image'); +} + +$verbose = $config->get("verbose"); +$cmdopts = array(); +$opts = array(); +$params = array(); + +// create $pear_user_config if it doesn't exit yet +if (!file_exists($pear_user_config)) { + // I think PEAR_Frontend_Web is running for the first time! + // Create config and install it properly ... + $ui->outputBegin(null); + print('

    Preparing PEAR_Frontend_Web for its first time use...

    '); + + // find pear_dir: + if (!isset($pear_dir) || !file_exists($pear_dir)) { + // __FILE__ is eg .../example/PEAR/pearfrontendweb.php + $pear_dir = dirname(__FILE__); // eg .../example/PEAR + } + if (substr($pear_dir, -1) == DIRECTORY_SEPARATOR) { + $pear_dir = substr($pear_dir, 0, -1); // strip trailing / + } + // extract base_dir from pear_dir + $dir = substr($pear_dir, 0, strrpos($pear_dir, DIRECTORY_SEPARATOR)); // eg .../example + + $dir .= DIRECTORY_SEPARATOR; + if (!is_dir($dir)) { + PEAR::raiseError('Can not find a base installation directory of PEAR ('.$dir.' doesn\'t work), so we can\'t create a config for it. Please supply it in the variable \'$pear_dir\'. The $pear_dir must have at least the subdirectory PEAR/ and be writable by this frontend.'); + die(); + } + + print('Saving config file ('.$pear_user_config.')...'); + // First of all set some config-vars: + // Tries to be compatible with go-pear + if (!isset($pear_dir)) { + $pear_dir = $dir.'PEAR'; // default (go-pear compatible) + } + $cmd = PEAR_Command::factory('config-set', $config); + $ok = $cmd->run('config-set', array(), array('php_dir', $pear_dir)); + $ok = $cmd->run('config-set', array(), array('doc_dir', $pear_dir.'/docs')); + $ok = $cmd->run('config-set', array(), array('ext_dir', $dir.'ext')); + $ok = $cmd->run('config-set', array(), array('bin_dir', $dir.'bin')); + $ok = $cmd->run('config-set', array(), array('data_dir', $pear_dir.'/data')); + $ok = $cmd->run('config-set', array(), array('test_dir', $pear_dir.'/test')); + $ok = $cmd->run('config-set', array(), array('temp_dir', $dir.'temp')); + $ok = $cmd->run('config-set', array(), array('download_dir', $dir.'temp/download')); + $ok = $cmd->run('config-set', array(), array('cache_dir', $pear_dir.'/cache')); + $ok = $cmd->run('config-set', array(), array('cache_ttl', 300)); + $ok = $cmd->run('config-set', array(), array('default_channel', 'pear.php.net')); + $ok = $cmd->run('config-set', array(), array('preferred_mirror', 'pear.php.net')); + + print('Checking package registry...'); + // Register packages + $packages = array( + 'Archive_Tar', + 'Console_Getopt', + 'HTML_Template_IT', + 'PEAR', + 'PEAR_Frontend_Web', + 'Structures_Graph' + ); + $reg = &$config->getRegistry(); + if (!file_exists($pear_dir.'/.registry')) { + PEAR::raiseError('Directory "'.$pear_dir.'/.registry" does not exist. please check your installation'); + } + + foreach($packages as $pkg) { + $info = $reg->packageInfo($pkg); + foreach($info['filelist'] as $fileName => $fileInfo) { + if($fileInfo['role'] == "php") { + $info['filelist'][$fileName]['installed_as'] = + str_replace('{dir}',$dir, $fileInfo['installed_as']); + } + } + $reg->updatePackage($pkg, $info, false); + } + + print('

    PEAR_Frontend_Web configured succesfully !

    '); + $msg = sprintf('

    Click here to continue

    ', + $_SERVER['PHP_SELF']); + print($msg); + $ui->outputEnd(null); + die(); +} + +// Check _isProtected() override (disables the 'not protected' warning) +if (isset($pear_frontweb_protected) && $pear_frontweb_protected === true) { + $GLOBALS['_PEAR_Frontend_Web_protected'] = true; +} + +$cache_dir = $config->get('cache_dir'); +if (!is_dir($cache_dir)) { + include_once 'System.php'; + if (!System::mkDir('-p', $cache_dir)) { + PEAR::raiseError('Directory "'.$cache_dir.'" does not exist and cannot be created. Please check your installation'); + } +} + +if (isset($_GET['command']) && !is_null($_GET['command'])) { + $command = $_GET['command']; +} else { + $command = 'list'; +} + +// Prepare and begin output +$ui->outputBegin($command); + +// Handle some different Commands + switch ($command) { + case 'install': + case 'uninstall': + case 'upgrade': + if ($_GET['command'] == 'install') { + // also install dependencies + $opts['onlyreqdeps'] = true; + if (isset($_GET['force']) && $_GET['force'] == 'on') { + $opts['force'] = true; + } + } + + if (strpos($_GET['pkg'], '\\\\') !== false) { + $_GET['pkg'] = stripslashes($_GET['pkg']); + } + $params = array($_GET["pkg"]); + $cmd = PEAR_Command::factory($command, $config); + $ok = $cmd->run($command, $opts, $params); + + $reg = &$config->getRegistry(); + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + $err = $reg->parsePackageName($_GET['pkg']); + PEAR::staticPopErrorHandling(); // reset error handling + + if (!PEAR::isError($err)) { + $ui->finishOutput('Back', array('link' => $_SERVER['PHP_SELF'].'?command=info&pkg='.$_GET['pkg'], + 'text' => 'View package information')); + } + break; + case 'run-scripts' : + $params = array($_GET['pkg']); + $cmd = PEAR_Command::factory($command, $config); + $ok = $cmd->run($command, $opts, $params); + break; + case 'info': + case 'remote-info': + $reg = &$config->getRegistry(); + // we decide what it is: + $pkg = $reg->parsePackageName($_GET['pkg']); + if ($reg->packageExists($pkg['package'], $pkg['channel'])) { + $command = 'info'; + } else { + $command = 'remote-info'; + } + + $params = array(strtolower($_GET['pkg'])); + $cmd = PEAR_Command::factory($command, $config); + $ok = $cmd->run($command, $opts, $params); + + break; + case 'search': + if (!isset($_POST['search']) || $_POST['search'] == '') { + // unsubmited, show forms + $ui->outputSearch(); + } else { + if ($_POST['channel'] == 'all') { + $opts['allchannels'] = true; + } else { + $opts['channel'] = $_POST['channel']; + } + $opts['channelinfo'] = true; + + // submited, do search + switch ($_POST['search']) { + case 'name': + $params = array($_POST['input']); + break; + case 'description': + $params = array($_POST['input'], $_POST['input']); + break; + default: + PEAR::raiseError('Can\'t search for '.$_POST['search']); + break; + } + + $cmd = PEAR_Command::factory($command, $config); + $ok = $cmd->run($command, $opts, $params); + } + + break; + case 'config-show': + $cmd = PEAR_Command::factory($command, $config); + $res = $cmd->run($command, $opts, $params); + + // if this code is reached, the config vars are submitted + $set = PEAR_Command::factory('config-set', $config); + foreach($GLOBALS['_PEAR_Frontend_Web_Config'] as $var => $value) { + if ($var == 'Filename') { + continue; // I hate obscure bugs + } + if ($value != $config->get($var)) { + print('Saving '.$var.'... '); + $res = $set->run('config-set', $opts, array($var, $value)); + $config->set($var, $value); + } + } + print('

    Config saved succesfully!

    '); + + $ui->finishOutput('Back', array('link' => $_SERVER['PHP_SELF'].'?command='.$command, 'text' => 'Back to the config')); + break; + case 'list-files': + $params = array($_GET['pkg']); + $cmd = PEAR_Command::factory($command, $config); + $res = $cmd->run($command, $opts, $params); + break; + case 'list-docs': + if (!isset($_GET['pkg'])) { + PEAR::raiseError('The webfrontend-command list-docs needs at least one \'pkg\' argument.'); + break; + } + + require_once('PEAR/Frontend/Web/Docviewer.php'); + $reg = $config->getRegistry(); + $pkg = $reg->parsePackageName($_GET['pkg']); + + $docview = new PEAR_Frontend_Web_Docviewer($ui); + $docview->outputListDocs($pkg['package'], $pkg['channel']); + break; + case 'doc-show': + if (!isset($_GET['pkg']) || !isset($_GET['file'])) { + PEAR::raiseError('The webfrontend-command list-docs needs one \'pkg\' and one \'file\' argument.'); + break; + } + + require_once('PEAR/Frontend/Web/Docviewer.php'); + $reg = $config->getRegistry(); + $pkg = $reg->parsePackageName($_GET['pkg']); + + $docview = new PEAR_Frontend_Web_Docviewer($ui); + $docview->outputDocShow($pkg['package'], $pkg['channel'], $_GET['file']); + break; + case 'list-all': + // Deprecated, use 'list-categories' is used instead + if (isset($_GET['chan']) && $_GET['chan'] != '') { + $opts['channel'] = $_GET['chan']; + } + $opts['channelinfo'] = true; + $cmd = PEAR_Command::factory($command, $config); + $res = $cmd->run($command, $opts, $params); + + break; + case 'list-categories': + case 'list-packages': + if (isset($_GET['chan']) && $_GET['chan'] != '') { + $opts['channel'] = $_GET['chan']; + } else { + // show 'table of contents' before all channel output + $ui->outputTableOfChannels(); + + $opts['allchannels'] = true; + } + if (isset($_GET['opt']) && $_GET['opt'] == 'packages') { + $opts['packages'] = true; + } + $cmd = PEAR_Command::factory($command, $config); + $res = $cmd->run($command, $opts, $params); + + break; + case 'list-category': + if (isset($_GET['chan']) && $_GET['chan'] != '') { + $opts['channel'] = $_GET['chan']; + } + $params = array($_GET['cat']); + $cmd = PEAR_Command::factory($command, $config); + $res = $cmd->run($command, $opts, $params); + + break; + case 'list': + $opts['allchannels'] = true; + $opts['channelinfo'] = true; + $cmd = PEAR_Command::factory($command, $config); + $res = $cmd->run($command, $opts, $params); + + break; + case 'list-upgrades': + $opts['channelinfo'] = true; + $cmd = PEAR_Command::factory($command, $config); + $res = $cmd->run($command, $opts, $params); + $ui->outputUpgradeAll(); + + break; + case 'upgrade-all': + $cmd = PEAR_Command::factory($command, $config); + $ok = $cmd->run($command, $opts, $params); + + $ui->finishOutput('Back', array('link' => $_SERVER['PHP_SELF'].'?command=list', + 'text' => 'Click here to go back')); + break; + case 'channel-info': + if (isset($_GET['chan'])) + $params[] = $_GET['chan']; + $cmd = PEAR_Command::factory($command, $config); + $ok = $cmd->run($command, $opts, $params); + + break; + case 'channel-discover': + if (isset($_GET['chan']) && $_GET['chan'] != '') + $params[] = $_GET['chan']; + $cmd = PEAR_Command::factory($command, $config); + $ui->startSession(); + $ok = $cmd->run($command, $opts, $params); + + $ui->finishOutput('Channel Discovery', array('link' => + $_SERVER['PHP_SELF'] . '?command=channel-info&chan=' . urlencode($_GET['chan']), + 'text' => 'Click Here for ' . htmlspecialchars($_GET['chan']) . ' Information')); + break; + case 'channel-delete': + if (isset($_GET["chan"])) + $params[] = $_GET["chan"]; + $cmd = PEAR_Command::factory($command, $config); + $ok = $cmd->run($command, $opts, $params); + + $ui->finishOutput('Delete Channel', array('link' => + $_SERVER['PHP_SELF'] . '?command=list-channels', + 'text' => 'Click here to list all channels')); + break; + case 'list-channels': + $cmd = PEAR_Command::factory($command, $config); + $ok = $cmd->run($command, $opts, $params); + + break; + case 'channel-update': + if (isset($_GET['chan'])) { + $params = array($_GET['chan']); + } + $cmd = PEAR_Command::factory($command, $config); + $ok = $cmd->run($command, $opts, $params); + + break; + case 'update-channels': + // update every channel manually, + // fixes bug PEAR/#10275 (XML_RPC dependency) + // will be fixed in next pear release + $reg = &$config->getRegistry(); + $channels = $reg->getChannels(); + $command = 'channel-update'; + $cmd = PEAR_Command::factory($command, $config); + + $success = true; + $ui->startSession(); + foreach ($channels as $channel) { + if ($channel->getName() != '__uri') { + $success &= $cmd->run($command, $opts, + array($channel->getName())); + } + } + + $ui->finishOutput('Update Channel List', array('link' => + $_SERVER['PHP_SELF'] . '?command=list-channels', + 'text' => 'Click here to list all channels')); + break; + default: + $cmd = PEAR_Command::factory($command, $config); + $res = $cmd->run($command, $opts, $params); + + break; + } + +$ui->outputEnd($command); + +?> diff --git a/src/lib/pear/PEAR/peclcmd.php b/src/lib/pear/PEAR/peclcmd.php new file mode 100644 index 0000000..d0751b4 --- /dev/null +++ b/src/lib/pear/PEAR/peclcmd.php @@ -0,0 +1,45 @@ + | +// | Tomas V.V.Cox | +// | | +// +----------------------------------------------------------------------+ +// +// $Id: peclcmd.php,v 1.1 2005/02/21 05:30:56 cellog Exp $ + +/** + * @nodep Gtk + */ +if ('/www/htdocs/w00acdb0/lib/pear/PEAR' != '@'.'include_path'.'@') { + ini_set('include_path', '/www/htdocs/w00acdb0/lib/pear/PEAR'); + $raw = false; +} else { + // this is a raw, uninstalled pear, either a cvs checkout, or php distro + $raw = true; +} +define('PEAR_RUNTYPE', 'pecl'); +require_once 'pearcmd.php'; +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: nil + * mode: php + * End: + */ +// vim600:syn=php + +?> diff --git a/src/lib/pear/PEAR/tests/Config/test/bug10010.phpt b/src/lib/pear/PEAR/tests/Config/test/bug10010.phpt new file mode 100644 index 0000000..a764b35 --- /dev/null +++ b/src/lib/pear/PEAR/tests/Config/test/bug10010.phpt @@ -0,0 +1,58 @@ +--TEST-- +regression test for bug #10010 +--FILE-- + 'bar', + 'aMonths' => array( + 1 => 'January', + 2 => 'February', + 3 => 'March', + 4 => 'April', + 5 => 'May', + 6 => 'June', + 7 => 'July', + 8 => 'August', + 9 => 'September', + 10 => 'October', + 11 => 'November', + 12 => 'December',) + ); + + +$c = new Config(); +$root = & $c->parseConfig($aTrans, + 'phparray', + array('duplicateDirectives' => false)); +$filename = './bug10010-output.php'; +$result = $c->writeConfig($filename, + 'phparray', + array('name' => 'words')); + +include($filename); +print_r($words) + +?> +--EXPECT-- +Array +( + [foo] => bar + [aMonths] => Array + ( + [1] => January + [2] => February + [3] => March + [4] => April + [5] => May + [6] => June + [7] => July + [8] => August + [9] => September + [10] => October + [11] => November + [12] => December + ) + +) diff --git a/src/lib/pear/PEAR/tests/Config/test/bug10185.phpt b/src/lib/pear/PEAR/tests/Config/test/bug10185.phpt new file mode 100644 index 0000000..82d830c --- /dev/null +++ b/src/lib/pear/PEAR/tests/Config/test/bug10185.phpt @@ -0,0 +1,40 @@ +--TEST-- +regression test for bug #10185 +--FILE-- +s %b" common'.PHP_EOL; +$conf .= ''.PHP_EOL; +$conf .= ' CustomLog "/foo/bar/access.log" common'.PHP_EOL; +$conf .= ''.PHP_EOL; +$conf .= ''.PHP_EOL; +$conf .= ' CustomLog "\foo\bar\access.log" common'.PHP_EOL; +$conf .= ''.PHP_EOL; +$conf .= ''.PHP_EOL; +$conf .= ' CustomLog "\\\foo\\\bar\\\access.log" common'.PHP_EOL; +$conf .= ''.PHP_EOL; + +$conf1 = new Config; +$root1 =& $conf1->parseConfig('bug10185.httpd.conf.old', 'apache'); +$conf1->writeConfig('bug10185.httpd.conf.new.php', 'phparray', + array('name' => 'test')); + +$conf2 = new Config; +$root2 =& $conf2->parseConfig('bug10185.httpd.conf.new.php', 'phparray', + array('name' => 'test')); +$conf2->writeConfig('bug10185.httpd.conf.new', 'apache'); +readfile('bug10185.httpd.conf.new'); + +?> +--EXPECT-- +LogFormat "%h %l %u %t \"%r\" %>s %b" common + + CustomLog "/foo/bar/access.log" common + + + CustomLog "\foo\bar\access.log" common + + + CustomLog "\\foo\\bar\\access.log" common + diff --git a/src/lib/pear/PEAR/tests/Config/test/bug2742.ini b/src/lib/pear/PEAR/tests/Config/test/bug2742.ini new file mode 100644 index 0000000..d071e17 --- /dev/null +++ b/src/lib/pear/PEAR/tests/Config/test/bug2742.ini @@ -0,0 +1 @@ +var = 1234 \ No newline at end of file diff --git a/src/lib/pear/PEAR/tests/Config/test/bug2742.phpt b/src/lib/pear/PEAR/tests/Config/test/bug2742.phpt new file mode 100644 index 0000000..bc301c3 --- /dev/null +++ b/src/lib/pear/PEAR/tests/Config/test/bug2742.phpt @@ -0,0 +1,16 @@ +--TEST-- +test for bug 2742 +--FILE-- +parseConfig($datasrc, 'inicommented'); +if ($phpt->assertNoErrors('problem!')) { + $phpt->assertEquals('$php_ini[\'var\'] = \'1234\';', + $root->toString('phparray', array('name' => 'php_ini')), + 'convert var = 1234 to array'); +} +echo 'tests done'; +?> +--EXPECT-- +tests done diff --git a/src/lib/pear/PEAR/tests/Config/test/bug2780.phpt b/src/lib/pear/PEAR/tests/Config/test/bug2780.phpt new file mode 100644 index 0000000..3acfbc2 --- /dev/null +++ b/src/lib/pear/PEAR/tests/Config/test/bug2780.phpt @@ -0,0 +1,14 @@ +--TEST-- +bug 2780 regression +--FILE-- +addItem($c2); + // Convert your ini file to a php array config + echo $c1->toString('phparray', array('name' => 'php_ini')); +?> +--EXPECT-- diff --git a/src/lib/pear/PEAR/tests/Config/test/bug3051.phpt b/src/lib/pear/PEAR/tests/Config/test/bug3051.phpt new file mode 100644 index 0000000..4b7d567 --- /dev/null +++ b/src/lib/pear/PEAR/tests/Config/test/bug3051.phpt @@ -0,0 +1,22 @@ +--TEST-- +test for bug 3051 +--FILE-- +parseConfig('bug3051.xml', 'xml'); + +$root =& $root->getChild(0); + +for ($i=0; $i < $root->countChildren('directive', 'item'); $i++) { + $item = $root->getItem('directive', 'item', null, null, $i); + print $item->getAttribute('name')."\n"; + +} +?> +--EXPECT-- +item1 +item2 + diff --git a/src/lib/pear/PEAR/tests/Config/test/bug3051.xml b/src/lib/pear/PEAR/tests/Config/test/bug3051.xml new file mode 100644 index 0000000..8770390 --- /dev/null +++ b/src/lib/pear/PEAR/tests/Config/test/bug3051.xml @@ -0,0 +1,4 @@ + + + + diff --git a/src/lib/pear/PEAR/tests/Config/test/bug3137.phpt b/src/lib/pear/PEAR/tests/Config/test/bug3137.phpt new file mode 100644 index 0000000..ffded29 --- /dev/null +++ b/src/lib/pear/PEAR/tests/Config/test/bug3137.phpt @@ -0,0 +1,32 @@ +--TEST-- +regression test for bug #3137 +--FILE-- +parseConfig($array, "phparray"); +if (PEAR::isError($root)) { + die('Error while reading configuration: ' . $root->getMessage() . "\r\n"); +} + +$result = $root->createComment("Comment", "before", $root->children[0]); +if (PEAR::isError($result)) { + die('Error while reading configuration: ' . $result->getMessage() . "\r\n"); +} + +$exp = '// Comment +$conf[0] = \'foo\'; +$conf[1] = \'bar\'; +$conf[2] = \'too\'; +'; + +//print_r($root->toString('phparray')); +if ($phpt->assertNoErrors('problem!')) { + $phpt->assertEquals($root->toString('phparray'), $exp, 'uh oh'); +} + +echo 'tests done'; +?> +--EXPECT-- +tests done diff --git a/src/lib/pear/PEAR/tests/Config/test/bug3298.phpt b/src/lib/pear/PEAR/tests/Config/test/bug3298.phpt new file mode 100644 index 0000000..f973ee1 --- /dev/null +++ b/src/lib/pear/PEAR/tests/Config/test/bug3298.phpt @@ -0,0 +1,25 @@ +--TEST-- +bug 3298 regression test +--FILE-- +parseConfig($datasrc, 'XML'); + +$configArray = $root->toArray('PHParray'); +$config2 = new Config(); +$root2 = $config2->parseConfig(current($configArray), 'PHParray'); + +if ($root2->writeDatasrc('new_config.xml', 'XML')) { + $file = file_get_contents("new_config.xml"); +} else { + echo "error updating XML"; +} + +if ($phpt->assertNoErrors('problem!')) { + $phpt->assertEquals( file_get_contents($datasrc), $file, "XML doesn't match"); +} +echo 'tests done'; +?> +--EXPECT-- +tests done diff --git a/src/lib/pear/PEAR/tests/Config/test/bug3298.xml b/src/lib/pear/PEAR/tests/Config/test/bug3298.xml new file mode 100644 index 0000000..84f3ef3 --- /dev/null +++ b/src/lib/pear/PEAR/tests/Config/test/bug3298.xml @@ -0,0 +1,30 @@ + + + clients + + + + + intern + true + + + + intern + true + +
    + + + + intern + true + + + + intern + true + +
    +
    +
    diff --git a/src/lib/pear/PEAR/tests/Config/test/bug3398.ini b/src/lib/pear/PEAR/tests/Config/test/bug3398.ini new file mode 100644 index 0000000..242c4f9 --- /dev/null +++ b/src/lib/pear/PEAR/tests/Config/test/bug3398.ini @@ -0,0 +1,5 @@ +[Preset] +presets=common + +[common] +sntpTZ=type=4,"value=CST6DST5,M4.1.0/02:00:00,M10.5.0/02:00:00",name=sntpTZ, label=TimeZone, form=text, "select=array (value => %value, size => 37);" diff --git a/src/lib/pear/PEAR/tests/Config/test/bug3398.phpt b/src/lib/pear/PEAR/tests/Config/test/bug3398.phpt new file mode 100644 index 0000000..830d6a4 --- /dev/null +++ b/src/lib/pear/PEAR/tests/Config/test/bug3398.phpt @@ -0,0 +1,33 @@ +--TEST-- +regression test for bug #3398 +--FILE-- +parseConfig($datasrc, 'inicommented'); +if (PEAR::isError($root)) { + die('Error while reading configuration: ' . $root->getMessage() . "\r\n"); +} + +$exp = array( 'root' => array ( + 'Preset' => array ('presets' => 'common'), + 'common' => array ( + 'sntpTZ' => array( + 0 => 'type=4', + 1 => 'value=CST6DST5,M4.1.0/02:00:00,M10.5.0/02:00:00', + 2 => 'name=sntpTZ', + 3 => 'label=TimeZone', + 4 => 'form=text', + 5 => 'select=array (value => %value, size => 37);') + ) + )); +//print_r($root->toArray()); +if ($phpt->assertNoErrors('problem!')) { + $phpt->assertEquals($root->toArray(), $exp, 'uh oh'); +} + +echo 'tests done'; +?> +--EXPECT-- +tests done diff --git a/src/lib/pear/PEAR/tests/Config/test/bug3590-input.php b/src/lib/pear/PEAR/tests/Config/test/bug3590-input.php new file mode 100644 index 0000000..acafa97 --- /dev/null +++ b/src/lib/pear/PEAR/tests/Config/test/bug3590-input.php @@ -0,0 +1,15 @@ + 'croooow', + 'password' => 'coolrobot', + 'host' => 'localhost', + 'database' => 'deep13' + ); + +$conf['emergencyemails'] = array( + 'joel@example.org', + 'cambot@example.org' + ); + +?> diff --git a/src/lib/pear/PEAR/tests/Config/test/bug3590.phpt b/src/lib/pear/PEAR/tests/Config/test/bug3590.phpt new file mode 100644 index 0000000..b01c4eb --- /dev/null +++ b/src/lib/pear/PEAR/tests/Config/test/bug3590.phpt @@ -0,0 +1,28 @@ +--TEST-- +regression test for bug #3590 +--FILE-- +parseConfig($datasrc, "phparray"); +if (PEAR::isError($root)) { + die('Error while reading configuration: ' . $root->getMessage() . "\r\n"); +} + +$exp = '$conf[\'mysql\'][\'user\'] = \'croooow\'; +$conf[\'mysql\'][\'password\'] = \'coolrobot\'; +$conf[\'mysql\'][\'host\'] = \'localhost\'; +$conf[\'mysql\'][\'database\'] = \'deep13\'; +$conf[\'emergencyemails\'][0] = \'joel@example.org\'; +$conf[\'emergencyemails\'][1] = \'cambot@example.org\'; +'; + +if ($phpt->assertNoErrors('problem!')) { + $phpt->assertEquals($root->toString('phparray'), $exp, 'uh oh'); +} + +echo 'tests done'; +?> +--EXPECT-- +tests done diff --git a/src/lib/pear/PEAR/tests/Config/test/bug4623.conf b/src/lib/pear/PEAR/tests/Config/test/bug4623.conf new file mode 100644 index 0000000..9527b72 --- /dev/null +++ b/src/lib/pear/PEAR/tests/Config/test/bug4623.conf @@ -0,0 +1,8 @@ + + ServerName www.foo.com + + + + Limit GET + TESTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT blah + diff --git a/src/lib/pear/PEAR/tests/Config/test/bug4623.phpt b/src/lib/pear/PEAR/tests/Config/test/bug4623.phpt new file mode 100644 index 0000000..a5a1dd8 --- /dev/null +++ b/src/lib/pear/PEAR/tests/Config/test/bug4623.phpt @@ -0,0 +1,22 @@ +--TEST-- +regression test for bug #3590 +--FILE-- +parseConfig($datasrc, "Apache"); +if (PEAR::isError($root)) { + die('Error while reading configuration: ' . $root->getMessage() . "\r\n"); +} + +$exp = $root->toString('Apache'); + +if ($phpt->assertNoErrors('problem!')) { + $phpt->assertEquals($root->toString('Apache'), $exp, 'uh oh'); +} + +echo 'tests done'; +?> +--EXPECT-- +tests done diff --git a/src/lib/pear/PEAR/tests/Config/test/bug6441.ini b/src/lib/pear/PEAR/tests/Config/test/bug6441.ini new file mode 100644 index 0000000..1b93e0e --- /dev/null +++ b/src/lib/pear/PEAR/tests/Config/test/bug6441.ini @@ -0,0 +1,8 @@ +val1 = true +val2 = false +val3 = True +val4 = False +val5 = TRUE +val6 = FALSE +val7 = "true" +val8 = "false" diff --git a/src/lib/pear/PEAR/tests/Config/test/bug6441.phpt b/src/lib/pear/PEAR/tests/Config/test/bug6441.phpt new file mode 100644 index 0000000..2e7e28d --- /dev/null +++ b/src/lib/pear/PEAR/tests/Config/test/bug6441.phpt @@ -0,0 +1,33 @@ +--TEST-- +regression test for bug #6441 +--FILE-- +parseConfig($datasrc, 'inicommented'); +$temp = $conf_obj->toArray(); +$conf = $temp['root']; +var_dump($conf); + +?> +--EXPECT-- +array(8) { + ["val1"]=> + string(1) "1" + ["val2"]=> + string(0) "" + ["val3"]=> + string(1) "1" + ["val4"]=> + string(0) "" + ["val5"]=> + string(1) "1" + ["val6"]=> + string(0) "" + ["val7"]=> + string(4) "true" + ["val8"]=> + string(5) "false" +} diff --git a/src/lib/pear/PEAR/tests/Config/test/bug7544-inicommented.phpt b/src/lib/pear/PEAR/tests/Config/test/bug7544-inicommented.phpt new file mode 100644 index 0000000..ff8978e --- /dev/null +++ b/src/lib/pear/PEAR/tests/Config/test/bug7544-inicommented.phpt @@ -0,0 +1,20 @@ +--TEST-- +regression test for bug #7544 - IniCommented +--FILE-- +parseConfig($datasrc, 'IniCommented'); + +$root =& $config->getRoot(); + +print $root->toString('phparray'); + +?> +--EXPECT-- +$conf['test']['myattrib1'] = 'wee'; +$conf['test']['myattrib2'] = ''; +// comment + +// after blank line diff --git a/src/lib/pear/PEAR/tests/Config/test/bug7544-inifile.phpt b/src/lib/pear/PEAR/tests/Config/test/bug7544-inifile.phpt new file mode 100644 index 0000000..0cfcbb3 --- /dev/null +++ b/src/lib/pear/PEAR/tests/Config/test/bug7544-inifile.phpt @@ -0,0 +1,17 @@ +--TEST-- +regression test for bug #7544 - IniFile +--FILE-- +parseConfig($datasrc, 'IniFile'); + +$root =& $config->getRoot(); + +print $root->toString('phparray'); + +?> +--EXPECT-- +$conf['test']['myattrib1'] = 'wee'; +$conf['test']['myattrib2'] = ''; diff --git a/src/lib/pear/PEAR/tests/Config/test/bug7544.ini b/src/lib/pear/PEAR/tests/Config/test/bug7544.ini new file mode 100644 index 0000000..fff8209 --- /dev/null +++ b/src/lib/pear/PEAR/tests/Config/test/bug7544.ini @@ -0,0 +1,6 @@ +[test] +myattrib1=wee +myattrib2= +;comment + +;after blank line diff --git a/src/lib/pear/PEAR/tests/Config/test/bug7652.phpt b/src/lib/pear/PEAR/tests/Config/test/bug7652.phpt new file mode 100644 index 0000000..5d1f2dd --- /dev/null +++ b/src/lib/pear/PEAR/tests/Config/test/bug7652.phpt @@ -0,0 +1,21 @@ +--TEST-- +regression test for bug #7652 +--FILE-- +parseConfig($datasrc, 'xml'); + +$root =& $config->getRoot(); + +print $root->toString('phparray'); + +?> +--EXPECT-- +$conf['root']['tag1'][0]['#'] = ''; +$conf['root']['tag1'][0]['@']['attrib'] = 'val'; +$conf['root']['tag1'][1]['@']['attrib'] = 'val2'; +$conf['root']['tag1'][1]['tag2'] = 'hello world'; +$conf['root']['tag1'][2]['#'] = ''; +$conf['root']['tag1'][2]['@']['attrib'] = 'val23'; diff --git a/src/lib/pear/PEAR/tests/Config/test/bug7652.xml b/src/lib/pear/PEAR/tests/Config/test/bug7652.xml new file mode 100644 index 0000000..d8c73da --- /dev/null +++ b/src/lib/pear/PEAR/tests/Config/test/bug7652.xml @@ -0,0 +1,8 @@ + + + + + hello world + + + diff --git a/src/lib/pear/PEAR/tests/Config/test/bug8357-inicommented.phpt b/src/lib/pear/PEAR/tests/Config/test/bug8357-inicommented.phpt new file mode 100644 index 0000000..6bc0719 --- /dev/null +++ b/src/lib/pear/PEAR/tests/Config/test/bug8357-inicommented.phpt @@ -0,0 +1,17 @@ +--TEST-- +regression test for bug #8357 - IniCommented +--FILE-- +parseConfig($datasrc, 'IniCommented'); + +$root =& $config->getRoot(); + +print $root->toString('phparray'); + +?> +--EXPECT-- +$conf['meta']['robots'] = 'index, follow'; +$conf['meta']['keywords'] = 'key, words'; diff --git a/src/lib/pear/PEAR/tests/Config/test/bug8357-inifile.phpt b/src/lib/pear/PEAR/tests/Config/test/bug8357-inifile.phpt new file mode 100644 index 0000000..e0e8f7d --- /dev/null +++ b/src/lib/pear/PEAR/tests/Config/test/bug8357-inifile.phpt @@ -0,0 +1,19 @@ +--TEST-- +regression test for bug #8357 - IniFile +--FILE-- +parseConfig($datasrc, 'IniFile'); + +$root =& $config->getRoot(); + +print $root->toString('phparray'); + +?> +--EXPECT-- +$conf['meta']['robots'][0] = 'index'; +$conf['meta']['robots'][1] = 'follow'; +$conf['meta']['keywords'][0] = 'key'; +$conf['meta']['keywords'][1] = 'words'; diff --git a/src/lib/pear/PEAR/tests/Config/test/bug8357.ini b/src/lib/pear/PEAR/tests/Config/test/bug8357.ini new file mode 100644 index 0000000..8eed59e --- /dev/null +++ b/src/lib/pear/PEAR/tests/Config/test/bug8357.ini @@ -0,0 +1,3 @@ +[meta] +robots = "index, follow" +keywords = "key, words" diff --git a/src/lib/pear/PEAR/tests/Config/test/phpt_test.php.inc b/src/lib/pear/PEAR/tests/Config/test/phpt_test.php.inc new file mode 100644 index 0000000..d7ecafb --- /dev/null +++ b/src/lib/pear/PEAR/tests/Config/test/phpt_test.php.inc @@ -0,0 +1,404 @@ +_diffonly = $diffonly; + $this->_errors = array(); + PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, array(&$this, 'pearerrorCallback')); + PEAR_ErrorStack::setDefaultCallback(array(&$this, 'pearerrorstackCallback')); + } + + function pearerrorCallback($err) + { + PEAR_ErrorStack::staticPush('PEAR_Error', -1, 'error', array('obj' => $err), + $err->getMessage()); + } + + function pearerrorstackCallback($err) + { + $this->_errors[] = $err; + } + + function assertPEARError($err, $message) + { + if (is_a($err, 'PEAR_Error')) { + return true; + } + $this->_failTest(debug_backtrace(), $message); + echo "Not a PEAR_Error\n"; + return false; + } + + function assertNoErrors($message, $trace = null) + { + if (count($this->_errors) == 0) { + return true; + } + if ($trace === null) { + $trace = debug_backtrace(); + } + $this->_failTest($trace, $message); + foreach ($this->_errors as $err) { + if ($err['package'] == 'PEAR_Error') { + echo "Unexpected PEAR_Error:\n"; + echo 'message "' . $err['message'] . "\"\n"; + } else { + echo "Unexpected PEAR_ErrorStack error:\n"; + echo 'package "' . $err['package'] . "\"\n"; + echo 'message "' . $err['message'] . "\"\n"; + } + } + $this->_errors = array(); + return false; + } + + function assertErrors($errors, $message, $trace = null) + { + if (!count($this->_errors)) { + if ($trace === null) { + $trace = debug_backtrace(); + } + $this->_failTest($trace, $message); + echo "No errors caught, but errors were expected\n"; + return false; + } + if (!isset($errors[0])) { + $errors = array($errors); + } + $failed = false; + foreach ($errors as $err) { + $found = false; + foreach ($this->_errors as $i => $caughterror) { + if ($caughterror['package'] == $err['package']) { + if ($caughterror['message'] == $err['message']) { + $found = true; + break; + } + } + } + if ($found) { + unset($this->_errors[$i]); + continue; + } + if (!$failed) { + if ($trace === null) { + $trace = debug_backtrace(); + } + $failed = true; + $this->_failTest($trace, $message); + } + echo "Unthrown error:\n"; + if ($err['package'] == 'PEAR_Error') { + echo "PEAR_Error:\n"; + } else { + echo "error package: \"$err[package]\"\n"; + } + echo "message: \"$err[message]\"\n"; + } + if (count($this->_errors)) { + if (!$failed) { + if ($trace === null) { + $trace = debug_backtrace(); + } + $failed = true; + $this->_failTest($trace, $message); + } + foreach ($this->_errors as $err) { + echo "Unexpected error:\n"; + if ($err['package'] == 'PEAR_Error') { + echo "PEAR_Error:\n"; + } else { + echo "error package: \"$err[package]\"\n"; + } + echo "message: \"$err[message]\"\n"; + } + } + $this->_errors = array(); + return !$failed; + } + + function assertTrue($test, $message) + { + $this->assertNoErrors($message, debug_backtrace()); + if ($test === true) { + return true; + } + $this->_failTest(debug_backtrace(), $message); + echo "Unexpected non-true value: \n"; + var_export($test); + echo "\n'$message'\n"; + return false; + } + + function assertIsa($control, $test, $message) + { + $this->assertNoErrors($message, debug_backtrace()); + if (is_a($test, $control)) { + return true; + } + $this->_failTest(debug_backtrace(), $message); + echo "Unexpected non-$control object: \n"; + var_export($test); + echo "\n'$message'\n"; + return false; + } + + function assertNull($test, $message) + { + $this->assertNoErrors($message, debug_backtrace()); + if ($test === null) { + return true; + } + $this->_failTest(debug_backtrace(), $message); + echo "Unexpected non-null value: \n"; + var_export($test); + echo "\n'$message'\n"; + return false; + } + + function assertNotNull($test, $message) + { + $this->assertNoErrors($message, debug_backtrace()); + if ($test !== null) { + return true; + } + $this->_failTest(debug_backtrace(), $message); + echo "Unexpected null: \n"; + var_export($test); + echo "\n'$message'\n"; + return false; + } + + function assertSame($test, $test1, $message) + { + $this->assertNoErrors($message, debug_backtrace()); + if ($test === $test1) { + return true; + } + $this->_failTest(debug_backtrace(), $message); + echo "Unexpectedly two vars are not the same thing: \n"; + echo "\n'$message'\n"; + return false; + } + + function assertNotSame($test, $test1, $message) + { + $this->assertNoErrors($message, debug_backtrace()); + if ($test !== $test1) { + return true; + } + $this->_failTest(debug_backtrace(), $message); + echo "Unexpectedly two vars are the same thing: \n"; + echo "\n'$message'\n"; + return false; + } + + function assertFalse($test, $message) + { + $this->assertNoErrors($message, debug_backtrace()); + if ($test === false) { + return true; + } + $this->_failTest(debug_backtrace(), $message); + echo "Unexpected non-false value: \n"; + var_export($test); + echo "\n'$message'\n"; + return false; + } + + function assertNotTrue($test, $message) + { + $this->assertNoErrors($message, debug_backtrace()); + if (!$test) { + return true; + } + $this->_failTest(debug_backtrace(), $message); + echo "Unexpected loose true value: \n"; + var_export($test); + echo "\n'$message'\n"; + return false; + } + + function assertNotFalse($test, $message) + { + $this->assertNoErrors($message, debug_backtrace()); + if ($test) { + return true; + } + $this->_failTest(debug_backtrace(), $message); + echo "Unexpected loose false value: \n"; + var_export($test); + echo "\n'$message'\n"; + return false; + } + + function assertEquals($control, $test, $message) + { + $this->assertNoErrors($message, debug_backtrace()); + if (str_replace(array("\r", "\n"), array('', ''), + var_export($control, true)) != str_replace(array("\r", "\n"), array('', ''), + var_export($test, true))) { + $this->_failTest(debug_backtrace(), $message); + if (class_exists('Text_Diff')) { + echo "Diff of expecting/received:\n"; + $diff = &new Text_Diff( + explode("\n", var_export($control, true)), + explode("\n", var_export($test, true))); + + // Output the diff in unified format. + $renderer = &new Text_Diff_Renderer_unified(); + echo $renderer->render($diff); + if ($this->_diffonly) { + return false; + } + } + echo "Expecting:\n"; + var_export($control); + echo "\nReceived:\n"; + var_export($test); + return false; + } + return true; + } + + function assertFileExists($fname, $message) + { + $this->assertNoErrors($message, debug_backtrace()); + if (!@file_exists($fname)) { + $this->_failTest(debug_backtrace(), $message); + echo "File '$fname' does not exist, and should\n"; + return false; + } + return true; + } + + function assertFileNotExists($fname, $message) + { + $this->assertNoErrors($message, debug_backtrace()); + if (@file_exists($fname)) { + $this->_failTest(debug_backtrace(), $message); + echo "File '$fname' exists, and should not\n"; + return false; + } + return true; + } + + function assertRegEquals($dump, &$reg, $message) + { + $actualdump = var_export(trim($this->dumpReg($reg)), true); + $testdump = var_export(trim($dump), true); + return $this->assertEquals($testdump, $actualdump, $message); + } + + function assertPackageInfoEquals($control, $test, $message) + { + $this->assertNoErrors($message, debug_backtrace()); + if (isset($control[0])) { + if (!isset($test[0]) || (count($control) != count($test))) { + echo "Invalid packageInfo\n"; + $ret = $this->assertEquals($control, $test, $message); + } + $ret = true; + foreach ($control as $i => $packageinfo) { + $ret = $ret && + $this->assertPackageInfoEquals($packageinfo, $test[$i], $message . $i); + } + return $ret; + } + if (isset($control['_lastmodified'])) { + if (!isset($test['_lastmodified'])) { + echo "_lastmodified is not set in packageInfo() output\n"; + $this->_failTest(debug_backtrace(), $message); + return false; + } + } + $savecontrol = $control; + $savetest = $test; + unset($control['_lastmodified']); + unset($test['_lastmodified']); + if (var_export($control, true) != var_export($test, true)) { + $this->_failTest(debug_backtrace(), $message); + if (class_exists('Text_Diff')) { + echo "Diff of expecting/received:\n"; + $diff = &new Text_Diff( + explode("\n", var_export($control, true)), + explode("\n", var_export($test, true))); + + // Output the diff in unified format. + $renderer = &new Text_Diff_Renderer_unified(); + echo $renderer->render($diff); + if ($this->_diffonly) { + return false; + } + } + echo "Expecting:\n"; + var_export($savecontrol); + echo "\nReceived:\n"; + var_export($savetest); + return false; + } + return true; + } + + function dumpReg(&$reg) + { + ob_start(); + print "dumping registry...\n"; + $infos = $reg->packageInfo(null, null, null); + foreach ($infos as $channel => $info) { + echo "channel $channel:\n"; + foreach ($info as $pkg) { + print $pkg["name"] . ":"; + unset($pkg["name"]); + foreach ($pkg as $k => $v) { + if ($k == '_lastmodified') { + print " _lastmodified is set"; + continue; + } + if (is_array($v) && $k == 'filelist') { + print " $k=array("; + $i = 0; + foreach ($v as $k2 => $v2) { + if ($i++ > 0) print ","; + print "{$k2}["; + $j = 0; + foreach ($v2 as $k3 => $v3) { + if ($j++ > 0) print ","; + print "$k3=$v3"; + } + print "]"; + } + print ")"; + } else { + print " $k=\"$v\""; + } + } + print "\n"; + } + } + print "dump done\n"; + $ret = ob_get_contents(); + ob_end_clean(); + return $ret; + } + + function _failTest($trace, $message) + { + echo 'Test Failure: "' . $message . "\"\n in " . $trace[0]['file'] . ' line ' . + $trace[0]['line'] . "\n"; + } + + function showAll() + { + $this->_diffonly = false; + } +} +?> \ No newline at end of file diff --git a/src/lib/pear/PEAR/tests/Config/test/setup.php.inc b/src/lib/pear/PEAR/tests/Config/test/setup.php.inc new file mode 100644 index 0000000..aabec18 --- /dev/null +++ b/src/lib/pear/PEAR/tests/Config/test/setup.php.inc @@ -0,0 +1,8 @@ + \ No newline at end of file diff --git a/src/lib/pear/PEAR/tests/HTML_Template_IT/tests/Console_TestListener.php b/src/lib/pear/PEAR/tests/HTML_Template_IT/tests/Console_TestListener.php new file mode 100644 index 0000000..871b7e9 --- /dev/null +++ b/src/lib/pear/PEAR/tests/HTML_Template_IT/tests/Console_TestListener.php @@ -0,0 +1,32 @@ +_errors += 1; + echo " Error $this->_errors in " . $test->getName() . " : $t\n"; + } + + function addFailure(&$test, &$t) { + $this->_fails += 1; + if ($this->_fails == 1) { + echo "\n"; + } + echo "Failure $this->_fails : $t\n"; + } + + function endTest(&$test) { + if ($this->_fails == 0 && $this->_errors == 0) { + echo ' Test passed'; + } else { + echo "There were $this->_fails failures for " . $test->getName() . "\n"; + echo "There were $this->_errors errors for " . $test->getName() . "\n"; + } + echo "\n"; + } + + function startTest(&$test) { + $this->_fails = 0; + $this->_errors = 0; + echo get_class($test) . " : Starting " . $test->getName() . " ..."; + } +} +?> \ No newline at end of file diff --git a/src/lib/pear/PEAR/tests/HTML_Template_IT/tests/ITX_api_testcase.php b/src/lib/pear/PEAR/tests/HTML_Template_IT/tests/ITX_api_testcase.php new file mode 100644 index 0000000..9485d02 --- /dev/null +++ b/src/lib/pear/PEAR/tests/HTML_Template_IT/tests/ITX_api_testcase.php @@ -0,0 +1,174 @@ +IT_api_TestCase($name); + } + + function setUp() + { + $this->tpl =& new HTML_Template_ITX('./templates'); + } + + function testPlaceholderExists() + { + $this->tpl->setTemplate('{var}'); + $this->assertTrue($this->tpl->placeholderExists('var'), 'Existing placeholder \'var\' reported as nonexistant'); + $this->assertTrue(!$this->tpl->placeholderExists('foobar'), 'Nonexistant placeholder \'foobar\' reported as existing'); + $this->assertTrue($this->tpl->placeholderExists('var', '__global__'), 'Existing in block \'__global__\' placeholder \'var\' reported as nonexistant'); + $this->assertTrue(!$this->tpl->placeholderExists('foobar', '__global__'), 'Nonexistant in block \'__global__\' placeholder \'foobar\' reported as existing'); + } + + function testBlockExists() + { + $this->tpl->setTemplate('{var}'); + $this->assertTrue($this->tpl->blockExists('__global__'), 'Existing block \'__global__\' reported as nonexistant'); + $this->assertTrue(!$this->tpl->blockExists('foobar'), 'Nonexistant block \'foobar\' reported as existing'); + } + + function testAddBlock() + { + $result = $this->tpl->loadTemplatefile('blocks.html', true, true); + if (PEAR::isError($result)) { + $this->assertTrue(false, 'Error loading template file: '. $result->getMessage()); + } + $this->tpl->addBlock('var', 'added', 'added:{new_var}'); + $this->assertTrue($this->tpl->blockExists('added'), 'The new block seems to be missing'); + $this->assertTrue(!$this->tpl->placeholderExists('var'), 'The old variable seems to be still present in the template'); + $this->tpl->setVariable('new_var', 'new_value'); + $this->assertEquals('added:new_value', $this->_stripWhitespace($this->tpl->get())); + } + + function testAddBlockfile() + { + $result = $this->tpl->loadTemplatefile('blocks.html', true, true); + if (PEAR::isError($result)) { + $this->assertTrue(false, 'Error loading template file: '. $result->getMessage()); + } + $result = $this->tpl->addBlockfile('var', 'added', 'addblock.html'); + if (PEAR::isError($result)) { + $this->assertTrue(false, 'Error adding block from file: '. $result->getMessage()); + } + $this->assertTrue($this->tpl->blockExists('added'), 'The new block seems to be missing'); + $this->assertTrue(!$this->tpl->placeholderExists('var'), 'The old variable seems to be still present in the template'); + $this->tpl->setVariable('new_var', 'new_value'); + $this->assertEquals('added:new_value', $this->_stripWhitespace($this->tpl->get())); + } + + function testReplaceBlock() + { + $result = $this->tpl->loadTemplatefile('blocks.html', true, true); + if (PEAR::isError($result)) { + $this->assertTrue(false, 'Error loading template file: '. $result->getMessage()); + } + $this->tpl->setVariable('old_var', 'old_value'); + $this->tpl->parse('old_block'); + // old_block's contents should be discarded + $this->tpl->replaceBlock('old_block', 'replaced:{replaced_var}#', false); + $this->assertTrue(!$this->tpl->blockExists('old_inner_block') && !$this->tpl->placeholderExists('old_var'), + 'The replaced block\'s contents seem to be still present'); + $this->tpl->setVariable('replaced_var', 'replaced_value'); + $this->tpl->parse('old_block'); + // this time old_block's contents should be preserved + $this->tpl->replaceBlock('old_block', 'replaced_again:{brand_new_var}', true); + $this->tpl->setVariable('brand_new_var', 'brand_new_value'); + $this->assertEquals('replaced:replaced_value#replaced_again:brand_new_value', $this->_stripWhitespace($this->tpl->get())); + } + + function testReplaceBlockfile() + { + $result = $this->tpl->loadTemplatefile('blocks.html', true, true); + if (PEAR::isError($result)) { + $this->assertTrue(false, 'Error loading template file: '. $result->getMessage()); + } + $this->tpl->setVariable('old_var', 'old_value'); + $this->tpl->parse('old_block'); + // old_block's contents should be discarded + $result = $this->tpl->replaceBlockfile('old_block', 'replaceblock.html', false); + if (PEAR::isError($result)) { + $this->assertTrue(false, 'Error replacing block from file: '. $result->getMessage()); + } + $this->assertTrue(!$this->tpl->blockExists('old_inner_block') && !$this->tpl->placeholderExists('old_var'), + 'The replaced block\'s contents seem to be still present'); + $this->tpl->setVariable(array( + 'replaced_var' => 'replaced_value', + 'replaced_inner_var' => 'inner_value' + )); + $this->tpl->parse('old_block'); + // this time old_block's contents should be preserved + $result = $this->tpl->replaceBlockfile('old_block', 'addblock.html', true); + if (PEAR::isError($result)) { + $this->assertTrue(false, 'Error replacing block from file: '. $result->getMessage()); + } + $this->tpl->setVariable('new_var', 'again'); + $this->assertEquals('replaced:replaced_value|inner_value#added:again', $this->_stripWhitespace($this->tpl->get())); + } + + function testCallback() + { + $this->tpl->setTemplate('callback:func_uppercase(word)'); + $this->tpl->setCallbackFunction('uppercase', '_uppercaseCallback'); + $res = $this->tpl->performCallback(); + if (PEAR::isError($res)) { + $this->assertTrue(false, 'Error performing callback: '. $res->getMessage()); + } + $this->assertEquals('callback:WORD', $this->tpl->get()); + + $this->tpl->setTemplate('callback:func_lowercase(Word)'); + $this->tpl->setCallbackFunction('lowercase', array('Callbacks','_lowercaseCallback')); + $res = $this->tpl->performCallback(); + if (PEAR::isError($res)) { + $this->assertTrue(false, 'Error performing callback: '. $res->getMessage()); + } + $this->assertEquals('callback:word', $this->tpl->get()); + + $this->tpl->setTemplate('callback:func_lowercase(Word)'); + $this->tpl->setCallbackFunction('lowercase', array(new Callbacks,'_lowercaseCallback')); + $res = $this->tpl->performCallback(); + if (PEAR::isError($res)) { + $this->assertTrue(false, 'Error performing callback: '. $res->getMessage()); + } + $this->assertEquals('callback:word', $this->tpl->get()); + + $this->tpl->setTemplate('callback:func_numberFormat(1.5, 2)'); + $this->tpl->setCallbackFunction('numberFormat', array('Callbacks', '_numberFormatCallback'), '', true); + $res = $this->tpl->performCallback(); + if (PEAR::isError($res)) { + $this->assertTrue(false, 'Error performing callback: '. $res->getMessage()); + } + $this->assertEquals('callback:1.50', $this->tpl->get()); + + $this->tpl->setTemplate('callback:func_numberFormat(1.5, 2)'); + $GLOBALS['obj'] = new Callbacks; + $this->tpl->setCallbackFunction('numberFormat', '_numberFormatCallback', 'obj', true); + $res = $this->tpl->performCallback(); + if (PEAR::isError($res)) { + $this->assertTrue(false, 'Error performing callback: '. $res->getMessage()); + } + $this->assertEquals('callback:1.50', $this->tpl->get()); + } +} + +?> diff --git a/src/lib/pear/PEAR/tests/HTML_Template_IT/tests/ITX_usage_testcase.php b/src/lib/pear/PEAR/tests/HTML_Template_IT/tests/ITX_usage_testcase.php new file mode 100644 index 0000000..6a2f846 --- /dev/null +++ b/src/lib/pear/PEAR/tests/HTML_Template_IT/tests/ITX_usage_testcase.php @@ -0,0 +1,17 @@ +IT_Usage_TestCase($name); + } + + function setUp() + { + $this->tpl =& new HTML_Template_ITX('./templates'); + } +} +?> \ No newline at end of file diff --git a/src/lib/pear/PEAR/tests/HTML_Template_IT/tests/IT_api_testcase.php b/src/lib/pear/PEAR/tests/HTML_Template_IT/tests/IT_api_testcase.php new file mode 100644 index 0000000..3e41f76 --- /dev/null +++ b/src/lib/pear/PEAR/tests/HTML_Template_IT/tests/IT_api_testcase.php @@ -0,0 +1,215 @@ +PHPUnit_TestCase($name); + } + + function setUp() + { + $this->tpl =& new HTML_Template_IT('./templates'); + } + + function tearDown() + { + unset($this->tpl); + } + + function _stripWhitespace($str) + { + return preg_replace('/\\s+/', '', $str); + } + + function _methodExists($name) + { + if (in_array(strtolower($name), get_class_methods($this->tpl))) { + return true; + } + $this->assertTrue(false, 'method '. $name . ' not implemented in ' . get_class($this->tpl)); + return false; + } + + /** + * Tests a setTemplate method + * + */ + function testSetTemplate() + { + $result = $this->tpl->setTemplate('A template', false, false); + if (PEAR::isError($result)) { + $this->assertTrue(false, 'Error setting template: '. $result->getMessage()); + } + $this->assertEquals('A template', $this->tpl->get()); + } + + /** + * Tests a loadTemplatefile method + * + */ + function testLoadTemplatefile() + { + $result = $this->tpl->loadTemplatefile('loadtemplatefile.html', false, false); + if (PEAR::isError($result)) { + $this->assertTrue(false, 'Error loading template file: '. $result->getMessage()); + } + $this->assertEquals('A template', trim($this->tpl->get())); + } + + /** + * Tests a setVariable method + * + */ + function testSetVariable() + { + $result = $this->tpl->setTemplate('{placeholder1} {placeholder2} {placeholder3}', true, true); + if (PEAR::isError($result)) { + $this->assertTrue(false, 'Error setting template: '. $result->getMessage()); + } + // "scalar" call + $this->tpl->setVariable('placeholder1', 'var1'); + // array call + $this->tpl->setVariable(array( + 'placeholder2' => 'var2', + 'placeholder3' => 'var3' + )); + $this->assertEquals('var1 var2 var3', $this->tpl->get()); + } + + /** + * Tests the functionality + * + */ + function testInclude() + { + $result = $this->tpl->loadTemplateFile('include.html', false, false); + if (PEAR::isError($result)) { + $this->assertTrue(false, 'Error loading template file: '. $result->getMessage()); + } + $this->assertEquals('Master file; Included file', trim($this->tpl->get())); + } + + /** + * + */ + function testCurrentBlock() + { + $result = $this->tpl->loadTemplateFile('blockiteration.html', true, true); + if (PEAR::isError($result)) { + $this->assertTrue(false, 'Error loading template file: '. $result->getMessage()); + } + $this->tpl->setVariable('outer', 'a'); + $this->tpl->setCurrentBlock('inner_block'); + for ($i = 0; $i < 5; $i++) { + $this->tpl->setVariable('inner', $i + 1); + $this->tpl->parseCurrentBlock(); + } // for + $this->assertEquals('a|1|2|3|4|5#', $this->_stripWhitespace($this->tpl->get())); + } + + /** + * + */ + function testRemovePlaceholders() + { + $result = $this->tpl->setTemplate('{placeholder1},{placeholder2},{placeholder3}', true, true); + if (PEAR::isError($result)) { + $this->assertTrue(false, 'Error setting template: '. $result->getMessage()); + } + // we do not set {placeholder3} + $this->tpl->setVariable(array( + 'placeholder1' => 'var1', + 'placeholder2' => 'var2' + )); + $this->assertEquals('var1,var2,', $this->tpl->get()); + + // Now, we should really add a switch for keeping {stuff} in + // data supplied to setVariable() safe. Until then, removing it should + // be expected behaviour + $result = $this->tpl->setTemplate('{placeholder1},{placeholder2},{placeholder3}', true, true); + if (PEAR::isError($result)) { + $this->assertTrue(false, 'Error setting template: '. $result->getMessage()); + } + $this->tpl->setVariable(array( + 'placeholder1' => 'var1', + 'placeholder2' => 'var2', + 'placeholder3' => 'var3{stuff}' + )); + $this->assertEquals('var1,var2,var3', $this->tpl->get()); + } + + /** + * + */ + function testTouchBlock() + { + $result = $this->tpl->loadTemplateFile('blockiteration.html', false, true); + if (PEAR::isError($result)) { + $this->assertTrue(false, 'Error loading template file: '. $result->getMessage()); + } + $this->tpl->setVariable('outer', 'data'); + // inner_block should be preserved in output, even if empty + $this->tpl->touchBlock('inner_block'); + $this->assertEquals('data|{inner}#', $this->_stripWhitespace($this->tpl->get())); + } + + // Not available in stock class + + /** + * + */ + /* + function testHideBlock() + { + if (!$this->_methodExists('hideBlock')) { + return; + } + $result = $this->tpl->loadTemplateFile('blockiteration.html', false, true); + if (PEAR::isError($result)) { + $this->assertTrue(false, 'Error loading template file: '. $result->getMessage()); + } + $this->tpl->setVariable(array( + 'outer' => 'data', + 'inner' => 'stuff' + )); + // inner_block is not empty, but should be removed nonetheless + $this->tpl->hideBlock('inner_block'); + $this->assertEquals('data#', $this->_stripWhitespace($this->tpl->get())); + } + */ + /** + * + */ + /* + function testSetGlobalVariable() + { + if (!$this->_methodExists('setGlobalVariable')) { + return; + } + $result = $this->tpl->loadTemplateFile('globals.html', false, true); + if (PEAR::isError($result)) { + $this->assertTrue(false, 'Error loading template file: '. $result->getMessage()); + } + $this->tpl->setGlobalVariable('glob', 'glob'); + // {var2} is not, block_two should be removed + $this->tpl->setVariable(array( + 'var1' => 'one', + 'var3' => 'three' + )); + for ($i = 0; $i < 3; $i++) { + $this->tpl->setVariable('var4', $i + 1); + $this->tpl->parse('block_four'); + } // for + $this->assertEquals('glob:one#glob:three|glob:1|glob:2|glob:3#', $this->_stripWhitespace($this->tpl->get())); + } + */ +} + +?> diff --git a/src/lib/pear/PEAR/tests/HTML_Template_IT/tests/IT_usage_testcase.php b/src/lib/pear/PEAR/tests/HTML_Template_IT/tests/IT_usage_testcase.php new file mode 100644 index 0000000..4527ffc --- /dev/null +++ b/src/lib/pear/PEAR/tests/HTML_Template_IT/tests/IT_usage_testcase.php @@ -0,0 +1,126 @@ +PHPUnit_TestCase($name); + } + + function setUp() + { + $this->tpl =& new HTML_Template_IT('./templates'); + } + + function tearDown() + { + unset($this->tpl); + } + + function _stripWhitespace($str) + { + return preg_replace('/\\s+/', '', $str); + } + + function _methodExists($name) + { + if (in_array(strtolower($name), get_class_methods($this->tpl))) { + return true; + } + $this->assertTrue(false, 'method '. $name . ' not implemented in ' . get_class($this->tpl)); + return false; + } + + + /** + * Tests iterations over two blocks + * + */ + function testBlockIteration() + { + $data = array( + 'a', + array('b', array('1', '2', '3', '4')), + 'c', + array('d', array('5', '6', '7')) + ); + + $result = $this->tpl->loadTemplateFile('blockiteration.html', true, true); + if (PEAR::isError($result)) { + $this->assertTrue(false, 'Error loading template file: '. $result->getMessage()); + } + foreach ($data as $value) { + if (is_array($value)) { + $this->tpl->setVariable('outer', $value[0]); + foreach ($value[1] as $v) { + $this->tpl->setVariable('inner', $v); + $this->tpl->parse('inner_block'); + } + } else { + $this->tpl->setVariable('outer', $value); + } + $this->tpl->parse('outer_block'); + } + $this->assertEquals('a#b|1|2|3|4#c#d|5|6|7#', $this->_stripWhitespace($this->tpl->get())); + } + + /** + * + * + */ + function testTouchBlockIteration() + { + $data = array('a','b','c','d','e'); + $result = $this->tpl->loadTemplateFile('blockiteration.html', true, true); + if (PEAR::isError($result)) { + $this->assertTrue(false, 'Error loading template file: '. $result->getMessage()); + } + for ($i = 0; $i < count($data); $i++) { + $this->tpl->setVariable('outer', $data[$i]); + // the inner_block is empty and should be removed + if (0 == $i % 2) { + $this->tpl->touchBlock('inner_block'); + } + $this->tpl->parse('outer_block'); + } + $this->assertEquals('a|#b#c|#d#e|#', $this->_stripWhitespace($this->tpl->get())); + } + + // Not available in stock version + + /** + * + */ + /* + function testHideBlockIteration() + { + if (!$this->_methodExists('hideBlock')) { + return; + } + $data = array('a','b','c','d','e'); + $result = $this->tpl->loadTemplateFile('blockiteration.html', true, true); + if (PEAR::isError($result)) { + $this->assertTrue(false, 'Error loading template file: '. $result->getMessage()); + } + for ($i = 0; $i < count($data); $i++) { + $this->tpl->setVariable(array( + 'inner' => $i + 1, + 'outer' => $data[$i] + )); + // the inner_block is not empty, but should be removed + if (0 == $i % 2) { + $this->tpl->hideBlock('inner_block'); + } + $this->tpl->parse('outer_block'); + } + $this->assertEquals('a#b|2#c#d|4#e#', $this->_stripWhitespace($this->tpl->get())); + } + */ +} +?> diff --git a/src/lib/pear/PEAR/tests/HTML_Template_IT/tests/templates/__include.html b/src/lib/pear/PEAR/tests/HTML_Template_IT/tests/templates/__include.html new file mode 100644 index 0000000..5291e99 --- /dev/null +++ b/src/lib/pear/PEAR/tests/HTML_Template_IT/tests/templates/__include.html @@ -0,0 +1 @@ +Included file diff --git a/src/lib/pear/PEAR/tests/HTML_Template_IT/tests/templates/addblock.html b/src/lib/pear/PEAR/tests/HTML_Template_IT/tests/templates/addblock.html new file mode 100644 index 0000000..bf58efa --- /dev/null +++ b/src/lib/pear/PEAR/tests/HTML_Template_IT/tests/templates/addblock.html @@ -0,0 +1 @@ +added:{new_var} diff --git a/src/lib/pear/PEAR/tests/HTML_Template_IT/tests/templates/blockiteration.html b/src/lib/pear/PEAR/tests/HTML_Template_IT/tests/templates/blockiteration.html new file mode 100644 index 0000000..d64cadb --- /dev/null +++ b/src/lib/pear/PEAR/tests/HTML_Template_IT/tests/templates/blockiteration.html @@ -0,0 +1,7 @@ + +{outer} + + |{inner} + +# + \ No newline at end of file diff --git a/src/lib/pear/PEAR/tests/HTML_Template_IT/tests/templates/blocks.html b/src/lib/pear/PEAR/tests/HTML_Template_IT/tests/templates/blocks.html new file mode 100644 index 0000000..e426ca0 --- /dev/null +++ b/src/lib/pear/PEAR/tests/HTML_Template_IT/tests/templates/blocks.html @@ -0,0 +1,8 @@ +{var} + +old:{old_var} + + |{old_inner_var} + +# + diff --git a/src/lib/pear/PEAR/tests/HTML_Template_IT/tests/templates/globals.html b/src/lib/pear/PEAR/tests/HTML_Template_IT/tests/templates/globals.html new file mode 100644 index 0000000..7157f12 --- /dev/null +++ b/src/lib/pear/PEAR/tests/HTML_Template_IT/tests/templates/globals.html @@ -0,0 +1,13 @@ + +{glob}:{var1}# + + +{glob}:{var2}# + + +{glob}:{var3} + + |{glob}:{var4} + +# + diff --git a/src/lib/pear/PEAR/tests/HTML_Template_IT/tests/templates/include.html b/src/lib/pear/PEAR/tests/HTML_Template_IT/tests/templates/include.html new file mode 100644 index 0000000..2704378 --- /dev/null +++ b/src/lib/pear/PEAR/tests/HTML_Template_IT/tests/templates/include.html @@ -0,0 +1 @@ +Master file; diff --git a/src/lib/pear/PEAR/tests/HTML_Template_IT/tests/templates/loadtemplatefile.html b/src/lib/pear/PEAR/tests/HTML_Template_IT/tests/templates/loadtemplatefile.html new file mode 100644 index 0000000..07bc2df --- /dev/null +++ b/src/lib/pear/PEAR/tests/HTML_Template_IT/tests/templates/loadtemplatefile.html @@ -0,0 +1 @@ +A template diff --git a/src/lib/pear/PEAR/tests/HTML_Template_IT/tests/templates/replaceblock.html b/src/lib/pear/PEAR/tests/HTML_Template_IT/tests/templates/replaceblock.html new file mode 100644 index 0000000..133485e --- /dev/null +++ b/src/lib/pear/PEAR/tests/HTML_Template_IT/tests/templates/replaceblock.html @@ -0,0 +1,5 @@ +replaced:{replaced_var} + + |{replaced_inner_var} + +# diff --git a/src/lib/pear/PEAR/tests/HTML_Template_IT/tests/test.php b/src/lib/pear/PEAR/tests/HTML_Template_IT/tests/test.php new file mode 100644 index 0000000..2255ea6 --- /dev/null +++ b/src/lib/pear/PEAR/tests/HTML_Template_IT/tests/test.php @@ -0,0 +1,30 @@ +addTest(new $testcase($method)); + } +} + +require_once 'Console_TestListener.php'; +$result =& new PHPUnit_TestResult(); +$result->addListener(new Console_TestListener); +$suite->run($result); +?> diff --git a/src/lib/pear/PEAR/tests/MIME_Type/tests/AllTests.php b/src/lib/pear/PEAR/tests/MIME_Type/tests/AllTests.php new file mode 100644 index 0000000..40d35ac --- /dev/null +++ b/src/lib/pear/PEAR/tests/MIME_Type/tests/AllTests.php @@ -0,0 +1,36 @@ +addTestSuite('MIME_TypeTest'); + $suite->addTestSuite('MIME_Type_ExtensionTest'); + + return $suite; + } +} + +if (PHPUnit_MAIN_METHOD == 'MIME_Type_AllTests::main') { + MIME_Type_AllTests::main(); +} +?> \ No newline at end of file diff --git a/src/lib/pear/PEAR/tests/MIME_Type/tests/MIME_Type_ExtensionTest.php b/src/lib/pear/PEAR/tests/MIME_Type/tests/MIME_Type_ExtensionTest.php new file mode 100644 index 0000000..720c6f2 --- /dev/null +++ b/src/lib/pear/PEAR/tests/MIME_Type/tests/MIME_Type_ExtensionTest.php @@ -0,0 +1,134 @@ +mte = new MIME_Type_Extension; + } + + /** + * Tears down the fixture, for example, closes a network connection. + * This method is called after a test is executed. + * + * @access protected + */ + protected function tearDown() + { + } + + public function testGetMIMEType() + { + $this->assertEquals('text/plain', + $this->mte->getMIMEType('a.txt')); + $this->assertEquals('text/plain', + $this->mte->getMIMEType('/path/to/a.txt')); + $this->assertEquals('image/png', + $this->mte->getMIMEType('a.png')); + $this->assertEquals('application/vnd.oasis.opendocument.text', + $this->mte->getMIMEType('a.odt')); + } + + + + public function testGetMIMETypeFullPath() + { + $this->assertEquals('text/plain', + $this->mte->getMIMEType('/path/to/a.txt')); + $this->assertEquals('text/plain', + $this->mte->getMIMEType('C:\\Programs\\blubbr.txt')); + } + + + + public function testGetMIMETypeNoExtension() + { + $this->assertType('PEAR_Error', + $this->mte->getMIMEType('file')); + $this->assertType('PEAR_Error', + $this->mte->getMIMEType('blubbr')); + } + + + + public function testGetMIMETypeFullPathNoExtension() + { + $this->assertType('PEAR_Error', + $this->mte->getMIMEType('/path/to/file')); + $this->assertType('PEAR_Error', + $this->mte->getMIMEType('C:\\Programs\\blubbr')); + } + + + + public function testGetMIMETypeUnknownExtension() + { + $this->assertType('PEAR_Error', + $this->mte->getMIMEType('file.ohmygodthatisnoextension')); + } + + + + public function testGetExtension() + { + $this->assertEquals('txt', + $this->mte->getExtension('text/plain')); + $this->assertEquals('csv', + $this->mte->getExtension('text/csv')); + } + + + + public function testGetExtensionFail() + { + $this->assertType('PEAR_Error', $this->mte->getExtension(null)); + $this->assertType('PEAR_Error', $this->mte->getExtension('')); + $this->assertType('PEAR_Error', $this->mte->getExtension('n')); + $this->assertType('PEAR_Error', $this->mte->getExtension('n/n')); + } + +} + +if (PHPUnit_MAIN_METHOD == "MIME_Type_ExtensionTest::main") { + MIME_Type_ExtensionTest::main(); +} +?> diff --git a/src/lib/pear/PEAR/tests/MIME_Type/tests/TypeTest.php b/src/lib/pear/PEAR/tests/MIME_Type/tests/TypeTest.php new file mode 100644 index 0000000..31ffa61 --- /dev/null +++ b/src/lib/pear/PEAR/tests/MIME_Type/tests/TypeTest.php @@ -0,0 +1,319 @@ +parse('application/ogg;description=Hello there!;asd=fgh'); + $this->assertEquals('application', $mt->media); + $this->assertEquals('ogg' , $mt->subType); + + $params = array( + 'description' => array('Hello there!', ''), + 'asd' => array('fgh', '') + ); + $this->assertEquals(2, count($mt->parameters)); + foreach ($params as $name => $param) { + $this->assertTrue(isset($mt->parameters[$name])); + $this->assertType('MIME_Type_Parameter', $mt->parameters[$name]); + $this->assertEquals($name, $mt->parameters[$name]->name); + $this->assertEquals($param[0], $mt->parameters[$name]->value); + $this->assertEquals($param[1], $mt->parameters[$name]->comment); + } + } + + /** + */ + public function testParseAgain() + { + $mt = new MIME_Type(); + $mt->parse('application/ogg;description=Hello there!;asd=fgh'); + $this->assertEquals(2, count($mt->parameters)); + + $mt->parse('text/plain;hello=there!'); + $this->assertEquals(1, count($mt->parameters)); + } + + /** + * + */ + public function testHasParameters() + { + $this->assertFalse(MIME_Type::hasParameters('text/plain')); + $this->assertFalse(MIME_Type::hasParameters('text/*')); + $this->assertFalse(MIME_Type::hasParameters('*/*')); + $this->assertTrue(MIME_Type::hasParameters('text/xml;description=test')); + $this->assertTrue(MIME_Type::hasParameters('text/xml;one=test;two=three')); + } + + /** + * + */ + public function testGetParameters() + { + $this->assertEquals( + array(), + MIME_Type::getParameters('text/plain') + ); + //rest is tested in testParse() + } + + /** + * + */ + public function testStripParameters() + { + $this->assertEquals( + 'text/plain', + MIME_Type::stripParameters('text/plain') + ); + $this->assertEquals( + 'text/plain', + MIME_Type::stripParameters('text/plain;asd=def') + ); + $this->assertEquals( + 'text/plain', + MIME_Type::stripParameters('text/plain;asd=def;ghj=jkl') + ); + } + + /** + * + */ + public function testStripComments() { + $this->assertEquals('def', MIME_Type::stripComments('(abc)def(ghi)', $null)); + $this->assertEquals('def', MIME_Type::stripComments('(abc)def', $null)); + $this->assertEquals('def', MIME_Type::stripComments('def(ghi)', $null)); + $this->assertEquals('def', MIME_Type::stripComments('(\)abc)def(\))', $null)); + $this->assertEquals('def', MIME_Type::stripComments('(a"bc)def")def', $null)); + $this->assertEquals('(abc)def', MIME_Type::stripComments('"(abc)def"', $null)); + + $comment = ''; + $this->assertEquals('def', MIME_Type::stripComments('(abc)def(ghi)', $comment)); + $this->assertEquals('abc ghi', $comment); + } + + /** + * + */ + public function testGetMedia() + { + $this->assertEquals('text', MIME_Type::getMedia('text/plain')); + $this->assertEquals('application', MIME_Type::getMedia('application/ogg')); + $this->assertEquals('*', MIME_Type::getMedia('*/*')); + } + + /** + * + */ + public function testGetSubType() + { + $this->assertEquals('plain', MIME_Type::getSubType('text/plain')); + $this->assertEquals('ogg', MIME_Type::getSubType('application/ogg')); + $this->assertEquals('*', MIME_Type::getSubType('*/*')); + $this->assertEquals('plain', MIME_Type::getSubType('text/plain;a=b')); + } + + /** + * + */ + public function testGet() + { + $mt = new MIME_Type('text/xml'); + $this->assertEquals('text/xml', $mt->get()); + + $mt = new MIME_Type('text/xml; this="is"; a="parameter" (with a comment)'); + $this->assertEquals( + 'text/xml; this="is"; a="parameter" (with a comment)', + $mt->get() + ); + } + + /** + * + */ + public function testIsExperimental() + { + $this->assertTrue(MIME_Type::isExperimental('text/x-test')); + $this->assertTrue(MIME_Type::isExperimental('image/X-test')); + $this->assertFalse(MIME_Type::isExperimental('text/plain')); + } + + /** + * + */ + public function testIsVendor() + { + $this->assertTrue(MIME_Type::isVendor('application/vnd.openoffice')); + $this->assertFalse(MIME_Type::isVendor('application/vendor.openoffice')); + $this->assertFalse(MIME_Type::isVendor('vnd/fsck')); + } + + /** + * + */ + public function testIsWildcard() + { + $this->assertTrue(MIME_Type::isWildcard('*/*')); + $this->assertTrue(MIME_Type::isWildcard('image/*')); + $this->assertFalse(MIME_Type::isWildcard('text/plain')); + } + + /** + * + */ + public function testWildcardMatch() { + $this->assertTrue(MIME_Type::wildcardMatch('*/*', 'image/png')); + $this->assertTrue(MIME_Type::wildcardMatch('image/*', 'image/png')); + $this->assertFalse(MIME_Type::wildcardMatch('image/*', 'text/plain')); + } + + /** + * @todo Implement testAddParameter(). + */ + public function testAddParameter() { + // Remove the following line when you implement this test. + $this->markTestIncomplete( + "This test has not been implemented yet." + ); + } + + /** + * @todo Implement testRemoveParameter(). + */ + public function testRemoveParameter() { + // Remove the following line when you implement this test. + $this->markTestIncomplete( + "This test has not been implemented yet." + ); + } + + /** + * + */ + public function testAutoDetect() + { + $dir = dirname(__FILE__) . '/files/'; + + $mt = new MIME_Type( + MIME_Type::autoDetect($dir . 'example.png') + ); + $this->assertType('MIME_Type', $mt); + $this->assertEquals('image', $mt->media); + $this->assertEquals('png', $mt->subType); + + $mt = new MIME_Type( + MIME_Type::autoDetect($dir . 'example.jpg') + ); + $this->assertType('MIME_Type', $mt); + $this->assertEquals('image', $mt->media); + $this->assertEquals('jpeg', $mt->subType); + } + + public function testComments() + { + $type = new MIME_Type('(UTF-8 Plain Text) text / plain ; charset = utf-8'); + $this->assertEquals( + 'text/plain; charset="utf-8"', $type->get() + ); + + $type = new MIME_Type('text (Text) / plain ; charset = utf-8'); + $this->assertEquals( + 'text/plain; charset="utf-8"', $type->get() + ); + + $type = new MIME_Type('text / (Plain) plain ; charset = utf-8'); + $this->assertEquals( + 'text/plain; charset="utf-8"', $type->get() + ); + + $type = new MIME_Type('text / plain (Plain Text) ; charset = utf-8'); + $this->assertEquals( + 'text/plain; charset="utf-8"', $type->get() + ); + + $type = new MIME_Type('text / plain ; (Charset=utf-8) charset = utf-8'); + $this->assertEquals( + 'text/plain; charset="utf-8" (Charset=utf-8)', $type->get() + ); + + $type = new MIME_Type('text / plain ; charset (Charset) = utf-8'); + $this->assertEquals( + 'text/plain; charset="utf-8" (Charset)', $type->get() + ); + + $type = new MIME_Type('text / plain ; charset = (UTF8) utf-8'); + $this->assertEquals( + 'text/plain; charset="utf-8" (UTF8)', $type->get() + ); + + $type = new MIME_Type('text / plain ; charset = utf-8 (UTF-8 Plain Text)'); + $this->assertEquals( + 'text/plain; charset="utf-8" (UTF-8 Plain Text)', $type->get() + ); + + $type = new MIME_Type('application/x-foobar;description="bbgh(kdur"'); + $this->assertEquals( + 'application/x-foobar; description="bbgh(kdur"', $type->get() + ); + + $type = new MIME_Type('application/x-foobar;description="a \"quoted string\""'); + $this->assertEquals( + 'application/x-foobar; description="a \"quoted string\""', $type->get() + ); + + } + +} + +// Call MIME_TypeTest::main() if this source file is executed directly. +if (PHPUnit_MAIN_METHOD == "MIME_TypeTest::main") { + MIME_TypeTest::main(); +} +?> diff --git a/src/lib/pear/PEAR/tests/MIME_Type/tests/files/example.bmp b/src/lib/pear/PEAR/tests/MIME_Type/tests/files/example.bmp new file mode 100644 index 0000000..c446e83 Binary files /dev/null and b/src/lib/pear/PEAR/tests/MIME_Type/tests/files/example.bmp differ diff --git a/src/lib/pear/PEAR/tests/MIME_Type/tests/files/example.gif b/src/lib/pear/PEAR/tests/MIME_Type/tests/files/example.gif new file mode 100644 index 0000000..f308a98 Binary files /dev/null and b/src/lib/pear/PEAR/tests/MIME_Type/tests/files/example.gif differ diff --git a/src/lib/pear/PEAR/tests/MIME_Type/tests/files/example.jpg b/src/lib/pear/PEAR/tests/MIME_Type/tests/files/example.jpg new file mode 100644 index 0000000..f60684e Binary files /dev/null and b/src/lib/pear/PEAR/tests/MIME_Type/tests/files/example.jpg differ diff --git a/src/lib/pear/PEAR/tests/MIME_Type/tests/files/example.png b/src/lib/pear/PEAR/tests/MIME_Type/tests/files/example.png new file mode 100644 index 0000000..299e073 Binary files /dev/null and b/src/lib/pear/PEAR/tests/MIME_Type/tests/files/example.png differ diff --git a/src/lib/pear/PEAR/tests/MIME_Type/tests/files/example.txt b/src/lib/pear/PEAR/tests/MIME_Type/tests/files/example.txt new file mode 100644 index 0000000..b3139b6 --- /dev/null +++ b/src/lib/pear/PEAR/tests/MIME_Type/tests/files/example.txt @@ -0,0 +1 @@ +This is an exemplarily text. \ No newline at end of file diff --git a/src/lib/pear/PEAR/tests/MIME_Type/tests/files/example.txt.bz2 b/src/lib/pear/PEAR/tests/MIME_Type/tests/files/example.txt.bz2 new file mode 100644 index 0000000..3b9d7b3 Binary files /dev/null and b/src/lib/pear/PEAR/tests/MIME_Type/tests/files/example.txt.bz2 differ diff --git a/src/lib/pear/PEAR/tests/MIME_Type/tests/files/example.txt.gz b/src/lib/pear/PEAR/tests/MIME_Type/tests/files/example.txt.gz new file mode 100644 index 0000000..8365dd0 Binary files /dev/null and b/src/lib/pear/PEAR/tests/MIME_Type/tests/files/example.txt.gz differ diff --git a/src/lib/pear/PEAR/tests/Structures_Graph/tests/README b/src/lib/pear/PEAR/tests/Structures_Graph/tests/README new file mode 100644 index 0000000..e69de29 diff --git a/src/lib/pear/PEAR/tests/Structures_Graph/tests/all-tests.php b/src/lib/pear/PEAR/tests/Structures_Graph/tests/all-tests.php new file mode 100644 index 0000000..7790ecd --- /dev/null +++ b/src/lib/pear/PEAR/tests/Structures_Graph/tests/all-tests.php @@ -0,0 +1,39 @@ +#!/usr/bin/php + | +// +-----------------------------------------------------------------------------+ +// + +// Place development Structures_Graph ahead in the include_path +ini_set('include_path', realpath(dirname(__FILE__) . "/..") . ":.:" . ini_get('include_path')); + +require_once 'testCase/BasicGraph.php'; +require_once 'PHPUnit.php'; + +$suite = new PHPUnit_TestSuite(); +$suite->addTest(new PHPUnit_TestSuite('BasicGraph')); +$result = PHPUnit::run($suite); + +echo $result->toString(); +?> diff --git a/src/lib/pear/PEAR/tests/Structures_Graph/tests/testCase/BasicGraph.php b/src/lib/pear/PEAR/tests/Structures_Graph/tests/testCase/BasicGraph.php new file mode 100644 index 0000000..6678587 --- /dev/null +++ b/src/lib/pear/PEAR/tests/Structures_Graph/tests/testCase/BasicGraph.php @@ -0,0 +1,182 @@ + | +// +-----------------------------------------------------------------------------+ +// + +require_once 'Structures/Graph.php'; +require_once 'PHPUnit.php'; + +/** + * @access private + */ +class BasicGraph extends PHPUnit_TestCase +{ + var $_graph = null; + + // constructor of the test suite + function StringTest($name) { + $this->PHPUnit_TestCase($name); + } + + function setUp() { + } + + function tearDown() { + } + + function test_create_graph() { + $this->_graph = new Structures_Graph(); + $this->assertTrue(is_a($this->_graph, 'Structures_Graph')); + } + + function test_add_node() { + $this->_graph = new Structures_Graph(); + $data = 1; + $node = new Structures_Graph_Node($data); + $this->_graph->addNode($node); + $node = new Structures_Graph_Node($data); + $this->_graph->addNode($node); + $node = new Structures_Graph_Node($data); + $this->_graph->addNode($node); + } + + function test_connect_node() { + $this->_graph = new Structures_Graph(); + $data = 1; + $node1 = new Structures_Graph_Node($data); + $node2 = new Structures_Graph_Node($data); + $this->_graph->addNode($node1); + $this->_graph->addNode($node2); + $node1->connectTo($node2); + + $node =& $this->_graph->getNodes(); + $node =& $node[0]; + $node = $node->getNeighbours(); + $node =& $node[0]; + /* + ZE1 == and === operators fail on $node,$node2 because of the recursion introduced + by the _graph field in the Node object. So, we'll use the stupid method for reference + testing + */ + $node = true; + $this->assertTrue($node2); + $node = false; + $this->assertFalse($node2); + } + + function test_data_references() { + $this->_graph = new Structures_Graph(); + $data = 1; + $node = new Structures_Graph_Node(); + $node->setData(&$data); + $this->_graph->addNode($node); + $data = 2; + $dataInNode =& $this->_graph->getNodes(); + $dataInNode =& $dataInNode[0]; + $dataInNode =& $dataInNode->getData(); + $this->assertTrue($data === $dataInNode); + } + + function test_metadata_references() { + $this->_graph = new Structures_Graph(); + $data = 1; + $node = new Structures_Graph_Node(); + $node->setMetadata('5', &$data); + $data = 2; + $dataInNode =& $node->getMetadata('5'); + $this->assertTrue($data === $dataInNode); + } + + function test_metadata_key_exists() { + $this->_graph = new Structures_Graph(); + $data = 1; + $node = new Structures_Graph_Node(); + $node->setMetadata('5', $data); + $this->assertTrue($node->metadataKeyExists('5')); + $this->assertFalse($node->metadataKeyExists('1')); + } + + function test_directed_degree() { + $this->_graph = new Structures_Graph(true); + $node = array(); + $node[] = new Structures_Graph_Node(); + $node[] = new Structures_Graph_Node(); + $node[] = new Structures_Graph_Node(); + $this->_graph->addNode($node[0]); + $this->_graph->addNode($node[1]); + $this->_graph->addNode($node[2]); + $this->assertEquals(0, $node[0]->inDegree(), 'inDegree test failed for node 0 with 0 arcs'); + $this->assertEquals(0, $node[1]->inDegree(), 'inDegree test failed for node 1 with 0 arcs'); + $this->assertEquals(0, $node[2]->inDegree(), 'inDegree test failed for node 2 with 0 arcs'); + $this->assertEquals(0, $node[0]->outDegree(), 'outDegree test failed for node 0 with 0 arcs'); + $this->assertEquals(0, $node[1]->outDegree(), 'outDegree test failed for node 1 with 0 arcs'); + $this->assertEquals(0, $node[2]->outDegree(), 'outDegree test failed for node 2 with 0 arcs'); + $node[0]->connectTo($node[1]); + $this->assertEquals(0, $node[0]->inDegree(), 'inDegree test failed for node 0 with 1 arc'); + $this->assertEquals(1, $node[1]->inDegree(), 'inDegree test failed for node 1 with 1 arc'); + $this->assertEquals(0, $node[2]->inDegree(), 'inDegree test failed for node 2 with 1 arc'); + $this->assertEquals(1, $node[0]->outDegree(), 'outDegree test failed for node 0 with 1 arc'); + $this->assertEquals(0, $node[1]->outDegree(), 'outDegree test failed for node 1 with 1 arc'); + $this->assertEquals(0, $node[2]->outDegree(), 'outDegree test failed for node 2 with 1 arc'); + $node[0]->connectTo($node[2]); + $this->assertEquals(0, $node[0]->inDegree(), 'inDegree test failed for node 0 with 2 arcs'); + $this->assertEquals(1, $node[1]->inDegree(), 'inDegree test failed for node 1 with 2 arcs'); + $this->assertEquals(1, $node[2]->inDegree(), 'inDegree test failed for node 2 with 2 arcs'); + $this->assertEquals(2, $node[0]->outDegree(), 'outDegree test failed for node 0 with 2 arcs'); + $this->assertEquals(0, $node[1]->outDegree(), 'outDegree test failed for node 1 with 2 arcs'); + $this->assertEquals(0, $node[2]->outDegree(), 'outDegree test failed for node 2 with 2 arcs'); + } + + function test_undirected_degree() { + $this->_graph = new Structures_Graph(false); + $node = array(); + $node[] = new Structures_Graph_Node(); + $node[] = new Structures_Graph_Node(); + $node[] = new Structures_Graph_Node(); + $this->_graph->addNode($node[0]); + $this->_graph->addNode($node[1]); + $this->_graph->addNode($node[2]); + $this->assertEquals(0, $node[0]->inDegree(), 'inDegree test failed for node 0 with 0 arcs'); + $this->assertEquals(0, $node[1]->inDegree(), 'inDegree test failed for node 1 with 0 arcs'); + $this->assertEquals(0, $node[2]->inDegree(), 'inDegree test failed for node 2 with 0 arcs'); + $this->assertEquals(0, $node[0]->outDegree(), 'outDegree test failed for node 0 with 0 arcs'); + $this->assertEquals(0, $node[1]->outDegree(), 'outDegree test failed for node 1 with 0 arcs'); + $this->assertEquals(0, $node[2]->outDegree(), 'outDegree test failed for node 2 with 0 arcs'); + $node[0]->connectTo($node[1]); + $this->assertEquals(1, $node[0]->inDegree(), 'inDegree test failed for node 0 with 1 arc'); + $this->assertEquals(1, $node[1]->inDegree(), 'inDegree test failed for node 1 with 1 arc'); + $this->assertEquals(0, $node[2]->inDegree(), 'inDegree test failed for node 2 with 1 arc'); + $this->assertEquals(1, $node[0]->outDegree(), 'outDegree test failed for node 0 with 1 arc'); + $this->assertEquals(1, $node[1]->outDegree(), 'outDegree test failed for node 1 with 1 arc'); + $this->assertEquals(0, $node[2]->outDegree(), 'outDegree test failed for node 2 with 1 arc'); + $node[0]->connectTo($node[2]); + $this->assertEquals(2, $node[0]->inDegree(), 'inDegree test failed for node 0 with 2 arcs'); + $this->assertEquals(1, $node[1]->inDegree(), 'inDegree test failed for node 1 with 2 arcs'); + $this->assertEquals(1, $node[2]->inDegree(), 'inDegree test failed for node 2 with 2 arcs'); + $this->assertEquals(2, $node[0]->outDegree(), 'outDegree test failed for node 0 with 2 arcs'); + $this->assertEquals(1, $node[1]->outDegree(), 'outDegree test failed for node 1 with 2 arcs'); + $this->assertEquals(1, $node[2]->outDegree(), 'outDegree test failed for node 2 with 2 arcs'); + } +} +?> diff --git a/src/lib/pear/PEAR/tests/XML_RPC/tests/allgot.inc b/src/lib/pear/PEAR/tests/XML_RPC/tests/allgot.inc new file mode 100644 index 0000000..3a74d53 --- /dev/null +++ b/src/lib/pear/PEAR/tests/XML_RPC/tests/allgot.inc @@ -0,0 +1,58 @@ + + * @copyright 2005-2006 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License + * @version CVS: $Id: allgot.inc,v 1.2 2006/06/11 00:25:17 danielc Exp $ + * @link http://pear.php.net/package/XML_RPC + * @since File available since Release 1.4.4 + */ + +ob_start(); + +function returnAllGot($params) { + $out = ''; + $count = count($params->params); + for ($i = 0; $i < $count; $i++) { + $param = $params->getParam($i); + if (!XML_RPC_Value::isValue($param)) { + $out .= "parameter $i was error: $param\n"; + continue; + } + $got = XML_RPC_Decode($param); + $out .= "param $i: " . var_export($got, true) . "\n"; + } + $val = new XML_RPC_Value($out, 'string'); + return new XML_RPC_Response($val); +} + +$server = new XML_RPC_Server( + array( + 'allgot' => array( + 'function' => 'returnAllGot', + ), + ) +); + +$got = ob_get_clean(); + +if ($got == $expect) { + echo "passed\n"; +} else { + echo "FAILED\n"; + echo "Expected:\n$expect\n"; + echo "Got:\n$got\n"; +} diff --git a/src/lib/pear/PEAR/tests/XML_RPC/tests/empty-value-struct.php b/src/lib/pear/PEAR/tests/XML_RPC/tests/empty-value-struct.php new file mode 100644 index 0000000..7ef9d48 --- /dev/null +++ b/src/lib/pear/PEAR/tests/XML_RPC/tests/empty-value-struct.php @@ -0,0 +1,90 @@ + + * @copyright 2005-2006 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License + * @version CVS: $Id: empty-value-struct.php,v 1.2 2006/06/11 00:25:17 danielc Exp $ + * @link http://pear.php.net/package/XML_RPC + * @since File available since Release 1.4.4 + */ + +/* + * If the package version number is found in the left hand + * portion of the if() expression below, that means this file has + * come from the PEAR installer. Therefore, let's test the + * installed version of XML_RPC which should be in the include path. + * + * If the version has not been substituted in the if() expression, + * this file has likely come from a CVS checkout or a .tar file. + * Therefore, we'll assume the tests should use the version of + * XML_RPC that has come from there as well. + */ +if ('1.5.1' != '@'.'package_version'.'@') { + /** + * Get the needed class from the PEAR installation + */ + require_once 'XML/RPC/Server.php'; +} else { + if (substr(dirname(__FILE__), -9, -6) != 'XML') { + echo "The parent directory must be named 'XML'.\n"; + exit; + } + + ini_set('include_path', '../../' + . PATH_SEPARATOR . '.' . PATH_SEPARATOR + . ini_get('include_path') + ); + + /** + * Get the needed class from the parent directory + */ + require_once '../Server.php'; +} + +$GLOBALS['HTTP_RAW_POST_DATA'] = << + + allgot + + + + + + fld1 + + + +EOPOST; + +$expect = << + + + +param 0: array ( + 'fld1' => '', +) + + + + +EOEXP; + +include './allgot.inc'; diff --git a/src/lib/pear/PEAR/tests/XML_RPC/tests/empty-value.php b/src/lib/pear/PEAR/tests/XML_RPC/tests/empty-value.php new file mode 100644 index 0000000..50de789 --- /dev/null +++ b/src/lib/pear/PEAR/tests/XML_RPC/tests/empty-value.php @@ -0,0 +1,88 @@ + + * @copyright 2005-2006 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License + * @version CVS: $Id: empty-value.php,v 1.2 2006/06/11 00:25:17 danielc Exp $ + * @link http://pear.php.net/package/XML_RPC + * @since File available since Release 1.4.4 + */ + +/* + * If the package version number is found in the left hand + * portion of the if() expression below, that means this file has + * come from the PEAR installer. Therefore, let's test the + * installed version of XML_RPC which should be in the include path. + * + * If the version has not been substituted in the if() expression, + * this file has likely come from a CVS checkout or a .tar file. + * Therefore, we'll assume the tests should use the version of + * XML_RPC that has come from there as well. + */ +if ('1.5.1' != '@'.'package_version'.'@') { + /** + * Get the needed class from the PEAR installation + */ + require_once 'XML/RPC/Server.php'; +} else { + if (substr(dirname(__FILE__), -9, -6) != 'XML') { + echo "The parent directory must be named 'XML'.\n"; + exit; + } + + ini_set('include_path', '../../' + . PATH_SEPARATOR . '.' . PATH_SEPARATOR + . ini_get('include_path') + ); + + /** + * Get the needed class from the parent directory + */ + require_once '../Server.php'; +} + +$GLOBALS['HTTP_RAW_POST_DATA'] = << + + allgot + + + first + + + + +EOPOST; + +$expect = << + + + +param 0: '' +param 1: 'first' +param 2: ' ' +param 3: '' + + + + +EOEXP; + +include './allgot.inc'; diff --git a/src/lib/pear/PEAR/tests/XML_RPC/tests/extra-lines.php b/src/lib/pear/PEAR/tests/XML_RPC/tests/extra-lines.php new file mode 100644 index 0000000..e5edfb8 --- /dev/null +++ b/src/lib/pear/PEAR/tests/XML_RPC/tests/extra-lines.php @@ -0,0 +1,109 @@ + + * @copyright 2005-2006 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License + * @version CVS: $Id: extra-lines.php,v 1.2 2006/06/11 00:25:17 danielc Exp $ + * @link http://pear.php.net/package/XML_RPC + * @since File available since Release 1.4.4 + */ + +/* + * If the package version number is found in the left hand + * portion of the if() expression below, that means this file has + * come from the PEAR installer. Therefore, let's test the + * installed version of XML_RPC which should be in the include path. + * + * If the version has not been substituted in the if() expression, + * this file has likely come from a CVS checkout or a .tar file. + * Therefore, we'll assume the tests should use the version of + * XML_RPC that has come from there as well. + */ +if ('1.5.1' != '@'.'package_version'.'@') { + /** + * Get the needed class from the PEAR installation + */ + require_once 'XML/RPC.php'; +} else { + if (substr(dirname(__FILE__), -9, -6) != 'XML') { + echo "The parent directory must be named 'XML'.\n"; + exit; + } + + ini_set('include_path', '../../' + . PATH_SEPARATOR . '.' . PATH_SEPARATOR + . ini_get('include_path') + ); + + /** + * Get the needed class from the parent directory + */ + require_once '../RPC.php'; +} + +$input = "First lfs\n\nSecond crlfs\r\n\r\nThird crs\r\rFourth line"; + +$expect_removed = " + +nada + + +First lfs +Second crlfs +Third crs +Fourth line + + + +"; + +$expect_not_removed = " + +nada + + +First lfs + +Second crlfs + +Third crs + +Fourth line + + + +"; + + +$msg = new XML_RPC_Message('nada', array(XML_RPC_encode($input))); +$msg->createPayload(); +if ($msg->payload == $expect_removed) { + echo "passed\n"; +} else { + echo "PROBLEM\n"; +} + +$msg = new XML_RPC_Message('nada', array(XML_RPC_encode($input))); +$msg->remove_extra_lines = false; +$msg->createPayload(); +if ($msg->payload == $expect_not_removed) { + echo "passed\n"; +} else { + echo "PROBLEM\n"; +} diff --git a/src/lib/pear/PEAR/tests/XML_RPC/tests/protoport.php b/src/lib/pear/PEAR/tests/XML_RPC/tests/protoport.php new file mode 100644 index 0000000..fea5b56 --- /dev/null +++ b/src/lib/pear/PEAR/tests/XML_RPC/tests/protoport.php @@ -0,0 +1,437 @@ + + * @copyright 2005-2006 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License + * @version CVS: $Id: protoport.php,v 1.6 2006/06/11 00:25:17 danielc Exp $ + * @link http://pear.php.net/package/XML_RPC + * @since File available since Release 1.2 + */ + +/* + * If the package version number is found in the left hand + * portion of the if() expression below, that means this file has + * come from the PEAR installer. Therefore, let's test the + * installed version of XML_RPC which should be in the include path. + * + * If the version has not been substituted in the if() expression, + * this file has likely come from a CVS checkout or a .tar file. + * Therefore, we'll assume the tests should use the version of + * XML_RPC that has come from there as well. + */ +if ('1.5.1' != '@'.'package_version'.'@') { + /** + * Get the needed class from the PEAR installation + */ + require_once 'XML/RPC.php'; +} else { + /** + * Get the needed class from the parent directory + */ + require_once '../RPC.php'; +} + +/** + * Compare the test result to the expected result + * + * If the test fails, echo out the results. + * + * @param array $expect the array of object properties you expect + * from the test + * @param object $actual the object results from the test + * @param string $test_name the name of the test + * + * @return void + */ +function compare($expect, $actual, $test_name) { + $actual = get_object_vars($actual); + if (count(array_diff($actual, $expect))) { + echo "$test_name failed.\nExpect: "; + print_r($expect); + echo "Actual: "; + print_r($actual); + echo "\n"; + } +} + +if (php_sapi_name() != 'cli') { + echo "
    \n";
    +}
    +
    +
    +$x = array(
    +    'path' => 'thepath',
    +    'server' => 'theserver',
    +    'protocol' => 'http://',
    +    'port' => 80,
    +    'proxy' => '',
    +    'proxy_protocol' => 'http://',
    +    'proxy_port' => 8080,
    +    'proxy_user' => '',
    +    'proxy_pass' => '',
    +    'errno' => 0,
    +    'errstring' => '',
    +    'debug' => 0,
    +    'username' => '',
    +    'password' => '',
    +);
    +$c = new XML_RPC_Client('thepath', 'theserver');
    +compare($x, $c, 'defaults');
    +
    +$x = array(
    +    'path' => 'thepath',
    +    'server' => 'theserver',
    +    'protocol' => 'http://',
    +    'port' => 80,
    +    'proxy' => '',
    +    'proxy_protocol' => 'http://',
    +    'proxy_port' => 8080,
    +    'proxy_user' => '',
    +    'proxy_pass' => '',
    +    'errno' => 0,
    +    'errstring' => '',
    +    'debug' => 0,
    +    'username' => '',
    +    'password' => '',
    +);
    +$c = new XML_RPC_Client('thepath', 'http://theserver');
    +compare($x, $c, 'defaults with http');
    +
    +$x = array(
    +    'path' => 'thepath',
    +    'server' => 'theserver',
    +    'protocol' => 'ssl://',
    +    'port' => 443,
    +    'proxy' => '',
    +    'proxy_protocol' => 'http://',
    +    'proxy_port' => 8080,
    +    'proxy_user' => '',
    +    'proxy_pass' => '',
    +    'errno' => 0,
    +    'errstring' => '',
    +    'debug' => 0,
    +    'username' => '',
    +    'password' => '',
    +);
    +$c = new XML_RPC_Client('thepath', 'https://theserver');
    +compare($x, $c, 'defaults with https');
    +
    +$x = array(
    +    'path' => 'thepath',
    +    'server' => 'theserver',
    +    'protocol' => 'ssl://',
    +    'port' => 443,
    +    'proxy' => '',
    +    'proxy_protocol' => 'http://',
    +    'proxy_port' => 8080,
    +    'proxy_user' => '',
    +    'proxy_pass' => '',
    +    'errno' => 0,
    +    'errstring' => '',
    +    'debug' => 0,
    +    'username' => '',
    +    'password' => '',
    +);
    +$c = new XML_RPC_Client('thepath', 'ssl://theserver');
    +compare($x, $c, 'defaults with ssl');
    +
    +
    +$x = array(
    +    'path' => 'thepath',
    +    'server' => 'theserver',
    +    'protocol' => 'http://',
    +    'port' => 65,
    +    'proxy' => '',
    +    'proxy_protocol' => 'http://',
    +    'proxy_port' => 8080,
    +    'proxy_user' => '',
    +    'proxy_pass' => '',
    +    'errno' => 0,
    +    'errstring' => '',
    +    'debug' => 0,
    +    'username' => '',
    +    'password' => '',
    +);
    +$c = new XML_RPC_Client('thepath', 'theserver', 65);
    +compare($x, $c, 'port 65');
    +
    +$x = array(
    +    'path' => 'thepath',
    +    'server' => 'theserver',
    +    'protocol' => 'http://',
    +    'port' => 65,
    +    'proxy' => '',
    +    'proxy_protocol' => 'http://',
    +    'proxy_port' => 8080,
    +    'proxy_user' => '',
    +    'proxy_pass' => '',
    +    'errno' => 0,
    +    'errstring' => '',
    +    'debug' => 0,
    +    'username' => '',
    +    'password' => '',
    +);
    +$c = new XML_RPC_Client('thepath', 'http://theserver', 65);
    +compare($x, $c, 'port 65 with http');
    +
    +$x = array(
    +    'path' => 'thepath',
    +    'server' => 'theserver',
    +    'protocol' => 'ssl://',
    +    'port' => 65,
    +    'proxy' => '',
    +    'proxy_protocol' => 'http://',
    +    'proxy_port' => 8080,
    +    'proxy_user' => '',
    +    'proxy_pass' => '',
    +    'errno' => 0,
    +    'errstring' => '',
    +    'debug' => 0,
    +    'username' => '',
    +    'password' => '',
    +);
    +$c = new XML_RPC_Client('thepath', 'https://theserver', 65);
    +compare($x, $c, 'port 65 with https');
    +
    +$x = array(
    +    'path' => 'thepath',
    +    'server' => 'theserver',
    +    'protocol' => 'ssl://',
    +    'port' => 65,
    +    'proxy' => '',
    +    'proxy_protocol' => 'http://',
    +    'proxy_port' => 8080,
    +    'proxy_user' => '',
    +    'proxy_pass' => '',
    +    'errno' => 0,
    +    'errstring' => '',
    +    'debug' => 0,
    +    'username' => '',
    +    'password' => '',
    +);
    +$c = new XML_RPC_Client('thepath', 'ssl://theserver', 65);
    +compare($x, $c, 'port 65 with ssl');
    +
    +
    +$x = array(
    +    'path' => 'thepath',
    +    'server' => 'theserver',
    +    'protocol' => 'http://',
    +    'port' => 80,
    +    'proxy' => 'theproxy',
    +    'proxy_protocol' => 'http://',
    +    'proxy_port' => 8080,
    +    'proxy_user' => '',
    +    'proxy_pass' => '',
    +    'errno' => 0,
    +    'errstring' => '',
    +    'debug' => 0,
    +    'username' => '',
    +    'password' => '',
    +);
    +$c = new XML_RPC_Client('thepath', 'theserver', 0,
    +                        'theproxy');
    +compare($x, $c, 'defaults proxy');
    +
    +$x = array(
    +    'path' => 'thepath',
    +    'server' => 'theserver',
    +    'protocol' => 'http://',
    +    'port' => 80,
    +    'proxy' => 'theproxy',
    +    'proxy_protocol' => 'http://',
    +    'proxy_port' => 8080,
    +    'proxy_user' => '',
    +    'proxy_pass' => '',
    +    'errno' => 0,
    +    'errstring' => '',
    +    'debug' => 0,
    +    'username' => '',
    +    'password' => '',
    +);
    +$c = new XML_RPC_Client('thepath', 'http://theserver', 0,
    +                        'http://theproxy');
    +compare($x, $c, 'defaults with http proxy');
    +
    +$x = array(
    +    'path' => 'thepath',
    +    'server' => 'theserver',
    +    'protocol' => 'ssl://',
    +    'port' => 443,
    +    'proxy' => 'theproxy',
    +    'proxy_protocol' => 'ssl://',
    +    'proxy_port' => 443,
    +    'proxy_user' => '',
    +    'proxy_pass' => '',
    +    'errno' => 0,
    +    'errstring' => '',
    +    'debug' => 0,
    +    'username' => '',
    +    'password' => '',
    +);
    +$c = new XML_RPC_Client('thepath', 'https://theserver', 0,
    +                        'https://theproxy');
    +compare($x, $c, 'defaults with https proxy');
    +
    +$x = array(
    +    'path' => 'thepath',
    +    'server' => 'theserver',
    +    'protocol' => 'ssl://',
    +    'port' => 443,
    +    'proxy' => 'theproxy',
    +    'proxy_protocol' => 'ssl://',
    +    'proxy_port' => 443,
    +    'proxy_user' => '',
    +    'proxy_pass' => '',
    +    'errno' => 0,
    +    'errstring' => '',
    +    'debug' => 0,
    +    'username' => '',
    +    'password' => '',
    +);
    +$c = new XML_RPC_Client('thepath', 'ssl://theserver', 0,
    +                        'ssl://theproxy');
    +compare($x, $c, 'defaults with ssl proxy');
    +
    +
    +$x = array(
    +    'path' => 'thepath',
    +    'server' => 'theserver',
    +    'protocol' => 'http://',
    +    'port' => 65,
    +    'proxy' => 'theproxy',
    +    'proxy_protocol' => 'http://',
    +    'proxy_port' => 6565,
    +    'proxy_user' => '',
    +    'proxy_pass' => '',
    +    'errno' => 0,
    +    'errstring' => '',
    +    'debug' => 0,
    +    'username' => '',
    +    'password' => '',
    +);
    +$c = new XML_RPC_Client('thepath', 'theserver', 65,
    +                        'theproxy', 6565);
    +compare($x, $c, 'port 65 proxy 6565');
    +
    +$x = array(
    +    'path' => 'thepath',
    +    'server' => 'theserver',
    +    'protocol' => 'http://',
    +    'port' => 65,
    +    'proxy' => 'theproxy',
    +    'proxy_protocol' => 'http://',
    +    'proxy_port' => 6565,
    +    'proxy_user' => '',
    +    'proxy_pass' => '',
    +    'errno' => 0,
    +    'errstring' => '',
    +    'debug' => 0,
    +    'username' => '',
    +    'password' => '',
    +);
    +$c = new XML_RPC_Client('thepath', 'http://theserver', 65,
    +                        'http://theproxy', 6565);
    +compare($x, $c, 'port 65 with http proxy 6565');
    +
    +$x = array(
    +    'path' => 'thepath',
    +    'server' => 'theserver',
    +    'protocol' => 'ssl://',
    +    'port' => 65,
    +    'proxy' => 'theproxy',
    +    'proxy_protocol' => 'ssl://',
    +    'proxy_port' => 6565,
    +    'proxy_user' => '',
    +    'proxy_pass' => '',
    +    'errno' => 0,
    +    'errstring' => '',
    +    'debug' => 0,
    +    'username' => '',
    +    'password' => '',
    +);
    +$c = new XML_RPC_Client('thepath', 'https://theserver', 65,
    +                        'https://theproxy', 6565);
    +compare($x, $c, 'port 65 with https proxy 6565');
    +
    +$x = array(
    +    'path' => 'thepath',
    +    'server' => 'theserver',
    +    'protocol' => 'ssl://',
    +    'port' => 65,
    +    'proxy' => 'theproxy',
    +    'proxy_protocol' => 'ssl://',
    +    'proxy_port' => 6565,
    +    'proxy_user' => '',
    +    'proxy_pass' => '',
    +    'errno' => 0,
    +    'errstring' => '',
    +    'debug' => 0,
    +    'username' => '',
    +    'password' => '',
    +);
    +$c = new XML_RPC_Client('thepath', 'ssl://theserver', 65,
    +                        'ssl://theproxy', 6565);
    +compare($x, $c, 'port 65 with ssl proxy 6565');
    +
    +
    +$x = array(
    +    'path' => 'thepath',
    +    'server' => 'theserver',
    +    'protocol' => 'ssl://',
    +    'port' => 443,
    +    'proxy' => 'theproxy',
    +    'proxy_protocol' => 'ssl://',
    +    'proxy_port' => 443,
    +    'proxy_user' => '',
    +    'proxy_pass' => '',
    +    'errno' => 0,
    +    'errstring' => '',
    +    'debug' => 0,
    +    'username' => '',
    +    'password' => '',
    +);
    +$c = new XML_RPC_Client('thepath', 'theserver', 443,
    +                        'theproxy', 443);
    +compare($x, $c, 'port 443 no protocol and proxy port 443 no protocol');
    +
    +$x = array(
    +    'path' => 'thepath',
    +    'server' => 'theserver',
    +    'protocol' => 'http://',
    +    'port' => 80,
    +    'proxy' => 'theproxy',
    +    'proxy_protocol' => 'ssl://',
    +    'proxy_port' => 6565,
    +    'proxy_user' => '',
    +    'proxy_pass' => '',
    +    'errno' => 0,
    +    'errstring' => '',
    +    'debug' => 0,
    +    'username' => '',
    +    'password' => '',
    +);
    +$c = new XML_RPC_Client('thepath', 'theserver', 0,
    +                        'ssl://theproxy', 6565);
    +compare($x, $c, 'port 443 no protocol and proxy port 443 no protocol');
    +
    +echo "\nIf no other output was produced, these tests passed.\n";
    diff --git a/src/lib/pear/PEAR/tests/XML_RPC/tests/test_Dump.php b/src/lib/pear/PEAR/tests/XML_RPC/tests/test_Dump.php
    new file mode 100644
    index 0000000..0b2739e
    --- /dev/null
    +++ b/src/lib/pear/PEAR/tests/XML_RPC/tests/test_Dump.php
    @@ -0,0 +1,50 @@
    +new XML_RPC_Value('das ist der Titel', 'string'),
    +    'startDate'=>new XML_RPC_Value(mktime(0,0,0,13,11,2004), 'dateTime.iso8601'),
    +    'endDate'  =>new XML_RPC_Value(mktime(0,0,0,15,11,2004), 'dateTime.iso8601'),
    +    'error'    =>'string',
    +    'arkey'    => new XML_RPC_Value( array(
    +        new XML_RPC_Value('simple string'),
    +        new XML_RPC_Value(12345, 'int')
    +        ), 'array')
    +    )
    +    ,'struct');
    +
    +XML_RPC_Dump($val);
    +
    +echo '==============' . "\r\n";
    +$val2 = new XML_RPC_Value(44353, 'int');
    +XML_RPC_Dump($val2);
    +
    +echo '==============' . "\r\n";
    +$val3 = new XML_RPC_Value('this should be a string', 'string');
    +XML_RPC_Dump($val3);
    +
    +echo '==============' . "\r\n";
    +$val4 = new XML_RPC_Value(true, 'boolean');
    +XML_RPC_Dump($val4);
    diff --git a/src/lib/pear/PEAR/tests/XML_RPC/tests/types.php b/src/lib/pear/PEAR/tests/XML_RPC/tests/types.php
    new file mode 100644
    index 0000000..2ed8678
    --- /dev/null
    +++ b/src/lib/pear/PEAR/tests/XML_RPC/tests/types.php
    @@ -0,0 +1,132 @@
    +
    + * @copyright  2005-2006 The PHP Group
    + * @license    http://www.php.net/license/3_01.txt  PHP License
    + * @version    CVS: $Id: types.php,v 1.2 2006/06/11 00:25:17 danielc Exp $
    + * @link       http://pear.php.net/package/XML_RPC
    + * @since      File available since Release 1.4.4
    + */
    +
    +/*
    + * If the package version number is found in the left hand
    + * portion of the if() expression below, that means this file has
    + * come from the PEAR installer.  Therefore, let's test the
    + * installed version of XML_RPC which should be in the include path.
    + * 
    + * If the version has not been substituted in the if() expression,
    + * this file has likely come from a CVS checkout or a .tar file.
    + * Therefore, we'll assume the tests should use the version of
    + * XML_RPC that has come from there as well.
    + */
    +if ('1.5.1' != '@'.'package_version'.'@') {
    +    /**
    +     * Get the needed class from the PEAR installation
    +     */
    +    require_once 'XML/RPC/Server.php';
    +} else {
    +    if (substr(dirname(__FILE__), -9, -6) != 'XML') {
    +        echo "The parent directory must be named 'XML'.\n";
    +        exit;
    +    }
    +
    +    ini_set('include_path', '../../'
    +            . PATH_SEPARATOR . '.' . PATH_SEPARATOR
    +            . ini_get('include_path')
    +    );
    +
    +    /**
    +     * Get the needed class from the parent directory
    +     */
    +    require_once '../Server.php';
    +}
    +
    +$GLOBALS['HTTP_RAW_POST_DATA'] = <<
    +
    + allgot
    +  
    +   default to string
    +   inside string
    +   8
    +   20050809T01:33:44
    +
    +   
    +    
    +     
    +      
    +       
    +        a
    +       
    +       
    +        b
    +       
    +      
    +     
    +    
    +   
    +
    +   
    +    
    +     
    +      
    +       a
    +       
    +        ay
    +       
    +      
    +      
    +       b
    +       
    +        be
    +       
    +      
    +     
    +    
    +   
    +
    +  
    + 
    +EOPOST;
    +
    +$expect = <<
    +
    +
    +
    +param 0: 'default to string'
    +param 1: 'inside string'
    +param 2: '8'
    +param 3: '20050809T01:33:44'
    +param 4: array (
    +  0 => 'a',
    +  1 => 'b',
    +)
    +param 5: array (
    +  'a' => 'ay',
    +  'b' => 'be',
    +)
    +
    +
    +
    +
    +EOEXP;
    +
    +include './allgot.inc';
    diff --git a/src/lib/pear/bin/pear b/src/lib/pear/bin/pear
    new file mode 100644
    index 0000000..173dfa7
    --- /dev/null
    +++ b/src/lib/pear/bin/pear
    @@ -0,0 +1,28 @@
    +#!/bin/sh
    +
    +# first find which PHP binary to use
    +if test "x$PHP_PEAR_PHP_BIN" != "x"; then
    +  PHP="$PHP_PEAR_PHP_BIN"
    +else
    +  if test "/usr/bin/php" = '@'php_bin'@'; then
    +    PHP=php 
    +  else
    +    PHP="/usr/bin/php"
    +  fi
    +fi
    +
    +# then look for the right pear include dir
    +if test "x$PHP_PEAR_INSTALL_DIR" != "x"; then
    +  INCDIR=$PHP_PEAR_INSTALL_DIR
    +  INCARG="-d include_path=$PHP_PEAR_INSTALL_DIR"
    +else
    +  if test "/www/htdocs/w00acdb0/lib/pear/PEAR" = '@'php_dir'@'; then
    +    INCDIR=`dirname $0`
    +    INCARG=""  
    +  else
    +    INCDIR="/www/htdocs/w00acdb0/lib/pear/PEAR"
    +    INCARG="-d include_path=/www/htdocs/w00acdb0/lib/pear/PEAR"
    +  fi
    +fi
    +
    +exec $PHP -C -q $INCARG -d output_buffering=1 -d variables_order=EGPCS -d open_basedir="" -d safe_mode=0 -d register_argc_argv="On" -d auto_prepend_file="" -d auto_append_file="" $INCDIR/pearcmd.php "$@"
    diff --git a/src/lib/pear/bin/peardev b/src/lib/pear/bin/peardev
    new file mode 100644
    index 0000000..852ea7e
    --- /dev/null
    +++ b/src/lib/pear/bin/peardev
    @@ -0,0 +1,28 @@
    +#!/bin/sh
    +
    +# first find which PHP binary to use
    +if test "x$PHP_PEAR_PHP_BIN" != "x"; then
    +  PHP="$PHP_PEAR_PHP_BIN"
    +else
    +  if test "/usr/bin/php" = '@'php_bin'@'; then
    +    PHP=php 
    +  else
    +    PHP="/usr/bin/php"
    +  fi
    +fi
    +
    +# then look for the right pear include dir
    +if test "x$PHP_PEAR_INSTALL_DIR" != "x"; then
    +  INCDIR=$PHP_PEAR_INSTALL_DIR
    +  INCARG="-d include_path=$PHP_PEAR_INSTALL_DIR"
    +else
    +  if test "/www/htdocs/w00acdb0/lib/pear/PEAR" = '@'php_dir'@'; then
    +    INCDIR=`dirname $0`
    +    INCARG=""  
    +  else
    +    INCDIR="/www/htdocs/w00acdb0/lib/pear/PEAR"
    +    INCARG="-d include_path=/www/htdocs/w00acdb0/lib/pear/PEAR"
    +  fi
    +fi
    +
    +exec $PHP -d memory_limit="-1" -C -q $INCARG -d output_buffering=1 -d open_basedir="" -d safe_mode=0 -d register_argc_argv="On" -d auto_prepend_file="" -d variables_order=EGPCS -d auto_append_file="" $INCDIR/pearcmd.php "$@"
    diff --git a/src/lib/pear/bin/pecl b/src/lib/pear/bin/pecl
    new file mode 100644
    index 0000000..d55f8c2
    --- /dev/null
    +++ b/src/lib/pear/bin/pecl
    @@ -0,0 +1,28 @@
    +#!/bin/sh
    +
    +# first find which PHP binary to use
    +if test "x$PHP_PEAR_PHP_BIN" != "x"; then
    +  PHP="$PHP_PEAR_PHP_BIN"
    +else
    +  if test "/usr/bin/php" = '@'php_bin'@'; then
    +    PHP=php 
    +  else
    +    PHP="/usr/bin/php"
    +  fi
    +fi
    +
    +# then look for the right pear include dir
    +if test "x$PHP_PEAR_INSTALL_DIR" != "x"; then
    +  INCDIR=$PHP_PEAR_INSTALL_DIR
    +  INCARG="-d include_path=$PHP_PEAR_INSTALL_DIR"
    +else
    +  if test "/www/htdocs/w00acdb0/lib/pear/PEAR" = '@'php_dir'@'; then
    +    INCDIR=`dirname $0`
    +    INCARG=""  
    +  else
    +    INCDIR="/www/htdocs/w00acdb0/lib/pear/PEAR"
    +    INCARG="-d include_path=/www/htdocs/w00acdb0/lib/pear/PEAR"
    +  fi
    +fi
    +
    +exec $PHP -C -n -q $INCARG -d output_buffering=1 -d variables_order=EGPCS -d safe_mode=0 -d register_argc_argv="On" $INCDIR/peclcmd.php "$@"
    diff --git a/src/lib/pear/go-pear.php b/src/lib/pear/go-pear.php
    new file mode 100644
    index 0000000..0817357
    --- /dev/null
    +++ b/src/lib/pear/go-pear.php
    @@ -0,0 +1,2675 @@
    +
    + * @author     Stig Bakken 
    + * @author     Christian Dickmann 
    + * @author     Pierre-Alain Joye 
    + * @author     Greg Beaver 
    + * @author     Tias Guns 
    + */
    +
    +
    +$sapi_name = php_sapi_name();
    +
    +$safe_mode = (bool)ini_get('safe_mode');
    +if (!$safe_mode) {
    +    set_time_limit(0);
    +}
    +
    +@ob_end_clean();
    +ob_implicit_flush(true);
    +define('WEBINSTALLER', ($sapi_name != 'cli' && !(substr($sapi_name,0,3)=='cgi' && !isset($_SERVER['GATEWAY_INTERFACE']))));
    +
    +ini_set('track_errors', true);
    +ini_set('html_errors', WEBINSTALLER);
    +ini_set('magic_quotes_runtime', false);
    +error_reporting( E_ALL & ~E_NOTICE);
    +
    +define('WINDOWS', (substr(PHP_OS, 0, 3) == 'WIN'));
    +define('GO_PEAR_VER', '1.1.1');
    +
    +define('WIN32GUI', !WEBINSTALLER && WINDOWS && $sapi_name=='cli' && which('cscript'));
    +
    +/*
    + * See bug #23069
    + */
    +if ( WEBINSTALLER && WINDOWS ) {
    +    $php_sapi_name = win32DetectPHPSAPI();
    +    if($php_sapi_name=='cgi'){
    +    $msg = nl2br("
    +Sorry! The PEAR installer actually does not work on Windows platform
    +using CGI and Apache. Please install the module SAPI (see
    +http://www.php.net/manual/en/install.apache.php for the instructions) or
    +use the CLI (cli\php.exe) in the console.
    +");
    +        displayHTML('error', $msg);
    +    }
    +}
    +
    +if (WEBINSTALLER && isset($_GET['action']) && $_GET['action'] == 'img' && isset($_GET['img'])) {
    +    switch ($_GET['img'])
    +    {
    +        case 'note':
    +        case 'pearlogo':
    +        case 'smallpear':
    +            showImage($_GET['img']);
    +            exit;
    +        default:
    +            exit;
    +    };
    +}
    +
    +// Check if PHP version is sufficient
    +if (function_exists("version_compare") && version_compare(phpversion(), "4.3.0",'<')) {
    +    die("Sorry!  Your PHP version is too old.  PEAR and this script requires at
    +least PHP 4.3.0 for stable operation.
    +
    +It may be that you have a newer version of PHP installed in your web
    +server, but an older version installed as the 'php' command.  In this
    +case, you need to rebuilt PHP from source.
    +If your source is 4.3.x or newer, just make sure you don't run
    +'configure' with --disable-cli, rebuilt and copy sapi/cli/php.
    +
    +Please upgrade PHP to a newer version, and try again.  See you then.
    +
    +");
    +}
    +
    +$gopear_bundle_dir = dirname(__FILE__).'/go-pear-bundle';
    +
    +$bootstrap_files = array(
    +    'PEAR.php'             => 'http://cvs.php.net/viewvc.cgi/pear-core/PEAR.php?view=co&pathrev=PEAR_1_4',
    +    'Archive/Tar.php'      => 'http://cvs.php.net/viewvc.cgi/pear/Archive_Tar/Archive/Tar.php?view=co&pathrev=RELEASE_1_3_2',
    +    'Console/Getopt.php'   => 'http://cvs.php.net/viewvc.cgi/pear-core/Console/Getopt.php?view=co&pathrev=PEAR_1_4',
    +    );
    +
    +$bootstrap_pkgs = array( // uses URL like http://pear.php.net/get/%s
    +    'PEAR',
    +    'Structures_Graph'
    +);
    +
    +$installer_packages = array(
    +    'PEAR',
    +    'Structures_Graph-stable',
    +    'Archive_Tar-stable',
    +    'Console_Getopt-stable',
    +);
    +
    +$pfc_packages = array(
    +    'PEAR_Frontend_Web-beta' => 'Webbased PEAR Installer',
    +    'PEAR_Frontend_Gtk2' => 'Graphical PEAR installer based on PHP-Gtk2',
    +    'MDB2' => 'database abstraction layer.',
    +);
    +
    +$config_desc = array(
    +    'prefix' => 'Installation prefix ($prefix)',
    +    'temp_dir' => 'Temporary files directory',
    +    'bin_dir' => 'Binaries directory',
    +    'php_dir' => 'PHP code directory ($php_dir)',
    +    'doc_dir' => 'Documentation base directory',
    +    'data_dir' => 'Data base directory',
    +    'test_dir' => 'Tests base directory',
    +);
    +
    +if(!WEBINSTALLER && WINDOWS){
    +    $config_desc['php_bin'] = 'php.exe path';
    +}
    +
    +if (WEBINSTALLER) {
    +    $config_desc['cache_dir'] = 'PEAR Installer cache directory';
    +    $config_desc['cache_ttl'] = 'Cache TimeToLive';
    +    $config_desc['webfrontend_file'] = 'Filename of WebFrontend';
    +    $config_desc['php_bin'] = "php.exe path, optional (CLI command tools)";
    +}
    +
    +if (my_env('HTTP_PROXY')) {
    +    $http_proxy = my_env('HTTP_PROXY');
    +} elseif (my_env('http_proxy')) {
    +    $http_proxy = my_env('http_proxy');
    +} else {
    +    $http_proxy = '';
    +}
    +
    +register_shutdown_function('bail');
    +
    +detect_install_dirs();
    +
    +if (WEBINSTALLER) {
    +    @session_start();
    +
    +    // If welcome, just welcome
    +    if (!isset($_GET['step'])) {
    +        $_GET['step'] = 'Welcome';
    +        /* clean up old sessions datas */
    +        session_destroy();
    +    }
    +    if ($_GET['step'] == 'Welcome') {
    +        displayHTML('Welcome');
    +        exit();
    +    }
    +
    +    if (!isset($_SESSION['go-pear']) || isset($_GET['restart'])) {
    +        $_SESSION['go-pear'] = array(
    +            'http_proxy' => $http_proxy,
    +            'config' => array(
    +                'prefix'    => dirname(__FILE__),
    +                'bin_dir'   => $bin_dir,
    +                'php_bin'   => $php_bin,
    +                'php_dir'   => '$prefix/PEAR',
    +                'doc_dir'   => $doc_dir,
    +                'data_dir'  => $data_dir,
    +                'test_dir'  => $test_dir,
    +                'temp_dir'   => '$prefix/temp',
    +                'cache_dir' => '$php_dir/cache',
    +                'cache_ttl' => 300,
    +                'webfrontend_file' => '$prefix/index.php',
    +                ),
    +            'install_pfc' => true,
    +            'install_optional_packages' => array(),
    +            'DHTML' => true,
    +            );
    +    }
    +
    +    // save submited values
    +    if ($_GET['step'] == 'install') {
    +        $_SESSION['go-pear']['http_proxy'] = strip_magic_quotes($_POST['proxy']['host']).':'.strip_magic_quotes($_POST['proxy']['port']);
    +        if ($_SESSION['go-pear']['http_proxy'] == ':') {
    +            $_SESSION['go-pear']['http_proxy'] = '';
    +        };
    +
    +        $config_errors = array();
    +        foreach($_POST['config'] as $key => $value) {
    +            $_POST['config'][$key] = strip_magic_quotes($value);
    +            if ($key != 'cache_ttl' && $key != 'php_bin') {
    +                if ( empty($_POST['config'][$key]) ) {
    +                    $config_errors[$key] = 'Please fill this path, you can use $prefix, $php_dir or a full path.';
    +                }
    +            }
    +        }
    +
    +        if( sizeof($config_errors)>0){
    +            $_GET['step'] = 'config';
    +        }
    +
    +        $_SESSION['go-pear']['config'] = $_POST['config'];
    +        $_SESSION['go-pear']['install_pfc'] = (isset($_POST['install_pfc']) && $_POST['install_pfc'] == 'on');
    +        // webinstaller allows to choose pfc packages individually
    +        foreach ($pfc_packages as $key => $value) {
    +            $pos = array_search($key, $_SESSION['go-pear']['install_optional_packages']);
    +            if (isset($_POST[$key]) && $_POST[$key] == 'on' && $pos === false) {
    +                $_SESSION['go-pear']['install_optional_packages'][] = $key;
    +            }
    +            if (!isset($_POST[$key]) && $pos !== false) {
    +                unset($_SESSION['go-pear']['install_optional_packages'][$pos]);
    +            }
    +        }
    +        $_SESSION['go-pear']['DHTML'] = isset($_POST['BCmode']) ? false : true;
    +    }
    +
    +    // export session values
    +    $http_proxy = $_SESSION['go-pear']['http_proxy'];
    +    $GLOBALS['config_vars'] = array_keys($config_desc);
    +    array_unshift($GLOBALS['config_vars'], '');
    +    unset($GLOBALS['config_vars'][0]); // make indices run from 1...
    +    foreach($_SESSION['go-pear']['config'] as $var => $value) {
    +        $$var = $value;
    +    }
    +    $install_pfc = $_SESSION['go-pear']['install_pfc'];
    +    $install_optional_packages = $_SESSION['go-pear']['install_optional_packages'];
    +
    +    if ($_GET['step'] == 'config') {
    +        displayHTML('config');
    +        exit();
    +    }
    +    // Anything past this step has something to do with the installation    
    +}
    +
    +if (!WEBINSTALLER) {
    +    $tty = WINDOWS ? @fopen('\con', 'r') : @fopen('/dev/tty', 'r');
    +
    +    if (!$tty) {
    +        $tty = fopen('php://stdin', 'r');
    +    }
    +
    +    $local = isset($_SERVER['argv'][1]) && $_SERVER['argv'][1] == 'local';
    +    if ($local) {
    +        $local = "
    +Running in local install mode
    +";
    +    } elseif (WINDOWS) {
    +        $local = "
    +Use 'php " . $_SERVER['argv'][0] . " local' to install a local copy of PEAR.
    +";
    +    }
    +    print "Welcome to go-pear!
    +
    +Go-pear will install the 'pear' command and all the files needed by
    +it.  This command is your tool for PEAR installation and maintenance.
    +$local
    +Go-pear also lets you download and install the following optional PEAR
    +packages: " . implode(', ', array_keys($pfc_packages)) . ".
    +
    +
    +If you wish to abort, press Control-C now, or press Enter to continue: ";
    +
    +    fgets($tty, 1024);
    +
    +    print "\n";
    +
    +        print "HTTP proxy (http://user:password@proxy.myhost.com:port), or Enter for none:";
    +
    +    if (!empty($http_proxy)) {
    +        print " [$http_proxy]";
    +    }
    +    print ": ";
    +    $tmp = trim(fgets($tty, 1024));
    +    if (!empty($tmp)) {
    +        $http_proxy = $tmp;
    +    }
    +}
    +
    +$origpwd = getcwd();
    +
    +$config_vars = array_keys($config_desc);
    +
    +// make indices run from 1...
    +array_unshift($config_vars, "");
    +unset($config_vars[0]);
    +reset($config_vars);
    +$desclen = max(array_map('strlen', $config_desc));
    +$descfmt = "%-{$desclen}s";
    +$first = key($config_vars);
    +end($config_vars);
    +$last = key($config_vars);
    +
    +$progress = 0;
    +
    +/*
    + * Checks PHP SAPI version under windows/CLI
    + */
    +if( WINDOWS && !WEBINSTALLER && $php_bin=='') {
    +    print "
    +We do not find any php.exe, please select the php.exe folder (CLI is
    +recommanded, usually in c:\php\cli\php.exe)
    +";
    +    $php_bin_set = false;
    +} elseif ( WINDOWS && !WEBINSTALLER && strlen($php_bin) ) {
    +    $php_bin_sapi = win32DetectPHPSAPI();
    +    $php_bin_set = true;
    +    switch($php_bin_sapi){
    +        case 'cli':
    +        break;
    +        case 'cgi':
    +            print "
    +*NOTICE*
    +We found php.exe under $php_bin, it uses a $php_bin_sapi SAPI. PEAR commandline
    +tool works well with it, if you have a CLI php.exe available, we
    +recommand to use it.
    +";
    +        break;
    +        default:
    +            print "
    +*WARNING*
    +We found php.exe under $php_bin, it uses an unknown SAPI. PEAR commandline
    +tool has not been tested with it, if you have a CLI (or CGI) php.exe available,
    +we strongly recommand to use it.
    +
    +";
    +        break;
    +    }
    +}
    +
    +while (!WEBINSTALLER) {
    +    print "
    +Below is a suggested file layout for your new PEAR installation.  To
    +change individual locations, type the number in front of the
    +directory.  Type 'all' to change all of them or simply press Enter to
    +accept these locations.
    +
    +";
    +
    +    foreach ($config_vars as $n => $var) {
    +        printf("%2d. $descfmt : %s\n", $n, $config_desc[$var], $$var);
    +    }
    +
    +    print "\n$first-$last, 'all' or Enter to continue: ";
    +    $tmp = trim(fgets($tty, 1024));
    +    if ( empty($tmp) ) {
    +        if( WINDOWS && !$php_bin_set ){
    +            echo "**ERROR**
    +Please, enter the php.exe path.
    +
    +";
    +        } else {
    +            break;
    +        }
    +    }
    +    if (isset($config_vars[(int)$tmp])) {
    +        $var = $config_vars[(int)$tmp];
    +        $desc = $config_desc[$var];
    +        $current = $$var;
    +
    +        if(WIN32GUI){
    +            $tmp = win32BrowseForFolder("$desc [$current] :");
    +        } else {
    +            print "$desc [$current] : ";
    +            $tmp = trim(fgets($tty, 1024));
    +        }
    +
    +        $old = $$var;
    +        if(WINDOWS && $var=='php_bin' ){
    +            if(file_exists($tmp.DIRECTORY_SEPARATOR.'php.exe')){
    +                $tmp = $tmp.DIRECTORY_SEPARATOR.'php.exe';
    +                $php_bin_sapi = win32DetectPHPSAPI();
    +                if($php_bin_sapi=='cgi'){
    +            print "
    +******************************************************************************
    +NOTICE! We found php.exe under $php_bin, it uses a $php_bin_sapi SAPI.
    +PEAR commandline tool works well with it.
    +If you have a CLI php.exe available, we recommand to use it.
    +
    +";
    +                } elseif ($php_bin_sapi=='unknown') {
    +            print "
    +******************************************************************************
    +WARNING! We found php.exe under $php_bin, it uses an $php_bin_sapi SAPI.
    +PEAR commandline tool has not been tested with it.
    +If you have a CLI (or CGI) php.exe available, we strongly recommand to use it.
    +
    +";
    +                }
    +                echo "php.exe (sapi: $php_bin_sapi) found.\n\n";
    +                $php_bin_set = true;
    +            } else {
    +                echo "**ERROR**: no php.exe found in this folder.\n";
    +                $tmp='';
    +            }
    +        }
    +
    +        if (!empty($tmp) ) {
    +            $$var = parse_dirname($tmp);
    +        }
    +    } elseif ($tmp == 'all') {
    +        foreach ($config_vars as $n => $var) {
    +            $desc = $config_desc[$var];
    +            $current = $$var;
    +            print "$desc [$current] : ";
    +            $tmp = trim(fgets($tty, 1024));
    +            if (!empty($tmp)) {
    +                $$var = $tmp;
    +            }
    +        }
    +    }
    +}
    +
    +####
    +# Installation stuff
    +####
    +
    +// expand all subvars in the config vars
    +foreach ($config_vars as $n => $var) {
    +    for ($m = 1; $m <= count($config_vars); $m++) {
    +        $var2 = $config_vars[$m];
    +        $$var = str_replace('$'.$var2, $$var2, $$var);
    +    }
    +    $$var = parse_dirname($$var);
    +}
    +
    +    // temp dir stuff (separate for windows bugs)
    +    if (!empty($temp_dir)) {
    +        $_found = temp_dir($temp_dir);
    +    } else {
    +        $_found = temp_dir();
    +    }
    +    if (!$_found) {
    +        if (!WEBINSTALLER) {
    +            print "
    +
    +******************************************************************************
    +FATAL ERROR! We cannot initialize the temp directory. Please be sure to give
    +full write access to this directory and the install directory.
    +
    +";
    +            if (!empty($temp_dir)) {
    +                print "'$temp_dir' was given.";
    +            }
    +            exit();
    +
    +        } else { // WEBINSTALLER
    +            if (!is_dir($temp_dir)) {
    +                $config_errors['temp_dir'] = 'FATAL ERROR! This directory does not exist and we can not create it. Create the directory manually or make sure we have full permission in its parent directory.';
    +                if (!WINDOWS) {
    +                    $config_errors['temp_dir'] .= '

    You can grant this permission by logging on to the server and issuing the following command:
    +mkdir '.dirname($temp_dir).' && chmod 0777 '.dirname($temp_dir).'

    '; + } + } else { // is_dir(temp_dir) + $config_errors['temp_dir'] = 'FATAL ERROR! This directory exists, but we have no write permission in it.'; + if (!WINDOWS) { + $config_errors['temp_dir'] .= '

    You can grant this permission by logging on to the server and issuing the following command:
    +chmod 0777 '.$temp_dir.'

    '; + } + } + } + } + if (@is_dir($ptmp)) { + chdir($ptmp); + } + + // check every dir, existence and permissions + foreach ($config_vars as $var) { + if (!preg_match('/_dir$/', $var) || $var == 'temp_dir') { + continue; + } + + $dir = $$var; + if (!@is_dir($dir)) { + if (!mkdir_p($dir)) { + if (!WEBINSTALLER) { + $root = WINDOWS ? 'administrator' : 'root'; + bail("Unable to create {$config_desc[$var]} $dir. +Run this script as $root or pick another location.\n"); + } else { // WEBINSTALLER + $config_errors[$var] = 'ERROR! This directory does not exist and we can not create it. Create the directory manually or make sure we have full permission in its parent directory.'; + if (!WINDOWS) { + $config_errors[$var] .= '

    You can grant this permission by logging on to the server and issuing the following command:
    +mkdir '.dirname($dir).' && chmod 0777 '.dirname($dir).'

    '; + } + } + } + } + if (WEBINSTALLER && @is_dir($dir) && !is_writable($dir)) { + $config_errors[$var] = 'ERROR! This directory exists, but we have no write permission in it.'; + if (!WINDOWS) { + $config_errors[$var] .= '

    You can grant this permission by logging on to the server and issuing the following command:
    +chmod 0777 '.$dir.'

    '; + } + } + } + + // check every file, existence and permissions + foreach ($config_vars as $var) { + if (!preg_match('/_file$/', $var)) { + continue; + } + + $file = $$var; + $dir = dirname($file); + if (!file_exists($file) && !is_writable($dir)) { + if (!WEBINSTALLER) { + $root = WINDOWS ? 'administrator' : 'root'; + bail("Unable to create {$config_desc[$var]} $file. +Run this script as $root or pick another location.\n"); + } else { // WEBINSTALLER + $config_errors[$var] = 'ERROR! This file does not exist and we can not create it. Make sure we have full permission in its parent directory.'; + if (!WINDOWS) { + $config_errors[$var] .= '

    You can grant this permission by logging on to the server and issuing the following command:
    +chmod 0777 '.$dir.'

    '; + } + } + } elseif (WEBINSTALLER && file_exists($file) && !is_writable($file)) { + $config_errors[$var] = 'ERROR! This file exists, but we have no write permission on it.'; + if (!WINDOWS) { + $config_errors[$var] .= '

    You can grant this permission by logging on to the server and issuing the following command:
    +chmod 0777 '.$file.'

    '; + } + } + } + +if (WEBINSTALLER) { + if ( isset($config_errors) && sizeof($config_errors) ) { + displayHTML('config'); + exit(); + } else { + if (isset($_SESSION['go-pear']['DHTML']) && $_SESSION['go-pear']['DHTML'] == true && $_GET['step'] == 'install') { + $_GET['step'] = 'preinstall'; + } + if ($_GET['step'] != 'install' && $_GET['step'] != 'install-progress') { + displayHTML($_GET['step']); + exit; + } + if ($_GET['step'] == 'install-progress') { + displayHTMLHeader(); + echo "Starting installation ...
    "; + } + ob_start(); + } +} + +if (!WEBINSTALLER) { + $msg = "The following PEAR packages are bundled with PHP: " . + implode(', ', array_keys($pfc_packages)); + print "\n" . wordwrap($msg, 75) . ".\n"; + print "Would you like to install these as well? [Y/n] : "; + $install_pfc = !stristr(fgets($tty, 1024), "n"); + $install_optional_packages = array(); + print "\n"; +} + +#### +# Download +#### + +if (function_exists('set_include_path')) { + set_include_path($ptmp); +} else { + ini_set('include_path', $ptmp); +} + +if (!extension_loaded('zlib') && !WEBINSTALLER) { // In Web context we could be in multithread env which makes dl() end up with a fatal error. + if (WINDOWS) { + @dl('php_zlib.dll'); + } elseif (PHP_OS == 'HP-UX') { + @dl('zlib.sl'); + } elseif (PHP_OS == 'AIX') { + @dl('zlib.a'); + } else { + @dl('zlib.so'); + } +} +if (!extension_loaded('zlib')) { + $urltemplate = 'http://pear.php.net/get/%s?uncompress=yes'; + $have_gzip = null; +} else { + $urltemplate = 'http://pear.php.net/get/%s'; + $have_gzip = true; +} + +print "Loading zlib: ".($have_gzip ? 'ok' : 'failed')."\n"; + +if (!$have_gzip) { + print "Downloading uncompressed packages\n"; +}; + +if ($install_pfc) { + $to_install = array_merge($installer_packages, array_keys($pfc_packages)); +} else { + $to_install = $installer_packages; + + // webinstaller allows to choose pfc packages individually + foreach ($pfc_packages as $pkg => $desc) { + if (in_array($pkg, $install_optional_packages)) { + array_push($to_install, $pkg); + } + } +} + +// gopear_bundle usage +$local_dir = array(); +if (file_exists($gopear_bundle_dir) || is_dir($gopear_bundle_dir)) { + $dh = @opendir($gopear_bundle_dir); + + while($file = @readdir($dh)) { + if ($file == '.' || $file == '..' || !is_file($gopear_bundle_dir.'/'.$file)) { + continue; + } + $_pos = strpos($file, '-'); + if ($_pos === false) { + $local_dir[$file] = $file; + } else { + $local_dir[substr($file, 0, $_pos)] = $file; + } + } + closedir($dh); + unset($dh, $file, $_pos); +} + +print "\n".'Bootstrapping Installer...................'."\n"; +displayHTMLProgress($progress = 5); + +// Bootstrap needed ? +$nobootstrap = false; +if (is_dir($php_dir)) { + $nobootstrap = true; + foreach ($bootstrap_files as $file => $url) { + $nobootstrap &= is_file($php_dir.'/'.$file); + } +} + +if ($nobootstrap) { + print('Using previously install ... '); + if (function_exists('set_include_path')) { + set_include_path($php_dir); + } else { + ini_set('include_path', $php_dir); + } + include_once 'PEAR.php'; + print "ok\n"; +} else { + foreach($bootstrap_files as $name => $url) { + $file = basename($name); + $dir = dirname($name); + + print 'Bootstrapping '.$name.'............'; + displayHTMLProgress($progress += round(14 / count($bootstrap_files))); + if ($dir != '' && $dir != '.') { + mkdir($dir, 0700); + } + + if (in_array($file, $local_dir)) { + copy($gopear_bundle_dir.'/'.$file, $name); + echo '(local) '; + } else { + download_url($url, $name, $http_proxy); + echo '(remote) '; + } + include_once $name; + print "ok\n"; + } +} +unset($nobootstrap, $file, $url, $name, $dir); + +PEAR::setErrorHandling(PEAR_ERROR_DIE, "\n%s\n"); +print "\n".'Extracting installer..................'."\n"; +displayHTMLProgress($progress = 20); + +// Extract needed ? +$noextract = false; +if (is_dir($php_dir)) { + $noextract = @include_once 'PEAR/Registry.php'; + + if ($noextract) { + $registry = new PEAR_Registry($php_dir); + foreach ($bootstrap_pkgs as $pkg) { + $noextract &= $registry->packageExists($pkg); + } + } +} + +if ($noextract) { + print('Using previously installed installer ... '); + print "ok\n"; +} else { + $bootstrap_pkgs_tarballs = array(); + foreach ($bootstrap_pkgs as $pkg) { + $tarball = null; + if (isset($local_dir[$pkg])) { + echo str_pad("Using local package: $pkg", max(38,21+strlen($pkg)+4), '.'); + copy($gopear_bundle_dir.'/'.$local_dir[$pkg], $local_dir[$pkg]); + $tarball = $local_dir[$pkg]; + } else { + print str_pad("Downloading package: $pkg", max(38,21+strlen($pkg)+4), '.'); + $url = sprintf($urltemplate, $pkg); + $pkg = str_replace('-stable', '', $pkg); + $tarball = download_url($url, null, $http_proxy); + } + displayHTMLProgress($progress += round(19 / count($bootstrap_pkgs))); + + $fullpkg = substr($tarball, 0, strrpos($tarball, '.')); + $tar = &new Archive_Tar($tarball, $have_gzip); + if (!$tar->extractModify($ptmp, $fullpkg)) { + bail("Extraction for $fullpkg failed!\n"); + } + $bootstrap_pkgs_tarballs[$pkg] = $tarball; + print "ok\n"; + } +} +unset($noextract, $registry, $pkg, $tarball, $url, $fullpkg, $tar); + + +print "\n".'Preparing installer..................'."\n"; +displayHTMLProgress($progress = 40); + +// Default for sig_bin +putenv('PHP_PEAR_SIG_BIN=""'); +// Default for sig_keydir +putenv('PHP_PEAR_SIG_KEYDIR=""'); +putenv('PHP_PEAR_DOWNLOAD_DIR=' . $temp_dir . '/download'); +putenv('PHP_PEAR_TEMP_DIR=' . $temp_dir); + +include_once "PEAR/Config.php"; +include_once "PEAR/Command.php"; +include_once "PEAR/Registry.php"; + +if (WEBINSTALLER || isset($_SERVER['argv'][1]) && $_SERVER['argv'][1] == 'local') { + $config = &PEAR_Config::singleton($prefix."/pear.conf", ''); +} else { + $config = &PEAR_Config::singleton(); +} + + +$config->set('preferred_state', 'stable'); +foreach ($config_vars as $var) { + if (isset($$var) && $$var != '') { + $config->set($var, $$var); + } +} +$config->set('download_dir', $temp_dir . '/download'); +$config->set('temp_dir', $temp_dir); +$config->set('http_proxy', $http_proxy); +$config->store(); + +$registry = new PEAR_Registry($php_dir); +PEAR_Command::setFrontendType('CLI'); + +PEAR::staticPushErrorHandling(PEAR_ERROR_DIE); //fail silently +$ch_cmd = &PEAR_Command::factory('update-channels', $config); +$ch_cmd->run('update-channels', $options, array()); +PEAR::staticPopErrorHandling(); // reset error handling +unset($ch_cmd); + + +print "\n".'Installing selected packages..................'."\n"; +displayHTMLProgress($progress = 45); + +$install = &PEAR_Command::factory('install', $config); +foreach ($to_install as $pkg) { + $pkg_basename = substr($pkg, 0, strpos($pkg, '-')); + + if (in_array($pkg, $installer_packages)) { + $options = array('nodeps' => true); + } else { + $options = array('onlyreqdeps' => true); + } + if ($registry->packageExists($pkg) || $registry->packageExists($pkg_basename)) { + print(str_pad("Package: $pkg", max(50,9+strlen($pkg)+4), '.').' already installed ... ok'."\n"); + displayHTMLProgress($progress += round(50 / count($to_install))); + continue; + } + + $pkg_basename = substr($pkg, 0, strpos($pkg, '-')); + if (in_array($pkg_basename, $bootstrap_pkgs)) { + print(str_pad("Installing bootstrap package: $pkg_basename", max(50,30+strlen($pkg_basename)+4), '.')."..."); + displayHTMLProgress($progress += round(25 / count($to_install))); + $install->run('install', $options, array($bootstrap_pkgs_tarballs[$pkg_basename])); + } elseif (isset($local_dir[$pkg_basename])) { + print(str_pad("Installing local package: $pkg", max(50,26+strlen($pkg)+4), '.')."..."); + displayHTMLProgress($progress += round(25 / count($to_install))); + $install->run('install', $options, array($gopear_bundle_dir.'/'.$local_dir[$pkg_basename])); + } else { // no local copy + print(str_pad("Downloading and installing package: $pkg", max(50,36+strlen($pkg)+4), '.')."..."); + displayHTMLProgress($progress += round(25 / count($to_install))); + $install->run('install', $options, array($pkg)); + } + displayHTMLProgress($progress += round(25 / count($to_install))); +} +unset($pkg, $pkg_basename, $options, $bootstrap_pkgs_tarballs); + +/* TODO: Memory exhaustion in webinstaller : / (8Mb) +print "\n".'Making sure every package is at the latest version........'; +$install->run('upgrade-all', array('soft' => true), array()); +print "ok\n"; +*/ +unset($config, $registry, $install); +displayHTMLProgress($progress = 99); + + +// Base installation finished + +ini_restore("include_path"); + +if (!WEBINSTALLER) { + $sep = WINDOWS ? ';' : ':'; + $include_path = explode($sep, ini_get('include_path')); + if (WINDOWS) { + $found = false; + $t = strtolower($php_dir); + foreach($include_path as $path) { + if ($t==strtolower($path)) { + $found = true; + break; + } + } + } else { + $found = in_array($php_dir, $include_path); + } + if (!$found) { + print " +****************************************************************************** +WARNING! The include_path defined in the currently used php.ini does not +contain the PEAR PHP directory you just specified: +<$php_dir> +If the specified directory is also not in the include_path used by +your scripts, you will have problems getting any PEAR packages working. +"; + + if ( $php_ini = getPhpiniPath() ) { + print "\n\nWould you like to alter php.ini <$php_ini>? [Y/n] : "; + $alter_phpini = !stristr(fgets($tty, 1024), "n"); + if( $alter_phpini ) { + alterPhpIni($php_ini); + } else { + if (WINDOWS) { + print " +Please look over your php.ini file to make sure +$php_dir is in your include_path."; + } else { + print " +I will add a workaround for this in the 'pear' command to make sure +the installer works, but please look over your php.ini or Apache +configuration to make sure $php_dir is in your include_path. +"; + } + + } + } + + print " +Current include path : ".ini_get('include_path')." +Configured directory : $php_dir +Currently used php.ini (guess) : $php_ini +"; + + print "Press Enter to continue: "; + fgets($tty, 1024); + } + + $pear_cmd = $bin_dir . DIRECTORY_SEPARATOR . 'pear'; + $pear_cmd = WINDOWS ? strtolower($pear_cmd).'.bat' : $pear_cmd; + + // check that the installed pear and the one in tha path are the same (if any) + $pear_old = which(WINDOWS ? 'pear.bat' : 'pear', $bin_dir); + if ($pear_old && ($pear_old != $pear_cmd)) { + // check if it is a link or symlink + $islink = WINDOWS ? false : is_link($pear_old) ; + if ($islink && readlink($pear_old) != $pear_cmd) { + print "\n** WARNING! The link $pear_old does not point to the " . + "installed $pear_cmd\n"; + } elseif (is_writable($pear_old) && !is_dir($pear_old)) { + rename($pear_old, "{$pear_old}_old"); + print "\n** WARNING! Backed up old pear to {$pear_old}_old\n"; + } else { + print "\n** WARNING! Old version found at $pear_old, please remove it or ". + "be sure to use the new $pear_cmd command\n"; + } + } + + print "\nThe 'pear' command is now at your service at $pear_cmd\n"; + + // Alert the user if the pear cmd is not in PATH + $old_dir = $pear_old ? dirname($pear_old) : false; + if (!which('pear', $old_dir)) { + print " +** The 'pear' command is not currently in your PATH, so you need to +** use '$pear_cmd' until you have added +** '$bin_dir' to your PATH environment variable. + +"; + + print "Run it without parameters to see the available actions, try 'pear list' +to see what packages are installed, or 'pear help' for help. + +For more information about PEAR, see: + + http://pear.php.net/faq.php + http://pear.php.net/manual/ + +Thanks for using go-pear! + +"; + } +} + +if (WEBINSTALLER) { + print "\n".'Writing WebFrontend file ... '; + @unlink($webfrontend_file); //Delete old one + copy ( $doc_dir.DIRECTORY_SEPARATOR. + 'PEAR_Frontend_Web'.DIRECTORY_SEPARATOR. + 'docs'.DIRECTORY_SEPARATOR. + 'index.php.txt', + $webfrontend_file + ); + print "ok\n"; + + if ($_GET['step'] == 'install-progress') { + displayHTMLProgress($progress = 100); + ob_end_clean(); + displayHTMLInstallationSummary(); + displayHTMLFooter(); + } else { + $out = ob_get_contents(); + + $out = explode("\n", $out); + foreach($out as $line => $value) { + if (preg_match('/ok$/', $value)) { + $value = preg_replace('/(ok)$/', '\1', $value); + }; + if (preg_match('/^install ok:/', $value)) { + $value = preg_replace('/^(install ok:)/', '\1', $value); + }; + if (preg_match('/^Warning:/', $value)) { + $value = ''.$value.''; + }; + $out[$line] = $value; + }; + $out = nl2br(implode("\n",$out)); + ob_end_clean(); + + displayHTML('install', $out); + } + // Little hack, this will be fixed in PEAR later + if ( WINDOWS ) { + clearstatcache(); + @unlink($bin_dir.DIRECTORY_SEPARATOR.'.tmppear'); + } + exit; +} + +// Little hack, this will be fixed in PEAR later +if ( WINDOWS ) { + clearstatcache(); + @unlink($bin_dir.DIRECTORY_SEPARATOR.'.tmppear'); +} + +if (WINDOWS && !WEBINSTALLER) { + win32CreateRegEnv(); +} +// Set of functions following +/** + * Parse the given dirname + * eg. expands '~' etc + * + * @param string $dir directory, from input + * @return string parsed directory + */ +function parse_dirname($dir) +{ + if (!isset($_ENV['HOME'])) { + if (strpos($dir, '~') === 0) { + if (WEBINSTALLER) { + die('

    Can\'t use the \'~\' symbol for homedir substitution, write the directory out in full.

    '); + } else { + die('Can\'t use the \'~\' symbol for homedir substitution, write the directory out in full.'); + } + } + return $dir; + } + + $home_root = $_ENV['HOME']; + // first strip last slash, if available + if (substr($home_root, -1) == DIRECTORY_SEPARATOR) { + $home_root = substr($home_root, 0, -1); + } + if (strpos($dir, '~/') === 0) { + // eg ~/ = /home/tias/ + $dir = substr_replace($dir, $home_root, 0, 1); + } elseif (strpos($dir, '~') === 0) { + // eg ~tias/ = /home/tias/ + // then delete user-dir + $home_root = dirname($home_root) . DIRECTORY_SEPARATOR; + $dir = substr_replace($dir, $home_root, 0, 1); + } + + return $dir; +} + + +// {{{ download_url() + +function download_url($url, $destfile = null, $proxy = null) +{ + $use_suggested_filename = ($destfile === null); + if ($use_suggested_filename) { + $destfile = basename($url); + } + $tmp = parse_url($url); + if (empty($tmp['port'])) { + $tmp['port'] = 80; + } + if (empty($proxy)) { + $fp = fsockopen($tmp['host'], $tmp['port'], $errno, $errstr); + //print "\nconnecting to $tmp[host]:$tmp[port]\n"; + } else { + $tmp_proxy = parse_url($proxy); + $phost = $tmp_proxy['host']; + $pport = $tmp_proxy['port']; + $fp = fsockopen($phost, $pport, $errno, $errstr); + //print "\nconnecting to $phost:$pport\n"; + } + if (!$fp) { + bail("download of $url failed: $errstr ($errno)\n"); + // If valid URL but error, no CURL extentions installed + } + if (empty($proxy)) { + $path = $tmp['path']; + } else { + $path = "http://$tmp[host]:$tmp[port]$tmp[path]"; + } + if (isset($tmp['query'])) { + $path .= "?$tmp[query]"; + } + if (isset($tmp['fragment'])) { + $path .= "#$tmp[fragment]"; + } + $request = "GET $path HTTP/1.0\r\nHost: $tmp[host]:$tmp[port]\r\n". + "User-Agent: go-pear\r\n"; + + if (!empty($proxy) && $tmp_proxy['user'] != '') { + $request .= 'Proxy-Authorization: Basic ' . + base64_encode($tmp_proxy['user'] . ':' . $tmp_proxy['pass']) . "\r\n"; + } + $request .= "\r\n"; + fwrite($fp, $request); + $cdh = "content-disposition:"; + $cdhl = strlen($cdh); + $content_length = 0; + while ($line = fgets($fp, 2048)) { + if (trim($line) == '') { + break; + } + if (preg_match('/^Content-Length: (.*)$/i', $line, $matches)) { + $content_length = trim($matches[1]); + } + if ($use_suggested_filename && !strncasecmp($line, $cdh, $cdhl)) { + if (eregi('filename="([^"]+)"', $line, $matches)) { + $destfile = basename($matches[1]); + } + } + } + + displayHTMLSetDownload($destfile); + $wp = fopen($destfile, "wb"); + if (!$wp) { + bail("could not open $destfile for writing\n"); + } + $bytes_read = 0; + $progress = 0; + while ($data = fread($fp, 2048)) { + fwrite($wp, $data); + $bytes_read += strlen($data); + if ($content_length != 0 && floor($bytes_read * 10 / $content_length) != $progress) { + $progress = floor($bytes_read * 10 / $content_length); + displayHTMLDownloadProgress($progress * 10); + }; + } + displayHTMLDownloadProgress(100); + fclose($fp); + fclose($wp); + + displayHTMLSetDownload(''); + return $destfile; +} + +// }}} +// {{{ which() + +function which($program, $dont_search_in = false) +{ + if (WINDOWS) { + if ($_path=my_env('Path')) { + $dirs = explode(';', $_path); + } else { + $dirs = explode(';', my_env('PATH')); + } + foreach ($dirs as $i => $dir) { + $dirs[$i] = strtolower(realpath($dir)); + } + if ($dont_search_in) { + $dont_search_in = strtolower(realpath($dont_search_in)); + } + if ($dont_search_in && + ($key = array_search($dont_search_in, $dirs)) !== false) + { + unset($dirs[$key]); + } + + foreach ($dirs as $dir) { + $dir = str_replace('\\\\', '\\', $dir); + if (!strlen($dir)) { + continue; + } + if ($dir{strlen($dir) - 1} != '\\') { + $dir .= '\\'; + } + $tmp = $dir . $program; + $info = pathinfo($tmp); + if (in_array(strtolower($info['extension']), + array('exe', 'com', 'bat', 'cmd'))) { + if (file_exists($tmp)) { + return strtolower($tmp); + } + } elseif (file_exists($ret = $tmp . '.exe') || + file_exists($ret = $tmp . '.com') || + file_exists($ret = $tmp . '.bat') || + file_exists($ret = $tmp . '.cmd')) { + return strtolower($ret); + } + } + } else { + $dirs = explode(':', my_env('PATH')); + if ($dont_search_in && + ($key = array_search($dont_search_in, $dirs)) !== false) + { + unset($dirs[$key]); + } + foreach ($dirs as $dir) { + if (is_executable("$dir/$program")) { + return "$dir/$program"; + } + } + } + return false; +} + +// }}} +// {{{ bail() + +function bail($msg = '') +{ + global $ptmp, $origpwd; + if ($ptmp && is_dir($ptmp)) { + chdir($origpwd); + rm_rf($ptmp); + } + if ($msg && WEBINSTALLER) { + $msg = @ob_get_contents() ."\n\n". $msg; + @ob_end_clean(); + displayHTML('error', $msg); + exit; + }; + if ($msg && !WEBINSTALLER) { + die($msg); + } +} + +// }}} +// {{{ mkdir_p() + +function mkdir_p($dir, $mode = 0777) +{ + if (@is_dir($dir)) { + return true; + } + + $parent = dirname($dir); + $ok = true; + if (!@is_dir($parent) && $parent != $dir) { + $ok = mkdir_p(dirname($dir), $mode); + } + if ($ok) { + $ok = @mkdir($dir, $mode); + // This is handled in the caller function (eg. webfrontend or not) + //if (!$ok) { + // print "mkdir failed: <$dir>\n"; + //} + } + return $ok; +} + +// }}} +// {{{ rm_rf() + +function rm_rf($path) +{ + if (@is_dir($path) && is_writable($path)) { + $dp = opendir($path); + while ($ent = readdir($dp)) { + if ($ent == '.' || $ent == '..') { + continue; + } + $file = $path . DIRECTORY_SEPARATOR . $ent; + if (@is_dir($file)) { + rm_rf($file); + } elseif (is_writable($file)) { + unlink($file); + } else { + echo $file . "is not writable and cannot be removed. +Please fix the permission or select a new path.\n"; + } + } + closedir($dp); + return rmdir($path); + } else { + return @unlink($path); + } +} + +// }}} +// {{{ tmpdir() +/* + * Fixes for winXP/wrong tmp set by Urs Gehrig (urs@circle.ch) + */ +function temp_dir($default=false) +{ + global $ptmp, $prefix; + + if ($default) { + if (!@is_dir($default)) { + if (!mkdir_p($default)) { + return false; + } + } + + /* try it really, is_writable is buggy with openbasedir */ + $fh = @fopen(realpath($default) . "/test","wb"); + if ($fh) { + // desparately try to set temp dir any possible way, see bug #13167 + $ptmp = $_temp = $temp_dir = $default; + putenv('TMPDIR='.$default); + return true; + } else { + return false; + } + } + + $_temp = false; + if (WINDOWS){ + if ( my_env('TEMP') ) { + $_temp = my_env('TEMP'); + } elseif ( my_env('TMP') ) { + $_temp = my_env('TMP'); + } elseif ( my_env('windir') ) { + $_temp = my_env('windir') . '\temp'; + } elseif ( my_env('SystemRoot') ) { + $_temp = my_env('SystemRoot') . '\temp'; + } + + // handle ugly ENV var like \Temp instead of c:\Temp + $dirs = explode("\\", realpath($_temp)); + if(strpos($_temp, ":") != 1) { + unset($_temp); + $_dirs = array(); + foreach($dirs as $val) { + if((boolean)$val ) { + $_dirs[] = str_replace("/", "", $val); + } + } + unset($dirs); + $dirs = $_dirs; + array_unshift ($dirs, "c:" ); + $_temp = $dirs[0]; + for($i = 1;$i < count($dirs);$i++) { + $_temp .= "//" . $dirs[$i]; + } + } + $ptmp = $_temp; + } else { + $_temp = my_env('TMPDIR'); + if (!$_temp) { + if (is_writable('/tmp')) { + $_temp = '/tmp'; + } + } + } + + // If for some reason the user has no rights to access to + // the standard tempdir, we assume that he has the right + // to access his prefix and choose $prefix/tmp as tempdir + if (!$_temp || !is_writable($_temp)) { + print "System's Tempdir failed, trying to use \$prefix/tmp ..."; + $res = mkdir_p($prefix.'/tmp'); + if (!$res) { + bail('mkdir '.$prefix.'/tmp'.' ... failed'); + } + + $ptmp = $prefix . '/tmp'; + $_temp = tempnam($prefix.'/tmp', 'gope'); + + rm_rf($_temp); + mkdir_p($_temp, 0700); + $ok = @chdir($ptmp); + + if (!$ok) { // This should not happen, really ;) + bail('chdir '.$ptmp.' ... failed'); + } + + print "ok\n"; + + // Adjust TEMPDIR envvars + if (!isset($_ENV)) { + $_ENV = array(); + } + $_ENV['TMPDIR'] = $_ENV['TEMP'] = $prefix.'/tmp'; + } else { + $_temp = tempnam($_temp.'/tmp', 'gope'); + } + $temp_dir = $ptmp = $_temp; + return true; +} + +// }}} +// {{{ my_env() +/* +(cox) In my system PHP 4.2.1 (both cgi & cli) $_ENV is empty + but getenv() does work fine +*/ +function my_env($var) +{ + if (is_array($_ENV) && isset($_ENV[$var])) { + return $_ENV[$var]; + } + return getenv($var); +} + +// }}} +// {{{ detect_install_dirs() + +function detect_install_dirs($_prefix = null) { + global $temp_dir, $prefix, $bin_dir, $php_dir, $php_bin, $doc_dir, $data_dir, $test_dir; + if (WINDOWS) { + if ($_prefix === null) { + $prefix = getcwd(); + } else { + $prefix = $_prefix; + } + + if (!@is_dir($prefix)) { + if (@is_dir('c:\php5')) { + $prefix = 'c:\php5'; + } elseif (@is_dir('c:\php4')) { + $prefix = 'c:\php4'; + } elseif (@is_dir('c:\php')) { + $prefix = 'c:\php'; + } + } + + $bin_dir = '$prefix'; + $php_dir = '$prefix\pear'; + $doc_dir = '$php_dir\docs'; + $data_dir = '$php_dir\data'; + $test_dir = '$php_dir\tests'; + $temp_dir = '$prefix\temp'; + + /* + * Detects php.exe + */ + if( $t=getenv('PHP_PEAR_PHP_BIN') ){ + $php_bin = $t; + } elseif ($t=getenv('PHP_BIN') ) { + $php_bin = $t; + } elseif ( $t=which('php') ) { + $php_bin = $t; + } elseif ( is_file($prefix.'\cli\php.exe') ) { + $php_bin = $prefix.'\cli\php.exe'; + } elseif ( is_file($prefix.'\php.exe') ) { + $php_bin = $prefix.'\php.exe'; + } + if( $php_bin && !is_file($php_bin) ){ + $php_bin = ''; + } else { + if(!ereg(":",$php_bin)){ + $php_bin = getcwd().DIRECTORY_SEPARATOR.$php_bin; + } + } + if (!is_file($php_bin)) { + if (is_file('c:/php/cli/php.exe')) { + $php_bin = 'c:/php/cli/php.exe'; + } elseif (is_file('c:/php5/php.exe')) { + $php_bin = 'c:/php5/php.exe'; + } elseif (is_file('c:/php4/cli/php.exe')) { + $php_bin = 'c:/php4/cli/php.exe'; + } + } + } else { + if ($_prefix === null) { + #$prefix = dirname(PHP_BINDIR); + $prefix = dirname(__FILE__); + } else { + $prefix = $_prefix; + } + $bin_dir = '$prefix/bin'; + #$php_dir = '$prefix/share/pear'; + $php_dir = '$prefix/PEAR'; + $doc_dir = '$php_dir/docs'; + $data_dir = '$php_dir/data'; + $test_dir = '$php_dir/tests'; + $temp_dir = '$prefix/temp'; + + // check if the user has installed PHP with PHP or GNU layout + if (@is_dir("$prefix/lib/php/.registry")) { + $php_dir = '$prefix/lib/php'; + } elseif (@is_dir("$prefix/share/pear/lib/.registry")) { + $php_dir = '$prefix/share/pear/lib'; + $doc_dir = '$prefix/share/pear/docs'; + $data_dir = '$prefix/share/pear/data'; + $test_dir = '$prefix/share/pear/tests'; + } elseif (@is_dir("$prefix/share/php/.registry")) { + $php_dir = '$prefix/share/php'; + } + } +} + +// }}} +// {{{ displayHTMLHeader + +function displayHTMLHeader() +{ +?> + + + + PEAR :: Installer :: Go-PEAR + + + + + + + + + + + + + + + + + + + + + +
    + PEAR + +   + + Go-PEAR Installer +
    + Version  
    +
    + + + + + + + + + +
    + + + + +
    +


    + 'Welcome to Go-PEAR', + 'config' => 'Configuration', + 'preinstall' => 'Installation', + 'install' => 'Completed'); + $after_current = false; + + // Menu robustness (a bit low, but better then never) + if ($page == 'error') { + $_GET['last'] = $_GET['step']; + $after_current = true; + } elseif (!array_key_exists($page, $menus)) { + $page = 'Welcome'; + } + + foreach ($menus as $menu => $descr) { + print(''); + + if (!$after_current) { + $class = ''; + if ($page == $menu) { + $class = 'green'; + } + if (!isSet($_GET['last'])) { $_GET['last'] = $page; } + print(''.$descr.'
    '); + + if ($_GET['last'] == $menu) { + $after_current = true; + } + } else { + print(''.$descr.'
    '); + } + } + ?> + +

    +
    + + + + +
    + + + + + + +
    + + + Error
    +
    +\1', $value); + } + if (preg_match('/failed$/', $value)) { + $value = preg_replace('/(failed)$/', '\1', $value); + } + if (preg_match('/^install ok:/', $value)) { + $value = preg_replace('/^(install ok:)/', '\1', $value); + } + if (preg_match('/^Warning:/', $value)) { + $value = ''.$value.''; + } + + echo nl2br($value); + } elseif ($page == 'Welcome') { +?> + Welcome to go-pear !
    +

    + Go-pear will install Pear, its Web Frontend and all the needed files. This
    + frontend is your tool for PEAR installation and maintenance. +

    +

    + Go-pear also lets you download and install the following optional PEAR
    + packages: . +

    + + Next >> + +
    + + Packages +

    + The following PEAR packages will be installed. You can select some optional
    + packages to be installed by go-pear too:
    +

    + + + + + + + + '); + unset($GLOBALS['pfc_packages'][$frontend]); + + foreach ($GLOBALS['pfc_packages'] as $var => $descr) { + $checked = ''; + if (in_array($var, $GLOBALS['install_optional_packages'])) { $checked = ' checked'; } + printf('', + $var, + $checked, + $var, + $descr); + } + ?> +
     PackageDescription
    (required)PEAR corePEAR Base System
    (required)'.$frontend.''.$GLOBALS['pfc_packages'][$frontend].'
    %s%s
    +
    + + + Configuration +

    + Below is a suggested file layout for your new PEAR installation. +

    + + + + + $var) { + $error_class = ''; + if (is_array($GLOBALS['config_errors']) && array_key_exists($var, $GLOBALS['config_errors'])) { + // www_error for this var + $error_class = ' class="red"'; + } + + printf('', + $n, + $GLOBALS['config_desc'][$var], + $var, + $_SESSION['go-pear']['config'][$var], + $error_class); + + // prefix dir, check perm (uses GLOBALS: resolved subvars) + if ($n == 1 && is_dir($GLOBALS[$var]) && !is_writable($GLOBALS[$var])) { + $error = 'WARNING! No permission to create subdirectories in this prefix dir. Unless you fix this, the default configuration will not work.'; + if (!WINDOWS) { + $error .= '

    You can grant this permission by logging on to the server and issuing the following command:
    +chmod 0777 '.$GLOBALS[$var].'

    '; + } + print(''); + } + + + if (is_array($GLOBALS['config_errors']) && array_key_exists($var, $GLOBALS['config_errors'])) { + // www_error for this var + print(''); + } + } +?> +
    %d. %s
    '.$error.'
    '.$GLOBALS['config_errors'][$var].'
    +

    +
    + + + Optional: + +
      +

      +

    • HTTP proxy (host:port) + : +

      + +

      +

    • Compatibility-Mode for old non-DOM Browsers + +

      +
    + + +

    + + + + + +
    + + Warning: Your PHP version (4.1.1) might be imcompatible with go-pear due to a bug
    + in your PHP binary. If the installation crashes you might want to update your PHP version.
    +
    +
    +

    + +
    + +

    + + + + + +
    + + Note: Installation might take some time, because go-pear has to
    + download all needed files from pear.php.net. Just be patient and wait for
    + the next page to load.
    +
    +
    +

    + + +
    + + + Installation Complete - Summary
    + +

    + Installation in progress ...
    + (If the page stops loading before the end of the installation, then just reload it)

    + + + + + +
    + + + + + + + + + + + + + + + +
               0 %
    +
    + + + + + + + + + + + + + + + + + +
               0 % 
    +
    + +
    + +
    + + +
    +
    + + + + ".$data; + } +?> +

    + Installation Completed ! +

    + + + + + + +
    + + Note: To use PEAR without any problems you need to add your
    + PEAR Installation path ()
    + to your include_path.
    +
    + Using a .htaccess file or directly edit httpd.conf would be working solutions
    + for Apache running servers, too.
    +
    +
    +
    + For more information about PEAR, see:
    + PEAR FAQ
    + PEAR Manual
    +
    + Thanks for using go-pear!
    +
    + + + + + + +
    + + Warning: Can not determine the URL of the freshly installed Web Frontend
    + (file: ).
    + Please access it manually ! +
    +
    + + Start Web Frontend of the PEAR Installer >> + + Start Web Frontend of the PEAR Installer >> + array( + 'type' => 'gif', + 'data' => 'R0lGODlhEQATAMQAAAAAACqUACiTAC2WAC+YAzKZBTSaBsHgszOZADCYADmcB4TCZp3Ohtfrzd/v1+by4PD47DaaAz+fDUijF2WyOlCoHvT58VqtJPn893y+S/v9+f7//f3+/Pz9+////////ywAAAAAEQATAAAFkqAnjiR5NGXqcdpCoapnMVRdWbEHUROVVROYalHJTCaVAKWTcjAUGckgQY04SJAFMhJJIL5e4a5I6X6/gwlkRIwOzucAY9SYZBRvOCKheIwYFxR5enxCLhVeemAHbBQVg4SMIoCCinsKVyIOdlKKAhQcJFpGiWgFQiIYPxeJCQEEcykcDIgDAwYUkjEWB70NGykhADs=', + ), + 'pearlogo' => array( + 'type' => 'gif', + 'data' => 'R0lGODlhaAAyAMT/AMDAwP3+/TWaAvD47Pj89vz++zebBDmcBj6fDEekFluvKmu3PvX68ujz4XvBS8LgrNXqxeHw1ZnPaa/dgvv9+cLqj8LmltD2msnuls3xmszwmf7+/f///wAAAAAAAAAAACH5BAEAAAAALAAAAABoADIAQAX/ICCOZGmeaKqubOtWWjwJphLLgH1XUu//C1Jisfj9YLEKQnSY3GaixWQqQTkYHM4AMulNLJFC9pEwIW/odKU8cqTfsWoTTtcomU4ZjbR4ZP+AgYKCG0EiZ1AuiossEhwEXRMEg5SVWQ6MmZqKWD0QlqCUEHubpaYlExwRPRZioZZVp7KzKQoSDxANDLsNXA5simd2FcQYb4YAc2jEU80TmAAIztPCMcjKdg4OEsZJmwIWWQPQI4ikIwtoVQnddgrv8PFlCWgYCwkI+fp5dkvJ/IlUKMCy6tYrDhNIIKLFEAWCTxse+ABD4SClWA0zovAjcUJFi6EwahxZwoGqHhFA/4IqoICkyxQSKkbo0gDkuBXV4FRAJkRCnTgi2P28IcEfk5xpWppykFJVuScmEvDTEETAVJ6bEpypcADPkz3pvKVAICHChkC7siQ08zVqu4Q6hgIFEFZuEn/KMgRUkaBmAQs+cEHgIiHVH5EAFpIgW4+NT6LnaqhDwe/Ov7YOmWZp4MkiAWBIl0kAVsJWuzcYpdiNgddc0E8cKBAu/FElBwagMb88ZZKDRAkWJtkWhHh3wwUbKHQJN3wQAaXGR2LpArv5oFHRR34C7Mf6oLXZNfqBgNI7oOLhj1f8PaGpygHQ0xtP8MDVKwYTSKcgxr9/hS6/pCCAAg5M4B9/sWh1YP9/XSgQWRML/idBfKUc4IBET9lFjggKhDYZAELZJYEBI2BDB3ouNBEABwE8gAwiCcSYgAKqPdEVAG7scM8BPPZ4AIlM+OgjAgpMhRE24OVoBwsIFEGFA7ZkQQBWienWxmRa7XDjKZXhBdAeSmKQwgLuUVLICa6VEKIGcK2mQWoVZHCBXJblJUFkY06yAXlGsPIHBEYdYiWHb+WQBgaIJqqoHFNpgMGB7dT5ZQuG/WbBAIAUEEFNfwxAWpokTIXJAWdgoJ9kRFG2g5eDRpXSBpEIF0oEQFaZhDbaSFANRgqcJoEDRARLREtxOQpsPO906ZUeJgjQB6dZUPBAdwcF8KLXXRVQaKFcsRRLJ6vMiiCNKxRE8ECZKgUA3Va4arOAAqdGRWO7uMZH5AL05gvsjQbg6y4NCjQ1kw8TVGcbdoKGKx8j3bGH7nARBArqwi0gkFJBrZiXBQRbHoIgnhSjcEBKfD7c3HMhz+JIQSY3t8GGKW+SUhfUajxGzKd0IoHBNkNQK86ZYEqdzYA8AHQpqXRUm80oHs1CAgMoBxzRqvzs9CIKECC1JBp7enUpfXHApwVYNAfo16c4IrYPLVdSAJVob7IAtCBFQGHcs/RRdiUDPHA33oADEAIAOw==', + ), + 'note' => array( + 'type' => 'png', + 'data' => 'iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAAAAADFHGIkAAAAAmJLR0QAAKqNIzIAAAEESURBVHjaZZIhksMwDEV9voWFSwsLA0MLDf8VdARBUUNBQ1FBHcErZ5M0baXJjOPnb0vfLuMMn3H+lWMgBKL89A1Eq9Q9IrwB+gIOsnMPBR8giMclguQfBGS8x5xIoPQxnxqb4LL/eQ4l2AVNONP2ZshLCqJ3qqzWtT5pNgNnLU4OcNbuiqaLmFmHGhJ0TCMC99+f2wphlhaOYjuQVc0IIzLH2BRWfQoWsNSjct8AVop4rF3belTuVAb3MRj6kLrcTwtIy+g03V1vC57t1XrMzqfP5pln5yLTkk7+5UhstvOni1X3ixLEdf2c36+W0Q7kOb48hnSRLI/XdNPfX4kpMkgP5R+elfdkDPprQgAAAEN0RVh0U29mdHdhcmUAQCgjKUltYWdlTWFnaWNrIDQuMi44IDk5LzA4LzAxIGNyaXN0eUBteXN0aWMuZXMuZHVwb250LmNvbZG6IbgAAAAqdEVYdFNpZ25hdHVyZQAzYmQ3NDdjNWU0NTgwNzAwNmIwOTBkZDNlN2EyNmM0NBTTk/oAAAAOdEVYdFBhZ2UAMjR4MjQrMCswclsJMQAAAABJRU5ErkJggg==', + ), + ); + + Header('Content-Type: image/'.$images[$img]['type']); + echo base64_decode($images[$img]['data']); +}; + +// }}} +// {{{ displayHTMLProgress + +function displayHTMLProgress($progress) +{ + if (!(WEBINSTALLER && isset($_SESSION['go-pear']['DHTML']) && $_SESSION['go-pear']['DHTML'])) { + return; + }; + $msg = ob_get_contents(); + ob_end_clean(); + + $msg = explode("\n", $msg); + foreach($msg as $key => $value) { + if (preg_match('/ok$/', $value)) { + $value = preg_replace('/(ok)$/', '\1', $value); + }; + if (preg_match('/failed$/', $value)) { + $value = preg_replace('/(failed)$/', '\1', $value); + }; + if (preg_match('/^install ok:/', $value)) { + //$value = preg_replace('/^(install ok:)/', '\1', $value).'
    '; + //$msg = array($value); // if install succeeded: don't show the irritatingly verbose pear installer + $msg = array('ok
    '); + break; + }; + if (preg_match('/^Warning:/', $value)) { + $value = ''.$value.''; + }; + $msg[$key] = $value; + }; + $msg = implode('
    ', $msg); + + $msg.=''; + + echo $msg; + ob_start(); +}; + +// }}} +// {{{ displayHTMLDownloadProgress + +function displayHTMLDownloadProgress($progress) +{ + if (!(WEBINSTALLER && isset($_SESSION['go-pear']['DHTML']) && $_SESSION['go-pear']['DHTML'])) { + return; + }; + $msg = ob_get_contents(); + ob_end_clean(); + + echo ''; + + ob_start(); + echo $msg; +}; + +// }}} +// {{{ displayHTMLSetDownload + +function displayHTMLSetDownload($file) +{ + if (!(WEBINSTALLER && isset($_SESSION['go-pear']['DHTML']) && $_SESSION['go-pear']['DHTML'])) { + return; + }; + $msg = ob_get_contents(); + ob_end_clean(); + + if ($file != null && $file != '') { + echo ''; + } else { + echo ''; + } + + ob_start(); + echo $msg; +}; + +// }}} +// {{{ win32BrowseForFolder + +/* + * Create a vbs script to browse the getfolder dialog, called + * by cscript, if it's available. + * $label is the label text in the header of the dialog box + * + * TODO: + * - Do not show Control panel + * - Replace WSH with calls to w32 as soon as callbacks work + * @Author Pierrre-Alain Joye + */ +function win32BrowseForFolder($label) +{ + global $ptmp; + static $wshSaved=false; + static $cscript=''; +$wsh_browserfolder = 'Option Explicit +Dim ArgObj, var1, var2, sa, sFld +Set ArgObj = WScript.Arguments +Const BIF_EDITBOX = &H10 +Const BIF_NEWDIALOGSTYLE = &H40 +Const BIF_RETURNONLYFSDIRS = &H0001 +Const BIF_DONTGOBELOWDOMAIN = &H0002 +Const BIF_STATUSTEXT = &H0004 +Const BIF_RETURNFSANCESTORS = &H0008 +Const BIF_VALIDATE = &H0020 +Const BIF_BROWSEFORCOMPUTER = &H1000 +Const BIF_BROWSEFORPRINTER = &H2000 +Const BIF_BROWSEINCLUDEFILES = &H4000 +Const OFN_LONGNAMES = &H200000 +Const OFN_NOLONGNAMES = &H40000 +Const ssfDRIVES = &H11 +Const ssfNETWORK = &H12 +Set sa = CreateObject("Shell.Application") +var1=ArgObj(0) +Set sFld = sa.BrowseForFolder(0, var1, BIF_EDITBOX + BIF_VALIDATE + BIF_BROWSEINCLUDEFILES + BIF_RETURNFSANCESTORS+BIF_NEWDIALOGSTYLE , ssfDRIVES ) +if not sFld is nothing Then + if not left(sFld.items.item.path,1)=":" Then + WScript.Echo sFld.items.item.path + Else + WScript.Echo "invalid" + End If +Else + WScript.Echo "cancel" +End If +'; + if( !$wshSaved){ + $cscript = $ptmp.DIRECTORY_SEPARATOR."bf.vbs"; + $fh = fopen($cscript,"wb+"); + fwrite($fh,$wsh_browserfolder,strlen($wsh_browserfolder)); + fclose($fh); + $wshSaved = true; + } + exec('cscript '.$cscript.' "'.$label.'" //noLogo',$arPath); + if($arPath[0]=='' || $arPath[0]=='cancel'){ + return ''; + } elseif ($arPath[0]=='invalid') { + echo "Invalid Path.\n"; + return ''; + } + return $arPath[0]; +} + +// }}} +// {{{ win32CreateRegEnv + +/* + * Generates a registry addOn for Win32 platform + * This addon set PEAR environment variables + * @Author Pierrre-Alain Joye + */ +function win32CreateRegEnv() +{ + global $prefix, $bin_dir, $php_dir, $php_bin, $doc_dir, $data_dir, $test_dir, $temp_dir; + $nl = "\r\n"; + $reg ='REGEDIT4'.$nl. + '[HKEY_CURRENT_USER\Environment]'.$nl. + '"PHP_PEAR_SYSCONF_DIR"="'.addslashes($prefix).'"'.$nl. + '"PHP_PEAR_INSTALL_DIR"="'.addslashes($php_dir).'"'.$nl. + '"PHP_PEAR_DOC_DIR"="'.addslashes($doc_dir).'"'.$nl. + '"PHP_PEAR_BIN_DIR"="'.addslashes($bin_dir).'"'.$nl. + '"PHP_PEAR_DATA_DIR"="'.addslashes($data_dir).'"'.$nl. + '"PHP_PEAR_PHP_BIN"="'.addslashes($php_bin).'"'.$nl. + '"PHP_PEAR_TEST_DIR"="'.addslashes($test_dir).'"'.$nl; + + $fh = fopen($prefix.DIRECTORY_SEPARATOR.'PEAR_ENV.reg','wb'); + if($fh){ + fwrite($fh, $reg ,strlen($reg)); + fclose($fh); + echo " + +* WINDOWS ENVIRONMENT VARIABLES * +For convenience, a REG file is available under $prefix\\PEAR_ENV.reg . +This file creates ENV variables for the current user. + +Double-click this file to add it to the current user registry. + +"; + } +} + +// }}} +// {{{ win32DetectPHPSAPI + +/* + * Try to detect the kind of SAPI used by the + * the given php.exe. + * @Author Pierrre-Alain Joye + */ +function win32DetectPHPSAPI() +{ + global $php_bin,$php_sapi_name; + if (WEBINSTALLER) { + return $php_sapi_name; + } + if($php_bin!=''){ + exec($php_bin.' -v', $res); + if(is_array($res)) { + if( isset($res[0]) && strpos($res[0],"(cli)")) { + return 'cli'; + } + if( isset($res[0]) && strpos($res[0],"cgi")) { + return 'cgi'; + } else { + return 'unknown'; + } + } + } + return 'unknown'; +} + +// }}} +// {{{ getPhpiniPath + +/* + * Get the php.ini file used with the current + * process or with the given php.exe + * + * Horrible hack, but well ;) + * + * Not used yet, will add the support later + * @Author Pierre-Alain Joye + */ +function getPhpiniPath() +{ + $pathIni = get_cfg_var('cfg_file_path'); + if( $pathIni && is_file($pathIni) ){ + return $pathIni; + } + + // Oh well, we can keep this too :) + // I dunno if get_cfg_var() is safe on every OS + if (WINDOWS) { + // on Windows, we can be pretty sure that there is a php.ini + // file somewhere + do { + $php_ini = PHP_CONFIG_FILE_PATH . DIRECTORY_SEPARATOR . 'php.ini'; + if ( @file_exists($php_ini) ) break; + $php_ini = 'c:\winnt\php.ini'; + if ( @file_exists($php_ini) ) break; + $php_ini = 'c:\windows\php.ini'; + } while (false); + } else { + $php_ini = PHP_CONFIG_FILE_PATH . DIRECTORY_SEPARATOR . 'php.ini'; + } + + if( @is_file($php_ini) ){ + return $php_ini; + } + + // We re running in hackz&troubles :) + ob_implicit_flush(false); + ob_start(); + phpinfo(INFO_GENERAL); + $strInfo = ob_get_contents (); + ob_end_clean(); + ob_implicit_flush(true); + + if ( php_sapi_name() != 'cli' ) { + $strInfo = strip_tags($strInfo,'
    '); + $arrayInfo = explode("
    + + + + + + + {if $fleet} + + + + + + + + {/if} + + + + + + + + + + + + + + + + +
    + + + +
    Flotte von {$nick} updaten

    + + + + +
    Flotte {$nick} ({$gala}:{$pos}) +
    + Kleptoren: {$fleet.kleptoren} Cancris: + {$fleet.cancris} Fregatten: {$fleet.fregatten}
    + Zerstörer: {$fleet.zerstoerer} Kreuzer: + {$fleet.kreuzer} Träger: {$fleet.traeger}
    + Jäger: {$fleet.jaeger} Bomber: {$fleet.bomber} + Schlachter: {$fleet.schlachter}
    + letzes update: {$fleetdate} , {$fleettime} Uhr
    + + + +
    Flotte:
    + + + + +
    +
    + {$forms.fleetupdate.fields.fleet.error}
    Du gehst in den Takscreen, klickst auf die Flotte des Users den du updaten willst und markierst + die Daten von "Jäger" bis zur 2ten Flotte Schutzschiffe.
    + Beispiel:
    + Jäger 0 0 100 .......
    + .
    + .
    + Schutzschiffe: 1000 0 0
    + + + + +
    + Hilfe
    + + + +
    + +


    +

    + diff --git a/src/templates/ally_add.html b/src/templates/ally_add.html new file mode 100644 index 0000000..f2a691b --- /dev/null +++ b/src/templates/ally_add.html @@ -0,0 +1,128 @@ +
    + + + + + + + + {if $errors} + + + + + + + {/if} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + +
    Allianz hinzufügen

    + +
    {foreach from=$errors item=error}{$error}
    {/foreach}
    +
    + + + +
    Name
    + + +
    +
    + + + +
    Allianztag
    + + +
    +
    + + + +
    Beschreibung
    + + +
    +
    + + + +
    IRC Channel
    + + + +
    +
    + + + +
    Homepage
    + + + +
    +
    + + + + +
    + Hilfe
    + + + +
    + +


    +

    +
    diff --git a/src/templates/ally_details.html b/src/templates/ally_details.html new file mode 100644 index 0000000..f2970cf --- /dev/null +++ b/src/templates/ally_details.html @@ -0,0 +1,113 @@ + + + + + + + + + + + + + + + + + + + + + {if $ally.descr} + + + + + + + + {/if} + {if $ally.irc} + + + + + + + + {/if} + {if $ally.url} + + + + + + + + {/if} + + + +
    + + + + +
    Allianz {$ally.name}

    + + + + +
    +    +
    + + + + +
    + {if $editlink} + + {/if} + {if $deletelink} + + {/if} +
    + + + + +
    Tag
    + + + + +
    {$ally.tag}
    + + + + +
    Beschreibung
    + + + +
    {$ally.descr|default:"keine"}
    + + + + +
    Irc Channel
    + + + +
    {$ally.irc}
    + + + + +
    Homepage
    + + + +
    {$ally.url}


    +

    \ No newline at end of file diff --git a/src/templates/ally_edit.html b/src/templates/ally_edit.html new file mode 100644 index 0000000..112b8a9 --- /dev/null +++ b/src/templates/ally_edit.html @@ -0,0 +1,129 @@ +
    + + + + + + + + + {if $errors} + + + + + + + {/if} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + +
    Allianz bearbeiten

    + +
    {foreach from=$errors item=error}{$error}
    {/foreach}
    +
    + + + +
    Name
    + + +
    +
    + + + +
    Allianztag
    + + +
    +
    + + + +
    Beschreibung
    + + +
    +
    + + + +
    IRC Channel
    + + + +
    +
    + + + +
    Homepage
    + + + +
    +
    + + + + +
    + Hilfe
    + + + +
    + +


    +

    +
    diff --git a/src/templates/ally_list.html b/src/templates/ally_list.html new file mode 100644 index 0000000..a3545ca --- /dev/null +++ b/src/templates/ally_list.html @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + {cycle print=false values="tbl_2,tbl_1"} + {section name=list loop=$allylist} + {cycle print=false assign="class"} + + + + + + + {sectionelse} + + + + + + + {/section} + + + + + + +
    + + + + + + + + +
    Allianzen

    {$forms.list.pages}
    +
    + + + + + + + +
    Name + + Tag + + Mitglieder + +  
    +
    + + + + + + + +
    {$allylist[list].name} {$allylist[list].tag} {$allylist[list].member|default:"keine"} +
    +
    + + + + +
    Keine Allianzen gefunden
    +
    + + + + +
    +
    {$forms.list.pages}
    +
    +

    +
    diff --git a/src/templates/attplan_add.html b/src/templates/attplan_add.html new file mode 100644 index 0000000..b097f62 --- /dev/null +++ b/src/templates/attplan_add.html @@ -0,0 +1,131 @@ +
    + + + + + + + + {if $errors} + + + + + + + {/if} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + +
    Angriffsplan hinzufügen

    + + + +
    {foreach from=$errors item=error}{$error}
    + {/foreach}
    + + + +
    Titel
    + + + +
    +
    + + + +
    Beschreibung
    + + + +
    +
    + Zeit für Reservierungsstart festlegen
    + + + +
    Start für Reservierung
    + + + +
    Datum: + + (dd.dd.dddd)    Zeit: + + (dd:dd)
    + + + +
    Plan solange verstecken
    + + + +
    + ja + + nein
    + + + + +
    + + + Hilfe
    + + + +
    + +


    +

    +
    diff --git a/src/templates/attplan_content_mytargets.html b/src/templates/attplan_content_mytargets.html new file mode 100644 index 0000000..2531ee4 --- /dev/null +++ b/src/templates/attplan_content_mytargets.html @@ -0,0 +1,6 @@ +
    Meine Ziele
    + Gala: irgendeine +
    + + + + + {if $scan.hasunit || $scan.hassector || $scan.hasgscan} + + {if $scan.hassector} + + {/if} + {if $scan.hasgscan} + + {/if} + {if $scan.hasunit} + + {/if} + + {/if} + {if $scan.hasmili} + + + + {/if} + {if $scan.hasnews} + + + + {/if} +
    1}colspan="{$scan.colspan}"{/if} bgcolor="{$color}"> + + + + + +
    +   + {if $scan.hasnews || $scan.hasmili} + + {else} +    + {/if} +    + + {$scan.gala}:{$scan.pos} {$scan.nick} + + {if $scan.simulator_link} + Simulieren   + {else} +   + {/if} +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {section start=0 loop=`$scan.maxrows-8` name="sectorscan"} + + + + {/section} + + + + +
    + Sektor ({$scan.sector_prec}%) + + {if $scan.sector_time < $timeout} + {$scan.sector_scandate}, {$scan.sector_scantime} + {else} + {$scan.sector_scandate}, {$scan.sector_scantime} + {/if} +
    Punkte:{$scan.sector_punkte2}
    Exen:{$scan.sector_exen}
    M-Exen:{$scan.sector_metall}
    K-Exen:{$scan.sector_kristall}
    Schiffe:{$scan.sector_ships}
    Verteidigung:{$scan.sector_deff}
    Asteroiden:{$scan.sector_roids}
     
    + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + {section start=0 loop=`$scan.maxrows-6` name="gscan"} + + + + {/section} + + + + +
    + Geschütz({$scan.gscan_prec}%) + + {if $scan.gscan_time < $timeout} + {$scan.gscan_scandate}, {$scan.gscan_scantime} + {else} + {$scan.gscan_scandate}, {$scan.gscan_scantime} + {/if} + ?
    Rubium:{$scan.gscan_rubium}
    Pulsar:{$scan.gscan_pulsar}
    Coon:{$scan.gscan_coon}
    Centurion:{$scan.gscan_centurion}
    Horus:{$scan.gscan_horus}
     
    + + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + Einheiten ({$scan.unit_prec}%) + + {if $scan.unit_time < $timeout} + {$scan.unit_scandate}, {$scan.unit_scantime} + {else} + {$scan.unit_scandate}, {$scan.unit_scantime} + {/if} +
    Jäger:{$scan.jaeger}
    Bomber:{$scan.bomber}
    Fregatten:{$scan.fregatten}
    Zerstörer:{$scan.zerstoerer}
    Kreuzer:{$scan.kreuzer}
    Schlachter:{$scan.schlachter}
    Träger:{$scan.traeger}
    Kaperschiffe:{$scan.kleptoren}
    Schutzschiffe:{$scan.cancris}
    + + +
    +
    + {if $scan.expand} + + {/if} +
    + + + +
    Keine Ziele vorhanden
    +
    Zielsuche
    Taktikschirm
    + + + + {if $errors} + + + + + + + {/if} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + +
    Angriffsplan '{$attplan.title}' bearbeiten

    + + + +
    {foreach from=$errors item=error}{$error}
    + {/foreach}
    + + + +
    Titel
    + + + +
    +
    + + + +
    Beschreibung
    + + + +
    +
    + Zeit für Reservierungsstart festlegen
    + + + +
    Start für Reservierung
    + + + +
    Datum: + + (dd.dd.dddd)    Zeit: + + (dd:dd)
    + + + +
    Plan solange verstecken
    + + + +
    + ja + + nein
    + + + + +
    + + + Hilfe
    + + + +
    + +


    +

    + diff --git a/src/templates/attplan_list.html b/src/templates/attplan_list.html new file mode 100644 index 0000000..62c9ab1 --- /dev/null +++ b/src/templates/attplan_list.html @@ -0,0 +1,62 @@ + + + + + + + + + {foreach from=$items.list item=item} + + + + + + + {foreachelse} + + + + + + + {/foreach} + + + + + + +
    + + + + + + + +
    geplante Angriffe

    {$pages}
    +
    + + + + + + +
    {$item.title}{if $item.scan_time}{$item.scan_time}{else}Scans verfügbar{/if}{if $item.showlink}Ansehen{else}Geschlossen{/if}
    +
    + + + + +
    Keine Angriffe geplant
    +
    + + + + +
    +
    {$pages}
    +
    +

    +
    diff --git a/src/templates/attplan_targets.html b/src/templates/attplan_targets.html new file mode 100644 index 0000000..0376541 --- /dev/null +++ b/src/templates/attplan_targets.html @@ -0,0 +1,133 @@ +{literal} + +
    + + + + + + + + + + + + + {if $targets} + + + + {/if} + + + + + + +
    + + + + +
    {$attplan.title}

    + Zurück zum Plan •  + Plan bearbeiten +
    +
    + + + + + +
    + Ziele hinzufügen + + {$pagebar} +
    +
    + markierte Ziele: + +
    + + + {foreach from=$targets item=target key=gala} + + {foreachelse} + + {/foreach} + {if $spacer} + + {/if} + +
    + + + + + + {foreach from=$target item=scan} + + + + + {/foreach} + + + + +
    Koords + + Atterstatus +
    + + + + + +
    {$scan.gala}:{$scan.pos}
    +
    + {if $scan.atter} + {$scan.atter} Atter + {else} + keine + {/if} +
    + alle + + keine +
    +
    + keine Ziele vorhanden +   + +
    +

    +
    +
    \ No newline at end of file diff --git a/src/templates/attplan_targets_add.html b/src/templates/attplan_targets_add.html new file mode 100644 index 0000000..1e0ea14 --- /dev/null +++ b/src/templates/attplan_targets_add.html @@ -0,0 +1,151 @@ +{literal} + +{/literal} +
    + + + + + + + + + {if $errors} + + + + + + + {/if} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + {$attplan.title}

    Angriffsziele hinzufügen
    +
    + + + +
    {foreach from=$errors item=error}{$error}
    + {/foreach}
    + +    ganze Galaxie hinzufügen (1-12) +
    + Galaxie +
    +    Teilbereich einer Galaxie hinzufügen (xx-yy) +
    + Galaxie + von Position + bis + hinzufügen +
    + +    einzelnes Ziel hinzufügen (gala : pos)
    + Galaxie + Position +
    + + + + +
    + + + Hilfe
    + + + +
    + +


    +

    +
    + diff --git a/src/templates/attplan_view.html b/src/templates/attplan_view.html new file mode 100644 index 0000000..93631f7 --- /dev/null +++ b/src/templates/attplan_view.html @@ -0,0 +1,173 @@ + + + + + + + + + {if $type eq "ziele"} + + + + {if $hastargets} + + + + + + + {if $scanlist} + {foreach item=scan from=$scanlist} + + + + + + + {/foreach} + {else} + + + + {/if} +{else} + + + +{/if} + + + +{/if} + + + + + + +
    + + + + +
    {$attplan.title}

    {if $attplan.descr}{$attplan.descr}

    {/if} + {if $attplan.isadmin}Plan bearbeiten • Plan löschen • Ziele bearbeiten{/if}
    +
    + + + + + +
    + Ziele + + {if $hastargets} +
    + + + + + + Galaxien: + +
    + {else} +   + {/if} +
    +
    + + + + + {if $scan.hasunit || $scan.hassector || $scan.hasgscan} + + {if $scan.hassector} + + {/if} + {if $scan.hasgscan} + + {/if} + {if $scan.hasunit} + + {/if} + + {/if} + {if $scan.hasmili} + + + + {/if} + {if $scan.hasnews} + + + + {/if} +
    1}colspan="{$scan.colspan}"{/if} bgcolor="#CCCCCC"> + + + + + + +
    +   + {if $scan.hasnews || $scan.hasmili} + + {else} +    + {/if} +    + + {$scan.gala}:{$scan.pos} {$scan.nick} + + {if $scan.canreserve} + {if !$scan.closed} + Reservieren + {/if} + {else} + von {$scan.atter_nick} ({$scan.atter_gala}:{$scan.atter_pos}) reserviert + {if $scan.candelete && !$scan.closed} +    Löschen + {/if} + {/if} + {if $scan.closed} +    Geschlossen + {/if} + + {if $scan.simulator_link} + Simulieren   + {else} +   + {/if} +
    +
    + {include file="scan_sektor.html"} + + {include file="scan_gscan.html"} + + {include file="scan_unit.html"} +
    + {if $scan.expand} + + {/if} +
    + Keine Scans für die Ziele in Galaxie {$selectedgala} gefunden +
    + Keine Ziele vorhanden +
    +

    +
    diff --git a/src/templates/bot_add.html b/src/templates/bot_add.html new file mode 100644 index 0000000..71a1c9a --- /dev/null +++ b/src/templates/bot_add.html @@ -0,0 +1,126 @@ +
    + + + + + + + + {if $errors} + + + + + + + {/if} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + +
    IRC Bot hinzufügen

    + +
    {foreach from=$errors item=error}{$error}
    {/foreach}
    +
    + + + +
    Name
    + + +
    +
    + + + +
    Login
    + + +
    +
    + + + +
    Passwort
    + + +
    +
    + + + +
    SOAP Server
    + + +
    +
    + + + +
    Hostmask
    + + +
    +
    + + + + +
    + Hilfe
    + + + +
    + +


    +

    +
    diff --git a/src/templates/bot_edit.html b/src/templates/bot_edit.html new file mode 100644 index 0000000..54d0b80 --- /dev/null +++ b/src/templates/bot_edit.html @@ -0,0 +1,127 @@ +
    + + + + + + + + + {if $errors} + + + + + + + {/if} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + +
    IRC Bot bearbeiten

    + +
    {foreach from=$errors item=error}{$error}
    {/foreach}
    +
    + + + +
    Name
    + + +
    +
    + + + +
    Login
    + + +
    +
    + + + +
    Passwort
    + + +
    +
    + + + +
    SOAP Server
    + + +
    +
    + + + +
    Hostmask
    + + +
    +
    + + + + +
    + Hilfe
    + + + +
    + +


    +

    +
    diff --git a/src/templates/bot_list.html b/src/templates/bot_list.html new file mode 100644 index 0000000..341de5a --- /dev/null +++ b/src/templates/bot_list.html @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + {cycle print=false values="tbl_2,tbl_1"} + {section name=list loop=$list} + {cycle print=false assign="class"} + + + + + + + {sectionelse} + + + + + + + {/section} + + + +
    + + + + +
    IRC Bots

    +
    + + + + + + + +
    NameStatusHost 
    +
    + + + + + + + +
    {$list[list].name} + {if $list[list].authstring} + online
    + online seit: {$list[list].firstauth} + {else} + offline
    + letzter login: + {if $list[list].lastauth} + {$list[list].lastauth} + {else} + unbekannt + {/if} + {/if}
    {$list[list].host} +
    +
    + + + + +
    Keine Bots vorhanden
    +

    +
    diff --git a/src/templates/box_activity_content.html b/src/templates/box_activity_content.html new file mode 100644 index 0000000..44839cc --- /dev/null +++ b/src/templates/box_activity_content.html @@ -0,0 +1,22 @@ + + + + + {if $box.activity.docheck} + + + + {else} + + + + {/if} +
    + {$box.activity.points} Punkte gesammelt +
    +
    + + + +
    +
    nächster Checkpoint:
    {$box.activity.nextcheck}
    \ No newline at end of file diff --git a/src/templates/box_case.html b/src/templates/box_case.html new file mode 100644 index 0000000..c3dc9ba --- /dev/null +++ b/src/templates/box_case.html @@ -0,0 +1,14 @@ +{strip} + + + + + + + + + +
    {$box_title|default:" "} + +
    {include file = "$box_content"}
    +{/strip} \ No newline at end of file diff --git a/src/templates/box_fleets_content.html b/src/templates/box_fleets_content.html new file mode 100644 index 0000000..04383b3 --- /dev/null +++ b/src/templates/box_fleets_content.html @@ -0,0 +1,32 @@ + + {foreach from=$box.fleets.list item=item} + + + + + {/foreach} +
    + + Flotte + {$item.num}:
    + {if $item.return_flight} + + Rückflug + {if $item.tgala}({$item.tgala}:{$item.tpos}){/if}
    +
    + ETA {$item.eta}
    + {else} + {if $item.status == 0} + Im Orbit
    + {elseif $item.status == 1} + Angriffsflug {if $item.tgala}({$item.tgala}:{$item.tpos}){/if}
    + ETA {$item.eta}
    + {elseif $item.status == 2} + Verteidigung {if $item.tgala}({$item.tgala}:{$item.tpos}){/if}
    + ETA {$item.eta}
    + {else} + Rückflug
    + ETA {$item.eta}
    + {/if} + {/if} +
    diff --git a/src/templates/box_takscreen_content.html b/src/templates/box_takscreen_content.html new file mode 100644 index 0000000..fe9bdd0 --- /dev/null +++ b/src/templates/box_takscreen_content.html @@ -0,0 +1,21 @@ +{strip} + + + + + +
      + {if $box.takscreen.info.incs} + {if $box.takscreen.info.safe == $box.takscreen.info.incs} + + {else} + + {/if} + {$box.takscreen.info.safe|default:"0"}/{$box.takscreen.info.incs} User safe
    +
    + {$box.takscreen.info.atter} {if $box.takscreen.info.atter == 1}Angriffsflotte{else}Angriffsflotten{/if}
    + {else} + keine Incomings + {/if} +
    + {/strip} \ No newline at end of file diff --git a/src/templates/box_userdata_content.html b/src/templates/box_userdata_content.html new file mode 100644 index 0000000..ee44e9c --- /dev/null +++ b/src/templates/box_userdata_content.html @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + +
    {$box.userbox.username} ({$box.userbox.gala}:{$box.userbox.pos}) 
    Passwort + ändern
    Einstellungen
    Taktikdaten + +
    + Flottenupdate +
    Logout
    diff --git a/src/templates/box_useronline_content.html b/src/templates/box_useronline_content.html new file mode 100644 index 0000000..6e37843 --- /dev/null +++ b/src/templates/box_useronline_content.html @@ -0,0 +1,21 @@ + + {foreach name=box_useronline_list from=$box.useronline.list item=user} + {if $smarty.foreach.box_useronline_list.first} + + + + + {/if} + + + + + {/foreach} +
    {$smarty.foreach.box_useronline_list.total} User online
    + + + + + +
    {$user.name}({$user.gala}:{$user.pos})
    +
    \ No newline at end of file diff --git a/src/templates/com_add_form.html b/src/templates/com_add_form.html new file mode 100644 index 0000000..be2c7dd --- /dev/null +++ b/src/templates/com_add_form.html @@ -0,0 +1,188 @@ + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + +
    Kommentar hinzufügen

    + + + +
    Text
    + + + +
    +
    {$forms.addcom.fields.message.error}
    + + + +
    Smilies
    + + + +
     
    + + + +
    BBCode
    + + + +
    + + einfacher Modus + + erweiterter Modus
    + + + + +
    + + + + + + + + + +
    +
    + + + + +
    + Hilfe
    + + + +
    + +


    +

    +
    diff --git a/src/templates/com_list.html b/src/templates/com_list.html new file mode 100644 index 0000000..ad70c37 --- /dev/null +++ b/src/templates/com_list.html @@ -0,0 +1,110 @@ + + + + + + + + + + + + + + + + + + + + + + {cycle print=false values="tbl_1,tbl_2"} + {section name=list loop=$comlist} + {cycle print=false assign="class"} + + + + + + + {sectionelse} + + + + + + + {/section} + + + + + + +
    + + + + +
    Kommentare

    +
    + + + + + + + +
    {$news.title} ({$news.ntime} {$news.ndate}) + von  {$news.nick} {if $news.usertitle} ({$news.usertitle}){/if}
    + {$news.content} +
    +
    + + + + + +
    + Neues + Kommentar {$forms.comlist.pages}
    +
    + + + + + + + + + + + +
    {$comlist[list].cdate}, + {$comlist[list].ctime} Uhr
    + {$comlist[list].content} +
    {if $canedit}{else} {/if} + + {if $comlist[list].uid} + von  {$comlist[list].nick} ({$comlist[list].gala}:{$comlist[list].pos}) + {else} + [User gelöscht] + {/if} +
    +
    + + + + +
    Keine Kommentare vorhanden
    +
    + + + + +
    +
    {$forms.comlist.pages}
    +
    +

    +
    diff --git a/src/templates/error.html b/src/templates/error.html new file mode 100644 index 0000000..fa1d228 --- /dev/null +++ b/src/templates/error.html @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + +Untitled + + + +{$message} +


    +
    + + \ No newline at end of file diff --git a/src/templates/footer.html b/src/templates/footer.html new file mode 100644 index 0000000..479823b --- /dev/null +++ b/src/templates/footer.html @@ -0,0 +1,10 @@ +{strip} + + + + +{/strip} \ No newline at end of file diff --git a/src/templates/gala_add.html b/src/templates/gala_add.html new file mode 100644 index 0000000..92a2808 --- /dev/null +++ b/src/templates/gala_add.html @@ -0,0 +1,91 @@ +
    + + + + + + + + {if $errors} + + + + + + + {/if} + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + +
    Galaxie hinzufügen

    + +
    {foreach from=$errors item=error}{$error}
    {/foreach}
    +
    + + + +
    Nummer
    + + +
    +
    + + + +
    Allianz
    + + + +
    + {if $rank < 2} + + {else} + {$ally} + {/if} +
    + + + + +
    + Hilfe
    + + + +
    + +


    +

    +
    diff --git a/src/templates/gala_details.html b/src/templates/gala_details.html new file mode 100644 index 0000000..ed180a7 --- /dev/null +++ b/src/templates/gala_details.html @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + +
    Galaxie {$galaxy.gala}

    + + + + {/if} + +
       + {if $searchlink} +
    + + + + +
    + {/if} + {if $editlink} + + {/if} + {if $deletelink} +
    + + + + +
    Nummer
    + + + + +
    {$galaxy.gala}
    + + + + +
    Allianz
    + + + +
    {$galaxy.name} ({$galaxy.tag})
    + + + + +
    Mitglieder
    + + + +
    {$galaxy.member|default:"keine"}


    +

    \ No newline at end of file diff --git a/src/templates/gala_edit.html b/src/templates/gala_edit.html new file mode 100644 index 0000000..a83bed8 --- /dev/null +++ b/src/templates/gala_edit.html @@ -0,0 +1,92 @@ +
    + + + + + + + + + {if $errors} + + + + + + + {/if} + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + +
    Galaxie bearbeiten

    + +
    {foreach from=$errors item=error}{$error}
    {/foreach}
    +
    + + + +
    Nummer
    + + +
    +
    + + + +
    Allianz
    + + + +
    + {if $rank < 2} + + {else} + {$ally} + {/if} +
    + + + + +
    + Hilfe
    + + + +
    + +


    +

    +
    diff --git a/src/templates/gala_list.html b/src/templates/gala_list.html new file mode 100644 index 0000000..24d9048 --- /dev/null +++ b/src/templates/gala_list.html @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + {cycle print=false values="tbl_2,tbl_1"} + {section name=list loop=$galaxylist} + {cycle print=false assign="class"} + + + + + + + {sectionelse} + + + + + + + {/section} + + + + + + +
    + + + + + + + + +
    Galaxien

    {$forms.list.pages}
    +
    + + + + + + + +
    Galaxie + + Allianz + + Mitglieder + +  
    +
    + + + + + + + +
    {$galaxylist[list].gala} {$galaxylist[list].tag} {$galaxylist[list].member|default:"keine"} +
    +
    + + + + +
    Keine Galaxien gefunden
    +
    + + + + +
    +
    {$forms.list.pages}
    +
    +

    +
    diff --git a/src/templates/group_add_form.html b/src/templates/group_add_form.html new file mode 100644 index 0000000..477ab53 --- /dev/null +++ b/src/templates/group_add_form.html @@ -0,0 +1,97 @@ +
    + + + + + + + + {if $errors} + + + + + + + {/if} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + +
    Gruppe hinzufügen

    + +
    {foreach from=$errors item=error}{$error}
    {/foreach}
    +
    + + + +
    Name
    + + +
    +
    + + + +
    Beschreibung
    + + +
    +
    + + + +
    Benutzertitel
    + + + +
    +
    + + + + +
    + Hilfe
    + + + +
    + +


    +

    +
    diff --git a/src/templates/group_details_admin.html b/src/templates/group_details_admin.html new file mode 100644 index 0000000..0836b21 --- /dev/null +++ b/src/templates/group_details_admin.html @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + +
    Gruppe {$forms.groupdetails.fields.name}

    + + + + +
       +
    + + + + +
    + +
    + + + + +
    Beschreibung
    + + + + +
    {$forms.groupdetails.fields.descr|default:"keine"}
    + + + + +
    Usertitel
    + + + + +
    {$forms.groupdetails.fields.usertitle|default:"keinen"}


    +

    \ No newline at end of file diff --git a/src/templates/group_edit_form.html b/src/templates/group_edit_form.html new file mode 100644 index 0000000..7479457 --- /dev/null +++ b/src/templates/group_edit_form.html @@ -0,0 +1,97 @@ +
    + + + + + + + + {if $errors} + + + + + + + {/if} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + +
    Gruppe {$forms.groupedit.name} bearbeiten

    + +
    {foreach from=$errors item=error}{$error}
    {/foreach}
    +
    + + + +
    Name
    + + +
    +
    + + + +
    Beschreibung
    + + +
    +
    + + + +
    Benutzertitel
    + + + +
    +
    + + + + +
    + Hilfe
    + + + +
    + +


    +

    +
    diff --git a/src/templates/group_editrights.html b/src/templates/group_editrights.html new file mode 100644 index 0000000..4eb20ab --- /dev/null +++ b/src/templates/group_editrights.html @@ -0,0 +1,85 @@ +
    + + + + + + + + + + + + + + + + + {foreach from=$rightslist item=right} + {if $right.rid} + + + + + + + + {/if} + {/foreach} + + + + + + + + + + +
    + + + +
    Gruppenrechte bearbeiten {$ebene}

    + + + + +
    + +
    +
    + + + +
    + {$right.descr}
    + + + + +
    + Ja: + + Nein: + + {$right.vererbt} +
    + + + + +
    + Hilfe
    + + + +
    + +


    +

    +
    diff --git a/src/templates/group_list.html b/src/templates/group_list.html new file mode 100644 index 0000000..4ef7c86 --- /dev/null +++ b/src/templates/group_list.html @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + {cycle print=false values="tbl_2,tbl_1"} + {section name=list loop=$grouplist} + {cycle print=false assign="class"} + + + + + + + {sectionelse} + + + + + + + {/section} + + + + + + +
    + + + + + + + + +
    Gruppenliste

    {$forms.grouplist.pages}
    +
    + + + + + + + +
    Name + + Beschreibung + + Mitglieder + +  
    +
    + + + + + + + +
    {$grouplist[list].name} {$grouplist[list].descr|default:"keine"} {$grouplist[list].member|default:"keine"} +
    +
    + + + + +
    Keine Gruppen gefunden
    +
    + + + + +
    +
    {$forms.grouplist.pages}
    +
    +

    +
    diff --git a/src/templates/group_rights.html b/src/templates/group_rights.html new file mode 100644 index 0000000..1ac11ac --- /dev/null +++ b/src/templates/group_rights.html @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + +
    + + + + +
    Gruppenrechte

    + +
    +
    + + + + +
    + +
    +


    +

    diff --git a/src/templates/header.html b/src/templates/header.html new file mode 100644 index 0000000..7b7dd35 --- /dev/null +++ b/src/templates/header.html @@ -0,0 +1,10 @@ +{strip} + + + +{$htmlpagetitle} + + + + +{/strip} \ No newline at end of file diff --git a/src/templates/highscore_index.html b/src/templates/highscore_index.html new file mode 100644 index 0000000..8607b5f --- /dev/null +++ b/src/templates/highscore_index.html @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + +
    {$highscore.title}

    +
    +
    + Total •  + Mitarbeiter + des Tages •  + Mitarbeiter + der Woche +
    {$pages}
    + {if $highscore.list} + + + + + + + + + {foreach from=$highscore.list item=user} + + + + + + + + {/foreach} +
    + Platz + + Koords + + Nick + + Allianz + + Punkte +
    + {$user.place} + + ({$user.gala}:{$user.pos}) + + {$user.nick} + + [{$user.tag}] + + {$user.activity_points} +
    + {else} + keine Einträge vorhanden + {/if} +

    +
    diff --git a/src/templates/index.html b/src/templates/index.html new file mode 100644 index 0000000..b9fcbae --- /dev/null +++ b/src/templates/index.html @@ -0,0 +1,182 @@ +{include file="header.html"} +{literal} + + +{/literal} + + + + + + + + + +
    {include file="box_case.html" box_content + = "`$box.menu.template`" box_width="120" box_title="`$box.menu.title`" }
    + Get Firefox!
    + {include file="box_case.html" box_content + = "`$box.mainbox.template`" box_width="700" box_title="`$box.mainbox.title`"} + +

    + {include file="box_case.html" box_content = "`$box.userbox.template`" box_width="135" box_title="`$box.userbox.title`" } + {if $box.targets.template} + {include file="box_case.html" box_content = "`$box.targets.template`" box_width="135" box_title="`$box.targets.title`" } + {/if} + {if $box.fleets.template} + {include file="box_case.html" box_content = "`$box.fleets.template`" box_width="135" box_title="`$box.fleets.title`" } + {/if} + {include file="box_case.html" box_content = "`$box.takscreen.template`" box_width="135" box_title="`$box.takscreen.title`" } + {if $box.activity.template} + {include file="box_case.html" box_content = "`$box.activity.template`" box_width="135" box_title="`$box.activity.title`" } + {/if} + {include file="box_case.html" box_content = "`$box.useronline.template`" box_width="135" box_title="`$box.useronline.title`" } +

    +
    {$version}
    +{include file="footer.html"} \ No newline at end of file diff --git a/src/templates/index.html.bak b/src/templates/index.html.bak new file mode 100644 index 0000000..1c30f6c --- /dev/null +++ b/src/templates/index.html.bak @@ -0,0 +1,213 @@ +{include file="header.html"} +{literal} + + +{/literal} + + + + + + + + + +
    {include file="box_case.html" box_content + = "`$box.menu.template`" box_width="120" box_title="`$box.menu.title`" } + + {include file="box_case.html" box_content + = "`$box.mainbox.template`" box_width="700" box_title="`$box.mainbox.title`"} + +

    + {include file="box_case.html" box_content = "`$box.userbox.template`" box_width="135" box_title="`$box.userbox.title`" } + {if $box.targets.template} + {include file="box_case.html" box_content = "`$box.targets.template`" box_width="135" box_title="`$box.targets.title`" } + {/if} + {if $box.fleets.template} + {include file="box_case.html" box_content = "`$box.fleets.template`" box_width="135" box_title="`$box.fleets.title`" } + {/if} + {include file="box_case.html" box_content = "`$box.takscreen.template`" box_width="135" box_title="`$box.takscreen.title`" } + {include file="box_case.html" box_content = "`$box.useronline.template`" box_width="135" box_title="`$box.useronline.title`" } +

    +
    {$version}
    +{include file="footer.html"} \ No newline at end of file diff --git a/src/templates/index_login.html b/src/templates/index_login.html new file mode 100644 index 0000000..eb755bc --- /dev/null +++ b/src/templates/index_login.html @@ -0,0 +1,84 @@ +{strip} + + +{$version} -- Login + +{literal}{/literal} + + +
    + + + + + + +
    + + + + +
    + + + + + + + + + +
    Login
    + + + + + + + + + + +
    + + + + + + +
    Username:
    Passwort:
    +
    keys
    +
    +
    +
    +
    + + + +{/strip} \ No newline at end of file diff --git a/src/templates/logfile_list.html b/src/templates/logfile_list.html new file mode 100644 index 0000000..bd903f1 --- /dev/null +++ b/src/templates/logfile_list.html @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + {cycle print=false values="tbl_2,tbl_1"} + {section name=list loop=$logfile} + {cycle print=false assign="class"} + + + + + + + {sectionelse} + + + + + + + {/section} + + + + + + +
    + + + + + + + + +
    Logfile

    + {$forms.logfile.pages}
    +
    + + + + + + + +
    Zeitpunkt  + + Aktion Nickname  + + Kategorie  + +
    +
    + + + + + + + +
    {$logfile[list].time} {$logfile[list].date} + {$logfile[list].descr} + {if $logfile[list].nick} {$logfile[list].nick} ({$logfile[list].gala}:{$logfile[list].pos}){else}unbekannt{/if} + {$logfile[list].cat} +
    +
    + + + + +
    Keine Einträge gefunden
    +
    + + + + +
    +
    {$forms.logfile.pages}
    +
    +

    +
    diff --git a/src/templates/logfile_list_form.html b/src/templates/logfile_list_form.html new file mode 100644 index 0000000..bc166aa --- /dev/null +++ b/src/templates/logfile_list_form.html @@ -0,0 +1,94 @@ +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + +
    Logfile durchsuchen

    + + + +
    Nickname
    + + + +
    + {$forms.logfile.fields.username.error}
    + + + +
    Gala
    + + + +
    + {$forms.logfile.fields.gala.error}
    + + + +
    Kategorie
    + + + +
    + + + + +
    + Hilfe
    + + + +
    + +


    +

    +
    diff --git a/src/templates/member_list.html b/src/templates/member_list.html new file mode 100644 index 0000000..c2beabe --- /dev/null +++ b/src/templates/member_list.html @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + {cycle print=false values="tbl_2,tbl_1"} + {foreach from=$userlist item=user} + {cycle print=false assign="class"} + + + + + + + {/foreach} + + + + + + +
    + + + + + + + + +
    Memberliste

    {$pages}
    +
    +
    + + + + + + + + +
    Nickname + + Koords + +
    +
    +
    + + + + + + + +
    [{$user.tag}]{$user.nick} {if $user.usertitle}({$user.usertitle}){/if}{$user.phone|default:"keine"} {$user.gala}:{$user.pos}
    +
    + + + + +
    +
    {$pages}
    +
    +

    +
    diff --git a/src/templates/menu.html b/src/templates/menu.html new file mode 100644 index 0000000..eb6a532 --- /dev/null +++ b/src/templates/menu.html @@ -0,0 +1,26 @@ +{strip} + + {foreach from=$menu item=menu} + + + + + {if $menu.items} + + + + + {/if} + {/foreach} +
    + + + {$menu.caption} +
    +{/strip} diff --git a/src/templates/message.html b/src/templates/message.html new file mode 100644 index 0000000..11a4205 --- /dev/null +++ b/src/templates/message.html @@ -0,0 +1,41 @@ +
    + {foreach from=$params item=item key=key} + + {/foreach} + + + + + + + + + + + + + + + + + + + + + + +
    + + + +
    {$title}

    + {$message} +
    + + + +
    +


    +

    + +
    diff --git a/src/templates/message_information.html b/src/templates/message_information.html new file mode 100644 index 0000000..1f86d00 --- /dev/null +++ b/src/templates/message_information.html @@ -0,0 +1,42 @@ +
    + + {if $forms.information.action}{/if} + + + + + + + + + + + + + + + + + + + + + + +
    + + + +
    {$forms.information.title}

    + + + +
    {$forms.information.message}
    + + + +
    +


    +

    + +
    diff --git a/src/templates/message_question.html b/src/templates/message_question.html new file mode 100644 index 0000000..eb4892b --- /dev/null +++ b/src/templates/message_question.html @@ -0,0 +1,45 @@ +
    + + + + + {if $forms.information.action}{/if} + + + + + + + + + + + + + + + + + + + + + + +
    + + + +
    {$forms.information.title}

    + + + +
    {$forms.information.message}
    + + + +
      +


    +

    + +
    diff --git a/src/templates/news.html b/src/templates/news.html new file mode 100644 index 0000000..41e843b --- /dev/null +++ b/src/templates/news.html @@ -0,0 +1 @@ +News diff --git a/src/templates/news_add_form.html b/src/templates/news_add_form.html new file mode 100644 index 0000000..fd02524 --- /dev/null +++ b/src/templates/news_add_form.html @@ -0,0 +1,205 @@ + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + +
    Nachricht hinzufügen

    + + + +
    Titel
    + + + +
    +
    {$forms.addnews.fields.title.error}
    + + + +
    Text
    + + + +
    +
    {$forms.addnews.fields.message.error}
    + + + +
    Smilies
    + + + +
     
    + + + +
    BBCode
    + + + +
    + + einfacher Modus + + erweiterter Modus
    + + + + +
    + + + + + + + + + +
    +
    + + + + +
    + Hilfe
    + + + +
    + + +


    +

    +
    diff --git a/src/templates/news_edit_form.html b/src/templates/news_edit_form.html new file mode 100644 index 0000000..e9872f9 --- /dev/null +++ b/src/templates/news_edit_form.html @@ -0,0 +1,205 @@ + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + +
    Nachricht bearbeiten

    + + + +
    Titel
    + + + +
    +
    {$forms.editnews.fields.title.error}
    + + + +
    Text
    + + + +
    +
    {$forms.editnews.fields.message.error}
    + + + +
    Smilies
    + + + +
     
    + + + +
    BBCode
    + + + +
    + + einfacher Modus + + erweiterter Modus
    + + + + +
    + + + + + + + + + +
    +
    + + + + +
    + Hilfe
    + + + +
    +   + +


    +

    +
    diff --git a/src/templates/news_list.html b/src/templates/news_list.html new file mode 100644 index 0000000..890d60f --- /dev/null +++ b/src/templates/news_list.html @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + {cycle print=false values="tbl_1,tbl_2"} + {section name=list loop=$newslist} + {cycle print=false assign="class"} + + + + + + + {sectionelse} + + + + + + + {/section} + + + + + + +
    + + + + +
    Nachrichten

    +
    + + + + + +
    {if $forms.newslist.canedit}{else} {/if} + {$forms.newslist.pages}
    +
    + + + + + + + + + + + +
    {$newslist[list].title} + ({$newslist[list].ntime} {$newslist[list].ndate}) + {if $newslist[list].uid} + von  {$newslist[list].nick} + {if $newslist[list].usertitle} ({$newslist[list].usertitle}){/if} + {/if} +
    + {$newslist[list].content} +
    {if $forms.newslist.canedit} +  {else} {/if} + +
    +
    + + + + +
    Keine Nachrichten vorhanden
    +
    + + + + +
    +
    {$forms.newslist.pages}
    +
    +

    +
    diff --git a/src/templates/scan_add_form.html b/src/templates/scan_add_form.html new file mode 100644 index 0000000..c04da0d --- /dev/null +++ b/src/templates/scan_add_form.html @@ -0,0 +1,92 @@ +
    + + + + + + + + {if $forms.addscan.message} + + + + + + + {/if} + {if $scanlist} + + + + + + + {/if} + + + + + + + + + + + + + + + + + + + + +
    + + + +
    Scan hinzufügen/updaten

    + + + +
    {$forms.addscan.message}
    + + {foreach from=$scanlist item=scan} + + + + {/foreach} +
    + {if $scan.type == "sector"}Sektor + {elseif $scan.type == "unit"}Einheiten + {elseif $scan.type == "gscan"}Geschütz + {elseif $scan.type == "mili"}Militär + {elseif $scan.type == "news"}Nachrichten + {/if} + ({$scan.prec}%) ({$scan.gala}:{$scan.pos}) {$scan.nick} +
    +
    + + + +
    Scan:
    + + + +
    + {$forms.addscan.fields.nickname.error}
    + + + + +
    + Hilfe
    + + + +
    + +


    +

    +
    diff --git a/src/templates/scan_details.html b/src/templates/scan_details.html new file mode 100644 index 0000000..b9c1460 --- /dev/null +++ b/src/templates/scan_details.html @@ -0,0 +1,108 @@ + + + + + + + + {if $scan} + + + + + + + + + + {else} + + + + {/if} + + + + + + + + + +
    + + + + + + +
    Details von ({$gala}:{$pos})

    +   +
    +
    + + + + + {if $scan.hasunit || $scan.hassector || $scan.hasgscan} + + {if $scan.hassector} + + {/if} + {if $scan.hasgscan} + + {/if} + {if $scan.hasunit} + + {/if} + + {/if} + {if $scan.hasmili} + + + + {/if} + {if $scan.hasnews} + + + + {/if} +
    1}colspan="{$scan.colspan}"{/if} bgcolor="#EFEFEF"> + + + + + +
    +   +    + + {$scan.gala}:{$scan.pos} {$scan.nick} + + {if $scan.simulator_link} + Simulieren   + {else} +   + {/if} +
    +
    + {include file="scan_sektor.html"} + + {include file="scan_gscan.html"} + + {include file="scan_unit.html"} +
    1}colspan="{$scan.colspan}"{/if} bgcolor="#EFEFEF" valign="top"> + {include file="scan_mili.html"} +
    1}colspan="{$scan.colspan}"{/if} valign="top" bgcolor="#EFEFEF"> + {include file="scan_news.html"} +
    +
    + + + +
    Keine Scans für ({$gala}:{$pos}) gefunden
    +
    + + + +
    {$forms.scanlist.pages}

    \ No newline at end of file diff --git a/src/templates/scan_gscan.html b/src/templates/scan_gscan.html new file mode 100644 index 0000000..922a331 --- /dev/null +++ b/src/templates/scan_gscan.html @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + {section start=0 loop=`$scan.maxrows-6` name="gscan"} + + + + {/section} + + + + +
    + Geschütz({$scan.gscan_prec}%) + + {if $scan.gscan_timeout}{/if} + {$scan.gscan_scanage} alt + {if $scan.gscan_timeout}{/if} +
    Rubium:{$scan.gscan_rubium|default:"0"}
    Pulsar:{$scan.gscan_pulsar|default:"0"}
    Coon:{$scan.gscan_coon|default:"0"}
    Centurion:{$scan.gscan_centurion|default:"0"}
    Horus:{$scan.gscan_horus|default:"0"}
     
    + + +
    diff --git a/src/templates/scan_list.html b/src/templates/scan_list.html new file mode 100644 index 0000000..6697764 --- /dev/null +++ b/src/templates/scan_list.html @@ -0,0 +1,171 @@ + + + + + + + + {if $showtargets} + + + + {else} + + + + {/if} + + + + {cycle print=false values="#EFEFEF"} + {foreach item=scan from=$scanlist} + {cycle print=false assign="color"} + + + + + + + + + + {foreachelse} + + + + {/foreach} + + + + + + + + + +
    + + + +
    {$scantitle}

    + + + + + + + + + + +
     {$forms.scanlist.pages}
    Koords + + Exen + +
    + {if $showform} + + + + + + + + + {/if} + + + +
    {$forms.scanlist.pages}
    Koords +
    + + + {if $prev}«« {/if} + + {if $next} »» +   {/if} + +
    {$hideoldtitle}
    + + + + + {if $scan.hasunit || $scan.hassector || $scan.hasgscan} + + {if $scan.hassector} + + {/if} + {if $scan.hasgscan} + + {/if} + {if $scan.hasunit} + + {/if} + + {/if} + {if $scan.hasmili} + + + + {/if} + {if $scan.hasnews} + + + + {/if} +
    1}colspan="{$scan.colspan}"{/if} bgcolor="{$color}"> + + + + + + +
    +   + {if $scan.hasnews || $scan.hasmili} + + {else} +    + {/if} +    + + {$scan.gala}:{$scan.pos} {$scan.nick} + +
    + {if $scan.uid}reserviert von {$scan.atter_nick} ({$scan.atter_gala}:{$scan.atter_pos}){else} {/if} +
    +
    + {if $scan.simulator_link} + Simulieren   + {else} +   + {/if} +
    +
    + {include file="scan_sektor.html"} + + {include file="scan_gscan.html"} + + {include file="scan_unit.html"} +
    + {if $scan.expand} + + {/if} +
    + + + +
    Keine Scans gefunden
    +
    + + + +
    {$forms.scanlist.pages}

    \ No newline at end of file diff --git a/src/templates/scan_mili.html b/src/templates/scan_mili.html new file mode 100644 index 0000000..faf7130 --- /dev/null +++ b/src/templates/scan_mili.html @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + +
    + Militär ({$scan.mili_prec}%) + + {if $scan.mili_timeout}{/if} + {$scan.mili_scanage} alt + {if $scan.mili_timeout}{/if} +
    Orbit:{$scan.mili_formated_fleets[0]}
    Flotte 1:{$scan.mili_formated_fleets[1]}
    Flotte 2:{$scan.mili_formated_fleets[2]}
    + + +
    diff --git a/src/templates/scan_news.html b/src/templates/scan_news.html new file mode 100644 index 0000000..8f69074 --- /dev/null +++ b/src/templates/scan_news.html @@ -0,0 +1,29 @@ + + + + + + {foreach from=$scan.news_formated_newsdata item=line} + + + + + {/foreach} + + + + +
    + Nachrichten ({$scan.news_prec}%) + + {if $scan.news_timeout}{/if} + {$scan.news_scanage} alt + {if $scan.news_timeout}{/if} +
    {$line[1]}{$line[2]}
    + + +
    diff --git a/src/templates/scan_sektor.html b/src/templates/scan_sektor.html new file mode 100644 index 0000000..faf7796 --- /dev/null +++ b/src/templates/scan_sektor.html @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {section start=0 loop=`$scan.maxrows-9` name="sectorscan"} + + + + {/section} + + + + +
    + Sektor ({$scan.sector_prec}%) + + {if $scan.sector_timeout}{/if} + {$scan.sector_scanage} alt + {if $scan.sector_timeout}{/if} +
    Punkte:{$scan.sector_punkte2}
    Macht:{$scan.sector_macht}
    Exen:{$scan.sector_exen}
    M-Exen:{$scan.sector_metall}
    K-Exen:{$scan.sector_kristall}
    Schiffe:{$scan.sector_ships}
    Verteidigung:{$scan.sector_deff}
    Asteroiden:{$scan.sector_roids}
     
    + + +
    diff --git a/src/templates/scan_target_form.html b/src/templates/scan_target_form.html new file mode 100644 index 0000000..d193296 --- /dev/null +++ b/src/templates/scan_target_form.html @@ -0,0 +1,100 @@ +
    + + + + + + + + + {if $errors} + + + + + + + {/if} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + +
    Ziele suchen

    + {foreach from=$errors item=error} + {$error}
    + {/foreach} +
    + + + +
    Macht (mindestens)
    + + + +
    + (optional)
    + + + +
    Exen (mindestens)
    + + + +
    + (optional)
    + + + +
    alte Scans ausblenden
    + + + +
    +
    + + + + +
    + Hilfe
    + + + +
    +


    +

    +
    diff --git a/src/templates/scan_target_set.html b/src/templates/scan_target_set.html new file mode 100644 index 0000000..8b70319 --- /dev/null +++ b/src/templates/scan_target_set.html @@ -0,0 +1,109 @@ +
    + + + + + + + + + + {if $errors} + + + + + + + {/if} + {if $showcomplete} + + + + + + + + {/if} + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + +
    Ziel reservieren

    + + + +
    {foreach from=$errors item=error}{$error}
    + {/foreach}
    + + + +
    Koords
    + + + +
    + : + +
    + + + +
    Flotte
    + + + +
    + Flotte 1 + + Flotte 2
    + + + +
    Abflug
    + + + +
    +
    + + + + +
    + Hilfe
    + + + +
    + +


    +

    +
    diff --git a/src/templates/scan_unit.html b/src/templates/scan_unit.html new file mode 100644 index 0000000..06d9202 --- /dev/null +++ b/src/templates/scan_unit.html @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + Einheiten ({$scan.unit_prec}%) + + {if $scan.unit_timeout}{/if} + {$scan.unit_scanage} alt + {if $scan.unit_timeout}{/if} +
    Jäger:{$scan.jaeger}
    Bomber:{$scan.bomber}
    Fregatten:{$scan.fregatten}
    Zerstörer:{$scan.zerstoerer}
    Kreuzer:{$scan.kreuzer}
    Schlachter:{$scan.schlachter}
    Träger:{$scan.traeger}
    Kaperschiffe:{$scan.kleptoren}
    Schutzschiffe:{$scan.cancris}
    + + +
    diff --git a/src/templates/scanner_list.html b/src/templates/scanner_list.html new file mode 100644 index 0000000..3a49332 --- /dev/null +++ b/src/templates/scanner_list.html @@ -0,0 +1,107 @@ + + + + + + + + + + + + + {cycle print=false values="tbl_2,tbl_1"} + {foreach from=$mililist item=user} + {cycle print=false assign="class"} + + + + + + + {foreachelse} + {cycle print=false assign="class"} + + + + + + + {/foreach} + + + + + + + {cycle print=false values="tbl_2,tbl_1"} + {foreach from=$newslist item=user} + {cycle print=false assign="class"} + + + + + + + {foreachelse} + {cycle print=false assign="class"} + + + + + + + {/foreach} + + + +
    + + + + +
    Scannerübersicht

    +
    + + + + +
    Einheiten / Militär
    +
    + + + + + + + +
    [{$user.tag}]({$user.gala}:{$user.pos}){$user.nick} {if $user.usertitle}({$user.usertitle}){/if}{$user.svs} sVs
    +
    + + + + +
    Keine vorhanden!
    +
    + + + + +
    Geschütz / Nachrichten
    +
    + + + + + + + +
    [{$user.tag}]({$user.gala}:{$user.pos}){$user.nick} {if $user.usertitle}({$user.usertitle}){/if}{$user.svs} sVs
    +
    + + + + +
    Keine vorhanden!
    +

    +
    diff --git a/src/templates/simulator_form.html b/src/templates/simulator_form.html new file mode 100644 index 0000000..efd5efd --- /dev/null +++ b/src/templates/simulator_form.html @@ -0,0 +1,786 @@ +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {if $ticklist} + + + + + + + {cycle values="tbl_1,tbl_2" print=no} + {foreach item=tick from=$ticklist} + + + + {/foreach} + + + + + + {/if} + + + + +
    + + + +
    Kampfsimulator

    + {if $backlink} {/if} +
    + + + +
    + {if $fleets_loaded} + geladene Attflotten:

    + {foreach from=$fleets_loaded item=fleet} + +  {$fleet.nick} ({$fleet.gala}:{$fleet.pos})
    + Kleptoren: {$fleet.kleptoren} Cancris: {$fleet.cancris} Fregatten: {$fleet.fregatten}
    + Zerstörer: {$fleet.zerstoerer} Kreuzer: {$fleet.kreuzer} Träger: {$fleet.traeger}
    + Jäger: {$fleet.jaeger} Bomber: {$fleet.bomber} Schlachter: {$fleet.schlachter}
    + letztes update {$fleet.fleetdate} , {$fleet.fleettime} + Uhr +
    +
    + {/foreach} + {/if} + Attflotte laden:    + +
    + + + +
    Schiffe
    + + + +
    Verteidiger
    + + + +
    Angreifer
    + + + +
    Jäger "Leo"
    + + + +
    +
    + + + +
    + + + +
    Bomber "Aquilae"
    + + + +
    + + + +
    + + + +
    Fregatte "Fronax"
    + + + +
    + + + +
    + + + +
    Zerstörer "Draco"
    + + + +
    + + + +
    + + + +
    Kreuzer "Goron"
    + + + +
    + + + +
    + + + +
    Schlachtschiff "Pentalin"
    + + + +
    + + + +
    + + + +
    Trägerschiff "Zenit"
    + + + +
    + + + +
    + + + +
    Kaperschiff "Cleptor"
    + + + +
    + + + +
    + + + +
    Schutzschiff "Cancri"
    + + + +
    + + + +
    + + + +
    Leichtes Orbitalgeschütz "Rubium"
    + + + +
    + + + +
     
    + + + +
    Leichtes Raumgeschütz "Pulsar"
    + + + +
    + + + +
     
    + + + +
    Mittlers Raumgeschütz "Coon"
    + + + +
    + + + +
     
    + + + +
    Schweres Raumgeschütz "Centurion"
    + + + +
    + + + +
     
    + + + +
    Abfangjäger "Horus"
    + + + +
    + + + +
     
    + + + +
    Metallextraktoren:
    + + + +
    + + + +
     
    + + + +
    Kristallextraktoren:
    + + + +
    + + + +
     
    Ticks:  Vorticks: + + + + +
    +
    + + + + +
    Auswertung
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    {$tick.name}VerteidigerAngreifer
    Typvorhernachhervorhernachher
    Jäger{$tick[2][0]}{$tick[3][0]}{$tick[0][0]}{$tick[1][0]}
    Bomber{$tick[2][1]}{$tick[3][1]}{$tick[0][1]}{$tick[1][1]}
    Freggs{$tick[2][2]}{$tick[3][2]}{$tick[0][2]}{$tick[1][2]}
    Zerris{$tick[2][3]}{$tick[3][3]}{$tick[0][3]}{$tick[1][3]}
    Kreuzer{$tick[2][4]}{$tick[3][4]}{$tick[0][4]}{$tick[1][4]}
    Schlachter{$tick[2][5]}{$tick[3][5]}{$tick[0][5]}{$tick[1][5]}
    Träger{$tick[2][6]}{$tick[3][6]}{$tick[0][6]}{$tick[1][6]}
    Kaperschiffe{$tick[2][7]}{$tick[3][7]}{$tick[0][7]}{$tick[1][7]}
    Schutzschiffe{$tick[2][8]}{$tick[3][8]}{$tick[0][8]}{$tick[1][8]}
    Leichtes Orbitalgeschütz{$tick[2][9]}{$tick[3][9]}  
    Leichtes Raumgeschütz{$tick[2][10]}{$tick[3][10]}  
    Mittleres Raumgeschütz{$tick[2][11]}{$tick[3][11]}  
    Schweres Raumgeschütz{$tick[2][12]}{$tick[3][12]}  
    Abfangjäger{$tick[2][13]}{$tick[3][13]}  
    Metallexen geklaut:{$tick.metall} 
    Kristallexen geklaut:{$tick.kristall} 
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    EndberichtVerluste
    TypVerteidigerAngreifer
    Jäger{$defflost[0]}{$attlost[0]}
    Bomber{$defflost[1]}{$attlost[1]}
    Freggs{$defflost[2]}{$attlost[2]}
    Zerris{$defflost[3]}{$attlost[3]}
    Kreuzer{$defflost[4]}{$attlost[4]}
    Schlachter{$defflost[5]}{$attlost[5]}
    Träger{$defflost[6]}{$attlost[6]}
    Kaperschiffe{$defflost[7]}{$attlost[7]}
    Schutzschiffe{$defflost[8]}{$attlost[8]}
    Leichtes Orbitalgeschütz{$defflost[9]} 
    Leichtes Raumgeschütz{$defflost[10]} 
    Mittleres Raumgeschütz{$defflost[11]} 
    Schweres Raumgeschütz{$defflost[12]} 
    Abfangjäger{$defflost[13]} 
    Metallverluste{$ress[1][0]}{$ress[0][0]}
    Kristallverluste{$ress[1][1]}{$ress[0][1]}
    Insgesamt{$ress[1][2]}{$ress[0][2]}
    Metallexen geklaut:{$metallstolen} 
    Kristallexen geklaut:{$kristallstolen} 
    +


    +

    +
    diff --git a/src/templates/simulator_public.html b/src/templates/simulator_public.html new file mode 100644 index 0000000..f3cd489 --- /dev/null +++ b/src/templates/simulator_public.html @@ -0,0 +1,753 @@ + + + +Kampfsimulator by KiBO|Huhn + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {if $ticklist} + + + + + + + {cycle values="tbl_1,tbl_2" print=no} + {foreach item=tick from=$ticklist} + + + + {/foreach} + + + + + + {/if} + + + + +
    + + + +
    Kampfsimulator by KiBO|Huhn

    + + + +
    Schiffe
    + + + +
    Verteidiger
    + + + +
    Angreifer
    + + + +
    Jäger "Leo"
    + + + +
    +
    + + + +
    + + + +
    Bomber "Aquilae"
    + + + +
    + + + +
    + + + +
    Fregatte "Fronax"
    + + + +
    + + + +
    + + + +
    Zerstörer "Draco"
    + + + +
    + + + +
    + + + +
    Kreuzer "Goron"
    + + + +
    + + + +
    + + + +
    Schlachtschiff "Pentalin"
    + + + +
    + + + +
    + + + +
    Trägerschiff "Zenit"
    + + + +
    + + + +
    + + + +
    Kaperschiff "Cleptor"
    + + + +
    + + + +
    + + + +
    Schutzschiff "Cancri"
    + + + +
    + + + +
    + + + +
    Leichtes Orbitalgeschütz "Rubium"
    + + + +
    + + + +
     
    + + + +
    Leichtes Raumgeschütz "Pulsar"
    + + + +
    + + + +
     
    + + + +
    Mittlers Raumgeschütz "Coon"
    + + + +
    + + + +
     
    + + + +
    Schweres Raumgeschütz "Centurion"
    + + + +
    + + + +
     
    + + + +
    Abfangjäger "Horus"
    + + + +
    + + + +
     
    + + + +
    Metallextraktoren:
    + + + +
    + + + +
     
    + + + +
    Kristallextraktoren:
    + + + +
    + + + +
     
    Ticks:  Vorticks: + + + + +
    +
    + + + + +
    Auswertung
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    {$tick.name}VerteidigerAngreifer
    Typvorhernachhervorhernachher
    Jäger{$tick[2][0]}{$tick[3][0]}{$tick[0][0]}{$tick[1][0]}
    Bomber{$tick[2][1]}{$tick[3][1]}{$tick[0][1]}{$tick[1][1]}
    Freggs{$tick[2][2]}{$tick[3][2]}{$tick[0][2]}{$tick[1][2]}
    Zerris{$tick[2][3]}{$tick[3][3]}{$tick[0][3]}{$tick[1][3]}
    Kreuzer{$tick[2][4]}{$tick[3][4]}{$tick[0][4]}{$tick[1][4]}
    Schlachter{$tick[2][5]}{$tick[3][5]}{$tick[0][5]}{$tick[1][5]}
    Träger{$tick[2][6]}{$tick[3][6]}{$tick[0][6]}{$tick[1][6]}
    Kaperschiffe{$tick[2][7]}{$tick[3][7]}{$tick[0][7]}{$tick[1][7]}
    Schutzschiffe{$tick[2][8]}{$tick[3][8]}{$tick[0][8]}{$tick[1][8]}
    Leichtes Orbitalgeschütz{$tick[2][9]}{$tick[3][9]}  
    Leichtes Raumgeschütz{$tick[2][10]}{$tick[3][10]}  
    Mittleres Raumgeschütz{$tick[2][11]}{$tick[3][11]}  
    Schweres Raumgeschütz{$tick[2][12]}{$tick[3][12]}  
    Abfangjäger{$tick[2][13]}{$tick[3][13]}  
    Metallexen geklaut:{$tick.metall} 
    Kristallexen geklaut:{$tick.kristall} 
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    EndberichtVerluste
    TypVerteidigerAngreifer
    Jäger{$defflost[0]}{$attlost[0]}
    Bomber{$defflost[1]}{$attlost[1]}
    Freggs{$defflost[2]}{$attlost[2]}
    Zerris{$defflost[3]}{$attlost[3]}
    Kreuzer{$defflost[4]}{$attlost[4]}
    Schlachter{$defflost[5]}{$attlost[5]}
    Träger{$defflost[6]}{$attlost[6]}
    Kaperschiffe{$defflost[7]}{$attlost[7]}
    Schutzschiffe{$defflost[8]}{$attlost[8]}
    Leichtes Orbitalgeschütz{$defflost[9]} 
    Leichtes Raumgeschütz{$defflost[10]} 
    Mittleres Raumgeschütz{$defflost[11]} 
    Schweres Raumgeschütz{$defflost[12]} 
    Abfangjäger{$defflost[13]} 
    Metallverluste{$ress[1][0]}{$ress[0][0]}
    Kristallverluste{$ress[1][1]}{$ress[0][1]}
    Insgesamt{$ress[1][2]}{$ress[0][2]}
    Metallexen geklaut:{$metallstolen} 
    Kristallexen geklaut:{$kristallstolen} 
    +


    +

    +
    + + + diff --git a/src/templates/takscreen_atter_add.html b/src/templates/takscreen_atter_add.html new file mode 100644 index 0000000..87f5628 --- /dev/null +++ b/src/templates/takscreen_atter_add.html @@ -0,0 +1,317 @@ +
    + + + + + + + + {if $errors} + + + + + + + {/if} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + +
    Incoming melden

    + +
    {foreach from=$errors item=error}{$error}
    {/foreach}
    +
    + + + +
    Opfer Koordinaten:
    + + +
    + : +
    + + + +
    Angreifer
    + + + +
    Koordinaten
    + + + +
    + : + +
    + + + +
    Ankunftszeit (ETA)
    + + + +
    +
    + + + +
    Flotte
    + + + +
    +
    + + + +
    Angreiferflotte (optional)
    + + + +
    Jäger
    + + + +
    +
    + + + +
    Bomber
    + + + +
    +
    + + + +
    Fregatten
    + + + +
    +
    + + + +
    Zerstörer
    + + + +
    +
    + + + +
    Kreuzer
    + + + +
    +
    + + + +
    Schlachter
    + + + +
    +
    + + + +
    Träger
    + + + +
    +
    + + + +
    Kleptoren
    + + + +
    +
    + + + +
    Cancris
    + + + +
    +
    + + + +
    Scangenauigkeit (%)
    + + + +
    +
    + + + +
    verwendete SVs
    + + + +
    +
    + + + + +
    + Hilfe
    + + + +
    + +


    +

    +
    diff --git a/src/templates/takscreen_deffer_add.html b/src/templates/takscreen_deffer_add.html new file mode 100644 index 0000000..6e47243 --- /dev/null +++ b/src/templates/takscreen_deffer_add.html @@ -0,0 +1,171 @@ +
    + + + + + + + + {if $errors} + + + + + + + {/if} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + +
    Deffer hinzufügen
    +
    + + + +
    {foreach from=$errors item=error}{$error}
    + {/foreach}
    + + + + +
    Zielkoordinaten:
    + + + + +
    + : + +
    + + + + +
    Defferkoordinaten
    +
    + + + + +
    + : + +
    +
    + + + +
    Ankunftszeit (ETA)
    + + + +
    +
    + + +
    + Zeit im Orbit: +
    +
    +
    + +
    +
    +
    + Verteidigung: +
    +
    +
    + +
    +
    + + + + +
    Flotte
    + + + + +
    + + + + + +
    + Hilfe
    + + + + +
    + +


    +

    +
    diff --git a/src/templates/takscreen_deffer_extern.html b/src/templates/takscreen_deffer_extern.html new file mode 100644 index 0000000..44d1802 --- /dev/null +++ b/src/templates/takscreen_deffer_extern.html @@ -0,0 +1,311 @@ +
    + + + + + + + + {if $errors} + + + + + + + {/if} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + +
    externen Deffer melden

    + + + +
    {foreach from=$errors item=error}{$error}
    + {/foreach}
    + + + +
    Opfer Koordinaten:
    + + + +
    + : + +
    + + + +
    Deffer
    + + + +
    Koordinaten
    + + + +
    + : + +
    + + + +
    Nickname
    + + + +
    + + + +
    Ankunftszeit (ETA)
    + + + +
    +
    + Ticks im Orbit: +
    +
    +
    + +
    +
    + + + +
    Defferflotte
    + + + +
    Flotte
    + + + +
    + + + +
    Jäger
    + + + +
    + + + +
    Bomber
    + + + +
    + + + +
    Fregatten
    + + + +
    + + + +
    Zerstörer
    + + + +
    + + + +
    Kreuzer
    + + + +
    + + + +
    Schlachter
    + + + +
    + + + +
    Träger
    + + + +
    + + + +
    Kleptoren
    + + + +
    + + + +
    Cancris
    + + + +
    + + + + +
    + Hilfe
    + + + +
    + +


    +

    +
    diff --git a/src/templates/takscreen_deffer_intern.html b/src/templates/takscreen_deffer_intern.html new file mode 100644 index 0000000..cc603fc --- /dev/null +++ b/src/templates/takscreen_deffer_intern.html @@ -0,0 +1,173 @@ +
    + + + + + + + + + {if $errors} + + + + + + + {/if} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + +
    internen Deffer melden

    + + + +
    {foreach from=$errors item=error}{$error}
    + {/foreach}
    + + + + +
    Deffer Koordinaten:
    + + + + +
    + : + +
    + + + + +
    Opfer Koordinaten
    +
    + + + + +
    + : + +
    +
    + + + +
    Ankunftszeit (ETA)
    + + + +
    +
    +
    + Verteidigung: +
    +
    +
    + +
    +
    +
    + Ticks im Orbit: +
    +
    +
    + +
    +
    + + + + +
    Flotte
    + + + + +
    + + + + + +
    + Hilfe
    + + + + +
    + +


    +

    +
    diff --git a/src/templates/takscreen_deffer_update.html b/src/templates/takscreen_deffer_update.html new file mode 100644 index 0000000..506b705 --- /dev/null +++ b/src/templates/takscreen_deffer_update.html @@ -0,0 +1,254 @@ +
    + + + + + + + + + + {if $errors} + + + + + + + {/if} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + +
    externen Deffer ({$deffer.egala}:{$deffer.epos}) {$deffer.enickname} + bei {$deffer.ogala}:{$deffer.opos} updaten

    + + + +
    {foreach from=$errors item=error}{$error}
    + {/foreach}
    + + + +
    Verteidigerflotte
    +
    + + + +
    Flotte
    + + + +
    + + + +
    ETA
    + + + +
    (min) oder (hh:mm)
    +
    + Ticks im Orbit: +
    +
    +
    + +
    +
    + + + +
    Jäger
    + + + +
    + + + +
    Bomber
    + + + +
    + + + +
    Fregatten
    + + + +
    + + + +
    Zerstörer
    + + + +
    + + + +
    Kreuzer
    + + + +
    + + + +
    Schlachter
    + + + +
    + + + +
    Träger
    + + + +
    + + + +
    Kleptoren
    + + + +
    + + + +
    Cancris
    + + + +
    + + + + +
    + Hilfe
    + + + +
    + +


    +

    +
    diff --git a/src/templates/takscreen_fleetstatus.html b/src/templates/takscreen_fleetstatus.html new file mode 100644 index 0000000..0fc3e8a --- /dev/null +++ b/src/templates/takscreen_fleetstatus.html @@ -0,0 +1,202 @@ +{strip} + + + + + + + + + {if $message} + + + + {/if} + {if $errors} + + + + {/if} + {if $page == 1} + + + + {elseif $page == 2} + + + + {elseif $page == 3} + + + + {elseif $page == 4} + + + + {/if} + + + +
    + + + + + + + +
    Flottendaten von {$status.gala}:{$status.pos} Flotte {$status.fleetnum|default:"unbekannt"}
    {$pages}
    +
    + ZurückTaktikScansManuellParser +
    + {$message} +
    + {foreach from=$errors item=error} + {$error} + {/foreach} +
    +
    + {foreach from=$form_params item=item} + + {/foreach} + + + + + + + + + + + + + + + + + +
    + Flotte: + + +
    + ETA: + + +
    + Zeit im Orbit: + + +
      + + + +
    +
    +
    + {if $scan.hasmili || $scan.hasunit} +
    + {foreach from=$form_params item=item} + + {/foreach} + + {if $scan.hasmili} + + + + + {/if} + {if $scan.hasunit} + + + + + {/if} + + + + +
    + Militärscan laden

    + +
    +
    + +
    + {include file="scan_mili.html"} +
    + Einheitenscan laden

    + +
    + {include file="scan_unit.html"} +
      + + + +
    +
    + {else} + Keine Militär oder Einheitenscans zu {$status.gala}:{$status.pos} gefunden. + {/if} +
    +
    + {foreach from=$form_params item=item} + + {/foreach} + + {foreach from=$fleetupdateform item=item} + + + + + {/foreach} + + + + +
    + {$item.title} + + +
      + +
    +
    +
    +
    + {foreach from=$form_params item=item} + + {/foreach} + + + + + + + + + + +
    + IRC Zeile(n): + + + + Übernimmt Flottenparserausgabe des Wurstscriptes als Flottendaten, einfach die IRC Zeilen kopieren. +
      + +
    +
    +
    +{/strip} diff --git a/src/templates/takscreen_inc_add.html b/src/templates/takscreen_inc_add.html new file mode 100644 index 0000000..0c52031 --- /dev/null +++ b/src/templates/takscreen_inc_add.html @@ -0,0 +1,317 @@ +
    + + + + + + + + {if $errors} + + + + + + + {/if} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + +
    Incoming melden

    + +
    {foreach from=$errors item=error}{$error}
    {/foreach}
    +
    + + + +
    Opfer Koordinaten:
    + + +
    + : +
    + + + +
    Angreifer
    + + + +
    Koordinaten
    + + + +
    + : + +
    + + + +
    Ankunftszeit (ETA)
    + + + +
    +
    + + + +
    Angreiferflotte (optional)
    + + + +
    Flotte
    + + + +
    +
    + + + +
    Jäger
    + + + +
    +
    + + + +
    Bomber
    + + + +
    +
    + + + +
    Fregatten
    + + + +
    +
    + + + +
    Zerstörer
    + + + +
    +
    + + + +
    Kreuzer
    + + + +
    +
    + + + +
    Schlachter
    + + + +
    +
    + + + +
    Träger
    + + + +
    +
    + + + +
    Kleptoren
    + + + +
    +
    + + + +
    Cancris
    + + + +
    +
    + + + +
    Scangenauigkeit (%)
    + + + +
    +
    + + + +
    verwendete SVs
    + + + +
    +
    + + + + +
    + Hilfe
    + + + +
    + +


    +

    +
    diff --git a/src/templates/takscreen_inc_details.html b/src/templates/takscreen_inc_details.html new file mode 100644 index 0000000..bb712d7 --- /dev/null +++ b/src/templates/takscreen_inc_details.html @@ -0,0 +1,341 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + +
    Incoming auf [{$inc.tag}] {$inc.nick} ({$inc.gala}:{$inc.pos}) {if + $inc.canedit}{/if} + {if $inc.safe}[safe]{/if}
    +
    +
    + + + + + +
       + Hier deffen + {if $inc.cansetsafe} + {if $inc.safe} + • Unsafe  + {else} + • Safe  + {/if} + {/if} + • Atter recallen +
    +
    + + + + + + + + + + + + + +
    + Flotte des Angegriffenen letztes update: {$inc.fleetupdate} +
    + + + + + + + + + + + + + + {foreach from=$userfleet item=fleet} + + + + + + + + + + + + + {/foreach} +
    FlotteCancrisFreggsZerrisKreuzerSchlachterTrägerJägerBomberCleps
    {$fleet.name}{$fleet.cancris}{$fleet.fregatten}{$fleet.zerstoerer}{$fleet.kreuzer}{$fleet.schlachter}{$fleet.traeger}{$fleet.jaeger}{$fleet.bomber}{$fleet.kleptoren}
    +
    Orbitalverteidigung letztes update: {$inc.deffupdate}
    + + + + + + + + + + + + + + + +
    HorusRubiumPulsarCoonCenturion
    {$inc.horus}{$inc.rubium}{$inc.pulsar}{$inc.coon}{$inc.centurion}
    +
    +
    + ausgewählte Flotten: {if $inc.atter_filter || $inc.deffer_filter} • Filter + löschen{/if} +
    + + + + + {if $atterlist} + + + + + + + + + + + + + + + + + + + {foreach from=$atterlist item=fleet} + {if !$fleet.hide} + + + + + + + + + + + + + + + + + + + {/if} + {/foreach} + {else} + + + + {/if} + + + + {if $inc.deffer} + {if $defferlist} + + + + + + + + + + + + + + + + + + + {foreach from=$defferlist item=fleet} + {if !$fleet.hide} + + + + + + + + + + + + + + + + + + + {/if} + {/foreach} + {else} + + + + {/if} + {else} + + + + {/if} +
    + Angreifer{if $inc.atter_filter} Filter aktiv{/if} +
     KoordsNickFlotteETACancrisFreggsZerrisKreuzerSchlachterTrägerJägerBomberCleps  
    {$fleet.gala}:{$fleet.pos}{$fleet.nick|default:" "}Flotte {$fleet.fleetnum}{$fleet.eta}{$fleet.cancris|default:"0"}{$fleet.fregatten|default:"0"}{$fleet.zerstoerer|default:"0"}{$fleet.kreuzer|default:"0"}{$fleet.schlachter|default:"0"}{$fleet.traeger|default:"0"}{$fleet.jaeger|default:"0"}{$fleet.bomber|default:"0"}{$fleet.kleptoren|default:"0"} + {if $fleet.canrecall} + + {else} +   + {/if} + + {if $fleet.canedit} + + {else} +   + {/if} +
    keine Angreifer im Filter
    + Verteidiger{if $inc.deffer_filter} Filter aktiv{/if} +
     KoordsNickFlotteETACancrisFreggsZerrisKreuzerSchlachterTrägerJägerBomberCleps  
    {$fleet.gala}:{$fleet.pos}{$fleet.nick|default:" "}Flotte {$fleet.fleetnum}{$fleet.eta}{$fleet.cancris|default:"0"}{$fleet.fregatten|default:"0"}{$fleet.zerstoerer|default:"0"}{$fleet.kreuzer|default:"0"}{$fleet.schlachter|default:"0"}{$fleet.traeger|default:"0"}{$fleet.jaeger|default:"0"}{$fleet.bomber|default:"0"}{$fleet.kleptoren|default:"0"} + {if $fleet.canrecall} + + {else} +   + {/if} + + {if $fleet.canedit} + + {else} +   + {/if} +
    keine Verteidiger im Filter
    keine Verteidiger vorhanden
    +
    + + + + + + + + +
    + Gesamtübersicht +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
     CancrisFreggsZerrisKreuzerSchlachterTrägerJägerBomberCleps
    Angreifer{$attersum.cancris|default:"0"}{$attersum.fregatten|default:"0"}{$attersum.zerstoerer|default:"0"}{$attersum.kreuzer|default:"0"}{$attersum.schlachter|default:"0"}{$attersum.traeger|default:"0"}{$attersum.jaeger|default:"0"}{$attersum.bomber|default:"0"}{$attersum.kleptoren|default:"0"}
    Verteidiger{$deffersum.cancris|default:0}{$deffersum.fregatten|default:0}{$deffersum.zerstoerer|default:0}{$deffersum.kreuzer|default:0}{$deffersum.schlachter|default:0}{$deffersum.traeger|default:0}{$deffersum.jaeger|default:0}{$deffersum.bomber|default:0}{$deffersum.kleptoren|default:0}
    +
    +
    +

    + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    +

    diff --git a/src/templates/takscreen_inc_details.html.bak b/src/templates/takscreen_inc_details.html.bak new file mode 100644 index 0000000..c7b7484 --- /dev/null +++ b/src/templates/takscreen_inc_details.html.bak @@ -0,0 +1,521 @@ + + + + + + + + + + + + + + {cycle print=false values="tbl_2,tbl_1"} {cycle print=false assign="class"} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + +
    Incoming auf ({$inc.ogala}:{$inc.opos}) {$inc.onick} {if + $inc.canupdateatter}{/if} + {if $inc.save}[safe]{/if}
    +
    + + + + + +
       Hier + deffen  {if $inc.cansetsave} {if $inc.save}   + {else}   + {/if} {/if} {if $inc.canrecallall}   + {/if}
    +
    + + + +
    Flotte des Angegriffenen letztes update: {$inc.fleetupdate}
    + + + + + + + + + + + + + + + + + + + + + + + + + + + {foreach from=$userfleet item=fleet} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {/foreach} +
    FlotteCancrisFreggsZerrisKreuzerSchlachterTrägerJägerBomberCleps
    {$fleet.name}{$fleet.cancris}{$fleet.fregatten}{$fleet.zerstoerer}{$fleet.kreuzer}{$fleet.schlachter}{$fleet.traeger}{$fleet.jaeger}{$fleet.bomber}{$fleet.kleptoren}
    +
    + + + + +
    Orbitalverteidigung letztes update: {$inc.deffupdate}
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    HorusRubiumPulsarCoonCenturion
    {$inc.horus}{$inc.rubium}{$inc.pulsar}{$inc.coon}{$inc.centurion}
    +
    + + + +
    Angreifer
    + + + + + + + + + + + + + + + + + + + + + + + {foreach from=$atterlist item=fleet} + + + + + + + + + + + + + + + + + + + + + + {/foreach} +
    SektorKommandantFlotteETACancrisFreggsZerrisKreuzerSchlachterTrägerJägerBomberClepsGenauigkeitSVs 
    {$fleet.igala}:{$fleet.ipos}{$fleet.inickname}Flotte {$fleet.fleetnum}{$fleet.eta}{$fleet.cancris}{$fleet.fregatten}{$fleet.zerstoerer}{$fleet.kreuzer}{$fleet.schlachter}{$fleet.traeger}{$fleet.jaeger}{$fleet.bomber}{$fleet.kleptoren}{$fleet.prec}%{$fleet.svs} + {if $fleet.canrecall} +   + {/if} +   + {if $fleet.hasmili} + Miliscan laden + {/if} +
    +
    + + + +
    Verteidiger
    {if $defferlist} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {foreach from=$defferlist item=fleet} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {/foreach} +
    SektorKommandantFlotteETACancrisFreggsZerrisKreuzerSchlachterTrägerJägerBomberCleps 
    {$fleet.gala}:{$fleet.pos} {$fleet.nick} Flotte {$fleet.fleetnum}{$fleet.eta}{$fleet.cancris}{$fleet.fregatten}{$fleet.zerstoerer}{$fleet.kreuzer}{$fleet.schlachter}{$fleet.traeger}{$fleet.jaeger}{$fleet.bomber}{$fleet.kleptoren} {if $fleet.canrecall}   + {/if} + {if $fleet.isextern} + + {/if} + {if $fleet.canupdatefleet} + + {/if} +
    + {else} + + + + + + +
    keine Verteidiger
    + {/if} +
    + + + +
    Gesamtübersicht
    + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
     CancrisFreggsZerrisKreuzerSchlachterTrägerJägerBomberCleps
    Angreifer{$attersum.cancris}{$attersum.fregatten}{$attersum.zerstoerer}{$attersum.kreuzer}{$attersum.schlachter}{$attersum.traeger}{$attersum.jaeger}{$attersum.bomber}{$attersum.kleptoren}
    Verteidiger{$deffersum.cancris|default:0}{$deffersum.fregatten|default:0}{$deffersum.zerstoerer|default:0}{$deffersum.kreuzer|default:0}{$deffersum.schlachter|default:0}{$deffersum.traeger|default:0}{$deffersum.jaeger|default:0}{$deffersum.bomber|default:0}{$deffersum.kleptoren|default:0}
    +
    +
    +

    + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    +

    \ No newline at end of file diff --git a/src/templates/takscreen_inc_update.html b/src/templates/takscreen_inc_update.html new file mode 100644 index 0000000..83a6479 --- /dev/null +++ b/src/templates/takscreen_inc_update.html @@ -0,0 +1,263 @@ +
    + + + + + + + + + + {if $errors} + + + + + + + {/if} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + +
    Atter ({$atter.igala}:{$atter.ipos}) {$atter.inickname} auf {$atter.ogala}:{$atter.opos} updaten

    + + + +
    {foreach from=$errors item=error}{$error}
    + {/foreach}
    + + + +
    Angreiferflotte
    + + + +
    Flotte
    + + + +
    + + + +
    ETA
    + + + +
    (min) oder (hh:mm)
    + + + +
    Jäger
    + + + +
    + + + +
    Bomber
    + + + +
    + + + +
    Fregatten
    + + + +
    + + + +
    Zerstörer
    + + + +
    + + + +
    Kreuzer
    + + + +
    + + + +
    Schlachter
    + + + +
    + + + +
    Träger
    + + + +
    + + + +
    Kleptoren
    + + + +
    + + + +
    Cancris
    + + + +
    + + + +
    Scangenauigkeit (%)
    + + + +
    + + + +
    verwendete SVs
    + + + +
    + + + + +
    + Hilfe
    + + + +
    + +


    +

    +
    diff --git a/src/templates/takscreen_index.html b/src/templates/takscreen_index.html new file mode 100644 index 0000000..2b5a92f --- /dev/null +++ b/src/templates/takscreen_index.html @@ -0,0 +1,180 @@ +{strip} + + + + + + + + + {cycle print=false values="color1,color2"} + {foreach from=$list item=inc} + {cycle print=false assign="class"} + + + + {foreachelse} + + + + {/foreach} + + + +
    + + + + + + + +
    Taktikschirm

    {$pages}
    +
    +
    + + + + + + + + +
    Koords + + Zeiten + + + Safe ausblenden + Undertime ausblenden + + + +
    +
    +
    + + + + + + + + + +
     {$inc.gala}:{$inc.pos}  [{$inc.tag}] {$inc.nick} {if + $inc.safe}[safe]{/if} + Hier deffen + {if $inc.safe} + • Unsafe  + {else} + • Safe  + {/if} + • Atter recallen +
    + + + + + + + + + +
    Angreifende Flotten:Verteidigende Flotten:
    + + {foreach from=$inc.atterlist item=atter} + + + + + + + + + {/foreach} +
    + {$atter.nick} ({$atter.gala}:{$atter.pos}) + + {if $atter.fleetnum}Flotte {$atter.fleetnum}{else} {/if} + + {if $atter.orbit} + (Im Orbit: {$atter.orbittime}) + {else} + {if $atter.arrival} + (ETA: {$atter.eta}) + {else} + ETA: n/a + {/if} + {/if} + + {if $atter.canrecall} + + {/if} + + + + {if $atter.prec < 100} + + {else} + + {/if} +
    +
    + + {foreach from=$inc.defferlist item=deffer} + + + + + + + + {foreachelse} + + + + {/foreach} +
    + {if $deffer.tag}[{$deffer.tag}] {/if}{$deffer.nick} ({$deffer.gala}:{$deffer.pos}){if $deffer.fleetnum} Flotte {$deffer.fleetnum}{/if} + + {if $deffer.orbit} + (Im Orbit: {$deffer.orbittime}) + {else} + {if $deffer.arrival} + (ETA: {$deffer.eta}) + {else} + ETA: n/a + {/if} + {/if} + + + + {if $deffer.canedit}{else} {/if} + + {if !$deffer.uid} + {if $deffer.prec < 100} + + {else} + + {/if} + {else} +   + {/if} +
    +  keine Verteidiger  +
    +
    +
    +
    Keine Incomings
    +{/strip} diff --git a/src/templates/takscreen_miliparser.html b/src/templates/takscreen_miliparser.html new file mode 100644 index 0000000..a807ad6 --- /dev/null +++ b/src/templates/takscreen_miliparser.html @@ -0,0 +1,68 @@ +
    + + + + + + + + {if $message} + + + + + + + {/if} + + + + + + + + + + + + + + + + + + + + +
    + + + +
    Miliscan parsen

    + + + +
    {$message}
    + + + +
    Scan:
    + + + +
    +
    + + + + +
    + Hilfe
    + + + +
    + +


    +

    +
    diff --git a/src/templates/takscreen_miliparser_step2.html b/src/templates/takscreen_miliparser_step2.html new file mode 100644 index 0000000..3ea7c9b --- /dev/null +++ b/src/templates/takscreen_miliparser_step2.html @@ -0,0 +1,181 @@ +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + {if $errors} + + + + + + + {/if} + {if $items.fleet1} + + + + + + + + {/if} + {if $items.fleet2} + + + + + + + + {/if} + + + + + + + + + + +
    + + + +
    Miliscan laden, Flotten zuweisen

    + + + + +
    Miliscan {$mili.nick} ({$mili.gala}:{$mili.pos}) {$mili.mili_prec}% +   Alter: {$mili.mili_scanage}
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + {foreach from=$mili.mili_fleets item=fleet} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {/foreach} +
    FlotteCancrisFreggsZerrisKreuzerSchlachterTrägerJägerBomberCleps
    {$fleet.type} {$fleet.dir}{$fleet.cancris}{$fleet.fregatten}{$fleet.zerstoerer}{$fleet.kreuzer}{$fleet.schlachter}{$fleet.traeger}{$fleet.jaeger}{$fleet.bomber}{$fleet.kleptoren}
    +
    + + {foreach from=$errors item=error} + {$error}
    + {/foreach} +
    +
    + + + +
    Flotte 1:
    + + + + +
    +
    +
    + + + +
    Flotte 2:
    + + + + +
    +
    +
    + + + + +
    + Hilfe
    + + + +
    + +


    +

    +
    diff --git a/src/templates/takscreen_parser_fleet.html b/src/templates/takscreen_parser_fleet.html new file mode 100644 index 0000000..d3a688c --- /dev/null +++ b/src/templates/takscreen_parser_fleet.html @@ -0,0 +1,107 @@ +
    + + + + + + + + {if $errors} + + + + + + + {/if} + {if $parse_errors} + + + + + + + {/if} + {if $parse_messages} + + + + + + + {/if} + + + + + + + + + + + + + + + + + + + + +
    + + + +
    Flotten/Deff parsen

    + + + +
    + {foreach from=$errors item=error} + {$error}
    + {/foreach} +
    + + + +
    + {foreach from=$parse_errors item=error} + {$error}
    + {/foreach} +
    + + + +
    + {foreach from=$parse_messages item=msg} + {$msg}
    + {/foreach} +
    + + + +
    Flottendaten:
    + + + + +
    + Klick auf die Flotte des Users im Takikschirm, Strg+A,Strg+Einfg, und ins Textfeld reinpasten. + Es können dabei beliebig viele Flotten geparst werden, einfach dranhängen. +
    + + + + +
    + Hilfe
    + + + +
    + +


    +

    +
    diff --git a/src/templates/takscreen_parser_takscreen.html b/src/templates/takscreen_parser_takscreen.html new file mode 100644 index 0000000..9af16ff --- /dev/null +++ b/src/templates/takscreen_parser_takscreen.html @@ -0,0 +1,159 @@ +
    + + + + + + + + + {if $errors} + + + + + + + {/if} + {if $parse_errors} + + + + + + + {/if} + {if $parse_messages} + + + + + + + {/if} + + + + + + + + + + + + + + + + + + + + + + {* + + + + + + + + *} + + + + + + + + + + + + + +
    + + + +
    Taktikscreen parsen

    + + + +
    + {foreach from=$errors item=error} + {$error}
    + {/foreach} +
    + + + +
    + {foreach from=$parse_errors item=error} + {$error}
    + {/foreach} +
    + + + +
    + {foreach from=$parse_messages item=msg} + {$msg}
    + {/foreach} +
    + + + +
    Taktikschirm:
    + + + + +
    + Rechtsklick auf den Taktikschirm,Quelltext anzeigen, + Alles markieren, ins Fenster reinkopieren, fertig
    +
    + Mozilla: This Frame -> View Frame Source
    + + + +
    Atter parsen:
    + + + +
    +
    + + + +
    Deffer parsen:
    + + + +
    +
    + + + +
    Flottenstatus der User parsen:
    + + + +
    +
    + + + + +
    + Hilfe
    + + + +
    + +


    +

    +
    diff --git a/src/templates/takscreen_parser_takscreen_step2.html b/src/templates/takscreen_parser_takscreen_step2.html new file mode 100644 index 0000000..72c1db5 --- /dev/null +++ b/src/templates/takscreen_parser_takscreen_step2.html @@ -0,0 +1,149 @@ +
    + + + + + + {foreach from=$userparse_list item=user} + + {/foreach} + + + + + {if $errors} + + + + + + + {/if} + {if $parse_errors} + + + + + + + {/if} + {if $parse_messages} + + + + + + + {/if} + {if $userparse_list} + + + + + + + {/if} + + + + + + + + + + + + + +
    + + + +
    Taktikscreen parsen

    + + + +
    + {foreach from=$errors item=error} + {$error}
    + {/foreach} +
    + + + +
    + {foreach from=$parse_errors item=error} + {$error}
    + {/foreach} +
    + + + +
    + {foreach from=$parse_messages item=msg} + {$msg}
    + {/foreach} +
    + + + + + + + {foreach from=$userparse_list item=user} + + + + + + {/foreach} +
    + Koords + + User + + Status +
    + {$user.gala}:{$user.pos} + + {$user.nick} + + + {foreach from=$user.form_data item=data} + + + + + {/foreach} +
    + Flotte {$data.fleet}: + + {if $data.do_selectbox} + + {else} + {$data.title}
    + {/if} + +
    +
    +
    + + + + +
    + Hilfe
    + + + +
    + +


    +

    +
    diff --git a/src/templates/user_add_form.html b/src/templates/user_add_form.html new file mode 100644 index 0000000..f43076f --- /dev/null +++ b/src/templates/user_add_form.html @@ -0,0 +1,212 @@ +
    + + + + + + + + {if $errors} + + + + + + + {/if} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + +
    Benutzer hinzufügen

    + + + + +
    {foreach from=$errors item=error}{$error}
    {/foreach}
    +
    + + + +
    GN Nickname
    + + + +
    +
    + + + +
    Login
    + + + +
    +
    + + + +
    Allianz
    + + + +
    + {if $rank < 2} + + {else} + {$ally} + {/if} +
    + + + +
    Galaxie
    + + + +
    {if $rank < 3} + + {else} + {$gala} + {/if} +
    + + + +
    Position
    + + + +
    +
    + + + +
    Gruppe
    + + + +
    + {if $changegroup} + + {else} + keine + {/if} +
    + + + +
    IRC Q-Auth
    + + + +
    + + +
    +
    + + + +
    Passwort
    + + + +
    +
    + + + + +
    + Hilfe
    + + + +
    + + +


    +

    +
    diff --git a/src/templates/user_changepwd_form.html b/src/templates/user_changepwd_form.html new file mode 100644 index 0000000..f6dcbe9 --- /dev/null +++ b/src/templates/user_changepwd_form.html @@ -0,0 +1,90 @@ +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + +
    Passwort ändern

    + {$forms.changepwd.message}
    + + + +
    altes Passwort
    + + + +
    + {$forms.changepwd.fields.oldpassword.error}
    + + + +
    neues Passwort
    + + + +
    + {$forms.changepwd.fields.password.error}
    + + + +
    neues Passwort wiederholen
    + + + +
    + {$forms.changepwd.fields.password2.error}
    + + + + +
    + Hilfe
    + + + +
    + +


    +

    +
    diff --git a/src/templates/user_details.html b/src/templates/user_details.html new file mode 100644 index 0000000..50c2c4e --- /dev/null +++ b/src/templates/user_details.html @@ -0,0 +1,101 @@ + + + + + + + + {if $forms.userdetails.usertitle} + + + + + + + + {/if} + + + + + + + + {if $forms.userdetails.koords} + + + + + + + + {/if} + {if $forms.userdetails.email} + + + + + + + + {/if} + {if $forms.userdetails.phone} + + + + + {/if} + + + + + + +
    + + + +
    Details von {$forms.userdetails.nickname}

    + +
    + + + +
    Titel
    + + + +
    {$forms.userdetails.usertitle}
    + + + +
    Allianz
    + + + +
    [{$forms.userdetails.allytag}] {$forms.userdetails.allyname}
    + + + +
    GN Koordinaten
    + + + +
    {$forms.userdetails.koords}
    + + + +
    Email
    + + + +
    {$forms.userdetails.email}
    + + + +
    Telefon
    + + + +
    {$forms.userdetails.phone}


    +

    diff --git a/src/templates/user_details_admin.html b/src/templates/user_details_admin.html new file mode 100644 index 0000000..8d7d3e5 --- /dev/null +++ b/src/templates/user_details_admin.html @@ -0,0 +1,145 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + +
    Details von {$user.nick}

    + + + + +
    + + {if $editlink} + + {/if} + {if $deletelink} + + {/if} +
    +
    + + + +
    Nickname
    + + + + +
    {$user.nick}
    + + + +
    Allianz
    + + + + +
    {$user.name} ({$user.tag})
    + + + +
    GN Koordinaten
    + + + +
    {$koords}
    + + + +
    Gruppe
    + + + +
    {$user.groupname|default:"keine"}
    + + + +
    Email
    + + + + +
    {$user.email|default:"keine"}
    + + + +
    Telefonnummer
    + + + + +
    {if $user.phone}{$user.phone}{else}fehlt{/if}
    + + + +
    Quakenet Auth
    + + + +
    {if $user.ircauth}{$user.ircauth}{else}fehlt{/if}


    +

    diff --git a/src/templates/user_edit_form.html b/src/templates/user_edit_form.html new file mode 100644 index 0000000..be524ca --- /dev/null +++ b/src/templates/user_edit_form.html @@ -0,0 +1,223 @@ +
    + + + + + + + + + {if $errors} + + + + + + + {/if} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + +
    Benutzerdaten von {$forms.useredit.username} ändern

    + + + + +
    {foreach from=$errors item=error}{$error}
    {/foreach}
    +
    + + + +
    GN Nickname
    + + + +
    +
    + + + +
    Login
    + + + +
    +
    + + + +
    Allianz
    + + + +
    + {if $rank < 2} + + {else} + {$ally} + {/if} +
    + + + +
    Galaxie
    + + + +
    + {if $rank < 3} + + {else} + {$gala} + {/if} +
    + + + +
    Position
    + + + +
    +
    + + + +
    Gruppe
    + + + +
    + {if $changegroup} + + {else} + {$group|default:"keine"} + {/if} +
    + + + +
    IRC Q-Auth
    + + + +
    + + +
    +
    + + + +
    Neues Passwort setzen (optional)
    + + + +
    Passwort:
    + + + +
    +
    + + + + +
    + Hilfe
    + + + +
    + +


    +

    +
    diff --git a/src/templates/user_fleets.html b/src/templates/user_fleets.html new file mode 100644 index 0000000..ff82d99 --- /dev/null +++ b/src/templates/user_fleets.html @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + {cycle print=false values="tbl_2,tbl_1"} + {section name=list loop=$fleetlist} + {cycle print=false assign="class"} + + + + + + + {/section} + + + + + + +
    + + + + + + + +
    Flottenübersicht

    {$forms.fleetlist.pages}
    +
    + + + + + + +
    Name + + Koords + + letztes Flottenupdate  + +
    +
    + + + + + + +
    {$fleetlist[list].nick} ({$fleetlist[list].gala}:{$fleetlist[list].pos}) + {if $fleetlist[list].fleettime} + Kleptoren: {$fleetlist[list].kleptoren} + Cancris: {$fleetlist[list].cancris} Fregatten: + {$fleetlist[list].fregatten}
    + Zerstörer: {$fleetlist[list].zerstoerer} + Kreuzer: {$fleetlist[list].kreuzer} Träger: + {$fleetlist[list].traeger}
    + Jäger: {$fleetlist[list].jaeger} Bomber: + {$fleetlist[list].bomber} Schlachter: + {$fleetlist[list].schlachter}
    + letztes Update: {$fleetlist[list].fleetdate} , + {$fleetlist[list].fleettime} Uhr + {else} + keine Flotte angegeben {/if}
    + Flotte updaten +
    {if $fleetlist[list].fleettime}{else} {/if}
    +
    + + + + +
    +
    {$forms.fleetlist.pages}
    +
    +

    +
    diff --git a/src/templates/user_fleetstatus.html b/src/templates/user_fleetstatus.html new file mode 100644 index 0000000..3c376aa --- /dev/null +++ b/src/templates/user_fleetstatus.html @@ -0,0 +1,154 @@ +
    + + + + + + + + + + + + + {if $errors} + + + + + + + {/if} + + + + + {if $items.status.value == 1 || $items.status.value == 2} + + + + + + + + {/if} + {if $items.status.value > 0} + + + + + + + + {/if} + {if $items.status.value == 2} + + + + + + + + {/if} + {if $items.status.value == 1 || $items.status.value == 2 } + + + + + + + + {/if} + + + + + + + + + + + + + +
    + + + + +
    Flottenstatus updaten

    +
    + + +
    {foreach from=$errors item=error}{$error}
    {/foreach}
    +
    +
    + Flottenstatus: +
    +
    +
    + +
    +
    +
    + Koords (optional): +
    +
    +
    + +
    +
    +
    + Flugzeit (ETA): +
    +
    +
    + +
    +
    +
    + Verteidigung: +
    +
    +
    + +
    +
    +
    + Zeit im Orbit: +
    +
    +
    + +
    +
    + + + + + +
    + Hilfe +
    +
    + + + + +
    + + +
    +


    +

    +
    +
    diff --git a/src/templates/user_fleetupdate.html b/src/templates/user_fleetupdate.html new file mode 100644 index 0000000..83c691a --- /dev/null +++ b/src/templates/user_fleetupdate.html @@ -0,0 +1,226 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + +
    Flotte von {$user.nick} ({$user.gala}:{$user.pos})
    +
    +
    +
    + Deff/Flotte + parsen • + Flotte + eingeben • + Verteidigung + eingeben
    + + + + + +
    Flotte
    letztes Update: {if $fleettime}{$fleetdate}, + {$fleettime} Uhr{else}unbekannt{/if}
    +
    + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + {foreach from=$fleets item=fleet} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {/foreach} +
    FlotteCancrisFreggsZerrisKreuzerSchlachterTrägerJägerBomberCleps
    {$fleet.dir}{$fleet.cancris}{$fleet.fregatten}{$fleet.zerstoerer}{$fleet.kreuzer}{$fleet.schlachter}{$fleet.traeger}{$fleet.jaeger}{$fleet.bomber}{$fleet.kleptoren}
    +
    + +
    + + + + + +
    Orbitalverteidigung
    letztes Update: {if $defftime}{$deffdate}, {$defftime} + Uhr{else}unbekannt{/if}
    +
    + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    HorusRubiumPulsarCoonCenturion
    {$deff.horus}{$deff.rubium}{$deff.pulsar}{$deff.coon}{$deff.centurion}
    +
    +
    + + + + +
    Flottenstatus
    +
    + + + + + +
    + + + + + +
    + Flotte 1:
    + {$fleets[1].dir}
    + {if $fleets[1].eta}{$fleets[1].eta}
    + {if $fleets[1].status == 1 && !$fleets[1].return_flight} + Angriffszeit: {$fleets[1].orbit}
    + {/if} + {if $fleets[1].status == 2 && !$fleets[1].return_flight} + Deffzeit: {$fleets[1].orbit}
    + {/if} + {/if} +
    + Flotte 2:
    + {$fleets[2].dir}
    + {if $fleets[2].eta}{$fleets[2].eta}
    + {if $fleets[2].status == 1 && !$fleets[2].return_flight} + Angriffszeit: {$fleets[2].orbit}
    + {/if} + {if $fleets[2].status == 2 && !$fleets[2].return_flight} + Deffzeit: {$fleets[2].orbit}
    + {/if} + {/if} +
    +
    + Flotte 1
    + Flotte 2 +
    +
    +


    +

    +
    \ No newline at end of file diff --git a/src/templates/user_fleetupdate_form.html b/src/templates/user_fleetupdate_form.html new file mode 100644 index 0000000..fbe8045 --- /dev/null +++ b/src/templates/user_fleetupdate_form.html @@ -0,0 +1,221 @@ +
    + + + + + + + + + + + + + + + + + + + + {if $errors} + + + + + + + {/if} + + + + + + + + + + + + + + + + + +
    + + + + +
    Flotte updaten

    +
    + + + + +
    Flotte
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    FlotteCancrisFreggsZerrisKreuzerSchlachterTrägerJägerBomberCleps
    Im Orbit{$fleet0.cancris}{$fleet0.fregatten}{$fleet0.zerstoerer}{$fleet0.kreuzer}{$fleet0.schlachter}{$fleet0.traeger}{$fleet0.jaeger}{$fleet0.bomber}{$fleet0.kleptoren}
    {$fleet1.cancris}{$fleet1.fregatten}{$fleet1.zerstoerer}{$fleet1.kreuzer}{$fleet1.schlachter}{$fleet1.traeger}{$fleet1.jaeger}{$fleet1.bomber}{$fleet1.kleptoren}
    {$fleet2.cancris}{$fleet2.fregatten}{$fleet2.zerstoerer}{$fleet2.kreuzer}{$fleet2.schlachter}{$fleet2.traeger}{$fleet2.jaeger}{$fleet2.bomber}{$fleet2.kleptoren}
    +
    + +
    {foreach from=$errors item=error}{$error}
    {/foreach}
    +
    + + + + +
    Flotte:
    +
    + + + + + +
    +

    Ihr geht in euren Takscreen, klickt auf eure Flotte und markiert + die Daten von "Jäger" bis zur 2ten Flotte Schutzschiffe.
    + Beispiel:
    + Jäger 0 0 100 .......
    + .
    + .
    + Schutzschiffe: 1000 0 0
    +

    +
    +
    + + + + + +
    + Hilfe +
    +
    + + + + +
    + +
    +


    +

    +
    +
    diff --git a/src/templates/user_fleetupdate_manuell.html b/src/templates/user_fleetupdate_manuell.html new file mode 100644 index 0000000..9c8b659 --- /dev/null +++ b/src/templates/user_fleetupdate_manuell.html @@ -0,0 +1,131 @@ +
    + + + + + + + + + + + + {if $errors} + + + + + + + {/if} + + + + + + + + + + + + + + + + +
    + + + + +
    Flotte updaten

    +
    + + +
    {foreach from=$errors item=error}{$error}
    {/foreach}
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      OrbitFlotte 1Flotte 2
    Jäger:
    Bomber:
    Fregatte:
    Zerstörer:
    Kreuzer:
    Schlachtschiff:
    Trägerschiff:
    Kaperschiff:
    Schutzschiff:
    +
    + + + + + +
    + Hilfe +
    +
    + + + + +
    + + +
    +


    +

    +
    +
    diff --git a/src/templates/user_fleetupdate_parser.html b/src/templates/user_fleetupdate_parser.html new file mode 100644 index 0000000..a864cc8 --- /dev/null +++ b/src/templates/user_fleetupdate_parser.html @@ -0,0 +1,91 @@ +
    + + + + + + + + + + + + {if $errors} + + + + + + + {/if} + + + + + + + + + + + + + + + + + +
    + + + + +
    Flotte/Verteidung updaten
    +
    +
    + + +
    {foreach from=$errors item=error}{$error}
    {/foreach}
    +
    + + + + +
    Text:
    +
    + + + + + +
    +

    Folgender Text wird erkannt:

    +
      +
    • Flottenbewegungansicht
    • +
    • Verteidigungansicht
    • +
    • Taktikschirmansicht der Flottendaten
    • +
    + Jeweils mit strg+a markieren und einfügen! +
    +
    + + + + + +
    + Hilfe +
    +
    + + + + +
    + + +
    +


    +

    +
    +
    diff --git a/src/templates/user_list.html b/src/templates/user_list.html new file mode 100644 index 0000000..2062175 --- /dev/null +++ b/src/templates/user_list.html @@ -0,0 +1,96 @@ + + + + + + + + + + + + + + + + {cycle print=false values="tbl_2,tbl_1"} + {section name=list loop=$userlist} + {cycle print=false assign="class"} + + + + + + + {sectionelse} + + + + + + + {/section} + + + + + + +
    + + + + + + + + +
    Benutzerliste

    {$forms.userlist.pages}
    +
    + + + + + + + + +
      + Name + + Koords + + Gruppe + +  
    +
    + + + + + + + + +
    [{$userlist[list].tag}] + {$userlist[list].nick} + {$userlist[list].gala}:{$userlist[list].pos} + {$userlist[list].groupname|default:"keine"} + +
    +
    + + + + +
    Keine Benutzer gefunden
    +
    + + + + +
    +
    {$forms.userlist.pages}
    +
    +

    +
    diff --git a/src/templates/user_list_form.html b/src/templates/user_list_form.html new file mode 100644 index 0000000..6ab1815 --- /dev/null +++ b/src/templates/user_list_form.html @@ -0,0 +1,134 @@ +
    + + + + + + + + + {if $errors} + + + + + + + {/if} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + +
    Benutzer suchen

    + + + + +
    {foreach from=$errors item=error}{$error}
    {/foreach}
    +
    + + + +
    Nickname
    + + + +
    +
    + + + +
    Allianz
    + + + +
    + {if $rank1} + + {else} + {$ally} + {/if} +
    + + + +
    Galaxie
    + + + +
    +
    + + + +
    Gruppe
    + + + +
    + + + + +
    + Hilfe
    + + + +
    +


    +

    +
    diff --git a/src/templates/user_orbitalupdate_manuell.html b/src/templates/user_orbitalupdate_manuell.html new file mode 100644 index 0000000..7062b16 --- /dev/null +++ b/src/templates/user_orbitalupdate_manuell.html @@ -0,0 +1,91 @@ +
    + + + + + + + + + + + + {if $errors} + + + + + + + {/if} + + + + + + + + + + + + + + + + +
    + + + + +
    Orbitalverteidigung updaten

    +
    + + +
    {foreach from=$errors item=error}{$error}
    {/foreach}
    +
    + + + + + + + + + + + + + + + + + + + + + +
    Leichtes Orbitalgeschütz "Rubium":
    Leichtes Raumgeschütz "Pulsar":
    Mittleres Raumgeschütz "Coon":
    Schweres Raumgeschütz "Centurion":
    Abfangjäger "Horus":
    +
    + + + + + +
    + Hilfe +
    +
    + + + + +
    + + +
    +


    +

    +
    +
    diff --git a/src/templates/user_orbitalupdate_parser.html b/src/templates/user_orbitalupdate_parser.html new file mode 100644 index 0000000..29d4cab --- /dev/null +++ b/src/templates/user_orbitalupdate_parser.html @@ -0,0 +1,86 @@ +
    + + + + + + + + + + + + {if $errors} + + + + + + + {/if} + + + + + + + + + + + + + + + + + +
    + + + + +
    Orbitalverteidigung updaten

    +
    + + +
    {foreach from=$errors item=error}{$error}
    {/foreach}
    +
    + + + + +
    Verteidigung:
    +
    + + + + + +
    +

    Ihr geht in euren Takscreen, klickt auf eure Flotte und markiert + die Daten von Leichtes Orbitalgeschütz "Rubium": bis hin zu dem Wert von den Abfangjägern.
    +

    +
    +
    + + + + + +
    + Hilfe +
    +
    + + + + +
    + + +
    +


    +

    +
    +
    diff --git a/src/templates/user_settings_form.html b/src/templates/user_settings_form.html new file mode 100644 index 0000000..59c894b --- /dev/null +++ b/src/templates/user_settings_form.html @@ -0,0 +1,203 @@ +
    + + + + + + + + + {if $errors} + + + + + + + {/if} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + +
    Benutzerdaten ändern

    + +
    {foreach from=$errors item=error}{$error}
    {/foreach}
    +
    + + + +
    Login
    + + + +
    +
    + + + +
    GN Nickname
    + + + +
    +
    + + + +
    Email
    + + + +
    +
    + + + +
    Email sichtbar ?
    + + + +
    + Ja + + Nein
    + + + +
    Telefonnummer
    + + + +
    +
    + + + +
    Scantyp
    + + + +
    + Geschütz/Nachrichten + + Einheiten/Militär
    + + + +
    Scanverstärker
    + + + +
    +
    + + + +
    Zeitanzeige:
    + + + +
    min HH:mm +
    + + + +
    Zweite Flotte:
    +
    + + + +
    offensiv deffensiv nicht gebaut +
    +
    + + + + +
    + Hilfe
    + + + +
    + +


    +

    +
    diff --git a/src/templates/user_stats.html b/src/templates/user_stats.html new file mode 100644 index 0000000..ae1edf2 --- /dev/null +++ b/src/templates/user_stats.html @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + {cycle print=false values="tbl_2,tbl_1"} + {section name=list loop=$userlist} + {cycle print=false assign="class"} + + + + + + + {sectionelse} + + + + + + + {/section} + + + + + + +
    + + + + + + + + +
    Benutzerstatistik

    {$forms.userlist.pages}
    +
    + + + + + + +
    Name + + Koords + + letzter Login  + +
    +
    + + + + + + +
    {$userlist[list].nick} + {$userlist[list].gala}:{$userlist[list].pos} + {if $userlist[list].loggedin}{$userlist[list].date} {$userlist[list].time}{else}noch nie{/if} +
    +
    + + + + +
    Keine Benutzer gefunden
    +
    + + + + +
    +
    {$forms.userlist.pages}
    +
    +

    +
    diff --git a/src/templates/userfleets_index.html b/src/templates/userfleets_index.html new file mode 100644 index 0000000..44935a5 --- /dev/null +++ b/src/templates/userfleets_index.html @@ -0,0 +1,112 @@ +{strip} + + + + + + + + + + + + + + + + + +
    + Flottenpflege

    +
    +
    + + + + + + + + +
    + Allianz: {$ally.name} + + Galaxie: + +
    +
    +
    + + {foreach from=$list item=user} + + + + {/foreach} +
    + + + + + + + + + + + + + + + + + + + {foreach from=$user.fleets item=fleet} + + + + + + + + + + + + + + + {/foreach} +
    + + + + + +
    + ({$user.gala}:{$user.pos}) {$user.nick}    + {if $user.fleettype == 1} + [zweite Flotte offensiv] + {elseif $user.fleettype == 2} + [zweite Flotte deffensiv] + {/if} + + letztes update: + {if $user.fleettime} + {$user.fleetdate}, {$user.fleettime} Uhr + {else} + noch nie + {/if} +    Bearbeiten +
    +
    FlotteCancrisFreggsZerrisKreuzerSchlachterTrägerJägerBomberClepsIRC CopyIRC Popup
    {$fleet.dir}{$fleet.cancris}{$fleet.fregatten}{$fleet.zerstoerer}{$fleet.kreuzer}{$fleet.schlachter}{$fleet.traeger}{$fleet.jaeger}{$fleet.bomber}{$fleet.kleptoren}{$fleet.name}{$fleet.name}
    +
    +

    +
    +{/strip} \ No newline at end of file diff --git a/src/templates/userfleets_update.html b/src/templates/userfleets_update.html new file mode 100644 index 0000000..022810f --- /dev/null +++ b/src/templates/userfleets_update.html @@ -0,0 +1,223 @@ +
    + + + + + + + + + + + + + + + + + + + + + {if $errors} + + + + + + + {/if} + + + + + + + + + + + + + + + + + +
    + + + + +
    Flotte updaten

    +
    + + + + + +
    Flotte von [{$user.tag}] {$user.nick} ({$user.gala}:{$user.pos})letztes update: {if $user.fleettime}{$user.fleetdate},{$user.fleettime}{else}noch nie{/if}
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    FlotteCancrisFreggsZerrisKreuzerSchlachterTrägerJägerBomberCleps
    Im Orbit{$fleet0.cancris}{$fleet0.fregatten}{$fleet0.zerstoerer}{$fleet0.kreuzer}{$fleet0.schlachter}{$fleet0.traeger}{$fleet0.jaeger}{$fleet0.bomber}{$fleet0.kleptoren}
    {$fleet1.cancris}{$fleet1.fregatten}{$fleet1.zerstoerer}{$fleet1.kreuzer}{$fleet1.schlachter}{$fleet1.traeger}{$fleet1.jaeger}{$fleet1.bomber}{$fleet1.kleptoren}
    {$fleet2.cancris}{$fleet2.fregatten}{$fleet2.zerstoerer}{$fleet2.kreuzer}{$fleet2.schlachter}{$fleet2.traeger}{$fleet2.jaeger}{$fleet2.bomber}{$fleet2.kleptoren}
    +
    + +
    {foreach from=$errors item=error}{$error}
    {/foreach}
    +
    + + + + +
    Flotte:
    +
    + + + + + +
    +

    Ihr geht in euren Takscreen, klickt auf eure Flotte und markiert + die Daten von "Jäger" bis zur 2ten Flotte Schutzschiffe.
    + Beispiel:
    + Jäger 0 0 100 .......
    + .
    + .
    + Schutzschiffe: 1000 0 0
    +

    +
    +
    + + + + + +
    + Hilfe +
    +
    + + + + +
    + +
    +


    +

    +
    +
    diff --git a/src/user.php b/src/user.php new file mode 100644 index 0000000..6aac66b --- /dev/null +++ b/src/user.php @@ -0,0 +1,6 @@ +run(); +?> \ No newline at end of file diff --git a/src/xmlrpc.php b/src/xmlrpc.php new file mode 100644 index 0000000..69ea660 --- /dev/null +++ b/src/xmlrpc.php @@ -0,0 +1,36 @@ + $XML_RPC_erruser+1,"msg" => "kein Scan vorhanden"); + + +$logger->debug("rpc request"); +$server = new XML_RPC_Server($xmlrpc_methods); + +$response = ob_get_contents(); +ob_end_clean(); +$logger->debug("xml response:\n".$response); +echo $response; +$logger->debug("rpc request done"); +?> \ No newline at end of file