/**
  * The mysql connection.
  * @return resource
  */
 public static function mysql()
 {
     if (is_null(self::$mysql)) {
         self::$mysql = new mysqli('localhost', 'portal', 'V0iiYF9C', 'portal_dev');
         if (!self::$mysql) {
             throw new Portal_MySQL_Exception(mysqli_connect_error());
         }
     }
     return self::$mysql;
 }
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 * $Id: jobstates.php 2490 2009-08-26 10:44:52Z pieterb $
 **************************************************************************/
/**
 * File documentation.
 * @package Portal
 */
require_once 'include/global.php';
REST::require_method('GET', 'HEAD');
$user_id = Portal_User::current()->user_id();
$resultDir = opendir(Portal::JOBRESULTS_DIR);
$resultFiles = array();
while (($file = readdir($resultDir)) !== false) {
    if (preg_match('/^\\d+$/', $file)) {
        $resultFiles[(int) $file] = (int) $file;
    }
}
closedir($resultDir);
$result = Portal_MySQL::query(<<<EOS
SELECT `token_id`, `token_error` = '' FROM `Token`
 WHERE `user_id` = {$user_id};
EOS
);
$directory = RESTDir::factory();
while ($row = $result->fetch_row()) {
    $directory->line($row[0], array('status' => isset($resultFiles[$row[0]]) ? 'Done' : ($row[1] ? 'Queued' : 'Error')));
}
$directory->end();
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 * $Id: jobresult.php 2471 2009-08-17 20:09:55Z pieterb $
 **************************************************************************/
/**
 * File documentation.
 * @package Portal
 */
require_once 'include/global.php';
REST::require_method('GET', 'HEAD', 'PUT');
$user_id = Portal_User::current()->user_id();
$path_info = Portal::path_info();
$jobid = $path_info[0];
$escjobid = Portal_MySQL::escape_string($jobid);
$escuserid = Portal_MySQL::escape_string($user_id);
if ($_SERVER['REQUEST_METHOD'] == 'PUT') {
    if (strpos(@$_SERVER['CONTENT_TYPE'], 'application/x-compressed-tar') !== 0) {
        REST::fatal(REST::HTTP_UNSUPPORTED_MEDIA_TYPE);
    }
    // The job wants to put its results on the portal server
    $tmpfilename = tempnam('/tmp', 'portal_');
    $tmpfile = fopen($tmpfilename, 'w');
    while (($block = fread(REST::inputhandle(), 8192)) !== "") {
        fwrite($tmpfile, $block);
    }
    fclose(REST::inputhandle());
    fclose($tmpfile);
    if (isset($_SERVER['CONTENT_LENGTH']) && $_SERVER['CONTENT_LENGTH'] != filesize($tmpfilename)) {
        unlink($tmpfilename);
        REST::fatal(REST::HTTP_BAD_REQUEST, "Content-Length header doesn't match actual content length.");
    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_OK, '<p>Your job finished with the following error:</p><pre>' . REST::htmlspecialchars($row[0]) . '</pre>');
    public static function recordRequest($url, $ip = '')
    {
        $user_id = Portal_MySQL::escape_string(Portal_User::current()->user_id());
        $esc_url = Portal_MySQL::escape_string($url);
        $esc_ip = Portal_MySQL::escape_string($ip);
        Portal_MySQL::real_query(<<<EOS
INSERT INTO `Statistics` (`requested_url`, `request_origin`, `user_id`)
     VALUES ({$esc_url}, {$esc_ip}, {$user_id});
EOS
);
    }
    $user_dn_md5 = Portal_MySQL::escape_string(basename($fullfilename, '.pem'));
    $result = Portal_MySQL::query(<<<EOS
SELECT `proxy_server`, `proxy_username`, `proxy_password` FROM `User`
 WHERE `user_dn_md5` = {$user_dn_md5};
EOS
);
    if ($row = $result->fetch_row()) {
        $escusername = escapeshellarg($row[1]);
        $escpassword = escapeshellarg($row[2]);
        $escserver = escapeshellarg($row[0]);
        exec("echo {$escpassword} | myproxy-logon -v -l {$escusername} -s {$escserver} -S -o {$escfullfilename} 2>&1", $output, $returnval);
        if ($returnval) {
            unlink($fullfilename);
            Portal_MySQL::query(<<<EOS
UPDATE `User` SET `proxy_server` = NULL, `proxy_username` = NULL, `proxy_password` = NULL
 WHERE `user_dn_md5` = {$user_dn_md5};
EOS
);
        }
    }
    //  exec("grid-proxy-info -f {$escfullfilename} -timeleft", $output, $returnval);
    //  if ((int)$output[0] <= 0) { // The proxy has expired completely
    //    unlink($fullfilename);
    //    Portal_MySQL::query(<<<EOS
    //UPDATE `User` SET `proxy_server` = NULL, `proxy_username` = NULL, `proxy_password` = NULL
    // WHERE `user_dn_md5` = '{$user_dn_md5}';
    //EOS
    //    );
    //  }
}
REST::header(array('status' => REST::HTTP_NO_CONTENT));
        REST::fatal(REST::HTTP_BAD_REQUEST, 'Missing required parameter "status"');
    }
    $status = (int) $_POST['status'];
    Portal_MySQL::real_query(<<<EOS
INSERT INTO `Usage` (`user_id`, `usage_seconds`, `token_id`, `usage_status`)
VALUES ({$userid}, {$seconds}, {$token}, {$status});
EOS
);
    REST::fatal(REST::HTTP_ACCEPTED);
}
REST::require_method('GET', 'HEAD');
$result = Portal_MySQL::query(<<<EOS
SELECT SUM(`usage_seconds`),
       DATE(`usage_timestamp`),
       `usage_status`
FROM `Usage`
WHERE `user_id` = {$userid}
GROUP BY 3,2
ORDER BY 3,2 ASC;
EOS
);
REST::header(REST::best_xhtml_type() . '; charset="UTF-8"');
echo REST::html_start('Usage statistics') . <<<EOS
<!--<form action="stats" method="post">
token: <input type="text" name="token" value=""/>
seconds: <input type="text" name="seconds" value=""/>
<input type="submit"/>
</form>-->
<table class="usagestats"><tbody>
<tr>
<th class="date">Date</th>
<th class="walltime">Walltime</th>
$options = '';
foreach (Portal_DB::databaseTypeIDs() as $databaseTypeID) {
    $databaseTypeName = Portal_DB::databaseTypeName($databaseTypeID);
    $options .= "\n<option value=\"{$databaseTypeName}\">{$databaseTypeName}</option>";
}
$directory = RESTDir::factory("{$path_info[0]}, version {$path_info[1]}")->setForm(<<<EOS
<h1>Database upload</h1>
<form method="post" action="./" enctype="multipart/form-data">
<input type="file" name="dbfile" /><br />
<input type="checkbox" name="shared" value="1" /> Share this database with others<br />
Database type: <select name="type">
{$options}
</select><br />
<input type="submit" value="Upload" />
</form>
EOS
);
$user_id = Portal_User::current()->user_id();
$result = Portal_MySQL::query(<<<EOS
SELECT `user_name`, `database_id`, `type` FROM `Database` LEFT JOIN `User` USING(`user_id`)
WHERE `name` = {$dbname}
  AND `version` = {$dbversion}
  AND ( `is_shared` > 0 OR `Database`.`user_id` = {$user_id})
ORDER BY 3, 1;
EOS
);
while ($row = $result->fetch_array()) {
    $filesize = filesize(Portal_DB::DATABASE_DIR . $row[1]);
    $directory->line($row[1] . '.' . Portal_DB::databaseTypeExtension($row[2]), array('Size' => filesize(Portal_DB::DATABASE_DIR . $row[1]) . ' B', 'DBType' => Portal_DB::databaseTypeName($row[2]), 'Creator' => $row[0], 'Content-Type' => Portal_DB::databaseTypeContentType($row[2])));
}
$directory->end();
    // Check the name:
    $_GET['name'] = preg_replace('/\\s+/', ' ', trim($_GET['name']));
    if ($_GET['name'] === '') {
        REST::fatal(REST::HTTP_BAD_REQUEST, '<p>Please provide a display name.</p>');
    }
    $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}>
    /**
     * @param bool $required
     * @return Portal_User
     */
    public static function current()
    {
        if (self::$current === null) {
            switch ($_SERVER['SERVER_PORT']) {
                case Portal::PORT_PLAIN:
                    self::unauthorized();
                    break;
                    // strictly unnecessary, but syntactically nicer.
                // strictly unnecessary, but syntactically nicer.
                case Portal::PORT_SSL:
                    if (!isset($_SERVER['PHP_AUTH_USER'])) {
                        self::unauthorized();
                    }
                    $user_email = Portal_MySQL::escape_string($_SERVER['PHP_AUTH_USER']);
                    $user_password = md5($_SERVER['PHP_AUTH_PW']);
                    $result = Portal_MySQL::query(<<<EOS
SELECT `user_id`, `user_name`, `user_dn` FROM `User`
WHERE `user_email`   =  {$user_email}
  AND `user_password`= '{$user_password}';
EOS
);
                    if (!($row = $result->fetch_row())) {
                        self::unauthorized();
                    }
                    self::$current = new Portal_User((int) $row[0], $_SERVER['PHP_AUTH_USER'], $row[1], $row[2]);
                    break;
                case Portal::PORT_SSL_CSA:
                    $user_dn = self::csa_dn();
                    if (isset($_SERVER['PHP_AUTH_USER']) && (int) $_SERVER['PHP_AUTH_USER'] > 0 && preg_match('@^/O=dutchgrid/O=users/O=sara/CN=(?:Evert Lammerts|Pieter van Beek)@', $_SERVER['SSL_CLIENT_S_DN'])) {
                        $esc_user_id = (int) $_SERVER['PHP_AUTH_USER'];
                        $result = Portal_MySQL::query(<<<EOS
SELECT `user_email`, `user_name`, `user_dn` FROM `User`
WHERE `user_id` = {$esc_user_id};
EOS
);
                        if (!($row = $result->fetch_row())) {
                            REST::fatal(REST::HTTP_UNAUTHORIZED, "No such user id: {$esc_user_id}");
                        }
                        self::$current = new Portal_User($esc_user_id, $row[1], $row[0], $row[2], true);
                    } else {
                        $esc_user_dn = Portal_MySQL::escape_string($user_dn);
                        $result = Portal_MySQL::query(<<<EOS
SELECT `user_id`, `user_email`, `user_name` FROM `User`
WHERE `user_dn` =  {$esc_user_dn};
EOS
);
                        if (!($row = $result->fetch_row())) {
                            self::unauthorized();
                        }
                        self::$current = new Portal_User($row[0], $row[2], $row[1], $user_dn);
                    }
                    break;
                default:
                    REST::fatal(REST::HTTP_INTERNAL_SERVER_ERROR);
            }
        }
        return self::$current;
    }
    $username = escapeshellarg(trim($_POST['username']));
    $password = escapeshellarg(trim($_POST['password']));
    $server = escapeshellarg(trim($_POST['server']));
    $filename = escapeshellarg(Portal::PROXY_DIR . $userdnmd5 . '.pem');
    exec("echo {$password} | myproxy-logon -v -l {$username} -s {$server} -S -o {$filename} 2>&1", $output, $returnval);
    $output = implode("\n", $output);
    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">
 * not use this file except in compliance with the License. You may obtain
 * a copy of the License at <http://www.apache.org/licenses/LICENSE-2.0>
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 * $Id: databases_versions.php 2459 2009-08-10 21:20:41Z pieterb $
 **************************************************************************/
/**
 * File documentation.
 * @package Portal
 */
require_once 'include/global.php';
REST::require_method('GET', 'HEAD');
$user_id = Portal_User::current()->user_id();
$path_info = Portal::path_info();
$dbname = Portal_MySQL::escape_string($path_info[0]);
$result = Portal_MySQL::query(<<<EOS
SELECT DISTINCT(`version`) FROM `Database`
WHERE `name` = {$dbname}
  AND ( `is_shared` > 0 OR `user_id` = {$user_id} );
EOS
);
$directory = RESTDir::factory("{$path_info['0']}: available versions");
while ($row = $result->fetch_row()) {
    $directory->line($row[0] . '/');
}
$directory->end();
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();
}
REST::require_method('GET', 'HEAD');
$path_info = Portal::path_info();
if (count($path_info) != 3) {
    REST::fatal(REST::HTTP_NOT_FOUND);
}
$file = explode('.', $path_info[2], 2);
if (!($database_id = (int) $file[0])) {
    REST::fatal(REST::HTTP_NOT_FOUND);
}
$user_id = Portal_User::current()->user_id();
$result = Portal_MySQL::query(<<<EOS
SELECT `d`.`name`,
       `d`.`version`,
       `d`.`type`,
       `d`.`checksum`,
       `u`.`user_name`
  FROM `Database` AS d LEFT JOIN `User` AS u USING(`user_id`)
 WHERE `d`.`database_id` = {$database_id}
   AND (`d`.`user_id` = {$user_id} OR `d`.`is_shared` = 1);
EOS
);
if (!($row = $result->fetch_row())) {
    REST::fatal(REST::HTTP_NOT_FOUND);
}
$fileinfo = @stat($realfilepath);
$filename = "{$row[0]}-{$row[1]}." . Portal_DB::databaseTypeExtension($row[2]);
REST::header(array('Content-Type' => Portal_DB::databaseTypeContentType($row[2]), 'Content-Encoding' => 'identity', 'Content-Disposition' => "attachment; filename=\"{$filename}\"", 'Last-Modified' => REST::http_date($fileinfo['mtime']), 'ETag' => "\"{$row[3]}\"", 'X-Creator-Name' => $row[4], 'Content-Length' => $fileinfo['size']));
if ($_SERVER['REQUEST_METHOD'] == 'GET') {
    readfile($realfilepath);
}
 * Licensed under the Apache License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License. You may obtain
 * a copy of the License at <http://www.apache.org/licenses/LICENSE-2.0>
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 * $Id: databases.php 2459 2009-08-10 21:20:41Z pieterb $
 **************************************************************************/
/**
 * File documentation.
 * @package Portal
 */
require_once 'include/global.php';
REST::require_method('GET', 'HEAD');
$user_id = Portal_User::current()->user_id();
$result = Portal_MySQL::query(<<<EOS
SELECT DISTINCT `name` FROM `Database`
WHERE `is_shared` > 0
   OR `user_id` = {$user_id}
EOS
);
$action = REST::htmlspecialchars($_SERVER['REQUEST_URI']);
$directory = RESTDir::factory('Available databases (by name)');
while ($row = $result->fetch_row()) {
    $directory->line($row[0] . '/');
}
$directory->end();
    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
);
    /**
     * 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;
    }