/**
  * Returns the base URI.
  * The base URI is 'protocol://server.name:port'
  * @return string
  */
 public static function urlbase()
 {
     if (is_null(self::$URLBASE)) {
         //DAV::debug('$_SERVER: ' . var_export($_SERVER, true));
         self::$URLBASE = REST::urlbase() . '/4/';
     }
     return self::$URLBASE;
 }
    if ($_SERVER['REQUEST_METHOD'] === 'PUT' && @$_GET['mode'] === 'create' && $handle->read()) {
        REST::fatal(REST::HTTP_PRECONDITION_FAILED, 'Handle exists.');
    } elseif ($_SERVER['REQUEST_METHOD'] === 'PUT' && @$_GET['mode'] === 'update' && !$handle->delete()) {
        REST::fatal(REST::HTTP_PRECONDITION_FAILED, 'Handle doesn\'t exist.');
    } else {
        $handle->delete();
    }
    // Store the data...
    $handle->create();
    // and return the proper response:
    switch ($_SERVER['REQUEST_METHOD']) {
        case 'PUT':
            REST::fatal(REST::HTTP_OK);
            break;
        case 'POST':
            REST::created(REST::urlbase() . CP::PORTAL_URL . urlencode($CP_PREFIX) . '/' . urlencode($CP_SUFFIX));
            break;
        default:
            // this shouldn't happen
            REST::fatal(REST::HTTP_INTERNAL_SERVER_ERROR);
    }
} elseif ($_SERVER['REQUEST_METHOD'] === 'DELETE') {
    $handle = new CP_Handle("{$CP_PREFIX}/{$CP_SUFFIX}");
    REST::fatal($handle->delete() ? REST::HTTP_OK : REST::HTTP_NOT_FOUND);
} else {
    // If we're here, the request method should be GET or HEAD. Otherwise, quit:
    REST::require_method('GET', 'HEAD');
    // Create a CP_Handle object...
    $handle = new CP_Handle("{$CP_PREFIX}/{$CP_SUFFIX}");
    // and read its contents from the database. If it's not there...
    if (!$handle->read()) {
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;
 }
    if (preg_match('/^(?:invalid pass phrase|No credentials exist for username .*)$/m', $output)) {
        REST::fatal(REST::HTTP_UNAUTHORIZED, 'Invalid username and/or pass phrase');
    }
    if ($returnval) {
        REST::fatal(REST::HTTP_BAD_REQUEST, '<pre>' . htmlentities($output) . '</pre>');
    }
    $escserver = Portal_MySQL::escape_string($_POST['server']);
    $escusername = Portal_MySQL::escape_string($_POST['username']);
    $escpassword = Portal_MySQL::escape_string($_POST['password']);
    Portal_MySQL::real_query("UPDATE `User` SET `proxy_server` = {$escserver}, `proxy_username` = {$escusername}, `proxy_password` = {$escpassword} WHERE `user_dn_md5` = '{$userdnmd5}'");
    $best_xhtml_type = REST::best_xhtml_type();
    $type = REST::best_content_type(array($best_xhtml_type => 1.0, 'text/plain' => 1.0), $best_xhtml_type);
    $relurl = REST::urlencode(dirname($_SERVER['REDIRECT_URL'])) . '/proxy';
    REST::header(array('status' => REST::HTTP_CREATED, 'Location' => REST::urlbase() . $relurl, 'Content-Type' => "{$type}; charset=UTF-8"));
    if ($type == 'text/plain') {
        echo REST::urlbase() . $relurl;
    } else {
        echo Portal::html_start('Proxy created') . "<p><a href=\"proxy\">proxy</a></p>" . Portal::html_end();
    }
    exit;
}
REST::header(REST::best_xhtml_type() . "; charset=UTF-8");
$default_server = getenv('MYPROXY_SERVER');
echo Portal::html_start("myProxy") . <<<EOS
<form action="./myproxy" method="post">
<table border="0" cellpadding="0" cellspacing="0"><tbody>
  <tr><td>Username</td><td><input type="text" name="username" /></td></tr>
  <tr><td>Password</td><td><input type="password" name="password" /></td></tr>
  <tr><td>MyProxy server</td><td><input type="text" name="server" value="{$default_server}" /></td></tr>
  <tr><td>&nbsp;</td><td><input type="submit" value="Delegate" /></td></tr>
</tbody></table>
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();
);
        } catch (Portal_MySQL_Exception $e) {
            unlink($tmpfilename);
            REST::fatal(REST::HTTP_CONFLICT, "Can't overwrite existing file: name={$dbname}, version={$dbversion}, type={$_POST['type']}");
        }
        $insert_id = Portal_MySQL::mysql()->insert_id;
        if (!rename($tmpfilename, Portal_DB::DATABASE_DIR . $insert_id)) {
            unlink($tmpfilename);
            Portal_MySQL::real_query("DELETE FROM `Database` WHERE `database_id` = {$insert_id}");
            REST::fatal(REST::HTTP_INTERNAL_SERVER_ERROR, "Couldn't store uploaded file.");
        }
        chmod(Portal_DB::DATABASE_DIR . $insert_id, 0660);
    }
    $extension = Portal_DB::databaseTypeExtension($typeId);
    $htmlurl = "{$insert_id}.{$extension}";
    $fullurl = REST::urlbase() . $_SERVER['REDIRECT_URL'] . $htmlurl;
    $content_type = REST::best_content_type(array(REST::best_xhtml_type() => 1.0, 'text/plain' => 0.5), 'text/plain');
    if ($content_type == 'text/plain') {
        REST::header(array('status' => REST::HTTP_CREATED, 'Location' => $fullurl, 'Content-Type' => 'text/plain; charset=US-ASCII'));
        echo $fullurl;
        exit;
    }
    REST::header(array('status' => REST::HTTP_CREATED, 'Location' => $fullurl, 'Content-Type' => REST::best_xhtml_type() . '; charset=US-ASCII'));
    echo Portal::html_start('New database created') . "<a href=\"{$htmlurl}\" rel=\"child\" rev=\"index\">{$htmlurl}</a>" . Portal::html_end();
    exit;
}
REST::require_method('GET', 'HEAD');
$options = '';
foreach (Portal_DB::databaseTypeIDs() as $databaseTypeID) {
    $databaseTypeName = Portal_DB::databaseTypeName($databaseTypeID);
    $options .= "\n<option value=\"{$databaseTypeName}\">{$databaseTypeName}</option>";