Location: PHPKode > projects > PHP SiteBuilder > include/class.htpasswd.html
<!-- $Id: class.htpasswd.html,v 1.2 2001/08/31 13:44:30 phps Exp $ -->
    <HTML> 
	<HEAD> 
	    <TITLE>class::Htpasswd - Manage Unix crypt-style password file.

</TITLE> 
	</HEAD>

	<BODY>

<!-- INDEX BEGIN -->

<UL>

	<LI><A HREF="#NAME">NAME</A>
	<LI><A HREF="#SYNOPSIS">SYNOPSIS</A>
	<LI><A HREF="#DESCRIPTION">DESCRIPTION</A>
	<LI><A HREF="#METHODS">METHODS</A>
	<LI><A HREF="#VARIABLES">VARIABLES</A>
	<LI><A HREF="#ERRORS">ERRORS</A>
	<LI><A HREF="#EXAMPLES">EXAMPLES</A>
	<LI><A HREF="#INSTALLATION">INSTALLATION</A>
	<LI><A HREF="#DOCUMENTATION">DOCUMENTATION</A>
	<LI><A HREF="#AVAILABILITY">AVAILABILITY</A>
	<LI><A HREF="#VERSION">VERSION</A>
	<LI><A HREF="#CHANGES">CHANGES</A>
	<LI><A HREF="#BUGS">BUGS</A>
	<LI><A HREF="#RESTRICTIONS">RESTRICTIONS</A>
	<LI><A HREF="#FILES">FILES</A>
	<LI><A HREF="#SEE_ALSO">SEE ALSO</A>
	<LI><A HREF="#AUTHOR_INFORMATION">AUTHOR INFORMATION</A>
</UL>
<!-- INDEX END -->

<HR>
<P>
<H1><A NAME="NAME">NAME

</A></H1>
class::Htpasswd - Manage Unix crypt-style password file.


<P>

<P>
<HR>
<H1><A NAME="SYNOPSIS">SYNOPSIS

</A></H1>
<STRONG>include("class.Htpasswd.php3");</STRONG>




<P>

<STRONG>$Htpasswd = new Htpasswd("/home/users/cdi/.htpasswd");</STRONG>




<P>

<STRONG>$Htpasswd-&gt;addUser("cdi","secret");</STRONG>




<P>

<STRONG>$Htpasswd-&gt;changePass("cdi","new-password","secret");</STRONG>




<P>

<STRONG>$Htpasswd-&gt;verifyUser("cdi","new-password");</STRONG>




<P>

<STRONG>$Htpasswd-&gt;getPass("cdi");</STRONG>




<P>

<STRONG>$Htpasswd-&gt;deleteUser("cdi");</STRONG>




<P>

<STRONG>$Htpasswd-&gt;renameUser("OldName","NewName","Password");</STRONG>




<P>

<P>
<HR>
<H1><A NAME="DESCRIPTION">DESCRIPTION

</A></H1>
This class facilitates the maintenance of htpasswd files, used to do Basic
Authentication on a web server. This class assumes PHP v3.0 or better and
Apache 1.3.3 or better.


<P>

The password file is a flat-file with login name and their associated
<EM>crypt.3</EM> passwords, in the format <STRONG>login:password</STRONG>.


<P>

<P>
<HR>
<H1><A NAME="METHODS">METHODS

</A></H1>
<STRONG><CODE>new("/full/path/to/htpasswd/file" );</CODE></STRONG>




<P>

Creates a new Htpasswd object. The path and file may be omitted. If the
path and file are omitted, the <CODE>initialize()</CODE> method <STRONG>must</STRONG> be called. 
<STRONG><CODE>"path-to-file"</CODE></STRONG> should be the path and name of the file containing the login/password
information.


<P>

<STRONG><CODE>initialize("/full/path/to/htpasswd/file" );</CODE></STRONG>




<P>

The first method that should be called. (if <STRONG>file</STRONG> was omitted from the <CODE>new()</CODE> method) Loads the file specified
into memory. Some methods may be called or some variables set prior to
<CODE>initialize()</CODE> to modify how it reads the file. See also
<CODE>sane(),</CODE> and <CODE>do_not_blame_cdi().</CODE>
<STRONG><CODE>"path-to-file"</CODE></STRONG> should be the path and name of the file containing the login/password
information.


<P>

<STRONG><CODE>verifyUser("user id", "unencrypted password" );</CODE></STRONG>




<P>

Given a user id and password, returns true if the password matches the
encrypted version stored in the htpasswd file. Returns false otherwise.


<P>

<STRONG><CODE>isUser("user");</CODE></STRONG>




<P>

Given a user id, will return true if that ID exists in the password file,
will return false otherwise. It should be noted that user ids are <STRONG>case
sensitive</STRONG>, so <STRONG>user</STRONG> is NOT the same user ID as <STRONG>User</STRONG> or <STRONG>USER</STRONG>.


<P>

<STRONG><CODE>getUserNum("user");</CODE></STRONG>




<P>

Given a user id, will return the user (line) number of that user. All
entrys in the password file are assigned the User Id of the <STRONG>USERS()</STRONG> array index. All of this is just glorified line numbers from the password
file, where line number 1 is user number 0. The total number of users in
the password file can be obtained from the <STRONG>USERCOUNT</STRONG> variable. Returns null if the user is not found.


<P>

<STRONG><CODE>version();</CODE></STRONG>




<P>

Returns the version information for this class.


<P>

<STRONG><CODE>do_not_blame_cdi();</CODE></STRONG>




<P>

Used to turn off sanity checking on the file pointed to by
<CODE>new()</CODE> or <CODE>initialize().</CODE> This is not reccommended.
See also <CODE>sane().</CODE>


<P>

<STRONG><CODE>getPass("user");</CODE></STRONG>




<P>

Given a userID, will return the user's encrypted password from the password
file. Returns null if the user is not found.


<P>

<STRONG><CODE>changePass("user", "newPass", "oldPass");</CODE></STRONG>




<P>

<CODE>changePass()</CODE> will change the password of an existing user. If <STRONG>"oldPass"</STRONG>
is omitted or is empty/null, a password change is forced. If the
<STRONG>"oldPass"</STRONG> is submitted, <CODE>changePass()</CODE> first verifies that the password
they entered was correct before it will change their password.  <STRONG>"newPass"</STRONG>
should be the plain text version of the user's password, as this method
will automatically encrypt it. Returns true upon success, returns false if
their
<STRONG>"oldPass"</STRONG> doesn't match or if the user wasn't found in the password file.


<P>

<STRONG><CODE>renameUser("OldName", "NewName", "password");</CODE></STRONG>




<P>

<CODE>renameUser()</CODE> changes a user ID in the password file. If the <STRONG>"password"</STRONG> is empty/null, the name change is forced. If the password is sent, the
<STRONG>"OldName"</STRONG> is first authenticated prior to allowing the name change. If
<STRONG>"OldName"</STRONG> doesn't exist or if <STRONG>"NewName"</STRONG> does exist, the change fails. Returns true on success, false on failure.


<P>

<STRONG><CODE>addUser("user", "password");</CODE></STRONG>




<P>

<CODE>addUser()</CODE> will add a user and password to the password file.
The password given to this method must not be encrypted as the
<CODE>addUser()</CODE> method will first encrypt the password, then save
it. You do not need to concern yourself with generating a salt for the
password encryption, as this method automatically calls
<CODE>genSalt().</CODE> Returns true on success, false on failure, and the
script exits with a fatal <STRONG>ERROR</STRONG> condition if it fails to save the new password file. Will also return false
if the user id submitted already exists in the password file.


<P>

<STRONG><CODE>genSalt();</CODE></STRONG>




<P>

Called directly, <CODE>genSalt()</CODE> will return a random two digit
salt. The salt will have the range <STRONG>A-Za-z./</STRONG>, which are the only legal characters that can be used by <EM>crypt.3</EM>. This method is considered internal, as all password encryption routines
will generate their own random salts automatically.


<P>

<STRONG><CODE>genPass();</CODE></STRONG>




<P>

If you want to generate a random password, which is always a better idea
than letting users pick wimpy passwords, use the <CODE>genPass()</CODE>
method. This method returns a randomly generated 5 to 8 character plain
text password, which can then be sent to <CODE>addUser()</CODE> or
<CODE>changePass()</CODE> as the users password. The password generated is
in the range <STRONG>[A-Za-z0-9!@#$%^&*()-=_+]</STRONG>.


<P>

<STRONG><CODE>assignPass("user");</CODE></STRONG>




<P>

<CODE>assignPass(UserID)</CODE> adds the user to the password file using an
automatically generated password. This method returns the plain text
version of a <CODE>genPass()</CODE> password. This method is designed to
quickly add users to the password file while maintaining the highest degree
of security by forcing random passwords on the user. It should be noted
that when this method returns the password, the user <STRONG>has already been added to the password
file</STRONG>. This method returns null upon failure. A file write error will cause the
program to immediately exit.


<P>

<STRONG><CODE>genUser();</CODE></STRONG>




<P>

To really clamp down on your system security, you can also assign random
user IDs. <CODE>genUser()</CODE> returns a random 5 to 8 character user ID,
suitable for use with <CODE>assignPass().</CODE> IDs generated will be in
the range <STRONG>A-Za-z0-9</STRONG>.


<P>

<STRONG><CODE>deleteUser("user");</CODE></STRONG>




<P>

Fairly straight forward, <CODE>deleteUser()</CODE> removes a given user
from the password file. Returns true on success, false on failure.


<P>

<STRONG><CODE>getUserNum("user");</CODE></STRONG>




<P>

All users in the password array have a user number assigned to them,
corresponding to their line number from the password file.
<CODE>getUserNum()</CODE> returns the users ID, or -1 on failure. Remember,
this is a zero based array where line number one from the password file
will be userNum zero. See also <STRONG>USERCOUNT</STRONG>.


<P>

<STRONG><CODE>cryptPass("password","salt");</CODE></STRONG>




<P>

Returns the encrypted form of <STRONG>password</STRONG> using the submitted <STRONG>salt</STRONG>. If the salt is omitted or is null, <CODE>cryptPass()</CODE> will
automatically generate a random salt before encrypting the password. This
method is considered internal, as the higher level methods that encrypt
user passwords will automatically call this method.


<P>

<STRONG><CODE>htWriteFile();</CODE></STRONG>




<P>

This is an internal method and is called anytime the password file needs to
be written. If however, you have made your own changes to the <STRONG>USERS</STRONG>
array, calling this method will save those changes to the file. Returns
true on success, false upon failure. If for any reason
<CODE>htWriteFile()</CODE> cannot save the file, it will immediately echo
an error message to the client and exit the program. If
<CODE>htWriteFile()</CODE> is successfull, it automatically re-calls the
<CODE>initialize()</CODE> method and refreshes the file contents in memory.
Word to the wise: Since the class loads the file contents into memory, if
multiple processes update the file, strange things may happen. I've tried
to make it so that the class makes no assumptions about the file's
contents, and the way it writes the file should be safe from multiple hits
to it simultaneously. I can't guarantee that though. The PHP maintainers
<STRONG>really</STRONG> need to implement some kind of file locking routines. If you're concerned
that this may become a problem, you'll need to implement some kind of
locking procedure within your own program. Some pseudo-code on how you
might do this;


<P>

<PRE>   +--+-  [check for a lock]
   |  |   |
   |  |   +------ No lock -&gt; initialize()
   |  |   |                            |
   |  |   |                            +- lock file
   |  |   +-- Locked --+                   |
   |  |                |                   +- Do Stuff
   |   +------&lt;--------+                        |
   |                                            +- Unlock
   |                                                 |
   + ------------------&lt;-----------------------------+
</PRE>

<P>


<P>
<HR>
<H1><A NAME="VARIABLES">VARIABLES

</A></H1>
The following global variables are available after an
<CODE>initialize()</CODE> method is invoked. Some may be set before the
<CODE>initialize()</CODE> method to effect the results. (DEBUG and the
method <CODE>do_not_blame_cdi()</CODE> )


<P>

<DL>
<DT><STRONG><A NAME="item_ERROR">ERROR (string)

</A></STRONG><DD>
If a method returns an error, or a method fails, the error can be retrived
by looking at this variable for the error text.


<P>

<DT><STRONG><A NAME="item_DEBUG">DEBUG (boolean)

</A></STRONG><DD>
Turns logging of errors on or off, default is true.


<P>

<DT><STRONG><A NAME="item_FILE">FILE (string)

</A></STRONG><DD>
Contains the path and file name submitted by the last <CODE>new()</CODE> or
<CODE>initialize()</CODE> method.


<P>

<DT><STRONG><A NAME="item_EXISTS">EXISTS (boolean)

</A></STRONG><DD>
Set to true if the file pointed to by <CODE>initialize()</CODE> or
<CODE>new()</CODE> exists. If starting a new password file, will remain
false until the first user is added to the file, then will be true from
then on out. (Or until all users are deleted from the file)


<P>

<DT><STRONG><A NAME="item_EMPTY">EMPTY (boolean)

</A></STRONG><DD>
Set to true if the file <STRONG>EXISTS</STRONG> but contains no data.


<P>

<DT><STRONG><A NAME="item_SANE">SANE (boolean)

</A></STRONG><DD>
Set to true if the password file is sane. False otherwise. Disable sanity
checking by calling <CODE>do_not_blame_cdi()</CODE> before calling the
<CODE>initialize()</CODE> method. If you want to turn off sanity checking,
you must call the <CODE>initialize()</CODE> method after calling the
<CODE>do_not_blame_cdi()</CODE> method.


<P>

<DT><STRONG><A NAME="item_VERSION">VERSION (string)

</A></STRONG><DD>
The version of this class file.


<P>

<DT><STRONG><A NAME="item_CONTENTS">CONTENTS (possibly really big string)

</A></STRONG><DD>
The raw file contents as one big scalar. Allows you to perform your own
functions upon the raw data. Changes made to <STRONG>CONTENTS</STRONG> are <STRONG>not</STRONG> written to the password file. You must modify the contents of the <STRONG>USERS</STRONG> array and then call <CODE>htWriteFile()</CODE> if you want changes made to
the actual file contents.


<P>

<DT><STRONG><A NAME="item_USERCOUNT">USERCOUNT (integer)

</A></STRONG><DD>
The total number of users (lines) in the password file. Remember, user
number 1 is <STRONG>USERCOUNT</STRONG> 0, so the actual total number of users in the file is <STRONG>USERCOUNT - 1</STRONG>. 


<P>

<DT><STRONG><A NAME="item_USERS">USERS (array)

</A></STRONG><DD>
The user database array after a successful <CODE>initialize()</CODE>
method. The array is in the form of:


<P>

<STRONG><CODE>$Htpasswd-&gt;USERS[index number][  "user"  ] = Username</CODE></STRONG>




<P>

<STRONG><CODE>$Htpasswd-&gt;USERS[index number][  "pass"  ] = Password</CODE></STRONG>




<P>

So, to grab the username for UserID # 5:


<P>

<STRONG><CODE>$User5 = $Htpasswd-&gt;USERS[ 5 ][  "user"  ]; </CODE></STRONG>




<P>

<DT><STRONG><A NAME="item_WIN32">WIN32 (boolean)

</A></STRONG><DD>
Set this to <STRONG>true</STRONG> if the script is on a Win32 box. Will prevent the class from performing
``unix only'' stuff.  


<P>

<H1><A NAME="ERRORS">ERRORS

</A></H1>
Most of the time, the contents of the last error can be obtained by
grabbing the <STRONG>ERROR</STRONG> variable. As in 


<P>

<STRONG><PRE> echo &quot; oops, $Htpasswd-E&lt;gt&gt;ERROR \n &quot; ; 
</PRE>
</STRONG>.


<P>

Only one type of error is not trapped in this fashion: Fatal file access
errors, specifically fatal file write errors. If at any time this class
cannot write a file it needs to write, it will <STRONG>immediately</STRONG> exit the entire program, rather than compromise security by assuming the
file was successfully written. The class will echo the contents of <STRONG>ERROR</STRONG> to the client prior to exiting.


<P>

<H1><A NAME="EXAMPLES">EXAMPLES

</A></H1>
See the example files in the <STRONG>examples/</STRONG> directory, created by this archive when it was uncompressed.


<P>

<H1><A NAME="INSTALLATION">INSTALLATION

</A></H1>
You install class.Htpasswd.php3, as you would install any PHP library, just
copy it to the directory pointed to by <STRONG>include_path</STRONG> in your php3.ini file:


<P>

<STRONG><CODE>cp class.Htpasswd.php3 $INCLUDE_PATH/class.Htpasswd.php3 </CODE></STRONG>




<P>

<STRONG><CODE>chmod 444 $INCLUDE_PATH/class.Htpasswd.php3</CODE></STRONG>




<P>

Change <STRONG>$INCLUDE_PATH</STRONG> to whatever your <STRONG>include_path</STRONG> directive is set to. If you don't have <STRONG>include_path</STRONG> set, then edit your php3.ini file and set one. That's it. Simple yes?


<P>

<H1><A NAME="DOCUMENTATION">DOCUMENTATION

</A></H1>
Other than this man page, you're on your own. Created using POD style
documentation and manified by a custom version of <STRONG>pod2man</STRONG>. HTML documentation created by a modified verison of <STRONG>pod2html</STRONG>.  


<P>

The comments in the source code itself should also help, but I'm not
guaranteeing that.


<P>

<H1><A NAME="AVAILABILITY">AVAILABILITY

</A></H1>
The latest version of class.Htpasswd.php3 should always be available from:


<P>

<A
HREF="http://www.thewebmasters.net/php/Htpasswd.phtml">http://www.thewebmasters.net/php/Htpasswd.phtml</A>



<P>

or


<P>

<A HREF="http://php.codebase.org/">http://php.codebase.org/</A>


<P>

<H1><A NAME="VERSION">VERSION

</A></H1>
<STRONG>Revision 0.9 1999/01/27 16:41:00</STRONG>




<P>

<H1><A NAME="CHANGES">CHANGES

</A></H1>
Added the <CODE>renameUser()</CODE> method per request from Rainer Scholz
<A HREF="MAILTO:hide@address.com">hide@address.com</A> .
General code clean-up.


<P>

Coming soon: class.Htgroup.php3


<P>

<H1><A NAME="BUGS">BUGS

</A></H1>
None, and you better not find any either.


<P>

<H1><A NAME="RESTRICTIONS">RESTRICTIONS

</A></H1>
May have problems on Win32 platforms. If you want it to work on Win32 then
you can bloody well make the changes. (And get credit for it in the
official distro if you're nice enough to send me your changes)


<P>

If running PHP as a CGI: Be sure to set <STRONG>DEBUG</STRONG> to false, or modify the <CODE>error()</CODE> function to log to someplace
other than <CODE>error_log().</CODE>


<P>

FATAL errors during file operations will cause an immediate exit of the
program. Fatal errors are echo'd to STDOUT.


<P>

<H1><A NAME="FILES">FILES

</A></H1>
<EM>class.htpasswd.php3</EM>, and this one <EM>Htpasswd.php.3</EM>




<P>

<H1><A NAME="SEE_ALSO">SEE ALSO

</A></H1>
Port inspired by the <STRONG>Apache::Htpasswd</STRONG> perl module by Kevin Meltzer,
<STRONG>hide@address.com</STRONG>. (Available from CPAN <STRONG>http://www.cpan.org</STRONG> )


<P>

<EM>htpasswd.1</EM>, <EM>httpd.8</EM>, and <EM>crypt.3</EM>




<P>

<H1><A NAME="AUTHOR_INFORMATION">AUTHOR INFORMATION

</A></H1>
Copyright 1999, CDI <A
HREF="MAILTO:hide@address.com">hide@address.com</A> All rights
reserved. It may be used and modified freely, but this copyright notice
must remain attached to the file (or modified versions of this file). You
may modify this source code as you wish, but if you redistribute a modified
version, you <STRONG>must</STRONG> attach a note listing the modifications you have made and you
<STRONG>must</STRONG> send me the source. If your changes or modifications warrant they will be
included in the next official revision.


<P>

Address bug reports and comments to:


<P>

<A HREF="MAILTO:hide@address.com">hide@address.com</A>


<P>

The author makes no warranties, promises, or gaurantees of this software.
As with all software, use at your own risk. This software is distributed
<STRONG>"AS-IS"</STRONG>.


<P>

</DL>
</DL>
    </BODY>

    </HTML>
Return current item: PHP SiteBuilder