diff --git a/GNUmakefile.in b/GNUmakefile.in
index 506373ca2e7d4259449c53fd2a35a3689da18613..98afa02a367f398f093ae79ce43ac8ae6ef3801d 100644
--- a/GNUmakefile.in
+++ b/GNUmakefile.in
@@ -58,6 +58,7 @@ ifeq ($(EVENTSYS),1)
 endif
 	@$(MAKE) -C mote post-install
 	@$(MAKE) -C tools post-install
+	@$(MAKE) -C wiki post-install
 
 #
 # For installation on the 'ops' or 'users' node (okay, plastic)
diff --git a/account/tbacct.in b/account/tbacct.in
index 26253e84d1588573800a598e1b135609c535e02c..fbf908ac39ffb3503d4d2366fb3c1f8bc67f63c7 100644
--- a/account/tbacct.in
+++ b/account/tbacct.in
@@ -167,7 +167,8 @@ if (AuditStart(0)) {
 #
 $query_result =
     DBQueryFatal("select u.usr_pswd,u.unix_uid,u.usr_name, ".
-		 " u.usr_email,u.status,u.webonly,u.usr_shell,admin,u.usr_w_pswd ".
+		 " u.usr_email,u.status,u.webonly,u.usr_shell,admin, ".
+		 " u.usr_w_pswd,u.wikionly ".
 		 "from users as u ".
 		 "where u.uid='$user'");
 
@@ -184,6 +185,7 @@ my $webonly     = $row[5];
 my $usr_shell   = $row[6];
 my $usr_admin   = $row[7];
 my $wpswd       = $row[8];
+my $wikionly    = $row[9];
 
 #
 # Get the users earliest project membership to use as the default group
@@ -273,10 +275,20 @@ sub AddUser()
     #
     # Check status. Only active users get accounts built.
     #
-    if ($webonly || $status ne USERSTATUS_ACTIVE) {
+    if ($webonly || $wikionly || $status ne USERSTATUS_ACTIVE) {
 	if ($webonly) {
 	    return 0;
 	}
+	if ($wikionly) {
+	    $EUID = $UID;
+
+	    # And to the wiki if enabled.
+	    system("$ADDWIKIUSER $user")
+		if ($WIKISUPPORT && !$batch);
+	    
+	    $EUID = 0;
+	    return 0;
+	}
 	fatal("$user is not active! Cannot build an account!");
     }
 
diff --git a/wiki/webhometemplate.in b/wiki/webhometemplate.in
index ba9dcafdb1e11749cb19b34d97a9526b2bd73fea..bb0a8b9c19b3f04eccabdd34e91c76bf5c1e787f 100644
--- a/wiki/webhometemplate.in
+++ b/wiki/webhometemplate.in
@@ -5,7 +5,7 @@ area for your project (or group).  If you are not familiar with the
 information on how to write and create TWiki pages.
 
 	* YourFirstWikiTopic (See TWiki.WikiTopic for a brief description)
-	*
+	* 
 
 
 __This project wiki can be accessed externally as:__ [[%SCRIPTURL%/view/%WEB%][%SCRIPTURL%/view/%WEB%]]
diff --git a/www/dbcheck.php3 b/www/dbcheck.php3
index f5cd1ae119ee060de086799d95801be5977138d4..08a1d7051915cab9e867de50de8af320580739c2 100644
--- a/www/dbcheck.php3
+++ b/www/dbcheck.php3
@@ -200,6 +200,10 @@ function TBvalid_usrname($token) {
     return TBcheck_dbslot($token, "users", "usr_name",
 			  TBDB_CHECKDBSLOT_WARN|TBDB_CHECKDBSLOT_ERROR);
 }
+function TBvalid_wikiname($token) {
+    return TBcheck_dbslot($token, "users", "wikiname",
+			  TBDB_CHECKDBSLOT_WARN|TBDB_CHECKDBSLOT_ERROR);
+}
 function TBvalid_email($token) {
     return TBcheck_dbslot($token, "users", "usr_email",
 			  TBDB_CHECKDBSLOT_WARN|TBDB_CHECKDBSLOT_ERROR);
diff --git a/www/dbdefs.php3.in b/www/dbdefs.php3.in
index 38bbbdb34d78309414ba9b017b8761bac9bee79d..a71b48788c9496fa1f6359f0f8142bd6c94d870f 100644
--- a/www/dbdefs.php3.in
+++ b/www/dbdefs.php3.in
@@ -863,6 +863,21 @@ function TBCurrentUser($uid)
     return mysql_num_rows($query_result);
 }
 
+#
+# Confirm a current WikiName or not.
+#
+# usage TBCurrentWikiName($uid)
+#       returns 1 if a current wikiname.
+#       returns 0 if not a current wikiname
+#
+function TBCurrentWikiName($wikiname)
+{
+    $query_result =
+	DBQueryFatal("SELECT usr_pswd FROM users WHERE wikiname='$wikiname'");
+
+    return mysql_num_rows($query_result);
+}
+
 #
 # Check to see if an email is being used twice.
 #
@@ -1502,6 +1517,14 @@ function TBCvswebAllowed($uid) {
     return mysql_num_rows($query_result);
 }
 
+function TBWikiOnlyUser($uid) {
+    $query_result =
+        DBQueryFatal("select wikionly from users ".
+		     "WHERE uid='$uid' and wikionly=1");
+
+    return mysql_num_rows($query_result);
+}
+
 #
 # Returns > 0 if a node has a serial console, 0 if it does not
 #
diff --git a/www/joinproject.php3 b/www/joinproject.php3
index 8a404876b299fa49f8eb596805a63b4525f4a0a9..98b7452de8a6a2d6d2d13045303309e4bb0716a6 100644
--- a/www/joinproject.php3
+++ b/www/joinproject.php3
@@ -22,7 +22,8 @@ $uid = GETLOGIN();
 if ($uid) {
     # Allow unapproved users to join multiple groups ...
     # Must be verified though.
-    LOGGEDINORDIE($uid, CHECKLOGIN_UNAPPROVED|CHECKLOGIN_WEBONLY);
+    LOGGEDINORDIE($uid, CHECKLOGIN_UNAPPROVED|
+		  CHECKLOGIN_WEBONLY|CHECKLOGIN_WIKIONLY);
     $joining_uid = $uid;
     $returning = 1;
 }
@@ -33,6 +34,10 @@ else {
     $returning = 0;
 }
 
+if (!isset($forwikionly)) {
+    $forwikionly = 0;
+}
+
 $ACCOUNTWARNING =
     "Before continuing, please make sure your username " .
     "reflects your normal login name. ".
@@ -50,15 +55,32 @@ function SPITFORM($formfields, $returning, $errors)
 {
     global $TBDB_UIDLEN, $TBDB_PIDLEN, $TBDB_GIDLEN;
     global $ACCOUNTWARNING, $EMAILWARNING;
-    
-    PAGEHEADER("Apply for Project Membership");
+    global $WIKISUPPORT, $forwikionly, $WIKIURL;
+
+    if ($forwikionly)
+	PAGEHEADER("Wiki Registration");
+    else
+	PAGEHEADER("Apply for Project Membership");
 
     if (! $returning) {
-	echo "<center><font size=+1>
+	echo "<center>\n";
+
+	if ($forwikionly) {
+	    echo "<font size=+2>Register for an Emulab Wiki account</font>
+                  <br><br>\n";
+	}
+        echo "<font size=+1>
                If you already have an Emulab account,
                <a href=login.php3?refer=1>
                <font color=red>please log on first!</font></a>
-              </font></center><br>\n";
+              </font>\n";
+	if ($forwikionly) {
+	    echo "<br>(You will already have a wiki account)\n";
+	}
+	echo "</center><br>\n";	
+    }
+    elseif ($forwikionly) {
+	USERERROR("You already have a Wiki account!", 1);
     }
 
     if ($errors) {
@@ -82,6 +104,34 @@ function SPITFORM($formfields, $returning, $errors)
 	}
 	echo "</table><br>\n";
     }
+    echo "<SCRIPT LANGUAGE=JavaScript>
+              function SetWikiName(theform) 
+              {
+	          var validchars = 'abcdefghijklmnopqrstuvwxyz0123456789';
+                  var usrname    = theform['formfields[usr_name]'].value;
+                  var wikiname   = '';
+                  var docap      = 1;
+
+		  for (var i = 0; i < usrname.length; i++) {
+                      var letter = usrname.charAt(i).toLowerCase();
+
+                      if (validchars.indexOf(letter) == -1) {
+                          if (letter == ' ') {
+                              docap = 1;
+                          }
+                          continue;
+                      }
+                      else {
+                          if (docap == 1) {
+                              letter = usrname.charAt(i).toUpperCase()
+                              docap  = 0;
+                          }
+                          wikiname = wikiname + letter;
+                      }
+                  }
+                  theform['formfields[wikiname]'].value = wikiname;
+              }
+          </SCRIPT>\n";
 
     echo "<table align=center border=1> 
           <tr>
@@ -90,8 +140,10 @@ function SPITFORM($formfields, $returning, $errors)
             </td>
           </tr>\n
 
-          <form enctype=multipart/form-data
-                action=joinproject.php3 method=post>\n";
+          <form name=myform enctype=multipart/form-data
+                action=" . ($forwikionly ?
+			    "wikiregister.php3" : "joinproject.php3") . " " .
+	        "method=post>\n";
 
     if (! $returning) {
         #
@@ -117,49 +169,68 @@ function SPITFORM($formfields, $returning, $errors)
                   <td class=left>
                       <input type=text
                              name=\"formfields[usr_name]\"
+                             onchange=\"SetWikiName(myform);\"
                              value=\"" . $formfields[usr_name] . "\"
 	                     size=30>
                   </td>
               </tr>\n";
 
-        #
-	# Title/Position:
-	# 
-	echo "<tr>
-                  <td colspan=2>*Title/Position:</td>
-                  <td class=left>
-                      <input type=text
-                             name=\"formfields[usr_title]\"
-                             value=\"" . $formfields[usr_title] . "\"
-	                     size=30>
-                  </td>
-              </tr>\n";
-
-        #
-	# Affiliation:
-	# 
-	echo "<tr>
-                  <td colspan=2>*Institutional<br>Affiliation:</td>
-                  <td class=left>
-                      <input type=text
-                             name=\"formfields[usr_affil]\"
-                             value=\"" . $formfields[usr_affil] . "\"
-	                     size=40>
-                  </td>
-              </tr>\n";
-
 	#
-	# User URL
+	# WikiName
 	#
-	echo "<tr>
-                  <td colspan=2>Home Page URL:</td>
-                  <td class=left>
-                      <input type=text
-                             name=\"formfields[usr_URL]\"
-                             value=\"" . $formfields[usr_URL] . "\"
-	                     size=45>
-                  </td>
-              </tr>\n";
+	if ($WIKISUPPORT) {
+	    echo "<tr>
+                      <td colspan=2>*
+                          <a href=${WIKIURL}/TWiki/WikiName
+                            target=_blank>WikiName</a>:<td class=left>
+                          <input type=text
+                                 name=\"formfields[wikiname]\"
+                                 value=\"" . $formfields[wikiname] . "\"
+	                         size=30>
+                      </td>
+                  </tr>\n";
+	}
+
+	if (! $forwikionly) {
+            #
+            # Title/Position:
+	    #
+	    echo "<tr>
+                      <td colspan=2>*Title/Position:</td>
+                      <td class=left>
+                          <input type=text
+                                 name=\"formfields[usr_title]\"
+                                 value=\"" . $formfields[usr_title] . "\"
+  	                         size=30>
+                      </td>
+                  </tr>\n";
+
+            #
+            # Affiliation:
+            # 
+	    echo "<tr>
+                      <td colspan=2>*Institutional<br>Affiliation:</td>
+                      <td class=left>
+                          <input type=text
+                                 name=\"formfields[usr_affil]\"
+                                 value=\"" . $formfields[usr_affil] . "\"
+	                         size=40>
+                      </td>
+                  </tr>\n";
+
+	    #
+	    # User URL
+	    #
+	        echo "<tr>
+                      <td colspan=2>Home Page URL:</td>
+                      <td class=left>
+                          <input type=text
+                                 name=\"formfields[usr_URL]\"
+                                 value=\"" . $formfields[usr_URL] . "\"
+	                         size=45>
+                      </td>
+                  </tr>\n";
+	}
 
 	#
 	# Email:
@@ -175,82 +246,88 @@ function SPITFORM($formfields, $returning, $errors)
                   </td>
               </tr>\n";
 
-	echo "<tr><td colspan=3>*Postal Address:<br /><center>
-		<table>
-		  <tr><td>Line 1</td><td colspan=3>
-                    <input type=text
-                           name=\"formfields[usr_addr]\"
-                           value=\"" . $formfields[usr_addr] . "\"
-	                   size=45></td></tr>
-		  <tr><td>Line 2</td><td colspan=3>
-                    <input type=text
-                           name=\"formfields[usr_addr2]\"
-                           value=\"" . $formfields[usr_addr2] . "\"
-	                   size=45></td></tr>
-		  <tr><td>City</td><td>
-                    <input type=text
-                           name=\"formfields[usr_city]\"
-                           value=\"" . $formfields[usr_city] . "\"
-	                   size=25></td>
-		      <td>State/Province</td><td>
-                    <input type=text
-                           name=\"formfields[usr_state]\"
-                           value=\"" . $formfields[usr_state] . "\"
-	                   size=2></td></tr>
-		  <tr><td>ZIP/Postal Code</td><td>
-                    <input type=text
-                           name=\"formfields[usr_zip]\"
-                           value=\"" . $formfields[usr_zip] . "\"
-	                   size=10></td>
-		      <td>Country</td><td>
-                    <input type=text
-                           name=\"formfields[usr_country]\"
-                           value=\"" . $formfields[usr_country] . "\"
-	                   size=15></td></tr>
-               </table></center></td></tr>";
-
-	#
-	# Phone
-	#
-	echo "<tr>
-                  <td colspan=2>*Phone #:</td>
-                  <td class=left>
-                      <input type=text
-                             name=\"formfields[usr_phone]\"
-                             value=\"" . $formfields[usr_phone] . "\"
-	                     size=15>
-                  </td>
-              </tr>\n";
+	if (! $forwikionly) {
+	    #
+	    # Postal Address
+	    #
+	    echo "<tr><td colspan=3>*Postal Address:<br /><center>
+		    <table>
+		      <tr><td>Line 1</td><td colspan=3>
+                        <input type=text
+                               name=\"formfields[usr_addr]\"
+                               value=\"" . $formfields[usr_addr] . "\"
+	                       size=45></td></tr>
+		      <tr><td>Line 2</td><td colspan=3>
+                        <input type=text
+                               name=\"formfields[usr_addr2]\"
+                               value=\"" . $formfields[usr_addr2] . "\"
+	                       size=45></td></tr>
+		      <tr><td>City</td><td>
+                        <input type=text
+                               name=\"formfields[usr_city]\"
+                               value=\"" . $formfields[usr_city] . "\"
+	                       size=25></td>
+		          <td>State/Province</td><td>
+                        <input type=text
+                               name=\"formfields[usr_state]\"
+                               value=\"" . $formfields[usr_state] . "\"
+	                       size=2></td></tr>
+		      <tr><td>ZIP/Postal Code</td><td>
+                        <input type=text
+                               name=\"formfields[usr_zip]\"
+                               value=\"" . $formfields[usr_zip] . "\"
+	                       size=10></td>
+		          <td>Country</td><td>
+                        <input type=text
+                               name=\"formfields[usr_country]\"
+                               value=\"" . $formfields[usr_country] . "\"
+	                       size=15></td></tr>
+                   </table></center></td></tr>";
+
+	    #
+	    # Phone
+	    #
+	    echo "<tr>
+                      <td colspan=2>*Phone #:</td>
+                      <td class=left>
+                          <input type=text
+                                 name=\"formfields[usr_phone]\"
+                                 value=\"" . $formfields[usr_phone] . "\"
+	                         size=15>
+                      </td>
+                  </tr>\n";
 
-	#
-	# SSH public key
-	#
-	echo "<tr>
-                  <td rowspan><center>
-                               Your SSH Pub Key: &nbsp<br>
-                                    [<b>2</b>]
-                              </center></td>
-
-                  <td rowspan><center>Upload (1K max)[<b>3</b>]<br>
-                                  <b>Or</b><br>
-                               Insert Key
-                             </center></td>
-
-                  <td rowspan>
-                      <input type=hidden name=MAX_FILE_SIZE value=1024>
-                      <input type=file
-                             name=usr_keyfile
-                             value=\"" . $_FILES['usr_keyfile']['name'] . "\"
-	                     size=50>
-                      <br>
-                      <br>
-	              <input type=text
-                             name=\"formfields[usr_key]\"
-                             value=\"$formfields[usr_key]\"
-	                     size=50
-	                     maxlength=1024>
-                  </td>
-              </tr>\n";
+	    #
+	    # SSH public key
+	    #
+	    echo "<tr>
+                     <td rowspan><center>
+                                   Your SSH Pub Key: &nbsp<br>
+                                        [<b>2</b>]
+                                  </center></td>
+    
+                      <td rowspan><center>Upload (1K max)[<b>3</b>]<br>
+                                      <b>Or</b><br>
+                                   Insert Key
+                                 </center></td>
+    
+                      <td rowspan>
+                          <input type=hidden name=MAX_FILE_SIZE value=1024>
+                          <input type=file
+                                 name=usr_keyfile
+                                 value=\"" . $_FILES['usr_keyfile']['name'] .
+		                       "\"
+	                         size=50>
+                          <br>
+                          <br>
+	                  <input type=text
+                                 name=\"formfields[usr_key]\"
+                                 value=\"$formfields[usr_key]\"
+	                         size=50
+	                         maxlength=1024>
+                      </td>
+                  </tr>\n";
+	}
 
 	#
 	# Password. Note that we do not resend the password. User
@@ -273,32 +350,34 @@ function SPITFORM($formfields, $returning, $errors)
              </tr>\n";
     }
 
-    #
-    # Project Name:
-    #
-    echo "<tr>
-              <td colspan=2>*Project Name:</td>
-              <td class=left>
-                  <input type=text
-                         name=\"formfields[pid]\"
-                         value=\"" . $formfields[pid] . "\"
-	                 size=$TBDB_PIDLEN maxlength=$TBDB_PIDLEN>
-              </td>
-          </tr>\n";
+    if (! $forwikionly) {
+        #
+        # Project Name:
+        #
+	echo "<tr>
+                  <td colspan=2>*Project Name:</td>
+                  <td class=left>
+                      <input type=text
+                             name=\"formfields[pid]\"
+                             value=\"" . $formfields[pid] . "\"
+	                     size=$TBDB_PIDLEN maxlength=$TBDB_PIDLEN>
+                  </td>
+              </tr>\n";
 
-    #
-    # Group Name:
-    #
-    echo "<tr>
-              <td colspan=2>Group Name:<br>
-              (Leave blank unless you <em>know</em> the group name)</td>
-              <td class=left>
-                  <input type=text
-                         name=\"formfields[gid]\"
-                         value=\"" . $formfields[gid] . "\"
-	                 size=$TBDB_GIDLEN maxlength=$TBDB_GIDLEN>
-              </td>
-          </tr>\n";
+        #
+        # Group Name:
+        #
+	echo "<tr>
+                  <td colspan=2>Group Name:<br>
+                  (Leave blank unless you <em>know</em> the group name)</td>
+                  <td class=left>
+                      <input type=text
+                             name=\"formfields[gid]\"
+                             value=\"" . $formfields[gid] . "\"
+	                     size=$TBDB_GIDLEN maxlength=$TBDB_GIDLEN>
+                  </td>
+              </tr>\n";
+    }
 
     echo "<tr>
               <td colspan=3 align=center>
@@ -315,7 +394,7 @@ function SPITFORM($formfields, $returning, $errors)
                  <a href = 'docwrapper.php3?docname=security.html'>
                  security policies</a> for information
                  regarding passwords and email addresses.\n";
-    if (! $returning) {
+    if (!$returning && !$forwikionly) {
 	echo "<li> If you want us to use your existing ssh public key,
                    then either paste it in or specify the path to your
                    your identity.pub file.  <font color=red>NOTE:</font>
@@ -342,12 +421,21 @@ function SPITFORM($formfields, $returning, $errors)
 # The conclusion of a join request. See below.
 # 
 if (isset($_GET['finished'])) {
-    PAGEHEADER("Apply for Project Membership");
+    if ($forwikionly) 
+	PAGEHEADER("Wiki Registration");
+    else
+	PAGEHEADER("Apply for Project Membership");
 
     #
     # Generate some warm fuzzies.
     #
-    if (! $returning) {
+    if ($forwikionly) {
+	echo "An email message has been sent to your account so we may verify
+              your email address. Please follow the instructions contained in
+              that message, which will verify your account, and grant you
+              access to the Wiki.\n";
+    }
+    elseif (! $returning) {
 	echo "<p>
               As a pending user of the Testbed you will receive a key via email.
               When you receive the message, please follow the instructions
@@ -356,7 +444,8 @@ if (isset($_GET['finished'])) {
 	      <p>
 	      When you have done that, the project leader will be
 	      notified of your application. ";
-    } else {
+    }
+    else {
           echo "<p>
 	  	The project leader has been notified of your application. ";
     }
@@ -420,13 +509,6 @@ if (! $returning) {
 	    posix_getpwnam($formfields[joining_uid])) {
 	$errors["UserName"] = "Already in use. Pick another";
     }
-    if (!isset($formfields[usr_title]) ||
-	strcmp($formfields[usr_title], "") == 0) {
-	$errors["Title/Position"] = "Missing Field";
-    }
-    elseif (! TBvalid_title($formfields[usr_title])) {
-	$errors["Title/Position"] = TBFieldErrorString();
-    }
     if (!isset($formfields[usr_name]) ||
 	strcmp($formfields[usr_name], "") == 0) {
 	$errors["Full Name"] = "Missing Field";
@@ -440,14 +522,34 @@ if (! $returning) {
     if (count($tokens) < 2) {
 	$errors["Full Name"] = "Please provide a first and last name";
     }
-
-    if (!isset($formfields[usr_affil]) ||
-	strcmp($formfields[usr_affil], "") == 0) {
-	$errors["Affiliation"] = "Missing Field";
-    }
-    elseif (! TBvalid_affiliation($formfields[usr_affil])) {
-	$errors["Affiliation"] = TBFieldErrorString();
+    if ($WIKISUPPORT) {
+	if (!isset($formfields[wikiname]) ||
+	    strcmp($formfields[wikiname], "") == 0) {
+	    $errors["WikiName"] = "Missing Field";
+	}
+	elseif (! TBvalid_wikiname($formfields[wikiname])) {
+	    $errors["WikiName"] = TBFieldErrorString();
+	}
+	elseif (TBCurrentWikiName($formfields[wikiname])) {
+	    $errors["WikiName"] = "Already in use. Pick another";
+	}
     }
+    if (!$forwikionly) {
+	if (!isset($formfields[usr_title]) ||
+	    strcmp($formfields[usr_title], "") == 0) {
+	    $errors["Title/Position"] = "Missing Field";
+	}
+	elseif (! TBvalid_title($formfields[usr_title])) {
+	    $errors["Title/Position"] = TBFieldErrorString();
+	}
+	if (!isset($formfields[usr_affil]) ||
+	    strcmp($formfields[usr_affil], "") == 0) {
+	    $errors["Affiliation"] = "Missing Field";
+	}
+	elseif (! TBvalid_affiliation($formfields[usr_affil])) {
+	    $errors["Affiliation"] = TBFieldErrorString();
+	}
+    }	
     if (!isset($formfields[usr_email]) ||
 	strcmp($formfields[usr_email], "") == 0) {
 	$errors["Email Address"] = "Missing Field";
@@ -465,58 +567,60 @@ if (! $returning) {
 		  "<a href='password.php3?email=$formfields[usr_email]'>".
 		  "forgotten your username.</a>", 1);
     }
-    if (isset($formfields[usr_URL]) &&
-	strcmp($formfields[usr_URL], "") &&
-	strcmp($formfields[usr_URL], $HTTPTAG) &&
-	! CHECKURL($formfields[usr_URL], $urlerror)) {
-	$errors["Home Page URL"] = $urlerror;
-    }
-    if (!isset($formfields[usr_addr]) ||
-	strcmp($formfields[usr_addr], "") == 0) {
-	$errors["Address 1"] = "Missing Field";
-    }
-    elseif (! TBvalid_addr($formfields[usr_addr])) {
-	$errors["Address 1"] = TBFieldErrorString();
-    }
-    # Optional
-    if (isset($formfields[usr_addr2]) &&
-	!TBvalid_addr($formfields[usr_addr2])) {
-	$errors["Address 2"] = TBFieldErrorString();
-    }
-    if (!isset($formfields[usr_city]) ||
-	strcmp($formfields[usr_city], "") == 0) {
-	$errors["City"] = "Missing Field";
-    }
-    elseif (! TBvalid_city($formfields[usr_city])) {
-	$errors["City"] = TBFieldErrorString();
-    }
-    if (!isset($formfields[usr_state]) ||
-	strcmp($formfields[usr_state], "") == 0) {
-	$errors["State"] = "Missing Field";
-    }
-    elseif (! TBvalid_state($formfields[usr_state])) {
-	$errors["State"] = TBFieldErrorString();
-    }
-    if (!isset($formfields[usr_zip]) ||
-	strcmp($formfields[usr_zip], "") == 0) {
-	$errors["ZIP/Postal Code"] = "Missing Field";
-    }
-    elseif (! TBvalid_zip($formfields[usr_zip])) {
-	$errors["Zip/Postal Code"] = TBFieldErrorString();
-    }
-    if (!isset($formfields[usr_country]) ||
-	strcmp($formfields[usr_country], "") == 0) {
-	$errors["Country"] = "Missing Field";
-    }
-    elseif (! TBvalid_country($formfields[usr_country])) {
-	$errors["Country"] = TBFieldErrorString();
-    }
-    if (!isset($formfields[usr_phone]) ||
-	strcmp($formfields[usr_phone], "") == 0) {
-	$errors["Phone #"] = "Missing Field";
-    }
-    elseif (!TBvalid_phone($formfields[usr_phone])) {
-	$errors["Phone #"] = TBFieldErrorString();
+    if (! $forwikionly) {
+	if (isset($formfields[usr_URL]) &&
+	    strcmp($formfields[usr_URL], "") &&
+	    strcmp($formfields[usr_URL], $HTTPTAG) &&
+	    ! CHECKURL($formfields[usr_URL], $urlerror)) {
+	    $errors["Home Page URL"] = $urlerror;
+	}
+	if (!isset($formfields[usr_addr]) ||
+	    strcmp($formfields[usr_addr], "") == 0) {
+	    $errors["Address 1"] = "Missing Field";
+	}
+	elseif (! TBvalid_addr($formfields[usr_addr])) {
+	    $errors["Address 1"] = TBFieldErrorString();
+	}
+        # Optional
+	if (isset($formfields[usr_addr2]) &&
+	    !TBvalid_addr($formfields[usr_addr2])) {
+	    $errors["Address 2"] = TBFieldErrorString();
+	}
+	if (!isset($formfields[usr_city]) ||
+	    strcmp($formfields[usr_city], "") == 0) {
+	    $errors["City"] = "Missing Field";
+	}
+	elseif (! TBvalid_city($formfields[usr_city])) {
+	    $errors["City"] = TBFieldErrorString();
+	}
+	if (!isset($formfields[usr_state]) ||
+	    strcmp($formfields[usr_state], "") == 0) {
+	    $errors["State"] = "Missing Field";
+	}
+	elseif (! TBvalid_state($formfields[usr_state])) {
+	    $errors["State"] = TBFieldErrorString();
+	}
+	if (!isset($formfields[usr_zip]) ||
+	    strcmp($formfields[usr_zip], "") == 0) {
+	    $errors["ZIP/Postal Code"] = "Missing Field";
+	}
+	elseif (! TBvalid_zip($formfields[usr_zip])) {
+	    $errors["Zip/Postal Code"] = TBFieldErrorString();
+	}
+	if (!isset($formfields[usr_country]) ||
+	    strcmp($formfields[usr_country], "") == 0) {
+	    $errors["Country"] = "Missing Field";
+	}
+	elseif (! TBvalid_country($formfields[usr_country])) {
+	    $errors["Country"] = TBFieldErrorString();
+	}
+	if (!isset($formfields[usr_phone]) ||
+	    strcmp($formfields[usr_phone], "") == 0) {
+	    $errors["Phone #"] = "Missing Field";
+	}
+	elseif (!TBvalid_phone($formfields[usr_phone])) {
+	    $errors["Phone #"] = TBFieldErrorString();
+	}
     }
     if (!isset($formfields[password1]) ||
 	strcmp($formfields[password1], "") == 0) {
@@ -536,8 +640,8 @@ if (! $returning) {
 	$errors["Password"] = "$checkerror";
     }
 }
-if (!isset($formfields[pid]) ||
-    strcmp($formfields[pid], "") == 0) {
+if (!$forwikionly && (!isset($formfields[pid]) ||
+		      strcmp($formfields[pid], "") == 0)) {
     $errors["Project Name"] = "Missing Field";
 }
 
@@ -552,18 +656,32 @@ if (count($errors)) {
 #
 if (!$returning) {
     $joining_uid       = $formfields[joining_uid];
-    $usr_title         = addslashes($formfields[usr_title]);
     $usr_name          = addslashes($formfields[usr_name]);
-    $usr_affil         = addslashes($formfields[usr_affil]);
     $usr_email         = $formfields[usr_email];
-    $usr_addr          = addslashes($formfields[usr_addr]);
-    $usr_city          = addslashes($formfields[usr_city]);
-    $usr_state         = addslashes($formfields[usr_state]);
-    $usr_zip           = addslashes($formfields[usr_zip]);
-    $usr_country       = addslashes($formfields[usr_country]);
-    $usr_phone         = $formfields[usr_phone];
     $password1         = $formfields[password1];
     $password2         = $formfields[password2];
+    $wikiname          = ($WIKISUPPORT ? $formfields[wikiname] : "");
+
+    if (!$forwikionly) {
+	$usr_affil         = addslashes($formfields[usr_affil]);
+	$usr_title         = addslashes($formfields[usr_title]);
+	$usr_addr          = addslashes($formfields[usr_addr]);
+	$usr_city          = addslashes($formfields[usr_city]);
+	$usr_state         = addslashes($formfields[usr_state]);
+	$usr_zip           = addslashes($formfields[usr_zip]);
+	$usr_country       = addslashes($formfields[usr_country]);
+	$usr_phone         = $formfields[usr_phone];
+    }
+    else {
+	$usr_affil         = "";
+	$usr_title         = "";
+	$usr_addr          = "";
+	$usr_city          = "";
+	$usr_state         = "";
+	$usr_zip           = "";
+	$usr_country       = "";
+	$usr_phone         = "";
+    }
 
     if (! isset($formfields[usr_URL]) ||
 	strcmp($formfields[usr_URL], "") == 0 ||
@@ -657,14 +775,16 @@ else {
     $gid = $pid;
 }
 
-if (!TBvalid_pid($pid) || !TBValidProject($pid)) {
-    $errors["Project Name"] = "Invalid Project Name";
-}
-elseif (!TBvalid_gid($gid) || !TBValidGroup($pid, $gid)) {
-    $errors["Group Name"] = "Invalid Group Name";
-}
-elseif (TBGroupMember($joining_uid, $pid, $gid, $approved)) {
-    $errors["Membership"] = "You are already a member";
+if (!$forwikionly) {
+    if (!TBvalid_pid($pid) || !TBValidProject($pid)) {
+	$errors["Project Name"] = "Invalid Project Name";
+    }
+    elseif (!TBvalid_gid($gid) || !TBValidGroup($pid, $gid)) {
+	$errors["Group Name"] = "Invalid Group Name";
+    }
+    elseif (TBGroupMember($joining_uid, $pid, $gid, $approved)) {
+	$errors["Membership"] = "You are already a member";
+    }
 }
 
 #
@@ -702,14 +822,14 @@ if (! $returning) {
 	"(uid,usr_created,usr_expires,usr_name,usr_email,usr_addr,".
 	" usr_addr2,usr_city,usr_state,usr_zip,usr_country, ".
 	" usr_URL,usr_phone,usr_shell,usr_title,usr_affil,usr_pswd,unix_uid,".
-	" status,pswd_expires,usr_modified) ".
+	" status,pswd_expires,usr_modified,wikionly,wikiname) ".
 	"VALUES ('$joining_uid', now(), '$usr_expires', '$usr_name', ".
         "'$usr_email', ".
 	"'$usr_addr', '$usr_addr2', '$usr_city', '$usr_state', '$usr_zip', ".
 	"'$usr_country', ".
 	"'$usr_URL', '$usr_phone', 'tcsh', '$usr_title', '$usr_affil', ".
         "'$encoding', NULL, 'newuser', ".
-	"date_add(now(), interval 1 year), now())");
+	"date_add(now(), interval 1 year), now(), $forwikionly, '$wikiname')");
 
     DBQueryFatal("INSERT INTO user_stats (uid) VALUES ('$joining_uid')");
 
@@ -724,11 +844,17 @@ if (! $returning) {
       "\n".
       "    ${TBBASE}/login.php3?vuid=$joining_uid&key=$key\n".
       "\n".
-      "Once you have verified your account, the project leader will be\n".
-      "able to approve you. You MUST verify your account before the project\n".
-      "leader can approve you. After project approval, you will be\n".
-      "marked as an active user, and will be granted full access to your\n".
-      "user account.\n\n".
+      ($forwikionly ?
+       "Once you have verified your account, you will be able to access\n".
+       "the Wiki. You MUST verify your account first!"
+       :       
+       "Once you have verified your account, the project leader will be\n".
+       "able to approve you. You MUST verify your account before the project".
+       "\n".
+       "leader can approve you. After project approval, you will be\n".
+       "marked as an active user, and will be granted full access to your\n".
+       "user account.") .
+      "\n\n".
       "Thanks,\n".
       "Testbed Operations\n",
       "From: $TBMAIL_APPROVAL\n".
@@ -736,6 +862,14 @@ if (! $returning) {
       "Errors-To: $TBMAIL_WWW");
 }
 
+#
+# For wikionly registration, we are done.
+# 
+if ($forwikionly) {
+    header("Location: wikiregister.php3?finished=1");
+    exit();
+}
+
 #
 # Add to the group, but with trust=none. The project/group leader will have
 # to upgrade the trust level, making the new user real.
@@ -814,5 +948,3 @@ if ($returning) {
 # See above for conclusion.
 # 
 header("Location: joinproject.php3?finished=1");
-
-?>
diff --git a/www/menu.php3 b/www/menu.php3
index eb14e98004aa2cd13d23bc731890595f4d562e05..eb0406c7c405e24cd67dd1669ecaf9a7412aabb2 100644
--- a/www/menu.php3
+++ b/www/menu.php3
@@ -357,10 +357,18 @@ function WRITESIDEBAR() {
 		WRITESIDEBARBUTTON("Change Your Password",
 				   $TBBASE, "moduserinfo.php3");
 	    }
-	    elseif ($login_status & CHECKLOGIN_WEBONLY) {
+	    elseif ($login_status & CHECKLOGIN_WEBONLY|CHECKLOGIN_WIKIONLY) {
 		WRITESIDEBARBUTTON("My Emulab",
 				   $TBBASE,
 				   "showuser.php3?target_uid=$login_uid");
+
+		if ($WIKISUPPORT && $CHECKLOGIN_WIKINAME != "") {
+		    $wikiname = $CHECKLOGIN_WIKINAME;
+		
+		    WRITESIDEBARBUTTON_ABSCOOL("My Wikis",
+					       "${WIKIURL}/Main/$wikiname",
+					       "${WIKIURL}/Main/$wikiname");
+		}
 	    
 		WRITESIDEBARBUTTON("Update User Information",
 				   $TBBASE, "moduserinfo.php3");
diff --git a/www/moduserinfo.php3 b/www/moduserinfo.php3
index 7b1738ac8c298e1fbaeded4eb30c94b930747541..ba604fb78a0f800df433283c9698fe5b782d874a 100644
--- a/www/moduserinfo.php3
+++ b/www/moduserinfo.php3
@@ -19,7 +19,8 @@ include("showstuff.php3");
 #
 $uid = GETLOGIN();
 LOGGEDINORDIE($uid,
-	      CHECKLOGIN_USERSTATUS|CHECKLOGIN_PSWDEXPIRED|CHECKLOGIN_WEBONLY);
+	      CHECKLOGIN_USERSTATUS|CHECKLOGIN_PSWDEXPIRED|
+	      CHECKLOGIN_WEBONLY|CHECKLOGIN_WIKIONLY);
 $isadmin = ISADMIN($uid);
 
 
@@ -29,13 +30,16 @@ $shelllist = array( 'tcsh', 'bash', 'csh', 'sh' );
 # used if db slot for user is NULL (should not happen.)
 $defaultshell = 'tcsh';
 
+# See below.
+$wikionly = 0;
+
 #
 # Spit the form out using the array of data and error strings (if any).
 # 
 function SPITFORM($formfields, $errors)
 {
     global $TBDB_UIDLEN, $TBDB_PIDLEN, $TBDB_GIDLEN, $isadmin;
-    global $target_uid;
+    global $target_uid, $wikionly;
     global $shelllist, $defaultshell;
     
     #
@@ -66,10 +70,13 @@ function SPITFORM($formfields, $errors)
 	echo "</table><br>\n";
     }
 
+    # For indicating that fields are optional or not.
+    $optfield = ($wikionly ? "" : "*");
+
     echo "<table align=center border=1> 
           <tr>
             <td align=center colspan=3>
-                Fields marked with * are required.
+                <b>Fields marked with * are required.</b>
             </td>
           </tr>\n
 
@@ -107,20 +114,20 @@ function SPITFORM($formfields, $errors)
 	# Title/Position:
 	# 
 	echo "<tr>
-                  <td colspan=2>*Title/Position:</td>
+                  <td colspan=2>${optfield}Title/Position:</td>
                   <td class=left>
                       <input type=text
                              name=\"formfields[usr_title]\"
                              value=\"" . $formfields[usr_title] . "\"
 	                     size=30>
                   </td>
-              </tr>\n";
+               </tr>\n";
 
         #
-	# Affiliation:
+   	# Affiliation:
 	# 
 	echo "<tr>
-                  <td colspan=2>*Institutional<br>Affiliation:</td>
+                  <td colspan=2>${optfield}Institutional<br>Affiliation:</td>
                   <td class=left>
                       <input type=text
                              name=\"formfields[usr_affil]\"
@@ -146,7 +153,7 @@ function SPITFORM($formfields, $errors)
 	# Email:
 	#
 	echo "<tr>
-                  <td colspan=2>*Email Address[<b>1</b>]:</td>
+                  <td colspan=2>Email Address[<b>1</b>]:</td>
                   <td class=left> ";
 	if ($isadmin)
 	    echo "    <input type=text ";
@@ -167,8 +174,11 @@ function SPITFORM($formfields, $errors)
 	    $formfields[usr_country] = "USA";
 	}
 
-	echo "<tr><td colspan=3>*Address:<br /><center>
-		<table>
+	#
+	# Postal Address
+        #
+	echo "<tr><td colspan=3>${optfield}Address:<br /><center>
+	      <table>
 		  <tr><td>Line 1</td><td colspan=3>
                     <input type=text
                            name=\"formfields[usr_addr]\"
@@ -201,17 +211,13 @@ function SPITFORM($formfields, $errors)
 	                   size=15></td></tr>
                </table></center></td></tr>";
 
-	#
-	# Default Group
-	#
-		
-	# Default Shell
-        echo "<tr><td colspan=2>Shell:</td>
+        # Default Shell
+	echo "<tr><td colspan=2>Shell:</td>
                   <td class=left>";
-        echo "<select name=\"formfields[usr_shell]\">";
+	echo "<select name=\"formfields[usr_shell]\">";
 	foreach ($shelllist as $s) {
 	    if ((!isset($formfields[usr_shell]) &&
-		0 == strcmp($defaultshell, $s)) ||
+		 0 == strcmp($defaultshell, $s)) ||
 		0 == strcmp($formfields[usr_shell],$s)) {
 		$sel = "selected='1'";
 	    } else {
@@ -219,13 +225,13 @@ function SPITFORM($formfields, $errors)
 	    }
 	    echo "<option value='$s' $sel>$s</option>";
 	}	
-        echo "</select></td></tr>";
+	echo "</select></td></tr>";
 
 	#
 	# Phone
 	#
 	echo "<tr>
-                  <td colspan=2>*Phone #:</td>
+                  <td colspan=2>${optfield}Phone #:</td>
                   <td class=left>
                       <input type=text
                              name=\"formfields[usr_phone]\"
@@ -238,6 +244,7 @@ function SPITFORM($formfields, $errors)
 	# Password. Note that we do not resend the password. User
 	# must retype on error.
 	#
+	echo "<tr></tr>\n";
 	echo "<tr>
                   <td colspan=2>Password[<b>1</b>]:</td>
                   <td class=left>
@@ -254,51 +261,55 @@ function SPITFORM($formfields, $errors)
                              size=8></td>
              </tr>\n";
 
-	# Windows Password.  Initial random default is based on the Unix
-	# password hash.
-	# 
-	# A separate password is kept for experiment nodes running Windows.
-	# It is presented behind-the-scenes to rdesktop and Samba by our Web
-	# interface, but you may still need to type it.  The default password
-	# is randomly generated.  You may change it to something easier to
-	# remember.
-	#
-	echo "<tr>
-                  <td colspan=2>Windows Password[<b>1,4</b>]:</td>
-                  <td class=left>
-                      <input type=text
-                             name=\"formfields[w_password1]\"
-                             value=\"" . $formfields[w_password1] . "\"
-                             size=8></td>
-              </tr>\n";
+	if (!$wikionly) {
+	    #
+            # Windows Password.  Initial random default is based on the Unix
+	    # password hash.
+	    #   
+	    # A separate password is kept for experiment nodes running Windows.
+	    # It is presented behind-the-scenes to rdesktop and Samba by our
+	    # Web# interface, but you may still need to type it.
+	    # The default password is randomly generated.
+	    # You may change it to something easier to remember.
+	    #
+	    echo "<tr>
+                      <td colspan=2>Windows Password[<b>1,4</b>]:</td>
+                      <td class=left>
+                          <input type=text
+                                 name=\"formfields[w_password1]\"
+                                 value=\"" . $formfields[w_password1] . "\"
+                                 size=8></td>
+                  </tr>\n";
 
-        echo "<tr>
-                  <td colspan=2>Retype Windows Password:</td>
-                  <td class=left>
-                      <input type=text
-                             name=\"formfields[w_password2]\"
-                             size=8></td>
-             </tr>\n";
+	    echo "<tr>
+                      <td colspan=2>Retype Windows Password:</td>
+                      <td class=left>
+                          <input type=text
+                                 name=\"formfields[w_password2]\"
+                                 size=8></td>
+                 </tr>\n";
+
+            #
+	    # Planetlab bit. This should really be a drop down menu of the
+	    #                choices.
+            #
+	    if ($formfields[user_interface] == TBDB_USER_INTERFACE_PLAB) {
+		$checked = "checked";
+	    } else {
+		$checked = "";
+	    }
 
-        #
-	# Planetlab bit. This should really be a drop down menu of the choices.
-	#
-	if ($formfields[user_interface] == TBDB_USER_INTERFACE_PLAB) {
-	    $checked = "checked";
-	} else {
-	    $checked = "";
+	    echo "<tr>
+		      <td colspan=2>Use simplified PlanetLab view:</td>
+		      <td class=left>
+		         <input type='checkbox'
+                                name=\"formfields[user_interface]\"
+                                value=\"" . TBDB_USER_INTERFACE_PLAB . "\"
+			        $checked>
+		      </td>
+	          </tr>\n";
 	}
 
-	echo "<tr>
-		  <td colspan=2>Use simplified PlanetLab view:</td>
-		  <td class=left>
-		     <input type='checkbox'
-                            name=\"formfields[user_interface]\"
-                            value=\"" . TBDB_USER_INTERFACE_PLAB . "\"
-			    $checked>
-		  </td>
-	      </tr>\n";
-
         #
 	# Notes
 	#
@@ -328,8 +339,9 @@ function SPITFORM($formfields, $errors)
             <li> Please consult our
                  <a href = 'docwrapper.php3?docname=security.html'>
                  security policies</a> for information
-                 regarding passwords and email addresses.
-            <li> You can also
+                 regarding passwords and email addresses.\n";
+    if (!$wikionly) {
+	echo "<li> You can also
                  <a href='showpubkeys.php3?target_uid=$target_uid'>
                  edit your ssh public keys</a> and your
                  <a href='showsfskeys.php3?target_uid=$target_uid'>
@@ -342,8 +354,9 @@ function SPITFORM($formfields, $errors)
                  Windows.  It is presented behind-the-scenes to rdesktop and
                  Samba by our Web interface, but you may still need to type
                  it.  The default password is randomly generated.  You may
-                 change it to something easier to remember.
-          </ol>
+                 change it to something easier to remember.\n";
+    }
+    echo "</ol>
           </blockquote></blockquote>
           </h4>\n";
 }
@@ -422,6 +435,7 @@ $defaults[usr_affil]   = $row[usr_affil];
 $defaults[usr_shell]   = $row[usr_shell];
 $defaults[notes]       = $row[notes];
 $defaults[user_interface] = $row[user_interface];
+$wikionly              = $row[wikionly];
 
 # Show and keep the Windows password if user-set, otherwise fill in the random one.
 if (strcmp($row[usr_w_pswd],""))
@@ -456,13 +470,6 @@ $errors = array();
 #
 # These fields are required!
 #
-if (!isset($formfields[usr_title]) ||
-    strcmp($formfields[usr_title], "") == 0) {
-    $errors["Title/Position"] = "Missing Field";
-}
-elseif (! TBvalid_title($formfields[usr_title])) {
-    $errors["Title/Position"] = TBFieldErrorString();
-}
 if (!isset($formfields[usr_name]) ||
     strcmp($formfields[usr_name], "") == 0) {
     $errors["Full Name"] = "Missing Field";
@@ -476,18 +483,35 @@ $tokens = preg_split("/[\s]+/", $formfields[usr_name],
 if (count($tokens) < 2) {
     $errors["Full Name"] = "Please provide a first and last name";
 }
-
-if (!isset($formfields[usr_affil]) ||
-    strcmp($formfields[usr_affil], "") == 0) {
-    $errors["Affiliation"] = "Missing Field";
+if (!$wikionly) {
+    # WikiOnly can leave these fields blank, but must error check them anyway.
+    if (!isset($formfields[usr_title]) ||
+	strcmp($formfields[usr_title], "") == 0) {
+	$errors["Title/Position"] = "Missing Field";
+    }
+    if (!isset($formfields[usr_affil]) ||
+	strcmp($formfields[usr_affil], "") == 0) {
+	$errors["Affiliation"] = "Missing Field";
+    }
+}
+if (isset($formfields[usr_title]) &&
+    ! TBvalid_title($formfields[usr_title])) {
+    $errors["Title/Position"] = TBFieldErrorString();
 }
-elseif (! TBvalid_affiliation($formfields[usr_affil])) {
+if (isset($formfields[usr_affil]) &&
+    ! TBvalid_affiliation($formfields[usr_affil])) {
     $errors["Affiliation"] = TBFieldErrorString();
 }
 if (!isset($formfields[usr_shell]) ||
     !in_array($formfields[usr_shell], $shelllist)) {
     $errors["Shell"] = "Invalid Shell";
 }
+if (isset($formfields[usr_URL]) &&
+    strcmp($formfields[usr_URL], "") &&
+    strcmp($formfields[usr_URL], $HTTPTAG) &&
+    ! CHECKURL($formfields[usr_URL], $urlerror)) {
+    $errors["Home Page URL"] = $urlerror;
+}
 if (!isset($formfields[usr_email]) ||
     strcmp($formfields[usr_email], "") == 0) {
     $errors["Email Address"] = "Missing Field";
@@ -495,13 +519,7 @@ if (!isset($formfields[usr_email]) ||
 elseif (! TBvalid_email($formfields[usr_email])) {
     $errors["Email Address"] = TBFieldErrorString();
 }
-if (isset($formfields[usr_URL]) &&
-    strcmp($formfields[usr_URL], "") &&
-    strcmp($formfields[usr_URL], $HTTPTAG) &&
-    ! CHECKURL($formfields[usr_URL], $urlerror)) {
-    $errors["Home Page URL"] = $urlerror;
-}
-if (!$isadmin) {
+if (!$isadmin && !$wikionly) {
     # Admins can leave these fields blank, but must error check them anyway.
     if (!isset($formfields[usr_addr]) ||
 	strcmp($formfields[usr_addr], "") == 0) {
@@ -553,7 +571,7 @@ if (isset($formfields[usr_country]) &&
     !TBvalid_country($formfields[usr_zip])) {
     $errors["Zip/Postal Code"] = TBFieldErrorString();
 }
-if (isset($formfields[usr_phone]) &&
+if (isset($formfields[usr_phone]) && $formfields[usr_phone] != "" &&
     !TBvalid_phone($formfields[usr_phone])) {
     $errors["Phone #"] = TBFieldErrorString();
 }
@@ -596,10 +614,12 @@ if (count($errors)) {
     return;
 }
 
-$usr_title    = addslashes($formfields[usr_title]);
 $usr_name     = addslashes($formfields[usr_name]);
-$usr_affil    = addslashes($formfields[usr_affil]);
 $usr_email    = $formfields[usr_email];
+$password1    = $formfields[password1];
+$password2    = $formfields[password2];
+$usr_title    = addslashes($formfields[usr_title]);
+$usr_affil    = addslashes($formfields[usr_affil]);
 $usr_addr     = addslashes($formfields[usr_addr]);
 $usr_city     = addslashes($formfields[usr_city]);
 $usr_state    = addslashes($formfields[usr_state]);
@@ -607,8 +627,6 @@ $usr_zip      = addslashes($formfields[usr_zip]);
 $usr_country  = addslashes($formfields[usr_country]);
 $usr_phone    = $formfields[usr_phone];
 $usr_shell    = $formfields[usr_shell];
-$password1    = $formfields[password1];
-$password2    = $formfields[password2];
 $w_password1  = $formfields[w_password1];
 $w_password2  = $formfields[w_password2];
 
@@ -691,7 +709,13 @@ if ((isset($password1) && strcmp($password1, "")) &&
 		     "pswd_expires=$expires ".
 		     "WHERE uid='$target_uid'");
 
-    if (HASREALACCOUNT($uid) && HASREALACCOUNT($target_uid)) {
+    if ($wikionly) {
+	if ($CHECKLOGIN_STATUS & CHECKLOGIN_ACTIVE) {
+	    SUEXEC("nobody", "nobody", "webtbacct passwd $target_uid",
+		   SUEXEC_ACTION_DIE);
+	}
+    }
+    elseif (HASREALACCOUNT($uid) && HASREALACCOUNT($target_uid)) {
 	SUEXEC($uid, "nobody", "webtbacct passwd $target_uid", 1);
     }
 }
@@ -700,8 +724,9 @@ if ((isset($password1) && strcmp($password1, "")) &&
 # See if the user is requesting to change the Windows password. We checked
 # them above when the form was submitted.
 #
-if ((isset($w_password1) && strcmp($w_password1, "")) &&
-    (isset($w_password2) && strcmp($w_password2, ""))) {
+if (!$wikionly &&
+    ((isset($w_password1) && strcmp($w_password1, "")) &&
+     (isset($w_password2) && strcmp($w_password2, "")))) {
 
     #
     # Insert into database.
@@ -802,6 +827,7 @@ if (strcmp($defaults[usr_name],  $formfields[usr_name]) ||
 	   "Phone:             $usr_phone\n".
 	   "Title:             $usr_title\n".
 	   "Shell:             $usr_shell\n",
+	   "WikiOnly:	       $wikionly\n",
 	   "From: $TBMAIL_OPS\n".
 	   $BCC .
 	   "Errors-To: $TBMAIL_WWW");
diff --git a/www/newproject.php3 b/www/newproject.php3
index 560f50df03fdb8262a53af385bc80e9655cd42fd..2a76297c0c3f6f781be7b73990aedc6d6091b097 100755
--- a/www/newproject.php3
+++ b/www/newproject.php3
@@ -52,7 +52,8 @@ function SPITFORM($formfields, $returning, $errors)
     global $TBDB_UIDLEN, $TBDB_PIDLEN, $TBDOCBASE, $WWWHOST;
     global $usr_keyfile;
     global $ACCOUNTWARNING, $EMAILWARNING;
-
+    global $WIKISUPPORT, $WIKIURL;
+    
     PAGEHEADER("Start a New Testbed Project");
 
     echo "<center><font size=+1>
@@ -92,6 +93,34 @@ function SPITFORM($formfields, $returning, $errors)
 	}
 	echo "</table><br>\n";
     }
+    echo "<SCRIPT LANGUAGE=JavaScript>
+              function SetWikiName(theform) 
+              {
+	          var validchars = 'abcdefghijklmnopqrstuvwxyz0123456789';
+                  var usrname    = theform['formfields[usr_name]'].value;
+                  var wikiname   = '';
+                  var docap      = 1;
+
+		  for (var i = 0; i < usrname.length; i++) {
+                      var letter = usrname.charAt(i).toLowerCase();
+
+                      if (validchars.indexOf(letter) == -1) {
+                          if (letter == ' ') {
+                              docap = 1;
+                          }
+                          continue;
+                      }
+                      else {
+                          if (docap == 1) {
+                              letter = usrname.charAt(i).toUpperCase()
+                              docap  = 0;
+                          }
+                          wikiname = wikiname + letter;
+                      }
+                  }
+                  theform['formfields[wikiname]'].value = wikiname;
+              }
+          </SCRIPT>\n";
 
     echo "<table align=center border=1> 
           <tr>
@@ -100,7 +129,7 @@ function SPITFORM($formfields, $returning, $errors)
             </td>
           </tr>\n
 
-          <form enctype=multipart/form-data
+          <form enctype=multipart/form-data name=myform
                 action=newproject.php3 method=post>\n";
 
     if (! $returning) {
@@ -141,10 +170,27 @@ function SPITFORM($formfields, $returning, $errors)
                       <input type=text
                              name=\"formfields[usr_name]\"
                              value=\"" . $formfields[usr_name] . "\"
+                             onchange=\"SetWikiName(myform);\"
 	                     size=30>
                   </td>
               </tr>\n";
 
+	#
+	# WikiName
+	#
+	if ($WIKISUPPORT) {
+	    echo "<tr>
+                      <td colspan=2>*
+                          <a href=${WIKIURL}/TWiki/WikiName
+                            target=_blank>WikiName</a>:<td class=left>
+                          <input type=text
+                                 name=\"formfields[wikiname]\"
+                                 value=\"" . $formfields[wikiname] . "\"
+	                         size=30>
+                      </td>
+                  </tr>\n";
+	}
+
         #
 	# Title/Position:
 	# 
@@ -592,7 +638,18 @@ if (! $returning) {
     if (count($tokens) < 2) {
 	$errors["Full Name"] = "Please provide a first and last name";
     }
-    
+    if ($WIKISUPPORT) {
+	if (!isset($formfields[wikiname]) ||
+	    strcmp($formfields[wikiname], "") == 0) {
+	    $errors["WikiName"] = "Missing Field";
+	}
+	elseif (! TBvalid_wikiname($formfields[wikiname])) {
+	    $errors["WikiName"] = TBFieldErrorString();
+	}
+	elseif (TBCurrentWikiName($formfields[wikiname])) {
+	    $errors["WikiName"] = "Already in use. Pick another";
+	}
+    }
     if (!isset($formfields[usr_affil]) ||
 	strcmp($formfields[usr_affil], "") == 0) {
 	$errors["Affiliation"] = "Missing Field";
@@ -795,6 +852,7 @@ if (!$returning) {
     $usr_phone         = $formfields[usr_phone];
     $password1         = $formfields[password1];
     $password2         = $formfields[password2];
+    $wikiname          = ($WIKISUPPORT ? $formfields[wikiname] : "");
     $usr_returning     = "No";
 
     if (! isset($formfields[usr_URL]) ||
@@ -891,6 +949,7 @@ else {
     $usr_country   = $row[usr_country];
     $usr_phone	   = $row[usr_phone];
     $usr_URL       = $row[usr_URL];
+    $wikiname      = $row[wikiname];
     $usr_returning = "Yes";
 }
 $pid               = $formfields[pid];
@@ -954,14 +1013,14 @@ if (! $returning) {
 	 "(uid,usr_created,usr_expires,usr_name,usr_email,usr_addr,".
 	 " usr_addr2,usr_city,usr_state,usr_zip,usr_country, ".
 	 " usr_URL,usr_title,usr_affil,usr_phone,usr_shell,usr_pswd,unix_uid,".
-	 " status,pswd_expires,usr_modified) ".
+	 " status,pswd_expires,usr_modified,wikiname) ".
 	 "VALUES ('$proj_head_uid', now(), '$proj_expires', '$usr_name', ".
          "'$usr_email', ".
 	 "'$usr_addr', '$usr_addr2', '$usr_city', '$usr_state', '$usr_zip', ".
 	 "'$usr_country', ".
 	 "'$usr_URL', '$usr_title', '$usr_affil', ".
 	 "'$usr_phone', 'tcsh', '$encoding', NULL, 'newuser', ".
-	 "date_add(now(), interval 1 year), now())");
+	 "date_add(now(), interval 1 year), now(), '$wikiname')");
 
     DBQueryFatal("INSERT INTO user_stats (uid) VALUES ('$proj_head_uid')");
     
diff --git a/www/showuser.php3 b/www/showuser.php3
index 16c3d4d6c71c6e69c129a257b1940476a7fdaca9..5ea1df61d1b4b7078f8bac84d547b956fec3acd4 100644
--- a/www/showuser.php3
+++ b/www/showuser.php3
@@ -1,7 +1,7 @@
 <?php
 #
 # EMULAB-COPYRIGHT
-# Copyright (c) 2000-2004 University of Utah and the Flux Group.
+# Copyright (c) 2000-2005 University of Utah and the Flux Group.
 # All rights reserved.
 #
 include("defs.php3");
@@ -11,7 +11,8 @@ include("showstuff.php3");
 # Only known and logged in users can do this.
 #
 $uid = GETLOGIN();
-LOGGEDINORDIE($uid, CHECKLOGIN_USERSTATUS|CHECKLOGIN_WEBONLY);
+LOGGEDINORDIE($uid, CHECKLOGIN_USERSTATUS|
+	      CHECKLOGIN_WEBONLY|CHECKLOGIN_WIKIONLY);
 $isadmin = ISADMIN($uid);
 
 #
@@ -39,6 +40,7 @@ else {
 if (! ($userstatus = TBUserStatus($target_uid))) {
     USERERROR("The user $target_uid is not a valid user", 1);
 }
+$wikionly = TBWikiOnlyUser($target_uid);
 
 #
 # Verify that this uid is a member of one of the projects that the
@@ -178,7 +180,7 @@ SUBMENUSTART("User Options");
 # 
 WRITESUBMENUBUTTON("Edit Profile",  "moduserinfo.php3?target_uid=$target_uid");
 
-if ($isadmin || !strcmp($uid, $target_uid)) {
+if (!$wikionly && ($isadmin || !strcmp($uid, $target_uid))) {
     WRITESUBMENUBUTTON("Edit SSH Keys",
 		       "showpubkeys.php3?target_uid=$target_uid");
     WRITESUBMENUBUTTON("Edit SFS Keys",
diff --git a/www/tbauth.php3 b/www/tbauth.php3
index cfa8ece57344e57c675a5ea0a3284af43ac83bee..9424c7ff3071f2d4ea964182f68fe2b976a3540a 100644
--- a/www/tbauth.php3
+++ b/www/tbauth.php3
@@ -44,6 +44,7 @@ define("CHECKLOGIN_ADMINOFF",		0x020000);
 define("CHECKLOGIN_WEBONLY",		0x040000);
 define("CHECKLOGIN_PLABUSER",		0x080000);
 define("CHECKLOGIN_STUDLY",		0x100000);
+define("CHECKLOGIN_WIKIONLY",		0x200000);
 
 #
 # Constants for tracking possible login attacks.
@@ -151,7 +152,8 @@ function CHECKLOGIN($uid) {
     $query_result =
 	DBQueryFatal("select NOW()>=u.pswd_expires,l.hashkey,l.timeout, ".
 		     "       status,admin,cvsweb,g.trust,adminoff,webonly, " .
-		     "       user_interface,n.type,u.stud,u.wikiname " .
+		     "       user_interface,n.type,u.stud,u.wikiname, ".
+		     "       u.wikionly " .
 		     " from users as u ".
 		     "left join login as l on l.uid=u.uid ".
 		     "left join group_membership as g on g.uid=u.uid ".
@@ -189,6 +191,7 @@ function CHECKLOGIN($uid) {
 	$type     = $row[10];
 	$stud     = $row[11];
 	$wikiname = $row[12];
+	$wikionly = $row[13];
 
 	$CHECKLOGIN_NODETYPES[$type] = 1;
     }
@@ -296,6 +299,8 @@ function CHECKLOGIN($uid) {
 	$CHECKLOGIN_STATUS |= CHECKLOGIN_ADMINOFF;
     if ($webonly)
 	$CHECKLOGIN_STATUS |= CHECKLOGIN_WEBONLY;
+    if ($wikionly)
+	$CHECKLOGIN_STATUS |= CHECKLOGIN_WIKIONLY;
     if ($trusted)
 	$CHECKLOGIN_STATUS |= CHECKLOGIN_TRUSTED;
     if ($stud)
@@ -390,6 +395,8 @@ function LOGGEDINORDIE($uid, $modifier = 0, $login_url = NULL) {
         USERERROR("Your account has not been approved yet!", 1);
     if (($status & CHECKLOGIN_WEBONLY) && ! ISADMIN($uid))
         USERERROR("Your account does not permit you to access this page!", 1);
+    if (($status & CHECKLOGIN_WIKIONLY) && ! ISADMIN($uid))
+        USERERROR("Your account does not permit you to access this page!", 1);
 
     #
     # Lastly, check for nologins here. This heads off a bunch of other
@@ -434,6 +441,19 @@ function STUDLY() {
 	    (CHECKLOGIN_LOGGEDIN|CHECKLOGIN_STUDLY));
 }
 
+function WIKIONLY() {
+    global $CHECKLOGIN_STATUS;
+    
+    if ($CHECKLOGIN_STATUS == CHECKLOGIN_NOSTATUS) {
+	$uid=GETUID();
+	TBERROR("WIKIONLY: $uid is not logged in!", 1);
+    }
+
+    return (($CHECKLOGIN_STATUS &
+	     (CHECKLOGIN_LOGGEDIN|CHECKLOGIN_WIKIONLY)) ==
+	    (CHECKLOGIN_LOGGEDIN|CHECKLOGIN_WIKIONLY));
+}
+
 # Is this user a real administrator (ignore onoff bit).
 function ISADMINISTRATOR() {
     global $CHECKLOGIN_STATUS;
@@ -823,16 +843,18 @@ function LASTWEBLOGIN($uid) {
 
 function HASREALACCOUNT($uid) {
     $query_result =
-	DBQueryFatal("select status,webonly from users where uid='$uid'");
+	DBQueryFatal("select status,webonly,wikionly from users ".
+		     "where uid='$uid'");
 
     if (!mysql_num_rows($query_result)) {
 	return 0;
     }
     $row = mysql_fetch_array($query_result);
-    $status  = $row[0];
-    $webonly = $row[1];
+    $status   = $row[0];
+    $webonly  = $row[1];
+    $wikionly = $row[2];
 
-    if ($webonly ||
+    if ($webonly || $wikionly ||
 	(strcmp($status, TBDB_USERSTATUS_ACTIVE) &&
 	 strcmp($status, TBDB_USERSTATUS_FROZEN))) {
 	return 0;
diff --git a/www/verifyusr.php3 b/www/verifyusr.php3
index f114f0632cb513c296fcac14f0c780f214f640d5..c707c55939b41e5bfe21111824804f3be1da0235 100644
--- a/www/verifyusr.php3
+++ b/www/verifyusr.php3
@@ -1,7 +1,7 @@
 <?php
 #
 # EMULAB-COPYRIGHT
-# Copyright (c) 2000-2003 University of Utah and the Flux Group.
+# Copyright (c) 2000-2003, 2005 University of Utah and the Flux Group.
 # All rights reserved.
 #
 include("defs.php3");
@@ -16,7 +16,8 @@ PAGEHEADER("Confirm Verification");
 #
 $uid = GETLOGIN();
 LOGGEDINORDIE($uid,
-	      CHECKLOGIN_UNVERIFIED|CHECKLOGIN_NEWUSER|CHECKLOGIN_WEBONLY);
+	      CHECKLOGIN_UNVERIFIED|CHECKLOGIN_NEWUSER|
+	      CHECKLOGIN_WEBONLY|CHECKLOGIN_WIKIONLY);
 
 #
 # Must provide the key!
@@ -30,12 +31,14 @@ if (!isset($key) || strcmp($key, "") == 0) {
 # Grab the status and do the modification.
 #
 $query_result =
-    DBQueryFatal("select status from users where uid='$uid'");
+    DBQueryFatal("select status,wikionly from users ".
+		 "where uid='$uid'");
 
 if (($row = mysql_fetch_row($query_result)) == 0) {
     TBERROR("Database Error retrieving status for $uid!", 1);
 }
-$status = $row[0];
+$status   = $row[0];
+$wikionly = $row[1];
 
 #
 # No multiple verifications!
@@ -216,24 +219,50 @@ if (strcmp($status, TBDB_USERSTATUS_UNVERIFIED) == 0) {
 	 "that are now available to you will appear.\n";
 }
 elseif (strcmp($status, TBDB_USERSTATUS_NEWUSER) == 0) {
-    DBQueryFatal("update users set status='unapproved' where uid='$uid'");
+    $newstatus = ($wikionly ? "active" : "unapproved");
+    
+    DBQueryFatal("update users set status='$newstatus' where uid='$uid'");
 
     TBMAIL($TBMAIL_AUDIT,
 	   "User '$uid' has been verified",
 	   "\n".
 	   "User '$uid' has been verified.\n".
-           "Status has been changed from 'newuser' to 'unapproved'\n".
+           "Status has been changed from 'newuser' to '$newstatus'\n".
 	   "\n".
 	   "Testbed Operations\n",
 	   "From: $TBMAIL_OPS\n".
 	   "Errors-To: $TBMAIL_WWW");
 
-    INFORMLEADERS($uid);
+    if ($wikionly) {
+	#
+	# For wikionly accounts, build the account now.
+	# Just builds the wiki account of course (nothing else).
+	#
+	SUEXEC("nobody", $TBADMINGROUP, "webtbacct add $uid",
+	       SUEXEC_ACTION_DIE);
 
-    echo "<p>".
-	 "You have now been verified. However, your application ".
-	 "has not yet been approved. You will receive ".
-	 "email when that has been done.\n";
+	#
+	# The backend sets the actual WikiName
+	# 
+	$query_result =
+	    DBQueryFatal("select wikiname from users where uid='$uid'");
+
+	if (($row = mysql_fetch_row($query_result)) == 0) {
+	    TBERROR("Database Error retrieving status for $uid!", 1);
+	}
+	$wikiname = $row[0];
+
+	echo "You have been verified. You may now access the Wiki at<br>".
+	    "<a href='$WIKIURL/$wikiname'>$WIKIURL/$wikiname</a>\n";
+    }
+    else {
+	INFORMLEADERS($uid);
+
+	echo "<p>".
+	     "You have now been verified. However, your application ".
+	    "has not yet been approved. You will receive ".
+	    "email when that has been done.\n";
+    }
 }
 else {
     TBERROR("Bad user status '$status' for $uid!", 1);
diff --git a/www/verifyusr_form.php3 b/www/verifyusr_form.php3
index 577a8ed4c754b51ff767e538971777bc5f83efa7..c47a0f309602a92f39508b8271f0e1d068ef5cd7 100644
--- a/www/verifyusr_form.php3
+++ b/www/verifyusr_form.php3
@@ -1,7 +1,7 @@
 <?php
 #
 # EMULAB-COPYRIGHT
-# Copyright (c) 2000-2002 University of Utah and the Flux Group.
+# Copyright (c) 2000-2002, 2005 University of Utah and the Flux Group.
 # All rights reserved.
 #
 include("defs.php3");
@@ -16,7 +16,8 @@ PAGEHEADER("New User Verification");
 #
 $uid = GETLOGIN();
 LOGGEDINORDIE($uid,
-	      CHECKLOGIN_UNVERIFIED|CHECKLOGIN_NEWUSER|CHECKLOGIN_WEBONLY);
+	      CHECKLOGIN_UNVERIFIED|CHECKLOGIN_NEWUSER|
+	      CHECKLOGIN_WEBONLY|CHECKLOGIN_WIKIONLY);
 
 echo "<p>
       The purpose of this page is to verify, for security purposes, that
diff --git a/www/wikiregister.php3 b/www/wikiregister.php3
new file mode 100644
index 0000000000000000000000000000000000000000..11f52ade3bf0ec739c440778ebf62f972e63b335
--- /dev/null
+++ b/www/wikiregister.php3
@@ -0,0 +1,12 @@
+<?php
+#
+# EMULAB-COPYRIGHT
+# Copyright (c) 2000-2003, 2005 University of Utah and the Flux Group.
+# All rights reserved.
+#
+
+$forwikionly = 1;
+
+include("joinproject.php3");
+
+?>