\n";
if (!isset($this_user)) {
SpitVerifyModal("verify_modal", "Create");
if ($newuser) {
if (is_string($newuser)) {
$stuffing = $newuser;
}
else {
$stuffing = substr(GENHASH(), 0, 16);
}
mail($formfields["email"],
"Confirm your email to create your Experiment",
"Here is your user verification code. Please copy and\n".
"paste this code into the box on the experiment page.\n\n".
" $stuffing\n",
"From: $TBMAIL_OPS");
echo "";
}
}
echo "\n";
SpitTopologyViewModal("quickvm_topomodal", $profile_array);
echo "\n";
echo "";
}
if (!isset($create)) {
$defaults = array();
$defaults["username"] = "";
$defaults["email"] = "";
$defaults["sshkey"] = "";
$defaults["profile"] = (isset($profile) ? $profile : $profile_default);
#
# Look for current user or cookie that tells us who the user is.
#
if ($this_user) {
$defaults["username"] = $this_user->uid();
$defaults["email"] = $this_user->email();
}
elseif (isset($_COOKIE['quickvm_user'])) {
$geniuser = GeniUser::Lookup("sa", $_COOKIE['quickvm_user']);
if ($geniuser) {
#
# Look for existing quickvm. User not allowed to create
# another one.
#
$instance = Instance::LookupByCreator($geniuser->uuid());
if ($instance && $instance->status() != "terminating") {
header("Location: status.php?uuid=" . $instance->uuid());
return;
}
$defaults["username"] = $geniuser->name();
$defaults["email"] = $geniuser->email();
$defaults["sshkey"] = $geniuser->SSHKey();
}
}
SPITFORM($defaults, false, array());
SPITFOOTER();
return;
}
#
# Otherwise, must validate and redisplay if errors
#
$errors = array();
$args = array();
if (!$this_user) {
#
# These check do not matter for a logged in user; we ignore the values.
#
if (!isset($formfields["email"]) || $formfields["email"] == "") {
$errors["email"] = "Missing Field";
}
elseif (! TBvalid_email($formfields["email"])) {
$errors["email"] = TBFieldErrorString();
}
if (!isset($formfields["username"]) || $formfields["username"] == "") {
$errors["username"] = "Missing Field";
}
elseif (! TBvalid_uid($formfields["username"])) {
$errors["username"] = TBFieldErrorString();
}
elseif (User::LookupByUid($formfields["username"])) {
# Do not allow uid overlap with real users.
$errors["username"] = "Already in use";
}
}
if (!isset($formfields["profile"]) || $formfields["profile"] == "") {
$errors["profile"] = "No selection made";
}
elseif (! array_key_exists($formfields["profile"], $profile_array)) {
$errors["profile"] = "Invalid Profile: " . $formfields["profile"];
}
if (count($errors)) {
SPITFORM($formfields, false, $errors);
SPITFOOTER();
return;
}
#
# More sanity checks.
#
if (!$this_user) {
$geniuser = GeniUser::LookupByEmail("sa", $formfields["email"]);
if ($geniuser) {
if ($geniuser->name() != $formfields["username"]) {
$errors["email"] = "Already in use by another user";
unset($geniuser);
}
}
}
# Existing guest users are allowed to resuse their ssh key, but can supply
# a new one if they want.
if (!isset($formfields["sshkey"]) || $formfields["sshkey"] == "") {
if (!($geniuser || $this_user)) {
$errors["sshkey"] = "Missing Field";
}
}
else {
$args["sshkey"] = $formfields["sshkey"];
}
if (count($errors)) {
SPITFORM($formfields, false, $errors);
SPITFOOTER();
return;
}
# Silently ignore the form for a logged in user.
$args["username"] = ($this_user ? $this_user->uid() : $formfields["username"]);
$args["email"] = ($this_user ? $this_user->email() : $formfields["email"]);
$args["profile"] = $formfields["profile"];
#
# See if user exists and is verified. We send email with a code, which
# they have to paste back into a box we add to the form. See above.
#
# We also get here if the user exists, but the browser did not have
# the tokens, as will happen if switching to another browser. We
# force the user to repeat the verification with the same code we
# have stored in the DB.
#
if (!$this_user &&
(!$geniuser || !isset($_COOKIE['quickvm_authkey']) ||
$_COOKIE['quickvm_authkey'] != $geniuser->auth_token())) {
if (isset($stuffing) && $stuffing != "") {
if (! (isset($verify) && $verify == $stuffing)) {
SPITFORM($formfields, $stuffing, $errors);
SPITFOOTER();
return;
}
#
# If this is an existing user and they give us the right code,
# we can check again for an existing VM and redirect to the
# status page, like we do above.
#
if ($geniuser) {
$instance = Instance::LookupByCreator($geniuser->uuid());
if ($instance && $instance->status() != "terminating") {
header("Location: status.php?uuid=" . $instance->uuid());
return;
}
}
# Pass to backend to save in user object.
$args["auth_token"] = $stuffing;
}
else {
# Existing user, use existing auth token.
# New user, we create a new one.
$token = ($geniuser ? $geniuser->auth_token() : true);
SPITFORM($formfields, $token, $errors);
SPITFOOTER();
return;
}
}
#
# This is so we can look up the slice after the backend creates it.
# We tell the backend what uuid to use.
#
$quickvm_uuid = NewUUID();
#
# Generate a temporary file and write in the XML goo.
#
$xmlname = tempnam("/tmp", "quickvm");
if (! $xmlname) {
TBERROR("Could not create temporary filename", 0);
$errors["internal"] = "Transient error(1); please try again later.";
}
elseif (! ($fp = fopen($xmlname, "w"))) {
TBERROR("Could not open temp file $xmlname", 0);
$errors["internal"] = "Transient error(2); please try again later.";
}
else {
fwrite($fp, "\n");
foreach ($args as $name => $value) {
fwrite($fp, "");
fwrite($fp, " " . htmlspecialchars($value) . "");
fwrite($fp, "\n");
}
fwrite($fp, "\n");
fclose($fp);
chmod($xmlname, 0666);
}
if (count($errors)) {
SPITFORM($formfields, false, $errors);
SPITFOOTER();
return;
}
#
# Invoke the backend. This will create the user and the slice record
# in the SA database, and then fork off in the background. If the
# first part works, we can return to the user and use some nifty ajax
# and javascript to watch for progress. We use a cookie that holds
# the slice uuid so that the JS code can ask about it.
#
# This option is used to tell the backend that it is okay to look
# in the emulab users table.
#
$opt = ($this_user ? "-l" : "");
$retval = SUEXEC("nobody", "nobody",
"webquickvm $opt -u $quickvm_uuid $xmlname",
SUEXEC_ACTION_CONTINUE);
if ($retval != 0) {
if ($retval < 0) {
$errors["error"] = "Transient error(3); please try again later.";
}
else {
if (count($suexec_output_array)) {
$line = $suexec_output_array[$i];
$errors["error"] = $line;
}
else {
$errors["error"] = "Transient error(4); please try again later.";
}
}
SPITFORM($formfields, false, $errors);
SPITFOOTER();
return;
}
unlink($xmlname);
$instance = Instance::Lookup($quickvm_uuid);
if (!$instance) {
$errors["error"] = "Transient error(5); please try again later.";
SPITFORM($formfields, false, $errors);
SPITFOOTER();
return;
}
if ($this_user) {
$creator = $this_user;
}
else {
$creator = GeniUser::Lookup("sa", $instance->creator_uuid());
}
if (! $creator) {
$errors["error"] = "Transient error(6); please try again later.";
SPITFORM($formfields, false, $errors);
SPITFOOTER();
return;
}
#
# Remember the user and auth key so that we can verify.
#
# The cookie handling is a pain since we run this under the aptlab
# virtual host, but the config uses a different domain, and so the
# cookies do not work. So, we have to look at our SERVER_NAME and
# set the cookie appropriately.
#
if (!$this_user) {
$cookiedomain = $TBAUTHDOMAIN;
setcookie("quickvm_user",
$creator->uuid(), time() + (24 * 3600 * 30),
"/", $cookiedomain, 0);
setcookie("quickvm_authkey",
$creator->auth_token(), time() + (24 * 3600 * 30),
"/", $cookiedomain, 0);
}
header("Location: status.php?uuid=" . $instance->uuid());
?>