Tải bản đầy đủ (.pdf) (67 trang)

Tài liệu Hello, Goodbye docx

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (3.42 MB, 67 trang )

JANUARY 2005
VOLUME IV - ISSUE 1
JANUARY 2005
VOLUME IV - ISSUE 1
www.phparch.com
The Magazine For PHP Professionals
TM

January 2005

PHP Architect

www.phparch.com
4
6 EDITORIAL
Hello, Goodbye
7 What’s New
24 Test Pattern
Shedding a Tier
by Marcus Baker
45 Product Review
Will the Best PHP IDE
Please Stand Up?
by Peter B. MacIntyre
56 Security Corner
SQL Injection
by Chris Shiflett
61 Tips & Tricks
Javascript Remote Scripting
with PHP


by John W. Holmes
65 exit(0);
The PHP Security Saga
by Marco Tabini
10 Generating OpenOffice.org
Documents with PHP
by Bård Farstad
18 Where in the World was that
Photo Taken?
by Ron Goff
30 Transliteration with PHP
by Derick Rethans
37 Akaar
Being Smarty with Smarty!
by Chirag Ahmedabadi
48 Iterators in PHP5
by Rami Kayyali
TABLE OF CONTENTS
II NN DD EE XX
php|architect
TM
Departments
Features

EEDDIITTOORRIIAALL
A
new year is upon us—and quite a few interesting things
have already happened. We just published our first book, for
example. The Zend PHP Certification Practice Test Book, which
I co-wrote with John Coggeshall, has just been unleashed on the

PHP community with (if I may unleash some personal pride)
extremely good results. In a separate—but far more important—
piece of news, PHP was named “language of the year 2004” by a
site that tracks language usage in the development community.
PHP 5 continues to plow along quickly and efficiently, with a new
point release scheduled for release soon that will introduce some
much-anticipated new functionality.
However you look at it, 2005 is poised to be a marquee year for
PHP. There is so much going on that I can hardly keep my head
around it and continue my daily activity here at php|a headquar-
ters (although I must say that the two weeks of vacation I took
around Christmas were very helpful in getting my head wrapped
around doing absolutely nothing. What a pleasant change of
pace…). On the other hand, 2004 was, in many ways a marquee
year for PHP as well. This just highlights the positive direction that
the language is taking, shaped in many ways by the vast amount
of work that everyone in the community—even those who can just
be found complaining on the mailing lists—has put into defining
its goals and needs.
Here at php|a, there are three important news items that I want
to share with you this month.
First of all, John W. Holmes, who has taken care of our Tips &
Tricks column since the very first issue, is leaving us. John is a
Captain in the U.S. Army, and his “day job” is keeping him way too
busy to deal with such a demanding column on a monthly basis. I
know you expected me to say this, but I really, really enjoyed work-
ing with John. He has the (unfortunately rare) ability to be techni-
cally accurate and linguistically clear—his writings were always as
pleasant to read as they were to edit. Luckily, the T&T column is
far from over—but more about that will have to wait for another

editorial. Thank you, John, and Godspeed.
Just to stay on the editorial front, we have a new column start-
ing this month, titled Test Pattern and penned by Marcus Baker. In
his column, Marcus will be dealing with the issue of proper soft-
ware design as applied to PHP development, from patterns, to tier-
ing, to testing. The goal of this column is to challenge you, dear
readers, not just to write more efficient, but also more beautiful
code—to make every single one of your applications a little work
of art that is well-thought-out, properly designed and executed
flawlessly. Marcus has an awesome job ahead of him, but, then
again, he is an awesome fellow, so I’m sure that you’ll enjoy his
writings.
Finally, you may have heard about some recent security issues
that have struck both PHP and PHP-based applications,
notably the popular forum software phpBB. The reaction to
these issues has been less than stellar, in my humble opinion,
January 2005

PHP Architect

www.phparch.com
6
php|architect
Volume IV - Issue 1
January, 2005
Publisher
Marco Tabini
Editorial Team
Arbi Arzoumani
Peter MacIntyre

Eddie Peloke
Graphics & Layout
Arbi Arzoumani
Managing Editor
Emanuela Corso
News Editor
Leslie Hill

Authors
Marcus Baker, Bård Farstad, Ron Goff,
Rami Kayyali, Andreas Koepke,
Peter MacIntyre, Derick Rethans,
Chirag Ahmedabadi
php|architect (ISSN 1709-7169) is published twelve times a year by
Marco Tabini & Associates, Inc., P.O. Box 54526, 1771 Avenue Road,
Toronto, ON M5M 4N5, Canada.
Although all possible care has been placed in assuring the accuracy of
the contents of this magazine, including all associated source code, list-
ings and figures, the publisher assumes no responsibilities with regards
of use of the information contained herein or in all associated material.
Contact Information:
General mailbox:

Editorial:
Subscriptions:
Sales & advertising:
Technical support:
Copyright © 2003-2004 Marco Tabini &
Associates, Inc. — All Rights Reserved
Hello, Goodbye

EE DD II TT OO RR II AA LL RR AA NN TT SS
TM
NNEEWW SSTTUUFFFF
January 2005

PHP Architect

www.phparch.com
7
What’s New!
php|architect launches php|
tropics
2005
Ever wonder what it's like to learn PHP in paradise? Well, this year we've decided to give
you a chance to find out!
We're proud to announce php|tropics 2005, a new conference that will take place between
May 11-15 at the Moon Palace Resort in Cancun, Mexico. The Moon Palace is an all-
inclusive (yes, we said all inclusive!) resort with over 100 acres of ground and 3,000 ft. of
private beach, as well as excellent state-of-the-art meeting facilities.
As always, we've planned an in-depth set of tracks for you, combined with a generous
amount of downtime for your enjoyment (and your family's, if you can take them along
with you).
We even have a very special early-bird fee in effect for a limited time only.
For more information, go to
/>.
Zend Technologies Unveils Integrated Software Platform
Zend has announced the unveiling of Zend Platform 1.1
Zend Technologies, Inc., creator and ongoing innovator of PHP, products and services supporting the
development, deployment and management of PHP-based applications, today unveiled Zend Platform 1.1.
The newest member in the Zend family of products is the first integrated software platform that supports

the reliability, scalability and interoperability requirements of business critical PHP applications. The prod-
uct was developed based on direct feedback from hundreds of Zend customers currently using Zend prod-
ucts to develop and manage corporate applications, and is currently in use at Zend customer sites. Zend
Platform adds a wide range of new functionality that speeds time to production and improves end user
satisfaction by increasing the overall performance of enterprise applications. Zend Platform 1.1 is available
immediately.
"As PHP matures and evolves, the need for an integrated solution for building and deploying business
critical applications becomes more relevant," said Pamela Roussos, vice president of marketing at Zend.
Zend Platform is the first comprehensive lifecycle management solution for PHP users and is the only
next generation infrastructure product that directly supports the development and deployment of busi-
ness critical enterprise PHP applications. The feedback from customers was critical in our development of
this solution, and directly addresses the needs in our user community."
For more information visit:
hhttttpp::////wwwwww zzeenndd ccoomm
The Zend PHP Certification Practice Test Book is now available!
We're happy to announce that, after many months of hard work, the Zend PHP
Certification Practice Test Book, written by John Coggeshall and Marco Tabini, is now
available for sale from our website and most book sellers worldwide!
The book provides 200 questions designed as a learning and practice tool for the
Zend PHP Certification exam. Each question has been written and edited by four
members of the Zend Education Board the very same group who prepared the
exam. The questions, which cover every topic in the exam, come with a detailed
answer that explains not only the correct choice, but also the question's intention,
pitfalls and the best strategy for tackling similar topics during the exam.
For more information, visit
hhttttpp::////wwwwww pphhppaarrcchh ccoomm//cceerrtt//mmoocckk__tteessttiinngg pphhpp
NN EE WW SS TT UU FF FF
NNEEWW SSTTUUFFFF
January 2005


PHP Architect

www.phparch.com
8
struts4php 1.0.4_20041212
struts4php.org has announced the latest release of struts4php. The developers of struts4php released a new version of the well-known
frameworks with numerous bugfixes and improvements.
The development team has also released a new website for better information and communication purposes.
New is the possibility to download struts4php in the current version as PEAR Package under
hhttttpp::////wwwwww ssttrruuttss44pphhpp oorrgg//ppeeaarr//ssttrruuttss44pphhpp ccuurrrreenntt ttggzz
For more information visit:
hhttttpp ////wwwwww ssttrruuttss44pphhpp oorrgg
Check out some of the hottest new releases from PEAR.
PEAR 1.3.4
PEAR 1.3.4 fixes a serious problem caused by a bug in all versions of PHP that caused multiple registration of the shutdown function of
PEAR.php, makes pear help listing more useful by putting the how-to-use info at the bottom of the listing, and several bug fixes.
Net_Monitor 0.0.7
A unified interface for checking the availability services on external servers and sending meaningful alerts through a variety of media if
a service becomes unavailable.
I18Nv2 0.10.0
This package provides basic support to localize your application, like locale based formatting of dates, numbers and currencies.
Beside that it attempts to provide an OS independent way to
sseettllooccaallee(())
and aims to provide language, country and currency names
translated into many languages.
Net_FTP 1.3.0RC2
Net_FTP allows you to communicate with FTP servers in a more comfortable waythan the native FTP functions of PHP do. The class
implements everything nativly supported by PHP and additionally features like recursive up- and downloading, dircreation and chmod-
ding. It although implements an observer pattern to allow for example the view of a progress bar.
PHP_Fork 0.2.0

PHP_Fork class. Wrapper around the
ppccnnttll__ffoorrkk(())
stuff with a API set like Java language.
Practical usage is done by extending this class, and re-defining the
rruunn(())
method.
[see basic example]
This way PHP developers can enclose logic into a class that extends PHP_Fork, then execute the
ssttaarrtt(())
method that forks a child
process. Communications with the forked process is ensured by using a Shared Memory Segment; by using a user-defined signal and
this shared memory developers can access to child process methods that returns a serializable variable.
The shared variable space can be accessed with the two methods:
• void setVariable($name, $value)
• mixed getVariable($name)
$$nnaammee
must be a valid PHP variable name;
$$vvaalluuee
must be a variable or a serializable object.
Resources (db connections, streams, etc.) cannot be serialized and so they’re not correctly handled.
Requires PHP build with
——eennaabbllee ccllii ——wwiitthh ppccnnttll ——eennaabbllee sshhmmoopp
.
Only runs on *NIX systems, because Windows lacks of the pcntl ext.
Php 4.3.10 and 5.0.3 Released
The PHP Development Team would like to announce the immediate release of PHP 4.3.10 and PHP 5.0.3. These are maintenance
releases that in addition to non-critical bug fixes address several very serious security issues. All Users of PHP are strongly encouraged
to upgrade to one of these releases as soon as possible.
For changes since PHP 4.3.9, please consult the PHP 4 ChangeLog. For changes since PHP 5.0.2, please consult the PHP 5 ChangeLog.
For more information, visit

hhttttpp::////wwwwww pphhpp nneett
NNEEWW SSTTUUFFFF
January 2005

PHP Architect

www.phparch.com
9
MySQL Query Browser 1.1.5
MySQL.com announces the latest relase of the MySQL Query Browser. MySQL.com claims: ” MySQL Query
Browser is the easiest visual tool for creating, executing, and optimizing SQL queries for your MySQL
Database Server. The MySQL Query Browser gives you a complete set of drag-and-drop tools to visually
build, analyze and manage your queries.”
For more information or to download, visit:
hhttttpp::////wwwwww mmyyssqqll ccoomm//pprroodduuccttss//qquueerryy bbrroowwsseerr
PHP awarded programming language of 2004
A new post on php.net announces PHP being awarded programming language of the
year.
PHP has been awarded the Programming Language of 2004, according to the TIOBE
Programming Community Index. This index uses information collected from the popu-
lar search engines, and are based on the world-wide availability of skilled engineers,
courses and third party vendors. Congratulations to us all!
For more information visit:
wwwwww pphhpp nneett
eAccelerator 0.9.1
eAccelerator announces their latest
release 0.9.1.
What is it? The eAccelerator sourceforge
page describes it as: ” a further development from mmcache PHP Accelerator &
Encoder. It increases [the] performance of PHP scripts by caching them in compiled

state, so that the overhead of compiling is almost completely eliminated.”
Get more information from
hhttttpp::////eeaacccceelleerraattoorr ssoouurrcceeffoorrggee nneett//HHoommee
.
Looking for a new PHP Extension? Check out some of the lastest offerings from PECL.
WinBinder 0.34.117
WinBinder is a new extension that allows PHP programmers to build native Windows
applications. It wraps the Windows API in a lightweight, easy-to-use library so that
program creation is quick and straightforward.
mailparse 2.1
Mailparse is an extension for parsing and working with email messages.
It can deal with rfc822 and rfc2045 (MIME) compliant messages.
newt 0.3
PHP-NEWT - PHP language extension for RedHat Newt library, a terminal-based win-
dow and widget library for writing applications with user friendly interface. Once this
extension is enabled in PHP it will provide the use of Newt widgets, such as windows,
buttons, checkboxes, radiobuttons, labels, editboxes, scrolls, textareas, scales, etc.
Use of this extension if very similar to the original Newt API of C programming lan-
guage.
ssh2 0.4.1
Provides bindings to the functions of libssh2 which implements the SSH2 protocol.
libssh2 is available from
hhttttpp::////wwwwww ssoouurrcceeffoorrggee nneett//pprroojjeeccttss//lliibbsssshh22
phpMyFAQ 1.5.0 Alpha 2
phpmyfaq.de announces “The second alpha version of phpMyFAQ 1.5.0 is available. This ver-
sion is PHP5 compatible and introduces a faster template engine. LDAP support is now a selec-
table option and the traditional Chinese and Japanese language files were updated. Beside
some code improvements we fixed a lot of bugs. Do not use this version in production systems, but test this version and report bugs!”
Get the latest info from
pphhppmmyyffaaqq ddee

.
with the blame bucket being
passed around several hands
rather than focusing everyone’s
energy on ensuring not only
that bugs would be fixed, but
that people would be properly
informed and made aware of
them.
For my part, I’ve decided that
we should help with what we
know how to do best: inform-
ing people. On January 1st (talk
about a New Year resolution!),
we started a new mailing list
dedicated exclusively to PHP
security. You can read more
about it in this month’s exit(0)
column (which you’ll find at
the end of the magazine), so I
won’t bore you here by dupli-
cating the details. I simply
hope that the mailing list will
help everyone keep security
more in check; PHP has
become so popular that we can
no longer afford to hide
beneath the folds of the Web
and hope that no-one will find
out about any of our weakness-

es—they will, and we must be
ready to deal with the conse-
quences.
Until next month, happy read-
ings!
Editorial
Hello Goodbye
Continued
Getting started
Before we get started with the actual coding, we need
to get an overview of the format we are working with.
OpenOffice.org documents are XML files stored inside
ZIP archives. In the list below, you can see the directo-
ry structure of the files inside an OpenOffice.org docu-
ment. When you unzip this document, you will simply
get some plain XML files and directories.
.
|— META-INF
| `— manifest.xml
|— content.xml
|— meta.xml
|— mimetype
|— settings.xml
`— styles.xml
Of course, in order to generate an OpenOffice.org doc-
ument, we need to perform this process in reverse and
create a ZIP file from the XML files that we create. In
this article, I will show you exactly how you can use PHP
to produce all the different files required to form a valid
OpenOffice.org Write document.

The files shown in the example above are the bare
minimum required to make up a document that
OpenOffice.org will recognize as valid. If you, for exam-
ple, have embedded an image inside your document,
then this is also stored as a separate file in a folder
named
PPiiccttuurreess
(not shown above).
The
ccoonntteenntt xxmmll
file contains the actual text in your
document. Headers, paragraphs, lists and tables are
recorded in an XML format for content that is well doc-
umented, unlike the formats used by competitors like
Microsoft Word. This is the file on which this article will
focus for most of the time.
The
ssttyylleess xxmmll
file contains the definition of the
fonts, colors, sizes and other stylistic elements used by
the document. To draw a parallel with HTML, this
would be the equivalent of a CSS file, while
ccoonntteenntt xxmmll
would be the equivalent of the HTML document to
which the stylesheet applies.
mmeettaa xxmmll
contains “meta” information about the doc-
ument. In this file, you can, for example, find the name
of the document, its keywords and statistics like the
total number of words that it contains. You can also

store meta information, like Dublin Core, in
mmeettaa xxmmll
.
PHP 4.3+
OS Any
Other Software N/A
Code Directory office
January 2005

PHP Architect

www.phparch.com
FFEEAATTUURREE
10
Generating OpenOffice.org
Documents with PHP
by Bård Farstad
As you might know, OpenOffice.org is getting more and
more users. This article will show you how you can gener-
ate documents from PHP that the Writer component of
OpenOffice.org can read. It’s a follow up to the author’s
previous article, which appeared in the October 2004
issue of php|architect and dealt with extracting informa-
tion from OpenOffice documents.
FF EE AA TT UU RR EE
REQUIREMENTS
FFEEAATTUURREE
Generating OpenOffice.org Documents with PHP
January 2005


PHP Architect

www.phparch.com
11
Dublin Core is a meta data standard that defines a
generic set of attributes used to describe a specific
piece of information.
SSeettttiinnggss xxmmll
is actually intended for the
OpenOffice.org editor itself. It’s used to store GUI set-
tings and, since this has nothing to do with content, we
are not going to look into how we can store arbitrary
settings into this file.
MMaanniiffeesstt xxmmll
is a simple XML file that contains a ref-
erence to each file that makes up the document. The
type of the document is stored in the
mmiimmeettyyppee
file,
which contains a single line with the MIME denomina-
tion of the document’s type, such as, for example,
“application/vnd.sun.xml.writer” for a Writer file.
Getting the Content Right
Since the most important part of our document is
(obviously) its content, I will start by showing you how
we can generate a minimal
ccoonntteenntt xxmmll
file. As you can
see in Listing 1, after the document type definitions we
get to the main element,

ooffffiiccee::ddooccuummeenntt ccoonntteenntt
,
which, in turn, contains optional elements like
ooffffiiccee::ssccrriipptt
,
ooffffiiccee::ffoonntt ddeeccllss
and
ooffffiiccee::aauuttoo
mmaattiicc ssttyylleess
. In our example, they are empty.
The
ooffffiiccee::bbooddyy
element contains the document’s
contents themselves, but, before we get into its details,
we should also mention the
tteexxtt::sseeqquueennccee ddeeccllss
ele-
ment, which is used for numbering items in the docu-
ment and defining in which order different items are
numbered. In our sample document, I have just sup-
plied the default order.
Immediately after the sequence declaration, we insert
our actual content in the
ooffffiiccee::bbooddyy
element. In this
minimal document, I have just added a small para-
graph that displays the text “Hello World!”
Paragraphs and Inline Styles
The most common element that is usually added a doc-
ument is a simple paragraph. In the code snipped

below, you can see the basic syntax of a minimal para-
graph:
<text:p text:style-name=’Standard’>Hello
World!</text:p>
Notice that the namespace prefix
tteexxtt
is used. This is
used for all textual elements in the document—which
makes it very simple to extract all textual information
from it. The paragraph is also styled with the
SSttaannddaarrdd
style. The definition of this style can be found in the in
the
ssttyylleess xxmmll
file.
If you need to add whitespace in your text, you can
use the
tteexxtt::ss
element. This is the spacing element:
you define how many characters this space takes up in
the
tteexxtt::cc
attribute. See the example below for a sim-
ple space definition which takes up 4 characters:
<text:s text:c=”4”/>
Inside paragraphs, you normally have formatting ele-
ments like bold, italic and underline. In
OpenOffice.org, these styles do not have any matching
tags—a
tteexxtt::ssppaann

tag to which different styles are
attached is used instead. All unique spans are given a
style name with the
tteexxtt::ssttyyllee nnaammee
attribute. The def-
inition of these styles if actually found in the
ccoonntteenntt xxmmll
files under the
ooffffiiccee::aauuttoommaattiicc ssttyylleess
1 <?xml version=’1.0’ encoding=’UTF-8’?>
2 <!DOCTYPE office:document-content PUBLIC ‘-//OpenOffice.org//DTD OfficeDocument1.0//EN’ ‘office.dtd’>
3 <office:document-content xmlns:office=’
4 xmlns:style=’
5 xmlns:text=’ />6 xmlns:table=’
7 xmlns:draw=’
8 xmlns:fo=’
9 xmlns:xlink=’
10 xmlns:number=’
11 xmlns:svg=’
12 xmlns:chart=’
13 xmlns:dr3d=’
14 xmlns:math=’
15 xmlns:form=’
16 xmlns:script=’
17 office:class=’text’
18 office:version=’1.0’>
19 <office:script/>
20 <office:font-decls/>
21 <office:automatic-styles/>
22 <office:body>

23 <text:sequence-decls>
24 <text:sequence-decl text:display-outline-level=’0’ text:name=’Illustration’/>
25 <text:sequence-decl text:display-outline-level=’0’ text:name=’Table’/>
26 <text:sequence-decl text:display-outline-level=’0’ text:name=’Text’/>
27 <text:sequence-decl text:display-outline-level=’0’ text:name=’Drawing’/>
28 </text:sequence-decls>
29 <text:p text:style-name=’Standard’>Hello World!</text:p>
30 </office:body>
31 </office:document-content>
Listing 1
element. To make some text bold, we therefore first
need to create a definition of the style, for example like
the one shown below:
<office:automatic-styles>
<style:style style:name=”T1” style:family=”text”>
<style:properties fo:font-weight=”bold”/>
</style:style>
</office:automatic-styles>
Every style that is part of the automatic styles group is
defined with the
ssttyyllee::ssttyyllee
element and given a
unique name. Its properties are set using the
ssttyyllee::pprrooppeerrttiieess
element—that is, the same way as all
styles are defined in
ssttyylleess xxmmll
. In our style, we simply
defined the
ffoo::ffoonntt wweeiigghhtt

to be
bboolldd
. This is the basic
definition of bold text.
Once we have created a style definition for it, we can
use the T1 style to mark bold text as such. We simply
add a span element around the text we want to affect
and set the style name to
TT11
. Below, you see an exam-
ple of how we mark text as being bold in our content:
<text:p text:style-name=’Standard’>Here are
<text:span text:style-name=”T1”>some bold
text.</text:span></text:p>
Headers
Headers are important parts of any document, as they
are used to structure content. They are defined at the
same level as paragraphs using the
tteexxtt::hh
element. As
with all other text elements, you define the style of the
element separately. In addition, you need to define the
level of the header using the
tteexxtt::lleevveell
attribute. For
example, here’s an example of a Level-1 header ele-
ment. To create a header with another level you simply
change the level and style attribute.
<text:h text:style-name=”Heading 1” text:level=”1”>A
header</text:h>

Images
Of course, any nice-looking document contains images.
The OpenOffice.org document format is a collection of
files, and images are no exception. You need to put any
image you want displayed in your documents in a sub-
directory called
PPiiccttuurreess
. This image, in turn, needs to
be referenced in the
ccoonntteenntt xxmmll
file. You can place
images inside paragraphs using the
ddrraaww::iimmaaggee
ele-
ment. The XML code below shows a typical image ele-
ment:
<draw:image draw:style-name=’fr1’
draw:name=’Graphic1’
text:anchor-type=’paragraph’
svg:width=’4inch’
svg:height=’3inch’
draw:z-index=’0’
xlink:href=’#Pictures/myimage.jpg’
xlink:type=’simple’
xlink:show=’embed’
xlink:actuate=’onLoad’/>
For a simple centered image, we do not have to worry
about all the attributes of this node, but what we do
need to take care of is the
ssvvgg::wwiiddtthh

and
ssvvnn::hheeiigghhtt
attributes, which define how large the image is when it
is displayed in the document. We also need to supply
the path to the image, which is relative from the root
of your document package; this is done with the
xxlliinnkk::hhrreeff
attribute.
In order to calculate the size of the image, we need
to translate pixels into inches. To do so, we must find
the size of the image in pixels, which can be done (for
example) using the
ggeettiimmaaggeessiizzee(())
standard PHP func-
tion. We also need the DPI (dot-per-inch) settings for
the image. For example, 75 is a common setting for
low-resolution images. If you use a high quality printer
or publisher, images usually need to be at least 300DPI.
Once we know how many dots (which in our case is the
same as pixels) we have, we can easily calculate the size
of the image in inches. The formula for this is:
Size in inches = pixel width/DPI
For example, a 300-pixel-wide image printed at 75DPI
will be 300 / 75 = 4 inches wide. The same calculation
is used for the height. In PHP, the size calculation can
be done as shown below.
$fileName = “/path/to/myimage.jpg”;
$sizeArray = getimagesize( $fileName );
$width = $sizeArray[0] / 75;
$height = $sizeArray[1] / 75;

Note that this is just one example. You can also use the
EXIF extension to retrieve the number of DPI.
Lists
You may also want to have some lists inside your docu-
ment. These are placed at the same level as paragraphs
and headers in your the content XML file. You can have
both unordered and ordered lists using the
tteexxtt::uunnoorrddeerreedd lliisstt
and
tteexxtt::oorrddeerreedd lliisstt
elements
respectively. The list contains one or more
tteexxtt::lliisstt
iitteemm
elements, which, in turn, enclose the content for
each list item—normally, just a paragraph with some
text inside, but (at least in theory) as complex as you
need it to be. The XML snippet below shows an
unordered list containing two elements. You can see
that lists, like all other block elements, are also styled
with the
tteexxtt::ssttyyllee nnaammee
attribute. OpenOffice.org
normally uses
LL11
,
LL22
, and so on for naming list styles,
but that’s just an arbitrary convention you can choose
to ignore in favour of your own flavour if you like.

<text:unordered-list text:style-name=”L1”>
<text:list-item>
January 2005

PHP Architect

www.phparch.com
FFEEAATTUURREE
12
Generating OpenOffice.org Documents with PHP
FFEEAATTUURREE
Generating OpenOffice.org Documents with PHP
January 2005

PHP Architect

www.phparch.com
13
<text:p text:style-name=”P1”>Item text</text:p>
</text:list-item>
<text:list-item>
<text:p text:style-name=”P1”>Second
item</text:p>
</text:list-item>
</text:unordered-list>
Writing the XML file
We have now looked at how we can build the
ccoonn
tteenntt xxmmll
file, which is the most important portion of

our document. In fact, if we do not care about what
styles are used, the only thing we have to worry about
is the content file—and use just a set of standard tem-
plates for the remainder ofthe document
components.
In my previous article about OpenOffice.org and PHP,
I showed how you can use PHP to parse the XML files
using a standard PHP DOM XML parser and XSLT trans-
formations. We can also use a DOM XML library to gen-
erate our XML documents, but, in this article, I will use
a much simpler approach: we’ll just write the XML text
directly to a file.
In my production code, I also do not use a DOM
library to generate the XML, since doing so would
make the code quite a bit slower. My code, in fact, is as
simple as the one shown in the snippets below.
Essentially, I place the XML code making up our
ccoonn
tteenntt xxmmll
file in a variable and then write it to disk. In
the code snippet below, for example, I named the vari-
able
$$ccoonntteennttXXMMLL
:
$contentXML = “<?xml version=’1.0’ ”;
$fileName = “path/to/content.xml”;
$fp = fopen( $fileName, “w” );
fwrite( $fp, $contentXML );
fclose( $fp );
You can see a complete (but still simple) XML docu-

1 <?xml version=’1.0’ encoding=’UTF-8’?>
2 <!DOCTYPE office:document-content PUBLIC ‘-//OpenOffice.org//DTD OfficeDocument1.0//EN’ ‘office.dtd’>
3 <office:document-content xmlns:office=’
4 xmlns:style=’
5 xmlns:text=’ />6 xmlns:table=’
7 xmlns:draw=’
8 xmlns:fo=’
9 xmlns:xlink=’
10 xmlns:number=’
11 xmlns:svg=’
12 xmlns:chart=’
13 xmlns:dr3d=’
14 xmlns:math=’
15 xmlns:form=’
16 xmlns:script=’
17 office:class=’text’
18 office:version=’1.0’>
19 <office:script/>
20 <office:font-decls/>
21 <office:automatic-styles>
22 <style:style style:name=”T1” style:family=”text”>
23 <style:properties fo:font-weight=”bold”/>
24 </style:style>
25 </office:automatic-styles>
26 <office:body>
27 <text:sequence-decls>
28 <text:sequence-decl text:display-outline-level=’0’ text:name=’Illustration’/>
29 <text:sequence-decl text:display-outline-level=’0’ text:name=’Table’/>
30 <text:sequence-decl text:display-outline-level=’0’ text:name=’Text’/>
31 <text:sequence-decl text:display-outline-level=’0’ text:name=’Drawing’/>

32 </text:sequence-decls>
33 <text:h text:style-name=”Heading 1” text:level=”1”>A header</text:h>
34 <text:p text:style-name=’Standard’>Hello World!</text:p>
35 <text:p text:style-name=’Standard’>Some spaces: <text:s text:c=”4”/></text:p>
36 <text:p text:style-name=’Standard’>Here are <text:span text:style-name=”T1”>some bold text.</text:span></text:p>
37 <text:p text:style-name=’Standard’>
38 <draw:image draw:style-name=’fr1’
39 draw:name=’Graphic1’
40 text:anchor-type=’paragraph’
41 svg:width=’4inch’
42 svg:height=’3inch’
43 draw:z-index=’0’
44 xlink:href=’#Pictures/myimage.jpg’
45 xlink:type=’simple’
46 xlink:show=’embed’
47 xlink:actuate=’onLoad’/>
48
</text:p>
49 <text:unordered-list text:style-name=”L1”>
50 <text:list-item>
51 <text:p text:style-name=”P1”>Item text</text:p>
52 </text:list-item>
53 <text:list-item>
54 <text:p text:style-name=”P1”>Second item</text:p>
55 </text:list-item>
56 </text:unordered-list>
57 </office:body>
58 </office:document-content>
Listing 2
January 2005


PHP Architect

www.phparch.com
FFEEAATTUURREE
14
Generating OpenOffice.org Documents with PHP
ment for
ccoonntteenntt xxmmll
in Listing 2.
If you are using PHP 5, you can actually save quite a
few lines of code by using the
ffiillee__ppuutt__ccoonntteennttss(())
function instead of opening and writing to the file man-
ually. An example of this approach is shown in the code
snippet below. This little script performs the same oper-
ation as the first example: first, it opens the file; then
writes the contents to it, and finally closes it—it just
does so with only two lines of code. We do not need to
make it any harder than this, and we’ll use the same
technique to generate the other XML files that are part
of our document as well.
$contentXML = “<?xml version=’1.0’ ”;
file_put_contents( “path/to/content.xml”, $contentXML
);
Styling our Document
If you want to introduce your own custom design ele-
ments in your document, you’ll need to work with the
ssttyylleess xxmmll
file. As mentioned earlier, this is where you

define fonts, colors, sizes and positions, and so on.
Let’s use headers as an example. In Listing 3, you can
see a minimal
ssttyylleess xxmmll
file containing the style defi-
nition for “Header 1.” Our style definitions are placed
directly under the
ooffffiiccee::ssttyyllee
element.
A style is defined with the element
ssttyyllee::ssttyyllee
. Each
style needs a unique name, which is set by using the
ssttyyllee::nnaammee
attribute. The
ssttyyllee::ffaammiillyy
attribute, on
the other hand, defines the type of style used. For
headers, we use paragraph styles, since headers are
rendered basically in the same way as a paragraph.
Every style has a “parent” style, which is used as a base
to set the underlying “defaults” of the style. The parent
style is defined with the
ssttyyllee::ppaarreenntt ssttyyllee nnaammee
attribute. Finally the last attribute in our style definition
is
ssttyyllee::ttyyppee
, which, in our case is just “text”.
The actual properties of the style, such as font size
and color, are defined in the

ssttyyllee::pprrooppeerrttiieess
element,
which is a child of
ssttyyllee::ssttyyllee
. In our example, we
have defined the font size with the
ffoo::ffoonntt ssiizzee
ele-
ment, the font weight as bold with the
ffoo::ffoonntt wweeiigghhtt
attribute and, finally, the color with the
ffoo::ccoolloorr
attrib-
ute. The color is defined in a hex triplet—that’s the
same way as you define colors in CSS and HTML, which
is something you’re probably familiar with.
The Manifest
The
mmaanniiffeesstt xxmmll
file contains information about all the
files that make up the document. This is an XML file
with two basic elements. The main node, called
mmaannii
ffeesstt::mmaanniiffeesstt
, contains one element for each file. The
1 <?xml version=’1.0’ encoding=’UTF-8’?>
2 <!DOCTYPE office:document-styles PUBLIC ‘-//OpenOffice.org//DTD OfficeDocument 1.0//EN’ ‘office.dtd’>
3 <office:document-styles xmlns:office=’
4 xmlns:style=’
5 xmlns:text=’

6 xmlns:table=’
7 xmlns:draw=’
8 xmlns:fo=’
9 xmlns:xlink=’
10 xmlns:number=’
11 xmlns:svg=’
12 xmlns:chart=’
13 xmlns:dr3d=’
14 xmlns:math=’
15 xmlns:form=’
16 xmlns:script=’
17 office:version=’1.0’>
18 <office:styles>
19 <style:style style:name=’Heading 1’
20 style:family=’paragraph’
21 style:parent-style-name=’Heading’
22 style:next-style-name=’Text body’
23 style:class=’text’>
24 <style:properties fo:font-size=’115%’
25 fo:font-weight=’bold’
26 fo:color=’#555599’/>
27 </style:style>
28 </office:styles>
29 </office:document-styles>
Listing 3
1 <?xml version=’1.0’ encoding=’UTF-8’?>
2 <!DOCTYPE manifest:manifest PUBLIC ‘-//OpenOffice.org//DTD Manifest 1.0//EN’ ‘Manifest.dtd’>
3 <manifest:manifest xmlns:manifest=’ />4 <manifest:file-entry manifest:media-type=’application/vnd.sun.xml.writer’ manifest:full-path=’/’/>
5 <manifest:file-entry manifest:media-type=’’ manifest:full-path=’Pictures/’/>
6 <manifest:file-entry manifest:media-type=”image/gif” manifest:full-path=”Pictures/myimage.jpg”/>

7 <manifest:file-entry manifest:media-type=’text/xml’ manifest:full-path=’content.xml’/>
8 <manifest:file-entry manifest:media-type=’text/xml’ manifest:full-path=’styles.xml’/>
9 <manifest:file-entry manifest:media-type=’text/xml’ manifest:full-path=’meta.xml’/>
10 <manifest:file-entry manifest:media-type=’text/xml’ manifest:full-path=’settings.xml’/>
11 </manifest:manifest>
Listing 4
specific files are then defined using the
mmaanniiffeesstt::ffiillee
eennttrryy
element. The mimetype of each file is declared in
the
mmaanniiffeesstt::mmeeddiiaa ttyyppee
attribute, and its path with
mmaanniiffeesstt::ffuullll ppaatthh
. Listing 4 contains the
mmaanniiffeesstt xxmmll
file for our basic document with one
image.
Meta information
If we want to add meta information to our document,
we can store it in
mmeettaa xxmmll
. At a minimum, information
like document generator, creation date, number of
edits and document statistics is stored here. However,
you can store much more data in this file if you like. For
example, if you need to comply with the Dublin Core
meta data standard, you can store that information in
this file. You can see an example in Listing 5.
Settings

The
sseettttiinnggss xxmmll
file is only used by the
OpenOffice.org writer editor to remember which tool-
bars were open and which GUI settings the user had
enabled when a document was last being edited. Since
we won’t be doing any editing, we are not going to
look much into this document other than to generate a
very minimally valid version of it. Listing 6 shows the
minimal XML document for
sseettttiinnggss xxmmll
—you can
just hard-code this value in a variable and reuse it as
needed without worrying about it anymore.
Packing the Final Document
We have now looked at what kind of XML is used in all
the different files that make up an OpenOffice.org doc-
ument. The
ccoonntteenntt xxmmll
and
ssttyylleess xxmmll
files, in that
order, are by far the most important portions of the
document. I also showed you how you can simply
manipulate your XML in PHP without the aid of any
specialized library, so, if you have stored all the XML
files in one directory and done the same with your pic-
ture, we are ready to package our document. In fact, all
that’s left to do is to ZIP down all the files in this folder
and re-name the resulting file so that its extension is

ssxxww
. Voila!
The simplest way of creating the ZIP archive is to run
the
zziipp
command found on most operating systems
directly from PHP. This can be done by using the
eexxeecc(())
function in PHP to instantiate and execute the com-
mand directly from the directory where you have
stored the document files. The code snippet below
shows a simple way of changing to the directory where
you have stored the files and ZIP the latter down into
an OpenOffice.org writer file:
chdir( “path/to/files” );
exec( “zip -r /oo_document_name.sxw *” );
If you are not dynamically changing the contents of the
mmeettaa xxmmll
and
mmiimmeettyyppee
files, there is no reason to actu-
1 <?xml version=’1.0’ encoding=’UTF-8’?>
2 <!DOCTYPE office:document-meta PUBLIC ‘-//OpenOffice.org//DTD OfficeDocument 1.0//EN’ ‘office.dtd’>
3 <office:document-meta xmlns:office=’
4 xmlns:xlink=’
5 xmlns:dc=’
6 xmlns:meta=’
7 office:version=’1.0’>
8 <office:meta>
9 <meta:generator>PHP</meta:generator>

10 <meta:creation-date>2004-12-10T11:39:50</meta:creation-date>
11 <dc:date>2004-12-10T11:40:15</dc:date>
12 <dc:language>en-US</dc:language>
13 <meta:editing-cycles>3</meta:editing-cycles>
14 <meta:editing-duration>PT26S</meta:editing-duration>
15 <meta:user-defined meta:name=’Info 1’/>
16 <meta:user-defined meta:name=’Info 2’/>
17 <meta:user-defined meta:name=’Info 3’/>
18 <meta:user-defined meta:name=’Info 4’/>
19 <meta:document-statistic meta:table-count=’0’
20 meta:image-count=’0’
21 meta:object-count=’0’
22 meta:page-count=’1’
23 meta:paragraph-count=’1’
24 meta:word-count=’2’
25 meta:character-count=’10’/>
26 </office:meta>
27 </office:document-meta>
Listing 5
1 <?xml version=’1.0’ encoding=’UTF-8’?>
2 <!DOCTYPE office:document-settings PUBLIC ‘-//OpenOffice.org//DTD OfficeDocument 1.0//EN’ ‘office.dtd’>
3 <office:document-settings xmlns:office=’
4 xmlns:xlink=’
5 xmlns:config=’
6 office:version=’1.0’>
7 <office:settings />
8 </office:document-settings>
Listing 6
FFEEAATTUURREE
January 2005


PHP Architect

www.phparch.com
Generating OpenOffice.org Documents with PHP
15
ally generate them from PHP. In fact, even
mmaanniiffeesstt xxmmll
does not really need to be correct—I’ve happened to
create documents that did not have images properly
defined in the manifest and still worked fine. Of course,
however, you should generate these files correctly
every time in order to comply with the document
standard.
On Not Re-inventing the Wheel
If you want to get started quickly with OpenOffice.org
writer document generation, you do not necessarily
have to write the whole code yourself. There already
exist some libraries that can take care of the dirty work
for you. For example, the eZ publish content manage-
ment system has a library for generating
OpenOffice.org writer documents. This library is part of
the public extension libraries in the product.
PHPDocWriter is another library that enables you to
generate OpenOffice.org writer documents easily in
PHP. There are probably other libraries out there as
well, so you can decide for yourself if you want to write
your own generator or if you want to use an existing
one for your needs.
Use Cases

At this point, you should have a pretty good idea of
how you can generate an OpenOffice.org writer docu-
ment with PHP. As you can see, this is much more work
than simply typing up the document in
OpenOffice.org—except, of course, for those cases
where you can’t. A typical use case for this technology
is a CMS system that needs to export its content to a
standard document format, thus lowering the invest-
ment of time and money required to manipulate and
reuse it. This is the same method I used when writing
content export functionality from eZ publish to
OpenOffice.org.
The Future
The OpenOffice.org XML format will be changed in the
future. Currently, members of OASIS (Organization for
the Advancement of Structured Information Standards)
are working together on creating an open XML stan-
dard for office applications based on the existing
OpenOffice.org XML format. Their goal is to create an
even more generic content format that can be used by
different applications—even CMS systems are covered
by their mission statement. Since this new standard is
based on the OpenOffice.org XML file format, you
shouldn’t need massive changes to support it when it is
released. Some people even speculate that this format
can be adopted by Microsoft Word so that, in the
future, you will be able save your office application data
in the same format regardless of which application you
use. The Oasis Open Office XML format is currently
available as a draft that has been approved by the

OASIS Open Office Technical committee.
Final Words
We have now looked at how we can generate an
OpenOffice.org writer document containing the most
common formatting features used in word processing.
This article, of course, only touches the surface of what
you can store in a document by using the
OpenOffice.org XML file format, but, hopefully, it gives
you some ideas on how you can harness the power of
this open— source office suite in your own application.
Generating OpenOffice.org spreadsheets and presen-
tation documents is done in much the same way and,
by reading up on the specifications of each XML file for-
mat, you should be able to create your ownz in no
time.
January 2005

PHP Architect

www.phparch.com
FFEEAATTUURREE
16
Generating OpenOffice.org Documents with PHP
About the Author
?>
To Discuss this article:
/>Bård Farstad is one of the three co-founders of eZ systems. He has been
working professionally with CMS development since 1999 and is the
author of many general purpose libraries, such as an XML parser, SOAP
library (client/server) and an XML-RPC library (client/server). He is also

one of the main developers of the eZ publish CMS. In his spare time, he
likes to play with his daughter and play the guitar; he is also “aquascap-
ing,” the art of decorating aquaria. You can reach Bård via e-mail at
bbff@@eezz nnoo
.
Resources
OpenOffice.org homepage
hhttttpp::////ooppeennooffffiiccee oorrgg
OpenOffice.org XML file format
hhttttpp::////xxmmll ooppeennooffffiiccee oorrgg
eZ publish homepage
hhttttpp::////eezz nnoo
eZ publish public extension repository
hhttttpp::////zzeevv eezz nnoo//ssvvnn//eexxtteennssiioonnss//
PHP DocWriter
hhttttpp::////pphhppddooccwwrriitteerr ssoouurrcceeffoorrggee nneett//
Oasis Open Office XML Format
hhttttpp::////wwwwww ooaassiiss ooppeenn oorrgg//ccoommmmiitttteeeess//ttcc__hhoommee pphhpp??wwgg__aabbbbrreevv==ooffffiiccee

January 2005

PHP Architect

www.phparch.com
FFEEAATTUURREE
18
S
itting in his comfy fortieth-story office, he effort-
lessly presses a button, sending a tracking robot
into the sky from the roof of the huge sky scraper.

The robot swoops down towards the ground, stopping
just feet away from the top of its target, a late model
truck hauling some sort of cargo. The robot follows the
vehicle and takes a picture every few seconds; it then
sends the photos to the fortieth-story office using its
Wi-Fi antenna. When the photos are received, on a
computer monitor in the office a dot is placed on a
map showing where they were taken, tracking the tar-
get all the way to its destination.
Of course, this story is fiction—except for the images
that were taken. The images mentioned in the story
were encoded with the longitude and latitude received
from GPS satellites. With the advancement of digital
photography and GPS technology, we have now access
to these types of images.
I remember when I first saw a GPS device. It was
about six years ago, I was in an archeology class in col-
lege and the only one who could touch the device was
the teacher because it was so expensive. The device we
used in that class was very basic and only told the direc-
tion and longitude and latitude. We had to use it in the
shade because the LCD display was so dim. But, it was
cool to be able to use the device, because not many
people had them at the time. These days, GPS devices
are almost as cheap as free and are much more sophis-
ticated and wrapped in much smaller packages, and
you can actually see what’s on the LCD display right in
the sunshine. Because the space that a GPS device
needs to function has been reduced, they’re ending up
in very unusual but useful places.

More and more cell phones hit the market every
year—and every manufacturer is adding new technolo-
gy to their continually shrinking devices. One of the
more recent developments is the integration of GPS
into cell phones. Besides just being able to tell where
you are at any given second, this new feature opens
many doors for navigation and tracking with the
phone. It definitely gives a new meaning to the words
“big brother,” though.
Along with GPS has been the inclusion of a camera
into the phone. Sure, digital cameras have been in the
phones for a while, much longer than GPS, but with
the new feature a melding of the two has occurred. If
Ever wonder where a photo was taken? We’ve all seen
exotic or interesting photos, but really had no way of pin-
pointing their location. Now, with the marriage of GPS
and digital photography, we can know the exact location
of where our favorite photos were taken.
FF EE AA TT UU RR EE
Where in the World was that Photo
Taken?
by Ron Goff
PHP 4.1.2+
OS Any
Other Software GD 1.6.2+, Exifer 1.4
Code Directory photo
REQUIREMENTS
FFEEAATTUURREE
January 2005


PHP Architect

www.phparch.com
19
your phone is equipped with GPS and also has a digital
camera built into it, you should be able to send images
via email or even download them to your computer
later that have the latitude, longitude, direction and
even the speed at which the photo was taken attached
to it. The information is not visible on the photo itself,
but it actually gets embedded into the image’s headers
when the photo is taken. Since the information is in the
photos, it is just a mater of retrieving it from the image,
which you will then be able to plot on a map to show
where the photo was taken—just like in my fictional
short story above.
When I first heard about the GPS data included with
images from cell phones, I figured it was sent as a line
in an email, totally separate from the image. Some early
adopters of the technology did go this route, but for
the most part today the images actually have the GPS
information placed into the EXIF tags that are located
in the JPEG image that is sent.
What is EXIF?
Here’s a definition of EXIF:
Exchangeable image file format, a JPEG-encoded file
format for digital cameras that has similar tags to
TIFF.
Most of the digital, professional to cell-phone quality,
cameras on the market use this standard to include tags

in the headers that provide information about the
photo. Some are so detailed that they’ll give you the
type of camera, camera settings, resolution of the pic-
ture, time and date it was taken and a lot more. Having
these tags embedded into the photo will give the pho-
tographer or viewer the ability to know how and even
where the photo was taken and can be viewed at any-
time without having to go to a separate file.
The standard was actually created in 1995 by the
JEITA (Japan Electronic Informational Technology
Association) to standardize not only the way the image
was recorded, but also the attributes of the photo.
Since there is a standard, many programs that are not
related to any type of camera or brand can view these
headers and use the information for other applications.
You can even install and configure PHP with the ability
to view EXIF headers directly without using a third
party tool, which, incidentally, is what we’ll be doing in
a little while.
In this article, we’ll see how to pull out the longitude
and latitude from a photo’s EXIF headers using a library
called Exifer written by Jake Olefsky. We will then for-
mat the GPS information into a useable format, and
plot the location of the photo onto a world map.
The sample image that we are using (Figure 1) actu-
ally came from a professional digital camera. The pho-
tographer used a program to include in the EXIF head-
ers GPS information from a GPS handheld device which
recorded the location and time of the photographer
throughout his day of photography. If you get a photo

from a cell phone with GPS or from a professional dig-
ital camera that had the GPS info added later on, the
longitude and latitude will still be placed into the EXIF
headers in the same format.
Let’s Get Plotting
Before you get started, you will need to grab the latest
version of Exifer. I used version 1.4 for this example, at
hhttttpp::////wwwwww jjaakkeeoo ccoomm//ssooffttwwaarree//eexxiiff//
. This is the library
we will use to get the longitude and latitude informa-
tion. I chose this route because it was the simplest to
get up and running and doesn’t require any installation
or configuration of PHP apart from placing the files
onto your web server.
We will have to use some sort of library to parse
through and decode these EXIF tags. For the most part,
the tags are not in any human readable format. If you
go to the image and open it up in some sort of text edi-
tor you will see just a bunch of gibberish—not really
Where in the World was that Photo Taken?
Figure 1
Copyright © FreeFoto (
ffrreeeeffoottoo ccoomm
), Ian Britton. (A photograph of a com-
munications tower—but this photo is able to communicate other things
besides just the image.)
anything you will be able to work with.
The first listing (Listing 1) includes the
eexxiiff pphhpp
file

from the Exifer library so that we can pull the EXIF infor-
mation from our image. The
$$ppaatthh
variable indicates
where on our server the image is located. We will then
set the
$$vveerrbboossee
setting to zero. If verbose is set to one,
it will include the image’s raw output as well, which, in
our case, would just end up as extra overhead in the
array. Now the last line of the listing will actually grab
the EXIF tags from the image, read through them and
place them into an array from which we can then pull
out any of the information in a very easy way.
Included in the Exifer library is the ability to view a list
of all available information and attributes for a photo.
You can run the index file that is located with the Exifer
package—it basically reads and outputs to the screen
the array that is created from the
eexxiiff pphhpp
file.
Listing 2 actually calls out the longitude and latitude
from the photo. Most of the photos that have this infor-
mation will be formatted in
hhhh mmmm ssss
(hours, minutes
and seconds) and look something like (34 55.43 23.44)
when retrieved from the array. With our example
image, the format is just
hhhh mmmm

.
Listing 3 actually breaks the longitude and latitude
into an array of hours, minutes and seconds. Because
we get the longitude and latitude in this format, our
coordinates will need to be converted into just a string
of numbers with a decimal point—something like
(35.445845). Listing 4 takes each element of the array
and converts each of the sets of numbers to give us two
usable numbers to be able to plot on our world map.
The conversion method is as follows:
First the seconds are divided by 60
ss/60
Then we do the same to the minutes
mm/60
Then the minutes and seconds are added together
mm+ss
Then the hours are rounded to the nearest whole
number and, finally, the rounded hour is combined
January 2005

PHP Architect

www.phparch.com
FFEEAATTUURREE
20
$lats = $result[GPS][Latitude];
$lons = $result[GPS][Longitude];
Listing 2
$lat_ar = explode(“ “, $lats);
$lon_ar = explode(“ “, $lons);

$l_h = $lat_ar[0];
$l_m = $lat_ar[1];
$l_s = $lat_ar[2];
$lo_h = $lon_ar[0];
$lo_m = $lon_ar[1];
$lo_s = $lon_ar[2];
Listing 3
Where in the World was that Photo Taken?
Figure 2
include(“exif.php”);
$path=”image.jpg”;
$verbose = 0;
$result = read_exif_data_raw($path,$verbose);
Listing 1
FFEEAATTUURREE
January 2005

PHP Architect

www.phparch.com
21
with the minutes which were combined with the sec-
onds.
hh+mm
In listing 5, I have included my home town’s longi-
tude and latitude to plot on the map. This will also
serve as way to check the accuracy of the plotting. If
the dot on the map is not where it should be, you will
know something is wrong with the code or map. You
can, of course, change this information with your own

area’s longitude and latitude. Most of the map services
on the internet should allow you to translate your
address into longitude and latitude coordinates. I have
found that
hhttttpp::////wwwwww mmaappoorraammaa ccoomm
does include most
countries around the world and gives you the longi-
tude and latitude in an easy to read format along the
left side of their site.
Now we come to actually plotting the locations on a
map. There are many different ways to do so, but, for
this example, we will use one of the easiest and most
basic methods by taking advantage of what is called a
cylindrical projection map. You can use the same map I
used, or you can find your own cylindrical projection
map. The map can be larger or smaller and will it not
affect this code at all. Most of the cylindrical projection
maps will work, as long as they do not have any type of
border around them. Even the most simplistic border
could throw off the calculations in later listings. I have
tested this program using the abstract maps from
hhttttpp::////ffllaattppllaanneett ssoouurrcceeffoorrggee nneett//mmaappss//
and it works just
fine, even though the maps on this site or much bigger
than our example map.
Also, in listing 5 we will start to create our map. I use
the
iimmaaggeeccoolloorrrreessoollvvee
function to define my colors
because I found that it is more accurate than using the

iimmaaggeeccoolloorraallllooccaattee
with the map I have chosen. One
color,
$$rreedd11
, will be used for the dot that locates my
home town, while another,
$$rreedd22
, will be used to locate
where the photo was taken when we plot the two on
the map.
Where in the World was that Photo Taken?
$lat_ar = explode(“ “, $lats);
$lon_ar = explode(“ “, $lons);
$l_h = $lat_ar[0];
$l_m = $lat_ar[1];
$l_s = $lat_ar[2];
$lo_h = $lon_ar[0];
$lo_m = $lon_ar[1];
$lo_s = $lon_ar[2];
Listing 3
if($l_m != ‘’){
$l_m = $l_m/60;
}
if($l_h != ‘’){
$l_h = round($l_h);
}
if($l_s != ‘’){
$l_s1 = $l_s/60;
$l_mt = $l_m+$l_s1;
}else{

$l_mt = $l_m;
}
$lat = $l_h+$l_mt;
if($lo_m != ‘’){
$lo_m = $lo_m/60;
}
if($lo_h != ‘’){
$lo_h = round($lo_h);
}
if($lo_s != ‘’){
$lo_s1 = $l_s/60;
$lo_mt = $lo_m+$lo_s1;
}else{
$lo_mt = $lo_m;
}
$long = $lo_h+$lo_mt;
$long
= -$long;
$lat = $lat;
Listing 4
$lata = 32.78714;
$longa = -115.55937;
$im = imagecreatefromjpeg(“map.jpg”);
$red1 = imagecolorresolve ($im,255,5,5);
$red2 = imagecolorresolve ($im,255,5,0);
Listing 5
“ Think of design patterns as
the collected wisdom of
many programmers solving a
similar problem many times.


$width = imagesx($im);
$height = imagesy($im);
Listing 6
$x = (($long + 180) * ($width / 360));
$y = ((($lat * -1) + 90) * ($height / 180));
$xx = round($x);
$yy = round($y);
imagefilledrectangle($im,$xx-2,$yy-2,$xx+2,$yy+2, $red2);
Listing 7
January 2005

PHP Architect

www.phparch.com
FFEEAATTUURREE
22
Listing 6 grabs the dimensions of the image so that
we can use it in the math that is used to plot the loca-
tions.
Listing 7 is the method for getting an
xx
and
yy
position
to plot on the map using our previously-converted lon-
gitude and latitude coordinates from our photo and the
height and width dimensions of the map. It will then
create a red square on the map image where the loca-
tion of the photo was taken. Again, this is probably one

of the simplest and definitely not the only or best ways
of plotting a location onto a map.
Listing 8 uses the same method and creates a slight-
ly darker square to show my home town as a reference
point to check the accuracy of the plotting.
Listing 9 will now display the newly created map in
your browser. If everything goes to plan, you should see
the same results as Figure 2—a world map with the
location where the image was taken marked in the
United Kingdom. If you have replaced my home town’s
coordinates with yours, you should see another dot
locating your area; otherwise the dot should be around
the Mexico border. You may want to check the accura-
cy of the plotting against another mapping system like
hhttttpp::////ggeeooeennggiinnee nniimmaa mmiill//mmuussee ccggii bbiinn//rraasstt__rrooaamm ccggii
.
This site actually has a lot of useful world maps, as well
as black-and-white aerial photo maps taken from satel-
lites that you can plot coordinates onto and also down-
load in a high- or low-resolution format.
There are other ways of plotting maps and I would
definitely suggest locating some other ways to show
where the photos were taken. As you can see from the
map generated by our program, the results we obtain
only provide a general idea of where the image was
taken but, if the map did have the ability to zoom in,
the user would be able to see exactly where it was
taken. Many maps that you can find from the internet
are available in vector and raster versions and will
sometimes include additional geographical informa-

tion, such as streets and highways—using them will
definitely add more detail. I know that the Tiger map-
ping system (
hhttttpp::////ttiiggeerr cceennssuuss ggoovv//ccggii bbiinn//mmaappbbrroowwssee
ttbbll
) created by the US Census Bureau allows you to cre-
ate maps with very detailed information, but its data is
limited to the US. Using a more detailed map will
mean your user will be able to better pinpoint where
and how to get to the place where the image was
taken. You may also want to check out the article titled
“Webmapping with MapServer,” written by Rodrigo
Becke Cabral and published in the July 2004 issue of
php|architect.
And there you have a program whose capabilities are
similar to those mentioned in my short story above
(minus the cool flying robot). Now, you can take a road
trip with your GPS-enabled cell phone and take pictures
of all the cool roadside monuments and then make a
map showing where you’ve been and what you’ve
seen.
Examples
There are several sites out there that are dedicated to
mapping out where photos are taken. Most of these
sites or projects are strictly for entertainment and
experimentation purposes and very few have been
applied to the professional marketplace. One of the
best examples of using this technology is
hhttttpp::////wwwwww ggeeoossnnaappppeerr ccoomm
. This site is dedicated to pho-

tos that have GPS data. It plots all the photos uploaded
onto a world map and you merely scroll over to the sec-
tion of the world you would like see and click on an
image—a very good and entertaining use of the tech-
nology.
Another good example is the WWMX (World Wide
Media Exchange), which can be found at
hhttttpp::////wwwwww wwwwmmxx oorrgg
. This site is a little different because
you actually download an application that works with
the GPS logs—basically a file usually giving a GPS coor-
dinate every minute—that come from a GPS device. It
then matches the timestamp of the photos you have
taken with a coordinating time on the GPS log and
selects the appropriate location.
With this information on hand, it creates a map and
webpage on which the location where every photo was
taken is plotted. You then can take the map and web-
page and upload it to your own website. The users of
this system are primarily taking advantage of it for trav-
el logs and for showing others the path they took and
what they saw along the way.
Since cell phones were married to digital cameras, it
has been becoming more and more popular to create
blogs using images taken with your phone. Now, with
the integration of GPS, we are seeing a new level added
to the standard blog. Several of the moblog (mobile
blog) sites also allow you to click an image and locate
where that photo was taken.
Here is more of a professional use of this

technology (or of a form of it, at any rate). At
hhttttpp::////aarrccwweebb eessrrii ccoomm//sscc//aallbbuumm//iinnddeexx hhttmmll
, you are able
to view and locate images from all over the world. This
system actually translates the street address of the pho-
Where in the World was that Photo Taken?
$x = (($longa + 180) * ($width / 360));
$y = ((($lata * -1) + 90) * ($height / 180));
$xx = round($x);
$yy = round($y);
imagefilledrectangle($im,$xx-2,$yy-2,$xx+2,$yy+2, $red1);
Listing 8
header (“Content-type: image/jpeg”);
imagejpeg($im);
imagedestroy($im);
Listing 9
FFEEAATTUURREE
tographer into latitude and longitude. Even though it
works slightly differently from ours, it is still creating a
map with the location of the photo.
This, however, is probably my favorite
uses of the GPS-tagged images:
hhttttpp::////wwwwww ddoowwnnggooeess
tthheessyysstteemm ccoomm//ddeevvzzoonnee//eexxiifftteesstt//ffiinnaall//
. Users actually
email the images to the site from their cell phones and
the site reads the EXIF headers and plots the images
onto the map, which is limited to Tokyo. The map
allows the user to zoom in and see where the photo
was taken and also see the photo by clicking on the

location marker. I probably like this one the most
because they are actually using tagged cell phone
images and not adding the data to the photo at a later
time.
Final Thoughts
As you can see, there are quite a few people and com-
panies developing or toying around with this type of
technology in some form or other. A handful of these
sites have yet to tap into the full features that EXIF tags
provide. Having to input the GPS data separately is
redundant and could possibly be less accurate, espe-
cially if you do have a cell phone or device that records
this information into the photo it self.
It seems to me that GPS is becoming more and more
popular and will, I assume, be packaged with more and
more electronic products in the future. Today, we see
GPS technology placed into delivery trucks to track
drivers around town or across the state. Or, you can
have a device installed into your car that tracks it if it is
stolen. Having GPS in our lives helps us in so many
ways. It is definitely helpful when lost on a highway, or
even out on an uncharted trail. Being able to pinpoint
your location or at least know the general area where
you are is a great benefit.
Hopefully, this program, as well as the idea of using
GPS-embedded photos, has sparked your own imagi-
nation. I know I was quite intrigued with the possibili-
ties of the technology and uses that it might hold from
the very first time I saw it. The melding of GPS and dig-
ital images in cell phones is fairly new and its usefulness

has not been fully explored. It will be very interesting to
see where it goes in the future.
About the Author
?>
To Discuss this article:
/>Ron is the technical director/senior programmer for Conveyor Group
(
hhttttpp::////wwwwww ccoonnvveeyyoorrggrroouupp ccoomm
), a Southern-California based web
development firm. His responsibilities include technology development,
programming, IT and network management, strategic research, server
systems management (webmaster), and website projects leader.
Award-winning IDE for dynamic languages,
providing a powerful workspace for editing,
debugging and testing your programs. Features
advanced support for Perl, PHP, Python, Tcl and
XSLT, on Linux, Solaris and Windows.
Download your free evalutation at www.ActiveState.com/Komodo30
Where in the World was that Photo Taken?
January 2005

PHP Architect

www.phparch.com
TTEESSTT PPAATTTTEERRNN
24
L
ayering is essential. The only way our rather feeble
brains can cope with software development at all is
by a process of divide and conquer. This is because

bugs are easy to fix once you find them—but finding
them is the problem. If we can make a part of our code
completely unaware of the other parts, we know for
sure that any errors in it are local. Layering is the grand-
est expression of divide-and-conquer: it divides our
entire application into a very few pieces and declares
that each one can only be influenced by itself and, at
most, one other. In particular each layer can only see
the next one down.
This is easy to understand and works well. It’s no sur-
prise, then, that this technique has been applied to
complex enterprise applications and that there are lots
of layered systems to choose from. It also means, unfor-
tunately, that terminology has suffered. Layers are
sometimes called logical tiers, or just tiers. You also see
texts where “tiering” or layering is described as the sep-
aration of hardware, that is, the use of multiple servers.
Faced with this confusion and the need to fit an expla-
nation into a single article, I am going to have to punt.
My preferred solution in this arena is four layers, so I’ll
take as my starting point the one used by Eric Evans in
“Domain Driven Design” (published by Addison
Wesley).
Then we’ll prod and poke it.
The Four-Layer Architecture
As you can see in Figure 1, the layers in our model are
presentation, application, domain and infrastructure. If
you are not used to UML, then the tabbed boxes are
packages—they are, basically, big dollops of code. The
arrows show visibility, so that the application layer is

blissfully unaware of the presentation layer, for exam-
ple. To demonstrate the way the layers work, I am
going to use the very trivial example of a contact man-
ager. Firstly, let’s see what the presentation code would
look like for the single task of e-mailing someone:
<?php
$community = new Community();
$email = $community->mail($_GET[‘name’],
$_GET[‘title’],
$_GET[‘message’]);
?><html>
<head><title>Mail sent</title></head>
Shedding a Tier
by Marcus Baker
The four-layer, or four-tier, architecture is an
enterprise development classic. The trouble is
that, for small projects (or big simple ones) it is
complete overkill. What happens when we try to
simplify this layering?
TT EE SS TT PP AA TT TT EE RR NN
PHP 4.x +
OS Any
Other Software None
Code Directory tier
REQUIREMENTS
January 2005

PHP Architect

www.phparch.com

25
Shedding a Tier
<body>Message sent to <?= $_GET[‘name’]
?></body>
</html>
The method and style of interaction, or, in this case, the
lack thereof, is what makes up the presentation layer. If
you can imagine changing the way the application is
used—for example, switching to a GUI or a web servic-
es API—then anything that would change must go into
this layer. That’s actually a lot of stuff: it naturally
includes JavaScript, CSS, form parameters and the
HTML, but it also includes sessions and maintaining
authorization. After all, these will be different for, say, a
desktop application compared with a web one.
The presentation layer is allowed to interrogate the
application one, here represented by the
CCoommmmuunniittyy
class. Let’s look at that next:
class Community {

function mail($name, $title, $message) {
$finder = new PersonFinder();
$person = &$finder->findByName($name);
$contact = &$person->getEmail();
return $contact->send($title, $message);
}
}
I don’t have the space to build a complete four-layer
application at this point, so I am going to have to illus-

trate the ideas with code fragments from now on.
The application layer is the glue that binds all of the
components together. It’s all about actions written in a
language that the business stakeholders would under-
stand. The domain objects contain the more innate
business rules. An example of domain knowledge is
how the e-mail is sent. The application layer knows
nothing of this process, extra headers, formatting, and
so on. It just kicks off the domain code.
What makes something an application object and
what makes it a domain object is subtle. The distinction
comes about because applications change more fre-
quently, often in response to what users want from the
business. The knowledge of the business domain itself
is acquired more slowly and with a lot more effort. In
fact, so much effort goes into this process of discussion
between the developers and stakeholders that it is a
process known as “knowledge crunching.” By contrast,
the application code should tell a simple story of what
is going on. In our example, this boils down to finding
a person, getting a contact point from them and final-
ly sending the message. The grammar just then is
English, but the grammar of our code snippet is PHP
syntax.
In our example, I am choosing the
CCoommmmuunniittyy
class to
be part of the application layer, but I would expect
classes like
PPeerrssoonn

to be used in several applications
within an organization. Because of this, I think it’s safe
to assume then that
PPeerrssoonn
is a domain layer object.
Let’s look at a domain object next:
class Person {

function &getEmail() {
$query = new SelectQuery(‘contacts’);
$query->mustEqual(‘owner’, $this->id);
$query->mustEqual(‘media’, ‘email’);
$query->orderBy(‘preference’);
$rows = &$this->connection->select($query);
if ($row = $rows->next()) {
return new Contact($row);
}
}
}
There are business rules, even here in this trivial exam-
ple. Ordering by preference means that we are taking
the first of a possible list of contact points. Because
there are other ways to contact our people, we had to
specify a media, in this case e-mail. Unlike the applica-
tion layer example, we have some clutter caused by the
database access. We’ll take a broom to this in a little
while.
As we descend to the lowest infrastructure level, we
start to get to the nitty-gritty. The code the domain
object is using is stuff that could be common to any

organisation—library code if you will. Here is some
infrastructure code:
class Connection {

function &select($query) {
$sql = $query->asString();
$result = mysql_query($sql, $this->connec-
tion_id);
if (! $result) {
return false;
}
}
return new ResultSet(result);
}
TTEESSTT PPAATTTTEERRNN
“All a template engine really does is separate the visual formatting from the
remainder of the application—it does not, by itself, separate all of the pres-
entation logic. ”

Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Tải bản đầy đủ ngay
×