<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Grep My Mind &#187; Tips &amp; Tricks</title>
	<atom:link href="http://www.grepmymind.com/topics/tips-tricks/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.grepmymind.com</link>
	<description>Wonder what’s on my mind? Now you know.</description>
	<lastBuildDate>Thu, 11 Jun 2009 20:00:55 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Status 200 != OK?</title>
		<link>http://www.grepmymind.com/2009/06/11/status-200-ok/</link>
		<comments>http://www.grepmymind.com/2009/06/11/status-200-ok/#comments</comments>
		<pubDate>Thu, 11 Jun 2009 19:59:03 +0000</pubDate>
		<dc:creator>Michael Tougeron</dc:creator>
				<category><![CDATA[Internet]]></category>
		<category><![CDATA[SEO]]></category>
		<category><![CDATA[Tips & Tricks]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[200]]></category>
		<category><![CDATA[401]]></category>
		<category><![CDATA[404]]></category>
		<category><![CDATA[500]]></category>
		<category><![CDATA[503]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[HTTP status codes]]></category>
		<category><![CDATA[yahoo!]]></category>

		<guid isPermaLink="false">http://www.grepmymind.com/?p=333</guid>
		<description><![CDATA[When you think about SEO do you remember to think about how your website handles HTTP status codes? The odds are that you don&#8217;t. Your &#8220;page not found&#8221; probably returns a 404 (everyone knows about that one) but what about programmatic error pages or login pages? Search engines index pretty much anything that has a [...]]]></description>
			<content:encoded><![CDATA[<p>When you think about <a href="http://en.wikipedia.org/wiki/Search_engine_optimization">SEO</a> do you remember to think about how your website handles <a href="http://en.wikipedia.org/wiki/List_of_HTTP_status_codes">HTTP status codes</a>?  The odds are that you don&#8217;t.  Your &#8220;page not found&#8221; probably returns a <a href="http://en.wikipedia.org/wiki/HTTP_404">404</a> (everyone knows about that one) but what about programmatic error pages or login pages?  Search engines index pretty much anything that has a 200 status code.  This means if you don&#8217;t pay attention you can end up with pages indexed &#038; findable that shouldn&#8217;t be.</p>
<p>For example, if you are logged out, <a href="http://www.washingtonpost.com/newsletters/">Washington Post&#8217;s</a> newsletter page 302 redirects you to a login page that then serves a 200.  This means a <a href="http://www.google.com/search?q=newsletters+site%3Awashingtonpost.com">Google search for newsletters</a> for <a href="http://www.washingtonpost.com/">washingtonpost.com</a> gets indexed with the text from the login page.  If they were to serve a 401 &#8220;Unauthorized&#8221; on the pages that require logins, these login pages would not be indexed.  Use caution with that scenario though.  It might be better to handle search engines differently than normal users so the content can be indexed.</p>
<p><span id="more-333"></span>What if sometimes you need to take a feature offline (or even, godz forbid, the entire site) for maintenance/upgrades?  I assume you provide some sort of messaging to the users.  If that page serves a 200 status and Google happens to try to index during that time you get screwed by having all of that feature&#8217;s pages get indexed as a single page.  It is better to have the offline message page return a 503 status so the search engine knows that the service is temporarily unavailable and to try again later.</p>
<p>It is becoming more common for sites to capture a 404 and try to do a site search, or similar processing, for a possible match.  Frequently when this happens it is handled within the app code rather than having the web server deliver the default 404 page.  At GameSpot.com, the programmer who first set this up forgot to serve the 404 status code and was returning a 200.  This meant that when a duplicate game was deleted from the database, the links to it were still showing up on Google.  Once we made sure the code returned a status of 404 they went away next time Google indexed the site.</p>
<p>Finally, don&#8217;t forget about the 400 status code.  If you try to load phpBB&#8217;s forums with an <a href="http://www.phpbb.com/community/viewforum.php?f=dsfsdg">invalid forum id</a> it will return a 200 status code even though it is not a valid request.  This is a good situation to serve a 400 Bad Request.  Keep in mind that that you probably wouldn&#8217;t want to return a 400 if the forum id just doesn&#8217;t exist (e.g., http://www.phpbb.com/community/viewforum.php?f=123456) because it might exist at some point.  At the very least, return a 404.</p>
<p>As a side note, with HTTP/1.1 there is a new 307 status code that is very similar to how you&#8217;re used to using 302s.  It will probably be a few more years before HTTP/1.1 is the default for browsers &#038; the 307 will be truly usable. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.grepmymind.com/2009/06/11/status-200-ok/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How FriendFeed uses MySQL to store schema-less data &#8211; SF MySQL Meetup April 6th, 2009</title>
		<link>http://www.grepmymind.com/2009/03/28/how-friendfeed-uses-mysql-to-store-schema-less-data-sf-mysql-meetup-april-6th-2009/</link>
		<comments>http://www.grepmymind.com/2009/03/28/how-friendfeed-uses-mysql-to-store-schema-less-data-sf-mysql-meetup-april-6th-2009/#comments</comments>
		<pubDate>Sat, 28 Mar 2009 20:40:29 +0000</pubDate>
		<dc:creator>Michael Tougeron</dc:creator>
				<category><![CDATA[Events]]></category>
		<category><![CDATA[Internet]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Tips & Tricks]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[Bret Taylor]]></category>
		<category><![CDATA[FriendFeed]]></category>
		<category><![CDATA[SF MySQL Meetup]]></category>

		<guid isPermaLink="false">http://www.grepmymind.com/?p=326</guid>
		<description><![CDATA[When: 6:30pm Monday April 6th, 2009 Where: CBS Interactive &#8211; 235 2nd Street San Francisco, CA RSVP: How FriendFeed uses MySQL to store schema-less data Join the SF MySQL Meetup for our April meetup where Bret Taylor from FriendFeed talks about how they store their data in a &#34;schema-less&#34; system on top of MySQL. FriendFeed [...]]]></description>
			<content:encoded><![CDATA[<p>When: 6:30pm Monday April 6th, 2009<br />
Where: CBS Interactive &#8211; 235 2nd Street San Francisco, CA<br />
RSVP: <a href="http://mysql.meetup.com/30/calendar/9862949/">How FriendFeed uses MySQL to store schema-less data</a></p>
<hr />
<p>Join the <a href="http://mysql.meetup.com/30/">SF MySQL Meetup</a> for our April meetup where <a href="http://bret.appspot.com/" target="_blank">Bret Taylor</a> from <a href="http://friendfeed.com" target="_blank">FriendFeed</a> <a href="http://bret.appspot.com/entry/how-friendfeed-uses-mysql" target="_blank">talks about how they store their data in a &quot;schema-less&quot; system on top of MySQL</a>.  FriendFeed stores over 250 million entries and a bunch of other data, from comments and &quot;likes&quot; to friend lists.</p>
<p>As the database has grown, they have tried to iteratively deal with the scaling issues that come with rapid growth. They did the typical things, like using read slaves and <a href="http://en.wikipedia.org/wiki/Memcached" target="_blank">memcache</a> to increase read throughput and <a href="http://en.wikipedia.org/wiki/Sharding" target="_blank">sharding</a> our database to improve write throughput. However, as FriendFeed grew, scaling their existing features to accommodate more traffic turned out to be much less of an issue than adding new features.</p>
<p>In particular, making schema changes or adding indexes to a database with more than 10 &#8211; 20 million rows completely locks the database for hours at a time.  After some deliberation, FriendFeed decided to implement a &quot;schema-less&quot; storage system on top of MySQL rather than use a completely new storage system. This talk attempts to describe the high-level details of the system.</p>
<p><span id="more-326"></span></p>
<hr />
<p>Bret Tayler is one of the founders of FriendFeed.com.  Before starting FriendFeed, he was a Group Product Manager at Google, responsible for Google&#8217;s developer products. Before that, he launched Google Maps and Google Local, and before that he worked on Google&#8217;s crawling and indexing infrastructure.</p>
<hr />
Agenda:<br />
6:30 &#8211; 7:15 &#8212; Doors open/general socializing &amp; food provided by Sun Startup Essentials<br />
7:15 &#8211; 8:30 &#8212; Main presentation by Bret Taylor from FriendFeed<br />
8:30 &#8211; 9:00 &#8212; Main presentation Q&amp;A<br />
9:00 &#8211; 10:00 &#8212; General discussion/Q&amp;A/networking/etc.<br />
10:00ish &#8212; end of group</p>
]]></content:encoded>
			<wfw:commentRss>http://www.grepmymind.com/2009/03/28/how-friendfeed-uses-mysql-to-store-schema-less-data-sf-mysql-meetup-april-6th-2009/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Diving into the Yahoo! Open Stack &#8211; SF PHP Meetup April 2nd, 2009</title>
		<link>http://www.grepmymind.com/2009/03/11/diving-into-the-yahoo-open-stack-sf-php-meetup-april-2nd-2009/</link>
		<comments>http://www.grepmymind.com/2009/03/11/diving-into-the-yahoo-open-stack-sf-php-meetup-april-2nd-2009/#comments</comments>
		<pubDate>Wed, 11 Mar 2009 16:03:35 +0000</pubDate>
		<dc:creator>Michael Tougeron</dc:creator>
				<category><![CDATA[Events]]></category>
		<category><![CDATA[Internet]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Tips & Tricks]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[dustin whittle]]></category>
		<category><![CDATA[php meetup]]></category>
		<category><![CDATA[yahoo!]]></category>
		<category><![CDATA[yahoo! open stack]]></category>

		<guid isPermaLink="false">http://www.grepmymind.com/?p=319</guid>
		<description><![CDATA[When: 6:30pm Thursday April 2nd, 2009 Where: CBS Interactive &#8211; 235 2nd Street San Francisco, CA RSVP: Diving into the Yahoo! Open Stack Join the SF PHP Meetup for an exploration into the Yahoo! Open Stack and learn how to leverage Yahoo&#8217;s platforms and scalability to build your next application. We will examine the components [...]]]></description>
			<content:encoded><![CDATA[<p>When: 6:30pm Thursday April 2nd, 2009<br />
Where: CBS Interactive &#8211; 235 2nd Street San Francisco, CA<br />
RSVP: <a href="http://www.meetup.com/sf-php/calendar/9864926/">Diving into the Yahoo! Open Stack</a></p>
<hr />
Join the <a href="http://www.meetup.com/sf-php/">SF PHP Meetup</a> for an exploration into the <a href="http://developer.yahoo.com/" target="_blank">Yahoo! Open Stack</a> and learn how to leverage Yahoo&#8217;s platforms and scalability to build your next application. We will examine the components that make up Yahoo&#8217;s open stack: developer tools (<a href="http://developer.yahoo.com/yui/" target="_blank">YUI</a>), data apis (<a href="http://developer.yahoo.com/yql/" target="_blank">YQL</a>, <a href="http://developer.yahoo.com/search/boss/" target="_blank">BOSS</a>), social apis, and the application platform (<a href="http://developer.yahoo.com/yap/" target="_blank">YAP</a>).</p>
<ul>
<li>Overview
<ul>
<li>What is the Yahoo! Open Stack?
<ul>
<li>Developer Tools &#8211; YUI, Tutorials</li>
<li>YOS SDK for PHP</li>
</ul>
</li>
<li> Data APIs &#8211; YQL, BOSS &#8230;</li>
<li> Social APIs &#8211; Profiles, Connections, Updates, &#8230;</li>
<li> Application Platform
<ul>
<li> OpenSocial Support</li>
</ul>
</li>
</ul>
</li>
<li> How does it all work?
<ul>
<li> Development Workflow</li>
</ul>
</li>
<li> Building an open application with PHP and YOS</li>
<li> Common Problems &amp; Solutions
<ul>
<li> CAJA</li>
<li> OpenSocial</li>
</ul>
</li>
</ul>
<p><span id="more-319"></span></p>
<hr /><a href="http://www.linkedin.com/in/iamdustinwhittle" target="_blank">Dustin Whittle</a> is a Technical Yahoo! and Developer Evangelist for Yahoo&#8217;s Open Strategy. When he is not evangelizing Yahoo&#8217;s Open Stack, he helps develop it through his work on the Yahoo! Developer Network and Yahoo! Application Platform. Prior to his work helping create an open Yahoo!, he has contributed to Yahoo! Answers and Delicious. When not focused on Yahoo!, he is an active open source contributor for the <a href="http://symfony-project.com/" target="_blank">symfony project</a> and is a regular speaker at technical conferences around the world.</p>
<hr />
Agenda:<br />
6:30 &#8211; 7:15 &#8212; Doors open/general socializing &amp; food provided by Yahoo!<br />
7:15 &#8211; 8:30 &#8212; Main presentation by Dustin Whittle on the Yahoo! Open Stack<br />
8:30 &#8211; 9:00 &#8212; Main presentation Q&amp;A<br />
9:00 &#8211; 10:00 &#8212; General discussion/Q&amp;A/networking/etc.<br />
10:00ish &#8212; end of group</p>
]]></content:encoded>
			<wfw:commentRss>http://www.grepmymind.com/2009/03/11/diving-into-the-yahoo-open-stack-sf-php-meetup-april-2nd-2009/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>svn pre-commit &amp; post-commit hooks</title>
		<link>http://www.grepmymind.com/2009/03/07/svn-pre-commit-post-commit-hooks/</link>
		<comments>http://www.grepmymind.com/2009/03/07/svn-pre-commit-post-commit-hooks/#comments</comments>
		<pubDate>Sat, 07 Mar 2009 16:47:55 +0000</pubDate>
		<dc:creator>Michael Tougeron</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Tips & Tricks]]></category>
		<category><![CDATA[post-commit]]></category>
		<category><![CDATA[pre-commit]]></category>
		<category><![CDATA[svn]]></category>
		<category><![CDATA[svn commit hooks]]></category>
		<category><![CDATA[svn hooks]]></category>

		<guid isPermaLink="false">http://www.grepmymind.com/?p=311</guid>
		<description><![CDATA[I have to say I love subversion (svn) hooks.  I&#8217;ve only been playing around with the concept fairly recently and I&#8217;m surprised that I lasted this long without them.  I wanted to take a few minutes and share my favorite ways of using them.  As well as a few that I don&#8217;t use but I [...]]]></description>
			<content:encoded><![CDATA[<p>I have to say I love <a href="http://subversion.tigris.org/">subversion</a> (svn) hooks.  I&#8217;ve only been playing around with the concept fairly recently and I&#8217;m surprised that I lasted this long without them.  I wanted to take a few minutes and share my favorite ways of using them.  As well as a few that I don&#8217;t use but I think could be pretty helpful.</p>
<p>Before we keep going, if you don&#8217;t know what svn hooks are you can read up on them at <a href="http://svnbook.red-bean.com/en/1.1/ch05s02.html">http://svnbook.red-bean.com/en/1.1/ch05s02.html</a>.  svnbook.red-bean.com is my reference site of choice whenever I need to look up a svn command.</p>
<p>My #1, all-time, greatest in the world, bestest favorite is a svn pre-commit hook to syntax check my <a href="http://php.net">PHP</a> code.  There is nothing I hate more than a developer checking in code with syntax errors and breaking qa or stage or even, god-forbid, production.  It&#8217;s as easy as setting up the hook to run a script that calls &#8220;/path/to/php -l /path/to/file.php&#8221; and on failure reject the commit.  This way code that has syntax errors will never make it into SVN.  Now if only open-source projects like <a href="http://framework.zend.com/">ZendFramework</a> did something like this before releasing their code.  To be fair, the syntax errors are in their documentation not in the /library/ files but that&#8217;s still pretty dumb &amp; annoying.</p>
<p>Another nice way to use a post-commit hook is to run something like <a href="http://pear.php.net/package/PHP_CodeSniffer">PHP_CodeSniffer</a> against the commit.  CodeSniffer is an awesome <a href="http://pear.php.net">PEAR </a>package that scans your file and flags coding standards violations.  It comes pre-packaged with sniffers for the PHPCS, <a href="http://pear.php.net/manual/en/standards.php">PEAR</a>, <a href="http://squiz.net">Squiz</a> and  <a href="http://framework.zend.com/manual/en/coding-standard.html">Zend</a>.  Set it up to run and if it finds coding standard violations you can have the hook send out nasty little blame messages.  <img src='http://www.grepmymind.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />   This isn&#8217;t something that I&#8217;d want to run on pre-commit just in case you really need to get something into production NOW.  But if I hosted an open source project, <a href="http://pear.php.net/manual/en/package.php.php-codesniffer.svn-pre-commit.php">I&#8217;d consider it</a>.</p>
<p>Having minified JavaScript &amp; CSS has become the standard way of serving JS &amp; CSS.  But who really wants to take the time to minify or combine them?  Once again, enter svn hooks.  One of the developers set this up for <a href="http://www.gamespot.com/">GameSpot</a> and it has been working great!  Basically it checks the commits against a defined naming standard, file.src.js or file.src.css, and then runs the <a href="http://developer.yahoo.com/yui/compressor/">YUI! Compressor</a> on it and commits in file.min.(js|css).  He also made it check a global.conf in the file&#8217;s directory so it came mash up smaller js files into a global.min.js so we serve one file instead of ten.</p>
<p>Of course, let&#8217;s not forget about what is probably the most common svn hook; the post-commit email hook.  I like <a href="http://opensource.perlig.de/svnmailer/">svnmailer</a> better than <a href="http://subversion.tigris.org/tools_contrib.html#mailer_py">mailer.py</a> that comes with svn by default.  I think it&#8217;s easier to configure/change and to setup rules for how you want the emails to look or where to go.</p>
<p>If you&#8217;re using a ticket tracking system like <a href="http://www.bugzilla.org/">Bugzilla</a> or <a href="http://trac.edgewall.org/">Trac</a> that doesn&#8217;t have its own way of peeking into svn (like <a href="http://www.atlassian.com/software/jira/">JIRA</a> can with this <a href="http://confluence.atlassian.com/display/JIRAEXT/JIRA+Subversion+plugin">plugin</a>) you can write a post-commit hook to update the ticket when something is committed.  You can see how Trac recommends you do it at <a href="http://trac.edgewall.org/browser/trunk/contrib/trac-post-commit-hook">http://trac.edgewall.org/browser/trunk/contrib/trac-post-commit-hook</a>.</p>
<p>To help you on the way to creating your own svn hooks, tigris has a few <a href="http://subversion.tigris.org/tools_contrib.html#hook_scripts">hooks that are distributed</a> with svn.  They can be quite helpful so you should take a look at them.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.grepmymind.com/2009/03/07/svn-pre-commit-post-commit-hooks/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Memcached Q&amp;A and SEO for Developers &#8211; SF PHP Meetup Feb 12th, 2009</title>
		<link>http://www.grepmymind.com/2009/02/04/memcached-qa-and-seo-for-developers-sf-php-meetup-feb-12th-2009/</link>
		<comments>http://www.grepmymind.com/2009/02/04/memcached-qa-and-seo-for-developers-sf-php-meetup-feb-12th-2009/#comments</comments>
		<pubDate>Wed, 04 Feb 2009 19:33:55 +0000</pubDate>
		<dc:creator>Michael Tougeron</dc:creator>
				<category><![CDATA[Events]]></category>
		<category><![CDATA[Internet]]></category>
		<category><![CDATA[Tips & Tricks]]></category>
		<category><![CDATA[php meetup]]></category>
		<category><![CDATA[seo]]></category>

		<guid isPermaLink="false">http://www.grepmymind.com/?p=282</guid>
		<description><![CDATA[This month the SF PHP Meetup has two great speakers lined up. The first will be the intro talk/Q&#38;A given by Dormando on memcached. This will be less of a talk than an interactive Q&#38;A session about memcached. For the main presentation David Gomel, Senior Program Manager leading SEO within CBS Interactive, will speak to [...]]]></description>
			<content:encoded><![CDATA[<p>This month the SF PHP Meetup has two great speakers lined up.  The first will be the intro talk/Q&amp;A given by <a href="http://dormando.livejournal.com/">Dormando</a> on <a href="http://danga.com/memcached">memcached</a>.  This will be less of a talk than an interactive Q&amp;A session about memcached.</p>
<p>For the main presentation David Gomel, Senior Program Manager leading SEO within CBS Interactive, will speak to us about SEO in a Web 2.0 world.  The session will cover many of the important SEO issues that involve front and back-end engineers on a daily basis. Many of the decisions that tech folks make have the potential to materially impact search engine traffic. Even if you have been to a similar talk in the past, you should consider attending as we will be discussing topics that are frequently evolving. Please bring questions!</p>
<p>Topics will include:</p>
<ul>
<li> HTML fundamentals</li>
<li> CSS Usage</li>
<li> JavaScript/Flash/Ajax</li>
<li> Graceful Degradation</li>
<li> Multimedia Content</li>
<li> Duplicate Content</li>
<li> Redirection</li>
<li> URLs</li>
<li> Bot Traffic</li>
<li> Robots.txt</li>
</ul>
<p>&#8230;And More!</p>
<p>David Gomel is the Senior Program Manager leading SEO within CBS Interactive. He is responsible for SEO knowledge sharing and training within the company.</p>
<hr />When: <strong>6:30pm Thursday Feb 12th, 2009</strong><br />
Where: CBSi &#8211; <a href="http://maps.google.com/maps?f=q&amp;source=s_q&amp;hl=en&amp;geocode=&amp;q=235+2nd+Street,+San+Francisco,+CA&amp;sll=37.0625,-95.677068&amp;sspn=46.946584,114.257812&amp;ie=UTF8&amp;z=16">235 2nd Street San Francisco, CA</a><br />
RSVP: <a href="http://www.meetup.com/sf-php/calendar/9230626/">http://www.meetup.com/sf-php/calendar/9230626/</a></p>
<hr />Agenda:<br />
6:30 &#8211; 7:00 &#8212; Doors open/general socializing &amp; food<br />
7:00 &#8211; 7:30 &#8212; Intro talk on <a href="http://danga.com/memcached">memcached</a> by <a href="http://dormando.livejournal.com/">Dormando</a><br />
7:30 &#8211; 8:30 &#8212; Main presentation by David Gomel on SEO.<br />
8:30 &#8211; 9:00 &#8212; Main presentation Q&amp;A<br />
9:00 &#8211; 10:00 &#8212; General discussion/Q&amp;A/networking/etc.<br />
10:00ish &#8212; end of group</p>
]]></content:encoded>
			<wfw:commentRss>http://www.grepmymind.com/2009/02/04/memcached-qa-and-seo-for-developers-sf-php-meetup-feb-12th-2009/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Validating HTML with tidy</title>
		<link>http://www.grepmymind.com/2009/01/15/validating-html-with-tidy/</link>
		<comments>http://www.grepmymind.com/2009/01/15/validating-html-with-tidy/#comments</comments>
		<pubDate>Thu, 15 Jan 2009 20:41:32 +0000</pubDate>
		<dc:creator>Michael Tougeron</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[Tips & Tricks]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[html parsing]]></category>
		<category><![CDATA[tidy]]></category>
		<category><![CDATA[tidyhtml]]></category>

		<guid isPermaLink="false">http://www.grepmymind.com/?p=42</guid>
		<description><![CDATA[If you ever have to do HTML validation or parsing in PHP the tidy extension is the way to do it! This extension lets you use the abilities of tidy in some pretty powerful ways. The extension, written by John Coggeshall, has been around for several years now. I can see how if someone just [...]]]></description>
			<content:encoded><![CDATA[<p>If you ever have to do HTML validation or parsing in PHP the <a href="http://us2.php.net/manual/en/book.tidy.php">tidy extension</a> is the way to do it!  This extension lets you use the abilities of <a href="http://tidy.sourceforge.net/">tidy</a> in some pretty powerful ways.  The extension, written by <a href="http://www.coggeshall.org/">John Coggeshall</a>, has been around for several years now.  I can see how if someone just took a quick glance at it they could think it was nice, but not really something they need.  How wrong they would be!  If you take a few minutes and look under the hood, tidy is an extremely powerful tool.  Not only can it format html to standards (what most people use it for), it can also be a powerful parser and validation tool.</p>
<p>When I&#8217;m dealing with user inputted data where I want to allow HTML I have two concerns.  First, I don&#8217;t want to allow XSS (some xml parsers think &lt;p kkk=&#8221;&gt;&lt;/p&gt;&#8221; closes the &lt;p&gt; tag).  Second, the user frequently enters invalid html (e.g., doesn&#8217;t close the &lt;a&gt; tag).  Fortunately tidy can easily deal with both.  The second issue is the easiest to solve by running tidy-&gt;cleanRepair() on the html.  The first is taken care of by looping through the tidy nodes and rebuilding the html using a whitelist. More about how to do this after the break.  <span id="more-4"></span></p>
<p>To start, you&#8217;ll need to setup your <a href="http://tidy.sourceforge.net/docs/quickref.html">tidy options</a>.  I tend to use the following options.  The <a href="http://tidy.sourceforge.net/docs/quickref.html#word-2000">word-2000</a> option is great because it strips out all of the annoying html, css, etc. that Microsoft Word inserts for its formatting.</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1"><span class="re0">$config</span> = <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st0">&#8216;indent&#8217;</span> =&gt; <span class="kw2">false</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="st0">&#8216;output-xhtml&#8217;</span> =&gt; <span class="kw2">true</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="st0">&#8216;wrap&#8217;</span> =&gt; <span class="nu0">0</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="st0">&#8216;fix-uri&#8217;</span> =&gt; <span class="kw2">true</span>,</div>
</li>
<li class="li2">
<div class="de2">&nbsp; <span class="st0">&#8216;word-2000&#8242;</span> =&gt; <span class="kw2">true</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="st0">&#8216;show-body-only&#8217;</span> =&gt; <span class="kw2">true</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="st0">&#8216;drop-proprietary-attributes&#8217;</span> =&gt; <span class="kw2">true</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="st0">&#8216;ncr&#8217;</span> =&gt; <span class="kw2">false</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="st0">&#8216;drop-empty-paras&#8217;</span> =&gt; <span class="kw2">false</span>,</div>
</li>
<li class="li2">
<div class="de2">&nbsp; <span class="st0">&#8216;hide-endtags&#8217;</span> =&gt; <span class="kw2">true</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="st0">&#8216;lower-literals&#8217;</span> =&gt; <span class="kw2">true</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="st0">&#8216;markup&#8217;</span> =&gt; <span class="kw2">true</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="st0">&#8216;quote-ampersand&#8217;</span> =&gt; <span class="kw2">true</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="st0">&#8216;force-output&#8217;</span> =&gt; <span class="kw2">true</span><span class="br0">&#41;</span>;</div>
</li>
</ol>
</div>
<p>Add/Remove these options as it works best for you.  I&#8217;ve found that these work best for the cleaning &amp; repairing of accidentally invalid HTML.  Read the tidy docs for what each of these mean and how they affect what tidy does.  Please note that in the above options I include &#8220;force-output&#8221; so that I can display back to the user what the results of trying to fix the HTML is so that they can fix their input.</p>
<p>If you&#8217;re parsing user generated content, usually they are just entering the tags and HTML for the specific content they want posted.  This means you&#8217;ll need to wrap that input in the &lt;!DOCTYPE&gt;, &lt;HTML&gt; and &lt;BODY&gt; tags before processing it through tidy.</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1"><span class="co1">// Let&#8217;s initialize tidy with our HTML and config options.</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$tidy</span> = tidy_parse_string<span class="br0">&#40;</span><span class="re0">$html</span>, <span class="re0">$config</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// Not let&#8217;s clean &amp;amp; repair to try and &quot;fix&quot; user errors</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$tidy</span>-&gt;<span class="me1">cleanRepair</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2"><span class="co1">// Start tracking any errors at this point so we can give good feedback to the user</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">if</span> <span class="br0">&#40;</span>tidy_error_count<span class="br0">&#40;</span><span class="re0">$tidy</span><span class="br0">&#41;</span> &amp;amp;&amp;amp; <span class="re0">$tidy</span>-&gt;<span class="me1">errorBuffer</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="re0">$errors</span> = <a href="http://www.php.net/explode"><span class="kw3">explode</span></a><span class="br0">&#40;</span><span class="st0">&quot;<span class="es0">\n</span>&quot;</span>, <span class="re0">$tidy</span>-&gt;<span class="me1">errorBuffer</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw1">foreach</span> <span class="br0">&#40;</span> <span class="re0">$errors</span> <span class="kw1">as</span> <span class="re0">$key</span> =&gt; <span class="re0">$error</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re0">$errors</span><span class="br0">&#91;</span><span class="re0">$key</span><span class="br0">&#93;</span> = <a href="http://www.php.net/htmlentities"><span class="kw3">htmlentities</span></a><span class="br0">&#40;</span><span class="re0">$error</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// Once tidy has cleaned &amp;amp; repaired the initial user input</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// we need to loop through the object and validate each</span></div>
</li>
<li class="li2">
<div class="de2"><span class="co1">// HTML tag block. &nbsp;We will only need to do that though if</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// the $body actually has child tags</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$body</span> = <span class="re0">$tidy</span>-&gt;<span class="me1">body</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">if</span> <span class="br0">&#40;</span> <span class="re0">$body</span>-&gt;<span class="me1">child</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="co1">// we need to validate each HTML tag in the &lt;body&gt;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; <span class="co1">// validateTidyNode() will be called recursively for</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="co1">// any sub-tag blocks</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw1">foreach</span> <span class="br0">&#40;</span> <span class="re0">$body</span>-&gt;<span class="me1">child</span> <span class="kw1">as</span> <span class="re0">$key</span> =&gt; <span class="re0">$child</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re0">$error</span> = validateTidyNode<span class="br0">&#40;</span><span class="re0">$child</span>, <span class="re0">$new_html</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re0">$body</span>-&gt;<span class="me1">child</span><span class="br0">&#91;</span><span class="re0">$key</span><span class="br0">&#93;</span> = <span class="re0">$child</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; <span class="co1">// And of course track the errors as they</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="co1">// appear to give good feedback to the user</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> <span class="re0">$error</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="re0">$errors</span> = <a href="http://www.php.net/array_merge"><span class="kw3">array_merge</span></a><span class="br0">&#40;</span><span class="br0">&#40;</span><a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#41;</span><span class="re0">$errors</span>, <span class="br0">&#40;</span><a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#41;</span><span class="re0">$error</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">return</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st0">&#8216;html&#8217;</span> =&gt; <span class="re0">$new_html</span>, <span class="st0">&#8216;errors&#8217;</span> =&gt; <span class="re0">$errors</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">function</span> validateTidyNode<span class="br0">&#40;</span>&amp;amp;<span class="re0">$tidy_node</span>, &amp;amp;<span class="re0">$html</span>, <span class="re0">$allowed_tags</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; <span class="re0">$bad_tag</span> = <span class="kw2">false</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="co1">// If the node is text, just add the text to the HTML</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> <span class="re0">$tidy_node</span>-&gt;<span class="me1">type</span> == TIDY_NODETYPE_TEXT <span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re0">$html</span> .= <span class="re0">$tidy_node</span>-&gt;<span class="me1">value</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">return</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="co1">// If the node does not exist in your array of acceptable HTML tags</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="co1">// then track and error message and set the $bad_tag flag.</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw1">elseif</span> <span class="br0">&#40;</span> !<a href="http://www.php.net/array_key_exists"><span class="kw3">array_key_exists</span></a><span class="br0">&#40;</span><a href="http://www.php.net/strtolower"><span class="kw3">strtolower</span></a><span class="br0">&#40;</span><span class="re0">$tidy_node</span>-&gt;<span class="me1">name</span><span class="br0">&#41;</span>, <span class="re0">$allowed_tags</span><span class="br0">&#41;</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re0">$errors</span><span class="br0">&#91;</span><span class="br0">&#93;</span> = <span class="st0">&#8216;Tag: &#8216;</span> . <span class="re0">$tidy_node</span>-&gt;<span class="me1">name</span> . <span class="st0">&#8216; is not allowed and has been removed.&#8217;</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; <span class="re0">$bad_tag</span> = <span class="kw2">true</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> <span class="re0">$tidy_node</span>-&gt;<span class="me1">child</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re0">$html2</span> = <span class="st0">&#8221;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">foreach</span> <span class="br0">&#40;</span> <span class="re0">$tidy_node</span>-&gt;<span class="me1">child</span> <span class="kw1">as</span> <span class="re0">$key</span> =&gt; <span class="re0">$child</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; <span class="re0">$error</span> = validateTidyNode<span class="br0">&#40;</span><span class="re0">$child</span>, <span class="re0">$html2</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="re0">$tidy_node</span>-&gt;<span class="me1">child</span><span class="br0">&#91;</span><span class="re0">$key</span><span class="br0">&#93;</span> = <span class="re0">$child</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> <span class="re0">$error</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$errors</span> = <a href="http://www.php.net/array_merge"><span class="kw3">array_merge</span></a><span class="br0">&#40;</span><span class="br0">&#40;</span><a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#41;</span><span class="re0">$errors</span>, <span class="br0">&#40;</span><a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#41;</span><span class="re0">$error</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> <span class="re0">$bad_tag</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// I prefer to &quot;display&quot; the bad HTML tags so that the</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// user can see that it was not accepted. &nbsp;But you</span></div>
</li>
<li class="li2">
<div class="de2"><span class="co1">// may prefer to just strip the tag.</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co1">//&nbsp; &nbsp; $html .= &#8216; &#8216;;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re0">$html</span> .= <span class="st0">&#8216;&amp;amp;lt;&#8217;</span> . <span class="re0">$tidy_node</span>-&gt;<span class="me1">name</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw1">else</span> <span class="br0">&#123;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re0">$html</span> .= <span class="st0">&#8216;&lt;&#8217;</span> . <span class="re0">$tidy_node</span>-&gt;<span class="me1">name</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> <span class="re0">$tidy_node</span>-&gt;<span class="me1">attribute</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <a href="http://www.php.net/unset"><span class="kw3">unset</span></a><span class="br0">&#40;</span><span class="re0">$found_attribs</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="kw1">foreach</span> <span class="br0">&#40;</span> <span class="re0">$tidy_node</span>-&gt;<span class="me1">attribute</span> <span class="kw1">as</span> <span class="re0">$attrib_name</span> =&gt; <span class="re0">$attrib_value</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li2">
<div class="de2"><span class="co1">// verify that the tag is allowed to have the specified attribute.</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> !<a href="http://www.php.net/array_key_exists"><span class="kw3">array_key_exists</span></a><span class="br0">&#40;</span><a href="http://www.php.net/strtolower"><span class="kw3">strtolower</span></a><span class="br0">&#40;</span><span class="re0">$attrib_name</span><span class="br0">&#41;</span>, <span class="re0">$allowed_tags</span><span class="br0">&#91;</span><span class="re0">$tidy_node</span>-&gt;<span class="me1">name</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="st0">&#8216;attribs&#8217;</span><span class="br0">&#93;</span><span class="br0">&#41;</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$errors</span><span class="br0">&#91;</span><span class="br0">&#93;</span> = <span class="st0">&#8216;Tag &#8216;</span> . <span class="re0">$tidy_node</span>-&gt;<span class="me1">name</span> . <span class="st0">&#8216; is not allowed to have the attribute &#8216;</span> . <span class="re0">$attrib_name</span> . <span class="st0">&#8216; and has been removed.&#8217;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.php.net/unset"><span class="kw3">unset</span></a><span class="br0">&#40;</span><span class="re0">$tidy_node</span>-&gt;<span class="me1">attribute</span><span class="br0">&#91;</span><span class="re0">$attrib_name</span><span class="br0">&#93;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// validate the attribute&#8217;s value. &nbsp;We don&#8217;t want invalid values.</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$res</span> = validateHTMLTagAttribute<span class="br0">&#40;</span><span class="re0">$tidy_node</span>-&gt;<span class="me1">name</span>, <span class="re0">$attrib_name</span>, <span class="re0">$attrib_value</span>, <span class="re0">$allowed_tags</span><span class="br0">&#91;</span><span class="re0">$tidy_node</span>-&gt;<span class="me1">name</span><span class="br0">&#93;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> !<span class="re0">$res</span><span class="br0">&#91;</span><span class="st0">&#8216;remove&#8217;</span><span class="br0">&#93;</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$html</span> .= <span class="st0">&#8216; &#8216;</span> . <span class="re0">$res</span><span class="br0">&#91;</span><span class="st0">&#8216;attrib_name&#8217;</span><span class="br0">&#93;</span> . <span class="st0">&#8216;=&quot;&#8217;</span> . <span class="re0">$res</span><span class="br0">&#91;</span><span class="st0">&#8216;attrib_value&#8217;</span><span class="br0">&#93;</span> . <span class="st0">&#8216;&quot;&#8217;</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> <span class="re0">$res</span><span class="br0">&#91;</span><span class="st0">&#8216;errors&#8217;</span><span class="br0">&#93;</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$errors</span><span class="br0">&#91;</span><span class="br0">&#93;</span> = <span class="re0">$res</span><span class="br0">&#91;</span><span class="st0">&#8216;errors&#8217;</span><span class="br0">&#93;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> <a href="http://www.php.net/trim"><span class="kw3">trim</span></a><span class="br0">&#40;</span><span class="re0">$attrib_name</span><span class="br0">&#41;</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$found_attribs</span><span class="br0">&#91;</span><span class="br0">&#93;</span> = <span class="re0">$attrib_name</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// check to make sure that required attributes are set. &nbsp;e.g. &lt;img&gt; needs to have the src attribute</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> <span class="re0">$allowed_tags</span><span class="br0">&#91;</span><span class="re0">$tidy_node</span>-&gt;<span class="me1">name</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="st0">&#8216;attribs&#8217;</span><span class="br0">&#93;</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="kw1">foreach</span> <span class="br0">&#40;</span> <span class="re0">$allowed_tags</span><span class="br0">&#91;</span><span class="re0">$tidy_node</span>-&gt;<span class="me1">name</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="st0">&#8216;attribs&#8217;</span><span class="br0">&#93;</span> <span class="kw1">as</span> <span class="re0">$attrib_name</span> =&gt; <span class="re0">$attrib_settings</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> <span class="re0">$attrib_settings</span><span class="br0">&#91;</span><span class="st0">&#8216;required&#8217;</span><span class="br0">&#93;</span> &amp;amp;&amp;amp; <span class="br0">&#40;</span>!<span class="re0">$found_attribs</span> || !<a href="http://www.php.net/in_array"><span class="kw3">in_array</span></a><span class="br0">&#40;</span><span class="re0">$attrib_name</span>, <span class="re0">$found_attribs</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$errors</span><span class="br0">&#91;</span><span class="br0">&#93;</span> = <span class="st0">&#8216;Tag &#8216;</span> . <span class="re0">$tidy_node</span>-&gt;<span class="me1">name</span> . <span class="st0">&#8216; is required to have the attribute &#8216;</span> . <span class="re0">$attrib_name</span> . <span class="st0">&#8216;.&#8217;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li2">
<div class="de2"><span class="co1">// some tags require at least one of a set of attributes. &nbsp;e.g. &lt;a&gt; needs to have either the href or name attribute.</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> <span class="re0">$allowed_tags</span><span class="br0">&#91;</span><span class="re0">$tidy_node</span>-&gt;<span class="me1">name</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="st0">&#8216;required_attribs&#8217;</span><span class="br0">&#93;</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="re0">$attrib_found</span> = <span class="kw2">false</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> <span class="re0">$found_attribs</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">foreach</span> <span class="br0">&#40;</span> <span class="re0">$allowed_tags</span><span class="br0">&#91;</span><span class="re0">$tidy_node</span>-&gt;<span class="me1">name</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="st0">&#8216;required_attribs&#8217;</span><span class="br0">&#93;</span> <span class="kw1">as</span> <span class="re0">$attrib_name</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> <a href="http://www.php.net/in_array"><span class="kw3">in_array</span></a><span class="br0">&#40;</span><span class="re0">$attrib_name</span>, <span class="re0">$found_attribs</span><span class="br0">&#41;</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$attrib_found</span> = <span class="kw2">true</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> !<span class="re0">$attrib_found</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$errors</span><span class="br0">&#91;</span><span class="br0">&#93;</span> = <span class="st0">&#8216;Tag &#8216;</span> . <span class="re0">$tidy_node</span>-&gt;<span class="me1">name</span> . <span class="st0">&#8216; is required to have one of the following attributes: &#8216;</span> . <a href="http://www.php.net/implode"><span class="kw3">implode</span></a><span class="br0">&#40;</span><span class="st0">&#8216;, &#8216;</span>, <span class="re0">$allowed_tags</span><span class="br0">&#91;</span><span class="re0">$tidy_node</span>-&gt;<span class="me1">name</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="st0">&#8216;required_attribs&#8217;</span><span class="br0">&#93;</span><span class="br0">&#41;</span> . <span class="st0">&#8216;.&#8217;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> <a href="http://www.php.net/isset"><span class="kw3">isset</span></a><span class="br0">&#40;</span><span class="re0">$allowed_tags</span><span class="br0">&#91;</span><span class="re0">$tidy_node</span>-&gt;<span class="me1">name</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="st0">&#8216;settings&#8217;</span><span class="br0">&#93;</span><span class="br0">&#41;</span> &amp;amp;&amp;amp; !<span class="re0">$allowed_tags</span><span class="br0">&#91;</span><span class="re0">$tidy_node</span>-&gt;<span class="me1">name</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="st0">&#8216;settings&#8217;</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="st0">&#8216;require_close&#8217;</span><span class="br0">&#93;</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re0">$html</span> .= <span class="st0">&#8216; /&#8217;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> <span class="re0">$bad_tag</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li2">
<div class="de2"><span class="co1">//&nbsp; &nbsp; $html .= &#8216; &#8216;;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re0">$html</span> .= <span class="st0">&#8216;&amp;amp;gt;&#8217;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw1">else</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re0">$html</span> .= <span class="st0">&#8216;&gt;&#8217;</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="re0">$html</span> .= <span class="re0">$html2</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> <span class="re0">$bad_tag</span> || <span class="re0">$allowed_tags</span><span class="br0">&#91;</span><span class="re0">$tidy_node</span>-&gt;<span class="me1">name</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="st0">&#8216;settings&#8217;</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="st0">&#8216;require_close&#8217;</span><span class="br0">&#93;</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> <span class="re0">$bad_tag</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="re0">$html</span> .= <span class="st0">&#8216;&amp;amp;lt;/&#8217;</span> . <span class="re0">$tidy_node</span>-&gt;<span class="me1">name</span> . <span class="st0">&#8216;&amp;amp;gt;&#8217;</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">else</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="re0">$html</span> .= <span class="st0">&#8216;&lt;/&#8217;</span> . <span class="re0">$tidy_node</span>-&gt;<span class="me1">name</span> . <span class="st0">&#8216;&gt;&#8217;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; <span class="kw1">return</span> <span class="re0">$errors</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">function</span> validateHTMLTagAttribute<span class="br0">&#40;</span> <span class="re0">$tag_name</span>, <span class="re0">$attrib_name</span>, <span class="re0">$attrib_value</span>, <span class="re0">$tag_data</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="co1">// set to the unmodified version first. &nbsp;if modified, it will change at the end of the method.</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; <span class="re0">$res</span><span class="br0">&#91;</span><span class="st0">&#8216;attrib_name&#8217;</span><span class="br0">&#93;</span> = <span class="re0">$attrib_name</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="re0">$res</span><span class="br0">&#91;</span><span class="st0">&#8216;attrib_value&#8217;</span><span class="br0">&#93;</span> = <span class="re0">$attrib_value</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> !<span class="re0">$tag_data</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re0">$res</span><span class="br0">&#91;</span>errors<span class="br0">&#93;</span> = <span class="st0">&quot;$tag_name could not be found. &nbsp;Invalid tag/attribute.&quot;</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; <span class="kw1">return</span> <span class="re0">$res</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> <span class="re0">$tag_data</span><span class="br0">&#91;</span><span class="st0">&#8216;attribs&#8217;</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="st0">&#8216;unlimited_attribs&#8217;</span><span class="br0">&#93;</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re0">$res</span><span class="br0">&#91;</span><span class="st0">&#8216;valid&#8217;</span><span class="br0">&#93;</span> = <span class="kw2">true</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; <span class="kw1">return</span> <span class="re0">$res</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="re0">$attrib</span> = <span class="re0">$tag_data</span><span class="br0">&#91;</span><span class="st0">&#8216;attribs&#8217;</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="re0">$attrib_name</span><span class="br0">&#93;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw1">switch</span> <span class="br0">&#40;</span> <span class="re0">$attrib</span><span class="br0">&#91;</span><span class="st0">&#8216;type&#8217;</span><span class="br0">&#93;</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li2">
<div class="de2"><span class="co1">// no restrictions on the value of the attributes (not normally recommended)</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">case</span> <span class="st0">&#8216;unrestricted&#8217;</span>:</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="kw1">break</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// the attribute can only have one of the defined values</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">case</span> <span class="st0">&#8216;fixed&#8217;</span>:</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> !<a href="http://www.php.net/in_array"><span class="kw3">in_array</span></a><span class="br0">&#40;</span><a href="http://www.php.net/strtolower"><span class="kw3">strtolower</span></a><span class="br0">&#40;</span><span class="re0">$attrib_value</span><span class="br0">&#41;</span>, <span class="re0">$attrib</span><span class="br0">&#91;</span><span class="st0">&#8216;values&#8217;</span><span class="br0">&#93;</span><span class="br0">&#41;</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$res</span><span class="br0">&#91;</span><span class="st0">&#8216;errors&#8217;</span><span class="br0">&#93;</span> = <span class="st0">&quot;$attrib_name is not set to an accepted value for $tag_name tag.&quot;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="re0">$res</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="kw1">break</span>;</div>
</li>
<li class="li2">
<div class="de2"><span class="co1">// some basic numeric checks</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">case</span> <span class="st0">&#8216;numeric&#8217;</span>:</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">case</span> <span class="st0">&#8216;px&#8217;</span>:</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">case</span> <span class="st0">&#8216;percent&#8217;</span>:</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="re0">$attrib_value</span> = <a href="http://www.php.net/intval"><span class="kw3">intval</span></a><span class="br0">&#40;</span><span class="re0">$attrib_value</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> <span class="re0">$attrib_value</span> &gt; <span class="re0">$attrib</span><span class="br0">&#91;</span><span class="st0">&#8216;max&#8217;</span><span class="br0">&#93;</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$res</span><span class="br0">&#91;</span><span class="st0">&#8216;errors&#8217;</span><span class="br0">&#93;</span> = <span class="st0">&quot;$attrib_name is greater than the max value (&quot;</span> . <span class="re0">$attrib</span><span class="br0">&#91;</span><span class="st0">&#8216;max&#8217;</span><span class="br0">&#93;</span> . <span class="st0">&quot;) allowed for $tag_name tag.&quot;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="re0">$res</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="kw1">elseif</span> <span class="br0">&#40;</span> <span class="re0">$attrib_value</span> &lt; <span class="re0">$attrib</span><span class="br0">&#91;</span><span class="st0">&#8216;min&#8217;</span><span class="br0">&#93;</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$res</span><span class="br0">&#91;</span><span class="st0">&#8216;errors&#8217;</span><span class="br0">&#93;</span> = <span class="st0">&quot;$attrib_name is less than the max value (&quot;</span> . <span class="re0">$attrib</span><span class="br0">&#91;</span><span class="st0">&#8216;min&#8217;</span><span class="br0">&#93;</span> . <span class="st0">&quot;) allowed for $tag_name tag.&quot;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="re0">$res</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> <span class="re0">$attrib</span><span class="br0">&#91;</span><span class="st0">&#8216;type&#8217;</span><span class="br0">&#93;</span> == <span class="st0">&#8216;percent&#8217;</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$attrib_value</span> = <span class="re0">$attrib_value</span> . <span class="st0">&quot;%&quot;</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="kw1">elseif</span> <span class="br0">&#40;</span> <span class="re0">$attrib</span><span class="br0">&#91;</span><span class="st0">&#8216;type&#8217;</span><span class="br0">&#93;</span> == <span class="st0">&#8216;px&#8217;</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$attrib_value</span> = <span class="re0">$attrib_value</span> . <span class="st0">&quot;px&quot;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="kw1">break</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; <span class="kw1">case</span> <span class="st0">&#8216;hex&#8217;</span>:</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="co1">// 6 characters of A-F and 0-9</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="co1">// optionally allow a # in front for a total</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="co1">// of 7 characters</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="kw1">break</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; <span class="kw1">case</span> <span class="st0">&#8216;url&#8217;</span>:</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="co1">// validate according to your valid URL criteria</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="co1">// e.g., only allow for current domain or if the</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="co1">// tag is &quot;img&quot; make sure the extension is .jpg or .gif</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="kw1">break</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; <span class="kw1">case</span> <span class="st0">&#8216;string&#8217;</span>:</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="co1">// validate for a string. &nbsp;I usually consider _-. and similar</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="co1">// characters acceptable for a &quot;string&quot; even though they are</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="co1">// not truly a string</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="kw1">break</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; <span class="kw2">default</span>:</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="re0">$res</span><span class="br0">&#91;</span><span class="st0">&#8216;errors&#8217;</span><span class="br0">&#93;</span> = <span class="st0">&quot;ERROR! &nbsp;Do not know how to process the tag $tag_name!&quot;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="kw1">break</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="re0">$res</span><span class="br0">&#91;</span><span class="st0">&#8216;attrib_name&#8217;</span><span class="br0">&#93;</span> = <span class="re0">$attrib_name</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; <span class="re0">$res</span><span class="br0">&#91;</span><span class="st0">&#8216;attrib_value&#8217;</span><span class="br0">&#93;</span> = <span class="re0">$attrib_value</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="re0">$res</span><span class="br0">&#91;</span><span class="st0">&#8216;valid&#8217;</span><span class="br0">&#93;</span> = <span class="kw2">true</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw1">return</span> <span class="re0">$res</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p>So how you setup the array for tag validation is pretty much up to you.  The format I used looks a lot like this:</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1"><span class="re0">$tags</span> = <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;a&#8217;</span> =&gt; <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>&nbsp;<span class="st0">&#8216;settings&#8217;</span> =&gt; <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st0">&#8216;require_close&#8217;</span> =&gt; <span class="kw2">true</span><span class="br0">&#41;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;attribs&#8217;</span> =&gt; <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>&nbsp;<span class="st0">&#8216;href&#8217;</span> =&gt; <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st0">&#8216;type&#8217;</span> =&gt; <span class="st0">&#8216;url&#8217;</span><span class="br0">&#41;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;name&#8217;</span> =&gt; <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st0">&#8216;type&#8217;</span> =&gt; <span class="st0">&#8216;string&#8217;</span><span class="br0">&#41;</span>,</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;id&#8217;</span> =&gt; <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span> <span class="st0">&#8216;type&#8217;</span> =&gt; <span class="st0">&#8216;string&#8217;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;auth_level&#8217;</span> =&gt; AUTH_LEVEL_TRUSTED_USER</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;class&#8217;</span> =&gt; <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span> <span class="st0">&#8216;type&#8217;</span> =&gt; <span class="st0">&#8216;unrestricted&#8217;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;auth_level&#8217;</span> =&gt; AUTH_LEVEL_TRUSTED_USER</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;onclick&#8217;</span> =&gt; <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span> <span class="st0">&#8216;type&#8217;</span> =&gt; <span class="st0">&#8216;unrestricted&#8217;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;auth_level&#8217;</span> =&gt; AUTH_LEVEL_TRUSTED_USER</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;onmouseover&#8217;</span> =&gt; <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span> <span class="st0">&#8216;type&#8217;</span> =&gt; <span class="st0">&#8216;unrestricted&#8217;</span>,</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;auth_level&#8217;</span> =&gt; AUTH_LEVEL_TRUSTED_USER</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;required_attribs&#8217;</span> =&gt; <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span> <span class="st0">&#8216;href&#8217;</span>, <span class="st0">&#8216;name&#8217;</span> <span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span>,</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;b&#8217;</span> =&gt; <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st0">&#8216;settings&#8217;</span> =&gt; <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>&nbsp;<span class="st0">&#8216;require_close&#8217;</span> =&gt; <span class="kw2">true</span><span class="br0">&#41;</span><span class="br0">&#41;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&#8216;img&#8217;</span> =&gt; <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>&nbsp; <span class="st0">&#8216;settings&#8217;</span> =&gt; <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>&nbsp; <span class="st0">&#8216;require_close&#8217;</span> =&gt; <span class="kw2">false</span><span class="br0">&#41;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;attribs&#8217;</span> =&gt; <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>&nbsp;&nbsp; <span class="st0">&#8216;src&#8217;</span> =&gt; <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>&nbsp;<span class="st0">&#8216;type&#8217;</span> =&gt; <span class="st0">&#8216;url&#8217;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;required&#8217;</span> =&gt; <span class="kw2">true</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span>,</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;alt&#8217;</span> =&gt; <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st0">&#8216;type&#8217;</span> =&gt; <span class="st0">&#8216;string&#8217;</span><span class="br0">&#41;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;border&#8217;</span> =&gt; <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span> &nbsp;<span class="st0">&#8216;type&#8217;</span> =&gt; <span class="st0">&#8216;numeric&#8217;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;min&#8217;</span> =&gt; <span class="nu0">0</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;max&#8217;</span> =&gt; <span class="nu0">5</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="br0">&#41;</span>,</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;align&#8217;</span> =&gt; <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>&nbsp;<span class="st0">&#8216;type&#8217;</span> =&gt; <span class="st0">&#8216;fixed&#8217;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;values&#8217;</span> =&gt; <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>&nbsp; <span class="st0">&#8216;center&#8217;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;left&#8217;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;right&#8217;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;height&#8217;</span> =&gt; <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span> &nbsp;<span class="st0">&#8216;type&#8217;</span> =&gt; <span class="st0">&#8216;numeric&#8217;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;min&#8217;</span> =&gt; <span class="nu0">1</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;max&#8217;</span> =&gt; <span class="nu0">2048</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="br0">&#41;</span>,</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;width&#8217;</span> =&gt; <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span> &nbsp; <span class="st0">&#8216;type&#8217;</span> =&gt; <span class="st0">&#8216;numeric&#8217;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;min&#8217;</span> =&gt; <span class="nu0">1</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;max&#8217;</span> =&gt; <span class="nu0">2048</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="br0">&#41;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;title&#8217;</span> =&gt; <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st0">&#8216;type&#8217;</span>=&gt;<span class="st0">&#8216;string&#8217;</span><span class="br0">&#41;</span>,</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;hspace&#8217;</span> =&gt; <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>&nbsp; <span class="st0">&#8216;type&#8217;</span> =&gt; <span class="st0">&#8216;numeric&#8217;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;min&#8217;</span> =&gt; <span class="nu0">0</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;max&#8217;</span> =&gt; <span class="nu0">10</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="br0">&#41;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;vspace&#8217;</span> =&gt; <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>&nbsp; <span class="st0">&#8216;type&#8217;</span> =&gt; <span class="st0">&#8216;numeric&#8217;</span>,</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;min&#8217;</span> =&gt; <span class="nu0">0</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;max&#8217;</span> =&gt; <span class="nu0">10</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="br0">&#41;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;id&#8217;</span> =&gt; <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span> <span class="st0">&#8216;type&#8217;</span> =&gt; <span class="st0">&#8216;string&#8217;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;auth_level&#8217;</span> =&gt; AUTH_LEVEL_TRUSTED_USER</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;class&#8217;</span> =&gt; <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span> <span class="st0">&#8216;type&#8217;</span> =&gt; <span class="st0">&#8216;unrestricted&#8217;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;auth_level&#8217;</span> =&gt; AUTH_LEVEL_TRUSTED_USER</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;onclick&#8217;</span> =&gt; <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span> <span class="st0">&#8216;type&#8217;</span> =&gt; <span class="st0">&#8216;unrestricted&#8217;</span>,</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;auth_level&#8217;</span> =&gt; AUTH_LEVEL_TRUSTED_USER</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;onmouseover&#8217;</span> =&gt; <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span> <span class="st0">&#8216;type&#8217;</span> =&gt; <span class="st0">&#8216;unrestricted&#8217;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;auth_level&#8217;</span> =&gt; AUTH_LEVEL_TRUSTED_USER</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span>;</div>
</li>
</ol>
</div>
<p>The auth_level is a filter that I have in place to only allow users with a certain amount of access, such as internal staff, to use that attribute.  As you probably already know, attributes like onmouseover are an easy gateway to XSS exploits.  As you add new elements to the tag rule definition you just need to update the validate function in order to validate against it.</p>
<p>You may have noticed that I&#8217;m using the deprecated HTML attributes instead of putting all of this in a &#8220;style&#8221; attribute.  I&#8217;ve found that most users don&#8217;t know CSS styles and are familiar with the old-style HTML attributes.  If you force your users to use styles you&#8217;ll have whole other validation routine to ensure exploits are not in the CSS.</p>
<p>Note: Please don&#8217;t just copy/paste this code into your code and use it.  I&#8217;m quite positive there are bugs and typos all throughout.  Oh, and no, this is <strong>not </strong>the code used by the sites I work on.  It is similar but definitely not the same. <img src='http://www.grepmymind.com/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.grepmymind.com/2009/01/15/validating-html-with-tidy/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Scaling MySQL powered Web Sites by Sharding and Replication &#8211; SF MySQL Meetup Nov 2008</title>
		<link>http://www.grepmymind.com/2008/10/23/scaling-mysql-powered-web-sites-by-sharding-and-replication-sf-mysql-meetup-nov-2008/</link>
		<comments>http://www.grepmymind.com/2008/10/23/scaling-mysql-powered-web-sites-by-sharding-and-replication-sf-mysql-meetup-nov-2008/#comments</comments>
		<pubDate>Thu, 23 Oct 2008 23:28:45 +0000</pubDate>
		<dc:creator>Michael Tougeron</dc:creator>
				<category><![CDATA[Events]]></category>
		<category><![CDATA[Internet]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Tips & Tricks]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[mysql meetup]]></category>
		<category><![CDATA[peter zaitsev]]></category>
		<category><![CDATA[replication.]]></category>
		<category><![CDATA[sharding]]></category>

		<guid isPermaLink="false">http://www.grepmymind.com/?p=87</guid>
		<description><![CDATA[Peter Zaitsev will be giving his excellent presentation &#8220;Scaling MySQL powered Web Sites by Sharding and Replication&#8221; to the upcoming SF MySQL 6:00pm on November 3rd @ the CBS Interactive (formerly CNET Networks) building in SOMA San Francisco (235 2nd St). RSVP here: http://mysql.meetup.com/30/calendar/8912109/ Description from the 2008 Velocity conference: When your application grows beyond [...]]]></description>
			<content:encoded><![CDATA[<div class="D_boxsection">
<p><a href="http://www.mysqlperformanceblog.com/about/" target="_blank">Peter Zaitsev</a> will be giving his excellent presentation &#8220;Scaling MySQL powered Web Sites by Sharding and Replication&#8221; to the upcoming SF MySQL 6:00pm on November 3rd @ the <a href="http://maps.google.com/maps?f=q&amp;hl=en&amp;geocode=&amp;time=&amp;date=&amp;ttype=&amp;q=235+2nd+St,+San+Francisco,+CA+94105&amp;sll=37.0625,-95.677068&amp;sspn=28.444641,57.65625&amp;ie=UTF8&amp;ll=37.786038,-122.397265&amp;spn=0.003455,0.007038&amp;z=18&amp;om=1" target="_blank">CBS Interactive</a> (formerly CNET Networks) building in SOMA San Francisco (<a href="http://maps.google.com/maps?f=q&amp;hl=en&amp;geocode=&amp;time=&amp;date=&amp;ttype=&amp;q=235+2nd+St,+San+Francisco,+CA+94105&amp;sll=37.0625,-95.677068&amp;sspn=28.444641,57.65625&amp;ie=UTF8&amp;ll=37.786038,-122.397265&amp;spn=0.003455,0.007038&amp;z=18&amp;om=1" target="_blank">235 2nd St</a>).</p>
<p>RSVP here: <a href="http://mysql.meetup.com/30/calendar/8912109/">http://mysql.meetup.com/30/calendar/8912109/</a></p>
<p>Description from the <a href="http://en.oreilly.com/velocity2008/public/schedule/detail/3163" target="_blank">2008 Velocity</a> conference:<br />
When your application grows beyond capacity of a single MySQL server there are few ways to scale, with most typical being Replication and Sharding.</p>
<p>In this presentation you will learn how, depending on your application performance scalability and high availability goals, you can choose what proper scaling strategy will be good for you.</p>
<p>We also will speak about scalability limitations of replication of Replication and Sharding, implementation complexities, and aspects of operation.</p>
<p>Peter Zaitsev&#8217;s bio:<br />
<a href="http://www.mysqlperformanceblog.com/" target="_blank">MySQL Performance Blog</a></p>
<p>Peter helped many companies ranging from one man startups to Fortune 500 companies with their Performance and Scaling problems on various stages starting from architecture design and down to queries and schema optimization.</p>
<p>Over cause of the years Peter has spoken on many International conferences focused on MySQL, Open Source, Databases or High Performance Web applications.</p>
<p>Before co-founding <a href="http://www.percona.com/" target="_blank">Percona</a> Peter worked for MySQL AB as head of High Performance Group being involved in Support, Consulting, Development and working with vendors helping to optimize their software or hardware to perform well with MySQL.</p>
<p>Peter also was involved in number of Web Startups in the roles ranging from CTO to Consultant and has a lot of experience in MySQL and Web Applications Operations, Deployment, Quality Assurance and Development.<br />
Please join us!</p>
<p><a href="http://maps.google.com/maps?f=q&amp;hl=en&amp;geocode=&amp;time=&amp;date=&amp;ttype=&amp;q=235+2nd+St,+San+Francisco,+CA+94105&amp;sll=37.0625,-95.677068&amp;sspn=28.444641,57.65625&amp;ie=UTF8&amp;ll=37.786038,-122.397265&amp;spn=0.003455,0.007038&amp;z=18&amp;om=1" target="_blank">Map to CNET Networks, Inc. </a><br />
When you arrive, please look for the PHP/MySQL Meetup sign pointing you to the conference room.</p>
<p>Look forward to seeing you there!</p></div>
]]></content:encoded>
			<wfw:commentRss>http://www.grepmymind.com/2008/10/23/scaling-mysql-powered-web-sites-by-sharding-and-replication-sf-mysql-meetup-nov-2008/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>memcached PHP semaphore &amp; cache expiration handling</title>
		<link>http://www.grepmymind.com/2008/01/11/memcached-php-semaphore-cache-expiration-handling/</link>
		<comments>http://www.grepmymind.com/2008/01/11/memcached-php-semaphore-cache-expiration-handling/#comments</comments>
		<pubDate>Fri, 11 Jan 2008 21:01:41 +0000</pubDate>
		<dc:creator>Michael Tougeron</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Tips & Tricks]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[memcached]]></category>
		<category><![CDATA[semaphore]]></category>

		<guid isPermaLink="false">http://www.grepmymind.com/2008/01/11/memcached-php-semaphore-cache-expiration-handling/</guid>
		<description><![CDATA[There are a lot of different ways that people use memcached and PHP. The most common of which is probably your basic set and get to cache data from your database. function get_my_data1&#40;&#41; &#123; &#160; &#160; $cache_id = &#34;mykey&#34;; &#160; &#160; $data = $memcache_obj-&#62;get&#40;$cache_id&#41;; &#160; &#160; if &#40; !$data &#41; &#123; &#160; &#160; &#160; &#160; [...]]]></description>
			<content:encoded><![CDATA[<p>There are a lot of different ways that people use <a href="http://www.danga.com/memcached/">memcached</a> and <a href="http://php.net/manual/en/ref.memcache.php">PHP</a>.   The most common of which is probably your basic <a href="http://php.net/manual/en/function.Memcache-set.php">set </a> and <a href="http://php.net/manual/en/function.Memcache-get.php">get</a> to cache data from your database.</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1"><span class="kw2">function</span> get_my_data1<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re0">$cache_id</span> = <span class="st0">&quot;mykey&quot;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re0">$data</span> = <span class="re0">$memcache_obj</span>-&gt;<span class="me1">get</span><span class="br0">&#40;</span><span class="re0">$cache_id</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> !<span class="re0">$data</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$data</span> = get_data_from_db_function<span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$memcache_obj</span>-&gt;<span class="me1">set</span><span class="br0">&#40;</span><span class="re0">$cache_id</span>, <span class="re0">$data</span>, <span class="re0">$sec_to_cache_for</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">return</span> <span class="re0">$data</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p>But what if the query that&#8217;s going to hit the database is pretty intensive and you don&#8217;t want more than one user to hit the db at a time?  That&#8217;s easily handling via a <a href="http://en.wikipedia.org/wiki/Semaphore_(programming)">semaphore</a> lock.</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1"><span class="kw2">function</span> get_my_data2<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re0">$cache_id</span> = <span class="st0">&quot;mykey&quot;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re0">$data</span> = <span class="re0">$memcache_obj</span>-&gt;<span class="me1">get</span><span class="br0">&#40;</span><span class="re0">$cache_id</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> !<span class="re0">$data</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// check to see if someone has already set the lock</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$data_lock</span> = <span class="re0">$memcache_obj</span>-&gt;<span class="me1">get</span><span class="br0">&#40;</span><span class="re0">$cache_id</span> . <span class="st0">&#8216;_qry_lock&#8217;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> <span class="re0">$data_lock</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$lock_counter</span> = <span class="nu0">0</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// loop until you find that the lock has been released. &nbsp;that implies that the query has finished</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">do</span> <span class="kw1">while</span> <span class="br0">&#40;</span> <span class="re0">$data_lock</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// you may only want to wait for a specified period of time.</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// one second is usually sufficient since your goal is to always have sub-second response time</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// if you query takes more than 1 second, you should consider &quot;warming&quot; your cached data via a cron job</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> <span class="re0">$lock_counter</span> &gt; <span class="re0">$max_time_to_wait</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$lock_failed</span> = <span class="kw2">true</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">break</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// you really want this to be a fraction of a second so the user waits as little as possible</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// for the simplicity of example, I&#8217;m using the sleep function.</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.php.net/sleep"><span class="kw3">sleep</span></a><span class="br0">&#40;</span><span class="nu0">1</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$data_lock</span> = <span class="re0">$memcache_obj</span>-&gt;<span class="me1">get</span><span class="br0">&#40;</span><span class="re0">$cache_id</span> . <span class="st0">&#8216;_qry_lock&#8217;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// if the loop is completed, that either means the user waited for too long</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// or that the lock has been removed. &nbsp;try to get the cached data again; it should exist now</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$data</span> = <span class="re0">$memcache_obj</span>-&gt;<span class="me1">get</span><span class="br0">&#40;</span><span class="re0">$cache_id</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> <span class="re0">$data</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="re0">$data</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// set a lock for 2 seconds</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$memcache_obj</span>-&gt;<span class="me1">set</span><span class="br0">&#40;</span><span class="re0">$cache_id</span> . <span class="st0">&#8216;_qry_lock&#8217;</span>, <span class="kw2">true</span>, <span class="nu0">2</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$data</span> = get_data_from_db_function<span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$memcache_obj</span>-&gt;<span class="me1">set</span><span class="br0">&#40;</span><span class="re0">$cache_id</span>, <span class="re0">$data</span>, <span class="re0">$sec_to_cache_for</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// don&#8217;t forget to remove the lock</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$memcache_obj</span>-&gt;<span class="me1">delete</span><span class="br0">&#40;</span><span class="re0">$cache_id</span> . <span class="st0">&#8216;_qry_lock&#8217;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">return</span> <span class="re0">$data</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p>More below the break &#8211;&gt;<span id="more-11"></span></p>
<p>Another good use of the semaphore locking is to set the expire time as part of the cached data and have an extended expire time set in memcache.  This allows you to have more control over what happens when the cached data becomes stale.  You can make it so that one user repopulates the cache while other users continue to get the existing cache until the first user has finished.</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1"><span class="kw2">function</span> get_my_data3<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re0">$cache_id</span> = <span class="st0">&quot;mykey&quot;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re0">$data</span> = <span class="re0">$memcache_obj</span>-&gt;<span class="me1">get</span><span class="br0">&#40;</span><span class="re0">$cache_id</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="co1">// if there is cached data and the expire timestamp has already expired or is within the next 2 minutes</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; <span class="co1">// then we want the user to freshen up the cached data</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> <span class="re0">$data</span> &amp;amp;&amp;amp; <span class="br0">&#40;</span><span class="re0">$data</span><span class="br0">&#91;</span><span class="st0">&#8216;cache_expires_timestamp&#8217;</span><span class="br0">&#93;</span> &#8211; <a href="http://www.php.net/time"><span class="kw3">time</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> &lt; <span class="nu0">120</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// if the semaphore lock has already been set, just return the data like you normally would.</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> <span class="re0">$memcache_obj</span>-&gt;<span class="me1">get</span><span class="br0">&#40;</span><span class="re0">$cache_id</span> . <span class="st0">&#8216;_expire_lock&#8217;</span><span class="br0">&#41;</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="re0">$data</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// now we want to set the lock and have the user freshen the data.</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$memcache_obj</span>-&gt;<span class="me1">set</span><span class="br0">&#40;</span><span class="re0">$cache_id</span> . <span class="st0">&#8216;_expire_lock&#8217;</span>, <span class="kw2">true</span>, <span class="nu0">2</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// by unsetting the data it will cause the data gather logic below to execute.</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.php.net/unset"><span class="kw3">unset</span></a><span class="br0">&#40;</span><span class="re0">$data</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> !<span class="re0">$data</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// be sure to include all of the semaphore logic from example 2</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// set the _qry_lock for 2 seconds</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$memcache_obj</span>-&gt;<span class="me1">set</span><span class="br0">&#40;</span><span class="re0">$cache_id</span> . <span class="st0">&#8216;_qry_lock&#8217;</span>, <span class="kw2">true</span>, <span class="nu0">2</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$raw_data</span> = get_data_from_db_function<span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$data</span><span class="br0">&#91;</span><span class="st0">&#8216;cache_expires_timestamp&#8217;</span><span class="br0">&#93;</span> = <a href="http://www.php.net/time"><span class="kw3">time</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span> + <span class="re0">$sec_to_cache_for</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$data</span><span class="br0">&#91;</span><span class="st0">&#8216;cached_data&#8217;</span><span class="br0">&#93;</span> = <span class="re0">$raw_data</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$memcache_obj</span>-&gt;<span class="me1">set</span><span class="br0">&#40;</span><span class="re0">$cache_id</span>, <span class="re0">$data</span>, <span class="re0">$sec_to_cache_for</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// remove the _qry_lock</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$memcache_obj</span>-&gt;<span class="me1">delete</span><span class="br0">&#40;</span><span class="re0">$cache_id</span> . <span class="st0">&#8216;_qry_lock&#8217;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// remove the _expires_lock</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$memcache_obj</span>-&gt;<span class="me1">delete</span><span class="br0">&#40;</span><span class="re0">$cache_id</span> . <span class="st0">&#8216;_expires_lock&#8217;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">return</span> <span class="re0">$data</span>;</div>
</li>
<li class="li2">
<div class="de2"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p>When you mash these functions together, you end up with a system where only one user every freshens the cache and/or hits the database with a specific query at a time.  There are a lot of other things that suddenly become available once you start thinking of memcached beyond just saving your db from hits.  You have things like session handling, smarty template caching, flags for per-server processing (e.g., clearing local file cache), and even as a temporary database.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.grepmymind.com/2008/01/11/memcached-php-semaphore-cache-expiration-handling/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
	</channel>
</rss>
