#!/usr/bin/env php . // 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"; exit; } // set the following to 1 to print queries but not do anything $dry_run = 0; function lookup_team_seti_id($id) { $result = mysql_query("select * from team where seti_id=$id"); if ($result) { $team = mysql_fetch_object($result); mysql_free_result($result); return $team; } return null; } function parse_team($f) { while ($s = fgets($f)) { if (strstr($s, '')) { $t->name = htmlspecialchars_decode($t->name); $t->url = htmlspecialchars_decode($t->url); $t->name_html = htmlspecialchars_decode($t->name_html); $t->description = htmlspecialchars_decode($t->description); $t->user_name = htmlspecialchars_decode($t->user_name); $t->user_country = htmlspecialchars_decode($t->user_country); $t->user_postal_code = htmlspecialchars_decode($t->user_postal_code); $t->user_url = htmlspecialchars_decode($t->user_url); return $t; } else if (strstr($s, '')) $t->name = parse_element($s, ''); else if (strstr($s, '')) $t->url = parse_element($s, ''); else if (strstr($s, '')) $t->type = parse_element($s, ''); else if (strstr($s, '')) $t->name_html = parse_element($s, ''); else if (strstr($s, '')) { while ($s = fgets($f)) { if (strstr($s, '')) break; $t->description .= $s; } } else if (strstr($s, '')) $t->country = parse_element($s, ''); else if (strstr($s, '')) $t->id = parse_element($s, ''); else if (strstr($s, '')) { $user_email_munged = parse_element($s, ''); $t->user_email = str_rot13($user_email_munged); } else if (strstr($s, '')) $t->user_name = parse_element($s, ''); else if (strstr($s, '')) $t->user_country = parse_element($s, ''); else if (strstr($s, '')) $t->user_postal_code = parse_element($s, ''); else if (strstr($s, '')) $t->user_url = parse_element($s, ''); } 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 = "update team set url='$url', type=$t->type, name_html='$name_html', description='$description', country='$country', seti_id=$t->id where id=$team->id"; if ($dry_run) { echo " $query\n"; return; } $retval = mysql_query($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(mysql_real_escape_string($t->user_email), mysql_real_escape_string($t->user_name), random_string()); if (!$user) { echo " Can't make user $t->user_email\n"; echo mysql_error(); exit; } } 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 mysql_error(); echo "\n"; exit; } mysql_query("update team set seti_id=$t->id where id=$team->id"); mysql_query("update user set teamid=$team->id where id=$user->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 = lookup_user_email_addr($t->user_email); $team = lookup_team_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, '')) { handle_team($f); } } echo "------------ Finished at ".time_str(time())."-------\n"; } db_init(); main(); ?>