From this page, you can modify a user ’ s name, access level, and signature... Change the user ’ s access level to Moderator, and click Modify Account.. If the user is an admin, then the
Trang 1value=” < ?php echo htmlspecialchars($useremail); ? > ”/ > < /p >
< ?php
if ($mode == ‘Modify’) { echo ‘ < div > < fieldset >
echo ‘ < legend > Access Level < /legend >
$sql = ‘SELECT access_lvl, access_name FROM
frm_access_levels ORDER BY
access_lvl DESC’;
$result = mysql_query($sql, $db) or die(mysql_error($db));
while ($row = mysql_fetch_array($result)) { echo ‘ < input type=”radio” id=”acl_’ $row[‘access_lvl’] ‘” name=”accesslvl” value=”’ $row[‘access_lvl’] ‘” ‘;
if ($row[‘access_lvl’] == $accesslvl) { echo ‘checked=”checked”’;
} echo ‘/ > ’ $row[‘access_name’] ‘ < br/ >
} echo ‘ < /fieldset > < /div >
}
if ($mode != ‘Modify’) { echo ‘ < div id=”passwords” >
}
if ($mode == ‘Edit’) {
if (isset($_GET[‘error’]) & & $_GET[‘error’] == ‘nopassedit’) { echo ‘ < strong > Could not modify passwords Please try again /strong > < br/ >
if ($mode != ‘Modify’) { echo ‘ < /div >
Trang 23 You are going to create a couple of new user identities to demonstrate the difference between
the various roles
Log out, and click Register You should see a screen similar to the one shown in Figure 16 - 3
Trang 34 Enter a name This name will be used for display purposes
5 Enter your e - mail address
6 Enter your password twice for verification
7 Click the Create Account button
Your account will be created, and you will be automatically logged in with your new account
8 Repeat steps 3 through 7 to create one more account
9 Log out, and then log back in with your original admin account
10 Now that you are logged in as the site administrator, you should see a menu item called Admin Click it
11 Click Users in the Administration menu
This displays the User Administration screen; from here, you can select a user from the drop down menu and edit user details
12 Choose one of the user profiles you created in step 7, and click Modify User You should see a page
similar to Figure 16 - 4 From this page, you can modify a user ’ s name, access level, and signature
Figure 16-4
Trang 413 Change the user ’ s access level to Moderator, and click Modify Account
How It Works
Let ’ s begin by looking at frm_useraccount.php At the beginning of the file, you check the user ’ s
credentials stored in your session variables If the user is an admin, then the form is set up to allow the
admin to change his or her access level
echo ‘ < div > < fieldset >
echo ‘ < legend > Access Level < /legend >
while ($row = mysql_fetch_array($result)) {
echo ‘ < input type=”radio” id=”acl_’ $row[‘access_lvl’]
Trang 5‘” name=”accesslvl” value=”’ $row[‘access_lvl’] ‘” ‘;
if ($row[‘access_lvl’] == $accesslvl) { echo ‘checked=”checked”’;
} echo ‘/ > ’ $row[‘access_name’] ‘ < br/ >
} echo ‘ < /fieldset > < /div >
}
The rest of the page simply finishes out the form Let ’ s move on to frm_admin.php You may have noticed sections of code in frm_admin.php that involve forum settings, BBcode settings, and more We ’ re going to ignore those for now to talk about the User Administration portion of the admin area, instead We promise that we ’ ll touch back on those other functions later in this chapter
User Administration
On the User Administration page, the first thing you need to do is gather up all of the access levels, along with their names That is done with the following code in frm_admin.php , which results in a numerical array of access levels:
$sql = ‘SELECT access_lvl, access_name FROM
frm_access_levels ORDER BY
access_lvl DESC’;
$result = mysql_query($sql, $db) or die(mysql_error($db));
while ($row = mysql_fetch_array($result)) { $a_users[$row[‘access_lvl’]] = $row[‘access_name’];
}
Next, under the edituser case of your switch() , you create an HTML select field, dynamically building up the options By looping through the access level array you just created, you can also use the
optgroup tag to categorize the select list by access level
< select id=”userlist” name=”userlist[]” >
< ?php foreach ($a_users as $key = > $value) { echo ‘ < optgroup label=”’ $value ‘” > ’ user_option_list($db, $key)
‘ < /optgroup >
}
? < /select >
Note that you create the list of users by calling the user_option_list() function This function resides
in frm_output_functions.inc.php and is called once for each access level A list of option tags is output, each containing the appropriate user information
Trang 6function user_option_list($db, $level) {
while ($row = mysql_fetch_array($result)) {
echo ‘ < option value=”’ $row[‘id’] ‘” > ’
htmlspecialchars($row[‘name’]) ‘ < /option >
}
mysql_free_result($result);
}
That ’ s really all there is to it When the appropriate user is chosen, his or her ID is passed on to
the frm_transact_admin.php transaction page, where the admin user is redirected to the
frm_useraccount.php page for that user
For um Functionality
The last section of this application covers the actual forum - specific functionality Up until now,
everything — with the exception of some functions and transaction pages — has been pretty generic,
and could really be used for almost any type of member - driven Web site Now, we ’ re getting to the fun
stuff, the reason for this chapter
Try It Out Editing Board Settings
The first thing you need to do is customize your bulletin board to your liking
1 Enter frm_edit_forum.php , which is used to edit forum details:
Trang 7if (isset($_GET[‘forum’])) { $forum = $_GET[‘forum’];
$sql = ‘SELECT forum_name, forum_desc, u.name, u.id FROM
frm_forum f LEFT JOIN frm_users u ON f.forum_moderator = u.id WHERE
f.id = ‘ $forum;
$result = mysql_query($sql, $db) or die(mysql_error($db));
if ($row = mysql_fetch_array($result)) { $fname = $row[‘forum_name’];
$fdesc = $row[‘forum_desc’];
$fmod = $row[‘name’];
$userid = $row[‘id’];
}}echo ‘ < h2 > ’ $action ‘forum < /h2 >
< td > < select id=”moderator” name=”forummod[]” >
< option value=”0” > unmoderated < /option >
< ?php
$sql = ‘SELECT
id, name FROM
frm_users WHERE
access_lvl > 1’;
$result = mysql_query($sql, $db) or die(mysql_error($db));
while ($row = mysql_fetch_array($result)) { echo ‘ < option value=”’ $row[‘id’] ‘”’;
if ($userid == $row[‘id’]) { echo ‘ selected=”selected”’;
} echo ‘ > ’ $row[‘name’] ‘ < /option >
}
? < /select >
< /td >
< /tr > < tr >
Trang 8< td colspan=”2” >
< input type=”hidden” name=”forum_id” value=” < ?php echo $forum; ? > ” / >
< input type=”submit” name=”action” value=” < ?php echo $action; ? > Forum” / >
2 Click the Admin link from the navigation menu This brings you to the administration page,
as shown in Figure 16 - 5 The values in the fields you now see are used in the application For
instance, the first field, Board Title, is “ Comic Book Appreciation Forums ”
Figure 16-5
3 Edit the Board Title field to read “ Comic Book Appreciation Bulletin Board, ” and click Update
The title at the top of the page should change accordingly
Trang 94 Complete the other fields in the administration page:
5 Change Pagination Limit to 3, and click the Update button
6 Now, click Forums in the Administration menu You should see a list of the forums available
for your board If this is your initial installation, you will have only one forum — called New Forum You can edit this forum, delete it, or create a new forum Feel free to create as many forums as you want Note that when creating or editing a forum, you can choose a moderator
The user ’ s account you edited earlier is now available as a choice in the Moderator field
7 Click BBcodes in the Administration menu
You will see a form where you can enter a “ template ” and “ replacement ” This allows you to designate words or phrases that will be replaced by different words or phrases For instance, you can enter the phrase “ very hard ” in the template field, and “ cats and dogs ” in the replacement field Once you click the Add New button, these will be added to the database
Note that the real power of this page is in the use of regular expressions If you are not familiar with regular expressions, we explain how they work in the “ How It Works ” section
8 Enter the following template and replacement values exactly as they are shown Remember to
click Add New after entering each one:
Trang 10How It Works
That brings you back to the frm_admin.php page You were able to get here by clicking the Admin
link, which is available only if you are logged in as the administrator So far, so good What if the user
attempts to access the frm_admin.php page directly?
Try it yourself Load frm_index.php in your browser, and then make sure you are logged out Once
you are logged out, load frm_admin.php by typing it directly in the address bar of your browser It
should load with no problem Now, edit one of the fields on the main admin page Again, nothing is
stopping you Indeed, when you click the Update button, the data will be saved
But wait … you are not logged in! How is this possible? Simple You have not checked the user ’ s
credentials once he or she got into the page
Just as you are responsible for checking IDs in your bar in case underage patrons slip in, you are
responsible for the users ’ access to your entire site If you don ’ t want certain people to access a page,
you not only have to bar access to any link loading the page, but kick them off the page if they are
successful in loading it
Fortunately, this is easy to do At the top of your page, simply check their credentials (those are up to
you — do they need a certain access level? do they just need to be logged in?), and then redirect them
to another page if they don ’ t pass ( shameonyou.php or simply back to frm_index.php )
You can do other things to make your site more secure Most are way beyond the scope of this book
A look at the W3C security FAQ link we gave you earlier should help you, if you are interested in
learning more about security Just don ’ t ever think you are “ secure enough ” if you haven ’ t considered
the risk of unauthorized access
While you are still visiting frm_admin.php , let ’ s take a closer look at it
The file frm_admin.php is set up in four different areas: Board Administration, User Administration,
Forum Admininistration, and BBcode Administration A lot is going on in this page You ’ ve already
seen User Administration, so we ’ ll tackle the other three areas one at a time First let ’ s look at Board
Administration
Board Administration
Looking at the code, you will see that you simply build your table of fields by looping through the array
called $admin that has the board configuration values
foreach ($admin as $key = > $value) {
Trang 11The array $admin is associative The key is a unique identifier for the data, which is associated with a value and a title For example, the title bar ’ s title is Board Titlebar, and the value is CBA Forums It is represented in the $admin array as follows:
$admin[‘titlebar’][‘title’] = ‘Board Titlebar’
$admin[‘titlebar’][‘value’] = ‘CBA Forums’
By looping through the $admin array, you can extract each piece of data and use it to build your form But the question is, where is $admin populated? It is certainly not created anywhere in frm_admin.php
If you look at the top of frm_admin.php , you ’ ll notice that frm_header.inc.php is included The array
is not built in frm_header.inc.php either, but looking at the top of frm_header.inc.php you will notice another included file, frm_config.inc.php A quick look into frm_config.inc.php uncovers the fact that $admin is loaded there Note that $bbcode is also being built You ’ ll see that used shortly
$sql = ‘SELECT * FROM frm_admin’;
$result = mysql_query($sql, $db) or die(mysql_error($db));
while ($row = mysql_fetch_array($result)) { $admin[$row[‘constant’]][‘title’] = $row[‘title’];
$admin[$row[‘constant’]][‘value’] = $row[‘value’];
}mysql_free_result($result);
$sql = ‘SELECT * FROM frm_bbcode’;
$result = mysql_query($sql, $db) or die(mysql_error($db));
while ($row = mysql_fetch_array($result)) { $bbcode[$row[‘id’]][‘template’] = $row[‘template’];
$bbcode[$row[‘id’]][‘replacement’] = $row[‘replacement’];
}mysql_free_result($result);
Notice that $admin and $bbcode are built by looping through the entire admin and BBcode table This is important because it illustrates how the Board Administration page contains every piece of data
contained in the admin table These values are available, and are used, throughout the application For example, frm_header.inc.php uses some of the $admin data:
Trang 12However, you may find the need to create a new row of data in the admin table to be used in your board
application For example, suppose you are using a style sheet to alter the appearance of the application
Perhaps you want the ability to dynamically change the style sheet used by changing a value in the
admin page, rather than by editing the frm_eader.php file
The good news is that once you add a new row of data to the admin table, it is automatically detected by
the Board Administration page and displayed The bottom line? If you feel you need a new,
administrator - controlled value in your application, simply add the appropriate row of data to your
admin table, and access it in your code, using the $admin[‘key’][‘value’] and
$admin[‘key’][ ’ title’] syntax
Forum Administration
Forum Administration is pretty straightforward You look up all of the forums in the forum table and
then list them with their descriptions, plus a link for editing and a link for deleting Choosing delete
takes the administrator to frm_ransact - affirm.php , which prompts the user for confirmation before
deleting the forum This is a safety precaution, because deleting a forum results in the deletion of all
posts within that forum as well We leave it to you to explore frm_transact - affirm.php on your own,
as it is a fairly self - explanatory page, and by now you should have no problem figuring out how it
works
BB code Administration
In step 8 of the previous “ Try It Out ” section, you entered a few strange patterns in the BBcode
Administration page These patterns are regular expressions, which were first discussed in Chapter 8
We will clear up the mystery of those values for you, if you ’ re having trouble deciphering them, and
show you how they work Before we do that, however, let ’ s look at how BBcodes are implemented Once
you see where the replacements take place, we will look at the actual patterns
If you take a look at the show_topic() function defined in frm_output_functions.inc.php , you ’ ll
see a line that looks like this:
echo ‘ < /p > < > ’ bbcode($db, nl2br(htmlspecialchars($body))) ‘ < /p > ’;
The variable $body contains the text you want to display on the screen However, before you do that,
you have a couple of cleanup tasks to perform First, you want to convert (and not render) any HTML
that might exist in the form to the HTML equivalents, so that the HTML is displayed in the body as it
was entered This will prevent malicious users from inputting HTML that can break your page The
function htmlspecialchars() performs this conversion for you
Once all of the necessary characters in the HTML have been converted to their HTML entity equivalents,
you want to replace each newline of the body text with < br/ > tags so that all of the paragraphs in the
post don ’ t run together PHP has a handy tool for that, too: the nl2br() function
Finally, you perform all of the replacements you have set up on the BBcode Administration page That is
accomplished using the function bbcode() , which runs through each of the target/replacement pairs in
the BBcode database, replacing any relevant text in the body It does this recursively for a max of four
iterations until no more matches are found
Trang 13function bbcode($db, $data) { $sql = ‘SELECT
template, replacement FROM
frm_bbcode’;
$result = mysql_query($sql, $db) or die(mysql_error($db));
if (mysql_num_rows($result) > 0) { while($row = mysql_fetch_array($result)) { $bbcode[‘tpl’][] = ‘/’
html_entity_decode($row[‘template’], ENT_QUOTES) ‘/i’;
$bbcode[‘rep’][] = html_entity_decode($row[‘replacement’], ENT_QUOTES);
} $data1 = preg_replace($bbcode[‘tpl’], $bbcode[‘rep’], $data);
}
Because regular expressions (or regex) use many odd characters in the pattern, before storing the data in your table you use htmlentities() to convert the data into something MySQL can safely store For that reason, when retrieving the data, you must perform html_entity_decode() Also note the use of
the i modifier after the right - hand modifier This specifies that you do not care about upper - or lowercase
matching If you want to respect case when matching a pattern, simply remove this modifier
As you can see from the code, $row[ ’ template’ ] contains the regex pattern The array variable
$row[ ’ replacement’ ] contains the replacement pattern Now, let ’ s look at some of the pattern/
replacement pairs you entered earlier:
Pattern Replacement Explanation
very hard cats and dogs This is a very simple replacement, using a literal
pattern match It replaces the words “ very hard ” with the words “ cats and dogs ” in any post or signature
You will see evidence of this in one of your posts
\[\/url\] < /a > Replaces any instance of [/url] in the body with
< /a > Note that the opening and closing square brackets and the forward slash have special meaning in
a regexp, so they must be delimited to show that you want to match them literally
\[b\]([^[]+?)
\[\/b\]
< > $1 < /b > Now we ’ re getting into some interesting stuff This
pattern matches [b]some text here[/b] and replaces it with < > some text here < /b >
Trang 14The last pattern deserves a bit of explanation, because it introduces a couple of new concepts The
parentheses are there so you can use what we call back references Note the $1 in the replacement pattern
This tells the function: “ Take whatever you found in the first set of parentheses and put it here ” If you
had a more complex pattern with a second set of parentheses, you would refer to the data matched
within those parentheses using $2 A third set of parenthesis would map to $3, and so forth
Within those parentheses, you are matching any character at all except a left square bracket The + tells
the expression to match from 1 to any number of those characters If you wanted the expression to match
0 or more, you would instead use *
The ? can be very confusing, especially if you ’ re not familiar with regular expressions Because it is
immediately preceded by a quantifier ( + ), it does not mean 0 characters or 1 character as it usually does
In this case, it is telling the regex not to be greedy What do we mean by “ greedy ” ? Let ’ s look at the
following text example:
Hello, [b]George[/b], how are [b]you[/b] doing today?
If you ran the regex pattern \[b\]([^[]+)\[\/b\] against that text (note the lack of ? ), the regex
would be greedy and match the maximum - sized pattern it could find, by default The result is that the
preceding text would be altered like so:
Hello, < > George[/b], how are [b]you < /b > doing today?
This isn ’ t good in this particular case, because you are only trying to style “ George ” and “ you ” in
boldface You use the ? in your pattern after the + to tell the regex pattern to be ungreedy , so that it finds
the smallest matches By adding in the ?, you get the result you really intended
Hello, < > George < /b > , how are < > you < /b > doing today?
We know regular expressions can be a bit confusing Take the time to learn them, though If you
understand them well, they can be your biggest ally You will be surprised at the sort of patterns you can
match with regex
Try It Out Using the Board
The final thing you ’ re going to do is use the board as a normal user would You ’ re going to create a
new post, view it, and reply to it
1 Create frm_view_forum.php , which displays all of the threads (topics) for a forum:
Trang 15echo breadcrumb($db, $forumid, ‘F’);
if (isset($_GET[‘page’])) { $page = $_GET[‘page’];
} else { $page = 1;
}
$limit = $admin[‘pageLimit’][‘value’];
if ($limit == ‘’) { $limit = 25;
frm_posts WHERE
forum_id = ‘ $forumid ‘ AND topic_id > 0 GROUP BY
tmp.postdate as re_posted FROM
frm_users u JOIN frm_posts t ON t.author_id = u.id LEFT JOIN tmp ON t.id = tmp.topic_id
LEFT JOIN frm_posts p ON p.topic_id = t.id WHERE
t.forum_id = ‘ $forumid ‘ AND t.topic_id = 0 GROUP BY
t.id ORDER BY re_posted DESC LIMIT ‘ $start ‘, ‘ $limit;
$result = mysql_query($sql, $db) or die(mysql_error($db));