<?php
/**
* @file modules_func.php -- Provides modes of install, uninstalling, and upgrading mods
* @Id $Id: modules_func.php,v 1.22 2004/07/21 19:13:35 jason Exp $
*
* Cynus - a web-based content manager
* Copyright (C) 2003 Brett and Jason Profitt
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
/*
Cynus
modules_func.php
Provides means of installing, uninstalling, and upgrading modules.
*/
/****************************************
*/
cynus_debug ("Loaded modules_func.php", 3);
function modules_list_modules() {
global $config;
$query="SELECT * FROM `$config[sql_prefix]modules` WHERE ( (`type` != 'pseudo') && (`type` != 'base') && (`type` != 'link') ) ORDER BY 'name' ASC";
cynus_debug ($query, 4);
$result = mysql_query ($query);
while ($mod_info = mysql_fetch_assoc ($result)) {
#$module_list[] = $mod_info;
$menu[] = "base:{$mod_info['friendly_name']} Module:admin.php?action=modules&op=view_module_info&mod_id={$mod_info['id']}:{$mod_info['location']}/{$mod_info['icon']}";
}
if (!is_array ($menu)) {
$menu[] = "base:No Modules Found Click here to download!:admin.php?action=modules&op=module_download_menu";
}
return cynus_menu($menu, 'mod_list');
}
function modules_view_module_info ($mod_id) {
global $config;
$query = "SELECT * FROM `$config[sql_prefix]modules` WHERE (`id` = '$mod_id')";
$mod_info = mysql_request ($query);
# modules that the current mod requires
# gotta check to see if it's empty....
if ($mod_info['deps']!="") {
$mod_deps = explode (',', $mod_info['deps']);
foreach ($mod_deps as $temp_info) {
if (strstr ($temp_info, '>=')) {
$print_text = 'greater than or equal to';
$split_str = '>=';
}
elseif (strstr ($temp_info, '<=')) {
$print_text = 'less than or equal to';
$split_str = '<=';
}
elseif (strstr ($temp_info, '==')) {
$print_text = 'equal to';
$split_str = '==';
}
list ($temp_name, $temp_version) = split ($split_str, $temp_info);
$mod_deps_print.= "$temp_name $print_text v$temp_version<br />";
}
}
else {
$mod_deps_print = "(none)";
}
#modules that require the current mod.
# regexing for the name that is followed by word boundries...
$query = "SELECT * FROM `$config[sql_prefix]modules` WHERE (`deps` REGEXP \"[[:<:]]{$mod_info['name']}[[:>:]]\")";
$result = mysql_query ($query);
while ($deps_temp = mysql_fetch_assoc ($result)){
#$dependent_mods[] = $deps_temp;
$dependent_mods_print.="{$deps_temp['name']} v{$deps_temp['version']}<br />";
}
if (!$dependent_mods_print) {
$dependent_mods_print = "(none)";
}
return<<<___eofh
<table cellspacing="0" cellpadding="7" border="0">
<tr>
<th colspan="2">
<img src="modules/{$mod_info['location']}/{$mod_info['icon']}"><br />
{$mod_info['name']}
</th>
</tr>
<tr>
<td>
Version:
</td>
<td>
{$mod_info['version']}
</td>
</tr>
<tr>
<td>
Author/Website:
</td>
<td>
<a href="mailto:{$mod_info['email']}">{$mod_info['author']}</a><br />
<a href="{$mod_info['site']}">{$mod_info['site']}</a>
</td>
</tr>
<tr>
<td>
Depends upon:
</td>
<td>
$mod_deps_print
</td>
</tr>
<tr>
<td>
Depended upon by:
</td>
<td>
$dependent_mods_print
</td>
</tr>
<tr>
<td>
Extra Information:
</td>
<td>
{$mod_info['info']}
</td>
</tr>
</table>
___eofh;
}
function modules_download_modules_menu () {
global $config;
include ("cynus_protocol/cp_client_class.php");
list ($maj_ver, $min_ver, $bug_ver) = explode ('.', $config['version']);
$cp_client = new cp_client;
$cp_client->client_maj_ver = $maj_ver;
$cp_client->client_min_ver = $min_ver;
$cp_client->client_bug_ver = $bug_ver;
$cp_client->client_url = $config['cynus_full_url'];
$cp_client->mod_server = $config['modules_url'];
if (!$modules = $cp_client->list_modules ()) {
cynus_error ('Problem parsing module list from server' . $cp_client->error);
}
#print_r ($modules);
#$modules = unserialize ($cp_client->reply['data']);
#$modules = unserialize ($modules);
foreach ($modules as $mod_info) {
$menu[] = "base:{$mod_info['friendly_name']} Module:admin.php?action=modules&op=view_remote_module_info&mod_id={$mod_info['id']}:{$config['modules_url']}/{$mod_info['icon']}";
}
return cynus_menu ($menu, 'external');
}
function modules_view_remote_module_info ($mod_id) {
global $config;
include ("cynus_protocol/cp_client_class.php");
list ($maj_ver, $min_ver, $bug_ver) = explode ('.', $config['version']);
$cp_client = new cp_client;
$cp_client->client_maj_ver = $maj_ver;
$cp_client->client_min_ver = $min_ver;
$cp_client->client_bug_ver = $bug_ver;
$cp_client->client_url = $config['cynus_full_url'];
$cp_client->mod_server = $config['modules_url'];
if (!$mod_info = $cp_client->view_remote_mod_info($mod_id)) {
cynus_error ($cp_client->error);
}
#$mod_info = unserialize ($mod_info);
# modules that the current mod requires
# gotta check to see if it's empty....
if ($mod_info['deps']!="") {
$mod_deps = explode (',', $mod_info['deps']);
foreach ($mod_deps as $temp_info) {
if (strstr ($temp_info, '>=')) {
$print_text = 'greater than or equal to';
$split_str = '>=';
}
elseif (strstr ($temp_info, '<=')) {
$print_text = 'less than or equal to';
$split_str = '<=';
}
elseif (strstr ($temp_info, '==')) {
$print_text = 'equal to';
$split_str = '==';
}
list ($temp_name, $temp_version) = split ($split_str, $temp_info);
# checking to see if we have the req modules or not
$query = "SELECT * FROM `$config[sql_prefix]modules` WHERE `name`='$temp_name'";
$check_mod_info = mysql_request ($query);
# blah..having to repeat code.
if ($split_str == '>=') {
if ($check_mod_info['version'] >= $temp_version) {
$check_message = "<font color=\"#00ff00\"><b>({$check_mod_info['version']} Installed)</b></font>";
}
else {
$uninstallable = 1;
if (!$check_mod_info['version']) {
$check_message = "<font color=\"#ff0000\"><b>(Not Installed)</b></font>";
}
else {
$check_message = "<font color=\"#ff0000\"><b>({$check_mod_info['version']})</b></font>";
}
}
}
elseif ($split_str == '<=') {
if ($check_mod_info['version'] >= $temp_version) {
$check_message = "<font color=\"#00ff00\"><b>({$check_mod_info['version']} Installed)</b></font>";
}
else {
$uninstallable = 1;
if (!$check_mod_info['version']) {
$check_message = "<font color=\"#ff0000\"><b>(Not Installed)</b></font>";
}
else {
$check_message = "<font color=\"#ff0000\"><b>({$check_mod_info['version']})</b></font>";
}
}
}
elseif ($split_str == '==') {
if ($check_mod_info['version'] >= $temp_version) {
$check_message = "<font color=\"#00ff00\"><b>({$check_mod_info['version']} Installed)</b></font>";
}
else {
$uninstallable = 1;
if (!$check_mod_info['version']) {
$check_message = "<font color=\"#ff0000\"><b>(Not Installed)</b></font>";
}
else {
$check_message = "<font color=\"#ff0000\"><b>({$check_mod_info['version']})</b></font>";
}
}
}
$mod_deps_print.= "$temp_name $split_str v$temp_version $check_message<br />";
}
}
else {
$mod_deps_print = "(none)";
}
if ($uninstallable == 1) {
$installable_message = "No";
}
else {
$installable_message = "Yes<br /><a href=\"{$_SERVER['PHP_SELF']}?action=modules&op=install_remote_module&mod_id={$mod_info['id']}\">Install Now</a>";
}
return<<<___eofh
<table cellspacing="0" cellpadding="7" border="0">
<tr>
<th colspan="2">
<img src="{$config['modules_url']}/{$mod_info['icon']}"><br />
{$mod_info['name']}
</th>
</tr>
<tr>
<td>
Version:
</td>
<td>
{$mod_info['version']}
</td>
</tr>
<tr>
<td>
Author/Website:
</td>
<td>
<a href="mailto:{$mod_info['email']}">{$mod_info['author']}</a><br />
<a href="{$mod_info['site']}">{$mod_info['site']}</a>
</td>
</tr>
<tr>
<td>
Depends upon:
</td>
<td>
$mod_deps_print
</td>
</tr>
<tr>
<td>
Extra Information:
</td>
<td>
{$mod_info['info']}
</td>
</tr>
<tr>
<td>
Installable:
</td>
<td>
$installable_message
</td>
</tr>
</table>
___eofh;
}
function modules_install_remote_module ($mod_id) {
global $config;
include ("cynus_protocol/cp_client_class.php");
list ($maj_ver, $min_ver, $bug_ver) = explode ('.', $config['version']);
$cp_client = new cp_client;
$cp_client->client_maj_ver = $maj_ver;
$cp_client->client_min_ver = $min_ver;
$cp_client->client_bug_ver = $bug_ver;
$cp_client->client_url = $config['cynus_full_url'];
$cp_client->mod_server = $config['modules_url'];
if (!$mod = $cp_client->get_remote_mod($mod_id)) {
cynus_error ($cp_client->error);
}
# assigning a temp filename
#$config['tmp_dir'] = "/tmp/";
$out_file = $config['tmp_dir'] . "/" . time() . '.tgz';
if (!$fp = @fopen( $out_file, "xb" )) {
cynus_debug ("Can't open $out_file in mode xb.", 2);
cynus_error ("Cannot open temporary file for write: $out_file");
}
if (!@fwrite($fp, base64_decode($mod))) {
cynus_debug ("Can't write to $out_file.", 2);
cynus_error ("Cannot write to temporary file: $out_file");
}
@fclose($fp);
/*
if (($v_list = $tar->listContent()) != 0)
for ($i=0; $i<sizeof($v_list); $i++)
{
echo "Filename :'".$v_list[$i][filename]."'<br>";
echo " .size :'".$v_list[$i][size]."'<br>";
echo " .mtime :'".$v_list[$i][mtime]."' (".date("l dS of F Y h:i:s A", $v_list[$i][mtime]).")<br>";
echo " .mode :'".$v_list[$i][mode]."'<br>";
echo " .uid :'".$v_list[$i][uid]."'<br>";
echo " .gid :'".$v_list[$i][gid]."'<br>";
echo " .typeflag :'".$v_list[$i][typeflag]."'<br>";
}
*/
#FIXME: make this cynus-specific.
# remove the ruddy PEAR calls.
include ("tar.php");
$tar = new Archive_Tar($out_file);
if ($tar->extract("modules/")) {
@unlink ($out_file);
}
else {
cynus_error ('There was a problem extracting the downloaded module.');
}
}
####################################
# WARNING!
# OLD CRAP BELOW!!!!!!!!!!!
function modules_download_list_menu () {
global $config;
#$modules_list = unserialize ($modules_list);
$modules_list = modules_download_list();
foreach ($modules_list as $mod_info) {
$extra_info = unserialize ($mod_info[info]);
#"mod_name:Text!!!:mod_link:icon_link"
#$menu_temp[] = "base:{$mod_info['name']}:test:test";
$content .= <<<___eofh
<table class="table-general">
<tr>
<td rowspan="6"><img src="{$mod_info['icon']}" border="0"></td>
</tr>
<tr>
<td>{$mod_info['name']} <br /> Version {$mod_info['version']}</td>
</tr>
<tr>
<td>Description:</td>
</tr>
<tr>
<td>{$extra_info['info']}</td>
</tr>
<tr>
<td>{$mod_info['deps']}</td>
</tr>
</table><br /> <br />
___eofh;
}
return $content;
}
function modules_download_list () {
global $config;
# Because PHP has no proxy support....grrrrr
if ($config['use_proxy']==1) {
$fp = fsockopen( "$config[proxy]", "$config[proxy_port]", $errno, $errstr, 5 );
if( !fputs( $fp, "GET http://$config[modules_url]/modules/modules.php?action=list_modules HTTP/1.0\r\nHost:10.5.1.140\r\n\r\n" ))
die( "unable to send get request" );
while( !feof( $fp )) {
$data = fgets ($fp,128);
$modules_list_temp.=$data;
}
fclose ($fp);
}
else {
# thanks php.net
$fp = fopen ("http://$config[modules_url]/modules/modules.php?action=list_modules", "rb");
$modules_list_temp = "";
do {
$data = fread($fp, 8192);
if (strlen($data) == 0) { break; }
$modules_list_temp .= $data;
} while(true);
fclose ($fp);
}
list ($headers, $modules_list) = split ("START_CYNUS_MODULES", $modules_list_temp);
$modules_list = unserialize ($modules_list);
return $modules_list;
}
function modules_wait_download() {
// A function that records the time when it is called
function profile ($dump = FALSE)
{
print "function profile<br>";
static $profile;
// Return the times stored in profile, then erase it
if ($dump) {
$temp = $profile;
unset ($profile);
return ($temp);
}
$profile[] = microtime ();
}
// Set up a tick handler
register_tick_function("profile");
// Initialize the function before the declare block
profile ();
// Run a block of code, throw a tick every 2nd statement
declare (ticks=2) {
for ($x = 1; $x != 0; ++$x) {
print "$x <br />";
}
}
// Display the data stored in the profiler
print_r (profile (TRUE));
exit;
}
function display_progress_window_js() {
$content = <<<___eofh
<script language="javascript1.2">
// <!--
var statusWin;
function showProgress() {
statusWin = open('http://localhost/brett/devel/cynus/progress_status.php','Status','height=150,width=350,location=no,scrollbars=no,menubars=no,toolbars=no,resizable=yes');
}
function newWindow() {
newWin = open('http://localhost/brett/devel/cynus/test.php', 'Test!', 'height=150,width=350,location=no,scrollbars=no,menubars=no,toolbars=no,resizable=yes');
}
function hideProgress() {
if (typeof(statusWin) != "undefined") {
statusWin.close();
statusWin = void(0);
}
}
function hideProgressAndReload() {
hideProgress();
history.go(0);
}
function imageEditChoice(selected_select) {
var sel_index = selected_select.selectedIndex;
var sel_value = selected_select.options[sel_index].value;
selected_select.options[0].selected = true;
selected_select.blur();
javascript:nw=window.open(sel_value,'Edit','height=500,width=500,location=no,scrollbars=yes,menubars=no,toolbars=no,resizable=yes');nw.opener=self;return false; }
// -->
</script>
___eofh;
return $content;
}
function test() {
require_once ("cynus_protocol/cynus_protocol_client.php");
$js = display_progress_window_js();
#$test = request_from_server (bob, 0, 0, 1);
#exit;
print<<<___eofh
<div id="hide_me" style="position: absolute;">
<h2>WAIT A MINUTE!!!</h2>
<img src="http://localhost/brett/devel/cynus/themes/blue/images/crest_logo.png">
</div>
<!-- in HEAD of document -->
<script language="javascript">
<!--
var state = 'visible';
function hide(layer_ref) {
state = 'hidden';
if (document.all) { //IS IE 4 or 5 (or 6 beta)
eval( "document.all." + layer_ref + ".style.visibility = state");
}
if (document.layers) { //IS NETSCAPE 4 or below
document.layers[layer_ref].visibility = state;
}
if (document.getElementById && !document.all) {
maxwell_smart = document.getElementById(layer_ref);
maxwell_smart.style.visibility = state;
}
}
//-->
</script>
___eofh;
print str_repeat(" ", 4096); // force a flush
flush();
sleep (3);
print "<script>hide('hide_me');</script>";
$content=<<<___eofh
<a href="#" onclick="hide('hide_me');">click me</a>
$js
<input type="button" value="Progress" onClick='showProgress();'>
<input type="button" value="newWindow" onClick='newWindow();'>
<a href="test.php">Results</a>
<br><br><br>
<a id="popuplink_2" target="Edit" href='http://localhost/brett/devel/cynus/test1.php' onClick="javascript:nw=window.open(document.getElementById('popuplink_2').href,'Edit','height=500,width=500,location=no,scrollbars=yes,menubars=no,toolbars=no,resizable=yes');nw.opener=self;return false;"><nobr>[add photo]</nobr></a>
<form action="http://localhost/brett/devel/cynus_modules/modules.php" method="POST">
client_maj_ver: <input type="text" name="client_maj_ver" size="50"><br />
client_min_ver: <input type="text" name="client_min_ver" size="50"<br />
cp_maj_ver: <input type="text" name="cp_maj_ver" size="50"<br />
cp_min_ver: <input type="text" name="cp_min_ver" size="50"<br />
client_ip: <input type="text" name="client_ip" size="50"<br />
client_url: <input type="text" name="client_url" size="50"<br />
cmd: <input type="text" name="cmd" size="50"<br />
action: <input type="text" name="action" size="50"<br />
<input type="submit" value="Submit">
</form>
___eofh;
return $content;
}
function mod_server_cli() {
$content=<<<___eofh
Command: <input type="text" name="cmd" size="20"><br />
___eofh;
}
?>