<?php /*>*/ if (!defined('PmWiki')) exit();
/*
 * New Member - Simple AuthUser addon's for PmWiki
 * Modified from HtpasswdForm by D.Faure (dfaure@cpan.org)
 * By Caveman (editor@fast.st). Added Session Variables.
 * Create Page flexibility and name collision protection by Ben Wilson (ameen@dausha.net)
 *
 * You can redistribute it and/or modify it under the terms of the GNU General
 * Public License as published by the Free Software Foundation; either version
 * 2 of the License, or (at your option) any later version.
 *
 * See http://www.pmwiki.org/wiki/Cookbook/FAST Membership & HtpasswdForm for info.
 */


# If the admin hasn't configured any password entries, just return.
if (!$AuthUser) return;


# Sets up array for membership info and other variables.
global $AuthUser, $HandleActions;
foreach((array)($AuthUser['htpasswd']) as $f) {
  SDV($MembershipFile, $f);
  break;
}  
$HandleActions['postnewhtpasswd'] = 'HandleMembershipNewForm';
SDV($_enteredName, '');
SDV($MembershipCreatedPage,'Site.Created');


# List of potential display messages.
SDVA($MembershipFmt, array(
'created' => "<h3 class='wikimessage'>$[Account was successfully created.]</h3>",
'exists' =>"<h3 class='wikimessage'>$[Member already exists. Please try again:]</h3>",
'invalid' => "<h3 class='wikimessage'>$[Invalid member name. Please try again:]</h3>",
'no_user' => "<h3 class='wikimessage'>$[No member name entered. Please try again:]</h3>",
'unmatched' => "<h3 class='wikimessage'>$[Passwords don't match. Please try again:]</h3>",
));


# Actual markup used in wiki page
Markup('membershipform', 'directive', '/\(:membership(.*?):\)/ei', "MembershipForm('$1')");


# Function called by markup
function MembershipForm($i) {
 global $MembershipCreatedPage;
 $args = parseArgs($i);
 if ($args['page']) $MembershipCreatedPage = $args['page'];
 global $MembershipFile, $_enteredName;
 $arr = LoadMembership($MembershipFile);


# Form printed on page as a result of the markup 
 return FmtPageName("
(:messages:)
(:input form '\$PageUrl':)(:input hidden action postnewhtpasswd:)
(:table border='0':)
(:cellnr:)\n(:cell:)$[Member Name]:\n(:input text logname value='$_enteredName':)\n(:cell:)$[Password]:\n(:input password passwd value='':)\n
(:cellnr colspan='2':)\n(:cell:)$[again]:\n(:input password passwd2 '':)\n(:cell valign='bottom':)(:input submit create value='$[Create!]':)\n
(:cellnr colspan='2':)\n(:cell colspan='2':)(:input hidden pwtype value='1':)(:input hidden redirect value='$MembershipCreatedPage':)
(:tableend:)(:input end:)", $pagename);
}


# Function called when form submitted
function HandleMembershipNewForm($pagename) {
 global $MembershipFile, $MessagesFmt, $MembershipFmt; $redirect_page;
 $msg = '';
 $arr = LoadMembership($MembershipFile);
 session_start();
 if($_REQUEST['create']) {
   $newName = GetName($pagename);
   $newPass = GetPasswd($pagename);
   for($i = 0; $i < count($arr); $i++)
     if($newName == $arr[$i][0]) {
       unset($newName);
	   $msg = sprintf($MembershipFmt['exists'], $user);
       $MessagesFmt[] = FmtPageName($msg, $pagename);
       HandleBrowse($pagename);
       exit;
     }
	 
     $redirect_page = $_REQUEST['redirect'];
     $arr[] = array($newName, $newPass);
     SaveMembership($MembershipFile, $arr);
     $MessagesFmt[] = $MembershipFmt['created'];
     Redirect(FmtPageName($redirect_page, $pagename));
     exit;
   }
}


# Retrieves and checks name from form
function GetName($pagename) {
  global $MessagesFmt, $MembershipFmt;
  $user = $_REQUEST['logname'];
  if(!$user) {
    $MessagesFmt[] = $MembershipFmt['no_user'];
    HandleBrowse($pagename);
    exit;
  }
  if($user!=PageVar(MakePageName($pagename, $user), '$Name')) {
    $MessagesFmt[] = $MembershipFmt['invalid'];
    HandleBrowse($pagename);
    exit;
  }
  $_SESSION['myname']=$user;
  return $user;
}


# Retrieves and checks password from form
function GetPasswd($pagename) {
  global $_enteredName, $MessagesFmt, $MembershipFmt;
  $plain = $_REQUEST['passwd'];
  if($plain != $_REQUEST['passwd2']) {
    $_enteredName = $_REQUEST['logname'];
    $MessagesFmt[] = $MembershipFmt['unmatched'];
    HandleBrowse($pagename);
    exit;
  }
  $pw = '';
  if($plain) {
    $salt = $_REQUEST['pwtype'] ?
      '$apr1$' . substr(md5(microtime() . mt_rand(10000, 32000)), 0, 8) : null;
    $pw = _crypt($plain, $salt);
  }
  $_SESSION['mypass']=$plain;
  return $pw;
}


# Loads htpasswd file into an array
function LoadMembership($f) {
  $arr = array();
  $fp = fopen($f, "r");
  if($fp) {
    while($l = fgets($fp, 1024)) {
      $l = rtrim($l);
      $arr[] = explode(':', $l, 3);
    }
    fclose($fp);
  }
  return $arr;
}


# Saves htpasswd file with changes
function SaveMembership($f, $arr) {
  ignore_user_abort(true);
  $fp = fopen($f, "w+");
  if(flock($fp, LOCK_EX)) {
    foreach($arr as $u)
      fputs($fp, "$u[0]:$u[1]" . ($u[2] ? ":$u[2]" : '') . "\n");
    flock($fp, LOCK_UN); // release the lock
  }
  fclose($fp);
  ignore_user_abort(false);
}