<?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>PoundBangWhack.com</title>
	<atom:link href="http://www.poundbangwhack.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.poundbangwhack.com</link>
	<description>A web development/programming blog providing info, tips, and tricks on programming languages, scripting, Linux, MySQL and more</description>
	<lastBuildDate>Sat, 17 Jul 2010 05:17:56 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>MySQL Quick-Tip: Target specific versions of MySQL with conditional comments</title>
		<link>http://www.poundbangwhack.com/2010/07/14/mysql-quick-tip-target-specific-versions-of-mysql-with-conditional-comments/</link>
		<comments>http://www.poundbangwhack.com/2010/07/14/mysql-quick-tip-target-specific-versions-of-mysql-with-conditional-comments/#comments</comments>
		<pubDate>Wed, 14 Jul 2010 07:02:24 +0000</pubDate>
		<dc:creator>Mark Stoecker</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Quick Tips]]></category>
		<category><![CDATA[comments]]></category>
		<category><![CDATA[conditional]]></category>
		<category><![CDATA[Quick-Tip]]></category>
		<category><![CDATA[specific]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[version]]></category>

		<guid isPermaLink="false">http://www.poundbangwhack.com/?p=1394</guid>
		<description><![CDATA[I was working on a project over the weekend that required me to run some code relating to MySQL privileges across a large number of MySQL servers all running various versions of MySQL between 4.0 and 5.0.  My initial efforts at this entailed writing out the version specific code and targeting the version with bash thusly:

<pre name="code" class="bash">
 VERSION=$( mysql -u$user -p$password -S $socket -e"SELECT VERSION();" &#124; cut -f1,2 -d. )
 if [ $VERSION = '5.0' ]; then
  # Execute 5.0 code
 elif [ $VERSION = '4.1' ]; then 
  # Execute 4.1 code 
 elif [ $VERSION = '4.0' ]; then 
  # Execute 4.0 code
 else
  echo "Unable to determine version
  exit 1
</pre>

This method involved a lot of code duplication.]]></description>
			<content:encoded><![CDATA[<p>I was working on a project over the weekend that required me to run some code relating to MySQL privileges across a large number of MySQL servers all running various versions of MySQL between 4.0 and 5.0.  My initial efforts at this entailed writing out the version specific code and targeting the version with bash thusly:</p>
<pre name="code" class="bash">
 VERSION=$( mysql -u$user -p$password -S $socket -e"SELECT VERSION();" | cut -f1,2 -d. )
 if [ $VERSION = '5.0' ]; then
  # Execute 5.0 code
 elif [ $VERSION = '4.1' ]; then
  # Execute 4.1 code
 elif [ $VERSION = '4.0' ]; then
  # Execute 4.0 code
 else
  echo "Unable to determine version
  exit 1
</pre>
<p>This method involved a lot of code duplication.  Yesterday, a co-worker mentioned using <strong>MySQL version specific comments</strong>, which I had seen before, but never fully understood.<br />
<span id="more-1394"></span><br />
Most of you have probably seen MySQL Comments before, whether you know it or not.  They take the form of:</p>
<pre name="code" class="sql">
/*!40101 SET NAMES utf8 */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
</pre>
<p>These types of comments are most popular in MySQL Dumps.  Once you understand what they mean, they&#8217;re very easy to use.  Here are the basics:</p>
<ul>
<li>MySQL version specific comments start with <span class="code">/*!</span></li>
<li>And end with <span class="code">*/</span></li>
<li>Version numbers are always 5 digits</li>
<li>Version numbers are in the format major release number, minor release number, revision number with the major being 1 digit and the minor and revision being 2 digits left-padded with 0&#8217;s</li>
<li>Version specific comments will target any version <strong>equal to or higher than</strong> the version number listed</li>
</ul>
<p>So in the examples above, the comments will target versions 4.1.1+ (40101), 4.1.3+ (40103), 4.0.14+ (40014), and 4.1.11+ (40111) respectively.  Any version below these, will simply read those lines as comments and ignore them.</p>
<p>So, if you were to take the following SQL code:</p>
<pre name="code" class="sql">
SELECT 1 /*!40122 , 2 */ /*!50067 , 3 */;
</pre>
<p>and run that on servers running 4.0. 4.1.22, and 5.0.67, you would get the following output:<br />
<strong>4.0</strong></p>
<pre name="code" class="sql">
mysql> SELECT 1 /*!40122 , 2 */ /*!50067 , 3 */;
+---+
| 1 |
+---+
| 1 |
+---+
</pre>
<p><strong>4.1.22</strong></p>
<pre name="code" class="sql">
mysql> SELECT 1 /*!40122 , 2 */ /*!50067 , 3 */;
+---+---+
| 1 | 2 |
+---+---+
| 1 | 2 |
+---+---+
</pre>
<p><strong>5.0.67</strong></p>
<pre name="code" class="sql">
mysql> SELECT 1 /*!40122 , 2 */ /*!50067 , 3 */;
+---+---+---+
| 1 | 2 | 3 |
+---+---+---+
| 1 | 2 | 3 |
+---+---+---+
</pre>
<p>Remember that the comments target all versions equal to or higher, so 4.0 will only see <span class="code">SELECT 1;</span>, 4.1.22 will see <span class="code">SELECT 1, 2;</span>, and 5.0.67 will see <span class="code">SELECT 1, 2, 3;</span>.  The rest of the code will just be read as inline comments.</p>
<p>Hopefully this helps to understand <strong>MySQL version specific conditional comments</strong> a little bit better.</p>
<p>Comments or questions are welcome and encouraged.</p>
<div class="references">References:<br />
<a href="http://www.xaprb.com/blog/2007/05/22/how-to-write-mysql-conditional-comments/">http://www.xaprb.com/blog/2007/05/22/how-to-write-mysql-conditional-comments/</a><br />
<a href="http://dev.mysql.com/doc/refman/4.1/en/comments.html">http://dev.mysql.com/doc/refman/4.1/en/comments.html</a></div>
]]></content:encoded>
			<wfw:commentRss>http://www.poundbangwhack.com/2010/07/14/mysql-quick-tip-target-specific-versions-of-mysql-with-conditional-comments/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to reset the bash IFS variable</title>
		<link>http://www.poundbangwhack.com/2010/07/09/how-to-reset-the-bash-ifs-variable/</link>
		<comments>http://www.poundbangwhack.com/2010/07/09/how-to-reset-the-bash-ifs-variable/#comments</comments>
		<pubDate>Fri, 09 Jul 2010 23:53:11 +0000</pubDate>
		<dc:creator>Mark Stoecker</dc:creator>
				<category><![CDATA[How To]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[SSH/Command Line]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[SSH]]></category>
		<category><![CDATA[Tips]]></category>

		<guid isPermaLink="false">http://www.poundbangwhack.com/?p=1381</guid>
		<description><![CDATA[Here&#8217;s a quick tip for everyone.  I was working on a one-liner today at work that involved parsing through a file with some data in it.  The data had spaces in it which can cause problems with the default $IFS variable (Internal File Separator). nixCraft has an excellent tutorial on working with the [...]]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s a quick tip for everyone.  I was working on a one-liner today at work that involved parsing through a file with some data in it.  The data had spaces in it which can cause problems with the default $IFS variable (Internal File Separator). <a href="http://www.cyberciti.biz/tips/handling-filenames-with-spaces-in-bash.html">nixCraft has an excellent tutorial on working with the $IFS variable.</a><br />
<span id="more-1381"></span><br />
As I was test iterations of my one-liner, I was setting resetting the $IFS variable.  While I was smart enough to save it first:</p>
<pre name="code" class="bash">
 OLDIFS=$IFS
</pre>
<p>I forgot to set it back at the end of my one-liner, which caused some problems for me.  I tried checking another server to see what the default is, but if you just run the command</p>
<pre name="code" class="bash">
# echo $IFS
#
</pre>
<p>you see that you just get a blank line.  The way to show all non-printing characters is to pipe the output into <span class="code">cat</span> with a couple of switches.</p>
<pre name="code" class="bash">
# echo "$IFS" | cat -vTE
 ^I$
$
#
</pre>
<p>The switches stand for the following:</p>
<dl>
<dt>-v, &#8211;show-nonprinting</dt>
<dd>use ^ and M- notation, except for LFD and TAB</dd>
<dt>-T, &#8211;show-tabs</dt>
<dd>display TAB characters as ^I</dd>
<dt>-E, &#8211;show-ends</dt>
<dd>display $ at end of each line</dt>
</dl>
<p>**Note -t can be substituted for -vT; -e can be substituted for -vE</p>
<p>So our output above, indicates that <strong>the default setting for the $IFS variable is: a space, followed by a tab, followed by a new line character.</strong></p>
<p>Once I had this information, it was very easy to then <strong>reset the $IFS variable back to it&#8217;s default</strong>.  While trying to set this, I had problems with the tab (for some reason it wasn&#8217;t registering) so I just wrote it as &#8216;^I&#8217;.  Once set, run the </p>
<pre name="code" class="bash">
echo "$IFS" | cat -vTE
</pre>
<p>command again to verify and make sure it matches the output above and you&#8217;ll be all set.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.poundbangwhack.com/2010/07/09/how-to-reset-the-bash-ifs-variable/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>What I learned from my first OWASP meeting (or why I will never use PHP Nuke)</title>
		<link>http://www.poundbangwhack.com/2010/07/06/what-i-learned-from-my-first-owasp-meeting-or-why-i-will-never-use-php-nuke/</link>
		<comments>http://www.poundbangwhack.com/2010/07/06/what-i-learned-from-my-first-owasp-meeting-or-why-i-will-never-use-php-nuke/#comments</comments>
		<pubDate>Wed, 07 Jul 2010 05:23:02 +0000</pubDate>
		<dc:creator>Mark Stoecker</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[Hack]]></category>
		<category><![CDATA[Mike Brooks]]></category>
		<category><![CDATA[SQL Injection]]></category>

		<guid isPermaLink="false">http://www.poundbangwhack.com/?p=1376</guid>
		<description><![CDATA[Like I said, I learned a lot (much more than I though I was going to) at the meeting and look forward to attending every month.  I highly suggest checking for <a href="http://www.owasp.org/index.php/Category:OWASP_Chapter">an OWASP chapter in your area</a> and attending monthly meetings.  In closing, I'd like to leave a list of some of the things I took away from this meeting:]]></description>
			<content:encoded><![CDATA[<p>I just got home from attending my first meeting of the Phoenix chapter of <a href="http://www.owasp.org/" title="Open Web Application Security Project">OWASP.</a>  <strong>WOW!!!</strong>  That&#8217;s all I have to say.  The guest speaker was <a href="https://sitewat.ch">Mike Brooks</a>, currently <a href="http://stackoverflow.com/users/183528/the-rook">the top answerer and asker of security questions on Stack Overflow</a>, who will be giving the same talk at the upcoming <a href="http://www.defcon.org/">DEF CON 18.</a>  Mike gave an amazing presentation on chaining vulnerabilities in order to bypass layered security systems and ways of obtaining wormable remote code execution on a modern <abbr title="Linux Apache MySQL PHP">LAMP</abbr> platform.<br />
<span id="more-1376"></span><br />
First off, let me just start with this statement: <strong>Mike Brooks is brilliant!</strong>  I won&#8217;t go to much in to detail of what he spoke about as he will be speaking at DEF CON as well and I don&#8217;t want to give away his talk, even though it has been published on the web already.  However, Mike showed some interesting ways of not only exploiting holes in the PHP Nuke application, but exploits that can be used elsewhere as well.  Obviously, I think it goes without saying (but I&#8217;ll say it anyway): <strong>I do not condone hacking or any use of black-hat methodologies for malicious purposes.</strong>  However, when used for educational purposes, the information is very useful.  How may hacking be educational?  Mike summed it up with the following quote: </p>
<blockquote><p>What I cannot create, I do not understand.<br /><cite><a href="http://en.wikiquote.org/wiki/Richard_Feynman">Richard Feynman</a></cite></p></blockquote>
<p>In a nutshell, <strong>we can not solve the problem if we don&#8217;t understand what the problem is.</strong></p>
<p>Mike utilized the following exploits/weaknesses to take over an installation of PHP Nuke and enable a remote code execution:</p>
<ul>
<li><a href="http://www.owasp.org/index.php/Top_10_2010-A1">OWASP A1 &#8211; SQL Injection</a></li>
<li><a href="http://www.owasp.org/index.php/Top_10_2010-A3">OWASP A3 &#8211; Broken Authentication and Session Management</a></li>
<li><a href="http://cwe.mitre.org/data/definitions/200.html">CWE-200: Information Exposure</a></li>
<li><a href="http://www.owasp.org/index.php/Top_10_2010-A1">OWASP A1 &#8211; SQL Injection</a></li>
<li><a href="http://cwe.mitre.org/data/definitions/98.html">CWE-98: Improper Control of Filename for Include/Require Statement in PHP Program (&#8216;PHP File Inclusion&#8217;)</a></li>
</ul>
<p>While Mike said it took over a year to develop the exploit, it seemed very easy.  However, I&#8217;m sure there is a lot of &#8220;guess and check&#8221; involved in hacking.  Maybe by easy, to me it seems that some <strong>very basic security measures</strong> would have prevented this, measures that PHP Nuke isn&#8217;t taking, but very easily could.  Things like</p>
<ul>
<li>Proper usage of MySQL Data Types</li>
<li>Proper management of user sessions</li>
<li>Better MySQL input sanitzation</li>
<li>Proper login methods</li>
</ul>
<p>These are just a few of the things that could help prevent against this exploit.  More than anything, what I was amazed at was that Mike was able to login to the admin portion of the (his) site without having to decrypt the md5 password hash due to the shoddy session management.  Apparently, this has been a well-documented PHP Nuke exploit for years, however he had to use some clever hacking first to obtain the information necessary.</p>
<p>Like I said, I learned a lot (much more than I though I was going to) at the meeting and look forward to attending every month.  I highly suggest checking for <a href="http://www.owasp.org/index.php/Category:OWASP_Chapter">an OWASP chapter in your area</a> and attending monthly meetings.  In closing, I&#8217;d like to leave a list of some of the things I took away from this meeting:</p>
<ul>
<li>Modules (to any web app) are a major risk for attack (I pretty much knew this one already, just wanted to share it)</li>
<li>Do not mix XSS and SQL Injection sanitization methods in the same function</li>
<li>Limit the abilities of what even the admin of your application can do so even if it gets popped, the damage can be minimized</li>
<li><strong>Do not use md5 for password hashing!</strong>  Instead use sha1 or sha256 (this was news to me)</li>
<li>Don&#8217;t manage your sessions yourself, let php manage them with <span class="code">session_start()</span></li>
<li>Use <a href="http://phpsec.org/projects/phpsecinfo/">PhpSecInfo</a></li>
<li>Granting MySQL FILE privileges are worse than granting GRANT privileges</li>
<li>Security through Obscurity is not security at all, instead it is merely a stop-gap</li>
<li><strong>I will NEVER use, work on, or support PHP Nuke</strong> (it has more holes than swiss cheese)</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.poundbangwhack.com/2010/07/06/what-i-learned-from-my-first-owasp-meeting-or-why-i-will-never-use-php-nuke/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Improve the performance of the WordPress plugin Statpress (and your blog)</title>
		<link>http://www.poundbangwhack.com/2010/07/03/improve-the-performance-of-the-wordpress-plugin-statpress-and-your-blog/</link>
		<comments>http://www.poundbangwhack.com/2010/07/03/improve-the-performance-of-the-wordpress-plugin-statpress-and-your-blog/#comments</comments>
		<pubDate>Sun, 04 Jul 2010 06:15:59 +0000</pubDate>
		<dc:creator>Mark Stoecker</dc:creator>
				<category><![CDATA[Blogging]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Wordpress Plugins]]></category>
		<category><![CDATA[Database]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Plugin]]></category>
		<category><![CDATA[StatPress]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://www.poundbangwhack.com/?p=1369</guid>
		<description><![CDATA[I haven't hid my feelings about <a href="http://www.poundbangwhack.com/2009/12/02/avoid-wordpress-statpress-plugin-like-the-plague/">the poor performing StatPress plugin for WordPress</a>.  However, performance issues aside, I will say that the information this plugin provides is useful, and detailed.  I've been running this plugin for 8 months now and have a good sized data set (125,000+ rows of data).  While I myself have not experienced as many issues with this plugin as I have seen on other blogs, it is mainly because I am running my blog on a virtual dedicated server as opposed to shared hosting.  I have seen smaller data sets than mine cause problems on shared hosting servers.]]></description>
			<content:encoded><![CDATA[<p>I haven&#8217;t hid my feelings about <a href="http://www.poundbangwhack.com/2009/12/02/avoid-wordpress-statpress-plugin-like-the-plague/">the poor performing StatPress plugin for WordPress</a>.  However, performance issues aside, I will say that the information this plugin provides is useful, and detailed.  I&#8217;ve been running this plugin for 8 months now and have a good sized data set (125,000+ rows of data).  While I myself have not experienced as many issues with this plugin as I have seen on other blogs, it is mainly because I am running my blog on a virtual dedicated server as opposed to shared hosting.  I have seen smaller data sets than mine cause problems on shared hosting servers.<br />
<span id="more-1369"></span><br />
I mentioned in my other post that I was working on fixing the faults in this plugin and am releasing my first round of updates for those of you using StatPress.  Take the following code and run it on your WordPress database, either through shell or through phpMyAdmin:</p>
<pre name="code" class="sql">
alter table wp_statpress
 modify column date int(8) NULL NULL,
 modify column time time NULL NULL,
 modify column ip varchar(15) NULL NULL,
 modify column nation varchar(10) NULL NULL,
 modify column os varchar(64) NULL NULL,
 modify column browser varchar(64) NULL NULL,
 modify column searchengine varchar(64) NULL NULL,
 modify column spider varchar(64) NULL NULL,
 modify column feed varchar(32) NULL NULL,
 modify column user varchar(64) NULL NULL,
 modify column timestamp timestamp NULL NULL,
 add index spider_nation (spider, nation),
 add index ip_date (ip, date),
 add index (agent(255)),
 add index (search(255)),
 add index (referrer(255)),
 add index feed_spider_os (feed, spider, os),
 add index (os),
 add index date_feed_spider (date, feed, spider),
 add index feed_spider_browser (feed, spider, browser),
 add index (browser);
</pre>
<p><em>**Note: This code assumes your StatPress table name is wp_statpress.  If it is not, make sure you update the code to reflect the name of your StatPress table.</em></p>
<p>This will set proper data types on the StatPress table as well as add indexes to the columns that are regularly queried by the plugin.   Hopefully with these changes, you will start to notice a performance improvement in your blog as well as a significant improvement on your StatPress plugin page on your dashboard.</p>
<p>Please let me know if this helps you out, or if you have any problems executing the code, by commenting below. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.poundbangwhack.com/2010/07/03/improve-the-performance-of-the-wordpress-plugin-statpress-and-your-blog/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>What do three &#8220;less than&#8221; (</title>
		<link>http://www.poundbangwhack.com/2010/07/02/what-is-heredoc/</link>
		<comments>http://www.poundbangwhack.com/2010/07/02/what-is-heredoc/#comments</comments>
		<pubDate>Fri, 02 Jul 2010 20:47:24 +0000</pubDate>
		<dc:creator>Mark Stoecker</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[SSH/Command Line]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[Heredoc]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Scripting]]></category>

		<guid isPermaLink="false">http://www.poundbangwhack.com/?p=1349</guid>
		<description><![CDATA[To teach myself PHP, I started out reading <a href="http://www.amazon.com/gp/product/0764543644?ie=UTF8&#038;tag=httpwwwdese09-20&#038;linkCode=as2&#038;camp=1789&#038;creative=390957&#038;creativeASIN=0764543644">Beginning PHP4 (Programmer to Programmer)</a><img src="http://www.assoc-amazon.com/e/ir?t=httpwwwdese09-20&#038;l=as2&#038;o=1&#038;a=0764543644" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />.  After that, I begin studying others' code.  One of the first things I learned from other peoples' code was <a href="http://www.php.net/manual/en/language.types.string.php#language.types.string.syntax.heredoc">heredoc syntax.</a>  It took me a while to fully understand what it was and how to use it, but now I use it all the time and it is a fantastic tool.]]></description>
			<content:encoded><![CDATA[<p>I am a true believer in that the best ways to learn how to do anything is by studying work of those who have done the same thing previously.  When programming, that means looking at others&#8217; code and learning from what they do.  However, <strong>don&#8217;t assume that everything someone else does is correct!</strong>  What this means is that not only should you learn what <strong>to</strong> do from other peoples&#8217; code, but you should also learn what <strong>not</strong> to do.<br />
<span id="more-1349"></span><br />
To teach myself PHP, I started out reading <a href="http://www.amazon.com/gp/product/0764543644?ie=UTF8&#038;tag=httpwwwdese09-20&#038;linkCode=as2&#038;camp=1789&#038;creative=390957&#038;creativeASIN=0764543644">Beginning PHP4 (Programmer to Programmer)</a><img src="http://www.assoc-amazon.com/e/ir?t=httpwwwdese09-20&#038;l=as2&#038;o=1&#038;a=0764543644" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />.  After that, I begin studying others&#8217; code.  One of the first things I learned from other peoples&#8217; code was <a href="http://www.php.net/manual/en/language.types.string.php#language.types.string.syntax.heredoc">heredoc syntax.</a>  It took me a while to fully understand what it was and how to use it, but now I use it all the time and it is a fantastic tool.</p>
<h3>What is heredoc?</h3>
<p>Heredoc syntax is a way to delimit strings in PHP (and other languages) with <strong>3 &#8220;less than&#8221; symbols: &lt;&lt;&lt;</strong>.  </p>
<blockquote><p>
After this operator, an identifier is provided, then a newline. The string itself follows, and then the same identifier again to close the quotation.</p>
<p>The closing identifier <strong>must </strong> begin in the first column of the line. Also, the identifier must follow the same naming rules as any other label in PHP: it must contain only alphanumeric characters and underscores, and must start with a non-digit character or underscore.<br />
<cite><a href="http://www.php.net/manual/en/language.types.string.php#language.types.string.syntax.heredoc">PHP: Strings &#8211; Manual</a></cite>
</p></blockquote>
<p>An example may help:</p>
<pre name="code" class="php">
&lt;?php
echo &lt;&lt;&lt;EOD
Example of string
spanning multiple lines
using heredoc syntax.
EOD;
?>
</pre>
<p>This will output:<br />
&#8220;Example of string<br />
spanning multiple lines<br />
using heredoc syntax&#8221;</p>
<p>Not very impressive.  However, where the handiness comes in is in the following:</p>
<blockquote><p>
Heredoc text behaves just like a double-quoted string, without the double quotes. This means that quotes in a heredoc do not need to be escaped. Variables are expanded, but the same care must be taken when expressing complex variables inside a heredoc as with strings.<br />
<cite><a href="http://www.php.net/manual/en/language.types.string.php#language.types.string.syntax.heredoc">PHP: Strings &#8211; Manual</a></cite>
</p></blockquote>
<p>This allows you to use variables and quotes in your heredocs without having to escape every single quote you want to use.  It makes it very useful for printing out extremely long strings of text.  </p>
<h3>Things to remember about using heredoc</h3>
<p>Heredocs are a great way to simplify your code and print out long strings.  Here is just a few things to keep in mind when using them:</p>
<ul>
<li>Heredocs start with &#8220;&lt;&lt;&lt;<em>IDENTIFIER</em> where <em>IDENTIFIER</em> must follow the same naming conventions of PHP variables.</li>
<li>The closing identifier <strong>must</strong> be the same as the opening identifier</li>
<li>The line with the closing identifier <strong>must contain no other characters</strong>, except possibly  a semicolon (;). That means especially that <strong>the identifier may not be indented</strong>, and <strong>there may not be any spaces or tabs before or after the semicolon</strong></li>
<li>Quotes and double quotes do not need to be escaped</li>
<li>Variables are expanded</li>
</ul>
<p>For more information, refer to the <a href="http://www.php.net/manual/en/language.types.string.php#language.types.string.syntax.heredoc">PHP: Strings Manual on php.net</a></p>
<h3>Bonus: Heredocs for bash scripting</h3>
<p>Heredocs for bash work pretty much the exact same way as they do for PHP but are delimited by <strong>2 &#8220;less than&#8221; symbols:&#8221; &lt;&lt;</strong> instead of 3.  Here is a handy way to output large fields of text into a file through a bash script:</p>
<pre name="code" class="php">
#!/bin/bash
cat &lt;&lt;OUTPUT > /etc/my.cnf
[mysqld]
socket=/tmp/mysql.sock
port=3306
user=mysql
password=supersecretpassword
log-bin=mysql-bin
server-id=1
OUTPUT
</pre>
<p>What about you? What new things have you learned from reading other peoples&#8217; code? Share with us and we&#8217;ll all learn something new.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.poundbangwhack.com/2010/07/02/what-is-heredoc/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>jQuery tabbed content switcher</title>
		<link>http://www.poundbangwhack.com/2010/06/27/jquery-tabbed-content-switcher/</link>
		<comments>http://www.poundbangwhack.com/2010/06/27/jquery-tabbed-content-switcher/#comments</comments>
		<pubDate>Mon, 28 Jun 2010 05:08:13 +0000</pubDate>
		<dc:creator>Mark Stoecker</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[How To]]></category>
		<category><![CDATA[JavaScript Scripts]]></category>
		<category><![CDATA[Web Design]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[Content Switcher]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Tabs]]></category>

		<guid isPermaLink="false">http://www.poundbangwhack.com/?p=1304</guid>
		<description><![CDATA[I was working on a new web design <del>last night</del> early this morning I found myself struggling (probably more than I should have been) with creating tabbed content switcher (hover over one element changes the content of another).  I knew <a href="http://jquery.com" target="_blank">the right way to go was jQuery</a>, and I wanted to avoid downloading a plugin as that would likely end up with more code and another HTTP request to the server.  As I was working on the content switcher, I had one of those "Let's try this and see if it works" moments (those tend to work all to often for me).  It turned out that it did half of what I needed, so I removed another line and voila! I had my content switcher.]]></description>
			<content:encoded><![CDATA[<p>Eat your heart out <a href="http://en.wikipedia.org/wiki/Alexander_Fleming" target="_blank">Sir Alexander Fleming</a>!  While my accidental invention of a <strong>jQuery tabbed content switcher</strong> may not be up there with <a href="http://popularemails.com/accidentalinventions.htm">penicillin, the pacemaker, and post-it notes</a>, it sure did wonders for my latest web design project.<br />
<span id="more-1304"></span></p>
<p>I was working on a new web design <del>last night</del> early this morning I found myself struggling (probably more than I should have been) with creating tabbed content switcher (hover over one element changes the content of another).  I knew <a href="http://jquery.com" target="_blank">the right way to go was jQuery</a>, and I wanted to avoid downloading a plugin as that would likely end up with more code and another HTTP request to the server.  As I was working on the content switcher, I had one of those &#8220;Let&#8217;s try this and see what it does&#8221; moments (those tend to work all to often for me).  It turned out that it did half of what I needed, so I removed another line and voila! I had my content switcher.  So without further ado, here it is.</p>
<h3>The Story</h3>
<p>This project was a site I took over from another developer.  My responsibilities were to finish the project and clean things up.  The previous developer went 95 yards, I needed to put the ball in the end zone.  For legal reasons, I can not show a screenshot of the full comp unfortunately. I initially was just going to clean up code and fix validation, CSS, and jQuery.  However, I quickly realized that would end up making it harder.  So I decided to rewrite the HTML and CSS and duplicate the look and feel of the previous version.  An added benefit to rewriting the code my own way, in addition to being more familiar with the code and all the CSS hooks, is that I could focus on reducing code bloat and cut down on the amount of images being used to help deliver a better performing site to the client.  Here is a look at the tabs themselves.  Hovering over each tab changes the content below:</p>
<p><img src="http://www.poundbangwhack.com/wp-content/uploads/tabbed_content.jpg" alt="" title="tabbed_content" width="547" height="197" class="aligncenter size-full wp-image-1307" /></p>
<h3>The HTML</h3>
<p>My first goal was to create the tabs and still make them SEO friendly by having all the content actually in the markup, and not added/removed as needed.  The markup for the tabs are as follows:</p>
<pre name="code" class="html">
     &lt;div id="main_middle">
      &lt;ul>
       &lt;li id="tab-1">&lt;a href="#" class="active_tab">Tab 1&lt;/a>&lt;/li>
       &lt;li id="tab-2">&lt;a href="#">Tab 2&lt;/a>&lt;/li>
       &lt;li id="tab-3">&lt;a href="#">Tab 3&lt;/a>&lt;/li>
       &lt;li id="tab-4">&lt;a href="#">Tab 4&lt;/a>&lt;/li>
       &lt;li id="tab-5">&lt;a href="#">Tab 5&lt;/a>&lt;/li>
      &lt;/ul>
      &lt;p class="active_tab_content">Content 1 - Lorem ipsum dolor sit amet, consectetur adipiscing elit.&lt;/p>
      &lt;p>Content 2 - Mauris ornare suscipit lacus eget lobortis. Vestibulum quis purus metus, sed condimentum magna.&lt;/p>
      &lt;p>Content 3 - Nunc et turpis laoreet mi dapibus pulvinar. Nunc a facilisis mauris. Nulla facilisi. Morbi sed volutpat elit. Cras varius sollicitudin mi at imperdiet.&lt;/p>
      &lt;p>Content 4 - Ut a consectetur quam. Nulla ut consequat metus. Nunc molestie erat sit amet tortor faucibus elementum. Praesent eu luctus nulla.&lt;/p>
      &lt;p>Content 5 - Proin porttitor mattis erat eget ullamcorper. Lorem ipsum dolor sit amet, consectetur adipiscing elit.&lt;/p>
     &lt;/div>
</pre>
<p>As you can see, the HTML is only 14 lines long: a container element, an unordered list, and paragraph elements (one for each tab).  This is a far cry from the 47 lines of HTML with divs nested 3 deep the previous developer was using.  Additionally, the container has an id as well as each tab, plus a class for the active tab and paragraph and that&#8217;s it.  This can be done without the id&#8217;s, I have them in there for <a href="http://www.poundbangwhack.com/2009/05/15/decrease-your-web-site-load-times-using-css-sprites/">CSS sprite</a> functionality.  The active_tab class is not required, again it&#8217;s something I use for my sprites.</p>
<h3>The CSS</h3>
<p>Here is the pertinent CSS to making this work.  I have a bunch extra for my sprites, but that&#8217;s beside the point:</p>
<pre name="code" class="css">
#main_middle ul li {
 display: -moz-inline-stack;
 display: inline-block;
 zoom: 1;
 *display: inline;
 text-align: center;
 vertical-align: text-top;
}

#main_middle ul li a {
 display: block;
 width: 100%;
 height: 100%;
}

#main_middle p {
 background: url(../images/tab_content_bg.png) 50% 0 no-repeat transparent;
 display: none;
}

#main_middle .active_tab_content {
 display: -moz-inline-stack;
 display: inline-block;
 zoom: 1;
 *display: inline;
}

#main_middle ul #tab-2 a { /* Example of Sprite Usage */
 background-position: -95px 0;
}

#main_middle ul #tab-2 .active_tab { /* Example of Sprite Usage  */
 background-position: -95px -79px;
</pre>
<p>The display/zoom lines is for <a href="http://blog.mozilla.com/webdev/2009/02/20/cross-browser-inline-block/"  target="_blank">cross-browser inline-block display</a>.  The code for the anchor elements simply sets them to a block the full size of the list item parent.  Next, all paragraph elements are hidden and only the one with the &#8220;active_tab_content&#8221; class is displayed.  The background is set for all the paragraph elements, although I could&#8217;ve just as easily set it for just the display content only.</p>
<p>Here is my sprite so you get the idea of what I&#8217;m doing with that code:<br />
<img src="http://www.poundbangwhack.com/wp-content/uploads/mid_icons.jpg" alt="" title="mid_icons" width="475" height="158" class="aligncenter size-full wp-image-1330" /></p>
<h3>The jQuery</h3>
<p>The biggest problem I was encountering while writing the jQuery was that when the user stops mousing over the tabs, the last tab moused over should remain visible, and not revert back to the &#8220;active_tab&#8221; and &#8220;active_tab_content&#8221; tab.</p>
<pre name="code" class="js">
$(function() {
 $("#main_middle ul li a").each(function(index) {
  $(this).hover(function() {
   $("#main_middle ul li a").each(function() { $(this).removeClass("active_tab"); });
   $("#main_middle p").each(function() { $(this).removeClass("active_tab_content"); });
   $(this).addClass("active_tab");
   $("#main_middle p:eq("+index+")").addClass("active_tab_content");
  });
 });
});
</pre>
<p>The jQuery code loops through each of the anchor elements and assigns a hover function to them.  The first thing this hover function does is loops through all anchors (tabs) and all paragraphs (tab content) and removes the classes.  It then adds the &#8220;active_tab&#8221; class to the current tab and the &#8220;active_tab_content&#8221; class to the respective paragraph.  It does this through the use of indexes.  One each pass through the anchors, the current element index is passed through the function and then used to select the paragraph with the equivalent index via the <a href="http://api.jquery.com/eq-selector/" target="_blank">eq selector.</a>  And that&#8217;s it.  My mistake that I kept running into, was assigning second function to the hover() to activate on mouseout.  This function was removing the classes that were being added.  This was my moment of <del>brilliance</del> luck when I removed that code by chance and everything worked.</p>
<h3><a href="http://www.poundbangwhack.com/scripts_source/tabbed_content_switcher/demo.html">See the code in action here</a></h3>
<p></p>
<p>You can use this code to make as many tabs as you need.  Just make sure you have as many paragraph elements as you do list elements and that the content for list item 1 corresponds with the content for paragraph 1.  I used inline tabs, but this can easily be done with vertical tabs as well, the logic is still the same.  Feel free to copy/use this code for your own purposes.  Share a link to your implementations in the comments below and/or how you would have done this differently.  Comments are welcome and enjoyed.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.poundbangwhack.com/2010/06/27/jquery-tabbed-content-switcher/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>CSS Sprites without the CSS (mostly)</title>
		<link>http://www.poundbangwhack.com/2010/06/21/css-sprites-without-the-css-mostly/</link>
		<comments>http://www.poundbangwhack.com/2010/06/21/css-sprites-without-the-css-mostly/#comments</comments>
		<pubDate>Mon, 21 Jun 2010 08:26:18 +0000</pubDate>
		<dc:creator>Mark Stoecker</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[Sprites]]></category>

		<guid isPermaLink="false">http://www.poundbangwhack.com/?p=1301</guid>
		<description><![CDATA[If you read that post, and I suggest you do, you'll see that the author talks about using Sprites without the use of a CSS Background Image.  When I rolled over the examples though, I got a basic sprite functionality.  But that's what he was talking about.  Although he mentioned they were just &#60;img /&#62; tags.  I just wasn't seeing it.  ]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s been a while since I blogged.  Hopefully I can get back into it on a regular basis now.</p>
<p>I came across an interesting post today titled <a href="http://www.sohtanaka.com/web-design/css-sprites-wout-background-images/" target="_blank"><strong>CSS Sprites w/out Using Background Images.</strong></a>  Now obviously I was intrigued as I&#8217;ve discussed <a href="http://www.poundbangwhack.com/2009/05/15/decrease-your-web-site-load-times-using-css-sprites/">how to use CSS Sprites</a> before and have really been getting into them lately with some new killer projects I&#8217;ve been contracted to do.  But this post, I just had to read.</p>
<p>If you read that post, and I suggest you do, you&#8217;ll see that the author talks about using Sprites without the use of a CSS Background Image.  When I rolled over the examples though, I got a basic sprite functionality.  But that&#8217;s what he was talking about.  Although he mentioned they were just &lt;img /&gt; tags.  I just wasn&#8217;t seeing it.  </p>
<p><a href="http://www.sohtanaka.com" target="_blank">Soh Tanaka</a> mentions that the goal was to make it simple for a client who may have multiple affiliate banners to upload and didn&#8217;t want his client trying to have to mess with CSS and creating custom classes and code.  Good point.  The way Soh went about achieving this was simple: Instead of moving the background image of an element, use an &lt;img /&gt; tag <strong>with the same sprite image</strong> and move the &lt;img /&gt; tag up with negative margins.  The theory is identical, the execution is just different.  </p>
<blockquote><p>Instead of setting a background image on the element and doing a <code>background-position: 0 -182px;</code> on the <code>:hover</code> Soh does uses an actual &lt;img /&gt; tag and sets a <code>margin-top: -182px</code> on it (182px was the size of the image, or half of it).  </p></blockquote>
<p>Now as <a href="http://www.wait-till-i.com/" target="_blank">author Chris Heilmann</a> mentioned in <a href="http://www.sohtanaka.com/web-design/css-sprites-wout-background-images/#comments" target="_blank">the comments</a>, this isn&#8217;t the best use of sprites in the world, and kind of defeats the purpose. But the functionality is there and it was something Soh did to make it easier on his client (which we&#8217;ve all done) and was just showing the technique for technique&#8217;s sake.  By the way, Chris authored <a href="http://www.amazon.com/gp/product/1590596803?ie=UTF8&#038;tag=httpwwwdese09-20&#038;link_code=as3&#038;camp=211189&#038;creative=373489&#038;creativeASIN=1590596803" target="_blank">a fantastic JavaScript/DOM Scripting/AJAX book</a> I have in <a href="http://www.poundbangwhack.com/tech-library/">my Tech Library.</a>  It&#8217;s definitely worth the read.</p>
<p>Anyways, I just wanted to drop this tip as I stared at it for a while utterly confused and wondering how this tip was any different as all I could see was the same sprite functionality.  But, like I said, that&#8217;s the point.  It still functions the same.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.poundbangwhack.com/2010/06/21/css-sprites-without-the-css-mostly/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Our first WordPress Plugin: WordPress Woot Watcher</title>
		<link>http://www.poundbangwhack.com/2010/02/17/our-first-wordpress-plugin-wordpress-woot-watcher/</link>
		<comments>http://www.poundbangwhack.com/2010/02/17/our-first-wordpress-plugin-wordpress-woot-watcher/#comments</comments>
		<pubDate>Wed, 17 Feb 2010 17:23:29 +0000</pubDate>
		<dc:creator>Mark Stoecker</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Wordpress Plugins]]></category>
		<category><![CDATA[Plugin]]></category>
		<category><![CDATA[Woot]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://www.poundbangwhack.com/?p=1268</guid>
		<description><![CDATA[In conjunction with Lee Thompson of MySQLHow2.com, we have released our first WordPress Plugin: 
WordPress Woot Watcher

WordPress Woot Watcher, will monitor and check woot, shirt.woot, kids.woot, wine.woot and sellout.woot for new products every 10 hours. When a woot-off is launched, the widget will update the woot product every 30 seconds. WordPress Woot Watcher is a [...]]]></description>
			<content:encoded><![CDATA[<p>In conjunction with <a href="http://www.mysqlhow2.com">Lee Thompson of MySQLHow2.com</a>, we have released our first WordPress Plugin: </p>
<blockquote><h4><a href="http://www.poundbangwhack.com/wordpress/plugins/wordpress-woot-watcher/">WordPress Woot Watcher</a></h4>
</blockquote>
<p>WordPress Woot Watcher, will monitor and check woot, shirt.woot, kids.woot, wine.woot and sellout.woot for new products every 10 hours. When a woot-off is launched, the widget will update the woot product every 30 seconds. WordPress Woot Watcher is a sidebar widget that enables select the woot sites you want to monitor in the administration section. The default installation selects woot.com only.</p>
<p>For all the details, installation, and more, visit the <a href="http://www.poundbangwhack.com/wordpress/plugins/wordpress-woot-watcher/">WordPress Woot Watcher</a> page.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.poundbangwhack.com/2010/02/17/our-first-wordpress-plugin-wordpress-woot-watcher/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to append values to an array in bash</title>
		<link>http://www.poundbangwhack.com/2010/02/04/how-to-append-values-to-an-array-in-bash/</link>
		<comments>http://www.poundbangwhack.com/2010/02/04/how-to-append-values-to-an-array-in-bash/#comments</comments>
		<pubDate>Thu, 04 Feb 2010 20:14:08 +0000</pubDate>
		<dc:creator>Mark Stoecker</dc:creator>
				<category><![CDATA[How To]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[SSH/Command Line]]></category>
		<category><![CDATA[Shell Scripts]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[SSH]]></category>

		<guid isPermaLink="false">http://www.poundbangwhack.com/?p=1257</guid>
		<description><![CDATA[Last week I was working on a bash script for a project at work.  The script parsed through a log file with server load and disk usage statistics at regular intervals.  The script was calculating the average CPU idle time, disk utilization, and disk usage for servers.  After calculating the averages for [...]]]></description>
			<content:encoded><![CDATA[<p>Last week I was working on a bash script for a project at work.  The script parsed through a log file with server load and disk usage statistics at regular intervals.  The script was calculating the average CPU idle time, disk utilization, and disk usage for servers.  After calculating the averages for each of these three metrics, I then proceeded to loop through all the lines in the file and create an array of all the times when the CPU idle time was below average, or the disk utilization or usage was above average.<br />
<span id="more-1257"></span><br />
The code that I used was originally taken from the article <a href="http://fvue.nl/wiki/Bash:_Append_to_array_using_while-loop" target="_blank">Bash: Append to array using while-loop</a> by Freddy Vulto. The concept that Freddy used is essentially the same as what I was doing.  I was using a <span class="pre">for</span> loop to scan a file, and if certain values in the file met a condition, the date was added to an array which was printed at the end of the script execution.  The code to achieve this is as follows:</p>
<p><code>array=( ${array[@]-} $(echo "$variable") )</code></p>
<p>The code above reads as follows:</p>
<p><span class="pre">array=( &#8230;.. )</span> : Set your array variable named, appropriately enough: <em>array</em>.</p>
<p><span class="pre">${array[@]-}</span> : Read all variables from the array <em>array</em>.  The hyphen at the end prevents an &#8220;unbound variable&#8221; error when <span class="code">-u</span> or <span class="code">-o nounset</span> is set and <em>array</em> is an empty array.  This is useful for appending the first value to an empty array in the event that one of the aforementioned flags is set.</p>
<p><span class="pre">$(echo &#8220;$variable&#8221;)</span> : Add the variable <em>$variable</em> to the array through the use of command substitution <span class="code">$(&#8230;)</span> by reading the output of <span class="code">echo &#8220;$variable&#8221;</span> as the input value for the array.  The reason for command substitution is that if you try it without the <span class="code">$(&#8230;)</span>, bash will read <span class="code">echo</span> and <span class="code">&#8220;$variable&#8221;</span> as separate entries into the array instead of just the value of <em>$variable</em></p>
]]></content:encoded>
			<wfw:commentRss>http://www.poundbangwhack.com/2010/02/04/how-to-append-values-to-an-array-in-bash/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Improve Your WordPress Blog&#8217;s Performance With this Database Hack</title>
		<link>http://www.poundbangwhack.com/2010/01/09/improve-your-wordpress-blogs-performance-with-this-database-hack/</link>
		<comments>http://www.poundbangwhack.com/2010/01/09/improve-your-wordpress-blogs-performance-with-this-database-hack/#comments</comments>
		<pubDate>Sun, 10 Jan 2010 05:52:50 +0000</pubDate>
		<dc:creator>Mark Stoecker</dc:creator>
				<category><![CDATA[Blogging]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Database]]></category>
		<category><![CDATA[Hack]]></category>
		<category><![CDATA[Optimization]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://www.poundbangwhack.com/?p=1236</guid>
		<description><![CDATA[One of daily responsibilities as a database administrator is maintaining the health of our shared hosting environment.  In doing so, I deal with plenty of <a href="http://www.wordpress.org">WordPress</a> blogs daily.  The one thing I have noticed is that <a href="http://www.poundbangwhack.com/2009/12/02/avoid-wordpress-statpress-plugin-like-the-plague/">many WordPress plugins are very poorly designed and can cause problems</a> in a shared hosting environment.  WordPress at it's core though, is very well designed, although I have noticed some areas of possible improvement.  As I come across common issues, I will post the fixes for them here for all to use.]]></description>
			<content:encoded><![CDATA[<p><em><strong>**UPDATE**:</strong> After further research of the query below, I have found some additional information.  The query was first introduced in WP 2.3 and is used for comment flood protection.  I am currently running WP 2.9.1 and do not have the issue as the query has been modified and using a proper index to assist with the query speed.  If you are using the latest version of WP, you won&#8217;t have this problem.  I am still trying to find exactly when the query was changed so you all can know where you stand.  However, I know that some people don&#8217;t upgrade their WP version due to changes they have made which upgrading will break.  If you are on an older version of WP and have a large number of comments (tens to hundreds of thousands), this query will help improve your comment post times.  If you are familiar enough with MySQL, look at the wp_comments table in your database.  If there is an index on the `comment_date_gmt` column, you are ok.  If not, read on, and run the query below as adding an index to the `comment_date_gmt` column won&#8217;t work as your query does not have that column in it&#8217;s WHERE clause.</em></p>
<p>One of daily responsibilities as a database administrator is maintaining the health of our shared hosting environment.  In doing so, I deal with plenty of <a href="http://www.wordpress.org">WordPress</a> blogs daily.  The one thing I have noticed is that <a href="http://www.poundbangwhack.com/2009/12/02/avoid-wordpress-statpress-plugin-like-the-plague/">many WordPress plugins are very poorly designed and can cause problems</a> in a shared hosting environment.  WordPress at it&#8217;s core though, is very well designed, although I have noticed some areas of possible improvement.  As I come across common issues, I will post the fixes for them here for all to use.<br />
<span id="more-1236"></span><br />
The following is one of the most common queries I see all the time that actually comes from the WordPress core:<br />
<code>SELECT comment_date_gmt<br />
FROM wp_comments<br />
WHERE comment_author_IP = '94.142.131.22' OR<br />
	comment_author_email = 'yigrzds@tkgmd.com'<br />
ORDER BY comment_date DESC<br />
LIMIT 1<br />
</code></p>
<p>The IP and email is obviously only sample data.  On the example server, the <a href="http://dev.mysql.com/doc/refman/5.0/en/using-explain.html">MySQL Explain</a> for the query showed the following:</p>
<p><code>id: 1<br />
select_type: SIMPLE<br />
table: wp_comments<br />
type: ALL<br />
possible_keys: NULL<br />
key: NULL<br />
key_len: NULL<br />
ref: NULL<br />
rows: 76845<br />
Extra: Using where; Using filesort</code></p>
<p>Now, a query that examines 76,000+ rows is not the end of the world, but with enough traffic, it can slow down the server immensely, mainly because the explain above indicates that no key is being used on the query and therefore a full table scan is being performed.</p>
<p>To help alleviate this, the following code can be executed from a MySQL command prompt, or a management type interface like phpMyAdmin:</p>
<p><code>mysql> <strong>ALTER TABLE wp_comments ADD INDEX(comment_author_IP), ADD INDEX(comment_author_email)</strong></code></p>
<p><strong>**Note: The above optimization assumes the default database prefix of &#8220;wp&#8221;.  If your database prefix is different, replace &#8220;wp&#8221; in the above query with your databases prefix.**</strong></p>
<p>Afterward, the explain on the exact same query returns the following:</p>
<p><code>id: 1<br />
select_type: SIMPLE<br />
table: wp_comments<br />
type: index_merge<br />
possible_keys: comment_author_IP,comment_author_email<br />
key: comment_author_IP,comment_author_email<br />
key_len: 302,302<br />
ref: NULL<br />
rows: 2139<br />
Extra: Using union(comment_author_IP,comment_author_email); Using where; Using filesort</code></p>
<p>As you can see, the query now examines 2139 rows as opposed to 76,000+ by using an <a href="http://dev.mysql.com/doc/refman/5.0/en/index-merge-optimization.html">Index Merge,</a> which means the query is pulling data using two different indexes on the same query.  Now keep in mind, index merges are only available in MySQL 5.0+.  If you are using MySQL 4.1 or below, an index merge will not work, and I would suggest adding an index on the comment_author_IP field as it will tend to have more unique values.  Simply remove everything after the comma in the above command.  </p>
<p>This optimization will improve the speed of the query on your database and will provide better performance on your WordPress blog.  Please share your thoughts below on this hack and the results for you.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.poundbangwhack.com/2010/01/09/improve-your-wordpress-blogs-performance-with-this-database-hack/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
