File Security and Resources with PHP

In this fourth part of an article series on working with the file and operating systems with PHP, you’ll learn about file ownership and permissions, and the concept of a resource. This article is excerpted from chapter 10 of the book Beginning PHP and PostgreSQL 8: From Novice to Professional, written by W. Jason Gilmore and Robert H. Treat (Apress; ISBN: 1590595475).

File Ownership and Permissions

These days, security is paramount to any server installation, large or small. Most modern operating systems have embraced the concept of the separation of file rights via a user/group ownership paradigm, which, when properly configured, offers a wonderfully convenient and powerful means for securing data. In this section, you’ll learn how to use PHP’s built-in functionality to review and manage these permissions.

Note that because PHP scripts typically execute under the guise of the server daemon process owner, some of these functions will fail unless highly insecure actions are taken to run the server as a privileged user. Thus, keep in mind that some of the functionality introduced in this chapter is much better suited for use when running PHP as a command-line interface (CLI), since scripts executed by way of the CLI could conceivably be run as any system user.

chown()

int chown (string filename, mixed user)

The chown() function attempts to change the owner of filename to user (specified either by the user’s username or UID), returning TRUE on success and FALSE otherwise.

chgrp()

int chgrp (string filename, mixed group)

The chgrp() function attempts to change the group membership of filename to group, returning TRUE on success and FALSE otherwise.

fileperms()

int fileperms (string filename)

The fileperms() function returns filename’s permissions in decimal format, or FALSE in case of error. Because the decimal permissions representation is almost certainly not the desired format, you’ll need to convert fileperms()’s return value. This is easily accomplished using the base_convert() function in conjunction with substr(). The base_convert() function converts a value from one number base to another; therefore, you can use it to convert fileperms()’s returned decimal value from base 10 to the desired base 8. The substr() function is then used to retrieve only the final three digits of base_convert()’s returned value, which are the only digits referred to when discussing Unix file permissions. Consider the following example:

<?php
echo substr(base_convert(fileperms("/etc/passwd"), 10, 8), 3);
?>

This returns:

——————————————–644
——————————————–

filegroup()

int filegroup (string filename)

The filegroup() function returns the group ID (GID) of the filename owner, and FALSE if the GID cannot be determined:

<?php
$gid = filegroup("/etc/passwd");
// Returns "0" on Unix, because root usually has GID of 0.
?>

Note that filegroup() returns the GID, and not the group name.

fileowner()

int fileowner (string filename)

The fileowner() function returns the user ID (UID) of the filename owner, or FALSE if the UID cannot be determined. Consider this example:

<?php
$uid = fileowner("/etc/passwd");
// Returns "0" on Linux, as root typically has UID of 0.
?>

Note that fileowner() returns the UID, and not the username.

isexecutable()

boolean isexecutable (string filename)

The isexecutable() function returns TRUE if filename exists and is executable, and FALSE otherwise. Note that this function is not available on the Windows platform.

isreadable()

boolean isreadable (string filename)

The isreadable() function returns TRUE if filename exists and is readable, and FALSE otherwise. If a directory name is passed in as filename, isreadable() will determine whether that directory is readable.

iswriteable()

boolean iswriteable (string filename)

The iswriteable() function returns TRUE if filename exists and is writable, and FALSE otherwise. If a directory name is passed in as filename, iswriteable() will determine whether that directory is writable.


Note The function iswritable() is an alias of iswriteable().


umask()

int umask ([int mask])

The umask() function determines the level of permissions assigned to a newly created file. The umask() function calculates PHP’s umask to be the result of mask bitwise ANDed with 0777, and returns the old mask. Keep in mind that mask is a three- or four-digit code representing the pewrmission level. PHP then uses this umask when creating files and directories throughout the script. Omitting the optional parameter mask results in the retrieval of PHP’s currently configured umask value.

File I/O

Writing exciting, useful programs almost always requires that the program work with some sort of external data source. Two prime examples of such data sources are files and databases. In this section, we delve deep into working with files. Before we introduce PHP’s numerous standard file-related functions, however, it’s worth introducing a few basic concepts pertinent to this topic.

{mospagebreak title=The Concept of a Resource}

The term "resource" is commonly attached to any entity from which an input or output stream can be initiated. Standard input or output, files, and network sockets are all examples of resources.

Newline

The newline character, which is represented by the n character sequence, represents the end of a line within a file. Keep this in mind when you need to input or output information one line at a time. Several functions introduced throughout the remainder of this chapter offer functionality tailored to working with the newline character. Some of these functions include file(), fgetcsv(), and fgets().

End-of-File

Programs require a standardized means for discerning when the end of a file has been reached. This standard is commonly referred to as the end-of-file, or EOF, character. This is such an important concept that almost every mainstream programming language offers a built-in function for verifying whether or not the parser has arrived at the EOF. In the case of PHP, this function is feof(), described next.

feof()

int feof (string resource)

The feof() function determines whether resource’s EOF has been reached. It is used quite commonly in file I/O operations. An example follows:

<?php
$fh = fopen("/home/www/data/users.txt", "rt");
while (!feof($fh)) echo fgets($fh);
fclose($fh);
?>

{mospagebreak title=Opening and Closing a File}

You’ll often need to establish a connection to a file resource before you can do anything with its contents. Likewise, once you’ve finished working with that resource, you should close the connection. Two standard functions are available for such tasks, both of which are introduced in this section.

fopen()

resource fopen (string resource, string mode [, int use_include_path
[, resource zcontext]])

The fopen() function binds a resource to a stream, or handler. Once bound, the script can interact with this resource via the handle. Most commonly, it’s used to open files for reading and manipulation. However, fopen() is also capable of opening resources via a number of protocols, including HTTP, HTTPS, and FTP, a concept discussed in Chapter 16.

The mode, assigned at the time a resource is opened, determines the level of access available to that resource. The various modes are defined in Table 10-1.

Table 10-1. File Modes

Mode Description
r Read-only. The file pointer is placed at the beginning of the file.
r+ Read and write. The file pointer is placed at the beginning of the file.
w Write only. Before writing, delete the file contents and return the file pointer to the beginning of the file. If the file does not exist, attempt to create it.
w+ Read and write. Before reading or writing, delete the file contents and return the file pointer to the beginning of the file. If the file does not exist, attempt to create it.
a Write only. The file pointer is placed at the end of the file. If the file does not exist, attempt to create it. This mode is better known as Append.
a+ Read and write. The file pointer is placed at the end of the file. If the file does not exist, attempt to create it. This process is known as appending to the file.
b Open the file in binary mode.
t Open the file in text mode.

 

 

 

 

 

 

 

 

 

 

 

If the resource is found on the local file system, PHP expects the resource to be available by either the local or relative path prefacing it. Alternatively, you can assign fopen()’s use_include_path parameter the value of 1, which will cause PHP to consider the paths specified in the include_path configuration directive.

The final parameter, zcontext, is used for setting configuration parameters specific to the file or stream, and for sharing file- or stream-specific information across multiple fopen() requests. This topic is discussed in further detail in Chapter 16.

Let’s consider a few examples. The first opens a read-only stream to a text file residing on the local server:

$fh = fopen("/usr/local/apache/data/users.txt","rt");

The next example demonstrates opening a write stream to a Microsoft Word document. Because Word documents are binary, you should specify the binary b mode variation.

$fh = fopen("/usr/local/apache/data/docs/summary.doc","wb");

The next example refers to the same Word document, except this time PHP will search for the file in the paths specified by the include_path directive:

$fh = fopen("summary.doc","wb", 1);

The final example opens a read-only stream to a remote index.html file:

$fh = fopen("http://www.example.com/", "rt");

You’ll see this function in numerous examples throughout this and the next chapter.

fclose()

boolean fclose (resource filehandle)

Good programming practice dictates that you should destroy pointers to any resources once you’re finished with them. The fclose() function handles this for you, closing the previously opened file pointer specified by filehandle, returning TRUE on success and FALSE otherwise. The filehandle must be an existing file pointer opened using fopen() or fsockopen().

Please check back for the next part of the series.

Google+ Comments

Google+ Comments