1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276
|
#!/usr/bin/env php
<?php
// This file is part of BOINC.
// http://boinc.berkeley.edu
// Copyright (C) 2008 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/>.
// fetch a list of "BOINC-wide teams" and create or update them
$cli_only = true;
require_once("../inc/util_ops.inc");
require_once("../inc/user.inc");
require_once("../inc/team.inc");
require_once("../inc/email.inc");
require_once("../project/project.inc");
if (defined('INVITE_CODES')) {
echo "Account creation is protected by invitation codes, so not importing teams";
exit;
}
$config = get_config();
if (parse_bool($config, "disable_account_creation")) {
echo "Account creation is disabled\n";
exit;
}
// set the following to 1 to print queries but not do anything
$dry_run = 0;
function lookup_team_seti_id($seti_id) {
return BoincTeam::lookup("seti_id=$seti_id");
}
function decode($x) {
return html_entity_decode($x, ENT_COMPAT, 'UTF-8');
}
function parse_team($f) {
$t = new stdClass();
while ($s = fgets($f)) {
if (strstr($s, '</team>')) {
$t->name = decode($t->name);
$t->url = decode($t->url);
$t->name_html = decode($t->name_html);
$t->description = decode($t->description);
$t->user_name = decode($t->user_name);
$t->user_country = decode($t->user_country);
$t->user_postal_code = decode($t->user_postal_code);
$t->user_url = decode($t->user_url);
return $t;
}
else if (strstr($s, '<name>')) $t->name = parse_element($s, '<name>');
else if (strstr($s, '<url>')) $t->url = parse_element($s, '<url>');
else if (strstr($s, '<type>')) $t->type = parse_element($s, '<type>');
else if (strstr($s, '<name_html>')) $t->name_html = parse_element($s, '<name_html>');
else if (strstr($s, '<description>')) {
while ($s = fgets($f)) {
if (strstr($s, '</description>')) break;
$t->description .= $s;
}
}
else if (strstr($s, '<country>')) $t->country = parse_element($s, '<country>');
else if (strstr($s, '<id>')) $t->id = parse_element($s, '<id>');
else if (strstr($s, '<user_email_munged>')) {
$user_email_munged = parse_element($s, '<user_email_munged>');
$t->user_email = str_rot13($user_email_munged);
}
else if (strstr($s, '<user_name>')) $t->user_name = parse_element($s, '<user_name>');
else if (strstr($s, '<user_country>')) $t->user_country = parse_element($s, '<user_country>');
else if (strstr($s, '<user_postal_code>')) $t->user_postal_code = parse_element($s, '<user_postal_code>');
else if (strstr($s, '<user_url>')) $t->user_url = parse_element($s, '<user_url>');
}
return null;
}
function valid_team($t) {
if (!$t->id) return false;
if (!$t->name) return false;
if (!$t->user_email) return false;
if (!$t->user_name) return false;
return true;
}
function update_team($t, $team, $user) {
global $dry_run;
if (
trim($t->url) == $team->url
&& $t->type == $team->type
&& trim($t->name_html) == $team->name_html
&& trim($t->description) == $team->description
&& $t->country == $team->country
&& $t->id == $team->seti_id
) {
echo " no changes\n";
return;
}
echo " updating\n";
$url = BoincDb::escape_string($t->url);
$name_html = BoincDb::escape_string($t->name_html);
$description = BoincDb::escape_string($t->description);
$country = BoincDb::escape_string($t->country);
$query = "url='$url', type=$t->type, name_html='$name_html', description='$description', country='$country', seti_id=$t->id";
if ($dry_run) {
echo " update to team $team->id: $query\n";
return;
}
$retval = $team->update($query);
if (!$retval) {
echo " update failed: $query\n";
exit;
}
}
function insert_case($t, $user) {
global $master_url;
global $dry_run;
if ($dry_run) {
if (!$user) echo " making user $t->user_email\n";
echo " making team $t->name\n";
return;
}
if (!$user) {
echo " making user $t->user_email\n";
$user = make_user($t->user_email, $t->user_name, random_string());
if (!$user) {
echo " Can't make user $t->user_email\n";
return;
}
}
echo " making team $t->name\n";
$team = make_team(
$user->id, $t->name, $t->url, $t->type, $t->name_html,
$t->description, $t->country
);
if (!$team) {
echo " Can't make team $t->id\n";
echo BoincDb::error();
echo "\n";
exit;
}
$team->update("seti_id=$t->id");
$user->update("teamid=$team->id");
send_email($user, "Team created on ".PROJECT,
"An instance of the BOINC-wide team '$t->name'
has been created on the project:
name: ".PROJECT."
URL: $master_url
"
);
}
// There are several cases for a given record:
// (note: "ID" means the ID coming from BOINC, stored locally in seti_id)
// insert case:
// There's no team with given name; create one,
// and create the user if needed
// update1 case:
// There's a team with the given name and the given ID
// and its founder has the right email address.
// Update its parameters if any are different.
// update2 case:
// There's a team with the given name and seti_id=0,
// and its founder has the right email address.
// Update its parameters if any are different,
// and set its seti_id.
// This handles the case where the team founder created the team
// before this new system was run.
// conflict case:
// There's a team with the given name,
// and either it has the wrong ID
// or its founder has a different email address.
// Don't change anything.
// These semantics mean that:
// - A BOINC team can't change its name via this mechanism.
// This avoids pathological cases, e.g. if two teams swapped names,
// the updates would always fail.
// If a BOINC team wants to change its name,
// it must do it manually everywhere.
// - If a BOINC team changes its founder (or the founder changes email)
// they'll have to make this change manually on all projects.
// (this is better than a security vulnerability)
// - This mechanism can't be used to update the founder's
// account parameters on all projects
function handle_team($f) {
$t = parse_team($f);
if (!$t) {
echo "Failed to parse team\n";
return;
}
//print_r($t);
//return;
if (!valid_team($t)) {
echo "Invalid team\n";
return;
}
echo "Processing $t->name $t->user_email\n";
$user = BoincUser::lookup_email_addr($t->user_email);
$team = BoincTeam::lookup_name($t->name);
if ($team) {
if (!$user) {
echo " team exists but user $t->user_email doesn't\n";
return;
}
if ($user->id != $team->userid) {
echo " team exists but is owned by a different user\n";
return;
}
if ($team->seti_id) {
if ($team->seti_id == $t->id) {
echo " case 1\n";
update_team($t, $team, $user); // update1 case
} else {
echo " team exists but has wrong seti_id\n";
}
} else {
$team2 = lookup_team_seti_id($t->id);
if ($team2) {
// update1 case
echo " case 2\n";
update_team($t, $team2, $user);
} else {
// update2 case
echo " case 3\n";
update_team($t, $team, $user);
}
}
} else {
$team = lookup_team_seti_id($t->id);
if ($team) {
echo " A team with same ID but different name exists;\n";
echo " Please report this to $t->user_email;\n";
} else {
echo " Adding team\n";
insert_case($t, $user);
}
}
}
function main() {
echo "------------ Starting at ".time_str(time())."-------\n";
$f = fopen("http://boinc.berkeley.edu/boinc_teams.xml", "r");
if (!$f) {
echo "Can't get times file\n";
exit;
}
while ($s = fgets($f)) {
if (strstr($s, '<team>')) {
handle_team($f);
}
}
echo "------------ Finished at ".time_str(time())."-------\n";
}
db_init();
main();
?>
|