2011-05-12 04:11:40 +00:00
|
|
|
#! /usr/bin/env php
|
|
|
|
|
|
|
|
<?php
|
2012-10-15 18:47:55 +00:00
|
|
|
// This file is part of BOINC.
|
|
|
|
// http://boinc.berkeley.edu
|
|
|
|
// Copyright (C) 2012 University of California
|
|
|
|
//
|
|
|
|
// BOINC 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 3 of the License, or (at your option) any later version.
|
|
|
|
//
|
|
|
|
// BOINC 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 BOINC. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
|
2014-07-29 18:11:48 +00:00
|
|
|
// script to create app versions,
|
2012-10-15 18:47:55 +00:00
|
|
|
// and stage their files in the download dir.
|
|
|
|
// See http://boinc.berkeley.edu/trac/wiki/AppVersionNew
|
|
|
|
|
2011-05-12 04:11:40 +00:00
|
|
|
|
2014-06-21 20:40:02 +00:00
|
|
|
error_reporting(E_ALL);
|
|
|
|
ini_set('display_errors', true);
|
|
|
|
ini_set('display_startup_errors', true);
|
|
|
|
|
2011-05-12 04:11:40 +00:00
|
|
|
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");
|
2012-10-29 18:02:12 +00:00
|
|
|
if (!$config) die("config.xml not found. Run this in project root dir.\n");
|
2011-05-12 04:11:40 +00:00
|
|
|
$download_url = parse_element($config, "<download_url>");
|
2012-10-29 18:02:12 +00:00
|
|
|
if (!$download_url) die("<download_url> not found in config.xml\n");
|
2011-05-12 04:11:40 +00:00
|
|
|
$download_dir = parse_element($config, "<download_dir>");
|
2012-10-29 18:02:12 +00:00
|
|
|
if (!$download_dir) die("<download_dir> not found in config.xml\n");
|
|
|
|
$key_dir = parse_element($config, "<key_dir>");
|
|
|
|
if (!$key_dir) die("<key_dir> not found in config.xml\n");
|
2011-05-12 04:11:40 +00:00
|
|
|
|
|
|
|
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) {
|
2012-10-29 18:02:12 +00:00
|
|
|
global $key_dir;
|
2011-05-12 04:11:40 +00:00
|
|
|
$fd = lookup_file($fds, $name);
|
|
|
|
if (!$fd) {
|
2013-05-05 08:26:17 +00:00
|
|
|
$fd = new StdClass;
|
2011-05-12 04:11:40 +00:00
|
|
|
$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 {
|
2012-10-29 18:02:12 +00:00
|
|
|
$keypath = "$key_dir/code_sign_private";
|
2011-05-12 04:11:40 +00:00
|
|
|
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) {
|
2013-02-10 20:07:09 +00:00
|
|
|
echo " No file was marked as the main program - skipping.\n";
|
|
|
|
return 1;
|
2011-05-12 04:11:40 +00:00
|
|
|
}
|
|
|
|
if ($n > 1) {
|
2013-02-10 20:07:09 +00:00
|
|
|
echo " More than one file was marked as the main program - skipping.\n";
|
|
|
|
return 1;
|
2011-05-12 04:11:40 +00:00
|
|
|
}
|
2013-02-10 20:07:09 +00:00
|
|
|
return 0;
|
2011-05-12 04:11:40 +00:00
|
|
|
}
|
|
|
|
|
2014-07-29 18:11:48 +00:00
|
|
|
function confirm($fds, $v) {
|
2011-05-12 04:11:40 +00:00
|
|
|
echo " Files:\n";
|
|
|
|
foreach ($fds as $fd) {
|
|
|
|
echo " $fd->physical_name";
|
|
|
|
if ($fd->main_program) {
|
|
|
|
echo " (main program)";
|
|
|
|
}
|
|
|
|
echo "\n";
|
|
|
|
}
|
2014-07-29 18:11:48 +00:00
|
|
|
echo " Flags:\n";
|
|
|
|
if ($v->dont_throttle) echo " don't throttle\n";
|
|
|
|
if ($v->needs_network) echo " needs network\n";
|
|
|
|
if ($v->is_wrapper) echo " is wrapper\n";
|
|
|
|
if ($v->beta) echo " beta\n";
|
|
|
|
if ($v->file_prefix) echo " file prefix: $v->file_prefix\n";
|
|
|
|
echo " API version: $v->api_version\n";
|
|
|
|
echo " Do you want to add this app 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);
|
2013-05-05 08:26:17 +00:00
|
|
|
$fd = new StdClass;
|
2011-05-12 04:11:40 +00:00
|
|
|
|
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;
|
|
|
|
}
|
2013-05-05 08:26:17 +00:00
|
|
|
$v = new StdClass;
|
2011-08-03 18:14:45 +00:00
|
|
|
$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");
|
2013-11-07 19:49:04 +00:00
|
|
|
$v->is_wrapper = get_bool($x, "is_wrapper");
|
2011-08-03 18:14:45 +00:00
|
|
|
$v->file_prefix = (string)$x->file_prefix;
|
2014-06-06 16:47:33 +00:00
|
|
|
$v->beta = get_bool($x, "beta");
|
2014-07-29 18:11:48 +00:00
|
|
|
$v->api_version = (string)$x->api_version;
|
2011-08-03 18:14:45 +00:00
|
|
|
return $v;
|
2011-05-12 04:11:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function process_version($a, $v, $p) {
|
2014-07-29 18:11:48 +00:00
|
|
|
echo "Found app version directory for: $a $v $p\n";
|
2011-05-12 04:11:40 +00:00
|
|
|
$app = lookup_app($a);
|
|
|
|
parse_platform_name($p, $platform, $plan_class);
|
|
|
|
if (already_exists($a, $v, $platform, $plan_class)) {
|
2014-07-29 18:11:48 +00:00
|
|
|
echo " (already exists in database)\n";
|
2011-05-12 04:11:40 +00:00
|
|
|
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 {
|
2013-05-05 08:26:17 +00:00
|
|
|
$vers = new StdClass;
|
2011-08-03 18:14:45 +00:00
|
|
|
$vers->files = array();
|
2012-04-24 19:24:31 +00:00
|
|
|
$vers->dont_throttle = false;
|
|
|
|
$vers->needs_network = false;
|
2013-11-07 19:49:04 +00:00
|
|
|
$vers->is_wrapper = false;
|
2014-06-06 16:47:33 +00:00
|
|
|
$vers->beta = false;
|
2012-04-24 19:24:31 +00:00
|
|
|
$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;
|
|
|
|
}
|
2013-02-10 20:07:09 +00:00
|
|
|
if (check_main_program($fds)) {
|
|
|
|
return;
|
|
|
|
}
|
2011-05-12 04:11:40 +00:00
|
|
|
|
2014-07-29 18:11:48 +00:00
|
|
|
// if API version isn't specified in version.xml,
|
|
|
|
// try to find it embedded in the executable
|
|
|
|
//
|
|
|
|
if (!strlen($vers->api_version)) {
|
|
|
|
$vers->api_version = get_api_version($a, $v, $p, $fds);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!confirm($fds, $vers)) {
|
2011-05-12 04:11:40 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
$xml = "";
|
|
|
|
foreach ($fds as $fd) {
|
|
|
|
$xml .= file_info_xml($fd);
|
|
|
|
}
|
|
|
|
$xml .=
|
|
|
|
"<app_version>\n".
|
|
|
|
" <app_name>".$app->name."</app_name>\n".
|
2014-07-29 18:11:48 +00:00
|
|
|
" <version_num>".parse_version($v)."</version_num>\n"
|
2011-05-12 04:11:40 +00:00
|
|
|
;
|
2014-07-31 18:28:39 +00:00
|
|
|
if (strlen($vers->api_version)) {
|
2014-07-29 18:11:48 +00:00
|
|
|
$xml .=
|
2014-07-31 18:28:39 +00:00
|
|
|
" <api_version>$vers->api_version</api_version>\n"
|
2014-07-29 18:11:48 +00:00
|
|
|
;
|
|
|
|
}
|
2011-05-12 04:11:40 +00:00
|
|
|
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";
|
|
|
|
}
|
2013-11-07 19:49:04 +00:00
|
|
|
if ($vers->is_wrapper) {
|
|
|
|
$xml .= " <is_wrapper/>\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);
|
2014-06-06 16:47:33 +00:00
|
|
|
$b = $vers->beta?1:0;
|
|
|
|
$query = "set create_time=$now, appid=$app->id, version_num=$vnum, platformid=$plat->id , xml_doc='$xml', plan_class='$plan_class', beta=$b";
|
2011-05-12 04:11:40 +00:00
|
|
|
|
|
|
|
$id = BoincAppVersion::insert($query);
|
|
|
|
if ($id) {
|
2014-07-29 18:11:48 +00:00
|
|
|
echo " App version added successfully; ID=$id\n";
|
2011-05-12 04:11:40 +00:00
|
|
|
} else {
|
2014-07-29 18:11:48 +00:00
|
|
|
echo " Error; app version not added\n";
|
2011-05-12 04:11:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
?>
|