Académique Documents
Professionnel Documents
Culture Documents
Joseph Crawford
info@josephcrawford.com
User #63883
CONTENTS
February 2009
FEATURES
13
20
Richard Bates
28
Ricky Robinett
33
41
Ben Ramsey
COLUMNS
4
6
8
10
48
50
Editorial
ElePHPants!
PEAR Corner
Enterprise PHP
Ivo Jansch
Security Roundup
Arne Blankerts
exit(0);
Marco Tabini
Version Naming
Technical Design
If you want to bring a PHP-related topic to the attention of the professional PHP community,
whether it is personal research, company software, or anything else, why not write an article for
php|architect? If you would like to contribute, contact us, and one of our editors will be happy to
help you hone your idea and turn it into a beautiful article for our magazine. Visit www.phparch.
com/writeforus.php or contact our editorial team at write@phparch.com and get started!
EDITORIAL
Round Two
by Elizabeth Tucker Long
February 2009
Volume 8 - Issue 2
Publisher
Arbi Arzoumani
Editor-in-Chief
Elizabeth Tucker Long
AuthorLiaison
Elizabeth Naramore
Cathleen MacIsaac
Technical Editors
Steph Fox
Simon Harris
Matthew Turland
Clark Everetts
Graphics & Layout
Arbi Arzoumani
Managing Editor
Arbi Arzoumani
Authors
Richard Bates, Arne Blankerts,
Chris Cornutt, Ivo Jansch, Matthew
Weier O'Phinney, Ben Ramsey, Ricky
Robinett, Jos Len Serna, Marco
Tabini, Helgi ormar orbjrnsson
php|architect (ISSN 1709-7169) is published
twelve times a year by Marco Tabini & Associates,
Inc., 28 Bombay Ave., Toronto, ON M3H1B7,
Canada.
Although all possible care has been placed in
assuring the accuracy 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.
php|architect, php|a, the php|architect logo,
Marco Tabini & Associates, Inc. and the MTA Logo
are trademarks of Marco Tabini & Associates, Inc.
Contact Information:
General mailbox:
info@phparch.com
Editorial:
editors@phparch.com
Sales & advertising:
sales@phparch.com
Printed in Canada
Copyright
2003-2009
Marco Tabini & Associates, Inc.
All Rights Reserved
ElePHPants!
the view.
ing and enjoying
Mountain climb
ns.
tha
Re
k
ric
De
of
Photo courtesy
taxi. Photo
Almost home, just waiting for a
courtesy of Ivo Jansch.
Do you have photos of your ElePHPant? We would love to print them. Send us a high-resolution image (or if you
have the high-resolution image posted online, just send us the link) of your ElePHPant. We'll choose several photos
a month to publish. Just can't get enough of these elePHPants? Be sure to check out the ElePHPant World Tour http://www.elephpantworldtour.com
6 | February 2009 www.phparch.com
The elePHPants love to travel the world! Here are some photos that they have sent
us from their travels.
COLUMN
PEAR Corner
Version
Naming
In this column series, Id like to write a openly about PEAR, specifically about its
good and bad sides.
Version Naming
Lets start by talking about the version naming standard and why its important.
Now dont get me wrong, its not like PEAR invented
the need for version naming, be it for PHP projects or
the software world at large, but the fact is that PEAR
was one of the first, if not the first, large-scale PHP
project that had more than one concurrent release at a
time. This fact required a proper standard in the end.
So, almost 5 years ago today, the PEAR group at the
time went ahead and formalized a standard to keep the
version naming more consistent, yet still working with
the version_compare function.
The document they produced can be accessed from
http://pear.php.net/group/docs/20040226-vn.php, but I will
attempt to simplify it a little bit.
First, its important to understand that there is a
difference between version numbers and version state
and how they interact. Lets look at how the basics of
the version numbering system work. Consider x.y.z for a
second, now lets translate that into something human
readable.
COLUMN
PEAR Corner
Backwards Compatibility
Now what is backwards compatibility? In short, it is
when I, as a application developer, pick lib X to use in
my application and pick release 1.2.0 to start utilizing
the API of lib X. Even though I dont follow the development of lib X, if they follow a proper, no-BC-breaking
approach, then I should be able to upgrade the lib from
1.2.0 to 1.6.0 without having to change a single line
in my code. If a BC break would have occurred between
1.2.0 and 1.6.0, then there is a good chance that my
application would stop working with such an upgrade.
So BC breaks should only happen below stable, preferably only in the alpha state, if possible.
9 | February 2009 www.phparch.com
COLUMN
PHP
by Ivo Jansch
High-Level Architecture
The technical design of an application has a lot of different aspects. One of the first decisions we have to
make is what high-level architecture we will implement.
Depending on the requirements and the available infrastructure, we might go for a single monolithic set-up
where all the code makes up a single application. This
is what we would call a normal architecture for PHP
applications, and it is probably right for 95% of the applications.
This column benefits greatly from reader input. If you have an interesting project or if
you want to share how you employ PHP in your organization, drop me an email at
enterprisephp@phparch.com. I might contact you for a short interview, or at least I will
use your input when writing this column!
Thank you!
Ivo
Technical Design
COLUMN
Version Naming
Database Design
After weve made a decision on what high-level architecture to implement, we can have a look at the underlying data model. It is up for debate whether or not the
data model should be designed at an early stage in the
design process, but it is my personal experience that
COLUMN
Application Design
The final aspect of the technical design is the design
of the code itself. After the high-level architecture and
the data model, the application design is the third important part of the technical design phase.
Typically, this part of the design consists of class
diagrams, sequence diagrams or data flow diagrams.
Data flow diagrams are useful when the focus of an application is on the data, and you need to identify how
this information flows from one component to the next
and what processing is done on the information. Class
diagrams are always useful, and sequence diagrams are
very useful if there is a complex hierarchy of classes
and you want to visualize what classes and method
calls are involved in a particular feature. All three modeling techniques help visualize the design of an application. The structure of an application is clearer if you
have it in front of you. If you need to change things or
add functionality, the models help in determining what
should be implemented where.
Conclusion
Weve covered just a few scenarios of high-level architecture, database design and application design. The
import take-away, however, is that you pay attention
to these design aspects. Tackling design issues during
the technical design phase saves a lot of time during
the implementation phase. In general, the earlier you
can tackle an issue, the lower the cost of the issue. In
the design phase, while there is no code to maintain,
you are in a good position to tackle architectural issues
such as the scalability of an application.
Version Naming
FEATURE
C
L
REQUIREMENTS
PHP: 5.2+
Other Software: Zend Framework, PEAR and others
Useful/Related Links:
http://www.qadram.com/vcl4php
http://en.wikipedia.org/wiki/Property_(computer_
science)
Interested in Visual RAD tools for PHP? This article provides a general overview of
VCL, Visual Component Library, for PHP, what its useful for, and introduces you to
integrating your own components into the Delphi for PHP IDE.
FEATURE
LISTING 1
1.<?php
2.require_once("vcl/vcl.inc.php");
3.//Includes
4.use_unit("forms.inc.php");
5.use_unit("extctrls.inc.php");
6.use_unit("stdctrls.inc.php");
7.
8.//Class definition
9.class Index extends Page
10.{
11. public $Button1 = null;
12. public $Panel1 = null;
13.}
14.
15.global $application;
16.
17.global $Index;
18.
19.//Creates the form
20.$Index=new Index($application);
21.
22.//Read from resource file
23.$Index->loadResource(__FILE__);
24.
25.//Shows the form
26.$Index->show();
27.
28.?>
29.
LISTING 2
1.<?php
2.<object class="Index" name="Index" baseclass="page">
3. <property name="Background"></property>
4. <property name="Caption">Index Page</property>
5. <property name="DocType">dtNone</property>
6. <property name="Height">600</property>
7. <property name="IsMaster">0</property>
8. <property name="Name">Index</property>
9. <property name="Width">800</property>
10. <object class="Panel" name="Panel1" >
11. <property name="Caption">Panel1</property>
12. <property name="Height">192</property>
13. <property name="Left">100</property>
14. <property name="Name">Panel1</property>
15. <property name="Top">72</property>
16. <property name="Width">364</property>
17. <object class="Button" name="Button1" >
18. <property name="Caption">Button1</property>
19. <property name="Height">25</property>
20. <property name="Left">88</property>
21. <property name="Name">Button1</property>
22. <property name="Top">68</property>
23. <property name="Width">75</property>
24. </object>
25. </object>
26.</object>
27.?>
28.
Resource Files
The Delphi for PHP IDE stores and reads component
properties from an .xml.php file. This file is created
by the IDE at design-time, but you are not required to
use the IDE; as it is an XML formatted text file, you
can create it with a text editor. This file is used by
the Page component to create all components and set
the properties to their initial values. This is done in
the loadResource() call, just before the show() call.
Show() is what causes a component to be displayed
in the browser. These files are external resources you
can use as templates, and they provide a separation
between the interface and the code.
In Listing 1, you can see the basic structure of a
Page class with calls to loadResource() and show(). In
Listing 2, you can see the contents of the .xml.php
file. Resource files are not a requirement. You can create your components and assign properties manually, as
shown in Listing 3.
FEATURE
Class Tree
The class library is made up of a
full tree of classes, but all of them
share common ancestors which
implement the core functionality. The root class is called Object,
and all classes in the library
inherit from it. The next major
classes that inherit from Object
are Persistent, Component, and
15 | February 2009 www.phparch.com
FIGURE 1
FIGURE 2
Ownership and
Parentship
Its important to understand the
difference between ownership and
parentship, as that will give you
an idea of how components are organized inside a Page. By default,
a Page owns all the components
placed inside, no matter which one
is the parent. After that, the parent for a control is the control into
which it is placed. Lets imagine a
Page, with a Panel, and inside the
Licensed to 63883 - Joseph Crawford (info@josephcrawford.com)
FEATURE
Panel, a Button. The Page is the owner of the Panel
and of the Button, but the Page is only the parent of
the Panel, and the Panel is the parent of the Button.
When you call show() for a Page, it iterates through
all the children, telling each of them to show(), and
in turn, each child tells all of its children to show().
These nested calls cause all the controls on a Page to
be shown.
Component Model
LISTING 3
1.<?php
2.require_once("vcl/vcl.inc.php");
3.//Includes
4.use_unit("forms.inc.php");
5.use_unit("extctrls.inc.php");
6.use_unit("stdctrls.inc.php");
7.
8.//Class definition
9.class Index extends Page
10.{
11. public $Button1 = null;
12. public $Panel1 = null;
13.}
14.
15.global $application;
16.
17.global $Index;
18.
19.//Creates the form
20.$Index=new Index($application);
21.
22.$Index->Panel1 = new Panel($Index);
23.$Index->Panel1->Parent = $Index;
24.$Index->Panel1->Height = 192;
25.$Index->Panel1->Left = 100;
26.$Index->Panel1->Name = "Panel1";
27.$Index->Panel1->Top = 72;
28.$Index->Panel1->Width = 364;
29.
30.$Index->Button1 = new Button($Index);
31.$Index->Button1->Parent = $Index->Panel1;
32.$Index->Button1->Caption = "Button1";
33.$Index->Button1->Height = 25;
34.$Index->Button1->Left = 88;
35.$Index->Button1->Name = "Button1";
36.$Index->Button1->Top = 68;
37.$Index->Button1->Width = 77;
38.
39.//Shows the form
40.$Index->show();
41.
42.?>
LISTING 4
1.<?php
2.function dumpContents()
3.{
4. $attributes = $this->getCommonAttributes();
5.
6. $style = $this->getCommonStyles();
7.
8. if ($this->readHidden())
9. {
10. if (($this->ControlState & csDesigning) != csDesigning)
11. {
12. $style.=" visibility:hidden; ";
13. }
14. }
15.
16.
17. if ($style != '') $style = 'style="' . $style . '" ';
18.
19. if ($this->_onshow != null)
20. {
21. $this->callEvent('onshow', array());
22. }
23.
24. echo '<input type="file" value="Up" id="'. $this->_name .
25. '" name="'. $this->_name .'" '. $style .' '.
26. $attributes .'/>';
27.
28.}
29.?>
30.
LISTING 5
1.unit listing5;
2.
3.interface
4.
5.type
6. TMyObject=class
7. private
8. FMyProperty: string;
9. procedure SetMyProperty(const Value: string);
10. published
11. property MyProperty:string read FMyProperty
12. write SetMyProperty;
13. end;
14.
15.implementation
16.
17.{ TMyObject }
18.
19.procedure TMyObject.SetMyProperty(const Value: string);
20.begin
21. FMyProperty := Value;
22.end;
23.
24.end.
25.
26.// to access the property
27.var obj: TMyObject;
28.obj.MyProperty := 'Property Value';
29.Writeln(obj.MyProperty);
30.
FEATURE
In PHP 5, the visibility of class members can be private, protected or public, but for the IDE, a new scope
must be added, called published. At run-time, a published property is public, but at design-time, only published properties will be shown in the Object Inspector.
This is necessary because not all properties should be
set by the developer at design-time. Since PHP doesnt
have this visibility keyword, VCL for PHP needs some
way to accomplish it.
This is the convention the IDE uses to identify which
properties to show in the Object Inspector: properties whose accessor method names start with read or
write are considered public, and those whose accessor
method names start with get and set are considered
published.
Events
A component can have two types of events, regular
events and Javascript events. Regular events are those
in which the event handler must be a PHP method;
i.e., the code must be written in PHP. For Javascript
events, the event handler must be a function written
in Javascript. The main difference is when and where
the code is executed. For PHP events, the code is executed when the form is submitted to the server. For
Javascript events, the code is executed in the browser,
before anything is posted to the server. For example, a
Button can have two OnClick events; the first one fired
is the Javascript OnClick event, and then after the form
is posted, the PHP OnClick is called.
Events are regular properties - they contain a string
with the name of the method to call - so, to allow
the IDE to know the difference between properties,
events and Javascript events, another convention is
used. Regular events must start with On; for example,
OnClick, and Javascript events must start with jsOn,
for example, jsOnClick.
Calling Events
Events are called by components when all relevant conditions are met. Lets take an easy example, like the
Button OnClick event. In HTML, you know a form button has been clicked if, in the request, there is a form
field that has a name matching the contents of the
name attribute of the <input> tag, with a value set in
the value attribute of the <input> tag. This is exactly
what the Button component looks for. In the init()
17 | February 2009 www.phparch.com
Session Persistence
One of the basic features of VCL for PHP is session
persistence. This features allows you to write web applications that behave like desktop apps. In a desktop
application, you dont worry when your application
starts and finishes, and there is no need to backup
and restore the status of all the controls you have on a
form as the user moves from screen to screen.
With VCL for PHP, you get the same behaviour, because it serializes and unserializes object properties
when required. That way, the state of those components will be always what you expect. For example, if
you change the background color of a Label to red, you
expect that, no matter what happens to the application, no matter which link the user follows, the background color for the Label should always be red, until
you decide to change it. All this is automatic if you
use VCL for PHP components, as it saves in the session
LISTING 6
1.<?php
2.
3.class TMyObject extends Object
4.{
5. protected $_myproperty="";
6.
7. function getMyProperty()
8. {
9. return $this->_myproperty;
10. }
11.
12. function setMyProperty($value)
13. {
14. $this->_myproperty=$value;
15. }
16.
17. function defaultMyProperty()
18. {
19. return "";
20. }
21.}
22.
23.?>
24.
FEATURE
all properties that differ from their default values, and
restores them back again when the script is started.
Default Values
Data Access
Ajax Integration
With VCL for PHP, you can make use of Ajax, by using
the method ajaxCall(), which generates all the required javascript code to perform a call to the server
using ajax, and then process the returned results to
update the browser.
To make it work, you need to set the UseAjax property of the Page to true, so that processing takes place.
If you need to get debug information for the ajax
requests, you can set UseAjaxDebug to true and youll
get a window with all the information.
In Listing 8, you can see how easy it is to call a PHP
Template Engines
VCL for PHP allows you to make use of templates,
you are not restricted to use .xml.php files, and you
LISTING 8
LISTING 7
1.<?php
2.require_once("vcl/vcl.inc.php");
3.
4.use_unit("forms.inc.php");
5.use_unit("stdctrls.inc.php");
6.
7.class MyPage extends Page
8.{
9. public $Button1=null;
10.
11. function Button1Click($sender, $params)
12. {
13. echo "Button clicked!<hr>";
14. }
15.}
16.
17.$MyPage = new MyPage($application);
18.$MyPage->Name = "MyPage";
19.$MyPage->Button1 = new Button($MyPage);
20.$MyPage->Button1->Name = "Button1";
21.$MyPage->Button1->Parent = $MyPage;
22.$MyPage->Button1->Left= 100;
23.$MyPage->Button1->Top= 100;
24.$MyPage->Button1->OnClick = "Button1Click";
25.$MyPage->init();
26.$MyPage->show();
27.?>
1.<?php
2.class Index extends Page
3.{
4. public $Label1 = null;
5. public $Button1 = null;
6. function Button1JSClick($sender, $params)
7. {
8. //Dump the call using Ajax to the Button1Click event
9. echo $this->Button1->ajaxCall("Button1Click");
10.?>
11. //Return false to prevent the button submit the form
12. return(false);
13. <?php
14. }
15.
16. function Button1Click($sender, $params)
17. {
18. $this->Button1->Caption = "clicked Ajax " .
19. date("Y-m-d g:i:s a");
20.
21. $this->Label1->Caption = "Hello from Ajax!! " .
22. date("Y-m-d g:i:s a");
23.
24. $this->Label1->Color = "#" .
25. dechex(rand(0, 0xFFFFFF));
26. }
27.}
28.?>
29.
FEATURE
HeaderCode
StartForm
EndForm
Check Listing 9 to see what a template looks like, and
where the tags should be inserted. To add VCL for PHP
components, just insert the name of a component as
a smarty tag wherever you want that component to be
shown. Then, just set the TemplateEngine property to
SmartyTemplate and TemplateFilename to the name of
the file in which you stored the template. When the
page is shown, the template will be used to render the
visual aspect and components will be inserted into the
page where you decided.
IDE Integration
To enable your components to be used in a visual IDE,
you need to specify some extra information, called
design-time information. This information allows the
IDE to know how to handle your component, how to
edit properties in the Object Inspector, and where to
place your components on the Tool Palette.
This information is not required when you deploy
your application, so it doesnt add any overhead or
extra size; it is information specific to the IDE. To set
this design-time information and install your components in the IDE, you create a package, a php file with
the extension .package.php. In Listing 10, you can
see a basic package file with calls to the functions that
interact with the IDE.
In a package, you can specify where the IDE can find
the icons that represent your components on the Tool
Palette, the title of your package, the components you
want to install, and the page in which the Tool Palette
will be placed.
To let the Object Inspector know how to handle
some properties, we need to provide specific information in the component package. For example, an array
property should be handled by a specific property
editor in the IDE, which reads the array and provides
a visual interface to edit it. Or a color property,
while the user can type a color name or rgb value, its
Conclusion
VCL for PHP is a new approach to developing PHP web
applications, not only allowing you to use a Visual IDE,
but to apply techniques used when building desktop
applications. This opens up a full range of new possibilities and also opens the door for developers to wrap
and market PHP code according to a new component
standard.
LISTING 9
1.<!DOCTYPE html PUBLIC
2."-//W3C//DTD XHTML 1.0 Transitional//EN"
3."http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
4.<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
5.<head>
6.<title>Test Template</title>
7.<meta http-equiv="content-type"
8. content="text/html; charset=utf-8" />
9.{%$HeaderCode%}
10.</head>
11.<body>
12.{%$StartForm%}
13.{%$EndForm%}
14.</body>
15.</html>
LISTING 10
1.<?php
2.require_once("vcl/vcl.inc.php");
3.use_unit("designide.inc.php");
4.
5.setPackageTitle("Put the title of your package here");
6.//Change this setting to the path where the icons for
7.//the components reside
8.setIconPath("./icons");
9.
10.// "PaletteCateg" below should be replaced with the
11.// category in the Tool Palette where the component
12.// should appear
13.
14.//Change yourunit.inc.php to the php file which contains
15.//the component's code
16.registerComponents("PaletteCateg",array("NewComponent"),
17. "yourunit.inc.php");
18.?>
FEATURE
PART 1
Fx
Related URLs
PHP: 5.1.4 (for Zend Framework)
Other Software:
Flex Builder v3+ or the Flex Builder plug-in for
Eclipse v3.01+
MySQL Server version 4+
Zend Framework 1.7+
Apache or another PHP-enabled Web server
Useful/Related Links:
Adobe Flex 3 LiveDocs: http://livedocs.adobe.
com/flex/3/
Zend Framework: http://framework.zend.com/
ActionScript 3 CoreLib: http://code.google.
com/p/as3corelib/
Authors Development Blog: http://flexandair.
com/
by Richard Bates
FEATURE
LISTING 2
1.
2.CREATE TABLE IF NOT EXISTS `users` (
3. `id` int(11) NOT NULL auto_increment,
4. `name` varchar(255) NOT NULL,
5. `email` varchar(255) NOT NULL,
6. `password` varchar(255) NOT NULL,
7. PRIMARY KEY (`id`)
8.) AUTO_INCREMENT=2 ;
9.
10.INSERT INTO
11. `users` (`id`, `name`, `email`, `password`)
12. VALUES
13. (1, 'Tester', 'test@test.com', 'password');
14.
FEATURE
FEATURE
{
$id = 0;
$name = '';
$email = '';
$password = '';
FIGURE 4
$dbh = mysql_connect('
localhost', 'root', 'password');
$query = "INSERT INTO `docs`.`documents`
(id, user_id, name,
url, description, type,
file_size)
VALUES
(NULL, '$user_id', '$name',
'$url', '$description', '$type',
'$file_size')";
$result = mysql_query($query, $dbh);
Note: Be sure to replace localhost, root, and password with your database information and credentials.
The other method you need to create is
retrieveDocuments(). Use this function to get all
23 | February 2009 www.phparch.com
1.<?php
2.
3.include 'User.php';
4.
5.class UserService {
6.
7.
8. /**
9. * validate a User
10. *
11. * @param User $user
12. * @return User
13. */
14. function loginUser(User $user)
15. {
16. $dbh = mysql_connect('localhost', 'root', 'password');
17. $query = "SELECT * FROM `docs`.`users`
18. WHERE email = '$user->email'
19. AND password = '$user->password'";
20. $result = mysql_query($query, $dbh);
21. $record = mysql_fetch_array($result);
22. $returnUser = new User();
23. if ( $record != false ) {
24. $returnUser->id = $record['id'];
25. $returnUser->name = $record['name'];
26. $returnUser->email = $record['email'];
27. $returnUser->password = $record['password'];
28. return $returnUser;
29. } else {
30. return $returnUser;
31. }
32. }
33.
34.}
35.
36.?>
FEATURE
FEATURE
require_once 'Zend/Amf/Server.php';
require_once 'include/services/DocumentService.php';
require_once 'include/services/UserService.php';
To test the code and file structure thus far, open a Web
browser and navigate to your gateway.php file (for example: http://localhost/docs/gateway.php). Depending
on your Web server and browser, you will get one of
FIGURE 6
FIGURE 7
FEATURE
several results. If your setup is in good working order,
you should either see the text Zend Amf Endpoint
or receive a file download prompt from your browser.
If you dont get either of those outcomes, doublecheck your directory structure, and make sure your
gateway.php file is echoing the output from the Zend_
Amf server instance. If you did get a successful result,
youve finished the Zend_Amf services, and youre ready
to create the last bit of PHP.
Within the /docs folder, create a new PHP file
named upload.php. Predictably, it will contain the
code for uploading files to your server from a Flex client. The code is shown in Listing 5, and is likely to be
a familiar sight.
As you can see from the first few lines, this script expects a file and two fields containing strings by means
of POST. The strings will be the file extension and the
document owners user ID. The script will get the current time as a UNIX timestamp, add an underscore, and
append the user ID and the extension. The script then
attempts to save the file in the directory specified in
the variable $file_path. Be sure to use the full path to
your upload directory. In this case, the upload directory will be within the /docs directory and is be named
uploadedFiles.
If all goes well and the file is saved, the script
returns the generated file name to the client. If
not, it returns a string determined by the error. The
error code muf_error signifies a problem during the
move_uploaded_file() operation, and the error code
Fx
LISTING 5
1.<?php
2.
3.$file_temp = $_FILES['file']['tmp_name'];
4.$file_name = $_FILES['file']['name'];
5.$file_ext = $_POST['exten'];
6.$user = $_POST['userid'];
7.$file_path = '/home/user/public_html/docs/uploadedFiles';
8.$timestamp = time();
9.
10.$uname = $timestamp . '_' . $user . '.' . $file_ext;
11.
12.// checks for duplicate files
13.if ( !file_exists($file_path . '/' . $uname) ) {
14.
15. //c omplete upload
16. $filestatus = move_uploaded_file($file_temp,
17. $file_path . '/' . $uname);
18. if ( !$filestatus) {
19. $message = 'muf_error';
20. } else {
21. $message = $uname;
22. }
23.} else {
24. $message = 'fe_error';
25.}
26.
27.echo $message;
28.
29.?>
Figure 6 reiterates the proper file and directory structure, accounting for the addition of upload.php and
the uploadedFiles folder.
Flex Time
Now that youve got all the PHP you need and its
speaking AMF, youre ready to leverage it with a Flex
client. To get started, open Flex Builder. Click New >
Flex Project to launch the New Project Wizard. For the
project name, simply type Docs. Also, ensure that Web
Application is selected as the project type. The appropriate settings appear in Figure 7.
Click Finish, and Flex Builder creates your project in
the workspace. When its finished, you should see the
Docs.mxml file in the main editor pane. If not, doubleclick the Docs.mxml file in the left pane of the window. If the file opens in Design view, click the Source
button in the upper-left corner of the main editor pane.
Youll see the MXML code, which begins with a standard
XML tag:
<?xml version="1.0" encoding="utf-8"?>
Fx
<mx:Application
xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute"
backgroundGradientAlphas="[1.0, 1.0]"
backgroundGradientColors="[#000000, #2E2E2E]">
Fx
FEATURE
<mx:RemoteObject
id="roDocumentService"
destination="zend"
source="DocumentService"
endpoint="http://localhost/docs/gateway.php">
<mx:method
name="createDocument"
result="onCreateDocumentResult(event)"
fault="handleFault(event)"/>
Youre not quite ready to create the functions mentioned in the roDocumentService remote object.
For the time being, youll need to comment out
roDocumentService and its methods by selecting the
text, right-clicking it, then clicking Source > Toggle
Block Comment.
So that you can call your login method for User
objects, declare another remote object and method,
similar to those for the DocumentService:
x
F
<mx:method name="retrieveDocuments"
result="onRetrieveDocumentsResult(event)"
fault="handleFault(event)"/>
<mx:RemoteObject
id="roUserService"
destination="zend"
source="UserService"
endpoint="http://localhost/docs/gateway.php">
<mx:method name="loginUser"
result="onRetrieveUserResult(event)"
fault="handleFault(event)"/>
</mx:RemoteObject>
FEATURE
Taking the
Desktop Back
Lets face it, for web developers, desktop application development can be scary. In
this article, Ill introduce you to the ideas and tools needed to start creating powerful
desktop RIAs using PHP and Adobe AIR.
Setting Up PHP
Im going to show you how to build a simple application that pulls current products from a database and allows a user to view the list from a desktop application.
28 | February 2009 www.phparch.com
REQUIREMENTS
PHP: 5.2.4+
Useful/Related Links:
Zend Framework 1.7 - http://framework.zend.com/
Adobe Flex Builder 3 - http://www.adobe.com/
products/flex/
by Ricky Robinett
Setting Up Zend_Amf_Server
Now that we have set up our class, we need to start up
our AMF server. Make sure you have a project set up in
the Zend Framework and have version 1.7 installed. If
you do not, please visit the Zend website and get your
project set up. I will be placing this in the webroot and
calling the file air.php. Using the Zend Framework,
we can set up this file with just 5 lines of code.
require_once('Zend/Amf/Server.php');
require_once('includes/productList.php');
$server = new Zend_Amf_Server();
$server->setClass('productList');
echo ( $server->handle() );
FEATURE
FEATURE
-services "../services-config.xml"
FEATURE
Error Handling
I intentionally did not implement error handling because it is a very important part of any application. I
wanted to leave it separated from the initial application build to give it the focus it deserves. In this section, I will go through all the steps needed to set up
error handling in our application.
The first thing well want to do is set up our remote
object to call a function when an error happens. In
MXML, errors are referred to as faults. We can do this
by adding the fault attribute to our remoteObject
tag and setting it to call the faultHandler function
with an argument of event on fault. As a result, the
code will look like this:
<mx:RemoteObject id="myservice"
fault="faultHandler(event)" source="productList"
destination="zend">
<mx:method name="getProducts"
result="resultHandler(event)" />
</mx:RemoteObject>
FEATURE
import mx.rpc.events.FaultEvent;
private function faultHandler(fault:FaultEvent):void
{
trace("code:\n" + fault.fault.faultCode + "\n\
nMessage:\n" + fault.fault.faultString + "\n\
nDetail:\n" + fault.fault.faultDetail);
}
What Now?
You have now successfully built a desktop RIA
using Adobe AIR and PHP. We covered the new
Zend_Amf_Server included in version 1.7 of the Zend
Framework and generated all the needed PHP code to
set up a server linked to a specific class. We then created an AIR application using Flex Builder that successfully talked to our PHP class. Now that you have
the basics, I would encourage you to explore and try
new things. There are endless possibilities of where this
technology can take you, so dive in and most importantly - have fun.
FEATURE
Optimizing Dojo
and
Zend Framework
Integration
In April 2008, Zend Framework announced a partnership with the Dojo Foundation
for delivering out-of-the-box Ajax and rich user interface support for Zend Framework
applications. This partnership came to fruition in August 2008 with the release of
version 1.6.0 of Zend Framework, the first release to ship with Dojo and built-in
support for Dojo.
REQUIREMENTS
PHP: 5.2.1+
Other Software: Zend Framework 1.6.0+, Dojo 1.1.0+
(optional)
Useful/Related Links:
http://framework.zend.com
http://dojotoolkit.org/
http://github.com/weierophinney/pastebin
As noted earlier, one hallmark of Dojo is its packaging system. Dojo defines a rich interface for defining
namespaced JavaScript classes and objects, as well as a
harness for loading them at will. As an example, if you
decided you wanted to use dijit.Dialog to pop up
a dialog message to your users, you can pull this in at
will:
dojo.require("dijit.Dialog");
LISTING 2
1.<code javascript>
2.var myDialog;
3.dojo.addOnLoad(function() {
4. myDialog = new dijit.Dialog({
5. title: "Hello, World!",
6. content: "This is the dialog content."
7. });
8. dojo.body().appendChild(myDialog.domNode);
9. myDialog.startup();
10.});
11.</code>
12.
FEATURE
FEATURE
Dijit-specific view helpers and form elements. Dijit provides a large number of UI
widgets; Zend_Dojo provides view helpers,
form elements, and form decorators corresponding to most layout and form dijits.
dojo.data support. dojo.data is a uniform
data-access layer used by a variety of Dojo
modules to abstract access to data stores
which may be in-memory data structures, files
on the server, or even dynamically generated
server-side content. Zend_Dojo_Data provides
the ability to create dojo.data-compatible
response payloads from your Zend Framework
applications.
JSON-RPC server implementation. Dojo
has led the efforts to create the JSON-RPC
specifications and has long had a JSON-RPC
client implementation. Zend Framework now
provides a JSON-RPC server implementation via Zend_Json_Server. This feature is
particularly useful when creating client-side
heavy applications that will be making many
XmlHttpRequests (XHR) to the server to retrieve data.
Dojo source distribution. In its minimal
distribution, Zend Framework does not ship
Dojo, but because it defaults to using an established CDN, all Dojo-specific functionality
will continue to work. In its full distribution,
Zend Framework provides a source distribution
of Dojo, which allows the end-user developer
to create custom builds of Dojo (more on that
later) as well as unit test their Dojo applications via Dojos DOH unit test framework.
LISTING 3
1.<code php>
2.<?php
3.$view->tabContainer()->captureStart('master');
4.$view->contentPane()->captureStart(
5. 'tab1',
6. array('title' => 'Tab 1')
7.);
8.?>
9.This is the content of tab 1.
10.<?php echo $view->form; ?>
11.And it contains a form.
12.<?php
13.echo $view->contentPane()->captureStop('tab1');
14.echo $view->contentPane('tab2', '', array(
15. 'href' => '/remote/source',
16. 'parseOnLoad' => true,
17.));
18.echo $view->tabContainer()->captureStop('master');
19.</code>
20.
LISTING 4
1.<code php>
2.// Using Zend_Dojo_Form:
3.$form = new Zend_Dojo_Form;
4.
5.// Extending Zend_Dojo_Form:
6.class My_Form extends Zend_Dojo_Form
7.{
8. public function init()
9. {
10. // ...
11. }
12.}
13.</code>
14.
A number of dijits for which Zend_Dojo provides integration are containers; they wrap other content. Rather
than require the developer to pass in the content via
a string or pre-generate it, these containers have the
ability to capture content. As an example, Listing 3
shows the creation of a TabContainer with several
ContentPanes; both dijits are containers, and this example shows multi-level capturing.
Note that when starting capturing, no echo statement is provided. You can echo when ending the capture, or simply assign the return value to a variable.
The second tab is an interesting case. It specifies
that its content should come from a remote source.
This is an easy way to lazy-load content and keep your
initial page loads slim.
Most often, unless you are using the various layout
dijits, you wont use the dijit view helpers; instead,
youll utilize the corresponding form elements and decorators (the latter actually consume the view helpers).
You can Dojo-enable an existing form object easily:
Zend_Dojo::enableForm($form);
FEATURE
FEATURE
$form->addElement('TextBox', 'name');
Each element has a variety of configuration keys mapping to methods that allow you to set specific dijit
parameters; this makes them a convenience over the
view helpers as your favorite IDE can provide hinting
for you. See Listing 5 for an example.
By default, all dijit elements have appropriate decorators that ensure the correct view helpers are utilized.
For your form, sub forms, and display groups, there are
also a variety of decorators corresponding to layout
dijits. This can give you the opportunity to build some
wizard-like forms. For instance, you might want to decorate your sub forms as ContentPanes and your form
with a TabContainer, giving you a multi-tab form as
shown in Listing 6.
Basically, if you are familiar with Zend_Form, using
Zend_Dojo_Form will be familiar. More importantly,
youll find that you wont need to learn much Dojo in
order to get some great looking, usable forms immediately.
Note: Dont forget to use a Dijit theme.
For Zend_Dojos form integration to render correctly,
you must remember to both inform the dojo() view
helper of the Dijit theme, as well as build a containing
element that has the dijit theme specified. See Listing
7 for an example view script.
addStylesheetModule() will set up the appropriate
CSS @import URL path for you (maps to dijit/themes/
tundra/tundra.css in this example), and the dojo()
view helper will then create a <style> tag with it. The
containing block then ensures that all content below it
is styled with the theme.
LISTING 5
1.<code php>
2.// Tell the element to use the proper case and trim filters:
3.$name->setLabel('Name:')
4. ->setPropercase(true)
5. ->setTrim(true);
6.
7.// Or, at creation:
8.$form->addElement('TextBox', 'textbox', array(
9. 'label' => 'Name:',
10. 'propercase' => true,
11. 'trim' => true,
12.));
13.</code>
14.
LISTING 7
1.<code php>
2.<?php
3.$this->dojo()->enable()
4. ->addStyleSheetModule('dijit.themes.tundra');
5.?>
6.<div class="tundra">
7. <?php echo $this->form; ?>
8.</div>
9.</code>
10.
LISTING 8
1.<code css>
2.@import url("../dijit.css");
3.@import url("Common.css");
4.
5.@import url("layout/ContentPane.css");
6.@import url("layout/TabContainer.css");
7.@import url("layout/AccordionContainer.css");
8.@import url("layout/SplitContainer.css");
9.@import url("layout/BorderContainer.css");
10.@import url("form/Common.css");
11./* ... */
12.</code>
13.
This does several things for you. First, you now have
a namespace for your custom JavaScript. Just like the
PHP project recommends prefixing your functions and
classes with a unique namespace, Dojo recommends
that you namespace your code via dojo.provide().
Second, you have now created the basis for your own
module simply by virtue of having a namespace.
Third, you now have a scope in which to list the dependencies for your application.
From here, the next step is to determine what those
dependencies may be. Lets say weve created a basic
authentication form using Zend_Dojo_Form. We can
then view source on that form, look in our HTML header, and may see something resembling Listing 9.
From here, well do two things. First, lets create
a CSS theme. Zend_Dojos convention is that when
38 | February 2009 www.phparch.com
LISTING 9
1.<code html>
2.<style>
3. @import url("/js/dijit/themes/tundra/tundra.css");
4.</style>
5.<script type="text/javascript" src="/js/dojo/dojo.js">
6.</script>
7.<script type="text/javascript">
8. dojo.require("dijit.form.Form");
9. dojo.require("dijit.form.ValidationTextBox");
10. dojo.require("dijit.form.Button");
11.</script>
12.</code>
13.
LISTING 10
1.<code javascript>
2.dojo.provide("custom._base");
3.function() {
4. dojo.require("dijit.form.Form");
5. dojo.require("dijit.form.ValidationTextBox");
6. dojo.require("dijit.form.Button");
7.}();
8.</code>
9.
FEATURE
"
You are not limited to only dojo.require() statements. This layer file can perform a variety of tasks
creating onLoad events, binding events to objects,
setting up module paths, declaring classes or extending
the base module, and more. Its an excellent place to
put common functionality that will be called throughout your site.
In our Zend Framework application, well now do a
little bootstrapping. First, we need to indicate that
were using a local Dojo installation; next, well indicate that were using a custom module; also, we need
to tell Dojo to load our custom theme; and finally, we
need to tell Dojo about our build layer.
$view->dojo()->setLocalPath('/js/dojo/dojo.js')
->registerModulePath('custom', '../
custom')
->addStylesheetModule('custom.themes.
site')
->addLayer('/js/custom/_base.js');
This will spit out Listing 11. At first glance, this looks
like more code. The benefits are in maintenance, in creating your build profile, and finally, as a result of the
custom build, in reducing the number of files included
in each request.
First, when it comes to maintenance, the above ensures several things. You can change CSS files in one
LISTING 12
1.<code javascript>
2.dependencies = {
3. layers: [
4. {
5. name: "../custom/_base.js",
6. dependencies: [
7. "custom._base",
8. ]
9. },
10. ],
11. prefixes: [
12. [ "dijit", "../dijit" ],
13. [ "custom", "../custom" ],
14. ]
15.}
16.</code>
17.
FEATURE
The Future
Right now, while Zend Frameworks Dojo integration
does a fantastic job of providing tools for rapidly developing Dojo-ized applications and provides the tools
necessary to create custom builds, at the time of this
writing, it does nothing to assist in creating these
builds. In the future, Zend Framework plans to create
a logging mechanism that will help automate the creation of custom layers and build profiles. This will allow
users to create build tasks that hook into them during
deployment, giving a simple, end-to-end solution for
creating dynamic, Dojo-driven user interfaces coupled
to your Zend Framework application.
Hopefully this article has given some insight
into the power of Dojos packaging and deployment solutions, as well as a starting point for hooking your Zend Framework applications to Dojo. The
Zend_Dojo manual pages provide additional information on the integration, and http://dojotoolkit.org and
http://dojocampus.org provide additional resources for
utilizing Dojo to its full potential.
LISTING 13
1.<code javascript>
2.dependencies = {
3. action: "release",
4. version: "1.2.1-custom",
5. releaseName: "custom",
6. loader: "default",
7. cssOptimize: "comments.keepLines",
8. optimize: "shrinksafe",
9. layerOptimize: "shrinksafe",
10. copyTests: false,
11. /* ... */
12.}
13.</code>
14.
FEATURE
FEATURE
with the luxury afforded to an artist with a plain canvas. No, he began with a network already in existence:
the Web. In an attempt to describe the way applications behave across that network, he conceived of a
Web with no constraints-the dark, formless cloud-and
began adding constraints to it, giving it shape. These
constraints became the core principles of REST.
Forget what you thought you knew about REST. Cast
it aside. Leave it at the door. Lets take a journey
through the Web, adding the constraints of the REST
style one-by-one as we move forward to see how the
Web-and REST-takes shape under these constraints.
The problem with many so-called RESTful services
is that they arent RESTful at all. Perhaps they exhibit
some of the traits of the REST style, but they miss the
point of many of the constraints. For an application
to take full advantage of the REST style, the entire
network on which the application runs must be RESTful.
This is because the REST style is intended for use in
network-based software applications. Calling a single
service RESTful is not enough because the service
by Ben Ramsey
Principles of REST
A network-based application is considered
RESTful when the following constraints are applied and none are broken.
Client-server: Provides full separation
of concerns
Stateless: Each request contains all of
the information necessary to be understood and processed; no shared context
exists between the client and server
(i.e. cookies, sessions)
Cache: Clients may reuse data that is
labeled as cacheable, improving network
efficiency
Uniform interface: Components
throughout the network share a uniform
interface
Resources: There are an infinite number
of resources, all of which have unique
addresses and share a common interface
for manipulation
Representations: A resource may be
represented by multiple media types,
and the representation is the primary
vehicle for a resources transfer of state
Hypermedia (Links): Resources should
be linked to other resources
Metadata: Describes the data contained
in the representation or other metadata
Layered: All components in the network can understand all requests as they
travel from client to server but they
cannot see beyond the current layer;
provides scalability and efficiency of
requests
Code-on-demand: Extends the functionality of the client with client-side
scripts, etc.
No State Allowed
The next constraint is that of statelessness.
Statelessness is an important part of the client-server
relationship. Every request from the client to the server
must contain all of the information needed for the
server to sufficiently process the request. That is, all
requests must be self-contained, or atomic. The client
cannot send a request that relies upon previous requests. Every request must be interpreted in isolation.
Of course, since the early days of the Web, developers have been breaking its RESTful nature by implementing state in the form of cookies. In PHP and other
web programming languages, even server-side sessions
are not RESTful because a cookie must still be set in
FEATURE
FEATURE
REST Vocabulary
Hypermedia: The use of media as elements of a hypertext system in which
elements are connected by links
Layer: An individual component within
the network; may be a client, server,
gateway, proxy, etc.
Representation: A media type (e.g. text/
html) used to communicate a change in
the state of the resource
Resource: Anything that has identity
RESTful: An application is said to be
RESTful when it adheres to the principles of the REST style
RESTafarian: An advocate or extreme
zealot of the REST style
FEATURE
Identity Matters
The first interface constraint, identification of resources, is often described as two separate topics when
discussing REST: resources and addresses. Yet, these
are one and the same in the context of the REST style,
since a resource must have an address. Another word
often used in the place of resource is noun.
Resources are all around. Take a look. I dare you.
"
FEATURE
LISTING 1
The second interface constraint is that of representations. Each resource has a representation such that the
client never requests the resource itself but a representation, or a concept, of that resource. This allows the
server to respond dynamically through content negotiation with a representation that satisfies the requesting
client. There is never a need to change the links to the
resource when the representation changes. The identity
remains the same, though the representation changes.
In the REST style, whenever actions are performed
on a resource, the client uses a representation of the
current state of that resource and transfers that representation to the server to communicate a change in
state. This is where the REST style gets its name. This is
representational state transfer: the act of manipulating
"
The client-server
relationship is the most
important constraint.
FEATURE
FEATURE
Security
Securing Software
& File Uploads
by Arne Blankerts
n December 2008, various big players in the IT security sector issued a serious and unusual warning:
Do not use Microsoft Internet Explorer. While the
majority of web developers would probably favor this
anyways, they did this for a different reason. Due to
unpatched security holes, which are actively exploited
already as so-called zero day exploits every user of
IE is in danger. This is nothing new to an experienced
user, but this time, the scenario has changed. Instead
of trying to lure users into visiting prepared websites,
as has been done in the past, todays attacks try to
exploit existing websites by automatically scanning
for XSS and SQL injection opportunities. When found,
these are used to inject the actual exploit code for the
Microsoft browser into these websites. Even though by
now, Microsoft has managed to produce a fix for the
current problem, there will always be security problems
in browsers. This scenario in mind, it becomes more
and more obvious how important it is to develop secure
web applications and keep all 3rd party applications
up-to-date.
Lets look at a few of the 3rd party applications:
The MediaWiki Foundation (see [1] in Related Urls)
released a new version to fix various XSS bugs and one
CSRF problem (versions 1.13.3 and 1.6.11 respectively,
users of older versions are encouraged to upgrade to at
least 1.13.3) in their free wiki application, making the
update a recommended release.
Also recommended for all users of PHP is the update
of the language itself. Version 5.2.8 contains various
bug fixes including some that do have a security-related background. If your code relies on magic_quotes
being enabled and your server currently runs on version
RELATED URLS
[1] http://lists.wikimedia.org/pipermail/mediawikiannounce/2008-December/000080.html
[2] http://www.hardened-php.net/suhosin/
Roundup
5.2.7, be advised that this release had broken
magic_quotes and has thus been pulled from distribution and should be upgraded as soon as possible to
5.2.8.
Using the latest versions does not guarantee protection against bad software design though. A very
problematic aspect in building a secure web application
seems to be the handling of file uploads. Probably the
worst mistake to make, from a security standpoint, is
the idea to store user-provided files within the document root of the webserver, allowing direct access from
the outside and by that, remote code execution. Blindly
trusting any kind of information provided by a remote
client is considered a bad idea for almost every use
case, but still, people often trust the mime-type information and original filename provided by the browser.
Instead of using the given mime-type, a secure upload
handler should run its own detection either by using
ext/fileinfo, the old mime functions, or, when run on
unix/linux, by manually executing the mime binary. A
good idea is to additionally install a virus scanner, and
thus make use of the hook provided by the suhosin security extension (see [2] in Related Urls) to automatically scan uploaded files even before granting access to
them in PHP.
The content of the user contributed file might not
be the only danger to the server or website user. There
is almost no limit in what can be used as a filename
in terms of characters. Thus, html tags could very well
be part of a filename in almost all operating systems.
So, using the provided name without any escaping, as
always, opens up the xss universe to any attacker with
upload privileges.
Summarizing, one could say that securely handling
file uploads is actually quite an easy task, assuming
some basic rules are applied: Do not store files in a location directly accessible by a remote user, do not trust
mime-type nor filename and, when possible, run a virus
scan before continuing the processing.
COLUMN
My Way or
the UNIX
Way
by Marco Tabini
exit(0);
perspective didnt interest me all that much. I didnt
want to useI wanted to understand, dissect, learn
and generally, get my hands dirty. After hearing so
many stories about lone programmers making money
hand over fist by selling scatological masterpieces
through the App Store, I figured I had to at least see
what the hubbub was all about.
Along the road to discovery, I stumbled upon a few
rather unhappy programmers who seem to think that
no App Store that sells virtual whoopee cushions for a
mere $0.99 could be taken seriously by serious development outfits who want to sell serious applications at
serious prices. On the surface, thats a fair pointas
I have two young children of my own, I do not need
technology to hear my fill of bodily noises on a daily
basis (on the other hand, if someone could come up
with technology capable of stopping said noises, Id be
all over it), and the App Store does seem to be overflowing with programs of questionable value. Whats
more, Apples insistence on being the ultimate arbiter
of whats fair game and what isnt, makes any significant investment in developing applications for the
Phone Formerly Known as as secure as investing the
American automotive industry.
Interestingly, the proliferation of simple, one-off applications has resulted in a strange fact: the iPhoney is,
in fact, an almost UNIX-like environment. I dont mean
this from a technical perspective, but from a philosophical one: just like under UNIX, each application is
designed to perform one task, and perform it as well as
it can. Whats really missing is the glue between applicationsin a shell, we have pipes, but on the iPuppy
the only way of channeling virtual farts from a whoopee
cushion app to the other is via URLs which are not that
well supported by the underlying operating system.
So, it seems to me that the Fruit Company has a
tough choice ahead of itself. On one hand, they could
raise the bar for getting into the App Store, or change
the store itself so that more complex applications sit in
their own space, well separated from the simpler ones.
On the other, they could foster the cooperation between applications and create a collaborative environment in which duplication just for the sake of duplication doesnt make nearly as much sense as it does
nowafter all, its worked for Unix, I dont see why it
shouldnt work for the Little Phone That Could.
COLUMN