<?php echo "<h2>" . _("Module Administration") . "</h2>"; if ($module_repo == "extended") { echo "<h4 align='center'>" . _("NOTICE") . "<br />" . _("You have accessed the extended repository which includes un-supported and third party modules") . "</h4>"; } } else { // $quietmode==true ?> <html><head> <link href="common/mainstyle.css" rel="stylesheet" type="text/css" /> </head><body> <?php } $modules_local = module_getinfo(false, false, true); if ($online) { $modules_online = module_getonlinexml(false, $repo); // $module_getonlinexml_error is a global set by module_getonlinexml() if ($module_getonlinexml_error) { echo "<div class=\"warning\"><p>" . sprintf(_("Warning: Cannot connect to online repository (%s). Online modules are not available."), "mirror.freepbx.org") . "</p></div><br />"; $online = 0; unset($modules_online); } else { if (!is_array($modules_online)) { echo "<div class=\"warning\"><p>" . sprintf(_("Warning: Error retrieving updates from online repository (%s). Online modules are not available."), "mirror.freepbx.org") . "</p></div><br />"; $online = 0; unset($modules_online); } else { // combine online and local modules $modules = $modules_online; foreach (array_keys($modules) as $name) { if (isset($modules_local[$name])) {
?> "></span></a> </div> <?php //TODO: decide if warnings of any sort need to be given, or just list of repos active? } else { // $quietmode==true ?> <html><head></head><body> <?php } $modules_local = module_getinfo(false, false, true); if ($online) { $security_array = array(); $security_issues_to_report = array(); $modules_online = module_getonlinexml(false, false, $security_array); // $module_getonlinexml_error is a global set by module_getonlinexml() if ($module_getonlinexml_error) { echo "<div class=\"warning\"><p>" . sprintf(_("Warning: Cannot connect to online repository(s) (%s). Online modules are not available."), $amp_conf['MODULE_REPO']) . "</p></div><br />"; $online = 0; unset($modules_online); } else { if (!is_array($modules_online)) { echo "<div class=\"warning\"><p>" . sprintf(_("Warning: Error retrieving updates from online repository(s) (%s). Online modules are not available."), $amp_conf['MODULE_REPO']) . "</p></div><br />"; $online = 0; unset($modules_online); } else { // combine online and local modules $modules = $modules_online; foreach (array_keys($modules) as $name) { if (isset($modules_local[$name])) {
function module_download($modulename, $force = false, $progress_callback = null, $override_svn = false, $override_xml = false) { global $amp_conf; if ($time_limit = ini_get('max_execution_time')) { set_time_limit($time_limit); } // size of download blocks to fread() // basically, this controls how often progress_callback is called $download_chunk_size = 12 * 1024; // invoke progress callback if (function_exists($progress_callback)) { $progress_callback('getinfo', array('module' => $modulename)); } $res = module_getonlinexml($modulename, $override_xml); if ($res == null) { return array(_("Module not found in repository")); } $file = basename($res['location']); $filename = $amp_conf['AMPWEBROOT'] . "/admin/modules/_cache/" . $file; // if we're not forcing the download, and a file with the target name exists.. if (!$force && file_exists($filename)) { // We might already have it! Let's check the MD5. $filedata = ""; if ($fh = @fopen($filename, "r")) { while (!feof($fh)) { $filedata .= fread($fh, 8192); } fclose($fh); } if (isset($res['md5sum']) && $res['md5sum'] == md5($filedata)) { // Note, if there's no MD5 information, it will redownload // every time. Otherwise theres no way to avoid a corrupt // download // invoke progress callback if (function_exists($progress_callback)) { $progress_callback('untar', array('module' => $modulename, 'size' => filesize($filename))); } /* We will explode the tarball in the cache directory and then once successful, remove the old module before before * moving the new one over. This way, things like removed files end up being removed instead of laying around * * TODO: save old module being replaced, if there is an old one. */ exec("rm -rf " . $amp_conf['AMPWEBROOT'] . "/admin/modules/_cache/{$modulename}", $output, $exitcode); if ($exitcode != 0) { return array(sprintf(_('Could not remove %s to install new version'), $amp_conf['AMPWEBROOT'] . '/admin/modules/_cache/' . $modulenam)); } exec("tar zxf " . escapeshellarg($filename) . " -C " . escapeshellarg($amp_conf['AMPWEBROOT'] . '/admin/modules/_cache/'), $output, $exitcode); if ($exitcode != 0) { return array(sprintf(_('Could not untar %s to %s'), $filename, $amp_conf['AMPWEBROOT'] . '/admin/modules/_cache')); } exec("rm -rf " . $amp_conf['AMPWEBROOT'] . "/admin/modules/{$modulename}", $output, $exitcode); if ($exitcode != 0) { return array(sprintf(_('Could not remove old module %s to install new version'), $amp_conf['AMPWEBROOT'] . '/admin/modules/' . $modulename)); } exec("mv " . $amp_conf['AMPWEBROOT'] . "/admin/modules/_cache/{$modulename} " . $amp_conf['AMPWEBROOT'] . "/admin/modules/{$modulename}", $output, $exitcode); if ($exitcode != 0) { return array(sprintf(_('Could not move %s to %s'), $amp_conf['AMPWEBROOT'] . "/admin/modules/_cache/{$modulename}", $amp_conf['AMPWEBROOT'] . '/admin/modules/')); } // invoke progress_callback if (function_exists($progress_callback)) { $progress_callback('done', array('module' => $modulename)); } return true; } else { unlink($filename); } } if ($override_svn) { $url = $override_svn . $res['location']; } else { $url = "http://mirror.freepbx.org/modules/" . $res['location']; } if (!($fp = @fopen($filename, "w"))) { return array(sprintf(_("Error opening %s for writing"), $filename)); } $headers = get_headers_assoc($url); $totalread = 0; // invoke progress_callback if (function_exists($progress_callback)) { $progress_callback('downloading', array('module' => $modulename, 'read' => $totalread, 'total' => $headers['content-length'])); } // Check MODULEADMINWGET first so we don't execute the fopen() if set // if ($amp_conf['MODULEADMINWGET'] || !($dp = @fopen($url, 'r'))) { exec("wget -O {$filename} {$url} 2> /dev/null", $filedata, $retcode); if ($retcode != 0) { return array(sprintf(_("Error opening %s for reading"), $url)); } else { if (!($dp = @fopen($filename, 'r'))) { return array(sprintf(_("Error opening %s for reading"), $url)); } } } $filedata = ''; while (!feof($dp)) { $data = fread($dp, $download_chunk_size); $filedata .= $data; $totalread += strlen($data); if (function_exists($progress_callback)) { $progress_callback('downloading', array('module' => $modulename, 'read' => $totalread, 'total' => $headers['content-length'])); } } fwrite($fp, $filedata); fclose($dp); fclose($fp); if (is_readable($filename) !== TRUE) { return array(sprintf(_('Unable to save %s'), $filename)); } // Check the MD5 info against what's in the module's XML if (!isset($res['md5sum']) || empty($res['md5sum'])) { //echo "<div class=\"error\">"._("Unable to Locate Integrity information for")." {$filename} - "._("Continuing Anyway")."</div>"; } else { if ($res['md5sum'] != md5($filedata)) { unlink($filename); return array(sprintf(_('File Integrity failed for %s - aborting'), $filename)); } } // invoke progress callback if (function_exists($progress_callback)) { $progress_callback('untar', array('module' => $modulename, 'size' => filesize($filename))); } /* We will explode the tarball in the cache directory and then once successful, remove the old module before before * moving the new one over. This way, things like removed files end up being removed instead of laying around * * TODO: save old module being replaced, if there is an old one. * */ exec("rm -rf " . $amp_conf['AMPWEBROOT'] . "/admin/modules/_cache/{$modulename}", $output, $exitcode); if ($exitcode != 0) { return array(sprintf(_('Could not remove %s to install new version'), $amp_conf['AMPWEBROOT'] . '/admin/modules/_cache/' . $modulenam)); } exec("tar zxf " . escapeshellarg($filename) . " -C " . escapeshellarg($amp_conf['AMPWEBROOT'] . '/admin/modules/_cache/'), $output, $exitcode); if ($exitcode != 0) { return array(sprintf(_('Could not untar %s to %s'), $filename, $amp_conf['AMPWEBROOT'] . '/admin/modules/_cache')); } exec("rm -rf " . $amp_conf['AMPWEBROOT'] . "/admin/modules/{$modulename}", $output, $exitcode); if ($exitcode != 0) { return array(sprintf(_('Could not remove old module %s to install new version'), $amp_conf['AMPWEBROOT'] . '/admin/modules/' . $modulename)); } exec("mv " . $amp_conf['AMPWEBROOT'] . "/admin/modules/_cache/{$modulename} " . $amp_conf['AMPWEBROOT'] . "/admin/modules/{$modulename}", $output, $exitcode); if ($exitcode != 0) { return array(sprintf(_('Could not move %s to %s'), $amp_conf['AMPWEBROOT'] . "/admin/modules/_cache/{$modulename}", $amp_conf['AMPWEBROOT'] . '/admin/modules/')); } // invoke progress_callback if (function_exists($progress_callback)) { $progress_callback('done', array('module' => $modulename)); } return true; }
function module_download($modulename, $force = false, $progress_callback = null, $override_svn = false, $override_xml = false) { global $amp_conf; if ($time_limit = ini_get('max_execution_time')) { set_time_limit($time_limit); } // size of download blocks to fread() // basically, this controls how often progress_callback is called $download_chunk_size = 12 * 1024; // invoke progress callback if (function_exists($progress_callback)) { $progress_callback('getinfo', array('module' => $modulename)); } $res = module_getonlinexml($modulename, $override_xml); if ($res == null) { return array(_("Module not found in repository")); } $file = basename($res['location']); $filename = $amp_conf['AMPWEBROOT'] . "/admin/modules/_cache/" . $file; // if we're not forcing the download, and a file with the target name exists.. if (!$force && file_exists($filename)) { // We might already have it! Let's check the MD5. $filedata = ""; if ($fh = @fopen($filename, "r")) { while (!feof($fh)) { $filedata .= fread($fh, 8192); } fclose($fh); } if (isset($res['md5sum']) && $res['md5sum'] == md5($filedata)) { // Note, if there's no MD5 information, it will redownload // every time. Otherwise theres no way to avoid a corrupt // download // invoke progress callback if (function_exists($progress_callback)) { $progress_callback('untar', array('module' => $modulename, 'size' => filesize($filename))); } /* We will explode the tarball in the cache directory and then once successful, remove the old module before before * moving the new one over. This way, things like removed files end up being removed instead of laying around * * TODO: save old module being replaced, if there is an old one. */ exec("rm -rf " . $amp_conf['AMPWEBROOT'] . "/admin/modules/_cache/{$modulename}", $output, $exitcode); if ($exitcode != 0) { return array(sprintf(_('Could not remove %s to install new version'), $amp_conf['AMPWEBROOT'] . '/admin/modules/_cache/' . $modulename)); } exec("tar zxf " . escapeshellarg($filename) . " -C " . escapeshellarg($amp_conf['AMPWEBROOT'] . '/admin/modules/_cache/'), $output, $exitcode); if ($exitcode != 0) { freepbx_log(FPBX_LOG_ERROR, sprintf(_("failed to open %s module archive into _cache directory."), $filename)); return array(sprintf(_('Could not untar %s to %s'), $filename, $amp_conf['AMPWEBROOT'] . '/admin/modules/_cache')); } else { // since untarring was successful, remvove the tarball so they do not accumulate if (unlink($filename) === false) { freepbx_log(FPBX_LOG_WARNING, sprintf(_("failed to delete %s from cache directory after opening module archive."), $filename)); } } exec("rm -rf " . $amp_conf['AMPWEBROOT'] . "/admin/modules/{$modulename}", $output, $exitcode); if ($exitcode != 0) { return array(sprintf(_('Could not remove old module %s to install new version'), $amp_conf['AMPWEBROOT'] . '/admin/modules/' . $modulename)); } exec("mv " . $amp_conf['AMPWEBROOT'] . "/admin/modules/_cache/{$modulename} " . $amp_conf['AMPWEBROOT'] . "/admin/modules/{$modulename}", $output, $exitcode); if ($exitcode != 0) { return array(sprintf(_('Could not move %s to %s'), $amp_conf['AMPWEBROOT'] . "/admin/modules/_cache/{$modulename}", $amp_conf['AMPWEBROOT'] . '/admin/modules/')); } // invoke progress_callback if (function_exists($progress_callback)) { $progress_callback('done', array('module' => $modulename)); } return true; } else { unlink($filename); } } if (!($fp = @fopen($filename, "w"))) { return array(sprintf(_("Error opening %s for writing"), $filename)); } if ($override_svn) { $url_list = array($override_svn . $res['location']); } else { $url_list = generate_module_repo_url("/modules/" . $res['location'], true); } // Check each URL until get_headers_assoc() returns something intelligible. We then use // that URL and hope the file is there, we won't check others. // $headers = false; foreach ($url_list as $u) { $headers = get_headers_assoc($u); if (!empty($headers)) { $url = $u; break; } freepbx_log(FPBX_LOG_ERROR, sprintf(_('Failed download module tarball from %s, server may be down'), $u)); } if (!$headers || !$url) { return array(sprintf(_("Unable to connect to servers from URLs provided: %s"), implode(',', $url_list))); } // TODO: do we want to make more robust past this point: // At this point we have settled on a specific URL that we can reach, if the file isn't there we won't try // other servers to check for it. The assumption is that no backup server will have it either at this point // If we wanted to make this more robust we could go back and try other servers. This code is a bit tangled // so some better factoring might help. // $totalread = 0; // invoke progress_callback if (function_exists($progress_callback)) { $progress_callback('downloading', array('module' => $modulename, 'read' => $totalread, 'total' => $headers['content-length'])); } // Check MODULEADMINWGET first so we don't execute the fopen() if set // if ($amp_conf['MODULEADMINWGET'] || !($dp = @fopen($url, 'r'))) { exec("wget --tries=1 --timeout=600 -O {$filename} {$url} 2> /dev/null", $filedata, $retcode); if ($retcode != 0) { return array(sprintf(_("Error opening %s for reading"), $url)); } else { if (!($dp = @fopen($filename, 'r'))) { return array(sprintf(_("Error opening %s for reading"), $url)); } } } $filedata = ''; while (!feof($dp)) { $data = fread($dp, $download_chunk_size); $filedata .= $data; $totalread += strlen($data); if (function_exists($progress_callback)) { $progress_callback('downloading', array('module' => $modulename, 'read' => $totalread, 'total' => $headers['content-length'])); } } fwrite($fp, $filedata); fclose($dp); fclose($fp); if (is_readable($filename) !== TRUE) { return array(sprintf(_('Unable to save %s'), $filename)); } // Check the MD5 info against what's in the module's XML if (!isset($res['md5sum']) || empty($res['md5sum'])) { //echo "<div class=\"error\">"._("Unable to Locate Integrity information for")." {$filename} - "._("Continuing Anyway")."</div>"; } else { if ($res['md5sum'] != md5($filedata)) { unlink($filename); return array(sprintf(_('File Integrity failed for %s - aborting'), $filename)); } } // invoke progress callback if (function_exists($progress_callback)) { $progress_callback('untar', array('module' => $modulename, 'size' => filesize($filename))); } /* We will explode the tarball in the cache directory and then once successful, remove the old module before before * moving the new one over. This way, things like removed files end up being removed instead of laying around * * TODO: save old module being replaced, if there is an old one. * */ exec("rm -rf " . $amp_conf['AMPWEBROOT'] . "/admin/modules/_cache/{$modulename}", $output, $exitcode); if ($exitcode != 0) { return array(sprintf(_('Could not remove %s to install new version'), $amp_conf['AMPWEBROOT'] . '/admin/modules/_cache/' . $modulename)); } exec("tar zxf " . escapeshellarg($filename) . " -C " . escapeshellarg($amp_conf['AMPWEBROOT'] . '/admin/modules/_cache/'), $output, $exitcode); if ($exitcode != 0) { freepbx_log(FPBX_LOG_ERROR, sprintf(_("failed to open %s module archive into _cache directory."), $filename)); return array(sprintf(_('Could not untar %s to %s'), $filename, $amp_conf['AMPWEBROOT'] . '/admin/modules/_cache')); } else { // since untarring was successful, remvove the tarball so they do not accumulate if (unlink($filename) === false) { freepbx_log(FPBX_LOG_WARNING, sprintf(_("failed to delete %s from cache directory after opening module archive."), $filename)); } } exec("rm -rf " . $amp_conf['AMPWEBROOT'] . "/admin/modules/{$modulename}", $output, $exitcode); if ($exitcode != 0) { return array(sprintf(_('Could not remove old module %s to install new version'), $amp_conf['AMPWEBROOT'] . '/admin/modules/' . $modulename)); } exec("mv " . $amp_conf['AMPWEBROOT'] . "/admin/modules/_cache/{$modulename} " . $amp_conf['AMPWEBROOT'] . "/admin/modules/{$modulename}", $output, $exitcode); if ($exitcode != 0) { return array(sprintf(_('Could not move %s to %s'), $amp_conf['AMPWEBROOT'] . "/admin/modules/_cache/{$modulename}", $amp_conf['AMPWEBROOT'] . '/admin/modules/')); } // invoke progress_callback if (function_exists($progress_callback)) { $progress_callback('done', array('module' => $modulename)); } return true; }