<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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/" version="2.0">

<channel>
	<title>WPStorm</title>
	
	<link>http://wpstorm.net</link>
	<description>Coding, Wordpress and Plugin Development</description>
	<lastBuildDate>Mon, 30 Jan 2012 00:25:21 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="wpstorm" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://wpstorm.net/feed/" /><feedburner:emailServiceId xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">wpstorm</feedburner:emailServiceId><feedburner:feedburnerHostname xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">http://feedburner.google.com</feedburner:feedburnerHostname><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://add.my.yahoo.com/rss?url=http%3A%2F%2Fwpstorm.net%2Ffeed%2F" src="http://us.i1.yimg.com/us.yimg.com/i/us/my/addtomyyahoo4.gif">Subscribe with My Yahoo!</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.newsgator.com/ngs/subscriber/subext.aspx?url=http%3A%2F%2Fwpstorm.net%2Ffeed%2F" src="http://www.newsgator.com/images/ngsub1.gif">Subscribe with NewsGator</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://feeds.my.aol.com/add.jsp?url=http%3A%2F%2Fwpstorm.net%2Ffeed%2F" src="http://o.aolcdn.com/favorites.my.aol.com/webmaster/ffclient/webroot/locale/en-US/images/myAOLButtonSmall.gif">Subscribe with My AOL</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.bloglines.com/sub/http://wpstorm.net/feed/" src="http://www.bloglines.com/images/sub_modern11.gif">Subscribe with Bloglines</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.netvibes.com/subscribe.php?url=http%3A%2F%2Fwpstorm.net%2Ffeed%2F" src="http://www.netvibes.com/img/add2netvibes.gif">Subscribe with Netvibes</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://fusion.google.com/add?feedurl=http%3A%2F%2Fwpstorm.net%2Ffeed%2F" src="http://buttons.googlesyndication.com/fusion/add.gif">Subscribe with Google</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.pageflakes.com/subscribe.aspx?url=http%3A%2F%2Fwpstorm.net%2Ffeed%2F" src="http://www.pageflakes.com/ImageFile.ashx?instanceId=Static_4&amp;fileName=ATP_blu_91x17.gif">Subscribe with Pageflakes</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.plusmo.com/add?url=http%3A%2F%2Fwpstorm.net%2Ffeed%2F" src="http://plusmo.com/res/graphics/fbplusmo.gif">Subscribe with Plusmo</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.thefreedictionary.com/_/hp/AddRSS.aspx?http%3A%2F%2Fwpstorm.net%2Ffeed%2F" src="http://img.tfd.com/hp/addToTheFreeDictionary.gif">Subscribe with The Free Dictionary</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.bitty.com/manual/?contenttype=rssfeed&amp;contentvalue=http%3A%2F%2Fwpstorm.net%2Ffeed%2F" src="http://www.bitty.com/img/bittychicklet_91x17.gif">Subscribe with Bitty Browser</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.live.com/?add=http%3A%2F%2Fwpstorm.net%2Ffeed%2F" src="http://tkfiles.storage.msn.com/x1piYkpqHC_35nIp1gLE68-wvzLZO8iXl_JMledmJQXP-XTBOLfmQv4zhj4MhcWEJh_GtoBIiAl1Mjh-ndp9k47If7hTaFno0mxW9_i3p_5qQw">Subscribe with Live.com</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://mix.excite.eu/add?feedurl=http%3A%2F%2Fwpstorm.net%2Ffeed%2F" src="http://image.excite.co.uk/mix/addtomix.gif">Subscribe with Excite MIX</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.webwag.com/wwgthis.php?url=http%3A%2F%2Fwpstorm.net%2Ffeed%2F" src="http://www.webwag.com/images/wwgthis.gif">Subscribe with Webwag</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.podcastready.com/oneclick_bookmark.php?url=http%3A%2F%2Fwpstorm.net%2Ffeed%2F" src="http://www.podcastready.com/images/podcastready_button.gif">Subscribe with Podcast Ready</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.wikio.com/subscribe?url=http%3A%2F%2Fwpstorm.net%2Ffeed%2F" src="http://www.wikio.com/shared/img/add2wikio.gif">Subscribe with Wikio</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.dailyrotation.com/index.php?feed=http%3A%2F%2Fwpstorm.net%2Ffeed%2F" src="http://www.dailyrotation.com/rss-dr2.gif">Subscribe with Daily Rotation</feedburner:feedFlare><item>
		<title>PayPal Donations Review</title>
		<link>http://wpstorm.net/2011/04/paypal-donations-review/</link>
		<comments>http://wpstorm.net/2011/04/paypal-donations-review/#comments</comments>
		<pubDate>Sat, 16 Apr 2011 09:07:42 +0000</pubDate>
		<dc:creator>Lotta</dc:creator>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[PayPal]]></category>
		<category><![CDATA[Plugin]]></category>
		<category><![CDATA[Review]]></category>

		<guid isPermaLink="false">http://wpstorm.net/?p=369</guid>
		<description><![CDATA[Joost de Valk have written a great review of the PayPal Donations plugin for WordPress. It was really nice to see such a positive review from one of the more experienced WordPress developers.]]></description>
			<content:encoded><![CDATA[<p>Joost de Valk have written a great review of the PayPal Donations plugin for WordPress. It was really nice to see such a positive review from one of the more experienced WordPress developers. Awesome! <img src='http://wpstorm.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Check out Yoast&#8217;s <a title="PayPal Donations Review" href="http://yoast.com/wp-plugin-review/paypal-donations/">PayPal Donations Review</a> »</p>
<img src="http://feeds.feedburner.com/~r/wpstorm/~4/zjl6DQurfh0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://wpstorm.net/2011/04/paypal-donations-review/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Use AWStats with Amazon S3 / CloudFront</title>
		<link>http://wpstorm.net/2011/01/awstats-amazon-s3-cloudfront/</link>
		<comments>http://wpstorm.net/2011/01/awstats-amazon-s3-cloudfront/#comments</comments>
		<pubDate>Thu, 13 Jan 2011 04:12:09 +0000</pubDate>
		<dc:creator>Lotta</dc:creator>
				<category><![CDATA[Cloud Services]]></category>
		<category><![CDATA[Amazon]]></category>
		<category><![CDATA[AWS]]></category>
		<category><![CDATA[AWStats]]></category>
		<category><![CDATA[CloudFront]]></category>
		<category><![CDATA[S3]]></category>

		<guid isPermaLink="false">http://wpstorm.net/?p=366</guid>
		<description><![CDATA[I&#8217;ve recently written two posts about AWS and log processing with an external server so here comes a final post to wrap it all up and tie it together. Goal To have an automatic cron process that polls Amazon S3 and/or CloudFront log files to your own server and then using logresolvemerge to combine them ...]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve recently written two posts about AWS and log processing with an external server so here comes a final post to wrap it all up and tie it together.</p>
<h2>Goal</h2>
<p>To have an automatic cron process that polls Amazon S3 and/or CloudFront log files to your own server and then using logresolvemerge to combine them for processing with AWStats.</p>
<h2>Requirements</h2>
<p>An Amazon Web Services account where you collect your log files in a bucket. Your own dedicated server, VPS or host where you have shell access to install and configure your own solutions so you can have Python and boto installed as well as adding your own scripts. Also you should have AWStats installed and up and running.<br />
I&#8217;ve made this setup using Ubuntu 10.04 which I run on a VPS over at <a title="Linode VPS hosting" href="http://www.linode.com/?r=bf4cdf3c84c6f6a25529f9e4592488a95f9e34d9">Linode</a> where I currently run a couple of projects.</p>
<h2>Setup</h2>
<p>I&#8217;m currently collecting logs from one CloudFront distribution and one S3 bucket which I have mapped my own CNAMEs to. Let&#8217;s call them s3.example.com and cdn.example.com. Then I have another bucket which is not public but where I store other things. So in this bucket I&#8217;ve made a folder named logs and in that folder I have a folder for each domain.<br />
So the log prefixes for me in this case becomes<br />
/logs/s3.example.com<br />
/logs/cdn.example.com</p>
<h3>Download AWS Logs</h3>
<p>To be able to download the log files from Amazon to a local directory, check out my earlier post about <a href="http://wpstorm.net/2010/11/aws-s3-logs-boto-python/">downloading AWS logs with boto and Python</a>.</p>
<h3>Configure AWStats</h3>
<p>Now we need to setup some AWStats configuration to prepare it for handling the AWS logs. I&#8217;ll create to configuration files for this example:<br />
<code>/etc/awstats/awstats.cdn.example.com.conf<br />
/etc/awstats/awstats.s3.example.com.conf</code></p>
<p>I assume that you already know your way around configuring AWStats so I&#8217;ll focus on the specifics for AWS compability. The final log files that will be created later on for AWStats to use will be stored in /var/log/apache2/ so I point the LogFile option to that location. And then we just have to setup the LogFormat correctly. Below is the setup for S3 log files and then for CloudFront log files.</p>
<h4>S3 AWStats LogFormat</h4>
<p><code>LogFile="/var/log/apache2/s3.example.com.log"<br />
LogFormat="%other %extra1 %time1 %host %logname %other %method %url %otherquot %code %extra2 %bytesd %other %extra3 %extra4 %refererquot %uaquot %other"</code></p>
<h4>CloudFront AWStats LogFormat</h4>
<p><code>LogFile="/var/log/apache2/cdn.example.com.log"<br />
LogFormat="%time2 %cluster %bytesd %host %method %virtualname %url %code %referer %ua %query"</code></p>
<p>If you also want the CloudFront statistics to display information about the edges you can check out my post about <a href="http://wpstorm.net/2011/01/amazon-cloudfront-edges-awstats/">CloudFront Edges in AWStats</a>.</p>
<h3>Automate everything</h3>
<p>Now when we have all components in place, we just need to automate them so we later on can add it to cron. I&#8217;ve made a bash script which takes care of the automation. The script is not very complicated but I&#8217;ll make a quick walk through of it, so it can be modified to specific needs and setups. I added a number at the comment for each section in the script which I use as a reference in the list below.</p>
<ol>
<li>A few variables used in the script. The date variable is just to collect the current date. I don&#8217;t really use this information at the moment other than appending it to a temporary directory name. But in case I want to expand on the script in the future to keep the archives around it could be handy. Then I create a variable for each log I want to process. In this example I process two logs, one S3 and one CloudFront, so I have 2 variables here containing paths to temp directories where the log files will be downloaded.</li>
<li>Here we use the boto Python script I created earlier to download all log files from Amazon to our local temp directories.</li>
<li>Now when all the log files have been downloaded, we need to combine them into a format that AWStats can understand. The first line combines the CloudFront logs. They are very straightforward so they just need to be combined into one large file and AWStats are ready to process it. Then the second line is to process the S3 log files into one large log file. S3 is a bit more tricky as it contains a few things AWStats don&#8217;t understand, so I use a regexp to remove the things that would cause AWStats some headache. I store my AWS final log files in /var/log/apache2/ which is the path I defined in the LogFile option for AWStats earlier.</li>
<li>Our log files are now downloaded and combined into the final log files that are stored in /var/log/apache2/ so I simply delete the temporary downloaded files, as I don&#8217;t need to keep them around anymore.</li>
<li>And finally we execute AWStats to update the statistics with the log files we just have processed.</li>
</ol>
<pre class="brush: bash; title: get-aws-logs.sh; notranslate">
#!/bin/bash
# Initial, cron script to download and merge AWS logs
# 29/11 - 2010, Johan Steen

# 1. Setup variables
date=`date +%Y-%m-%d`
cdn_folder=&quot;/tmp/log_cdn_$date/&quot;
static_folder=&quot;/tmp/log_static_$date/&quot;

# 2. Call the python script to download log folders from Amazon to local folders
python /home/johan/get-aws-logs.py --prefix=logs/cdn.example.com/ --local=$cdn_folder
python /home/johan/get-aws-logs.py --prefix=logs/s3.example.com/ --local=$static_folder

# 3. Merge and add the downloaded log files to the local log file
/usr/local/bin/logresolvemerge.pl ${cdn_folder}* &gt;&gt; /var/log/apache2/cdn.example.com.log
/usr/local/bin/logresolvemerge.pl ${static_folder}* | sed -e 's/SOAP\.\([A-Z]*\)/\1/' -e 's/REST\.\([A-Z]*\)\.[A-Z]*/\1/' &gt;&gt; /var/log/apache2/s3.example.com.log

# 4. Delete the downloaded log files
rm -rf $cdn_folder
rm -rf $static_folder

# 5. Update the AWStats Logs
/usr/lib/cgi-bin/awstats.pl -config=cdn.example.com -update
/usr/lib/cgi-bin/awstats.pl -config=s3.example.com -update
</pre>
<h3>Cron it!</h3>
<p>And finally, add the bash script to your cron to be run as often as you feel is appropriate for your setup.</p>
<pre class="brush: plain; title: ; notranslate">
# Process the AWS Logs at 4:43 every night
43 4 * * * root /home/johan/get-aws-logs.sh &gt;/dev/null
</pre>
<p>And that&#8217;s it. Feel free to leave a comment if you have any questions or suggestions for improvements.</p>
<img src="http://feeds.feedburner.com/~r/wpstorm/~4/JDKa34hEF5w" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://wpstorm.net/2011/01/awstats-amazon-s3-cloudfront/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Amazon CloudFront Edges in AWStats</title>
		<link>http://wpstorm.net/2011/01/amazon-cloudfront-edges-awstats/</link>
		<comments>http://wpstorm.net/2011/01/amazon-cloudfront-edges-awstats/#comments</comments>
		<pubDate>Fri, 07 Jan 2011 02:02:00 +0000</pubDate>
		<dc:creator>Lotta</dc:creator>
				<category><![CDATA[Cloud Services]]></category>
		<category><![CDATA[Amazon]]></category>
		<category><![CDATA[AWS]]></category>
		<category><![CDATA[AWStats]]></category>
		<category><![CDATA[CloudFront]]></category>
		<category><![CDATA[Log]]></category>

		<guid isPermaLink="false">http://wpstorm.net/?p=363</guid>
		<description><![CDATA[Here&#8217;s a quick breakdown of how to get the usage of your different Amazon CloudFront Edge locations within AWStats. I confess that I get some crazy pleasure from collecting statistics, still though, bandwidth usage is of interest in this case, as well as hits and that it can be interesting to see which regions most ...]]></description>
			<content:encoded><![CDATA[<div id="attachment_364" class="wp-caption alignright" style="width: 310px"><a href="http://wpstorm.net/files/2011/01/cloudfront-awstats-cluster.jpg"><img src="http://wpstorm.net/files/2011/01/cloudfront-awstats-cluster-300x144.jpg" alt="" title="CloudFront Edges in AWStats" width="300" height="144" class="size-medium wp-image-364" /></a><p class="wp-caption-text">Click to enlarge</p></div>
<p>Here&#8217;s a quick breakdown of how to get the usage of your different Amazon CloudFront Edge locations within AWStats. I confess that I get some crazy pleasure from collecting statistics, still though, bandwidth usage is of interest in this case, as well as hits and that it can be interesting to see which regions most of the visitors come from.</p>
<p>I use the cluster functionality in AWStats to display the CloudFront Edges, as can be seen in the screenshot to the right.</p>
<p>I&#8217;m running AWStats on an Ubuntu server and this guide assumes that you are already collecting your CloudFront logs to a server and processes them with AWStats. If not, check out my other article dealing with that.</p>
<p>Let&#8217;s work with our hypothetical CloudFront distribution named cdn.example.com.</p>
<p>In Ubuntu AWStats stores the configurations files in /etc/awstats/ so I will assume there is a file located there named<br />
<code>/etc/awstats/awstats.cdn.example.com.conf</code><br />
which processes the CloudFront log already. </p>
<p>If you have configured the above .conf file properly for CloudFront, %cluster is collected in the LogFormat which contains all information needed to be able to display the edges. So now we only need to tell AWStats to start using that information.</p>
<p>First in the awstats.cdn.example.com.conf, enable cluster statistics by finding ShowClusterStats=0 and change it to:<br />
<code>ShowClusterStats=PHB</code><br />
And then continue down to the plugin section and uncomment<br />
<code>LoadPlugin="clusterinfo"</code></p>
<p>Now we only need to tell AWStats the name of the edges, so they make sense when checking the statistics later on. In AWStats DirData directory, create a file named clusterinfo.[your awstats config name].txt</p>
<p>Which in our example would be<br />
<code>/var/lib/awstats/clusterinfo.cdn.example.com.txt</code></p>
<p>This file shall contain a tab separated list of cluster numbers and then a text to display for each cluster. At the time of writing this article this is the complete list to paste into that file for all available CloudFront Edges. If Amazon adds more edges in the future they will have to be added at that time.</p>
<pre class="brush: plain; title: ; notranslate">
DFW3    USA: Dallas/Fort Worth, TX
EWR2    USA: Newark, NJ
IAD2    USA: Ashburn, VA
JAX1    USA: Jacksonville, FL
JFK1    USA: New York, NY
LAX1    USA: Los Angeles, CA
MIA3    USA: Miami, FL
SEA4    USA: Seattle, WA
SFO4    USA: Palo Alto, CA
STL2    USA: St. Louis, MO
AMS1    Europe: Amsterdam
DUB2    Europe: Dublin
FRA2    Europe: Frankfurt
LHR3    Europe: London
HKG1    Asia: Hong Kong
NRT4    Asia: Tokyo
SIN2    Asia: Singapore
</pre>
<p>Okay, that&#8217;s it, the next time AWStats updates the statistics output you should start getting Edge usage outputted in the Cluster section, like in the screenshot above.</p>
<img src="http://feeds.feedburner.com/~r/wpstorm/~4/R-LPp-OD-sY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://wpstorm.net/2011/01/amazon-cloudfront-edges-awstats/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Download AWS S3 Logs with Python &amp; boto</title>
		<link>http://wpstorm.net/2010/11/aws-s3-logs-boto-python/</link>
		<comments>http://wpstorm.net/2010/11/aws-s3-logs-boto-python/#comments</comments>
		<pubDate>Mon, 29 Nov 2010 00:21:19 +0000</pubDate>
		<dc:creator>Lotta</dc:creator>
				<category><![CDATA[Cloud Services]]></category>
		<category><![CDATA[Amazon]]></category>
		<category><![CDATA[AWS]]></category>
		<category><![CDATA[boto]]></category>
		<category><![CDATA[Log]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://wpstorm.net/?p=362</guid>
		<description><![CDATA[I&#8217;ve started to move my static content for some of my web sites to Amazon Web Services using S3 and CloudFront for delivery. I&#8217;ve enabled logging for my CloudFront distributions as well as my public S3 buckets, and wanted to be able to automatically download the logs using cron to my server for processing with ...]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve started to move my static content for some of my web sites to Amazon Web Services using S3 and CloudFront for delivery. I&#8217;ve enabled logging for my CloudFront distributions as well as my public S3 buckets, and wanted to be able to automatically download the logs using cron to my server for processing with AWStats.</p>
<p>To make this happen I&#8217;ve written a script in <a href="http://aws.amazon.com/python/">Python</a> with the <a href="http://boto.cloudhackers.com/">boto module</a> that downloads all generated log files to a local folder and then deletes them from the Amazon S3 Bucket when done. The log files downloaded to the local folder can then be further processed with logresolvemerge and AWStats.</p>
<p>You need to have the boto module installed for this to work. Personally I&#8217;m working with Ubuntu 10.04, where boto can be easily installed by executing:</p>
<pre class="brush: bash; title: ; notranslate">
sudo apt-get install python-boto
</pre>
<p>The script takes some command line arguments that are listed in the doc header. All of these can have a default value set in the head of the get_logs class. If you set default values in the script, the command line arguments are useful if you need to override a default value on some occasions.</p>
<h3>get-aws-logs.py</h3>
<pre class="brush: python; title: ; notranslate">
#! /usr/bin/env python
&quot;&quot;&quot;Download and delete log files for AWS S3 / CloudFront

Usage: python get-aws-logs.py [options]

Options:
  -b ..., --bucket=...    AWS Bucket
  -p ..., --prefix=...    AWS Key Prefix
  -a ..., --access=...    AWS Access Key ID
  -s ..., --secret=...    AWS Secret Access Key
  -l ..., --local=...     Local Download Path
  -h, --help              Show this help
  -d                      Show debugging information while parsing

Examples:
  get-aws-logs.py -b eqxlogs
  get-aws-logs.py --bucket=eqxlogs
  get-aws-logs.py -p logs/cdn.example.com/
  get-aws-logs.py --prefix=logs/cdn.example.com/

This program requires the boto module for Python to be installed.
&quot;&quot;&quot;

__author__ = &quot;Johan Steen (http://www.artstorm.net/)&quot;
__version__ = &quot;0.5.0&quot;
__date__ = &quot;28 Nov 2010&quot;

import boto
import getopt
import sys, os

_debug = 0

class get_logs:
	&quot;&quot;&quot;Download log files from the specified bucket and path and then delete them from the bucket.
	Uses: http://boto.s3.amazonaws.com/index.html
	&quot;&quot;&quot;
	# Set default values
	AWS_BUCKET_NAME = '{bucket}'
	AWS_KEY_PREFIX = '{prefix}'
	AWS_ACCESS_KEY_ID = '{access key}'
	AWS_SECRET_ACCESS_KEY = '{secret key}'
	LOCAL_PATH = '{local path}'
	# Don't change below here
	s3_conn = None
	bucket_list = None

	def __init__(self):
		s3_conn = None
		bucket_list = None

	def start(self):
		&quot;&quot;&quot;Connect, get file list, copy and delete the logs&quot;&quot;&quot;
		self.s3Connect()
		self.getList()
		self.copyFiles()

	def s3Connect(self):
		&quot;&quot;&quot;Creates a S3 Connection Object&quot;&quot;&quot;
		self.s3_conn = boto.connect_s3(self.AWS_ACCESS_KEY_ID, self.AWS_SECRET_ACCESS_KEY)

	def getList(self):
		&quot;&quot;&quot;Connects to the bucket and then gets a list of all keys available with the chosen prefix&quot;&quot;&quot;
		bucket = self.s3_conn.get_bucket(self.AWS_BUCKET_NAME)
		self.bucket_list = bucket.list(self.AWS_KEY_PREFIX)

	def copyFiles(self):
		&quot;&quot;&quot;Creates a local folder if not already exists and then download all keys and deletes them from the bucket&quot;&quot;&quot;
		# Using makedirs as it's recursive
		if not os.path.exists(self.LOCAL_PATH):
			os.makedirs(self.LOCAL_PATH)
		for key_list in self.bucket_list:
			key = str(key_list.key)
			# Get the log filename (L[-1] can be used to access the last item in a list).
			filename = key.split('/')[-1]
			# check if file exists locally, if not: download it
			if not os.path.exists(self.LOCAL_PATH+filename):
				key_list.get_contents_to_filename(self.LOCAL_PATH+filename)
				if _debug:
					print &quot;Downloaded from bucket: &quot;+filename
			# check so file is downloaded, if so: delete from bucket
			if os.path.exists(self.LOCAL_PATH+filename):
				key_list.delete()
				if _debug:
					print &quot;Deleted from bucket:    &quot;+filename

def usage():
	print __doc__

def main(argv):
	try:
		opts, args = getopt.getopt(argv, &quot;hb:p:l:a:s:d&quot;, [&quot;help&quot;, &quot;bucket=&quot;, &quot;prefix=&quot;, &quot;local=&quot;, &quot;access=&quot;, &quot;secret=&quot;])
	except getopt.GetoptError:
		usage()
		sys.exit(2)
	logs = get_logs()
	for opt, arg in opts:
		if opt in (&quot;-h&quot;, &quot;--help&quot;):
			usage()
			sys.exit()
		elif opt == '-d':
			global _debug
			_debug = 1
		elif opt in (&quot;-b&quot;, &quot;--bucket&quot;):
			logs.AWS_BUCKET_NAME = arg
		elif opt in (&quot;-p&quot;, &quot;--prefix&quot;):
			logs.AWS_KEY_PREFIX = arg
		elif opt in (&quot;-a&quot;, &quot;--access&quot;):
			logs.AWS_ACCESS_KEY_ID = arg
		elif opt in (&quot;-s&quot;, &quot;--secret&quot;):
			logs.AWS_SECRET_ACCESS_KEY = arg
		elif opt in (&quot;-l&quot;, &quot;--local&quot;):
			logs.LOCAL_PATH = arg
	logs.start()

if __name__ == &quot;__main__&quot;:
	main(sys.argv[1:])
</pre>
<p>Have in mind that I&#8217;m pretty new to Linux and to Python, so I bet things can be solved better, easier or in a more beautiful way than what I&#8217;ve done, as well as making it more fail safe.</p>
<p>Feel free to suggest improvements that can be made to the code.</p>
<img src="http://feeds.feedburner.com/~r/wpstorm/~4/w2-L5lm70cE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://wpstorm.net/2010/11/aws-s3-logs-boto-python/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Paste Clipboard to Dropbox with DOpus</title>
		<link>http://wpstorm.net/2010/11/paste-clipboard-dropbox-directory-opus/</link>
		<comments>http://wpstorm.net/2010/11/paste-clipboard-dropbox-directory-opus/#comments</comments>
		<pubDate>Thu, 18 Nov 2010 12:55:24 +0000</pubDate>
		<dc:creator>Lotta</dc:creator>
				<category><![CDATA[Cloud Services]]></category>
		<category><![CDATA[Clipboard]]></category>
		<category><![CDATA[Directory Opus]]></category>
		<category><![CDATA[Dropbox]]></category>
		<category><![CDATA[File Sharing]]></category>
		<category><![CDATA[FTP]]></category>

		<guid isPermaLink="false">http://wpstorm.net/?p=359</guid>
		<description><![CDATA[One thing I keep doing over and over again is taking screenshots to share with friends, colleagues, forums and so on by hosting it online. To make that process as quick and streamlined as possible I&#8217;ve setup a button to automate this in my file manager of choice, Directory Opus. I used to use my ...]]></description>
			<content:encoded><![CDATA[<p>One thing I keep doing over and over again is taking screenshots to share with friends, colleagues, forums and so on by hosting it online. To make that process as quick and streamlined as possible I&#8217;ve setup a button to automate this in my file manager of choice, <a href="http://www.gpsoft.com.au/" title="Directory Opus File Manager">Directory Opus</a>.</p>
<p>I used to use my own web server and FTP to host the images, but nowadays I&#8217;m using the excellent free service <a href="http://db.tt/yxGtERO" title="Dropbox file sharing">Dropbox</a> for this, and for many of my other file sharing needs. If you don&#8217;t already have a Dropbox account, you can use the previous link to signup. It&#8217;s a referral link which gives you (and me) an extra 250 MB of storage for free in addition to the original 2 GB you get.</p>
<p>When I&#8217;ve a screenshot in my Clipboard I want a button in DOpus to perform the following:</p>
<ol>
<li>Paste it to my Public Dropbox folder as a high quality JPEG.</li>
<li>Give the image a name of my choice.</li>
<li>Copy the URL to the image to my Clipboard, ready to be pasted into Messenger, Skype, a forum etc.</li>
</ol>
<div id="attachment_360" class="wp-caption aligncenter" style="width: 530px"><img src="http://wpstorm.net/files/2010/11/dropbox-button.jpg" alt="Dropbox Button in DOpus" title="Dropbox Button" width="520" height="320" class="size-full wp-image-360" /><p class="wp-caption-text">Paste to Dropbox button in DOpus</p></div>
<p>I&#8217;ve my screen grab application mapped to the keyboard shortcut Win+S to, so I can at any time drag out a rectangle on screen that goes into the Clipboard and then run the function in DOpus to be able to share it immediately.</p>
<p>Here&#8217;s the script I&#8217;ve added to my button:</p>
<pre class="brush: powershell; title: ; notranslate">
@set url = http://dl.dropbox.com/u/&lt;dropbox id&gt;/
@set dropbox = E:\User Storage\Dropbox\Public\
@set imagequality = 90
@set imagefile = {dlgstring|Set image name (without extension)}

Clipboard PASTE jpg:{$imagequality} AS=&quot;{$dropbox}{$imagefile}.jpg&quot;

Clipboard SET {$url}{$imagefile}.jpg

@confirm Done! URL copied to clipboard.|Okidoki
</pre>
<p>When you press the button, you get asked for a name to give the file, and then it copies it to your dropbox, and stores the URL in the clipboard and gives you a confirmation. Change the @set url line to use your own dropbox id so the URL stored in the clipboard is correct, and also change the path in @set dropbox to your public dropbox folder.</p>
<p>If you rather prefer to use your own FTP and web server instead of Dropbox, here&#8217;s my old button script that I used before I switched to Dropbox, feel free to use that as a starting point to tweak to fit your needs.</p>
<pre class="brush: powershell; title: ; notranslate">
@set url = http://your.domain.address/
@set tmpfolder = E:\User Storage\Downloads\
@set imagefile = {dlgstring|Set image name (without extension)}

Clipboard PASTE jpg:90 AS=&quot;{$tmpfolder}{$imagefile}.jpg&quot;

Copy FILE=&quot;{$tmpfolder}{$imagefile}.jpg&quot; TO=@your-ftp-site-dopus-profile-name

Delete FILE=&quot;{$tmpfolder}{$imagefile}.jpg&quot; QUIET

Clipboard SET {$url}{$imagefile}.jpg

@confirm Done! URL copied to clipboard.|Okidoki
</pre>
<p>Enjoy and have some fun with the precious time saved for each image shared.<br />
Cheers!</p>
<img src="http://feeds.feedburner.com/~r/wpstorm/~4/-uwHe-UHyN4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://wpstorm.net/2010/11/paste-clipboard-dropbox-directory-opus/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>CloudBerry Explorer and SyncBack for Amazon S3</title>
		<link>http://wpstorm.net/2010/11/cloudberry-explorer-syncback-amazon-s3/</link>
		<comments>http://wpstorm.net/2010/11/cloudberry-explorer-syncback-amazon-s3/#comments</comments>
		<pubDate>Tue, 16 Nov 2010 14:58:10 +0000</pubDate>
		<dc:creator>Lotta</dc:creator>
				<category><![CDATA[Cloud Services]]></category>
		<category><![CDATA[Amazon]]></category>
		<category><![CDATA[AWS]]></category>
		<category><![CDATA[Backup]]></category>
		<category><![CDATA[CloudBerry Explorer]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[S3]]></category>
		<category><![CDATA[SyncBack]]></category>

		<guid isPermaLink="false">http://wpstorm.net/?p=356</guid>
		<description><![CDATA[I&#8217;ve been using SyncBack to handle my backup needs to external drives and FTP for a couple of years and it has worked a charm. Time changes though and I&#8217;ve recently embraced the concept of using online storage for my backup needs, and went with Amazon S3. Unfortunately at this time, SyncBack does not support ...]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been using <a href="http://www.2brightsparks.com/syncback/" title="SyncBack Backup Software">SyncBack</a> to handle my backup needs to external drives and FTP for a couple of years and it has worked a charm. Time changes though and I&#8217;ve recently embraced the concept of using online storage for my backup needs, and went with Amazon S3.</p>
<p>Unfortunately at this time, SyncBack does not support using a service like Amazon S3 for backup. Not to worry though, after some research I found a solution for SyncBack by using Windows&#8217; built-in PowerShell together with the awesome <a href="http://www.cloudberrylab.com/default.aspx?page=cloudberry-explorer-amazon-s3" title="CloudBerry Explorer for Amazon S3">CloudBerry Explorer</a> which comes with a PowerShell Snap-In.</p>
<p>I&#8217;m very happy I found CloudBerry Explorer, as it seems to support all new features introduced by Amazon S3 as soon as they are available, and I&#8217;ll probably start using it for all my S3 managing needs and not only to sync my backups.</p>
<p>Anyway, let&#8217;s get started with how to set this up.</p>
<h2>PowerShell Setup</h2>
<p>This was more or less the first time I used the new PowerShell in Windows, and I quickly noticed that it didn&#8217;t execute my script files. By default PowerShell&#8217;s script execution policy is set to restricted, so I started by changing this policy to RemoteSigned, which means that scripts needs to be signed to be executed except those I write myself. Perfect, just what I wanted.<br />
Change the execution policy in PowerShell with this command:</p>
<pre class="brush: powershell; title: ; notranslate">
Set-ExecutionPolicy RemoteSigned
</pre>
<p>See the screenshot below for how to check the current policy and changing it.</p>
<p><a href="http://wpstorm.net/files/2010/11/powershell-execution-policy.jpg"><img src="http://wpstorm.net/files/2010/11/powershell-execution-policy.jpg" alt="PowerShell Execution Policy" title="PowerShell Execution Policy" width="585" height="317" class="alignnone size-full wp-image-357" /></a></p>
<h2>CloudBerry Explorer PowerShell Script</h2>
<p>All available commands and parameters as well as a few examples for the CloudBerry Explorer PowerShell Snap-In can be found <a href="http://www.cloudberrylab.com/default.aspx?page=amazon-s3-powershell" title="CloudBerry Explorer PowerShell Snap-In">here >></a>.</p>
<p>Copy the script below to a local file and name it something like SyncFolderWithAmazonS3.ps1</p>
<pre class="brush: powershell; title: ; notranslate">
# Setup
$key = &quot;&lt;your access key&gt;&quot;
$secret = &quot;&lt;your secret key&gt;&quot;
$s3bucket = &quot;&lt;bucket&gt;/&lt;path&gt;&quot;
$localsource = &quot;&lt;local path to sync&gt;&quot;

# Add the CloudBerry SnapIn to the Console
Add-PSSnapin CloudBerryLab.Explorer.PSSnapIn

# Connect to the Amazon S3 Account and select the path
$s3 = Get-CloudS3Connection -Key $key -Secret $secret
$target = $s3 | Select-CloudFolder -Path $s3bucket

#Connect to local file system and select local folder
$local = Get-CloudFileSystemConnection
$source = $local | Select-CloudFolder $localsource

# Perform the Syncing
$source | Copy-CloudSyncFolders $target -DeleteOnTarget -IncludeSubFolders
</pre>
<p>It&#8217;s pretty straightforward, change the values in the first section to your Amazon keys, your backup bucket name and path as well as your local folder to sync to Amazon S3.</p>
<p>Then run it from the command prompt in PowerShell to make sure it works as expected and that the CloudBerry Explorer PowerShell Snap-In is properly installed.</p>
<h2>SyncBack Setup</h2>
<p>In SyncBack I&#8217;ve created a profile which I&#8217;ve called &#8216;Backup to Amazon S3&#8242;. You can make an infinite number of different variations on the actual backup settings of this profile depending on how you like and prefer to make backups. But the core thing to setup is to go into your profile for Amazon S3 backups and switch to expert mode. In the option for &#8216;Programs &#8211; Before&#8217;, go to the sub page for &#8216;After&#8217; and set PowerShell with the CloudBerry Explorer script to be run after the profile has finished.</p>
<div id="attachment_358" class="wp-caption aligncenter" style="width: 510px"><a href="http://wpstorm.net/files/2010/11/syncback-run-after-profile.jpg"><img src="http://wpstorm.net/files/2010/11/syncback-run-after-profile-500.jpg" alt="SyncBack - Run After Profile" title="SyncBack - Run After Profile" width="500" height="353" class="size-full wp-image-358" /></a><p class="wp-caption-text">Click to enlarge</p></div>
<p>The command line to add to the &#8216;Run after profile&#8217; field:</p>
<pre class="brush: powershell; title: ; notranslate">
PowerShell.exe &amp;'E:\Web\Server\SyncFolderWithAmazonS3.ps1'
</pre>
<p>Personally I&#8217;ve set my Amazon S3 Backup Profile to run once every night. All my important working files are backed up to a folder on my local backup drive, using a mirror backup mode to not leave deleted files in the sync folder. This folder is also the folder I&#8217;ve set as the $localsource in my SyncFolderWithAmazonS3.ps1 CloudBerry Explorer PowerShell script. So after the files in the local backup folder has been updated and are in sync with my system, the profile executes the script to sync all the changes to my Amazon S3 bucket as well.</p>
<p>This works great and I just love how secure I feel with my backups these days if something should happen locally.</p>
<p>Cheers!</p>
<img src="http://feeds.feedburner.com/~r/wpstorm/~4/qy659isUaZA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://wpstorm.net/2010/11/cloudberry-explorer-syncback-amazon-s3/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Editor Styles for Custom Post Types in WordPress 3.0</title>
		<link>http://wpstorm.net/2010/04/editor-styles-custom-post-types-wordpress-3-0/</link>
		<comments>http://wpstorm.net/2010/04/editor-styles-custom-post-types-wordpress-3-0/#comments</comments>
		<pubDate>Tue, 06 Apr 2010 16:27:51 +0000</pubDate>
		<dc:creator>Lotta</dc:creator>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[Coding]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Tweak]]></category>
		<category><![CDATA[WordPress 3.0]]></category>

		<guid isPermaLink="false">http://wpstorm.net/?p=333</guid>
		<description><![CDATA[I&#8217;ve had some fun playing around with the recently released WordPress 3.0, Beta 1. One of my new favorite additions is the add_editor_style() which allows you to assign a CSS file for the TinyMCE when editing posts, pages and the new custom post types. This is very handy to get closer to a WYSIWYG experience ...]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve had some fun playing around with the recently released <a href="http://wordpress.org/development/2010/04/wordpress-3-0-beta-1/">WordPress 3.0, Beta 1</a>. One of my new favorite additions is the add_editor_style() which allows you to assign a CSS file for the TinyMCE when editing posts, pages and the new custom post types. This is very handy to get closer to a WYSIWYG experience in WordPress&#8217; editor and not having to preview the posts all the times while writing, to check where line breaks end up and so on (if you care about those things).</p>
<p>I&#8217;m also loving the new Custom Post Types, and on one of my sites, I have setup a few different post types. On the frontend I have different widths for posts, pages and my new WordPress 3.0 custom post type &#8216;portfolio. I wanted to reflect the different widths in my admin editor style sheet as well. The posts are the narrowest ones, while pages are wider and my custom post type portfolio is the widest, so I have made 3 style sheets which are pretty much the same, with the exception of the</p>
<pre class="brush: css; title: ; notranslate">
html .mceContentBody {
	max-width:640px;
}
</pre>
<p>which sets the width for the editor. My style sheets are named; editor-style-post.css, editor-style-page.css and editor-style-portfolio.css.<br />
To be able to decide which post type I&#8217;m editing I check post_type in the $current_screen variable and then set the correct CSS according to that.</p>
<p>The code I end up with adding to my <em>functions.php</em> file looks something like this.</p>
<pre class="brush: php; title: ; notranslate">
function my_editor_style() {
	global $current_screen;
	switch ($current_screen-&gt;post_type) {
	case 'post':
		add_editor_style('editor-style-post.css');
		break;
	case 'page':
		add_editor_style('editor-style-page.css');
		break;
	case 'portfolio':
		add_editor_style('editor-style-portfolio.css');
		break;
	}
}
add_action( 'admin_head', 'my_editor_style' );
</pre>
<p>By expanding on the code above you can continue defining stylesheets for any custom post types you might end up with in WordPress 3.0.</p>
<p>That&#8217;s it folks, cheers!</p>
<img src="http://feeds.feedburner.com/~r/wpstorm/~4/-7DeH6q8OJg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://wpstorm.net/2010/04/editor-styles-custom-post-types-wordpress-3-0/feed/</wfw:commentRss>
		<slash:comments>27</slash:comments>
		</item>
		<item>
		<title>PayPal Donations WordPress Widget</title>
		<link>http://wpstorm.net/2009/06/paypal-donation-wordpress-widget/</link>
		<comments>http://wpstorm.net/2009/06/paypal-donation-wordpress-widget/#comments</comments>
		<pubDate>Thu, 18 Jun 2009 18:56:18 +0000</pubDate>
		<dc:creator>Lotta</dc:creator>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[Plugin]]></category>

		<guid isPermaLink="false">http://wpstorm.net/?p=279</guid>
		<description><![CDATA[I just released a new version of PayPal Donations, version 1.2. New in this version is the inclusion of a sidebar Widget for the PayPal button. I&#8217;m using the new WordPress 2.8 API for the Widget, so it&#8217;s only available if you run the plugin on WordPress 2.8 or newer. In the widget admin you ...]]></description>
			<content:encoded><![CDATA[<div id="attachment_280" class="wp-caption alignright" style="width: 160px"><a href="http://wpstorm.net/files/2009/06/paypal-donations-widget-screenshot-1.2.jpg"><img class="size-thumbnail wp-image-280" title="PayPal Donation Widget" src="http://wpstorm.net/files/2009/06/paypal-donations-widget-screenshot-1.2-150x150.jpg" alt="PayPal Donation Widget Setup" width="150" height="150" /></a><p class="wp-caption-text">PayPal Widget Setup</p></div>
<p>I just released a new version of <a title="PayPal Donation for WordPress" href="http://wpstorm.net/wordpress-plugins/paypal-donations/">PayPal Donations</a>, version 1.2.</p>
<p>New in this version is the inclusion of a sidebar Widget for the PayPal button. I&#8217;m using the new WordPress 2.8 API for the Widget, so it&#8217;s only available if you run the plugin on WordPress 2.8 or newer.</p>
<p>In the widget admin you can specify a descriptive text as well as overrides for Purpose and Reference if you wish.</p>
<p>Enjoy and cheers!</p>
<img src="http://feeds.feedburner.com/~r/wpstorm/~4/wVjIZNijM1U" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://wpstorm.net/2009/06/paypal-donation-wordpress-widget/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Optimize and style Contact Form 7 for WordPress</title>
		<link>http://wpstorm.net/2009/06/optimize-style-contact-form-7-wordpress/</link>
		<comments>http://wpstorm.net/2009/06/optimize-style-contact-form-7-wordpress/#comments</comments>
		<pubDate>Sat, 06 Jun 2009 12:52:04 +0000</pubDate>
		<dc:creator>Lotta</dc:creator>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[Coding]]></category>
		<category><![CDATA[Contact]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Plugin]]></category>
		<category><![CDATA[Tweak]]></category>

		<guid isPermaLink="false">http://wpstorm.net/?p=244</guid>
		<description><![CDATA[One of my favorite WordPress plugins is Contact Form 7 which I use on several of my WordPress based sites. Even though it&#8217;s highly customizable and configurable I have a few gripes with some hard coded functions in it. You can always edit the plugin file, which I did at first, but then you have ...]]></description>
			<content:encoded><![CDATA[<p>One of my favorite WordPress plugins is <a title="Contact Form for WordPress" href="http://ideasilo.wordpress.com/2007/04/30/contact-form-7/">Contact Form 7</a> which I use on several of my WordPress based sites. Even though it&#8217;s highly customizable and configurable I have a few gripes with some hard coded functions in it. You can always edit the plugin file, which I did at first, but then you have to reapply your edits every time the plugin gets updated, which can be cumbersome as this plugin gets updated quite often. So instead of keep editing the plugin file on every update I created some overrides instead.</p>
<h3>The Issues</h3>
<ul>
<li>The url to the AJAX loader symbol is hardcoded into the plugin, so if you don&#8217;t use a white background in your theme the loading symbol looks quite ugly. If you replace the default icon with your own it gets overwritten on each plugin update.</li>
<li>The javascripts for the plugin gets loaded on every single page of the site no matter if the plugin is used or not on that page, which adds unnecessary loading time where it&#8217;s not needed.</li>
<li>The path to the stylesheet for the validation and submit messages is also hardcoded into the plugin, and if you edit the stylesheet to fit your theme, the edits gets lost on each update, and you have to reupload your custom stylesheet for the plugin.</li>
</ul>
<h3>The Solutions</h3>
<p>So to not have to edit the plugin file, I added a few overrides in my theme&#8217;s functions.php file instead to change the behaviour of the plugin where needed.</p>
<p>Let&#8217;s start by taking care of the AJAX loading symbol. To change the path to the gif file I use a regular expression to update the url.</p>
<pre class="brush: php; title: ; notranslate">// Change the URL to the ajax-loader image
function change_wpcf7_ajax_loader($content) {
	if ( is_page('contact') ) {
		$string = $content;
		$pattern = '/(&lt;img class=&quot;ajax-loader&quot; style=&quot;visibility: hidden;&quot; alt=&quot;ajax loader&quot; src=&quot;)(.*)(&quot; \/&gt;)/i';
		$replacement = &quot;$1&quot;.get_template_directory_uri().&quot;/images/ajax-loader.gif$3&quot;;
		$content =  preg_replace($pattern, $replacement, $string);
	}
	return $content;
}
add_filter( 'the_content', 'change_wpcf7_ajax_loader', 100 );</pre>
<p>This function filters the content, tracks down the AJAX loader tag and replaces the URL with a path to the current {theme folder}/images/ajax-loader.gif. So you can have your own custom AJAX loader stored in your theme folder instead, untouched on each plugin update. I added the if( is_page(contact) ) {} to the function to make sure the filter only runs on pages where needed, to not waste CPU cycles on pages where the plugin is not used. Contact is the name of the page where I use the form, change it to the name, or names of pages where you use the plugin.</p>
<p>Okay, now let&#8217;s see take care of the script loading on each page of the site.</p>
<pre class="brush: php; title: ; notranslate">// Add the Contact Form 7 scripts on selected pages
function add_wpcf7_scripts() {
	if ( is_page('contact') )
		wpcf7_enqueue_scripts();
}
if ( ! is_admin() &amp;&amp; WPCF7_LOAD_JS )
	remove_action( 'init', 'wpcf7_enqueue_scripts' );
add_action( 'wp', 'add_wpcf7_scripts' );</pre>
<p>This function removes the call to add the Contact Form 7 scripts on every page, and then adds back the call where needed, in my case I add them back at the page called contact, but change that to whatever works for you.</p>
<p>And finally, let&#8217;s deal with the stylesheet.</p>
<pre class="brush: php; title: ; notranslate">function remove_wpcf7_stylesheet() {
	remove_action( 'wp_head', 'wpcf7_wp_head' );
}
add_action( 'init' , 'remove_wpcf7_stylesheet' );</pre>
<p>Here I actually remove the call to the stylesheet completely. As I have made my own style that fits my theme, I don&#8217;t use the default stylings. If you use the default stylings but just want it to load where needed, you could use an is_page condition like on the loading of the scripts. I could have put the Contact Form 7 Stylesheet in the theme folder using the same technique as on the AJAX loader to leave it untouched on a plugin update, but as I like to keep the calls to external files to a minimum to have the site load as fast as possible, I just put the WPCF7 CSS styles directly in my default style.css of my theme instead and got rid of the plugin stylesheet loading.</p>
<h3>The Final Code</h3>
<p>And here is what the final code looks like, ready to get pasted into the functions.php file in the theme you are using.</p>
<pre class="brush: php; title: ; notranslate">/**
 * Functions:	Optimize and style Contact Form 7 - WPCF7
 *
 */
// Remove the default Contact Form 7 Stylesheet
function remove_wpcf7_stylesheet() {
	remove_action( 'wp_head', 'wpcf7_wp_head' );
}

// Add the Contact Form 7 scripts on selected pages
function add_wpcf7_scripts() {
	if ( is_page('contact') )
		wpcf7_enqueue_scripts();
}

// Change the URL to the ajax-loader image
function change_wpcf7_ajax_loader($content) {
	if ( is_page('contact') ) {
		$string = $content;
		$pattern = '/(&lt;img class=&quot;ajax-loader&quot; style=&quot;visibility: hidden;&quot; alt=&quot;ajax loader&quot; src=&quot;)(.*)(&quot; \/&gt;)/i';
		$replacement = &quot;$1&quot;.get_template_directory_uri().&quot;/images/ajax-loader.gif$3&quot;;
		$content =  preg_replace($pattern, $replacement, $string);
	}
	return $content;
}

// If the Contact Form 7 Exists, do the tweaks
if ( function_exists('wpcf7_contact_form') ) {
	if ( ! is_admin() &amp;&amp; WPCF7_LOAD_JS )
		remove_action( 'init', 'wpcf7_enqueue_scripts' );

	add_action( 'wp', 'add_wpcf7_scripts' );
	add_action( 'init' , 'remove_wpcf7_stylesheet' );
	add_filter( 'the_content', 'change_wpcf7_ajax_loader', 100 );
}</pre>
<p>This tweak was published when Contact Form 7 was at version 1.10, and should continue to work just fine as long as no major changes is made to the inner workings of the plugin.</p>
<img src="http://feeds.feedburner.com/~r/wpstorm/~4/4UfOyw2IiQE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://wpstorm.net/2009/06/optimize-style-contact-form-7-wordpress/feed/</wfw:commentRss>
		<slash:comments>53</slash:comments>
		</item>
		<item>
		<title>Email log messages library in CodeIgniter</title>
		<link>http://wpstorm.net/2009/05/email-log-messages-library-codeigniter/</link>
		<comments>http://wpstorm.net/2009/05/email-log-messages-library-codeigniter/#comments</comments>
		<pubDate>Sun, 31 May 2009 16:53:08 +0000</pubDate>
		<dc:creator>Lotta</dc:creator>
				<category><![CDATA[CodeIgniter]]></category>
		<category><![CDATA[Coding]]></category>
		<category><![CDATA[Email]]></category>
		<category><![CDATA[Library]]></category>
		<category><![CDATA[Log]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://wpstorm.net/?p=231</guid>
		<description><![CDATA[When working with CodeIgniter, I&#8217;ve found the log message functionality built into the framework very helpful. The other day I noticed in my log of one of my CodeIgniter based sites that I&#8217;ve had some 404 errors going on for some time. As I don&#8217;t have the time to check my logs daily, I hadn&#8217;t ...]]></description>
			<content:encoded><![CDATA[<p>When working with CodeIgniter, I&#8217;ve found the log message functionality built into the framework very helpful. The other day I noticed in my log of one of my CodeIgniter based sites that I&#8217;ve had some 404 errors going on for some time. As I don&#8217;t have the time to check my logs daily, I hadn&#8217;t noticed this problem until now.</p>
<p>This led me to think that it would be real handy to get the log messages sent out by email as well, so you don&#8217;t risk to have a problem going on at the site unnoticed for days or even weeks.</p>
<p>So I wrote an extension to the native Log class in CodeIgniter which adds this functionality. Below is the code for MY_Log.php which extends the CI_Log class. MY_Log calls the native Log functions so the log file still gets generated, and if a log message was executed it also gets sent out by email afterward.</p>
<p>Change the email address in the code to the one you want to receive the log messages to, and then save the file in your application/libraries/ folder as MY_Log.php. This assumes that your Class Extension Prefix is set to MY_ in your config file.</p>
<p>I hope some of you find this class extension useful, and feel free to improve upon it. Cheers!</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php
/**
 * MY_Log Class
 *
 * This library extends the native Log library.
 * It adds the function to have the log messages being emailed when they have been outputted to the log file.
 *
 * @package		CodeIgniter
 * @subpackage		Libraries
 * @category		Logging
 * @author		Johan Steen
 * @link		http://wpstorm.net/
 */
class MY_Log extends CI_Log {
	/**
	 * Constructor
	 *
	 * @access	public
	 */
	function MY_Log()
	{
		parent::CI_Log();
	}

	/**
	 * Write Log File
	 *
	 * Calls the native write_log() method and then sends an email if a log message was generated.
	 *
	 * @access	public
	 * @param	string	the error level
	 * @param	string	the error message
	 * @param	bool	whether the error is a native PHP error
	 * @return	bool
	 */
	function write_log($level = 'error', $msg, $php_error = FALSE)
	{
		$result = parent::write_log($level, $msg, $php_error);

		if ($result == TRUE &amp;&amp; strtoupper($level) == 'ERROR') {
			$message = &quot;An error occurred: \n\n&quot;;
			$message .= $level.' - '.date($this-&gt;_date_fmt). ' --&gt; '.$msg.&quot;\n&quot;;

			$to = 'someone@example.com';
			$subject = 'An error has occured';
			$headers = 'From: Example Name &lt;no-reply@example.com&gt;' . &quot;\r\n&quot;;
			$headers .= 'Content-type: text/plain; charset=utf-8\r\n';

			mail($to, $subject, $message, $headers);
		}
		return $result;
	}
}
?&gt;
</pre>
<img src="http://feeds.feedburner.com/~r/wpstorm/~4/WivfFTBrjCs" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://wpstorm.net/2009/05/email-log-messages-library-codeigniter/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
	</channel>
</rss>

