Web RPC: add an RPC that lets "front-end" web sites show Download buttons that auto-attach to back-end BOINC projects or account managers.

This commit is contained in:
David Anderson 2021-01-22 00:47:02 -08:00
parent ba3702e8c8
commit 43e277c82a
2 changed files with 198 additions and 23 deletions

View File

@ -17,6 +17,8 @@
// along with BOINC. If not, see <http://www.gnu.org/licenses/>.
// PHP interfaces to some of BOINC's Web RPCs
//
// This file is free-standing; it doesn't include other BOINC PHP files
// my PHP currently doesn't support file_get_contents(https://...)
// so do it with Curl
@ -59,7 +61,7 @@ function lookup_account(
}
}
// return (authenticator, errmsg)
// return (authenticator, errno, errmsg)
//
function create_account(
$project_url,
@ -96,9 +98,107 @@ function create_account(
}
}
function example1() {
// Get info needed to show Download buttons
// that auto-attach to a particular project or account manager.
//
// args:
// $project_url: the URL of the project or account manager
// $rpc_key: a security token supplied by the above
// $auth: the authenticator of the account to auto-attach to
// $user_agent: the user agent string supplied by user's browser
// This indicates what kind of computer they're on.
//
// return: (parsed XML reply, errno, errmsg)
//
function download_software($project_url, $rpc_key, $auth, $user_agent) {
$url = sprintf(
'%s/download_software.php?action=get_info&rpc_key=%s&auth=%s&user_agent=%s',
$project_url, $rpc_key, $auth, urlencode($user_agent)
);
$reply = fetch_url($url);
if (!$reply) return array(null, -1, "HTTP error to $url");
$r = @simplexml_load_string($reply);
if (!$r) {
return array(null, -1, "Can't parse reply XML:\n$reply");
}
if ((int)$r->error_num) {
return array(null, (int)$r->error_num, (string)$r->error_msg);
}
return array($r, 0, null);
}
if (1) {
// Example usage of download_software().
// Show a download button, which when clicked will download a
// BOINC client that auto-attaches to a particular account
//
// Adapt to your web site. The following assumes Bootstrap.
//
function show_download_button($info, $is_vbox) {
$desc = $is_vbox?$info->boinc_vbox:$info->boinc;
echo sprintf('
<form action="https://boinc.berkeley.edu/concierge.php" method="post">
<input type=hidden name=project_id value="%d">
<input type=hidden name=token value="%s">
<input type=hidden name=user_id value="%d">
<input type=hidden name=filename value="%s">
<button class="btn">
<font size=2><u>Download BOINC%s</u></font> <br>for %s (%s MB)
',
(int)$info->project_id,
(string)$info->token,
(int)$info->user_id,
(string)$desc->filename,
$is_vbox?" + VirtualBox":"",
(string)$info->platform,
(string)$desc->size_mb
);
if ($is_vbox) {
echo sprintf('
<br><small>BOINC %s, VirtualBox %s</small>
</button>
',
(string)$desc->boinc_version,
(string)$desc->vbox_version
);
} else {
echo sprintf('
<br><small>BOINC %s</small>
</button>
',
(string)$desc->boinc_version
);
}
echo '</form>
';
}
echo "If BOINC is already installed on this computer,
go <a href=X>here</a>; otherwise:
";
list($info, $errno, $errmsg) = download_software(
"https://boinc.berkeley.edu/test",
"xxx",
"xxx",
"Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0)"
);
if ($errno) {
echo "Go <a href=https://boinc.berkeley.edu/download.php>here</a>
to download BOINC, then attach to target_project
";
} else {
if ($info->boinc_vbox) {
show_download_button($info, true);
}
show_download_button($info, false);
}
}
if (0) {
$x = create_account(
"http://isaac.ssl.berkeley.edu/test/",
"http://foo.bar.com/test/",
"john@a.b.c",
"12345678901234567890123456789012",
"John Doe"
@ -106,14 +206,12 @@ function example1() {
print_r($x);
}
function example2() {
if (0) {
$x = lookup_account(
"http://isaac.ssl.berkeley.edu/test/",
"davea@ssl.berkeley.edu",
"http://foo.bar.com/test/",
"john@a.b.c",
"xxx"
);
print_r($x);
}
//example2();
?>

View File

@ -44,6 +44,16 @@
// 2) Put your project ID in a constant PROJECT_ID
// (this all works only for listed projects)
// Can also be called as a web RPC;
// see https://boinc.berkeley.edu/trac/wiki/WebRpc#download
// rpc this says it's an RPC
// user_agent web browser info
// authenticator the account to link to
// returns an XML doc of the form
// <download_info>
// [ <manual/> ] // not win or mac - tell user to visit BOINC download page
// <project_id>X</project_id>
require_once("../inc/util.inc");
require_once("../inc/account.inc");
@ -52,8 +62,7 @@ define("VBOX_DOWNLOAD_URL", "https://www.virtualbox.org/wiki/Downloads");
// take the user agent string reported by web browser,
// and return best guess for platform
//
function get_platform() {
global $user_agent;
function get_platform($user_agent) {
if (strstr($user_agent, 'Windows')) {
if (strstr($user_agent, 'Win64')||strstr($user_agent, 'WOW64')) {
return 'windows_x86_64';
@ -93,10 +102,9 @@ function is_windows() {
// find release version for user's platform
//
function get_version($dev) {
global $user_agent;
function get_version($user_agent, $dev) {
$v = simplexml_load_file("versions.xml");
$p = get_platform();
$p = get_platform($user_agent);
foreach ($v->version as $i=>$v) {
if ((string)$v->dbplatform != $p) {
continue;
@ -232,7 +240,7 @@ function direct_to_boinc() {
page_tail();
}
function show_download_page($user, $dev) {
function show_download_page($user, $user_agent, $dev) {
global $need_vbox, $project_id;
// If no project ID, we can't use simplified install
@ -241,7 +249,7 @@ function show_download_page($user, $dev) {
direct_to_boinc();
return;
}
$v = get_version($dev);
$v = get_version($user_agent, $dev);
// if we can't figure out the user's platform,
// take them to the download page on the BOINC site
@ -346,25 +354,94 @@ function installed() {
page_tail();
}
// RPC handler
//
function handle_get_info() {
require_once("../inc/xml.inc");
global $config, $user;
xml_header();
$rpc_key = get_str('rpc_key');
if ($rpc_key != parse_config($config, "<rpc_key>")) {
xml_error(-1, "RPC key mismatch");
}
$user = BoincUser::lookup_auth(get_str('auth'));
if (!$user) {
xml_error(-1, "user not found");
}
$project_id = parse_config($config, '<project_id>');
if (!$project_id) {
xml_error(-1, "no project ID");
}
$user_agent = get_str('user_agent');
$v = get_version($user_agent, false);
if (!$v) {
xml_error(-1, "no version for platform");
}
$want_vbox = parse_bool($config, 'need_vbox')
|| parse_bool($config, 'recommend_vbox')
;
$token = make_login_token($user);
echo sprintf(
'<download_info>
<project_id>%s</project_id>
<token>%s</token>
<user_id>%d</user_id>
<platform>%s</platform>
<boinc>
<filename>%s</filename>
<size_mb>%s</size_mb>
<boinc_version>%s</boinc_version>
</boinc>
',
$project_id,
$token,
$user->id,
(string)$v->platform,
(string)$v->filename,
(string)$v->size_mb,
(string)$v->version_num
);
if ($v->vbox_filename && $want_vbox) {
echo sprintf(
' <boinc_vbox>
<filename>%s</filename>
<size_mb>%s</size_mb>
<boinc_version>%s</boinc_version>
<vbox_version>%s</vbox_version>
</boinc_vbox>
',
(string)$v->vbox_filename,
(string)$v->vbox_size_mb,
(string)$v->version_num,
(string)$v->vbox_version
);
}
echo '</download_info>
';
}
// get config.xml items
//
$need_vbox = parse_bool($config, "need_vbox");
$recommend_vbox = parse_bool($config, "recommend_vbox");
$project_id = parse_config($config, "<project_id>");
$user = get_logged_in_user();
$action = get_str("action", true);
$dev = get_str("dev", true);
$user_agent = get_str("user_agent", true); // for debugging
if (!$user_agent) {
$user_agent = $_SERVER['HTTP_USER_AGENT'];
}
if ($action == "installed") {
installed();
} else if ($action == 'get_info') {
handle_get_info();
} else {
show_download_page($user, $dev);
$dev = get_str("dev", true);
$user_agent = get_str("user_agent", true); // for debugging
if (!$user_agent) {
$user_agent = $_SERVER['HTTP_USER_AGENT'];
}
$user = get_logged_in_user();
show_download_page($user, $user_agent, $dev);
}
?>