··#·· echo "Error: You must be user <b>admin</b> to use APM."
··#·· exit 0
··# fi
··# Получить имя файла с паролями из файла. htaccess
··if [! -r "$htaccess"]; then
····echo "Error: cannot read $htaccess file."
····exit 1
··fi
··passwdfile="$(grep "AuthUserFile" $htaccess | cut −d\ −f2)"
··if [! -r $passwdfile]; then
····echo "Error: can't read password file: can't make updates."
····exit 1
··elif [! -w $passwdfile]; then
····echo "Error: can't write to password file: can't update."
····exit 1
··fi
··echo "<center><h1 style='background:#ccf;border-radius:3px;border:1px solid
··#99c;padding:3px;'>"
··echo "Apache Password Manager</h1>"
··action="$(echo $QUERY_STRING | cut −c3)"
··user="$(echo $QUERY_STRING|cut −d\& −f2|cut −d= −f2 |\
··tr '[: upper: ]' '[: lower: ]')"
··case "$action" in
····A) echo "<h3>Adding New User <u>$user</u></h3>"
········if [! -z "$(grep −E "^${user}:" $passwdfile)"]; then
··········echo "Error: user <b>$user</b> already appears in the file."
········else
··········pass="$(echo $QUERY_STRING|cut −d\& −f3|cut −d= −f2)"
··········if [! -z "$(echo $pass|tr −d '[[: upper: ][:lower: ][:digit: ]]')"];
··········then
············echo "Error: passwords can only contain a-z A-Z 0–9 ($pass)"
··········else
············$htpasswd $passwdfile "$user" "$pass"
············echo "Added!<br>"
··········fi
········fi
········;;
····U) echo "<h3>Updating Password for user <u>$user</u></h3>"
········if [-z "$(grep −E "^${user}:" $passwdfile)"]; then
··········echo "Error: user <b>$user</b> isn't in the password file?"
··········echo "searched for "^${user}:" in $passwdfile"
········else
··········pass="$(echo $QUERY_STRING|cut −d\& −f3|cut −d= −f2)"
··········if [! -z "$(echo $pass|tr −d '[[: upper: ][:lower: ][:digit: ]]')"];
··········then
············echo "Error: passwords can only contain a-z A-Z 0–9 ($pass)"
··········else
············grep −vE "^${user}:" $passwdfile | tee $passwdfile > /dev/null
············$htpasswd $passwdfile "$user" "$pass"
············echo "Updated!<br>"
··········fi
········fi
········;;
····D) echo "<h3>Deleting User <u>$user</u></h3>"
········if [-z "$(grep −E "^${user}:" $passwdfile)"]; then
··········echo "Error: user <b>$user</b> isn't in the password file?"
········elif ["$user" = "admin"]; then
··········echo "Error: you can't delete the 'admin' account."
········else
··········grep −vE "^${user}:" $passwdfile | tee $passwdfile >/dev/null
··········echo "Deleted!<br>"
········fi
········;;
··esac
··# Всегда перечислять текущих пользователей в файле паролей…
··echo "<br><br><table border='1' cellspacing='0' width='80 %' cellpadding='3'>"
··echo "<tr bgcolor='#cccccc'><th colspan='3'>List "
··echo "of all current users</td></tr>"
··oldIFS=$IFS; IFS=":" # Изменить разделитель слов…
··while read acct pw; do
····echo "<tr><th>$acct</th><td align=center><a href=\"$myname?a=D&u=$acct\">"
····echo "[delete]</a></td></tr>"
··done < $passwdfile
··echo "</table>"
··IFS=$oldIFS·········· #…и восстановить его.
··# Собрать строку выбора со всеми учетными записями…
··optionstring="$(cut −d: −f1 $passwdfile | sed 's/^/<option>/'|tr '\n' ' ')"
··if [! -r $footer]; then
····echo "Warning: can't read $footer"
··else
····#…и вывести нижний колонтитул.
····sed −e "s/-myname-/$myname/g" −e "s/-options-/$optionstring/g" < $footer
··fi
··exit 0
Как это работает
Для нормальной работы этого сценария требуется очень многое. Необходимо правильно настроить не только конфигурацию веб-сервера Apache (или эквивалентного ему), но и содержимое файла .htaccess, и в файле .htpasswd должна иметься хотя бы запись для пользователя admin.
Сам сценарий извлекает в htpasswd имя файла с паролями из файла .htaccess и выполняет разные проверки, чтобы исключить наиболее типичные ошибки при работе с htpasswd, в том числе и ошибку недоступности файла для записи. Все это делает инструкция case перед основным блоком сценария.
Инструкция case определяет, какая из трех возможных операций запрошена −A (добавить пользователя), U (изменить запись с информацией о пользователе) или D (удалить пользователя), — и выполняет соответствующий фрагмент кода. Код операции и имя пользователя хранятся в переменной QUERY_STRING. Значение для этой переменной посылается на сервер веб-браузером в составе URL, в виде a=X&u=Y, где X — буквенный код операции, а Y — имя пользователя. Когда запрашивается операция изменения пароля или добавления пользователя, должен передаваться третий аргумент, p, с паролем.