From 43e277c82a14bf5696ac1f399179aff2ce8927d7 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Fri, 22 Jan 2021 00:47:02 -0800 Subject: [PATCH] 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. --- html/inc/web_rpc_api.inc | 114 +++++++++++++++++++++++++++++--- html/user/download_software.php | 107 +++++++++++++++++++++++++----- 2 files changed, 198 insertions(+), 23 deletions(-) diff --git a/html/inc/web_rpc_api.inc b/html/inc/web_rpc_api.inc index 0587c613f6..6dca1b9895 100644 --- a/html/inc/web_rpc_api.inc +++ b/html/inc/web_rpc_api.inc @@ -17,6 +17,8 @@ // along with BOINC. If not, see . // 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(' +
+ + + + + +', + (string)$desc->boinc_version, + (string)$desc->vbox_version + ); + } else { + echo sprintf(' +
BOINC %s + +', + (string)$desc->boinc_version + ); + } + echo '
+'; + } + + echo "If BOINC is already installed on this computer, + go here; 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 here + 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(); ?> diff --git a/html/user/download_software.php b/html/user/download_software.php index 692705ea48..2cf953c84f 100644 --- a/html/user/download_software.php +++ b/html/user/download_software.php @@ -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 +// +// [ ] // not win or mac - tell user to visit BOINC download page +// X + 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, "")) { + 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, ''); + 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( +' + %s + %s + %d + %s + + %s + %s + %s + +', + $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( +' + %s + %s + %s + %s + +', + (string)$v->vbox_filename, + (string)$v->vbox_size_mb, + (string)$v->version_num, + (string)$v->vbox_version + ); + } + echo ' +'; +} + // get config.xml items // $need_vbox = parse_bool($config, "need_vbox"); $recommend_vbox = parse_bool($config, "recommend_vbox"); $project_id = parse_config($config, ""); -$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); } ?>