2011-05-12 04:11:40 +00:00
|
|
|
#! /usr/bin/env php
|
|
|
|
|
|
|
|
<?php
|
|
|
|
|
|
|
|
require_once("html/inc/boinc_db.inc");
|
|
|
|
require_once("html/inc/util_basic.inc");
|
|
|
|
|
|
|
|
$apps = BoincApp::enum("");
|
|
|
|
$platforms = BoincPlatform::enum("");
|
|
|
|
|
|
|
|
$config = file_get_contents("config.xml");
|
|
|
|
$download_url = parse_element($config, "<download_url>");
|
|
|
|
$download_dir = parse_element($config, "<download_dir>");
|
|
|
|
$fanout = parse_element($config, "<uldl_dir_fanout>");
|
|
|
|
|
|
|
|
function lookup_app($name) {
|
|
|
|
global $apps;
|
|
|
|
foreach ($apps as $app) {
|
|
|
|
if ($app->name == $name) return $app;
|
|
|
|
}
|
2011-08-07 04:32:02 +00:00
|
|
|
die("app not found: $name\n");
|
2011-05-12 04:11:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function lookup_platform($p) {
|
|
|
|
global $platforms;
|
|
|
|
foreach ($platforms as $platform) {
|
|
|
|
if ($platform->name == $p) return $platform;
|
|
|
|
}
|
2011-08-07 04:32:02 +00:00
|
|
|
die("platform not found: $p\n");
|
2011-05-12 04:11:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function readdir_aux($d) {
|
|
|
|
while ($f = readdir($d)) {
|
2011-08-02 17:20:18 +00:00
|
|
|
if (substr($f, 0, 1) == ".") continue;
|
2011-05-12 04:11:40 +00:00
|
|
|
return $f;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Data structures:
|
|
|
|
// Files are described by objects with fields
|
|
|
|
// physical_name
|
|
|
|
// logical_name
|
|
|
|
// main_program
|
|
|
|
// url
|
|
|
|
// etc.
|
|
|
|
// This are parsed from version.xml, or created by us
|
|
|
|
//
|
|
|
|
// Variables named $fd refer to such objects
|
|
|
|
//
|
|
|
|
|
|
|
|
// return a <file_info> element for the file
|
|
|
|
//
|
|
|
|
function file_info_xml($fd) {
|
|
|
|
$xml =
|
|
|
|
"<file_info>\n".
|
|
|
|
" <name>".$fd->physical_name."</name>\n"
|
|
|
|
;
|
|
|
|
if (is_array($fd->url)) {
|
|
|
|
foreach ($fd->url as $url) {
|
|
|
|
$xml .= " <url>$url</url>\n";
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
$xml .= " <url>$fd->url</url>\n";
|
- client: add a mechanism for restartable download of compressed files.
(It turns out that the compression schemes supported by
Apache and libcurl, suprisingly, aren't restartable.)
if a <file_info> from the server contains <gzipped_url> tags,
use those instead of the <url> tags,
and flag the file as "download_gzipped".
If this is the case, download NAME.gz and save it as NAME.gzt.
When the download is complete, rename NAME.gzt to NAME.gz,
and uncompress it to NAME.
(this ensures that if NAME.gz is present, it's complete).
Also do the uncompression, if needed, in verify_file().
This ensures that the uncompression will eventually get done
even if the client quits are crashes in the middle.
- update_versions: if <gzip> is present in a <file_info>,
add a gzipped copy in the download directory
and add a <gzipped_url> elements to the app version's xml_doc.
svn path=/trunk/boinc/; revision=25112
2012-01-20 23:34:15 +00:00
|
|
|
if ($fd->gzip) {
|
2012-01-21 01:36:53 +00:00
|
|
|
$xml .= " <gzipped_url>$fd->url.gz</gzipped_url>\n";
|
- client: add a mechanism for restartable download of compressed files.
(It turns out that the compression schemes supported by
Apache and libcurl, suprisingly, aren't restartable.)
if a <file_info> from the server contains <gzipped_url> tags,
use those instead of the <url> tags,
and flag the file as "download_gzipped".
If this is the case, download NAME.gz and save it as NAME.gzt.
When the download is complete, rename NAME.gzt to NAME.gz,
and uncompress it to NAME.
(this ensures that if NAME.gz is present, it's complete).
Also do the uncompression, if needed, in verify_file().
This ensures that the uncompression will eventually get done
even if the client quits are crashes in the middle.
- update_versions: if <gzip> is present in a <file_info>,
add a gzipped copy in the download directory
and add a <gzipped_url> elements to the app version's xml_doc.
svn path=/trunk/boinc/; revision=25112
2012-01-20 23:34:15 +00:00
|
|
|
}
|
2011-05-12 04:11:40 +00:00
|
|
|
}
|
2011-05-24 19:16:54 +00:00
|
|
|
if ($fd->executable || $fd->main_program) {
|
2011-05-12 04:11:40 +00:00
|
|
|
$xml .= " <executable/>\n";
|
|
|
|
}
|
|
|
|
$xml .= " <file_signature>\n";
|
|
|
|
$xml .= $fd->signature;
|
|
|
|
$xml .=
|
|
|
|
" </file_signature>\n".
|
2012-01-26 08:39:51 +00:00
|
|
|
" <nbytes>".$fd->nbytes."</nbytes>\n"
|
2011-05-12 04:11:40 +00:00
|
|
|
;
|
2012-01-26 08:39:51 +00:00
|
|
|
if ($fd->gzip) {
|
|
|
|
$xml .= " <gzipped_nbytes>".$fd->gzipped_nbytes."</gzipped_nbytes>\n";
|
|
|
|
}
|
|
|
|
$xml .= "</file_info>\n";
|
2011-05-12 04:11:40 +00:00
|
|
|
return $xml;
|
|
|
|
}
|
|
|
|
|
|
|
|
// return a <file_ref> element for the file
|
|
|
|
//
|
|
|
|
function file_ref_xml($fd) {
|
|
|
|
$xml =
|
|
|
|
"<file_ref>\n".
|
|
|
|
" <file_name>".$fd->physical_name."</file_name>\n"
|
|
|
|
;
|
|
|
|
if (isset($fd->logical_name) && strlen($fd->logical_name)) {
|
|
|
|
$xml .= " <open_name>$fd->logical_name</open_name>\n";
|
|
|
|
}
|
2011-05-18 16:59:15 +00:00
|
|
|
if ($fd->copy_file) {
|
|
|
|
$xml .= " <copy_file/>\n";
|
|
|
|
}
|
2011-05-12 04:11:40 +00:00
|
|
|
if ($fd->main_program) {
|
|
|
|
$xml .= " <main_program/>\n";
|
|
|
|
}
|
2011-05-17 16:00:23 +00:00
|
|
|
$xml .= "</file_ref>\n";
|
2011-05-12 04:11:40 +00:00
|
|
|
return $xml;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
function lookup_file($fds, $name) {
|
|
|
|
foreach ($fds as $fd) {
|
|
|
|
if ($fd->physical_name == $name) return $fd;
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
// update file in list, or add to list
|
|
|
|
//
|
|
|
|
function update_file($fds, $fd) {
|
|
|
|
for ($i=0; $i<sizeof($fds); $i++) {
|
|
|
|
if ($fds[$i]->physical_name == $fd->physical_name) {
|
|
|
|
$fds[$i] = $fd;
|
|
|
|
return $fds;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
$fds[] = $fd;
|
|
|
|
return $fds;
|
|
|
|
}
|
|
|
|
|
|
|
|
// move file to download dir, check immutability, fill in $fd->url
|
|
|
|
//
|
|
|
|
function stage_file($a, $v, $p, $fd) {
|
|
|
|
global $download_url, $download_dir;
|
|
|
|
|
|
|
|
$name = $fd->physical_name;
|
2011-05-12 04:14:53 +00:00
|
|
|
$path = "apps/$a/$v/$p/$name";
|
2011-05-12 04:11:40 +00:00
|
|
|
$dl_path = "$download_dir/$name";
|
|
|
|
if (is_file($dl_path)) {
|
|
|
|
if (md5_file($path) != md5_file($dl_path)) {
|
|
|
|
die ("Error: files $path and $dl_path differ.\nBOINC files are immutable.\nIf you change a file, you must give it a new name.\n");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
echo("cp $path $dl_path\n");
|
|
|
|
system("cp $path $dl_path");
|
|
|
|
}
|
|
|
|
|
|
|
|
$fd->url = "$download_url/$name";
|
2012-01-26 08:39:51 +00:00
|
|
|
if ($fd->gzip) {
|
|
|
|
if (!file_exists("$dl_path.gz")) {
|
|
|
|
$tmp = "$dl_path.tmp";
|
|
|
|
system("cp $dl_path $tmp");
|
|
|
|
system("gzip $dl_path");
|
|
|
|
system("mv $tmp $dl_path");
|
|
|
|
}
|
|
|
|
$stat = stat("$dl_path.gz");
|
|
|
|
$fd->gzipped_nbytes = $stat['size'];
|
2011-08-02 07:38:45 +00:00
|
|
|
}
|
2011-05-12 04:11:40 +00:00
|
|
|
return $fd;
|
|
|
|
}
|
|
|
|
|
|
|
|
function get_api_version($a, $v, $p, $fds) {
|
|
|
|
foreach ($fds as $fd) {
|
|
|
|
if ($fd->main_program) {
|
2011-05-12 04:14:53 +00:00
|
|
|
$path = "apps/$a/$v/$p/$fd->physical_name";
|
2011-05-12 04:11:40 +00:00
|
|
|
$handle = popen("strings $path | grep API_VERSION", "r");
|
|
|
|
$x = fread($handle, 8192);
|
|
|
|
pclose($handle);
|
|
|
|
$x = strstr($x, "API_VERSION_");
|
|
|
|
return trim(substr($x, strlen("API_VERSION_")));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
|
|
|
$sig_gen_confirmed = false;
|
|
|
|
|
|
|
|
function confirm_sig_gen($name) {
|
|
|
|
global $sig_gen_confirmed;
|
|
|
|
|
|
|
|
if ($sig_gen_confirmed) return true;
|
|
|
|
|
|
|
|
echo "
|
|
|
|
NOTICE: You have not provided a signature file for $name,
|
|
|
|
and your project's code-signing private key is on your server.
|
|
|
|
|
|
|
|
IF YOUR PROJECT IS PUBLICLY ACCESSABLE, THIS IS A SECURITY VULNERABILITY.
|
|
|
|
PLEASE STOP YOUR PROJECT IMMEDIATELY AND READ:
|
|
|
|
http://boinc.berkeley.edu/trac/wiki/CodeSigning
|
|
|
|
|
|
|
|
Continue (y/n)? ";
|
|
|
|
|
2011-06-11 15:30:10 +00:00
|
|
|
$x = trim(fgets(STDIN));
|
2011-05-12 04:11:40 +00:00
|
|
|
if ($x != "y") {
|
|
|
|
exit;
|
|
|
|
}
|
|
|
|
$sig_gen_confirmed = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// process a file
|
|
|
|
//
|
|
|
|
function process_file($a, $v, $p, $name, $fds) {
|
|
|
|
$fd = lookup_file($fds, $name);
|
|
|
|
if (!$fd) {
|
|
|
|
$fd = null;
|
|
|
|
$fd->physical_name = $name;
|
2011-08-07 04:32:02 +00:00
|
|
|
$fd->logical_name = null;
|
2011-05-12 04:11:40 +00:00
|
|
|
$fd->url = array();
|
2011-08-07 04:32:02 +00:00
|
|
|
$fd->main_program = false;
|
|
|
|
$fd->copy_file = false;
|
|
|
|
$fd->gzip = false;
|
2011-05-12 04:11:40 +00:00
|
|
|
}
|
2011-05-12 04:14:53 +00:00
|
|
|
$path = "apps/$a/$v/$p/$name";
|
2011-05-12 04:11:40 +00:00
|
|
|
|
|
|
|
$stat = stat($path);
|
|
|
|
$fd->nbytes = $stat['size'];
|
|
|
|
|
2011-05-12 04:14:53 +00:00
|
|
|
$sigpath = "apps/$a/$v/$p/$name.sig";
|
2011-05-12 04:11:40 +00:00
|
|
|
if (is_file($sigpath)) {
|
|
|
|
$fd->signature = file_get_contents($sigpath);
|
|
|
|
} else {
|
|
|
|
$keypath = "keys/code_sign_private";
|
|
|
|
if (is_file($keypath)) {
|
|
|
|
confirm_sig_gen($name);
|
|
|
|
$handle = popen("bin/sign_executable $path $keypath", "r");
|
|
|
|
$fd->signature = fread($handle, 8192);
|
|
|
|
pclose($handle);
|
|
|
|
} else {
|
|
|
|
die(" Error: no .sig file for $name, and no code signing private key\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!sizeof($fd->url)) {
|
|
|
|
$fd = stage_file($a, $v, $p, $fd);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!isset($fd->executable)) {
|
|
|
|
$perms = fileperms($path);
|
|
|
|
$fd->executable = ($perms & 0x0040)?true:false;
|
|
|
|
}
|
|
|
|
|
|
|
|
$fd->present = true;
|
|
|
|
$fds = update_file($fds, $fd);
|
|
|
|
return $fds;
|
|
|
|
}
|
|
|
|
|
2011-08-07 04:32:02 +00:00
|
|
|
// scan the directory, and process files.
|
|
|
|
// "fds" is the list of files described in version.xml;
|
|
|
|
// return this list, augmented with any files not in version.xml
|
|
|
|
//
|
2011-05-12 04:11:40 +00:00
|
|
|
//
|
|
|
|
function process_files($a, $v, $p, $fds) {
|
2011-05-12 04:14:53 +00:00
|
|
|
$d = opendir("apps/$a/$v/$p");
|
2011-05-12 04:11:40 +00:00
|
|
|
while ($f = readdir_aux($d)) {
|
|
|
|
if ($f == "version.xml") continue;
|
|
|
|
if (strstr($f, ".sig") == ".sig") continue;
|
|
|
|
$fds = process_file($a, $v, $p, $f, $fds);
|
|
|
|
}
|
|
|
|
return $fds;
|
|
|
|
}
|
|
|
|
|
|
|
|
function parse_platform_name($p, &$platform, &$plan_class) {
|
|
|
|
$x = explode("__", $p);
|
|
|
|
$platform = $x[0];
|
|
|
|
if (sizeof($x) > 1) {
|
|
|
|
$plan_class = $x[1];
|
|
|
|
} else {
|
|
|
|
$plan_class = "";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function parse_version($v) {
|
|
|
|
$x = explode(".", $v);
|
|
|
|
if (!is_numeric($x[0])) return -1;
|
|
|
|
if (sizeof($x) > 1) {
|
|
|
|
if (!is_numeric($x[1])) return -1;
|
2011-05-17 15:53:06 +00:00
|
|
|
return $x[1] + 100*$x[0];
|
2011-05-12 04:11:40 +00:00
|
|
|
}
|
|
|
|
return (int)$x[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
function already_exists($a, $v, $platform, $plan_class) {
|
|
|
|
$app = lookup_app($a);
|
|
|
|
$plat = lookup_platform($platform);
|
|
|
|
$vnum = parse_version($v);
|
|
|
|
$av = BoincAppVersion::lookup("appid=$app->id and version_num=$vnum and platformid=$plat->id and plan_class='$plan_class'");
|
|
|
|
if ($av) return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
function missing_files($fds) {
|
|
|
|
$missing = false;
|
|
|
|
foreach ($fds as $fd) {
|
|
|
|
if (!$fd->present) {
|
|
|
|
echo " File $fd->physical_name is listed in version.xml but not present\n";
|
|
|
|
$missing = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return $missing;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check whether there's a main program
|
|
|
|
//
|
|
|
|
function check_main_program($fds) {
|
|
|
|
$n = 0;
|
|
|
|
foreach ($fds as $fd) {
|
|
|
|
if ($fd->main_program) $n++;
|
|
|
|
}
|
|
|
|
if ($n == 0) {
|
2011-08-07 04:32:02 +00:00
|
|
|
die(" No file was marked as the main program.\n");
|
2011-05-12 04:11:40 +00:00
|
|
|
}
|
|
|
|
if ($n > 1) {
|
2011-08-07 04:32:02 +00:00
|
|
|
die(" More than one file was marked as the main program.\n");
|
2011-05-12 04:11:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function confirm($fds) {
|
|
|
|
echo " Files:\n";
|
|
|
|
foreach ($fds as $fd) {
|
|
|
|
echo " $fd->physical_name";
|
|
|
|
if ($fd->main_program) {
|
|
|
|
echo " (main program)";
|
|
|
|
}
|
|
|
|
echo "\n";
|
|
|
|
}
|
|
|
|
echo " Do you want to add this application version (y/n)? ";
|
2011-06-11 15:30:10 +00:00
|
|
|
$x = trim(fgets(STDIN));
|
2011-05-12 04:11:40 +00:00
|
|
|
return ($x == "y");
|
|
|
|
}
|
|
|
|
|
2011-08-03 18:14:45 +00:00
|
|
|
function get_bool($xml_element, $name) {
|
|
|
|
foreach($xml_element->xpath($name) as $x) {
|
|
|
|
$s = trim((string) $x);
|
|
|
|
if ($s == "" || int($s)>0) return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-05-12 04:11:40 +00:00
|
|
|
// convert SimpleXMLElement object to a standard object
|
|
|
|
//
|
|
|
|
function convert_simplexml($x) {
|
|
|
|
$fds = array();
|
|
|
|
$fxs = $x->xpath('file');
|
|
|
|
foreach ($fxs as $fx) {
|
|
|
|
//echo "fx: "; print_r($fx);
|
|
|
|
$fd = null;
|
|
|
|
|
2011-05-21 06:22:15 +00:00
|
|
|
$fd->present = false;
|
|
|
|
$fd->physical_name = trim((string) $fx->physical_name);
|
|
|
|
$fd->logical_name = trim((string) $fx->logical_name);
|
2011-05-12 04:11:40 +00:00
|
|
|
$fd->url = array();
|
|
|
|
foreach($fx->xpath('url') as $url) {
|
2011-05-21 06:22:15 +00:00
|
|
|
$fd->url[] = trim((string) $url);
|
2011-05-12 04:11:40 +00:00
|
|
|
}
|
2011-08-03 18:14:45 +00:00
|
|
|
$fd->main_program = get_bool($fx, "main_program");
|
|
|
|
$fd->copy_file = get_bool($fx, "copy_file");
|
|
|
|
$fd->gzip = get_bool($fx, "gzip");
|
2011-05-12 04:11:40 +00:00
|
|
|
|
|
|
|
$fds[] = $fd;
|
|
|
|
}
|
2011-08-03 18:14:45 +00:00
|
|
|
$v = null;
|
|
|
|
$v->files = $fds;
|
|
|
|
$v->dont_throttle = get_bool($x, "dont_throttle");
|
2011-12-26 06:03:50 +00:00
|
|
|
$v->needs_network = get_bool($x, "needs_network");
|
2011-08-03 18:14:45 +00:00
|
|
|
$v->file_prefix = (string)$x->file_prefix;
|
|
|
|
return $v;
|
2011-05-12 04:11:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function process_version($a, $v, $p) {
|
|
|
|
echo "Found application version: $a $v $p\n";
|
|
|
|
$app = lookup_app($a);
|
|
|
|
parse_platform_name($p, $platform, $plan_class);
|
|
|
|
if (already_exists($a, $v, $platform, $plan_class)) {
|
|
|
|
echo " This app version already exists\n";
|
|
|
|
return;
|
|
|
|
}
|
2011-05-12 04:14:53 +00:00
|
|
|
$vfile = "apps/$a/$v/$p/version.xml";
|
2011-05-12 04:11:40 +00:00
|
|
|
if (is_file($vfile)) {
|
|
|
|
$x = simplexml_load_file($vfile);
|
|
|
|
if (!$x) {
|
|
|
|
die("Can't load XML file apps/$a/$v/$p. Check that it exists and is valid.");
|
|
|
|
}
|
2011-08-03 18:14:45 +00:00
|
|
|
$vers = convert_simplexml($x);
|
2011-05-12 04:11:40 +00:00
|
|
|
} else {
|
2011-08-03 18:14:45 +00:00
|
|
|
$vers = null;
|
|
|
|
$vers->files = array();
|
2012-04-24 19:24:31 +00:00
|
|
|
$vers->dont_throttle = false;
|
|
|
|
$vers->needs_network = false;
|
|
|
|
$vers->file_prefix = false;
|
2011-05-12 04:11:40 +00:00
|
|
|
}
|
|
|
|
|
2011-08-03 18:14:45 +00:00
|
|
|
$fds = process_files($a, $v, $p, $vers->files);
|
2011-05-12 04:11:40 +00:00
|
|
|
|
|
|
|
if (missing_files($fds)) return;
|
2011-08-03 18:14:45 +00:00
|
|
|
if (sizeof($fds) == 1) {
|
|
|
|
$fds[0]->main_program = true;
|
|
|
|
}
|
2011-08-07 04:32:02 +00:00
|
|
|
check_main_program($fds);
|
2011-05-12 04:11:40 +00:00
|
|
|
$api_version = get_api_version($a, $v, $p, $fds);
|
|
|
|
|
|
|
|
if (!confirm($fds)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
$xml = "";
|
|
|
|
foreach ($fds as $fd) {
|
|
|
|
$xml .= file_info_xml($fd);
|
|
|
|
}
|
|
|
|
$xml .=
|
|
|
|
"<app_version>\n".
|
|
|
|
" <app_name>".$app->name."</app_name>\n".
|
2011-07-05 17:45:24 +00:00
|
|
|
" <version_num>".parse_version($v)."</version_num>\n".
|
2011-05-12 04:11:40 +00:00
|
|
|
" <api_version>$api_version</api_version>\n"
|
|
|
|
;
|
|
|
|
foreach ($fds as $fd) {
|
|
|
|
$xml .= file_ref_xml($fd);
|
|
|
|
}
|
2011-08-03 18:14:45 +00:00
|
|
|
if ($vers->dont_throttle) {
|
|
|
|
$xml .= " <dont_throttle/>\n";
|
|
|
|
}
|
2011-12-26 06:03:50 +00:00
|
|
|
if ($vers->needs_network) {
|
|
|
|
$xml .= " <needs_network/>\n";
|
|
|
|
}
|
2011-08-03 18:14:45 +00:00
|
|
|
if ($vers->file_prefix != "") {
|
|
|
|
$xml .= " <file_prefix>$vers->file_prefix</file_prefix>\n";
|
|
|
|
}
|
2011-05-12 04:11:40 +00:00
|
|
|
$xml .= "</app_version>\n";
|
|
|
|
|
|
|
|
$now = time();
|
|
|
|
$vnum = parse_version($v);
|
|
|
|
$plat = lookup_platform($platform);
|
|
|
|
$query = "set create_time=$now, appid=$app->id, version_num=$vnum, platformid=$plat->id , xml_doc='$xml', plan_class='$plan_class'";
|
|
|
|
|
|
|
|
$id = BoincAppVersion::insert($query);
|
|
|
|
if ($id) {
|
|
|
|
echo " Application version added successfully; ID=$id\n";
|
|
|
|
} else {
|
|
|
|
echo " Error; application version not added\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function scan_version_dir($a, $v) {
|
2011-05-12 04:14:53 +00:00
|
|
|
$d = opendir("apps/$a/$v");
|
2011-05-12 04:11:40 +00:00
|
|
|
while ($p = readdir_aux($d)) {
|
|
|
|
process_version($a, $v, $p);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function scan_app_dir($a) {
|
2011-05-12 04:14:53 +00:00
|
|
|
$d = opendir("apps/$a");
|
2011-05-12 04:11:40 +00:00
|
|
|
while ($v = readdir_aux($d)) {
|
|
|
|
if (parse_version($v) < 0) {
|
|
|
|
echo "$v is not a version number; skipping\n";
|
2005-01-27 23:09:19 +00:00
|
|
|
continue;
|
2011-05-12 04:11:40 +00:00
|
|
|
}
|
|
|
|
scan_version_dir($a, $v);
|
|
|
|
}
|
|
|
|
closedir($d);
|
|
|
|
}
|
|
|
|
|
|
|
|
function scan_apps() {
|
2011-05-12 04:14:53 +00:00
|
|
|
$d = opendir("apps");
|
2011-05-12 04:11:40 +00:00
|
|
|
while ($a = readdir_aux($d)) {
|
|
|
|
if (!lookup_app($a)) {
|
|
|
|
echo "$a is not an app\n";
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
scan_app_dir($a);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
scan_apps();
|
2011-10-21 20:14:54 +00:00
|
|
|
touch("reread_db"); // if feeder is running, tell it to reread DB
|
2011-05-12 04:11:40 +00:00
|
|
|
|
|
|
|
?>
|