Thisallows us to easily implement interface,abstract classes, and more inheritance capa-bilities, not to mention excellent error han-dling and the ability to better conform withuser-crea
Trang 1See inside for details
Get Ready For
Creating a Reusable Menu
System with XML and PHP
Understand the need, the solutions,
and the processes
Installing Java for PHP
Demystify the beast
Advanced Database Features Exposed Come to terms with using the best tool for the job
Secure PHP Taking the key out
of the lock
Trang 2Signup now and save $100.00!
Hurry, space is limited.
Visit us at www.phparch.com/cruise for more details.
March 1 st - March 5 th 2004
Andrei Zmievski - Andrei's Regex Clinic, James Cox - XML for the Masses, Wez Furlong -Extending PHP,Stuart Herbert - Safe and Advanced Error Handling in PHP5, Peter James -mod_rewrite: From Zero to Hero, George
Schlossnagle - Profiling PHP, Ilia Alshanetsky - Programming Web Services, John Coggeshall - Mastering PDFLib,
Jason Sweat - Data Caching Techniques
We’ve got you covered, from port to sockets.
Port Canaveral • Coco Cay • Nassau
Plus: Stream socket programming, debugging techniques, writing high-performance code,
Trang 3F R O M T H E E X P E R T S AT D E V E L O P E R ’ S L I B R A RY .
M O R E T I T L E S F R O M D E V E L O P E R ’ S L I B R A R Y
Advanced PHP Programming
by George Schlossnagle
ISBN: 0-672-32561-6
$49.99 US • 500 pages
PHP and MySQL Web
Development, Second Edition
by Luke Welling and
While there are many books on
learning PHP and developing
small applications with it, there is
a serious lack of information on
scaling PHP for large-scale,
business-critical systems
Schlossnagle’s Advanced PHP
Programming fills that void,
demonstrating that PHP is ready
for enterprise Web applications
by showing the reader how to
develop PHP-based applications
for maximum performance, stability,
and extensibility
Essential references for programming professionals
php|architect readers, get 40% off books in the Developer’s Library
Visit www.developers-library.comand add the books of yourchoosing to your shopping cart Upon check-out, enter thecoupon code PHPARCH03
to receive discount Offer validthrough 12/31/03
Trang 469 Tips & Tricks
By John W Holmes
73 Bits & Pieces
Real Interesting Stuff.
76 exit(0);
Buy vs Build
By Marco Tabini
9 Secure PHP Coding
by David Jorm and Jody Melbourne
19 Introduction to Bug Management
Trang 5*By signing this order form, you agree that we will charge your account in Canadian dollars for the
“CAD” amounts indicated above Because of fluctuations in the exchange rates, the actual amount charged in your currency on your credit card statement may vary slightly †Limited time offer extended to September 30th, 2003.
Choose a Subscription type:
Canada/USA $ 81.59 $67.99 CAD ($59.99 $49.99 US*)International Surface $108.99 $94.99 CAD ($79.99 $69.99 US*)International Air $122.99 $108.99 CAD ($89.99 $79.99 US*)
Your charge will appear under the name "Marco Tabini & Associates, Inc." Please allow up to 4 to 6 weeks for your subscription to be established and your first issue to be mailed to you.
*US Pricing is approximate and for illustration purposes only.
php|architect Subscription Dept.
VISA Mastercard American Express
Credit Card Number:
Expiration Date:
E-mail address:
Phone Number:
Buy now and save $10 off the price of any subscription†
Visit: http://www.phparch.com/print for more information or to subscribe online.
Signature: Date:
php|architect
The Magazine For PHP Professionals
Existing subscribers
can upgrade to
the Print edition
and save!
Login to your account
for more details.
NEW!
Trang 6PublisherMarco TabiniEditor-in-ChiefPeter James
petej@phparch.com
Editor-at-LargeBrian K Jones
brian@phparch.com
Editorial TeamArbi ArzoumaniPeter JamesBrian JonesEddie PelokeGraphics & LayoutArbi Arzoumani, Hammed Malik,
Marina ZlatogorovManaging EditorEmanuela CorsoDirector of Marketing
J Scott Johnson
scott@phparch.com
Account ExecutiveShelley Johnston
shelley@phparch.com
AuthorsDejan Bosanac, David Jorm, Dave Palmer, Davor Pleskina, Allessandro Sfondrini, Leon Vismer
php|architect (ISSN 1705-1142) is published twelve times a year
by Marco Tabini & Associates, Inc., P.O Box 3342, Markham, ON
L3R 6G6, Canada
Although all possible care has been placed in assuring the racy of the contents of this magazine, including all associated source code, listings and figures, the publisher assumes no responsibilities with regards of use of the information contained herein or in all associated material.
accu-Contact Information:
General mailbox: info@phparch.com Editorial: editors@phparch.com Subscriptions: subs@phparch.com Sales & advertising: sales@phparch.com Technical support: support@phparch.com
In the relatively short time that I’ve been with
php|architect (about six months now), I’ve
seen a lot of our magazine content cross my
(very messy) desk In that same time period,
I’ve been committed to gobbling up any and all
PHP content gracing the pages of other
publi-cations and developer sites I now feel that I
am qualified to state an opinion:
We have great content
Our authors consistently dig deep into their
top-ics, bringing you their practical experience,
exam-ples, and well-written explanations Their
enthusi-asm for their articles shines through, and brings
warmth and community to the pages of
php|architect every month
We constantly demand the best from our
authors, and they, in turn, demand the best from
us The php|architect editorial team prides itself
on being transparent, and I believe that authors
enjoy writing for us because of it (maybe this
helps explain why there are only two new
authors and four return authors this month) By
transparent, I mean that we are honest and up
front with them, as well as ourselves We view
our authors as collaborators and team members,
never as service providers or vendors We are
easy to work with, and are eager to bend over
backward to help if we can see that an honest
effort is being made
Through all of this we never compromise our
integrity or settle for second best Really, though,
how could we? We serve one of the greatest
soft-ware communities in the world!
This brings me to my next point I am
absolutely ecstatic to have been bestowed the
honor of directing the editorial path of
php|architect Our authors, our readers, and
our editorial team have all worked hard to build
an excellent resource that brings you the best
that the PHP world has to offer each and every
month
The hardest part of my new role here at php|a
will probably be trying to fill Brian’s shoes – he’s
got really big feet.* Brian has worked
extreme-ly hard to foster long-term relationships with
our authors, and I will be working feverishly to
continue to build and maintain that community,
as well as various other initiatives on the front
and back-end of the publication
But don’t worry, I’m still sleeping four hours a
night
I sincerely hope you enjoy this month’s issue
People lost hair, sleep, and teeth over it And, as
always, if you see anything you particularly like or
don’t like in our magazine this month, I strongly
encourage you to send us your feedback at
Trang 7editors@phparch.com Even fan letters firmly
stating that “You suck.” will be warmly accepted, as
they help to break up the large amounts of spam
that we all get from that address
* Actually, I’ve never physically seen Brian, or
Brian’s shoes I’m pretty sure I can smell them,
though
EDITORIAL
When in Rome
Go to PHP Day 2003!
The first conference dedicated exclusively
to the Italian PHP Community, called PHPDay 2003, will take place on October 24,
2003 in Rome at the Universita’ Tor Vergata.The program includes several speakers fromthe Italian technical community, and focuses
on the theme of interface development, aswell as a few tutorials to get the beginners upand running Most of all, PHP Day revolvesaround the concept of providing the PHP com-munity with an opportunity to meet andexchange their experiences
If you live in Italy, this is a great opportunity
to meet your fellow PHP enthusiasts If youdon’t live in Italy this might be the perfectexcuse for that long-postponed vacation!
For more information on PHP Day, visithttp://www.phpday.it or mail the organizers
at staff@phpday.it
PHP 4.3.3
release of PHP 4.3.3
This release contains a
large number of bug fixes
and it is recommended that
all users ugrade to this
• and much more
Visit to php.net download or view the change log
Apache Cocoon 2.1
Apache Cocoon is a web development
frame-work built around the concepts of separation ofconcerns (making sure people can interact andcollaborate on a project, without stepping oneach other toes) and component-based webdevelopment
Cocoon implements these concepts around thenotion of ‘component pipelines’, each component
on the pipeline specializing on a particular tion This makes it possible to use a Lego(tm)-likeapproach in building web solutions, hookingtogether components into pipelines without anyrequired programming
opera-Cocoon is “web glue for your web applicationdevelopment needs” It is a glue that keeps con-cerns separate and allows parallel evolution of thetwo sides, improving development pace andreducing the chance of conflicts
Cocoon has a PHP Generator which is not
includ-ed in the binary distribution but can be found at:
Trang 8ZEND Studio 3.0.0 Beta
the Zend Studio 3.0.0 Beta for Windows and Mac
The latest release includes:
• Code Profiler – Determine which scripts are
slowing down your project so you can focus
your time on improving their performance
• One-click debugging and profiling tool –
Direct debugging and profiling of web
pages directly from your browser
• Code Analyzer – Pinpoint messy code,
allowing you to write cleaner more correct
code
• Highlight syntax errors – Write clean PHP
code while you are typing
• Support for PHP 5.0 – Including syntax
highlighting, code completion, file and
proj-ect inspproj-ectors
• Dramatic performance improvements
• Code Completion improvements –
Including improve speed, recognized
con-stants, and new functions arguments
view and much more
Get more information or download from
Zend.com
PhpBB 2.0.6
The phpBB Group is pleased to announce the
release of phpBB 2.0.6 the “phew, it’s way to hot
to be furry” Edition This release had been made
to fix a number of potential security related issues
and more annoying bugs Work continues on 2.2.0
and another 2.0.x release is not planned except
where critical issues arise
phpBB.com describes phpBB as:
” a high powered, fully scalable, and highly
customisable open-source bulletin board
package phpBB has a user-friendly
inter-face, simple and straightforward
administra-tion panel, and helpful FAQ Based on the
powerful PHP server language and your
choice of MySQL, MS-SQL, PostgreSQL or
Access/ODBC database servers, phpBB isthe ideal free community solution for allweb sites.”
phpBB strongly advises all users to upgrade
Get more information for phpBB.com
“Japha is an attempt to bring the main classes
in the Java 1.4.1 (soon to be 1.4.2, time ing) to PHP for use in everyday programs We
allow-do this using the syntax that has been madecommon with the new releases of PHP 5 Thisallows us to easily implement interface,abstract classes, and more inheritance capa-bilities, not to mention excellent error han-dling and the ability to better conform withuser-created data types.”
Get more information or download the latestversion from Japha.xzon.net
LightBulb 4.79
LightBulb (formerly EzSDK) is a PHP SDK whichincludes a PHP source code generator, a library ofPHP Classes, and an application environment con-sisting of premade supporting modules The mod-ules handle user application and data accesssecurity, DB compatibility, a built-in GUI interfacewith an interactive desktop and more Check outthis month’s product review for more information.This release contains changes to the spellchecking features
Spell checking of user data is now an ent, interactive user option throughout thesystem Developers are able to utilize thespell check features throughout every appli-cation developed without writing any sourcecode to facilitate this
inher-Get more information or view the demo at
ezsdk.com
php|a
Trang 9Web applications, by their very nature,
have a broad exposure to remote ers and a set of potential vulnerabilities
attack-as rich attack-as the languages and protocols from
which they are born Web applications are
han-dling an ever-growing list of business functions,
and the code driving them must be paid due
attention with regard not only to performance
and stability, but also to security
This article is aimed at providing a concise
list-ing and discussion of the most common
vulnera-bilities that exist in PHP web applications This
vulnerability listing is used at the end of the
arti-cle as the basis for developing coding and code
audit/testing methodologies which can be
applied to any PHP web application
Note that, for the sake of brevity, only the most
common and severe vulnerabilities have been
listed and that vulnerabilities outside the scope
of PHP code – such as those which may exist in a
web server or PHP itself – are not covered by this
article
SQL Injection
An SQL injection vulnerability can rear its uglyhead when user-submitted variables are used toassemble SQL queries on the server side withoutsufficient input validation The underlying SQLstatement can be manipulated or additional SQLstatements injected by an attacker SQL Injection
is one of the most common web application nerabilities, but does not affect PHP code asmuch as other languages, mostly due to PHP’sautomatic character escaping and built-in valida-tion functions A sample vulnerability is shown inListing 1
vul-A sample attack on that vulnerability mightlook like the following:
Note that the value being passed to artid is aurlencoded version of “0 or ArticleID <> 0”.Making a call to the link above would cause thefollowing value to be assigned to $ssql and exe-
http://www.server.com/listing1.php?artid=
0%20or%20ArticleID%20<>%200
NOTE: All examples use the HTTP GET
method so that attacks can be easily
illus-trated as URIs Keep in mind that using POST
is no defence; the variables are simply in the
HTTP message body rather than the query
string component of the URI From a
theoret-ical perspective, at least, POST variables are
just as easy to manipulate as GET variables.
REQUIREMENTS
Trang 10cuted on the SQL server:
Some database servers also allow multiple SQL
statements to be concatenated using a
semi-colon (;) as a separator In that case, the
follow-ing attack could be used:
In this case, the urlencoded value being passed
into artid is “0; DROP TABLE Articles” You can
imagine the problems that this might cause
The key to protecting code against SQL
injec-tion attacks – also key for protecting against
most web application vulnerabilities – is
rigor-ous input validation PHP can automatically
escape some characters, such as apostrophes
(‘), providing protection against attacks
involv-ing those characters, but this is not sufficient
immunity All user-controlled variables used to
construct SQL statements or other commands
must be stripped of any content that may alter
the effects of the query For numeric inputs,
either verify that the value is indeed numeric,
or make it numeric using settype() For
non-numeric inputs, run the variable through
addslashes() or addcslashes() before using it
to construct a query The vulnerable example
above is patched in Listing 2 More information
on patching against SQL injection is available at
In testing for SQL injection, the blackbox tester
studies application inputs and attempts to insert
special characters (such as commas, apostrophes,
semicolons, quotation marks, and equal signs) or
SQL keywords (AND, OR, SELECT, INSERT, etc)
With many of the popular backends,
informa-tive error pages are displayed by default, which
can often give clues to the underlying SQL query
in use For example, asking for
instead of
could return a telltale error like this one:
It is evident from this response that the valuefor itemID is being used directly (without any val-idation) within an SQL query
PHP Code InjectionWhen user-defined inputs form the file pathparameters used to call include(), fopen() orother similar functions, there are several possi-bilities for exploitation The first, PHP code injec-tion, is based on manipulating the input to
include() to run your own PHP code The ond, path traversal, is based on manipulating theinput to include()or fopen()to display files orcreate an open proxy Note that both of thesebugs rely on the same basic problem and overlapsomewhat
sec-PHP code injection is similar to SQL injection,but involves native PHP code being injected bythe user rather than SQL This is made possiblewhen the code makes use of the include()func-tion The include() function will accept a filename or URI (if the appropriate wrapper isinstalled) and include the contents of theresource as part of the PHP program This is fre-quently used as a means of keeping libraries ofcode separate, and applications more modular,
mySQL error with query SELECT myitem FROM shop_item WHERE itemid=123’;:
You have an error in your SQL syntax near
‘’’ at line 1
http://example.com/items.php?itemID=123 http://example.com/items.php?itemID=123’
http://www.server.com/listing1.php?artid=
0;%20DROP%20TABLE%20Articles
SELECT ArticleContents FROM Articles
WHERE ArticleID = 0 OR ArticleID <> 0
1 <?php
2
3 // sqlinject.php
4 $ssql = ”SELECT ArticleContents FROM Articles WHERE
ArticleID = “ $_GET [ ‘artid’ ];
5 $conn = mysql_connect ( ‘127.0.0.1’ , ‘dbuser’ , ‘dbpw’ );
6 $res = mysql_query ( $ssql , $conn );
7 while ( $resarr = mysql_fetch_row ( $res )) {
8 echo “<span id=\”article\”>” $resarr [ ]
7 $conn = mysql_connect ( ‘127.0.0.1’ , ‘dbuser’ , ‘dbpw’ );
8 $res = mysql_query ( $ssql , $conn );
9 while ( $resarr = mysql_fetch_row ( $res )) {
10 echo “<span id=\”article\”>” $resarr [ ]
Trang 11calling include() to load needed functions at
runtime or ‘on demand’, but it’s also frequently
mis-used to include local text files, or worse,
remote data from a URI PHP code injection is
achieved by placing malicious PHP code inside a
resource which is run through include(), or
finding a way to have the include() call load
something unintended by the application
devel-oper A sample vulnerability is shown in Listing
3
A sample attack on that vulnerability might
look like the following:
Making a call to the above link would cause the
contents of www.hacker.com/phpinjection.phpto
be included into the program and executed
local-ly This page could output any malicious code the
attacker can conjure up
The primary strategy for defending against
code injection attacks is to use include()
appro-priately Having URI file wrappers enabled is
gen-erally a security liability and if your site does not
explicitly use them, they should be disabled If it
is necessary to have user manipulable variables
run through include(), ensure that they are
properly validated Listing 3 is patched in Listing
4
When trying to locate these vulnerabilities via
blackbox testing, the tester would attempt to
inject file and directory special characters (such
as and /) into variables and see if this elicits a
response from the application which might aid
an attack Imagine that a regular
(non-mali-cious) URL looks like this:
Let’s look at what we get if we change the
query string a little, as follows:
The response from the application might besome telltale warnings, like so:
This response indicates that the value of the
‘in’ variable is being used within an include()
call In this case, an attacker would be able tosubmit a request such as:
to open (include) any readable file
Path TraversalVery closely related to PHP code injection is pathtraversal Although Listing 4 protects againstPHP code injection, it applies no input validation
to the page GET variable, allowing the user toenter not just a file name but an absolute path.This can allow an attacker to view any file thatthe web server has permission to read If URIwrappers were enabled, it would also allow anattacker to use the site as an open proxy to view
http://example.com/main.php?in= / / /
/etc/passwd
Warning: main(./ /test.inc) [function.main]: failed to create stream:
No such file or directory in main.php on line 102
Warning: main() [function.main]: Failed opening ‘./ /test.inc’ for inclusion (include_path=’.:’) in main.php on line 102
4 if isset( $_GET [ ‘page’ ])
5 include( $_GET [ ‘page’ ]);
3 //phpcodeinjectpatched.php
4 if isset( $_GET [ ‘page’ ]) {
5 $fp = fopen ( $_GET [ ‘page’ ], ‘rb’ );
3 //pathtraversal.php
4 if isset( $_GET [ ‘page’ ]) {
5 $fp = fopen ( $_GET [ ‘page’ ], ‘rb’ );
Trang 12other resources on the web A sample
vulnera-bility is shown in Listing 5
A sample attack on that vulnerability might
look like the following:
Calling the above link might cause the contents
of /etc/passwd to be returned to the attacker —
obviously not what the script was supposed to
do! If URI wrappers were enabled, the following
attack could also be used:
This would cause the web server to source the
contents of the URI www.phparch.com and
return them to the attacker, effectively working
as an open proxy Oh, what we wouldn’t do for
our daily dose of PHP goodness!
The key to defending against path traversal
attacks is, once again, input validation Ideally,
all files that the script is serving can be
numeri-cally sequenced, requiring only a numeric input
of the file number from the user A patched
ver-sion of Listing 5 using this method is shown in
Listing 6
Alternatively, the page variable can be
stripped of all characters which may allow a user
to enter an absolute path or URI A patched
ver-sion of Listing 5 using this method is shown in
Listing 7
These vulnerabilities can often be located
through blackbox testing of the application The
tester would attempt to inject file and directory
special characters (such as and /) into variables
and see if this returns (or attempts to return)
arbitrary files Imagine that a regular
(non-mali-cious) URL looks like this:
To test for path traversal, we might use the
fol-lowing URL’s:
If the tester receives a ‘File not found’ or
‘Cannot open’ error, it may simply be a matter of
adjusting paths or increasing the amount of
tra-versal characters ( /) fopen() and include()
error messages are generally very informative indescribing the error, and can give the tester allthe information needed to correctly manipulatethis request
Trusted User Manipulable Values
A major problem with the web application ronment and the advanced tools used within it,
envi-of which PHP is only one, is the fact that theyhide the source of some inputs from the develop-
er For example, PHP will expose the contents of
a form field, GET variable or POST variable criminately as a variable with the same name asthe field or HTTP variable Developers come torely on this feature and can fail to considerwhether a trusted variable, such as the value of
indis-a product or nindis-ame of indis-a file, comes from indis-a sourcewhich cannot be manipulated by an attacker Theclassic example is hidden form fields used tocarry session-related variables, such as thename and value for products on an e-commercesite The developer is relying on the notion thatsince he has set these values, he will read themback in from the subsequent form, unchanged.But when a form is submitted, the contents ofthe form fields are simply passed to the resource
in the FORM tag’s ACTION attribute as either GET
or POST variables, as specified by the METHODattribute An attacker can then change the price
of products by making his own form carrying thedesired values, or manipulating GET/POST vari-
http://example.com/viewfile.php?cat=/etc
/motd http://example.com/viewfile.php?cat= /
/ / /etc/passwd http://example.com/viewfile.php?cat=users
3 //pathtraversalpatched1.php
4 if is_numeric ( $_GET [ ‘page’ ]) {
5 $fp = fopen ( ‘/var/www/files/file’ $_GET [ ‘page’ ]
3 //pathtraversalpatched2.php
4 if isset( $_GET [ ‘page’ ]) {
5 $fp = fopen ( stripfilename ( $_GET [ ‘page’ ]), ‘rb’ );
11 function stripfilename ( $filename ) {
12 $filename = str_replace ( ‘.’ , ‘’ , $filename );
13 return str_replace ( ‘/’ , ‘’ , $filename );
14 }
15
16 ?>
Listing 7
Trang 13ables manually A sample vulnerability is shown
in Listings 8 (the HTML form) and 9 (the form
handler)
A sample attack on that vulnerability might
look like the following:
Calling the link above allows an attacker to
successfully place an order, using a valid credit
card, but with a price of the attacker’s choosing,
in this case $1 The developer is presuming that
the only way his form handler will be accessed is
via Listing 8, where the price value is set by a
PHP variable Were POST being used rather than
GET, an attacker could construct an HTML
docu-ment, as shown in Listing 10, and place the order
for $1 by simply submitting the new form
Trusted variable vulnerabilities can be avoided
by setting session-related variables appropriately,
using sessions or cookies (although both of these
have some, albeit lesser, problems in their own
right) A preferable solution would be to always
reference the price from a database on the server
side and carry a productid variable in a PHP
ses-sion or browser cookie Both of the previous
vul-nerabilities are patched with Listings 11 and 12
The blackbox tester examines all available
source pages for evidence of HIDDEN or
dynami-cally-generated variables The tester saves a copy
of the form page locally and manipulates these
variables, loads the form page into a browser and
submits the modified request In many cases, the
tester may not be able to determine if the
modi-fied values have been accepted unless they are
displayed on a subsequent page (such as in the
Checkout page of a shopping-cart application.)
Weak AuthenticationDespite the widespread gospel that clear-textauthentication credentials are a cardinal sin andthat passwords should conform to minimum com-plexity rules, these fundamentals of secure pro-gramming are frequently not applied in the webapplication world HTTP includes two standardauthentication mechanisms: basic and digest.Both mechanisms operate as a series of HTTPexchanges with a demand for authenticationissued by the server in an HTTP header, followed
by a repeated request from the client, includingauthentication credentials in another HTTP header.The primary difference is that basic authenticationuses clear text and is simply base64 encoded,while digest is encrypted using a nonce (time sen-
3 <form action=”trustedvaluesformhandler.php” method=”get”>
4 <input type=”hidden” name=”price” value=” <?=$price?> ”>
5 Credit Card #:<input type=”text” size=”10” name=”cc”>
3 //trustedvaluesformhandler.php
4 if (!isset( $_GET [ ‘price’ ]) || !isset( $_GET [ ‘cc’ ]))
5 die;
6 mail ( “billing@server.com” , “New Bill” , “Bill card “
$_GET [ ‘cc’ ] “\nFor amount: \$”
3 <input type=”hidden” name=”price” value=”1”>
4 <input type=”hidden” name=”cc” value=”5353167819823”>
5 <input type=”submit” value=”Order Product”>
6 </form>
7 </html>
Listing 10
1 <?php 2
3 //trustedvaluesformhandlerpatched.php
4 session_start ();
5 if (!isset( $_SESSION [ ‘productid’ ]) || !isset( $_GET [ ‘cc’ ]))
6 die;
7 // Call me paranoid, but sanity check session variable
8 if (! isnumeric ( $_SESSION [ ‘productid’ ]))
9 die;
10 $ssql = ”SELECT Price FROM Products WHERE ProductID = “
$_SESSION [ ‘productid’ ];
11 $conn = mysql_connect ( ‘127.0.0.1’ , ‘dbuser’ , ‘dbpw’ );
12 $res = mysql_query ( $ssql , $conn );
13 $resarr = mysql_fetch_row ( $res );
14 mysql_close ( $conn );
15 mail ( “billing@server.com” , “New Bill” , “Bill card “
$_GET [ ‘cc’ ] “\nFor amount: \$” $resarr [ ]);
16 echo “Order placed\n” ;
17
18 ?>
Listing 12
1 <?php 2
10 <input type=”hidden” name=”price” value=” <?=$price?> ”>
11 Credit Card #:<input type=”text” size=”10” name=”cc”>
Trang 14sitive value) issued by the server as a key
Basic authentication can be set up easily by using
PHP’s header() function to issue the required
header The $_SERVER[‘PHP_AUTH_USER’] and
$_SERVER[‘PHP_AUTH_PW’] variables are created
by PHP when a request has included authentication
credentials This is, unfortunately, promoted by
many tutorials on PHP programming The main
alternative to basic HTTP authentication is to have
a custom solution where a session id or cookie is
issued to the client once it has successfully
authen-ticated – this token then being checked with each
subsequent request for a protected resource This
relies on the developer correctly enforcing
pass-word complexity rules and is vulnerable to replay
attacks A sample vulnerability is shown in Listing
13 (allowing a weak password to be set) and 14
(doing effectively clear-text authentication)
Lack of complexity rules can make you
vulnera-ble to brute force attacks, because with short and
common passwords little key space will need to be
exhausted before an attacker finds his way in
Brute force attacks most commonly work either
from a dictionary file of common words, or in an
incremental mode trying every possible string
Sometimes a hybrid of the two is used, attaching
short incremental suffixes and prefixes to
com-mon words Listing 15 is an example of an
incre-mental-mode brute-forcing tool
Basic HTTP authentication is vulnerable only to
third party attack, where an attacker is sniffing
or otherwise intercepting the site’s
communica-tion and extracting the clear text authenticacommunica-tion
credentials No sample attack is provided for
extracting clear text credentials
There is no patch, as such, for the use of basic
HTTP authentication The point was merely toillustrate that its use, without SSL or some otherform of encryption, is a security liability
Password complexity rules, however, can beapplied in a variety of ways PHP functions areavailable to utilise the CrackLib library to checkthe strength of passwords The strength is deter-mined by length, use of upper and lower caseand dictionary checks If CrackLib is not available
or you wish to enforce custom business rules forpassword strength, writing your own implemen-tation is simple Listing 13 is patched using acustom password strength test in Listing 16
To identify these vulnerabilities, the blackboxtester must first identify the authenticationmethod in use If basic HTTP authentication is
4 if ( $PHP_AUTH_USER != “user” || $PHP_AUTH_PW != ”pass” ) {
5 header ( ‘WWW-Authenticate: Basic realm=”server.com”’ );
28 echo “String ‘“ $str “‘ works as password\n” ;
29 if ( $ord_arr [ sizeof ( $ord_arr )- 1 ] == $num_chars ) {
44 for ( $i = sizeof ( $ord_arr )- 1 ; $i >= 0 ; $i —) {
45 if ( $ord_arr [ $i ] == $num_chars &&
Trang 15being used, the tester can attempt to
brute-force a valid login and password pair – in
most cases, account lockout restrictions are not
enforced
There are many tools available online to test the
strength of basic HTTP authentication One of the
more popular password cracking tools is Cain&Abel
– available from http://www.oxid.it/cain.html
Poorly-Applied Authentication
Authentication mechanisms can sometimes fail
to cover every access method for a resource and
restrict access accordingly The classic example
is a menu driven by permissions associated with
authentication credentials providing access to a
list of resources the user is allowed to view The
resources themselves, however, do not require
authentication credentials and rely on the notion
that they are hidden unless access to them is
provided via a menu This is security through
obscurity, and is a major flaw A recent
high-pro-file example of this problem is an Australian
Taxation Office site where a user provided
detailed credentials to authenticate their
identi-ty and were then allowed to view details
associ-ated with their Tax File Number The page
pro-viding this access simply accepted the Tax File
Number as a GET variable, such as:
An attacker could simply plug in another TFN to
view its details:
A sample vulnerability is shown in Listings 17
(the menu) and 18 (the resource)
A sample attack on that vulnerability might
look like the following:
By accessing the above URI, an attacker can
bypass the authentication applied by Listing 17,
and go straight to the resource (Listing 18) it was
designed to provide access to
The best strategy to avoid these kinds of
prob-lems is to apply authentication at every individual
resource, so it can never be bypassed In the
pro-duction world, your authentication would never be
as simple as the ‘if’ test used in Listing 17, so a
con-venient technique is to create an authentication
class and include it with every resource These nerabilities are patched by Listings 19 (the authen-tication class) and 20 (the protected resource)
vul-Authentication and logic flaws in applicationscan sometimes be located via blackbox testingmethods The tester, using valid credentials,authenticates to the application and interacts as anormal user At every point beyond the initialauthentication routine, the tester locates any GETand POST variables, manipulates them using validdata, and examines the output Imagine that a
5 if ( $_GET [ ‘un’ ] == ‘user’ && $_GET [ ‘pw’ ] == ‘pass’ ) {
6 echo “<form>\n”
7 “<input type=\”button\” value=\”Resource 1\”
8 onClick=\”location.replace (‘poorauthresource.php?res=1’);\”>\n<br>\n”
9 “<input type=\”button\” value=\”Resource 2\”
Trang 16regular (non-malicious) URI looks like this:
A blackbox tester might try the following:
In the above example, the user might expect to
receive an ‘unauthorized’ error message when
attempting to submit an alternate ‘startpg’
vari-able If authentication has only been applied to the
application portal page (and subsequent requests
are not being re-authenticated) an attacker may
be able to request arbitrary start pages
Cross-Site Scripting
Many sites, such as message forums, allow a user
to enter content and post it to the site This is
usu-ally handled using an SQL database to store
mes-sages and PHP code to add and render posts on
demand If the contents of these messages are not
stripped for HTML tags and Javascript code, an
attacker can effectively inject client-side scripts
which will be run under the security context of the
message forum This vulnerability, however, is not
limited to message forums Any site where the
contents of user-defined variables such as
GET/POST variables, HTTP headers or cookies will
form part of the page returned can be vulnerable
to cross-site scripting, or XSS As an example of
XSS outside of a classic message forum example,
take the following URI:
In this case, the q variable would be set to
“<script>alert(document.cookie);</script>”
This will run the Javascript code
alert(docu-ment.cookie); within the security context the
user has set for ninemsn.com.au This will
expose the user’s cookie for the site On a
mes-sage board this could well include a session id
token which could be replayed to hijack their
ses-sion This could then be logged to a remote
cap-ture application using Javascript code such as:
A sample vulnerability is shown in Listing 21 Asample attack on that vulnerability might looklike the following:
This would cause the “query” GET variable tocontain:
Accessing the above URL would causewww.porn.com to be opened in a new window
100 times by a Javascript-enabled browser
Defending against XSS is not just simply a matter
of stripping special characters as with SQL tion Not accepting certain input may limit the func-
injec-<script>for (i=0;i<100;i++;) { window.open(‘http://www.porn.com/’);
8 function auth ( $un , $pw ) {
9 if ( $un == ‘user’ && $pw == ‘pass’ )
10 $this -> isvalid = true ;
Trang 17tionality of the site A better strategy is to parse
user-defined inputs after they have been used by
the PHP script, but before being returned as part of
the response, to replace ‘<’ and ‘>’ characters with
‘<’ and ‘>’ respectively This will prevent
‘<script>’ or other tags from being injected Listing
21 is patched using this technique in Listing 22
Cross-site scripting vulnerabilities are generally
quite easy to locate using blackbox testing
meth-ods The tester examines all GET and POST
vari-ables to determine if any of these values are being
returned within page outputs In the example
below, the tester can safely assume that the
con-tents of the Title variable will be used somewhere
within the returned page Imagine that a regular
(non-malicious) URI looks like this:
The tester inserts HTML special characters (<>)
into the Title variable and resubmits the request
If the injected HTML can be found within the
returned page, then this application is vulnerable
to cross-site scripting In this case, if the Title
value is being used directly between <title> and
</title> tags, without filtering of <> characters,
additional HTML and Javascript can be injected
into the returned page
Environment Information Disclosure
By default, PHP displays all warnings and errors
These frequently contain verbose information
per-taining to the operating environment, such as file
paths, database credentials and configuration
details A sample vulnerability is shown in Listing 23
A sample attack on that vulnerability mightlook like the following:
If an attacker runs the above URI when thedatabase server is down and/mnt/data/file1.txt is not available, the fol-lowing error (with HTML removed) will be given
by PHP:
This discloses both the name of the databaseserver and the path from which the script is read-ing files Although this does not open the site toany specific attack, it is not good security prac-tice to disclose this kind of information
The best strategy to prevent this is to disableerror reporting on production sites and reserve itfor development use This is best implemented
in php.ini but is illustrated using the
error_reporting()function in Listing 24
The blackbox tester inserts special charactersinto all identified GET and POST variables in anattempt to elicit exception conditions from theapplication Errors from failed include(),
popen(), fopen() and DB-related calls can beextremely informative and may assist the tester
in identifying further vulnerabilities Imaginethat a regular (non-malicious) URI looks like this:
Let’s look at what we get if we change thequery string a little, as follows:
Warning: MySQL Connection Failed:
Unknown MySQL Server Host er.com’ (2) in C:\PHP\phparch\env.php on line 2
‘dbserver.serv-Warning: fopen(“/mnt/data/file1.txt”,
“rb”) - No such file or directory in C:\PHP\phparch\env.php on line 3 http://www.server.com/listing23.php
4 $q = str_replace ( ‘<’ , ‘<’ , $_GET [ ‘query’ ]);
5 $q = str_replace ( ‘>’ , ‘>’ , $_GET [ ‘query’ ]);
6 echo “You searched for “ $q ;
Trang 18The server’s response could be as follows:
Secure Coding Methodology
The key to coding secure web applications in PHP
is to be aware of the potential flaws that your code
may be vulnerable to, and be attentive in
prevent-ing these flaws throughout the entire
develop-ment process Too often security is an
after-thought or added feature The most secure code
is written with security in mind from the word ‘go’
Testing Methodology
The blackbox testing method is where a security
professional attempts to expose flaws in an
application The term ‘blackbox’ refers to the
closed-source or proprietary application, and the
process of manipulating known inputs and
ana-lyzing outputs from the application
In blackbox testing PHP code, the tester
exam-ines the application and identifies all of the
expected GET and POST variables, including
hid-den and dynamically-generated variables These
variables are then manipulated using potentially
“unexpected” values – such as special characters
and type-mismatched or oversized requests In
most cases, the PHP applications’ expected inputs
can be identified by reading all available HTML
source pages, and/or capturing and decoding
valid requests
As an example, examine the following URI:
In the above example, the GET variables that
should be manipulated and tested are ID, title
and lang
As another example, examine the form in
Listing 25 Here, the POST variables to be
test-ed are ‘sid’, ‘listid’ and ‘usermail’
The tester inserts special characters into each
of these inputs, and submits the request Output
is analyzed to determine if the application
han-dled the input correctly, or if some unexpected
error has occurred
Manipulated POST variables can be submitted
using a command-line tool such as lynx or curl,
or a copy of the form input page can be saved
and modified locally Manipulated GET variablescan be submitted using a regular browser
Unexpected behavior may take the form ofhalf-loaded or blank pages, or a redirect to afront page If the application displays an errormessage, the tester can determine if it is vulner-able to any of the common PHP coding errorsdetailed in this article
ConclusionWeb applications are, in security terms, a differentball game from conventional applications Thecommunication protocols, server-side applicationcode and client-side presentation code combine toform a development environment in which bugscan make use of problems in various components
of the technology simultaneously To compoundthis problem, web technology was originallydesigned to handle the public dissemination ofmarkup documents, not the development ofsecure applications This is slowly being rectified,but the developer must remain astute to securityconcerns if he is to produce secure applications.Hopefully what has been outlined above can assist
in the creation of more secure web applications
Warning: MySQL Connection Failed: Unknown
MySQL Server Host ‘sql.example.com’ (2)
in /www.example.com/cgi-bin/index.php on
line 45
Click HERE To Discuss This Article http://forums.phparch.com/44
David works as a document imaging and OCR programmer for a small Australian company He spends his spare time writing PHP code and studying environmental science
1 <form action=”subscribe.php” method=”POST”>
2 <input type=”hidden” name=”sid” value=”666”>
3 <input type=”hidden” name=”listid” value=”1024”>
4 Email:<input type=”text” size=”100” name=”usermail”>
5 <input type=”submit” value=”subscribe”>
6 </form>
Listing 25
Trang 19What is a bug?
It all started in 1945 at Harvard University, while
testing the Mark II Aiken Relay Calculator for
mal-function A moth was found trapped between two
electrical relays Operators removed the moth and
entered the log entry “First actual case of bug being
found.” They said that they had “debugged” the
machine and the term “debugging a computer
pro-gram” was introduced
Anyone who has ever used any kind of software
is familiar with the term “bug” But before we
pro-ceed further with our story, we should make it
clear what we mean by this term Classic definition
of the bug is that it is an error in software code that
causes the program to malfunction We must be
careful with this, however, because it is very
close-ly related to the requirements of our project We
can’t tell that something is not working properly
unless we know the desired behavior Some users
for example, can interpret lack of certain
function-ality as a bug Because of this thin line between
bugs and functionality, it is a good practice to do
request tracking along with the bug tracking
process, as we will see later in the text We will
introduce a new term (issue), to describe both
bugs and feature requests
The layman would say that bugs in software are
only the result of programmer carelessness, but
anyone who has ever worked on a large software
project knows that is not always true Sometimes
projects are so complicated that a minor change in
one module could produce an unexpected disaster
where it is least expected There are many softwaretechniques that model how to take your software’squality to a higher level, but that is way beyond thescope of this article Here, we will try to concentrate
on how to keep track of the bugs (and requests) inyour project We will also learn how to organize thedevelopment process so that most of the malfunc-tions in the software code are detected before finalrelease and not by your customers
Life cycle of a bugThe first thing you will always hear when discussingsoftware testing and quality assurance is that theperson who implements the code should not be theperson who is testing it There are few reasons forthis statement The first is that the person who isactually writing the code has his own mindset andcannot see the certain flaws in the design even if helooks at it for a very long time Another person, who
is actually only looking at the code’s behaviour, caneasily spot things that the original writer missed.The second argument is rather psychological; thetester should act destructively against the code,which is very hard to do with your own work Wewon’t go deeper into details about software testing,
REQUIREMENTS
Trang 20that could be the topic of some future article, but
this story is very important in establishing roles in
our bug management process Three roles are
nec-essary for successful bug tracking:
• Developer – person who actually writes
code and fixes bugs
• Tester (QA staff) – person who tests the
code and writes bug reports This
per-son, as we will see later, also verifies
that the certain bug is fixed
• Project manager – person who assigns
certain properties to bugs (like we are
going to see in the next section) and
assigns them to developers for fixing
The bug life cycle would look like this: quality
assurance person finds the bug and submits the
bug report Project manager reviews every bug
report If he finds that the bug is valid, he assigns
some attributes to the bug and assigns it to the
appropriate developer The developer than fixes
the bug and assigns it to QA for verification QA
repeats the tests on a requirement and the bug
gets closed or reopened depending on the
prob-lem’s presence in the system
Anatomy of a bug
Now is a good time to see what bug attributes we
need in order to successfully track our bugs
Components
Components help us to partition and
decou-ple the whole project imdecou-plementation and
also make it easier to find who is in charge of
the particular code base You can divide the
project vertically by encapsulating all the
code that is solving the same problem
domain (business logic) into a component
(financial classes, address book and so on) or
horizontally by making components of the
particular application layers Or you could do
both There are no strict rules You should find
the scheme that best suits your needs For
example, we could introduce the followingcomponents for tracking bugs in the project:
• Presentation layer – all bugs that arerelated to the user interface such asHTML code, client side code (JavaScript),etc
• Business layer – malfunctions in ness scripts and classes
busi-• Data access layer – bugs in Data Objectclasses, SQL queries, database wrappersand so on
So when QA reports the bug, the componentattribute should address a certain projectsubsystem in order to make it easier for theproject manager to assign it later
Severity
Severity is another important bug attributethat tells us how serious our bug is Somecommon values are:
• Stopper – This kind of bug is stoppingeither the client in software usage orfurther development (e.g crashes, bugs
in database wrapper that disables thewhole project from connecting to data-base, etc.)
• Critical – serious bug that causes heavyprogram malfunctions (e.g bug in acore library that causes other subsys-tems to act unstable)
• Major – ‘major’ bugs make our softwareunreliable and can cause serious dam-age to us or our clients (e.g bad datacalculation in some cases that makesthe data unreliable)
• Normal – bugs that are not serious butare unpleasant to our clients (e.g bro-ken links in pages)
• Minor – small bugs that are not crucialfor core program execution, but should
be fixed in order to make better quality
of the product (e.g bad label for a formfield)
QA submit bug report
Project manager reviews the bug report and assigns it if necessary
Bug gets closed Developer fixes the bug
QA verifies that bug is fixed
Bug Life Cycle
Trang 21• Enhancement – this is not a real bug,
but a request for a new feature
Priority
Priority is the attribute that is assigned by
the project manager and helps developers
organize their tasks It’s a common practice
to have five priority levels and the bugs with
higher priorities should be fixed first
Status
Status is directly connected with bug life
cycle It tells us in what stage of the bug
cycle our bug currently resides Some
com-monly used values are:
• New – bug has been reported, but not
yet reviewed
• Assigned – bug has been reviewed by
project manager and assigned to
par-ticular developer
• Fixed – bug has been fixed by
develop-ment team and has to be reviewed by
QA
• Verified (Closed) – QA has verified that
the bug has been fixed
• Reopened – QA have run tests against
the bug that was marked as fixed, and
some problems still remain, so it is sent
back to development for further repair
• Duplicated – this bug has already been
reported
• Won’t fix – these are so called “known
bugs” that are not going to be fixed in
this development cycle, mostly because
of a great risk involved in fixing the bug
or the required time for that job
• Invalid – Problem that is reported is not
a bug
• Works for me – Problem that has been
reported couldn’t be reproduced so it is
put in the repository for later analysis
Subject
Every bug report should have a subject
attribute for easier browsing and querying
Milestone
The software development process is often
divided into smaller iterations called
mile-stones We should keep track of the project
milestone that a bug has been reported to
and for which it has to be fixed We can
demonstrate this by imagining that we have
delivered version 1.2 of the project to the
client and continued to work on the next
release (1.3) We need a way to separate
bugs that are reported to these two versionsbecause it is often a completely differentcode base
Comments
Comments are a very important and usefulattribute of the bug We should always allowour team members to enter an unlimitednumber of comments to the bug Doing sowill allow us to keep track of the communi-cation and history of the bug An initial com-ment for the bug could be a description ofthe problem that QA (or the client) hasfound in our software
Attachment
In some development organizations a verylimited number of developers can commitchanges to the code repository In this case,the bug’s attachment attribute is used to addpatches of code that fixes bugs Attachmentcan also be used for many other purposeslike screen shots, test cases and all materialthat helps to document the bug properly
The bug attributes described above are just asmall subset of commonly used attributes in theproject You should, of course, adjust theseattributes to the specifics of your individual proj-ect and process Some additional attributes thatcan be useful to describe the bug are web brows-
er (particularly interesting for web applicationdevelopment), URL of the page in which bugappears, operating system (for platform specificproblems) and many, many more
Now that we know how to define our bugs, weshould mention the process of collecting newfeature requests for our project This process issometimes very closely related to the bug man-agement process When we were talking aboutthe bug status attribute earlier, we said thatspecial status could be introduced to separatethe bug from a request for enhancement (RFE).Basically a feature request could have a verysimilar structure to the bug report and, sincemany bug tracking tools support this functional-ity, it is natural (to some point) to keep track ofenhancement requests in the same repository
as bugs
Bug reports
OK, we have now discussed some basic tion about the structure and life cycle of bugs.This information, however, is not enough for asuccessful bug tracking process In order tomake your process efficient, the QA department
informa-F
Trang 22needs to supply useful bug reports to the
devel-opment team The more information developers
have to work on, the sooner the bug will be
traced and fixed
When submitting a bug report, there are a few
things to keep in mind First things first, a basic
rule in any bug tracking process is to always try
to repeat the bug before submitting the report
This is very important because some bugs occur
only under very specific circumstances and
envi-ronment settings You must be sure that you
know the specific environment variables and
steps that lead to the malfunction that you are
going to submit Of course, some bugs are
almost impossible to trace, but even then you
should make it easier for the developer by
point-ing him to all of the thpoint-ings that failed to repeat
it That way we can save some time by not
dupli-cating effort, and it gives certain clues to the
development team about what could be the
problem
Let’s take a look now at what makes a good
report We can start by showing one bad example
and go through to see how to make it better Let’s
say that a report like this is submitted:
When a developer gets a message like this, the
only thing he knows is that some problem exists in
the process of adding a new customer He can’t
begin fixing the problem without actually
contact-ing the person that submitted this report because
he hasn’t a clue where to start So, the usual
ques-tions end up being asked: What error was
dis-played? What data did you submit? On what page
did the error occur? In 99% of the cases, the
sub-mitter doesn’t remember all the details because it
was a “century” ago, and we’re trapped in an
infi-nite loop But, if we use another approach and
submit a report like this, everything could be very
• Subject: Add a new customer
• Brief description: submitting of a new customer
with the regular data failed
• Steps:
Log in
Click the link to the address book
Click” Add new customer” button Enter the data (see “data” section) Click “Save changes” button
• Data:
Name: Dejan Bosanac Email: chubrilo@yahoo.com Title: Software developer All other fields: empty (default)
• Expected results: The data is submitted to the database and “view” page for the customer is displayed
• Actual results: Error page with a message “Error executing SQL query: phone_number field cannot
as the comment or the attachment to the bug Wecan now summarize what a good report shouldconsist of:
1 Brief description of the problem
2 Environment under which problemoccurs
3 Steps needed to reproduce the problem
4 Specific inputs that caused the problem
5 pected and actual results
6 Summary of what the problem could be
Of course, details of the each step depend onwhat the specific problem is For example, if thebug is found during unit testing, input datashould be the test case that caused the bug (youcan attach the test class that caused the bug, ifyou want) Or, in another extreme case, if it is avisual (cosmetic) bug, all you have to submit ishow to enter the specific page and what is wrong(environment-specific data is always useful) Ageneral rule is that the more complex the prob-lem is, the more information the developer isgoing to need
Bug tracking and development cyclesFor successful bug and request tracking there are
a few more issues that you must keep in mind.The development cycle plays a key role in how theprocess is handled It can be divided into threesections:
• Development - implementation of thesystem functionality, resulting in huge
When I inserted some customer data and
clicked on the “Save changes” button, an
error page was displayed.
Trang 23changes to the codeset
• Code freeze – software has entered beta
testing phase and code is usually frozen
• Release planning – preparations for the
next project release are under way
In order to have an efficient development
process, we will look at how to use the
bug-track-ing system in each of these phases
In the development phase, good practice dictates
that developers create test cases at the same time
they write the code A test case is code that is
writ-ten to test certain functionality and to report the
error if it is found This way, we will actually have
the confirmation that the software is doing the job
for which it is meant These test cases are
normal-ly grouped in a test suite that is executed regularnormal-ly
(preferably every night) This type of testing is
called regression testing We will not get into this in
this article, but it is important to mention it because
it affects the bug tracking process itself Some
authors say that in this stage of development we
should not use a bug-tracking system as a
reposi-tory for bug issues, as our test suite would keep this
information for us The would advise, though, to
use a bug-tracking system for storing features that
will be introduced later in the process
While this may true to some point, some errors
cannot be detected with regression testing Defects
that are found during code reviews, user
experi-ence issues, and visual defects are just some of the
bugs that we must handle outside of a test suite
So, my opinion is that in this phase we shouldn’t
really submit duplicate reports to the system, but
all the other issues that are reported during testing
should be stored If we don’t do this, we can
easi-ly forget about them until it is too late Of course, if
you don’t have automated testing introduced into
your process, you should keep all the issues this
way Feature requests are always good to be stored
in the system for later analysis
In the code freeze (beta testing) phase, the code
is usually frozen and no immediate changes can
be done Now, we should keep track of all found
malfunctions so that they can be fixed before the
final release It is also convenient to keep track of
a user’s feature requests (usually beta testers are
potential future users) At this point, we should
introduce a request “grade” In other words, we
should keep track of how many requests we have
for each feature, so we can easily separate the
must-have features from the eccentric ones
When you are ready to start planning the next
release, you could use the information stored in
your tracking system According to the request
grade you can decide what features will become
part of the next release One more thing is tant in this stage: you must estimate the effortneeded to implement certain features For exam-ple, if some feature is a must-have feature and itrequires minor code changes, then it should defi-nitely be planned for the next release In the casewhere the feature implementation requires hugecode refactoring and involves great risk, youshould think of delaying those features to somefuture release
impor-When you have specifications for future
releas-es, you should build the test cases for them andmark those requests as closed (remove them fromthe system)
Bug tracking tools
To start implementing organized bug management
in your organization, you merely need concretebug-tracking software You could use a well-definedsheet in Excel-like software You will soon see, how-ever, that it would be much more efficient if youhad just a little more Many companies decide tobuild their own solutions, often seriously underesti-mating the effort for such a task Many start with noclear idea of what they really want or need, andstart coding a solution with minimal requirements.Soon after, they realize that maintenance andimprovements to the solution are not cost effective
by any means, and that costs of later porting tosome commercial solution are much higher then itwould have be in the start Even if you have a smallbudget, it is not really hard to find a free solution intoday’s open source software initiative Many ofthese solutions will save you enormous time andmanpower compared to building your own solution.That way, your developers can focus on buildingthe project that needs the bug tracking process andnot the particular tool itself
So, let’s start talking about what the tracking tool needs to provide you
defect-How to choose the right tool for you?
Before starting your search for a bug-trackingtool, you should have a clear vision of your bugtracking process so you can choose the tool thatwill have all the necessary requirements to meetyour needs Let’s divide the requirements into twobasic groups: business requirements and techni-cal requirements
Business requirementsFirst of all, you should fit the tool into your currentcompany profile and budget There are various sys-tems on the market with a wide price range, so youshould start by positioning yourself into a group
F
Trang 24that you can currently afford If your budget is
small, don’t worry, there are many very nice
open-source solutions There are also companies that
allow you to outsource this service to them for a
reasonable amount
Second, you should know who the users of the
bug management system will be, and if they have
any specific needs You will also need to be aware
of how many users will be using the system, as
well as their locations The price of the bug
man-agement tool is often related to this information
You can divide users into two large groups
Internal users
• QA staff will submit and query reports to
find bugs that need to be verified
• Developers will query reports to find
assigned tasks
• Project manager will query reports to
find unassigned bugs, and also run
met-rics on the data
External users
• Customers
• Clients
• Beta Testers
External users may like to submit
enhance-ment requests or bugs, and see the progress and
status of certain issues In this case, you will
probably be searching for a tool that can be
exposed to the web for external (and, of course,
internal) users This leads us to the question of
security Does the potential tool allow the
cre-ation of groups of users, as well as the
separa-tion of their privileges on acsepara-tions and data? We
might want to only allow external users to query
a small subset of all issues (for example, only
those that they have entered), and allow them
only to submit new reports, but not allow them to
modify existing data We could, of course, enable
only some groups to submit reports, but I think
that it would be better to allow all users to
sub-mit, as fewer bugs will be missed that way We
could also expect that only project management
staff could change details such as severity and
priority All of these decisions are up to you
Usability of the system is another important
parameter Does the potential tool define the bug
workflow that you need? Could it be configured?
Does the bug submission form have all of the
attributes that you need? Could it be configured?
It is very important for the tool to be easy to use,
as that will minimize the resistance to the tool by
team members that may jeopardize the whole
process You should also consider whether the tool
supports various methods of notification when abug status changes Does the software sendemail, SMS messages, or have any otheradvanced techniques for notification You maywant the project manager to be immediately noti-fied when a new critical bug report arrives, or youcould enable your customers to be alerted when acertain bug is fixed
Administration concerns are the last issue that
we will mention for the business requirements Weshould know if we have someone who has skillsthat are needed for successful deployment, con-figuration, and maintenance of the system andhow much time it is going to take aside from theirregular duties If this is a problem, then employinganother person for this task must be considered.The administration of the bug management tool isusually the responsibility of project andnetwork/database administrators
Technical requirementsTechnical requirements for defect tracking soft-ware are basically the same as for all other soft-ware products
• Reliability – software is stable and takescare of data consistency
• Robustness – software behaves well inextreme conditions and large data vol-umes
• Programmability – software has an cation programming interface (API)through which it can be extended toyour particular needs
appli-• Security – software gives needed
securi-ty for the data and has no securisecuri-ty flawsthat can be easily exploited
• Supportability – software vendor givesfair technical support for their product
• Scalability – software is adaptable toyour particular needs
These are just basic technical concerns Youshould also consider your current environmentand skills For example, does the product supportdatabase servers that you are comfortable with(MySQL, Sybase, Oracle, etc.)? Does the servercode (in client/server and web-based solutions)suit your current development environment(Linux, Windows 2000, …), or will you need to pre-pare a new server for it? There are many factors
to consider when choosing the perfect solution
Just one tip for the end, you should actually tryevery solution that seems to suit, since youwon’t necessarily find the flaws just by readingthe product specification
Trang 25Some popular solutions
As I said before many software packages are built
for this specific need We will mention two
com-mon ones - the further hunt is up to you
• Bugzilla
( http://www.mozilla.org/projects/bugzilla/ ) –
this product has its genesis in the
open-source Mozilla web browser It is written in
Perl to replace an old bug tracking system
used internally for Netscape
Communications It quickly became the
de-facto standard in the open source
commu-nity, so you can see it in action on many
projects on the web Unix-like environments
are natural for this software, and it is very
well integrated with MySQL (but that’s the
only database server that is currently
sup-ported) The source code comes under a
mix of various licence policies that include
the Netscape Public License (NPL), the
Mozilla Public License (MPL), the GNU
General Public License (GPL) and the GNU
Lesser General Public License (LGPL) Some
features worthy of note:
– Integrated, product-based granular
security schema
– Inter-bug dependencies and
dependen-cy graphing
– Advanced reporting capabilities
– A robust, stable RDBMS back-end
– Extensive configurability
– A very understood and
well-thought-out natural bug resolution
protocol
– Email, XML, console, and HTTP APIs
– Available integration with automated
software configuration management
systems, including Perforce and CVS
(through the Bugzilla email interface
and checkin/checkout scripts)
There are also some drawbacks that will
be addressed in the future:
– Reliance on only single database server
(MySQL)
– Rough user interface
– Spartan email notification templates
– Little report configurability
– Some unsupported bug statuses
– Little support for internationalisation
– Dependence on some non-standard
libraries
• Elementool ( http://elementool.com ) - It is possible these days to outsource your bug tracking to some other company It is very convenient in situations when you don’t have,
or can’t afford, more time and resources for the solution All you need is a few minutes to set-up your account using your web browser, and you are ready to start Also, this is an ideal solution for one-off projects because you can cancel your account at any time with no obligations With this approach you don’t have any concerns regarding installing and updating your software, since you will always have the latest version ready for use.
Their basic free package includes:
– 200 issue storage capacity – Unlimited number of users – Mail notifications
– Downloadable database for your own backup
For extra features like reports, history trail, customisable forms and so on, you must reg- ister for an advanced, commercial package.
These are just representatives of two
approach-es, you should really spend some more time tofind a perfect solution for your needs
Closing wordThe aim of every professional software package is
a satisfied customer If you have an organizedprocess for tracking bugs and feature requests inyour project, you can be sure that less bugs will bedetected by customers, and that the time cycleneeded to fix those bugs (and track down newrequirements) will be noticeably shorter There aremany tools available on the market that couldhelp you organize your defects and requirements,but, before you start tracking them, be sure thatyou know what you need Bug tracking is closelyrelated to quality assurance issues and teamorganization, so it is important to start from there.Just try it; it’s easier than it sounds
F
Click HERE To Discuss This Article http://forums.phparch.com/45
Dejan Bosanac works as a fulltime software developer for DNS Europe Ltd ( http://www.dnseurope.net ) on the Billing software system for ISP's In his spare time he also serves as a Lead Engineer at Noumenaut Software( http://www.noumenaut.com ) on the online jour- naling project He holds a Bachelor degree in Computer Science and currently is on the master studies in the same field.
Trang 27Although most web applications do not
require highly advanced database servers,
some of these servers provide more
advanced features – such as subqueries,
referen-tial integrity, transaction handling, and support for
stored procedures and triggers – which can make
a developer’s life far easier We will examine
these aforementioned features from a higher
level, giving examples of their use and usefulness,
as well as showing how some of them can be
sim-ulated at a low level within PHP
Perhaps you have heard of some of these
fea-tures, and maybe even used some of them This
article’s intent is to lower the bar for the
uninitiat-ed, and hopefully show you a right tool or two for
the job I mean, there is no sense trying to
devel-op a semi-usable transaction handling system in
PHP (which would be a difficult task indeed), when
you could just use a database with transaction
support built-in, right?
As much as possible, I’ll try to avoid database
specific code To avoid presenting
database-spe-cific PHP examples, I am going to use the PEAR DB
class PEAR (the PHP Extension and Application
Repository) is a free online PHP software
reposito-ry, and can be found at http://pear.php.net PEAR
is usually installed automatically when you install
PHP using common install packages In all
exam-ples, we will assume that we are already
connect-ed to a database server, and that we already have
a database connection handle which we are going
to call $dbh There will also be no error messages
Suppose we have two small tables, one taining data about our customers, and the othercontaining their addresses (we might expect acustomer to have more than one address).These tables are going to contain a very smallnumber of columns, and we will avoid specifyingspecific data types
con-Here are the table structures we’ll work with:
continued
CUSTOMER table:
CUSTOMER_ID FIRST_NAME LAST_NAME GENDER ADDITIONAL_INFO LAST_CHANGE
REQUIREMENTS
Databases have ceased to be a mystery
Designing and setting up databases and
data-base-driven applications is no longer a terribly
complicated task handled successfully only by
specialists and technicians Behind almost
every site that consists of more than a product
brochure is some kind of database from which
information is retrieved and presented
Trang 28It may be apparent that CUSTOMER_ID is
going to be our customer’s unique identification
number, as well as that table’s primary key
Other information that we will store about the
customer includes first and last name, gender,
and any desired additional info The last column
in the CUSTOMER table represents the date of
the last change made to a specific customer’s
information
The ADDRESS table can hold more than one
address for a single customer The unique
identi-fier and primary key for each address is stored in
a column named ADDRESS_ID This table must
also contain a reference to the appropriate
cus-tomer, and this is found in the CUSTOMER_ID
col-umn Specific address data is also stored,
includ-ing the street, city, postal code and country
columns, while the last column again holds
infor-mation about when the specific record last
changed
Subqueries
You can think of subqueries (or sub-SELECTs) as
SELECTs within other SELECTs A simple example
could look like:
Let’s look at a demonstration of the
impor-tance and use of subqueries Consider that from
time to time we want to remove customers who
do not have any addresses in our database To do
that without subqueries would require a number
of steps We would need to browse the
CUS-TOMER table record-by-record checking for
matching records in the ADDRESS table, deleting
the customers with none An example of doing
this with PHP is shown in Listing 1
Using a subquery, we could do all of this in one
step with the following statement:
As you can see, the subquery will perform asmall join on CUSTOMER and ADDRESS If thesubquery doesn’t return a row for a particularcustomer, it means that there are no addresses
in the ADDRESS table, and the customer can bedeleted What a job done in only one statement!The statement could also have been writtenusing IN operator like
DELETE FROM CUSTOMER WHERE NOT EXISTS
(SELECT CUSTOMER_ID FROM ADDRESS
WHERE CUSTOMER.CUSTOMER_ID = ADDRESS.CUSTOMER_ID)
SELECT something
FROM table_1
WHERE something IN (
SELECT something_else FROM table_2 WHERE something_else LIKE
5 $query_customers = “SELECT * FROM CUSTOMER” ; 6
7 // SQL statements are not complete - we will add parameters later
8 $query_check_address = “SELECT COUNT(*)
28 // Get number of addresses
29 $count = $row [ ‘CNT_ADDRESS’ ];
36 } 37
38 } 39
40 ?>
Listing 1
Trang 29This is a different approach to doing the same
job, but returns and checks more data for each
customer, which is not recommended when the
tables involved store a large amount of data In
such cases, EXISTS is a more suitable operator
If your applications use very complex SQL
state-ments to retrieve data, you can also simplify
them, and avoid joining too many related tables,
by using subqueries to retrieve single data
col-umn from related tables Note the following two
statements, which both return the same result:
In both cases, the customer’s ID and count of
related addresses is returned; however, in the first
statement we had to group data using the GROUP
BY clause, which is in most cases a slow operation
on large tables In the second statement, we
exe-cuted small and quick subquery (it is quick
because it retrieves only related data from the
ADDRESS table for each customer and counts it
using the table’s primary keys) thereby avoiding
joining and grouping
Although, on first sight, the second statement
would now look more complex than the first one,
think what would it look like if we had to join and
group more than two tables with many fields –
there would appear many field names in the
WHERE and GROUP BY clauses, and the SELECT
list would look much more complicated Field
name conflicts could also appear, and we would
be forced to assign the table name to each field
which appears more than once We should also
mention that all field names in a subquery are
local to that statement, and we do not need to
worry about conflicts with field names in the
main statement
If your statements are complex, the use of queries can often help with their simplification.This is not to say that there are not good reasons
sub-to use each of these other methods Depending
on the SQL statement’s complexity, the number ofjoined tables, and the amount of data processed,each method will act differently
Views
A view is a virtual table which does not physicallyexist It is defined as a query on one or more tablesand stored in the database definition as an SQLstatement You can do any kind of SELECT from aview, and use it in any SQL statement just as youwould any physical table Views can sometimes beupdated and deleted from, but whether a view isupdateable or not depends on the complexity of itsSQL definition and join conditions Views can becreated, altered, or dropped just like regular tables.Let’s return to our problem of counting a cus-tomer’s addresses from table ADDRESS Instead
of doing a subquery or creating a temporary table
to hold the counts of all addresses for each tomer we could simply create a view like this one:
cus-We have defined a virtual table named TOMER_ADDRESS_COUNT, which contains onerow for each customer with his addresses counted
CUS-in field NO_OF_ADDRESSES Now we can selectdata from the view by issuing a statement like
We will get a set of rows containing TOMER_ID and NO_OF_ADDRESSES for eachcustomer, just like we did with the previous SQLstatements that used subqueries or joins Havingthis view defined, we could now repeat ouraddress count check from Listing 1, avoiding the
CUS-$query_check_address SQL statement Betterthan that, our main query can be changed so that
it returns only customers with no addresses:
SELECT * FROM CUSTOMER, CUSTOMER_ADDRESS_COUNT WHERE CUSTOMER.CUSTOMER_ID =
CUSTOMER_ADDRESS_COUNT.CUSTOMER_ID AND NO_OF_ADDRESSES = 0
SELECT * FROM CUSTOMER_ADDRESSES_COUNT
CREATE VIEW CUSTOMER_ADDRESS_COUNT AS SELECT
CUSTOMER_ID, COUNT (*) AS
NO_OF_ADDRESSES FROM ADDRESS
GROUP BY CUSTOMER_ID
SELECT
CUSTOMER.CUSTOMER_ID
COUNT (ADDRESS.*) AS NO_OF_ADDRESSES
FROM CUSTOMER, ADDRESS
WHERE CUSTOMER.CUSTOMER_ID =
ADDRESS.CUSTOMER_ID GROUP BY CUSTOMER.CUSTOMER_ID
DELETE FROM CUSTOMER
WHERE CUSTOMER_ID NOT IN
(SELECT CUSTOMER_ID FROM ADDRESS)
F
Trang 30This statement immediately returns only tomers without addresses, and we can deletethem easily
cus-Views can be (and are) used to do much morecomplex things than this In fact, their main pur-pose is simplification of SQL statements Viewscan also be used to restrict database access, oftenhiding the structure and full contents of the phys-ical tables from whoever selects data
Referential Integrity
As explained in pretty much any relational base theory book, referential integrity preventsapplications from creating inconsistent dataentries in a database It is usually represented bysome kind of relationship between two databaseobjects (tables), or simply with some rules thatdetermine which data can be entered into existingdatabase objects
data-As a simple example, referential integrity couldprevent entering data into table X if some corre-sponding data does not exist in table Y Likewise, itcould prevent applications from deleting any data
in table X that has corresponding data in table Y
Many relational database systems support ferent modes of referential integrity, but the mostcommon method is the creation of foreign keys Iftable X has a foreign key that points to a field intable Y, a referential integrity system mightrestrict adding records to Table X that don’t refer
dif-to a value in that table Y field It might also vent deletion or single-side change of the linkeddata in table Y, or take care that all deleted ormodified data in table Y is likewise deleted andmodified in all linked tables (table X) While theformer method is preventative or restrictive, thelatter method cascades changes from table Y totable X, and is thus referred to as “cascadingdelete” and “cascading update”
pre-In our case, we should take care that usershandling our application do not delete a cus-tomer from the CUSTOMER table if there areaddresses stored in ADDRESS table that belong
to him Deleting the customer data (as in Listing2) would leave his addresses orphaned, andthere is the possibly that they could be unwit-tingly re-attached at a later time to some newlyentered customer (if the deleted customer’s IDwas re-used when a new customer was added).With referential integrity, we can easily establish
a relation between the CUSTOMER and ADDRESStables by creating a FOREIGN KEY in tableADDRESS which points to the customer’s ID inCUSTOMER We should give the key a name, solet’s make it FK_ADDRESS_CUSTOMER_ID, simplyshowing that it relates the ADDRESS table to the
11 // display an error message and exit
12 echo “Error deleting customer.” ;
11 $result = $dbh -> query ( $query_check_address );
12 $row = $result -> fetchRow ());
13 $count = $row [ ‘CNT_ADDRESS’ ];
25 // display an error message and exit
26 echo “Error deleting customer.” ;
Trang 31CUSTOMER table through column CUSTOMER_ID.
Our foreign key will do several things for us:
• it will prevent us from entering a
CUS-TOMER_ID into the ADDRESS table that
does not yet exist in the CUSTOMER
table
• it will prevent us from deleting a
cus-tomer whose CUSTOMER_ID is
refer-enced from addresses stored in the
ADDRESS table
• if defined with ON … CASCADE clause, it
would ensure that deleting a customer
would delete all his addresses, or that
updating his CUSTOMER_ID in the
CUS-TOMER table would update it in all
refer-ring records in the ADDRESS table
Our foreign key definition should normally be
specified in the ADDRESS table creation code, and
might look like:
The above statement creates a restrictive
for-eign key To add support for cascading, use:
Now imagine Listing 2 running on linked tables
The referential integrity engine would either
phys-ically prevent the deletion of customer records
that have addresses (restrict), or delete the
addresses as well (cascade)
If you are using a RDBMS that does not support
referential integrity, you can still simulate it fairly
successfully In this simple case it might be an
extended version of our function from Listing 2,
shown in Listing 3
Although writing code to extend this function
does not appear to be too much hard work, it is
obvious that simulating just a simple restrictive
referential integrity engine can mean writing
some amount of extra code Simulating a
cas-cading delete is a fairly simple change (shown in
Listing 4):
There are some performance issues to considerwhen using cascading updates In the case thatyour database server contains a large amount ofrelated data, the change or deletion of some mas-ter records could force the database server to per-form large, time-consuming update operations Inthe worst case scenario, this could result in excep-tional load on the server, as well as script execu-tion timeouts
The proper use of referential integrity can help
to reduce the amount of sanity checking codenecessary and the number of errors introduced,
as well as helping to increase the amount of sleepyou get at night
Transactions
OK, we did nice job programming an checking routine which checks for existingaddresses and either prevents us from deletingthe customers to which they belong, or deletesthe addresses as well Consider, though, that yourapplication communicates with the remote data-base server through some wired link Imaginethat just between deleting data from theADDRESS table and the CUSTOMER table, some-one cuts the wire? Of course, this is not a hugeproblem in our simple case, but there are complexsituations where this would be a big problem
integrity-FOREIGN KEY FK_ADDRESS_CUSTOMER_ID
(CUSTOMER_ID) REFERENCES CUSTOMER (CUSTOMER_ID)
ON UPDATE CASCADE
ON DELETE CASCADE
FOREIGN KEY FK_ADDRESS_CUSTOMER_ID
(CUSTOMER_ID)REFERENCES CUSTOMER (CUSTOMER_ID)
10 $result = $dbh -> query ( $query_delete_address );
11 if ( $dbh -> isError ( $result ))
12 {
13 // display an error message and exit
14 echo “Error deleting addresses.” ;
22 // display an error message and exit
23 echo “Error deleting customer.” ;
24 return 0 ;
25 }
26 else return 1 ;
27 } 28
29 } 30
31 ?>
Listing 4
Trang 32Besides, users would be confused if addresseswere deleted while customer data stays.
How can we get around this? By usingtransactions
Transactions are, roughly explained, closedprocesses that are invisible to concurrent data-base users A transaction remains invisible toother users until such time as it is committed If
a transaction is rolled back, or discarded, otherusers will never know it even happened in thefirst place
This means that when we start a transaction,whatever we do with data in the database will
be invisible to other users If we send a MIT statement, all of our work will be actuallywritten to the database and other users will beable to see the altered values If we issue aROLLBACK statement, no changes will be writ-ten at all, leaving the data in the same state as
COM-we started with A transaction rollback, ing on the database server’s settings, also hap-pens when the connection to the server is lost
depend-or broken, depend-or if an errdepend-or condition was raisedwhile we were working That is awesome dataconsistency protection!
As we mentioned, with the previous data tion example it was not possible to leave cus-tomers without address data if our script brokebetween the two DELETE statements What if,for some particular reason, we want to changeour customer’s ID? To keep data in the two tablesrelated to each other, the changed ID must also
dele-be updated in all customer address records Ifthe connection breaks in the middle of thechanges, our addresses could be left without acustomer, or our customer could be left withoutaddresses
By invoking a transaction before we startupdating data, and committing it after updateshave completed, we can ensure that no data will
be left in an inconsistent state An example isgiven in Listing 5 Let’s have a look at it
After we set up the queries to run in order tochange our customer ID from $old_customer_id
to $new_customer_id, we also set up an errorindicator The $success variable will tell us if allhas been completed correctly at the end of ourfunction
Notice one special function call,
$dbh->autoCommit(false) This function tellsthe RDBMS which serves our data that we want
to turn off the ‘auto commit’ feature ‘Autocommit’ is supported by many database serverengines, and it means simply that the transac-tion started implicitly by each query will auto-matically be committed when the query is fin-
14 // Server starts the transaction implicitly,
15 // if auto commit option is set to FALSE
21 // display an error message and exit
22 echo “Error updating addresses.” ;
29 // display an error message and exit
30 echo “Error updating customer.” ;
46 // Otherwise, we can undo a complete task
47 // leaving the data in the state just as
before we started
48 $dbh -> rollback ();
49 }
50
51 // You might want to set auto commit option
52 // back to True for other processes that
do not use transactions
Trang 33ished Most RDBMS’s have this turned on by
default, but to prevent storing incomplete
changes we must turn this feature off We do
not want to store anything until all changes are
complete In the PEAR DB class we can turn off
‘auto commit’ programmatically by calling the
actually means that the first and subsequent
changes to our data will be done within a
trans-action, and will not be written or discarded until
we issue a commit or a rollback
At the end of our function in Listing 5, we can
check if any errors happened while updating
the data If not, we can call the commit()
method, which will write out all of our changes
and close the transaction If an error did ocur,
we can simply call the rollback() method,
which will discard all of our changes and close
the transaction
A little better error handling around the
which case no data would be written It isimportant to handle transaction completionproperly because leaving open transactions(especially in conjunction with table locks)could cause locked data and prevent otherusers from accessing the database!
It should be noted that, although we used thePEAR methods above, transactions can usually beset up manually with SQL statements The exactsyntax varies from system to system
We should also mention that transactionscould be simulated by PHP Any simulation ofthis feature would be hard-pressed to be robustenough for real world use, and would be a verycomplex piece of code, but it is possible to do.The most common way is to prepare all edits
F
1 PROCEDURE NEW_CUSTOMER (FIRST_NAME, LAST_NAME, ADDITIONAL_INFO, GENDER)
1 CREATE TRIGGER before_new_customer
2 BEFORE INSERT ON customer_id
3 REFERENCING NEW AS new_customer_row
4 FOR EACH ROW
5 BEGIN
6 new_customer_row.CUSTOMER_ID =
7 (SELECT MAX(CUSTOMER_ID)+1 FROM CUSTOMER);
8 ENDListing 8
24 // Now incease it’s value
25 $new_id = $result ( ‘LAST_ID’ ) + 1 ;
31 // display an error message and exit
32 echo “Error adding customer.” ;
advanced database servers, some of these servers pro- vide more advanced features.”
Trang 34and updates in separate tables and then
trans-fer them to the actual data tables, checking if
all updates were OK
Procedures and Functions
Procedures, functions, or stored procedures – they
are all essentially the same thing: blocks of code
(using some supported language, such as SQL,
PL/SQL, C, Java, and recently PHP!) that are
exe-cuted on the database server Procedures that
run on the database server have many uses,
including embedding business logic in the
data-base, data consistency checking, and
simplifica-tion of the database access interface Let’s look
at an example
Consider that instead of customer updates or
deletes, we now have the need to add a new
cus-tomer into the database Among other data, we
must provide a unique ID value to identify the
cus-tomer A PHP function to store new customer data
into the database could look something like
Listing 6
Notice that we do not receive CUSTOMER_ID as
a parameter to the function Instead, we retrieve
the highest existing value from the CUSTOMER
table and add one to it But, what if just between
when we got the last ID and inserted our new
record, someone else got the same ID and tried
to insert the data in the same time? One of us
would receive an error and no data would be
inserted!
Procedures can offer a good solution to this
problem, as they are executed very quickly, and
may be executed serially on your system This
means that we can use them to “get around” the
aforementioned race condition, or at least narrow
the window Truly patching this race condition
would usually require table locking, which may be
the subject of a future article
As the code for writing database procedures is
often very specific for each database system, we
will skip writing a real example, point you to
some pseudo code in Listing 7, and ask you to
consult your local database system manual
Triggers
Triggers are usually functions in disguise, linked
to a specific table, and executed before or after
events like inserting, updating or deleting
records There can often be more than one
trig-ger attached to a single table, and trigtrig-gers are
then executed in specified order, one-by-one
The most common use of triggers is for
main-taining referential integrity Triggers specified
before an action can often choose to prevent the
action, or perform other actions on other tables
(like deleting matching records, in the case ofcascade) Triggers can also change values in therow being modified This will help us in our nextexample
Rather than having to run a query to find outwhat ID we can use, then inserting anotherrow, wouldn’t it be much nicer to just insert therow and let the system worry about giving it anID? This is exactly how Listing 8 works Listing
8 shows a trigger on the CUSTOMER table, to
be fired right before the row is inserted Thebody of the trigger (who’s real implementationwould vary greatly on different systems) getsthe next ID, and sets the CUSTOMER_ID field inthe inserted row This way, adding a new row
is as simple as inserting the data, not worryingabout which ID to use Again, we have to worryabout a race condition, but this could be han-dled with table locks or sequences – topics foranother day
Wrapping upThere are a number of advanced features that wehaven’t covered here, including table locking, rowlocking, sequences, rules, etc Perhaps these can
be the topics for another article
The more tasks the database server can do foryour application, the less code you will have towrite Stability, security, and performance arealso a consideration Generally speaking, featuresembedded in the server are going to be muchmore robust and reliable than any simulation wecan make As database systems are improved,more automated features will likely be engineeredand introduced, allowing us to focus on the moreimportant things
You might think that you should search out thedatabase with all of these features, and be setfor the future, but that’s not necessarily true.Most of the above features come at a cost, andusually it’s performance If you don’t anticipate
a need for these more advanced capabilities, youmay see much better performance with a lessadvanced system
Click HERE To Discuss This Article http://forums.phparch.com/46
Davor Pleskina lives in Opatijia, Croatia He is the author of Davor's
PHP Editor You can reach Davor at davor@pleskina.com
Trang 35Over the last few months we have seen some
thought-provoking articles on technologies like
XML and the Smarty template engine Other
articles have indirectly expressed the
advan-tages of using OOP (Object-oriented
program-ming) instead of procedural programming In
this article we will like to focus on combining
the knowledge from these previous gems to
build something useful every web developer
can use
Every modern Internet or intranet web
applica-tion these days require some sort of menu
struc-ture or interface to allow for the easy navigation
within the application Let’s use the
aforemen-tioned technologies to build a reusable menu
structure This menu structure will make use of
object-oriented concepts, be defined in XML, and
be driven by templates/styles to allow changes
to the look and feel
Before we start
Firstly, let’s quickly get the logistical things out of
the way To make sure that everything runs
smooth-ly on your side you are going to need the Expat XML
library and the Smarty template engine installed
Most Linux distributions have the Expat library
compiled in with PHP package (Debian, Redhat,
Mandrake, Suse) You can use the following code
to see if Expat has been included in your PHP
package:
You should see a section ‘xml’ with ‘XML port active’ and the ‘EXPAT Version’ asshown in Figure 1 If you do not have Expat sup-port you can get the source from
Expat support within PHP simply include xmlwhen running the configure build script fromthe PHP source directory However it is highlyunlikely that you will not have Expat support
—with-The Smarty template engine is downloadable
<?php phpinfo ();
XML Namespace Support active
EXPAT Version expat_1.95.6
xml
PHP: 4.2+, XML extension, MySQLOS: N/A
Applications: SmartyCode Directory: xml_menus
REQUIREMENTS
Trang 36from http://smarty.php.netand the latest version
as of this writing is version 2.50 Why use
Smarty? First of all, reinventing a well-invented
wheel is seldom necessary Second, it is almost
always advisable to separate the business logic
from the presentation layer, and Smarty does a
good job of that You will need to uncompress the
Smarty source code into a PHP accessible
direc-tory In my code distribution, I include a
code/class.MySmarty.phpwrapper file (we will
discuss this later) that includes the Smarty
tem-plate engine as:
You might need to change this require
state-ment to point to the correct location of Smarty
The source code for this article contains a
‘code’ directory that should be moved into a
web-accessible area on your local machine in
order to make the examples work
In this article I presume that you know some
basics about XML, Object-oriented programming
and using the Smarty template engine In the
same breath, however, I would also like to use
this article to introduce some of these concepts
I hope you enjoy the ride!
Our requirements
Lets have a look at what we would like to see in
our menu component
• We want to store our menu structure in
a manageable, portable structure, so
we will be using XML to define ourmenu structure
• The menu structure must be able tohandle the following:
- an optional menu heading
- multiple collapsible menu tions
sec multiple menu items undereach menu section
- menu items must support animage and or text description
• The menu structure needs to supportHTML frames, directing access to differ-ent windows
• The menu needs to support differentthemes or styles
• We need to be able to use our menu as
a drop-in component to an existingpage or as a standalone menu inter-face with a separate header and footer
to signify a complete HTML page Wewill be able to achieve this functionalityusing our templates
The following is the basic outline of our menusystem:
Mapping what we need into XMLNext we need to look at mapping our menurequirements into a XML definition In Listing 1(menu_example_1.xml) we see the menu defini-tion starting and ending with <menu> tags Theexample menu is typically something we will find
in our web administration section Every menustructure has an optional menu heading and thedefault state of the menu (either open or closed) The menu structure can have multiple sectionswith multiple menu items linked to a specific sec-tion Every section has a unique id that identifiesthe section We will use this id as theheading/title for the section Multiple menuitems can belong to a section Every item has anitem name to identify the menu item, the item’s
menu heading (optional)
menu section1 (optional) (click to expand/collapse)
menu item menu item menu section2 (optional) (click to expand/collapse)
menu item menu item
require_once( ‘smarty/Smarty.class.php’ );
< menu >
< heading >php|a</ heading >
< state >closed</ state >
< section id =”Company Management”>
< item >
< name >Add a new company</ name >
< href >action.php?function=add_company</ href >
< image />
</ item >
< item >
< name >Delete a company</ name >
< href >action.php?function=del_company</ href >
< name >Add a new user</ name >
< href >action.php?function=add_user</ href >
< image />
</ item >
< item >
< name >Delete a user</ name >
< href >action.php?function=del_user</ href >
3 $menu = new Menu ( ‘menu_example_1.xml’ , ‘default’ );
4 $menu -> setTarget ( ‘info’ );
5 $menu -> buildMenu ();
6 $menu -> displayMenu ();
7 ?>
Listing 2: menu.php
Trang 37link, and an optional image for the menu item In
our example, every menu item will be using the
arrow.gif image to identify a menu item
How does everything fit together?
We will take a slightly different approach here, and
show you the end result first Listing 2 (menu.php)
shows how we would like to create our menu
We first create an instance of the Menu class
The Menu class constructor takes two parameters,
our menu structure, saved as a xml file, and the
style we would like to use for displaying the menu
We then set the default target of the menu items
to ‘info’ (an HTML frame) After creating the menu
with a call to buildMenu(), we display the menu
to screen Wow five lines of code, that looks easy
I see that hand Yes, we will be working in a
framed environment for this example Listing 3
(example_1.html) shows the HTML code we will use
For those of us that have itchy fingers, you are
welcome to open example_1.html in your browser to
see the menu we have just created You are only
allowed to do that, though, if you promise to
return After all, we will need to have a look at how
we did that Figure 2 is a screen shot of the
‘default’ menu style with both sections expanded
(The ‘default’ style’s images and style sheet are
included in the article’s source directory)
Figure 2
What do we need to continue?
Looking at Listing 2, we will explain our project
by examining the following:
1 We will first look at a class for parsing our
XML menu structure This class will create
a menu array, containing the structure andinformation about our menu
2 Second, we will look at a class to managethe style component of our menu We willexamine our style file (menu.tmp) and thecode we use to assign the Smarty vari-ables within our menu template
3 Third, we will look into the detail of ating collapsible and expandable menusections and items
cre-4 Finally, we will end off with the Menuclass, tying all of this together
Lets carry on by looking at the XML parser class
6 <frame src=’menu.php’ scrolling=’auto’ frameborder=’no’
mar-ginwidth=’2’ marginheight=’2’ noresize name=’main’>
7 <frame src=’blank.html’ scrolling=’auto’ frameborder=’no’
mar-ginwidth=’2’ marginheight=’2’ noresize name=’info’>
37 if (isset( $element [ ‘attributes’ ][ ‘ID’ ]) )
38 $key = $element [ ‘attributes’ ][ ‘ID’ ];
45 $this -> menu [ $key ][ $i ][ ‘href’ ] =
str_replace ( ‘##’ , ‘&’ , $element [ ‘value’ ]);
Trang 38The XML parser
On to the real stuff In our XML class we want to
create an array that will hold the contents of our
menu structure Looking at Listing 4
(class.MenuXML.php), we see the MenuXML
class with four important class variables
Our class constructor expects a $data variable
If the $data variable is a valid file location, we
read the contents of the file into our $data class
variable, else the $data variable is assigned to
the class $data variable By doing it this way, we
allow future support where we could create our
menu XML structure from a database, choosing
not to store the menu structure in a file
We next call the loadXML() method to create
our menu array In our loadXML()method we first
load the contents of our menu structure file into a
variable After creating an XML parser, a call to
xml_parse_into_struct() parses the XML data
into 2 array structures The $i_ar (index) array
contains pointer to the location of the appropriate
values in the $d_ar (values) array After freeing
the XML parser we are ready to work with our
val-ues array ($d_ar) to construct our menu array
Looping over our values array ($d_ar), we set
our heading, state and type class variables
When we encounter a ‘section’ element we get
the value of the ‘id’ tag The ‘id’ tag’s value will
be used as a $key for building our menu array
The following code tests our MenuXML class
Listing 5 shows us the output of the above
script, derived from the XML definition in Listing
1 (menu_example_1.xml)
Using Smarty and
our MenuStyle class
As we defined in our requirements, our menu
system needs to support themes or styles
Listing 6 (class.MySmarty.php) is a wrapperclass that extends the Smarty class In our con-structor we set the template directory, the con-fig directory, the compile directory and, lastly, adirectory where we store extra Smarty plug-ins
If the ‘compile’ directory does not exist, we ate it and set the appropriate permissions (Youmight need to change this setting if your tem-plate directory needs to have world access)Listing 7 (class.MenuStyle.php) contains ourMenuStyleclass which manages the style or theme
cre-of our menu system The style class currently onlyworks with one Smarty template file, calledmenu.tmp, stored in the style’s specific directory
‘style/STYLE_NAME/’ Listing 8 is the defaultmenu.tmp style file (style/default/menu.tmp)which we used to build the look and feel in Figure 1.The accompanying source code also includes thestyle sheet (styles.css)
Have a look at the sidebar on Smarty (page 40)
if you’re a little rusty or have never ventured thatway
As we look at our style class, we will see theSmarty functions assign() and fetch() beingused You should be familiar with the assign()
function from the sidebar, but the fetch() tion returns our completed template into a vari-able, instead of directly printing it out
func-In our style class’ constructor, shown in Listing
$heading Contains the heading we are
using for our menu
$state Contains the default state of
the menu (open or closed)
1 <pre>php|a
2 closed 3