Topos::deleteTokenFile($jobid);
    Portal_MySQL::real_query(<<<EOS
DELETE FROM `Token`
 WHERE `token_id`={$escjobid}
   AND `user_id`={$escuserid};
EOS
);
    if (!Portal_MySQL::mysql()->affected_rows) {
        REST::fatal(REST::HTTP_NOT_FOUND);
    }
    REST::header(array('status' => REST::HTTP_NO_CONTENT));
    exit;
}
// The user tries to get information about eir jobs
if (file_exists($fullfilename = Portal::JOBRESULTS_DIR . $jobid)) {
    REST::redirect(REST::HTTP_SEE_OTHER, Portal::portalURL() . "jobresults/{$jobid}");
}
$result = Portal_MySQL::query(<<<EOS
SELECT `token_error` 
  FROM `Token`
 WHERE `token_id`={$escjobid}
   AND `user_id`={$escuserid};
EOS
);
if (!($row = $result->fetch_row())) {
    // Can't find what the user is looking for
    REST::fatal(REST::HTTP_GONE);
}
if (empty($row[0])) {
    REST::fatal(REST::HTTP_NOT_FOUND, "<p>Your job hasn't been executed yet. Try again later.</p>");
}
    REST::fatal(REST::HTTP_BAD_REQUEST, 'Missing (one of) required parameters "email" and "password"');
}
$dn = Portal_User::csa_dn();
if (empty($dn)) {
    REST::fatal(REST::HTTP_NOT_FOUND);
}
$escemail = Portal_MySQL::escape_string($_GET['email']);
$md5password = md5($_GET['password']);
$escdn = Portal_MySQL::escape_string($dn);
Portal_MySQL::real_query(<<<EOS
DELETE FROM `User`
WHERE `user_dn` = {$escdn}
  AND `user_email` <> {$escemail};
EOS
);
Portal_MySQL::real_query(<<<EOS
UPDATE `User`
SET `user_dn` = {$escdn}
WHERE `user_email` = {$escemail}
  AND `user_password` = '{$md5password}';
EOS
);
if (!Portal_MySQL::mysql()->affected_rows) {
    Portal_User::unauthorized();
}
$url = REST::htmlspecialchars(Portal::portalURL());
REST::fatal(REST::HTTP_OK, <<<EOS
<p>Registration complete.</p>
<p>You can now start <a href="{$url}">using the GridApps web service</a>.</p>
EOS
);
    $escemail = Portal_MySQL::escape_string($_GET['email']);
    $escname = Portal_MySQL::escape_string($_GET['name']);
    //  $dn = ($_SERVER['SERVER_PORT'] == Portal::PORT_SSL_CSA)
    //    ? Portal_User::csa_dn() : null;
    //  $escdn = Portal_MySQL::escape_string($dn);
    $password = Portal_User::createPassword();
    $md5password = md5($password);
    Portal_MySQL::real_query(<<<EOS
INSERT INTO `User` (`user_email`, `user_name`, `user_password`)
VALUES ({$escemail}, {$escname}, '{$md5password}')
ON DUPLICATE KEY UPDATE
  `user_name` = {$escname},
  `user_password` = '{$md5password}';
EOS
);
    $csa_confirm = 'https://' . $_SERVER['SERVER_NAME'] . ':' . Portal::PORT_SSL_CSA . Portal::portalURL() . 'csaconfirm?email=' . urlencode($_GET['email']) . '&password='******'email'], 'Access to ' . $_SERVER['SERVER_NAME'], <<<EOS
Hi {$_GET['name']},

These are the credentials you may use for the Grid Application Portal:

Login:    {$_GET['email']}
Password: {$password}

If you want to authenticate using a client certificate, please open a 
browser with your client certificate in it, and follow this link:
<{$csa_confirm}>

Best regards,

EOS
function myPilotJob($poolURL)
{
    $portal_jobs = REST::urlbase() . Portal::portalURL() . 'jobs/';
    return <<<EOS
#!/bin/bash
set -ex

SANDBOX="\${PWD}"
CURL="\${SANDBOX}/curl --silent --fail --insecure --cert \${X509_USER_PROXY} --retry 20"
TOPOS_POOL='{$poolURL}'
PORTAL_JOBS='{$portal_jobs}'
DOWNLOADED_APPLICATIONS=''
DOWNLOADED_DATABASES=''
INDIR="\${TMPDIR}/indir/"
OUTDIR="\${TMPDIR}/outdir/"
APPDIR="\${TMPDIR}/apps/"
DBDIR="\${TMPDIR}/dbs/"
export INDIR OUTDIR APPDIR

chmod 755 ./curl
mkdir \${APPDIR}
mkdir \${DBDIR}


function reportError {
  echo "\$1" |
  \${CURL} --upload-file - --header 'Content-Type: text/plain' "\${PORTAL_JOBS}\${TOKEN_ID}" &&
  \${CURL} -X DELETE "\${TOKEN_URL}" || true
  exit 0      # TODO: REMOVE THIS
}


while true; do
  TOKEN_URL=\$(
    \${CURL} --header 'Accept: text/plain' \${TOPOS_POOL}nextToken
  )
  # [ "\${TOKEN_URL}" ] || exit 0;
  TOKEN_ID=\$( basename \${TOKEN_URL} )
  rm -rf \${INDIR} || true
  mkdir  \${INDIR}
  rm -rf \${OUTDIR} || true
  mkdir  \${OUTDIR}
  
  cd \${INDIR}
  TMPTAR=\$( mktemp -p \${TMPDIR} ).tar
  \${CURL} \${TOKEN_URL} > \${TMPTAR} || continue
  if ! tar xf \${TMPTAR}; then
    rm \${TMPTAR}
    reportError "The token in ToPoS isn't a valid tar file." 
    continue
  fi
  rm \${TMPTAR}
  
  if ! source ./run.sh; then
    reportError "Couldn't source ./run.sh." 
    continue
  fi
  
  if ! echo "\${DOWNLOADED_APPLICATIONS}" | grep -q -F "\${APPLICATION}"; then
    if ! \${CURL} "\${APPLICATION}" | tar -C \${APPDIR} -x -B; then
      reportError "Couldn't download and/or untar application \${APPLICATION}"
      continue
    fi
    DOWNLOADED_APPLICATIONS="\${DOWNLOADED_APPLICATIONS} \${APPLICATION}"
  fi
  
  export DBFILE=\${DBDIR}\$( basename "\${DATABASE}" )
  if ! echo "\${DOWNLOADED_DATABASES}" | grep -q -F "\${DATABASE}"; then
    if ! \${CURL} "\${DATABASE}" > "\${DBFILE}"; then
      reportError "Couldn't download database \${DATABASE}"
      continue
    fi
    DOWNLOADED_DATABASES="\${DOWNLOADED_DATABASES} \${DATABASE}"
  fi
  
  cd \${OUTDIR}
  ( runJob > pilotstdout.txt 2>pilotstderr.txt 2>&1 )
  STATUS=\$?
  cd \${OUTDIR}
  if [ \${STATUS} -eq 0 ]; then
    find -maxdepth 1 -mindepth 1 -print0 | xargs -0 tar cf \$TMPTAR
    if \${CURL} --header 'Content-Type: application/x-tar' --upload-file \$TMPTAR "\${PORTAL_JOBS}\${TOKEN_ID}"; then
      \${CURL} -X DELETE "\$TOKEN_URL" || true
    else
      reportError "Couldn't upload results to \${PORTAL_JOBS}\${TOKEN_ID}"
    fi
    rm \$TMPTAR
  else
    cat pilotstdout.txt >> pilotstderr.txt
    \${CURL} --upload-file pilotstderr.txt --header 'Content-Type: text/plain' "\${PORTAL_JOBS}\${TOKEN_ID}" || true;
    [ \${STATUS} -eq 2 ] && \${CURL} -X DELETE "\$TOKEN_URL" || true
  fi
done


EOS;
}
 /**
  * Never returns
  */
 public static function unauthorized()
 {
     if ($_SERVER['SERVER_PORT'] == Portal::PORT_PLAIN) {
         REST::redirect(REST::HTTP_TEMPORARY_REDIRECT, 'https://' . $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI']);
     }
     header('WWW-Authenticate: Basic realm="Grid Portal"');
     $register = REST::htmlspecialchars('https://' . $_SERVER['SERVER_NAME'] . Portal::portalURL() . 'register?referrer=' . urlencode(REST::urlbase() . $_SERVER['REQUEST_URI']));
     REST::fatal(REST::HTTP_UNAUTHORIZED, "<p>You can register <a href=\"{$register}\">here</a>.</p>");
     exit;
 }
EOS
);
    exec("cd '{$sandbox}'; find -mindepth 1 -maxdepth 1 -print0 | xargs -0 tar zcf {$TEMPNAM}.tgz", $output, $return_var);
    if ($return_var) {
        $output = implode("\n", $output);
        REST::fatal(REST::HTTP_INTERNAL_SERVER_ERROR, $output);
    }
    $tokenhandle = fopen("{$TEMPNAM}.tgz", 'r');
    try {
        $token_url = Topos::putTokenFile($tokenhandle, 'application/x-compressed-tar');
    } catch (Exception $e) {
        fclose($tokenhandle);
        throw $e;
    }
    fclose($tokenhandle);
    $token_id = basename($token_url);
    Portal_MySQL::real_query(<<<EOS
INSERT INTO `Token`
       ( `token_id`,  `user_id` )
VALUES ( {$token_id}, {$user_id} );
EOS
);
    $resultURL = REST::urlbase() . Portal::portalURL() . "jobstates/{$token_id}";
    REST::created($resultURL);
}
Portal_User::current();
REST::header(array('Content-Type' => REST::best_xhtml_type()));
echo Portal::html_start("{$appname}-{$appversion}") . '<form action="' . $appversion . '" method="post" enctype="multipart/form-data">';
$portlet->doGET();
echo '</form>' . Portal::html_end();
    /**
     * Get a list of available databases, given a set of database types.
     * @param $name... string the name(s) of the database types.
     * @return string an x fragment, to be put inside a select element.
     */
    public static function availableDatabases()
    {
        $dbTypes = func_get_args();
        if (empty($dbTypes)) {
            return array();
        }
        foreach ($dbTypes as $key => $value) {
            $dbTypes[$key] = self::databaseTypeIDByName($value);
        }
        $dbTypes = implode(',', $dbTypes);
        $user_id = Portal_User::current()->user_id();
        $result = Portal_MySQL::query(<<<EOS
SELECT `d`.`name`, `d`.`version`, `d`.`type`, `u`.`user_name`, `d`.`database_id`
  FROM `Database` AS d LEFT JOIN `User` AS u USING(`user_id`)
 WHERE (`d`.`is_shared` > 0 OR `d`.`user_id` = {$user_id})
   AND `d`.`type` IN({$dbTypes});
EOS
);
        $sorter = array();
        while ($row = $result->fetch_row()) {
            $extension = self::databaseTypeExtension($row[2]);
            $sorter[$row[3]]["{$row[0]}-{$row[1]}.{$extension}"] = REST::urlencode(Portal::portalURL() . 'databases/' . $row[0] . '/' . $row[1] . '/' . $row[4] . '.' . $extension);
        }
        $user_names = array_keys($sorter);
        natsort($user_names);
        $retval = '';
        foreach ($user_names as $user_name) {
            $retval .= "\n<optgroup label=\"" . htmlentities($user_name) . "\">";
            $dbnames = array_keys($sorter[$user_name]);
            natsort($dbnames);
            foreach ($dbnames as $dbname) {
                $retval .= "\n<option value=\"" . $sorter[$user_name][$dbname] . "\">{$dbname}</option>";
            }
            $retval .= "\n</optgroup>";
        }
        return $retval;
    }