All new accounts created on Gitlab now require administrator approval. If you invite any collaborators, please let Flux staff know so they can approve the accounts.

Commit a70c2716 authored by Kevin Atkinson's avatar Kevin Atkinson

Merge branch 'exp-vis'.

This adds experimental support for experiment visualization.  It
currently is a Utah only features and is thus guarded by the
EXP_VIS_SUPPORT site variable, and also requires some changes to
httpd.conf on ops which are not committed.

The experiment visualization support allows users to create basic
per-experiment or per-project web pages by putting an index.html file
in /proj/PROJ/www/exp-vis/EXP, or /proj/PROJ/www/group-vis.  The web
pages can then be accessed via the "(User) Visualization" tab in the
experient or project web page or directly via
https://users.emulab.net/exp-vis/PROJ/EXP, or /proj-vis/PROJ.  A proxy
is used so that only project members can access the web page.  Some
support for per-group vis. is also provided (use
/group-vis/PROJ/GROUP).
parents 231b5953 5f71ab30
......@@ -90,3 +90,5 @@ HAVE_ULXMLRPCPP = @HAVE_ULXMLRPCPP@
STANDALONE_CLEARINGHOUSE = @STANDALONE_CLEARINGHOUSE@
NODE_USAGE_SUPPORT = @NODE_USAGE_SUPPORT@
EXP_VIS_SUPPORT = @EXP_VIS_SUPPORT@
......@@ -12,6 +12,9 @@ SUBDIR = collab
include $(OBJDIR)/Makeconf
SUBDIRS = mailman cvstools jabber trac
ifeq ($(EXP_VIS_SUPPORT),1)
SUBDIRS += exp-vis
endif
all: all-subdirs
......@@ -31,6 +34,9 @@ post-install:
@$(MAKE) -C cvstools post-install
@$(MAKE) -C jabber post-install
@$(MAKE) -C trac post-install
ifeq ($(EXP_VIS_SUPPORT),1)
@$(MAKE) -C exp-vis post-install
endif
# How to recursively descend into subdirectories to make general
# targets such as `all'.
......
#
# EMULAB-COPYRIGHT
# Copyright (c) 2009 University of Utah and the Flux Group.
# All rights reserved.
#
SRCDIR = @srcdir@
TESTBED_SRCDIR = @top_srcdir@
OBJDIR = ../..
SUBDIR = collab/exp-vis
include $(OBJDIR)/Makeconf
CGI_SCRIPTS = fetch-vis
LIBEXEC_SCRIPTS = write-vis-auth
CTRL_LIBEXEC_SCRIPTS = write-vis-auth.proxy
SETUID_LIBX_SCRIPTS = write-vis-auth
#
# Force dependencies on the scripts so that they will be rerun through
# configure if the .in file is changed.
#
all: $(CGI_SCRIPTS) $(LIBEXEC_SCRIPTS) $(CTRL_LIBEXEC_SCRIPTS)
include $(TESTBED_SRCDIR)/GNUmakerules
install: \
$(addprefix $(INSTALL_LIBEXECDIR)/, $(LIBEXEC_SCRIPTS)) \
$(addprefix $(TBROOT)/opsdir/www/cgi-bin/, $(CGI_SCRIPTS)) \
$(addprefix $(INSTALL_DIR)/opsdir/libexec/, $(CTRL_LIBEXEC_SCRIPTS))
$(TBROOT)/opsdir/www/cgi-bin/fetch-vis: fetch-vis
-$(SUDO) mkdir -m 775 $(TBROOT)/opsdir/www/cgi-bin
$(SUDO) $(INSTALL) -o root -m 4775 $< $@
$(INSTALL_DIR)/opsdir/libexec/write-vis-auth.proxy: write-vis-auth.proxy
-mkdir -p $(INSTALL_DIR)/opsdir/libexec
$(INSTALL) $< $@
post-install:
clean:
#!/usr/bin/perl -T
#
#
#
use strict;
use warnings;
use POSIX qw(setuid setgid);
use Cwd qw(realpath);
use CGI;
use CGI::Cookie;
use HTTP::Date;
#use Data::Dumper;
#print "\n\n";
#print STDERR Dumper(\%ENV);
my $FSDIR_PROJ = "@FSDIR_PROJ@";
my $FSDIR_GROUPS = "@FSDIR_GROUPS@";
sub error($) {
print "Content-Type: text/plain\n";
print "Status: 404 Not Found\n\n";
print "$_[0]\n";
#die "$_[0]\n";
exit 1;
}
my $SCRIPT_URL = $ENV{REQUEST_URI};
# Parse URL
my ($proj,$group,$exp,$dir,$file);
local $_ = $SCRIPT_URL;
if (/^\/proj-vis\/([a-zA-Z0-9-]+)\/?(.*)$/) {
$proj = $1;
$group = $1;
$file = $2;
} elsif (/^\/group-vis\/([a-zA-Z0-9-]+)\/?([a-zA-Z0-9-]+)\/?(.*)$/) {
$proj = $1;
$group = $2;
$file = $3;
} elsif (/^\/exp-vis\/([a-zA-Z0-9-]+)\/?([a-zA-Z0-9-]+)\/?(.*)$/) {
$proj = $1;
$exp = $2;
$file = $3;
} else {
error("Malformed URL");
}
if (defined $exp) {
my $exp_dir = "/proj/$proj/exp/$exp";
local $_ = realpath $exp_dir;
if (/^$FSDIR_PROJ\/$proj\//) {
$group = $proj;
} elsif (/^$FSDIR_GROUPS\/$proj\/(.+?)\//) {
$group = $1;
}
$dir = "/groups/$proj/$group/www/exp-vis/$exp";
} else {
$dir = "/groups/$proj/$group/www/group-vis";
}
# Lookup up the Unix GID for the proj and the group
my (undef,undef,undef,undef,undef,$gid) = stat("/proj/$proj") or die;
my ($gid_name,undef,undef,$gid_members) = getgrgid($gid);
die "Error: Bad proj GID: $gid_name != $proj" unless $gid_name eq $proj;
my (undef,undef,undef,undef,undef,$gid2) = stat("/groups/$proj/$group") or die;
my ($gid2_name,undef,undef,$gid2_members) = getgrgid($gid2);
# For security remove any ".." from the path and abort if we would
# leave $dir
my @dirs = split /\//, $file;
my @res;
foreach my $d (@dirs) {
if ($d eq '' || $d eq '.') {
# nothing to do
} elsif ($d eq '..') {
error("Malformed URL") if @res == 0;
pop @res;
} else {
push @res, $d;
}
}
# Create the path
$file = join ('/', @res);
my $path = "$dir/$file";
if (-d $path) {
my $orig_path = $path;
$path .= "/index.html" if -e "$path/index.html";
$path .= "/index.htm" if -e "$path/index.htm";
error("Can't index dir: $path") unless $path ne $orig_path;
}
error("File Doesn't Exist: $path") unless -e $path;
# Make sure that the path, after resolving any symbolic links,
# still resides is /proj/<proj> or /groups/<proj>/<group>
my $realpath = realpath $path;
error("Invalid path: $realpath") unless $realpath =~ /^$FSDIR_PROJ\/$proj|^$FSDIR_GROUPS\/$proj\/$group/;
#
# Special rule for boss. Since we are bypassing authorization, don't
# show anything, just let boss know that the url is valid.
#
if ($ENV{REMOTE_ADDR} eq "@BOSSNODE_IP@") {
print "Content-Type: text/plain\n\n";
print "I exist!\n";
exit(0);
}
#
# Get session cookie and make sure user is logged in and authorized to
# view.
#
my %cookies = raw_fetch CGI::Cookie;
my $session_key = $cookies{exp_vis_session};
error("Not logged in.") unless defined $session_key;
my $user;
open F, "/var/run/exp-vis.auth" or die;
foreach (<F>) {
chop;
my ($key, $u) = split / /;
if ($key eq $session_key) {
$user = $u;
last;
}
}
error("Login Timed Out.") unless defined $user;
my (undef, undef, $uid, $user_gid) = getpwnam($user);
die if $user_gid == 0;
error("You do not have permission to view $proj files")
unless $gid == $user_gid || grep {$_ eq $user} split /\s+/, $gid_members;
error("You do not have permission to view $proj/$group files")
unless $gid2 == $user_gid || grep {$_ eq $user} split /\s+/, $gid2_members;
# OK, Now we are sure the user has permission to view this file.
# Now become a member of the GID for the proj and group and clear out
# any other GIDs
undef $!;
setgid($gid);
$) = "$gid $gid $gid2";
die $! if $!;
# Now drop privileges, using setuid to make sure the saved uid
# is also changes, ie, so that the change is permanent.
setuid($<) or die $!;
my %mime_map =
qw(html text/html htm text/html
txt text/plain
png image/png
gif image/gif
jpg image/jpeg jpeg image/jpeg
zip application/zip);
my ($ext) = $path =~ /\.([^.]+)$/;
$ext = lc $ext;
my $mime_type = $mime_map{$ext};
$/ = undef;
open F, "$path" or error "Can't read file: $path";
my ($dev,$ino,$mode,$nlink,undef,undef,$rdev,$size,
$atime,$mtime,$ctime,$blksize,$blocks) = stat F;
my $if_mod_since = 0;
$if_mod_since = str2time($ENV{HTTP_IF_MODIFIED_SINCE})
if defined $ENV{HTTP_IF_MODIFIED_SINCE};
if ($if_mod_since > 0 && $if_mod_since <= $mtime) {
print "Status: 304 Not Modified\n\n";
} else {
print "Content-Type: $mime_type\n" if defined $mime_type;
print "Content-Length: ", $size, "\n";
print "Last-Modified: ", time2str($mtime), "\n";
print "\n";
print <F> unless $ENV{REQUEST_METHOD} eq 'HEAD';
}
exit 0;
#!/usr/bin/perl -wT
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2007 University of Utah and the Flux Group.
# All rights reserved.
#
use strict;
use Getopt::Std;
#
# Configure variables
#
my $TB = "@prefix@";
my $TBOPS = "@TBOPSEMAIL@";
my $USERNODE = "@USERNODE@";
my $SSH = "$TB/bin/sshtb -l root -host $USERNODE";
my $background = 0;
# un-taint path
$ENV{'PATH'} = '/bin:/usr/bin:/usr/local/bin';
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
# Turn off line buffering on output
$| = 1;
#
# Capture stdout and stderr to a file so if we die we can mail the output to
# testbed-ops
#
# XXX: Don't hardcode
my $logfile = "/tmp/write-vis-auth.$$";
use vars qw(*OLDOUT *OLDERR);
open OLDOUT, ">&STDOUT" or die "Can't dup STDOUT $!";
open OLDERR, ">&STDERR" or die "Can't dup STDERR $!";
open STDOUT, ">$logfile" or die "Can't open $logfile: $!";
open STDERR, ">&STDOUT" or die "Can't dup STDERR $!";
$SIG{__DIE__} = sub {
return unless defined $^S; # In Parser
return if $^S; # In Eval Block
local $_ = $_[0];
open STDOUT, ">&OLDOUT";
open STDERR, ">&OLDERR";
SENDMAIL($TBOPS, "write-vis-auth failed", $_, undef, undef, $logfile);
unlink $logfile;
TBScriptUnlock();
print STDERR "write-vis-auth failed, see testbed-ops mail\n";
exit(1);
};
#
# Load the Testbed support stuff.
#
use lib "@prefix@/lib";
use libdb;
use libtestbed;
if ((my $locked = TBScriptLock("write-vis-auth", 1)) != TBSCRIPTLOCK_OKAY()) {
exit(0)
if ($locked == TBSCRIPTLOCK_IGNORE);
die("Could not get the lock after a long time!\n");
}
# become root, needed for ssh
$< = $>;
my $db_result =
DBQueryFatal("select opskey, uid from login");
open O, "| $SSH $TB/libexec/write-vis-auth.proxy"
or die "ssh to ops failed: $!\n";
my $prev_opskey = '';
while (my ($opskey,$uid) = $db_result->fetchrow_array) {
$opskey = "00000000000000000000000000000000" if $opskey eq '';
print O "$opskey $uid\n";
}
close O;
die "ssh to ops failed: $!\n" if $!;
die "ssh to ops failed with exit code $?\n" if $? != 0;
unlink $logfile;
TBScriptUnlock();
exit(0);
#!/bin/sh
set -e
if [ "$USER" != "root" ]; then
echo "Must be root." 1>&2
exit 1
fi
TEMPFILE=`mktemp /var/run/exp-vis.XXXXXX`
cat > $TEMPFILE
mv $TEMPFILE /var/run/exp-vis.auth
......@@ -1495,6 +1495,8 @@ done
......@@ -1582,6 +1584,7 @@ PROTOGENI_CLEARINGHOUSE=0
PROTOGENI_DOMAIN="unknown"
STANDALONE_CLEARINGHOUSE=0
NODE_USAGE_SUPPORT=0
EXP_VIS_SUPPORT=0
NOSTACKMIB=0
#
......@@ -2192,17 +2195,17 @@ for ac_hdr in ulxmlrpcpp/ulxr_config.h
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
echo "configure:2195: checking for $ac_hdr" >&5
echo "configure:2199: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 2200 "configure"
#line 2204 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:2205: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
{ (eval echo configure:2209: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
......@@ -2241,17 +2244,17 @@ for ac_hdr in linux/videodev.h
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
echo "configure:2244: checking for $ac_hdr" >&5
echo "configure:2248: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 2249 "configure"
#line 2253 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:2254: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
{ (eval echo configure:2258: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
......@@ -2284,7 +2287,7 @@ done
# Extract the first word of "gtk-config", so it can be a program name with args.
set dummy gtk-config; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:2287: checking for $ac_word" >&5
echo "configure:2291: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_GTK_CONFIG'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
......@@ -2341,7 +2344,7 @@ ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftes
cross_compiling=$ac_cv_prog_cxx_cross
echo $ac_n "checking how to run the C++ preprocessor""... $ac_c" 1>&6
echo "configure:2344: checking how to run the C++ preprocessor" >&5
echo "configure:2348: checking how to run the C++ preprocessor" >&5
if test -z "$CXXCPP"; then
if eval "test \"`echo '$''{'ac_cv_prog_CXXCPP'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
......@@ -2354,12 +2357,12 @@ ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftes
cross_compiling=$ac_cv_prog_cxx_cross
CXXCPP="${CXX-g++} -E"
cat > conftest.$ac_ext <<EOF
#line 2357 "configure"
#line 2361 "configure"
#include "confdefs.h"
#include <stdlib.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:2362: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
{ (eval echo configure:2366: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
:
......@@ -2385,17 +2388,17 @@ echo "$ac_t""$CXXCPP" 1>&6
ac_safe=`echo "xercesc/dom/DOM.hpp" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for xercesc/dom/DOM.hpp""... $ac_c" 1>&6
echo "configure:2388: checking for xercesc/dom/DOM.hpp" >&5
echo "configure:2392: checking for xercesc/dom/DOM.hpp" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 2393 "configure"
#line 2397 "configure"
#include "confdefs.h"
#include <xercesc/dom/DOM.hpp>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:2398: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
{ (eval echo configure:2402: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
......@@ -2459,7 +2462,7 @@ fi
# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
# ./install, which can be erroneously created by make from ./install.sh.
echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
echo "configure:2462: checking for a BSD compatible install" >&5
echo "configure:2466: checking for a BSD compatible install" >&5
if test -z "$INSTALL"; then
if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
......@@ -2520,7 +2523,7 @@ esac
# Extract the first word of "rsync", so it can be a program name with args.
set dummy rsync; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:2523: checking for $ac_word" >&5
echo "configure:2527: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_RSYNC'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
......@@ -2771,6 +2774,7 @@ outfiles="$outfiles Makeconf GNUmakefile \
collab/cvstools/cvs.proxy collab/cvstools/cvs_ctrl \
collab/cvstools/cvsrepo_ctrl.proxy collab/cvstools/cvsrepo_ctrl \
collab/cvstools/webcvsrepo_ctrl \
collab/exp-vis/GNUmakefile collab/exp-vis/fetch-vis \
node_usage/GNUmakefile node_usage/mk-plots \
node_usage/analy node_usage/publish \
node_usage/analy2 node_usage/refresh \
......@@ -3059,6 +3063,7 @@ s%@STANDALONE_CLEARINGHOUSE@%$STANDALONE_CLEARINGHOUSE%g
s%@GMAP_API_KEY@%$GMAP_API_KEY%g
s%@NODE_USAGE_SUPPORT@%$NODE_USAGE_SUPPORT%g
s%@NOSTACKMIB@%$NOSTACKMIB%g
s%@EXP_VIS_SUPPORT@%$EXP_VIS_SUPPORT%g
s%@TBOPSEMAIL@%$TBOPSEMAIL%g
s%@TBOPSEMAIL_NOSLASH@%$TBOPSEMAIL_NOSLASH%g
s%@TBROBOCOPSEMAIL@%$TBROBOCOPSEMAIL%g
......
......@@ -217,6 +217,7 @@ AC_SUBST(STANDALONE_CLEARINGHOUSE)
AC_SUBST(GMAP_API_KEY)
AC_SUBST(NODE_USAGE_SUPPORT)
AC_SUBST(NOSTACKMIB)
AC_SUBST(EXP_VIS_SUPPORT)
#
# Offer both versions of the email addresses that have the @ escaped
......@@ -302,6 +303,7 @@ PROTOGENI_CLEARINGHOUSE=0
PROTOGENI_DOMAIN="unknown"
STANDALONE_CLEARINGHOUSE=0
NODE_USAGE_SUPPORT=0
EXP_VIS_SUPPORT=0
NOSTACKMIB=0
#
......@@ -1017,6 +1019,7 @@ outfiles="$outfiles Makeconf GNUmakefile \
collab/cvstools/cvs.proxy collab/cvstools/cvs_ctrl \
collab/cvstools/cvsrepo_ctrl.proxy collab/cvstools/cvsrepo_ctrl \
collab/cvstools/webcvsrepo_ctrl \
collab/exp-vis/GNUmakefile collab/exp-vis/fetch-vis \
node_usage/GNUmakefile node_usage/mk-plots \
node_usage/analy node_usage/publish \
node_usage/analy2 node_usage/refresh \
......
......@@ -66,6 +66,7 @@ OPSDBSUPPORT=1
PELABSUPPORT=1
PLABSUPPORT=1
PLAB_ROOTBALL="plabroot-21.tar.bz2"
EXP_VIS_SUPPORT=1
# Do not turn this on unless you talk to Utah first!
PROTOGENI_SUPPORT=1
# If you are not the main Emulab site in Utah, change this!
......
......@@ -34,6 +34,7 @@ $CVSSUPPORT = @CVSSUPPORT@;
$MAILMANSUPPORT = @MAILMANSUPPORT@;
$CHATSUPPORT = @CHATSUPPORT@;
$PROTOGENI = @PROTOGENI_SUPPORT@;
$EXP_VIS = @EXP_VIS_SUPPORT@;
$ISOLATEADMINS = @ISOLATEADMINS@;
$CONTROL_NETWORK= "@CONTROL_NETWORK@";
$CONTROL_NETMASK= "@CONTROL_NETMASK@";
......
......@@ -62,6 +62,13 @@ if ($EXPOSETEMPLATES) {
#
# For the Sajax Interface
#
$USER_VIS_URL = "http://$USERNODE/exp-vis/$pid/$eid/";
$HAVE_USER_VIS = 0;
$whocares = null;
if ($EXP_VIS && CHECKURL($USER_VIS_URL, $whocares)) {
$HAVE_USER_VIS = 1;
}
function FreeNodeHtml()
{
global $this_user, $experiment;
......@@ -87,6 +94,7 @@ function ModifyAnno($newtext)
function Show($which, $arg1, $arg2)
{
global $experiment, $instance, $uid, $TBSUEXEC_PATH, $TBADMINGROUP;
global $USER_VIS_URL;
$pid = $experiment->pid();
$eid = $experiment->eid();
$html = "";
......@@ -227,6 +235,11 @@ function Show($which, $arg1, $arg2)
$html .= " onclick=\"SaveNS();\">";
$html .= "Save</button>\n";
}
elseif ($which == "uservis") {
ob_start();
$html .= "<iframe src=\"$USER_VIS_URL\" width=\"100%\" height=600 id=\"vis-iframe\"></iframe>";
ob_end_clean();
}
return $html;
}
......@@ -693,6 +706,12 @@ if ($instance) {
"id=\"li_anno\" onclick=\"Show('anno');\">".
"Annotation</a></li>\n";
}
if ($HAVE_USER_VIS) {
echo "<li>
<a href=\"#E\" class=topnavbar onfocus=\"this.hideFocus=true;\" ".
"id=\"li_uservis\" onclick=\"Show('uservis');\">".
"User Visualization</a></li>\n";
}
echo "</ul>\n";
echo "</div>\n";
echo "<div align=center id=topnavbarbottom>&nbsp</div>\n";
......
......@@ -109,6 +109,12 @@ if ($PUBSUPPORT) {
}
}
$vis_html = null;
$whocares = null;
if ($EXP_VIS && CHECKURL("http://$USERNODE/proj-vis/$pid/", $whocares)) {
$vis_html = "<iframe src=\"http://$USERNODE/proj-vis/$pid/\" width=\"100%\" height=600 id=\"vis-iframe\"></iframe>";
}
#
# Show number of PCS
#
......@@ -200,6 +206,12 @@ if ($papers_html) {
"id=\"li_papers\" onclick=\"Show('papers');\">".
"Publications</a></li>\n";
}
if ($vis_html) {
echo "<li>
<a href=\"#G\" class=topnavbar onfocus=\"this.hideFocus=true;\" ".
"id=\"li_vis\" onclick=\"Show('vis');\">".
"Visualization</a></li>\n";
}
echo "</ul>\n";
echo "</div>\n";
echo "<div align=center id=topnavbarbottom>&nbsp</div>\n";
......@@ -223,6 +235,9 @@ if ($isadmin && $stats_html) {
if ($papers_html) {
echo "<div class=invisible id=\"div_papers\">$papers_html</div>";
}
if ($vis_html) {
echo "<div class=invisible id=\"div_vis\">$vis_html</div>";
}
SUBPAGEEND();
#
......
......@@ -952,6 +952,7 @@ function DOLOGIN_MAGIC($uid, $uid_idx, $email = null, $adminon = 0)
global $TBMAIL_OPS, $TBMAIL_AUDIT, $TBMAIL_WWW;
global $WIKISUPPORT, $WIKICOOKIENAME;
global $BUGDBSUPPORT, $BUGDBCOOKIENAME, $TRACSUPPORT, $TRACCOOKIENAME;
global $TBLIBEXEC_DIR, $EXP_VIS;
# Caller makes these checks too.
if (!TBvalid_uid($uid)) {
......@@ -970,10 +971,11 @@ function DOLOGIN_MAGIC($uid, $uid_idx, $email = null, $adminon = 0)
$timeout = $now + $TBAUTHTIMEOUT;
$hashkey = GENHASH();
$crc = bin2hex(mhash(MHASH_CRC32, $hashkey));
$opskey = GENHASH();
DBQueryFatal("replace into login ".
" (uid,uid_idx,hashkey,hashhash,timeout,adminon) values ".
" ('$uid', $uid_idx, '$hashkey', '$crc', '$timeout', $adminon)");
" (uid,uid_idx,hashkey,hashhash,timeout,adminon,opskey) values ".
" ('$uid', $uid_idx, '$hashkey', '$crc', '$timeout', $adminon, '$opskey')");