*/ if (!defined('PmWiki')) exit(); /* * HtpasswdForm - An Htpasswd file editor for PmWiki 2.x * Copyright 2005-2007 by D.Faure (dfaure@cpan.org) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * * See http://www.pmwiki.org/wiki/Cookbook/HtpasswdForm for info. */ $RecipeInfo['HtpasswdForm']['Version'] = '20070321-2'; include_once("$FarmD/scripts/authuser.php"); SDV($HtpasswordAuth, '@admins'); SDV($HtpasswordDefaultType, 0); SDV($HtpasswordDefaultGroup, ''); SDVA($HtpasswordTypes, array( /* label salt timestamp? */ 0 => array('apr1', '$apr1$', true), 1 => array('crypt', null, false), 2 => array('SHA-1', '{SHA}', false), )); SDVA($HtpasswordMsgFmt, array( 'created' => "

$['%s' has been created.]

", 'deleted' => "

$['%s' has been deleted.]

", 'no_name' => "

$[no name specified.]

", 'unmatched' => "

$[passwords don't match.]

", 'renamed' => "

$['%s' has been renamed to '%s'.]

", 'passupdated' => "

$['%s' password has been updated.]

", 'infoupdated' => "

$['%s' comment has been updated.]

", 'usersupdated' => "

$['%s' group has been updated.]

", 'no_group' => "

$[no group specified.]

", 'useradded' => "

$['%s' has been added to '%s'.]

", 'exists' => "

$['%s' is already defined. Choose a new one.]

", '' => "

 

", )); $HandleActions['postadmhtpasswd'] = 'HandleHtpasswdAdmForm'; $HandleActions['postusrhtpasswd'] = 'HandleHtpasswdUsrForm'; if(IsEnabled($HtpasswordNewUsers, 0)) $HandleActions['postnewhtpasswd'] = 'HandleHtpasswdNewForm'; Markup('htpasswdform', ' 0) foreach($arr as $i => $g) { $chk = ($i == $PCache[$pagename]['idxgrp']) ? "checked='on'" : ''; $out[] = "(:cellnr:)(:input radio idxgrp value='{$i}' tabindex='$tx' $chk:)"; $tx++; $out[] = "(:cell:){$g[0]}\n(:cell colspan='2':){$g[1]}"; } else $out[] = "(:cellnr:)\n(:cell colspan='3':)\n\\\\\n%center%(no group)\\\\\\\n"; $out[] = "(:cellnr:)\n(:cell:)(:input submit rengrp value='$[Rename]' tabindex='$tx':)\\"; $tx++; $out[] = " (:input submit delgrp value='$[Delete]' tabindex='$tx':)"; $tx++; $out[] = "(:cell colspan='2':)(:input submit adduser value='$[Add a User]' tabindex='$tx':)\\"; $tx++; $out[] = " (:input submit setusers value='$[Set all Users]' tabindex='$tx':)"; $tx++; $out[] = "(:cellnr:)\n(:cell:)$[Group]:\n(:input text namegrp value='{$PCache[$pagename]['namegrp']}' tabindex='$tx':)"; $tx++; $out[] = "(:cell colspan='2':)$[User(s)]:\n(:input text users value='' tabindex='$tx':)"; $tx++; $out[] = "(:cellnr colspan='2':)\n(:cell colspan='2':)(:input submit newgrp value='$[Create Group]' tabindex='$tx':)"; if(IsEnabled($EnableHtpassword, 1)) $out[] = "(:cellnr colspan='4':)\n----"; } if(IsEnabled($EnableHtpassword, 1) && isset($HtpasswdFile)) { $out[] = "(:cellnr colspan='4':)''$HtpasswdFile''"; $out[] = "(:cellnr:)\n(:cell:)'''$[User]'''\n(:cell:)'''$[Password]'''\n(:cell:)'''$[Comment]'''"; $arr = LoadHtpasswd($HtpasswdFile); if(count($arr) > 0) foreach($arr as $i => $u) { $chk = ($i == $PCache[$pagename]['idxusr']) ? "checked='on'" : ''; $out[] = "(:cellnr:)(:input radio idxusr value='{$i}' tabindex='$tx' $chk:)"; $tx++; $user = IsEnabled($EnableHtpasswordProfileLinks, 1) ? "%newwin% [[~{$u[0]}]]" : $u[0]; $out[] = "(:cell:){$user}\n(:cell:)[@{$u[1]}@]\n(:cell:){$u[2]}"; } else $out[] = "(:cellnr:)\n(:cell colspan='3':)\n\\\\\n%center%(no user)\\\\\\\n"; $out[] = "(:cellnr:)\n(:cell:)(:input submit renusr value='$[Rename]' tabindex='$tx':)\\"; $tx++; $out[] = " (:input submit delusr value='$[Delete]' tabindex='$tx':)"; $tx++; $out[] = "(:cell:)(:input submit setpw value='$[Set Password]' tabindex='$tx':)"; $tx++; $out[] = "(:cell:)(:input submit setinfo value='$[Set Comment]' tabindex='$tx':)"; $tx++; $out[] = "(:cellnr:)\n(:cell:)$[Username]:\n(:input text nameusr value='{$PCache[$pagename]['nameusr']}' tabindex='$tx':)"; $tx++; $out[] = "(:cell:)$[Password]:\n(:input password passwd value='' tabindex='$tx':)"; $tx2 = ++$tx; $tx++; $out[] = "(:cell:)$[Comment]:\n(:input text info value='' tabindex='$tx':)"; $tx++; $out[] = "(:cellnr colspan='2':)\n(:cell:)$[again]:\n(:input password passwd2 value='' tabindex='$tx2':)"; $out[] = "(:cell valign='bottom':)(:input submit newusr value='$[Create User]' tabindex='$tx':)"; $tx++; $out[] = "(:cellnr colspan='2':)\n(:cell:)"; foreach($HtpasswordTypes as $i => $t) { $chk = ($i == $HtpasswordDefaultType) ? "checked='on'" : ''; $out[] = "(:input radio pwtype value='{$i}' tabindex='$tx' $chk:){$t[0]}"; $tx++; } $out[] = "(:cell:)"; if(IsEnabled($EnableHtgroup, 1) && $grpCount > 0) { $chk = $PCache[$pagename]['curgrp'] ? "checked='on'" : ''; $out[] = "(:input checkbox curgrp tabindex='$tx' value='1' $chk:)$[add in selected group]"; $tx++; } } $out[] = "(:tableend:)(:input end:)"; SDV($PCache[$pagename]['focus'], 'nameusr'); if(isset($HtgroupFile) || isset($HtpasswdFile)) $out[] = HtSetFocus('htpasswdadmform', $PCache[$pagename]['focus']); return implode("\n", $out); } function HandleHtpasswdAdmForm($pagename, $auth) { global $HtpasswordAuth, $EnableHtgroup, $HtgroupFile, $EnableHtpassword, $HtpasswdFile, $MessagesFmt, $HtpasswordMsgFmt, $HandleActions; $page = RetrieveAuthPage($pagename, $HtpasswordAuth, false); if (!$page) Abort('?unauthorized'); PCache($pagename, $page); $browse = $HandleActions['browse']; $msg = ''; $idxusr = $_REQUEST['idxusr']; $idxgrp = $_REQUEST['idxgrp']; if($EnableHtgroup) { // group handling if($_REQUEST['newgrp']) { $name = HtpasswdGetFormGroup($pagename, $auth); $arr = LoadHtgroup($HtgroupFile); $arr[] = array($name, $_REQUEST['users']); SaveHtgroup($HtgroupFile, $arr); $msg = sprintf($HtpasswordMsgFmt['created'], $name); } elseif(isset($idxgrp)) { if($_REQUEST['delgrp']) { $arr = LoadHtgroup($HtgroupFile); $name = $arr[$idxgrp][0]; unset($arr[$idxgrp]); SaveHtgroup($HtgroupFile, $arr); $msg = sprintf($HtpasswordMsgFmt['deleted'], $name); } elseif($_REQUEST['rengrp']) { $new = HtpasswdGetFormGroup($pagename, $auth); $arr = LoadHtgroup($HtgroupFile); $name = $arr[$idxgrp][0]; $arr[$idxgrp][0] = $new; SaveHtgroup($HtgroupFile, $arr); $msg = sprintf($HtpasswordMsgFmt['renamed'], $name, $new); } elseif($_REQUEST['adduser']) { $user = $_REQUEST['users']; if($EnableHtpassword && !$user && isset($idxusr)) { $arr = LoadHtpasswd($HtpasswdFile); $user = $arr[$idxusr][0]; } if($user) { $arr = LoadHtgroup($HtgroupFile); $name = $arr[$idxgrp][0]; HtgroupAddUser($arr, $name, $user); SaveHtgroup($HtgroupFile, $arr); $msg = sprintf($HtpasswordMsgFmt['useradded'], $user, $name); } } elseif($_REQUEST['setusers']) { $arr = LoadHtgroup($HtgroupFile); $name = $arr[$idxgrp][0]; $arr[$idxgrp][1] = $_REQUEST['users']; SaveHtgroup($HtgroupFile, $arr); $msg = sprintf($HtpasswordMsgFmt['usersupdated'], $name); } } } if($EnableHtpassword) { // user handling if($_REQUEST['newusr']) { $name = HtpasswdGetFormName($pagename, $auth, true); $pass = HtpasswdGetFormPasswd($pagename, $auth, $_REQUEST['pwtype']); $info = $_REQUEST['info']; $arr = LoadHtpasswd($HtpasswdFile); $arr[] = array($name, $pass, $info); SaveHtpasswd($HtpasswdFile, $arr); if($EnableHtgroup && isset($idxgrp) && $_REQUEST['curgrp']) { $arr = LoadHtgroup($HtgroupFile); if(count($arr)) { $group = $arr[$idxgrp][0]; HtgroupAddUser($arr, $group, $name); SaveHtgroup($HtgroupFile, $arr); } } $msg = sprintf($HtpasswordMsgFmt['created'], $name); } elseif(isset($idxusr)) { if($_REQUEST['delusr']) { $arr = LoadHtpasswd($HtpasswdFile); $name = $arr[$idxusr][0]; unset($arr[$idxusr]); SaveHtpasswd($HtpasswdFile, $arr); $groups = LoadHtgroup($HtgroupFile); HtgroupDelUserFromGroups($groups, $name); SaveHtgroup($HtgroupFile, $groups); $msg = sprintf($HtpasswordMsgFmt['deleted'], $name); } elseif($_REQUEST['renusr']) { $new = HtpasswdGetFormName($pagename, $auth, true); $arr = LoadHtpasswd($HtpasswdFile); $name = $arr[$idxusr][0]; $arr[$idxusr][0] = $new; SaveHtpasswd($HtpasswdFile, $arr); $groups = LoadHtgroup($HtgroupFile); HtgroupRenameUser($groups, $name, $new); SaveHtgroup($HtgroupFile, $groups); $msg = sprintf($HtpasswordMsgFmt['renamed'], $name, $new); } elseif($_REQUEST['setpw']) { $pass = HtpasswdGetFormPasswd($pagename, $auth, $_REQUEST['pwtype']); $arr = LoadHtpasswd($HtpasswdFile); $name = $arr[$idxusr][0]; $arr[$idxusr][1] = $pass; SaveHtpasswd($HtpasswdFile, $arr); $msg = sprintf($HtpasswordMsgFmt['passupdated'], $name); } elseif($_REQUEST['setinfo']) { $arr = LoadHtpasswd($HtpasswdFile); $name = $arr[$idxusr][0]; $arr[$idxusr][2] = $_REQUEST['info']; SaveHtpasswd($HtpasswdFile, $arr); $msg = sprintf($HtpasswordMsgFmt['infoupdated'], $name); } } } $MessagesFmt[] = FmtPageName($msg, $pagename); $browse($pagename, $auth); exit(); } function HtpasswdUsrForm($pagename) { global $InputAttrs, $HtpasswordForms, $PCache, $AuthId; $InputAttrs[] = 'tabindex'; SDV($HtpasswordForms['user'], "(:messages:) (:input form name='htpasswdusrform' '{\$PageUrl}':)(:input hidden action postusrhtpasswd:) (:table border='0':) (:cellnr:)$[Name]:\n(:input text nameusr value='_nameusr_' tabindex='1':) (:cell:)$[Old Password]:\n(:input password passwd0 value='' tabindex='2':) (:cellnr:)\n(:cell:)$[New Password]:\n(:input password passwd value='' tabindex='3':) (:cellnr:)\n(:cell:)$[again]:\n(:input password passwd2 value='' tabindex='4':) (:cell valign='bottom':)(:input submit change value='$[Change Password]' tabindex='5':) (:tableend:)(:input end:)"); SDV($PCache[$pagename]['nameusr'], @$AuthId); return FmtPageName(str_replace('_nameusr_', $PCache[$pagename]['nameusr'], $HtpasswordForms['user']), $pagename) . HtSetFocus('htpasswdusrform', 'nameusr'); } function HandleHtpasswdUsrForm($pagename, $auth) { global $EnableHtpassword, $HtpasswdFile, $HtpasswordTypes, $HtpasswordDefaultType, $MessagesFmt, $HtpasswordMsgFmt, $AuthId, $HtpasswordAutoLogin, $HandleActions; if($EnableHtpassword) { $msg = ''; if($_REQUEST['change']) { $name = HtpasswdGetFormName($pagename, $auth); $arr = LoadHtpasswd($HtpasswdFile); for($i = 0; $i < count($arr); $i++) { if($name == $arr[$i][0]) { $plain = $_REQUEST['passwd0']; $old = $arr[$i][1]; if(!($old || $plain) || _crypt($plain, $old) == $old) { $arr[$i][1] = HtpasswdGetFormPasswd($pagename, $auth, $HtpasswordDefaultType, $old, false); SaveHtpasswd($HtpasswdFile, $arr); $msg = sprintf($HtpasswordMsgFmt['passupdated'], $name); } break; } } } $MessagesFmt[] = FmtPageName($msg, $pagename); } $HandleActions['browse']($pagename, $auth); exit(); } function HtpasswdNewForm($pagename, $args) { global $InputAttrs, $HtpasswdForms; $InputAttrs[] = 'tabindex'; $opt = ParseArgs($args); SDV($HtpasswordForms['new'], "(:messages:) (:input form name='htpasswdnewform' '{\$PageUrl}':)(:input hidden action postnewhtpasswd:) (:table border='0':) (:cellnr:)\n(:cell:)$[Name]:\n(:input text nameusr value='' tabindex='1':) (:cell:)$[Password]:\n(:input password passwd value='' tabindex='2':) (:if false:)(:cell:)$[Comment]:\n(:if:)(:input hidden info value='' tabindex='4':) (:cellnr colspan='2':)\n(:cell:)$[again]:\n(:input password passwd2 value='' tabindex='3':) (:cell valign='bottom':)(:input submit create value='$[Create]' tabindex='5':) (:cellnr colspan='2':)\n(:cell colspan='2':) (:tableend:)(:input end:)"); return FmtPageName(str_replace('postnewhtpasswd', "postnewhtpasswd:)(:input hidden page '{$opt['page']}'", $HtpasswordForms['new']), $pagename) . HtSetFocus('htpasswdnewform', 'nameusr'); } function HandleHtpasswdNewForm($pagename, $auth) { global $EnableHtpassword, $HtpasswdFile, $HtpasswordDefaultType, $HtpasswordMsgFmt, $EnableHtgroup, $HtgroupFile, $HtpasswordDefaultGroup, $MessagesFmt, $AuthId, $HtpasswordAutoLogin, $HtpasswordNewPageRedirect, $HandleActions; $browse = $HandleActions['browse']; if($EnableHtpassword) { $arr = LoadHtpasswd($HtpasswdFile); if($_REQUEST['create']) { $newName = HtpasswdGetFormName($pagename, $auth); $newPass = HtpasswdGetFormPasswd($pagename, $auth, $HtpasswordDefaultType, '', false); for($i = 0; $i < count($arr); $i++) if($newName == $arr[$i][0]) { $MessagesFmt[] = FmtPageName(sprintf($HtpasswordMsgFmt['exists'], $newName), $pagename); $browse($pagename, $auth); exit(); } $arr[] = array($newName, $newPass); SaveHtpasswd($HtpasswdFile, $arr); if($EnableHtgroup && $HtgroupFile && $HtpasswordDefaultGroup) { $arr = LoadHtgroup($HtgroupFile); HtgroupAddUser($arr, $HtpasswordDefaultGroup, $newName); SaveHtgroup($HtgroupFile, $arr); } SDV($HtpasswordNewPageRedirect, $pagename); $target = FmtPageName($_REQUEST['page'] ? $_REQUEST['page'] : $HtpasswordNewPageRedirect, $pagename); if(IsEnabled($HtpasswordAutoLogin, 1)) { unset($AuthId); AuthUserId($target, $newName, $_REQUEST['passwd']); } if($target == $pagename) { $MessagesFmt[] = FmtPageName(sprintf($HtpasswordMsgFmt['created'], $newName), $pagename); $browse($pagename, $auth); } else Redirect($target); exit(); } } $browse($pagename, $auth); } function HtpasswdGetFormName($pagename, $auth, $adm = false) { global $PCache, $MessagesFmt, $HtpasswordMsgFmt, $HandleActions; $user = $_REQUEST['nameusr']; if(!$user) { if($adm) { $PCache[$pagename]['idxusr'] = $_REQUEST['idxusr']; $PCache[$pagename]['curgrp'] = $_REQUEST['curgrp']; $PCache[$pagename]['idxgrp'] = $_REQUEST['idxgrp']; $PCache[$pagename]['namegrp'] = $_REQUEST['namegrp']; $PCache[$pagename]['focus'] = 'nameusr'; } $MessagesFmt[] = FmtPageName($HtpasswordMsgFmt['no_name'], $pagename); $HandleActions['browse']($pagename, $auth); exit(); } return $user; } function HtpasswdGetFormPasswd($pagename, $auth, $pwtype, $salt = '', $adm = true) { global $PCache, $MessagesFmt, $HtpasswordMsgFmt, $HtpasswordTypes, $HandleActions; $plain = $_REQUEST['passwd']; if($plain != $_REQUEST['passwd2']) { if($adm) { $PCache[$pagename]['idxusr'] = $_REQUEST['idxusr']; $PCache[$pagename]['nameusr'] = $_REQUEST['nameusr']; $PCache[$pagename]['curgrp'] = $_REQUEST['curgrp']; $PCache[$pagename]['idxgrp'] = $_REQUEST['idxgrp']; $PCache[$pagename]['namegrp'] = $_REQUEST['namegrp']; $PCache[$pagename]['focus'] = 'passwd'; } $MessagesFmt[] = FmtPageName($HtpasswordMsgFmt['unmatched'], $pagename); $HandleActions['browse']($pagename, $auth); exit(); } $pw = ''; if($plain) { if(!$salt) { $salt = $HtpasswordTypes[$pwtype][1]; if($salt && $HtpasswordTypes[$pwtype][2]) $salt .= substr(md5(microtime() . mt_rand(10000, 32000)), 0, 8); } $pw = _crypt($plain, $salt); } return $pw; } function HtpasswdGetFormGroup($pagename, $auth) { global $PCache, $MessagesFmt, $HtpasswordMsgFmt, $HandleActions; $group = $_REQUEST['namegrp']; if(!$group) { $PCache[$pagename]['idxusr'] = $_REQUEST['idxusr']; $PCache[$pagename]['nameusr'] = $_REQUEST['nameusr']; $PCache[$pagename]['curgrp'] = $_REQUEST['curgrp']; $PCache[$pagename]['idxgrp'] = $_REQUEST['idxgrp']; $PCache[$pagename]['focus'] = 'namegrp'; $MessagesFmt[] = FmtPageName($HtpasswordMsgFmt['no_group'], $pagename); $HandleActions['browse']($pagename, $auth); exit(); } return $group; } # --- Utilities --- function HtgroupAddUser(&$arr, $group, $user) { for($i = 0; $i < count($arr); $i++) if($arr[$i][0] == $group) { if($arr[$i][1]) $arr[$i][1] .= ' '; if(preg_match("/['\"\\s]/", $user)) $user = "'" . preg_replace("/'/", "\\'", $user) . "'"; $arr[$i][1] .= $user; break; } } function HtgroupDelUserFromGroups(&$arr, $user) { for($i = 0; $i < count($arr); $i++) { $users = split(' ', $arr[$i][1]); for ($j = 0; $j < count($users); ++$j) { if ($users[$j] == $user) { unset($users[$j]); } } $arr[$i][1] = join(' ', $users); } } function HtgroupRenameUser(&$arr, $user_old, $user_new) { if(preg_match("/['\"\\s]/", $user_old)) $user_old = "'" . preg_replace("/'/", "\\'", $user_old) . "'"; if(preg_match("/['\"\\s]/", $user_new)) $user_new = "'" . preg_replace("/'/", "\\'", $user_new) . "'"; for($i = 0; $i < count($arr); $i++) { $users = split(' ', $arr[$i][1]); foreach ($users as $j => $user) { if ($user == $user_old) { $users[$j] = $user_new; } } $arr[$i][1] = join(' ', $users); } } function HtSetFocus($form, $name, $set = false) { return '<:block>' . Keep(""); } # --- File management --- function HtArraySort(&$arr, $flag) { if($flag) { $cmp = create_function('$x,$y', "return strcasecmp(\$x[0],\$y[0]);"); usort($arr, $cmp); } } function LoadHtpasswd($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; } function SaveHtpasswd($f, $arr) { global $HtpasswordSortedFile; HtArraySort($arr, IsEnabled($HtpasswordSortedFile, 0)); 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); } fclose($fp); ignore_user_abort(false); } function LoadHtgroup($f) { $arr = array(); $fp = @fopen($f, "r"); if($fp) { while($l = fgets($fp, 4096)) { if (preg_match('/^(\\w[^\\s:]+)\\s*:(.*)$/', trim($l), $m)) { /* $gl = preg_split('/[\\s,]+/', $m[2], -1, PREG_SPLIT_NO_EMPTY); $arr[] = array($m[1], $gl); #*/ $arr[] = array($m[1], $m[2]); } } fclose($fp); } return $arr; } function SaveHtgroup($f, $arr) { global $HtgroupSortedFile; HtArraySort($arr, IsEnabled($HtgroupSortedFile, 0)); ignore_user_abort(true); $fp = fopen($f, "w+"); if(flock($fp, LOCK_EX)) { foreach($arr as $g) /* fputs($fp, "$g[0]:" . implode(' ', $g[1]) . "\n"); #*/ fputs($fp, "$g[0]:$g[1]\n"); flock($fp, LOCK_UN); } fclose($fp); ignore_user_abort(false); }