"Fossies" - the Fresh Open Source Software Archive

Member "htpasstool-v1.03/index.php" (19 Jan 2007, 30169 Bytes) of package /linux/www/old/htpasstool-v1.03.tgz:


The requested HTML page contains a <FORM> tag that is unusable on "Fossies" in "automatic" (rendered) mode so that page is shown as HTML source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "index.php" see the Fossies "Dox" file reference documentation.

A hint: This file contains one or more very long lines, so maybe it is better readable using the pure text view mode that shows the contents as wrapped lines within the browser window.


    1 <?
    2 # * htpasstool v1.0.3
    3 # *
    4 # * Copyright (C) 2006,2007  Ward Vandewege (ward AT pong DOT be)
    5 # *
    6 # * This program is free software; you can redistribute it and/or modify
    7 # * it under the terms of the GNU General Public License as published by
    8 # * the Free Software Foundation; either version 2 of the License, or
    9 # * (at your option) any later version.
   10 # *
   11 # * This program is distributed in the hope that it will be useful,
   12 # * but WITHOUT ANY WARRANTY; without even the implied warranty of
   13 # * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   14 # * GNU General Public License for more details.
   15 # *
   16 # * You should have received a copy of the GNU General Public License
   17 # * along with this program; if not, write to the Free Software
   18 # * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
   19 # *
   20 
   21 # ***************************************************************************
   22 # Start of configuration settings
   23 
   24   // If you want to manage directories that are not strictly lower than this
   25   // directory in your webspace, change BASE_DIRECTORY: replace realpath('.')
   26   // with a path on your filesystem.
   27 
   28   define("BASE_DIRECTORY", realpath('.'));
   29 
   30   // If you change BASE_DIRECTORY above, you should also set $url_prefix below.
   31   // Generally speaking, you should put the url that correspondes with
   32   // BASE_DIRECTORY as the value of $url_prefix.  For instance, if you are
   33   // setting BASE_DIRECTORY to '/var/www', and that is the DocumentRoot for
   34   // your web server, you should set $url_prefix to '/' - in that case you can
   35   // use a relative URL. But you may have to define $url_prefix to be a fully
   36   // fledged URL, depending on what URL BASE_DIRECTORY corresponds to for your
   37   // setup. You don't have to end $url_prefix with a slash.
   38   $url_prefix = '';
   39 
   40   // The e-mail address of the sender for the password reset/assign e-mails
   41   $admin_email = '';
   42 
   43   // The template subject for the password reset/assign e-mails
   44   $password_subject = "Login information";
   45 
   46   // The template message for the password reset/assign e-mails
   47   $password_body = "
   48 
   49 Your login information is:
   50 
   51   url: %%url%%
   52 
   53   login: %%login%%
   54   password: %%password%%
   55 
   56 ";
   57 
   58 
   59 # End of user-modifiable code. Change nothing below this line unless you know
   60 # what you are doing!
   61 # ***************************************************************************
   62 
   63   // return images
   64   if (isset($_REQUEST['image'])) {
   65     $imagesEncoded = Array(
   66       "padlock"  => "iVBORw0KGgoAAAANSUhEUgAAAA4AAAALCAYAAABPhbxiAAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsNAAALDQHtB8AsAAAAB3RJTUUH1AQFFhQ155Nu3wAAAFRJREFUeJxjZMAE/5HYjFjkGRgYGBiYcGhiROMTBOgKcWpEt5GBgYGBjVhbYIAVagM65sGmGNnz+PyDEUjYnEoUwKrx/3/CgUm2jVTxIwcOTczYBAEMQw8nZ2fMggAAAABJRU5ErkJggg==",
   67       "padlock-open"      => "iVBORw0KGgoAAAANSUhEUgAAAA4AAAALCAYAAABPhbxiAAAABmJLR0QA/wAAAAAzJ3zzAAAACXBIWXMAAAsNAAALDQHtB8AsAAAAB3RJTUUH1AQFFhYN/ae0wwAAAFFJREFUeJxjYMAETGj0fySMFzAisZE1EKUZWSNWPhOaBAsDAwMrsabCACsDqn9gmAebYnT/4AKM6ALoTiUaYNX4/z/hwCPbRqr4kQOHJmZsggBvtxMm/Y4B+AAAAABJRU5ErkJggg==",
   68     );
   69     $imageDataEnc = $imagesEncoded[$_GET["image"]];
   70     if ($imageDataEnc) {
   71       $maxAge = 31536000; // one year
   72       $imageDataRaw = base64_decode($imageDataEnc);
   73       Header("Content-Type: image/png");
   74       Header("Content-Length: ".strlen($imageDataRaw));
   75       Header("Cache-Control: public, max-age=$maxAge, must-revalidate");
   76       echo $imageDataRaw;
   77     }
   78     exit;
   79   }
   80   
   81 ?>
   82 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
   83             "http://www.w3.org/TR/html4/strict.dtd">
   84 <html>
   85 <head>
   86    <title>htpasstool</title>
   87    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
   88    <meta http-equiv="pragma" content="no-cache">
   89    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
   90    <meta http-equiv="pragma" content="no-cache">
   91 <STYLE TYPE="text/css">
   92 <!--
   93 body  {
   94   background: #f9fcfe;
   95   color: #000;
   96   margin: 3;
   97   padding: 0;
   98 }
   99       
  100 body, td {
  101   font: 13px "Lucida Grande", "Lucida Sans Unicode", Tahoma, Verdana;
  102 }
  103       
  104 div.centered {
  105   text-align: center;
  106 }
  107       
  108 div.centered table#outside {
  109   border: solid 1px #000000;
  110   margin: 0 auto; 
  111   text-align: left;
  112   border-collapse:collapse;
  113 }
  114       
  115 td.outside {
  116   border-bottom: solid 1px #000000;
  117 }
  118       
  119 td {
  120   border-bottom: solid 0px #000000;
  121 }
  122       
  123 div.centerbold {
  124   text-align: center;
  125   font-weight: bold;
  126   padding: 2px 2px 2px 2px;
  127   margin: 5px;
  128   font-size: 12px;
  129   background-color: #ffffff;
  130   color: #000000;
  131 }
  132       
  133 div#notice {
  134   text-align: center;
  135   font-weight: bold;
  136   padding: 2px 2px 2px 2px;
  137   font-size: 12px;
  138   background-color: #00c000;
  139   color: #ffffff;
  140 }
  141       
  142 span.ok {
  143   text-align: center;
  144   font-weight: bold;
  145   padding: 2px 2px 2px 2px;
  146   font-size: 12px;
  147   background-color: #00c000;
  148   color: #ffffff;
  149 }
  150  span.warn {
  151   text-align: center;
  152   font-weight: bold;
  153   padding: 2px 2px 2px 2px;
  154   font-size: 12px;
  155   background-color: #ff3300;
  156   color: #ffffff;
  157 }
  158       
  159 span.required {
  160   font-weight: bold;
  161   color: #ff0000;
  162 }
  163 div#error {
  164   text-align: center;
  165   font-weight: bold;
  166   padding: 2px 2px 2px 2px;
  167   font-size: 12px;
  168   background-color: #c00000;
  169   color: #ffffff;
  170 }
  171 -->
  172 </STYLE>
  173 </head>
  174 <body>
  175 
  176 <div class="centered">
  177 <table id="outside" width="600">
  178 <?
  179 
  180   define("HTACCESS", ".htaccess");
  181   define("HTPASSWD", ".htpasswd");
  182   define("VERSION", "v1.02");
  183 
  184   $dir = $_REQUEST['dir'];
  185   $action = $_REQUEST['action'];
  186   $login = $_REQUEST['login'];
  187   $newlogin = $_REQUEST['newlogin'];
  188   $password = $_REQUEST['password'];
  189   $password2 = $_REQUEST['password2'];
  190   $assign_random_password = $_REQUEST['assign_random_password'];
  191   $email = $_REQUEST['email'];
  192   $sender = $_REQUEST['sender'];
  193   $subject = $_REQUEST['subject'];
  194   $body = $_REQUEST['body'];
  195   $comment = $_REQUEST['comment'];
  196   $message = '';
  197   $pwd_printed = 0;
  198 
  199   # Sanitize the input
  200   $dir = preg_replace('/[^_a-zA-Z0-9\/]/','',$dir);
  201   $dir = preg_replace('/\/{1,}/','/',$dir);
  202 
  203     # We need this later
  204   $pattern = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
  205 
  206   if (!isset($_REQUEST['dir'])) $dir = '';
  207 
  208   if (($url_prefix != '') && (!preg_match('/\/$/',$url_prefix))) $url_prefix .= '/';
  209   define("URL_PREFIX", $url_prefix);
  210 
  211   $orig_cwd = BASE_DIRECTORY;
  212   $wdir = BASE_DIRECTORY . "/" . $dir;
  213   $wdir = preg_replace('/\/{1,}/','/',$wdir);
  214 
  215  function redirect($url) {
  216    header("HTTP/1.0 302 Redirect");
  217    header("Location: $url");
  218    header("Content-type:text/html");
  219 ?>
  220 <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
  221 <HTML><HEAD>
  222 <TITLE>302 Found</TITLE>
  223 </HEAD><BODY>
  224 <H1>Found</H1>
  225 The document has moved <A HREF="<?=$url?>">here</A>.<P>
  226 <HR>
  227 </BODY></HTML>
  228 
  229 <?php
  230    exit;
  231  }
  232 
  233   function test_secured($path) {
  234     // Returns 1 if 'path' is .htaccess protected.
  235     // Returns 2 if 'path' is .htaccess protected, but the .htaccess file was not generated by htpasstool
  236     $secured = 0;
  237     if (file_exists("$path/" . HTACCESS) && is_file("$path/" . HTACCESS)) {
  238       // we deliberately don't check for the presence of a HTPASSWD file here!
  239       $htaccess = @file_get_contents("$path/" . HTACCESS);
  240       if (preg_match("/^ *require valid-user/m",$htaccess)) $secured = 1; # This check is fairly basic...
  241       # we did not make this htaccess file!
  242       if (!preg_match("/^# htpasstool v\d.\d protected/",$htaccess)) $secured = 2; 
  243     }
  244     return $secured;
  245   }
  246 
  247   function in_htpasstool_dir() {
  248     global $orig_cwd;
  249     global $wdir;
  250 
  251     $tmp1 = $orig_cwd;
  252     $tmp2 = $wdir;
  253 
  254     # Follow symlinks
  255     if (is_link($tmp1)) $tmp1 = readlink($tmp1);
  256     if (is_link($tmp2)) $tmp2 = readlink($tmp2);
  257 
  258     # Deal with relative symlinks
  259     if (!preg_match('/^\//',$tmp1)) $tmp1 = preg_replace('/\/[^\/]*$/',"/$tmp1",$orig_cwd);
  260     if (!preg_match('/^\//',$tmp2)) $tmp2 = preg_replace('/\/[^\/]*$/',"/$tmp2",$wdir);
  261 
  262     $tmp1 = preg_replace("/\/$/",'',$tmp1);
  263     $tmp2 = preg_replace("/\/$/",'',$tmp2);
  264 
  265     return ($tmp1 == $tmp2);
  266   }
  267 
  268   function linkit($dir,$action,$user,$pretty='') {
  269     if ($pretty == '') $pretty = ucfirst($action);
  270     $deletestr = '';
  271     if ($action == 'delete') {
  272       $deletestr = " onclick=\"return confirm('Do you really want to delete this user?')\"";
  273     }
  274     return "<a href=\"${$_SERVER['SCRIPT_NAME']}?action=$action&amp;dir=$dir&amp;login=$user\"$deletestr>$pretty</a>";
  275   }
  276 
  277   function warn($desc,$no_overview=0) {
  278     global $wdir, $dir;
  279     global $pwd_printed;
  280     if (file_exists($wdir) and (!$pwd_printed)) {
  281       pwd();
  282       $pwd_printed = 1;
  283     }
  284     print "<tr><td class=\"outside\">";
  285     print "<div id=\"error\">$desc</div>\n";
  286     print "</td></tr>";
  287     if (!$no_overview) overview($wdir,$dir);
  288 
  289   }
  290 
  291   function fail($desc,$no_overview=0) {
  292     global $wdir, $dir;
  293     global $pwd_printed;
  294     if (file_exists($wdir) and (!$pwd_printed)) {
  295       pwd();
  296       $pwd_printed = 1;
  297     }
  298     print "<tr><td class=\"outside\">";
  299     print "<div id=\"error\">$desc</div>\n";
  300     print "</td></tr>";
  301     if (!$no_overview) overview($wdir,$dir);
  302 
  303     print "</table>";
  304     print "</div>";
  305 
  306     exit;
  307   }
  308   
  309   function php4_scandir($dir, $sort = 0) {
  310      if (PHP_VERSION >= '5') return scandir($dir, $sort);
  311      $dirmap = array();
  312      if(!is_dir($dir))
  313      {
  314          trigger_error("lib::scandir($dir): failed to open dir: Invalid argument", E_USER_WARNING);
  315          return false;
  316      }
  317      $dir = opendir($dir);
  318      while (false !== ($file = readdir($dir)))
  319          $dirmap[] = $file;
  320      closedir($dir);
  321      ($sort == 1) ? rsort($dirmap) : sort($dirmap);
  322      return $dirmap;
  323   }
  324 
  325   function pwd() {
  326     global $wdir, $dir;
  327         $wd_link = URL_PREFIX . $dir;
  328         $wd_link2 = '';
  329         if (strlen($wd_link) != 0) {
  330             $wd_link = '<a href="' . $wd_link . '">';
  331             $wd_link2 = '</a>';
  332         }
  333 ?>
  334   <tr>
  335     <td align="center" class="outside">
  336       <a href="http://patch.be/htpasstool">htpasstool <?= VERSION ?></a>
  337     </td>
  338   </tr>
  339   <tr>
  340     <td class="outside">
  341       <table width="100%">
  342         <tr>
  343           <td colspan="2">Base directory: <?= BASE_DIRECTORY ?></td>
  344         </tr>
  345         <tr>
  346           <td>Working directory: <?= $wd_link ?><?=$dir?><?= $wd_link2 ?> [<a href="<?=$_SERVER['SCRIPT_NAME']?>?action=changewdform&amp;dir=<?=$dir?>">change</a>]</td>
  347 <?
  348 
  349 
  350     $test_secured = test_secured($wdir);
  351     if ($test_secured >= 1) {
  352       print "<td align=\"right\"><a href=\"${$_SERVER['SCRIPT_NAME']}?dir=$dir&amp;action=removehtaccessfileform\"><span class=\"ok\"><img src=\"$PHP_SELF?image=padlock\" alt=\"closed padlock icon\" border=0>Protected</span></a></td></tr>";
  353     } else {
  354       print "<td align=\"right\"><a href=\"${$_SERVER['SCRIPT_NAME']}?dir=$dir&amp;action=installhtaccessfile\"><span class=\"warn\"><img src=\"$PHP_SELF?image=padlock-open\" alt=\"open padlock icon\" border=0>Unprotected</span></a></td></tr>";
  355     }
  356 ?>
  357       </table>
  358     </td>
  359   </tr>
  360 <?
  361 
  362     if (!@php4_scandir($wdir)) {
  363       if ($_REQUEST['action'] != 'changewdform') {
  364         fail("The working directory $dir does not exist",1);
  365 
  366       } else {
  367         warn("The working directory $dir does not exist",1);
  368       }
  369     }
  370   }
  371 
  372   function overview($wdir,$dir) {
  373     global $message;
  374 
  375     if (is_file("$wdir/" . HTPASSWD) and !is_readable("$wdir/" . HTPASSWD)) {
  376       fail("The $wdir/" . HTPASSWD . " file is not readable. Please check the permissions.\n",1);
  377     }
  378 
  379     if (!is_writeable($wdir)) {
  380       fail("The $wdir directory is not writeable. Please check the permissions.\n",1);
  381     }
  382     if (is_file("$wdir/" . HTPASSWD) and !is_writeable("$wdir/" . HTPASSWD)) {
  383       fail("The $wdir/" . HTPASSWD . " file is not writeable. Please check the permissions.\n",1);
  384     }
  385 
  386     $output = '';
  387 
  388     if ($message != '') {
  389       $output .= "<tr><td class=\"outside\">";
  390       if ($message != '') $output .= "<div id=\"notice\">$message</div>";
  391       $output .= "</td></tr>";
  392     }
  393     $output .= "<tr><td class=\"outside\">";
  394 
  395     $output .= "<div class=\"centerbold\">Users: [<a href=\"${$_SERVER['SCRIPT_NAME']}?action=addform&amp;dir=$dir\">add</a>]</div>";
  396 
  397     if (is_readable("$wdir/" . HTPASSWD)) {
  398       $fp = openfile("$wdir/" . HTPASSWD);
  399       $lines = readhtpasswd($fp);
  400       closefile($fp);
  401       $output .= "<div class=\"centered\">\n<table width=80% align=\"center\">";
  402       if (count($lines) != 0) {
  403         foreach ($lines as $k=>$v) {
  404           $output .= "<tr bgcolor=\"#FFFFFF\" onMouseOver=\"this.style.backgroundColor='#DDDDDD'\" onMouseOut=\"this.style.backgroundColor=''\">";
  405           $output .= "<td align=\"left\">$k</td><td>{$lines[$k]['comment']}</td><td>" . linkit($dir,'editform',$k,'Edit') . " " . linkit($dir,'passwordform',$k,'Password') . " " . linkit($dir,'delete',$k) . " " . linkit($dir,'assignpasswordform',$k,'Assign random password') . " </td></tr>\n";
  406         }
  407         $output .= "</table>\n</div>\n";
  408       } else {
  409         $output .= "<tr><td><div class=\"centered\">The " . HTPASSWD . " file is currently empty.</div></td></tr>\n";
  410         $output .= "</table>";
  411         $output .= "</div>";
  412       }
  413     } else {
  414       $output .= "<div class=\"centered\">The " . HTPASSWD . " file does not exist yet.</div>\n";
  415     }
  416     $output .= "</td></tr>";
  417     print $output;
  418   }
  419 
  420   function openfile($path) {
  421     $fp = @fopen("$path", "r+") or fail("File $path could not be opened",1);
  422 
  423     if (flock($fp, LOCK_EX)) { // do an exclusive lock
  424       return $fp;
  425     } else {
  426       fclose($fp);
  427       fail("Couldn't lock the file !");
  428     }
  429   }
  430 
  431   function createfile($path) {
  432     $path = preg_replace('/\/{1,}/','/',$path);
  433     $fp = @fopen("$path", "w") or fail("File $path could not be created",1);
  434 
  435     if (flock($fp, LOCK_EX)) { // do an exclusive lock
  436       return $fp;
  437     } else {
  438       fclose($fp);
  439       fail("Couldn't lock the file !");
  440     }
  441   }
  442 
  443   function removehtaccessfile($dir) {
  444     if (!file_exists("$dir/" . HTACCESS)) fail("The $dir/" . HTACCESS . " file does not exist");
  445 
  446     @unlink("$dir/" . HTACCESS) or fail("Could not remove $dir/" . HTACCESS);
  447   }
  448 
  449   function installhtaccessfile($dir) {
  450 
  451     if (file_exists("$dir/" . HTACCESS)) fail("The $dir/" . HTACCESS . " file/dir exists");
  452 
  453     $fp = createfile("$dir/" . HTACCESS);
  454 
  455     $output = "# htpasstool v1.0 protected\nAuthType Basic\nAuthName \"Restricted Area\"\nAuthUserFile \"$dir/" . HTPASSWD . "\"\nrequire valid-user\n";
  456     fwrite($fp,$output);
  457     closefile($fp); 
  458 
  459   }
  460 
  461   function readhtpasswd($fp) {
  462     while (!feof($fp)) {
  463       $data = fgets($fp, 4096); # We assume no line is longer than 4096 characters
  464       if (preg_match("/^\s*$/",$data)) continue; # We don't need blank lines
  465       $data = preg_replace("/\n/",'',$data);
  466       $tmp = preg_split('/:/', $data);
  467       if ($tmp[0] == '') continue; # Skip blank lines or lines with empty logins
  468       $lines[$tmp[0]]['password'] = $tmp[1];
  469       $lines[$tmp[0]]['email'] = $tmp[2];
  470       $lines[$tmp[0]]['comment'] = $tmp[3];
  471     }
  472     return $lines;
  473   }
  474 
  475   function writehtpasswd($fp,$lines) {
  476     fseek($fp, 0);
  477     ksort($lines);
  478     foreach ($lines as $key => $value) {
  479       #print "line to write: $key:$value\n<p>";
  480       $output .= $key . ':' . $lines[$key]['password'] . ':'  . $lines[$key]['email'] . ':' . $lines[$key]['comment'] . "\n";
  481     }
  482 #    $output = preg_replace("/\n$/",'',$output);
  483     fwrite($fp,$output);
  484     ftruncate($fp,ftell($fp));  # We want to erase any additional content in the file
  485   }
  486 
  487   function closefile($fp) {
  488     flock($fp, LOCK_UN); // release the lock
  489     fclose($fp);
  490   }
  491 
  492     function assignpasswordform() {
  493     global $wdir, $dir, $pwd_printed, $url_prefix;
  494         global $login, $admin_email, $password_subject, $password_body, $pattern;
  495     pwd();
  496     $pwd_printed = 1;
  497 
  498     $fp = openfile("$wdir/" . HTPASSWD);
  499     $lines = readhtpasswd($fp);
  500     closefile($fp);
  501 
  502     if (!array_key_exists($login ,$lines)) {
  503       fail("This user does not exist");
  504     }
  505 
  506         $password_parsed_subject = $password_subject;
  507 
  508     $tmp_pass = $pattern{rand(0,61)} . $pattern{rand(0,61)} . $pattern{rand(0,61)} . $pattern{rand(0,61)} . $pattern{rand(0,61)} . $pattern{rand(0,61)} . $pattern{rand(0,61)} . $pattern{rand(0,61)};
  509 
  510 
  511         if ($url_prefix == '') {
  512         $http = 'http://';
  513             if ($_SERVER['HTTPS'] != '') $http = 'https://';
  514 
  515             $tmpa = preg_replace('/\/[^\/]+$/','/',$_SERVER['REQUEST_URI']);
  516             $tmpurl = $http . $_SERVER['SERVER_NAME'] . "$tmpa$dir";
  517         } else {
  518             $tmpurl = $url_prefix . $dir;
  519         }
  520 
  521         $patterns = array("/%%admin_email%%/","/%%url%%/","/%%login%%/","/%%password%%/");
  522         $replacements = array($admin_email,$tmpurl,$login,$tmp_pass);
  523 
  524         $password_parsed_body = preg_replace($patterns,$replacements,$password_body);
  525 
  526 ?>
  527   <tr>
  528   <td class="outside">
  529   <form action="<?=$_SERVER['SCRIPT_NAME']?>">
  530   <input type="hidden" name="action" value="assignpassword">
  531   <input type="hidden" name="dir" value="<?=$dir?>">
  532   <input type="hidden" name="login" value="<?=$login?>">
  533   <input type="hidden" name="password" value="<?=$tmp_pass?>">
  534   <div class="centerbold">Assign and e-mail a new password:</div>
  535 
  536   <div class="centered">
  537   <table width=80% align="center">
  538     <tr>
  539       <td align="left">User:</td><td align="left"><?= $login ?></td>
  540     </tr>
  541     <tr>
  542       <td align="left">E-mail address:</td><td align="left"><input type="text" size="20" name="email" value="<?= $lines[$login]['email'] ?>"></td>
  543     </tr>
  544     <tr>
  545       <td align="left">Sender e-mail address:</td><td align="left"><input type="text" size="40" name="sender" value="<?= $admin_email ?>"></td>
  546     </tr>
  547     <tr>
  548       <td align="left">Subject:</td><td align="left"><input type="text" size="40" name="subject" value="<?= $password_parsed_subject ?>"></td>
  549     </tr>
  550     <tr>
  551       <td align="left" colspan="2">Message:</td>
  552         </tr>
  553         <tr>
  554             <td align="left" colspan="2"><textarea cols="80" rows="15" name="body"><?= $password_parsed_body ?></textarea></td>
  555     </tr>
  556     <tr><td colspan="2"><input type="submit" value="Assign and send"></td></tr>
  557   </table>
  558   </div>
  559   </form>
  560   </td>
  561   </tr>
  562 <?
  563     }
  564 
  565   function verify_address($email) {
  566     $valid = 0;
  567     # According to RFC 2822, these characters are valid 'atext' chars - valid for the localpart of an e-mail address
  568     # [a-z0-9!#\$%&'*+\-\/=?\^_`{\|}~.]
  569     if (preg_match("/^[a-z0-9!#\$%&'*+\-\/=?\^_\`{\|}~.]+@[a-z0-9!#\$%&'*+\-\/=?\^_\`{\|}~.]+\.[a-z0-9!#\$%&'*+\-\/=?\^_\`{\|}~]{2,}$/",$email)) $valid = 1;
  570     return $valid;
  571   }
  572 
  573 
  574   if ($action == 'addform') {
  575     pwd();
  576     $pwd_printed = 1;
  577 ?>
  578   <tr>
  579   <td class="outside">
  580   <form action="<?=$_SERVER['SCRIPT_NAME']?>">
  581   <input type="hidden" name="action" value="add">
  582   <input type="hidden" name="dir" value="<?=$dir?>">
  583   <div class="centerbold">Add user:</div>
  584   <div class="centered">
  585   <table width=80% align="center">
  586     <tr>
  587       <td align="left"><span class="required">*</span>Login:</td><td align="left"><input type="text" size="20" name="login"></td>
  588     </tr>
  589     <tr>
  590       <td align="left">Assign random password:</td><td align="left"><input type="checkbox" size="40" name="assign_random_password" onclick="document.getElementById('password').style.visibility = this.checked ? 'hidden' : 'visible'; document.getElementById('confirm_password').style.visibility = this.checked ? 'hidden' : 'visible'"></td>
  591     </tr>
  592     <tr id="password">
  593       <td align="left"><span class="required">*</span>Password:</td><td align="left"><input type="password" size="20" name="password"></div></td>
  594     </tr>
  595     <tr id="confirm_password">
  596       <td align="left"><span class="required">*</span>Password (confirm):</td><td align="left"><input type="password" size="20" name="password2"></td>
  597     </tr>
  598     <tr>
  599       <td align="left">E-mail:</td><td align="left"><input type="text" size="40" name="email"></td>
  600     </tr>
  601     <tr>
  602       <td align="left">Comment:</td><td align="left"><input type="text" size="40" name="comment"></td>
  603     </tr>
  604     <tr><td colspan="2"><input type="submit" value="Add"></td></tr>
  605   </table>
  606   </div>
  607   </form>
  608   </td>
  609   </tr>
  610 <?
  611   } elseif ($action == 'add') {
  612     if (strlen($login) < 1) fail("The login can not be empty");
  613         if ($assign_random_password == '') {
  614         if (strlen($password) < 6) fail("The password needs to be at least 6 characters long");
  615         if ($password != $password2) fail("The passwords you have supplied do not match");
  616         if ($password == '') fail("Missing parameter");
  617         if ($password2 == '') fail("Missing parameter");
  618         } else {
  619             # Temporarily assign a random password. This is just to make sure that we
  620             # don't end up with accounts without passwords if the user doesn't follow
  621             # up on the 'assign & send' page.
  622         $password = $pattern{rand(0,61)} . $pattern{rand(0,61)} . $pattern{rand(0,61)} . $pattern{rand(0,61)} . $pattern{rand(0,61)} . $pattern{rand(0,61)} . $pattern{rand(0,61)} . $pattern{rand(0,61)};
  623         }
  624 
  625     if (is_readable("$wdir/" . HTPASSWD)) {
  626       $fp = openfile("$wdir/" . HTPASSWD);
  627       $lines = readhtpasswd($fp);
  628     } else {
  629       $fp = createfile("$wdir/" . HTPASSWD);
  630       $lines = array();
  631     }
  632 
  633     if ((count($lines) != 0) and (array_key_exists($login,$lines))) {
  634       closefile($fp);
  635       fail("Failed: this login is in use");
  636     }
  637 
  638     if ($email != '') {
  639       if (verify_address($email) == 0) {
  640         closefile($fp);
  641         fail("Failed: this e-mail address is not valid.");
  642       }
  643     }
  644 
  645     $lines[$login]['password'] = crypt($password,$pattern{rand(0,61)} . $pattern{rand(0,61)});
  646     $lines[$login]['email'] = $email;
  647     $lines[$login]['comment'] = $comment;
  648     writehtpasswd($fp,$lines);
  649     closefile($fp);
  650         if ($assign_random_password != '') {
  651             assignpasswordform();
  652         } else {
  653         $message = "User $name has been created successfully";
  654         }
  655   } elseif ($action == 'changewdform') {
  656     pwd();
  657     $pwd_printed = 1;
  658 ?>
  659   <tr>
  660   <td class="outside">
  661   <form action="<?=$_SERVER['SCRIPT_NAME']?>">
  662   <div class="centerbold">Change working directory:</div>
  663 
  664   <div class="centered">
  665   <table width=80% align="center">
  666     <tr>
  667       <td align="left">New working directory:</td><td align="left"><input type="text" size="60" name="dir"></td>
  668     </tr>
  669     <tr><td colspan="2"><input type="submit" value="Change"></td></tr>
  670   </table>
  671   </div>
  672   </form>
  673   </td>
  674   </tr>
  675 <?
  676   } elseif ($action == 'assignpasswordform') {
  677         assignpasswordform();
  678   } elseif ($action == 'assignpassword') {
  679     if ($login == '') fail("Missing parameter");
  680     if ($email == '') fail("Destination e-mail address may not be empty");
  681     if ($sender == '') fail("Sender e-mail address may not be empty");
  682     if ($subject == '') fail("Subjet may not be empty");
  683     if ($body == '') fail("Body may not be empty");
  684     if (verify_address($email) == 0) fail("Destination e-mail address invalid");
  685     if (verify_address($sender) == 0) fail("Sender e-mail address invalid");
  686 
  687     $fp = openfile("$wdir/" . HTPASSWD);
  688     $lines = readhtpasswd($fp);
  689 
  690     if (!array_key_exists($login ,$lines)) {
  691       closefile($fp);
  692       fail("This user does not exist");
  693     }
  694 
  695     $lines[$login]['password'] = crypt($password,$pattern{rand(0,61)} . $pattern{rand(0,61)});
  696         # If the e-mail address on file is empty, replace it with the one that was given here. Otherwise, ignore the one that was given here.
  697         if ($lines[$login]['email'] == '') {
  698         $lines[$login]['email'] = $email;
  699         }
  700     $lines[$login]['password'] = crypt($password,$pattern{rand(0,61)} . $pattern{rand(0,61)});
  701     writehtpasswd($fp,$lines);
  702     closefile($fp);
  703 
  704         $headers = "From: $sender\r\nTo: $email\r\nReply-To: $sender\r\n";
  705         $extra = "-f $sender";
  706 
  707         mail($email,$subject,$body,$headers,$extra);
  708         mail($sender,"(carbon copy): $subject",$body,$headers,$extra);
  709 
  710     $message = "The new password for user $login has been assigned, and the e-mail has been sent. You have been sent a carbon copy for your records.";
  711   } elseif ($action == 'passwordform') {
  712     pwd();
  713     $pwd_printed = 1;
  714 ?>
  715   <tr>
  716   <td class="outside">
  717   <form action="<?=$_SERVER['SCRIPT_NAME']?>">
  718   <input type="hidden" name="action" value="password">
  719   <input type="hidden" name="dir" value="<?=$dir?>">
  720   <input type="hidden" name="login" value="<?=$login?>">
  721   <div class="centerbold">Change password:</div>
  722 
  723   <div class="centered">
  724   <table width=60% align="center">
  725     <tr>
  726       <td align="left">User:</td><td align="left"><?= $login ?></td>
  727     </tr>
  728     <tr>
  729       <td align="left">New password:</td><td align="left"><input type="password" size="20" name="password"></td>
  730     </tr>
  731     <tr>
  732       <td align="left">New password (confirm):</td><td align="left"><input type="password" size="20" name="password2"></td>
  733     </tr>
  734     <tr><td colspan="2"><input type="submit" value="Change"></td></tr>
  735   </table>
  736   </div>
  737   </form>
  738   </td>
  739   </tr>
  740 <?
  741   } elseif ($action == 'password') {
  742     if ($login == '') fail("Missing parameter");
  743     if (strlen($password) < 6) fail("The password needs to be at least 6 characters long");
  744     if ($password == '') fail("Missing parameter");
  745     if ($password2 == '') fail("Missing parameter");
  746     if ($password != $password2) fail("The passwords you have supplied do not match");
  747 
  748     $fp = openfile("$wdir/" . HTPASSWD);
  749     $lines = readhtpasswd($fp);
  750 
  751     if (!array_key_exists($login ,$lines)) {
  752       closefile($fp);
  753       fail("This user does not exist");
  754     }
  755 
  756     $lines[$login]['password'] = crypt($password,$pattern{rand(0,61)} . $pattern{rand(0,61)});
  757     writehtpasswd($fp,$lines);
  758     closefile($fp);
  759     $message = "The password for user $login has been updated";
  760   } elseif ($action == 'editform') {
  761     pwd();
  762     $pwd_printed = 1;
  763     $fp = openfile("$wdir/" . HTPASSWD);
  764     $lines = readhtpasswd($fp);
  765     closefile($fp);
  766     if (!array_key_exists($login,$lines)) {
  767       fail("This user does not exist");
  768     }
  769 ?>
  770   <tr>
  771   <td class="outside">
  772   <form action="<?=$_SERVER['SCRIPT_NAME']?>">
  773   <input type="hidden" name="action" value="update">
  774   <input type="hidden" name="dir" value="<?=$dir?>">
  775   <input type="hidden" name="login" value="<?=$login?>">
  776   <div class="centerbold">Edit user:</div>
  777   <div class="centered">
  778   <table width=60% align="center">
  779     <tr>
  780       <td align="left">Login:</td><td align="left"><input type="text" size="20" name="newlogin" value="<?=$login?>"></td>
  781     </tr>
  782     <tr>
  783       <td align="left">E-mail:</td><td align="left"><input type="text" size="40" name="email" value="<?=$lines[$login]['email']?>"></td>
  784     </tr>
  785     <tr>
  786       <td align="left">Comment:</td><td align="left"><input type="text" size="40" name="comment" value="<?=$lines[$login]['comment']?>"></td>
  787     </tr>
  788     <tr><td colspan="2"><input type="submit" value="Update"></td></tr>
  789   </table>
  790   </div>
  791   </form>
  792   </td>
  793   </tr>
  794 <?
  795   } elseif ($action == 'update') {
  796     if ($login == '') fail("Missing parameter");
  797     if ($newlogin == '') fail("Missing parameter");
  798     $fp = openfile("$wdir/" . HTPASSWD);
  799     $lines = readhtpasswd($fp);
  800 
  801     if ($email != '') {
  802       if (verify_address($email) == 0) {
  803         closefile($fp);
  804         fail("Update failed: this e-mail address is not valid.");
  805       }
  806     }
  807 
  808     $lines[$login]['email'] = $email;
  809     $lines[$login]['comment'] = $comment;
  810     if ($login != $newlogin) {
  811       $lines[$newlogin] = $lines[$login];
  812       unset($lines[$login]);
  813     }
  814     writehtpasswd($fp,$lines);
  815     closefile($fp);
  816     $message = "User $newlogin has been updated.";
  817   } elseif ($action == 'delete') {
  818     if ($login == '') fail("Missing parameter");
  819 
  820     $fp = openfile("$wdir/" . HTPASSWD);
  821     $lines = readhtpasswd($fp);
  822 
  823     if (!array_key_exists($login,$lines)) {
  824       closefile($fp);
  825       fail("This user does not exist");
  826     }
  827 
  828     unset($lines[$login]);
  829     if (in_htpasstool_dir() and(count($lines) == 0)) {
  830       closefile($fp);
  831       fail("You can not remove the last user from the .htaccess file that governs the htpasstool directory");
  832     }
  833     writehtpasswd($fp,$lines);
  834     closefile($fp);
  835     $message = "User $login has been removed";
  836   } elseif ($action == 'removehtaccessfileform') {
  837     pwd();
  838     $pwd_printed = 1;
  839 ?>
  840   <tr>
  841   <td class="outside">
  842   <form action="<?=$_SERVER['SCRIPT_NAME']?>">
  843   <input type="hidden" name="action" value="removehtaccessfile">
  844   <input type="hidden" name="dir" value="<?=$dir?>">
  845   <input type="hidden" name="login" value="<?=$login?>">
  846   <div class="centerbold">Remove .htaccess file:</div>
  847   <div class="centered">
  848   <table width=60% align="center">
  849     <tr>
  850       <td align="left" colspan="2">
  851         You are about to remove the .htaccess file from the directory <?=$dir?>. This will make this directory accessible for anyone on the network, without a password prompt. Are you sure you want to do this?
  852 <?
  853   if (test_secured($dir) == 2) {
  854 ?>
  855     <p><span class="warn">WARNING!</span> This .htaccess file was NOT created by htpasstool. Are you sure?
  856 <?
  857   }
  858   if (in_htpasstool_dir()) {
  859 ?>
  860     <p><span class="warn">WARNING!</span> This .htaccess file protects htpasstool. If you remove this .htaccess file, ANYONE will be able to set/remove passwords in your webspace, because htpasstool will no longer be password protected. Are you sure?
  861 <?
  862   }
  863 ?>
  864       </td>
  865     </tr>
  866     <tr><td><input type="submit" name="submit" value="Cancel"></td><td><input type="submit" name="submit" value="OK"></td></tr>
  867   </table>
  868   </div>
  869   </form>
  870   </td>
  871   </tr>
  872 <?
  873   } elseif ($action == 'removehtaccessfile') {
  874     if ($_REQUEST['submit'] == 'OK') {
  875       removehtaccessfile("$wdir");
  876       $message = "The directory $dir is no longer protected\n";
  877     }
  878   } elseif ($action == 'installhtaccessfile') {
  879     # Now; IF we are working on the htpasstool directory, refuse to activate
  880     # protection unless there is one user defined (the minimum HTPASSWD file
  881     # length is 15 chars: one for the username, one for the colon, and 13 for
  882     # the crypt'ed password).
  883     if (!in_htpasstool_dir() or (is_readable("$wdir/" . HTPASSWD) and (filesize("$wdir/" . HTPASSWD) >= 15))) {
  884       installhtaccessfile("$wdir");
  885       $message = "The directory $dir has been protected\n";
  886     } else {
  887       fail("When protecting the directory that governs htpasstool, you need to define at least one user first");
  888     }
  889   } 
  890 
  891   if (!$pwd_printed) {
  892     pwd();
  893     $pwd_printed = 1;
  894   }
  895 
  896   overview($wdir,$dir);
  897 
  898 ?>
  899 </table>
  900 </div>
  901 
  902 </body>
  903 </html>